blob: 19df73e00f64d5d402e3588e680c93fa27a90948 [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
Pau Espin Pedrolf0b9fa02022-09-12 13:31:07 +0200691/* Drop HNBAP conn (HNBAP DEREG) and reconnect it (HNBAP REG) using same SCTP association.
692 * Related: OS#5676, SYS#6113 */
693testcase TC_hnb_reregister_reuse_sctp_assoc() runs on test_CT {
694 g_num_hnbs := 1;
695 f_init();
696 f_hnbap_register(0);
697 HNBAP[0].send(ts_HNBAP_HNBDe_Register(ts_HnbapCause(unspecified)));
698 f_hnbap_register(0);
699 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
700 f_shutdown_helper();
701}
702
Daniel Willmann19b8d902022-01-05 09:12:34 +0100703/***********************************************************************
704 * RUA / RANAP Testing
705 ***********************************************************************/
706
707private template (value) TestHdlrParams
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200708t_pars(integer imsi_suffix, boolean ps_domain := false, integer hnb_idx := 0,
709 boolean separate_sccp_cr := false) := {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100710 hnb_idx := hnb_idx,
711 imsi := f_gen_imsi(imsi_suffix),
712 ps_domain := ps_domain,
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200713 hnb := omit, /* filled in later */
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200714 separate_sccp_cr := separate_sccp_cr,
715 pfcp_local_addr := mp_pfcp_ip_local
Daniel Willmann19b8d902022-01-05 09:12:34 +0100716}
717
718/* Create an Iuh connection; send InitialUE; expect it to appear on new SCCP conenction */
719friend function f_tc_initial_ue(charstring id, TestHdlrParams pars) runs on ConnHdlr {
720 f_init_handler(pars);
721 var RANAP_PDU tx := f_build_initial_ue(g_pars);
722 f_iuh2iu_connect(tx);
723}
724testcase TC_ranap_cs_initial_ue() runs on test_CT {
725 var ConnHdlr vc_conn;
726
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200727 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100728 f_init();
729 f_start_hnbs();
730
731 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(1));
732 vc_conn.done;
733}
734testcase TC_ranap_ps_initial_ue() runs on test_CT {
735 var ConnHdlr vc_conn;
736
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200737 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100738 f_init();
739 f_start_hnbs();
740
741 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(2, true));
742 vc_conn.done;
743}
744
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200745private function f_vty_set_sccp_cr_max_payload_len(TELNETasp_PT pt, integer val := 999999)
746{
747 f_vty_enter_config(pt);
748 f_vty_transceive(pt, "hnbgw");
749 f_vty_transceive(pt, "sccp cr max-payload-len " & int2str(val));
750 f_vty_transceive(pt, "end");
751}
752
753testcase TC_ranap_cs_initial_ue_empty_cr() runs on test_CT {
754 var ConnHdlr vc_conn;
755
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200756 g_num_hnbs := 1;
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200757 f_init();
758 f_start_hnbs();
759
760 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY, 0);
761
762 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(1, separate_sccp_cr := true));
763 vc_conn.done;
764
765 /* reset */
766 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY);
767}
768testcase TC_ranap_ps_initial_ue_empty_cr() runs on test_CT {
769 var ConnHdlr vc_conn;
770
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200771 g_num_hnbs := 1;
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200772 f_init();
773 f_start_hnbs();
774
775 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY, 0);
776
777 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(2, true, separate_sccp_cr := true));
778 vc_conn.done;
779
780 /* reset */
781 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY);
782}
783
Daniel Willmann19b8d902022-01-05 09:12:34 +0100784/* Reply to a received CRCX with an OK (or the reply configured in cpars), using the given parameters.
785 * Return true when an OK reply was sent, false otherwise.
786 * Count occurrence of Osmux, include Osmux parameters in the reply if necessary. */
787function f_handle_crcx(inout MgcpParameters pars, MgcpCommand mgcp_cmd) return template MgcpResponse {
788 var CrcxResponse conn := pars.mgw_conn_1;
789 if (pars.got_crcx_count > 0) {
790 conn := pars.mgw_conn_2;
791 }
792 pars.got_crcx_count := pars.got_crcx_count + 1;
793
794 var MgcpMessage mgcp_msg := {
795 command := mgcp_cmd
796 }
797 var template MgcpResponse mgcp_resp;
798 var MgcpOsmuxCID osmux_cid;
799 var MgcpCallId call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
800 if (ispresent(pars.mgcp_call_id)) {
801 if (pars.mgcp_call_id != call_id) {
802 setverdict(fail, "CRCX contained unexpected call id. Expected:", pars.mgcp_call_id, " got:", call_id);
803 mtc.stop;
804 }
805 } else {
806 pars.mgcp_call_id := call_id;
807 }
808
809 /* When the endpoint contains a wildcard we keep the endpoint
810 * identifier we have set up in pars. Otherwise we use the
811 * endpoint name that the call agent has supplied */
812 if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard) == false) {
813 pars.mgcp_ep := mgcp_cmd.line.ep;
814 }
815
816 if (conn.resp == -1) {
817 /* Reply with rror */
818 var MgcpResponse mgcp_rsp := {
819 line := {
820 code := "542",
821 trans_id := mgcp_cmd.line.trans_id,
822 string := "FORCED_FAIL"
823 },
824 sdp := omit
825
826 }
827 var MgcpParameter mgcp_rsp_param := {
828 code := "Z",
829 val := pars.mgcp_ep
830 };
831 mgcp_rsp.params[0] := mgcp_rsp_param;
832 return mgcp_rsp;
833 }
834
835 if (conn.resp == 0) {
836 /* Do not reply at all */
837 return omit;
838 }
839
840 if (conn.resp != 1) {
841 setverdict(fail, "Unexpected value for pars.mgw_conn_*.resp, expect -1, 0 or 1");
842 mtc.stop;
843 }
844
845 var SDP_Message sdp := valueof(ts_SDP(conn.mgw_rtp_ip, conn.mgw_rtp_ip,
846 hex2str(pars.mgcp_call_id), "42",
847 conn.mgw_rtp_port,
848 { int2str(pars.rtp_payload_type) },
849 { valueof(ts_SDP_rtpmap(pars.rtp_payload_type,
850 pars.rtp_sdp_format)),
851 valueof(ts_SDP_ptime(20)) }));
852
853 if (f_mgcp_contains_par(mgcp_msg, "X-OSMUX")) {
854 if (not pars.use_osmux) {
855 setverdict(fail, "MSC sent X-Osmux parameter in MGCP, but not expecting any Osmux");
856 mtc.stop;
857 }
858 pars.got_osmux_count := pars.got_osmux_count + 1;
859 /* we expect MSC to use wildcard here, i.e. osmux_cid == -1 */
860 osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
861 log("f_handle_crcx(): got Osmux CID: ", osmux_cid);
862 if (osmux_cid != -1) {
863 setverdict(fail, "MSC using unexpected CID " & int2str(osmux_cid) & " != -1");
864 mtc.stop;
865 }
866
867 osmux_cid := 0;
868 mgcp_resp := ts_CRCX_ACK_osmux(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, osmux_cid, sdp);
869 } else {
870 mgcp_resp := ts_CRCX_ACK(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, sdp);
871 }
872
873 f_mgcp_par_append(mgcp_resp.params, ts_MgcpParSpecEP(pars.mgcp_ep));
874
875 return mgcp_resp;
876}
877
Daniel Willmann3e15b7b2022-02-21 17:07:02 +0100878friend function f_create_rab(inout MgcpParameters pars) runs on ConnHdlr {
879 f_rab_ass_req(pars);
880 f_rab_ass_resp(pars);
881}
882
883friend function f_rab_ass_req(inout MgcpParameters pars) runs on ConnHdlr {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100884 var MgcpCommand mgcp_cmd;
885 var RANAP_PDU tx;
886 var template RAB_SetupOrModifyList rab_sml;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100887 timer T := 5.0;
888
889 /* Send RAB Assignment Request */
890 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));
891 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
892 BSSAP.send(tx);
893 T.start;
894
895 /* Handle MGCP CRCX */
896 alt {
897 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
898 log("CRCX1", mgcp_cmd);
899 var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
900 MGCP.send(valueof(mgcp_rsp));
901 }
902 [] T.timeout {
903 setverdict(fail, "Timeout waiting for MGCP");
904 }
905 }
906
907 /* Expect RAB Assignment Request with IP/port from CRCX ACK via Iuh */
908 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));
909 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
910
911 alt {
912 [] RUA.receive(tx) {
913 setverdict(pass);
914 }
915 [] T.timeout {
916 setverdict(fail, "Timeout waiting for Iuh ", tx);
917 }
918 }
Daniel Willmann3e15b7b2022-02-21 17:07:02 +0100919}
920
921friend function f_rab_ass_resp(inout MgcpParameters pars) runs on ConnHdlr {
922 var MgcpCommand mgcp_cmd;
923 var RANAP_PDU tx;
924 var template RAB_SetupOrModifiedList rab_smdl;
925 timer T := 5.0;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100926
927 /* Send back RAB Assignment Response via Iuh */
928 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));
929 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
930 RUA.send(tx);
931 T.start;
932
933 interleave {
934 /* Expect MDCX with IP/port from RAB Assignment Response */
935 [] MGCP.receive(tr_MDCX(tr_SDP(pars.hnb_rtp_ip, pars.hnb_rtp_port))) -> value mgcp_cmd {
936 log("MDCX1", mgcp_cmd);
937 /* Verify SDP of MDCX */
938 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,
939 { int2str(pars.rtp_payload_type) }, { valueof(ts_SDP_rtpmap(pars.rtp_payload_type, pars.rtp_sdp_format)), valueof(ts_SDP_ptime(20)) } ));
940 var template MgcpResponse mgcp_rsp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, pars.mgw_conn_1.mgcp_connection_id, sdp);
941 MGCP.send(valueof(mgcp_rsp));
942 }
943 /* Handle CRCX for second leg of endpoint, answer with IP/port */
944 [] MGCP.receive(tr_CRCX(pars.mgcp_ep, tr_SDP(pars.cn_rtp_ip, pars.cn_rtp_port))) -> value mgcp_cmd {
945 log("CRCX2", mgcp_cmd);
946 /* Verify SDP of CRCX */
947 var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
948 MGCP.send(valueof(mgcp_rsp));
949 }
950 }
951
952 /* Expect RAB Assignment Response with IP/port from second CRCX ACK */
953 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));
954 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
955
956 alt {
957 [] BSSAP.receive(tx) {
958 setverdict(pass);
959 }
960 [] T.timeout {
961 setverdict(fail, "Timeout waiting for Iuh ", tx);
962 }
963 }
964}
965
966private altstep as_mgcp_dlcx(inout TestHdlrParams pars) runs on ConnHdlr {
967 var MgcpCommand mgcp_cmd;
968
969 [] MGCP.receive(tr_DLCX(pars.mgcp_pars.mgcp_ep)) -> value mgcp_cmd {
970 log("DLCX", mgcp_cmd);
971 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
972 pars.mgcp_pars.got_dlcx_count := pars.mgcp_pars.got_dlcx_count + 1;
Daniel Willmann3e15b7b2022-02-21 17:07:02 +0100973 if (pars.mgcp_pars.got_dlcx_count != pars.mgcp_pars.got_crcx_count) {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100974 repeat;
975 }
976 setverdict(pass);
977 }
978}
979
980friend function f_tc_rab_assignment(charstring id, TestHdlrParams pars) runs on ConnHdlr {
981 var MgcpCommand mgcp_cmd;
982 var RANAP_PDU tx;
983 timer T := 5.0;
984
985 f_init_handler(pars);
986 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
987
988 tx := f_build_initial_ue(g_pars);
989 f_iuh2iu_connect(tx);
990
991 f_create_rab(pars.mgcp_pars);
992
993 /* Send Iu Release */
994 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
995 f_iu2iuh(tx);
996
997 T.start;
998 alt {
999 [] as_mgcp_dlcx(pars) {}
1000 [] T.timeout {
1001 setverdict(fail, "Timeout waiting for DLCX");
1002 }
1003 }
1004
1005 tx := valueof(ts_RANAP_IuReleaseComplete());
1006 f_iuh2iu(tx);
1007}
1008
1009testcase TC_rab_assignment() runs on test_CT {
1010 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001011 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001012 f_init();
1013 f_start_hnbs();
1014
1015 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assignment), t_pars(3));
1016 vc_conn.done;
1017}
1018
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001019friend function f_tc_rab_assign_fail(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1020 var MgcpCommand mgcp_cmd;
1021 var RANAP_PDU tx;
1022 timer T := 5.0;
1023
1024 f_init_handler(pars);
1025 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1026
1027 tx := f_build_initial_ue(g_pars);
1028 f_iuh2iu_connect(tx);
1029
1030 f_rab_ass_req(pars.mgcp_pars);
1031
1032 /* Send RAB failed list in response */
1033 tx := valueof(ts_RANAP_RabAssResp(rab_fl := ts_RAB_FL(t_RAB_id(23), ts_RanapCause_om_intervention)));
1034 f_iuh2iu(tx);
1035
1036 T.start;
1037 alt {
1038 [] as_mgcp_dlcx(pars) {}
1039 [] T.timeout {
1040 setverdict(fail, "Timeout waiting for DLCX");
1041 }
1042 }
1043}
1044
1045testcase TC_rab_assign_fail() runs on test_CT {
1046 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001047 g_num_hnbs := 1;
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001048 f_init();
1049 f_start_hnbs();
1050
1051 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_fail), t_pars(4));
1052 vc_conn.done;
1053}
1054
Daniel Willmann19b8d902022-01-05 09:12:34 +01001055friend function f_tc_rab_release(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1056 var MgcpCommand mgcp_cmd;
1057 var RANAP_PDU tx;
1058 timer T := 15.0;
1059
1060 f_init_handler(pars);
1061 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1062
1063 tx := f_build_initial_ue(g_pars);
1064 f_iuh2iu_connect(tx);
1065
1066 f_create_rab(pars.mgcp_pars);
1067
1068 /* Send RAB Release */
Daniel Willmann9e789be2022-02-22 13:30:51 +01001069 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 +01001070 BSSAP.send(tx);
1071
1072 T.start;
1073
1074 alt {
1075 [] as_mgcp_dlcx(pars) {}
1076 [] T.timeout {
1077 setverdict(fail, "Timeout waiting for DLCX");
1078 }
1079 }
1080
1081 alt {
1082 [] RUA.receive(tx) {
1083 setverdict(pass);
1084 }
1085 [] T.timeout {
1086 setverdict(fail, "Timeout waiting for Iuh ", tx);
1087 }
1088 }
1089
1090}
1091
1092testcase TC_rab_release() runs on test_CT {
1093 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001094 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001095 f_init();
1096 f_start_hnbs();
1097
1098 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_release), t_pars(5));
1099 vc_conn.done;
1100}
1101
Daniel Willmann37c877f2022-02-22 16:47:06 +01001102friend function f_tc_rab_assign_mgcp_to(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1103 var MgcpCommand mgcp_cmd;
1104 var RANAP_PDU tx;
1105 var template RAB_SetupOrModifyList rab_sml;
1106 timer T := 15.0;
1107
1108 T.start;
1109 f_init_handler(pars);
1110 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1111
1112 tx := f_build_initial_ue(g_pars);
1113 f_iuh2iu_connect(tx);
1114
1115
1116 /* Send RAB Assignment Request */
1117 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));
1118 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1119 BSSAP.send(tx);
1120
1121 /* Ignore MGCP CRCX */
1122 alt {
1123 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
1124 log("Ignoreing CRCX1", mgcp_cmd);
1125 repeat;
1126 }
1127 [] BSSAP.receive(tr_RANAP_IuReleaseRequest(?)) { }
1128 [] T.timeout {
1129 setverdict(fail, "Timeout waiting for IuRelease");
1130 }
1131 }
1132
1133 /* Send Iu Release */
1134 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1135 f_iu2iuh(tx);
1136
1137 tx := valueof(ts_RANAP_IuReleaseComplete());
1138 f_iuh2iu(tx);
1139}
1140
1141testcase TC_rab_assign_mgcp_to() runs on test_CT {
1142 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001143 g_num_hnbs := 1;
Daniel Willmann37c877f2022-02-22 16:47:06 +01001144 f_init();
1145 f_start_hnbs();
1146
1147 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_mgcp_to), t_pars(6));
1148 vc_conn.done;
1149}
1150
Daniel Willmann19b8d902022-01-05 09:12:34 +01001151/* Create an Iuh connection; send InitialUE; transceive data both directions */
1152friend function f_tc_ranap_bidir(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1153 f_init_handler(pars);
1154
1155 /* HNB -> MSC: InitialUE */
1156 f_iuh2iu_connect(f_build_initial_ue(g_pars));
1157
1158 /* MSC <- HNB: DirectTransfer */
1159 f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1160 /* MSC -> HNB: DirectTransfer */
1161 f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1162
1163 /* HNB <- MSC: CommonID */
1164 f_iu2iuh(ts_RANAP_CommonId(hex2oct(pars.imsi)));
1165}
1166testcase TC_ranap_cs_bidir() runs on test_CT {
1167 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001168 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001169 f_init();
1170 f_start_hnbs();
1171
1172 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(3));
1173 vc_conn.done;
1174}
1175testcase TC_ranap_ps_bidir() runs on test_CT {
1176 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001177 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001178 f_init();
1179 f_start_hnbs();
1180
1181 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(4, true));
1182 vc_conn.done;
1183}
1184
1185
1186private function f_tc_ranap_mo_disconnect(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1187 f_init_handler(pars);
1188
1189 /* HNB -> MSC: InitialUE */
1190 f_iuh2iu_connect(f_build_initial_ue(g_pars));
1191
1192 /* MSC <- HNB: DirectTransfer */
1193 f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1194 /* MSC -> HNB: DirectTransfer */
1195 f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1196
1197 /* MSC <- HNB: RUA disconnect */
1198 f_iuh2iu_disconnect(ts_RANAP_IuReleaseComplete, RUA_IEs.Cause:{misc:=processing_overload});
1199}
1200testcase TC_ranap_cs_mo_disconnect() runs on test_CT {
1201 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001202 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001203 f_init();
1204 f_start_hnbs();
1205
1206 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(5));
1207 vc_conn.done;
1208}
1209testcase TC_ranap_ps_mo_disconnect() runs on test_CT {
1210 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001211 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001212 f_init();
1213 f_start_hnbs();
1214
1215 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(6));
1216 vc_conn.done;
1217}
1218
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001219type record FTeid {
1220 HostName addr,
1221 OCT4 teid
1222}
1223
1224type record FTeids {
1225 FTeid local,
1226 FTeid remote
1227}
Daniel Willmann19b8d902022-01-05 09:12:34 +01001228
1229
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001230/* 'local' and 'remote' refer to the GTP information from the UPF's point of view:
1231 * HNB UPF CN
1232 * access.remote <---> access.local | core.local <---> core.remote
1233 */
1234type record GtpParameters {
1235 FTeids core,
1236 FTeids access
1237}
1238
1239/* HNB UPF CN
1240 * access.remote <---> access.local | core.local <---> core.remote
1241 * 127.0.0.4 127.0.0.3 127.0.0.2 127.0.0.1
1242 * 0x44004400 0x30303030 0x22002200 0x10101010
1243 */
1244template GtpParameters t_GtpParameters := {
1245 core := {
1246 local := {
1247 addr := "127.0.0.2",
1248 teid := '22002200'O
1249 },
1250 remote := {
1251 addr := "127.0.0.1",
1252 teid := '10101010'O
1253 }
1254 },
1255 access := {
1256 local := {
1257 addr := "127.0.0.3",
1258 teid := '30303030'O
1259 },
1260 remote := {
1261 addr := "127.0.0.4",
1262 teid := '44004400'O
1263 }
1264 }
1265}
1266
1267friend function f_tc_ps_rab_assignment(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1268 var RANAP_PDU tx;
1269 var RANAP_PDU rx;
1270 timer T := 5.0;
1271
1272 f_init_handler(pars);
1273
1274 f_pfcp_register();
1275
1276 var PDU_PFCP m;
1277 var Node_ID upf_node_id := valueof(ts_PFCP_Node_ID_fqdn("\07osmocom\03org"));
1278
1279 PFCP.receive(tr_PFCP_Assoc_Setup_Req()) -> value m;
1280 PFCP.send(ts_PFCP_Assoc_Setup_Resp(m.sequence_number, upf_node_id,
1281 ts_PFCP_Cause(REQUEST_ACCEPTED), 1234));
1282
1283 tx := f_build_initial_ue(g_pars);
1284 f_iuh2iu_connect(tx);
1285
1286 var GtpParameters gtp_pars := valueof(t_GtpParameters);
1287 var template RAB_SetupOrModifyList rab_sml;
1288
1289 /* Send RAB Assignment Request */
1290 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.remote.addr), gtp_pars.core.remote.teid);
1291 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1292 BSSAP.send(tx);
1293
1294 /* Expect PFCP Session Establishment Request. */
1295 PFCP.receive(tr_PFCP_Session_Est_Req()) -> value m;
1296 var F_SEID hnbgw_f_seid := m.message_body.pfcp_session_establishment_request.CP_F_SEID;
1297 var PFCP_Session_Establishment_Request serq := m.message_body.pfcp_session_establishment_request;
1298
1299 /* Acting as UPF, invent a new PFCP SEID to send to HNBGW. Respond to the Session Establishment.
1300 * The PFCP response must have the same sequence_number as the request. */
1301 var F_SEID up_f_seid := valueof(ts_PFCP_F_SEID_ipv4("127.0.0.1", '1111111111111111'O));
1302 var template PDU_PFCP r := ts_PFCP_Session_Est_Resp(m.sequence_number, upf_node_id, hnbgw_f_seid.seid);
1303 r.message_body.pfcp_session_establishment_response := {
1304 offending_ie := omit,
1305 UP_F_SEID := up_f_seid,
1306 created_PDR_list := {
1307 ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[0].grouped_ie.pdr_id,
1308 local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.core.local.teid,
1309 gtp_pars.core.local.addr)),
1310 ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[1].grouped_ie.pdr_id,
1311 local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.access.local.teid,
1312 gtp_pars.access.local.addr))
1313 },
1314 load_control_information := omit,
1315 overload_control_information := omit,
1316 node_list := omit,
1317 failed_rule_id := omit,
1318 created_traffic_endpoint_list := omit
1319 };
1320 PFCP.send(r);
1321
1322 /* Expect on Iuh: RAB Assignment Request with IP/port from PFCP Session Est Resp */
1323 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.local.addr),
1324 gtp_pars.access.local.teid);
1325 rx := valueof(ts_RANAP_RabAssReq(rab_sml));
1326 RUA.receive(rx);
1327
1328 /* Send back RAB Assignment Response via Iuh */
1329 var template RAB_SetupOrModifiedList rab_smdl;
1330 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.remote.addr),
1331 gtp_pars.access.remote.teid);
1332 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1333 RUA.send(tx);
1334 T.start;
1335
1336 PFCP.receive(tr_PFCP_Session_Mod_Req(up_f_seid.seid)) -> value m;
1337 r := ts_PFCP_Session_Mod_Resp(m.sequence_number, hnbgw_f_seid.seid);
1338 PFCP.send(r);
1339
1340 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.local.addr), gtp_pars.core.local.teid);
1341 BSSAP.receive(tr_RANAP_RabAssResp(rab_smdl));
1342
1343 f_sleep(2.0);
1344 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1345 f_iu2iuh(tx);
1346
1347 tx := valueof(ts_RANAP_IuReleaseComplete());
1348 f_iuh2iu(tx);
1349
1350 PFCP.receive(tr_PFCP_Session_Del_Req(up_f_seid.seid)) -> value m;
1351 PFCP.send(ts_PFCP_Session_Del_Resp(m.sequence_number, hnbgw_f_seid.seid));
1352
1353 f_sleep(2.0);
1354}
1355
1356testcase TC_ps_rab_assignment() runs on test_CT {
1357 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001358 g_num_hnbs := 1;
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001359 f_init();
1360 f_start_hnbs();
1361 f_sleep(1.0);
1362
1363 vc_conn := f_start_handler_with_pars(refers(f_tc_ps_rab_assignment), t_pars(7, ps_domain := true));
1364 vc_conn.done;
1365}
Daniel Willmann19b8d902022-01-05 09:12:34 +01001366
1367control {
1368 execute(TC_hnb_register());
Daniel Willmannc79679a2022-08-23 17:48:39 +02001369 execute(TC_hnb_register_duplicate());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001370 execute(TC_ranap_cs_initial_ue());
1371 execute(TC_ranap_ps_initial_ue());
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02001372 execute(TC_ranap_cs_initial_ue_empty_cr());
1373 execute(TC_ranap_ps_initial_ue_empty_cr());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001374 execute(TC_ranap_cs_bidir());
1375 execute(TC_ranap_ps_bidir());
1376 execute(TC_rab_assignment());
1377 execute(TC_rab_release());
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001378 execute(TC_rab_assign_fail());
Daniel Willmann37c877f2022-02-22 16:47:06 +01001379 execute(TC_rab_assign_mgcp_to());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001380 execute(TC_ranap_cs_mo_disconnect());
1381 execute(TC_ranap_ps_mo_disconnect());
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001382 execute(TC_ps_rab_assignment());
Pau Espin Pedrolf0b9fa02022-09-12 13:31:07 +02001383
1384 /* Run at the end since it makes osmo-hnbgw <= 1.3.0 crash: OS#5676 */
1385 execute(TC_hnb_reregister_reuse_sctp_assoc());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001386}
1387
1388}