blob: b1868c2c6ee75d4c6e5f2b8e344d8c78126cbb4d [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
Daniel Willmannc79679a2022-08-23 17:48:39 +0200684testcase TC_hnb_register_duplicate() runs on test_CT {
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200685 g_num_hnbs := 2;
Daniel Willmannc79679a2022-08-23 17:48:39 +0200686 f_init();
687 f_hnbap_register(0);
688 f_hnbap_register(1, 0, expect_reject := true);
689 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
690 f_shutdown_helper();
691}
692
Pau Espin Pedrolf0b9fa02022-09-12 13:31:07 +0200693/* Drop HNBAP conn (HNBAP DEREG) and reconnect it (HNBAP REG) using same SCTP association.
694 * Related: OS#5676, SYS#6113 */
695testcase TC_hnb_reregister_reuse_sctp_assoc() runs on test_CT {
696 g_num_hnbs := 1;
697 f_init();
698 f_hnbap_register(0);
699 HNBAP[0].send(ts_HNBAP_HNBDe_Register(ts_HnbapCause(unspecified)));
700 f_hnbap_register(0);
701 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
702 f_shutdown_helper();
703}
704
Daniel Willmann19b8d902022-01-05 09:12:34 +0100705/***********************************************************************
706 * RUA / RANAP Testing
707 ***********************************************************************/
708
709private template (value) TestHdlrParams
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200710t_pars(integer imsi_suffix, boolean ps_domain := false, integer hnb_idx := 0,
711 boolean separate_sccp_cr := false) := {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100712 hnb_idx := hnb_idx,
713 imsi := f_gen_imsi(imsi_suffix),
714 ps_domain := ps_domain,
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200715 hnb := omit, /* filled in later */
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200716 separate_sccp_cr := separate_sccp_cr,
717 pfcp_local_addr := mp_pfcp_ip_local
Daniel Willmann19b8d902022-01-05 09:12:34 +0100718}
719
720/* Create an Iuh connection; send InitialUE; expect it to appear on new SCCP conenction */
721friend function f_tc_initial_ue(charstring id, TestHdlrParams pars) runs on ConnHdlr {
722 f_init_handler(pars);
723 var RANAP_PDU tx := f_build_initial_ue(g_pars);
724 f_iuh2iu_connect(tx);
725}
726testcase TC_ranap_cs_initial_ue() runs on test_CT {
727 var ConnHdlr vc_conn;
728
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200729 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100730 f_init();
731 f_start_hnbs();
732
733 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(1));
734 vc_conn.done;
735}
736testcase TC_ranap_ps_initial_ue() runs on test_CT {
737 var ConnHdlr vc_conn;
738
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200739 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100740 f_init();
741 f_start_hnbs();
742
743 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(2, true));
744 vc_conn.done;
745}
746
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200747private function f_vty_set_sccp_cr_max_payload_len(TELNETasp_PT pt, integer val := 999999)
748{
749 f_vty_enter_config(pt);
750 f_vty_transceive(pt, "hnbgw");
751 f_vty_transceive(pt, "sccp cr max-payload-len " & int2str(val));
752 f_vty_transceive(pt, "end");
753}
754
755testcase TC_ranap_cs_initial_ue_empty_cr() runs on test_CT {
756 var ConnHdlr vc_conn;
757
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200758 g_num_hnbs := 1;
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200759 f_init();
760 f_start_hnbs();
761
762 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY, 0);
763
764 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(1, separate_sccp_cr := true));
765 vc_conn.done;
766
767 /* reset */
768 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY);
769}
770testcase TC_ranap_ps_initial_ue_empty_cr() runs on test_CT {
771 var ConnHdlr vc_conn;
772
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200773 g_num_hnbs := 1;
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200774 f_init();
775 f_start_hnbs();
776
777 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY, 0);
778
779 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(2, true, separate_sccp_cr := true));
780 vc_conn.done;
781
782 /* reset */
783 f_vty_set_sccp_cr_max_payload_len(HNBGWVTY);
784}
785
Daniel Willmann19b8d902022-01-05 09:12:34 +0100786/* Reply to a received CRCX with an OK (or the reply configured in cpars), using the given parameters.
787 * Return true when an OK reply was sent, false otherwise.
788 * Count occurrence of Osmux, include Osmux parameters in the reply if necessary. */
789function f_handle_crcx(inout MgcpParameters pars, MgcpCommand mgcp_cmd) return template MgcpResponse {
790 var CrcxResponse conn := pars.mgw_conn_1;
791 if (pars.got_crcx_count > 0) {
792 conn := pars.mgw_conn_2;
793 }
794 pars.got_crcx_count := pars.got_crcx_count + 1;
795
796 var MgcpMessage mgcp_msg := {
797 command := mgcp_cmd
798 }
799 var template MgcpResponse mgcp_resp;
800 var MgcpOsmuxCID osmux_cid;
801 var MgcpCallId call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
802 if (ispresent(pars.mgcp_call_id)) {
803 if (pars.mgcp_call_id != call_id) {
804 setverdict(fail, "CRCX contained unexpected call id. Expected:", pars.mgcp_call_id, " got:", call_id);
805 mtc.stop;
806 }
807 } else {
808 pars.mgcp_call_id := call_id;
809 }
810
811 /* When the endpoint contains a wildcard we keep the endpoint
812 * identifier we have set up in pars. Otherwise we use the
813 * endpoint name that the call agent has supplied */
814 if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard) == false) {
815 pars.mgcp_ep := mgcp_cmd.line.ep;
816 }
817
818 if (conn.resp == -1) {
819 /* Reply with rror */
820 var MgcpResponse mgcp_rsp := {
821 line := {
822 code := "542",
823 trans_id := mgcp_cmd.line.trans_id,
824 string := "FORCED_FAIL"
825 },
826 sdp := omit
827
828 }
829 var MgcpParameter mgcp_rsp_param := {
830 code := "Z",
831 val := pars.mgcp_ep
832 };
833 mgcp_rsp.params[0] := mgcp_rsp_param;
834 return mgcp_rsp;
835 }
836
837 if (conn.resp == 0) {
838 /* Do not reply at all */
839 return omit;
840 }
841
842 if (conn.resp != 1) {
843 setverdict(fail, "Unexpected value for pars.mgw_conn_*.resp, expect -1, 0 or 1");
844 mtc.stop;
845 }
846
847 var SDP_Message sdp := valueof(ts_SDP(conn.mgw_rtp_ip, conn.mgw_rtp_ip,
848 hex2str(pars.mgcp_call_id), "42",
849 conn.mgw_rtp_port,
850 { int2str(pars.rtp_payload_type) },
851 { valueof(ts_SDP_rtpmap(pars.rtp_payload_type,
852 pars.rtp_sdp_format)),
853 valueof(ts_SDP_ptime(20)) }));
854
855 if (f_mgcp_contains_par(mgcp_msg, "X-OSMUX")) {
856 if (not pars.use_osmux) {
857 setverdict(fail, "MSC sent X-Osmux parameter in MGCP, but not expecting any Osmux");
858 mtc.stop;
859 }
860 pars.got_osmux_count := pars.got_osmux_count + 1;
861 /* we expect MSC to use wildcard here, i.e. osmux_cid == -1 */
862 osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
863 log("f_handle_crcx(): got Osmux CID: ", osmux_cid);
864 if (osmux_cid != -1) {
865 setverdict(fail, "MSC using unexpected CID " & int2str(osmux_cid) & " != -1");
866 mtc.stop;
867 }
868
869 osmux_cid := 0;
870 mgcp_resp := ts_CRCX_ACK_osmux(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, osmux_cid, sdp);
871 } else {
872 mgcp_resp := ts_CRCX_ACK(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, sdp);
873 }
874
875 f_mgcp_par_append(mgcp_resp.params, ts_MgcpParSpecEP(pars.mgcp_ep));
876
877 return mgcp_resp;
878}
879
Daniel Willmann3e15b7b2022-02-21 17:07:02 +0100880friend function f_create_rab(inout MgcpParameters pars) runs on ConnHdlr {
881 f_rab_ass_req(pars);
882 f_rab_ass_resp(pars);
883}
884
885friend function f_rab_ass_req(inout MgcpParameters pars) runs on ConnHdlr {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100886 var MgcpCommand mgcp_cmd;
887 var RANAP_PDU tx;
888 var template RAB_SetupOrModifyList rab_sml;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100889 timer T := 5.0;
890
891 /* Send RAB Assignment Request */
892 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));
893 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
894 BSSAP.send(tx);
895 T.start;
896
897 /* Handle MGCP CRCX */
898 alt {
899 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
900 log("CRCX1", mgcp_cmd);
901 var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
902 MGCP.send(valueof(mgcp_rsp));
903 }
904 [] T.timeout {
905 setverdict(fail, "Timeout waiting for MGCP");
906 }
907 }
908
909 /* Expect RAB Assignment Request with IP/port from CRCX ACK via Iuh */
910 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));
911 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
912
913 alt {
914 [] RUA.receive(tx) {
915 setverdict(pass);
916 }
917 [] T.timeout {
918 setverdict(fail, "Timeout waiting for Iuh ", tx);
919 }
920 }
Daniel Willmann3e15b7b2022-02-21 17:07:02 +0100921}
922
923friend function f_rab_ass_resp(inout MgcpParameters pars) runs on ConnHdlr {
924 var MgcpCommand mgcp_cmd;
925 var RANAP_PDU tx;
926 var template RAB_SetupOrModifiedList rab_smdl;
927 timer T := 5.0;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100928
929 /* Send back RAB Assignment Response via Iuh */
930 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));
931 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
932 RUA.send(tx);
933 T.start;
934
935 interleave {
936 /* Expect MDCX with IP/port from RAB Assignment Response */
937 [] MGCP.receive(tr_MDCX(tr_SDP(pars.hnb_rtp_ip, pars.hnb_rtp_port))) -> value mgcp_cmd {
938 log("MDCX1", mgcp_cmd);
939 /* Verify SDP of MDCX */
940 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,
941 { int2str(pars.rtp_payload_type) }, { valueof(ts_SDP_rtpmap(pars.rtp_payload_type, pars.rtp_sdp_format)), valueof(ts_SDP_ptime(20)) } ));
942 var template MgcpResponse mgcp_rsp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, pars.mgw_conn_1.mgcp_connection_id, sdp);
943 MGCP.send(valueof(mgcp_rsp));
944 }
945 /* Handle CRCX for second leg of endpoint, answer with IP/port */
946 [] MGCP.receive(tr_CRCX(pars.mgcp_ep, tr_SDP(pars.cn_rtp_ip, pars.cn_rtp_port))) -> value mgcp_cmd {
947 log("CRCX2", mgcp_cmd);
948 /* Verify SDP of CRCX */
949 var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
950 MGCP.send(valueof(mgcp_rsp));
951 }
952 }
953
954 /* Expect RAB Assignment Response with IP/port from second CRCX ACK */
955 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));
956 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
957
958 alt {
959 [] BSSAP.receive(tx) {
960 setverdict(pass);
961 }
962 [] T.timeout {
963 setverdict(fail, "Timeout waiting for Iuh ", tx);
964 }
965 }
966}
967
968private altstep as_mgcp_dlcx(inout TestHdlrParams pars) runs on ConnHdlr {
969 var MgcpCommand mgcp_cmd;
970
971 [] MGCP.receive(tr_DLCX(pars.mgcp_pars.mgcp_ep)) -> value mgcp_cmd {
972 log("DLCX", mgcp_cmd);
973 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
974 pars.mgcp_pars.got_dlcx_count := pars.mgcp_pars.got_dlcx_count + 1;
Daniel Willmann3e15b7b2022-02-21 17:07:02 +0100975 if (pars.mgcp_pars.got_dlcx_count != pars.mgcp_pars.got_crcx_count) {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100976 repeat;
977 }
978 setverdict(pass);
979 }
980}
981
982friend function f_tc_rab_assignment(charstring id, TestHdlrParams pars) runs on ConnHdlr {
983 var MgcpCommand mgcp_cmd;
984 var RANAP_PDU tx;
985 timer T := 5.0;
986
987 f_init_handler(pars);
988 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
989
990 tx := f_build_initial_ue(g_pars);
991 f_iuh2iu_connect(tx);
992
993 f_create_rab(pars.mgcp_pars);
994
995 /* Send Iu Release */
996 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
997 f_iu2iuh(tx);
998
999 T.start;
1000 alt {
1001 [] as_mgcp_dlcx(pars) {}
1002 [] T.timeout {
1003 setverdict(fail, "Timeout waiting for DLCX");
1004 }
1005 }
1006
1007 tx := valueof(ts_RANAP_IuReleaseComplete());
1008 f_iuh2iu(tx);
1009}
1010
1011testcase TC_rab_assignment() runs on test_CT {
1012 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001013 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001014 f_init();
1015 f_start_hnbs();
1016
1017 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assignment), t_pars(3));
1018 vc_conn.done;
1019}
1020
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001021friend function f_tc_rab_assign_fail(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1022 var MgcpCommand mgcp_cmd;
1023 var RANAP_PDU tx;
1024 timer T := 5.0;
1025
1026 f_init_handler(pars);
1027 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1028
1029 tx := f_build_initial_ue(g_pars);
1030 f_iuh2iu_connect(tx);
1031
1032 f_rab_ass_req(pars.mgcp_pars);
1033
1034 /* Send RAB failed list in response */
1035 tx := valueof(ts_RANAP_RabAssResp(rab_fl := ts_RAB_FL(t_RAB_id(23), ts_RanapCause_om_intervention)));
1036 f_iuh2iu(tx);
1037
1038 T.start;
1039 alt {
1040 [] as_mgcp_dlcx(pars) {}
1041 [] T.timeout {
1042 setverdict(fail, "Timeout waiting for DLCX");
1043 }
1044 }
1045}
1046
1047testcase TC_rab_assign_fail() runs on test_CT {
1048 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001049 g_num_hnbs := 1;
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001050 f_init();
1051 f_start_hnbs();
1052
1053 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_fail), t_pars(4));
1054 vc_conn.done;
1055}
1056
Daniel Willmann19b8d902022-01-05 09:12:34 +01001057friend function f_tc_rab_release(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1058 var MgcpCommand mgcp_cmd;
1059 var RANAP_PDU tx;
1060 timer T := 15.0;
1061
1062 f_init_handler(pars);
1063 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1064
1065 tx := f_build_initial_ue(g_pars);
1066 f_iuh2iu_connect(tx);
1067
1068 f_create_rab(pars.mgcp_pars);
1069
1070 /* Send RAB Release */
Daniel Willmann9e789be2022-02-22 13:30:51 +01001071 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 +01001072 BSSAP.send(tx);
1073
1074 T.start;
1075
1076 alt {
1077 [] as_mgcp_dlcx(pars) {}
1078 [] T.timeout {
1079 setverdict(fail, "Timeout waiting for DLCX");
1080 }
1081 }
1082
1083 alt {
1084 [] RUA.receive(tx) {
1085 setverdict(pass);
1086 }
1087 [] T.timeout {
1088 setverdict(fail, "Timeout waiting for Iuh ", tx);
1089 }
1090 }
1091
1092}
1093
1094testcase TC_rab_release() runs on test_CT {
1095 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001096 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001097 f_init();
1098 f_start_hnbs();
1099
1100 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_release), t_pars(5));
1101 vc_conn.done;
1102}
1103
Daniel Willmann37c877f2022-02-22 16:47:06 +01001104friend function f_tc_rab_assign_mgcp_to(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1105 var MgcpCommand mgcp_cmd;
1106 var RANAP_PDU tx;
1107 var template RAB_SetupOrModifyList rab_sml;
1108 timer T := 15.0;
1109
1110 T.start;
1111 f_init_handler(pars);
1112 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1113
1114 tx := f_build_initial_ue(g_pars);
1115 f_iuh2iu_connect(tx);
1116
1117
1118 /* Send RAB Assignment Request */
1119 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));
1120 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1121 BSSAP.send(tx);
1122
1123 /* Ignore MGCP CRCX */
1124 alt {
1125 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
1126 log("Ignoreing CRCX1", mgcp_cmd);
1127 repeat;
1128 }
1129 [] BSSAP.receive(tr_RANAP_IuReleaseRequest(?)) { }
1130 [] T.timeout {
1131 setverdict(fail, "Timeout waiting for IuRelease");
1132 }
1133 }
1134
1135 /* Send Iu Release */
1136 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1137 f_iu2iuh(tx);
1138
1139 tx := valueof(ts_RANAP_IuReleaseComplete());
1140 f_iuh2iu(tx);
1141}
1142
1143testcase TC_rab_assign_mgcp_to() runs on test_CT {
1144 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001145 g_num_hnbs := 1;
Daniel Willmann37c877f2022-02-22 16:47:06 +01001146 f_init();
1147 f_start_hnbs();
1148
1149 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_mgcp_to), t_pars(6));
1150 vc_conn.done;
1151}
1152
Daniel Willmann19b8d902022-01-05 09:12:34 +01001153/* Create an Iuh connection; send InitialUE; transceive data both directions */
1154friend function f_tc_ranap_bidir(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1155 f_init_handler(pars);
1156
1157 /* HNB -> MSC: InitialUE */
1158 f_iuh2iu_connect(f_build_initial_ue(g_pars));
1159
1160 /* MSC <- HNB: DirectTransfer */
1161 f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1162 /* MSC -> HNB: DirectTransfer */
1163 f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1164
1165 /* HNB <- MSC: CommonID */
1166 f_iu2iuh(ts_RANAP_CommonId(hex2oct(pars.imsi)));
1167}
1168testcase TC_ranap_cs_bidir() runs on test_CT {
1169 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001170 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001171 f_init();
1172 f_start_hnbs();
1173
1174 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(3));
1175 vc_conn.done;
1176}
1177testcase TC_ranap_ps_bidir() runs on test_CT {
1178 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001179 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001180 f_init();
1181 f_start_hnbs();
1182
1183 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(4, true));
1184 vc_conn.done;
1185}
1186
1187
1188private function f_tc_ranap_mo_disconnect(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1189 f_init_handler(pars);
1190
1191 /* HNB -> MSC: InitialUE */
1192 f_iuh2iu_connect(f_build_initial_ue(g_pars));
1193
1194 /* MSC <- HNB: DirectTransfer */
1195 f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1196 /* MSC -> HNB: DirectTransfer */
1197 f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1198
1199 /* MSC <- HNB: RUA disconnect */
1200 f_iuh2iu_disconnect(ts_RANAP_IuReleaseComplete, RUA_IEs.Cause:{misc:=processing_overload});
1201}
1202testcase TC_ranap_cs_mo_disconnect() runs on test_CT {
1203 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001204 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001205 f_init();
1206 f_start_hnbs();
1207
1208 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(5));
1209 vc_conn.done;
1210}
1211testcase TC_ranap_ps_mo_disconnect() runs on test_CT {
1212 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001213 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001214 f_init();
1215 f_start_hnbs();
1216
1217 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(6));
1218 vc_conn.done;
1219}
1220
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001221type record FTeid {
1222 HostName addr,
1223 OCT4 teid
1224}
1225
1226type record FTeids {
1227 FTeid local,
1228 FTeid remote
1229}
Daniel Willmann19b8d902022-01-05 09:12:34 +01001230
1231
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001232/* 'local' and 'remote' refer to the GTP information from the UPF's point of view:
1233 * HNB UPF CN
1234 * access.remote <---> access.local | core.local <---> core.remote
1235 */
1236type record GtpParameters {
1237 FTeids core,
1238 FTeids access
1239}
1240
1241/* HNB UPF CN
1242 * access.remote <---> access.local | core.local <---> core.remote
1243 * 127.0.0.4 127.0.0.3 127.0.0.2 127.0.0.1
1244 * 0x44004400 0x30303030 0x22002200 0x10101010
1245 */
1246template GtpParameters t_GtpParameters := {
1247 core := {
1248 local := {
1249 addr := "127.0.0.2",
1250 teid := '22002200'O
1251 },
1252 remote := {
1253 addr := "127.0.0.1",
1254 teid := '10101010'O
1255 }
1256 },
1257 access := {
1258 local := {
1259 addr := "127.0.0.3",
1260 teid := '30303030'O
1261 },
1262 remote := {
1263 addr := "127.0.0.4",
1264 teid := '44004400'O
1265 }
1266 }
1267}
1268
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001269friend function f_tc_ps_rab_assignment_with_pfcp(charstring id, TestHdlrParams pars) runs on ConnHdlr {
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001270 var RANAP_PDU tx;
1271 var RANAP_PDU rx;
1272 timer T := 5.0;
1273
1274 f_init_handler(pars);
1275
1276 f_pfcp_register();
1277
1278 var PDU_PFCP m;
1279 var Node_ID upf_node_id := valueof(ts_PFCP_Node_ID_fqdn("\07osmocom\03org"));
1280
1281 PFCP.receive(tr_PFCP_Assoc_Setup_Req()) -> value m;
1282 PFCP.send(ts_PFCP_Assoc_Setup_Resp(m.sequence_number, upf_node_id,
1283 ts_PFCP_Cause(REQUEST_ACCEPTED), 1234));
1284
1285 tx := f_build_initial_ue(g_pars);
1286 f_iuh2iu_connect(tx);
1287
1288 var GtpParameters gtp_pars := valueof(t_GtpParameters);
1289 var template RAB_SetupOrModifyList rab_sml;
1290
1291 /* Send RAB Assignment Request */
1292 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.remote.addr), gtp_pars.core.remote.teid);
1293 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1294 BSSAP.send(tx);
1295
1296 /* Expect PFCP Session Establishment Request. */
1297 PFCP.receive(tr_PFCP_Session_Est_Req()) -> value m;
1298 var F_SEID hnbgw_f_seid := m.message_body.pfcp_session_establishment_request.CP_F_SEID;
1299 var PFCP_Session_Establishment_Request serq := m.message_body.pfcp_session_establishment_request;
1300
1301 /* Acting as UPF, invent a new PFCP SEID to send to HNBGW. Respond to the Session Establishment.
1302 * The PFCP response must have the same sequence_number as the request. */
1303 var F_SEID up_f_seid := valueof(ts_PFCP_F_SEID_ipv4("127.0.0.1", '1111111111111111'O));
1304 var template PDU_PFCP r := ts_PFCP_Session_Est_Resp(m.sequence_number, upf_node_id, hnbgw_f_seid.seid);
1305 r.message_body.pfcp_session_establishment_response := {
1306 offending_ie := omit,
1307 UP_F_SEID := up_f_seid,
1308 created_PDR_list := {
1309 ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[0].grouped_ie.pdr_id,
1310 local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.core.local.teid,
1311 gtp_pars.core.local.addr)),
1312 ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[1].grouped_ie.pdr_id,
1313 local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.access.local.teid,
1314 gtp_pars.access.local.addr))
1315 },
1316 load_control_information := omit,
1317 overload_control_information := omit,
1318 node_list := omit,
1319 failed_rule_id := omit,
1320 created_traffic_endpoint_list := omit
1321 };
1322 PFCP.send(r);
1323
1324 /* Expect on Iuh: RAB Assignment Request with IP/port from PFCP Session Est Resp */
1325 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.local.addr),
1326 gtp_pars.access.local.teid);
1327 rx := valueof(ts_RANAP_RabAssReq(rab_sml));
1328 RUA.receive(rx);
1329
1330 /* Send back RAB Assignment Response via Iuh */
1331 var template RAB_SetupOrModifiedList rab_smdl;
1332 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.remote.addr),
1333 gtp_pars.access.remote.teid);
1334 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1335 RUA.send(tx);
1336 T.start;
1337
1338 PFCP.receive(tr_PFCP_Session_Mod_Req(up_f_seid.seid)) -> value m;
1339 r := ts_PFCP_Session_Mod_Resp(m.sequence_number, hnbgw_f_seid.seid);
1340 PFCP.send(r);
1341
1342 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.local.addr), gtp_pars.core.local.teid);
1343 BSSAP.receive(tr_RANAP_RabAssResp(rab_smdl));
1344
1345 f_sleep(2.0);
1346 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1347 f_iu2iuh(tx);
1348
1349 tx := valueof(ts_RANAP_IuReleaseComplete());
1350 f_iuh2iu(tx);
1351
1352 PFCP.receive(tr_PFCP_Session_Del_Req(up_f_seid.seid)) -> value m;
1353 PFCP.send(ts_PFCP_Session_Del_Resp(m.sequence_number, hnbgw_f_seid.seid));
1354
1355 f_sleep(2.0);
1356}
1357
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001358testcase TC_ps_rab_assignment_with_pfcp() runs on test_CT {
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001359 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001360 g_num_hnbs := 1;
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001361 f_init();
1362 f_start_hnbs();
1363 f_sleep(1.0);
1364
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001365 vc_conn := f_start_handler_with_pars(refers(f_tc_ps_rab_assignment_with_pfcp), t_pars(7, ps_domain := true));
1366 vc_conn.done;
1367}
1368
1369altstep as_disallow_pfcp() runs on ConnHdlr {
1370 [] PFCP.receive(PDU_PFCP:?) {
1371 setverdict(fail, "Received PFCP message, but no PFCP communication expected");
1372 mtc.stop;
1373 }
1374}
1375
1376friend function f_tc_ps_rab_assignment_without_pfcp(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1377 var RANAP_PDU tx;
1378 var RANAP_PDU rx;
1379 timer T := 5.0;
1380
1381 f_init_handler(pars);
1382
1383 f_pfcp_register();
1384 activate(as_disallow_pfcp());
1385
1386 tx := f_build_initial_ue(g_pars);
1387 f_iuh2iu_connect(tx);
1388
1389 var GtpParameters gtp_pars := valueof(t_GtpParameters);
1390 var template RAB_SetupOrModifyList rab_sml;
1391
1392 /* Send RAB Assignment Request */
1393 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.remote.addr), gtp_pars.core.remote.teid);
1394 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1395 BSSAP.send(tx);
1396
1397 /* Expect on Iuh: unmodified RAB Assignment Request */
1398 rx := valueof(ts_RANAP_RabAssReq(rab_sml));
1399 RUA.receive(rx);
1400
1401 /* Send back RAB Assignment Response via Iuh */
1402 var template RAB_SetupOrModifiedList rab_smdl;
1403 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.remote.addr),
1404 gtp_pars.access.remote.teid);
1405 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1406 RUA.send(tx);
1407
1408 /* Expect on IuPS: unmodified RAB Assignment Response */
1409 BSSAP.receive(tr_RANAP_RabAssResp(rab_smdl));
1410
1411 f_sleep(2.0);
1412 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1413 f_iu2iuh(tx);
1414
1415 tx := valueof(ts_RANAP_IuReleaseComplete());
1416 f_iuh2iu(tx);
1417
1418 f_sleep(2.0);
1419}
1420
1421testcase TC_ps_rab_assignment_without_pfcp() runs on test_CT {
1422 var ConnHdlr vc_conn;
1423 f_init();
1424 f_start_hnbs();
1425 f_sleep(1.0);
1426
1427 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 +02001428 vc_conn.done;
1429}
Daniel Willmann19b8d902022-01-05 09:12:34 +01001430
1431control {
1432 execute(TC_hnb_register());
Daniel Willmannc79679a2022-08-23 17:48:39 +02001433 execute(TC_hnb_register_duplicate());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001434 execute(TC_ranap_cs_initial_ue());
1435 execute(TC_ranap_ps_initial_ue());
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02001436 execute(TC_ranap_cs_initial_ue_empty_cr());
1437 execute(TC_ranap_ps_initial_ue_empty_cr());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001438 execute(TC_ranap_cs_bidir());
1439 execute(TC_ranap_ps_bidir());
1440 execute(TC_rab_assignment());
1441 execute(TC_rab_release());
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001442 execute(TC_rab_assign_fail());
Daniel Willmann37c877f2022-02-22 16:47:06 +01001443 execute(TC_rab_assign_mgcp_to());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001444 execute(TC_ranap_cs_mo_disconnect());
1445 execute(TC_ranap_ps_mo_disconnect());
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001446
1447 if (mp_enable_pfcp_tests) {
1448 execute(TC_ps_rab_assignment_with_pfcp());
1449 } else {
1450 execute(TC_ps_rab_assignment_without_pfcp());
1451 }
Pau Espin Pedrolf0b9fa02022-09-12 13:31:07 +02001452
1453 /* Run at the end since it makes osmo-hnbgw <= 1.3.0 crash: OS#5676 */
1454 execute(TC_hnb_reregister_reuse_sctp_assoc());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001455}
1456
1457}