blob: d77a18fc9f49d0e27b1c979b69375f4f5703b4b2 [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
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +0200100 boolean mp_enable_pfcp_tests := false;
101
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200102 /* IP address at which we listen for PFCP to emulate a UPF in ttcn3 */
103 charstring mp_pfcp_ip_local := "127.0.0.1";
104
105 /* IP address from which the SUT (osmo-hnbgw) sends PFCP requests, and to which the ttcn3 UPF emulation sends
106 * PFCP responses. */
107 charstring mp_pfcp_ip_remote := "127.0.0.2";
Daniel Willmann19b8d902022-01-05 09:12:34 +0100108}
109
110function MSC_UnitdataCallback(RANAP_PDU ranap) runs on RAN_Emulation_CT return template RANAP_PDU {
111 // TODO: Actually implement unitdata handling
112 return ts_RANAP_Reset(ts_RanapCause_om_intervention, cs_domain);
113}
114
115const RanOps MSC_RanOps := {
116 ranap_create_cb := refers(RAN_Emulation.RanapExpectedCreateCallback),
117 ranap_unitdata_cb := refers(MSC_UnitdataCallback),
118 ps_domain := false,
119 decode_dtap := false,
120 role_ms := false,
121 protocol := RAN_PROTOCOL_RANAP,
122 transport := RANAP_TRANSPORT_IuCS,
123 use_osmux := false,
Eric Wild6e511ce2022-04-02 21:35:56 +0200124 bssap_reset_retries := 1,
Daniel Willmann19b8d902022-01-05 09:12:34 +0100125 sccp_addr_local := omit,
126 sccp_addr_peer := omit
127}
128
129type record CrcxResponse {
130 integer resp,
131 HostName mgw_rtp_ip,
132 PortNumber mgw_rtp_port,
133 MgcpConnectionId mgcp_connection_id
134}
135type record MgcpParameters {
136 integer got_crcx_count,
137 integer got_dlcx_count,
138 MgcpCallId mgcp_call_id optional,
139 MgcpEndpoint mgcp_ep,
140 CrcxResponse mgw_conn_1,
141 CrcxResponse mgw_conn_2,
142 uint7_t rtp_payload_type,
143 charstring rtp_sdp_format,
144 HostName hnb_rtp_ip,
145 PortNumber hnb_rtp_port,
146 HostName cn_rtp_ip,
147 PortNumber cn_rtp_port,
148 boolean use_osmux,
149 integer got_osmux_count
150}
151
152template (value) MgcpParameters t_MgcpParams := {
153 got_crcx_count := 0,
154 got_dlcx_count := 0,
155 mgcp_call_id := omit,
156 mgcp_ep := "rtpbridge/1@mgw",
157 mgw_conn_1 := {
158 resp := 1,
159 mgw_rtp_ip := "127.1.2.1",
160 mgw_rtp_port := 10000,
161 mgcp_connection_id := '11111'H
162 },
163 mgw_conn_2 := {
164 resp := 1,
165 mgw_rtp_ip := "127.1.2.2",
166 mgw_rtp_port := 20000,
167 mgcp_connection_id := '22222'H
168 },
169 rtp_payload_type := 23,
170 rtp_sdp_format := "FOO",
171 hnb_rtp_ip := "127.1.1.1",
172 hnb_rtp_port := 10001,
173 cn_rtp_ip := "127.1.3.1",
174 cn_rtp_port := 20001,
175 use_osmux := false,
176 got_osmux_count := 0
177}
178
179type record TestHdlrParams {
180 integer hnb_idx,
181 hexstring imsi,
182 boolean ps_domain,
183 MgcpParameters mgcp_pars optional,
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200184 HnbConfig hnb optional,
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200185 boolean separate_sccp_cr,
186 charstring pfcp_local_addr
Daniel Willmann19b8d902022-01-05 09:12:34 +0100187}
188
189/* We extend:
190 * RUA_ConnHdlr (for the Iuh side, emulating the HNB)
191 * RAN_ConnHdlr (for the Iu side, emulating the MSC)
192 * MGCP_ConnHdlr (for the MGCP side, emulating the MGW)
193 */
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200194type component ConnHdlr extends RAN_ConnHdlr, MGCP_ConnHdlr, RUA_ConnHdlr, PFCP_ConnHdlr {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100195 var integer g_sccp_conn_id;
196 var TestHdlrParams g_pars;
197 timer g_Tguard;
198}
199
200
201const MGCPOps MSC_MGCPOps := {
202 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
203 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
204}
205
206function f_create_ranap_exp(octetstring l3_enc) runs on ConnHdlr {
207 BSSAP_PROC.call(RAN_register:{l3_enc, self}) {
208 [] BSSAP_PROC.getreply(RAN_register:{?, ?}) {};
209 }
210}
211
212
Daniel Willmannc79679a2022-08-23 17:48:39 +0200213const integer NUM_HNB := 2;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100214
Daniel Willmann19b8d902022-01-05 09:12:34 +0100215type record HnbConfig {
216 LocationAreaIdentification lai,
217 integer sac
218}
219
220type component test_CT extends CTRL_Adapter_CT {
221 var boolean g_initialized := false;
222
223 /********************* Iu side */
224 var RAN_Adapter g_msc;
225 var RAN_Adapter g_sgsn;
226 /* SGSN IuPS missing */
227
228 /********************* Iuh side */
229 var HnbConfig g_hnb_cfg[NUM_HNB];
230 var Iuh_Emulation_CT vc_Iuh[NUM_HNB];
231 var RUA_Emulation_CT vc_RUA[NUM_HNB];
232 port HNBAP_PT HNBAP[NUM_HNB];
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200233 /* Number of HNBs to be used/started by the test */
234 var integer g_num_hnbs := NUM_HNB;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100235
236 var MGCP_Emulation_CT vc_MGCP;
237 port TELNETasp_PT HNBGWVTY;
238 /* global test case guard timer (actual timeout value is set in f_init()) */
239 timer T_guard := 30.0;
240}
241
242/* global altstep for global guard timer; */
243altstep as_Tguard() runs on test_CT {
244 [] T_guard.timeout {
245 setverdict(fail, "Timeout of T_guard");
246 mtc.stop;
247 }
248}
249
250friend function f_logp(TELNETasp_PT pt, charstring log_msg)
251{
252 // log on TTCN3 log output
253 log(log_msg);
254 // log in stderr log
255 f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
256}
257
258function f_init_vty(charstring id := "foo") runs on test_CT {
259 if (HNBGWVTY.checkstate("Mapped")) {
260 /* skip initialization if already executed once */
261 return;
262 }
263 map(self:HNBGWVTY, system:HNBGWVTY);
264 f_vty_set_prompts(HNBGWVTY);
265 f_vty_transceive(HNBGWVTY, "enable");
266}
267
268function f_init_mgcp(charstring id) runs on test_CT {
269 id := id & "-MGCP";
270 var MGCPOps ops := {
271 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
272 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
273 }
274 var MGCP_conn_parameters pars := {
275 callagent_ip := mp_hnbgw_ip,
276 callagent_udp_port := -1,
277 mgw_ip := mp_mgw_ip,
278 mgw_udp_port := mp_mgw_port,
279 multi_conn_mode := false
280 }
281
282 vc_MGCP := MGCP_Emulation_CT.create(id);
283 map(vc_MGCP:MGCP, system:MGCP_CODEC_PT);
284 vc_MGCP.start(MGCP_Emulation.main(ops, pars, id));
285}
286
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200287function f_init_pfcp(charstring id) runs on ConnHdlr {
288 id := id & "-PFCP";
289
290 var PFCP_Emulation_Cfg pfcp_cfg := {
291 pfcp_bind_ip := mp_pfcp_ip_local,
292 pfcp_bind_port := PFCP_PORT,
293 pfcp_remote_ip := mp_pfcp_ip_remote,
294 pfcp_remote_port := PFCP_PORT,
295 role := UPF
296 };
297
298 vc_PFCP := PFCP_Emulation_CT.create(id) alive;
299 connect(self:PFCP, vc_PFCP:CLIENT);
300 connect(self:PFCP_PROC, vc_PFCP:CLIENT_PROC);
301 vc_PFCP.start(PFCP_Emulation.main(pfcp_cfg));
302}
303
Daniel Willmann19b8d902022-01-05 09:12:34 +0100304function f_init_hnodeb(charstring id, integer hnb_idx, RuaOps rua_ops) runs on test_CT {
305 id := id & "-Iuh" & int2str(hnb_idx);
306
307 /* Iuh lower layer (RUA/HNBAP demux) */
308 var Iuh_conn_parameters iuh_pars;
309 iuh_pars.remote_ip := mp_hnbgw_ip;
310 iuh_pars.remote_sctp_port := mp_hnbgw_iuh_port;
311 iuh_pars.local_ip := mp_hnodeb_ip;
312 iuh_pars.local_sctp_port := mp_hnodeb_port + hnb_idx;
313 vc_Iuh[hnb_idx] := Iuh_Emulation_CT.create(id);
314 connect(self:HNBAP[hnb_idx], vc_Iuh[hnb_idx]:HNBAP);
315
316 vc_RUA[hnb_idx] := RUA_Emulation_CT.create(id & "-RUA");
317 connect(vc_RUA[hnb_idx]:RUA, vc_Iuh[hnb_idx]:RUA);
318
319 /* Start Iuh side components */
320 vc_Iuh[hnb_idx].start(Iuh_Emulation.main(iuh_pars, id));
321 vc_RUA[hnb_idx].start(RUA_Emulation.main(rua_ops, id & "-RUA"));
322}
323
324/* global initialization function */
Neels Hofmeyr82e79b02022-06-08 00:08:09 +0200325function f_init(charstring id := "HNBGW", float guard_timeout := 30.0) runs on test_CT {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100326
Daniel Willmann19b8d902022-01-05 09:12:34 +0100327 T_guard.start(guard_timeout);
328 activate(as_Tguard());
329
330 /* RUA/RANAP emulation on top of lower-layer Iuh */
331 var RuaOps rua_ops := {
332 create_cb := refers(IuhRanapCreateCallback),
333 unitdata_cb := refers(IuhRanapUnitdataCallback)
334 };
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200335 for (var integer i := 0; i < g_num_hnbs; i := i+1) {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200336 g_hnb_cfg[i] := {
337 lai := {
338 mcc_mnc := '00101'H,
339 lac := 2342 + i
340 },
341 sac := 55
342 };
Daniel Willmann19b8d902022-01-05 09:12:34 +0100343 f_init_hnodeb(testcasename(), i, rua_ops);
344 }
345
346 /* MSC emulation */
347 var RanOps ranops := {
348 ranap_create_cb := refers(RAN_Emulation.RanapExpectedCreateCallback),
349 ranap_unitdata_cb := omit,
350 ps_domain := false,
351 decode_dtap := false,
352 role_ms := false,
353 protocol := RAN_PROTOCOL_RANAP,
354 transport := RANAP_TRANSPORT_IuCS,
355 use_osmux := false,
Eric Wild6e511ce2022-04-02 21:35:56 +0200356 bssap_reset_retries := 1,
Daniel Willmann19b8d902022-01-05 09:12:34 +0100357 sccp_addr_local := omit,
358 sccp_addr_peer := omit
359 };
360 f_ran_adapter_init(g_msc, mp_msc_cfg, "HNBGW_Test", ranops);
361 f_ran_adapter_start(g_msc);
362
363 /* SGSN emulation */
364 ranops.ps_domain := true;
365 f_ran_adapter_init(g_sgsn, mp_sgsn_cfg, "HNBGW_Test", ranops);
366 f_ran_adapter_start(g_sgsn);
367
368 f_init_mgcp(id);
369 f_init_vty("VirtHNBGW");
370}
371
372friend function f_shutdown_helper() runs on test_CT {
373 all component.stop;
374 setverdict(pass);
375 mtc.stop;
376}
377
378/* helper function to start all of the simulated hNodeBs */
379function f_start_hnbs() runs on test_CT {
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200380 for (var integer i:= 0; i < g_num_hnbs; i := i+1) {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200381 f_hnbap_register(i, i);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100382 }
383}
384
385/***********************************************************************
386 * code running in test_CT, preparing start of per-UE ConnHdlr
387 ***********************************************************************/
388
389/* inbound RUA connection establishment on Iuh side */
390function IuhRanapCreateCallback(ContextId context_id, RUA_IEs.CN_DomainIndicator domain, charstring id)
391runs on RUA_Emulation_CT return RUA_ConnHdlr {
392 log("CreateCallback");
393 return null;
394}
395
396/* inbound RUA connectionless data on Iuh side */
397function IuhRanapUnitdataCallback(RANAP_PDU ranap)
398runs on RUA_Emulation_CT return template RANAP_PDU {
399 log("UnitdataCallback");
400 return omit;
401}
402
403private function f_start_handler_create(TestHdlrParams pars) runs on test_CT return ConnHdlr {
404 var ConnHdlr vc_conn;
405 var charstring id := testcasename() & int2str(pars.hnb_idx);
406
407 vc_conn := ConnHdlr.create(id);
408
409 /* Iuh RUA part */
410 connect(vc_conn:RUA, vc_RUA[pars.hnb_idx]:CLIENT);
411
412 if (pars.ps_domain) {
413 /* SGSN side */
414 connect(vc_conn:BSSAP, g_sgsn.vc_RAN:CLIENT);
415 connect(vc_conn:BSSAP_PROC, g_sgsn.vc_RAN:PROC);
416 } else {
417 /* MSC side */
418 connect(vc_conn:BSSAP, g_msc.vc_RAN:CLIENT);
419 connect(vc_conn:BSSAP_PROC, g_msc.vc_RAN:PROC);
420 }
421 /* MGCP part */
422 connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
423 connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
424
425 return vc_conn;
426}
427
428private function f_start_handler_run(ConnHdlr vc_conn, void_fn fn, TestHdlrParams pars) runs on test_CT {
429 var charstring id := testcasename(); // & int2str(pars.ran_idx);
430 /* We cannot use vc_conn.start(f_init_handler(fn, id, pars)); as we cannot have
431 * a stand-alone 'derefers()' call, see https://www.eclipse.org/forums/index.php/t/1091364/ */
432 pars.hnb := g_hnb_cfg[pars.hnb_idx];
433 pars.mgcp_pars := valueof(t_MgcpParams);
434 vc_conn.start(derefers(fn)(id, pars));
435}
436
437function f_start_handler_with_pars(void_fn fn, template (value) TestHdlrParams pars)
438runs on test_CT return ConnHdlr {
439 var ConnHdlr vc_conn;
440 vc_conn := f_start_handler_create(valueof(pars));
441 f_start_handler_run(vc_conn, fn, valueof(pars));
442 return vc_conn;
443}
444
445/***********************************************************************
446 * code running inside per-UE ConnHdlr
447 ***********************************************************************/
448
449type function void_fn(charstring id, TestHdlrParams pars) runs on ConnHdlr;
450
451function f_init_handler(TestHdlrParams pars, float t_guard := 20.0) runs on ConnHdlr {
452 /* make parameters available via component variable */
453 g_pars := pars;
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200454
455 f_init_pfcp(testcasename());
456
Daniel Willmann19b8d902022-01-05 09:12:34 +0100457 /* start guard timer and activate it as default */
458 g_Tguard.start(t_guard);
459 activate(as_Tguard_ConnHdlr());
460
461 /* TODO: CTRL? */
462 /* TODO: VTY? */
463}
464
465/* global altstep for global guard timer; */
466private altstep as_Tguard_ConnHdlr() runs on ConnHdlr {
467 [] g_Tguard.timeout {
468 setverdict(fail, "Timeout of T_guard");
469 mtc.stop;
470 }
471}
472
473/* send RANAP on Iuh and expect it to show up on Iu */
474function f_iuh2iu(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
475runs on ConnHdlr return RANAP_PDU {
476 var RANAP_PDU rx;
477 timer T := 5.0;
478
479 if (istemplatekind(exp_rx, "omit")) {
480 exp_rx := tx;
481 }
482
483 RUA.send(tx);
484 T.start;
485
486 alt {
487 [] BSSAP.receive(exp_rx) -> value rx {
488 setverdict(pass);
489 }
490 [] T.timeout {
491 setverdict(fail, "Timeout waiting for Iu ", exp_rx);
492 }
493 }
494 return rx;
495}
496
497/* send RANAP on Iu and expect it to show up on Iuh */
498function f_iu2iuh(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
499runs on ConnHdlr return RANAP_PDU {
500 var RANAP_PDU rx;
501 timer T := 5.0;
502
503 if (istemplatekind(exp_rx, "omit")) {
504 exp_rx := tx;
505 }
506
507 BSSAP.send(tx);
508 T.start;
509
510 alt {
511 [] RUA.receive(exp_rx) -> value rx {
512 setverdict(pass);
513 }
514 [] T.timeout {
515 setverdict(fail, "Timeout waiting for Iuh ", exp_rx);
516 }
517 }
518 return rx;
519}
520
521/* send RANAP on Iuh and expect it to show up on Iu */
522function f_iuh2iu_connect(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
523runs on ConnHdlr return RANAP_PDU {
524 var RANAP_PDU rx;
525 timer T := 5.0;
526
527 if (istemplatekind(exp_rx, "omit")) {
528 exp_rx := tx;
529 }
530
531 /* create an expect on the Iu side for the random NAS portion */
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200532 if (g_pars.separate_sccp_cr) {
533 f_ran_register_sccp_cr_without_payload();
534 } else {
535 var template (omit) octetstring nas := f_ranap_extract_l3(valueof(tx));
536 f_ran_register_exp(valueof(nas));
537 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100538
539 /* send it via Iuh (creating a RUA connection) */
540 RUA.send(RUA_Conn_Req:{g_pars.ps_domain, tx});
541
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200542 if (g_pars.separate_sccp_cr) {
543 /* Acknowledge the empty SCCP CR. RAN_Emulation does the confirmation, no need to respond. */
544 BSSAP.receive(tr_RANAP_Conn_Req());
545 }
546
Daniel Willmann19b8d902022-01-05 09:12:34 +0100547 /* expect to receive it on the Iu side */
548 T.start;
549 alt {
550 [] BSSAP.receive(exp_rx) -> value rx {
551 setverdict(pass);
552 }
553 [] T.timeout {
554 setverdict(fail, "Timeout waiting for Iu ", exp_rx);
555 }
556 }
557 return rx;
558}
559
560function f_iuh2iu_disconnect(template (present) RANAP_PDU tx, RUA_IEs.Cause cause,
561 template RANAP_PDU exp_rx := omit)
562runs on ConnHdlr return RANAP_PDU {
563 var RANAP_PDU rx
564 timer T := 5.0;
565
566 if (istemplatekind(exp_rx, "omit")) {
567 exp_rx := tx;
568 }
569
570 /* send it via Iuh (creating a RUA connection) */
571 RUA.send(RUA_Disc_Req:{tx, cause});
572
573 /* expect to receive it on the Iu side */
574 T.start;
575 alt {
576 [] BSSAP.receive(exp_rx) -> value rx {
577 }
578 [] T.timeout {
579 setverdict(fail, "Timeout waiting for Iu ", exp_rx);
580 return rx;
581 }
582 }
583
584 /* expect disconnect on the Iu side */
585 alt {
586 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {
587 setverdict(pass);
588 }
589 [] T.timeout {
590 setverdict(fail, "Timeout waiting for Iu disconnect");
591 return rx;
592 }
593
594 }
595 return rx;
596}
597
598/* build a RANAP InitialUE based on the TestHdlrParams */
599friend function f_build_initial_ue(TestHdlrParams pars) return RANAP_PDU {
600 var LAI lai := {
601 pLMNidentity := hex2oct(pars.hnb.lai.mcc_mnc),
602 lAC := int2oct(pars.hnb.lai.lac, 2),
603 iE_Extensions := omit
604 };
605 var SAI sai := {
606 pLMNidentity := lai.pLMNidentity,
607 lAC := lai.lAC,
608 sAC := int2oct(pars.hnb.sac, 2),
609 iE_Extensions := omit
610 }
611 var octetstring nas := f_rnd_octstring(10);
612 var IuSignallingConnectionIdentifier sigc_id := int2bit(f_rnd_int(1000), 24);
613 var GlobalRNC_ID grnc_id := {
614 pLMNidentity := lai.pLMNidentity,
615 rNC_ID := 2342
616 }
617
618 if (pars.ps_domain) {
619 var RAC rac := '00'O;
620 return valueof(ts_RANAP_initialUE_PS(lai, rac, sai, nas, sigc_id, grnc_id));
621 } else {
622 return valueof(ts_RANAP_initialUE_CS(lai, sai, nas, sigc_id, grnc_id));
623 }
624}
625
626/* build a RANAP RAB AssignmentResponse based on the TestHdlrParams */
627friend function f_build_rab_ass_resp(TestHdlrParams pars) return RANAP_PDU {
628 var template RAB_SetupOrModifiedList rab_sml;
629
630 rab_sml := ts_RAB_SMdL(t_RAB_id(23), f_ts_RAB_TLA("192.168.1.23"), t_RAB_binding_port(1234));
631
632 return valueof(ts_RANAP_RabAssResp(rab_sml));
633}
634
635
636/***********************************************************************
637 * HNBAP Testing
638 ***********************************************************************/
639
640
Daniel Willmannc79679a2022-08-23 17:48:39 +0200641function 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 +0100642{
643 timer T := 2.0;
644
Daniel Willmann28209ec2022-08-24 09:58:07 +0200645 HNBAP[hnb_idx].send(ts_HNBAP_HNBRegisterRequest(char2oct("TTCN3 HNodeB"),
Daniel Willmann19b8d902022-01-05 09:12:34 +0100646 '00F110'O,
Daniel Willmannc79679a2022-08-23 17:48:39 +0200647 int2bit(1 + cell_id, 28),
Daniel Willmann19b8d902022-01-05 09:12:34 +0100648 int2oct(2, 2),
649 int2oct(3, 1),
650 int2oct(4, 2)));
651
652 T.start;
653 alt {
654 [] HNBAP[hnb_idx].receive(tr_HNBAP_HNBRegisterAccept(?)) {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200655 if (expect_reject) {
656 setverdict(fail, "Rx HNB Register Accept while expecting reject");
657 } else {
658 setverdict(pass);
659 }
660 }
661 [] HNBAP[hnb_idx].receive(tr_HNBAP_HNBRegisterReject(?)) {
662 if (expect_reject) {
663 setverdict(pass);
664 } else {
665 setverdict(fail, "Rx HNB Register Reject while expecting accept");
666 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100667 }
668 [] HNBAP[hnb_idx].receive(IUHEM_Event:?) {
669 repeat;
670 }
671 [] T.timeout {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200672 setverdict(fail, "Timeout waiting for HNB Register response");
Daniel Willmann19b8d902022-01-05 09:12:34 +0100673 }
674 }
675}
676
677testcase TC_hnb_register() runs on test_CT {
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200678 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100679 f_init();
680 f_hnbap_register(0);
681 f_shutdown_helper();
682}
683
Pau Espin Pedrolacf4f222022-09-27 14:33:40 +0200684/* Try to register the same HNB from 2 different concurrent connections. Second
685 * one should be rejected. */
Daniel Willmannc79679a2022-08-23 17:48:39 +0200686testcase TC_hnb_register_duplicate() runs on test_CT {
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200687 g_num_hnbs := 2;
Daniel Willmannc79679a2022-08-23 17:48:39 +0200688 f_init();
689 f_hnbap_register(0);
690 f_hnbap_register(1, 0, expect_reject := true);
691 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
692 f_shutdown_helper();
693}
694
Pau Espin Pedrolacf4f222022-09-27 14:33:40 +0200695/* Try to register the same HNB in the same connection already established, aka
696 * duplicate HNB Register Request. It should be accepted and new configuration
697 * applied. TS 25.469 8.2.4 */
698testcase TC_hnb_register_duplicate_reuse_sctp_assoc() runs on test_CT {
699 g_num_hnbs := 1;
700 f_init();
701 f_hnbap_register(0);
702 f_hnbap_register(0);
703 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
704 f_shutdown_helper();
705}
706
Pau Espin Pedrolf0b9fa02022-09-12 13:31:07 +0200707/* Drop HNBAP conn (HNBAP DEREG) and reconnect it (HNBAP REG) using same SCTP association.
708 * Related: OS#5676, SYS#6113 */
709testcase TC_hnb_reregister_reuse_sctp_assoc() runs on test_CT {
710 g_num_hnbs := 1;
711 f_init();
712 f_hnbap_register(0);
713 HNBAP[0].send(ts_HNBAP_HNBDe_Register(ts_HnbapCause(unspecified)));
714 f_hnbap_register(0);
715 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
716 f_shutdown_helper();
717}
718
Daniel Willmann19b8d902022-01-05 09:12:34 +0100719/***********************************************************************
720 * RUA / RANAP Testing
721 ***********************************************************************/
722
723private template (value) TestHdlrParams
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200724t_pars(integer imsi_suffix, boolean ps_domain := false, integer hnb_idx := 0,
725 boolean separate_sccp_cr := false) := {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100726 hnb_idx := hnb_idx,
727 imsi := f_gen_imsi(imsi_suffix),
728 ps_domain := ps_domain,
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200729 hnb := omit, /* filled in later */
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200730 separate_sccp_cr := separate_sccp_cr,
731 pfcp_local_addr := mp_pfcp_ip_local
Daniel Willmann19b8d902022-01-05 09:12:34 +0100732}
733
734/* Create an Iuh connection; send InitialUE; expect it to appear on new SCCP conenction */
735friend function f_tc_initial_ue(charstring id, TestHdlrParams pars) runs on ConnHdlr {
736 f_init_handler(pars);
737 var RANAP_PDU tx := f_build_initial_ue(g_pars);
738 f_iuh2iu_connect(tx);
739}
740testcase TC_ranap_cs_initial_ue() runs on test_CT {
741 var ConnHdlr vc_conn;
742
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200743 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100744 f_init();
745 f_start_hnbs();
746
747 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(1));
748 vc_conn.done;
749}
750testcase TC_ranap_ps_initial_ue() runs on test_CT {
751 var ConnHdlr vc_conn;
752
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200753 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100754 f_init();
755 f_start_hnbs();
756
757 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(2, true));
758 vc_conn.done;
759}
760
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200761private function f_vty_set_sccp_cr_max_payload_len(TELNETasp_PT pt, integer val := 999999)
762{
763 f_vty_enter_config(pt);
764 f_vty_transceive(pt, "hnbgw");
765 f_vty_transceive(pt, "sccp cr max-payload-len " & int2str(val));
766 f_vty_transceive(pt, "end");
767}
768
769testcase TC_ranap_cs_initial_ue_empty_cr() runs on test_CT {
770 var ConnHdlr vc_conn;
771
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200772 g_num_hnbs := 1;
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200773 f_init();
774 f_start_hnbs();
775
776 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY, 0);
777
778 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(1, separate_sccp_cr := true));
779 vc_conn.done;
780
781 /* reset */
782 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY);
783}
784testcase TC_ranap_ps_initial_ue_empty_cr() runs on test_CT {
785 var ConnHdlr vc_conn;
786
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200787 g_num_hnbs := 1;
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200788 f_init();
789 f_start_hnbs();
790
791 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY, 0);
792
793 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(2, true, separate_sccp_cr := true));
794 vc_conn.done;
795
796 /* reset */
797 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY);
798}
799
Daniel Willmann19b8d902022-01-05 09:12:34 +0100800/* Reply to a received CRCX with an OK (or the reply configured in cpars), using the given parameters.
801 * Return true when an OK reply was sent, false otherwise.
802 * Count occurrence of Osmux, include Osmux parameters in the reply if necessary. */
803function f_handle_crcx(inout MgcpParameters pars, MgcpCommand mgcp_cmd) return template MgcpResponse {
804 var CrcxResponse conn := pars.mgw_conn_1;
805 if (pars.got_crcx_count > 0) {
806 conn := pars.mgw_conn_2;
807 }
808 pars.got_crcx_count := pars.got_crcx_count + 1;
809
810 var MgcpMessage mgcp_msg := {
811 command := mgcp_cmd
812 }
813 var template MgcpResponse mgcp_resp;
814 var MgcpOsmuxCID osmux_cid;
815 var MgcpCallId call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
816 if (ispresent(pars.mgcp_call_id)) {
817 if (pars.mgcp_call_id != call_id) {
818 setverdict(fail, "CRCX contained unexpected call id. Expected:", pars.mgcp_call_id, " got:", call_id);
819 mtc.stop;
820 }
821 } else {
822 pars.mgcp_call_id := call_id;
823 }
824
825 /* When the endpoint contains a wildcard we keep the endpoint
826 * identifier we have set up in pars. Otherwise we use the
827 * endpoint name that the call agent has supplied */
828 if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard) == false) {
829 pars.mgcp_ep := mgcp_cmd.line.ep;
830 }
831
832 if (conn.resp == -1) {
833 /* Reply with rror */
834 var MgcpResponse mgcp_rsp := {
835 line := {
836 code := "542",
837 trans_id := mgcp_cmd.line.trans_id,
838 string := "FORCED_FAIL"
839 },
840 sdp := omit
841
842 }
843 var MgcpParameter mgcp_rsp_param := {
844 code := "Z",
845 val := pars.mgcp_ep
846 };
847 mgcp_rsp.params[0] := mgcp_rsp_param;
848 return mgcp_rsp;
849 }
850
851 if (conn.resp == 0) {
852 /* Do not reply at all */
853 return omit;
854 }
855
856 if (conn.resp != 1) {
857 setverdict(fail, "Unexpected value for pars.mgw_conn_*.resp, expect -1, 0 or 1");
858 mtc.stop;
859 }
860
861 var SDP_Message sdp := valueof(ts_SDP(conn.mgw_rtp_ip, conn.mgw_rtp_ip,
862 hex2str(pars.mgcp_call_id), "42",
863 conn.mgw_rtp_port,
864 { int2str(pars.rtp_payload_type) },
865 { valueof(ts_SDP_rtpmap(pars.rtp_payload_type,
866 pars.rtp_sdp_format)),
867 valueof(ts_SDP_ptime(20)) }));
868
869 if (f_mgcp_contains_par(mgcp_msg, "X-OSMUX")) {
870 if (not pars.use_osmux) {
871 setverdict(fail, "MSC sent X-Osmux parameter in MGCP, but not expecting any Osmux");
872 mtc.stop;
873 }
874 pars.got_osmux_count := pars.got_osmux_count + 1;
875 /* we expect MSC to use wildcard here, i.e. osmux_cid == -1 */
876 osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
877 log("f_handle_crcx(): got Osmux CID: ", osmux_cid);
878 if (osmux_cid != -1) {
879 setverdict(fail, "MSC using unexpected CID " & int2str(osmux_cid) & " != -1");
880 mtc.stop;
881 }
882
883 osmux_cid := 0;
884 mgcp_resp := ts_CRCX_ACK_osmux(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, osmux_cid, sdp);
885 } else {
886 mgcp_resp := ts_CRCX_ACK(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, sdp);
887 }
888
889 f_mgcp_par_append(mgcp_resp.params, ts_MgcpParSpecEP(pars.mgcp_ep));
890
891 return mgcp_resp;
892}
893
Daniel Willmann3e15b7b2022-02-21 17:07:02 +0100894friend function f_create_rab(inout MgcpParameters pars) runs on ConnHdlr {
895 f_rab_ass_req(pars);
896 f_rab_ass_resp(pars);
897}
898
899friend function f_rab_ass_req(inout MgcpParameters pars) runs on ConnHdlr {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100900 var MgcpCommand mgcp_cmd;
901 var RANAP_PDU tx;
902 var template RAB_SetupOrModifyList rab_sml;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100903 timer T := 5.0;
904
905 /* Send RAB Assignment Request */
906 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));
907 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
908 BSSAP.send(tx);
909 T.start;
910
911 /* Handle MGCP CRCX */
912 alt {
913 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
914 log("CRCX1", mgcp_cmd);
915 var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
916 MGCP.send(valueof(mgcp_rsp));
917 }
918 [] T.timeout {
919 setverdict(fail, "Timeout waiting for MGCP");
920 }
921 }
922
923 /* Expect RAB Assignment Request with IP/port from CRCX ACK via Iuh */
924 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));
925 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
926
927 alt {
928 [] RUA.receive(tx) {
929 setverdict(pass);
930 }
931 [] T.timeout {
932 setverdict(fail, "Timeout waiting for Iuh ", tx);
933 }
934 }
Daniel Willmann3e15b7b2022-02-21 17:07:02 +0100935}
936
937friend function f_rab_ass_resp(inout MgcpParameters pars) runs on ConnHdlr {
938 var MgcpCommand mgcp_cmd;
939 var RANAP_PDU tx;
940 var template RAB_SetupOrModifiedList rab_smdl;
941 timer T := 5.0;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100942
943 /* Send back RAB Assignment Response via Iuh */
944 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));
945 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
946 RUA.send(tx);
947 T.start;
948
949 interleave {
950 /* Expect MDCX with IP/port from RAB Assignment Response */
951 [] MGCP.receive(tr_MDCX(tr_SDP(pars.hnb_rtp_ip, pars.hnb_rtp_port))) -> value mgcp_cmd {
952 log("MDCX1", mgcp_cmd);
953 /* Verify SDP of MDCX */
954 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,
955 { int2str(pars.rtp_payload_type) }, { valueof(ts_SDP_rtpmap(pars.rtp_payload_type, pars.rtp_sdp_format)), valueof(ts_SDP_ptime(20)) } ));
956 var template MgcpResponse mgcp_rsp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, pars.mgw_conn_1.mgcp_connection_id, sdp);
957 MGCP.send(valueof(mgcp_rsp));
958 }
959 /* Handle CRCX for second leg of endpoint, answer with IP/port */
960 [] MGCP.receive(tr_CRCX(pars.mgcp_ep, tr_SDP(pars.cn_rtp_ip, pars.cn_rtp_port))) -> value mgcp_cmd {
961 log("CRCX2", mgcp_cmd);
962 /* Verify SDP of CRCX */
963 var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
964 MGCP.send(valueof(mgcp_rsp));
965 }
966 }
967
968 /* Expect RAB Assignment Response with IP/port from second CRCX ACK */
969 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));
970 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
971
972 alt {
973 [] BSSAP.receive(tx) {
974 setverdict(pass);
975 }
976 [] T.timeout {
977 setverdict(fail, "Timeout waiting for Iuh ", tx);
978 }
979 }
980}
981
982private altstep as_mgcp_dlcx(inout TestHdlrParams pars) runs on ConnHdlr {
983 var MgcpCommand mgcp_cmd;
984
985 [] MGCP.receive(tr_DLCX(pars.mgcp_pars.mgcp_ep)) -> value mgcp_cmd {
986 log("DLCX", mgcp_cmd);
987 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
988 pars.mgcp_pars.got_dlcx_count := pars.mgcp_pars.got_dlcx_count + 1;
Daniel Willmann3e15b7b2022-02-21 17:07:02 +0100989 if (pars.mgcp_pars.got_dlcx_count != pars.mgcp_pars.got_crcx_count) {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100990 repeat;
991 }
992 setverdict(pass);
993 }
994}
995
996friend function f_tc_rab_assignment(charstring id, TestHdlrParams pars) runs on ConnHdlr {
997 var MgcpCommand mgcp_cmd;
998 var RANAP_PDU tx;
999 timer T := 5.0;
1000
1001 f_init_handler(pars);
1002 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1003
1004 tx := f_build_initial_ue(g_pars);
1005 f_iuh2iu_connect(tx);
1006
1007 f_create_rab(pars.mgcp_pars);
1008
1009 /* Send Iu Release */
1010 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1011 f_iu2iuh(tx);
1012
1013 T.start;
1014 alt {
1015 [] as_mgcp_dlcx(pars) {}
1016 [] T.timeout {
1017 setverdict(fail, "Timeout waiting for DLCX");
1018 }
1019 }
1020
1021 tx := valueof(ts_RANAP_IuReleaseComplete());
1022 f_iuh2iu(tx);
1023}
1024
1025testcase TC_rab_assignment() runs on test_CT {
1026 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001027 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001028 f_init();
1029 f_start_hnbs();
1030
1031 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assignment), t_pars(3));
1032 vc_conn.done;
1033}
1034
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001035friend function f_tc_rab_assign_fail(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1036 var MgcpCommand mgcp_cmd;
1037 var RANAP_PDU tx;
1038 timer T := 5.0;
1039
1040 f_init_handler(pars);
1041 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1042
1043 tx := f_build_initial_ue(g_pars);
1044 f_iuh2iu_connect(tx);
1045
1046 f_rab_ass_req(pars.mgcp_pars);
1047
1048 /* Send RAB failed list in response */
1049 tx := valueof(ts_RANAP_RabAssResp(rab_fl := ts_RAB_FL(t_RAB_id(23), ts_RanapCause_om_intervention)));
1050 f_iuh2iu(tx);
1051
1052 T.start;
1053 alt {
1054 [] as_mgcp_dlcx(pars) {}
1055 [] T.timeout {
1056 setverdict(fail, "Timeout waiting for DLCX");
1057 }
1058 }
1059}
1060
1061testcase TC_rab_assign_fail() runs on test_CT {
1062 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001063 g_num_hnbs := 1;
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001064 f_init();
1065 f_start_hnbs();
1066
1067 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_fail), t_pars(4));
1068 vc_conn.done;
1069}
1070
Daniel Willmann19b8d902022-01-05 09:12:34 +01001071friend function f_tc_rab_release(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1072 var MgcpCommand mgcp_cmd;
1073 var RANAP_PDU tx;
1074 timer T := 15.0;
1075
1076 f_init_handler(pars);
1077 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1078
1079 tx := f_build_initial_ue(g_pars);
1080 f_iuh2iu_connect(tx);
1081
1082 f_create_rab(pars.mgcp_pars);
1083
1084 /* Send RAB Release */
Daniel Willmann9e789be2022-02-22 13:30:51 +01001085 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 +01001086 BSSAP.send(tx);
1087
1088 T.start;
1089
1090 alt {
1091 [] as_mgcp_dlcx(pars) {}
1092 [] T.timeout {
1093 setverdict(fail, "Timeout waiting for DLCX");
1094 }
1095 }
1096
1097 alt {
1098 [] RUA.receive(tx) {
1099 setverdict(pass);
1100 }
1101 [] T.timeout {
1102 setverdict(fail, "Timeout waiting for Iuh ", tx);
1103 }
1104 }
1105
1106}
1107
1108testcase TC_rab_release() runs on test_CT {
1109 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001110 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001111 f_init();
1112 f_start_hnbs();
1113
1114 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_release), t_pars(5));
1115 vc_conn.done;
1116}
1117
Daniel Willmann37c877f2022-02-22 16:47:06 +01001118friend function f_tc_rab_assign_mgcp_to(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1119 var MgcpCommand mgcp_cmd;
1120 var RANAP_PDU tx;
1121 var template RAB_SetupOrModifyList rab_sml;
1122 timer T := 15.0;
1123
1124 T.start;
1125 f_init_handler(pars);
1126 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1127
1128 tx := f_build_initial_ue(g_pars);
1129 f_iuh2iu_connect(tx);
1130
1131
1132 /* Send RAB Assignment Request */
1133 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));
1134 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1135 BSSAP.send(tx);
1136
1137 /* Ignore MGCP CRCX */
1138 alt {
1139 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
1140 log("Ignoreing CRCX1", mgcp_cmd);
1141 repeat;
1142 }
1143 [] BSSAP.receive(tr_RANAP_IuReleaseRequest(?)) { }
1144 [] T.timeout {
1145 setverdict(fail, "Timeout waiting for IuRelease");
1146 }
1147 }
1148
1149 /* Send Iu Release */
1150 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1151 f_iu2iuh(tx);
1152
1153 tx := valueof(ts_RANAP_IuReleaseComplete());
1154 f_iuh2iu(tx);
1155}
1156
1157testcase TC_rab_assign_mgcp_to() runs on test_CT {
1158 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001159 g_num_hnbs := 1;
Daniel Willmann37c877f2022-02-22 16:47:06 +01001160 f_init();
1161 f_start_hnbs();
1162
1163 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_mgcp_to), t_pars(6));
1164 vc_conn.done;
1165}
1166
Daniel Willmann19b8d902022-01-05 09:12:34 +01001167/* Create an Iuh connection; send InitialUE; transceive data both directions */
1168friend function f_tc_ranap_bidir(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1169 f_init_handler(pars);
1170
1171 /* HNB -> MSC: InitialUE */
1172 f_iuh2iu_connect(f_build_initial_ue(g_pars));
1173
1174 /* MSC <- HNB: DirectTransfer */
1175 f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1176 /* MSC -> HNB: DirectTransfer */
1177 f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1178
1179 /* HNB <- MSC: CommonID */
1180 f_iu2iuh(ts_RANAP_CommonId(hex2oct(pars.imsi)));
1181}
1182testcase TC_ranap_cs_bidir() runs on test_CT {
1183 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001184 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001185 f_init();
1186 f_start_hnbs();
1187
1188 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(3));
1189 vc_conn.done;
1190}
1191testcase TC_ranap_ps_bidir() runs on test_CT {
1192 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001193 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001194 f_init();
1195 f_start_hnbs();
1196
1197 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(4, true));
1198 vc_conn.done;
1199}
1200
1201
1202private function f_tc_ranap_mo_disconnect(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1203 f_init_handler(pars);
1204
1205 /* HNB -> MSC: InitialUE */
1206 f_iuh2iu_connect(f_build_initial_ue(g_pars));
1207
1208 /* MSC <- HNB: DirectTransfer */
1209 f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1210 /* MSC -> HNB: DirectTransfer */
1211 f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1212
1213 /* MSC <- HNB: RUA disconnect */
1214 f_iuh2iu_disconnect(ts_RANAP_IuReleaseComplete, RUA_IEs.Cause:{misc:=processing_overload});
1215}
1216testcase TC_ranap_cs_mo_disconnect() runs on test_CT {
1217 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001218 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001219 f_init();
1220 f_start_hnbs();
1221
1222 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(5));
1223 vc_conn.done;
1224}
1225testcase TC_ranap_ps_mo_disconnect() runs on test_CT {
1226 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001227 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001228 f_init();
1229 f_start_hnbs();
1230
1231 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(6));
1232 vc_conn.done;
1233}
1234
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001235type record FTeid {
1236 HostName addr,
1237 OCT4 teid
1238}
1239
1240type record FTeids {
1241 FTeid local,
1242 FTeid remote
1243}
Daniel Willmann19b8d902022-01-05 09:12:34 +01001244
1245
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001246/* 'local' and 'remote' refer to the GTP information from the UPF's point of view:
1247 * HNB UPF CN
1248 * access.remote <---> access.local | core.local <---> core.remote
1249 */
1250type record GtpParameters {
1251 FTeids core,
1252 FTeids access
1253}
1254
1255/* HNB UPF CN
1256 * access.remote <---> access.local | core.local <---> core.remote
1257 * 127.0.0.4 127.0.0.3 127.0.0.2 127.0.0.1
1258 * 0x44004400 0x30303030 0x22002200 0x10101010
1259 */
1260template GtpParameters t_GtpParameters := {
1261 core := {
1262 local := {
1263 addr := "127.0.0.2",
1264 teid := '22002200'O
1265 },
1266 remote := {
1267 addr := "127.0.0.1",
1268 teid := '10101010'O
1269 }
1270 },
1271 access := {
1272 local := {
1273 addr := "127.0.0.3",
1274 teid := '30303030'O
1275 },
1276 remote := {
1277 addr := "127.0.0.4",
1278 teid := '44004400'O
1279 }
1280 }
1281}
1282
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001283friend function f_tc_ps_rab_assignment_with_pfcp(charstring id, TestHdlrParams pars) runs on ConnHdlr {
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001284 var RANAP_PDU tx;
1285 var RANAP_PDU rx;
1286 timer T := 5.0;
1287
1288 f_init_handler(pars);
1289
1290 f_pfcp_register();
1291
1292 var PDU_PFCP m;
1293 var Node_ID upf_node_id := valueof(ts_PFCP_Node_ID_fqdn("\07osmocom\03org"));
1294
1295 PFCP.receive(tr_PFCP_Assoc_Setup_Req()) -> value m;
1296 PFCP.send(ts_PFCP_Assoc_Setup_Resp(m.sequence_number, upf_node_id,
1297 ts_PFCP_Cause(REQUEST_ACCEPTED), 1234));
1298
1299 tx := f_build_initial_ue(g_pars);
1300 f_iuh2iu_connect(tx);
1301
1302 var GtpParameters gtp_pars := valueof(t_GtpParameters);
1303 var template RAB_SetupOrModifyList rab_sml;
1304
1305 /* Send RAB Assignment Request */
1306 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.remote.addr), gtp_pars.core.remote.teid);
1307 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1308 BSSAP.send(tx);
1309
1310 /* Expect PFCP Session Establishment Request. */
1311 PFCP.receive(tr_PFCP_Session_Est_Req()) -> value m;
1312 var F_SEID hnbgw_f_seid := m.message_body.pfcp_session_establishment_request.CP_F_SEID;
1313 var PFCP_Session_Establishment_Request serq := m.message_body.pfcp_session_establishment_request;
1314
1315 /* Acting as UPF, invent a new PFCP SEID to send to HNBGW. Respond to the Session Establishment.
1316 * The PFCP response must have the same sequence_number as the request. */
1317 var F_SEID up_f_seid := valueof(ts_PFCP_F_SEID_ipv4("127.0.0.1", '1111111111111111'O));
1318 var template PDU_PFCP r := ts_PFCP_Session_Est_Resp(m.sequence_number, upf_node_id, hnbgw_f_seid.seid);
1319 r.message_body.pfcp_session_establishment_response := {
1320 offending_ie := omit,
1321 UP_F_SEID := up_f_seid,
1322 created_PDR_list := {
1323 ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[0].grouped_ie.pdr_id,
1324 local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.core.local.teid,
1325 gtp_pars.core.local.addr)),
1326 ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[1].grouped_ie.pdr_id,
1327 local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.access.local.teid,
1328 gtp_pars.access.local.addr))
1329 },
1330 load_control_information := omit,
1331 overload_control_information := omit,
1332 node_list := omit,
1333 failed_rule_id := omit,
1334 created_traffic_endpoint_list := omit
1335 };
1336 PFCP.send(r);
1337
1338 /* Expect on Iuh: RAB Assignment Request with IP/port from PFCP Session Est Resp */
1339 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.local.addr),
1340 gtp_pars.access.local.teid);
1341 rx := valueof(ts_RANAP_RabAssReq(rab_sml));
1342 RUA.receive(rx);
1343
1344 /* Send back RAB Assignment Response via Iuh */
1345 var template RAB_SetupOrModifiedList rab_smdl;
1346 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.remote.addr),
1347 gtp_pars.access.remote.teid);
1348 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1349 RUA.send(tx);
1350 T.start;
1351
1352 PFCP.receive(tr_PFCP_Session_Mod_Req(up_f_seid.seid)) -> value m;
1353 r := ts_PFCP_Session_Mod_Resp(m.sequence_number, hnbgw_f_seid.seid);
1354 PFCP.send(r);
1355
1356 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.local.addr), gtp_pars.core.local.teid);
1357 BSSAP.receive(tr_RANAP_RabAssResp(rab_smdl));
1358
1359 f_sleep(2.0);
1360 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1361 f_iu2iuh(tx);
1362
1363 tx := valueof(ts_RANAP_IuReleaseComplete());
1364 f_iuh2iu(tx);
1365
1366 PFCP.receive(tr_PFCP_Session_Del_Req(up_f_seid.seid)) -> value m;
1367 PFCP.send(ts_PFCP_Session_Del_Resp(m.sequence_number, hnbgw_f_seid.seid));
1368
1369 f_sleep(2.0);
1370}
1371
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001372testcase TC_ps_rab_assignment_with_pfcp() runs on test_CT {
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001373 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001374 g_num_hnbs := 1;
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001375 f_init();
1376 f_start_hnbs();
1377 f_sleep(1.0);
1378
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001379 vc_conn := f_start_handler_with_pars(refers(f_tc_ps_rab_assignment_with_pfcp), t_pars(7, ps_domain := true));
1380 vc_conn.done;
1381}
1382
1383altstep as_disallow_pfcp() runs on ConnHdlr {
1384 [] PFCP.receive(PDU_PFCP:?) {
1385 setverdict(fail, "Received PFCP message, but no PFCP communication expected");
1386 mtc.stop;
1387 }
1388}
1389
1390friend function f_tc_ps_rab_assignment_without_pfcp(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1391 var RANAP_PDU tx;
1392 var RANAP_PDU rx;
1393 timer T := 5.0;
1394
1395 f_init_handler(pars);
1396
1397 f_pfcp_register();
1398 activate(as_disallow_pfcp());
1399
1400 tx := f_build_initial_ue(g_pars);
1401 f_iuh2iu_connect(tx);
1402
1403 var GtpParameters gtp_pars := valueof(t_GtpParameters);
1404 var template RAB_SetupOrModifyList rab_sml;
1405
1406 /* Send RAB Assignment Request */
1407 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.remote.addr), gtp_pars.core.remote.teid);
1408 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1409 BSSAP.send(tx);
1410
1411 /* Expect on Iuh: unmodified RAB Assignment Request */
1412 rx := valueof(ts_RANAP_RabAssReq(rab_sml));
1413 RUA.receive(rx);
1414
1415 /* Send back RAB Assignment Response via Iuh */
1416 var template RAB_SetupOrModifiedList rab_smdl;
1417 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.remote.addr),
1418 gtp_pars.access.remote.teid);
1419 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1420 RUA.send(tx);
1421
1422 /* Expect on IuPS: unmodified RAB Assignment Response */
1423 BSSAP.receive(tr_RANAP_RabAssResp(rab_smdl));
1424
1425 f_sleep(2.0);
1426 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1427 f_iu2iuh(tx);
1428
1429 tx := valueof(ts_RANAP_IuReleaseComplete());
1430 f_iuh2iu(tx);
1431
1432 f_sleep(2.0);
1433}
1434
1435testcase TC_ps_rab_assignment_without_pfcp() runs on test_CT {
1436 var ConnHdlr vc_conn;
1437 f_init();
1438 f_start_hnbs();
1439 f_sleep(1.0);
1440
1441 vc_conn := f_start_handler_with_pars(refers(f_tc_ps_rab_assignment_without_pfcp), t_pars(7, ps_domain := true));
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001442 vc_conn.done;
1443}
Daniel Willmann19b8d902022-01-05 09:12:34 +01001444
1445control {
1446 execute(TC_hnb_register());
Daniel Willmannc79679a2022-08-23 17:48:39 +02001447 execute(TC_hnb_register_duplicate());
Pau Espin Pedrolacf4f222022-09-27 14:33:40 +02001448 execute(TC_hnb_register_duplicate_reuse_sctp_assoc());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001449 execute(TC_ranap_cs_initial_ue());
1450 execute(TC_ranap_ps_initial_ue());
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02001451 execute(TC_ranap_cs_initial_ue_empty_cr());
1452 execute(TC_ranap_ps_initial_ue_empty_cr());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001453 execute(TC_ranap_cs_bidir());
1454 execute(TC_ranap_ps_bidir());
1455 execute(TC_rab_assignment());
1456 execute(TC_rab_release());
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001457 execute(TC_rab_assign_fail());
Daniel Willmann37c877f2022-02-22 16:47:06 +01001458 execute(TC_rab_assign_mgcp_to());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001459 execute(TC_ranap_cs_mo_disconnect());
1460 execute(TC_ranap_ps_mo_disconnect());
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001461
1462 if (mp_enable_pfcp_tests) {
1463 execute(TC_ps_rab_assignment_with_pfcp());
1464 } else {
1465 execute(TC_ps_rab_assignment_without_pfcp());
1466 }
Pau Espin Pedrolf0b9fa02022-09-12 13:31:07 +02001467
1468 /* Run at the end since it makes osmo-hnbgw <= 1.3.0 crash: OS#5676 */
1469 execute(TC_hnb_reregister_reuse_sctp_assoc());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001470}
1471
1472}