blob: e5f227e6a2956064bc96756339191a89b858afef [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
Daniel Willmann19b8d902022-01-05 09:12:34 +010064modulepar {
65 /* IP address at which the HNodeB can be reached */
66 charstring mp_hnodeb_ip := "127.0.0.1";
67 integer mp_hnodeb_port := -1;
68
69 /* IP address at which the test binds */
70 charstring mp_hnbgw_ip := "127.0.0.1";
71 integer mp_hnbgw_iuh_port := 29169;
72
73 charstring mp_mgw_ip := "127.0.0.1";
74 integer mp_mgw_port := 2427;
75
76 RAN_Configuration mp_msc_cfg := {
77 transport := RANAP_TRANSPORT_IuCS,
78 sccp_service_type := "mtp3_itu",
79 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
80 own_pc := 188, /* 0.23.4 first MSC emulation */
81 own_ssn := 142,
82 peer_pc := 189, /* 0.23.5 osmo-hnbgw */
83 peer_ssn := 142,
84 sio := '83'O,
85 rctx := 1
86 };
87 RAN_Configuration mp_sgsn_cfg := {
88 transport := RANAP_TRANSPORT_IuCS,
89 sccp_service_type := "mtp3_itu",
90 sctp_addr := { 23906, "127.0.0.1", 2905, "127.0.0.1" },
91 own_pc := 185, /* 0.23.1 first SGSN emulation */
92 own_ssn := 142,
93 peer_pc := 189, /* 0.23.5 osmo-hnbgw */
94 peer_ssn := 142,
95 sio := '83'O,
96 rctx := 2
97 };
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +020098
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +020099 boolean mp_enable_pfcp_tests := false;
100
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200101 /* IP address at which we listen for PFCP to emulate a UPF in ttcn3 */
102 charstring mp_pfcp_ip_local := "127.0.0.1";
103
104 /* IP address from which the SUT (osmo-hnbgw) sends PFCP requests, and to which the ttcn3 UPF emulation sends
105 * PFCP responses. */
106 charstring mp_pfcp_ip_remote := "127.0.0.2";
Daniel Willmann19b8d902022-01-05 09:12:34 +0100107}
108
109function MSC_UnitdataCallback(RANAP_PDU ranap) runs on RAN_Emulation_CT return template RANAP_PDU {
110 // TODO: Actually implement unitdata handling
111 return ts_RANAP_Reset(ts_RanapCause_om_intervention, cs_domain);
112}
113
114const RanOps MSC_RanOps := {
115 ranap_create_cb := refers(RAN_Emulation.RanapExpectedCreateCallback),
116 ranap_unitdata_cb := refers(MSC_UnitdataCallback),
117 ps_domain := false,
118 decode_dtap := false,
119 role_ms := false,
120 protocol := RAN_PROTOCOL_RANAP,
121 transport := RANAP_TRANSPORT_IuCS,
122 use_osmux := false,
Eric Wild6e511ce2022-04-02 21:35:56 +0200123 bssap_reset_retries := 1,
Daniel Willmann19b8d902022-01-05 09:12:34 +0100124 sccp_addr_local := omit,
125 sccp_addr_peer := omit
126}
127
128type record CrcxResponse {
129 integer resp,
130 HostName mgw_rtp_ip,
131 PortNumber mgw_rtp_port,
132 MgcpConnectionId mgcp_connection_id
133}
134type record MgcpParameters {
135 integer got_crcx_count,
136 integer got_dlcx_count,
137 MgcpCallId mgcp_call_id optional,
138 MgcpEndpoint mgcp_ep,
139 CrcxResponse mgw_conn_1,
140 CrcxResponse mgw_conn_2,
141 uint7_t rtp_payload_type,
142 charstring rtp_sdp_format,
143 HostName hnb_rtp_ip,
144 PortNumber hnb_rtp_port,
145 HostName cn_rtp_ip,
146 PortNumber cn_rtp_port,
147 boolean use_osmux,
148 integer got_osmux_count
149}
150
151template (value) MgcpParameters t_MgcpParams := {
152 got_crcx_count := 0,
153 got_dlcx_count := 0,
154 mgcp_call_id := omit,
155 mgcp_ep := "rtpbridge/1@mgw",
156 mgw_conn_1 := {
157 resp := 1,
158 mgw_rtp_ip := "127.1.2.1",
159 mgw_rtp_port := 10000,
160 mgcp_connection_id := '11111'H
161 },
162 mgw_conn_2 := {
163 resp := 1,
164 mgw_rtp_ip := "127.1.2.2",
165 mgw_rtp_port := 20000,
166 mgcp_connection_id := '22222'H
167 },
168 rtp_payload_type := 23,
169 rtp_sdp_format := "FOO",
170 hnb_rtp_ip := "127.1.1.1",
171 hnb_rtp_port := 10001,
172 cn_rtp_ip := "127.1.3.1",
173 cn_rtp_port := 20001,
174 use_osmux := false,
175 got_osmux_count := 0
176}
177
178type record TestHdlrParams {
179 integer hnb_idx,
180 hexstring imsi,
181 boolean ps_domain,
182 MgcpParameters mgcp_pars optional,
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200183 HnbConfig hnb optional,
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200184 boolean expect_separate_sccp_cr,
185 integer tx_sccp_cr_data_len,
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200186 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;
Neels Hofmeyr72a8d622023-01-26 13:47:01 +0100198
199 port TELNETasp_PT HNBGWVTY;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100200}
201
202
203const MGCPOps MSC_MGCPOps := {
204 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
205 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
206}
207
208function f_create_ranap_exp(octetstring l3_enc) runs on ConnHdlr {
209 BSSAP_PROC.call(RAN_register:{l3_enc, self}) {
210 [] BSSAP_PROC.getreply(RAN_register:{?, ?}) {};
211 }
212}
213
214
Daniel Willmannc79679a2022-08-23 17:48:39 +0200215const integer NUM_HNB := 2;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100216
Daniel Willmann19b8d902022-01-05 09:12:34 +0100217type record HnbConfig {
218 LocationAreaIdentification lai,
219 integer sac
220}
221
222type component test_CT extends CTRL_Adapter_CT {
223 var boolean g_initialized := false;
224
225 /********************* Iu side */
226 var RAN_Adapter g_msc;
227 var RAN_Adapter g_sgsn;
228 /* SGSN IuPS missing */
229
230 /********************* Iuh side */
231 var HnbConfig g_hnb_cfg[NUM_HNB];
232 var Iuh_Emulation_CT vc_Iuh[NUM_HNB];
233 var RUA_Emulation_CT vc_RUA[NUM_HNB];
234 port HNBAP_PT HNBAP[NUM_HNB];
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200235 /* Number of HNBs to be used/started by the test */
236 var integer g_num_hnbs := NUM_HNB;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100237
238 var MGCP_Emulation_CT vc_MGCP;
239 port TELNETasp_PT HNBGWVTY;
240 /* global test case guard timer (actual timeout value is set in f_init()) */
241 timer T_guard := 30.0;
242}
243
244/* global altstep for global guard timer; */
245altstep as_Tguard() runs on test_CT {
246 [] T_guard.timeout {
247 setverdict(fail, "Timeout of T_guard");
248 mtc.stop;
249 }
250}
251
252friend function f_logp(TELNETasp_PT pt, charstring log_msg)
253{
254 // log on TTCN3 log output
255 log(log_msg);
256 // log in stderr log
257 f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
258}
259
260function f_init_vty(charstring id := "foo") runs on test_CT {
261 if (HNBGWVTY.checkstate("Mapped")) {
262 /* skip initialization if already executed once */
263 return;
264 }
265 map(self:HNBGWVTY, system:HNBGWVTY);
266 f_vty_set_prompts(HNBGWVTY);
267 f_vty_transceive(HNBGWVTY, "enable");
268}
269
270function f_init_mgcp(charstring id) runs on test_CT {
271 id := id & "-MGCP";
272 var MGCPOps ops := {
273 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
274 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
275 }
276 var MGCP_conn_parameters pars := {
277 callagent_ip := mp_hnbgw_ip,
278 callagent_udp_port := -1,
279 mgw_ip := mp_mgw_ip,
280 mgw_udp_port := mp_mgw_port,
281 multi_conn_mode := false
282 }
283
284 vc_MGCP := MGCP_Emulation_CT.create(id);
285 map(vc_MGCP:MGCP, system:MGCP_CODEC_PT);
286 vc_MGCP.start(MGCP_Emulation.main(ops, pars, id));
287}
288
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200289function f_init_pfcp(charstring id) runs on ConnHdlr {
290 id := id & "-PFCP";
291
292 var PFCP_Emulation_Cfg pfcp_cfg := {
293 pfcp_bind_ip := mp_pfcp_ip_local,
294 pfcp_bind_port := PFCP_PORT,
295 pfcp_remote_ip := mp_pfcp_ip_remote,
296 pfcp_remote_port := PFCP_PORT,
297 role := UPF
298 };
299
300 vc_PFCP := PFCP_Emulation_CT.create(id) alive;
301 connect(self:PFCP, vc_PFCP:CLIENT);
302 connect(self:PFCP_PROC, vc_PFCP:CLIENT_PROC);
303 vc_PFCP.start(PFCP_Emulation.main(pfcp_cfg));
304}
305
Daniel Willmann19b8d902022-01-05 09:12:34 +0100306function f_init_hnodeb(charstring id, integer hnb_idx, RuaOps rua_ops) runs on test_CT {
307 id := id & "-Iuh" & int2str(hnb_idx);
308
309 /* Iuh lower layer (RUA/HNBAP demux) */
310 var Iuh_conn_parameters iuh_pars;
311 iuh_pars.remote_ip := mp_hnbgw_ip;
312 iuh_pars.remote_sctp_port := mp_hnbgw_iuh_port;
313 iuh_pars.local_ip := mp_hnodeb_ip;
314 iuh_pars.local_sctp_port := mp_hnodeb_port + hnb_idx;
315 vc_Iuh[hnb_idx] := Iuh_Emulation_CT.create(id);
316 connect(self:HNBAP[hnb_idx], vc_Iuh[hnb_idx]:HNBAP);
317
318 vc_RUA[hnb_idx] := RUA_Emulation_CT.create(id & "-RUA");
319 connect(vc_RUA[hnb_idx]:RUA, vc_Iuh[hnb_idx]:RUA);
320
321 /* Start Iuh side components */
322 vc_Iuh[hnb_idx].start(Iuh_Emulation.main(iuh_pars, id));
323 vc_RUA[hnb_idx].start(RUA_Emulation.main(rua_ops, id & "-RUA"));
324}
325
326/* global initialization function */
Neels Hofmeyr82e79b02022-06-08 00:08:09 +0200327function f_init(charstring id := "HNBGW", float guard_timeout := 30.0) runs on test_CT {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100328
Daniel Willmann19b8d902022-01-05 09:12:34 +0100329 T_guard.start(guard_timeout);
330 activate(as_Tguard());
331
332 /* RUA/RANAP emulation on top of lower-layer Iuh */
333 var RuaOps rua_ops := {
334 create_cb := refers(IuhRanapCreateCallback),
335 unitdata_cb := refers(IuhRanapUnitdataCallback)
336 };
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200337 for (var integer i := 0; i < g_num_hnbs; i := i+1) {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200338 g_hnb_cfg[i] := {
339 lai := {
340 mcc_mnc := '00101'H,
341 lac := 2342 + i
342 },
343 sac := 55
344 };
Daniel Willmann19b8d902022-01-05 09:12:34 +0100345 f_init_hnodeb(testcasename(), i, rua_ops);
346 }
347
348 /* MSC emulation */
349 var RanOps ranops := {
350 ranap_create_cb := refers(RAN_Emulation.RanapExpectedCreateCallback),
351 ranap_unitdata_cb := omit,
352 ps_domain := false,
353 decode_dtap := false,
354 role_ms := false,
355 protocol := RAN_PROTOCOL_RANAP,
356 transport := RANAP_TRANSPORT_IuCS,
357 use_osmux := false,
Eric Wild6e511ce2022-04-02 21:35:56 +0200358 bssap_reset_retries := 1,
Daniel Willmann19b8d902022-01-05 09:12:34 +0100359 sccp_addr_local := omit,
360 sccp_addr_peer := omit
361 };
362 f_ran_adapter_init(g_msc, mp_msc_cfg, "HNBGW_Test", ranops);
363 f_ran_adapter_start(g_msc);
364
365 /* SGSN emulation */
366 ranops.ps_domain := true;
367 f_ran_adapter_init(g_sgsn, mp_sgsn_cfg, "HNBGW_Test", ranops);
368 f_ran_adapter_start(g_sgsn);
369
370 f_init_mgcp(id);
371 f_init_vty("VirtHNBGW");
372}
373
374friend function f_shutdown_helper() runs on test_CT {
375 all component.stop;
376 setverdict(pass);
377 mtc.stop;
378}
379
380/* helper function to start all of the simulated hNodeBs */
381function f_start_hnbs() runs on test_CT {
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200382 for (var integer i:= 0; i < g_num_hnbs; i := i+1) {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200383 f_hnbap_register(i, i);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100384 }
385}
386
387/***********************************************************************
388 * code running in test_CT, preparing start of per-UE ConnHdlr
389 ***********************************************************************/
390
391/* inbound RUA connection establishment on Iuh side */
392function IuhRanapCreateCallback(ContextId context_id, RUA_IEs.CN_DomainIndicator domain, charstring id)
393runs on RUA_Emulation_CT return RUA_ConnHdlr {
394 log("CreateCallback");
395 return null;
396}
397
398/* inbound RUA connectionless data on Iuh side */
399function IuhRanapUnitdataCallback(RANAP_PDU ranap)
400runs on RUA_Emulation_CT return template RANAP_PDU {
401 log("UnitdataCallback");
402 return omit;
403}
404
405private function f_start_handler_create(TestHdlrParams pars) runs on test_CT return ConnHdlr {
406 var ConnHdlr vc_conn;
407 var charstring id := testcasename() & int2str(pars.hnb_idx);
408
409 vc_conn := ConnHdlr.create(id);
410
411 /* Iuh RUA part */
412 connect(vc_conn:RUA, vc_RUA[pars.hnb_idx]:CLIENT);
413
414 if (pars.ps_domain) {
415 /* SGSN side */
416 connect(vc_conn:BSSAP, g_sgsn.vc_RAN:CLIENT);
417 connect(vc_conn:BSSAP_PROC, g_sgsn.vc_RAN:PROC);
418 } else {
419 /* MSC side */
420 connect(vc_conn:BSSAP, g_msc.vc_RAN:CLIENT);
421 connect(vc_conn:BSSAP_PROC, g_msc.vc_RAN:PROC);
422 }
423 /* MGCP part */
424 connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
425 connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
426
427 return vc_conn;
428}
429
430private function f_start_handler_run(ConnHdlr vc_conn, void_fn fn, TestHdlrParams pars) runs on test_CT {
431 var charstring id := testcasename(); // & int2str(pars.ran_idx);
432 /* We cannot use vc_conn.start(f_init_handler(fn, id, pars)); as we cannot have
433 * a stand-alone 'derefers()' call, see https://www.eclipse.org/forums/index.php/t/1091364/ */
434 pars.hnb := g_hnb_cfg[pars.hnb_idx];
435 pars.mgcp_pars := valueof(t_MgcpParams);
436 vc_conn.start(derefers(fn)(id, pars));
437}
438
439function f_start_handler_with_pars(void_fn fn, template (value) TestHdlrParams pars)
440runs on test_CT return ConnHdlr {
441 var ConnHdlr vc_conn;
442 vc_conn := f_start_handler_create(valueof(pars));
443 f_start_handler_run(vc_conn, fn, valueof(pars));
444 return vc_conn;
445}
446
447/***********************************************************************
448 * code running inside per-UE ConnHdlr
449 ***********************************************************************/
450
451type function void_fn(charstring id, TestHdlrParams pars) runs on ConnHdlr;
452
453function f_init_handler(TestHdlrParams pars, float t_guard := 20.0) runs on ConnHdlr {
454 /* make parameters available via component variable */
455 g_pars := pars;
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200456
457 f_init_pfcp(testcasename());
458
Daniel Willmann19b8d902022-01-05 09:12:34 +0100459 /* start guard timer and activate it as default */
460 g_Tguard.start(t_guard);
461 activate(as_Tguard_ConnHdlr());
462
Neels Hofmeyr72a8d622023-01-26 13:47:01 +0100463 map(self:HNBGWVTY, system:HNBGWVTY);
464 f_vty_set_prompts(HNBGWVTY);
465 f_vty_transceive(HNBGWVTY, "enable");
466
Daniel Willmann19b8d902022-01-05 09:12:34 +0100467 /* TODO: CTRL? */
Neels Hofmeyr59517222023-06-23 04:46:59 +0200468
469 f_sleep(1.0);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100470}
471
472/* global altstep for global guard timer; */
473private altstep as_Tguard_ConnHdlr() runs on ConnHdlr {
474 [] g_Tguard.timeout {
475 setverdict(fail, "Timeout of T_guard");
476 mtc.stop;
477 }
478}
479
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100480private function f_bssap_expect(template (present) RANAP_PDU exp_rx) runs on ConnHdlr return RANAP_PDU
481{
482 var RANAP_PDU rx;
483 timer T := 5.0;
484 T.start;
485 alt {
486 [] BSSAP.receive(exp_rx) -> value rx {
487 setverdict(pass);
488 }
489 [] BSSAP.receive(RANAP_PDU:?) {
490 setverdict(fail, "Got an unexpected RANAP message on BSSAP port, was waiting for ", exp_rx);
491 mtc.stop;
492 }
493 [] T.timeout {
494 setverdict(fail, "Timeout waiting for RANAP on BSSAP port: ", exp_rx);
495 mtc.stop;
496 }
497 }
498 T.stop;
499 return rx;
500}
501
Daniel Willmann19b8d902022-01-05 09:12:34 +0100502/* send RANAP on Iuh and expect it to show up on Iu */
503function f_iuh2iu(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
504runs on ConnHdlr return RANAP_PDU {
505 var RANAP_PDU rx;
506 timer T := 5.0;
507
508 if (istemplatekind(exp_rx, "omit")) {
509 exp_rx := tx;
510 }
511
512 RUA.send(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100513
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100514 return f_bssap_expect(exp_rx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100515}
516
517/* send RANAP on Iu and expect it to show up on Iuh */
518function f_iu2iuh(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
519runs on ConnHdlr return RANAP_PDU {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100520 if (istemplatekind(exp_rx, "omit")) {
521 exp_rx := tx;
522 }
523
524 BSSAP.send(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100525
Neels Hofmeyr735b6562023-03-09 02:51:28 +0100526 return f_rua_expect(exp_rx)
527}
528
529/* expect to receive a specific RUA message on Iuh */
530private function f_rua_expect(template (present) RANAP_PDU exp_rx) runs on ConnHdlr return RANAP_PDU
531{
532 var RANAP_PDU rx;
533 timer T := 5.0;
534 T.start;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100535 alt {
536 [] RUA.receive(exp_rx) -> value rx {
537 setverdict(pass);
538 }
Neels Hofmeyr735b6562023-03-09 02:51:28 +0100539 [] RUA.receive(RANAP_PDU:?) {
540 setverdict(fail, "Got an unexpected RUA message, was waiting for ", exp_rx);
541 mtc.stop;
542 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100543 [] T.timeout {
544 setverdict(fail, "Timeout waiting for Iuh ", exp_rx);
Neels Hofmeyr735b6562023-03-09 02:51:28 +0100545 mtc.stop;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100546 }
547 }
Neels Hofmeyr735b6562023-03-09 02:51:28 +0100548 T.stop;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100549 return rx;
550}
551
552/* send RANAP on Iuh and expect it to show up on Iu */
553function f_iuh2iu_connect(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
554runs on ConnHdlr return RANAP_PDU {
555 var RANAP_PDU rx;
556 timer T := 5.0;
557
558 if (istemplatekind(exp_rx, "omit")) {
559 exp_rx := tx;
560 }
561
562 /* create an expect on the Iu side for the random NAS portion */
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200563 if (g_pars.expect_separate_sccp_cr) {
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200564 f_ran_register_sccp_cr_without_payload();
565 } else {
566 var template (omit) octetstring nas := f_ranap_extract_l3(valueof(tx));
567 f_ran_register_exp(valueof(nas));
568 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100569
570 /* send it via Iuh (creating a RUA connection) */
571 RUA.send(RUA_Conn_Req:{g_pars.ps_domain, tx});
572
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200573 if (g_pars.expect_separate_sccp_cr) {
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200574 /* Acknowledge the empty SCCP CR. RAN_Emulation does the confirmation, no need to respond. */
575 BSSAP.receive(tr_RANAP_Conn_Req());
576 }
577
Daniel Willmann19b8d902022-01-05 09:12:34 +0100578 /* expect to receive it on the Iu side */
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100579 return f_bssap_expect(exp_rx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100580}
581
Neels Hofmeyr99b7d402023-02-20 14:26:31 +0100582/* 3GPP TS 48.006 9.2 Connection release:
583 *
584 * The MSC sends a SCCP released message. This message shall not contain
585 * any user data field.
586 *
587 * So what we expect normally is:
588 *
589 * HNBGW MSC
590 * RUA --id-Disconnect-------> | ---Data-Form-1(!)---> | Iu-ReleaseComplete
591 * | <--Released---------- | (no data)
592 *
593 * This function tests osmo-hnbgw behavior if the CN fails to send a RLSD:
594 * after some timeout, osmo-hnbgw should send a RLSD to the CN.
595 */
Daniel Willmann19b8d902022-01-05 09:12:34 +0100596function f_iuh2iu_disconnect(template (present) RANAP_PDU tx, RUA_IEs.Cause cause,
597 template RANAP_PDU exp_rx := omit)
598runs on ConnHdlr return RANAP_PDU {
599 var RANAP_PDU rx
Neels Hofmeyr99b7d402023-02-20 14:26:31 +0100600 timer T := 10.0;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100601
602 if (istemplatekind(exp_rx, "omit")) {
603 exp_rx := tx;
604 }
605
606 /* send it via Iuh (creating a RUA connection) */
607 RUA.send(RUA_Disc_Req:{tx, cause});
608
609 /* expect to receive it on the Iu side */
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100610 rx := f_bssap_expect(exp_rx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100611
612 /* expect disconnect on the Iu side */
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100613 T.start;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100614 alt {
615 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {
616 setverdict(pass);
617 }
618 [] T.timeout {
619 setverdict(fail, "Timeout waiting for Iu disconnect");
620 return rx;
621 }
622
623 }
624 return rx;
625}
626
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200627private function f_build_initial_ue_with_nas(TestHdlrParams pars, octetstring nas)
628 return RANAP_PDU {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100629 var LAI lai := {
630 pLMNidentity := hex2oct(pars.hnb.lai.mcc_mnc),
631 lAC := int2oct(pars.hnb.lai.lac, 2),
632 iE_Extensions := omit
633 };
634 var SAI sai := {
635 pLMNidentity := lai.pLMNidentity,
636 lAC := lai.lAC,
637 sAC := int2oct(pars.hnb.sac, 2),
638 iE_Extensions := omit
639 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100640 var IuSignallingConnectionIdentifier sigc_id := int2bit(f_rnd_int(1000), 24);
641 var GlobalRNC_ID grnc_id := {
642 pLMNidentity := lai.pLMNidentity,
643 rNC_ID := 2342
644 }
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200645 var template RANAP_PDU ret;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100646 if (pars.ps_domain) {
647 var RAC rac := '00'O;
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200648 ret := ts_RANAP_initialUE_PS(lai, rac, sai, nas, sigc_id, grnc_id);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100649 } else {
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200650 ret := ts_RANAP_initialUE_CS(lai, sai, nas, sigc_id, grnc_id);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100651 }
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200652 return valueof(ret);
653}
654
655/* build a RANAP InitialUE based on the TestHdlrParams */
656friend function f_build_initial_ue(TestHdlrParams pars) return RANAP_PDU {
657
658 var octetstring nas;
659
660 if (pars.tx_sccp_cr_data_len == 0) {
661 nas := f_rnd_octstring(10);
662 } else {
663 /* The test asks for an exact number of Optional Data bytes. */
664
665 /* First see what size the RANAP part of the payload data is,
666 * to adjust the NAS PDU size to the size requested by the test (pars.tx_sccp_cr_data_len). */
667 var RANAP_PDU initial_ue := f_build_initial_ue_with_nas(pars, '00'O);
668
669 var octetstring ranap_plus_one_byte_nas := enc_RANAP_PDU(initial_ue);
670 var integer ranap_length := lengthof(ranap_plus_one_byte_nas) - 1;
671
672 log("ranap_plus_one_byte_nas = ", lengthof(ranap_plus_one_byte_nas), " bytes, ", initial_ue, " = ",
673 ranap_plus_one_byte_nas);
674 log("ranap_length = ", ranap_length);
675
676 /* SCCP CR has a payload length limit of 130 bytes. To trigger this limit, the RANAP + NAS PDU has to be
677 * > 130 bytes. It doesn't need to be 131 bytes in the NAS PDU alone, but let's just make it definitely
678 * large enough. To test for this limit, pars.tx_sccp_cr_data_len asks for a specific amount of data len. */
679 nas := f_rnd_octstring(pars.tx_sccp_cr_data_len - ranap_length);
680 }
681
682 var RANAP_PDU ret := f_build_initial_ue_with_nas(pars, nas);
683
684 if (pars.tx_sccp_cr_data_len != 0) {
685 for (var integer attempts := 0; attempts < 2; attempts := attempts + 1) {
686 var octetstring check_len := enc_RANAP_PDU(ret);
687 log("final RANAP PDU length = ", lengthof(check_len));
688 if (lengthof(check_len) == pars.tx_sccp_cr_data_len) {
689 return ret;
690 }
691 nas := f_rnd_octstring(lengthof(nas) + (pars.tx_sccp_cr_data_len - lengthof(check_len)));
692 log("that was off, changed NAS length to ", lengthof(nas), " and trying again");
693 ret := f_build_initial_ue_with_nas(pars, nas);
694 }
695 setverdict(fail, "Ended up with wrong Optional Data length");
696 mtc.stop;
697 }
698 return ret;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100699}
700
701/* build a RANAP RAB AssignmentResponse based on the TestHdlrParams */
702friend function f_build_rab_ass_resp(TestHdlrParams pars) return RANAP_PDU {
703 var template RAB_SetupOrModifiedList rab_sml;
704
705 rab_sml := ts_RAB_SMdL(t_RAB_id(23), f_ts_RAB_TLA("192.168.1.23"), t_RAB_binding_port(1234));
706
707 return valueof(ts_RANAP_RabAssResp(rab_sml));
708}
709
710
711/***********************************************************************
712 * HNBAP Testing
713 ***********************************************************************/
714
715
Daniel Willmannc79679a2022-08-23 17:48:39 +0200716function 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 +0100717{
718 timer T := 2.0;
719
Daniel Willmann28209ec2022-08-24 09:58:07 +0200720 HNBAP[hnb_idx].send(ts_HNBAP_HNBRegisterRequest(char2oct("TTCN3 HNodeB"),
Daniel Willmann19b8d902022-01-05 09:12:34 +0100721 '00F110'O,
Daniel Willmannc79679a2022-08-23 17:48:39 +0200722 int2bit(1 + cell_id, 28),
Daniel Willmann19b8d902022-01-05 09:12:34 +0100723 int2oct(2, 2),
724 int2oct(3, 1),
725 int2oct(4, 2)));
726
727 T.start;
728 alt {
729 [] HNBAP[hnb_idx].receive(tr_HNBAP_HNBRegisterAccept(?)) {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200730 if (expect_reject) {
731 setverdict(fail, "Rx HNB Register Accept while expecting reject");
732 } else {
733 setverdict(pass);
734 }
735 }
736 [] HNBAP[hnb_idx].receive(tr_HNBAP_HNBRegisterReject(?)) {
737 if (expect_reject) {
738 setverdict(pass);
739 } else {
740 setverdict(fail, "Rx HNB Register Reject while expecting accept");
741 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100742 }
743 [] HNBAP[hnb_idx].receive(IUHEM_Event:?) {
744 repeat;
745 }
746 [] T.timeout {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200747 setverdict(fail, "Timeout waiting for HNB Register response");
Daniel Willmann19b8d902022-01-05 09:12:34 +0100748 }
749 }
750}
751
752testcase TC_hnb_register() runs on test_CT {
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200753 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100754 f_init();
755 f_hnbap_register(0);
756 f_shutdown_helper();
757}
758
Pau Espin Pedrolacf4f222022-09-27 14:33:40 +0200759/* Try to register the same HNB from 2 different concurrent connections. Second
760 * one should be rejected. */
Daniel Willmannc79679a2022-08-23 17:48:39 +0200761testcase TC_hnb_register_duplicate() runs on test_CT {
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200762 g_num_hnbs := 2;
Daniel Willmannc79679a2022-08-23 17:48:39 +0200763 f_init();
764 f_hnbap_register(0);
765 f_hnbap_register(1, 0, expect_reject := true);
766 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
767 f_shutdown_helper();
768}
769
Pau Espin Pedrolacf4f222022-09-27 14:33:40 +0200770/* Try to register the same HNB in the same connection already established, aka
771 * duplicate HNB Register Request. It should be accepted and new configuration
772 * applied. TS 25.469 8.2.4 */
773testcase TC_hnb_register_duplicate_reuse_sctp_assoc() runs on test_CT {
774 g_num_hnbs := 1;
775 f_init();
776 f_hnbap_register(0);
777 f_hnbap_register(0);
778 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
779 f_shutdown_helper();
780}
781
Pau Espin Pedrolf0b9fa02022-09-12 13:31:07 +0200782/* Drop HNBAP conn (HNBAP DEREG) and reconnect it (HNBAP REG) using same SCTP association.
783 * Related: OS#5676, SYS#6113 */
784testcase TC_hnb_reregister_reuse_sctp_assoc() runs on test_CT {
785 g_num_hnbs := 1;
786 f_init();
787 f_hnbap_register(0);
788 HNBAP[0].send(ts_HNBAP_HNBDe_Register(ts_HnbapCause(unspecified)));
789 f_hnbap_register(0);
790 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
791 f_shutdown_helper();
792}
793
Daniel Willmann19b8d902022-01-05 09:12:34 +0100794/***********************************************************************
795 * RUA / RANAP Testing
796 ***********************************************************************/
797
798private template (value) TestHdlrParams
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200799t_pars(integer imsi_suffix, boolean ps_domain := false, integer hnb_idx := 0,
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200800 boolean expect_separate_sccp_cr := false, integer tx_sccp_cr_data_len := 0) := {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100801 hnb_idx := hnb_idx,
802 imsi := f_gen_imsi(imsi_suffix),
803 ps_domain := ps_domain,
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200804 hnb := omit, /* filled in later */
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200805 expect_separate_sccp_cr := expect_separate_sccp_cr,
806 tx_sccp_cr_data_len := tx_sccp_cr_data_len,
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200807 pfcp_local_addr := mp_pfcp_ip_local
Daniel Willmann19b8d902022-01-05 09:12:34 +0100808}
809
810/* Create an Iuh connection; send InitialUE; expect it to appear on new SCCP conenction */
811friend function f_tc_initial_ue(charstring id, TestHdlrParams pars) runs on ConnHdlr {
812 f_init_handler(pars);
813 var RANAP_PDU tx := f_build_initial_ue(g_pars);
814 f_iuh2iu_connect(tx);
815}
816testcase TC_ranap_cs_initial_ue() runs on test_CT {
817 var ConnHdlr vc_conn;
818
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200819 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100820 f_init();
821 f_start_hnbs();
822
823 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(1));
824 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +0200825
826 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +0100827}
828testcase TC_ranap_ps_initial_ue() runs on test_CT {
829 var ConnHdlr vc_conn;
830
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200831 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100832 f_init();
833 f_start_hnbs();
834
835 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(2, true));
836 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +0200837
838 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +0100839}
840
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200841private function f_vty_set_sccp_max_optional_data(TELNETasp_PT pt, integer val := -1)
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200842{
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200843 var charstring valstr;
844 if (val < 0) {
845 valstr := "standard";
846 } else {
847 valstr := int2str(val);
848 }
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200849 f_vty_enter_config(pt);
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200850 f_vty_transceive(pt, "cs7 instance 0");
851 f_vty_transceive(pt, "sccp max-optional-data " & valstr);
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200852 f_vty_transceive(pt, "end");
853}
854
855testcase TC_ranap_cs_initial_ue_empty_cr() runs on test_CT {
856 var ConnHdlr vc_conn;
857
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200858 g_num_hnbs := 1;
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200859 f_init();
860 f_start_hnbs();
861
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200862 f_vty_set_sccp_max_optional_data(HNBGWVTY, 0);
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200863
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200864 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 +0200865 vc_conn.done;
866
867 /* reset */
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200868 f_vty_set_sccp_max_optional_data(HNBGWVTY);
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +0200869
870 f_shutdown_helper();
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200871}
872testcase TC_ranap_ps_initial_ue_empty_cr() runs on test_CT {
873 var ConnHdlr vc_conn;
874
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200875 g_num_hnbs := 1;
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200876 f_init();
877 f_start_hnbs();
878
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200879 f_vty_set_sccp_max_optional_data(HNBGWVTY, 0);
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200880
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200881 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 +0200882 vc_conn.done;
883
884 /* reset */
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200885 f_vty_set_sccp_max_optional_data(HNBGWVTY);
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +0200886
887 f_shutdown_helper();
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200888}
889
890type record Testdata_CR_Limit {
891 integer data_len,
892 integer max_optional_data,
893 boolean expect_separate_sccp_cr
894};
895type record of Testdata_CR_Limit Testdata_CR_Limits;
896
897testcase TC_sccp_cr_limit() runs on test_CT {
898 g_num_hnbs := 1;
899 f_init();
900 f_start_hnbs();
901
902 const Testdata_CR_Limits tests := {
903 { data_len := 130, max_optional_data := -1, expect_separate_sccp_cr := false },
904 { data_len := 131, max_optional_data := -1, expect_separate_sccp_cr := true },
905
906 { data_len := 100, max_optional_data := 100, expect_separate_sccp_cr := false },
907 { data_len := 101, max_optional_data := 100, expect_separate_sccp_cr := true },
908
909 { data_len := 200, max_optional_data := 200, expect_separate_sccp_cr := false },
910 { data_len := 201, max_optional_data := 200, expect_separate_sccp_cr := true }
911 };
912
913 var integer csps;
914 for (csps := 0; csps < 2; csps := csps + 1) {
915 var boolean ps_domain := (csps > 0);
916
917 var integer i;
918 for (i := 0; i < lengthof(tests); i := i + 1) {
919 var Testdata_CR_Limit t := tests[i];
920 f_logp(HNBGWVTY,
921 "TEST PART TC_sccp_cr_limit ps_domain=" & f_bool2str(ps_domain)
922 & " data_len=" & int2str(t.data_len)
923 & " max_optional_data=" & int2str(t.max_optional_data)
924 & " expect_separate_sccp_cr=" & f_bool2str(t.expect_separate_sccp_cr)
925 );
926
927 f_vty_set_sccp_max_optional_data(HNBGWVTY, t.max_optional_data);
928 var ConnHdlr vc_conn;
929 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue),
930 t_pars(100 + i,
931 ps_domain := ps_domain,
932 expect_separate_sccp_cr := t.expect_separate_sccp_cr,
933 tx_sccp_cr_data_len := t.data_len));
934 vc_conn.done;
935 }
936 }
937
938 /* reset */
939 f_vty_set_sccp_max_optional_data(HNBGWVTY);
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +0200940
941 f_shutdown_helper();
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200942}
943
Daniel Willmann19b8d902022-01-05 09:12:34 +0100944/* Reply to a received CRCX with an OK (or the reply configured in cpars), using the given parameters.
945 * Return true when an OK reply was sent, false otherwise.
946 * Count occurrence of Osmux, include Osmux parameters in the reply if necessary. */
947function f_handle_crcx(inout MgcpParameters pars, MgcpCommand mgcp_cmd) return template MgcpResponse {
948 var CrcxResponse conn := pars.mgw_conn_1;
949 if (pars.got_crcx_count > 0) {
950 conn := pars.mgw_conn_2;
951 }
952 pars.got_crcx_count := pars.got_crcx_count + 1;
953
954 var MgcpMessage mgcp_msg := {
955 command := mgcp_cmd
956 }
957 var template MgcpResponse mgcp_resp;
958 var MgcpOsmuxCID osmux_cid;
959 var MgcpCallId call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
960 if (ispresent(pars.mgcp_call_id)) {
961 if (pars.mgcp_call_id != call_id) {
962 setverdict(fail, "CRCX contained unexpected call id. Expected:", pars.mgcp_call_id, " got:", call_id);
963 mtc.stop;
964 }
965 } else {
966 pars.mgcp_call_id := call_id;
967 }
968
969 /* When the endpoint contains a wildcard we keep the endpoint
970 * identifier we have set up in pars. Otherwise we use the
971 * endpoint name that the call agent has supplied */
972 if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard) == false) {
973 pars.mgcp_ep := mgcp_cmd.line.ep;
974 }
975
976 if (conn.resp == -1) {
977 /* Reply with rror */
978 var MgcpResponse mgcp_rsp := {
979 line := {
980 code := "542",
981 trans_id := mgcp_cmd.line.trans_id,
982 string := "FORCED_FAIL"
983 },
984 sdp := omit
985
986 }
987 var MgcpParameter mgcp_rsp_param := {
988 code := "Z",
989 val := pars.mgcp_ep
990 };
991 mgcp_rsp.params[0] := mgcp_rsp_param;
992 return mgcp_rsp;
993 }
994
995 if (conn.resp == 0) {
996 /* Do not reply at all */
997 return omit;
998 }
999
1000 if (conn.resp != 1) {
1001 setverdict(fail, "Unexpected value for pars.mgw_conn_*.resp, expect -1, 0 or 1");
1002 mtc.stop;
1003 }
1004
1005 var SDP_Message sdp := valueof(ts_SDP(conn.mgw_rtp_ip, conn.mgw_rtp_ip,
1006 hex2str(pars.mgcp_call_id), "42",
1007 conn.mgw_rtp_port,
1008 { int2str(pars.rtp_payload_type) },
1009 { valueof(ts_SDP_rtpmap(pars.rtp_payload_type,
1010 pars.rtp_sdp_format)),
1011 valueof(ts_SDP_ptime(20)) }));
1012
1013 if (f_mgcp_contains_par(mgcp_msg, "X-OSMUX")) {
1014 if (not pars.use_osmux) {
1015 setverdict(fail, "MSC sent X-Osmux parameter in MGCP, but not expecting any Osmux");
1016 mtc.stop;
1017 }
1018 pars.got_osmux_count := pars.got_osmux_count + 1;
1019 /* we expect MSC to use wildcard here, i.e. osmux_cid == -1 */
1020 osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
1021 log("f_handle_crcx(): got Osmux CID: ", osmux_cid);
1022 if (osmux_cid != -1) {
1023 setverdict(fail, "MSC using unexpected CID " & int2str(osmux_cid) & " != -1");
1024 mtc.stop;
1025 }
1026
1027 osmux_cid := 0;
1028 mgcp_resp := ts_CRCX_ACK_osmux(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, osmux_cid, sdp);
1029 } else {
1030 mgcp_resp := ts_CRCX_ACK(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, sdp);
1031 }
1032
1033 f_mgcp_par_append(mgcp_resp.params, ts_MgcpParSpecEP(pars.mgcp_ep));
1034
1035 return mgcp_resp;
1036}
1037
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001038friend function f_create_rab(inout MgcpParameters pars) runs on ConnHdlr {
1039 f_rab_ass_req(pars);
1040 f_rab_ass_resp(pars);
1041}
1042
1043friend function f_rab_ass_req(inout MgcpParameters pars) runs on ConnHdlr {
Daniel Willmann19b8d902022-01-05 09:12:34 +01001044 var MgcpCommand mgcp_cmd;
1045 var RANAP_PDU tx;
1046 var template RAB_SetupOrModifyList rab_sml;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001047 timer T := 5.0;
1048
1049 /* Send RAB Assignment Request */
1050 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));
1051 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1052 BSSAP.send(tx);
1053 T.start;
1054
1055 /* Handle MGCP CRCX */
1056 alt {
1057 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
1058 log("CRCX1", mgcp_cmd);
1059 var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
1060 MGCP.send(valueof(mgcp_rsp));
1061 }
1062 [] T.timeout {
1063 setverdict(fail, "Timeout waiting for MGCP");
1064 }
1065 }
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001066 T.stop;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001067
1068 /* Expect RAB Assignment Request with IP/port from CRCX ACK via Iuh */
1069 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));
1070 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1071
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001072 f_rua_expect(tx);
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001073}
1074
1075friend function f_rab_ass_resp(inout MgcpParameters pars) runs on ConnHdlr {
1076 var MgcpCommand mgcp_cmd;
1077 var RANAP_PDU tx;
1078 var template RAB_SetupOrModifiedList rab_smdl;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001079
1080 /* Send back RAB Assignment Response via Iuh */
1081 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));
1082 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1083 RUA.send(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +01001084
1085 interleave {
1086 /* Expect MDCX with IP/port from RAB Assignment Response */
1087 [] MGCP.receive(tr_MDCX(tr_SDP(pars.hnb_rtp_ip, pars.hnb_rtp_port))) -> value mgcp_cmd {
1088 log("MDCX1", mgcp_cmd);
1089 /* Verify SDP of MDCX */
1090 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,
1091 { int2str(pars.rtp_payload_type) }, { valueof(ts_SDP_rtpmap(pars.rtp_payload_type, pars.rtp_sdp_format)), valueof(ts_SDP_ptime(20)) } ));
1092 var template MgcpResponse mgcp_rsp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, pars.mgw_conn_1.mgcp_connection_id, sdp);
1093 MGCP.send(valueof(mgcp_rsp));
1094 }
1095 /* Handle CRCX for second leg of endpoint, answer with IP/port */
1096 [] MGCP.receive(tr_CRCX(pars.mgcp_ep, tr_SDP(pars.cn_rtp_ip, pars.cn_rtp_port))) -> value mgcp_cmd {
1097 log("CRCX2", mgcp_cmd);
1098 /* Verify SDP of CRCX */
1099 var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
1100 MGCP.send(valueof(mgcp_rsp));
1101 }
1102 }
1103
1104 /* Expect RAB Assignment Response with IP/port from second CRCX ACK */
1105 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));
1106 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1107
Neels Hofmeyrdc416c92023-03-09 02:47:50 +01001108 f_bssap_expect(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +01001109}
1110
1111private altstep as_mgcp_dlcx(inout TestHdlrParams pars) runs on ConnHdlr {
1112 var MgcpCommand mgcp_cmd;
1113
1114 [] MGCP.receive(tr_DLCX(pars.mgcp_pars.mgcp_ep)) -> value mgcp_cmd {
1115 log("DLCX", mgcp_cmd);
1116 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
1117 pars.mgcp_pars.got_dlcx_count := pars.mgcp_pars.got_dlcx_count + 1;
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001118 if (pars.mgcp_pars.got_dlcx_count != pars.mgcp_pars.got_crcx_count) {
Daniel Willmann19b8d902022-01-05 09:12:34 +01001119 repeat;
1120 }
1121 setverdict(pass);
1122 }
1123}
1124
1125friend function f_tc_rab_assignment(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1126 var MgcpCommand mgcp_cmd;
1127 var RANAP_PDU tx;
1128 timer T := 5.0;
1129
1130 f_init_handler(pars);
1131 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1132
1133 tx := f_build_initial_ue(g_pars);
1134 f_iuh2iu_connect(tx);
1135
1136 f_create_rab(pars.mgcp_pars);
1137
1138 /* Send Iu Release */
1139 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1140 f_iu2iuh(tx);
1141
1142 T.start;
1143 alt {
1144 [] as_mgcp_dlcx(pars) {}
1145 [] T.timeout {
1146 setverdict(fail, "Timeout waiting for DLCX");
1147 }
1148 }
1149
1150 tx := valueof(ts_RANAP_IuReleaseComplete());
1151 f_iuh2iu(tx);
1152}
1153
1154testcase TC_rab_assignment() runs on test_CT {
1155 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001156 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001157 f_init();
1158 f_start_hnbs();
1159
1160 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assignment), t_pars(3));
1161 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001162
1163 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001164}
1165
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001166friend function f_tc_rab_assign_fail(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1167 var MgcpCommand mgcp_cmd;
1168 var RANAP_PDU tx;
1169 timer T := 5.0;
1170
1171 f_init_handler(pars);
1172 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1173
1174 tx := f_build_initial_ue(g_pars);
1175 f_iuh2iu_connect(tx);
1176
1177 f_rab_ass_req(pars.mgcp_pars);
1178
1179 /* Send RAB failed list in response */
1180 tx := valueof(ts_RANAP_RabAssResp(rab_fl := ts_RAB_FL(t_RAB_id(23), ts_RanapCause_om_intervention)));
1181 f_iuh2iu(tx);
1182
1183 T.start;
1184 alt {
1185 [] as_mgcp_dlcx(pars) {}
1186 [] T.timeout {
1187 setverdict(fail, "Timeout waiting for DLCX");
1188 }
1189 }
1190}
1191
1192testcase TC_rab_assign_fail() runs on test_CT {
1193 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001194 g_num_hnbs := 1;
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001195 f_init();
1196 f_start_hnbs();
1197
1198 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_fail), t_pars(4));
1199 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001200
1201 f_shutdown_helper();
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001202}
1203
Daniel Willmann19b8d902022-01-05 09:12:34 +01001204friend function f_tc_rab_release(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1205 var MgcpCommand mgcp_cmd;
1206 var RANAP_PDU tx;
1207 timer T := 15.0;
1208
1209 f_init_handler(pars);
1210 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1211
1212 tx := f_build_initial_ue(g_pars);
1213 f_iuh2iu_connect(tx);
1214
1215 f_create_rab(pars.mgcp_pars);
1216
1217 /* Send RAB Release */
Daniel Willmann9e789be2022-02-22 13:30:51 +01001218 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 +01001219 BSSAP.send(tx);
1220
1221 T.start;
1222
1223 alt {
1224 [] as_mgcp_dlcx(pars) {}
1225 [] T.timeout {
1226 setverdict(fail, "Timeout waiting for DLCX");
1227 }
1228 }
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001229 T.stop;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001230
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001231 f_rua_expect(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +01001232}
1233
1234testcase TC_rab_release() runs on test_CT {
1235 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001236 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001237 f_init();
1238 f_start_hnbs();
1239
1240 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_release), t_pars(5));
1241 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001242
1243 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001244}
1245
Daniel Willmann37c877f2022-02-22 16:47:06 +01001246friend function f_tc_rab_assign_mgcp_to(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1247 var MgcpCommand mgcp_cmd;
1248 var RANAP_PDU tx;
1249 var template RAB_SetupOrModifyList rab_sml;
1250 timer T := 15.0;
1251
1252 T.start;
1253 f_init_handler(pars);
1254 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1255
1256 tx := f_build_initial_ue(g_pars);
1257 f_iuh2iu_connect(tx);
1258
1259
1260 /* Send RAB Assignment Request */
1261 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));
1262 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1263 BSSAP.send(tx);
1264
1265 /* Ignore MGCP CRCX */
1266 alt {
1267 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
1268 log("Ignoreing CRCX1", mgcp_cmd);
1269 repeat;
1270 }
1271 [] BSSAP.receive(tr_RANAP_IuReleaseRequest(?)) { }
1272 [] T.timeout {
1273 setverdict(fail, "Timeout waiting for IuRelease");
1274 }
1275 }
1276
1277 /* Send Iu Release */
1278 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1279 f_iu2iuh(tx);
1280
1281 tx := valueof(ts_RANAP_IuReleaseComplete());
1282 f_iuh2iu(tx);
1283}
1284
1285testcase TC_rab_assign_mgcp_to() runs on test_CT {
1286 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001287 g_num_hnbs := 1;
Daniel Willmann37c877f2022-02-22 16:47:06 +01001288 f_init();
1289 f_start_hnbs();
1290
1291 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_mgcp_to), t_pars(6));
1292 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001293
1294 f_shutdown_helper();
Daniel Willmann37c877f2022-02-22 16:47:06 +01001295}
1296
Daniel Willmann19b8d902022-01-05 09:12:34 +01001297/* Create an Iuh connection; send InitialUE; transceive data both directions */
1298friend function f_tc_ranap_bidir(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1299 f_init_handler(pars);
1300
1301 /* HNB -> MSC: InitialUE */
1302 f_iuh2iu_connect(f_build_initial_ue(g_pars));
1303
1304 /* MSC <- HNB: DirectTransfer */
1305 f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1306 /* MSC -> HNB: DirectTransfer */
1307 f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1308
1309 /* HNB <- MSC: CommonID */
1310 f_iu2iuh(ts_RANAP_CommonId(hex2oct(pars.imsi)));
1311}
1312testcase TC_ranap_cs_bidir() runs on test_CT {
1313 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001314 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001315 f_init();
1316 f_start_hnbs();
1317
1318 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(3));
1319 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001320
1321 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001322}
1323testcase TC_ranap_ps_bidir() runs on test_CT {
1324 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001325 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001326 f_init();
1327 f_start_hnbs();
1328
1329 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(4, true));
1330 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001331
1332 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001333}
1334
1335
1336private function f_tc_ranap_mo_disconnect(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1337 f_init_handler(pars);
1338
1339 /* HNB -> MSC: InitialUE */
1340 f_iuh2iu_connect(f_build_initial_ue(g_pars));
1341
1342 /* MSC <- HNB: DirectTransfer */
1343 f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1344 /* MSC -> HNB: DirectTransfer */
1345 f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1346
1347 /* MSC <- HNB: RUA disconnect */
1348 f_iuh2iu_disconnect(ts_RANAP_IuReleaseComplete, RUA_IEs.Cause:{misc:=processing_overload});
1349}
1350testcase TC_ranap_cs_mo_disconnect() runs on test_CT {
1351 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001352 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001353 f_init();
1354 f_start_hnbs();
1355
1356 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(5));
1357 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001358
1359 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001360}
1361testcase TC_ranap_ps_mo_disconnect() runs on test_CT {
1362 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001363 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001364 f_init();
1365 f_start_hnbs();
1366
1367 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(6));
1368 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001369
1370 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001371}
1372
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001373type record FTeid {
1374 HostName addr,
1375 OCT4 teid
1376}
1377
1378type record FTeids {
1379 FTeid local,
1380 FTeid remote
1381}
Daniel Willmann19b8d902022-01-05 09:12:34 +01001382
1383
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001384/* 'local' and 'remote' refer to the GTP information from the UPF's point of view:
1385 * HNB UPF CN
1386 * access.remote <---> access.local | core.local <---> core.remote
1387 */
1388type record GtpParameters {
1389 FTeids core,
1390 FTeids access
1391}
1392
1393/* HNB UPF CN
1394 * access.remote <---> access.local | core.local <---> core.remote
1395 * 127.0.0.4 127.0.0.3 127.0.0.2 127.0.0.1
1396 * 0x44004400 0x30303030 0x22002200 0x10101010
1397 */
1398template GtpParameters t_GtpParameters := {
1399 core := {
1400 local := {
1401 addr := "127.0.0.2",
1402 teid := '22002200'O
1403 },
1404 remote := {
1405 addr := "127.0.0.1",
1406 teid := '10101010'O
1407 }
1408 },
1409 access := {
1410 local := {
1411 addr := "127.0.0.3",
1412 teid := '30303030'O
1413 },
1414 remote := {
1415 addr := "127.0.0.4",
1416 teid := '44004400'O
1417 }
1418 }
1419}
1420
Neels Hofmeyr65499282023-04-25 02:31:51 +02001421private 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 +01001422{
1423 var PDU_PFCP rx;
Neels Hofmeyr65499282023-04-25 02:31:51 +02001424 timer T := wait_time;
Neels Hofmeyr6bbfe052023-03-09 02:51:46 +01001425 T.start;
1426 alt {
1427 [] PFCP.receive(exp_rx) -> value rx {
1428 setverdict(pass);
1429 }
1430 [] PFCP.receive(PDU_PFCP:?) {
1431 setverdict(fail, "Got an unexpected PFCP message, was waiting for ", exp_rx);
1432 mtc.stop;
1433 }
1434 [] T.timeout {
1435 setverdict(fail, "Timeout waiting for PFCP ", exp_rx);
1436 mtc.stop;
1437 }
1438 }
1439 T.stop;
1440 return rx;
1441}
1442
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001443friend function f_tc_ps_rab_assignment_with_pfcp(charstring id, TestHdlrParams pars) runs on ConnHdlr {
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001444 var RANAP_PDU tx;
1445 var RANAP_PDU rx;
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001446
1447 f_init_handler(pars);
1448
1449 f_pfcp_register();
1450
1451 var PDU_PFCP m;
1452 var Node_ID upf_node_id := valueof(ts_PFCP_Node_ID_fqdn("\07osmocom\03org"));
1453
Neels Hofmeyr65499282023-04-25 02:31:51 +02001454 m := f_pfcp_expect(tr_PFCP_Assoc_Setup_Req(), wait_time := 15.0);
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001455 PFCP.send(ts_PFCP_Assoc_Setup_Resp(m.sequence_number, upf_node_id,
1456 ts_PFCP_Cause(REQUEST_ACCEPTED), 1234));
1457
1458 tx := f_build_initial_ue(g_pars);
1459 f_iuh2iu_connect(tx);
1460
1461 var GtpParameters gtp_pars := valueof(t_GtpParameters);
1462 var template RAB_SetupOrModifyList rab_sml;
1463
1464 /* Send RAB Assignment Request */
1465 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.remote.addr), gtp_pars.core.remote.teid);
1466 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1467 BSSAP.send(tx);
1468
1469 /* Expect PFCP Session Establishment Request. */
Neels Hofmeyr6bbfe052023-03-09 02:51:46 +01001470 m := f_pfcp_expect(tr_PFCP_Session_Est_Req());
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001471 var F_SEID hnbgw_f_seid := m.message_body.pfcp_session_establishment_request.CP_F_SEID;
1472 var PFCP_Session_Establishment_Request serq := m.message_body.pfcp_session_establishment_request;
1473
1474 /* Acting as UPF, invent a new PFCP SEID to send to HNBGW. Respond to the Session Establishment.
1475 * The PFCP response must have the same sequence_number as the request. */
Neels Hofmeyr1e311462023-01-11 01:19:12 +01001476 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 +02001477 var template PDU_PFCP r := ts_PFCP_Session_Est_Resp(m.sequence_number, upf_node_id, hnbgw_f_seid.seid);
1478 r.message_body.pfcp_session_establishment_response := {
1479 offending_ie := omit,
1480 UP_F_SEID := up_f_seid,
1481 created_PDR_list := {
1482 ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[0].grouped_ie.pdr_id,
1483 local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.core.local.teid,
Neels Hofmeyr1e311462023-01-11 01:19:12 +01001484 f_inet_addr(gtp_pars.core.local.addr))),
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001485 ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[1].grouped_ie.pdr_id,
1486 local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.access.local.teid,
Neels Hofmeyr1e311462023-01-11 01:19:12 +01001487 f_inet_addr(gtp_pars.access.local.addr)))
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001488 },
1489 load_control_information := omit,
1490 overload_control_information := omit,
1491 node_list := omit,
1492 failed_rule_id := omit,
1493 created_traffic_endpoint_list := omit
1494 };
1495 PFCP.send(r);
1496
1497 /* Expect on Iuh: RAB Assignment Request with IP/port from PFCP Session Est Resp */
1498 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.local.addr),
1499 gtp_pars.access.local.teid);
1500 rx := valueof(ts_RANAP_RabAssReq(rab_sml));
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001501 f_rua_expect(rx);
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001502
1503 /* Send back RAB Assignment Response via Iuh */
1504 var template RAB_SetupOrModifiedList rab_smdl;
1505 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.remote.addr),
1506 gtp_pars.access.remote.teid);
1507 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1508 RUA.send(tx);
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001509
Neels Hofmeyr6bbfe052023-03-09 02:51:46 +01001510 m := f_pfcp_expect(tr_PFCP_Session_Mod_Req(up_f_seid.seid));
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001511 r := ts_PFCP_Session_Mod_Resp(m.sequence_number, hnbgw_f_seid.seid);
1512 PFCP.send(r);
1513
1514 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 +01001515 f_bssap_expect(tr_RANAP_RabAssResp(rab_smdl));
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001516
1517 f_sleep(2.0);
1518 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1519 f_iu2iuh(tx);
1520
1521 tx := valueof(ts_RANAP_IuReleaseComplete());
1522 f_iuh2iu(tx);
1523
Neels Hofmeyr6bbfe052023-03-09 02:51:46 +01001524 m := f_pfcp_expect(tr_PFCP_Session_Del_Req(up_f_seid.seid));
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001525 PFCP.send(ts_PFCP_Session_Del_Resp(m.sequence_number, hnbgw_f_seid.seid));
1526
1527 f_sleep(2.0);
1528}
1529
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001530testcase TC_ps_rab_assignment_with_pfcp() runs on test_CT {
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001531 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001532 g_num_hnbs := 1;
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001533 f_init();
1534 f_start_hnbs();
1535 f_sleep(1.0);
1536
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001537 vc_conn := f_start_handler_with_pars(refers(f_tc_ps_rab_assignment_with_pfcp), t_pars(7, ps_domain := true));
1538 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001539
1540 f_shutdown_helper();
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001541}
1542
1543altstep as_disallow_pfcp() runs on ConnHdlr {
1544 [] PFCP.receive(PDU_PFCP:?) {
1545 setverdict(fail, "Received PFCP message, but no PFCP communication expected");
1546 mtc.stop;
1547 }
1548}
1549
1550friend function f_tc_ps_rab_assignment_without_pfcp(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1551 var RANAP_PDU tx;
1552 var RANAP_PDU rx;
1553 timer T := 5.0;
1554
1555 f_init_handler(pars);
1556
1557 f_pfcp_register();
1558 activate(as_disallow_pfcp());
1559
1560 tx := f_build_initial_ue(g_pars);
1561 f_iuh2iu_connect(tx);
1562
1563 var GtpParameters gtp_pars := valueof(t_GtpParameters);
1564 var template RAB_SetupOrModifyList rab_sml;
1565
1566 /* Send RAB Assignment Request */
1567 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.remote.addr), gtp_pars.core.remote.teid);
1568 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1569 BSSAP.send(tx);
1570
1571 /* Expect on Iuh: unmodified RAB Assignment Request */
1572 rx := valueof(ts_RANAP_RabAssReq(rab_sml));
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001573 f_rua_expect(rx);
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001574
1575 /* Send back RAB Assignment Response via Iuh */
1576 var template RAB_SetupOrModifiedList rab_smdl;
1577 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.remote.addr),
1578 gtp_pars.access.remote.teid);
1579 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1580 RUA.send(tx);
1581
1582 /* Expect on IuPS: unmodified RAB Assignment Response */
Neels Hofmeyrdc416c92023-03-09 02:47:50 +01001583 f_bssap_expect(tr_RANAP_RabAssResp(rab_smdl));
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001584
1585 f_sleep(2.0);
1586 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1587 f_iu2iuh(tx);
1588
1589 tx := valueof(ts_RANAP_IuReleaseComplete());
1590 f_iuh2iu(tx);
1591
1592 f_sleep(2.0);
1593}
1594
1595testcase TC_ps_rab_assignment_without_pfcp() runs on test_CT {
1596 var ConnHdlr vc_conn;
1597 f_init();
1598 f_start_hnbs();
1599 f_sleep(1.0);
1600
1601 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 +02001602 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001603
1604 f_shutdown_helper();
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001605}
Daniel Willmann19b8d902022-01-05 09:12:34 +01001606
1607control {
1608 execute(TC_hnb_register());
Daniel Willmannc79679a2022-08-23 17:48:39 +02001609 execute(TC_hnb_register_duplicate());
Pau Espin Pedrolacf4f222022-09-27 14:33:40 +02001610 execute(TC_hnb_register_duplicate_reuse_sctp_assoc());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001611 execute(TC_ranap_cs_initial_ue());
1612 execute(TC_ranap_ps_initial_ue());
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02001613 execute(TC_ranap_cs_initial_ue_empty_cr());
1614 execute(TC_ranap_ps_initial_ue_empty_cr());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001615 execute(TC_ranap_cs_bidir());
1616 execute(TC_ranap_ps_bidir());
1617 execute(TC_rab_assignment());
1618 execute(TC_rab_release());
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001619 execute(TC_rab_assign_fail());
Daniel Willmann37c877f2022-02-22 16:47:06 +01001620 execute(TC_rab_assign_mgcp_to());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001621 execute(TC_ranap_cs_mo_disconnect());
1622 execute(TC_ranap_ps_mo_disconnect());
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001623
1624 if (mp_enable_pfcp_tests) {
1625 execute(TC_ps_rab_assignment_with_pfcp());
1626 } else {
1627 execute(TC_ps_rab_assignment_without_pfcp());
1628 }
Pau Espin Pedrolf0b9fa02022-09-12 13:31:07 +02001629
1630 /* Run at the end since it makes osmo-hnbgw <= 1.3.0 crash: OS#5676 */
1631 execute(TC_hnb_reregister_reuse_sctp_assoc());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001632}
1633
1634}