blob: e9db214a7a5f1a67ee8ff3eb9d63f6c8df861d72 [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;
Neels Hofmeyr1e311462023-01-11 01:19:12 +010021import from Native_Functions all;
Daniel Willmann19b8d902022-01-05 09:12:34 +010022
23import from Osmocom_CTRL_Functions all;
24import from Osmocom_CTRL_Types all;
25import from Osmocom_CTRL_Adapter all;
26
27import from StatsD_Types all;
28import from StatsD_CodecPort all;
29import from StatsD_CodecPort_CtrlFunct all;
30import from StatsD_Checker all;
31
32import from Osmocom_VTY_Functions all;
33import from TELNETasp_PortType all;
34
35import from HNBAP_Templates all;
36import from HNBAP_PDU_Descriptions all;
37
38import from RUA_IEs all;
39import from RUA_Templates all;
40import from RUA_Emulation all;
41
42import from Iuh_Emulation all;
43
44import from RANAP_Types all;
45import from RANAP_PDU_Descriptions all;
46import from RANAP_PDU_Contents all;
47import from RANAP_IEs all;
48import from RANAP_Templates all;
49
50import from RAN_Adapter all;
Daniel Willmann19b8d902022-01-05 09:12:34 +010051import from RAN_Emulation all;
52
53import from MGCP_Emulation all;
54import from MGCP_Types all;
55import from MGCP_Templates all;
56import from MGCP_CodecPort all;
57import from SDP_Types all;
58
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +020059import from PFCP_Types all;
60import from PFCP_Emulation all;
61import from PFCP_Templates all;
62import from PFCP_CodecPort all;
63
Neels Hofmeyr75d905b2023-04-27 00:30:25 +020064import from TCCConversion_Functions all;
65
Daniel Willmann19b8d902022-01-05 09:12:34 +010066modulepar {
67 /* IP address at which the HNodeB can be reached */
68 charstring mp_hnodeb_ip := "127.0.0.1";
69 integer mp_hnodeb_port := -1;
70
71 /* IP address at which the test binds */
72 charstring mp_hnbgw_ip := "127.0.0.1";
73 integer mp_hnbgw_iuh_port := 29169;
74
75 charstring mp_mgw_ip := "127.0.0.1";
76 integer mp_mgw_port := 2427;
77
78 RAN_Configuration mp_msc_cfg := {
79 transport := RANAP_TRANSPORT_IuCS,
80 sccp_service_type := "mtp3_itu",
81 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
82 own_pc := 188, /* 0.23.4 first MSC emulation */
83 own_ssn := 142,
84 peer_pc := 189, /* 0.23.5 osmo-hnbgw */
85 peer_ssn := 142,
86 sio := '83'O,
87 rctx := 1
88 };
89 RAN_Configuration mp_sgsn_cfg := {
90 transport := RANAP_TRANSPORT_IuCS,
91 sccp_service_type := "mtp3_itu",
Neels Hofmeyrb869dc82023-04-16 01:49:38 +020092 sctp_addr := { /* local */ 23906, "127.0.0.1", /* remote */ 2905, "127.0.0.1" },
Daniel Willmann19b8d902022-01-05 09:12:34 +010093 own_pc := 185, /* 0.23.1 first SGSN emulation */
94 own_ssn := 142,
95 peer_pc := 189, /* 0.23.5 osmo-hnbgw */
96 peer_ssn := 142,
97 sio := '83'O,
98 rctx := 2
99 };
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200100
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +0200101 boolean mp_enable_pfcp_tests := false;
102
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200103 /* IP address at which we listen for PFCP to emulate a UPF in ttcn3 */
104 charstring mp_pfcp_ip_local := "127.0.0.1";
105
106 /* IP address from which the SUT (osmo-hnbgw) sends PFCP requests, and to which the ttcn3 UPF emulation sends
107 * PFCP responses. */
108 charstring mp_pfcp_ip_remote := "127.0.0.2";
Daniel Willmann19b8d902022-01-05 09:12:34 +0100109}
110
111function MSC_UnitdataCallback(RANAP_PDU ranap) runs on RAN_Emulation_CT return template RANAP_PDU {
112 // TODO: Actually implement unitdata handling
Neels Hofmeyrcf6dc492023-06-27 00:51:08 +0200113 return omit;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100114}
115
116const RanOps MSC_RanOps := {
117 ranap_create_cb := refers(RAN_Emulation.RanapExpectedCreateCallback),
118 ranap_unitdata_cb := refers(MSC_UnitdataCallback),
119 ps_domain := false,
120 decode_dtap := false,
121 role_ms := false,
122 protocol := RAN_PROTOCOL_RANAP,
123 transport := RANAP_TRANSPORT_IuCS,
124 use_osmux := false,
Eric Wild6e511ce2022-04-02 21:35:56 +0200125 bssap_reset_retries := 1,
Daniel Willmann19b8d902022-01-05 09:12:34 +0100126 sccp_addr_local := omit,
127 sccp_addr_peer := omit
128}
129
130type record CrcxResponse {
131 integer resp,
132 HostName mgw_rtp_ip,
133 PortNumber mgw_rtp_port,
134 MgcpConnectionId mgcp_connection_id
135}
136type record MgcpParameters {
137 integer got_crcx_count,
138 integer got_dlcx_count,
139 MgcpCallId mgcp_call_id optional,
140 MgcpEndpoint mgcp_ep,
141 CrcxResponse mgw_conn_1,
142 CrcxResponse mgw_conn_2,
143 uint7_t rtp_payload_type,
144 charstring rtp_sdp_format,
145 HostName hnb_rtp_ip,
146 PortNumber hnb_rtp_port,
147 HostName cn_rtp_ip,
148 PortNumber cn_rtp_port,
149 boolean use_osmux,
150 integer got_osmux_count
151}
152
153template (value) MgcpParameters t_MgcpParams := {
154 got_crcx_count := 0,
155 got_dlcx_count := 0,
156 mgcp_call_id := omit,
157 mgcp_ep := "rtpbridge/1@mgw",
158 mgw_conn_1 := {
159 resp := 1,
160 mgw_rtp_ip := "127.1.2.1",
161 mgw_rtp_port := 10000,
162 mgcp_connection_id := '11111'H
163 },
164 mgw_conn_2 := {
165 resp := 1,
166 mgw_rtp_ip := "127.1.2.2",
167 mgw_rtp_port := 20000,
168 mgcp_connection_id := '22222'H
169 },
Philipp Maier6c5ba0752023-07-04 16:53:40 +0200170 rtp_payload_type := 112,
171 rtp_sdp_format := "VND.3GPP.IUFP",
Daniel Willmann19b8d902022-01-05 09:12:34 +0100172 hnb_rtp_ip := "127.1.1.1",
173 hnb_rtp_port := 10001,
174 cn_rtp_ip := "127.1.3.1",
175 cn_rtp_port := 20001,
176 use_osmux := false,
177 got_osmux_count := 0
178}
179
180type record TestHdlrParams {
181 integer hnb_idx,
182 hexstring imsi,
183 boolean ps_domain,
184 MgcpParameters mgcp_pars optional,
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200185 HnbConfig hnb optional,
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200186 boolean expect_separate_sccp_cr,
187 integer tx_sccp_cr_data_len,
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200188 charstring pfcp_local_addr
Daniel Willmann19b8d902022-01-05 09:12:34 +0100189}
190
191/* We extend:
192 * RUA_ConnHdlr (for the Iuh side, emulating the HNB)
193 * RAN_ConnHdlr (for the Iu side, emulating the MSC)
194 * MGCP_ConnHdlr (for the MGCP side, emulating the MGW)
195 */
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200196type component ConnHdlr extends RAN_ConnHdlr, MGCP_ConnHdlr, RUA_ConnHdlr, PFCP_ConnHdlr {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100197 var integer g_sccp_conn_id;
198 var TestHdlrParams g_pars;
199 timer g_Tguard;
Neels Hofmeyr72a8d622023-01-26 13:47:01 +0100200
201 port TELNETasp_PT HNBGWVTY;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100202}
203
204
205const MGCPOps MSC_MGCPOps := {
206 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
207 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
208}
209
210function f_create_ranap_exp(octetstring l3_enc) runs on ConnHdlr {
211 BSSAP_PROC.call(RAN_register:{l3_enc, self}) {
212 [] BSSAP_PROC.getreply(RAN_register:{?, ?}) {};
213 }
214}
215
216
Daniel Willmannc79679a2022-08-23 17:48:39 +0200217const integer NUM_HNB := 2;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100218
Daniel Willmann19b8d902022-01-05 09:12:34 +0100219type record HnbConfig {
220 LocationAreaIdentification lai,
221 integer sac
222}
223
224type component test_CT extends CTRL_Adapter_CT {
225 var boolean g_initialized := false;
226
227 /********************* Iu side */
228 var RAN_Adapter g_msc;
229 var RAN_Adapter g_sgsn;
230 /* SGSN IuPS missing */
231
232 /********************* Iuh side */
233 var HnbConfig g_hnb_cfg[NUM_HNB];
234 var Iuh_Emulation_CT vc_Iuh[NUM_HNB];
235 var RUA_Emulation_CT vc_RUA[NUM_HNB];
236 port HNBAP_PT HNBAP[NUM_HNB];
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200237 /* Number of HNBs to be used/started by the test */
238 var integer g_num_hnbs := NUM_HNB;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100239
240 var MGCP_Emulation_CT vc_MGCP;
241 port TELNETasp_PT HNBGWVTY;
242 /* global test case guard timer (actual timeout value is set in f_init()) */
243 timer T_guard := 30.0;
244}
245
246/* global altstep for global guard timer; */
247altstep as_Tguard() runs on test_CT {
248 [] T_guard.timeout {
249 setverdict(fail, "Timeout of T_guard");
250 mtc.stop;
251 }
252}
253
254friend function f_logp(TELNETasp_PT pt, charstring log_msg)
255{
256 // log on TTCN3 log output
257 log(log_msg);
258 // log in stderr log
259 f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
260}
261
262function f_init_vty(charstring id := "foo") runs on test_CT {
263 if (HNBGWVTY.checkstate("Mapped")) {
264 /* skip initialization if already executed once */
265 return;
266 }
267 map(self:HNBGWVTY, system:HNBGWVTY);
268 f_vty_set_prompts(HNBGWVTY);
269 f_vty_transceive(HNBGWVTY, "enable");
270}
271
272function f_init_mgcp(charstring id) runs on test_CT {
273 id := id & "-MGCP";
274 var MGCPOps ops := {
275 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
276 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
277 }
278 var MGCP_conn_parameters pars := {
279 callagent_ip := mp_hnbgw_ip,
280 callagent_udp_port := -1,
281 mgw_ip := mp_mgw_ip,
282 mgw_udp_port := mp_mgw_port,
283 multi_conn_mode := false
284 }
285
286 vc_MGCP := MGCP_Emulation_CT.create(id);
287 map(vc_MGCP:MGCP, system:MGCP_CODEC_PT);
288 vc_MGCP.start(MGCP_Emulation.main(ops, pars, id));
289}
290
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200291function f_init_pfcp(charstring id) runs on ConnHdlr {
292 id := id & "-PFCP";
293
294 var PFCP_Emulation_Cfg pfcp_cfg := {
295 pfcp_bind_ip := mp_pfcp_ip_local,
296 pfcp_bind_port := PFCP_PORT,
297 pfcp_remote_ip := mp_pfcp_ip_remote,
298 pfcp_remote_port := PFCP_PORT,
299 role := UPF
300 };
301
302 vc_PFCP := PFCP_Emulation_CT.create(id) alive;
303 connect(self:PFCP, vc_PFCP:CLIENT);
304 connect(self:PFCP_PROC, vc_PFCP:CLIENT_PROC);
305 vc_PFCP.start(PFCP_Emulation.main(pfcp_cfg));
306}
307
Daniel Willmann19b8d902022-01-05 09:12:34 +0100308function f_init_hnodeb(charstring id, integer hnb_idx, RuaOps rua_ops) runs on test_CT {
309 id := id & "-Iuh" & int2str(hnb_idx);
310
311 /* Iuh lower layer (RUA/HNBAP demux) */
312 var Iuh_conn_parameters iuh_pars;
313 iuh_pars.remote_ip := mp_hnbgw_ip;
314 iuh_pars.remote_sctp_port := mp_hnbgw_iuh_port;
315 iuh_pars.local_ip := mp_hnodeb_ip;
316 iuh_pars.local_sctp_port := mp_hnodeb_port + hnb_idx;
317 vc_Iuh[hnb_idx] := Iuh_Emulation_CT.create(id);
318 connect(self:HNBAP[hnb_idx], vc_Iuh[hnb_idx]:HNBAP);
319
320 vc_RUA[hnb_idx] := RUA_Emulation_CT.create(id & "-RUA");
321 connect(vc_RUA[hnb_idx]:RUA, vc_Iuh[hnb_idx]:RUA);
322
323 /* Start Iuh side components */
324 vc_Iuh[hnb_idx].start(Iuh_Emulation.main(iuh_pars, id));
325 vc_RUA[hnb_idx].start(RUA_Emulation.main(rua_ops, id & "-RUA"));
326}
327
328/* global initialization function */
Neels Hofmeyr82e79b02022-06-08 00:08:09 +0200329function f_init(charstring id := "HNBGW", float guard_timeout := 30.0) runs on test_CT {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100330
Daniel Willmann19b8d902022-01-05 09:12:34 +0100331 T_guard.start(guard_timeout);
332 activate(as_Tguard());
333
334 /* RUA/RANAP emulation on top of lower-layer Iuh */
335 var RuaOps rua_ops := {
336 create_cb := refers(IuhRanapCreateCallback),
337 unitdata_cb := refers(IuhRanapUnitdataCallback)
338 };
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200339 for (var integer i := 0; i < g_num_hnbs; i := i+1) {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200340 g_hnb_cfg[i] := {
341 lai := {
Neels Hofmeyr497216f2023-06-27 00:59:26 +0200342 mcc_mnc := '00F110'H,
Daniel Willmannc79679a2022-08-23 17:48:39 +0200343 lac := 2342 + i
344 },
345 sac := 55
346 };
Daniel Willmann19b8d902022-01-05 09:12:34 +0100347 f_init_hnodeb(testcasename(), i, rua_ops);
348 }
349
350 /* MSC emulation */
351 var RanOps ranops := {
352 ranap_create_cb := refers(RAN_Emulation.RanapExpectedCreateCallback),
353 ranap_unitdata_cb := omit,
354 ps_domain := false,
355 decode_dtap := false,
356 role_ms := false,
357 protocol := RAN_PROTOCOL_RANAP,
358 transport := RANAP_TRANSPORT_IuCS,
359 use_osmux := false,
Eric Wild6e511ce2022-04-02 21:35:56 +0200360 bssap_reset_retries := 1,
Daniel Willmann19b8d902022-01-05 09:12:34 +0100361 sccp_addr_local := omit,
362 sccp_addr_peer := omit
363 };
364 f_ran_adapter_init(g_msc, mp_msc_cfg, "HNBGW_Test", ranops);
365 f_ran_adapter_start(g_msc);
366
367 /* SGSN emulation */
368 ranops.ps_domain := true;
369 f_ran_adapter_init(g_sgsn, mp_sgsn_cfg, "HNBGW_Test", ranops);
370 f_ran_adapter_start(g_sgsn);
371
372 f_init_mgcp(id);
373 f_init_vty("VirtHNBGW");
374}
375
376friend function f_shutdown_helper() runs on test_CT {
Neels Hofmeyr75d905b2023-04-27 00:30:25 +0200377 f_verify_talloc_bytes(HNBGWVTY, {"asn1_context"}, 1);
378
Daniel Willmann19b8d902022-01-05 09:12:34 +0100379 all component.stop;
380 setverdict(pass);
381 mtc.stop;
382}
383
384/* helper function to start all of the simulated hNodeBs */
385function f_start_hnbs() runs on test_CT {
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200386 for (var integer i:= 0; i < g_num_hnbs; i := i+1) {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200387 f_hnbap_register(i, i);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100388 }
389}
390
391/***********************************************************************
392 * code running in test_CT, preparing start of per-UE ConnHdlr
393 ***********************************************************************/
394
395/* inbound RUA connection establishment on Iuh side */
396function IuhRanapCreateCallback(ContextId context_id, RUA_IEs.CN_DomainIndicator domain, charstring id)
397runs on RUA_Emulation_CT return RUA_ConnHdlr {
398 log("CreateCallback");
399 return null;
400}
401
402/* inbound RUA connectionless data on Iuh side */
403function IuhRanapUnitdataCallback(RANAP_PDU ranap)
404runs on RUA_Emulation_CT return template RANAP_PDU {
405 log("UnitdataCallback");
406 return omit;
407}
408
409private function f_start_handler_create(TestHdlrParams pars) runs on test_CT return ConnHdlr {
410 var ConnHdlr vc_conn;
411 var charstring id := testcasename() & int2str(pars.hnb_idx);
412
413 vc_conn := ConnHdlr.create(id);
414
415 /* Iuh RUA part */
416 connect(vc_conn:RUA, vc_RUA[pars.hnb_idx]:CLIENT);
417
418 if (pars.ps_domain) {
419 /* SGSN side */
420 connect(vc_conn:BSSAP, g_sgsn.vc_RAN:CLIENT);
421 connect(vc_conn:BSSAP_PROC, g_sgsn.vc_RAN:PROC);
422 } else {
423 /* MSC side */
424 connect(vc_conn:BSSAP, g_msc.vc_RAN:CLIENT);
425 connect(vc_conn:BSSAP_PROC, g_msc.vc_RAN:PROC);
426 }
427 /* MGCP part */
428 connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
429 connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
430
431 return vc_conn;
432}
433
434private function f_start_handler_run(ConnHdlr vc_conn, void_fn fn, TestHdlrParams pars) runs on test_CT {
435 var charstring id := testcasename(); // & int2str(pars.ran_idx);
436 /* We cannot use vc_conn.start(f_init_handler(fn, id, pars)); as we cannot have
437 * a stand-alone 'derefers()' call, see https://www.eclipse.org/forums/index.php/t/1091364/ */
438 pars.hnb := g_hnb_cfg[pars.hnb_idx];
439 pars.mgcp_pars := valueof(t_MgcpParams);
440 vc_conn.start(derefers(fn)(id, pars));
441}
442
443function f_start_handler_with_pars(void_fn fn, template (value) TestHdlrParams pars)
444runs on test_CT return ConnHdlr {
445 var ConnHdlr vc_conn;
446 vc_conn := f_start_handler_create(valueof(pars));
447 f_start_handler_run(vc_conn, fn, valueof(pars));
448 return vc_conn;
449}
450
451/***********************************************************************
452 * code running inside per-UE ConnHdlr
453 ***********************************************************************/
454
455type function void_fn(charstring id, TestHdlrParams pars) runs on ConnHdlr;
456
457function f_init_handler(TestHdlrParams pars, float t_guard := 20.0) runs on ConnHdlr {
458 /* make parameters available via component variable */
459 g_pars := pars;
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200460
461 f_init_pfcp(testcasename());
462
Daniel Willmann19b8d902022-01-05 09:12:34 +0100463 /* start guard timer and activate it as default */
464 g_Tguard.start(t_guard);
465 activate(as_Tguard_ConnHdlr());
466
Neels Hofmeyr72a8d622023-01-26 13:47:01 +0100467 map(self:HNBGWVTY, system:HNBGWVTY);
468 f_vty_set_prompts(HNBGWVTY);
469 f_vty_transceive(HNBGWVTY, "enable");
470
Daniel Willmann19b8d902022-01-05 09:12:34 +0100471 /* TODO: CTRL? */
Neels Hofmeyr59517222023-06-23 04:46:59 +0200472
473 f_sleep(1.0);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100474}
475
476/* global altstep for global guard timer; */
477private altstep as_Tguard_ConnHdlr() runs on ConnHdlr {
478 [] g_Tguard.timeout {
479 setverdict(fail, "Timeout of T_guard");
480 mtc.stop;
481 }
482}
483
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100484private function f_bssap_expect(template (present) RANAP_PDU exp_rx) runs on ConnHdlr return RANAP_PDU
485{
486 var RANAP_PDU rx;
487 timer T := 5.0;
488 T.start;
489 alt {
490 [] BSSAP.receive(exp_rx) -> value rx {
491 setverdict(pass);
492 }
493 [] BSSAP.receive(RANAP_PDU:?) {
494 setverdict(fail, "Got an unexpected RANAP message on BSSAP port, was waiting for ", exp_rx);
495 mtc.stop;
496 }
497 [] T.timeout {
498 setverdict(fail, "Timeout waiting for RANAP on BSSAP port: ", exp_rx);
499 mtc.stop;
500 }
501 }
502 T.stop;
503 return rx;
504}
505
Daniel Willmann19b8d902022-01-05 09:12:34 +0100506/* send RANAP on Iuh and expect it to show up on Iu */
507function f_iuh2iu(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
508runs on ConnHdlr return RANAP_PDU {
509 var RANAP_PDU rx;
510 timer T := 5.0;
511
512 if (istemplatekind(exp_rx, "omit")) {
513 exp_rx := tx;
514 }
515
516 RUA.send(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100517
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100518 return f_bssap_expect(exp_rx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100519}
520
521/* send RANAP on Iu and expect it to show up on Iuh */
522function f_iu2iuh(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
523runs on ConnHdlr return RANAP_PDU {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100524 if (istemplatekind(exp_rx, "omit")) {
525 exp_rx := tx;
526 }
527
528 BSSAP.send(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100529
Neels Hofmeyr735b6562023-03-09 02:51:28 +0100530 return f_rua_expect(exp_rx)
531}
532
533/* expect to receive a specific RUA message on Iuh */
534private function f_rua_expect(template (present) RANAP_PDU exp_rx) runs on ConnHdlr return RANAP_PDU
535{
536 var RANAP_PDU rx;
537 timer T := 5.0;
538 T.start;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100539 alt {
540 [] RUA.receive(exp_rx) -> value rx {
541 setverdict(pass);
542 }
Neels Hofmeyr735b6562023-03-09 02:51:28 +0100543 [] RUA.receive(RANAP_PDU:?) {
544 setverdict(fail, "Got an unexpected RUA message, was waiting for ", exp_rx);
545 mtc.stop;
546 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100547 [] T.timeout {
548 setverdict(fail, "Timeout waiting for Iuh ", exp_rx);
Neels Hofmeyr735b6562023-03-09 02:51:28 +0100549 mtc.stop;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100550 }
551 }
Neels Hofmeyr735b6562023-03-09 02:51:28 +0100552 T.stop;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100553 return rx;
554}
555
556/* send RANAP on Iuh and expect it to show up on Iu */
557function f_iuh2iu_connect(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
558runs on ConnHdlr return RANAP_PDU {
559 var RANAP_PDU rx;
560 timer T := 5.0;
561
562 if (istemplatekind(exp_rx, "omit")) {
563 exp_rx := tx;
564 }
565
566 /* create an expect on the Iu side for the random NAS portion */
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200567 if (g_pars.expect_separate_sccp_cr) {
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200568 f_ran_register_sccp_cr_without_payload();
569 } else {
570 var template (omit) octetstring nas := f_ranap_extract_l3(valueof(tx));
571 f_ran_register_exp(valueof(nas));
572 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100573
574 /* send it via Iuh (creating a RUA connection) */
575 RUA.send(RUA_Conn_Req:{g_pars.ps_domain, tx});
576
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200577 if (g_pars.expect_separate_sccp_cr) {
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200578 /* Acknowledge the empty SCCP CR. RAN_Emulation does the confirmation, no need to respond. */
579 BSSAP.receive(tr_RANAP_Conn_Req());
580 }
581
Daniel Willmann19b8d902022-01-05 09:12:34 +0100582 /* expect to receive it on the Iu side */
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100583 return f_bssap_expect(exp_rx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100584}
585
Neels Hofmeyr99b7d402023-02-20 14:26:31 +0100586/* 3GPP TS 48.006 9.2 Connection release:
587 *
588 * The MSC sends a SCCP released message. This message shall not contain
589 * any user data field.
590 *
591 * So what we expect normally is:
592 *
593 * HNBGW MSC
594 * RUA --id-Disconnect-------> | ---Data-Form-1(!)---> | Iu-ReleaseComplete
595 * | <--Released---------- | (no data)
596 *
597 * This function tests osmo-hnbgw behavior if the CN fails to send a RLSD:
598 * after some timeout, osmo-hnbgw should send a RLSD to the CN.
599 */
Daniel Willmann19b8d902022-01-05 09:12:34 +0100600function f_iuh2iu_disconnect(template (present) RANAP_PDU tx, RUA_IEs.Cause cause,
601 template RANAP_PDU exp_rx := omit)
602runs on ConnHdlr return RANAP_PDU {
603 var RANAP_PDU rx
Neels Hofmeyr99b7d402023-02-20 14:26:31 +0100604 timer T := 10.0;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100605
606 if (istemplatekind(exp_rx, "omit")) {
607 exp_rx := tx;
608 }
609
610 /* send it via Iuh (creating a RUA connection) */
611 RUA.send(RUA_Disc_Req:{tx, cause});
612
613 /* expect to receive it on the Iu side */
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100614 rx := f_bssap_expect(exp_rx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100615
616 /* expect disconnect on the Iu side */
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100617 T.start;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100618 alt {
619 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {
620 setverdict(pass);
621 }
622 [] T.timeout {
623 setverdict(fail, "Timeout waiting for Iu disconnect");
624 return rx;
625 }
626
627 }
628 return rx;
629}
630
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200631private function f_build_initial_ue_with_nas(TestHdlrParams pars, octetstring nas)
632 return RANAP_PDU {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100633 var LAI lai := {
634 pLMNidentity := hex2oct(pars.hnb.lai.mcc_mnc),
635 lAC := int2oct(pars.hnb.lai.lac, 2),
636 iE_Extensions := omit
637 };
638 var SAI sai := {
639 pLMNidentity := lai.pLMNidentity,
640 lAC := lai.lAC,
641 sAC := int2oct(pars.hnb.sac, 2),
642 iE_Extensions := omit
643 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100644 var IuSignallingConnectionIdentifier sigc_id := int2bit(f_rnd_int(1000), 24);
645 var GlobalRNC_ID grnc_id := {
646 pLMNidentity := lai.pLMNidentity,
647 rNC_ID := 2342
648 }
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200649 var template RANAP_PDU ret;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100650 if (pars.ps_domain) {
651 var RAC rac := '00'O;
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200652 ret := ts_RANAP_initialUE_PS(lai, rac, sai, nas, sigc_id, grnc_id);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100653 } else {
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200654 ret := ts_RANAP_initialUE_CS(lai, sai, nas, sigc_id, grnc_id);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100655 }
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200656 return valueof(ret);
657}
658
659/* build a RANAP InitialUE based on the TestHdlrParams */
660friend function f_build_initial_ue(TestHdlrParams pars) return RANAP_PDU {
661
662 var octetstring nas;
663
664 if (pars.tx_sccp_cr_data_len == 0) {
665 nas := f_rnd_octstring(10);
666 } else {
667 /* The test asks for an exact number of Optional Data bytes. */
668
669 /* First see what size the RANAP part of the payload data is,
670 * to adjust the NAS PDU size to the size requested by the test (pars.tx_sccp_cr_data_len). */
671 var RANAP_PDU initial_ue := f_build_initial_ue_with_nas(pars, '00'O);
672
673 var octetstring ranap_plus_one_byte_nas := enc_RANAP_PDU(initial_ue);
674 var integer ranap_length := lengthof(ranap_plus_one_byte_nas) - 1;
675
676 log("ranap_plus_one_byte_nas = ", lengthof(ranap_plus_one_byte_nas), " bytes, ", initial_ue, " = ",
677 ranap_plus_one_byte_nas);
678 log("ranap_length = ", ranap_length);
679
680 /* SCCP CR has a payload length limit of 130 bytes. To trigger this limit, the RANAP + NAS PDU has to be
681 * > 130 bytes. It doesn't need to be 131 bytes in the NAS PDU alone, but let's just make it definitely
682 * large enough. To test for this limit, pars.tx_sccp_cr_data_len asks for a specific amount of data len. */
683 nas := f_rnd_octstring(pars.tx_sccp_cr_data_len - ranap_length);
684 }
685
686 var RANAP_PDU ret := f_build_initial_ue_with_nas(pars, nas);
687
688 if (pars.tx_sccp_cr_data_len != 0) {
689 for (var integer attempts := 0; attempts < 2; attempts := attempts + 1) {
690 var octetstring check_len := enc_RANAP_PDU(ret);
691 log("final RANAP PDU length = ", lengthof(check_len));
692 if (lengthof(check_len) == pars.tx_sccp_cr_data_len) {
693 return ret;
694 }
695 nas := f_rnd_octstring(lengthof(nas) + (pars.tx_sccp_cr_data_len - lengthof(check_len)));
696 log("that was off, changed NAS length to ", lengthof(nas), " and trying again");
697 ret := f_build_initial_ue_with_nas(pars, nas);
698 }
699 setverdict(fail, "Ended up with wrong Optional Data length");
700 mtc.stop;
701 }
702 return ret;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100703}
704
705/* build a RANAP RAB AssignmentResponse based on the TestHdlrParams */
706friend function f_build_rab_ass_resp(TestHdlrParams pars) return RANAP_PDU {
707 var template RAB_SetupOrModifiedList rab_sml;
708
709 rab_sml := ts_RAB_SMdL(t_RAB_id(23), f_ts_RAB_TLA("192.168.1.23"), t_RAB_binding_port(1234));
710
711 return valueof(ts_RANAP_RabAssResp(rab_sml));
712}
713
714
715/***********************************************************************
716 * HNBAP Testing
717 ***********************************************************************/
718
719
Daniel Willmannc79679a2022-08-23 17:48:39 +0200720function 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 +0100721{
722 timer T := 2.0;
723
Neels Hofmeyrfffe79b2023-06-27 01:16:15 +0200724 HNBAP[hnb_idx].send(ts_HNBAP_HNBRegisterRequest(char2oct("TTCN3-HNB-" & int2str(hnb_idx)),
Daniel Willmann19b8d902022-01-05 09:12:34 +0100725 '00F110'O,
Daniel Willmannc79679a2022-08-23 17:48:39 +0200726 int2bit(1 + cell_id, 28),
Daniel Willmann19b8d902022-01-05 09:12:34 +0100727 int2oct(2, 2),
728 int2oct(3, 1),
729 int2oct(4, 2)));
730
731 T.start;
732 alt {
733 [] HNBAP[hnb_idx].receive(tr_HNBAP_HNBRegisterAccept(?)) {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200734 if (expect_reject) {
735 setverdict(fail, "Rx HNB Register Accept while expecting reject");
736 } else {
737 setverdict(pass);
738 }
739 }
740 [] HNBAP[hnb_idx].receive(tr_HNBAP_HNBRegisterReject(?)) {
741 if (expect_reject) {
742 setverdict(pass);
743 } else {
744 setverdict(fail, "Rx HNB Register Reject while expecting accept");
745 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100746 }
747 [] HNBAP[hnb_idx].receive(IUHEM_Event:?) {
748 repeat;
749 }
750 [] T.timeout {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200751 setverdict(fail, "Timeout waiting for HNB Register response");
Daniel Willmann19b8d902022-01-05 09:12:34 +0100752 }
753 }
754}
755
756testcase TC_hnb_register() runs on test_CT {
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200757 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100758 f_init();
759 f_hnbap_register(0);
760 f_shutdown_helper();
761}
762
Pau Espin Pedrolacf4f222022-09-27 14:33:40 +0200763/* Try to register the same HNB from 2 different concurrent connections. Second
764 * one should be rejected. */
Daniel Willmannc79679a2022-08-23 17:48:39 +0200765testcase TC_hnb_register_duplicate() runs on test_CT {
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200766 g_num_hnbs := 2;
Daniel Willmannc79679a2022-08-23 17:48:39 +0200767 f_init();
768 f_hnbap_register(0);
769 f_hnbap_register(1, 0, expect_reject := true);
770 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
771 f_shutdown_helper();
772}
773
Pau Espin Pedrolacf4f222022-09-27 14:33:40 +0200774/* Try to register the same HNB in the same connection already established, aka
775 * duplicate HNB Register Request. It should be accepted and new configuration
776 * applied. TS 25.469 8.2.4 */
777testcase TC_hnb_register_duplicate_reuse_sctp_assoc() runs on test_CT {
778 g_num_hnbs := 1;
779 f_init();
780 f_hnbap_register(0);
781 f_hnbap_register(0);
782 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
783 f_shutdown_helper();
784}
785
Pau Espin Pedrolf0b9fa02022-09-12 13:31:07 +0200786/* Drop HNBAP conn (HNBAP DEREG) and reconnect it (HNBAP REG) using same SCTP association.
787 * Related: OS#5676, SYS#6113 */
788testcase TC_hnb_reregister_reuse_sctp_assoc() runs on test_CT {
789 g_num_hnbs := 1;
790 f_init();
791 f_hnbap_register(0);
792 HNBAP[0].send(ts_HNBAP_HNBDe_Register(ts_HnbapCause(unspecified)));
793 f_hnbap_register(0);
794 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
795 f_shutdown_helper();
796}
797
Daniel Willmann19b8d902022-01-05 09:12:34 +0100798/***********************************************************************
799 * RUA / RANAP Testing
800 ***********************************************************************/
801
802private template (value) TestHdlrParams
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200803t_pars(integer imsi_suffix, boolean ps_domain := false, integer hnb_idx := 0,
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200804 boolean expect_separate_sccp_cr := false, integer tx_sccp_cr_data_len := 0) := {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100805 hnb_idx := hnb_idx,
806 imsi := f_gen_imsi(imsi_suffix),
807 ps_domain := ps_domain,
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200808 hnb := omit, /* filled in later */
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200809 expect_separate_sccp_cr := expect_separate_sccp_cr,
810 tx_sccp_cr_data_len := tx_sccp_cr_data_len,
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200811 pfcp_local_addr := mp_pfcp_ip_local
Daniel Willmann19b8d902022-01-05 09:12:34 +0100812}
813
814/* Create an Iuh connection; send InitialUE; expect it to appear on new SCCP conenction */
815friend function f_tc_initial_ue(charstring id, TestHdlrParams pars) runs on ConnHdlr {
816 f_init_handler(pars);
817 var RANAP_PDU tx := f_build_initial_ue(g_pars);
818 f_iuh2iu_connect(tx);
819}
820testcase TC_ranap_cs_initial_ue() runs on test_CT {
821 var ConnHdlr vc_conn;
822
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200823 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100824 f_init();
825 f_start_hnbs();
826
827 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(1));
828 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +0200829
830 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +0100831}
832testcase TC_ranap_ps_initial_ue() runs on test_CT {
833 var ConnHdlr vc_conn;
834
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200835 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100836 f_init();
837 f_start_hnbs();
838
839 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(2, true));
840 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +0200841
842 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +0100843}
844
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200845private function f_vty_set_sccp_max_optional_data(TELNETasp_PT pt, integer val := -1)
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200846{
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200847 var charstring valstr;
848 if (val < 0) {
849 valstr := "standard";
850 } else {
851 valstr := int2str(val);
852 }
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200853 f_vty_enter_config(pt);
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200854 f_vty_transceive(pt, "cs7 instance 0");
855 f_vty_transceive(pt, "sccp max-optional-data " & valstr);
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200856 f_vty_transceive(pt, "end");
857}
858
859testcase TC_ranap_cs_initial_ue_empty_cr() runs on test_CT {
860 var ConnHdlr vc_conn;
861
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200862 g_num_hnbs := 1;
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200863 f_init();
864 f_start_hnbs();
865
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200866 f_vty_set_sccp_max_optional_data(HNBGWVTY, 0);
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200867
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200868 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(1, expect_separate_sccp_cr := true));
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200869 vc_conn.done;
870
871 /* reset */
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200872 f_vty_set_sccp_max_optional_data(HNBGWVTY);
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +0200873
874 f_shutdown_helper();
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200875}
876testcase TC_ranap_ps_initial_ue_empty_cr() runs on test_CT {
877 var ConnHdlr vc_conn;
878
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200879 g_num_hnbs := 1;
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200880 f_init();
881 f_start_hnbs();
882
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200883 f_vty_set_sccp_max_optional_data(HNBGWVTY, 0);
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200884
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200885 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(2, true, expect_separate_sccp_cr := true));
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200886 vc_conn.done;
887
888 /* reset */
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200889 f_vty_set_sccp_max_optional_data(HNBGWVTY);
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +0200890
891 f_shutdown_helper();
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200892}
893
894type record Testdata_CR_Limit {
895 integer data_len,
896 integer max_optional_data,
897 boolean expect_separate_sccp_cr
898};
899type record of Testdata_CR_Limit Testdata_CR_Limits;
900
901testcase TC_sccp_cr_limit() runs on test_CT {
902 g_num_hnbs := 1;
903 f_init();
904 f_start_hnbs();
905
906 const Testdata_CR_Limits tests := {
907 { data_len := 130, max_optional_data := -1, expect_separate_sccp_cr := false },
908 { data_len := 131, max_optional_data := -1, expect_separate_sccp_cr := true },
909
910 { data_len := 100, max_optional_data := 100, expect_separate_sccp_cr := false },
911 { data_len := 101, max_optional_data := 100, expect_separate_sccp_cr := true },
912
913 { data_len := 200, max_optional_data := 200, expect_separate_sccp_cr := false },
914 { data_len := 201, max_optional_data := 200, expect_separate_sccp_cr := true }
915 };
916
917 var integer csps;
918 for (csps := 0; csps < 2; csps := csps + 1) {
919 var boolean ps_domain := (csps > 0);
920
921 var integer i;
922 for (i := 0; i < lengthof(tests); i := i + 1) {
923 var Testdata_CR_Limit t := tests[i];
924 f_logp(HNBGWVTY,
925 "TEST PART TC_sccp_cr_limit ps_domain=" & f_bool2str(ps_domain)
926 & " data_len=" & int2str(t.data_len)
927 & " max_optional_data=" & int2str(t.max_optional_data)
928 & " expect_separate_sccp_cr=" & f_bool2str(t.expect_separate_sccp_cr)
929 );
930
931 f_vty_set_sccp_max_optional_data(HNBGWVTY, t.max_optional_data);
932 var ConnHdlr vc_conn;
933 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue),
934 t_pars(100 + i,
935 ps_domain := ps_domain,
936 expect_separate_sccp_cr := t.expect_separate_sccp_cr,
937 tx_sccp_cr_data_len := t.data_len));
938 vc_conn.done;
939 }
940 }
941
942 /* reset */
943 f_vty_set_sccp_max_optional_data(HNBGWVTY);
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +0200944
945 f_shutdown_helper();
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200946}
947
Daniel Willmann19b8d902022-01-05 09:12:34 +0100948/* Reply to a received CRCX with an OK (or the reply configured in cpars), using the given parameters.
949 * Return true when an OK reply was sent, false otherwise.
950 * Count occurrence of Osmux, include Osmux parameters in the reply if necessary. */
951function f_handle_crcx(inout MgcpParameters pars, MgcpCommand mgcp_cmd) return template MgcpResponse {
952 var CrcxResponse conn := pars.mgw_conn_1;
953 if (pars.got_crcx_count > 0) {
954 conn := pars.mgw_conn_2;
955 }
956 pars.got_crcx_count := pars.got_crcx_count + 1;
957
958 var MgcpMessage mgcp_msg := {
959 command := mgcp_cmd
960 }
961 var template MgcpResponse mgcp_resp;
962 var MgcpOsmuxCID osmux_cid;
963 var MgcpCallId call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
964 if (ispresent(pars.mgcp_call_id)) {
965 if (pars.mgcp_call_id != call_id) {
966 setverdict(fail, "CRCX contained unexpected call id. Expected:", pars.mgcp_call_id, " got:", call_id);
967 mtc.stop;
968 }
969 } else {
970 pars.mgcp_call_id := call_id;
971 }
972
973 /* When the endpoint contains a wildcard we keep the endpoint
974 * identifier we have set up in pars. Otherwise we use the
975 * endpoint name that the call agent has supplied */
976 if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard) == false) {
977 pars.mgcp_ep := mgcp_cmd.line.ep;
978 }
979
980 if (conn.resp == -1) {
981 /* Reply with rror */
982 var MgcpResponse mgcp_rsp := {
983 line := {
984 code := "542",
985 trans_id := mgcp_cmd.line.trans_id,
986 string := "FORCED_FAIL"
987 },
988 sdp := omit
989
990 }
991 var MgcpParameter mgcp_rsp_param := {
992 code := "Z",
993 val := pars.mgcp_ep
994 };
995 mgcp_rsp.params[0] := mgcp_rsp_param;
996 return mgcp_rsp;
997 }
998
999 if (conn.resp == 0) {
1000 /* Do not reply at all */
1001 return omit;
1002 }
1003
1004 if (conn.resp != 1) {
1005 setverdict(fail, "Unexpected value for pars.mgw_conn_*.resp, expect -1, 0 or 1");
1006 mtc.stop;
1007 }
1008
1009 var SDP_Message sdp := valueof(ts_SDP(conn.mgw_rtp_ip, conn.mgw_rtp_ip,
1010 hex2str(pars.mgcp_call_id), "42",
1011 conn.mgw_rtp_port,
1012 { int2str(pars.rtp_payload_type) },
1013 { valueof(ts_SDP_rtpmap(pars.rtp_payload_type,
1014 pars.rtp_sdp_format)),
1015 valueof(ts_SDP_ptime(20)) }));
1016
1017 if (f_mgcp_contains_par(mgcp_msg, "X-OSMUX")) {
1018 if (not pars.use_osmux) {
1019 setverdict(fail, "MSC sent X-Osmux parameter in MGCP, but not expecting any Osmux");
1020 mtc.stop;
1021 }
1022 pars.got_osmux_count := pars.got_osmux_count + 1;
1023 /* we expect MSC to use wildcard here, i.e. osmux_cid == -1 */
1024 osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
1025 log("f_handle_crcx(): got Osmux CID: ", osmux_cid);
1026 if (osmux_cid != -1) {
1027 setverdict(fail, "MSC using unexpected CID " & int2str(osmux_cid) & " != -1");
1028 mtc.stop;
1029 }
1030
1031 osmux_cid := 0;
1032 mgcp_resp := ts_CRCX_ACK_osmux(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, osmux_cid, sdp);
1033 } else {
1034 mgcp_resp := ts_CRCX_ACK(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, sdp);
1035 }
1036
1037 f_mgcp_par_append(mgcp_resp.params, ts_MgcpParSpecEP(pars.mgcp_ep));
1038
1039 return mgcp_resp;
1040}
1041
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001042friend function f_create_rab(inout MgcpParameters pars) runs on ConnHdlr {
1043 f_rab_ass_req(pars);
1044 f_rab_ass_resp(pars);
1045}
1046
1047friend function f_rab_ass_req(inout MgcpParameters pars) runs on ConnHdlr {
Daniel Willmann19b8d902022-01-05 09:12:34 +01001048 var MgcpCommand mgcp_cmd;
1049 var RANAP_PDU tx;
1050 var template RAB_SetupOrModifyList rab_sml;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001051 timer T := 5.0;
1052
1053 /* Send RAB Assignment Request */
1054 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));
1055 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1056 BSSAP.send(tx);
1057 T.start;
1058
1059 /* Handle MGCP CRCX */
1060 alt {
1061 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
1062 log("CRCX1", mgcp_cmd);
1063 var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
1064 MGCP.send(valueof(mgcp_rsp));
1065 }
1066 [] T.timeout {
1067 setverdict(fail, "Timeout waiting for MGCP");
1068 }
1069 }
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001070 T.stop;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001071
1072 /* Expect RAB Assignment Request with IP/port from CRCX ACK via Iuh */
1073 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));
1074 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1075
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001076 f_rua_expect(tx);
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001077}
1078
1079friend function f_rab_ass_resp(inout MgcpParameters pars) runs on ConnHdlr {
1080 var MgcpCommand mgcp_cmd;
1081 var RANAP_PDU tx;
1082 var template RAB_SetupOrModifiedList rab_smdl;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001083
1084 /* Send back RAB Assignment Response via Iuh */
1085 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));
1086 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1087 RUA.send(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +01001088
1089 interleave {
1090 /* Expect MDCX with IP/port from RAB Assignment Response */
1091 [] MGCP.receive(tr_MDCX(tr_SDP(pars.hnb_rtp_ip, pars.hnb_rtp_port))) -> value mgcp_cmd {
1092 log("MDCX1", mgcp_cmd);
1093 /* Verify SDP of MDCX */
1094 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,
1095 { int2str(pars.rtp_payload_type) }, { valueof(ts_SDP_rtpmap(pars.rtp_payload_type, pars.rtp_sdp_format)), valueof(ts_SDP_ptime(20)) } ));
1096 var template MgcpResponse mgcp_rsp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, pars.mgw_conn_1.mgcp_connection_id, sdp);
1097 MGCP.send(valueof(mgcp_rsp));
1098 }
1099 /* Handle CRCX for second leg of endpoint, answer with IP/port */
1100 [] MGCP.receive(tr_CRCX(pars.mgcp_ep, tr_SDP(pars.cn_rtp_ip, pars.cn_rtp_port))) -> value mgcp_cmd {
1101 log("CRCX2", mgcp_cmd);
1102 /* Verify SDP of CRCX */
1103 var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
1104 MGCP.send(valueof(mgcp_rsp));
1105 }
1106 }
1107
1108 /* Expect RAB Assignment Response with IP/port from second CRCX ACK */
1109 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));
1110 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1111
Neels Hofmeyrdc416c92023-03-09 02:47:50 +01001112 f_bssap_expect(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +01001113}
1114
1115private altstep as_mgcp_dlcx(inout TestHdlrParams pars) runs on ConnHdlr {
1116 var MgcpCommand mgcp_cmd;
1117
1118 [] MGCP.receive(tr_DLCX(pars.mgcp_pars.mgcp_ep)) -> value mgcp_cmd {
1119 log("DLCX", mgcp_cmd);
1120 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
1121 pars.mgcp_pars.got_dlcx_count := pars.mgcp_pars.got_dlcx_count + 1;
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001122 if (pars.mgcp_pars.got_dlcx_count != pars.mgcp_pars.got_crcx_count) {
Daniel Willmann19b8d902022-01-05 09:12:34 +01001123 repeat;
1124 }
1125 setverdict(pass);
1126 }
1127}
1128
1129friend function f_tc_rab_assignment(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1130 var MgcpCommand mgcp_cmd;
1131 var RANAP_PDU tx;
1132 timer T := 5.0;
1133
1134 f_init_handler(pars);
1135 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1136
1137 tx := f_build_initial_ue(g_pars);
1138 f_iuh2iu_connect(tx);
1139
1140 f_create_rab(pars.mgcp_pars);
1141
1142 /* Send Iu Release */
1143 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1144 f_iu2iuh(tx);
1145
1146 T.start;
1147 alt {
1148 [] as_mgcp_dlcx(pars) {}
1149 [] T.timeout {
1150 setverdict(fail, "Timeout waiting for DLCX");
1151 }
1152 }
1153
1154 tx := valueof(ts_RANAP_IuReleaseComplete());
1155 f_iuh2iu(tx);
1156}
1157
1158testcase TC_rab_assignment() runs on test_CT {
1159 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001160 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001161 f_init();
1162 f_start_hnbs();
1163
1164 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assignment), t_pars(3));
1165 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001166
1167 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001168}
1169
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001170friend function f_tc_rab_assign_fail(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1171 var MgcpCommand mgcp_cmd;
1172 var RANAP_PDU tx;
1173 timer T := 5.0;
1174
1175 f_init_handler(pars);
1176 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1177
1178 tx := f_build_initial_ue(g_pars);
1179 f_iuh2iu_connect(tx);
1180
1181 f_rab_ass_req(pars.mgcp_pars);
1182
1183 /* Send RAB failed list in response */
1184 tx := valueof(ts_RANAP_RabAssResp(rab_fl := ts_RAB_FL(t_RAB_id(23), ts_RanapCause_om_intervention)));
1185 f_iuh2iu(tx);
1186
1187 T.start;
1188 alt {
1189 [] as_mgcp_dlcx(pars) {}
1190 [] T.timeout {
1191 setverdict(fail, "Timeout waiting for DLCX");
1192 }
1193 }
1194}
1195
1196testcase TC_rab_assign_fail() runs on test_CT {
1197 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001198 g_num_hnbs := 1;
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001199 f_init();
1200 f_start_hnbs();
1201
1202 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_fail), t_pars(4));
1203 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001204
1205 f_shutdown_helper();
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001206}
1207
Daniel Willmann19b8d902022-01-05 09:12:34 +01001208friend function f_tc_rab_release(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1209 var MgcpCommand mgcp_cmd;
1210 var RANAP_PDU tx;
1211 timer T := 15.0;
1212
1213 f_init_handler(pars);
1214 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1215
1216 tx := f_build_initial_ue(g_pars);
1217 f_iuh2iu_connect(tx);
1218
1219 f_create_rab(pars.mgcp_pars);
1220
1221 /* Send RAB Release */
Daniel Willmann9e789be2022-02-22 13:30:51 +01001222 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 +01001223 BSSAP.send(tx);
1224
1225 T.start;
1226
1227 alt {
1228 [] as_mgcp_dlcx(pars) {}
1229 [] T.timeout {
1230 setverdict(fail, "Timeout waiting for DLCX");
1231 }
1232 }
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001233 T.stop;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001234
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001235 f_rua_expect(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +01001236}
1237
1238testcase TC_rab_release() runs on test_CT {
1239 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001240 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001241 f_init();
1242 f_start_hnbs();
1243
1244 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_release), t_pars(5));
1245 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001246
1247 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001248}
1249
Daniel Willmann37c877f2022-02-22 16:47:06 +01001250friend function f_tc_rab_assign_mgcp_to(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1251 var MgcpCommand mgcp_cmd;
1252 var RANAP_PDU tx;
1253 var template RAB_SetupOrModifyList rab_sml;
1254 timer T := 15.0;
1255
1256 T.start;
1257 f_init_handler(pars);
1258 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1259
1260 tx := f_build_initial_ue(g_pars);
1261 f_iuh2iu_connect(tx);
1262
1263
1264 /* Send RAB Assignment Request */
1265 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));
1266 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1267 BSSAP.send(tx);
1268
1269 /* Ignore MGCP CRCX */
1270 alt {
1271 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
1272 log("Ignoreing CRCX1", mgcp_cmd);
1273 repeat;
1274 }
1275 [] BSSAP.receive(tr_RANAP_IuReleaseRequest(?)) { }
1276 [] T.timeout {
1277 setverdict(fail, "Timeout waiting for IuRelease");
1278 }
1279 }
1280
1281 /* Send Iu Release */
1282 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1283 f_iu2iuh(tx);
1284
1285 tx := valueof(ts_RANAP_IuReleaseComplete());
1286 f_iuh2iu(tx);
1287}
1288
1289testcase TC_rab_assign_mgcp_to() runs on test_CT {
1290 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001291 g_num_hnbs := 1;
Daniel Willmann37c877f2022-02-22 16:47:06 +01001292 f_init();
1293 f_start_hnbs();
1294
1295 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_mgcp_to), t_pars(6));
1296 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001297
1298 f_shutdown_helper();
Daniel Willmann37c877f2022-02-22 16:47:06 +01001299}
1300
Daniel Willmann19b8d902022-01-05 09:12:34 +01001301/* Create an Iuh connection; send InitialUE; transceive data both directions */
1302friend function f_tc_ranap_bidir(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1303 f_init_handler(pars);
1304
1305 /* HNB -> MSC: InitialUE */
1306 f_iuh2iu_connect(f_build_initial_ue(g_pars));
1307
1308 /* MSC <- HNB: DirectTransfer */
1309 f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1310 /* MSC -> HNB: DirectTransfer */
1311 f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1312
1313 /* HNB <- MSC: CommonID */
1314 f_iu2iuh(ts_RANAP_CommonId(hex2oct(pars.imsi)));
1315}
1316testcase TC_ranap_cs_bidir() runs on test_CT {
1317 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001318 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001319 f_init();
1320 f_start_hnbs();
1321
1322 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(3));
1323 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001324
1325 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001326}
1327testcase TC_ranap_ps_bidir() runs on test_CT {
1328 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001329 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001330 f_init();
1331 f_start_hnbs();
1332
1333 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(4, true));
1334 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001335
1336 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001337}
1338
1339
1340private function f_tc_ranap_mo_disconnect(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1341 f_init_handler(pars);
1342
1343 /* HNB -> MSC: InitialUE */
1344 f_iuh2iu_connect(f_build_initial_ue(g_pars));
1345
1346 /* MSC <- HNB: DirectTransfer */
1347 f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1348 /* MSC -> HNB: DirectTransfer */
1349 f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1350
1351 /* MSC <- HNB: RUA disconnect */
1352 f_iuh2iu_disconnect(ts_RANAP_IuReleaseComplete, RUA_IEs.Cause:{misc:=processing_overload});
1353}
1354testcase TC_ranap_cs_mo_disconnect() runs on test_CT {
1355 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001356 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001357 f_init();
1358 f_start_hnbs();
1359
1360 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(5));
1361 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001362
1363 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001364}
1365testcase TC_ranap_ps_mo_disconnect() runs on test_CT {
1366 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001367 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001368 f_init();
1369 f_start_hnbs();
1370
1371 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(6));
1372 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001373
1374 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001375}
1376
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001377type record FTeid {
1378 HostName addr,
1379 OCT4 teid
1380}
1381
1382type record FTeids {
1383 FTeid local,
1384 FTeid remote
1385}
Daniel Willmann19b8d902022-01-05 09:12:34 +01001386
1387
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001388/* 'local' and 'remote' refer to the GTP information from the UPF's point of view:
1389 * HNB UPF CN
1390 * access.remote <---> access.local | core.local <---> core.remote
1391 */
1392type record GtpParameters {
1393 FTeids core,
1394 FTeids access
1395}
1396
1397/* HNB UPF CN
1398 * access.remote <---> access.local | core.local <---> core.remote
1399 * 127.0.0.4 127.0.0.3 127.0.0.2 127.0.0.1
1400 * 0x44004400 0x30303030 0x22002200 0x10101010
1401 */
1402template GtpParameters t_GtpParameters := {
1403 core := {
1404 local := {
1405 addr := "127.0.0.2",
1406 teid := '22002200'O
1407 },
1408 remote := {
1409 addr := "127.0.0.1",
1410 teid := '10101010'O
1411 }
1412 },
1413 access := {
1414 local := {
1415 addr := "127.0.0.3",
1416 teid := '30303030'O
1417 },
1418 remote := {
1419 addr := "127.0.0.4",
1420 teid := '44004400'O
1421 }
1422 }
1423}
1424
Neels Hofmeyr65499282023-04-25 02:31:51 +02001425private function f_pfcp_expect(template (present) PDU_PFCP exp_rx, float wait_time := 5.0) runs on ConnHdlr return PDU_PFCP
Neels Hofmeyr6bbfe052023-03-09 02:51:46 +01001426{
1427 var PDU_PFCP rx;
Neels Hofmeyr65499282023-04-25 02:31:51 +02001428 timer T := wait_time;
Neels Hofmeyr6bbfe052023-03-09 02:51:46 +01001429 T.start;
1430 alt {
1431 [] PFCP.receive(exp_rx) -> value rx {
1432 setverdict(pass);
1433 }
1434 [] PFCP.receive(PDU_PFCP:?) {
1435 setverdict(fail, "Got an unexpected PFCP message, was waiting for ", exp_rx);
1436 mtc.stop;
1437 }
1438 [] T.timeout {
1439 setverdict(fail, "Timeout waiting for PFCP ", exp_rx);
1440 mtc.stop;
1441 }
1442 }
1443 T.stop;
1444 return rx;
1445}
1446
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001447friend function f_tc_ps_rab_assignment_with_pfcp(charstring id, TestHdlrParams pars) runs on ConnHdlr {
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001448 var RANAP_PDU tx;
1449 var RANAP_PDU rx;
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001450
1451 f_init_handler(pars);
1452
1453 f_pfcp_register();
1454
1455 var PDU_PFCP m;
1456 var Node_ID upf_node_id := valueof(ts_PFCP_Node_ID_fqdn("\07osmocom\03org"));
1457
Neels Hofmeyr65499282023-04-25 02:31:51 +02001458 m := f_pfcp_expect(tr_PFCP_Assoc_Setup_Req(), wait_time := 15.0);
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001459 PFCP.send(ts_PFCP_Assoc_Setup_Resp(m.sequence_number, upf_node_id,
1460 ts_PFCP_Cause(REQUEST_ACCEPTED), 1234));
1461
1462 tx := f_build_initial_ue(g_pars);
1463 f_iuh2iu_connect(tx);
1464
1465 var GtpParameters gtp_pars := valueof(t_GtpParameters);
1466 var template RAB_SetupOrModifyList rab_sml;
1467
1468 /* Send RAB Assignment Request */
1469 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.remote.addr), gtp_pars.core.remote.teid);
1470 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1471 BSSAP.send(tx);
1472
1473 /* Expect PFCP Session Establishment Request. */
Neels Hofmeyr6bbfe052023-03-09 02:51:46 +01001474 m := f_pfcp_expect(tr_PFCP_Session_Est_Req());
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001475 var F_SEID hnbgw_f_seid := m.message_body.pfcp_session_establishment_request.CP_F_SEID;
1476 var PFCP_Session_Establishment_Request serq := m.message_body.pfcp_session_establishment_request;
1477
1478 /* Acting as UPF, invent a new PFCP SEID to send to HNBGW. Respond to the Session Establishment.
1479 * The PFCP response must have the same sequence_number as the request. */
Neels Hofmeyr1e311462023-01-11 01:19:12 +01001480 var F_SEID up_f_seid := valueof(ts_PFCP_F_SEID_ipv4(f_inet_addr("127.0.0.1"), '1111111111111111'O));
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001481 var template PDU_PFCP r := ts_PFCP_Session_Est_Resp(m.sequence_number, upf_node_id, hnbgw_f_seid.seid);
1482 r.message_body.pfcp_session_establishment_response := {
1483 offending_ie := omit,
1484 UP_F_SEID := up_f_seid,
1485 created_PDR_list := {
1486 ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[0].grouped_ie.pdr_id,
1487 local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.core.local.teid,
Neels Hofmeyr1e311462023-01-11 01:19:12 +01001488 f_inet_addr(gtp_pars.core.local.addr))),
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001489 ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[1].grouped_ie.pdr_id,
1490 local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.access.local.teid,
Neels Hofmeyr1e311462023-01-11 01:19:12 +01001491 f_inet_addr(gtp_pars.access.local.addr)))
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001492 },
1493 load_control_information := omit,
1494 overload_control_information := omit,
1495 node_list := omit,
1496 failed_rule_id := omit,
1497 created_traffic_endpoint_list := omit
1498 };
1499 PFCP.send(r);
1500
1501 /* Expect on Iuh: RAB Assignment Request with IP/port from PFCP Session Est Resp */
1502 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.local.addr),
1503 gtp_pars.access.local.teid);
1504 rx := valueof(ts_RANAP_RabAssReq(rab_sml));
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001505 f_rua_expect(rx);
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001506
1507 /* Send back RAB Assignment Response via Iuh */
1508 var template RAB_SetupOrModifiedList rab_smdl;
1509 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.remote.addr),
1510 gtp_pars.access.remote.teid);
1511 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1512 RUA.send(tx);
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001513
Neels Hofmeyr6bbfe052023-03-09 02:51:46 +01001514 m := f_pfcp_expect(tr_PFCP_Session_Mod_Req(up_f_seid.seid));
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001515 r := ts_PFCP_Session_Mod_Resp(m.sequence_number, hnbgw_f_seid.seid);
1516 PFCP.send(r);
1517
1518 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.local.addr), gtp_pars.core.local.teid);
Neels Hofmeyrdc416c92023-03-09 02:47:50 +01001519 f_bssap_expect(tr_RANAP_RabAssResp(rab_smdl));
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001520
1521 f_sleep(2.0);
1522 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1523 f_iu2iuh(tx);
1524
1525 tx := valueof(ts_RANAP_IuReleaseComplete());
1526 f_iuh2iu(tx);
1527
Neels Hofmeyr6bbfe052023-03-09 02:51:46 +01001528 m := f_pfcp_expect(tr_PFCP_Session_Del_Req(up_f_seid.seid));
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001529 PFCP.send(ts_PFCP_Session_Del_Resp(m.sequence_number, hnbgw_f_seid.seid));
1530
1531 f_sleep(2.0);
1532}
1533
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001534testcase TC_ps_rab_assignment_with_pfcp() runs on test_CT {
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001535 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001536 g_num_hnbs := 1;
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001537 f_init();
1538 f_start_hnbs();
1539 f_sleep(1.0);
1540
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001541 vc_conn := f_start_handler_with_pars(refers(f_tc_ps_rab_assignment_with_pfcp), t_pars(7, ps_domain := true));
1542 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001543
1544 f_shutdown_helper();
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001545}
1546
1547altstep as_disallow_pfcp() runs on ConnHdlr {
1548 [] PFCP.receive(PDU_PFCP:?) {
1549 setverdict(fail, "Received PFCP message, but no PFCP communication expected");
1550 mtc.stop;
1551 }
1552}
1553
1554friend function f_tc_ps_rab_assignment_without_pfcp(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1555 var RANAP_PDU tx;
1556 var RANAP_PDU rx;
1557 timer T := 5.0;
1558
1559 f_init_handler(pars);
1560
1561 f_pfcp_register();
1562 activate(as_disallow_pfcp());
1563
1564 tx := f_build_initial_ue(g_pars);
1565 f_iuh2iu_connect(tx);
1566
1567 var GtpParameters gtp_pars := valueof(t_GtpParameters);
1568 var template RAB_SetupOrModifyList rab_sml;
1569
1570 /* Send RAB Assignment Request */
1571 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.remote.addr), gtp_pars.core.remote.teid);
1572 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1573 BSSAP.send(tx);
1574
1575 /* Expect on Iuh: unmodified RAB Assignment Request */
1576 rx := valueof(ts_RANAP_RabAssReq(rab_sml));
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001577 f_rua_expect(rx);
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001578
1579 /* Send back RAB Assignment Response via Iuh */
1580 var template RAB_SetupOrModifiedList rab_smdl;
1581 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.remote.addr),
1582 gtp_pars.access.remote.teid);
1583 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1584 RUA.send(tx);
1585
1586 /* Expect on IuPS: unmodified RAB Assignment Response */
Neels Hofmeyrdc416c92023-03-09 02:47:50 +01001587 f_bssap_expect(tr_RANAP_RabAssResp(rab_smdl));
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001588
1589 f_sleep(2.0);
1590 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1591 f_iu2iuh(tx);
1592
1593 tx := valueof(ts_RANAP_IuReleaseComplete());
1594 f_iuh2iu(tx);
1595
1596 f_sleep(2.0);
1597}
1598
1599testcase TC_ps_rab_assignment_without_pfcp() runs on test_CT {
1600 var ConnHdlr vc_conn;
1601 f_init();
1602 f_start_hnbs();
1603 f_sleep(1.0);
1604
1605 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 +02001606 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001607
1608 f_shutdown_helper();
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001609}
Daniel Willmann19b8d902022-01-05 09:12:34 +01001610
1611control {
1612 execute(TC_hnb_register());
Daniel Willmannc79679a2022-08-23 17:48:39 +02001613 execute(TC_hnb_register_duplicate());
Pau Espin Pedrolacf4f222022-09-27 14:33:40 +02001614 execute(TC_hnb_register_duplicate_reuse_sctp_assoc());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001615 execute(TC_ranap_cs_initial_ue());
1616 execute(TC_ranap_ps_initial_ue());
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02001617 execute(TC_ranap_cs_initial_ue_empty_cr());
1618 execute(TC_ranap_ps_initial_ue_empty_cr());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001619 execute(TC_ranap_cs_bidir());
1620 execute(TC_ranap_ps_bidir());
1621 execute(TC_rab_assignment());
1622 execute(TC_rab_release());
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001623 execute(TC_rab_assign_fail());
Daniel Willmann37c877f2022-02-22 16:47:06 +01001624 execute(TC_rab_assign_mgcp_to());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001625 execute(TC_ranap_cs_mo_disconnect());
1626 execute(TC_ranap_ps_mo_disconnect());
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001627
1628 if (mp_enable_pfcp_tests) {
1629 execute(TC_ps_rab_assignment_with_pfcp());
1630 } else {
1631 execute(TC_ps_rab_assignment_without_pfcp());
1632 }
Pau Espin Pedrolf0b9fa02022-09-12 13:31:07 +02001633
1634 /* Run at the end since it makes osmo-hnbgw <= 1.3.0 crash: OS#5676 */
1635 execute(TC_hnb_reregister_reuse_sctp_assoc());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001636}
1637
1638}