blob: 67411ff8e3b416258075f7e79dcff8d486f6cf9c [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;
Neels Hofmeyrb1bf16d2023-06-27 02:10:04 +020049import from RANAP_CodecPort all;
Daniel Willmann19b8d902022-01-05 09:12:34 +010050
51import from RAN_Adapter all;
Daniel Willmann19b8d902022-01-05 09:12:34 +010052import from RAN_Emulation all;
53
54import from MGCP_Emulation all;
55import from MGCP_Types all;
56import from MGCP_Templates all;
57import from MGCP_CodecPort all;
58import from SDP_Types all;
59
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +020060import from PFCP_Types all;
61import from PFCP_Emulation all;
62import from PFCP_Templates all;
63import from PFCP_CodecPort all;
64
Neels Hofmeyr75d905b2023-04-27 00:30:25 +020065import from TCCConversion_Functions all;
Neels Hofmeyr7a48df12023-04-20 20:43:43 +020066import from MobileL3_Types all;
Neels Hofmeyr7d0e6802023-04-20 20:43:55 +020067import from MobileL3_CommonIE_Types all;
68import from MobileL3_GMM_SM_Types all;
Neels Hofmeyr7a48df12023-04-20 20:43:43 +020069import from L3_Templates all;
Neels Hofmeyr7d0e6802023-04-20 20:43:55 +020070import from L3_Common all;
Neels Hofmeyr7a48df12023-04-20 20:43:43 +020071
Neels Hofmeyrb1bf16d2023-06-27 02:10:04 +020072import from SCCPasp_Types all;
73
Neels Hofmeyr7a48df12023-04-20 20:43:43 +020074const integer NUM_MSC := 4;
75const integer NUM_SGSN := 4;
76
77const integer FIRST_MSC_IDX := 0;
78const integer FIRST_SGSN_IDX := NUM_MSC;
Neels Hofmeyr75d905b2023-04-27 00:30:25 +020079
Daniel Willmann19b8d902022-01-05 09:12:34 +010080modulepar {
81 /* IP address at which the HNodeB can be reached */
82 charstring mp_hnodeb_ip := "127.0.0.1";
83 integer mp_hnodeb_port := -1;
84
85 /* IP address at which the test binds */
86 charstring mp_hnbgw_ip := "127.0.0.1";
87 integer mp_hnbgw_iuh_port := 29169;
Neels Hofmeyrffcb8892023-06-27 01:09:57 +020088 integer mp_hnbgw_ctrl_port := 4262;
Daniel Willmann19b8d902022-01-05 09:12:34 +010089
90 charstring mp_mgw_ip := "127.0.0.1";
91 integer mp_mgw_port := 2427;
92
Neels Hofmeyr7a48df12023-04-20 20:43:43 +020093 RAN_Configurations mp_cn_cfg := {
94 /* MSCs (NUM_MSC entries) */
95 {
96 transport := RANAP_TRANSPORT_IuCS,
97 sccp_service_type := "mtp3_itu",
98 sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
99 own_pc := 188, /* 0.23.4 first MSC emulation */
100 own_ssn := 142,
101 peer_pc := 189, /* 0.23.5 osmo-hnbgw */
102 peer_ssn := 142,
103 sio := '83'O,
104 rctx := 1
105 },
106 {
107 transport := RANAP_TRANSPORT_IuCS,
108 sccp_service_type := "mtp3_itu",
109 sctp_addr := { 23907, "127.0.0.1", 2905, "127.0.0.1" },
110 own_pc := 2, /* 0.0.2 second MSC emulation */
111 own_ssn := 142,
112 peer_pc := 189, /* 0.23.5 osmo-hnbgw */
113 peer_ssn := 142,
114 sio := '83'O,
115 rctx := 3
116 },
117 {
118 transport := RANAP_TRANSPORT_IuCS,
119 sccp_service_type := "mtp3_itu",
120 sctp_addr := { 23909, "127.0.0.1", 2905, "127.0.0.1" },
121 own_pc := 3, /* 0.0.3 third MSC emulation */
122 own_ssn := 142,
123 peer_pc := 189, /* 0.23.5 osmo-hnbgw */
124 peer_ssn := 142,
125 sio := '83'O,
126 rctx := 5
127 },
128 {
129 transport := RANAP_TRANSPORT_IuCS,
130 sccp_service_type := "mtp3_itu",
131 sctp_addr := { 23911, "127.0.0.1", 2905, "127.0.0.1" },
132 own_pc := 4, /* 0.0.4 fourth MSC emulation */
133 own_ssn := 142,
134 peer_pc := 189, /* 0.23.5 osmo-hnbgw */
135 peer_ssn := 142,
136 sio := '83'O,
137 rctx := 7
138 },
139
140 /* SGSNs (NUM_SGSN entries) */
141 {
142 transport := RANAP_TRANSPORT_IuCS,
143 sccp_service_type := "mtp3_itu",
144 sctp_addr := { /* local */ 23906, "127.0.0.1", /* remote */ 2905, "127.0.0.1" },
145 own_pc := 185, /* 0.23.1 first SGSN emulation */
146 own_ssn := 142,
147 peer_pc := 189, /* 2237, 1.23.5 osmo-hnbgw */
148 peer_ssn := 142,
149 sio := '83'O,
150 rctx := 2
151 },
152 {
153 transport := RANAP_TRANSPORT_IuCS,
154 sccp_service_type := "mtp3_itu",
155 sctp_addr := { /* local */ 23908, "127.0.0.1", /* remote */ 2905, "127.0.0.1" },
156 own_pc := 10, /* 0.1.2 second SGSN emulation */
157 own_ssn := 142,
158 peer_pc := 189, /* 2237, 1.23.5 osmo-hnbgw */
159 peer_ssn := 142,
160 sio := '83'O,
161 rctx := 4
162 },
163 {
164 transport := RANAP_TRANSPORT_IuCS,
165 sccp_service_type := "mtp3_itu",
166 sctp_addr := { /* local */ 23910, "127.0.0.1", /* remote */ 2905, "127.0.0.1" },
167 own_pc := 11, /* 0.1.3 third SGSN emulation */
168 own_ssn := 142,
169 peer_pc := 189, /* 2237, 1.23.5 osmo-hnbgw */
170 peer_ssn := 142,
171 sio := '83'O,
172 rctx := 6
173 },
174 {
175 transport := RANAP_TRANSPORT_IuCS,
176 sccp_service_type := "mtp3_itu",
177 sctp_addr := { /* local */ 23912, "127.0.0.1", /* remote */ 2905, "127.0.0.1" },
178 own_pc := 12, /* 0.1.4 fourth SGSN emulation */
179 own_ssn := 142,
180 peer_pc := 189, /* 2237, 1.23.5 osmo-hnbgw */
181 peer_ssn := 142,
182 sio := '83'O,
183 rctx := 8
184 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100185 };
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200186
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +0200187 boolean mp_enable_pfcp_tests := false;
188
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200189 /* IP address at which we listen for PFCP to emulate a UPF in ttcn3 */
190 charstring mp_pfcp_ip_local := "127.0.0.1";
191
192 /* IP address from which the SUT (osmo-hnbgw) sends PFCP requests, and to which the ttcn3 UPF emulation sends
193 * PFCP responses. */
194 charstring mp_pfcp_ip_remote := "127.0.0.2";
Pau Espin Pedrol6c87ad92023-07-18 11:24:25 +0200195
196 boolean mp_validate_talloc_asn1 := true;
Pau Espin Pedrolee4ce862023-11-02 12:23:25 +0100197
198 /* The X31 timer configured at osmo-hnbgw (seconds). This provided an idea on
199 * minimum time the test must wait to consider this timer triggered */
200 integer mp_hnbgw_timer_x31 := 5;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100201}
202
203function MSC_UnitdataCallback(RANAP_PDU ranap) runs on RAN_Emulation_CT return template RANAP_PDU {
204 // TODO: Actually implement unitdata handling
Neels Hofmeyrcf6dc492023-06-27 00:51:08 +0200205 return omit;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100206}
207
208const RanOps MSC_RanOps := {
209 ranap_create_cb := refers(RAN_Emulation.RanapExpectedCreateCallback),
210 ranap_unitdata_cb := refers(MSC_UnitdataCallback),
211 ps_domain := false,
212 decode_dtap := false,
213 role_ms := false,
214 protocol := RAN_PROTOCOL_RANAP,
215 transport := RANAP_TRANSPORT_IuCS,
216 use_osmux := false,
Eric Wild6e511ce2022-04-02 21:35:56 +0200217 bssap_reset_retries := 1,
Daniel Willmann19b8d902022-01-05 09:12:34 +0100218 sccp_addr_local := omit,
219 sccp_addr_peer := omit
220}
221
222type record CrcxResponse {
223 integer resp,
224 HostName mgw_rtp_ip,
225 PortNumber mgw_rtp_port,
226 MgcpConnectionId mgcp_connection_id
227}
228type record MgcpParameters {
229 integer got_crcx_count,
230 integer got_dlcx_count,
231 MgcpCallId mgcp_call_id optional,
232 MgcpEndpoint mgcp_ep,
Pau Espin Pedrolb85ac2f2023-11-29 15:48:57 +0100233 CrcxResponse mgw_conn_ran,
234 CrcxResponse mgw_conn_cn,
Daniel Willmann19b8d902022-01-05 09:12:34 +0100235 uint7_t rtp_payload_type,
236 charstring rtp_sdp_format,
237 HostName hnb_rtp_ip,
238 PortNumber hnb_rtp_port,
239 HostName cn_rtp_ip,
240 PortNumber cn_rtp_port,
241 boolean use_osmux,
242 integer got_osmux_count
243}
244
245template (value) MgcpParameters t_MgcpParams := {
246 got_crcx_count := 0,
247 got_dlcx_count := 0,
248 mgcp_call_id := omit,
249 mgcp_ep := "rtpbridge/1@mgw",
Pau Espin Pedrolb85ac2f2023-11-29 15:48:57 +0100250 mgw_conn_ran := {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100251 resp := 1,
252 mgw_rtp_ip := "127.1.2.1",
253 mgw_rtp_port := 10000,
254 mgcp_connection_id := '11111'H
255 },
Pau Espin Pedrolb85ac2f2023-11-29 15:48:57 +0100256 mgw_conn_cn := {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100257 resp := 1,
258 mgw_rtp_ip := "127.1.2.2",
259 mgw_rtp_port := 20000,
260 mgcp_connection_id := '22222'H
261 },
Philipp Maier6c5ba0752023-07-04 16:53:40 +0200262 rtp_payload_type := 112,
263 rtp_sdp_format := "VND.3GPP.IUFP",
Daniel Willmann19b8d902022-01-05 09:12:34 +0100264 hnb_rtp_ip := "127.1.1.1",
265 hnb_rtp_port := 10001,
266 cn_rtp_ip := "127.1.3.1",
267 cn_rtp_port := 20001,
268 use_osmux := false,
269 got_osmux_count := 0
270}
271
272type record TestHdlrParams {
273 integer hnb_idx,
Neels Hofmeyr7a48df12023-04-20 20:43:43 +0200274 /* cn_idx indicates which CN link from g_cn[] to connect to the test component.
275 * See also f_cn_idx(). */
276 integer cn_idx,
Daniel Willmann19b8d902022-01-05 09:12:34 +0100277 hexstring imsi,
278 boolean ps_domain,
279 MgcpParameters mgcp_pars optional,
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200280 HnbConfig hnb optional,
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200281 boolean expect_separate_sccp_cr,
282 integer tx_sccp_cr_data_len,
Neels Hofmeyr7d0e6802023-04-20 20:43:55 +0200283 charstring pfcp_local_addr,
Neels Hofmeyrb1bf16d2023-06-27 02:10:04 +0200284 octetstring nas_pdu optional,
285 /* local and remote SCCP addresses, used in TC_mscpool_paging_* */
286 SCCP_PAR_Address sccp_addr_msc optional,
287 SCCP_PAR_Address sccp_addr_hnbgw optional
Daniel Willmann19b8d902022-01-05 09:12:34 +0100288}
289
290/* We extend:
291 * RUA_ConnHdlr (for the Iuh side, emulating the HNB)
292 * RAN_ConnHdlr (for the Iu side, emulating the MSC)
293 * MGCP_ConnHdlr (for the MGCP side, emulating the MGW)
294 */
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200295type component ConnHdlr extends RAN_ConnHdlr, MGCP_ConnHdlr, RUA_ConnHdlr, PFCP_ConnHdlr {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100296 var integer g_sccp_conn_id;
297 var TestHdlrParams g_pars;
298 timer g_Tguard;
Neels Hofmeyr72a8d622023-01-26 13:47:01 +0100299
300 port TELNETasp_PT HNBGWVTY;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100301}
302
303
304const MGCPOps MSC_MGCPOps := {
305 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
306 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
307}
308
309function f_create_ranap_exp(octetstring l3_enc) runs on ConnHdlr {
310 BSSAP_PROC.call(RAN_register:{l3_enc, self}) {
311 [] BSSAP_PROC.getreply(RAN_register:{?, ?}) {};
312 }
313}
314
315
Daniel Willmannc79679a2022-08-23 17:48:39 +0200316const integer NUM_HNB := 2;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100317
Daniel Willmann19b8d902022-01-05 09:12:34 +0100318type record HnbConfig {
319 LocationAreaIdentification lai,
320 integer sac
321}
322
323type component test_CT extends CTRL_Adapter_CT {
324 var boolean g_initialized := false;
325
326 /********************* Iu side */
Neels Hofmeyr7a48df12023-04-20 20:43:43 +0200327 var RAN_Adapter g_cn[NUM_MSC + NUM_SGSN];
Daniel Willmann19b8d902022-01-05 09:12:34 +0100328
329 /********************* Iuh side */
330 var HnbConfig g_hnb_cfg[NUM_HNB];
331 var Iuh_Emulation_CT vc_Iuh[NUM_HNB];
332 var RUA_Emulation_CT vc_RUA[NUM_HNB];
333 port HNBAP_PT HNBAP[NUM_HNB];
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200334 /* Number of HNBs to be used/started by the test */
335 var integer g_num_hnbs := NUM_HNB;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100336
337 var MGCP_Emulation_CT vc_MGCP;
338 port TELNETasp_PT HNBGWVTY;
339 /* global test case guard timer (actual timeout value is set in f_init()) */
340 timer T_guard := 30.0;
Neels Hofmeyr7d0e6802023-04-20 20:43:55 +0200341
342 /* The cnlink type 'msc' or 'sgsn', to be used in CTRL commands to obtain counters */
343 var charstring g_ctr_cn_node_name;
344 /* Counter state */
345 var CounterNameValsList g_ctr_cn;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100346}
347
348/* global altstep for global guard timer; */
349altstep as_Tguard() runs on test_CT {
350 [] T_guard.timeout {
351 setverdict(fail, "Timeout of T_guard");
352 mtc.stop;
353 }
354}
355
Daniel Willmann19b8d902022-01-05 09:12:34 +0100356function f_init_vty(charstring id := "foo") runs on test_CT {
357 if (HNBGWVTY.checkstate("Mapped")) {
358 /* skip initialization if already executed once */
359 return;
360 }
361 map(self:HNBGWVTY, system:HNBGWVTY);
362 f_vty_set_prompts(HNBGWVTY);
363 f_vty_transceive(HNBGWVTY, "enable");
364}
365
366function f_init_mgcp(charstring id) runs on test_CT {
367 id := id & "-MGCP";
368 var MGCPOps ops := {
369 create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
370 unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
371 }
372 var MGCP_conn_parameters pars := {
373 callagent_ip := mp_hnbgw_ip,
374 callagent_udp_port := -1,
375 mgw_ip := mp_mgw_ip,
376 mgw_udp_port := mp_mgw_port,
377 multi_conn_mode := false
378 }
379
380 vc_MGCP := MGCP_Emulation_CT.create(id);
381 map(vc_MGCP:MGCP, system:MGCP_CODEC_PT);
382 vc_MGCP.start(MGCP_Emulation.main(ops, pars, id));
383}
384
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200385function f_init_pfcp(charstring id) runs on ConnHdlr {
386 id := id & "-PFCP";
387
388 var PFCP_Emulation_Cfg pfcp_cfg := {
389 pfcp_bind_ip := mp_pfcp_ip_local,
390 pfcp_bind_port := PFCP_PORT,
391 pfcp_remote_ip := mp_pfcp_ip_remote,
392 pfcp_remote_port := PFCP_PORT,
393 role := UPF
394 };
395
396 vc_PFCP := PFCP_Emulation_CT.create(id) alive;
397 connect(self:PFCP, vc_PFCP:CLIENT);
398 connect(self:PFCP_PROC, vc_PFCP:CLIENT_PROC);
399 vc_PFCP.start(PFCP_Emulation.main(pfcp_cfg));
400}
401
Daniel Willmann19b8d902022-01-05 09:12:34 +0100402function f_init_hnodeb(charstring id, integer hnb_idx, RuaOps rua_ops) runs on test_CT {
403 id := id & "-Iuh" & int2str(hnb_idx);
404
405 /* Iuh lower layer (RUA/HNBAP demux) */
406 var Iuh_conn_parameters iuh_pars;
407 iuh_pars.remote_ip := mp_hnbgw_ip;
408 iuh_pars.remote_sctp_port := mp_hnbgw_iuh_port;
409 iuh_pars.local_ip := mp_hnodeb_ip;
410 iuh_pars.local_sctp_port := mp_hnodeb_port + hnb_idx;
411 vc_Iuh[hnb_idx] := Iuh_Emulation_CT.create(id);
412 connect(self:HNBAP[hnb_idx], vc_Iuh[hnb_idx]:HNBAP);
413
414 vc_RUA[hnb_idx] := RUA_Emulation_CT.create(id & "-RUA");
415 connect(vc_RUA[hnb_idx]:RUA, vc_Iuh[hnb_idx]:RUA);
416
417 /* Start Iuh side components */
418 vc_Iuh[hnb_idx].start(Iuh_Emulation.main(iuh_pars, id));
419 vc_RUA[hnb_idx].start(RUA_Emulation.main(rua_ops, id & "-RUA"));
420}
421
Neels Hofmeyr3d5a0da2023-06-27 00:57:46 +0200422private type record of boolean BooleanList;
423
424private function f_vty_cnlink_allow_attach(TELNETasp_PT pt, boolean ps_domain, BooleanList allow_attach_list)
425{
426 var charstring config := f_vty_transceive_ret(pt, "show running-config");
427
428 var charstring msc_sgsn;
429 if (ps_domain) {
430 msc_sgsn := "sgsn";
431 } else {
432 msc_sgsn := "msc";
433 }
434
435 f_vty_enter_config(pt);
436 for (var integer cn_nr := 0; cn_nr < sizeof(allow_attach_list); cn_nr := cn_nr+1) {
437 if (f_strstr(config, "\n" & msc_sgsn & " " & int2str(cn_nr) & "\n") < 0) {
438 /* There is no 'msc N' for this cn_nr in the running config, so don't create an empty cn by
439 * stepping into that config node. */
440 log(msc_sgsn, cn_nr, " is not configured, skipping");
441 continue;
442 }
443 f_vty_transceive(pt, msc_sgsn & " " & int2str(cn_nr));
444
445 if (allow_attach_list[cn_nr]) {
446 /* strict := false: ignore if osmo-hnbgw does not support this config option (latest build) */
447 f_vty_transceive(pt, "allow-attach", strict := false);
448 } else {
449 f_vty_transceive(pt, "no allow-attach", strict := false);
450 }
451 f_vty_transceive(pt, "exit");
452 }
453 f_vty_transceive(pt, "exit");
454}
455
456/* Start RAN adapter for CN link N.
457 * e.g. link for 'msc 0' = (ps_domain := false, cn_nr := 0)
458 * link for 'sgsn 3' = (ps_domain := true, cn_nr := 3)
459 */
460private function f_cn_nr_init(boolean ps_domain, integer cn_nr) runs on test_CT {
461 var RanOps ranops := MSC_RanOps;
462 ranops.ps_domain := ps_domain;
463 var integer cn_idx := f_cn_idx(ps_domain, cn_nr);
464 var charstring msc_sgsn := "msc";
465 if (ps_domain) {
466 msc_sgsn := "sgsn";
467 }
468 f_ran_adapter_init(g_cn[cn_idx], mp_cn_cfg[cn_idx], "HNBGW_Test." & msc_sgsn & int2str(cn_nr), ranops);
469 f_ran_adapter_start(g_cn[cn_idx]);
470}
471
472private function f_cn_idx_disconnect(integer cn_idx) runs on test_CT {
473 f_ran_adapter_cleanup(g_cn[cn_idx]);
474}
475
Daniel Willmann19b8d902022-01-05 09:12:34 +0100476/* global initialization function */
Neels Hofmeyr333ea392023-06-27 00:58:05 +0200477function f_init(charstring id := "HNBGW", float guard_timeout := 30.0, integer nr_msc := 1, integer nr_sgsn := 1,
478 boolean start_hnb := true) runs on test_CT {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100479
Daniel Willmann19b8d902022-01-05 09:12:34 +0100480 T_guard.start(guard_timeout);
481 activate(as_Tguard());
482
483 /* RUA/RANAP emulation on top of lower-layer Iuh */
484 var RuaOps rua_ops := {
485 create_cb := refers(IuhRanapCreateCallback),
486 unitdata_cb := refers(IuhRanapUnitdataCallback)
487 };
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200488 for (var integer i := 0; i < g_num_hnbs; i := i+1) {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200489 g_hnb_cfg[i] := {
490 lai := {
Neels Hofmeyr497216f2023-06-27 00:59:26 +0200491 mcc_mnc := '00F110'H,
Daniel Willmannc79679a2022-08-23 17:48:39 +0200492 lac := 2342 + i
493 },
494 sac := 55
495 };
Daniel Willmann19b8d902022-01-05 09:12:34 +0100496 f_init_hnodeb(testcasename(), i, rua_ops);
497 }
498
Neels Hofmeyr3d5a0da2023-06-27 00:57:46 +0200499 f_init_vty("VirtHNBGW");
Neels Hofmeyrffcb8892023-06-27 01:09:57 +0200500 f_ipa_ctrl_start_client(mp_hnbgw_ip, mp_hnbgw_ctrl_port);
501
Daniel Willmann19b8d902022-01-05 09:12:34 +0100502 /* MSC emulation */
Neels Hofmeyr3d5a0da2023-06-27 00:57:46 +0200503
504 /* Make sure each MSC's internal state is "DISCONNECTED" at first */
505 for (var integer i := 0; i < NUM_MSC; i := i + 1) {
506 f_vty_transceive(HNBGWVTY, "msc " & int2str(i) & " ranap reset", strict := false);
507 }
508
509 var BooleanList allow_attach := { false, false, false, false };
Neels Hofmeyr7a48df12023-04-20 20:43:43 +0200510 for (var integer i := 0; i < nr_msc; i := i + 1) {
511 var integer cn_idx := FIRST_MSC_IDX + i;
Neels Hofmeyr3d5a0da2023-06-27 00:57:46 +0200512 allow_attach[i] := true;
513 f_cn_nr_init(ps_domain := false, cn_nr := i);
Neels Hofmeyr7a48df12023-04-20 20:43:43 +0200514 }
Neels Hofmeyr3d5a0da2023-06-27 00:57:46 +0200515 /* start the test with exactly all enabled MSCs allowed to attach */
516 f_vty_cnlink_allow_attach(HNBGWVTY, false, allow_attach);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100517
518 /* SGSN emulation */
Neels Hofmeyr3d5a0da2023-06-27 00:57:46 +0200519
520 /* Make sure each SGSN's internal state is "DISCONNECTED" at first */
521 for (var integer i := 0; i < NUM_SGSN; i := i + 1) {
522 f_vty_transceive(HNBGWVTY, "sgsn " & int2str(i) & " ranap reset", strict := false);
Neels Hofmeyr7a48df12023-04-20 20:43:43 +0200523 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100524
Neels Hofmeyr3d5a0da2023-06-27 00:57:46 +0200525 allow_attach := { false, false, false, false };
526 for (var integer i := 0; i < nr_sgsn; i := i + 1) {
527 var integer cn_idx := FIRST_SGSN_IDX + i;
528 allow_attach[i] := true;
529 f_cn_nr_init(ps_domain := true, cn_nr := i);
530 }
531 f_vty_cnlink_allow_attach(HNBGWVTY, true, allow_attach);
532
Daniel Willmann19b8d902022-01-05 09:12:34 +0100533 f_init_mgcp(id);
Neels Hofmeyr333ea392023-06-27 00:58:05 +0200534
535 if (start_hnb) {
536 f_start_hnbs();
537 }
Neels Hofmeyr467eb7e2023-08-10 03:38:07 +0200538
539 /* Sometimes, the RUA InitialUE-Message from a test happens too quickly, before the RANAP RESET from
540 * RAN_Emulation is through, after above f_cn_nr_init(). In the pcap it seems to be a matter of 50 ms. Give some
541 * grace. */
542 f_sleep(1.0);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100543}
544
545friend function f_shutdown_helper() runs on test_CT {
Pau Espin Pedrol6c87ad92023-07-18 11:24:25 +0200546 if (mp_validate_talloc_asn1) {
547 f_verify_talloc_bytes(HNBGWVTY, {"asn1_context"}, 1);
548 }
Neels Hofmeyr75d905b2023-04-27 00:30:25 +0200549
Daniel Willmann19b8d902022-01-05 09:12:34 +0100550 all component.stop;
551 setverdict(pass);
552 mtc.stop;
553}
554
555/* helper function to start all of the simulated hNodeBs */
556function f_start_hnbs() runs on test_CT {
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200557 for (var integer i:= 0; i < g_num_hnbs; i := i+1) {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200558 f_hnbap_register(i, i);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100559 }
560}
561
562/***********************************************************************
563 * code running in test_CT, preparing start of per-UE ConnHdlr
564 ***********************************************************************/
565
566/* inbound RUA connection establishment on Iuh side */
567function IuhRanapCreateCallback(ContextId context_id, RUA_IEs.CN_DomainIndicator domain, charstring id)
568runs on RUA_Emulation_CT return RUA_ConnHdlr {
569 log("CreateCallback");
570 return null;
571}
572
573/* inbound RUA connectionless data on Iuh side */
574function IuhRanapUnitdataCallback(RANAP_PDU ranap)
575runs on RUA_Emulation_CT return template RANAP_PDU {
576 log("UnitdataCallback");
577 return omit;
578}
579
580private function f_start_handler_create(TestHdlrParams pars) runs on test_CT return ConnHdlr {
581 var ConnHdlr vc_conn;
582 var charstring id := testcasename() & int2str(pars.hnb_idx);
583
584 vc_conn := ConnHdlr.create(id);
585
586 /* Iuh RUA part */
587 connect(vc_conn:RUA, vc_RUA[pars.hnb_idx]:CLIENT);
588
Neels Hofmeyr7a48df12023-04-20 20:43:43 +0200589 /* MSC or SGSN */
590 connect(vc_conn:BSSAP, g_cn[pars.cn_idx].vc_RAN:CLIENT);
591 connect(vc_conn:BSSAP_PROC, g_cn[pars.cn_idx].vc_RAN:PROC);
592
Daniel Willmann19b8d902022-01-05 09:12:34 +0100593 /* MGCP part */
594 connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
595 connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
596
597 return vc_conn;
598}
599
600private function f_start_handler_run(ConnHdlr vc_conn, void_fn fn, TestHdlrParams pars) runs on test_CT {
601 var charstring id := testcasename(); // & int2str(pars.ran_idx);
602 /* We cannot use vc_conn.start(f_init_handler(fn, id, pars)); as we cannot have
603 * a stand-alone 'derefers()' call, see https://www.eclipse.org/forums/index.php/t/1091364/ */
604 pars.hnb := g_hnb_cfg[pars.hnb_idx];
605 pars.mgcp_pars := valueof(t_MgcpParams);
606 vc_conn.start(derefers(fn)(id, pars));
607}
608
609function f_start_handler_with_pars(void_fn fn, template (value) TestHdlrParams pars)
610runs on test_CT return ConnHdlr {
611 var ConnHdlr vc_conn;
612 vc_conn := f_start_handler_create(valueof(pars));
613 f_start_handler_run(vc_conn, fn, valueof(pars));
614 return vc_conn;
615}
616
617/***********************************************************************
618 * code running inside per-UE ConnHdlr
619 ***********************************************************************/
620
621type function void_fn(charstring id, TestHdlrParams pars) runs on ConnHdlr;
622
623function f_init_handler(TestHdlrParams pars, float t_guard := 20.0) runs on ConnHdlr {
624 /* make parameters available via component variable */
625 g_pars := pars;
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +0200626
627 f_init_pfcp(testcasename());
628
Daniel Willmann19b8d902022-01-05 09:12:34 +0100629 /* start guard timer and activate it as default */
630 g_Tguard.start(t_guard);
631 activate(as_Tguard_ConnHdlr());
632
Neels Hofmeyr72a8d622023-01-26 13:47:01 +0100633 map(self:HNBGWVTY, system:HNBGWVTY);
634 f_vty_set_prompts(HNBGWVTY);
635 f_vty_transceive(HNBGWVTY, "enable");
636
Daniel Willmann19b8d902022-01-05 09:12:34 +0100637 /* TODO: CTRL? */
Neels Hofmeyr59517222023-06-23 04:46:59 +0200638
639 f_sleep(1.0);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100640}
641
642/* global altstep for global guard timer; */
643private altstep as_Tguard_ConnHdlr() runs on ConnHdlr {
644 [] g_Tguard.timeout {
645 setverdict(fail, "Timeout of T_guard");
646 mtc.stop;
647 }
648}
649
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100650private function f_bssap_expect(template (present) RANAP_PDU exp_rx) runs on ConnHdlr return RANAP_PDU
651{
652 var RANAP_PDU rx;
653 timer T := 5.0;
654 T.start;
655 alt {
656 [] BSSAP.receive(exp_rx) -> value rx {
657 setverdict(pass);
658 }
659 [] BSSAP.receive(RANAP_PDU:?) {
660 setverdict(fail, "Got an unexpected RANAP message on BSSAP port, was waiting for ", exp_rx);
661 mtc.stop;
662 }
663 [] T.timeout {
664 setverdict(fail, "Timeout waiting for RANAP on BSSAP port: ", exp_rx);
665 mtc.stop;
666 }
667 }
668 T.stop;
669 return rx;
670}
671
Daniel Willmann19b8d902022-01-05 09:12:34 +0100672/* send RANAP on Iuh and expect it to show up on Iu */
673function f_iuh2iu(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
674runs on ConnHdlr return RANAP_PDU {
675 var RANAP_PDU rx;
676 timer T := 5.0;
677
678 if (istemplatekind(exp_rx, "omit")) {
679 exp_rx := tx;
680 }
681
682 RUA.send(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100683
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100684 return f_bssap_expect(exp_rx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100685}
686
687/* send RANAP on Iu and expect it to show up on Iuh */
688function f_iu2iuh(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
689runs on ConnHdlr return RANAP_PDU {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100690 if (istemplatekind(exp_rx, "omit")) {
691 exp_rx := tx;
692 }
693
694 BSSAP.send(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100695
Neels Hofmeyr735b6562023-03-09 02:51:28 +0100696 return f_rua_expect(exp_rx)
697}
698
699/* expect to receive a specific RUA message on Iuh */
700private function f_rua_expect(template (present) RANAP_PDU exp_rx) runs on ConnHdlr return RANAP_PDU
701{
702 var RANAP_PDU rx;
703 timer T := 5.0;
704 T.start;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100705 alt {
706 [] RUA.receive(exp_rx) -> value rx {
707 setverdict(pass);
708 }
Neels Hofmeyr735b6562023-03-09 02:51:28 +0100709 [] RUA.receive(RANAP_PDU:?) {
710 setverdict(fail, "Got an unexpected RUA message, was waiting for ", exp_rx);
711 mtc.stop;
712 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100713 [] T.timeout {
714 setverdict(fail, "Timeout waiting for Iuh ", exp_rx);
Neels Hofmeyr735b6562023-03-09 02:51:28 +0100715 mtc.stop;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100716 }
717 }
Neels Hofmeyr735b6562023-03-09 02:51:28 +0100718 T.stop;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100719 return rx;
720}
721
722/* send RANAP on Iuh and expect it to show up on Iu */
723function f_iuh2iu_connect(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
724runs on ConnHdlr return RANAP_PDU {
725 var RANAP_PDU rx;
726 timer T := 5.0;
727
728 if (istemplatekind(exp_rx, "omit")) {
729 exp_rx := tx;
730 }
731
732 /* create an expect on the Iu side for the random NAS portion */
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200733 if (g_pars.expect_separate_sccp_cr) {
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200734 f_ran_register_sccp_cr_without_payload();
735 } else {
736 var template (omit) octetstring nas := f_ranap_extract_l3(valueof(tx));
737 f_ran_register_exp(valueof(nas));
738 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100739
740 /* send it via Iuh (creating a RUA connection) */
741 RUA.send(RUA_Conn_Req:{g_pars.ps_domain, tx});
742
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200743 if (g_pars.expect_separate_sccp_cr) {
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200744 /* Acknowledge the empty SCCP CR. RAN_Emulation does the confirmation, no need to respond. */
745 BSSAP.receive(tr_RANAP_Conn_Req());
746 }
747
Daniel Willmann19b8d902022-01-05 09:12:34 +0100748 /* expect to receive it on the Iu side */
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100749 return f_bssap_expect(exp_rx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100750}
751
Neels Hofmeyr99b7d402023-02-20 14:26:31 +0100752/* 3GPP TS 48.006 9.2 Connection release:
753 *
754 * The MSC sends a SCCP released message. This message shall not contain
755 * any user data field.
756 *
757 * So what we expect normally is:
758 *
759 * HNBGW MSC
760 * RUA --id-Disconnect-------> | ---Data-Form-1(!)---> | Iu-ReleaseComplete
761 * | <--Released---------- | (no data)
762 *
763 * This function tests osmo-hnbgw behavior if the CN fails to send a RLSD:
764 * after some timeout, osmo-hnbgw should send a RLSD to the CN.
765 */
Daniel Willmann19b8d902022-01-05 09:12:34 +0100766function f_iuh2iu_disconnect(template (present) RANAP_PDU tx, RUA_IEs.Cause cause,
767 template RANAP_PDU exp_rx := omit)
768runs on ConnHdlr return RANAP_PDU {
769 var RANAP_PDU rx
Pau Espin Pedrolee4ce862023-11-02 12:23:25 +0100770 timer T := int2float(mp_hnbgw_timer_x31) + 1.0;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100771
772 if (istemplatekind(exp_rx, "omit")) {
773 exp_rx := tx;
774 }
775
776 /* send it via Iuh (creating a RUA connection) */
777 RUA.send(RUA_Disc_Req:{tx, cause});
778
779 /* expect to receive it on the Iu side */
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100780 rx := f_bssap_expect(exp_rx);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100781
782 /* expect disconnect on the Iu side */
Neels Hofmeyrdc416c92023-03-09 02:47:50 +0100783 T.start;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100784 alt {
785 [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {
786 setverdict(pass);
787 }
788 [] T.timeout {
789 setverdict(fail, "Timeout waiting for Iu disconnect");
790 return rx;
791 }
792
793 }
794 return rx;
795}
796
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200797private function f_build_initial_ue_with_nas(TestHdlrParams pars, octetstring nas)
798 return RANAP_PDU {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100799 var LAI lai := {
800 pLMNidentity := hex2oct(pars.hnb.lai.mcc_mnc),
801 lAC := int2oct(pars.hnb.lai.lac, 2),
802 iE_Extensions := omit
803 };
804 var SAI sai := {
805 pLMNidentity := lai.pLMNidentity,
806 lAC := lai.lAC,
807 sAC := int2oct(pars.hnb.sac, 2),
808 iE_Extensions := omit
809 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100810 var IuSignallingConnectionIdentifier sigc_id := int2bit(f_rnd_int(1000), 24);
811 var GlobalRNC_ID grnc_id := {
812 pLMNidentity := lai.pLMNidentity,
813 rNC_ID := 2342
814 }
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200815 var template RANAP_PDU ret;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100816 if (pars.ps_domain) {
817 var RAC rac := '00'O;
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200818 ret := ts_RANAP_initialUE_PS(lai, rac, sai, nas, sigc_id, grnc_id);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100819 } else {
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200820 ret := ts_RANAP_initialUE_CS(lai, sai, nas, sigc_id, grnc_id);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100821 }
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200822 return valueof(ret);
823}
824
825/* build a RANAP InitialUE based on the TestHdlrParams */
826friend function f_build_initial_ue(TestHdlrParams pars) return RANAP_PDU {
827
828 var octetstring nas;
829
830 if (pars.tx_sccp_cr_data_len == 0) {
831 nas := f_rnd_octstring(10);
832 } else {
833 /* The test asks for an exact number of Optional Data bytes. */
834
835 /* First see what size the RANAP part of the payload data is,
836 * to adjust the NAS PDU size to the size requested by the test (pars.tx_sccp_cr_data_len). */
837 var RANAP_PDU initial_ue := f_build_initial_ue_with_nas(pars, '00'O);
838
839 var octetstring ranap_plus_one_byte_nas := enc_RANAP_PDU(initial_ue);
840 var integer ranap_length := lengthof(ranap_plus_one_byte_nas) - 1;
841
842 log("ranap_plus_one_byte_nas = ", lengthof(ranap_plus_one_byte_nas), " bytes, ", initial_ue, " = ",
843 ranap_plus_one_byte_nas);
844 log("ranap_length = ", ranap_length);
845
846 /* SCCP CR has a payload length limit of 130 bytes. To trigger this limit, the RANAP + NAS PDU has to be
847 * > 130 bytes. It doesn't need to be 131 bytes in the NAS PDU alone, but let's just make it definitely
848 * large enough. To test for this limit, pars.tx_sccp_cr_data_len asks for a specific amount of data len. */
849 nas := f_rnd_octstring(pars.tx_sccp_cr_data_len - ranap_length);
850 }
851
852 var RANAP_PDU ret := f_build_initial_ue_with_nas(pars, nas);
853
854 if (pars.tx_sccp_cr_data_len != 0) {
855 for (var integer attempts := 0; attempts < 2; attempts := attempts + 1) {
856 var octetstring check_len := enc_RANAP_PDU(ret);
857 log("final RANAP PDU length = ", lengthof(check_len));
858 if (lengthof(check_len) == pars.tx_sccp_cr_data_len) {
859 return ret;
860 }
861 nas := f_rnd_octstring(lengthof(nas) + (pars.tx_sccp_cr_data_len - lengthof(check_len)));
862 log("that was off, changed NAS length to ", lengthof(nas), " and trying again");
863 ret := f_build_initial_ue_with_nas(pars, nas);
864 }
865 setverdict(fail, "Ended up with wrong Optional Data length");
866 mtc.stop;
867 }
868 return ret;
Daniel Willmann19b8d902022-01-05 09:12:34 +0100869}
870
871/* build a RANAP RAB AssignmentResponse based on the TestHdlrParams */
872friend function f_build_rab_ass_resp(TestHdlrParams pars) return RANAP_PDU {
873 var template RAB_SetupOrModifiedList rab_sml;
874
875 rab_sml := ts_RAB_SMdL(t_RAB_id(23), f_ts_RAB_TLA("192.168.1.23"), t_RAB_binding_port(1234));
876
877 return valueof(ts_RANAP_RabAssResp(rab_sml));
878}
879
880
881/***********************************************************************
882 * HNBAP Testing
883 ***********************************************************************/
884
885
Daniel Willmannc79679a2022-08-23 17:48:39 +0200886function 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 +0100887{
888 timer T := 2.0;
889
Neels Hofmeyrfffe79b2023-06-27 01:16:15 +0200890 HNBAP[hnb_idx].send(ts_HNBAP_HNBRegisterRequest(char2oct("TTCN3-HNB-" & int2str(hnb_idx)),
Daniel Willmann19b8d902022-01-05 09:12:34 +0100891 '00F110'O,
Daniel Willmannc79679a2022-08-23 17:48:39 +0200892 int2bit(1 + cell_id, 28),
Daniel Willmann19b8d902022-01-05 09:12:34 +0100893 int2oct(2, 2),
894 int2oct(3, 1),
895 int2oct(4, 2)));
896
897 T.start;
898 alt {
899 [] HNBAP[hnb_idx].receive(tr_HNBAP_HNBRegisterAccept(?)) {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200900 if (expect_reject) {
901 setverdict(fail, "Rx HNB Register Accept while expecting reject");
902 } else {
903 setverdict(pass);
904 }
905 }
906 [] HNBAP[hnb_idx].receive(tr_HNBAP_HNBRegisterReject(?)) {
907 if (expect_reject) {
908 setverdict(pass);
909 } else {
910 setverdict(fail, "Rx HNB Register Reject while expecting accept");
911 }
Daniel Willmann19b8d902022-01-05 09:12:34 +0100912 }
913 [] HNBAP[hnb_idx].receive(IUHEM_Event:?) {
914 repeat;
915 }
916 [] T.timeout {
Daniel Willmannc79679a2022-08-23 17:48:39 +0200917 setverdict(fail, "Timeout waiting for HNB Register response");
Daniel Willmann19b8d902022-01-05 09:12:34 +0100918 }
919 }
920}
921
922testcase TC_hnb_register() runs on test_CT {
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200923 g_num_hnbs := 1;
Neels Hofmeyr333ea392023-06-27 00:58:05 +0200924 f_init(start_hnb := false);
Daniel Willmann19b8d902022-01-05 09:12:34 +0100925 f_hnbap_register(0);
926 f_shutdown_helper();
927}
928
Pau Espin Pedrolacf4f222022-09-27 14:33:40 +0200929/* Try to register the same HNB from 2 different concurrent connections. Second
930 * one should be rejected. */
Daniel Willmannc79679a2022-08-23 17:48:39 +0200931testcase TC_hnb_register_duplicate() runs on test_CT {
Pau Espin Pedrol83a49612022-09-12 21:11:05 +0200932 g_num_hnbs := 2;
Neels Hofmeyr333ea392023-06-27 00:58:05 +0200933 f_init(start_hnb := false);
Daniel Willmannc79679a2022-08-23 17:48:39 +0200934 f_hnbap_register(0);
935 f_hnbap_register(1, 0, expect_reject := true);
936 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
937 f_shutdown_helper();
938}
939
Pau Espin Pedrolacf4f222022-09-27 14:33:40 +0200940/* Try to register the same HNB in the same connection already established, aka
941 * duplicate HNB Register Request. It should be accepted and new configuration
942 * applied. TS 25.469 8.2.4 */
943testcase TC_hnb_register_duplicate_reuse_sctp_assoc() runs on test_CT {
944 g_num_hnbs := 1;
Neels Hofmeyr333ea392023-06-27 00:58:05 +0200945 f_init(start_hnb := false);
Pau Espin Pedrolacf4f222022-09-27 14:33:40 +0200946 f_hnbap_register(0);
947 f_hnbap_register(0);
948 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
949 f_shutdown_helper();
950}
951
Pau Espin Pedrolf0b9fa02022-09-12 13:31:07 +0200952/* Drop HNBAP conn (HNBAP DEREG) and reconnect it (HNBAP REG) using same SCTP association.
953 * Related: OS#5676, SYS#6113 */
954testcase TC_hnb_reregister_reuse_sctp_assoc() runs on test_CT {
955 g_num_hnbs := 1;
Neels Hofmeyr333ea392023-06-27 00:58:05 +0200956 f_init(start_hnb := false);
Pau Espin Pedrolf0b9fa02022-09-12 13:31:07 +0200957 f_hnbap_register(0);
958 HNBAP[0].send(ts_HNBAP_HNBDe_Register(ts_HnbapCause(unspecified)));
959 f_hnbap_register(0);
960 f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
961 f_shutdown_helper();
962}
963
Daniel Willmann19b8d902022-01-05 09:12:34 +0100964/***********************************************************************
965 * RUA / RANAP Testing
966 ***********************************************************************/
967
Neels Hofmeyr7a48df12023-04-20 20:43:43 +0200968/* Translate from {msc,sgsn}x{0..n} to the proper index to use in g_cn[].
969 * g_cn[] stores CN links, MSCs and SGSNs in the same array.
970 * For example, for 'sgsn 23', use g_cn[ f_cn_idx(ps_domain := true, cn_nr := 23) ].
971 *
972 * Note the naming:
973 * cn_nr is the number used in the cfg file, as in 'msc 0'.
974 * cn_idx is the array index in g_cn[].
975 */
976private function f_cn_idx(boolean ps_domain, integer cn_nr := 0) return integer
977{
978 if (ps_domain) {
979 return FIRST_SGSN_IDX + cn_nr;
980 }
981 return FIRST_MSC_IDX + cn_nr;
982}
983
Daniel Willmann19b8d902022-01-05 09:12:34 +0100984private template (value) TestHdlrParams
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200985t_pars(integer imsi_suffix, boolean ps_domain := false, integer hnb_idx := 0,
Neels Hofmeyr7a48df12023-04-20 20:43:43 +0200986 boolean expect_separate_sccp_cr := false, integer tx_sccp_cr_data_len := 0,
987 integer cn_nr := 0) := {
Daniel Willmann19b8d902022-01-05 09:12:34 +0100988 hnb_idx := hnb_idx,
Neels Hofmeyr7a48df12023-04-20 20:43:43 +0200989 cn_idx := f_cn_idx(ps_domain, cn_nr),
Daniel Willmann19b8d902022-01-05 09:12:34 +0100990 imsi := f_gen_imsi(imsi_suffix),
991 ps_domain := ps_domain,
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +0200992 hnb := omit, /* filled in later */
Neels Hofmeyrf2c95022023-04-19 01:24:39 +0200993 expect_separate_sccp_cr := expect_separate_sccp_cr,
994 tx_sccp_cr_data_len := tx_sccp_cr_data_len,
Neels Hofmeyr7d0e6802023-04-20 20:43:55 +0200995 pfcp_local_addr := mp_pfcp_ip_local,
Neels Hofmeyrb1bf16d2023-06-27 02:10:04 +0200996 nas_pdu := omit,
997 sccp_addr_msc := omit,
998 sccp_addr_hnbgw := omit
Daniel Willmann19b8d902022-01-05 09:12:34 +0100999}
1000
1001/* Create an Iuh connection; send InitialUE; expect it to appear on new SCCP conenction */
1002friend function f_tc_initial_ue(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1003 f_init_handler(pars);
1004 var RANAP_PDU tx := f_build_initial_ue(g_pars);
1005 f_iuh2iu_connect(tx);
1006}
1007testcase TC_ranap_cs_initial_ue() runs on test_CT {
1008 var ConnHdlr vc_conn;
1009
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001010 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001011 f_init();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001012
1013 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(1));
1014 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001015
1016 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001017}
1018testcase TC_ranap_ps_initial_ue() runs on test_CT {
1019 var ConnHdlr vc_conn;
1020
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001021 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001022 f_init();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001023
1024 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(2, true));
1025 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001026
1027 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001028}
1029
Neels Hofmeyrf2c95022023-04-19 01:24:39 +02001030private function f_vty_set_sccp_max_optional_data(TELNETasp_PT pt, integer val := -1)
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02001031{
Neels Hofmeyrf2c95022023-04-19 01:24:39 +02001032 var charstring valstr;
1033 if (val < 0) {
1034 valstr := "standard";
1035 } else {
1036 valstr := int2str(val);
1037 }
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02001038 f_vty_enter_config(pt);
Neels Hofmeyrf2c95022023-04-19 01:24:39 +02001039 f_vty_transceive(pt, "cs7 instance 0");
1040 f_vty_transceive(pt, "sccp max-optional-data " & valstr);
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02001041 f_vty_transceive(pt, "end");
1042}
1043
1044testcase TC_ranap_cs_initial_ue_empty_cr() runs on test_CT {
1045 var ConnHdlr vc_conn;
1046
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001047 g_num_hnbs := 1;
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02001048 f_init();
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02001049
Neels Hofmeyrf2c95022023-04-19 01:24:39 +02001050 f_vty_set_sccp_max_optional_data(HNBGWVTY, 0);
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02001051
Neels Hofmeyrf2c95022023-04-19 01:24:39 +02001052 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 +02001053 vc_conn.done;
1054
1055 /* reset */
Neels Hofmeyrf2c95022023-04-19 01:24:39 +02001056 f_vty_set_sccp_max_optional_data(HNBGWVTY);
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001057
1058 f_shutdown_helper();
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02001059}
1060testcase TC_ranap_ps_initial_ue_empty_cr() runs on test_CT {
1061 var ConnHdlr vc_conn;
1062
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001063 g_num_hnbs := 1;
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02001064 f_init();
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02001065
Neels Hofmeyrf2c95022023-04-19 01:24:39 +02001066 f_vty_set_sccp_max_optional_data(HNBGWVTY, 0);
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02001067
Neels Hofmeyrf2c95022023-04-19 01:24:39 +02001068 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 +02001069 vc_conn.done;
1070
1071 /* reset */
Neels Hofmeyrf2c95022023-04-19 01:24:39 +02001072 f_vty_set_sccp_max_optional_data(HNBGWVTY);
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001073
1074 f_shutdown_helper();
Neels Hofmeyrf2c95022023-04-19 01:24:39 +02001075}
1076
1077type record Testdata_CR_Limit {
1078 integer data_len,
1079 integer max_optional_data,
1080 boolean expect_separate_sccp_cr
1081};
1082type record of Testdata_CR_Limit Testdata_CR_Limits;
1083
1084testcase TC_sccp_cr_limit() runs on test_CT {
1085 g_num_hnbs := 1;
1086 f_init();
Neels Hofmeyrf2c95022023-04-19 01:24:39 +02001087
1088 const Testdata_CR_Limits tests := {
1089 { data_len := 130, max_optional_data := -1, expect_separate_sccp_cr := false },
1090 { data_len := 131, max_optional_data := -1, expect_separate_sccp_cr := true },
1091
1092 { data_len := 100, max_optional_data := 100, expect_separate_sccp_cr := false },
1093 { data_len := 101, max_optional_data := 100, expect_separate_sccp_cr := true },
1094
1095 { data_len := 200, max_optional_data := 200, expect_separate_sccp_cr := false },
1096 { data_len := 201, max_optional_data := 200, expect_separate_sccp_cr := true }
1097 };
1098
1099 var integer csps;
1100 for (csps := 0; csps < 2; csps := csps + 1) {
1101 var boolean ps_domain := (csps > 0);
1102
1103 var integer i;
1104 for (i := 0; i < lengthof(tests); i := i + 1) {
1105 var Testdata_CR_Limit t := tests[i];
1106 f_logp(HNBGWVTY,
1107 "TEST PART TC_sccp_cr_limit ps_domain=" & f_bool2str(ps_domain)
1108 & " data_len=" & int2str(t.data_len)
1109 & " max_optional_data=" & int2str(t.max_optional_data)
1110 & " expect_separate_sccp_cr=" & f_bool2str(t.expect_separate_sccp_cr)
1111 );
1112
1113 f_vty_set_sccp_max_optional_data(HNBGWVTY, t.max_optional_data);
1114 var ConnHdlr vc_conn;
1115 vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue),
1116 t_pars(100 + i,
1117 ps_domain := ps_domain,
1118 expect_separate_sccp_cr := t.expect_separate_sccp_cr,
1119 tx_sccp_cr_data_len := t.data_len));
1120 vc_conn.done;
1121 }
1122 }
1123
1124 /* reset */
1125 f_vty_set_sccp_max_optional_data(HNBGWVTY);
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001126
1127 f_shutdown_helper();
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02001128}
1129
Daniel Willmann19b8d902022-01-05 09:12:34 +01001130/* Reply to a received CRCX with an OK (or the reply configured in cpars), using the given parameters.
1131 * Return true when an OK reply was sent, false otherwise.
1132 * Count occurrence of Osmux, include Osmux parameters in the reply if necessary. */
1133function f_handle_crcx(inout MgcpParameters pars, MgcpCommand mgcp_cmd) return template MgcpResponse {
Pau Espin Pedrolb85ac2f2023-11-29 15:48:57 +01001134 var CrcxResponse conn := pars.mgw_conn_ran;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001135 if (pars.got_crcx_count > 0) {
Pau Espin Pedrolb85ac2f2023-11-29 15:48:57 +01001136 conn := pars.mgw_conn_cn;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001137 }
1138 pars.got_crcx_count := pars.got_crcx_count + 1;
1139
1140 var MgcpMessage mgcp_msg := {
1141 command := mgcp_cmd
1142 }
1143 var template MgcpResponse mgcp_resp;
1144 var MgcpOsmuxCID osmux_cid;
1145 var MgcpCallId call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
1146 if (ispresent(pars.mgcp_call_id)) {
1147 if (pars.mgcp_call_id != call_id) {
1148 setverdict(fail, "CRCX contained unexpected call id. Expected:", pars.mgcp_call_id, " got:", call_id);
1149 mtc.stop;
1150 }
1151 } else {
1152 pars.mgcp_call_id := call_id;
1153 }
1154
1155 /* When the endpoint contains a wildcard we keep the endpoint
1156 * identifier we have set up in pars. Otherwise we use the
1157 * endpoint name that the call agent has supplied */
1158 if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard) == false) {
1159 pars.mgcp_ep := mgcp_cmd.line.ep;
1160 }
1161
1162 if (conn.resp == -1) {
1163 /* Reply with rror */
1164 var MgcpResponse mgcp_rsp := {
1165 line := {
1166 code := "542",
1167 trans_id := mgcp_cmd.line.trans_id,
1168 string := "FORCED_FAIL"
1169 },
1170 sdp := omit
1171
1172 }
1173 var MgcpParameter mgcp_rsp_param := {
1174 code := "Z",
1175 val := pars.mgcp_ep
1176 };
1177 mgcp_rsp.params[0] := mgcp_rsp_param;
1178 return mgcp_rsp;
1179 }
1180
1181 if (conn.resp == 0) {
1182 /* Do not reply at all */
1183 return omit;
1184 }
1185
1186 if (conn.resp != 1) {
1187 setverdict(fail, "Unexpected value for pars.mgw_conn_*.resp, expect -1, 0 or 1");
1188 mtc.stop;
1189 }
1190
1191 var SDP_Message sdp := valueof(ts_SDP(conn.mgw_rtp_ip, conn.mgw_rtp_ip,
1192 hex2str(pars.mgcp_call_id), "42",
1193 conn.mgw_rtp_port,
1194 { int2str(pars.rtp_payload_type) },
1195 { valueof(ts_SDP_rtpmap(pars.rtp_payload_type,
1196 pars.rtp_sdp_format)),
1197 valueof(ts_SDP_ptime(20)) }));
1198
1199 if (f_mgcp_contains_par(mgcp_msg, "X-OSMUX")) {
1200 if (not pars.use_osmux) {
1201 setverdict(fail, "MSC sent X-Osmux parameter in MGCP, but not expecting any Osmux");
1202 mtc.stop;
1203 }
1204 pars.got_osmux_count := pars.got_osmux_count + 1;
1205 /* we expect MSC to use wildcard here, i.e. osmux_cid == -1 */
1206 osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
1207 log("f_handle_crcx(): got Osmux CID: ", osmux_cid);
1208 if (osmux_cid != -1) {
1209 setverdict(fail, "MSC using unexpected CID " & int2str(osmux_cid) & " != -1");
1210 mtc.stop;
1211 }
1212
1213 osmux_cid := 0;
1214 mgcp_resp := ts_CRCX_ACK_osmux(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, osmux_cid, sdp);
1215 } else {
1216 mgcp_resp := ts_CRCX_ACK(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, sdp);
1217 }
1218
1219 f_mgcp_par_append(mgcp_resp.params, ts_MgcpParSpecEP(pars.mgcp_ep));
1220
1221 return mgcp_resp;
1222}
1223
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001224friend function f_create_rab(inout MgcpParameters pars) runs on ConnHdlr {
1225 f_rab_ass_req(pars);
1226 f_rab_ass_resp(pars);
1227}
1228
1229friend function f_rab_ass_req(inout MgcpParameters pars) runs on ConnHdlr {
Daniel Willmann19b8d902022-01-05 09:12:34 +01001230 var MgcpCommand mgcp_cmd;
1231 var RANAP_PDU tx;
1232 var template RAB_SetupOrModifyList rab_sml;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001233 timer T := 5.0;
1234
1235 /* Send RAB Assignment Request */
1236 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));
1237 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1238 BSSAP.send(tx);
1239 T.start;
1240
1241 /* Handle MGCP CRCX */
1242 alt {
1243 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
1244 log("CRCX1", mgcp_cmd);
1245 var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
1246 MGCP.send(valueof(mgcp_rsp));
1247 }
1248 [] T.timeout {
1249 setverdict(fail, "Timeout waiting for MGCP");
1250 }
1251 }
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001252 T.stop;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001253
1254 /* Expect RAB Assignment Request with IP/port from CRCX ACK via Iuh */
Pau Espin Pedrolb85ac2f2023-11-29 15:48:57 +01001255 rab_sml := ts_RAB_SML(t_RAB_id(23), f_ts_RAB_TLA(pars.mgw_conn_ran.mgw_rtp_ip), t_RAB_binding_port(pars.mgw_conn_ran.mgw_rtp_port));
Daniel Willmann19b8d902022-01-05 09:12:34 +01001256 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1257
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001258 f_rua_expect(tx);
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001259}
1260
1261friend function f_rab_ass_resp(inout MgcpParameters pars) runs on ConnHdlr {
1262 var MgcpCommand mgcp_cmd;
1263 var RANAP_PDU tx;
1264 var template RAB_SetupOrModifiedList rab_smdl;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001265
1266 /* Send back RAB Assignment Response via Iuh */
1267 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));
1268 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1269 RUA.send(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +01001270
1271 interleave {
1272 /* Expect MDCX with IP/port from RAB Assignment Response */
1273 [] MGCP.receive(tr_MDCX(tr_SDP(pars.hnb_rtp_ip, pars.hnb_rtp_port))) -> value mgcp_cmd {
1274 log("MDCX1", mgcp_cmd);
1275 /* Verify SDP of MDCX */
Pau Espin Pedrolb85ac2f2023-11-29 15:48:57 +01001276 var SDP_Message sdp := valueof(ts_SDP(pars.mgw_conn_ran.mgw_rtp_ip, pars.mgw_conn_ran.mgw_rtp_ip, hex2str(pars.mgcp_call_id), "42", pars.mgw_conn_ran.mgw_rtp_port,
Daniel Willmann19b8d902022-01-05 09:12:34 +01001277 { int2str(pars.rtp_payload_type) }, { valueof(ts_SDP_rtpmap(pars.rtp_payload_type, pars.rtp_sdp_format)), valueof(ts_SDP_ptime(20)) } ));
Pau Espin Pedrolb85ac2f2023-11-29 15:48:57 +01001278 var template MgcpResponse mgcp_rsp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, pars.mgw_conn_ran.mgcp_connection_id, sdp);
Daniel Willmann19b8d902022-01-05 09:12:34 +01001279 MGCP.send(valueof(mgcp_rsp));
1280 }
1281 /* Handle CRCX for second leg of endpoint, answer with IP/port */
1282 [] MGCP.receive(tr_CRCX(pars.mgcp_ep, tr_SDP(pars.cn_rtp_ip, pars.cn_rtp_port))) -> value mgcp_cmd {
1283 log("CRCX2", mgcp_cmd);
1284 /* Verify SDP of CRCX */
1285 var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
1286 MGCP.send(valueof(mgcp_rsp));
1287 }
1288 }
1289
1290 /* Expect RAB Assignment Response with IP/port from second CRCX ACK */
Pau Espin Pedrolb85ac2f2023-11-29 15:48:57 +01001291 rab_smdl := ts_RAB_SMdL(t_RAB_id(23), f_ts_RAB_TLA(pars.mgw_conn_cn.mgw_rtp_ip), t_RAB_binding_port(pars.mgw_conn_cn.mgw_rtp_port));
Daniel Willmann19b8d902022-01-05 09:12:34 +01001292 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1293
Neels Hofmeyrdc416c92023-03-09 02:47:50 +01001294 f_bssap_expect(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +01001295}
1296
1297private altstep as_mgcp_dlcx(inout TestHdlrParams pars) runs on ConnHdlr {
1298 var MgcpCommand mgcp_cmd;
1299
1300 [] MGCP.receive(tr_DLCX(pars.mgcp_pars.mgcp_ep)) -> value mgcp_cmd {
1301 log("DLCX", mgcp_cmd);
1302 MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
1303 pars.mgcp_pars.got_dlcx_count := pars.mgcp_pars.got_dlcx_count + 1;
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001304 if (pars.mgcp_pars.got_dlcx_count != pars.mgcp_pars.got_crcx_count) {
Daniel Willmann19b8d902022-01-05 09:12:34 +01001305 repeat;
1306 }
1307 setverdict(pass);
1308 }
1309}
1310
1311friend function f_tc_rab_assignment(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1312 var MgcpCommand mgcp_cmd;
1313 var RANAP_PDU tx;
1314 timer T := 5.0;
1315
1316 f_init_handler(pars);
1317 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1318
1319 tx := f_build_initial_ue(g_pars);
1320 f_iuh2iu_connect(tx);
1321
1322 f_create_rab(pars.mgcp_pars);
1323
1324 /* Send Iu Release */
1325 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1326 f_iu2iuh(tx);
1327
1328 T.start;
1329 alt {
1330 [] as_mgcp_dlcx(pars) {}
1331 [] T.timeout {
1332 setverdict(fail, "Timeout waiting for DLCX");
1333 }
1334 }
1335
1336 tx := valueof(ts_RANAP_IuReleaseComplete());
1337 f_iuh2iu(tx);
1338}
1339
1340testcase TC_rab_assignment() runs on test_CT {
1341 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001342 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001343 f_init();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001344
1345 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assignment), t_pars(3));
1346 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001347
1348 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001349}
1350
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001351friend function f_tc_rab_assign_fail(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1352 var MgcpCommand mgcp_cmd;
1353 var RANAP_PDU tx;
1354 timer T := 5.0;
1355
1356 f_init_handler(pars);
1357 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1358
1359 tx := f_build_initial_ue(g_pars);
1360 f_iuh2iu_connect(tx);
1361
1362 f_rab_ass_req(pars.mgcp_pars);
1363
1364 /* Send RAB failed list in response */
1365 tx := valueof(ts_RANAP_RabAssResp(rab_fl := ts_RAB_FL(t_RAB_id(23), ts_RanapCause_om_intervention)));
1366 f_iuh2iu(tx);
1367
1368 T.start;
1369 alt {
1370 [] as_mgcp_dlcx(pars) {}
1371 [] T.timeout {
1372 setverdict(fail, "Timeout waiting for DLCX");
1373 }
1374 }
1375}
1376
1377testcase TC_rab_assign_fail() runs on test_CT {
1378 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001379 g_num_hnbs := 1;
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001380 f_init();
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001381
1382 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_fail), t_pars(4));
1383 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001384
1385 f_shutdown_helper();
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01001386}
1387
Daniel Willmann19b8d902022-01-05 09:12:34 +01001388friend function f_tc_rab_release(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1389 var MgcpCommand mgcp_cmd;
1390 var RANAP_PDU tx;
1391 timer T := 15.0;
1392
1393 f_init_handler(pars);
1394 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1395
1396 tx := f_build_initial_ue(g_pars);
1397 f_iuh2iu_connect(tx);
1398
1399 f_create_rab(pars.mgcp_pars);
1400
1401 /* Send RAB Release */
Daniel Willmann9e789be2022-02-22 13:30:51 +01001402 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 +01001403 BSSAP.send(tx);
1404
1405 T.start;
1406
1407 alt {
1408 [] as_mgcp_dlcx(pars) {}
1409 [] T.timeout {
1410 setverdict(fail, "Timeout waiting for DLCX");
1411 }
1412 }
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001413 T.stop;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001414
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001415 f_rua_expect(tx);
Daniel Willmann19b8d902022-01-05 09:12:34 +01001416}
1417
1418testcase TC_rab_release() runs on test_CT {
1419 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001420 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001421 f_init();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001422
1423 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_release), t_pars(5));
1424 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001425
1426 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001427}
1428
Daniel Willmann37c877f2022-02-22 16:47:06 +01001429friend function f_tc_rab_assign_mgcp_to(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1430 var MgcpCommand mgcp_cmd;
1431 var RANAP_PDU tx;
1432 var template RAB_SetupOrModifyList rab_sml;
1433 timer T := 15.0;
1434
1435 T.start;
1436 f_init_handler(pars);
1437 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
1438
1439 tx := f_build_initial_ue(g_pars);
1440 f_iuh2iu_connect(tx);
1441
1442
1443 /* Send RAB Assignment Request */
1444 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));
1445 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1446 BSSAP.send(tx);
1447
1448 /* Ignore MGCP CRCX */
1449 alt {
1450 [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
1451 log("Ignoreing CRCX1", mgcp_cmd);
1452 repeat;
1453 }
1454 [] BSSAP.receive(tr_RANAP_IuReleaseRequest(?)) { }
1455 [] T.timeout {
1456 setverdict(fail, "Timeout waiting for IuRelease");
1457 }
1458 }
1459
1460 /* Send Iu Release */
1461 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1462 f_iu2iuh(tx);
1463
1464 tx := valueof(ts_RANAP_IuReleaseComplete());
1465 f_iuh2iu(tx);
1466}
1467
1468testcase TC_rab_assign_mgcp_to() runs on test_CT {
1469 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001470 g_num_hnbs := 1;
Daniel Willmann37c877f2022-02-22 16:47:06 +01001471 f_init();
Daniel Willmann37c877f2022-02-22 16:47:06 +01001472
1473 vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_mgcp_to), t_pars(6));
1474 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001475
1476 f_shutdown_helper();
Daniel Willmann37c877f2022-02-22 16:47:06 +01001477}
1478
Daniel Willmann19b8d902022-01-05 09:12:34 +01001479/* Create an Iuh connection; send InitialUE; transceive data both directions */
1480friend function f_tc_ranap_bidir(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1481 f_init_handler(pars);
1482
1483 /* HNB -> MSC: InitialUE */
1484 f_iuh2iu_connect(f_build_initial_ue(g_pars));
1485
1486 /* MSC <- HNB: DirectTransfer */
1487 f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1488 /* MSC -> HNB: DirectTransfer */
1489 f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1490
1491 /* HNB <- MSC: CommonID */
1492 f_iu2iuh(ts_RANAP_CommonId(hex2oct(pars.imsi)));
1493}
1494testcase TC_ranap_cs_bidir() runs on test_CT {
1495 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001496 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001497 f_init();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001498
1499 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(3));
1500 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001501
1502 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001503}
1504testcase TC_ranap_ps_bidir() runs on test_CT {
1505 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001506 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001507 f_init();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001508
1509 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(4, true));
1510 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001511
1512 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001513}
1514
1515
1516private function f_tc_ranap_mo_disconnect(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1517 f_init_handler(pars);
1518
1519 /* HNB -> MSC: InitialUE */
1520 f_iuh2iu_connect(f_build_initial_ue(g_pars));
1521
1522 /* MSC <- HNB: DirectTransfer */
1523 f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1524 /* MSC -> HNB: DirectTransfer */
1525 f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
1526
1527 /* MSC <- HNB: RUA disconnect */
1528 f_iuh2iu_disconnect(ts_RANAP_IuReleaseComplete, RUA_IEs.Cause:{misc:=processing_overload});
1529}
1530testcase TC_ranap_cs_mo_disconnect() runs on test_CT {
1531 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001532 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001533 f_init();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001534
1535 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(5));
1536 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001537
1538 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001539}
1540testcase TC_ranap_ps_mo_disconnect() runs on test_CT {
1541 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001542 g_num_hnbs := 1;
Daniel Willmann19b8d902022-01-05 09:12:34 +01001543 f_init();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001544
1545 vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(6));
1546 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001547
1548 f_shutdown_helper();
Daniel Willmann19b8d902022-01-05 09:12:34 +01001549}
1550
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001551type record FTeid {
1552 HostName addr,
1553 OCT4 teid
1554}
1555
1556type record FTeids {
1557 FTeid local,
1558 FTeid remote
1559}
Daniel Willmann19b8d902022-01-05 09:12:34 +01001560
1561
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001562/* 'local' and 'remote' refer to the GTP information from the UPF's point of view:
1563 * HNB UPF CN
1564 * access.remote <---> access.local | core.local <---> core.remote
1565 */
1566type record GtpParameters {
1567 FTeids core,
1568 FTeids access
1569}
1570
1571/* HNB UPF CN
1572 * access.remote <---> access.local | core.local <---> core.remote
1573 * 127.0.0.4 127.0.0.3 127.0.0.2 127.0.0.1
1574 * 0x44004400 0x30303030 0x22002200 0x10101010
1575 */
1576template GtpParameters t_GtpParameters := {
1577 core := {
1578 local := {
1579 addr := "127.0.0.2",
1580 teid := '22002200'O
1581 },
1582 remote := {
1583 addr := "127.0.0.1",
1584 teid := '10101010'O
1585 }
1586 },
1587 access := {
1588 local := {
1589 addr := "127.0.0.3",
1590 teid := '30303030'O
1591 },
1592 remote := {
1593 addr := "127.0.0.4",
1594 teid := '44004400'O
1595 }
1596 }
1597}
1598
Neels Hofmeyr65499282023-04-25 02:31:51 +02001599private 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 +01001600{
1601 var PDU_PFCP rx;
Neels Hofmeyr65499282023-04-25 02:31:51 +02001602 timer T := wait_time;
Neels Hofmeyr6bbfe052023-03-09 02:51:46 +01001603 T.start;
1604 alt {
1605 [] PFCP.receive(exp_rx) -> value rx {
1606 setverdict(pass);
1607 }
1608 [] PFCP.receive(PDU_PFCP:?) {
1609 setverdict(fail, "Got an unexpected PFCP message, was waiting for ", exp_rx);
1610 mtc.stop;
1611 }
1612 [] T.timeout {
1613 setverdict(fail, "Timeout waiting for PFCP ", exp_rx);
1614 mtc.stop;
1615 }
1616 }
1617 T.stop;
1618 return rx;
1619}
1620
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001621friend function f_tc_ps_rab_assignment_with_pfcp(charstring id, TestHdlrParams pars) runs on ConnHdlr {
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001622 var RANAP_PDU tx;
1623 var RANAP_PDU rx;
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001624
1625 f_init_handler(pars);
1626
1627 f_pfcp_register();
1628
1629 var PDU_PFCP m;
1630 var Node_ID upf_node_id := valueof(ts_PFCP_Node_ID_fqdn("\07osmocom\03org"));
1631
Neels Hofmeyr65499282023-04-25 02:31:51 +02001632 m := f_pfcp_expect(tr_PFCP_Assoc_Setup_Req(), wait_time := 15.0);
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001633 PFCP.send(ts_PFCP_Assoc_Setup_Resp(m.sequence_number, upf_node_id,
1634 ts_PFCP_Cause(REQUEST_ACCEPTED), 1234));
1635
1636 tx := f_build_initial_ue(g_pars);
1637 f_iuh2iu_connect(tx);
1638
1639 var GtpParameters gtp_pars := valueof(t_GtpParameters);
1640 var template RAB_SetupOrModifyList rab_sml;
1641
1642 /* Send RAB Assignment Request */
1643 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.remote.addr), gtp_pars.core.remote.teid);
1644 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1645 BSSAP.send(tx);
1646
1647 /* Expect PFCP Session Establishment Request. */
Neels Hofmeyr6bbfe052023-03-09 02:51:46 +01001648 m := f_pfcp_expect(tr_PFCP_Session_Est_Req());
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001649 var F_SEID hnbgw_f_seid := m.message_body.pfcp_session_establishment_request.CP_F_SEID;
1650 var PFCP_Session_Establishment_Request serq := m.message_body.pfcp_session_establishment_request;
1651
1652 /* Acting as UPF, invent a new PFCP SEID to send to HNBGW. Respond to the Session Establishment.
1653 * The PFCP response must have the same sequence_number as the request. */
Neels Hofmeyr1e311462023-01-11 01:19:12 +01001654 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 +02001655 var template PDU_PFCP r := ts_PFCP_Session_Est_Resp(m.sequence_number, upf_node_id, hnbgw_f_seid.seid);
1656 r.message_body.pfcp_session_establishment_response := {
1657 offending_ie := omit,
1658 UP_F_SEID := up_f_seid,
1659 created_PDR_list := {
1660 ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[0].grouped_ie.pdr_id,
1661 local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.core.local.teid,
Neels Hofmeyr1e311462023-01-11 01:19:12 +01001662 f_inet_addr(gtp_pars.core.local.addr))),
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001663 ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[1].grouped_ie.pdr_id,
1664 local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.access.local.teid,
Neels Hofmeyr1e311462023-01-11 01:19:12 +01001665 f_inet_addr(gtp_pars.access.local.addr)))
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001666 },
1667 load_control_information := omit,
1668 overload_control_information := omit,
1669 node_list := omit,
1670 failed_rule_id := omit,
1671 created_traffic_endpoint_list := omit
1672 };
1673 PFCP.send(r);
1674
1675 /* Expect on Iuh: RAB Assignment Request with IP/port from PFCP Session Est Resp */
1676 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.local.addr),
1677 gtp_pars.access.local.teid);
1678 rx := valueof(ts_RANAP_RabAssReq(rab_sml));
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001679 f_rua_expect(rx);
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001680
1681 /* Send back RAB Assignment Response via Iuh */
1682 var template RAB_SetupOrModifiedList rab_smdl;
1683 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.remote.addr),
1684 gtp_pars.access.remote.teid);
1685 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1686 RUA.send(tx);
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001687
Neels Hofmeyr6bbfe052023-03-09 02:51:46 +01001688 m := f_pfcp_expect(tr_PFCP_Session_Mod_Req(up_f_seid.seid));
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001689 r := ts_PFCP_Session_Mod_Resp(m.sequence_number, hnbgw_f_seid.seid);
1690 PFCP.send(r);
1691
1692 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 +01001693 f_bssap_expect(tr_RANAP_RabAssResp(rab_smdl));
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001694
1695 f_sleep(2.0);
1696 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1697 f_iu2iuh(tx);
1698
1699 tx := valueof(ts_RANAP_IuReleaseComplete());
1700 f_iuh2iu(tx);
1701
Neels Hofmeyr6bbfe052023-03-09 02:51:46 +01001702 m := f_pfcp_expect(tr_PFCP_Session_Del_Req(up_f_seid.seid));
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001703 PFCP.send(ts_PFCP_Session_Del_Resp(m.sequence_number, hnbgw_f_seid.seid));
1704
1705 f_sleep(2.0);
1706}
1707
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001708testcase TC_ps_rab_assignment_with_pfcp() runs on test_CT {
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001709 var ConnHdlr vc_conn;
Pau Espin Pedrol83a49612022-09-12 21:11:05 +02001710 g_num_hnbs := 1;
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001711 f_init();
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001712 f_sleep(1.0);
1713
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001714 vc_conn := f_start_handler_with_pars(refers(f_tc_ps_rab_assignment_with_pfcp), t_pars(7, ps_domain := true));
1715 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001716
1717 f_shutdown_helper();
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001718}
1719
1720altstep as_disallow_pfcp() runs on ConnHdlr {
1721 [] PFCP.receive(PDU_PFCP:?) {
1722 setverdict(fail, "Received PFCP message, but no PFCP communication expected");
1723 mtc.stop;
1724 }
1725}
1726
1727friend function f_tc_ps_rab_assignment_without_pfcp(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1728 var RANAP_PDU tx;
1729 var RANAP_PDU rx;
1730 timer T := 5.0;
1731
1732 f_init_handler(pars);
1733
1734 f_pfcp_register();
1735 activate(as_disallow_pfcp());
1736
1737 tx := f_build_initial_ue(g_pars);
1738 f_iuh2iu_connect(tx);
1739
1740 var GtpParameters gtp_pars := valueof(t_GtpParameters);
1741 var template RAB_SetupOrModifyList rab_sml;
1742
1743 /* Send RAB Assignment Request */
1744 rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.remote.addr), gtp_pars.core.remote.teid);
1745 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
1746 BSSAP.send(tx);
1747
1748 /* Expect on Iuh: unmodified RAB Assignment Request */
1749 rx := valueof(ts_RANAP_RabAssReq(rab_sml));
Neels Hofmeyr735b6562023-03-09 02:51:28 +01001750 f_rua_expect(rx);
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001751
1752 /* Send back RAB Assignment Response via Iuh */
1753 var template RAB_SetupOrModifiedList rab_smdl;
1754 rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.remote.addr),
1755 gtp_pars.access.remote.teid);
1756 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
1757 RUA.send(tx);
1758
1759 /* Expect on IuPS: unmodified RAB Assignment Response */
Neels Hofmeyrdc416c92023-03-09 02:47:50 +01001760 f_bssap_expect(tr_RANAP_RabAssResp(rab_smdl));
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001761
1762 f_sleep(2.0);
1763 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
1764 f_iu2iuh(tx);
1765
1766 tx := valueof(ts_RANAP_IuReleaseComplete());
1767 f_iuh2iu(tx);
1768
1769 f_sleep(2.0);
1770}
1771
1772testcase TC_ps_rab_assignment_without_pfcp() runs on test_CT {
1773 var ConnHdlr vc_conn;
1774 f_init();
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02001775 f_sleep(1.0);
1776
1777 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 +02001778 vc_conn.done;
Neels Hofmeyr3a9140e2023-06-23 04:50:39 +02001779
1780 f_shutdown_helper();
Neels Hofmeyra56e8fd2022-05-08 01:16:55 +02001781}
Daniel Willmann19b8d902022-01-05 09:12:34 +01001782
Neels Hofmeyr7d0e6802023-04-20 20:43:55 +02001783/* Default list of counters for a 'cn' entity to test the cnpool feature. */
1784const CounterNameVals counternames_cnpool := {
1785 { "cnpool:subscr:new", 0 },
1786 { "cnpool:subscr:known", 0 },
1787 { "cnpool:subscr:reattach", 0 },
1788 { "cnpool:subscr:attach_lost", 0 },
1789 { "cnpool:subscr:paged", 0 }
1790};
1791private function f_ctrs_cn_init(boolean ps_domain, integer cn_count := 0,
1792 CounterNameVals counternames := counternames_cnpool) runs on test_CT {
1793 if (ps_domain) {
1794 g_ctr_cn_node_name := "sgsn";
1795 if (cn_count == 0) {
1796 cn_count := NUM_SGSN;
1797 }
1798 } else {
1799 g_ctr_cn_node_name := "msc";
1800 if (cn_count == 0) {
1801 cn_count := NUM_MSC;
1802 }
1803 }
1804 g_ctr_cn := f_counter_name_vals_get_n(IPA_CTRL, g_ctr_cn_node_name, cn_count, counternames);
1805 log("initial " & g_ctr_cn_node_name & " rate counters: ", g_ctr_cn);
1806}
1807
1808/* f_ctrs_cn_init();
1809 * f_do_thing(on_cn := 0);
1810 * f_do_thing(on_cn := 0);
1811 * f_do_other(on_cn := 1);
1812 * f_ctrs_cn_add(0, "thing", 2);
1813 * f_ctrs_cn_add(1, "other");
1814 * f_ctrs_cn_verify();
1815 */
1816private function f_ctrs_cn_verify() runs on test_CT {
1817 log("verifying", g_ctr_cn_node_name, " rate counters: ", g_ctr_cn);
1818 f_counter_name_vals_expect_n(IPA_CTRL, g_ctr_cn_node_name, g_ctr_cn);
1819}
1820
1821/* convenience: f_ctrs_cn_add() and f_ctrs_cn_verify() in one call.
1822 * f_ctrs_cn_init();
1823 * f_do_thing(on_cn := 0);
1824 * f_do_thing(on_cn := 0);
1825 * f_do_thing(on_cn := 0);
1826 * f_ctrs_cn_expect(0, "thing", 3);
1827 */
1828private function f_ctrs_cn_expect(integer cn_nr, charstring countername, integer val := 1) runs on test_CT {
1829 f_ctrs_cn_add(cn_nr, countername, val);
1830 f_ctrs_cn_verify();
1831}
1832
1833private function f_ctrs_cn_add(integer cn_nr, charstring countername, integer val := 1) runs on test_CT {
1834 f_counter_name_vals_list_add(g_ctr_cn, cn_nr, countername, val);
1835}
1836
1837private function f_perform_compl_l3(octetstring nas, boolean do_clear := true, boolean expect_iu_l3 := true)
1838runs on ConnHdlr {
1839 timer T := 10.0;
1840
1841 /* create an expect on the Iu side for the random NAS portion */
1842 if (g_pars.expect_separate_sccp_cr) {
1843 f_ran_register_sccp_cr_without_payload();
1844 } else {
1845 f_ran_register_exp(nas);
1846 }
1847
1848 /* send Connect via Iuh (creating a RUA connection) */
1849 var RANAP_PDU tx := f_build_initial_ue_with_nas(g_pars, nas);
1850 RUA.send(RUA_Conn_Req:{g_pars.ps_domain, tx});
1851
1852 if (expect_iu_l3) {
1853 /* Expect same message to arrive at CN */
1854 f_bssap_expect(tx);
1855 }
1856}
1857
1858private function f_tc_cnpool_compl_l3(charstring id, TestHdlrParams pars) runs on ConnHdlr {
1859 f_init_handler(pars);
1860 f_perform_compl_l3(g_pars.nas_pdu);
1861}
1862
1863private function f_TC_cnpool_compl_l3(boolean ps_domain, octetstring nas_pdu, integer cn_nr,
1864 template (omit) charstring inc_countername := omit) runs on test_CT {
1865 var ConnHdlr vc_conn;
1866 var template (value) TestHdlrParams pars := t_pars(0, ps_domain := ps_domain, cn_nr := cn_nr);
1867 pars.nas_pdu := nas_pdu;
1868 log("XXX ", pars);
1869 vc_conn := f_start_handler_with_pars(refers(f_tc_cnpool_compl_l3), pars);
1870 vc_conn.done;
1871
1872 if (not istemplatekind(inc_countername, "omit")) {
1873 f_ctrs_cn_expect(cn_nr, valueof(inc_countername));
1874 }
1875}
1876
1877function f_TC_cnpool_compl_l3_list(boolean ps_domain, ro_octetstring compl3, Osmocom_Types.ro_integer cn_nrs,
1878 charstring inc_countername) runs on test_CT {
1879 var integer n := lengthof(compl3);
1880 if (n < lengthof(cn_nrs)) {
1881 n := lengthof(cn_nrs);
1882 }
1883 for (var integer i := 0; i < n; i := i + 1) {
1884 var integer cn_nr := cn_nrs[i mod lengthof(cn_nrs)];
1885 f_TC_cnpool_compl_l3(ps_domain, compl3[i mod lengthof(compl3)], cn_nr, inc_countername);
1886 }
1887}
1888
1889type enumerated Compl3Type {
1890 /* CS */
1891 LU,
1892 CMSERV,
1893 PAGRESP,
1894 IMSIDETACH,
1895
1896 /* PS */
1897 ATTACHREQ,
1898 RAUREQ,
1899 DETREQ
1900};
1901
1902private function f_gen_one_compl_l3(Compl3Type compl3type, template (value) MobileIdentityLV mi,
1903 integer ps_nri := -1
1904 ) return octetstring
1905{
1906 /* CS */
1907 if (compl3type == LU) {
1908 return enc_PDU_ML3_MS_NW(valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(mi), '00F110'O)));
1909 }
1910 if (compl3type == CMSERV) {
1911 return enc_PDU_ML3_MS_NW(valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(mi))));
1912 }
1913 if (compl3type == PAGRESP) {
1914 return enc_PDU_ML3_MS_NW(valueof(ts_PAG_RESP(valueof(mi))));
1915 }
1916 if (compl3type == IMSIDETACH) {
1917 return enc_PDU_ML3_MS_NW(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(mi))));
1918 }
1919
1920 /* PS */
1921 var template (omit) NetworkResourceIdentifierContainerTLV nri := omit;
1922 if (ps_nri >= 0) {
1923 nri := valueof(ts_GMM_NRI(ps_nri));
1924 }
1925
1926 if (compl3type == ATTACHREQ) {
1927 return enc_PDU_L3_MS_SGSN(valueof(ts_GMM_ATTACH_REQ(valueof(mi), f_RAI('001'H, '01'H, '2a2a'O, '17'O),
1928 nri := nri)));
1929 }
1930 if (compl3type == RAUREQ) {
1931 return enc_PDU_L3_MS_SGSN(valueof(ts_GMM_RAU_REQ(valueof(mi), GPRS_UPD_T_PERIODIC,
1932 f_RAI('001'H, '01'H, '2a2a'O, '17'O),
1933 nri := nri)));
1934 }
1935 if (compl3type == DETREQ) {
1936 return enc_PDU_L3_MS_SGSN(valueof(ts_GMM_DET_REQ_MO_mi(c_GMM_DTT_MO_GPRS, power_off := false,
1937 p_tmsi := valueof(ts_MI_TLV(mi.mobileIdentityV)))));
1938 }
1939
1940 setverdict(fail, "unknown complete layer 3 type");
1941 mtc.stop;
1942}
1943
1944type record of Compl3Type ro_Compl3Type;
1945type record of MobileIdentityLV ro_MobileIdentityLV;
1946type record of octetstring ro_octetstring;
1947
1948/* Generate a list of n Complete Layer 3 NAS PDUs,
1949 * rotating through the message kinds listed in 'types' and the mobile identities in mis.
1950 */
1951private function f_gen_compl_l3(ro_Compl3Type types, ro_MobileIdentityLV mis, integer n) return ro_octetstring
1952{
1953 var ro_octetstring res := {};
1954 for (var integer i := 0; i < n; i := i + 1) {
1955 var integer ti := i mod lengthof(types);
1956 var integer mi := i mod lengthof(mis);
1957 res[i] := f_gen_one_compl_l3(types[ti], mis[mi]);
1958 }
1959 return res;
1960}
1961
1962private function f_gen_mi_imsi(integer n) return MobileIdentityLV
1963{
1964 return valueof(ts_MI_IMSI_LV(f_gen_imsi(n)));
1965}
1966
1967private function f_gen_mi_imsis(integer n) return ro_MobileIdentityLV
1968{
1969 var ro_MobileIdentityLV mis := {};
1970 for (var integer i := 0; i < n; i := i + 1) {
1971 mis[i] := f_gen_mi_imsi(n);
1972 }
1973 return mis;
1974}
1975
1976function f_vty_set_roundrobin_next(TELNETasp_PT VTY, boolean ps_domain, integer cn_nr)
1977{
1978 var charstring msc_sgsn;
1979 if (ps_domain) {
1980 msc_sgsn := "sgsn";
1981 } else {
1982 msc_sgsn := "msc";
1983 }
1984 f_vty_transceive(VTY, "cnpool roundrobin next " & msc_sgsn & " " & int2str(cn_nr));
1985}
1986
1987private function f_gen_compl3_by_domain(boolean ps_domain, integer n, template (omit) ro_MobileIdentityLV mis := omit) return ro_octetstring{
1988 var ro_Compl3Type types;
1989 if (ps_domain) {
1990 types := { ATTACHREQ, RAUREQ, DETREQ };
1991 } else {
1992 types := { LU, CMSERV, PAGRESP, IMSIDETACH };
1993 }
1994 if (istemplatekind(mis, "omit")) {
1995 mis := f_gen_mi_imsis(n);
1996 }
1997 return f_gen_compl_l3(types, valueof(mis), n);
1998}
1999
2000/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
2001testcase TC_mscpool_L3Compl_on_1_cnlink() runs on test_CT {
2002 f_TC_cnpool_L3Compl_on_1_cnlink(ps_domain := false);
2003}
2004testcase TC_sgsnpool_L3Compl_on_1_cnlink() runs on test_CT {
2005 f_TC_cnpool_L3Compl_on_1_cnlink(ps_domain := true);
2006}
2007function f_TC_cnpool_L3Compl_on_1_cnlink(boolean ps_domain) runs on test_CT {
2008
2009 f_init();
2010
2011 f_ctrs_cn_init(ps_domain := ps_domain);
2012
2013 var ro_octetstring compl3 := f_gen_compl3_by_domain(ps_domain, 4);
2014 f_TC_cnpool_compl_l3_list(ps_domain, compl3, {0, 0, 0, 0}, "cnpool:subscr:new");
2015
2016 f_shutdown_helper();
2017}
2018
2019/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
2020testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
2021 f_TC_cnpool_L3Complete_by_imsi_round_robin(ps_domain := false);
2022}
2023testcase TC_sgsnpool_L3Complete_no_nri_round_robin() runs on test_CT {
2024 f_TC_cnpool_L3Complete_by_imsi_round_robin(ps_domain := true);
2025}
2026function f_TC_cnpool_L3Complete_by_imsi_round_robin(boolean ps_domain) runs on test_CT {
2027
2028 f_init(nr_msc := 2, nr_sgsn := 2);
2029 f_sleep(1.0);
2030
2031 /* Control which MSC gets chosen next by the round-robin, otherwise
2032 * would be randomly affected by which other tests ran before this. */
2033 f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
2034
2035 f_ctrs_cn_init(ps_domain := ps_domain);
2036
2037 var ro_octetstring compl3 := f_gen_compl3_by_domain(ps_domain, 3);
2038
2039 f_TC_cnpool_compl_l3_list(ps_domain, compl3,
2040 /* Third Complete Layer 3 wraps back to msc 0 */
2041 cn_nrs := {0, 1, 0},
2042 inc_countername := "cnpool:subscr:new");
2043
2044 f_shutdown_helper();
2045}
2046
2047/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain a NULL-NRI (0, 1)
2048 * (configured in osmo-hnbgw.cfg). */
2049testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
2050 f_TC_cnpool_LU_by_tmsi_null_nri_N_round_robin(ps_domain := false, nri_val := 0);
2051}
2052/* For NRI == 1, one of the MSC also has the NULL-NRI as part of its owned NRIs, but the NULL-NRI setting is stronger
2053 * than that. */
2054testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
2055 f_TC_cnpool_LU_by_tmsi_null_nri_N_round_robin(ps_domain := false, nri_val := 1);
2056}
2057function f_TC_cnpool_LU_by_tmsi_null_nri_N_round_robin(boolean ps_domain, integer nri_val) runs on test_CT {
2058
2059 f_init(nr_msc := 2, nr_sgsn := 2);
2060 f_sleep(1.0);
2061
2062 /* Control which MSC gets chosen next by the round-robin, otherwise
2063 * would be randomly affected by which other tests ran before this. */
2064 f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
2065
2066 f_ctrs_cn_init(ps_domain := ps_domain);
2067
2068 var ro_MobileIdentityLV mis := { valueof(ts_MI_TMSI_NRI_LV(nri_val)) };
2069 var ro_octetstring compl3;
2070 if (ps_domain) {
2071 compl3 := {
2072 f_gen_one_compl_l3(ATTACHREQ, mis[0], nri_val)
2073 };
2074 } else {
2075 compl3 := f_gen_compl_l3({LU}, mis, 1);
2076 }
2077
2078 f_TC_cnpool_compl_l3_list(ps_domain, compl3,
2079 /* The third Complete Layer 3 wraps back to msc 0 */
2080 {0, 1, 0},
2081 "cnpool:subscr:reattach");
2082 f_shutdown_helper();
2083}
2084
2085/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
2086 * assigned to any MSC (configured in osmo-hnbgw.cfg). */
2087testcase TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() runs on test_CT {
2088 f_TC_cnpool_L3Complete_by_tmsi_unassigned_nri_round_robin(ps_domain := false);
2089}
2090function f_TC_cnpool_L3Complete_by_tmsi_unassigned_nri_round_robin(boolean ps_domain) runs on test_CT {
2091
2092 f_init(nr_msc := 2, nr_sgsn := 2);
2093 f_sleep(1.0);
2094
2095 /* Control which MSC gets chosen next by the round-robin, otherwise
2096 * would be randomly affected by which other tests ran before this. */
2097 f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
2098
2099 f_ctrs_cn_init(ps_domain := ps_domain);
2100
2101 /* 3 NRIs that are not assigned to any MSC */
2102 var ro_MobileIdentityLV mis := {
2103 valueof(ts_MI_TMSI_NRI_LV(1000)),
2104 valueof(ts_MI_TMSI_NRI_LV(768)),
2105 valueof(ts_MI_TMSI_NRI_LV(819))
2106 };
2107
2108 var ro_octetstring compl3 := f_gen_compl3_by_domain(ps_domain, 3, mis);
2109 f_TC_cnpool_compl_l3_list(ps_domain, compl3, { 0, 1, 0 }, "cnpool:subscr:new");
2110
2111 f_shutdown_helper();
2112}
2113
2114/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
2115 * assigned to a CN link that is currently not connected (configured in osmo-hnbgw.cfg). */
2116testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
2117 f_TC_cnpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin(ps_domain := false);
2118}
2119function f_TC_cnpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin(boolean ps_domain) runs on test_CT {
2120
2121 f_init(nr_msc := 2, nr_sgsn := 2);
2122 f_sleep(1.0);
2123
2124 /* Control which MSC gets chosen next by the round-robin, otherwise
2125 * would be randomly affected by which other tests ran before this. */
2126 f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
2127
2128 f_ctrs_cn_init(ps_domain := ps_domain);
2129
2130 /* 3 NRIs that are assigned to an unconnected MSC */
2131 var ro_MobileIdentityLV mis := {
2132 valueof(ts_MI_TMSI_NRI_LV(512)),
2133 valueof(ts_MI_TMSI_NRI_LV(767)),
2134 valueof(ts_MI_TMSI_NRI_LV(750))
2135 };
2136
2137 var ro_octetstring compl3 := f_gen_compl3_by_domain(ps_domain, 3, mis);
2138
2139 f_TC_cnpool_compl_l3(ps_domain, compl3[0], cn_nr := 0);
2140 f_ctrs_cn_add(2, "cnpool:subscr:attach_lost");
2141 f_ctrs_cn_add(0, "cnpool:subscr:new");
2142 f_ctrs_cn_verify();
2143
2144 f_TC_cnpool_compl_l3(ps_domain, compl3[1], cn_nr := 1);
2145 f_ctrs_cn_add(2, "cnpool:subscr:attach_lost");
2146 f_ctrs_cn_add(1, "cnpool:subscr:new");
2147 f_ctrs_cn_verify();
2148
2149 f_TC_cnpool_compl_l3(ps_domain, compl3[2], cn_nr := 0);
2150 f_ctrs_cn_add(2, "cnpool:subscr:attach_lost");
2151 f_ctrs_cn_add(0, "cnpool:subscr:new");
2152 f_ctrs_cn_verify();
2153
2154 f_shutdown_helper();
2155}
2156
2157/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
2158 * osmo-hnbgw.cfg). */
2159testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
2160 f_TC_cnpool_L3Complete_valid_nri_1(ps_domain := false);
2161}
2162testcase TC_sgsnpool_L3Complete_valid_nri_1() runs on test_CT {
2163 f_TC_cnpool_L3Complete_valid_nri_1(ps_domain := true);
2164}
2165function f_TC_cnpool_L3Complete_valid_nri_1(boolean ps_domain) runs on test_CT {
2166
2167 f_init(nr_msc := 2, nr_sgsn := 2);
2168 f_sleep(1.0);
2169
2170 /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
2171 * this is not using round-robin. */
2172 f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
2173
2174 f_ctrs_cn_init(ps_domain := ps_domain);
2175
2176 var ro_octetstring compl3;
2177
2178 /* 3 NRIs of the second MSC's range (256-511) */
2179 var ro_MobileIdentityLV mis := {
2180 valueof(ts_MI_TMSI_NRI_LV(256)),
2181 valueof(ts_MI_TMSI_NRI_LV(260)),
2182 valueof(ts_MI_TMSI_NRI_LV(511))
2183 };
2184 if (ps_domain) {
2185 compl3 := {
2186 f_gen_one_compl_l3(RAUREQ, mis[0], 256),
2187 f_gen_one_compl_l3(RAUREQ, mis[1], 260),
2188 f_gen_one_compl_l3(RAUREQ, mis[2], 511)
2189 };
2190 } else {
2191 compl3 := f_gen_compl3_by_domain(ps_domain, 3, mis);
2192 }
2193
2194 f_TC_cnpool_compl_l3_list(ps_domain, compl3, {1, 1, 1}, "cnpool:subscr:known");
2195
2196 f_shutdown_helper();
2197}
2198
2199/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-hnbgw.cfg),
2200 * while a round-robin remains unaffected by that. */
2201testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
2202 f_TC_cnpool_L3Complete_valid_nri_2(ps_domain := false);
2203}
2204testcase TC_sgsnpool_L3Complete_valid_nri_2() runs on test_CT {
2205 f_TC_cnpool_L3Complete_valid_nri_2(ps_domain := true);
2206}
2207function f_TC_cnpool_L3Complete_valid_nri_2(boolean ps_domain) runs on test_CT {
2208
2209 f_init(nr_msc := 3, nr_sgsn := 3);
2210 f_sleep(1.0);
2211
2212 /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
2213 * this is not using round-robin. */
2214 f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 1);
2215
2216 f_ctrs_cn_init(ps_domain := ps_domain);
2217
2218 var ro_octetstring compl3;
2219
2220 /* 2 NRIs of the third MSC's range (512-767) */
2221 var ro_MobileIdentityLV mis := {
2222 valueof(ts_MI_TMSI_NRI_LV(512)),
2223 valueof(ts_MI_TMSI_NRI_LV(678))
2224 };
2225 if (ps_domain) {
2226 compl3 := {
2227 f_gen_one_compl_l3(ATTACHREQ, mis[0], 512),
2228 f_gen_one_compl_l3(ATTACHREQ, mis[1], 678)
2229 };
2230 } else {
2231 compl3 := f_gen_compl3_by_domain(ps_domain, 2, mis);
2232 }
2233
2234 f_TC_cnpool_compl_l3_list(ps_domain, compl3, {2, 2}, "cnpool:subscr:known");
2235
2236 /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
2237 f_TC_cnpool_compl_l3_list(ps_domain, f_gen_compl3_by_domain(ps_domain, 1), {1}, "cnpool:subscr:new");
2238
2239 f_shutdown_helper();
2240}
2241
2242/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
2243testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
2244 f_TC_cnpool_nri_from_other_PLMN(ps_domain := false);
2245}
2246testcase TC_sgsnpool_nri_from_other_PLMN() runs on test_CT {
2247 f_TC_cnpool_nri_from_other_PLMN(ps_domain := true);
2248}
2249function f_TC_cnpool_nri_from_other_PLMN(boolean ps_domain) runs on test_CT {
2250
2251 f_init(nr_msc := 3, nr_sgsn := 3);
2252 f_sleep(1.0);
2253
2254 /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
2255 * instead, and hits msc 0. */
2256 f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
2257
2258 f_ctrs_cn_init(ps_domain := ps_domain);
2259
2260 var ro_octetstring compl3;
2261
2262 var ro_MobileIdentityLV mis := {
2263 valueof(ts_MI_TMSI_NRI_LV(260)),
2264 valueof(ts_MI_TMSI_NRI_LV(555))
2265 };
2266 if (ps_domain) {
2267 compl3 := {
2268 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-hnbgw.cfg */
2269 enc_PDU_L3_MS_SGSN(valueof(ts_GMM_ATTACH_REQ(mis[0], f_RAI('999'H, '99'H, '2a2a'O,
2270 '17'O),
2271 nri := ts_GMM_NRI(260)
2272 ))),
2273 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
2274 f_gen_one_compl_l3(ATTACHREQ, mis[1], 555)
2275 }
2276 } else {
2277 compl3 := {
2278 /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-hnbgw.cfg */
2279 enc_PDU_ML3_MS_NW(valueof(ts_LU_REQ(LU_Type_IMSI_Attach, mis[0], '99F999'O))),
2280 /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
2281 enc_PDU_ML3_MS_NW(valueof(ts_LU_REQ(LU_Type_IMSI_Attach, mis[1], '00F110'O)))
2282 };
2283 }
2284
2285 /* Foreign NRI: roundrobin */
2286 f_TC_cnpool_compl_l3(ps_domain, compl3[0], cn_nr := 0, inc_countername := "cnpool:subscr:new");
2287
2288 /* Local NRI: matching msc */
2289 f_TC_cnpool_compl_l3(ps_domain, compl3[1], cn_nr := 2, inc_countername := "cnpool:subscr:known");
2290
2291 f_shutdown_helper();
2292}
2293
Neels Hofmeyrb1bf16d2023-06-27 02:10:04 +02002294/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
2295 * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
2296friend function f_tc_mscpool_paging_imsi(charstring id, TestHdlrParams pars) runs on ConnHdlr {
2297 f_init_handler(pars);
2298
2299 var hexstring imsi := '001010000000123'H;
2300 var RANAP_IEs.CN_DomainIndicator domain_ind;
2301 if (pars.ps_domain) {
2302 domain_ind := ps_domain;
2303 } else {
2304 domain_ind := cs_domain;
2305 }
2306 var template (value) RANAP_PDU paging := ts_RANAP_Paging(domain_ind, imsi_hex2oct(imsi));
2307 BSSAP.send(ts_RANAP_UNITDATA_req(pars.sccp_addr_hnbgw, pars.sccp_addr_msc, paging));
2308 /* TODO: Expect RUA ConnectionlessTransfer Paging (on all HNB).
2309 * We could verify the Paging sent from osmo-hnbgw to RUA with some effort,
2310 * but, this test does not care whether the Paging was forwarded to RUA or not, only that osmo-hnbgw *received*
2311 * the Paging. In the CN pool decisions, osmo-hnbgw should match up Paging Response to an earlier Paging.
2312 */
2313
2314 f_sleep(1.0);
2315
2316 /* Despite the round robin pointing at the second MSC ('roundrobin next msc 1'), the earlier Paging for the same IMSI
2317 * causes this Paging Response to go to the first MSC ('msc 0'). */
2318 f_perform_compl_l3(f_gen_one_compl_l3(PAGRESP, ts_MI_IMSI_LV(imsi)));
2319 f_sleep(1.0);
2320}
2321
2322testcase TC_mscpool_paging_imsi() runs on test_CT {
2323 f_init(nr_msc := 3);
2324 f_sleep(1.0);
2325
2326 var boolean ps_domain := false;
2327
2328 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
2329 * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
2330 f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
2331
2332 f_ctrs_cn_init(ps_domain := ps_domain);
2333
2334 var ConnHdlr vc_conn1;
2335 var template (value) TestHdlrParams pars1 := t_pars(0, ps_domain := ps_domain, cn_nr := 0);
2336 pars1.sccp_addr_hnbgw := g_cn[valueof(pars1.cn_idx)].sccp_addr_peer;
2337 pars1.sccp_addr_msc := g_cn[valueof(pars1.cn_idx)].sccp_addr_own;
2338 vc_conn1 := f_start_handler_with_pars(refers(f_tc_mscpool_paging_imsi), pars1);
2339 vc_conn1.done;
2340 f_ctrs_cn_expect(0, "cnpool:subscr:paged");
2341 f_shutdown_helper();
2342}
2343
2344/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
2345 * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
2346friend function f_tc_mscpool_paging_tmsi(charstring id, TestHdlrParams pars) runs on ConnHdlr {
2347 f_init_handler(pars);
2348
2349 var hexstring imsi := '001010000000124'H;
2350 var integer nri_v := 300; /* <-- second MSC's NRI */
2351 var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
2352
2353 var RANAP_IEs.CN_DomainIndicator domain_ind;
2354 if (pars.ps_domain) {
2355 domain_ind := ps_domain;
2356 } else {
2357 domain_ind := cs_domain;
2358 }
2359 var template (value) RANAP_PDU paging := ts_RANAP_Paging_temp_id(domain_ind, imsi_hex2oct(imsi),
2360 ts_RANAP_TemporaryUE_ID_TMSI(tmsi));
2361 BSSAP.send(ts_RANAP_UNITDATA_req(pars.sccp_addr_hnbgw, pars.sccp_addr_msc, paging));
2362 /* TODO: Expect RUA ConnectionlessTransfer Paging (on all HNB).
2363 * We could verify the Paging sent from osmo-hnbgw to RUA with some effort,
2364 * but, this test does not care whether the Paging was forwarded to RUA or not, only that osmo-hnbgw *received*
2365 * the Paging. In the CN pool decisions, osmo-hnbgw should match up Paging Response to an earlier Paging.
2366 */
2367
2368 f_sleep(1.0);
2369
2370 /* Despite the round robin pointing at the third MSC ('roundrobin next msc 2'), the earlier Paging for the same
2371 * TMSI causes this Paging Response to go to the first MSC ('msc 0'). */
2372 f_perform_compl_l3(f_gen_one_compl_l3(PAGRESP, ts_MI_TMSI_NRI_LV(nri_v)));
2373 f_sleep(1.0);
2374}
2375testcase TC_mscpool_paging_tmsi() runs on test_CT {
2376 f_init(nr_msc := 3);
2377 f_sleep(1.0);
2378
2379 var boolean ps_domain := false;
2380
2381 /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
2382 * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
2383 f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
2384
2385 f_ctrs_cn_init(ps_domain := ps_domain);
2386
2387 var ConnHdlr vc_conn1;
2388 var template (value) TestHdlrParams pars1 := t_pars(0, ps_domain := ps_domain, cn_nr := 0);
2389 pars1.sccp_addr_hnbgw := g_cn[valueof(pars1.cn_idx)].sccp_addr_peer;
2390 pars1.sccp_addr_msc := g_cn[valueof(pars1.cn_idx)].sccp_addr_own;
2391 vc_conn1 := f_start_handler_with_pars(refers(f_tc_mscpool_paging_tmsi), pars1);
2392 vc_conn1.done;
2393 f_ctrs_cn_expect(0, "cnpool:subscr:paged");
2394 f_shutdown_helper();
2395}
2396
Neels Hofmeyr7d0e6802023-04-20 20:43:55 +02002397/* For round-robin, skip a CN link that has 'no allow-attach' set. */
2398testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
2399
2400 f_init(nr_msc := 3);
2401 f_sleep(1.0);
2402
2403 var boolean ps_domain := false;
2404
2405 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
2406 f_vty_cnlink_allow_attach(HNBGWVTY, ps_domain, {true, false, true});
2407
2408 /* Control which MSC gets chosen next by the round-robin, otherwise
2409 * would be randomly affected by which other tests ran before this. */
2410 f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
2411
2412 f_ctrs_cn_init(ps_domain := ps_domain);
2413
2414 f_TC_cnpool_compl_l3_list(ps_domain, f_gen_compl3_by_domain(ps_domain, 3),
2415 /* msc 1 is skipped */
2416 {0, 2, 0},
2417 "cnpool:subscr:new");
2418
2419 f_shutdown_helper();
2420}
2421
2422/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
2423 * TMSI NRI. */
2424testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
2425
2426 f_init(nr_msc := 3);
2427 f_sleep(1.0);
2428
2429 var boolean ps_domain := false;
2430
2431 /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
2432 f_vty_cnlink_allow_attach(HNBGWVTY, ps_domain, {true, false, true});
2433
2434 /* Control which MSC gets chosen next by the round-robin, otherwise
2435 * would be randomly affected by which other tests ran before this. */
2436 f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
2437
2438 f_ctrs_cn_init(ps_domain := ps_domain);
2439
2440 var ro_MobileIdentityLV mis := {
2441 valueof(ts_MI_TMSI_NRI_LV(260)),
2442 valueof(ts_MI_IMSI_LV('001010000000002'H)),
2443 valueof(ts_MI_IMSI_LV('001010000000003'H))
2444 };
2445
2446 var ro_octetstring compl3 := f_gen_compl3_by_domain(ps_domain, 3, mis);
2447
2448 /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
2449 f_TC_cnpool_compl_l3(ps_domain, compl3[0], cn_nr := 1, inc_countername := "cnpool:subscr:known");
2450
2451 /* Normal round robin skips msc 1, because it has 'no allow-attach' */
2452 f_TC_cnpool_compl_l3(ps_domain, compl3[1], cn_nr := 0, inc_countername := "cnpool:subscr:new");
2453 f_TC_cnpool_compl_l3(ps_domain, compl3[2], cn_nr := 2, inc_countername := "cnpool:subscr:new");
2454
2455 f_shutdown_helper();
2456}
2457
2458/* When a peer point-code gets an SCCP N-PCSTATE saying it is unreachable, immediately mark the CN link as unusable. */
2459testcase TC_mscpool_sccp_n_pcstate_detaches_cnlink() runs on test_CT {
2460 f_TC_cnpool_sccp_n_pcstate_detaches_cnlink(ps_domain := false);
2461}
2462testcase TC_sgsnpool_sccp_n_pcstate_detaches_cnlink() runs on test_CT {
2463 f_TC_cnpool_sccp_n_pcstate_detaches_cnlink(ps_domain := true);
2464}
2465function f_TC_cnpool_sccp_n_pcstate_detaches_cnlink(boolean ps_domain) runs on test_CT
2466{
2467
2468 f_init(nr_msc := 2, nr_sgsn := 2);
2469 f_sleep(1.0);
2470
2471 /* Control which MSC gets chosen next by the round-robin, otherwise
2472 * would be randomly affected by which other tests ran before this. */
2473 f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
2474
2475 f_ctrs_cn_init(ps_domain := ps_domain);
2476
2477 var ro_octetstring compl3 := f_gen_compl3_by_domain(ps_domain, 3);
2478
2479 f_TC_cnpool_compl_l3(ps_domain, compl3[0], cn_nr := 0, inc_countername := "cnpool:subscr:new");
2480 f_TC_cnpool_compl_l3(ps_domain, compl3[1], cn_nr := 1, inc_countername := "cnpool:subscr:new");
2481
2482 f_logp(HNBGWVTY, "disconnecting msc0");
2483 f_cn_idx_disconnect(f_cn_idx(ps_domain, 0));
2484
2485 /* Now round-robin would wrap to the first MSC, but since the first MSC is disconnected, it wraps around to the
2486 * second. */
2487 f_TC_cnpool_compl_l3(ps_domain, compl3[2], cn_nr := 1, inc_countername := "cnpool:subscr:new");
2488
2489 f_shutdown_helper();
2490}
2491
2492/* When a CN link point-code gets an SCCP N-PCSTATE saying it is now reachable, immediately trigger RESET and bring up the
2493 * MSC. */
2494testcase TC_mscpool_sccp_n_pcstate_attaches_cnlink() runs on test_CT {
2495 f_TC_cnpool_sccp_n_pcstate_attaches_cnlink(ps_domain := false);
2496}
2497testcase TC_sgsnpool_sccp_n_pcstate_attaches_cnlink() runs on test_CT {
2498 f_TC_cnpool_sccp_n_pcstate_attaches_cnlink(ps_domain := true);
2499}
2500function f_TC_cnpool_sccp_n_pcstate_attaches_cnlink(boolean ps_domain) runs on test_CT
2501{
2502 f_init(nr_msc := 1, nr_sgsn := 1);
2503 f_sleep(1.0);
2504
2505 /* Control which MSC gets chosen next by the round-robin, otherwise
2506 * would be randomly affected by which other tests ran before this. */
2507 f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
2508
2509 var ro_octetstring compl3 := f_gen_compl3_by_domain(ps_domain, 3);
2510
2511 f_ctrs_cn_init(ps_domain := ps_domain);
2512
2513 /* There is only one MSC, round robin stays on msc0 */
2514 f_TC_cnpool_compl_l3(ps_domain := ps_domain, nas_pdu := compl3[0], cn_nr := 0, inc_countername := "cnpool:subscr:new");
2515 f_TC_cnpool_compl_l3(ps_domain := ps_domain, nas_pdu := compl3[1], cn_nr := 0, inc_countername := "cnpool:subscr:new");
2516
2517 f_logp(HNBGWVTY, "connecting cnlink 1");
2518 f_cn_nr_init(ps_domain, 1);
2519 f_vty_cnlink_allow_attach(HNBGWVTY, ps_domain, { true, true });
2520 f_sleep(1.0);
2521
2522 /* This time round-robin wraps to the second MSC, because it is now online. */
2523 f_TC_cnpool_compl_l3(ps_domain := ps_domain, nas_pdu := compl3[2], cn_nr := 1, inc_countername := "cnpool:subscr:new");
2524
2525 f_shutdown_helper();
2526}
2527
Neels Hofmeyrd019cc02023-06-02 16:31:23 +02002528private function f_vty_add_sccp_addr(TELNETasp_PT pt, charstring addr_name, charstring pc, integer cs7_nr := 0)
2529{
2530 f_vty_enter_config(pt);
2531 f_vty_transceive(pt, "cs7 instance 0");
2532 f_vty_transceive(pt, "sccp-address " & addr_name);
2533 f_vty_transceive(pt, "point-code " & pc);
2534 f_vty_transceive(pt, "end");
2535}
2536
2537private function f_vty_set_cnlink_addr(TELNETasp_PT pt, charstring cnlink_and_nr, charstring addr_name)
2538{
2539 f_vty_enter_config(pt);
2540 f_vty_transceive(pt, cnlink_and_nr);
2541 f_vty_transceive(pt, "remote-addr " & addr_name);
2542 f_vty_transceive(pt, "end");
2543}
2544
2545private function f_vty_apply_sccp(TELNETasp_PT pt)
2546{
2547 f_vty_enter_config(pt);
2548 f_vty_transceive(pt, "apply sccp");
2549 f_vty_transceive(pt, "end");
2550}
2551
2552template (present) RUA_Disc_Req tr_RUA_Disc_Req := {
2553 ranap := ?,
2554 cause := ?
2555};
2556
2557/* With a cnlink up, change the SCCP address, and verify that it restarts upon vty 'apply sccp' */
2558private function f_tc_apply_sccp(charstring id, TestHdlrParams pars) runs on ConnHdlr
2559{
2560 f_init_handler(pars);
2561 f_perform_compl_l3(f_gen_compl3_by_domain(pars.ps_domain, 1)[0]);
2562
2563 f_sleep(1.0);
2564 f_logp(HNBGWVTY, "Changing SCCP address, don't apply yet");
2565
2566 f_vty_add_sccp_addr(HNBGWVTY, "msc-foo", "0.42.4");
2567 f_vty_set_cnlink_addr(HNBGWVTY, "msc 0", "msc-foo");
2568
2569 /* No effect yet, link still open both ways */
2570 f_sleep(1.0);
2571 f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
2572 f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
2573
2574 f_logp(HNBGWVTY, "Apply SCCP address changes");
2575 f_vty_apply_sccp(HNBGWVTY);
2576
2577 /* We modified the SCCP configuration, expect disconnect of UE that was active on the aborted link. */
2578 RUA.receive(RUA_Disc_Ind:?);
2579 BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
2580
2581 /* Would be nice to test reconnection on the other point-code, too. That would require another cnlink in
2582 * osmo-stp.cfg and module parameters... */
2583
2584 f_sleep(1.0);
2585}
2586testcase TC_apply_sccp() runs on test_CT
2587{
2588 f_init();
2589 f_sleep(1.0);
2590
2591 var ConnHdlr vc_conn;
2592 var template (value) TestHdlrParams pars := t_pars(0);
2593 vc_conn := f_start_handler_with_pars(refers(f_tc_apply_sccp), pars);
2594 vc_conn.done;
2595
2596 f_shutdown_helper();
2597}
2598
Neels Hofmeyrc3c01d32023-11-07 02:19:00 +01002599/* In the field, we encountered a "normal" RAB Assignment that concludes successfully, followed by another RAB
2600 * Assignment that has different SDU subflow parameters, and does not contain RTP information. At the time of writing,
2601 * it seems that the second RAB Assignment causes a crash. Play through this scenario. */
2602friend function f_tc_second_rab_assignment(charstring id, TestHdlrParams pars) runs on ConnHdlr {
2603 var MgcpCommand mgcp_cmd;
2604 var RANAP_PDU tx;
2605 timer T := 5.0;
2606
2607 f_init_handler(pars);
2608 f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
2609
2610 tx := f_build_initial_ue(g_pars);
2611 f_iuh2iu_connect(tx);
2612
2613 f_create_rab(pars.mgcp_pars);
2614
2615 /* Now send a second RAB Assignment with different subflows and omitting transportLayerInformation. (Assuming
2616 * the first RAB Assignment's transportLayerInformation remains in use unchanged.) */
2617 var template RAB_SetupOrModifyList rab_sml;
2618 rab_sml := ts_RAB_SML2(t_RAB_id(23),
2619 ts_RabParams,
2620 user_plane_info := omit,
2621 transport_layer_info := omit);
2622 tx := valueof(ts_RANAP_RabAssReq(rab_sml));
2623 BSSAP.send(tx);
2624 T.start;
2625
2626 /* Expect this secondary RAB Assignment to go through unchanged. */
2627 f_rua_expect(tx);
2628
2629 /* I'm guessing that the RAB Assignment Response also omits transportLayerInformation, so far not known because
2630 * osmo-hnbgw crashed before we could receive the response. */
2631
2632 /* Send back RAB Assignment Response via Iuh */
2633 var template RAB_SetupOrModifiedList rab_smdl;
2634 rab_smdl := ts_RAB_SMdL_no_tla(t_RAB_id(23));
2635 tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
2636 RUA.send(tx);
2637 f_bssap_expect(tx);
2638
2639 /* Send Iu Release */
2640 tx := valueof(ts_RANAP_IuReleaseCommand(ts_RanapCause_om_intervention));
2641 f_iu2iuh(tx);
2642
2643 T.start;
2644 alt {
2645 [] as_mgcp_dlcx(pars) {}
2646 [] T.timeout {
2647 setverdict(fail, "Timeout waiting for DLCX");
2648 }
2649 }
2650
2651 tx := valueof(ts_RANAP_IuReleaseComplete());
2652 f_iuh2iu(tx);
2653}
2654
2655testcase TC_second_rab_assignment() runs on test_CT {
2656 var ConnHdlr vc_conn;
2657 g_num_hnbs := 1;
2658 f_init();
2659
2660 vc_conn := f_start_handler_with_pars(refers(f_tc_second_rab_assignment), t_pars(3));
2661 vc_conn.done;
2662
2663 f_shutdown_helper();
2664}
2665
Daniel Willmann19b8d902022-01-05 09:12:34 +01002666control {
2667 execute(TC_hnb_register());
Daniel Willmannc79679a2022-08-23 17:48:39 +02002668 execute(TC_hnb_register_duplicate());
Pau Espin Pedrolacf4f222022-09-27 14:33:40 +02002669 execute(TC_hnb_register_duplicate_reuse_sctp_assoc());
Daniel Willmann19b8d902022-01-05 09:12:34 +01002670 execute(TC_ranap_cs_initial_ue());
2671 execute(TC_ranap_ps_initial_ue());
Neels Hofmeyrf0b9ed12022-06-07 17:46:32 +02002672 execute(TC_ranap_cs_initial_ue_empty_cr());
2673 execute(TC_ranap_ps_initial_ue_empty_cr());
Daniel Willmann19b8d902022-01-05 09:12:34 +01002674 execute(TC_ranap_cs_bidir());
2675 execute(TC_ranap_ps_bidir());
2676 execute(TC_rab_assignment());
2677 execute(TC_rab_release());
Daniel Willmann3e15b7b2022-02-21 17:07:02 +01002678 execute(TC_rab_assign_fail());
Daniel Willmann37c877f2022-02-22 16:47:06 +01002679 execute(TC_rab_assign_mgcp_to());
Daniel Willmann19b8d902022-01-05 09:12:34 +01002680 execute(TC_ranap_cs_mo_disconnect());
2681 execute(TC_ranap_ps_mo_disconnect());
Neels Hofmeyrbacb74f2022-08-29 16:24:12 +02002682
2683 if (mp_enable_pfcp_tests) {
2684 execute(TC_ps_rab_assignment_with_pfcp());
2685 } else {
2686 execute(TC_ps_rab_assignment_without_pfcp());
2687 }
Pau Espin Pedrolf0b9fa02022-09-12 13:31:07 +02002688
Neels Hofmeyr7d0e6802023-04-20 20:43:55 +02002689 execute( TC_mscpool_L3Compl_on_1_cnlink() );
2690 execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
2691 execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
2692 execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
2693 execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
2694 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
2695 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
2696 execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
2697 execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
Neels Hofmeyrb1bf16d2023-06-27 02:10:04 +02002698 execute( TC_mscpool_paging_imsi() );
2699 execute( TC_mscpool_paging_tmsi() );
Neels Hofmeyr7d0e6802023-04-20 20:43:55 +02002700 execute( TC_mscpool_no_allow_attach_round_robin() );
2701 execute( TC_mscpool_no_allow_attach_valid_nri() );
2702 execute( TC_mscpool_sccp_n_pcstate_detaches_cnlink() );
2703 execute( TC_mscpool_sccp_n_pcstate_attaches_cnlink() );
2704
2705 execute( TC_sgsnpool_L3Compl_on_1_cnlink() );
2706 execute( TC_sgsnpool_L3Complete_no_nri_round_robin() );
2707 execute( TC_sgsnpool_L3Complete_valid_nri_1() );
2708 execute( TC_sgsnpool_L3Complete_valid_nri_2() );
2709 execute( TC_sgsnpool_nri_from_other_PLMN() );
2710 execute( TC_sgsnpool_sccp_n_pcstate_detaches_cnlink() );
2711 execute( TC_sgsnpool_sccp_n_pcstate_attaches_cnlink() );
2712
Oliver Smithaa919b42023-11-14 11:30:55 +01002713 /* Run only on nightly since it makes osmo-hnbgw <= 1.5.0 crash: OS#6253 */
2714 if (f_osmo_repo_is("nightly")) {
2715 execute(TC_second_rab_assignment());
2716 }
Neels Hofmeyrc3c01d32023-11-07 02:19:00 +01002717
Pau Espin Pedrolf0b9fa02022-09-12 13:31:07 +02002718 /* Run at the end since it makes osmo-hnbgw <= 1.3.0 crash: OS#5676 */
2719 execute(TC_hnb_reregister_reuse_sctp_assoc());
Neels Hofmeyrd019cc02023-06-02 16:31:23 +02002720
2721 /* Run at the end since it messes with the SCCP config */
2722 execute( TC_apply_sccp() );
Daniel Willmann19b8d902022-01-05 09:12:34 +01002723}
2724
2725}