blob: c3dbecd1b069e1466d339ff5bb06944cc7a72c0d [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? */
Daniel Willmann19b8d902022-01-05 09:12:34 +0100468}
469
470/* global altstep for global guard timer; */
471private altstep as_Tguard_ConnHdlr() runs on ConnHdlr {
472 [] g_Tguard.timeout {
473 setverdict(fail, "Timeout of T_guard");
474 mtc.stop;
475 }
476}
477
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100478private function f_bssap_expect(template (present) RANAP_PDU exp_rx) runs on ConnHdlr return RANAP_PDU
479{
480 var RANAP_PDU rx;
481 timer T := 5.0;
482 T.start;
483 alt {
484 [] BSSAP.receive(exp_rx) -> value rx {
485 setverdict(pass);
486 }
487 [] BSSAP.receive(RANAP_PDU:?) {
488 setverdict(fail, "Got an unexpected RANAP message on BSSAP port, was waiting for ", exp_rx);
489 mtc.stop;
490 }
491 [] T.timeout {
492 setverdict(fail, "Timeout waiting for RANAP on BSSAP port: ", exp_rx);
493 mtc.stop;
494 }
495 }
496 T.stop;
497 return rx;
498}
499
Daniel Willmann19b8d902022-01-05 09:12:34 +0100500/* send RANAP on Iuh and expect it to show up on Iu */
501function f_iuh2iu(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
502runs on ConnHdlr return RANAP_PDU {
503 var RANAP_PDU rx;
504 timer T := 5.0;
505
506 if (istemplatekind(exp_rx, "omit")) {
507 exp_rx := tx;
508 }
509
510 RUA.send(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100511
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100512 return f_bssap_expect(exp_rx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100513}
514
515/* send RANAP on Iu and expect it to show up on Iuh */
516function f_iu2iuh(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
517runs on ConnHdlr return RANAP_PDU {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100518 if (istemplatekind(exp_rx, "omit")) {
519 exp_rx := tx;
520 }
521
522 BSSAP.send(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100523
Neels Hofmeyr735b6562023-03-09 02:51:28 +0100524 return f_rua_expect(exp_rx)
525}
526
527/* expect to receive a specific RUA message on Iuh */
528private function f_rua_expect(template (present) RANAP_PDU exp_rx) runs on ConnHdlr return RANAP_PDU
529{
530 var RANAP_PDU rx;
531 timer T := 5.0;
532 T.start;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100533 alt {
534 [] RUA.receive(exp_rx) -> value rx {
535 setverdict(pass);
536 }
Neels Hofmeyr735b6562023-03-09 02:51:28 +0100537 [] RUA.receive(RANAP_PDU:?) {
538 setverdict(fail, "Got an unexpected RUA message, was waiting for ", exp_rx);
539 mtc.stop;
540 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100541 [] T.timeout {
542 setverdict(fail, "Timeout waiting for Iuh ", exp_rx);
Neels Hofmeyr735b6562023-03-09 02:51:28 +0100543 mtc.stop;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100544 }
545 }
Neels Hofmeyr735b6562023-03-09 02:51:28 +0100546 T.stop;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100547 return rx;
548}
549
550/* send RANAP on Iuh and expect it to show up on Iu */
551function f_iuh2iu_connect(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
552runs on ConnHdlr return RANAP_PDU {
553 var RANAP_PDU rx;
554 timer T := 5.0;
555
556 if (istemplatekind(exp_rx, "omit")) {
557 exp_rx := tx;
558 }
559
560 /* create an expect on the Iu side for the random NAS portion */
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200561 if (g_pars.expect_separate_sccp_cr) {
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200562 f_ran_register_sccp_cr_without_payload();
563 } else {
564 var template (omit) octetstring nas := f_ranap_extract_l3(valueof(tx));
565 f_ran_register_exp(valueof(nas));
566 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100567
568 /* send it via Iuh (creating a RUA connection) */
569 RUA.send(RUA_Conn_Req:{g_pars.ps_domain, tx});
570
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200571 if (g_pars.expect_separate_sccp_cr) {
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200572 /* Acknowledge the empty SCCP CR. RAN_Emulation does the confirmation, no need to respond. */
573 BSSAP.receive(tr_RANAP_Conn_Req());
574 }
575
Daniel Willmann19b8d902022-01-05 09:12:34 +0100576 /* expect to receive it on the Iu side */
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100577 return f_bssap_expect(exp_rx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100578}
579
Neels Hofmeyr99b7d402023-02-20 14:26:31 +0100580/* 3GPP TS 48.006 9.2 Connection release:
581 *
582 * The MSC sends a SCCP released message. This message shall not contain
583 * any user data field.
584 *
585 * So what we expect normally is:
586 *
587 * HNBGW MSC
588 * RUA --id-Disconnect-------> | ---Data-Form-1(!)---> | Iu-ReleaseComplete
589 * | <--Released---------- | (no data)
590 *
591 * This function tests osmo-hnbgw behavior if the CN fails to send a RLSD:
592 * after some timeout, osmo-hnbgw should send a RLSD to the CN.
593 */
Daniel Willmann19b8d902022-01-05 09:12:34 +0100594function f_iuh2iu_disconnect(template (present) RANAP_PDU tx, RUA_IEs.Cause cause,
595 template RANAP_PDU exp_rx := omit)
596runs on ConnHdlr return RANAP_PDU {
597 var RANAP_PDU rx
Neels Hofmeyr99b7d402023-02-20 14:26:31 +0100598 timer T := 10.0;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100599
600 if (istemplatekind(exp_rx, "omit")) {
601 exp_rx := tx;
602 }
603
604 /* send it via Iuh (creating a RUA connection) */
605 RUA.send(RUA_Disc_Req:{tx, cause});
606
607 /* expect to receive it on the Iu side */
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100608 rx := f_bssap_expect(exp_rx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100609
610 /* expect disconnect on the Iu side */
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100611 T.start;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100612 alt {
613 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {
614 setverdict(pass);
615 }
616 [] T.timeout {
617 setverdict(fail, "Timeout waiting for Iu disconnect");
618 return rx;
619 }
620
621 }
622 return rx;
623}
624
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200625private function f_build_initial_ue_with_nas(TestHdlrParams pars, octetstring nas)
626 return RANAP_PDU {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100627 var LAI lai := {
628 pLMNidentity := hex2oct(pars.hnb.lai.mcc_mnc),
629 lAC := int2oct(pars.hnb.lai.lac, 2),
630 iE_Extensions := omit
631 };
632 var SAI sai := {
633 pLMNidentity := lai.pLMNidentity,
634 lAC := lai.lAC,
635 sAC := int2oct(pars.hnb.sac, 2),
636 iE_Extensions := omit
637 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100638 var IuSignallingConnectionIdentifier sigc_id := int2bit(f_rnd_int(1000), 24);
639 var GlobalRNC_ID grnc_id := {
640 pLMNidentity := lai.pLMNidentity,
641 rNC_ID := 2342
642 }
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200643 var template RANAP_PDU ret;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100644 if (pars.ps_domain) {
645 var RAC rac := '00'O;
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200646 ret := ts_RANAP_initialUE_PS(lai, rac, sai, nas, sigc_id, grnc_id);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100647 } else {
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200648 ret := ts_RANAP_initialUE_CS(lai, sai, nas, sigc_id, grnc_id);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100649 }
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200650 return valueof(ret);
651}
652
653/* build a RANAP InitialUE based on the TestHdlrParams */
654friend function f_build_initial_ue(TestHdlrParams pars) return RANAP_PDU {
655
656 var octetstring nas;
657
658 if (pars.tx_sccp_cr_data_len == 0) {
659 nas := f_rnd_octstring(10);
660 } else {
661 /* The test asks for an exact number of Optional Data bytes. */
662
663 /* First see what size the RANAP part of the payload data is,
664 * to adjust the NAS PDU size to the size requested by the test (pars.tx_sccp_cr_data_len). */
665 var RANAP_PDU initial_ue := f_build_initial_ue_with_nas(pars, '00'O);
666
667 var octetstring ranap_plus_one_byte_nas := enc_RANAP_PDU(initial_ue);
668 var integer ranap_length := lengthof(ranap_plus_one_byte_nas) - 1;
669
670 log("ranap_plus_one_byte_nas = ", lengthof(ranap_plus_one_byte_nas), " bytes, ", initial_ue, " = ",
671 ranap_plus_one_byte_nas);
672 log("ranap_length = ", ranap_length);
673
674 /* SCCP CR has a payload length limit of 130 bytes. To trigger this limit, the RANAP + NAS PDU has to be
675 * > 130 bytes. It doesn't need to be 131 bytes in the NAS PDU alone, but let's just make it definitely
676 * large enough. To test for this limit, pars.tx_sccp_cr_data_len asks for a specific amount of data len. */
677 nas := f_rnd_octstring(pars.tx_sccp_cr_data_len - ranap_length);
678 }
679
680 var RANAP_PDU ret := f_build_initial_ue_with_nas(pars, nas);
681
682 if (pars.tx_sccp_cr_data_len != 0) {
683 for (var integer attempts := 0; attempts < 2; attempts := attempts + 1) {
684 var octetstring check_len := enc_RANAP_PDU(ret);
685 log("final RANAP PDU length = ", lengthof(check_len));
686 if (lengthof(check_len) == pars.tx_sccp_cr_data_len) {
687 return ret;
688 }
689 nas := f_rnd_octstring(lengthof(nas) + (pars.tx_sccp_cr_data_len - lengthof(check_len)));
690 log("that was off, changed NAS length to ", lengthof(nas), " and trying again");
691 ret := f_build_initial_ue_with_nas(pars, nas);
692 }
693 setverdict(fail, "Ended up with wrong Optional Data length");
694 mtc.stop;
695 }
696 return ret;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100697}
698
699/* build a RANAP RAB AssignmentResponse based on the TestHdlrParams */
700friend function f_build_rab_ass_resp(TestHdlrParams pars) return RANAP_PDU {
701 var template RAB_SetupOrModifiedList rab_sml;
702
703 rab_sml := ts_RAB_SMdL(t_RAB_id(23), f_ts_RAB_TLA("192.168.1.23"), t_RAB_binding_port(1234));
704
705 return valueof(ts_RANAP_RabAssResp(rab_sml));
706}
707
708
709/***********************************************************************
710 * HNBAP Testing
711 ***********************************************************************/
712
713
Daniel Willmannc79679a2022-08-23 17:48:39 +0200714function 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 +0100715{
716 timer T := 2.0;
717
Daniel Willmann28209ec2022-08-24 09:58:07 +0200718 HNBAP[hnb_idx].send(ts_HNBAP_HNBRegisterRequest(char2oct("TTCN3 HNodeB"),
Daniel Willmann19b8d902022-01-05 09:12:34 +0100719 '00F110'O,
Daniel Willmannc79679a2022-08-23 17:48:39 +0200720 int2bit(1 + cell_id, 28),
Daniel Willmann19b8d902022-01-05 09:12:34 +0100721 int2oct(2, 2),
722 int2oct(3, 1),
723 int2oct(4, 2)));
724
725 T.start;
726 alt {
727 [] HNBAP[hnb_idx].receive(tr_HNBAP_HNBRegisterAccept(?)) {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200728 if (expect_reject) {
729 setverdict(fail, "Rx HNB Register Accept while expecting reject");
730 } else {
731 setverdict(pass);
732 }
733 }
734 [] HNBAP[hnb_idx].receive(tr_HNBAP_HNBRegisterReject(?)) {
735 if (expect_reject) {
736 setverdict(pass);
737 } else {
738 setverdict(fail, "Rx HNB Register Reject while expecting accept");
739 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100740 }
741 [] HNBAP[hnb_idx].receive(IUHEM_Event:?) {
742 repeat;
743 }
744 [] T.timeout {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200745 setverdict(fail, "Timeout waiting for HNB Register response");
Daniel Willmann19b8d902022-01-05 09:12:34 +0100746 }
747 }
748}
749
750testcase TC_hnb_register() runs on test_CT {
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200751 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100752 f_init();
753 f_hnbap_register(0);
754 f_shutdown_helper();
755}
756
Pau Espin Pedrolacf4f222022-09-27 14:33:40 +0200757/* Try to register the same HNB from 2 different concurrent connections. Second
758 * one should be rejected. */
Daniel Willmannc79679a2022-08-23 17:48:39 +0200759testcase TC_hnb_register_duplicate() runs on test_CT {
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200760 g_num_hnbs := 2;
Daniel Willmannc79679a2022-08-23 17:48:39 +0200761 f_init();
762 f_hnbap_register(0);
763 f_hnbap_register(1, 0, expect_reject := true);
764 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
765 f_shutdown_helper();
766}
767
Pau Espin Pedrolacf4f222022-09-27 14:33:40 +0200768/* Try to register the same HNB in the same connection already established, aka
769 * duplicate HNB Register Request. It should be accepted and new configuration
770 * applied. TS 25.469 8.2.4 */
771testcase TC_hnb_register_duplicate_reuse_sctp_assoc() runs on test_CT {
772 g_num_hnbs := 1;
773 f_init();
774 f_hnbap_register(0);
775 f_hnbap_register(0);
776 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
777 f_shutdown_helper();
778}
779
Pau Espin Pedrolf0b9fa02022-09-12 13:31:07 +0200780/* Drop HNBAP conn (HNBAP DEREG) and reconnect it (HNBAP REG) using same SCTP association.
781 * Related: OS#5676, SYS#6113 */
782testcase TC_hnb_reregister_reuse_sctp_assoc() runs on test_CT {
783 g_num_hnbs := 1;
784 f_init();
785 f_hnbap_register(0);
786 HNBAP[0].send(ts_HNBAP_HNBDe_Register(ts_HnbapCause(unspecified)));
787 f_hnbap_register(0);
788 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
789 f_shutdown_helper();
790}
791
Daniel Willmann19b8d902022-01-05 09:12:34 +0100792/***********************************************************************
793 * RUA / RANAP Testing
794 ***********************************************************************/
795
796private template (value) TestHdlrParams
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200797t_pars(integer imsi_suffix, boolean ps_domain := false, integer hnb_idx := 0,
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200798 boolean expect_separate_sccp_cr := false, integer tx_sccp_cr_data_len := 0) := {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100799 hnb_idx := hnb_idx,
800 imsi := f_gen_imsi(imsi_suffix),
801 ps_domain := ps_domain,
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200802 hnb := omit, /* filled in later */
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200803 expect_separate_sccp_cr := expect_separate_sccp_cr,
804 tx_sccp_cr_data_len := tx_sccp_cr_data_len,
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200805 pfcp_local_addr := mp_pfcp_ip_local
Daniel Willmann19b8d902022-01-05 09:12:34 +0100806}
807
808/* Create an Iuh connection; send InitialUE; expect it to appear on new SCCP conenction */
809friend function f_tc_initial_ue(charstring id, TestHdlrParams pars) runs on ConnHdlr {
810 f_init_handler(pars);
811 var RANAP_PDU tx := f_build_initial_ue(g_pars);
812 f_iuh2iu_connect(tx);
813}
814testcase TC_ranap_cs_initial_ue() runs on test_CT {
815 var ConnHdlr vc_conn;
816
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200817 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100818 f_init();
819 f_start_hnbs();
820
821 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(1));
822 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +0200823
824 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +0100825}
826testcase TC_ranap_ps_initial_ue() runs on test_CT {
827 var ConnHdlr vc_conn;
828
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200829 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100830 f_init();
831 f_start_hnbs();
832
833 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(2, true));
834 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +0200835
836 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +0100837}
838
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200839private function f_vty_set_sccp_max_optional_data(TELNETasp_PT pt, integer val := -1)
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200840{
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200841 var charstring valstr;
842 if (val < 0) {
843 valstr := "standard";
844 } else {
845 valstr := int2str(val);
846 }
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200847 f_vty_enter_config(pt);
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200848 f_vty_transceive(pt, "cs7 instance 0");
849 f_vty_transceive(pt, "sccp max-optional-data " & valstr);
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200850 f_vty_transceive(pt, "end");
851}
852
853testcase TC_ranap_cs_initial_ue_empty_cr() runs on test_CT {
854 var ConnHdlr vc_conn;
855
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200856 g_num_hnbs := 1;
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200857 f_init();
858 f_start_hnbs();
859
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200860 f_vty_set_sccp_max_optional_data(HNBGWVTY, 0);
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200861
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200862 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 +0200863 vc_conn.done;
864
865 /* reset */
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200866 f_vty_set_sccp_max_optional_data(HNBGWVTY);
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +0200867
868 f_shutdown_helper();
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200869}
870testcase TC_ranap_ps_initial_ue_empty_cr() runs on test_CT {
871 var ConnHdlr vc_conn;
872
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200873 g_num_hnbs := 1;
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200874 f_init();
875 f_start_hnbs();
876
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200877 f_vty_set_sccp_max_optional_data(HNBGWVTY, 0);
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200878
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200879 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 +0200880 vc_conn.done;
881
882 /* reset */
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200883 f_vty_set_sccp_max_optional_data(HNBGWVTY);
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +0200884
885 f_shutdown_helper();
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200886}
887
888type record Testdata_CR_Limit {
889 integer data_len,
890 integer max_optional_data,
891 boolean expect_separate_sccp_cr
892};
893type record of Testdata_CR_Limit Testdata_CR_Limits;
894
895testcase TC_sccp_cr_limit() runs on test_CT {
896 g_num_hnbs := 1;
897 f_init();
898 f_start_hnbs();
899
900 const Testdata_CR_Limits tests := {
901 { data_len := 130, max_optional_data := -1, expect_separate_sccp_cr := false },
902 { data_len := 131, max_optional_data := -1, expect_separate_sccp_cr := true },
903
904 { data_len := 100, max_optional_data := 100, expect_separate_sccp_cr := false },
905 { data_len := 101, max_optional_data := 100, expect_separate_sccp_cr := true },
906
907 { data_len := 200, max_optional_data := 200, expect_separate_sccp_cr := false },
908 { data_len := 201, max_optional_data := 200, expect_separate_sccp_cr := true }
909 };
910
911 var integer csps;
912 for (csps := 0; csps < 2; csps := csps + 1) {
913 var boolean ps_domain := (csps > 0);
914
915 var integer i;
916 for (i := 0; i < lengthof(tests); i := i + 1) {
917 var Testdata_CR_Limit t := tests[i];
918 f_logp(HNBGWVTY,
919 "TEST PART TC_sccp_cr_limit ps_domain=" & f_bool2str(ps_domain)
920 & " data_len=" & int2str(t.data_len)
921 & " max_optional_data=" & int2str(t.max_optional_data)
922 & " expect_separate_sccp_cr=" & f_bool2str(t.expect_separate_sccp_cr)
923 );
924
925 f_vty_set_sccp_max_optional_data(HNBGWVTY, t.max_optional_data);
926 var ConnHdlr vc_conn;
927 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue),
928 t_pars(100 + i,
929 ps_domain := ps_domain,
930 expect_separate_sccp_cr := t.expect_separate_sccp_cr,
931 tx_sccp_cr_data_len := t.data_len));
932 vc_conn.done;
933 }
934 }
935
936 /* reset */
937 f_vty_set_sccp_max_optional_data(HNBGWVTY);
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +0200938
939 f_shutdown_helper();
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200940}
941
Daniel Willmann19b8d902022-01-05 09:12:34 +0100942/* Reply to a received CRCX with an OK (or the reply configured in cpars), using the given parameters.
943 * Return true when an OK reply was sent, false otherwise.
944 * Count occurrence of Osmux, include Osmux parameters in the reply if necessary. */
945function f_handle_crcx(inout MgcpParameters pars, MgcpCommand mgcp_cmd) return template MgcpResponse {
946 var CrcxResponse conn := pars.mgw_conn_1;
947 if (pars.got_crcx_count > 0) {
948 conn := pars.mgw_conn_2;
949 }
950 pars.got_crcx_count := pars.got_crcx_count + 1;
951
952 var MgcpMessage mgcp_msg := {
953 command := mgcp_cmd
954 }
955 var template MgcpResponse mgcp_resp;
956 var MgcpOsmuxCID osmux_cid;
957 var MgcpCallId call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
958 if (ispresent(pars.mgcp_call_id)) {
959 if (pars.mgcp_call_id != call_id) {
960 setverdict(fail, "CRCX contained unexpected call id. Expected:", pars.mgcp_call_id, " got:", call_id);
961 mtc.stop;
962 }
963 } else {
964 pars.mgcp_call_id := call_id;
965 }
966
967 /* When the endpoint contains a wildcard we keep the endpoint
968 * identifier we have set up in pars. Otherwise we use the
969 * endpoint name that the call agent has supplied */
970 if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard) == false) {
971 pars.mgcp_ep := mgcp_cmd.line.ep;
972 }
973
974 if (conn.resp == -1) {
975 /* Reply with rror */
976 var MgcpResponse mgcp_rsp := {
977 line := {
978 code := "542",
979 trans_id := mgcp_cmd.line.trans_id,
980 string := "FORCED_FAIL"
981 },
982 sdp := omit
983
984 }
985 var MgcpParameter mgcp_rsp_param := {
986 code := "Z",
987 val := pars.mgcp_ep
988 };
989 mgcp_rsp.params[0] := mgcp_rsp_param;
990 return mgcp_rsp;
991 }
992
993 if (conn.resp == 0) {
994 /* Do not reply at all */
995 return omit;
996 }
997
998 if (conn.resp != 1) {
999 setverdict(fail, "Unexpected value for pars.mgw_conn_*.resp, expect -1, 0 or 1");
1000 mtc.stop;
1001 }
1002
1003 var SDP_Message sdp := valueof(ts_SDP(conn.mgw_rtp_ip, conn.mgw_rtp_ip,
1004 hex2str(pars.mgcp_call_id), "42",
1005 conn.mgw_rtp_port,
1006 { int2str(pars.rtp_payload_type) },
1007 { valueof(ts_SDP_rtpmap(pars.rtp_payload_type,
1008 pars.rtp_sdp_format)),
1009 valueof(ts_SDP_ptime(20)) }));
1010
1011 if (f_mgcp_contains_par(mgcp_msg, "X-OSMUX")) {
1012 if (not pars.use_osmux) {
1013 setverdict(fail, "MSC sent X-Osmux parameter in MGCP, but not expecting any Osmux");
1014 mtc.stop;
1015 }
1016 pars.got_osmux_count := pars.got_osmux_count + 1;
1017 /* we expect MSC to use wildcard here, i.e. osmux_cid == -1 */
1018 osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
1019 log("f_handle_crcx(): got Osmux CID: ", osmux_cid);
1020 if (osmux_cid != -1) {
1021 setverdict(fail, "MSC using unexpected CID " & int2str(osmux_cid) & " != -1");
1022 mtc.stop;
1023 }
1024
1025 osmux_cid := 0;
1026 mgcp_resp := ts_CRCX_ACK_osmux(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, osmux_cid, sdp);
1027 } else {
1028 mgcp_resp := ts_CRCX_ACK(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, sdp);
1029 }
1030
1031 f_mgcp_par_append(mgcp_resp.params, ts_MgcpParSpecEP(pars.mgcp_ep));
1032
1033 return mgcp_resp;
1034}
1035
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001036friend function f_create_rab(inout MgcpParameters pars) runs on ConnHdlr {
1037 f_rab_ass_req(pars);
1038 f_rab_ass_resp(pars);
1039}
1040
1041friend function f_rab_ass_req(inout MgcpParameters pars) runs on ConnHdlr {
Daniel Willmann19b8d902022-01-05 09:12:34 +01001042 var MgcpCommand mgcp_cmd;
1043 var RANAP_PDU tx;
1044 var template RAB_SetupOrModifyList rab_sml;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001045 timer T := 5.0;
1046
1047 /* Send RAB Assignment Request */
1048 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));
1049 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1050 BSSAP.send(tx);
1051 T.start;
1052
1053 /* Handle MGCP CRCX */
1054 alt {
1055 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
1056 log("CRCX1", mgcp_cmd);
1057 var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
1058 MGCP.send(valueof(mgcp_rsp));
1059 }
1060 [] T.timeout {
1061 setverdict(fail, "Timeout waiting for MGCP");
1062 }
1063 }
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001064 T.stop;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001065
1066 /* Expect RAB Assignment Request with IP/port from CRCX ACK via Iuh */
1067 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));
1068 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1069
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001070 f_rua_expect(tx);
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001071}
1072
1073friend function f_rab_ass_resp(inout MgcpParameters pars) runs on ConnHdlr {
1074 var MgcpCommand mgcp_cmd;
1075 var RANAP_PDU tx;
1076 var template RAB_SetupOrModifiedList rab_smdl;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001077
1078 /* Send back RAB Assignment Response via Iuh */
1079 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));
1080 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1081 RUA.send(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +01001082
1083 interleave {
1084 /* Expect MDCX with IP/port from RAB Assignment Response */
1085 [] MGCP.receive(tr_MDCX(tr_SDP(pars.hnb_rtp_ip, pars.hnb_rtp_port))) -> value mgcp_cmd {
1086 log("MDCX1", mgcp_cmd);
1087 /* Verify SDP of MDCX */
1088 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,
1089 { int2str(pars.rtp_payload_type) }, { valueof(ts_SDP_rtpmap(pars.rtp_payload_type, pars.rtp_sdp_format)), valueof(ts_SDP_ptime(20)) } ));
1090 var template MgcpResponse mgcp_rsp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, pars.mgw_conn_1.mgcp_connection_id, sdp);
1091 MGCP.send(valueof(mgcp_rsp));
1092 }
1093 /* Handle CRCX for second leg of endpoint, answer with IP/port */
1094 [] MGCP.receive(tr_CRCX(pars.mgcp_ep, tr_SDP(pars.cn_rtp_ip, pars.cn_rtp_port))) -> value mgcp_cmd {
1095 log("CRCX2", mgcp_cmd);
1096 /* Verify SDP of CRCX */
1097 var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
1098 MGCP.send(valueof(mgcp_rsp));
1099 }
1100 }
1101
1102 /* Expect RAB Assignment Response with IP/port from second CRCX ACK */
1103 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));
1104 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1105
Neels Hofmeyrdc416c92023-03-09 02:47:50 +01001106 f_bssap_expect(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +01001107}
1108
1109private altstep as_mgcp_dlcx(inout TestHdlrParams pars) runs on ConnHdlr {
1110 var MgcpCommand mgcp_cmd;
1111
1112 [] MGCP.receive(tr_DLCX(pars.mgcp_pars.mgcp_ep)) -> value mgcp_cmd {
1113 log("DLCX", mgcp_cmd);
1114 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
1115 pars.mgcp_pars.got_dlcx_count := pars.mgcp_pars.got_dlcx_count + 1;
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001116 if (pars.mgcp_pars.got_dlcx_count != pars.mgcp_pars.got_crcx_count) {
Daniel Willmann19b8d902022-01-05 09:12:34 +01001117 repeat;
1118 }
1119 setverdict(pass);
1120 }
1121}
1122
1123friend function f_tc_rab_assignment(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1124 var MgcpCommand mgcp_cmd;
1125 var RANAP_PDU tx;
1126 timer T := 5.0;
1127
1128 f_init_handler(pars);
1129 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1130
1131 tx := f_build_initial_ue(g_pars);
1132 f_iuh2iu_connect(tx);
1133
1134 f_create_rab(pars.mgcp_pars);
1135
1136 /* Send Iu Release */
1137 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1138 f_iu2iuh(tx);
1139
1140 T.start;
1141 alt {
1142 [] as_mgcp_dlcx(pars) {}
1143 [] T.timeout {
1144 setverdict(fail, "Timeout waiting for DLCX");
1145 }
1146 }
1147
1148 tx := valueof(ts_RANAP_IuReleaseComplete());
1149 f_iuh2iu(tx);
1150}
1151
1152testcase TC_rab_assignment() runs on test_CT {
1153 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001154 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001155 f_init();
1156 f_start_hnbs();
1157
1158 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assignment), t_pars(3));
1159 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001160
1161 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001162}
1163
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001164friend function f_tc_rab_assign_fail(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1165 var MgcpCommand mgcp_cmd;
1166 var RANAP_PDU tx;
1167 timer T := 5.0;
1168
1169 f_init_handler(pars);
1170 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1171
1172 tx := f_build_initial_ue(g_pars);
1173 f_iuh2iu_connect(tx);
1174
1175 f_rab_ass_req(pars.mgcp_pars);
1176
1177 /* Send RAB failed list in response */
1178 tx := valueof(ts_RANAP_RabAssResp(rab_fl := ts_RAB_FL(t_RAB_id(23), ts_RanapCause_om_intervention)));
1179 f_iuh2iu(tx);
1180
1181 T.start;
1182 alt {
1183 [] as_mgcp_dlcx(pars) {}
1184 [] T.timeout {
1185 setverdict(fail, "Timeout waiting for DLCX");
1186 }
1187 }
1188}
1189
1190testcase TC_rab_assign_fail() runs on test_CT {
1191 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001192 g_num_hnbs := 1;
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001193 f_init();
1194 f_start_hnbs();
1195
1196 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_fail), t_pars(4));
1197 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001198
1199 f_shutdown_helper();
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001200}
1201
Daniel Willmann19b8d902022-01-05 09:12:34 +01001202friend function f_tc_rab_release(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1203 var MgcpCommand mgcp_cmd;
1204 var RANAP_PDU tx;
1205 timer T := 15.0;
1206
1207 f_init_handler(pars);
1208 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1209
1210 tx := f_build_initial_ue(g_pars);
1211 f_iuh2iu_connect(tx);
1212
1213 f_create_rab(pars.mgcp_pars);
1214
1215 /* Send RAB Release */
Daniel Willmann9e789be2022-02-22 13:30:51 +01001216 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 +01001217 BSSAP.send(tx);
1218
1219 T.start;
1220
1221 alt {
1222 [] as_mgcp_dlcx(pars) {}
1223 [] T.timeout {
1224 setverdict(fail, "Timeout waiting for DLCX");
1225 }
1226 }
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001227 T.stop;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001228
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001229 f_rua_expect(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +01001230}
1231
1232testcase TC_rab_release() runs on test_CT {
1233 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001234 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001235 f_init();
1236 f_start_hnbs();
1237
1238 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_release), t_pars(5));
1239 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001240
1241 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001242}
1243
Daniel Willmann37c877f2022-02-22 16:47:06 +01001244friend function f_tc_rab_assign_mgcp_to(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1245 var MgcpCommand mgcp_cmd;
1246 var RANAP_PDU tx;
1247 var template RAB_SetupOrModifyList rab_sml;
1248 timer T := 15.0;
1249
1250 T.start;
1251 f_init_handler(pars);
1252 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1253
1254 tx := f_build_initial_ue(g_pars);
1255 f_iuh2iu_connect(tx);
1256
1257
1258 /* Send RAB Assignment Request */
1259 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));
1260 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1261 BSSAP.send(tx);
1262
1263 /* Ignore MGCP CRCX */
1264 alt {
1265 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
1266 log("Ignoreing CRCX1", mgcp_cmd);
1267 repeat;
1268 }
1269 [] BSSAP.receive(tr_RANAP_IuReleaseRequest(?)) { }
1270 [] T.timeout {
1271 setverdict(fail, "Timeout waiting for IuRelease");
1272 }
1273 }
1274
1275 /* Send Iu Release */
1276 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1277 f_iu2iuh(tx);
1278
1279 tx := valueof(ts_RANAP_IuReleaseComplete());
1280 f_iuh2iu(tx);
1281}
1282
1283testcase TC_rab_assign_mgcp_to() runs on test_CT {
1284 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001285 g_num_hnbs := 1;
Daniel Willmann37c877f2022-02-22 16:47:06 +01001286 f_init();
1287 f_start_hnbs();
1288
1289 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_mgcp_to), t_pars(6));
1290 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001291
1292 f_shutdown_helper();
Daniel Willmann37c877f2022-02-22 16:47:06 +01001293}
1294
Daniel Willmann19b8d902022-01-05 09:12:34 +01001295/* Create an Iuh connection; send InitialUE; transceive data both directions */
1296friend function f_tc_ranap_bidir(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1297 f_init_handler(pars);
1298
1299 /* HNB -> MSC: InitialUE */
1300 f_iuh2iu_connect(f_build_initial_ue(g_pars));
1301
1302 /* MSC <- HNB: DirectTransfer */
1303 f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1304 /* MSC -> HNB: DirectTransfer */
1305 f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1306
1307 /* HNB <- MSC: CommonID */
1308 f_iu2iuh(ts_RANAP_CommonId(hex2oct(pars.imsi)));
1309}
1310testcase TC_ranap_cs_bidir() runs on test_CT {
1311 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001312 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001313 f_init();
1314 f_start_hnbs();
1315
1316 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(3));
1317 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001318
1319 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001320}
1321testcase TC_ranap_ps_bidir() runs on test_CT {
1322 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001323 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001324 f_init();
1325 f_start_hnbs();
1326
1327 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(4, true));
1328 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001329
1330 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001331}
1332
1333
1334private function f_tc_ranap_mo_disconnect(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1335 f_init_handler(pars);
1336
1337 /* HNB -> MSC: InitialUE */
1338 f_iuh2iu_connect(f_build_initial_ue(g_pars));
1339
1340 /* MSC <- HNB: DirectTransfer */
1341 f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1342 /* MSC -> HNB: DirectTransfer */
1343 f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1344
1345 /* MSC <- HNB: RUA disconnect */
1346 f_iuh2iu_disconnect(ts_RANAP_IuReleaseComplete, RUA_IEs.Cause:{misc:=processing_overload});
1347}
1348testcase TC_ranap_cs_mo_disconnect() runs on test_CT {
1349 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001350 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001351 f_init();
1352 f_start_hnbs();
1353
1354 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(5));
1355 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001356
1357 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001358}
1359testcase TC_ranap_ps_mo_disconnect() runs on test_CT {
1360 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001361 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001362 f_init();
1363 f_start_hnbs();
1364
1365 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(6));
1366 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001367
1368 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001369}
1370
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001371type record FTeid {
1372 HostName addr,
1373 OCT4 teid
1374}
1375
1376type record FTeids {
1377 FTeid local,
1378 FTeid remote
1379}
Daniel Willmann19b8d902022-01-05 09:12:34 +01001380
1381
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001382/* 'local' and 'remote' refer to the GTP information from the UPF's point of view:
1383 * HNB UPF CN
1384 * access.remote <---> access.local | core.local <---> core.remote
1385 */
1386type record GtpParameters {
1387 FTeids core,
1388 FTeids access
1389}
1390
1391/* HNB UPF CN
1392 * access.remote <---> access.local | core.local <---> core.remote
1393 * 127.0.0.4 127.0.0.3 127.0.0.2 127.0.0.1
1394 * 0x44004400 0x30303030 0x22002200 0x10101010
1395 */
1396template GtpParameters t_GtpParameters := {
1397 core := {
1398 local := {
1399 addr := "127.0.0.2",
1400 teid := '22002200'O
1401 },
1402 remote := {
1403 addr := "127.0.0.1",
1404 teid := '10101010'O
1405 }
1406 },
1407 access := {
1408 local := {
1409 addr := "127.0.0.3",
1410 teid := '30303030'O
1411 },
1412 remote := {
1413 addr := "127.0.0.4",
1414 teid := '44004400'O
1415 }
1416 }
1417}
1418
Neels Hofmeyr65499282023-04-25 02:31:51 +02001419private 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 +01001420{
1421 var PDU_PFCP rx;
Neels Hofmeyr65499282023-04-25 02:31:51 +02001422 timer T := wait_time;
Neels Hofmeyr6bbfe052023-03-09 02:51:46 +01001423 T.start;
1424 alt {
1425 [] PFCP.receive(exp_rx) -> value rx {
1426 setverdict(pass);
1427 }
1428 [] PFCP.receive(PDU_PFCP:?) {
1429 setverdict(fail, "Got an unexpected PFCP message, was waiting for ", exp_rx);
1430 mtc.stop;
1431 }
1432 [] T.timeout {
1433 setverdict(fail, "Timeout waiting for PFCP ", exp_rx);
1434 mtc.stop;
1435 }
1436 }
1437 T.stop;
1438 return rx;
1439}
1440
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001441friend function f_tc_ps_rab_assignment_with_pfcp(charstring id, TestHdlrParams pars) runs on ConnHdlr {
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001442 var RANAP_PDU tx;
1443 var RANAP_PDU rx;
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001444
1445 f_init_handler(pars);
1446
1447 f_pfcp_register();
1448
1449 var PDU_PFCP m;
1450 var Node_ID upf_node_id := valueof(ts_PFCP_Node_ID_fqdn("\07osmocom\03org"));
1451
Neels Hofmeyr65499282023-04-25 02:31:51 +02001452 m := f_pfcp_expect(tr_PFCP_Assoc_Setup_Req(), wait_time := 15.0);
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001453 PFCP.send(ts_PFCP_Assoc_Setup_Resp(m.sequence_number, upf_node_id,
1454 ts_PFCP_Cause(REQUEST_ACCEPTED), 1234));
1455
1456 tx := f_build_initial_ue(g_pars);
1457 f_iuh2iu_connect(tx);
1458
1459 var GtpParameters gtp_pars := valueof(t_GtpParameters);
1460 var template RAB_SetupOrModifyList rab_sml;
1461
1462 /* Send RAB Assignment Request */
1463 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.remote.addr), gtp_pars.core.remote.teid);
1464 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1465 BSSAP.send(tx);
1466
1467 /* Expect PFCP Session Establishment Request. */
Neels Hofmeyr6bbfe052023-03-09 02:51:46 +01001468 m := f_pfcp_expect(tr_PFCP_Session_Est_Req());
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001469 var F_SEID hnbgw_f_seid := m.message_body.pfcp_session_establishment_request.CP_F_SEID;
1470 var PFCP_Session_Establishment_Request serq := m.message_body.pfcp_session_establishment_request;
1471
1472 /* Acting as UPF, invent a new PFCP SEID to send to HNBGW. Respond to the Session Establishment.
1473 * The PFCP response must have the same sequence_number as the request. */
Neels Hofmeyr1e311462023-01-11 01:19:12 +01001474 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 +02001475 var template PDU_PFCP r := ts_PFCP_Session_Est_Resp(m.sequence_number, upf_node_id, hnbgw_f_seid.seid);
1476 r.message_body.pfcp_session_establishment_response := {
1477 offending_ie := omit,
1478 UP_F_SEID := up_f_seid,
1479 created_PDR_list := {
1480 ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[0].grouped_ie.pdr_id,
1481 local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.core.local.teid,
Neels Hofmeyr1e311462023-01-11 01:19:12 +01001482 f_inet_addr(gtp_pars.core.local.addr))),
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001483 ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[1].grouped_ie.pdr_id,
1484 local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.access.local.teid,
Neels Hofmeyr1e311462023-01-11 01:19:12 +01001485 f_inet_addr(gtp_pars.access.local.addr)))
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001486 },
1487 load_control_information := omit,
1488 overload_control_information := omit,
1489 node_list := omit,
1490 failed_rule_id := omit,
1491 created_traffic_endpoint_list := omit
1492 };
1493 PFCP.send(r);
1494
1495 /* Expect on Iuh: RAB Assignment Request with IP/port from PFCP Session Est Resp */
1496 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.local.addr),
1497 gtp_pars.access.local.teid);
1498 rx := valueof(ts_RANAP_RabAssReq(rab_sml));
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001499 f_rua_expect(rx);
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001500
1501 /* Send back RAB Assignment Response via Iuh */
1502 var template RAB_SetupOrModifiedList rab_smdl;
1503 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.remote.addr),
1504 gtp_pars.access.remote.teid);
1505 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1506 RUA.send(tx);
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001507
Neels Hofmeyr6bbfe052023-03-09 02:51:46 +01001508 m := f_pfcp_expect(tr_PFCP_Session_Mod_Req(up_f_seid.seid));
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001509 r := ts_PFCP_Session_Mod_Resp(m.sequence_number, hnbgw_f_seid.seid);
1510 PFCP.send(r);
1511
1512 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 +01001513 f_bssap_expect(tr_RANAP_RabAssResp(rab_smdl));
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001514
1515 f_sleep(2.0);
1516 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1517 f_iu2iuh(tx);
1518
1519 tx := valueof(ts_RANAP_IuReleaseComplete());
1520 f_iuh2iu(tx);
1521
Neels Hofmeyr6bbfe052023-03-09 02:51:46 +01001522 m := f_pfcp_expect(tr_PFCP_Session_Del_Req(up_f_seid.seid));
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001523 PFCP.send(ts_PFCP_Session_Del_Resp(m.sequence_number, hnbgw_f_seid.seid));
1524
1525 f_sleep(2.0);
1526}
1527
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001528testcase TC_ps_rab_assignment_with_pfcp() runs on test_CT {
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001529 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001530 g_num_hnbs := 1;
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001531 f_init();
1532 f_start_hnbs();
1533 f_sleep(1.0);
1534
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001535 vc_conn := f_start_handler_with_pars(refers(f_tc_ps_rab_assignment_with_pfcp), t_pars(7, ps_domain := true));
1536 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001537
1538 f_shutdown_helper();
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001539}
1540
1541altstep as_disallow_pfcp() runs on ConnHdlr {
1542 [] PFCP.receive(PDU_PFCP:?) {
1543 setverdict(fail, "Received PFCP message, but no PFCP communication expected");
1544 mtc.stop;
1545 }
1546}
1547
1548friend function f_tc_ps_rab_assignment_without_pfcp(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1549 var RANAP_PDU tx;
1550 var RANAP_PDU rx;
1551 timer T := 5.0;
1552
1553 f_init_handler(pars);
1554
1555 f_pfcp_register();
1556 activate(as_disallow_pfcp());
1557
1558 tx := f_build_initial_ue(g_pars);
1559 f_iuh2iu_connect(tx);
1560
1561 var GtpParameters gtp_pars := valueof(t_GtpParameters);
1562 var template RAB_SetupOrModifyList rab_sml;
1563
1564 /* Send RAB Assignment Request */
1565 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.remote.addr), gtp_pars.core.remote.teid);
1566 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1567 BSSAP.send(tx);
1568
1569 /* Expect on Iuh: unmodified RAB Assignment Request */
1570 rx := valueof(ts_RANAP_RabAssReq(rab_sml));
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001571 f_rua_expect(rx);
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001572
1573 /* Send back RAB Assignment Response via Iuh */
1574 var template RAB_SetupOrModifiedList rab_smdl;
1575 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.remote.addr),
1576 gtp_pars.access.remote.teid);
1577 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1578 RUA.send(tx);
1579
1580 /* Expect on IuPS: unmodified RAB Assignment Response */
Neels Hofmeyrdc416c92023-03-09 02:47:50 +01001581 f_bssap_expect(tr_RANAP_RabAssResp(rab_smdl));
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001582
1583 f_sleep(2.0);
1584 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1585 f_iu2iuh(tx);
1586
1587 tx := valueof(ts_RANAP_IuReleaseComplete());
1588 f_iuh2iu(tx);
1589
1590 f_sleep(2.0);
1591}
1592
1593testcase TC_ps_rab_assignment_without_pfcp() runs on test_CT {
1594 var ConnHdlr vc_conn;
1595 f_init();
1596 f_start_hnbs();
1597 f_sleep(1.0);
1598
1599 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 +02001600 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001601
1602 f_shutdown_helper();
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001603}
Daniel Willmann19b8d902022-01-05 09:12:34 +01001604
1605control {
1606 execute(TC_hnb_register());
Daniel Willmannc79679a2022-08-23 17:48:39 +02001607 execute(TC_hnb_register_duplicate());
Pau Espin Pedrolacf4f222022-09-27 14:33:40 +02001608 execute(TC_hnb_register_duplicate_reuse_sctp_assoc());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001609 execute(TC_ranap_cs_initial_ue());
1610 execute(TC_ranap_ps_initial_ue());
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02001611 execute(TC_ranap_cs_initial_ue_empty_cr());
1612 execute(TC_ranap_ps_initial_ue_empty_cr());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001613 execute(TC_ranap_cs_bidir());
1614 execute(TC_ranap_ps_bidir());
1615 execute(TC_rab_assignment());
1616 execute(TC_rab_release());
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001617 execute(TC_rab_assign_fail());
Daniel Willmann37c877f2022-02-22 16:47:06 +01001618 execute(TC_rab_assign_mgcp_to());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001619 execute(TC_ranap_cs_mo_disconnect());
1620 execute(TC_ranap_ps_mo_disconnect());
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001621
1622 if (mp_enable_pfcp_tests) {
1623 execute(TC_ps_rab_assignment_with_pfcp());
1624 } else {
1625 execute(TC_ps_rab_assignment_without_pfcp());
1626 }
Pau Espin Pedrolf0b9fa02022-09-12 13:31:07 +02001627
1628 /* Run at the end since it makes osmo-hnbgw <= 1.3.0 crash: OS#5676 */
1629 execute(TC_hnb_reregister_reuse_sctp_assoc());
Daniel Willmann19b8d902022-01-05 09:12:34 +01001630}
1631
1632}