blob: f3079da521e987c39f94bac26e65964aeafae5df [file] [log] [blame]
Daniel Willmann19b8d902022-01-05 09:12:34 +01001module HNBGW_Tests {
2
3/* Integration Tests for OsmoHNBGW
4 * (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
5 * All rights reserved.
6 *
7 * Released under the terms of GNU General Public License, Version 2 or
8 * (at your option) any later version.
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 *
12 * This test suite tests OsmoHNBGW while emulating the hNodeB as well as MSC, SGSN, MGW
13 * See README for more details.
14 */
15
16import from Misc_Helpers all;
17import from General_Types all;
18import from GSM_Types all;
19import from Osmocom_Types all;
20import from IPL4asp_Types all;
21
22import from Osmocom_CTRL_Functions all;
23import from Osmocom_CTRL_Types all;
24import from Osmocom_CTRL_Adapter all;
25
26import from StatsD_Types all;
27import from StatsD_CodecPort all;
28import from StatsD_CodecPort_CtrlFunct all;
29import from StatsD_Checker all;
30
31import from Osmocom_VTY_Functions all;
32import from TELNETasp_PortType all;
33
34import from HNBAP_Templates all;
35import from HNBAP_PDU_Descriptions all;
36
37import from RUA_IEs all;
38import from RUA_Templates all;
39import from RUA_Emulation all;
40
41import from Iuh_Emulation all;
42
43import from RANAP_Types all;
44import from RANAP_PDU_Descriptions all;
45import from RANAP_PDU_Contents all;
46import from RANAP_IEs all;
47import from RANAP_Templates all;
48
49import from RAN_Adapter all;
50
51import from RAN_Adapter all;
52import from RAN_Emulation all;
53
54import from MGCP_Emulation all;
55import from MGCP_Types all;
56import from MGCP_Templates all;
57import from MGCP_CodecPort all;
58import from SDP_Types all;
59
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +020060import from PFCP_Types all;
61import from PFCP_Emulation all;
62import from PFCP_Templates all;
63import from PFCP_CodecPort all;
64
Daniel Willmann19b8d902022-01-05 09:12:34 +010065modulepar {
66 /* IP address at which the HNodeB can be reached */
67 charstring mp_hnodeb_ip := "127.0.0.1";
68 integer mp_hnodeb_port := -1;
69
70 /* IP address at which the test binds */
71 charstring mp_hnbgw_ip := "127.0.0.1";
72 integer mp_hnbgw_iuh_port := 29169;
73
74 charstring mp_mgw_ip := "127.0.0.1";
75 integer mp_mgw_port := 2427;
76
77 RAN_Configuration mp_msc_cfg := {
78 transport := RANAP_TRANSPORT_IuCS,
79 sccp_service_type := "mtp3_itu",
80 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
81 own_pc := 188, /* 0.23.4 first MSC emulation */
82 own_ssn := 142,
83 peer_pc := 189, /* 0.23.5 osmo-hnbgw */
84 peer_ssn := 142,
85 sio := '83'O,
86 rctx := 1
87 };
88 RAN_Configuration mp_sgsn_cfg := {
89 transport := RANAP_TRANSPORT_IuCS,
90 sccp_service_type := "mtp3_itu",
91 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
92 own_pc := 185, /* 0.23.1 first SGSN emulation */
93 own_ssn := 142,
94 peer_pc := 189, /* 0.23.5 osmo-hnbgw */
95 peer_ssn := 142,
96 sio := '83'O,
97 rctx := 2
98 };
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +020099
100 /* IP address at which we listen for PFCP to emulate a UPF in ttcn3 */
101 charstring mp_pfcp_ip_local := "127.0.0.1";
102
103 /* IP address from which the SUT (osmo-hnbgw) sends PFCP requests, and to which the ttcn3 UPF emulation sends
104 * PFCP responses. */
105 charstring mp_pfcp_ip_remote := "127.0.0.2";
Daniel Willmann19b8d902022-01-05 09:12:34 +0100106}
107
108function MSC_UnitdataCallback(RANAP_PDU ranap) runs on RAN_Emulation_CT return template RANAP_PDU {
109 // TODO: Actually implement unitdata handling
110 return ts_RANAP_Reset(ts_RanapCause_om_intervention, cs_domain);
111}
112
113const RanOps MSC_RanOps := {
114 ranap_create_cb := refers(RAN_Emulation.RanapExpectedCreateCallback),
115 ranap_unitdata_cb := refers(MSC_UnitdataCallback),
116 ps_domain := false,
117 decode_dtap := false,
118 role_ms := false,
119 protocol := RAN_PROTOCOL_RANAP,
120 transport := RANAP_TRANSPORT_IuCS,
121 use_osmux := false,
Eric Wild6e511ce2022-04-02 21:35:56 +0200122 bssap_reset_retries := 1,
Daniel Willmann19b8d902022-01-05 09:12:34 +0100123 sccp_addr_local := omit,
124 sccp_addr_peer := omit
125}
126
127type record CrcxResponse {
128 integer resp,
129 HostName mgw_rtp_ip,
130 PortNumber mgw_rtp_port,
131 MgcpConnectionId mgcp_connection_id
132}
133type record MgcpParameters {
134 integer got_crcx_count,
135 integer got_dlcx_count,
136 MgcpCallId mgcp_call_id optional,
137 MgcpEndpoint mgcp_ep,
138 CrcxResponse mgw_conn_1,
139 CrcxResponse mgw_conn_2,
140 uint7_t rtp_payload_type,
141 charstring rtp_sdp_format,
142 HostName hnb_rtp_ip,
143 PortNumber hnb_rtp_port,
144 HostName cn_rtp_ip,
145 PortNumber cn_rtp_port,
146 boolean use_osmux,
147 integer got_osmux_count
148}
149
150template (value) MgcpParameters t_MgcpParams := {
151 got_crcx_count := 0,
152 got_dlcx_count := 0,
153 mgcp_call_id := omit,
154 mgcp_ep := "rtpbridge/1@mgw",
155 mgw_conn_1 := {
156 resp := 1,
157 mgw_rtp_ip := "127.1.2.1",
158 mgw_rtp_port := 10000,
159 mgcp_connection_id := '11111'H
160 },
161 mgw_conn_2 := {
162 resp := 1,
163 mgw_rtp_ip := "127.1.2.2",
164 mgw_rtp_port := 20000,
165 mgcp_connection_id := '22222'H
166 },
167 rtp_payload_type := 23,
168 rtp_sdp_format := "FOO",
169 hnb_rtp_ip := "127.1.1.1",
170 hnb_rtp_port := 10001,
171 cn_rtp_ip := "127.1.3.1",
172 cn_rtp_port := 20001,
173 use_osmux := false,
174 got_osmux_count := 0
175}
176
177type record TestHdlrParams {
178 integer hnb_idx,
179 hexstring imsi,
180 boolean ps_domain,
181 MgcpParameters mgcp_pars optional,
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200182 HnbConfig hnb optional,
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200183 boolean separate_sccp_cr,
184 charstring pfcp_local_addr
Daniel Willmann19b8d902022-01-05 09:12:34 +0100185}
186
187/* We extend:
188 * RUA_ConnHdlr (for the Iuh side, emulating the HNB)
189 * RAN_ConnHdlr (for the Iu side, emulating the MSC)
190 * MGCP_ConnHdlr (for the MGCP side, emulating the MGW)
191 */
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200192type component ConnHdlr extends RAN_ConnHdlr, MGCP_ConnHdlr, RUA_ConnHdlr, PFCP_ConnHdlr {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100193 var integer g_sccp_conn_id;
194 var TestHdlrParams g_pars;
195 timer g_Tguard;
196}
197
198
199const MGCPOps MSC_MGCPOps := {
200 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
201 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
202}
203
204function f_create_ranap_exp(octetstring l3_enc) runs on ConnHdlr {
205 BSSAP_PROC.call(RAN_register:{l3_enc, self}) {
206 [] BSSAP_PROC.getreply(RAN_register:{?, ?}) {};
207 }
208}
209
210
Daniel Willmannc79679a2022-08-23 17:48:39 +0200211const integer NUM_HNB := 2;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100212
Daniel Willmann19b8d902022-01-05 09:12:34 +0100213type record HnbConfig {
214 LocationAreaIdentification lai,
215 integer sac
216}
217
218type component test_CT extends CTRL_Adapter_CT {
219 var boolean g_initialized := false;
220
221 /********************* Iu side */
222 var RAN_Adapter g_msc;
223 var RAN_Adapter g_sgsn;
224 /* SGSN IuPS missing */
225
226 /********************* Iuh side */
227 var HnbConfig g_hnb_cfg[NUM_HNB];
228 var Iuh_Emulation_CT vc_Iuh[NUM_HNB];
229 var RUA_Emulation_CT vc_RUA[NUM_HNB];
230 port HNBAP_PT HNBAP[NUM_HNB];
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200231 /* Number of HNBs to be used/started by the test */
232 var integer g_num_hnbs := NUM_HNB;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100233
234 var MGCP_Emulation_CT vc_MGCP;
235 port TELNETasp_PT HNBGWVTY;
236 /* global test case guard timer (actual timeout value is set in f_init()) */
237 timer T_guard := 30.0;
238}
239
240/* global altstep for global guard timer; */
241altstep as_Tguard() runs on test_CT {
242 [] T_guard.timeout {
243 setverdict(fail, "Timeout of T_guard");
244 mtc.stop;
245 }
246}
247
248friend function f_logp(TELNETasp_PT pt, charstring log_msg)
249{
250 // log on TTCN3 log output
251 log(log_msg);
252 // log in stderr log
253 f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
254}
255
256function f_init_vty(charstring id := "foo") runs on test_CT {
257 if (HNBGWVTY.checkstate("Mapped")) {
258 /* skip initialization if already executed once */
259 return;
260 }
261 map(self:HNBGWVTY, system:HNBGWVTY);
262 f_vty_set_prompts(HNBGWVTY);
263 f_vty_transceive(HNBGWVTY, "enable");
264}
265
266function f_init_mgcp(charstring id) runs on test_CT {
267 id := id & "-MGCP";
268 var MGCPOps ops := {
269 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
270 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
271 }
272 var MGCP_conn_parameters pars := {
273 callagent_ip := mp_hnbgw_ip,
274 callagent_udp_port := -1,
275 mgw_ip := mp_mgw_ip,
276 mgw_udp_port := mp_mgw_port,
277 multi_conn_mode := false
278 }
279
280 vc_MGCP := MGCP_Emulation_CT.create(id);
281 map(vc_MGCP:MGCP, system:MGCP_CODEC_PT);
282 vc_MGCP.start(MGCP_Emulation.main(ops, pars, id));
283}
284
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200285function f_init_pfcp(charstring id) runs on ConnHdlr {
286 id := id & "-PFCP";
287
288 var PFCP_Emulation_Cfg pfcp_cfg := {
289 pfcp_bind_ip := mp_pfcp_ip_local,
290 pfcp_bind_port := PFCP_PORT,
291 pfcp_remote_ip := mp_pfcp_ip_remote,
292 pfcp_remote_port := PFCP_PORT,
293 role := UPF
294 };
295
296 vc_PFCP := PFCP_Emulation_CT.create(id) alive;
297 connect(self:PFCP, vc_PFCP:CLIENT);
298 connect(self:PFCP_PROC, vc_PFCP:CLIENT_PROC);
299 vc_PFCP.start(PFCP_Emulation.main(pfcp_cfg));
300}
301
Daniel Willmann19b8d902022-01-05 09:12:34 +0100302function f_init_hnodeb(charstring id, integer hnb_idx, RuaOps rua_ops) runs on test_CT {
303 id := id & "-Iuh" & int2str(hnb_idx);
304
305 /* Iuh lower layer (RUA/HNBAP demux) */
306 var Iuh_conn_parameters iuh_pars;
307 iuh_pars.remote_ip := mp_hnbgw_ip;
308 iuh_pars.remote_sctp_port := mp_hnbgw_iuh_port;
309 iuh_pars.local_ip := mp_hnodeb_ip;
310 iuh_pars.local_sctp_port := mp_hnodeb_port + hnb_idx;
311 vc_Iuh[hnb_idx] := Iuh_Emulation_CT.create(id);
312 connect(self:HNBAP[hnb_idx], vc_Iuh[hnb_idx]:HNBAP);
313
314 vc_RUA[hnb_idx] := RUA_Emulation_CT.create(id & "-RUA");
315 connect(vc_RUA[hnb_idx]:RUA, vc_Iuh[hnb_idx]:RUA);
316
317 /* Start Iuh side components */
318 vc_Iuh[hnb_idx].start(Iuh_Emulation.main(iuh_pars, id));
319 vc_RUA[hnb_idx].start(RUA_Emulation.main(rua_ops, id & "-RUA"));
320}
321
322/* global initialization function */
Neels Hofmeyr82e79b02022-06-08 00:08:09 +0200323function f_init(charstring id := "HNBGW", float guard_timeout := 30.0) runs on test_CT {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100324
Daniel Willmann19b8d902022-01-05 09:12:34 +0100325 T_guard.start(guard_timeout);
326 activate(as_Tguard());
327
328 /* RUA/RANAP emulation on top of lower-layer Iuh */
329 var RuaOps rua_ops := {
330 create_cb := refers(IuhRanapCreateCallback),
331 unitdata_cb := refers(IuhRanapUnitdataCallback)
332 };
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200333 for (var integer i := 0; i < g_num_hnbs; i := i+1) {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200334 g_hnb_cfg[i] := {
335 lai := {
336 mcc_mnc := '00101'H,
337 lac := 2342 + i
338 },
339 sac := 55
340 };
Daniel Willmann19b8d902022-01-05 09:12:34 +0100341 f_init_hnodeb(testcasename(), i, rua_ops);
342 }
343
344 /* MSC emulation */
345 var RanOps ranops := {
346 ranap_create_cb := refers(RAN_Emulation.RanapExpectedCreateCallback),
347 ranap_unitdata_cb := omit,
348 ps_domain := false,
349 decode_dtap := false,
350 role_ms := false,
351 protocol := RAN_PROTOCOL_RANAP,
352 transport := RANAP_TRANSPORT_IuCS,
353 use_osmux := false,
Eric Wild6e511ce2022-04-02 21:35:56 +0200354 bssap_reset_retries := 1,
Daniel Willmann19b8d902022-01-05 09:12:34 +0100355 sccp_addr_local := omit,
356 sccp_addr_peer := omit
357 };
358 f_ran_adapter_init(g_msc, mp_msc_cfg, "HNBGW_Test", ranops);
359 f_ran_adapter_start(g_msc);
360
361 /* SGSN emulation */
362 ranops.ps_domain := true;
363 f_ran_adapter_init(g_sgsn, mp_sgsn_cfg, "HNBGW_Test", ranops);
364 f_ran_adapter_start(g_sgsn);
365
366 f_init_mgcp(id);
367 f_init_vty("VirtHNBGW");
368}
369
370friend function f_shutdown_helper() runs on test_CT {
371 all component.stop;
372 setverdict(pass);
373 mtc.stop;
374}
375
376/* helper function to start all of the simulated hNodeBs */
377function f_start_hnbs() runs on test_CT {
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200378 for (var integer i:= 0; i < g_num_hnbs; i := i+1) {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200379 f_hnbap_register(i, i);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100380 }
381}
382
383/***********************************************************************
384 * code running in test_CT, preparing start of per-UE ConnHdlr
385 ***********************************************************************/
386
387/* inbound RUA connection establishment on Iuh side */
388function IuhRanapCreateCallback(ContextId context_id, RUA_IEs.CN_DomainIndicator domain, charstring id)
389runs on RUA_Emulation_CT return RUA_ConnHdlr {
390 log("CreateCallback");
391 return null;
392}
393
394/* inbound RUA connectionless data on Iuh side */
395function IuhRanapUnitdataCallback(RANAP_PDU ranap)
396runs on RUA_Emulation_CT return template RANAP_PDU {
397 log("UnitdataCallback");
398 return omit;
399}
400
401private function f_start_handler_create(TestHdlrParams pars) runs on test_CT return ConnHdlr {
402 var ConnHdlr vc_conn;
403 var charstring id := testcasename() & int2str(pars.hnb_idx);
404
405 vc_conn := ConnHdlr.create(id);
406
407 /* Iuh RUA part */
408 connect(vc_conn:RUA, vc_RUA[pars.hnb_idx]:CLIENT);
409
410 if (pars.ps_domain) {
411 /* SGSN side */
412 connect(vc_conn:BSSAP, g_sgsn.vc_RAN:CLIENT);
413 connect(vc_conn:BSSAP_PROC, g_sgsn.vc_RAN:PROC);
414 } else {
415 /* MSC side */
416 connect(vc_conn:BSSAP, g_msc.vc_RAN:CLIENT);
417 connect(vc_conn:BSSAP_PROC, g_msc.vc_RAN:PROC);
418 }
419 /* MGCP part */
420 connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
421 connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
422
423 return vc_conn;
424}
425
426private function f_start_handler_run(ConnHdlr vc_conn, void_fn fn, TestHdlrParams pars) runs on test_CT {
427 var charstring id := testcasename(); // & int2str(pars.ran_idx);
428 /* We cannot use vc_conn.start(f_init_handler(fn, id, pars)); as we cannot have
429 * a stand-alone 'derefers()' call, see https://www.eclipse.org/forums/index.php/t/1091364/ */
430 pars.hnb := g_hnb_cfg[pars.hnb_idx];
431 pars.mgcp_pars := valueof(t_MgcpParams);
432 vc_conn.start(derefers(fn)(id, pars));
433}
434
435function f_start_handler_with_pars(void_fn fn, template (value) TestHdlrParams pars)
436runs on test_CT return ConnHdlr {
437 var ConnHdlr vc_conn;
438 vc_conn := f_start_handler_create(valueof(pars));
439 f_start_handler_run(vc_conn, fn, valueof(pars));
440 return vc_conn;
441}
442
443/***********************************************************************
444 * code running inside per-UE ConnHdlr
445 ***********************************************************************/
446
447type function void_fn(charstring id, TestHdlrParams pars) runs on ConnHdlr;
448
449function f_init_handler(TestHdlrParams pars, float t_guard := 20.0) runs on ConnHdlr {
450 /* make parameters available via component variable */
451 g_pars := pars;
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200452
453 f_init_pfcp(testcasename());
454
Daniel Willmann19b8d902022-01-05 09:12:34 +0100455 /* start guard timer and activate it as default */
456 g_Tguard.start(t_guard);
457 activate(as_Tguard_ConnHdlr());
458
459 /* TODO: CTRL? */
460 /* TODO: VTY? */
461}
462
463/* global altstep for global guard timer; */
464private altstep as_Tguard_ConnHdlr() runs on ConnHdlr {
465 [] g_Tguard.timeout {
466 setverdict(fail, "Timeout of T_guard");
467 mtc.stop;
468 }
469}
470
471/* send RANAP on Iuh and expect it to show up on Iu */
472function f_iuh2iu(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
473runs on ConnHdlr return RANAP_PDU {
474 var RANAP_PDU rx;
475 timer T := 5.0;
476
477 if (istemplatekind(exp_rx, "omit")) {
478 exp_rx := tx;
479 }
480
481 RUA.send(tx);
482 T.start;
483
484 alt {
485 [] BSSAP.receive(exp_rx) -> value rx {
486 setverdict(pass);
487 }
488 [] T.timeout {
489 setverdict(fail, "Timeout waiting for Iu ", exp_rx);
490 }
491 }
492 return rx;
493}
494
495/* send RANAP on Iu and expect it to show up on Iuh */
496function f_iu2iuh(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
497runs on ConnHdlr return RANAP_PDU {
498 var RANAP_PDU rx;
499 timer T := 5.0;
500
501 if (istemplatekind(exp_rx, "omit")) {
502 exp_rx := tx;
503 }
504
505 BSSAP.send(tx);
506 T.start;
507
508 alt {
509 [] RUA.receive(exp_rx) -> value rx {
510 setverdict(pass);
511 }
512 [] T.timeout {
513 setverdict(fail, "Timeout waiting for Iuh ", exp_rx);
514 }
515 }
516 return rx;
517}
518
519/* send RANAP on Iuh and expect it to show up on Iu */
520function f_iuh2iu_connect(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
521runs on ConnHdlr return RANAP_PDU {
522 var RANAP_PDU rx;
523 timer T := 5.0;
524
525 if (istemplatekind(exp_rx, "omit")) {
526 exp_rx := tx;
527 }
528
529 /* create an expect on the Iu side for the random NAS portion */
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200530 if (g_pars.separate_sccp_cr) {
531 f_ran_register_sccp_cr_without_payload();
532 } else {
533 var template (omit) octetstring nas := f_ranap_extract_l3(valueof(tx));
534 f_ran_register_exp(valueof(nas));
535 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100536
537 /* send it via Iuh (creating a RUA connection) */
538 RUA.send(RUA_Conn_Req:{g_pars.ps_domain, tx});
539
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200540 if (g_pars.separate_sccp_cr) {
541 /* Acknowledge the empty SCCP CR. RAN_Emulation does the confirmation, no need to respond. */
542 BSSAP.receive(tr_RANAP_Conn_Req());
543 }
544
Daniel Willmann19b8d902022-01-05 09:12:34 +0100545 /* expect to receive it on the Iu side */
546 T.start;
547 alt {
548 [] BSSAP.receive(exp_rx) -> value rx {
549 setverdict(pass);
550 }
551 [] T.timeout {
552 setverdict(fail, "Timeout waiting for Iu ", exp_rx);
553 }
554 }
555 return rx;
556}
557
558function f_iuh2iu_disconnect(template (present) RANAP_PDU tx, RUA_IEs.Cause cause,
559 template RANAP_PDU exp_rx := omit)
560runs on ConnHdlr return RANAP_PDU {
561 var RANAP_PDU rx
562 timer T := 5.0;
563
564 if (istemplatekind(exp_rx, "omit")) {
565 exp_rx := tx;
566 }
567
568 /* send it via Iuh (creating a RUA connection) */
569 RUA.send(RUA_Disc_Req:{tx, cause});
570
571 /* expect to receive it on the Iu side */
572 T.start;
573 alt {
574 [] BSSAP.receive(exp_rx) -> value rx {
575 }
576 [] T.timeout {
577 setverdict(fail, "Timeout waiting for Iu ", exp_rx);
578 return rx;
579 }
580 }
581
582 /* expect disconnect on the Iu side */
583 alt {
584 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {
585 setverdict(pass);
586 }
587 [] T.timeout {
588 setverdict(fail, "Timeout waiting for Iu disconnect");
589 return rx;
590 }
591
592 }
593 return rx;
594}
595
596/* build a RANAP InitialUE based on the TestHdlrParams */
597friend function f_build_initial_ue(TestHdlrParams pars) return RANAP_PDU {
598 var LAI lai := {
599 pLMNidentity := hex2oct(pars.hnb.lai.mcc_mnc),
600 lAC := int2oct(pars.hnb.lai.lac, 2),
601 iE_Extensions := omit
602 };
603 var SAI sai := {
604 pLMNidentity := lai.pLMNidentity,
605 lAC := lai.lAC,
606 sAC := int2oct(pars.hnb.sac, 2),
607 iE_Extensions := omit
608 }
609 var octetstring nas := f_rnd_octstring(10);
610 var IuSignallingConnectionIdentifier sigc_id := int2bit(f_rnd_int(1000), 24);
611 var GlobalRNC_ID grnc_id := {
612 pLMNidentity := lai.pLMNidentity,
613 rNC_ID := 2342
614 }
615
616 if (pars.ps_domain) {
617 var RAC rac := '00'O;
618 return valueof(ts_RANAP_initialUE_PS(lai, rac, sai, nas, sigc_id, grnc_id));
619 } else {
620 return valueof(ts_RANAP_initialUE_CS(lai, sai, nas, sigc_id, grnc_id));
621 }
622}
623
624/* build a RANAP RAB AssignmentResponse based on the TestHdlrParams */
625friend function f_build_rab_ass_resp(TestHdlrParams pars) return RANAP_PDU {
626 var template RAB_SetupOrModifiedList rab_sml;
627
628 rab_sml := ts_RAB_SMdL(t_RAB_id(23), f_ts_RAB_TLA("192.168.1.23"), t_RAB_binding_port(1234));
629
630 return valueof(ts_RANAP_RabAssResp(rab_sml));
631}
632
633
634/***********************************************************************
635 * HNBAP Testing
636 ***********************************************************************/
637
638
Daniel Willmannc79679a2022-08-23 17:48:39 +0200639function f_hnbap_register(integer hnb_idx := 0, integer cell_id := 0, boolean expect_reject := false) runs on test_CT
Daniel Willmann19b8d902022-01-05 09:12:34 +0100640{
641 timer T := 2.0;
642
Daniel Willmann28209ec2022-08-24 09:58:07 +0200643 HNBAP[hnb_idx].send(ts_HNBAP_HNBRegisterRequest(char2oct("TTCN3 HNodeB"),
Daniel Willmann19b8d902022-01-05 09:12:34 +0100644 '00F110'O,
Daniel Willmannc79679a2022-08-23 17:48:39 +0200645 int2bit(1 + cell_id, 28),
Daniel Willmann19b8d902022-01-05 09:12:34 +0100646 int2oct(2, 2),
647 int2oct(3, 1),
648 int2oct(4, 2)));
649
650 T.start;
651 alt {
652 [] HNBAP[hnb_idx].receive(tr_HNBAP_HNBRegisterAccept(?)) {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200653 if (expect_reject) {
654 setverdict(fail, "Rx HNB Register Accept while expecting reject");
655 } else {
656 setverdict(pass);
657 }
658 }
659 [] HNBAP[hnb_idx].receive(tr_HNBAP_HNBRegisterReject(?)) {
660 if (expect_reject) {
661 setverdict(pass);
662 } else {
663 setverdict(fail, "Rx HNB Register Reject while expecting accept");
664 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100665 }
666 [] HNBAP[hnb_idx].receive(IUHEM_Event:?) {
667 repeat;
668 }
669 [] T.timeout {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200670 setverdict(fail, "Timeout waiting for HNB Register response");
Daniel Willmann19b8d902022-01-05 09:12:34 +0100671 }
672 }
673}
674
675testcase TC_hnb_register() runs on test_CT {
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200676 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100677 f_init();
678 f_hnbap_register(0);
679 f_shutdown_helper();
680}
681
Daniel Willmannc79679a2022-08-23 17:48:39 +0200682testcase TC_hnb_register_duplicate() runs on test_CT {
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200683 g_num_hnbs := 2;
Daniel Willmannc79679a2022-08-23 17:48:39 +0200684 f_init();
685 f_hnbap_register(0);
686 f_hnbap_register(1, 0, expect_reject := true);
687 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
688 f_shutdown_helper();
689}
690
Daniel Willmann19b8d902022-01-05 09:12:34 +0100691/***********************************************************************
692 * RUA / RANAP Testing
693 ***********************************************************************/
694
695private template (value) TestHdlrParams
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200696t_pars(integer imsi_suffix, boolean ps_domain := false, integer hnb_idx := 0,
697 boolean separate_sccp_cr := false) := {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100698 hnb_idx := hnb_idx,
699 imsi := f_gen_imsi(imsi_suffix),
700 ps_domain := ps_domain,
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200701 hnb := omit, /* filled in later */
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200702 separate_sccp_cr := separate_sccp_cr,
703 pfcp_local_addr := mp_pfcp_ip_local
Daniel Willmann19b8d902022-01-05 09:12:34 +0100704}
705
706/* Create an Iuh connection; send InitialUE; expect it to appear on new SCCP conenction */
707friend function f_tc_initial_ue(charstring id, TestHdlrParams pars) runs on ConnHdlr {
708 f_init_handler(pars);
709 var RANAP_PDU tx := f_build_initial_ue(g_pars);
710 f_iuh2iu_connect(tx);
711}
712testcase TC_ranap_cs_initial_ue() runs on test_CT {
713 var ConnHdlr vc_conn;
714
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200715 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100716 f_init();
717 f_start_hnbs();
718
719 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(1));
720 vc_conn.done;
721}
722testcase TC_ranap_ps_initial_ue() runs on test_CT {
723 var ConnHdlr vc_conn;
724
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200725 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100726 f_init();
727 f_start_hnbs();
728
729 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(2, true));
730 vc_conn.done;
731}
732
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200733private function f_vty_set_sccp_cr_max_payload_len(TELNETasp_PT pt, integer val := 999999)
734{
735 f_vty_enter_config(pt);
736 f_vty_transceive(pt, "hnbgw");
737 f_vty_transceive(pt, "sccp cr max-payload-len " & int2str(val));
738 f_vty_transceive(pt, "end");
739}
740
741testcase TC_ranap_cs_initial_ue_empty_cr() runs on test_CT {
742 var ConnHdlr vc_conn;
743
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200744 g_num_hnbs := 1;
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200745 f_init();
746 f_start_hnbs();
747
748 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY, 0);
749
750 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(1, separate_sccp_cr := true));
751 vc_conn.done;
752
753 /* reset */
754 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY);
755}
756testcase TC_ranap_ps_initial_ue_empty_cr() runs on test_CT {
757 var ConnHdlr vc_conn;
758
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200759 g_num_hnbs := 1;
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200760 f_init();
761 f_start_hnbs();
762
763 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY, 0);
764
765 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(2, true, separate_sccp_cr := true));
766 vc_conn.done;
767
768 /* reset */
769 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY);
770}
771
Daniel Willmann19b8d902022-01-05 09:12:34 +0100772/* Reply to a received CRCX with an OK (or the reply configured in cpars), using the given parameters.
773 * Return true when an OK reply was sent, false otherwise.
774 * Count occurrence of Osmux, include Osmux parameters in the reply if necessary. */
775function f_handle_crcx(inout MgcpParameters pars, MgcpCommand mgcp_cmd) return template MgcpResponse {
776 var CrcxResponse conn := pars.mgw_conn_1;
777 if (pars.got_crcx_count > 0) {
778 conn := pars.mgw_conn_2;
779 }
780 pars.got_crcx_count := pars.got_crcx_count + 1;
781
782 var MgcpMessage mgcp_msg := {
783 command := mgcp_cmd
784 }
785 var template MgcpResponse mgcp_resp;
786 var MgcpOsmuxCID osmux_cid;
787 var MgcpCallId call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
788 if (ispresent(pars.mgcp_call_id)) {
789 if (pars.mgcp_call_id != call_id) {
790 setverdict(fail, "CRCX contained unexpected call id. Expected:", pars.mgcp_call_id, " got:", call_id);
791 mtc.stop;
792 }
793 } else {
794 pars.mgcp_call_id := call_id;
795 }
796
797 /* When the endpoint contains a wildcard we keep the endpoint
798 * identifier we have set up in pars. Otherwise we use the
799 * endpoint name that the call agent has supplied */
800 if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard) == false) {
801 pars.mgcp_ep := mgcp_cmd.line.ep;
802 }
803
804 if (conn.resp == -1) {
805 /* Reply with rror */
806 var MgcpResponse mgcp_rsp := {
807 line := {
808 code := "542",
809 trans_id := mgcp_cmd.line.trans_id,
810 string := "FORCED_FAIL"
811 },
812 sdp := omit
813
814 }
815 var MgcpParameter mgcp_rsp_param := {
816 code := "Z",
817 val := pars.mgcp_ep
818 };
819 mgcp_rsp.params[0] := mgcp_rsp_param;
820 return mgcp_rsp;
821 }
822
823 if (conn.resp == 0) {
824 /* Do not reply at all */
825 return omit;
826 }
827
828 if (conn.resp != 1) {
829 setverdict(fail, "Unexpected value for pars.mgw_conn_*.resp, expect -1, 0 or 1");
830 mtc.stop;
831 }
832
833 var SDP_Message sdp := valueof(ts_SDP(conn.mgw_rtp_ip, conn.mgw_rtp_ip,
834 hex2str(pars.mgcp_call_id), "42",
835 conn.mgw_rtp_port,
836 { int2str(pars.rtp_payload_type) },
837 { valueof(ts_SDP_rtpmap(pars.rtp_payload_type,
838 pars.rtp_sdp_format)),
839 valueof(ts_SDP_ptime(20)) }));
840
841 if (f_mgcp_contains_par(mgcp_msg, "X-OSMUX")) {
842 if (not pars.use_osmux) {
843 setverdict(fail, "MSC sent X-Osmux parameter in MGCP, but not expecting any Osmux");
844 mtc.stop;
845 }
846 pars.got_osmux_count := pars.got_osmux_count + 1;
847 /* we expect MSC to use wildcard here, i.e. osmux_cid == -1 */
848 osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
849 log("f_handle_crcx(): got Osmux CID: ", osmux_cid);
850 if (osmux_cid != -1) {
851 setverdict(fail, "MSC using unexpected CID " & int2str(osmux_cid) & " != -1");
852 mtc.stop;
853 }
854
855 osmux_cid := 0;
856 mgcp_resp := ts_CRCX_ACK_osmux(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, osmux_cid, sdp);
857 } else {
858 mgcp_resp := ts_CRCX_ACK(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, sdp);
859 }
860
861 f_mgcp_par_append(mgcp_resp.params, ts_MgcpParSpecEP(pars.mgcp_ep));
862
863 return mgcp_resp;
864}
865
Daniel Willmann3e15b7b2022-02-21 17:07:02 +0100866friend function f_create_rab(inout MgcpParameters pars) runs on ConnHdlr {
867 f_rab_ass_req(pars);
868 f_rab_ass_resp(pars);
869}
870
871friend function f_rab_ass_req(inout MgcpParameters pars) runs on ConnHdlr {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100872 var MgcpCommand mgcp_cmd;
873 var RANAP_PDU tx;
874 var template RAB_SetupOrModifyList rab_sml;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100875 timer T := 5.0;
876
877 /* Send RAB Assignment Request */
878 rab_sml := ts_RAB_SML(t_RAB_id(23), f_ts_RAB_TLA(pars.cn_rtp_ip), t_RAB_binding_port(pars.cn_rtp_port));
879 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
880 BSSAP.send(tx);
881 T.start;
882
883 /* Handle MGCP CRCX */
884 alt {
885 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
886 log("CRCX1", mgcp_cmd);
887 var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
888 MGCP.send(valueof(mgcp_rsp));
889 }
890 [] T.timeout {
891 setverdict(fail, "Timeout waiting for MGCP");
892 }
893 }
894
895 /* Expect RAB Assignment Request with IP/port from CRCX ACK via Iuh */
896 rab_sml := ts_RAB_SML(t_RAB_id(23), f_ts_RAB_TLA(pars.mgw_conn_1.mgw_rtp_ip), t_RAB_binding_port(pars.mgw_conn_1.mgw_rtp_port));
897 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
898
899 alt {
900 [] RUA.receive(tx) {
901 setverdict(pass);
902 }
903 [] T.timeout {
904 setverdict(fail, "Timeout waiting for Iuh ", tx);
905 }
906 }
Daniel Willmann3e15b7b2022-02-21 17:07:02 +0100907}
908
909friend function f_rab_ass_resp(inout MgcpParameters pars) runs on ConnHdlr {
910 var MgcpCommand mgcp_cmd;
911 var RANAP_PDU tx;
912 var template RAB_SetupOrModifiedList rab_smdl;
913 timer T := 5.0;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100914
915 /* Send back RAB Assignment Response via Iuh */
916 rab_smdl := ts_RAB_SMdL(t_RAB_id(23), f_ts_RAB_TLA(pars.hnb_rtp_ip), t_RAB_binding_port(pars.hnb_rtp_port));
917 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
918 RUA.send(tx);
919 T.start;
920
921 interleave {
922 /* Expect MDCX with IP/port from RAB Assignment Response */
923 [] MGCP.receive(tr_MDCX(tr_SDP(pars.hnb_rtp_ip, pars.hnb_rtp_port))) -> value mgcp_cmd {
924 log("MDCX1", mgcp_cmd);
925 /* Verify SDP of MDCX */
926 var SDP_Message sdp := valueof(ts_SDP(pars.mgw_conn_1.mgw_rtp_ip, pars.mgw_conn_1.mgw_rtp_ip, hex2str(pars.mgcp_call_id), "42", pars.mgw_conn_1.mgw_rtp_port,
927 { int2str(pars.rtp_payload_type) }, { valueof(ts_SDP_rtpmap(pars.rtp_payload_type, pars.rtp_sdp_format)), valueof(ts_SDP_ptime(20)) } ));
928 var template MgcpResponse mgcp_rsp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, pars.mgw_conn_1.mgcp_connection_id, sdp);
929 MGCP.send(valueof(mgcp_rsp));
930 }
931 /* Handle CRCX for second leg of endpoint, answer with IP/port */
932 [] MGCP.receive(tr_CRCX(pars.mgcp_ep, tr_SDP(pars.cn_rtp_ip, pars.cn_rtp_port))) -> value mgcp_cmd {
933 log("CRCX2", mgcp_cmd);
934 /* Verify SDP of CRCX */
935 var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
936 MGCP.send(valueof(mgcp_rsp));
937 }
938 }
939
940 /* Expect RAB Assignment Response with IP/port from second CRCX ACK */
941 rab_smdl := ts_RAB_SMdL(t_RAB_id(23), f_ts_RAB_TLA(pars.mgw_conn_2.mgw_rtp_ip), t_RAB_binding_port(pars.mgw_conn_2.mgw_rtp_port));
942 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
943
944 alt {
945 [] BSSAP.receive(tx) {
946 setverdict(pass);
947 }
948 [] T.timeout {
949 setverdict(fail, "Timeout waiting for Iuh ", tx);
950 }
951 }
952}
953
954private altstep as_mgcp_dlcx(inout TestHdlrParams pars) runs on ConnHdlr {
955 var MgcpCommand mgcp_cmd;
956
957 [] MGCP.receive(tr_DLCX(pars.mgcp_pars.mgcp_ep)) -> value mgcp_cmd {
958 log("DLCX", mgcp_cmd);
959 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
960 pars.mgcp_pars.got_dlcx_count := pars.mgcp_pars.got_dlcx_count + 1;
Daniel Willmann3e15b7b2022-02-21 17:07:02 +0100961 if (pars.mgcp_pars.got_dlcx_count != pars.mgcp_pars.got_crcx_count) {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100962 repeat;
963 }
964 setverdict(pass);
965 }
966}
967
968friend function f_tc_rab_assignment(charstring id, TestHdlrParams pars) runs on ConnHdlr {
969 var MgcpCommand mgcp_cmd;
970 var RANAP_PDU tx;
971 timer T := 5.0;
972
973 f_init_handler(pars);
974 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
975
976 tx := f_build_initial_ue(g_pars);
977 f_iuh2iu_connect(tx);
978
979 f_create_rab(pars.mgcp_pars);
980
981 /* Send Iu Release */
982 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
983 f_iu2iuh(tx);
984
985 T.start;
986 alt {
987 [] as_mgcp_dlcx(pars) {}
988 [] T.timeout {
989 setverdict(fail, "Timeout waiting for DLCX");
990 }
991 }
992
993 tx := valueof(ts_RANAP_IuReleaseComplete());
994 f_iuh2iu(tx);
995}
996
997testcase TC_rab_assignment() runs on test_CT {
998 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200999 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001000 f_init();
1001 f_start_hnbs();
1002
1003 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assignment), t_pars(3));
1004 vc_conn.done;
1005}
1006
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001007friend function f_tc_rab_assign_fail(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1008 var MgcpCommand mgcp_cmd;
1009 var RANAP_PDU tx;
1010 timer T := 5.0;
1011
1012 f_init_handler(pars);
1013 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1014
1015 tx := f_build_initial_ue(g_pars);
1016 f_iuh2iu_connect(tx);
1017
1018 f_rab_ass_req(pars.mgcp_pars);
1019
1020 /* Send RAB failed list in response */
1021 tx := valueof(ts_RANAP_RabAssResp(rab_fl := ts_RAB_FL(t_RAB_id(23), ts_RanapCause_om_intervention)));
1022 f_iuh2iu(tx);
1023
1024 T.start;
1025 alt {
1026 [] as_mgcp_dlcx(pars) {}
1027 [] T.timeout {
1028 setverdict(fail, "Timeout waiting for DLCX");
1029 }
1030 }
1031}
1032
1033testcase TC_rab_assign_fail() runs on test_CT {
1034 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001035 g_num_hnbs := 1;
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001036 f_init();
1037 f_start_hnbs();
1038
1039 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_fail), t_pars(4));
1040 vc_conn.done;
1041}
1042
Daniel Willmann19b8d902022-01-05 09:12:34 +01001043friend function f_tc_rab_release(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1044 var MgcpCommand mgcp_cmd;
1045 var RANAP_PDU tx;
1046 timer T := 15.0;
1047
1048 f_init_handler(pars);
1049 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1050
1051 tx := f_build_initial_ue(g_pars);
1052 f_iuh2iu_connect(tx);
1053
1054 f_create_rab(pars.mgcp_pars);
1055
1056 /* Send RAB Release */
Daniel Willmann9e789be2022-02-22 13:30:51 +01001057 tx := valueof(ts_RANAP_RabAssReq(rab_rl := ts_RAB_RL(t_RAB_id(23), ts_RanapCause_om_intervention)));
Daniel Willmann19b8d902022-01-05 09:12:34 +01001058 BSSAP.send(tx);
1059
1060 T.start;
1061
1062 alt {
1063 [] as_mgcp_dlcx(pars) {}
1064 [] T.timeout {
1065 setverdict(fail, "Timeout waiting for DLCX");
1066 }
1067 }
1068
1069 alt {
1070 [] RUA.receive(tx) {
1071 setverdict(pass);
1072 }
1073 [] T.timeout {
1074 setverdict(fail, "Timeout waiting for Iuh ", tx);
1075 }
1076 }
1077
1078}
1079
1080testcase TC_rab_release() runs on test_CT {
1081 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001082 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001083 f_init();
1084 f_start_hnbs();
1085
1086 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_release), t_pars(5));
1087 vc_conn.done;
1088}
1089
Daniel Willmann37c877f2022-02-22 16:47:06 +01001090friend function f_tc_rab_assign_mgcp_to(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1091 var MgcpCommand mgcp_cmd;
1092 var RANAP_PDU tx;
1093 var template RAB_SetupOrModifyList rab_sml;
1094 timer T := 15.0;
1095
1096 T.start;
1097 f_init_handler(pars);
1098 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1099
1100 tx := f_build_initial_ue(g_pars);
1101 f_iuh2iu_connect(tx);
1102
1103
1104 /* Send RAB Assignment Request */
1105 rab_sml := ts_RAB_SML(t_RAB_id(23), f_ts_RAB_TLA(pars.mgcp_pars.cn_rtp_ip), t_RAB_binding_port(pars.mgcp_pars.cn_rtp_port));
1106 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1107 BSSAP.send(tx);
1108
1109 /* Ignore MGCP CRCX */
1110 alt {
1111 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
1112 log("Ignoreing CRCX1", mgcp_cmd);
1113 repeat;
1114 }
1115 [] BSSAP.receive(tr_RANAP_IuReleaseRequest(?)) { }
1116 [] T.timeout {
1117 setverdict(fail, "Timeout waiting for IuRelease");
1118 }
1119 }
1120
1121 /* Send Iu Release */
1122 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1123 f_iu2iuh(tx);
1124
1125 tx := valueof(ts_RANAP_IuReleaseComplete());
1126 f_iuh2iu(tx);
1127}
1128
1129testcase TC_rab_assign_mgcp_to() runs on test_CT {
1130 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001131 g_num_hnbs := 1;
Daniel Willmann37c877f2022-02-22 16:47:06 +01001132 f_init();
1133 f_start_hnbs();
1134
1135 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_mgcp_to), t_pars(6));
1136 vc_conn.done;
1137}
1138
Daniel Willmann19b8d902022-01-05 09:12:34 +01001139/* Create an Iuh connection; send InitialUE; transceive data both directions */
1140friend function f_tc_ranap_bidir(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1141 f_init_handler(pars);
1142
1143 /* HNB -> MSC: InitialUE */
1144 f_iuh2iu_connect(f_build_initial_ue(g_pars));
1145
1146 /* MSC <- HNB: DirectTransfer */
1147 f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1148 /* MSC -> HNB: DirectTransfer */
1149 f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1150
1151 /* HNB <- MSC: CommonID */
1152 f_iu2iuh(ts_RANAP_CommonId(hex2oct(pars.imsi)));
1153}
1154testcase TC_ranap_cs_bidir() runs on test_CT {
1155 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001156 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001157 f_init();
1158 f_start_hnbs();
1159
1160 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(3));
1161 vc_conn.done;
1162}
1163testcase TC_ranap_ps_bidir() runs on test_CT {
1164 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001165 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001166 f_init();
1167 f_start_hnbs();
1168
1169 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(4, true));
1170 vc_conn.done;
1171}
1172
1173
1174private function f_tc_ranap_mo_disconnect(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1175 f_init_handler(pars);
1176
1177 /* HNB -> MSC: InitialUE */
1178 f_iuh2iu_connect(f_build_initial_ue(g_pars));
1179
1180 /* MSC <- HNB: DirectTransfer */
1181 f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1182 /* MSC -> HNB: DirectTransfer */
1183 f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1184
1185 /* MSC <- HNB: RUA disconnect */
1186 f_iuh2iu_disconnect(ts_RANAP_IuReleaseComplete, RUA_IEs.Cause:{misc:=processing_overload});
1187}
1188testcase TC_ranap_cs_mo_disconnect() runs on test_CT {
1189 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001190 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001191 f_init();
1192 f_start_hnbs();
1193
1194 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(5));
1195 vc_conn.done;
1196}
1197testcase TC_ranap_ps_mo_disconnect() runs on test_CT {
1198 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001199 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001200 f_init();
1201 f_start_hnbs();
1202
1203 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(6));
1204 vc_conn.done;
1205}
1206
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001207type record FTeid {
1208 HostName addr,
1209 OCT4 teid
1210}
1211
1212type record FTeids {
1213 FTeid local,
1214 FTeid remote
1215}
Daniel Willmann19b8d902022-01-05 09:12:34 +01001216
1217
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001218/* 'local' and 'remote' refer to the GTP information from the UPF's point of view:
1219 * HNB UPF CN
1220 * access.remote <---> access.local | core.local <---> core.remote
1221 */
1222type record GtpParameters {
1223 FTeids core,
1224 FTeids access
1225}
1226
1227/* HNB UPF CN
1228 * access.remote <---> access.local | core.local <---> core.remote
1229 * 127.0.0.4 127.0.0.3 127.0.0.2 127.0.0.1
1230 * 0x44004400 0x30303030 0x22002200 0x10101010
1231 */
1232template GtpParameters t_GtpParameters := {
1233 core := {
1234 local := {
1235 addr := "127.0.0.2",
1236 teid := '22002200'O
1237 },
1238 remote := {
1239 addr := "127.0.0.1",
1240 teid := '10101010'O
1241 }
1242 },
1243 access := {
1244 local := {
1245 addr := "127.0.0.3",
1246 teid := '30303030'O
1247 },
1248 remote := {
1249 addr := "127.0.0.4",
1250 teid := '44004400'O
1251 }
1252 }
1253}
1254
1255friend function f_tc_ps_rab_assignment(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1256 var RANAP_PDU tx;
1257 var RANAP_PDU rx;
1258 timer T := 5.0;
1259
1260 f_init_handler(pars);
1261
1262 f_pfcp_register();
1263
1264 var PDU_PFCP m;
1265 var Node_ID upf_node_id := valueof(ts_PFCP_Node_ID_fqdn("\07osmocom\03org"));
1266
1267 PFCP.receive(tr_PFCP_Assoc_Setup_Req()) -> value m;
1268 PFCP.send(ts_PFCP_Assoc_Setup_Resp(m.sequence_number, upf_node_id,
1269 ts_PFCP_Cause(REQUEST_ACCEPTED), 1234));
1270
1271 tx := f_build_initial_ue(g_pars);
1272 f_iuh2iu_connect(tx);
1273
1274 var GtpParameters gtp_pars := valueof(t_GtpParameters);
1275 var template RAB_SetupOrModifyList rab_sml;
1276
1277 /* Send RAB Assignment Request */
1278 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.remote.addr), gtp_pars.core.remote.teid);
1279 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1280 BSSAP.send(tx);
1281
1282 /* Expect PFCP Session Establishment Request. */
1283 PFCP.receive(tr_PFCP_Session_Est_Req()) -> value m;
1284 var F_SEID hnbgw_f_seid := m.message_body.pfcp_session_establishment_request.CP_F_SEID;
1285 var PFCP_Session_Establishment_Request serq := m.message_body.pfcp_session_establishment_request;
1286
1287 /* Acting as UPF, invent a new PFCP SEID to send to HNBGW. Respond to the Session Establishment.
1288 * The PFCP response must have the same sequence_number as the request. */
1289 var F_SEID up_f_seid := valueof(ts_PFCP_F_SEID_ipv4("127.0.0.1", '1111111111111111'O));
1290 var template PDU_PFCP r := ts_PFCP_Session_Est_Resp(m.sequence_number, upf_node_id, hnbgw_f_seid.seid);
1291 r.message_body.pfcp_session_establishment_response := {
1292 offending_ie := omit,
1293 UP_F_SEID := up_f_seid,
1294 created_PDR_list := {
1295 ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[0].grouped_ie.pdr_id,
1296 local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.core.local.teid,
1297 gtp_pars.core.local.addr)),
1298 ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[1].grouped_ie.pdr_id,
1299 local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.access.local.teid,
1300 gtp_pars.access.local.addr))
1301 },
1302 load_control_information := omit,
1303 overload_control_information := omit,
1304 node_list := omit,
1305 failed_rule_id := omit,
1306 created_traffic_endpoint_list := omit
1307 };
1308 PFCP.send(r);
1309
1310 /* Expect on Iuh: RAB Assignment Request with IP/port from PFCP Session Est Resp */
1311 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.local.addr),
1312 gtp_pars.access.local.teid);
1313 rx := valueof(ts_RANAP_RabAssReq(rab_sml));
1314 RUA.receive(rx);
1315
1316 /* Send back RAB Assignment Response via Iuh */
1317 var template RAB_SetupOrModifiedList rab_smdl;
1318 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.remote.addr),
1319 gtp_pars.access.remote.teid);
1320 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1321 RUA.send(tx);
1322 T.start;
1323
1324 PFCP.receive(tr_PFCP_Session_Mod_Req(up_f_seid.seid)) -> value m;
1325 r := ts_PFCP_Session_Mod_Resp(m.sequence_number, hnbgw_f_seid.seid);
1326 PFCP.send(r);
1327
1328 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.local.addr), gtp_pars.core.local.teid);
1329 BSSAP.receive(tr_RANAP_RabAssResp(rab_smdl));
1330
1331 f_sleep(2.0);
1332 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1333 f_iu2iuh(tx);
1334
1335 tx := valueof(ts_RANAP_IuReleaseComplete());
1336 f_iuh2iu(tx);
1337
1338 PFCP.receive(tr_PFCP_Session_Del_Req(up_f_seid.seid)) -> value m;
1339 PFCP.send(ts_PFCP_Session_Del_Resp(m.sequence_number, hnbgw_f_seid.seid));
1340
1341 f_sleep(2.0);
1342}
1343
1344testcase TC_ps_rab_assignment() runs on test_CT {
1345 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001346 g_num_hnbs := 1;
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001347 f_init();
1348 f_start_hnbs();
1349 f_sleep(1.0);
1350
1351 vc_conn := f_start_handler_with_pars(refers(f_tc_ps_rab_assignment), t_pars(7, ps_domain := true));
1352 vc_conn.done;
1353}
Daniel Willmann19b8d902022-01-05 09:12:34 +01001354
1355control {
1356 execute(TC_hnb_register());
Daniel Willmannc79679a2022-08-23 17:48:39 +02001357 execute(TC_hnb_register_duplicate());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001358 execute(TC_ranap_cs_initial_ue());
1359 execute(TC_ranap_ps_initial_ue());
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02001360 execute(TC_ranap_cs_initial_ue_empty_cr());
1361 execute(TC_ranap_ps_initial_ue_empty_cr());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001362 execute(TC_ranap_cs_bidir());
1363 execute(TC_ranap_ps_bidir());
1364 execute(TC_rab_assignment());
1365 execute(TC_rab_release());
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001366 execute(TC_rab_assign_fail());
Daniel Willmann37c877f2022-02-22 16:47:06 +01001367 execute(TC_rab_assign_mgcp_to());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001368 execute(TC_ranap_cs_mo_disconnect());
1369 execute(TC_ranap_ps_mo_disconnect());
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001370 execute(TC_ps_rab_assignment());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001371}
1372
1373}