blob: e3e61f47ce6892439712e1d090b81b30a63ef53c [file] [log] [blame]
Daniel Willmann423d8f42020-09-08 18:58:22 +02001module GBProxy_Tests {
2
3/* Osmocom GBProxy test suite in TTCN-3
Harald Welte207166c2021-01-16 12:52:30 +01004 * (C) 2020-2021 Harald Welte <laforge@osmocom.org>
Daniel Willmann423d8f42020-09-08 18:58:22 +02005 * (C) 2020 sysmocom - s.f.m.c. GmbH
6 * All rights reserved.
7 *
8 * Author: Daniel Willmann <dwillmann@sysmocom.de>
9
10 * Released under the terms of GNU General Public License, Version 2 or
11 * (at your option) any later version.
12 *
13 * SPDX-License-Identifier: GPL-2.0-or-later
14 */
15
16import from General_Types all;
17import from Osmocom_Types all;
Harald Welteb9f0fdc2020-12-09 14:44:50 +010018import from Misc_Helpers all;
Daniel Willmann423d8f42020-09-08 18:58:22 +020019import from GSM_Types all;
20import from Native_Functions all;
21import from NS_Types all;
22import from NS_Emulation all;
23import from BSSGP_Types all;
24import from BSSGP_Emulation all;
25import from SCCPasp_Types all;
26import from Osmocom_Gb_Types all;
27
28import from MobileL3_CommonIE_Types all;
29import from MobileL3_GMM_SM_Types all;
30import from MobileL3_Types all;
31import from L3_Templates all;
32import from L3_Common all;
33
34import from TELNETasp_PortType all;
35import from Osmocom_VTY_Functions all;
36
37import from LLC_Types all;
38import from LLC_Templates all;
39
40import from GSM_RR_Types all;
41
Harald Welte6d63f742020-11-15 19:44:04 +010042/* mcc_mnc is 24.008 10.5.5.15 encoded. 262 42 */
43const BcdMccMnc c_mcc_mnc := '262F42'H;
44
Harald Welte0d5fceb2020-11-29 16:04:07 +010045/* 48.016 section 6.1.4.2: The default maximum information field size of 1600 octets shall be supported on the Gb interface */
46const integer max_fr_info_size := 1600;
47
Daniel Willmann423d8f42020-09-08 18:58:22 +020048modulepar {
Harald Welte77218d02021-01-15 19:59:15 +010049 /* NRI bit-length. 0 for no pooling */
50 integer mp_nri_bitlength := 5;
51 roro_integer mp_sgsn_nri := {
52 { 3 }, /* list of NRIs of first SGSN */
53 { 4 } /* list of NRIs of second SGSN */
54 };
Harald Weltef6e59b02020-12-08 08:29:09 +010055 boolean mp_enable_bss_load_sharing := false;
Daniel Willmann2c9300f2020-12-01 10:54:08 +010056 /* SGSN NS configuration */
Harald Welte6d63f742020-11-15 19:44:04 +010057 NSConfigurations mp_nsconfig_sgsn := {
Daniel Willmann423d8f42020-09-08 18:58:22 +020058 {
Daniel Willmann423d8f42020-09-08 18:58:22 +020059 nsei := 101,
60 role_sgsn := true,
Harald Welte90f19742020-11-06 19:34:40 +010061 handle_sns := false,
62 nsvc := {
63 {
64 provider := {
65 ip := {
66 address_family := AF_INET,
67 local_udp_port := 7777,
Harald Welted05a4a92021-01-18 12:03:53 +010068 local_ip := "127.0.0.10",
Harald Welte90f19742020-11-06 19:34:40 +010069 remote_udp_port := 23000,
Harald Weltebe7afce2021-01-17 22:04:36 +010070 remote_ip := "127.0.0.1",
Harald Welte388057d2021-01-18 18:52:49 +010071 data_weight := 0,
Harald Weltebe7afce2021-01-17 22:04:36 +010072 signalling_weight := 1
Harald Welte90f19742020-11-06 19:34:40 +010073 }
74 },
75 nsvci := 101
Harald Welte388057d2021-01-18 18:52:49 +010076 }, {
77 provider := {
78 ip := {
79 address_family := AF_INET,
80 local_udp_port := 7770,
81 local_ip := "127.0.0.10",
82 remote_udp_port := 23000,
83 remote_ip := "127.0.0.1",
84 data_weight := 1,
85 signalling_weight := 0
86 }
87 },
88 nsvci := 201
Harald Welte90f19742020-11-06 19:34:40 +010089 }
Harald Weltebe7afce2021-01-17 22:04:36 +010090
Harald Welte90f19742020-11-06 19:34:40 +010091 }
Harald Welteb978ed62020-12-12 14:01:11 +010092 }, {
93 nsei := 102,
94 role_sgsn := true,
95 handle_sns := false,
96 nsvc := {
97 {
98 provider := {
99 ip := {
100 address_family := AF_INET,
101 local_udp_port := 8888,
Harald Welted05a4a92021-01-18 12:03:53 +0100102 local_ip := "127.0.0.11",
Harald Welteb978ed62020-12-12 14:01:11 +0100103 remote_udp_port := 23000,
Harald Weltebe7afce2021-01-17 22:04:36 +0100104 remote_ip := "127.0.0.1",
Harald Welte388057d2021-01-18 18:52:49 +0100105 data_weight := 0,
Harald Weltebe7afce2021-01-17 22:04:36 +0100106 signalling_weight := 1
Harald Welteb978ed62020-12-12 14:01:11 +0100107 }
108 },
109 nsvci := 102
Harald Welte388057d2021-01-18 18:52:49 +0100110 }, {
111 provider := {
112 ip := {
113 address_family := AF_INET,
114 local_udp_port := 8880,
115 local_ip := "127.0.0.11",
116 remote_udp_port := 23000,
117 remote_ip := "127.0.0.1",
118 data_weight := 1,
119 signalling_weight := 0
120 }
121 },
122 nsvci := 202
Harald Welteb978ed62020-12-12 14:01:11 +0100123 }
124 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200125 }
126 };
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100127 /* BSS NSEI start at 2000 + x
128 * NSVCI start from value of NSEI + 100
129 * UDP port is NSVCI * 10 */
Harald Welte6d63f742020-11-15 19:44:04 +0100130 NSConfigurations mp_nsconfig_pcu := {
Daniel Willmann423d8f42020-09-08 18:58:22 +0200131 {
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100132 nsei := 2001,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200133 role_sgsn := false,
Harald Welte90f19742020-11-06 19:34:40 +0100134 handle_sns := false,
135 nsvc := {
136 {
137 provider := {
138 ip := {
139 address_family := AF_INET,
140 local_udp_port := 21010,
Harald Welted05a4a92021-01-18 12:03:53 +0100141 local_ip := "127.0.1.1",
Harald Welte90f19742020-11-06 19:34:40 +0100142 remote_udp_port := 23000,
Harald Weltebe7afce2021-01-17 22:04:36 +0100143 remote_ip := "127.0.0.1",
144 data_weight := 1,
145 signalling_weight := 1
Harald Welte90f19742020-11-06 19:34:40 +0100146 }
147 },
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100148 nsvci := 2101
Harald Welte90f19742020-11-06 19:34:40 +0100149 }
150 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200151 },
152 {
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100153 nsei := 2002,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200154 role_sgsn := false,
Harald Welte90f19742020-11-06 19:34:40 +0100155 handle_sns := false,
156 nsvc := {
157 {
158 provider := {
159 ip := {
160 address_family := AF_INET,
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100161 local_udp_port := 21020,
Harald Welted05a4a92021-01-18 12:03:53 +0100162 local_ip := "127.0.2.1",
Harald Welte90f19742020-11-06 19:34:40 +0100163 remote_udp_port := 23000,
Harald Weltebe7afce2021-01-17 22:04:36 +0100164 remote_ip := "127.0.0.1",
165 data_weight := 1,
166 signalling_weight := 1
Harald Welte90f19742020-11-06 19:34:40 +0100167 }
168 },
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100169 nsvci := 2102
Harald Welte90f19742020-11-06 19:34:40 +0100170 }
171 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200172 },
173 {
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100174 nsei := 2003,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200175 role_sgsn := false,
Harald Welte90f19742020-11-06 19:34:40 +0100176 handle_sns := false,
177 nsvc := {
178 {
179 provider := {
180 ip := {
181 address_family := AF_INET,
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100182 local_udp_port := 21030,
Harald Welted05a4a92021-01-18 12:03:53 +0100183 local_ip := "127.0.3.1",
Harald Welte90f19742020-11-06 19:34:40 +0100184 remote_udp_port := 23000,
Harald Weltebe7afce2021-01-17 22:04:36 +0100185 remote_ip := "127.0.0.1",
186 data_weight := 1,
187 signalling_weight := 1
Harald Welte90f19742020-11-06 19:34:40 +0100188 }
189 },
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100190 nsvci := 2103
Harald Welte90f19742020-11-06 19:34:40 +0100191 }
192 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200193 }
194 };
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100195 /* BVCI are NSEI*10 + x
196 * The first NSE only has one BVC, the second one 2 and so on
197 * The Cell ID is BVCI + 10000
198 * LAC/RAC are configured in such a way that:
199 * LAC 13135 is present once in NSE(2001), twice in NSE(2002) and once in NSE(2003)
200 * LAC 13300 is present twice in NSE(2003)
201 * RAI 13135-1 is present in NSE(2002) and NSE(2003)
202 * RAI 13300-0 is present twice in NSE(2003)
203 */
Harald Welte6d63f742020-11-15 19:44:04 +0100204 BssgpConfigs mp_gbconfigs := {
205 {
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100206 nsei := 2001,
Harald Welte6d63f742020-11-15 19:44:04 +0100207 sgsn_role := false,
208 bvc := {
209 {
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100210 bvci := 20011,
Harald Welte6d63f742020-11-15 19:44:04 +0100211 cell_id := {
212 ra_id := {
213 lai := {
214 mcc_mnc := c_mcc_mnc,
215 lac := 13135
216 },
217 rac := 0
218 },
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100219 cell_id := 30011
Harald Welte6d63f742020-11-15 19:44:04 +0100220 },
221 depth := BSSGP_DECODE_DEPTH_BSSGP,
222 create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
223 }
224 }
225 }, {
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100226 nsei := 2002,
Harald Welte6d63f742020-11-15 19:44:04 +0100227 sgsn_role := false,
228 bvc := {
229 {
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100230 bvci := 20021,
Harald Welte6d63f742020-11-15 19:44:04 +0100231 cell_id := {
232 ra_id := {
233 lai := {
234 mcc_mnc := c_mcc_mnc,
Harald Welte0e188242020-11-22 21:46:48 +0100235 lac := 13135
Harald Welte6d63f742020-11-15 19:44:04 +0100236 },
Harald Welte0e188242020-11-22 21:46:48 +0100237 rac := 1
Harald Welte6d63f742020-11-15 19:44:04 +0100238 },
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100239 cell_id := 30021
240 },
241 depth := BSSGP_DECODE_DEPTH_BSSGP,
242 create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
243 },
244 {
245 bvci := 20022,
246 cell_id := {
247 ra_id := {
248 lai := {
249 mcc_mnc := c_mcc_mnc,
250 lac := 13135
251 },
252 rac := 2
253 },
254 cell_id := 30022
Harald Welte6d63f742020-11-15 19:44:04 +0100255 },
256 depth := BSSGP_DECODE_DEPTH_BSSGP,
257 create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
258 }
259 }
260 }, {
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100261 nsei := 2003,
Harald Welte6d63f742020-11-15 19:44:04 +0100262 sgsn_role := false,
263 bvc := {
264 {
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100265 bvci := 20031,
266 cell_id := {
267 ra_id := {
268 lai := {
269 mcc_mnc := c_mcc_mnc,
270 lac := 13135
271 },
272 rac := 1
273 },
274 cell_id := 30031
275 },
276 depth := BSSGP_DECODE_DEPTH_BSSGP,
277 create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
278 },
279 {
280 bvci := 20032,
Harald Welte6d63f742020-11-15 19:44:04 +0100281 cell_id := {
282 ra_id := {
283 lai := {
284 mcc_mnc := c_mcc_mnc,
285 lac := 13300
286 },
287 rac := 0
288 },
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100289 cell_id := 30032
290 },
291 depth := BSSGP_DECODE_DEPTH_BSSGP,
292 create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
293 },
294 {
295 bvci := 20033,
296 cell_id := {
297 ra_id := {
298 lai := {
299 mcc_mnc := c_mcc_mnc,
300 lac := 13300
301 },
302 rac := 0
303 },
304 cell_id := 30033
Harald Welte6d63f742020-11-15 19:44:04 +0100305 },
306 depth := BSSGP_DECODE_DEPTH_BSSGP,
307 create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
308 }
309 }
310 }
311 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200312};
313
Daniel Willmann423d8f42020-09-08 18:58:22 +0200314type record GbInstance {
315 NS_CT vc_NS,
316 BSSGP_CT vc_BSSGP,
Harald Welte67dc8c22020-11-17 18:32:29 +0100317 BSSGP_BVC_CTs vc_BSSGP_BVC,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200318 BssgpConfig cfg
319};
Harald Welte67dc8c22020-11-17 18:32:29 +0100320type record of BSSGP_BVC_CT BSSGP_BVC_CTs
Daniel Willmann423d8f42020-09-08 18:58:22 +0200321
322const integer NUM_PCU := 3;
Harald Welte6d63f742020-11-15 19:44:04 +0100323type record of GbInstance GbInstances;
324type record of BssgpConfig BssgpConfigs;
325type record of NSConfiguration NSConfigurations;
326type record of BssgpCellId BssgpCellIds;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200327
Harald Welteb978ed62020-12-12 14:01:11 +0100328const integer NUM_SGSN := 2;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200329
330type component test_CT {
Harald Welte6d63f742020-11-15 19:44:04 +0100331 var GbInstances g_pcu;
332 var GbInstances g_sgsn;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200333
334 port BSSGP_CT_PROC_PT PROC;
335
Harald Weltefbae83f2020-11-15 23:25:55 +0100336 port BSSGP_BVC_MGMT_PT SGSN_MGMT;
337 port BSSGP_BVC_MGMT_PT PCU_MGMT;
338
Daniel Willmann423d8f42020-09-08 18:58:22 +0200339 port TELNETasp_PT GBPVTY;
340
341 var boolean g_initialized := false;
342 var boolean g_use_echo := false;
Harald Welte16786e92020-11-27 19:11:56 +0100343
344 var ro_integer g_roi := {};
Harald Welte425d3762020-12-09 14:33:18 +0100345 timer g_Tguard;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200346};
347
348type component BSSGP_ConnHdlr {
Harald Welte3dd21b32020-11-17 19:21:00 +0100349 /* array of per-BVC ports on the PCU side */
Harald Welte158becf2020-12-09 12:32:32 +0100350 port BSSGP_PT PCU_PTP[NUM_PCU];
Daniel Willmann423d8f42020-09-08 18:58:22 +0200351 port BSSGP_PT PCU_SIG[NUM_PCU];
352 port BSSGP_PROC_PT PCU_PROC[NUM_PCU];
Harald Welte3dd21b32020-11-17 19:21:00 +0100353 /* component reference to the component to which we're currently connected */
354 var BSSGP_BVC_CT pcu_ct[NUM_PCU];
Harald Welte0e188242020-11-22 21:46:48 +0100355 /* BSSGP BVC configuration of the component to which we're currently connected */
356 var BssgpBvcConfig pcu_bvc_cfg[NUM_PCU];
Harald Welte3dd21b32020-11-17 19:21:00 +0100357
358 /* array of per-BVC ports on the SGSN side */
Harald Welte158becf2020-12-09 12:32:32 +0100359 port BSSGP_PT SGSN_PTP[NUM_SGSN];
Daniel Willmann423d8f42020-09-08 18:58:22 +0200360 port BSSGP_PT SGSN_SIG[NUM_SGSN];
361 port BSSGP_PROC_PT SGSN_PROC[NUM_SGSN];
Harald Welte3dd21b32020-11-17 19:21:00 +0100362 /* component reference to the component to which we're currently connected */
363 var BSSGP_BVC_CT sgsn_ct[NUM_PCU];
Daniel Willmann423d8f42020-09-08 18:58:22 +0200364
365 var BSSGP_ConnHdlrPars g_pars;
366 timer g_Tguard;
367 var LLC_Entities llc;
Harald Welte0e188242020-11-22 21:46:48 +0100368
369 var ro_integer g_roi := {};
Daniel Willmann423d8f42020-09-08 18:58:22 +0200370}
371
372type record SGSN_ConnHdlrNetworkPars {
373 boolean expect_ptmsi,
374 boolean expect_auth,
375 boolean expect_ciph
376};
377
378type record BSSGP_ConnHdlrPars {
379 /* IMEI of the simulated ME */
380 hexstring imei,
381 /* IMSI of the simulated MS */
382 hexstring imsi,
383 /* MSISDN of the simulated MS (probably unused) */
384 hexstring msisdn,
385 /* P-TMSI allocated to the simulated MS */
386 OCT4 p_tmsi optional,
387 OCT3 p_tmsi_sig optional,
388 /* TLLI of the simulated MS */
389 OCT4 tlli,
390 OCT4 tlli_old optional,
391 RoutingAreaIdentificationV ra optional,
Harald Welte16357a92020-11-17 18:20:00 +0100392 GbInstances pcu,
Harald Welte3dd21b32020-11-17 19:21:00 +0100393 GbInstances sgsn,
Harald Weltec5f486b2021-01-16 11:07:01 +0100394 /* The SGSN index to be used within the test */
395 integer sgsn_idx,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200396 float t_guard
397};
398
Harald Welte04358652021-01-17 13:48:13 +0100399private function get_bvc_idx_for_bvci(GbInstance gbi, BssgpBvci bvci) return integer
400{
401 var integer i;
402
403 for (i := 0; i < lengthof(gbi.cfg.bvc); i := i + 1) {
404 if (gbi.cfg.bvc[i].bvci == bvci) {
405 return i;
406 }
407 }
408 setverdict(fail, "Could not find BVC Index for BVCI ", bvci);
409 return -1;
410}
411
Daniel Willmann423d8f42020-09-08 18:58:22 +0200412private function f_cellid_to_RAI(in BssgpCellId cell_id) return RoutingAreaIdentificationV {
413 /* mcc_mnc is encoded as of 24.008 10.5.5.15 */
414 var BcdMccMnc mcc_mnc := cell_id.ra_id.lai.mcc_mnc;
415
416 var RoutingAreaIdentificationV ret := {
417 mccDigit1 := mcc_mnc[0],
418 mccDigit2 := mcc_mnc[1],
419 mccDigit3 := mcc_mnc[2],
420 mncDigit3 := mcc_mnc[3],
421 mncDigit1 := mcc_mnc[4],
422 mncDigit2 := mcc_mnc[5],
423 lac := int2oct(cell_id.ra_id.lai.lac, 16),
424 rac := int2oct(cell_id.ra_id.rac, 8)
425 }
426 return ret;
427};
428
Harald Welte95339432020-12-02 18:50:52 +0100429private function f_fix_create_cb(inout BssgpConfig cfg)
430{
431 for (var integer i := 0; i < lengthof(cfg.bvc); i := i + 1) {
432 if (not isbound(cfg.bvc[i].create_cb)) {
433 cfg.bvc[i].create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
434 }
435 }
436}
437
Daniel Willmann423d8f42020-09-08 18:58:22 +0200438private function f_init_gb_pcu(inout GbInstance gb, charstring id, integer offset) runs on test_CT {
Harald Welteb419d0e2020-11-16 16:45:05 +0100439 var charstring ns_id := id & "-NS(PCU[" & int2str(offset) & "])";
440 var charstring bssgp_id := id & "-BSSGP(PCU[" & int2str(offset) & "])";
441 gb.vc_NS := NS_CT.create(ns_id);
442 gb.vc_BSSGP := BSSGP_CT.create(bssgp_id);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200443 /* connect lower end of BSSGP emulation with NS upper port */
444 connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
445
Harald Welteb419d0e2020-11-16 16:45:05 +0100446 gb.vc_NS.start(NSStart(mp_nsconfig_pcu[offset], ns_id));
447 gb.vc_BSSGP.start(BssgpStart(gb.cfg, bssgp_id));
Daniel Willmann423d8f42020-09-08 18:58:22 +0200448
449 for (var integer i := 0; i < lengthof(gb.cfg.bvc); i := i + 1) {
Harald Welteb978ed62020-12-12 14:01:11 +0100450 /* obtain the component reference of the BSSGP_BVC_CT for each PTP BVC */
Daniel Willmann423d8f42020-09-08 18:58:22 +0200451 connect(self:PROC, gb.vc_BSSGP:PROC);
452 gb.vc_BSSGP_BVC[i] := f_bssgp_get_bvci_ct(gb.cfg.bvc[i].bvci, PROC);
453 disconnect(self:PROC, gb.vc_BSSGP:PROC);
Harald Welteb978ed62020-12-12 14:01:11 +0100454 /* connect all of the per-BVC MGMT ports to our PCU_MGMT port (1:N) */
Harald Weltefbae83f2020-11-15 23:25:55 +0100455 connect(self:PCU_MGMT, gb.vc_BSSGP_BVC[i]:MGMT);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200456 }
Harald Welteb978ed62020-12-12 14:01:11 +0100457 /* connect all of the BSSGP/NSE global MGMT port to our PCU_MGMT port (1:N) */
Harald Welte16786e92020-11-27 19:11:56 +0100458 connect(self:PCU_MGMT, gb.vc_BSSGP:MGMT);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200459}
460
461private function f_init_gb_sgsn(inout GbInstance gb, charstring id, integer offset) runs on test_CT {
Harald Welteb419d0e2020-11-16 16:45:05 +0100462 var charstring ns_id := id & "-NS(SGSN[" & int2str(offset) & "])";
463 var charstring bssgp_id := id & "-BSSGP(SGSN[" & int2str(offset) & "])";
464 gb.vc_NS := NS_CT.create(ns_id);
465 gb.vc_BSSGP := BSSGP_CT.create(bssgp_id);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200466 /* connect lower end of BSSGP emulation with NS upper port */
467 connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
468
Harald Welteb419d0e2020-11-16 16:45:05 +0100469 gb.vc_NS.start(NSStart(mp_nsconfig_sgsn[offset], ns_id));
470 gb.vc_BSSGP.start(BssgpStart(gb.cfg, bssgp_id));
Daniel Willmann423d8f42020-09-08 18:58:22 +0200471
472 for (var integer i := 0; i < lengthof(gb.cfg.bvc); i := i + 1) {
Harald Welteb978ed62020-12-12 14:01:11 +0100473 /* obtain the component reference of the BSSGP_BVC_CT for each PTP BVC */
Daniel Willmann423d8f42020-09-08 18:58:22 +0200474 connect(self:PROC, gb.vc_BSSGP:PROC);
475 gb.vc_BSSGP_BVC[i] := f_bssgp_get_bvci_ct(gb.cfg.bvc[i].bvci, PROC);
476 disconnect(self:PROC, gb.vc_BSSGP:PROC);
Harald Welteb978ed62020-12-12 14:01:11 +0100477 /* connect all of the per-BVC MGMT ports to our SGSN_MGMT port (1:N) */
Harald Weltefbae83f2020-11-15 23:25:55 +0100478 connect(self:SGSN_MGMT, gb.vc_BSSGP_BVC[i]:MGMT);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200479 }
Harald Welteb978ed62020-12-12 14:01:11 +0100480 /* connect all of the BSSGP/NSE global MGMT port to our SGSN_MGMT port (1:N) */
Harald Welte16786e92020-11-27 19:11:56 +0100481 connect(self:SGSN_MGMT, gb.vc_BSSGP:MGMT);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200482}
483
484
Harald Welteb9f0fdc2020-12-09 14:44:50 +0100485private function f_destroy_gb(inout GbInstance gb) runs on test_CT {
486 gb.vc_NS.stop;
487 gb.vc_BSSGP.stop;
488
489 for (var integer i := 0; i < lengthof(gb.cfg.bvc); i := i + 1) {
490 gb.vc_BSSGP_BVC[i].stop;
491 }
492}
493
Daniel Willmann423d8f42020-09-08 18:58:22 +0200494private function f_init_vty() runs on test_CT {
495 map(self:GBPVTY, system:GBPVTY);
496 f_vty_set_prompts(GBPVTY);
497 f_vty_transceive(GBPVTY, "enable");
498}
499
Harald Weltefbae83f2020-11-15 23:25:55 +0100500type record of integer ro_integer;
501
502private function ro_integer_contains(ro_integer r, integer x) return boolean {
503 for (var integer j := 0; j < lengthof(r); j := j+1) {
504 if (r[j] == x) {
505 return true;
506 }
507 }
508 return false;
509}
510
Harald Welteb978ed62020-12-12 14:01:11 +0100511private type record of ro_integer roro_integer;
512
513/* count the number of unblocked BVCI for each SGSN NSE */
514private altstep as_count_unblocked4nse(integer sgsn_idx, inout roro_integer bvci_unblocked)
515runs on test_CT {
516 var BssgpStatusIndication bsi;
517 [] SGSN_MGMT.receive(BssgpStatusIndication:{g_sgsn[sgsn_idx].cfg.nsei, ?, BVC_S_UNBLOCKED}) -> value bsi {
518 bvci_unblocked[sgsn_idx] := bvci_unblocked[sgsn_idx] & { bsi.bvci };
519 /* 'repeat' until sufficient number of BVC-rest has been received on all SGSNs */
520 for (var integer i := 0; i < lengthof(bvci_unblocked); i := i+1) {
521 if (lengthof(bvci_unblocked[i]) < lengthof(g_sgsn[i].cfg.bvc)) {
522 repeat;
523 }
524 }
525 }
526}
527
Harald Welte425d3762020-12-09 14:33:18 +0100528function f_init(float t_guard := 30.0) runs on test_CT {
Harald Welteb978ed62020-12-12 14:01:11 +0100529 var roro_integer bvci_unblocked;
Harald Weltefbae83f2020-11-15 23:25:55 +0100530 var BssgpStatusIndication bsi;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200531 var integer i;
532
533 if (g_initialized == true) {
534 return;
535 }
536 g_initialized := true;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200537
Harald Welte425d3762020-12-09 14:33:18 +0100538 g_Tguard.start(t_guard);
539 activate(as_gTguard(g_Tguard));
540
Harald Welteb978ed62020-12-12 14:01:11 +0100541 var BssgpBvcConfigs bvcs := { };
Harald Welte6d63f742020-11-15 19:44:04 +0100542 for (i := 0; i < lengthof(mp_gbconfigs); i := i+1) {
543 g_pcu[i].cfg := mp_gbconfigs[i];
Harald Welte95339432020-12-02 18:50:52 +0100544 /* make sure all have a proper crate_cb, which cannot be specified in config file */
545 f_fix_create_cb(g_pcu[i].cfg);
Harald Welte6d63f742020-11-15 19:44:04 +0100546 /* concatenate all the PCU-side BVCs for the SGSN side */
Harald Welteb978ed62020-12-12 14:01:11 +0100547 bvcs := bvcs & g_pcu[i].cfg.bvc;
548 }
549
550 for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
551 g_sgsn[i].cfg := {
552 nsei := mp_nsconfig_sgsn[i].nsei,
553 sgsn_role := true,
554 bvc := bvcs
555 }
Harald Welte6d63f742020-11-15 19:44:04 +0100556 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200557
558 f_init_vty();
Harald Welte6d63f742020-11-15 19:44:04 +0100559 for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
Daniel Willmann443fc572020-11-18 13:26:57 +0100560 f_vty_transceive(GBPVTY, "nsvc nsei " & int2str(g_sgsn[i].cfg.nsei) & " force-unconfigured");
Daniel Willmannad93c052020-12-04 14:14:38 +0100561 }
562 for (i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
563 f_vty_transceive(GBPVTY, "nsvc nsei " & int2str(g_pcu[i].cfg.nsei) & " force-unconfigured");
564 f_vty_transceive(GBPVTY, "delete-gbproxy-peer " & int2str(g_pcu[i].cfg.nsei) & " only-bvc");
565 }
566
567 for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
Harald Welteea1ba592020-11-17 18:05:13 +0100568 f_init_gb_sgsn(g_sgsn[i], "GbProxy_Test", i);
Harald Welte6d63f742020-11-15 19:44:04 +0100569 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200570 f_sleep(4.0);
Harald Welte6d63f742020-11-15 19:44:04 +0100571 for (i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
Harald Welteb419d0e2020-11-16 16:45:05 +0100572 f_init_gb_pcu(g_pcu[i], "GbProxy_Test", i);
Harald Welte6d63f742020-11-15 19:44:04 +0100573 }
Harald Weltefbae83f2020-11-15 23:25:55 +0100574
Harald Welteb978ed62020-12-12 14:01:11 +0100575 for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
576 bvci_unblocked[i] := {};
577 }
578
Harald Weltefbae83f2020-11-15 23:25:55 +0100579 /* wait until all BVC are unblocked on both sides */
Harald Welted2801272020-11-17 19:22:58 +0100580 timer T := 15.0;
Harald Weltefbae83f2020-11-15 23:25:55 +0100581 T.start;
582 alt {
Harald Welteb978ed62020-12-12 14:01:11 +0100583 /* TODO: We need to add more lines if NUM_SGSN increases. Activating default altsteps
584 * unfortunately doesn't work as we want to access the local variable bvci_unblocked. */
585 [] as_count_unblocked4nse(0, bvci_unblocked);
586 [lengthof(g_sgsn) > 1] as_count_unblocked4nse(1, bvci_unblocked);
Harald Weltefbae83f2020-11-15 23:25:55 +0100587 [] SGSN_MGMT.receive(BssgpStatusIndication:{*, ?, ?}) {
588 repeat;
589 }
Harald Welte3c905152020-11-26 20:56:09 +0100590 [] SGSN_MGMT.receive(BssgpResetIndication:?) {
591 repeat;
592 }
Harald Weltefbae83f2020-11-15 23:25:55 +0100593 [] SGSN_MGMT.receive {
594 setverdict(fail, "Received unexpected message on SGSN_MGMT");
595 mtc.stop;
596 }
597
598 [] PCU_MGMT.receive(BssgpStatusIndication:{*, ?, BVC_S_UNBLOCKED}) -> value bsi {
599 repeat;
600 }
601 [] PCU_MGMT.receive(BssgpStatusIndication:{*, ?, ?}) {
602 repeat;
603 }
604 [] PCU_MGMT.receive(BssgpResetIndication:{0}) {
605 repeat;
606 }
607 [] PCU_MGMT.receive {
608 setverdict(fail, "Received unexpected message on PCU_MGMT");
609 mtc.stop;
610 }
611
612 [] T.timeout {
Harald Welte6929e322020-12-12 13:10:45 +0100613 setverdict(fail, "Timeout waiting for unblock of all BVCs on SGSN side; ",
Harald Welteb978ed62020-12-12 14:01:11 +0100614 "unblocked so far: ", bvci_unblocked);
Harald Welte6929e322020-12-12 13:10:45 +0100615 /* don't stop here but print below analysis */
Harald Weltefbae83f2020-11-15 23:25:55 +0100616 }
617 }
618
Harald Welteb978ed62020-12-12 14:01:11 +0100619 for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
620 /* iterate over list and check all BVCI */
621 for (var integer j := 0; j < lengthof(g_sgsn[i].cfg.bvc); j := j+1) {
622 var BssgpBvci bvci := g_sgsn[i].cfg.bvc[j].bvci;
623 if (not ro_integer_contains(bvci_unblocked[i], bvci)) {
624 setverdict(fail, "SGSN ", i, " BVCI=", bvci, " was not unblocked during start-up");
625 mtc.stop;
626 }
Harald Weltefbae83f2020-11-15 23:25:55 +0100627 }
628 }
Harald Welte425d3762020-12-09 14:33:18 +0100629
630 /* re-start guard timer after all BVCs are up, so it only counts the actual test case */
631 g_Tguard.start(t_guard);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200632}
633
634function f_cleanup() runs on test_CT {
Harald Welteb9f0fdc2020-12-09 14:44:50 +0100635 var integer i;
636
Daniel Willmann491af2a2021-01-08 01:32:51 +0100637 /* To avoid a dynamic test case error we need to prevent messages arriving on unconnected
638 * ports. Waiting here ensures that any messages "in flight" will be delivered to the port
639 * before the component is shutdown and disconnected. */
640 f_sleep(0.2);
641
Harald Welteb9f0fdc2020-12-09 14:44:50 +0100642 for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
643 f_destroy_gb(g_sgsn[i]);
644 }
645 for (i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
646 f_destroy_gb(g_pcu[i]);
647 }
648
649 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200650}
651
652type function void_fn(charstring id) runs on BSSGP_ConnHdlr;
653
654/* helper function to create, connect and start a BSSGP_ConnHdlr component */
Harald Welte207166c2021-01-16 12:52:30 +0100655function f_start_handler(void_fn fn, charstring id, integer imsi_suffix, float t_guard := 30.0,
656 integer sgsn_idx := 0, integer nri_idx := 0, boolean have_ptmsi := true)
Daniel Willmann423d8f42020-09-08 18:58:22 +0200657runs on test_CT return BSSGP_ConnHdlr {
658 var BSSGP_ConnHdlr vc_conn;
Harald Weltec5f486b2021-01-16 11:07:01 +0100659 var integer nri := mp_sgsn_nri[sgsn_idx][nri_idx];
Harald Welte77218d02021-01-15 19:59:15 +0100660 var OCT4 p_tmsi := f_gen_tmsi(imsi_suffix, nri_v := nri, nri_bitlen := mp_nri_bitlength);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200661
662 var BSSGP_ConnHdlrPars pars := {
663 imei := f_gen_imei(imsi_suffix),
664 imsi := f_gen_imsi(imsi_suffix),
665 msisdn := f_gen_msisdn(imsi_suffix),
Harald Weltedbd5e672021-01-14 21:03:14 +0100666 p_tmsi := p_tmsi,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200667 p_tmsi_sig := omit,
Harald Weltedbd5e672021-01-14 21:03:14 +0100668 tlli := f_gprs_tlli_from_tmsi(p_tmsi, TLLI_LOCAL),
Daniel Willmann423d8f42020-09-08 18:58:22 +0200669 tlli_old := omit,
670 ra := omit,
Harald Welte2ecbca82021-01-16 11:23:09 +0100671 pcu := g_pcu,
672 sgsn := g_sgsn,
Harald Weltec5f486b2021-01-16 11:07:01 +0100673 sgsn_idx := sgsn_idx,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200674 t_guard := t_guard
675 };
Harald Welte207166c2021-01-16 12:52:30 +0100676 if (not have_ptmsi) {
677 pars.p_tmsi := omit;
678 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200679
680 vc_conn := BSSGP_ConnHdlr.create(id);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200681
Harald Welte25a04b12021-01-17 11:09:49 +0100682 log("Starting ", id, " for SGSN[", sgsn_idx, "], NRI=", nri, ", P-TMSI=", pars.p_tmsi,
683 ", TLLI=", pars.tlli, ", IMSI=", pars.imsi, " on component=", vc_conn);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200684 vc_conn.start(f_handler_init(fn, id, pars));
685 return vc_conn;
686}
687
Harald Welte207166c2021-01-16 12:52:30 +0100688function f_start_handlers(void_fn fn, charstring id, integer imsi_suffix, float t_guard := 30.0,
689 boolean have_ptmsi := true)
Harald Weltec5f486b2021-01-16 11:07:01 +0100690runs on test_CT
691{
692 var integer sgsn_idx, nri_idx;
693 for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx:=sgsn_idx+1) {
694 for (nri_idx := 0; nri_idx < lengthof(mp_sgsn_nri[sgsn_idx]); nri_idx:=nri_idx+1) {
695 var integer extd_imsi_suffix := 1000*sgsn_idx + 100*nri_idx;
696 var BSSGP_ConnHdlr vc_conn;
Harald Welte207166c2021-01-16 12:52:30 +0100697 vc_conn := f_start_handler(fn, id, extd_imsi_suffix, t_guard, sgsn_idx, nri_idx,
698 have_ptmsi);
Harald Weltec5f486b2021-01-16 11:07:01 +0100699 /* Idea: we could also run them in parallel ? */
700 vc_conn.done;
701 }
702 }
703}
704
Harald Welte3dd21b32020-11-17 19:21:00 +0100705/* Connect the PCU-side per-BVC ports (PCU/PCU_SIG/PCU_PROC) array slot 'port_idx' to specified per-BVC component */
Harald Welte0e188242020-11-22 21:46:48 +0100706private function f_connect_to_pcu_bvc(integer port_idx, integer nse_idx, integer bvc_idx)
707runs on BSSGP_ConnHdlr {
708 var BSSGP_BVC_CT bvc_ct := g_pars.pcu[nse_idx].vc_BSSGP_BVC[bvc_idx]
Harald Welte158becf2020-12-09 12:32:32 +0100709 if (PCU_PTP[port_idx].checkstate("Connected")) {
Harald Welte3dd21b32020-11-17 19:21:00 +0100710 /* unregister + disconnect from old BVC */
711 f_client_unregister(g_pars.imsi, PCU_PROC[port_idx]);
Harald Welte158becf2020-12-09 12:32:32 +0100712 disconnect(self:PCU_PTP[port_idx], pcu_ct[port_idx]:BSSGP_SP);
Harald Welte3dd21b32020-11-17 19:21:00 +0100713 disconnect(self:PCU_SIG[port_idx], pcu_ct[port_idx]:BSSGP_SP_SIG);
714 disconnect(self:PCU_PROC[port_idx], pcu_ct[port_idx]:BSSGP_PROC);
715 }
716 /* connect to new BVC and register us */
Harald Welte158becf2020-12-09 12:32:32 +0100717 connect(self:PCU_PTP[port_idx], bvc_ct:BSSGP_SP);
Harald Welte3dd21b32020-11-17 19:21:00 +0100718 connect(self:PCU_SIG[port_idx], bvc_ct:BSSGP_SP_SIG);
719 connect(self:PCU_PROC[port_idx], bvc_ct:BSSGP_PROC);
720 f_client_register(g_pars.imsi, g_pars.tlli, PCU_PROC[port_idx]);
721 pcu_ct[port_idx] := bvc_ct;
Harald Welte0e188242020-11-22 21:46:48 +0100722 pcu_bvc_cfg[port_idx] := g_pars.pcu[nse_idx].cfg.bvc[bvc_idx];
Harald Welte3dd21b32020-11-17 19:21:00 +0100723}
724
725/* Connect the SGSN-side per-BVC ports (SGSN/SGSN_SIG/SGSN_PROC) array slot 'port_idx' to specified per-BVC component */
726private function f_connect_to_sgsn_bvc(integer port_idx, BSSGP_BVC_CT bvc_ct) runs on BSSGP_ConnHdlr {
Harald Welte158becf2020-12-09 12:32:32 +0100727 if (SGSN_PTP[port_idx].checkstate("Connected")) {
Harald Welte3dd21b32020-11-17 19:21:00 +0100728 /* unregister + disconnect from old BVC */
729 f_client_unregister(g_pars.imsi, SGSN_PROC[port_idx]);
Harald Welte158becf2020-12-09 12:32:32 +0100730 disconnect(self:SGSN_PTP[port_idx], sgsn_ct[port_idx]:BSSGP_SP);
Harald Welte3dd21b32020-11-17 19:21:00 +0100731 disconnect(self:SGSN_SIG[port_idx], sgsn_ct[port_idx]:BSSGP_SP_SIG);
732 disconnect(self:SGSN_PROC[port_idx], sgsn_ct[port_idx]:BSSGP_PROC);
733 }
734 /* connect to new BVC and register us */
Harald Welte158becf2020-12-09 12:32:32 +0100735 connect(self:SGSN_PTP[port_idx], bvc_ct:BSSGP_SP);
Harald Welte3dd21b32020-11-17 19:21:00 +0100736 connect(self:SGSN_SIG[port_idx], bvc_ct:BSSGP_SP_SIG);
737 connect(self:SGSN_PROC[port_idx], bvc_ct:BSSGP_PROC);
738 f_client_register(g_pars.imsi, g_pars.tlli, SGSN_PROC[port_idx]);
739 sgsn_ct[port_idx] := bvc_ct;
740}
741
Harald Welte425d3762020-12-09 14:33:18 +0100742private altstep as_gTguard(timer Tguard) {
743 [] Tguard.timeout {
Daniel Willmann423d8f42020-09-08 18:58:22 +0200744 setverdict(fail, "Tguard timeout");
745 mtc.stop;
746 }
747}
748
749/* first function called in every ConnHdlr */
750private function f_handler_init(void_fn fn, charstring id, BSSGP_ConnHdlrPars pars)
751runs on BSSGP_ConnHdlr {
Harald Welte1e834f32020-11-15 20:02:59 +0100752 var integer i;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200753 /* do some common stuff like setting up g_pars */
754 g_pars := pars;
755
756 llc := f_llc_create(false);
757
Harald Welte3dd21b32020-11-17 19:21:00 +0100758 /* default connections on PCU side: First BVC of each NSE/PCU */
759 for (i := 0; i < lengthof(g_pars.pcu); i := i+1) {
Harald Welte0e188242020-11-22 21:46:48 +0100760 f_connect_to_pcu_bvc(port_idx := i, nse_idx := i, bvc_idx := 0);
Harald Welte1e834f32020-11-15 20:02:59 +0100761 }
Harald Welte3dd21b32020-11-17 19:21:00 +0100762
763 /* default connections on SGSN side: First BVC of each NSE/SGSN */
764 for (i := 0; i < lengthof(g_pars.sgsn); i := i+1) {
765 f_connect_to_sgsn_bvc(i, g_pars.sgsn[i].vc_BSSGP_BVC[0]);
Harald Welte1e834f32020-11-15 20:02:59 +0100766 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200767
768 g_Tguard.start(pars.t_guard);
Harald Welte425d3762020-12-09 14:33:18 +0100769 activate(as_gTguard(g_Tguard));
Daniel Willmann423d8f42020-09-08 18:58:22 +0200770
771 /* call the user-supplied test case function */
772 fn.apply(id);
Harald Welteb33fb592021-01-16 12:50:56 +0100773
774 for (i := 0; i < NUM_SGSN; i := i+1) {
775 if (SGSN_PROC[i].checkstate("Connected")) {
776 f_client_unregister(g_pars.imsi, SGSN_PROC[i])
777 }
778 }
779
780 for (i := 0; i < NUM_PCU; i := i+1) {
781 if (PCU_PROC[i].checkstate("Connected")) {
782 f_client_unregister(g_pars.imsi, PCU_PROC[i])
783 }
784 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200785}
786
Harald Welte1e834f32020-11-15 20:02:59 +0100787private function f_client_register(hexstring imsi, OCT4 tlli, BSSGP_PROC_PT PT)
788runs on BSSGP_ConnHdlr {
789 PT.call(BSSGP_register_client:{imsi, tlli}) {
790 [] PT.getreply(BSSGP_register_client:{imsi, tlli}) {};
791 }
792}
793
794private function f_client_unregister(hexstring imsi, BSSGP_PROC_PT PT)
795runs on BSSGP_ConnHdlr {
796 PT.call(BSSGP_unregister_client:{imsi}) {
797 [] PT.getreply(BSSGP_unregister_client:{imsi}) {};
798 }
799}
800
Harald Welte22ef5d92020-11-16 13:35:14 +0100801/* Send 'tx' on PTP-BVCI from PCU; expect 'rx' on SGSN */
802friend function f_pcu2sgsn(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
Harald Weltec5f486b2021-01-16 11:07:01 +0100803 integer pcu_idx := 0, boolean use_sig := false) runs on BSSGP_ConnHdlr {
804 var integer sgsn_idx := g_pars.sgsn_idx;
Harald Welte22ef5d92020-11-16 13:35:14 +0100805 var PDU_BSSGP rx;
806 timer T := 1.0;
807
Daniel Willmann4798fd72020-11-24 16:23:29 +0100808 if (use_sig) {
809 PCU_SIG[pcu_idx].send(tx);
810 } else {
Harald Welte158becf2020-12-09 12:32:32 +0100811 PCU_PTP[pcu_idx].send(tx);
Daniel Willmann4798fd72020-11-24 16:23:29 +0100812 }
813
Harald Welte22ef5d92020-11-16 13:35:14 +0100814 T.start;
815 alt {
Daniel Willmann4798fd72020-11-24 16:23:29 +0100816 [use_sig] SGSN_SIG[sgsn_idx].receive(exp_rx) {
817 setverdict(pass);
818 }
Harald Welte158becf2020-12-09 12:32:32 +0100819 [not use_sig] SGSN_PTP[sgsn_idx].receive(exp_rx) {
Harald Welte22ef5d92020-11-16 13:35:14 +0100820 setverdict(pass);
821 }
Harald Welte158becf2020-12-09 12:32:32 +0100822 [] SGSN_PTP[sgsn_idx].receive(PDU_BSSGP:?) -> value rx {
Harald Weltec5f486b2021-01-16 11:07:01 +0100823 setverdict(fail, "Unexpected BSSGP on SGSN[", sgsn_idx, "] side: ", rx);
Harald Welte22ef5d92020-11-16 13:35:14 +0100824 mtc.stop;
825 }
Daniel Willmann4798fd72020-11-24 16:23:29 +0100826 [] SGSN_SIG[sgsn_idx].receive(PDU_BSSGP:?) -> value rx {
Harald Weltec5f486b2021-01-16 11:07:01 +0100827 setverdict(fail, "Unexpected SIG BSSGP on SGSN[", sgsn_idx, "] side: ", rx);
Daniel Willmann4798fd72020-11-24 16:23:29 +0100828 mtc.stop;
829 }
Harald Welte22ef5d92020-11-16 13:35:14 +0100830 [] T.timeout {
Harald Weltec5f486b2021-01-16 11:07:01 +0100831 setverdict(fail, "Timeout waiting for BSSGP on SGSN[", sgsn_idx, "] side: ", exp_rx);
Harald Welte22ef5d92020-11-16 13:35:14 +0100832 mtc.stop;
833 }
834 }
835}
836
Harald Welte3148a962021-01-17 11:15:28 +0100837/* Send 'tx' from PCU; expect 'exp_rx' on _any_ SGSN */
838friend function f_pcu2any_sgsn(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
839 integer pcu_idx := 0, boolean use_sig := false)
840runs on BSSGP_ConnHdlr return integer {
841 var integer rx_idx := -1;
842 var PDU_BSSGP rx;
843 timer T := 1.0;
844
845 if (use_sig) {
846 PCU_SIG[pcu_idx].send(tx);
847 } else {
848 PCU_PTP[pcu_idx].send(tx);
849 }
850
851 T.start;
852 alt {
853 [use_sig] any from SGSN_SIG.receive(exp_rx) -> @index value rx_idx {
854 setverdict(pass);
855 }
856 [not use_sig] any from SGSN_PTP.receive(exp_rx) -> @index value rx_idx {
857 setverdict(pass);
858 }
859 [] any from SGSN_PTP.receive(PDU_BSSGP:?) -> value rx @index value rx_idx {
860 setverdict(fail, "Unexpected BSSGP on SGSN[", rx_idx, "] side: ", rx);
861 mtc.stop;
862 }
863 [] any from SGSN_SIG.receive(PDU_BSSGP:?) -> value rx @index value rx_idx {
864 setverdict(fail, "Unexpected SIG BSSGP on SGSN[", rx_idx, "] side: ", rx);
865 mtc.stop;
866 }
867 [] T.timeout {
868 setverdict(fail, "Timeout waiting for BSSGP on SGSN side: ", exp_rx);
869 mtc.stop;
870 }
871 }
872 return rx_idx;
873}
874
Harald Welte22ef5d92020-11-16 13:35:14 +0100875/* Send 'tx' on PTP-BVCI from SGSN; expect 'rx' on PCU */
876friend function f_sgsn2pcu(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
Harald Weltec5f486b2021-01-16 11:07:01 +0100877 integer pcu_idx := 0, boolean use_sig := false) runs on BSSGP_ConnHdlr {
878 var integer sgsn_idx := g_pars.sgsn_idx;
Harald Welte22ef5d92020-11-16 13:35:14 +0100879 var PDU_BSSGP rx;
880 timer T := 1.0;
881
Daniel Willmann4798fd72020-11-24 16:23:29 +0100882 if (use_sig) {
883 SGSN_SIG[sgsn_idx].send(tx);
884 } else {
Harald Welte158becf2020-12-09 12:32:32 +0100885 SGSN_PTP[sgsn_idx].send(tx);
Daniel Willmann4798fd72020-11-24 16:23:29 +0100886 }
887
Harald Welte22ef5d92020-11-16 13:35:14 +0100888 T.start;
889 alt {
Daniel Willmann4798fd72020-11-24 16:23:29 +0100890 [use_sig] PCU_SIG[pcu_idx].receive(exp_rx) {
891 setverdict(pass);
892 }
Harald Welte158becf2020-12-09 12:32:32 +0100893 [not use_sig] PCU_PTP[pcu_idx].receive(exp_rx) {
Harald Welte22ef5d92020-11-16 13:35:14 +0100894 setverdict(pass);
895 }
Harald Welte158becf2020-12-09 12:32:32 +0100896 [] PCU_PTP[pcu_idx].receive(PDU_BSSGP:?) -> value rx {
Harald Welte22ef5d92020-11-16 13:35:14 +0100897 setverdict(fail, "Unexpected BSSGP on PCU side: ", rx);
898 mtc.stop;
899 }
Daniel Willmann4798fd72020-11-24 16:23:29 +0100900 [] PCU_SIG[pcu_idx].receive(PDU_BSSGP:?) -> value rx {
901 setverdict(fail, "Unexpected SIG BSSGP on PCU side: ", rx);
902 mtc.stop;
903 }
Harald Welte22ef5d92020-11-16 13:35:14 +0100904 [] T.timeout {
Harald Welte8b326412020-11-29 16:05:38 +0100905 setverdict(fail, "Timeout waiting for BSSGP on PCU side: ", exp_rx);
Harald Welte22ef5d92020-11-16 13:35:14 +0100906 mtc.stop;
907 }
908 }
909}
Harald Welte1e834f32020-11-15 20:02:59 +0100910
Harald Welte3807ed12020-11-24 19:05:22 +0100911/***********************************************************************
912 * GlobaLTest_CT: Using the per-NSE GLOBAL ports on PCU + SGSN side
913 ***********************************************************************/
914
915type component GlobalTest_CT extends test_CT {
916 port BSSGP_PT G_PCU[NUM_PCU];
Harald Welte04358652021-01-17 13:48:13 +0100917 var integer g_pcu_idx[NUM_PCU]; /* BVC index currently connected to G_PCU */
Harald Welte3807ed12020-11-24 19:05:22 +0100918 port BSSGP_PT G_SGSN[NUM_SGSN];
Harald Welte04358652021-01-17 13:48:13 +0100919 var integer g_sgsn_idx[NUM_SGSN]; /* BVC index currently connected to G_SGSN */
Harald Weltef86f1852021-01-16 21:56:17 +0100920 port BSSGP_PT RIM_PCU[NUM_PCU];
921 port BSSGP_PT RIM_SGSN[NUM_SGSN];
Harald Welte3807ed12020-11-24 19:05:22 +0100922};
923
Harald Welte299aa482020-12-09 15:10:55 +0100924/* connect the signaling BVC of each NSE to the G_PCU / G_SGSN ports */
Harald Welte3807ed12020-11-24 19:05:22 +0100925private function f_global_init() runs on GlobalTest_CT {
926 var integer i;
927 for (i := 0; i < lengthof(g_sgsn); i := i+1) {
928 connect(self:G_SGSN[i], g_sgsn[i].vc_BSSGP:GLOBAL);
Harald Weltef86f1852021-01-16 21:56:17 +0100929 connect(self:RIM_SGSN[i], g_sgsn[i].vc_BSSGP:RIM);
Harald Welte3807ed12020-11-24 19:05:22 +0100930 }
931 for (i := 0; i < lengthof(g_pcu); i := i+1) {
932 connect(self:G_PCU[i], g_pcu[i].vc_BSSGP:GLOBAL);
Harald Weltef86f1852021-01-16 21:56:17 +0100933 connect(self:RIM_PCU[i], g_pcu[i].vc_BSSGP:RIM);
Harald Welte3807ed12020-11-24 19:05:22 +0100934 }
935}
936
Harald Welte299aa482020-12-09 15:10:55 +0100937/* connect the first PTP BVC of each NSE to the G_PCU / G_SGSN ports */
938private function f_global_init_ptp() runs on GlobalTest_CT {
939 var integer i;
940 for (i := 0; i < lengthof(g_sgsn); i := i+1) {
Harald Welte04358652021-01-17 13:48:13 +0100941 log("Connecting G_SGSN[", i, "] to BVCI=", g_sgsn[i].cfg.bvc[0].bvci);
Harald Welte299aa482020-12-09 15:10:55 +0100942 connect(self:G_SGSN[i], g_sgsn[i].vc_BSSGP_BVC[0]:GLOBAL);
Harald Welte04358652021-01-17 13:48:13 +0100943 g_sgsn_idx[i] := 0;
Harald Welte299aa482020-12-09 15:10:55 +0100944 }
945 for (i := 0; i < lengthof(g_pcu); i := i+1) {
Harald Welte04358652021-01-17 13:48:13 +0100946 log("Connecting G_PCU[", i, "] to BVCI=", g_pcu[i].cfg.bvc[0].bvci);
Harald Welte299aa482020-12-09 15:10:55 +0100947 connect(self:G_PCU[i], g_pcu[i].vc_BSSGP_BVC[0]:GLOBAL);
Harald Welte04358652021-01-17 13:48:13 +0100948 g_pcu_idx[i] := 0;
Harald Welte299aa482020-12-09 15:10:55 +0100949 }
950}
951
Harald Welte04358652021-01-17 13:48:13 +0100952/* (re)connect G_SGSN[sgsn_idx] to a specific PTP BVCI */
953private function f_global_ptp_connect_sgsn_bvci(integer sgsn_idx, BssgpBvci bvci) runs on GlobalTest_CT
954{
955 var integer sgsn_bvc_idx := get_bvc_idx_for_bvci(g_sgsn[sgsn_idx], bvci);
956 var integer old_sgsn_bvc_idx := g_sgsn_idx[sgsn_idx];
957 disconnect(self:G_SGSN[sgsn_idx], g_sgsn[sgsn_idx].vc_BSSGP_BVC[old_sgsn_bvc_idx]:GLOBAL);
958 connect(self:G_SGSN[sgsn_idx], g_sgsn[sgsn_idx].vc_BSSGP_BVC[sgsn_bvc_idx]:GLOBAL);
959 g_sgsn_idx[sgsn_idx] := sgsn_bvc_idx;
960}
961
962/* (re)connect G_PCU[pcu_idx] to a specific PTP BVCI */
963private function f_global_ptp_connect_pcu_bvci(integer pcu_idx, BssgpBvci bvci) runs on GlobalTest_CT
964{
965 var integer pcu_bvc_idx := get_bvc_idx_for_bvci(g_pcu[pcu_idx], bvci);
966 var integer old_pcu_bvc_idx := g_pcu_idx[pcu_idx];
967 disconnect(self:G_PCU[pcu_idx], g_pcu[pcu_idx].vc_BSSGP_BVC[old_pcu_bvc_idx]:GLOBAL);
968 connect(self:G_PCU[pcu_idx], g_pcu[pcu_idx].vc_BSSGP_BVC[pcu_bvc_idx]:GLOBAL);
969 g_pcu_idx[pcu_idx] := pcu_bvc_idx;
970}
971
Harald Welte3807ed12020-11-24 19:05:22 +0100972/* Send 'tx' on PTP-BVCI from PCU; expect 'rx' on SGSN */
973friend function f_global_pcu2sgsn(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
974 integer pcu_idx := 0, integer sgsn_idx := 0) runs on GlobalTest_CT {
Harald Welte04358652021-01-17 13:48:13 +0100975 var integer rx_idx;
Harald Welte3807ed12020-11-24 19:05:22 +0100976 var PDU_BSSGP rx;
977 timer T := 1.0;
978
979 G_PCU[pcu_idx].send(tx);
980 T.start;
981 alt {
982 [] G_SGSN[sgsn_idx].receive(exp_rx) {
983 setverdict(pass);
984 }
Harald Welte04358652021-01-17 13:48:13 +0100985 [] any from G_SGSN.receive(exp_rx) -> @index value rx_idx {
986 setverdict(fail, "BSSGP arrived on wrong SGSN[", rx_idx, "] instead of SGSN[", sgsn_idx, "]");
987 }
Harald Welte3807ed12020-11-24 19:05:22 +0100988 [] G_SGSN[sgsn_idx].receive(PDU_BSSGP:?) -> value rx {
989 setverdict(fail, "Unexpected BSSGP on SGSN side: ", rx);
990 mtc.stop;
991 }
992 [] T.timeout {
Harald Weltedc805c02020-12-11 10:59:17 +0100993 setverdict(fail, "Timeout waiting for BSSGP on SGSN side: ", exp_rx);
Harald Welte3807ed12020-11-24 19:05:22 +0100994 mtc.stop;
995 }
996 }
997}
998
999/* Send 'tx' on PTP-BVCI from SGSN; expect 'rx' on PCU */
1000friend function f_global_sgsn2pcu(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
1001 integer sgsn_idx := 0, integer pcu_idx := 0) runs on GlobalTest_CT {
Harald Welte04358652021-01-17 13:48:13 +01001002 var integer rx_idx;
Harald Welte3807ed12020-11-24 19:05:22 +01001003 var PDU_BSSGP rx;
1004 timer T := 1.0;
1005
1006 G_SGSN[sgsn_idx].send(tx);
1007 T.start;
1008 alt {
1009 [] G_PCU[pcu_idx].receive(exp_rx) {
1010 setverdict(pass);
1011 }
Harald Welte04358652021-01-17 13:48:13 +01001012 [] any from G_PCU.receive(exp_rx) -> @index value rx_idx {
1013 setverdict(fail, "BSSGP arrived on wrong PCU[", rx_idx, "] instead of PCU[", pcu_idx, "]");
1014 }
Harald Welte3807ed12020-11-24 19:05:22 +01001015 [] G_PCU[pcu_idx].receive(PDU_BSSGP:?) -> value rx {
1016 setverdict(fail, "Unexpected BSSGP on PCU side: ", rx);
1017 mtc.stop;
1018 }
1019 [] T.timeout {
Harald Weltedc805c02020-12-11 10:59:17 +01001020 setverdict(fail, "Timeout waiting for BSSGP on PCU side: ", exp_rx);
Harald Welte3807ed12020-11-24 19:05:22 +01001021 mtc.stop;
1022 }
1023 }
1024}
1025
1026
Daniel Willmann423d8f42020-09-08 18:58:22 +02001027/* TODO:
1028 * Detach without Attach
1029 * SM procedures without attach / RAU
1030 * ATTACH / RAU
1031 ** with / without authentication
1032 ** with / without P-TMSI allocation
1033 * re-transmissions of LLC frames
1034 * PDP Context activation
1035 ** with different GGSN config in SGSN VTY
1036 ** with different PDP context type (v4/v6/v46)
1037 ** timeout from GGSN
1038 ** multiple / secondary PDP context
1039 */
1040
1041private function f_TC_BVC_bringup(charstring id) runs on BSSGP_ConnHdlr {
1042 f_sleep(5.0);
1043 setverdict(pass);
1044}
1045
1046testcase TC_BVC_bringup() runs on test_CT {
Daniel Willmann423d8f42020-09-08 18:58:22 +02001047 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001048 f_start_handlers(refers(f_TC_BVC_bringup), testcasename(), 51);
Daniel Willmann423d8f42020-09-08 18:58:22 +02001049 f_cleanup();
1050}
1051
1052friend function f_bssgp_suspend(integer ran_idx := 0) runs on BSSGP_ConnHdlr return OCT1 {
Harald Welte16357a92020-11-17 18:20:00 +01001053 var BssgpBvcConfig bvcc := g_pars.pcu[ran_idx].cfg.bvc[0];
Daniel Willmann423d8f42020-09-08 18:58:22 +02001054 timer T := 5.0;
1055 var PDU_BSSGP rx_pdu;
Harald Welte16357a92020-11-17 18:20:00 +01001056 PCU_SIG[ran_idx].send(ts_BSSGP_SUSPEND(g_pars.tlli, bvcc.cell_id.ra_id));
Daniel Willmann423d8f42020-09-08 18:58:22 +02001057 T.start;
1058 alt {
Harald Welte16357a92020-11-17 18:20:00 +01001059 [] PCU_SIG[ran_idx].receive(tr_BSSGP_SUSPEND_ACK(g_pars.tlli, bvcc.cell_id.ra_id, ?)) -> value rx_pdu {
Daniel Willmann423d8f42020-09-08 18:58:22 +02001060 return rx_pdu.pDU_BSSGP_SUSPEND_ACK.suspend_Reference_Number.suspend_Reference_Number_value;
1061 }
Harald Welte16357a92020-11-17 18:20:00 +01001062 [] PCU_SIG[ran_idx].receive(tr_BSSGP_SUSPEND_NACK(g_pars.tlli, bvcc.cell_id.ra_id, ?)) -> value rx_pdu {
Daniel Willmann423d8f42020-09-08 18:58:22 +02001063 setverdict(fail, "SUSPEND-NACK in response to SUSPEND for TLLI ", g_pars.tlli);
1064 mtc.stop;
1065 }
1066 [] T.timeout {
1067 setverdict(fail, "No SUSPEND-ACK in response to SUSPEND for TLLI ", g_pars.tlli);
1068 mtc.stop;
1069 }
1070 }
1071 return '00'O;
1072}
1073
1074friend function f_bssgp_resume(OCT1 susp_ref, integer ran_idx := 0) runs on BSSGP_ConnHdlr {
Harald Welte16357a92020-11-17 18:20:00 +01001075 var BssgpBvcConfig bvcc := g_pars.pcu[ran_idx].cfg.bvc[0];
Daniel Willmann423d8f42020-09-08 18:58:22 +02001076 timer T := 5.0;
Harald Welte16357a92020-11-17 18:20:00 +01001077 PCU_SIG[ran_idx].send(ts_BSSGP_RESUME(g_pars.tlli, bvcc.cell_id.ra_id, susp_ref));
Daniel Willmann423d8f42020-09-08 18:58:22 +02001078 T.start;
1079 alt {
Harald Welte16357a92020-11-17 18:20:00 +01001080 [] PCU_SIG[ran_idx].receive(tr_BSSGP_RESUME_ACK(g_pars.tlli, bvcc.cell_id.ra_id));
1081 [] PCU_SIG[ran_idx].receive(tr_BSSGP_RESUME_NACK(g_pars.tlli, bvcc.cell_id.ra_id, ?)) {
Daniel Willmann423d8f42020-09-08 18:58:22 +02001082 setverdict(fail, "RESUME-NACK in response to RESUME for TLLI ", g_pars.tlli);
1083 mtc.stop;
1084 }
1085 [] T.timeout {
1086 setverdict(fail, "No RESUME-ACK in response to SUSPEND for TLLI ", g_pars.tlli);
1087 mtc.stop;
1088 }
1089 }
1090}
1091
1092
Harald Welte92686012020-11-15 21:45:49 +01001093/* send uplink-unitdata of a variety of different sizes; expect it to show up on SGSN */
1094private function f_TC_ul_unitdata(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte16357a92020-11-17 18:20:00 +01001095 var integer ran_idx := 0;
1096 var BssgpBvcConfig bvcc := g_pars.pcu[ran_idx].cfg.bvc[0];
Harald Welte92686012020-11-15 21:45:49 +01001097 var integer i;
1098
Harald Welte0d5fceb2020-11-29 16:04:07 +01001099 for (i := 0; i < max_fr_info_size-4; i := i+4) {
Harald Welte92686012020-11-15 21:45:49 +01001100 var octetstring payload := f_rnd_octstring(i);
Harald Welte16357a92020-11-17 18:20:00 +01001101 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_UL_UD(g_pars.tlli, bvcc.cell_id, payload);
Harald Welte92686012020-11-15 21:45:49 +01001102 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
Harald Welte16357a92020-11-17 18:20:00 +01001103 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_UL_UD(g_pars.tlli, bvcc.cell_id, payload);
Harald Welte92686012020-11-15 21:45:49 +01001104
Harald Welte0d5fceb2020-11-29 16:04:07 +01001105 log("UL-UNITDATA(payload_size=", i);
Harald Welte22ef5d92020-11-16 13:35:14 +01001106 f_pcu2sgsn(pdu_tx, pdu_rx);
Harald Welte92686012020-11-15 21:45:49 +01001107 }
1108 setverdict(pass);
1109}
1110
1111testcase TC_ul_unitdata() runs on test_CT
1112{
Harald Welte92686012020-11-15 21:45:49 +01001113 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001114 f_start_handlers(refers(f_TC_ul_unitdata), testcasename(), 1);
Harald Welte92686012020-11-15 21:45:49 +01001115 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
Harald Welte92686012020-11-15 21:45:49 +01001116 f_cleanup();
1117}
1118
Harald Welte78d8db92020-11-15 23:27:27 +01001119/* send downlink-unitdata of a variety of different sizes; expect it to show up on PCU */
1120private function f_TC_dl_unitdata(charstring id) runs on BSSGP_ConnHdlr {
1121 var integer i;
1122
Harald Welte0d5fceb2020-11-29 16:04:07 +01001123 for (i := 0; i < max_fr_info_size-4; i := i+4) {
Harald Welte78d8db92020-11-15 23:27:27 +01001124 var octetstring payload := f_rnd_octstring(i);
1125 var template (value) PDU_BSSGP pdu_tx :=
1126 ts_BSSGP_DL_UD(g_pars.tlli, payload, omit, ts_BSSGP_IMSI(g_pars.imsi));
1127 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1128 var template (present) PDU_BSSGP pdu_rx :=
1129 tr_BSSGP_DL_UD(g_pars.tlli, payload, tr_BSSGP_IMSI(g_pars.imsi));
1130
Harald Welte0d5fceb2020-11-29 16:04:07 +01001131 log("DL-UNITDATA(payload_size=", i);
Harald Welte22ef5d92020-11-16 13:35:14 +01001132 f_sgsn2pcu(pdu_tx, pdu_rx);
Harald Welte78d8db92020-11-15 23:27:27 +01001133 }
1134 setverdict(pass);
1135}
1136
1137testcase TC_dl_unitdata() runs on test_CT
1138{
Harald Welte78d8db92020-11-15 23:27:27 +01001139 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001140 f_start_handlers(refers(f_TC_dl_unitdata), testcasename(), 2);
Harald Welte78d8db92020-11-15 23:27:27 +01001141 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
Harald Welte78d8db92020-11-15 23:27:27 +01001142 f_cleanup();
1143}
Harald Welte92686012020-11-15 21:45:49 +01001144
Harald Welte6dc2ac42020-11-16 09:16:17 +01001145private function f_TC_ra_capability(charstring id) runs on BSSGP_ConnHdlr {
1146 var integer i;
1147
1148 for (i := 0; i < 10; i := i+1) {
1149 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RA_CAP(g_pars.tlli, { ts_RaCapRec_BSSGP });
1150 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1151 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RA_CAP(g_pars.tlli, { tr_RaCapRec_BSSGP })
1152
Harald Welte22ef5d92020-11-16 13:35:14 +01001153 f_sgsn2pcu(pdu_tx, pdu_rx);
Harald Welte6dc2ac42020-11-16 09:16:17 +01001154 }
1155 setverdict(pass);
1156}
1157testcase TC_ra_capability() runs on test_CT
1158{
Harald Welte6dc2ac42020-11-16 09:16:17 +01001159 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001160 f_start_handlers(refers(f_TC_ra_capability), testcasename(), 3);
Harald Welte6dc2ac42020-11-16 09:16:17 +01001161 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
Harald Welte6dc2ac42020-11-16 09:16:17 +01001162 f_cleanup();
1163}
1164
Daniel Willmannace3ece2020-11-16 19:53:26 +01001165private function f_TC_ra_capability_upd(charstring id) runs on BSSGP_ConnHdlr {
1166 var integer i;
1167 var OCT1 tag;
1168 for (i := 0; i < 10; i := i+1) {
1169 tag := int2oct(23 + i, 1);
1170 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RA_CAP_UPD(g_pars.tlli, tag);
1171 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1172 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RA_CAP_UPD(g_pars.tlli, tag)
1173
1174 f_pcu2sgsn(pdu_tx, pdu_rx);
1175
1176 pdu_tx := ts_BSSGP_RA_CAP_UPD_ACK(g_pars.tlli, tag, '42'O);
1177 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1178 pdu_rx := tr_BSSGP_RA_CAP_UPD_ACK(g_pars.tlli, tag, '42'O)
1179
1180 f_sgsn2pcu(pdu_tx, pdu_rx);
1181 }
1182 setverdict(pass);
1183}
1184testcase TC_ra_capability_upd() runs on test_CT
1185{
Daniel Willmannace3ece2020-11-16 19:53:26 +01001186 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001187 f_start_handlers(refers(f_TC_ra_capability_upd), testcasename(), 4);
Daniel Willmannace3ece2020-11-16 19:53:26 +01001188 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
Daniel Willmannace3ece2020-11-16 19:53:26 +01001189 f_cleanup();
1190}
1191
Daniel Willmann165d6612020-11-19 14:27:29 +01001192private function f_TC_radio_status(charstring id) runs on BSSGP_ConnHdlr {
1193 var integer i;
1194 var BssgpRadioCause cause := BSSGP_RADIO_CAUSE_CONTACT_LOST;
1195 for (i := 0; i < 10; i := i+1) {
1196 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RADIO_STATUS(g_pars.tlli, cause);
1197 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1198 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RADIO_STATUS(g_pars.tlli, cause)
1199
1200 f_pcu2sgsn(pdu_tx, pdu_rx);
1201 }
1202 setverdict(pass);
1203}
1204testcase TC_radio_status() runs on test_CT
1205{
Daniel Willmann165d6612020-11-19 14:27:29 +01001206 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001207 f_start_handlers(refers(f_TC_radio_status), testcasename(), 5);
Daniel Willmann165d6612020-11-19 14:27:29 +01001208 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
Daniel Willmann165d6612020-11-19 14:27:29 +01001209 f_cleanup();
1210}
1211
Harald Welte3148a962021-01-17 11:15:28 +01001212private function f_TC_radio_status_tmsi(charstring id) runs on BSSGP_ConnHdlr {
1213 var integer i;
1214 var BssgpRadioCause cause := BSSGP_RADIO_CAUSE_CONTACT_LOST;
1215 for (i := 0; i < 10; i := i+1) {
1216 var integer tmsi_int := oct2int(g_pars.p_tmsi);
1217 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RADIO_STATUS(omit, cause, tmsi_int);
1218 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1219 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RADIO_STATUS(omit, cause, tmsi_int);
1220 f_pcu2sgsn(pdu_tx, pdu_rx);
1221 }
1222 setverdict(pass);
1223}
1224testcase TC_radio_status_tmsi() runs on test_CT
1225{
1226 f_init();
1227 f_start_handlers(refers(f_TC_radio_status_tmsi), testcasename(), 5);
1228 f_cleanup();
1229}
1230
1231private function f_TC_radio_status_imsi(charstring id) runs on BSSGP_ConnHdlr {
1232 var integer i;
1233 var BssgpRadioCause cause := BSSGP_RADIO_CAUSE_CONTACT_LOST;
1234 for (i := 0; i < 10; i := i+1) {
1235 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RADIO_STATUS(omit, cause, imsi := g_pars.imsi);
1236 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1237 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RADIO_STATUS(omit, cause, imsi := g_pars.imsi);
1238 f_pcu2any_sgsn(pdu_tx, pdu_rx);
1239 }
1240 setverdict(pass);
1241}
1242testcase TC_radio_status_imsi() runs on test_CT
1243{
1244 f_init();
1245 f_start_handlers(refers(f_TC_radio_status_imsi), testcasename(), 5);
1246 f_cleanup();
1247}
1248
1249
1250
Harald Welte99ed5072021-01-15 20:38:58 +01001251private function f_suspend_one(integer sgsn_idx, integer nri_idx, integer pcu_idx, integer bvc_idx,
1252 integer suffix)
Harald Welte00963752021-01-15 20:33:11 +01001253runs on GlobalTest_CT
1254{
1255 var RoutingAreaIdentification ra_id := g_pcu[pcu_idx].cfg.bvc[bvc_idx].cell_id.ra_id;
Harald Welte99ed5072021-01-15 20:38:58 +01001256 var OCT4 p_tmsi := f_gen_tmsi(suffix, nri_v := mp_sgsn_nri[sgsn_idx][nri_idx],
1257 nri_bitlen := mp_nri_bitlength);
1258 var OCT4 tlli := f_gprs_tlli_from_tmsi(p_tmsi, TLLI_LOCAL);
Harald Welte00963752021-01-15 20:33:11 +01001259 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_SUSPEND(tlli, ra_id);
1260 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1261 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_SUSPEND(tlli, ra_id);
1262 f_global_pcu2sgsn(pdu_tx, pdu_rx, pcu_idx, sgsn_idx);
1263
1264 pdu_tx := ts_BSSGP_SUSPEND_ACK(tlli, ra_id, int2oct(suffix, 1));
1265 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1266 pdu_rx := tr_BSSGP_SUSPEND_ACK(tlli, ra_id, int2oct(suffix, 1));
1267 f_global_sgsn2pcu(pdu_tx, pdu_rx, sgsn_idx, pcu_idx);
1268
1269 pdu_tx := ts_BSSGP_SUSPEND(tlli, ra_id);
1270 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1271 pdu_rx := tr_BSSGP_SUSPEND(tlli, ra_id);
1272 f_global_pcu2sgsn(pdu_tx, pdu_rx, pcu_idx, sgsn_idx);
1273
1274 /* These messages are simple passed through so just also test sending NACK */
1275 pdu_tx := ts_BSSGP_SUSPEND_NACK(tlli, ra_id, BSSGP_CAUSE_UNKNOWN_MS);
1276 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1277 pdu_rx := tr_BSSGP_SUSPEND_NACK(tlli, ra_id, BSSGP_CAUSE_UNKNOWN_MS);
1278 f_global_sgsn2pcu(pdu_tx, pdu_rx, sgsn_idx, pcu_idx);
1279}
1280
Harald Weltec5c33732021-01-15 21:04:35 +01001281private function f_TC_suspend(integer sgsn_idx, integer nri_idx, integer pcu_idx, integer bvc_idx)
1282runs on GlobalTest_CT {
Daniel Willmannfa67f492020-11-19 15:48:05 +01001283 var integer i;
Daniel Willmann165d6612020-11-19 14:27:29 +01001284
Daniel Willmannfa67f492020-11-19 15:48:05 +01001285 for (i := 0; i < 10; i := i+1) {
Harald Weltec5c33732021-01-15 21:04:35 +01001286 f_suspend_one(sgsn_idx, nri_idx, pcu_idx, bvc_idx, suffix := i);
Daniel Willmannfa67f492020-11-19 15:48:05 +01001287 }
1288 setverdict(pass);
1289}
Harald Welte3807ed12020-11-24 19:05:22 +01001290testcase TC_suspend() runs on GlobalTest_CT
Daniel Willmannfa67f492020-11-19 15:48:05 +01001291{
Harald Weltec5c33732021-01-15 21:04:35 +01001292 var integer sgsn_idx, nri_idx;
Daniel Willmannfa67f492020-11-19 15:48:05 +01001293 f_init();
Harald Welte3807ed12020-11-24 19:05:22 +01001294 f_global_init();
Harald Weltec5c33732021-01-15 21:04:35 +01001295 for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx+1) {
1296 for (nri_idx := 0; nri_idx < lengthof(mp_sgsn_nri[sgsn_idx]); nri_idx := nri_idx+1) {
1297 f_TC_suspend(sgsn_idx, nri_idx, pcu_idx:=0, bvc_idx:=0);
1298 }
1299 }
Daniel Willmannfa67f492020-11-19 15:48:05 +01001300 f_cleanup();
1301}
Harald Welte6dc2ac42020-11-16 09:16:17 +01001302
Harald Welte99ed5072021-01-15 20:38:58 +01001303private function f_resume_one(integer sgsn_idx, integer nri_idx, integer pcu_idx, integer bvc_idx,
1304 integer suffix)
Harald Welte00963752021-01-15 20:33:11 +01001305runs on GlobalTest_CT
1306{
1307 var RoutingAreaIdentification ra_id := g_pcu[pcu_idx].cfg.bvc[bvc_idx].cell_id.ra_id;
Harald Welte99ed5072021-01-15 20:38:58 +01001308 var OCT4 p_tmsi := f_gen_tmsi(suffix, nri_v := mp_sgsn_nri[sgsn_idx][nri_idx],
1309 nri_bitlen := mp_nri_bitlength);
1310 var OCT4 tlli := f_gprs_tlli_from_tmsi(p_tmsi, TLLI_LOCAL);
Harald Welte00963752021-01-15 20:33:11 +01001311 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RESUME(tlli, ra_id, int2oct(suffix, 1));
1312 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1313 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RESUME(tlli, ra_id, int2oct(suffix, 1));
1314 f_global_pcu2sgsn(pdu_tx, pdu_rx, pcu_idx, sgsn_idx);
1315
1316 pdu_tx := ts_BSSGP_RESUME_ACK(tlli, ra_id);
1317 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1318 pdu_rx := tr_BSSGP_RESUME_ACK(tlli, ra_id);
1319 f_global_sgsn2pcu(pdu_tx, pdu_rx, sgsn_idx, pcu_idx);
1320
1321 pdu_tx := ts_BSSGP_RESUME(tlli, ra_id, int2oct(suffix, 1));
1322 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1323 pdu_rx := tr_BSSGP_RESUME(tlli, ra_id, int2oct(suffix, 1));
1324 f_global_pcu2sgsn(pdu_tx, pdu_rx, pcu_idx, sgsn_idx);
1325
1326 /* These messages are simple passed through so just also test sending NACK */
1327 pdu_tx := ts_BSSGP_RESUME_NACK(tlli, ra_id, BSSGP_CAUSE_UNKNOWN_MS);
1328 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1329 pdu_rx := tr_BSSGP_RESUME_NACK(tlli, ra_id, BSSGP_CAUSE_UNKNOWN_MS);
1330 f_global_sgsn2pcu(pdu_tx, pdu_rx, sgsn_idx, pcu_idx);
1331}
1332
Harald Weltec5c33732021-01-15 21:04:35 +01001333private function f_TC_resume(integer sgsn_idx, integer nri_idx, integer pcu_idx, integer bvc_idx)
1334runs on GlobalTest_CT {
Daniel Willmann087a33d2020-11-19 15:58:43 +01001335 var integer i;
1336
Daniel Willmann087a33d2020-11-19 15:58:43 +01001337 for (i := 0; i < 10; i := i+1) {
Harald Weltec5c33732021-01-15 21:04:35 +01001338 f_resume_one(sgsn_idx, nri_idx, pcu_idx, bvc_idx, suffix := i);
Daniel Willmann087a33d2020-11-19 15:58:43 +01001339 }
1340 setverdict(pass);
1341}
Harald Welte3807ed12020-11-24 19:05:22 +01001342testcase TC_resume() runs on GlobalTest_CT
Daniel Willmann087a33d2020-11-19 15:58:43 +01001343{
Harald Weltec5c33732021-01-15 21:04:35 +01001344 var integer sgsn_idx, nri_idx;
Daniel Willmann087a33d2020-11-19 15:58:43 +01001345 f_init();
Harald Welte3807ed12020-11-24 19:05:22 +01001346 f_global_init();
Harald Weltec5c33732021-01-15 21:04:35 +01001347 for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx+1) {
1348 for (nri_idx := 0; nri_idx < lengthof(mp_sgsn_nri[sgsn_idx]); nri_idx := nri_idx+1) {
1349 f_TC_resume(sgsn_idx, nri_idx, pcu_idx:=0, bvc_idx:=0);
1350 }
1351 }
Daniel Willmann087a33d2020-11-19 15:58:43 +01001352 f_cleanup();
1353}
1354
Harald Weltef8ef0282020-11-18 12:16:59 +01001355/* test the load-sharing between multiple NS-VC on the BSS side */
1356private function f_TC_dl_ud_unidir(charstring id) runs on BSSGP_ConnHdlr {
1357 var integer i;
1358
1359 for (i := 0; i < 10; i := i+1) {
1360 var octetstring payload := f_rnd_octstring(i);
1361 var template (value) PDU_BSSGP pdu_tx :=
1362 ts_BSSGP_DL_UD(g_pars.tlli, payload, omit, ts_BSSGP_IMSI(g_pars.imsi));
Harald Welte09a1ce42021-01-16 11:18:38 +01001363 SGSN_PTP[g_pars.sgsn_idx].send(pdu_tx);
Harald Weltef8ef0282020-11-18 12:16:59 +01001364 }
1365 setverdict(pass);
1366}
Harald Welte09a1ce42021-01-16 11:18:38 +01001367
1368private function f_TC_load_sharing_dl(integer sgsn_idx) runs on test_CT_NS
Harald Weltef8ef0282020-11-18 12:16:59 +01001369{
1370 const integer num_ue := 10;
1371 var BSSGP_ConnHdlr vc_conn[num_ue];
Harald Weltef8ef0282020-11-18 12:16:59 +01001372 /* all BVC are now fully brought up. We disconnect BSSGP from NS on the BSS
1373 * side so we get the raw NsUnitdataIndication and hence observe different
1374 * NSVCI */
1375 disconnect(g_pcu[0].vc_NS:NS_SP, g_pcu[0].vc_BSSGP:BSCP);
1376 connect(g_pcu[0].vc_NS:NS_SP, self:NS);
1377
1378 /* there may still be some NS-VCs coming up? After all, the BVC-RESET succeeds after the first
1379 * of the NS-VC is ALIVE/UNBLOCKED */
1380 f_sleep(3.0);
1381
1382 /* start parallel components generating DL-UNITDATA from the SGSN side */
1383 for (var integer i:= 0; i < num_ue; i := i+1) {
Harald Welte2ecbca82021-01-16 11:23:09 +01001384 vc_conn[i] := f_start_handler(refers(f_TC_dl_ud_unidir), testcasename(),
Harald Welte09a1ce42021-01-16 11:18:38 +01001385 5+i, 30.0, sgsn_idx);
Harald Weltef8ef0282020-11-18 12:16:59 +01001386 }
1387
1388 /* now start counting all the messages that were queued before */
1389 /* TODO: We have a hard-coded assumption of 4 NS-VC in one NSE/NS-VCG here! */
1390 var ro_integer rx_count := { 0, 0, 0, 0 };
1391 timer T := 2.0;
1392 T.start;
1393 alt {
1394 [] as_NsUdiCount(0, rx_count);
1395 [] as_NsUdiCount(1, rx_count);
1396 [] as_NsUdiCount(2, rx_count);
1397 [] as_NsUdiCount(3, rx_count);
1398 [] NS.receive(NsUnitdataIndication:{0,?,?,*,*}) { repeat; } /* signaling BVC */
1399 [] NS.receive(NsStatusIndication:?) { repeat; }
1400 [] NS.receive {
1401 setverdict(fail, "Rx unexpected NS");
1402 mtc.stop;
1403 }
1404 [] T.timeout {
1405 }
1406 }
1407 for (var integer i := 0; i < lengthof(rx_count); i := i+1) {
1408 log("Rx on NSVCI ", mp_nsconfig_pcu[0].nsvc[i].nsvci, ": ", rx_count[i]);
1409 if (rx_count[i] == 0) {
1410 setverdict(fail, "Data not shared over all NSVC");
1411 }
1412 }
Harald Welte09a1ce42021-01-16 11:18:38 +01001413}
1414
1415testcase TC_load_sharing_dl() runs on test_CT_NS
1416{
1417 var integer sgsn_idx, nri_idx;
1418 f_init();
1419 for (sgsn_idx:=0; sgsn_idx < NUM_SGSN; sgsn_idx:=sgsn_idx+1) {
1420 f_TC_load_sharing_dl(sgsn_idx);
1421 }
Harald Weltef8ef0282020-11-18 12:16:59 +01001422 setverdict(pass);
1423}
1424private altstep as_NsUdiCount(integer nsvc_idx, inout ro_integer roi) runs on test_CT_NS {
1425 var NsUnitdataIndication udi;
1426 var BssgpBvcConfig bvcc := g_pcu[0].cfg.bvc[0];
1427 [] NS.receive(NsUnitdataIndication:{bvcc.bvci, g_pcu[0].cfg.nsei, mp_nsconfig_pcu[0].nsvc[nsvc_idx].nsvci, *, *}) -> value udi {
1428 roi[nsvc_idx] := roi[nsvc_idx] + 1;
1429 repeat;
1430 }
1431}
1432type component test_CT_NS extends test_CT {
1433 port NS_PT NS;
1434};
1435
1436
Harald Welte0e188242020-11-22 21:46:48 +01001437/***********************************************************************
1438 * PAGING PS procedure
1439 ***********************************************************************/
1440
1441private function f_send_paging_ps(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
1442 boolean use_sig := false)
1443runs on BSSGP_ConnHdlr return template (present) PDU_BSSGP {
1444 var template (value) PDU_BSSGP pdu_tx;
1445 var template (present) PDU_BSSGP pdu_rx;
1446 /* we always specify '0' as BVCI in the templates below, as we override it with
1447 * 'p4' later anyway */
1448 pdu_rx := tr_BSSGP_PS_PAGING(0);
1449 pdu_rx.pDU_BSSGP_PAGING_PS.iMSI := tr_BSSGP_IMSI(g_pars.imsi);
1450 if (ispresent(g_pars.p_tmsi)) {
1451 pdu_tx := ts_BSSGP_PS_PAGING_PTMSI(0, g_pars.imsi, oct2int(g_pars.p_tmsi));
1452 pdu_rx.pDU_BSSGP_PAGING_PS.pTMSI := tr_BSSGP_TMSI(oct2int(g_pars.p_tmsi));
1453 } else {
1454 pdu_tx := ts_BSSGP_PS_PAGING_IMSI(0, g_pars.imsi);
1455 pdu_rx.pDU_BSSGP_PAGING_PS.pTMSI := omit;
1456 }
1457 pdu_tx.pDU_BSSGP_PAGING_PS.paging_Field4 := p4;
1458 pdu_rx.pDU_BSSGP_PAGING_PS.paging_Field4 := p4;
1459 if (use_sig == false) {
Harald Welte158becf2020-12-09 12:32:32 +01001460 SGSN_PTP[sgsn_idx].send(pdu_tx);
Harald Welte0e188242020-11-22 21:46:48 +01001461 } else {
1462 SGSN_SIG[sgsn_idx].send(pdu_tx);
1463 }
1464 return pdu_rx;
1465}
1466
1467/* send paging defined by 'p4' on given SGSN-side index (ptp or signaling) and expect one paging to arrive on
1468 * specified PCU index */
1469private function f_send_paging_ps_exp_one_bss(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
1470 boolean use_sig := false,integer pcu_idx := 0)
1471runs on BSSGP_ConnHdlr {
1472 var template (present) PDU_BSSGP exp_rx;
Daniel Willmann1a859712020-12-04 00:59:45 +01001473 var boolean test_done := false;
Harald Welte0e188242020-11-22 21:46:48 +01001474 /* doesn't really make sense: Sending to a single BVCI means the message ends up
1475 * at that BVC (cell) only, and paging all over the BSS area is not possible */
1476 exp_rx := f_send_paging_ps(p4, sgsn_idx, use_sig);
1477 /* Expect paging to propagate to the one BSS addressed by the BVCI only */
1478 timer T := 2.0;
1479 T.start;
1480 alt {
Harald Welte158becf2020-12-09 12:32:32 +01001481 [not use_sig and not test_done] PCU_PTP[pcu_idx].receive(exp_rx) {
Harald Welte0e188242020-11-22 21:46:48 +01001482 setverdict(pass);
Daniel Willmann1a859712020-12-04 00:59:45 +01001483 test_done := true;
Harald Welte0e188242020-11-22 21:46:48 +01001484 repeat;
1485 }
1486 [not use_sig] PCU_SIG[pcu_idx].receive(exp_rx) {
1487 setverdict(fail, "Received paging on SIGNALING BVC, expected PTP BVC");
1488 }
Daniel Willmann1a859712020-12-04 00:59:45 +01001489 [use_sig and not test_done] PCU_SIG[pcu_idx].receive(exp_rx) {
Harald Welte0e188242020-11-22 21:46:48 +01001490 setverdict(pass);
Daniel Willmann1a859712020-12-04 00:59:45 +01001491 test_done := true;
Harald Welte0e188242020-11-22 21:46:48 +01001492 repeat;
1493 }
Harald Welte158becf2020-12-09 12:32:32 +01001494 [use_sig] PCU_PTP[pcu_idx].receive(exp_rx) {
Harald Welte0e188242020-11-22 21:46:48 +01001495 setverdict(fail, "Received paging on PTP BVC, expected SIGNALING BVC");
1496 }
Harald Welte158becf2020-12-09 12:32:32 +01001497 [] any from PCU_PTP.receive(exp_rx) {
Harald Welte0e188242020-11-22 21:46:48 +01001498 setverdict(fail, "Paging received on unexpected BVC");
1499 }
1500 [] any from PCU_SIG.receive(exp_rx) {
1501 setverdict(fail, "Paging received on unexpected BVC");
1502 }
Harald Welte158becf2020-12-09 12:32:32 +01001503 [] any from PCU_PTP.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}) {
Harald Welte0e188242020-11-22 21:46:48 +01001504 setverdict(fail, "Different Paging than expected received PTP BVC");
1505 }
1506 [] any from PCU_SIG.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}) {
1507 setverdict(fail, "Different Paging than expected on SIGNALING BVC");
1508 }
Daniel Willmann1a859712020-12-04 00:59:45 +01001509 [not test_done] T.timeout {
1510 setverdict(fail, "Timeout waiting for paging");
1511 }
1512 [test_done] T.timeout;
Harald Welte0e188242020-11-22 21:46:48 +01001513 }
1514}
1515
Harald Welte7462a592020-11-23 22:07:07 +01001516/* send a PS-PAGING but don't expect it to show up on any PTP or SIG BVC */
1517private function f_send_paging_ps_exp_no_bss(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
1518 boolean use_sig := false)
1519runs on BSSGP_ConnHdlr {
1520 var template (present) PDU_BSSGP exp_rx;
1521 exp_rx := f_send_paging_ps(p4, sgsn_idx, use_sig);
1522 /* Expect paging to propagate to no BSS */
1523 timer T := 2.0;
1524 T.start;
1525 alt {
Harald Welte158becf2020-12-09 12:32:32 +01001526 [] any from PCU_PTP.receive(exp_rx) {
Harald Welte7462a592020-11-23 22:07:07 +01001527 setverdict(fail, "Paging received on unexpected BVC");
1528 }
1529 [] any from PCU_SIG.receive(exp_rx) {
1530 setverdict(fail, "Paging received on unexpected BVC");
1531 }
Harald Welte158becf2020-12-09 12:32:32 +01001532 [] any from PCU_PTP.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}) {
Harald Welte7462a592020-11-23 22:07:07 +01001533 setverdict(fail, "Different Paging received on PTP BVC");
1534 }
1535 [] any from PCU_SIG.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}) {
1536 setverdict(fail, "Different Paging received on SIGNALING BVC");
1537 }
1538 [] T.timeout {
1539 setverdict(pass);
1540 }
1541 }
1542}
1543
Harald Welte0e188242020-11-22 21:46:48 +01001544private function f_TC_paging_ps_ptp_bss(charstring id) runs on BSSGP_ConnHdlr
1545{
1546 /* doesn't really make sense: Sending to a single BVCI means the message ends up
1547 * at that BVC (cell) only, and paging all over the BSS area is not possible */
Daniel Willmann2a330672021-01-18 18:50:02 +01001548 f_send_paging_ps_exp_one_bss(ts_BssgpP4BssArea, g_pars.sgsn_idx, false, 0);
Harald Welte0e188242020-11-22 21:46:48 +01001549}
1550testcase TC_paging_ps_ptp_bss() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001551 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001552 f_start_handlers(refers(f_TC_paging_ps_ptp_bss), testcasename(), 9);
Harald Welte0e188242020-11-22 21:46:48 +01001553 f_cleanup();
1554}
1555
1556/* PS-PAGING on PTP-BVC for Location Area */
1557private function f_TC_paging_ps_ptp_lac(charstring id) runs on BSSGP_ConnHdlr
1558{
1559 var template (present) PDU_BSSGP exp_rx;
1560 /* doesn't really make sense: Sending to a single BVCI means the message ends up
1561 * at that BVC (cell) only, and paging all over the BSS area is not possible */
Daniel Willmann2a330672021-01-18 18:50:02 +01001562 f_send_paging_ps_exp_one_bss(ts_BssgpP4LAC(pcu_bvc_cfg[0].cell_id.ra_id.lai), g_pars.sgsn_idx, false, 0);
Harald Welte0e188242020-11-22 21:46:48 +01001563}
1564testcase TC_paging_ps_ptp_lac() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001565 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001566 f_start_handlers(refers(f_TC_paging_ps_ptp_lac), testcasename(), 10);
Harald Welte0e188242020-11-22 21:46:48 +01001567 f_cleanup();
1568}
1569
Harald Welte7462a592020-11-23 22:07:07 +01001570/* PS-PAGING on PTP-BVC for unknown Location Area */
1571private function f_TC_paging_ps_ptp_lac_unknown(charstring id) runs on BSSGP_ConnHdlr
1572{
1573 var GSM_Types.LocationAreaIdentification unknown_la := {
1574 mcc_mnc := '567F99'H,
1575 lac := 33333
1576 };
1577 /* as it's sent on the PTP BVC, we expect it to pass even for unknown LAC */
Daniel Willmann2a330672021-01-18 18:50:02 +01001578 f_send_paging_ps_exp_one_bss(ts_BssgpP4LAC(unknown_la), g_pars.sgsn_idx, false, 0);
Harald Welte7462a592020-11-23 22:07:07 +01001579}
1580testcase TC_paging_ps_ptp_lac_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01001581 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001582 f_start_handlers(refers(f_TC_paging_ps_ptp_lac_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01001583 f_cleanup();
1584}
1585
Harald Welte0e188242020-11-22 21:46:48 +01001586/* PS-PAGING on PTP-BVC for Routeing Area */
1587private function f_TC_paging_ps_ptp_rac(charstring id) runs on BSSGP_ConnHdlr
1588{
1589 /* doesn't really make sense: Sending to a single BVCI means the message ends up
1590 * at that BVC (cell) only, and paging all over the BSS area is not possible */
Daniel Willmann2a330672021-01-18 18:50:02 +01001591 f_send_paging_ps_exp_one_bss(ts_BssgpP4RAC(pcu_bvc_cfg[0].cell_id.ra_id), g_pars.sgsn_idx, false, 0);
Harald Welte0e188242020-11-22 21:46:48 +01001592}
1593testcase TC_paging_ps_ptp_rac() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001594 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001595 f_start_handlers(refers(f_TC_paging_ps_ptp_rac), testcasename(), 11);
Harald Welte0e188242020-11-22 21:46:48 +01001596 f_cleanup();
1597}
1598
Harald Welte7462a592020-11-23 22:07:07 +01001599/* PS-PAGING on PTP-BVC for unknown Routeing Area */
1600private function f_TC_paging_ps_ptp_rac_unknown(charstring id) runs on BSSGP_ConnHdlr
1601{
1602 var RoutingAreaIdentification unknown_ra := {
1603 lai := {
1604 mcc_mnc := '567F99'H,
1605 lac := 33333
1606 },
1607 rac := 254
1608 };
1609 /* as it's sent on the PTP BVC, we expect it to pass even for unknown RAC */
Daniel Willmann2a330672021-01-18 18:50:02 +01001610 f_send_paging_ps_exp_one_bss(ts_BssgpP4RAC(unknown_ra), g_pars.sgsn_idx, false, 0);
Harald Welte7462a592020-11-23 22:07:07 +01001611}
1612testcase TC_paging_ps_ptp_rac_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01001613 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001614 f_start_handlers(refers(f_TC_paging_ps_ptp_rac_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01001615 f_cleanup();
1616}
1617
Harald Welte0e188242020-11-22 21:46:48 +01001618/* PS-PAGING on PTP-BVC for BVCI (one cell) */
1619private function f_TC_paging_ps_ptp_bvci(charstring id) runs on BSSGP_ConnHdlr
1620{
1621 /* this should be the normal case for MS in READY MM state after a lower layer failure */
Daniel Willmann2a330672021-01-18 18:50:02 +01001622 f_send_paging_ps_exp_one_bss(ts_BssgpP4Bvci(pcu_bvc_cfg[0].bvci), g_pars.sgsn_idx, false, 0);
Harald Welte0e188242020-11-22 21:46:48 +01001623}
1624testcase TC_paging_ps_ptp_bvci() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001625 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001626 f_start_handlers(refers(f_TC_paging_ps_ptp_bvci), testcasename(), 12);
Harald Welte0e188242020-11-22 21:46:48 +01001627 f_cleanup();
1628}
1629
Harald Welteb5a04aa2021-01-16 13:04:40 +01001630
1631/* PS-PAGING on PTP-BVC for BVCI (one cell) using IMSI only (no P-TMSI allocated) */
1632testcase TC_paging_ps_ptp_bvci_imsi() runs on test_CT {
1633 f_init();
1634 f_start_handlers(refers(f_TC_paging_ps_ptp_bvci), testcasename(), 12, have_ptmsi:=false);
1635 f_cleanup();
1636}
1637
Harald Weltecf200072021-01-16 15:20:46 +01001638/* Rejected PS-PAGING on PTP-BVC for BVCI (one cell) */
1639testcase TC_paging_ps_reject_ptp_bvci() runs on test_CT {
1640 f_init();
1641 f_start_handlers(refers(f_TC_paging_ps_reject_ptp_bvci), testcasename(), 16);
1642 f_cleanup();
1643}
1644
1645/* Rejected PS-PAGING on PTP-BVC for BVCI (one cell) using IMSI only (no P-TMSI allocated) */
1646private function f_TC_paging_ps_reject_ptp_bvci(charstring id) runs on BSSGP_ConnHdlr
1647{
1648 /* first send the PS-PAGING from SGSN -> PCU */
Daniel Willmann2a330672021-01-18 18:50:02 +01001649 f_send_paging_ps_exp_one_bss(ts_BssgpP4Bvci(pcu_bvc_cfg[0].bvci), g_pars.sgsn_idx, false, 0);
Harald Weltecf200072021-01-16 15:20:46 +01001650 /* then simulate the PS-PAGING-REJECT from the PCU */
1651 f_send_paging_ps_rej(use_sig:=false);
1652}
1653testcase TC_paging_ps_reject_ptp_bvci_imsi() runs on test_CT {
1654 f_init();
1655 f_start_handlers(refers(f_TC_paging_ps_reject_ptp_bvci), testcasename(), 16, have_ptmsi:=false);
1656 f_cleanup();
1657}
Harald Welteb5a04aa2021-01-16 13:04:40 +01001658
Harald Welte7462a592020-11-23 22:07:07 +01001659/* PS-PAGING on PTP-BVC for unknown BVCI */
1660private function f_TC_paging_ps_ptp_bvci_unknown(charstring id) runs on BSSGP_ConnHdlr
1661{
1662 /* as it's sent on the PTP BVC, we expect it to pass even for unknown BVCI */
Daniel Willmann2a330672021-01-18 18:50:02 +01001663 f_send_paging_ps_exp_one_bss(ts_BssgpP4Bvci(33333), g_pars.sgsn_idx, false, 0);
Harald Welte7462a592020-11-23 22:07:07 +01001664}
1665testcase TC_paging_ps_ptp_bvci_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01001666 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001667 f_start_handlers(refers(f_TC_paging_ps_ptp_bvci_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01001668 f_cleanup();
1669}
1670
Harald Welte7595d562021-01-16 19:09:20 +01001671/* DUMMY PAGING PS on PTP BVC */
1672private function f_TC_dummy_paging_ps_ptp(charstring id) runs on BSSGP_ConnHdlr
1673{
1674 f_sgsn2pcu(ts_BSSGP_DUMMY_PAGING_PS(g_pars.imsi, omit),
1675 tr_BSSGP_DUMMY_PAGING_PS(g_pars.imsi, omit), use_sig := false);
1676 f_pcu2sgsn(ts_BSSGP_DUMMY_PAGING_PS_RESP(g_pars.imsi, 1, 5),
1677 tr_BSSGP_DUMMY_PAGING_PS_RESP(g_pars.imsi, 1, 5), use_sig := false)
1678}
1679testcase TC_dummy_paging_ps_ptp() runs on test_CT {
1680 f_init();
1681 f_start_handlers(refers(f_TC_dummy_paging_ps_ptp), testcasename(), 11);
1682 f_cleanup();
1683}
1684
Harald Welte0e188242020-11-22 21:46:48 +01001685/* altstep for expecting BSSGP PDU on signaling BVC of given pcu_idx + storing in 'roi' */
1686private altstep as_paging_sig_pcu(integer pcu_idx, template (present) PDU_BSSGP exp_rx, inout ro_integer roi)
1687runs on BSSGP_ConnHdlr {
1688[] PCU_SIG[pcu_idx].receive(exp_rx) {
1689 if (ro_integer_contains(roi, pcu_idx)) {
1690 setverdict(fail, "Received multiple paging on same SIG BVC");
1691 }
1692 roi := roi & { pcu_idx };
1693 repeat;
1694 }
Harald Welte158becf2020-12-09 12:32:32 +01001695[] PCU_PTP[pcu_idx].receive(exp_rx) {
Harald Welte0e188242020-11-22 21:46:48 +01001696 setverdict(fail, "Received paging on PTP BVC, expected SIGNALING BVC");
1697 }
1698[] PCU_SIG[pcu_idx].receive(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}) {
1699 setverdict(fail, "Different Paging than expected received SIGNALING BVC");
1700 }
Harald Welte158becf2020-12-09 12:32:32 +01001701[] PCU_PTP[pcu_idx].receive(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}) {
Harald Welte0e188242020-11-22 21:46:48 +01001702 setverdict(fail, "Different Paging than expected received PTP BVC");
1703 }
1704}
1705
1706type record of default ro_default;
1707
1708/* send PS-PAGING on SIG BVC, expect it to arrive on given list of PCU indexes */
1709private function f_send_paging_ps_exp_multi(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
1710 ro_integer exp_on_pcu_idx) runs on BSSGP_ConnHdlr
1711{
1712 var template (present) PDU_BSSGP exp_rx;
Daniel Willmann193e1a02021-01-17 12:55:53 +01001713 exp_rx := f_send_paging_ps(p4, sgsn_idx, true);
Harald Welte0e188242020-11-22 21:46:48 +01001714
1715 /* FIXME: make sure the relevant BVCs/BSS are connected to the ports! */
1716 var ro_default defaults := {};
1717 for (var integer i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
1718 var default d := activate(as_paging_sig_pcu(i, exp_rx, g_roi));
1719 defaults := defaults & { d };
1720 }
1721 f_sleep(2.0);
1722 for (var integer i := 0; i < lengthof(defaults); i := i+1) {
1723 deactivate(defaults[i]);
1724 }
1725 log("Paging received on PCU ", g_roi);
1726
1727 for (var integer i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
1728 var boolean rx_on_i := ro_integer_contains(g_roi, i);
1729 var boolean exp_on_i := ro_integer_contains(exp_on_pcu_idx, i);
1730 if (exp_on_i and not rx_on_i) {
1731 setverdict(fail, "PS-PAGING not received on ", mp_nsconfig_pcu[i].nsei);
1732 }
1733 if (not exp_on_i and rx_on_i) {
1734 setverdict(fail, "PS-PAGING not expected but received on ", mp_nsconfig_pcu[i].nsei);
1735 }
1736 }
1737 setverdict(pass);
1738}
1739
Harald Weltecf200072021-01-16 15:20:46 +01001740/* Send PAGING-PS-REJECT on SIG BVC, expect it to arrive on the "right" SGSN */
1741private function f_send_paging_ps_rej(boolean use_sig := true, integer pcu_idx := 0) runs on BSSGP_ConnHdlr
1742{
1743 var template (value) PDU_BSSGP pdu_tx;
1744 var template (present) PDU_BSSGP exp_rx;
1745 var PDU_BSSGP pdu_rx;
1746 timer T := 5.0;
1747 var template (omit) GsmTmsi tmsi_int := omit;
1748
1749 if (ispresent(g_pars.p_tmsi)) {
1750 tmsi_int := oct2int(g_pars.p_tmsi);
1751 }
1752
1753 pdu_tx := ts_BSSGP_PAGING_PS_REJ(g_pars.imsi, 23, 42, tmsi_int);
1754 exp_rx := tr_BSSGP_PAGING_PS_REJ(g_pars.imsi, 23, 42, tmsi_int);
1755
1756 if (use_sig) {
1757 PCU_SIG[pcu_idx].send(pdu_tx);
1758 } else {
1759 PCU_PTP[pcu_idx].send(pdu_tx);
1760 }
1761 T.start;
1762 alt {
1763 [use_sig] SGSN_SIG[g_pars.sgsn_idx].receive(exp_rx) -> value pdu_rx {
1764 setverdict(pass);
1765 }
1766 [use_sig] SGSN_SIG[g_pars.sgsn_idx].receive {
1767 setverdict(fail, "Unexpected PDU on SGSN");
1768 }
1769 [use_sig] any from SGSN_SIG.receive(exp_rx) -> value pdu_rx {
1770 setverdict(fail, "PAGING-PS-REJECT arrived on wrong SGSN");
1771 }
1772 [not use_sig] SGSN_PTP[g_pars.sgsn_idx].receive(exp_rx) -> value pdu_rx {
1773 setverdict(pass);
1774 }
1775 [not use_sig] SGSN_PTP[g_pars.sgsn_idx].receive {
1776 setverdict(fail, "Unexpected PDU on SGSN");
1777 }
1778 [not use_sig] any from SGSN_PTP.receive(exp_rx) -> value pdu_rx {
1779 setverdict(fail, "PAGING-PS-REJECT arrived on wrong SGSN");
1780 }
1781 [] T.timeout {
1782 setverdict(fail, "Timeout waiting for PAGING-PS-REJECT");
1783 }
1784 }
1785}
1786
Harald Welte0e188242020-11-22 21:46:48 +01001787/* PS-PAGING on SIG-BVC for BSS Area */
1788private function f_TC_paging_ps_sig_bss(charstring id) runs on BSSGP_ConnHdlr
1789{
1790 /* we expect the paging to arrive on all three NSE */
Daniel Willmann43320442021-01-17 14:07:05 +01001791 f_send_paging_ps_exp_multi(ts_BssgpP4BssArea, g_pars.sgsn_idx, {0, 1, 2});
Harald Welte0e188242020-11-22 21:46:48 +01001792}
1793testcase TC_paging_ps_sig_bss() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001794 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001795 f_start_handlers(refers(f_TC_paging_ps_sig_bss), testcasename(), 13);
Harald Welte0e188242020-11-22 21:46:48 +01001796 f_cleanup();
1797}
1798
1799/* PS-PAGING on SIG-BVC for Location Area */
1800private function f_TC_paging_ps_sig_lac(charstring id) runs on BSSGP_ConnHdlr
1801{
Daniel Willmann2c9300f2020-12-01 10:54:08 +01001802 /* The first LAC (13135) is shared by all three NSEs */
Daniel Willmann43320442021-01-17 14:07:05 +01001803 f_send_paging_ps_exp_multi(ts_BssgpP4LAC(pcu_bvc_cfg[0].cell_id.ra_id.lai), g_pars.sgsn_idx, {0, 1, 2});
Daniel Willmann2c9300f2020-12-01 10:54:08 +01001804 /* Reset state */
1805 g_roi := {};
1806 /* Make LAC (13300) available on pcu index 2 */
1807 f_connect_to_pcu_bvc(port_idx := 2, nse_idx := 2, bvc_idx := 1);
Daniel Willmann43320442021-01-17 14:07:05 +01001808 f_send_paging_ps_exp_multi(ts_BssgpP4LAC(pcu_bvc_cfg[2].cell_id.ra_id.lai), g_pars.sgsn_idx, {2});
Harald Welte0e188242020-11-22 21:46:48 +01001809}
1810testcase TC_paging_ps_sig_lac() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001811 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001812 f_start_handlers(refers(f_TC_paging_ps_sig_lac), testcasename(), 14);
Harald Welte0e188242020-11-22 21:46:48 +01001813 f_cleanup();
1814}
1815
Harald Welte7462a592020-11-23 22:07:07 +01001816/* PS-PAGING on SIG-BVC for unknown Location Area */
1817private function f_TC_paging_ps_sig_lac_unknown(charstring id) runs on BSSGP_ConnHdlr
1818{
1819 var GSM_Types.LocationAreaIdentification unknown_la := {
1820 mcc_mnc := '567F99'H,
1821 lac := 33333
1822 };
Daniel Willmann2a330672021-01-18 18:50:02 +01001823 f_send_paging_ps_exp_no_bss(ts_BssgpP4LAC(unknown_la), g_pars.sgsn_idx, true);
Harald Welte7462a592020-11-23 22:07:07 +01001824}
1825testcase TC_paging_ps_sig_lac_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01001826 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001827 f_start_handlers(refers(f_TC_paging_ps_sig_lac_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01001828 f_cleanup();
1829}
1830
Harald Welte0e188242020-11-22 21:46:48 +01001831/* PS-PAGING on SIG-BVC for Routeing Area */
1832private function f_TC_paging_ps_sig_rac(charstring id) runs on BSSGP_ConnHdlr
1833{
Daniel Willmann2c9300f2020-12-01 10:54:08 +01001834 /* Only PCU index 0 has a matching BVC with the RA ID */
Daniel Willmann43320442021-01-17 14:07:05 +01001835 f_send_paging_ps_exp_multi(ts_BssgpP4RAC(pcu_bvc_cfg[0].cell_id.ra_id), g_pars.sgsn_idx, {0});
Daniel Willmann2c9300f2020-12-01 10:54:08 +01001836 g_roi := {};
1837 /* PCU index 1 and 2 have a matching BVC with the RA ID */
Daniel Willmann43320442021-01-17 14:07:05 +01001838 f_send_paging_ps_exp_multi(ts_BssgpP4RAC(pcu_bvc_cfg[2].cell_id.ra_id), g_pars.sgsn_idx, {1, 2});
Daniel Willmann2c9300f2020-12-01 10:54:08 +01001839 g_roi := {};
1840 /* PCU index 2 has two matching BVCs with the RA ID */
1841 f_connect_to_pcu_bvc(port_idx := 2, nse_idx := 2, bvc_idx := 1);
Daniel Willmann43320442021-01-17 14:07:05 +01001842 f_send_paging_ps_exp_multi(ts_BssgpP4RAC(pcu_bvc_cfg[2].cell_id.ra_id), g_pars.sgsn_idx, {2});
Harald Welte0e188242020-11-22 21:46:48 +01001843}
1844testcase TC_paging_ps_sig_rac() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001845 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001846 f_start_handlers(refers(f_TC_paging_ps_sig_rac), testcasename(), 15);
Harald Welte0e188242020-11-22 21:46:48 +01001847 f_cleanup();
1848}
1849
Harald Welte7462a592020-11-23 22:07:07 +01001850/* PS-PAGING on SIG-BVC for unknown Routeing Area */
1851private function f_TC_paging_ps_sig_rac_unknown(charstring id) runs on BSSGP_ConnHdlr
1852{
1853 var RoutingAreaIdentification unknown_ra := {
1854 lai := {
1855 mcc_mnc := '567F99'H,
1856 lac := 33333
1857 },
1858 rac := 254
1859 };
Daniel Willmann2a330672021-01-18 18:50:02 +01001860 f_send_paging_ps_exp_no_bss(ts_BssgpP4RAC(unknown_ra), g_pars.sgsn_idx, true);
Harald Welte7462a592020-11-23 22:07:07 +01001861}
1862testcase TC_paging_ps_sig_rac_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01001863 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001864 f_start_handlers(refers(f_TC_paging_ps_sig_rac_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01001865 f_cleanup();
1866}
1867
Harald Welte0e188242020-11-22 21:46:48 +01001868/* PS-PAGING on SIG-BVC for BVCI (one cell) */
1869private function f_TC_paging_ps_sig_bvci(charstring id) runs on BSSGP_ConnHdlr
1870{
Daniel Willmann43320442021-01-17 14:07:05 +01001871 f_send_paging_ps_exp_multi(ts_BssgpP4Bvci(pcu_bvc_cfg[0].bvci), g_pars.sgsn_idx, {0});
Harald Welte0e188242020-11-22 21:46:48 +01001872}
1873testcase TC_paging_ps_sig_bvci() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001874 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001875 f_start_handlers(refers(f_TC_paging_ps_sig_bvci), testcasename(), 16);
Harald Welte0e188242020-11-22 21:46:48 +01001876 f_cleanup();
1877}
1878
Harald Welteb5a04aa2021-01-16 13:04:40 +01001879/* PS-PAGING on SIG-BVC for BVCI (one cell) using IMSI only (no P-TMSI allocated) */
1880testcase TC_paging_ps_sig_bvci_imsi() runs on test_CT {
1881 f_init();
1882 f_start_handlers(refers(f_TC_paging_ps_sig_bvci), testcasename(), 16, have_ptmsi:=false);
1883 f_cleanup();
1884}
1885
Harald Weltecf200072021-01-16 15:20:46 +01001886/* Rejected PS-PAGING on SIG-BVC for BVCI (one cell) */
1887private function f_TC_paging_ps_reject_sig_bvci(charstring id) runs on BSSGP_ConnHdlr
1888{
1889 /* first send the PS-PAGING from SGSN -> PCU */
Daniel Willmann43320442021-01-17 14:07:05 +01001890 f_send_paging_ps_exp_multi(ts_BssgpP4Bvci(pcu_bvc_cfg[0].bvci), g_pars.sgsn_idx, {0});
Harald Weltecf200072021-01-16 15:20:46 +01001891 /* then simulate the PS-PAGING-REJECT from the PCU */
1892 f_send_paging_ps_rej(use_sig:=true);
1893
1894}
1895testcase TC_paging_ps_reject_sig_bvci() runs on test_CT {
1896 f_init();
1897 f_start_handlers(refers(f_TC_paging_ps_reject_sig_bvci), testcasename(), 16);
1898 f_cleanup();
1899}
1900
1901/* Rejected PS-PAGING on SIG-BVC for BVCI (one cell) using IMSI only (no P-TMSI allocated) */
1902testcase TC_paging_ps_reject_sig_bvci_imsi() runs on test_CT {
1903 f_init();
1904 f_start_handlers(refers(f_TC_paging_ps_reject_sig_bvci), testcasename(), 16, have_ptmsi:=false);
1905 f_cleanup();
1906}
1907
Harald Welte7462a592020-11-23 22:07:07 +01001908/* PS-PAGING on SIG-BVC for unknown BVCI */
1909private function f_TC_paging_ps_sig_bvci_unknown(charstring id) runs on BSSGP_ConnHdlr
1910{
Daniel Willmann2a330672021-01-18 18:50:02 +01001911 f_send_paging_ps_exp_no_bss(ts_BssgpP4Bvci(33333), g_pars.sgsn_idx, true);
Harald Welte7462a592020-11-23 22:07:07 +01001912}
1913testcase TC_paging_ps_sig_bvci_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01001914 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001915 f_start_handlers(refers(f_TC_paging_ps_sig_bvci_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01001916 f_cleanup();
1917}
1918
Harald Welte7595d562021-01-16 19:09:20 +01001919/* DUMMY PAGING PS on SIG BVC */
1920private function f_TC_dummy_paging_ps_sig(charstring id) runs on BSSGP_ConnHdlr
1921{
1922 f_sgsn2pcu(ts_BSSGP_DUMMY_PAGING_PS(g_pars.imsi, omit),
1923 tr_BSSGP_DUMMY_PAGING_PS(g_pars.imsi, omit), use_sig := true);
1924 f_pcu2sgsn(ts_BSSGP_DUMMY_PAGING_PS_RESP(g_pars.imsi, 1, 5),
1925 tr_BSSGP_DUMMY_PAGING_PS_RESP(g_pars.imsi, 1, 5), use_sig := true)
1926}
1927testcase TC_dummy_paging_ps_sig() runs on test_CT {
1928 f_init();
1929 f_start_handlers(refers(f_TC_dummy_paging_ps_sig), testcasename(), 11);
1930 f_cleanup();
1931}
1932
Harald Welte7462a592020-11-23 22:07:07 +01001933
Harald Welte0e188242020-11-22 21:46:48 +01001934
1935/***********************************************************************
1936 * PAGING CS procedure
1937 ***********************************************************************/
1938
1939private function f_send_paging_cs(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
1940 boolean use_sig := false)
1941runs on BSSGP_ConnHdlr return template (present) PDU_BSSGP {
1942 var template (value) PDU_BSSGP pdu_tx;
1943 var template (present) PDU_BSSGP pdu_rx;
1944 /* we always specify '0' as BVCI in the templates below, as we override it with
1945 * 'p4' later anyway */
1946 pdu_rx := tr_BSSGP_CS_PAGING(0);
1947 pdu_rx.pDU_BSSGP_PAGING_CS.iMSI := tr_BSSGP_IMSI(g_pars.imsi);
1948 if (ispresent(g_pars.p_tmsi)) {
1949 pdu_tx := ts_BSSGP_CS_PAGING_PTMSI(0, g_pars.imsi, oct2int(g_pars.p_tmsi));
1950 pdu_rx.pDU_BSSGP_PAGING_CS.tMSI := tr_BSSGP_TMSI(oct2int(g_pars.p_tmsi));
1951 } else {
1952 pdu_tx := ts_BSSGP_CS_PAGING_IMSI(0, g_pars.imsi);
1953 pdu_rx.pDU_BSSGP_PAGING_CS.tMSI := omit;
1954 }
1955 pdu_tx.pDU_BSSGP_PAGING_CS.paging_Field4 := p4;
1956 pdu_rx.pDU_BSSGP_PAGING_CS.paging_Field4 := p4;
1957 if (use_sig == false) {
Harald Welte158becf2020-12-09 12:32:32 +01001958 SGSN_PTP[sgsn_idx].send(pdu_tx);
Harald Welte0e188242020-11-22 21:46:48 +01001959 } else {
1960 SGSN_SIG[sgsn_idx].send(pdu_tx);
1961 }
1962 return pdu_rx;
1963}
1964
1965/* send paging defined by 'p4' on given SGSN-side index (ptp or signaling) and expect one paging to arrive on
1966 * specified PCU index */
1967private function f_send_paging_cs_exp_one_bss(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
1968 boolean use_sig := false,integer pcu_idx := 0)
1969runs on BSSGP_ConnHdlr {
1970 var template (present) PDU_BSSGP exp_rx;
Daniel Willmann1a859712020-12-04 00:59:45 +01001971 var boolean test_done := false;
Harald Welte0e188242020-11-22 21:46:48 +01001972 /* doesn't really make sense: Sending to a single BVCI means the message ends up
1973 * at that BVC (cell) only, and paging all over the BSS area is not possible */
1974 exp_rx := f_send_paging_cs(p4, sgsn_idx, use_sig);
1975 /* Expect paging to propagate to the one BSS addressed by the BVCI only */
1976 timer T := 2.0;
1977 T.start;
1978 alt {
Harald Welte158becf2020-12-09 12:32:32 +01001979 [not use_sig and not test_done] PCU_PTP[pcu_idx].receive(exp_rx) {
Harald Welte0e188242020-11-22 21:46:48 +01001980 setverdict(pass);
Daniel Willmann1a859712020-12-04 00:59:45 +01001981 test_done := true;
Harald Welte0e188242020-11-22 21:46:48 +01001982 repeat;
1983 }
1984 [not use_sig] PCU_SIG[pcu_idx].receive(exp_rx) {
1985 setverdict(fail, "Received paging on SIGNALING BVC, expected PTP BVC");
1986 }
Daniel Willmann1a859712020-12-04 00:59:45 +01001987 [use_sig and not test_done] PCU_SIG[pcu_idx].receive(exp_rx) {
Harald Welte0e188242020-11-22 21:46:48 +01001988 setverdict(pass);
Daniel Willmann1a859712020-12-04 00:59:45 +01001989 test_done := true;
Harald Welte0e188242020-11-22 21:46:48 +01001990 repeat;
1991 }
Harald Welte158becf2020-12-09 12:32:32 +01001992 [use_sig] PCU_PTP[pcu_idx].receive(exp_rx) {
Harald Welte0e188242020-11-22 21:46:48 +01001993 setverdict(fail, "Received paging on PTP BVC, expected SIGNALING BVC");
1994 }
Harald Welte158becf2020-12-09 12:32:32 +01001995 [] any from PCU_PTP.receive(exp_rx) {
Harald Welte0e188242020-11-22 21:46:48 +01001996 setverdict(fail, "Paging received on unexpected BVC");
1997 }
1998 [] any from PCU_SIG.receive(exp_rx) {
1999 setverdict(fail, "Paging received on unexpected BVC");
2000 }
Harald Welte158becf2020-12-09 12:32:32 +01002001 [] any from PCU_PTP.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_CS:=?}) {
Harald Welte0e188242020-11-22 21:46:48 +01002002 setverdict(fail, "Different Paging than expected received PTP BVC");
2003 }
2004 [] any from PCU_SIG.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_CS:=?}) {
2005 setverdict(fail, "Different Paging than expected on SIGNALING BVC");
2006 }
Daniel Willmann1a859712020-12-04 00:59:45 +01002007 [not test_done] T.timeout {
2008 setverdict(fail, "Timeout while waiting for paging")
2009 }
2010 [test_done] T.timeout;
Harald Welte0e188242020-11-22 21:46:48 +01002011 }
2012}
2013
Harald Welte7462a592020-11-23 22:07:07 +01002014/* send a CS-PAGING but don't expect it to show up on any PTP or SIG BVC */
2015private function f_send_paging_cs_exp_no_bss(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
2016 boolean use_sig := false)
2017runs on BSSGP_ConnHdlr {
2018 var template (present) PDU_BSSGP exp_rx;
2019 exp_rx := f_send_paging_cs(p4, sgsn_idx, use_sig);
2020 /* Expect paging to propagate to no BSS */
2021 timer T := 2.0;
2022 T.start;
2023 alt {
Harald Welte158becf2020-12-09 12:32:32 +01002024 [] any from PCU_PTP.receive(exp_rx) {
Harald Welte7462a592020-11-23 22:07:07 +01002025 setverdict(fail, "Paging received on unexpected BVC");
2026 }
2027 [] any from PCU_SIG.receive(exp_rx) {
2028 setverdict(fail, "Paging received on unexpected BVC");
2029 }
Harald Welte158becf2020-12-09 12:32:32 +01002030 [] any from PCU_PTP.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_CS:=?}) {
Harald Welte7462a592020-11-23 22:07:07 +01002031 setverdict(fail, "Different Paging received on PTP BVC");
2032 }
2033 [] any from PCU_SIG.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_CS:=?}) {
2034 setverdict(fail, "Different Paging received on SIGNALING BVC");
2035 }
2036 [] T.timeout {
2037 setverdict(pass);
2038 }
2039 }
2040}
2041
Harald Welte0e188242020-11-22 21:46:48 +01002042private function f_TC_paging_cs_ptp_bss(charstring id) runs on BSSGP_ConnHdlr
2043{
2044 /* doesn't really make sense: Sending to a single BVCI means the message ends up
2045 * at that BVC (cell) only, and paging all over the BSS area is not possible */
2046 f_send_paging_cs_exp_one_bss(ts_BssgpP4BssArea, 0, false, 0);
2047}
2048testcase TC_paging_cs_ptp_bss() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01002049 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002050 f_start_handlers(refers(f_TC_paging_cs_ptp_bss), testcasename(), 17);
Harald Welte0e188242020-11-22 21:46:48 +01002051 f_cleanup();
2052}
2053
2054/* CS-PAGING on PTP-BVC for Location Area */
2055private function f_TC_paging_cs_ptp_lac(charstring id) runs on BSSGP_ConnHdlr
2056{
2057 var template (present) PDU_BSSGP exp_rx;
2058 /* doesn't really make sense: Sending to a single BVCI means the message ends up
2059 * at that BVC (cell) only, and paging all over the BSS area is not possible */
2060 f_send_paging_cs_exp_one_bss(ts_BssgpP4LAC(pcu_bvc_cfg[0].cell_id.ra_id.lai), 0, false, 0);
2061}
2062testcase TC_paging_cs_ptp_lac() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01002063 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002064 f_start_handlers(refers(f_TC_paging_cs_ptp_lac), testcasename(), 18);
Harald Welte0e188242020-11-22 21:46:48 +01002065 f_cleanup();
2066}
2067
Harald Welte7462a592020-11-23 22:07:07 +01002068/* CS-PAGING on PTP-BVC for unknown Location Area */
2069private function f_TC_paging_cs_ptp_lac_unknown(charstring id) runs on BSSGP_ConnHdlr
2070{
2071 var GSM_Types.LocationAreaIdentification unknown_la := {
2072 mcc_mnc := '567F99'H,
2073 lac := 33333
2074 };
2075 /* as it's sent on the PTP BVC, we expect it to pass even for unknown LAC */
2076 f_send_paging_cs_exp_one_bss(ts_BssgpP4LAC(unknown_la), 0, false, 0);
2077}
2078testcase TC_paging_cs_ptp_lac_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01002079 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002080 f_start_handlers(refers(f_TC_paging_cs_ptp_lac_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01002081 f_cleanup();
2082}
2083
Harald Welte0e188242020-11-22 21:46:48 +01002084/* CS-PAGING on PTP-BVC for Routeing Area */
2085private function f_TC_paging_cs_ptp_rac(charstring id) runs on BSSGP_ConnHdlr
2086{
2087 /* doesn't really make sense: Sending to a single BVCI means the message ends up
2088 * at that BVC (cell) only, and paging all over the BSS area is not possible */
2089 f_send_paging_cs_exp_one_bss(ts_BssgpP4RAC(pcu_bvc_cfg[0].cell_id.ra_id), 0, false, 0);
2090}
2091testcase TC_paging_cs_ptp_rac() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01002092 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002093 f_start_handlers(refers(f_TC_paging_cs_ptp_rac), testcasename(), 19);
Harald Welte0e188242020-11-22 21:46:48 +01002094 f_cleanup();
2095}
2096
Harald Welte7462a592020-11-23 22:07:07 +01002097/* CS-PAGING on PTP-BVC for unknown Routeing Area */
2098private function f_TC_paging_cs_ptp_rac_unknown(charstring id) runs on BSSGP_ConnHdlr
2099{
2100 var RoutingAreaIdentification unknown_ra := {
2101 lai := {
2102 mcc_mnc := '567F99'H,
2103 lac := 33333
2104 },
2105 rac := 254
2106 };
2107 /* as it's sent on the PTP BVC, we expect it to pass even for unknown RAC */
2108 f_send_paging_cs_exp_one_bss(ts_BssgpP4RAC(unknown_ra), 0, false, 0);
2109}
2110testcase TC_paging_cs_ptp_rac_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01002111 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002112 f_start_handlers(refers(f_TC_paging_cs_ptp_rac_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01002113 f_cleanup();
2114}
2115
Harald Welte0e188242020-11-22 21:46:48 +01002116/* CS-PAGING on PTP-BVC for BVCI (one cell) */
2117private function f_TC_paging_cs_ptp_bvci(charstring id) runs on BSSGP_ConnHdlr
2118{
2119 /* this should be the normal case for MS in READY MM state after a lower layer failure */
2120 f_send_paging_cs_exp_one_bss(ts_BssgpP4Bvci(pcu_bvc_cfg[0].bvci), 0, false, 0);
2121}
2122testcase TC_paging_cs_ptp_bvci() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01002123 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002124 f_start_handlers(refers(f_TC_paging_cs_ptp_bvci), testcasename(), 20);
Harald Welte0e188242020-11-22 21:46:48 +01002125 f_cleanup();
2126}
2127
Harald Welte7462a592020-11-23 22:07:07 +01002128/* CS-PAGING on PTP-BVC for unknown BVCI */
2129private function f_TC_paging_cs_ptp_bvci_unknown(charstring id) runs on BSSGP_ConnHdlr
2130{
2131 /* as it's sent on the PTP BVC, we expect it to pass even for unknown BVCI */
2132 f_send_paging_cs_exp_one_bss(ts_BssgpP4Bvci(33333), 0, false, 0);
2133}
2134testcase TC_paging_cs_ptp_bvci_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01002135 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002136 f_start_handlers(refers(f_TC_paging_cs_ptp_bvci_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01002137 f_cleanup();
2138}
2139
Harald Welte0e188242020-11-22 21:46:48 +01002140/* send CS-PAGING on SIG BVC, expect it to arrive on given list of PCU indexes */
2141private function f_send_paging_cs_exp_multi(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
2142 ro_integer exp_on_pcu_idx) runs on BSSGP_ConnHdlr
2143{
2144 var template (present) PDU_BSSGP exp_rx;
2145 exp_rx := f_send_paging_cs(p4, 0, true);
2146
2147 /* FIXME: make sure the relevant BVCs/BSS are connected to the ports! */
2148 var ro_default defaults := {};
2149 for (var integer i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
2150 var default d := activate(as_paging_sig_pcu(i, exp_rx, g_roi));
2151 defaults := defaults & { d };
2152 }
2153 f_sleep(2.0);
2154 for (var integer i := 0; i < lengthof(defaults); i := i+1) {
2155 deactivate(defaults[i]);
2156 }
2157 log("Paging received on PCU ", g_roi);
2158
2159 for (var integer i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
2160 var boolean rx_on_i := ro_integer_contains(g_roi, i);
2161 var boolean exp_on_i := ro_integer_contains(exp_on_pcu_idx, i);
2162 if (exp_on_i and not rx_on_i) {
2163 setverdict(fail, "PS-PAGING not received on ", mp_nsconfig_pcu[i].nsei);
2164 }
2165 if (not exp_on_i and rx_on_i) {
2166 setverdict(fail, "PS-PAGING not expected but received on ", mp_nsconfig_pcu[i].nsei);
2167 }
2168 }
2169 setverdict(pass);
2170}
2171
2172/* CS-PAGING on SIG-BVC for BSS Area */
2173private function f_TC_paging_cs_sig_bss(charstring id) runs on BSSGP_ConnHdlr
2174{
2175 /* we expect the paging to arrive on all three NSE */
2176 f_send_paging_cs_exp_multi(ts_BssgpP4BssArea, 0, {0, 1, 2});
2177}
2178testcase TC_paging_cs_sig_bss() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01002179 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002180 f_start_handlers(refers(f_TC_paging_cs_sig_bss), testcasename(), 13);
Harald Welte0e188242020-11-22 21:46:48 +01002181 f_cleanup();
2182}
2183
2184/* CS-PAGING on SIG-BVC for Location Area */
2185private function f_TC_paging_cs_sig_lac(charstring id) runs on BSSGP_ConnHdlr
2186{
Daniel Willmannd4fb73c2020-12-07 13:57:17 +01002187 /* The first LAC (13135) is shared by all three NSEs */
2188 f_send_paging_cs_exp_multi(ts_BssgpP4LAC(pcu_bvc_cfg[0].cell_id.ra_id.lai), 0, {0, 1, 2});
2189 /* Reset state */
2190 g_roi := {};
2191 /* Make LAC (13300) available on pcu index 2 */
2192 f_connect_to_pcu_bvc(port_idx := 2, nse_idx := 2, bvc_idx := 1);
2193 f_send_paging_cs_exp_multi(ts_BssgpP4LAC(pcu_bvc_cfg[2].cell_id.ra_id.lai), 0, {2});
Harald Welte0e188242020-11-22 21:46:48 +01002194}
2195testcase TC_paging_cs_sig_lac() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01002196 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002197 f_start_handlers(refers(f_TC_paging_cs_sig_lac), testcasename(), 14);
Harald Welte0e188242020-11-22 21:46:48 +01002198 f_cleanup();
2199}
2200
Harald Welte7462a592020-11-23 22:07:07 +01002201/* CS-PAGING on SIG-BVC for unknown Location Area */
2202private function f_TC_paging_cs_sig_lac_unknown(charstring id) runs on BSSGP_ConnHdlr
2203{
2204 var GSM_Types.LocationAreaIdentification unknown_la := {
2205 mcc_mnc := '567F99'H,
2206 lac := 33333
2207 };
2208 f_send_paging_cs_exp_no_bss(ts_BssgpP4LAC(unknown_la), 0, true);
2209}
2210testcase TC_paging_cs_sig_lac_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01002211 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002212 f_start_handlers(refers(f_TC_paging_cs_sig_lac_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01002213 f_cleanup();
2214}
2215
Harald Welte0e188242020-11-22 21:46:48 +01002216/* CS-PAGING on SIG-BVC for Routeing Area */
2217private function f_TC_paging_cs_sig_rac(charstring id) runs on BSSGP_ConnHdlr
2218{
Daniel Willmannd4fb73c2020-12-07 13:57:17 +01002219 /* Only PCU index 0 has a matching BVC with the RA ID */
Harald Welte0e188242020-11-22 21:46:48 +01002220 f_send_paging_cs_exp_multi(ts_BssgpP4RAC(pcu_bvc_cfg[0].cell_id.ra_id), 0, {0});
Daniel Willmannd4fb73c2020-12-07 13:57:17 +01002221 g_roi := {};
2222 /* PCU index 1 and 2 have a matching BVC with the RA ID */
2223 f_send_paging_cs_exp_multi(ts_BssgpP4RAC(pcu_bvc_cfg[2].cell_id.ra_id), 0, {1, 2});
2224 g_roi := {};
2225 /* PCU index 2 has two matching BVCs with the RA ID */
2226 f_connect_to_pcu_bvc(port_idx := 2, nse_idx := 2, bvc_idx := 1);
2227 f_send_paging_cs_exp_multi(ts_BssgpP4RAC(pcu_bvc_cfg[2].cell_id.ra_id), 0, {2});
Harald Welte0e188242020-11-22 21:46:48 +01002228}
2229testcase TC_paging_cs_sig_rac() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01002230 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002231 f_start_handlers(refers(f_TC_paging_cs_sig_rac), testcasename(), 15);
Harald Welte0e188242020-11-22 21:46:48 +01002232 f_cleanup();
2233}
2234
Harald Welte7462a592020-11-23 22:07:07 +01002235/* CS-PAGING on SIG-BVC for unknown Routeing Area */
2236private function f_TC_paging_cs_sig_rac_unknown(charstring id) runs on BSSGP_ConnHdlr
2237{
2238 var RoutingAreaIdentification unknown_ra := {
2239 lai := {
2240 mcc_mnc := '567F99'H,
2241 lac := 33333
2242 },
2243 rac := 254
2244 };
2245 f_send_paging_cs_exp_no_bss(ts_BssgpP4RAC(unknown_ra), 0, true);
2246}
2247testcase TC_paging_cs_sig_rac_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01002248 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002249 f_start_handlers(refers(f_TC_paging_cs_sig_rac_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01002250 f_cleanup();
2251}
2252
Harald Welte0e188242020-11-22 21:46:48 +01002253/* CS-PAGING on SIG-BVC for BVCI (one cell) */
2254private function f_TC_paging_cs_sig_bvci(charstring id) runs on BSSGP_ConnHdlr
2255{
2256 f_send_paging_cs_exp_multi(ts_BssgpP4Bvci(pcu_bvc_cfg[0].bvci), 0, {0});
2257}
2258testcase TC_paging_cs_sig_bvci() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01002259 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002260 f_start_handlers(refers(f_TC_paging_cs_sig_bvci), testcasename(), 16);
Harald Welte0e188242020-11-22 21:46:48 +01002261 f_cleanup();
2262}
2263
Harald Welte7462a592020-11-23 22:07:07 +01002264/* CS-PAGING on SIG-BVC for unknown BVCI */
2265private function f_TC_paging_cs_sig_bvci_unknown(charstring id) runs on BSSGP_ConnHdlr
2266{
2267 f_send_paging_cs_exp_no_bss(ts_BssgpP4Bvci(33333), 0, true);
2268}
2269testcase TC_paging_cs_sig_bvci_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01002270 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002271 f_start_handlers(refers(f_TC_paging_cs_sig_bvci_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01002272 f_cleanup();
2273}
2274
Harald Welte4f91c3b2020-12-09 12:25:51 +01002275/***********************************************************************
2276 * FLUSH-LL procedure
2277 ***********************************************************************/
2278
Daniel Willmann91a8e25b2020-11-24 14:50:59 +01002279private function f_TC_flush_ll(charstring id) runs on BSSGP_ConnHdlr {
2280 var BssgpBvci bvci := g_pars.pcu[0].cfg.bvc[0].bvci;
2281 var integer i;
2282 for (i := 0; i < 10; i := i+1) {
2283 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_FLUSH_LL(g_pars.tlli, bvci, bvci_new := bvci);
2284 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
2285 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_FLUSH_LL(g_pars.tlli, bvci, bvci_new := bvci);
2286
2287 f_sgsn2pcu(pdu_tx, pdu_rx, use_sig := true);
2288
2289 pdu_tx := ts_BSSGP_FLUSH_LL_ACK(g_pars.tlli, int2oct(0, 1), 23, bvci_new := bvci);
2290 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
2291 pdu_rx := tr_BSSGP_FLUSH_LL_ACK(g_pars.tlli, int2oct(0, 1), 23, bvci_new := bvci);
2292
2293 f_pcu2sgsn(pdu_tx, pdu_rx, use_sig := true);
2294 }
2295 setverdict(pass);
2296}
2297testcase TC_flush_ll() runs on test_CT
2298{
Daniel Willmann91a8e25b2020-11-24 14:50:59 +01002299 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002300 f_start_handlers(refers(f_TC_flush_ll), testcasename(), 6);
Daniel Willmann91a8e25b2020-11-24 14:50:59 +01002301 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
Daniel Willmann91a8e25b2020-11-24 14:50:59 +01002302 f_cleanup();
2303}
Harald Welte6dc2ac42020-11-16 09:16:17 +01002304
Harald Welte4f91c3b2020-12-09 12:25:51 +01002305/***********************************************************************
2306 * SGSN-INVOKE-TRACE procedure
2307 ***********************************************************************/
2308
Harald Weltef8e5c5d2020-11-27 22:37:23 +01002309private altstep as_bssgp_g_pcu_count(integer pcu_idx, template (present) PDU_BSSGP exp_rx, inout ro_integer roi)
2310runs on GlobalTest_CT {
2311[] G_PCU[pcu_idx].receive(exp_rx) from g_pcu[pcu_idx].vc_BSSGP {
2312 if (ro_integer_contains(roi, pcu_idx)) {
2313 setverdict(fail, "Received multiple on same SIG BVC");
2314 }
2315 roi := roi & { pcu_idx };
2316 repeat;
2317 }
2318}
2319/* send a INVOKE-TRACE from SGSN and expect to receive a copy on each NSE */
2320testcase TC_trace() runs on GlobalTest_CT
2321{
2322 var BSSGP_ConnHdlr vc_conn;
2323 f_init();
2324 f_global_init();
2325
2326 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_INVOKE_TRACE('23'O, '4321'O);
2327 var template (present) PDU_BSSGP exp_rx := ts_BSSGP_INVOKE_TRACE('23'O, '4321'O);
2328
2329 var ro_default defaults := {};
2330 for (var integer i := 0; i < lengthof(g_pcu); i := i+1) {
2331 activate(as_bssgp_g_pcu_count(i, exp_rx, g_roi));
2332 }
2333 G_SGSN[0].send(pdu_tx);
2334 f_sleep(2.0);
2335 for (var integer i := 0; i < lengthof(defaults); i := i+1) {
2336 deactivate(defaults[i]);
2337 }
2338
2339 for (var integer i := 0; i < lengthof(g_pcu); i := i+1) {
2340 if (not ro_integer_contains(g_roi, i)) {
2341 setverdict(fail, "Failed to receive TRACE on PCU index ", i);
2342 }
2343 }
2344 setverdict(pass);
2345
2346 f_cleanup();
2347}
2348
Harald Welte4f91c3b2020-12-09 12:25:51 +01002349/***********************************************************************
2350 * LLC-DISCARDED procedure
2351 ***********************************************************************/
2352
Harald Weltec0351d12020-11-27 22:49:02 +01002353private function f_TC_llc_discarded(charstring id) runs on BSSGP_ConnHdlr {
2354 var BssgpBvci bvci := g_pars.pcu[0].cfg.bvc[0].bvci;
2355
2356 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_LLC_DISCARDED(g_pars.tlli, 23, bvci, 2342);
2357 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
2358 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_LLC_DISCARDED(g_pars.tlli, 23, bvci, 2342);
2359
2360 f_pcu2sgsn(pdu_tx, pdu_rx, use_sig := true);
2361
2362 setverdict(pass);
2363}
2364/* Send a LLC-DISCARDED from BSS side and expect it to show up on SGSN (SIG BVC) */
2365testcase TC_llc_discarded() runs on test_CT
2366{
Harald Weltec0351d12020-11-27 22:49:02 +01002367 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002368 f_start_handlers(refers(f_TC_llc_discarded), testcasename(), 6);
Harald Weltec0351d12020-11-27 22:49:02 +01002369 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
Harald Weltec0351d12020-11-27 22:49:02 +01002370 f_cleanup();
2371}
2372
Harald Welte4f91c3b2020-12-09 12:25:51 +01002373/***********************************************************************
2374 * OVERLOAD procedure
2375 ***********************************************************************/
2376
Harald Weltef20af412020-11-28 16:11:11 +01002377/* Send an OVERLOAD from SGSN side and expect it to show up on each PCU (SIG BVC) */
2378testcase TC_overload() runs on GlobalTest_CT
2379{
2380 f_init();
2381 f_global_init();
2382
2383 var template (value) PDU_BSSGP pdu_tx := ts_OVERLOAD('1'B);
2384 var template (present) PDU_BSSGP exp_rx := tr_OVERLOAD('1'B);
2385
2386 var ro_default defaults := {};
2387 for (var integer i := 0; i < lengthof(g_pcu); i := i+1) {
2388 activate(as_bssgp_g_pcu_count(i, exp_rx, g_roi));
2389 }
2390 G_SGSN[0].send(pdu_tx);
2391 f_sleep(2.0);
2392 for (var integer i := 0; i < lengthof(defaults); i := i+1) {
2393 deactivate(defaults[i]);
2394 }
2395
2396 for (var integer i := 0; i < lengthof(g_pcu); i := i+1) {
2397 if (not ro_integer_contains(g_roi, i)) {
2398 setverdict(fail, "Failed to receive OVERLOAD on PCU index ", i);
2399 }
2400 }
2401 setverdict(pass);
2402
2403 f_cleanup();
2404}
2405
Harald Welte4f91c3b2020-12-09 12:25:51 +01002406/***********************************************************************
2407 * BVC-BLOCK / BVC-UNBLOCK procedure
2408 ***********************************************************************/
2409
Harald Welte239aa502020-11-24 23:14:20 +01002410private function f_block_ptp_bvc_from_pcu(integer pcu_idx, integer bvc_idx) runs on test_CT
2411{
2412 var BSSGP_BVC_CT bvc_ct := g_pcu[pcu_idx].vc_BSSGP_BVC[bvc_idx];
2413 var BssgpBvcConfig bvc_cfg := g_pcu[pcu_idx].cfg.bvc[bvc_idx];
2414 var Nsei nsei_pcu := g_pcu[pcu_idx].cfg.nsei;
2415
2416 SGSN_MGMT.clear;
2417 PCU_MGMT.clear;
2418
2419 /* block the PTP BVC from the PCU side */
2420 PCU_MGMT.send(BssgpBlockRequest:{cause:=BSSGP_CAUSE_OM_INTERVENTION}) to bvc_ct;
2421 /* expect state on both PCU and SGSN side to change */
2422 interleave {
2423 [] PCU_MGMT.receive(tr_BssgpStsInd(nsei_pcu, bvc_cfg.bvci, BVC_S_BLOCKED)) from bvc_ct;
2424 [] SGSN_MGMT.receive(tr_BssgpStsInd(*, bvc_cfg.bvci, BVC_S_BLOCKED));
2425 }
2426 setverdict(pass);
2427}
2428testcase TC_bvc_block_ptp() runs on test_CT
2429{
2430 f_init();
2431 f_sleep(1.0);
2432 f_block_ptp_bvc_from_pcu(0, 0);
2433 f_cleanup();
2434}
2435
2436private function f_unblock_ptp_bvc_from_pcu(integer pcu_idx, integer bvc_idx) runs on test_CT
2437{
2438 var BSSGP_BVC_CT bvc_ct := g_pcu[pcu_idx].vc_BSSGP_BVC[bvc_idx];
2439 var BssgpBvcConfig bvc_cfg := g_pcu[pcu_idx].cfg.bvc[bvc_idx];
2440 var Nsei nsei_pcu := g_pcu[pcu_idx].cfg.nsei;
2441
2442 SGSN_MGMT.clear;
2443 PCU_MGMT.clear;
2444
2445 /* block the PTP BVC from the PCU side */
2446 PCU_MGMT.send(BssgpUnblockRequest:{}) to bvc_ct;
2447 /* expect state on both PCU and SGSN side to change */
2448 interleave {
2449 [] PCU_MGMT.receive(tr_BssgpStsInd(nsei_pcu, bvc_cfg.bvci, BVC_S_UNBLOCKED)) from bvc_ct;
2450 [] SGSN_MGMT.receive(tr_BssgpStsInd(*, bvc_cfg.bvci, BVC_S_UNBLOCKED));
2451 }
2452 setverdict(pass);
2453}
2454testcase TC_bvc_unblock_ptp() runs on test_CT
2455{
2456 f_init();
2457 f_sleep(1.0);
2458 f_block_ptp_bvc_from_pcu(0, 0);
2459 f_sleep(1.0);
2460 f_unblock_ptp_bvc_from_pcu(0, 0);
2461 f_cleanup();
2462}
2463
Harald Welte4f91c3b2020-12-09 12:25:51 +01002464/***********************************************************************
2465 * BVC-RESET procedure
2466 ***********************************************************************/
2467
Harald Welte60a8ec72020-11-25 17:12:53 +01002468private altstep as_ignore_status(BSSGP_BVC_MGMT_PT pt) {
2469[] pt.receive(BssgpStatusIndication:?) { repeat; }
2470}
2471private function f_get_sgsn_bvc_ct(integer sgsn_idx, BssgpBvci bvci) runs on test_CT return BSSGP_BVC_CT {
2472 for (var integer i := 0; i < lengthof(g_sgsn[sgsn_idx].cfg.bvc); i := i+1) {
2473 if (g_sgsn[sgsn_idx].cfg.bvc[i].bvci == bvci) {
2474 return g_sgsn[sgsn_idx].vc_BSSGP_BVC[i];
2475 }
2476 }
2477 return null;
2478}
2479private function f_reset_ptp_bvc_from_pcu(integer pcu_idx, integer bvc_idx) runs on test_CT
2480{
2481 var BSSGP_BVC_CT pcu_bvc_ct := g_pcu[pcu_idx].vc_BSSGP_BVC[bvc_idx];
2482 var BssgpBvcConfig bvc_cfg := g_pcu[pcu_idx].cfg.bvc[bvc_idx];
2483 var Nsei nsei_pcu := g_pcu[pcu_idx].cfg.nsei;
2484 var BSSGP_BVC_CT sgsn_bvc_ct := f_get_sgsn_bvc_ct(0, bvc_cfg.bvci);
2485 var default d;
2486
2487 SGSN_MGMT.clear;
2488 PCU_MGMT.clear;
2489
2490 /* block the PTP BVC from the PCU side */
2491 PCU_MGMT.send(BssgpResetRequest:{cause:=BSSGP_CAUSE_OM_INTERVENTION}) to pcu_bvc_ct;
2492 /* expect state on both PCU and SGSN side to change */
2493 d := activate(as_ignore_status(SGSN_MGMT));
2494 interleave {
2495 [] PCU_MGMT.receive(tr_BssgpStsInd(nsei_pcu, bvc_cfg.bvci, BVC_S_BLOCKED)) from pcu_bvc_ct;
2496 [] SGSN_MGMT.receive(BssgpResetIndication:{bvc_cfg.bvci}) from sgsn_bvc_ct;
2497 }
2498 deactivate(d);
2499 setverdict(pass);
2500}
2501/* Send a BVC-RESET for a PTP BVC from the BSS side: expect it to propagate */
2502testcase TC_bvc_reset_ptp_from_bss() runs on test_CT
2503{
2504 f_init();
2505 f_sleep(3.0);
2506 f_reset_ptp_bvc_from_pcu(0, 0);
2507 f_cleanup();
2508}
2509
Harald Welte16786e92020-11-27 19:11:56 +01002510private altstep as_count_bvc_block(integer sgsn_idx, BssgpBvci bvci, inout ro_integer roi)
2511runs on test_CT {
2512 var BSSGP_BVC_CT sgsn_bvc_ct := f_get_sgsn_bvc_ct(sgsn_idx, bvci);
2513 [] SGSN_MGMT.receive(tr_BssgpStsInd(?, bvci, BVC_S_BLOCKED)) from sgsn_bvc_ct {
2514 roi := roi & { bvci };
Harald Welteb2647f72020-12-07 14:36:35 +01002515 repeat;
Harald Welte16786e92020-11-27 19:11:56 +01002516 }
2517}
2518/* reset the signaling BVC from one BSS; expect no signaling BVC reset on SGSN; but BVC-BLOCK for PTP */
2519testcase TC_bvc_reset_sig_from_bss() runs on test_CT {
2520
2521 f_init();
2522 f_sleep(3.0);
2523
2524 /* Start BVC-RESET procedure for BVCI=0 */
2525 PCU_MGMT.send(BssgpResetRequest:{cause:=BSSGP_CAUSE_OM_INTERVENTION}) to g_pcu[0].vc_BSSGP;
2526
2527 /* Activate altsteps: One for each PTP BVC within that PCUs NSE */
2528 var ro_default defaults := {};
2529 for (var integer i := 0; i < lengthof(g_pcu[0].cfg.bvc); i := i+1) {
2530 var BssgpBvcConfig bvcc := g_pcu[0].cfg.bvc[i];
2531 var default d := activate(as_count_bvc_block(0, bvcc.bvci, g_roi));
2532 defaults := defaults & { d };
2533 }
2534
2535 timer T := 3.0;
2536 T.start;
2537 alt {
2538 [] SGSN_MGMT.receive(BssgpResetIndication:{0}) {
2539 setverdict(fail, "BSS-side Reset of BVCI=0 should not propagate");
2540 }
2541 [] T.timeout;
2542 }
2543
2544 for (var integer i := 0; i < lengthof(defaults); i := i+1) {
2545 deactivate(defaults[i]);
2546 }
2547
2548 /* check if BVC-block was received on all expected BVC */
2549 for (var integer i := 0; i < lengthof(g_pcu[0].cfg.bvc); i := i+1) {
2550 var BssgpBvcConfig bvcc := g_pcu[0].cfg.bvc[i];
2551 if (not ro_integer_contains(g_roi, bvcc.bvci)) {
2552 setverdict(fail, "Missing SGSN-side BVC-BLOCK of BVCI=", bvcc.bvci);
2553 }
2554 }
2555
2556 /* check if BVC-block was not received on any unexpected BVC is not required as
2557 * such a message would basically run into 'no matching clause' */
Daniel Willmannf2590212020-12-04 14:20:50 +01002558 setverdict(pass);
Harald Welte16786e92020-11-27 19:11:56 +01002559 f_cleanup();
2560}
2561
Harald Welte60a8ec72020-11-25 17:12:53 +01002562private function f_reset_ptp_bvc_from_sgsn(integer pcu_idx, integer bvc_idx) runs on test_CT
2563{
2564 var BSSGP_BVC_CT pcu_bvc_ct := g_pcu[pcu_idx].vc_BSSGP_BVC[bvc_idx];
2565 var BssgpBvcConfig bvc_cfg := g_pcu[pcu_idx].cfg.bvc[bvc_idx];
2566 var Nsei nsei_pcu := g_pcu[pcu_idx].cfg.nsei;
2567 var BSSGP_BVC_CT sgsn_bvc_ct := f_get_sgsn_bvc_ct(0, bvc_cfg.bvci);
2568 var default d;
2569
2570 SGSN_MGMT.clear;
2571 PCU_MGMT.clear;
2572
2573 /* block the PTP BVC from the PCU side */
2574 SGSN_MGMT.send(BssgpResetRequest:{cause:=BSSGP_CAUSE_OM_INTERVENTION}) to sgsn_bvc_ct;
2575 /* expect state on both PCU and SGSN side to change */
2576 d := activate(as_ignore_status(PCU_MGMT));
2577 interleave {
2578 [] SGSN_MGMT.receive(tr_BssgpStsInd(?, bvc_cfg.bvci, BVC_S_BLOCKED)) from sgsn_bvc_ct;
2579 [] PCU_MGMT.receive(BssgpResetIndication:{bvc_cfg.bvci}) from pcu_bvc_ct;
2580 }
2581 deactivate(d);
2582 setverdict(pass);
2583}
2584/* Send a BVC-RESET for a PTP BVC from the SGSN side: expect it to propagate */
2585testcase TC_bvc_reset_ptp_from_sgsn() runs on test_CT
2586{
2587 f_init();
2588 f_sleep(3.0);
2589 f_reset_ptp_bvc_from_sgsn(0, 0);
2590 f_cleanup();
2591}
2592
Daniel Willmannef7015f2021-01-08 00:43:56 +01002593private altstep as_ignore_mgmt(BSSGP_BVC_MGMT_PT pt) {
2594 [] pt.receive {repeat; }
2595}
2596
Harald Welte16786e92020-11-27 19:11:56 +01002597private altstep as_count_bvc0_block(integer pcu_idx, Nsei nsei, inout ro_integer roi)
2598runs on test_CT {
2599 var BSSGP_CT pcu_ct := g_pcu[pcu_idx].vc_BSSGP;
2600 [] PCU_MGMT.receive(BssgpResetIndication:{0}) from pcu_ct {
2601 roi := roi & { nsei };
Daniel Willmannef7015f2021-01-08 00:43:56 +01002602 repeat;
Harald Welte16786e92020-11-27 19:11:56 +01002603 }
2604}
Daniel Willmannef7015f2021-01-08 00:43:56 +01002605
Harald Welte16786e92020-11-27 19:11:56 +01002606/* reset the signaling BVC from the SGSN; expect all signaling BVC on all BSS to be reset */
2607testcase TC_bvc_reset_sig_from_sgsn() runs on test_CT {
2608
2609 f_init();
2610 f_sleep(3.0);
2611
Daniel Willmannef7015f2021-01-08 00:43:56 +01002612 SGSN_MGMT.clear;
2613 PCU_MGMT.clear;
2614
Harald Welte16786e92020-11-27 19:11:56 +01002615 /* Start BVC-RESET procedure for BVCI=0 */
2616 SGSN_MGMT.send(BssgpResetRequest:{cause:=BSSGP_CAUSE_OM_INTERVENTION}) to g_sgsn[0].vc_BSSGP;
2617
Daniel Willmannef7015f2021-01-08 00:43:56 +01002618 /* Defaults match in reverse activation order, this one is a catch-all for Status indications
2619 * and reset indications sent from other components (like the ptp_bvcs). If we don't drain
2620 * the port and a different message sits at the front we wait forever and fail the test.
2621 */
2622 var ro_default defaults := { activate(as_ignore_mgmt(PCU_MGMT)) };
2623
Harald Welte16786e92020-11-27 19:11:56 +01002624 /* Activate altsteps: One for each PCU NSE */
Harald Welte16786e92020-11-27 19:11:56 +01002625 for (var integer i := 0; i < lengthof(g_pcu); i := i+1) {
2626 var NSConfiguration nscfg := mp_nsconfig_pcu[i];
2627 var default d := activate(as_count_bvc0_block(i, nscfg.nsei, g_roi));
2628 defaults := defaults & { d };
2629 }
2630
2631 f_sleep(3.0);
2632
2633 for (var integer i := 0; i < lengthof(defaults); i := i+1) {
2634 deactivate(defaults[i]);
2635 }
2636
2637 /* check if BVC-block was received on all expected BVC */
2638 for (var integer i := 0; i < lengthof(g_pcu); i := i+1) {
2639 var NSConfiguration nscfg := mp_nsconfig_pcu[i];
2640 if (not ro_integer_contains(g_roi, nscfg.nsei)) {
2641 setverdict(fail, "Missing PCU-side BVC-RESET of BVCI=0 on PCU index ", i);
2642 }
2643 }
2644
2645 /* check if BVC-block was not received on any unexpected BVC is not required as
2646 * such a message would basically run into 'no matching clause' */
2647
2648 f_cleanup();
2649}
2650
Harald Welte299aa482020-12-09 15:10:55 +01002651/***********************************************************************
2652 * FLOW-CONTROL-BVC procedure
2653 ***********************************************************************/
2654
2655private altstep as_g_count_sgsn(integer sgsn_idx, inout ro_integer roi,
2656 template PDU_BSSGP exp_rx, template (omit) PDU_BSSGP tx_reply)
2657runs on GlobalTest_CT {
2658 [] G_SGSN[sgsn_idx].receive(exp_rx) {
2659 roi := roi & { sgsn_idx };
2660 if (ispresent(tx_reply)) {
2661 G_SGSN[sgsn_idx].send(tx_reply);
2662 }
Harald Welte5fb01742021-01-15 21:07:52 +01002663 repeat;
Harald Welte299aa482020-12-09 15:10:55 +01002664 }
2665}
2666/* Send FC-BVC from simulated PCU; expect each SGSN to receive it; expect PCU to receive ACK */
2667testcase TC_fc_bvc() runs on GlobalTest_CT
2668{
2669 f_init();
2670 f_global_init_ptp();
2671
2672 var template (value) PDU_BSSGP pdu_tx := t_BVC_FC_BVC(10240, 2000, 1024, 1000, '01'O);
2673 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
2674 var template (present) PDU_BSSGP pdu_rx := tr_BVC_FC_BVC(10240, 2000, 1024, 1000, '01'O);
2675 var template (omit) PDU_BSSGP ack_tx :=
2676 t_BVC_FC_BVC_ACK(pdu_tx.pDU_BSSGP_FLOW_CONTROL_BVC.tag.unstructured_Value);
2677
2678 /* Send a FC-BVC from BSS to gbproxy, expect an ACK in response */
2679 G_PCU[0].send(pdu_tx);
2680
2681 /* Activate altsteps: One for each SGSN-side PTP BVC port */
2682 var ro_default defaults := {};
2683 for (var integer i := 0; i < lengthof(g_sgsn); i := i+1) {
2684 var default d := activate(as_g_count_sgsn(i, g_roi, pdu_rx, ack_tx));
2685 defaults := defaults & { d };
2686 }
2687
2688 f_sleep(3.0);
2689
2690 for (var integer i := 0; i < lengthof(defaults); i := i+1) {
2691 deactivate(defaults[i]);
2692 }
2693
2694 /* check if BVC-block was received on all expected BVC */
2695 for (var integer i := 0; i < lengthof(g_sgsn); i := i+1) {
2696 if (not ro_integer_contains(g_roi, i)) {
2697 setverdict(fail, "Missing BVC-FLOW-CONTROL on SGSN index ", i);
2698 }
2699 }
2700
2701 /* Expect ACK on PCU side */
2702 G_PCU[0].receive(ack_tx);
2703
2704 setverdict(pass);
2705
2706 f_cleanup();
2707}
2708
Harald Weltecc3894b2020-12-09 16:50:12 +01002709/***********************************************************************
2710 * FLOW-CONTROL-MS procedure
2711 ***********************************************************************/
2712
2713private function f_TC_fc_ms(charstring id) runs on BSSGP_ConnHdlr {
2714 var BssgpBvci bvci := g_pars.pcu[0].cfg.bvc[0].bvci;
2715
2716 var template (value) PDU_BSSGP fc_tx := ts_BVC_FC_MS(g_pars.tlli, 100, 200, '12'O);
2717 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
2718 var template (present) PDU_BSSGP fc_rx := tr_BVC_FC_MS(g_pars.tlli, 100, 200, '12'O);
2719 var template (value) PDU_BSSGP ack_tx := ts_BVC_FC_MS_ACK(g_pars.tlli, '12'O);
2720
2721 f_pcu2sgsn(fc_tx, fc_rx, use_sig := false);
2722 f_sgsn2pcu(ack_tx, ack_tx, use_sig := false);
2723
2724 setverdict(pass);
2725}
2726/* Send a FLOW-CONTROL-MS from BSS side and expect it to show up on SGSN (PTP BVC) */
2727testcase TC_fc_ms() runs on test_CT
2728{
Harald Weltecc3894b2020-12-09 16:50:12 +01002729 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002730 f_start_handlers(refers(f_TC_fc_ms), testcasename(), 21);
Harald Weltecc3894b2020-12-09 16:50:12 +01002731 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
Harald Weltecc3894b2020-12-09 16:50:12 +01002732 f_cleanup();
2733}
2734
Harald Welted6f89812021-01-16 18:57:49 +01002735/***********************************************************************
2736 * MS-REGISTRATION ENQUIRY procedure
2737 ***********************************************************************/
Harald Weltecc3894b2020-12-09 16:50:12 +01002738
Harald Welted6f89812021-01-16 18:57:49 +01002739private function f_TC_ms_reg_enq(charstring id) runs on BSSGP_ConnHdlr
2740{
2741 f_pcu2sgsn(ts_BSSGP_MS_REG_ENQ(g_pars.imsi), tr_BSSGP_MS_REG_ENQ(g_pars.imsi), use_sig := true);
2742 f_sgsn2pcu(ts_BSSGP_MS_REW_ENQ_RESP(g_pars.imsi, omit), tr_BSSGP_MS_REW_ENQ_RESP(g_pars.imsi, omit), use_sig := true);
2743}
2744testcase TC_ms_reg_enq() runs on test_CT
2745{
2746 f_init();
2747 f_start_handlers(refers(f_TC_ms_reg_enq), testcasename(), 22);
2748 f_cleanup();
2749}
Harald Welte299aa482020-12-09 15:10:55 +01002750
Harald Weltef86f1852021-01-16 21:56:17 +01002751/***********************************************************************
2752 * RIM (RAN Information Management)
2753 ***********************************************************************/
2754
2755/* Our tests here are rather synthetic, as they don't reflect normal message flows
2756 as they would be observed in a live network. However, for testing gbproxy, this shouldn't
2757 matter as gbproxy is not concerned with anything but the source / destination routing
2758 information */
2759
2760/* gbproxy must route all unknown RIM Routing Info (Cell Id) to the SGSN. We just define
2761 one here of which we know it is not used among the [simulated] PCUs */
2762const BssgpCellId cell_id_sgsn := {
2763 ra_id := {
2764 lai := {
2765 mcc_mnc := c_mcc_mnc,
2766 lac := 65534
2767 },
2768 rac := 0
2769 },
2770 cell_id := 65533
2771};
2772
2773/* Send 'tx' on PTP-BVCI from PCU; expect 'rx' on any of our SGSN (RIM can be routed anywhere) */
2774friend function f_rim_pcu2sgsn(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
2775 integer pcu_idx := 0) runs on GlobalTest_CT {
2776 var PDU_BSSGP rx;
2777 timer T := 1.0;
2778
2779 RIM_PCU[pcu_idx].send(tx);
2780 T.start;
2781 alt {
2782 [] any from RIM_SGSN.receive(exp_rx) {
2783 setverdict(pass);
2784 }
2785 [] any from RIM_SGSN.receive(PDU_BSSGP:?) -> value rx {
2786 setverdict(fail, "Unexpected BSSGP on SGSN side: ", rx);
2787 mtc.stop;
2788 }
2789 [] T.timeout {
2790 setverdict(fail, "Timeout waiting for BSSGP on SGSN side: ", exp_rx);
2791 mtc.stop;
2792 }
2793 }
2794}
2795
2796/* Send 'tx' on PTP-BVCI from SGSN; expect 'rx' on PCU */
2797friend function f_rim_sgsn2pcu(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
2798 integer sgsn_idx := 0, integer pcu_idx := 0) runs on GlobalTest_CT {
2799 var PDU_BSSGP rx;
2800 timer T := 1.0;
2801
2802 RIM_SGSN[sgsn_idx].send(tx);
2803 T.start;
2804 alt {
2805 [] RIM_PCU[pcu_idx].receive(exp_rx) {
2806 setverdict(pass);
2807 }
2808 [] RIM_PCU[pcu_idx].receive(PDU_BSSGP:?) -> value rx {
2809 setverdict(fail, "Unexpected BSSGP on PCU side: ", rx);
2810 mtc.stop;
2811 }
2812 [] T.timeout {
2813 setverdict(fail, "Timeout waiting for BSSGP on PCU side: ", exp_rx);
2814 mtc.stop;
2815 }
2816 }
2817}
2818
2819/* Send 'tx' on PTP-BVCI from SRC-PCU; expect 'rx' on DST-PCU */
2820friend function f_rim_pcu2pcu(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
2821 integer src_pcu_idx, integer dst_pcu_idx) runs on GlobalTest_CT {
2822 var integer rx_idx;
2823 var PDU_BSSGP rx;
2824 timer T := 1.0;
2825
2826 RIM_PCU[src_pcu_idx].send(tx);
2827 T.start;
2828 alt {
2829 [] RIM_PCU[dst_pcu_idx].receive(exp_rx) -> value rx{
2830 setverdict(pass);
2831 }
2832 [] any from RIM_PCU.receive(exp_rx) -> @index value rx_idx {
2833 setverdict(fail, "Received RIM on wrong PCU[", rx_idx ,"], expected on PCU[", dst_pcu_idx, "]");
2834 }
2835 [] any from RIM_SGSN.receive(exp_rx) {
2836 setverdict(fail, "Received RIM on SGSN but expected it on other PCU");
2837 }
2838 [] any from RIM_SGSN.receive(PDU_BSSGP:?) -> value rx {
2839 setverdict(fail, "Unexpected BSSGP on SGSN side: ", rx);
2840 mtc.stop;
2841 }
2842 [] T.timeout {
2843 setverdict(fail, "Timeout waiting for BSSGP on SGSN side: ", exp_rx);
2844 mtc.stop;
2845 }
2846 }
2847}
2848
2849
2850type function rim_fn(integer sgsn_idx, integer pcu_idx, integer bvc_idx) runs on GlobalTest_CT;
2851
2852/* helper function for the RIM test cases: Execute 'fn' for each BVC on each PCU for
2853 each SGSN */
2854private function f_rim_iterator(rim_fn fn) runs on GlobalTest_CT
2855{
2856 var integer sgsn_idx, pcu_idx, bvc_idx;
2857 for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx+1) {
2858 for (pcu_idx := 0; pcu_idx < lengthof(g_pcu); pcu_idx := pcu_idx+1) {
2859 for (bvc_idx := 0; bvc_idx < lengthof(g_pcu[pcu_idx].cfg.bvc); bvc_idx := bvc_idx+1) {
2860 log("Testing RIM SGSN[", sgsn_idx, "] <-> PCU[", pcu_idx, "][", bvc_idx, "]");
2861 fn.apply(sgsn_idx, pcu_idx, bvc_idx);
2862 }
2863 }
2864 }
2865}
2866
2867/* RAN-INFORMATION-REQUEST */
2868private function f_TC_rim_info_req(integer sgsn_idx, integer pcu_idx, integer bvc_idx := 0)
2869runs on GlobalTest_CT
2870{
2871 var BssgpCellId cell_id := g_pcu[pcu_idx].cfg.bvc[bvc_idx].cell_id;
2872 var template (value) RIM_Routing_Information ri_pcu;
2873 var template (value) RIM_Routing_Information ri_sgsn;
2874 var template (value) RAN_Information_Request_RIM_Container cont;
2875
2876 ri_sgsn := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, t_RIM_Routing_Address_cid(cell_id_sgsn));
2877 ri_pcu := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, t_RIM_Routing_Address_cid(cell_id));
2878 cont := ts_RAN_Information_Request_RIM_Container(ts_RIM_Application_Identity(RIM_APP_ID_NACC),
2879 ts_RIM_Sequence_Number(0),
2880 ts_RIM_PDU_Indications(false, RIM_PDU_TYPE_STOP));
2881 f_rim_pcu2sgsn(ts_RAN_INFORMATION_REQUEST(dst := ri_sgsn, src := ri_pcu, cont := cont),
2882 tr_RAN_INFORMATION_REQUEST(dst := ri_sgsn, src := ri_pcu, cont := cont),
2883 pcu_idx);
2884 f_rim_sgsn2pcu(ts_RAN_INFORMATION_REQUEST(dst := ri_pcu, src := ri_sgsn, cont := cont),
2885 tr_RAN_INFORMATION_REQUEST(dst := ri_pcu, src := ri_sgsn, cont := cont),
2886 sgsn_idx, pcu_idx);
2887}
2888testcase TC_rim_info_req() runs on GlobalTest_CT
2889{
2890 f_init();
2891 f_global_init();
2892 f_rim_iterator(refers(f_TC_rim_info_req));
2893 f_cleanup();
2894}
2895
2896/* RAN-INFORMATION */
2897private function f_TC_rim_info(integer sgsn_idx, integer pcu_idx, integer bvc_idx := 0)
2898runs on GlobalTest_CT
2899{
2900 var BssgpCellId cell_id := g_pcu[pcu_idx].cfg.bvc[bvc_idx].cell_id;
2901 var template (value) RIM_Routing_Information ri_pcu;
2902 var template (value) RIM_Routing_Information ri_sgsn;
2903 var template (value) RAN_Information_RIM_Container cont;
2904
2905 ri_sgsn := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, t_RIM_Routing_Address_cid(cell_id_sgsn));
2906 ri_pcu := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, t_RIM_Routing_Address_cid(cell_id));
2907 cont := ts_RAN_Information_RIM_Container(ts_RIM_Application_Identity(RIM_APP_ID_NACC),
2908 ts_RIM_Sequence_Number(0),
2909 ts_RIM_PDU_Indications(false, RIM_PDU_TYPE_STOP));
2910 f_rim_pcu2sgsn(ts_PDU_BSSGP_RAN_INFORMATION(dst := ri_sgsn, src := ri_pcu, cont := cont),
2911 tr_PDU_BSSGP_RAN_INFORMATION(dst := ri_sgsn, src := ri_pcu, cont := cont),
2912 pcu_idx);
2913 f_rim_sgsn2pcu(ts_PDU_BSSGP_RAN_INFORMATION(dst := ri_pcu, src := ri_sgsn, cont := cont),
2914 tr_PDU_BSSGP_RAN_INFORMATION(dst := ri_pcu, src := ri_sgsn, cont := cont),
2915 sgsn_idx, pcu_idx);
2916}
2917testcase TC_rim_info() runs on GlobalTest_CT
2918{
2919 f_init();
2920 f_global_init();
2921 f_rim_iterator(refers(f_TC_rim_info));
2922 f_cleanup();
2923}
2924
2925/* RAN-INFORMATION-ACK */
2926private function f_TC_rim_info_ack(integer sgsn_idx, integer pcu_idx, integer bvc_idx := 0)
2927runs on GlobalTest_CT
2928{
2929 var BssgpCellId cell_id := g_pcu[pcu_idx].cfg.bvc[bvc_idx].cell_id;
2930 var template (value) RIM_Routing_Information ri_pcu;
2931 var template (value) RIM_Routing_Information ri_sgsn;
2932 var template (value) RAN_Information_Ack_RIM_Container cont;
2933
2934 ri_sgsn := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, t_RIM_Routing_Address_cid(cell_id_sgsn));
2935 ri_pcu := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, t_RIM_Routing_Address_cid(cell_id));
2936 cont := ts_RAN_Information_Ack_RIM_Container(ts_RIM_Application_Identity(RIM_APP_ID_NACC),
2937 ts_RIM_Sequence_Number(0));
2938 f_rim_pcu2sgsn(ts_PDU_BSSGP_RAN_INFORMATION_ACK(dst := ri_sgsn, src := ri_pcu, cont := cont),
2939 tr_PDU_BSSGP_RAN_INFORMATION_ACK(dst := ri_sgsn, src := ri_pcu, cont := cont),
2940 pcu_idx);
2941 f_rim_sgsn2pcu(ts_PDU_BSSGP_RAN_INFORMATION_ACK(dst := ri_pcu, src := ri_sgsn, cont := cont),
2942 tr_PDU_BSSGP_RAN_INFORMATION_ACK(dst := ri_pcu, src := ri_sgsn, cont := cont),
2943 sgsn_idx, pcu_idx);
2944}
2945testcase TC_rim_info_ack() runs on GlobalTest_CT
2946{
2947 f_init();
2948 f_global_init();
2949 f_rim_iterator(refers(f_TC_rim_info_ack));
2950 f_cleanup();
2951}
2952
2953/* RAN-INFORMATION-ERROR */
2954private function f_TC_rim_info_error(integer sgsn_idx, integer pcu_idx, integer bvc_idx := 0)
2955runs on GlobalTest_CT
2956{
2957 var BssgpCellId cell_id := g_pcu[pcu_idx].cfg.bvc[bvc_idx].cell_id;
2958 var template (value) RIM_Routing_Information ri_pcu;
2959 var template (value) RIM_Routing_Information ri_sgsn;
2960 var template (value) RAN_Information_Error_RIM_Container cont;
2961
2962 ri_sgsn := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, t_RIM_Routing_Address_cid(cell_id_sgsn));
2963 ri_pcu := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, t_RIM_Routing_Address_cid(cell_id));
2964 cont := ts_RAN_Information_Error_RIM_Container(ts_RIM_Application_Identity(RIM_APP_ID_NACC),
2965 ts_BSSGP_CAUSE(BSSGP_CAUSE_EQUIMENT_FAILURE),
2966 omit, valueof(t_BVC_UNBLOCK(23)));
2967 f_rim_pcu2sgsn(ts_PDU_BSSGP_RAN_INFORMATION_ERROR(dst := ri_sgsn, src := ri_pcu, cont := cont),
2968 tr_PDU_BSSGP_RAN_INFORMATION_ERROR(dst := ri_sgsn, src := ri_pcu, cont := cont),
2969 pcu_idx);
2970 f_rim_sgsn2pcu(ts_PDU_BSSGP_RAN_INFORMATION_ERROR(dst := ri_pcu, src := ri_sgsn, cont := cont),
2971 tr_PDU_BSSGP_RAN_INFORMATION_ERROR(dst := ri_pcu, src := ri_sgsn, cont := cont),
2972 sgsn_idx, pcu_idx);
2973}
2974testcase TC_rim_info_error() runs on GlobalTest_CT
2975{
2976 f_init();
2977 f_global_init();
2978 f_rim_iterator(refers(f_TC_rim_info_error));
2979 f_cleanup();
2980}
2981
2982/* RAN-INFORMATION-APPLICATION-ERROR */
2983private function f_TC_rim_info_app_error(integer sgsn_idx, integer pcu_idx, integer bvc_idx := 0)
2984runs on GlobalTest_CT
2985{
2986 var BssgpCellId cell_id := g_pcu[pcu_idx].cfg.bvc[bvc_idx].cell_id;
2987 var template (value) RIM_Routing_Information ri_pcu;
2988 var template (value) RIM_Routing_Information ri_sgsn;
2989 var template (value) Application_Error_Container app_cont;
2990 var template (value) RAN_Information_Application_Error_RIM_Container cont;
2991
2992 ri_sgsn := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, t_RIM_Routing_Address_cid(cell_id_sgsn));
2993 ri_pcu := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, t_RIM_Routing_Address_cid(cell_id));
2994 app_cont := tsu_Application_Error_Container_NACC(cell_id, 23,
2995 tsu_Application_Container_IE_NACC_req(cell_id));
2996 cont := ts_RAN_Information_Application_Error_RIM_Container(ts_RIM_Application_Identity(RIM_APP_ID_NACC),
2997 ts_RIM_Sequence_Number(0),
2998 ts_RIM_PDU_Indications(false, RIM_PDU_TYPE_STOP),
2999 omit, app_cont);
3000 f_rim_pcu2sgsn(ts_PDU_BSSGP_RAN_INFORMATION_APPLICATION_ERROR(dst := ri_sgsn, src := ri_pcu, cont := cont),
3001 tr_PDU_BSSGP_RAN_INFORMATION_APPLICATION_ERROR(dst := ri_sgsn, src := ri_pcu, cont := cont),
3002 pcu_idx);
3003 f_rim_sgsn2pcu(ts_PDU_BSSGP_RAN_INFORMATION_APPLICATION_ERROR(dst := ri_pcu, src := ri_sgsn, cont := cont),
3004 tr_PDU_BSSGP_RAN_INFORMATION_APPLICATION_ERROR(dst := ri_pcu, src := ri_sgsn, cont := cont),
3005 sgsn_idx, pcu_idx);
3006}
3007testcase TC_rim_info_app_error() runs on GlobalTest_CT
3008{
3009 f_init();
3010 f_global_init();
3011 f_rim_iterator(refers(f_TC_rim_info_app_error));
3012 f_cleanup();
3013}
3014
3015/* RAN-INFORMATION routing directly between PCUs, without SGSN involvement */
3016private function f_TC_rim_info_pcu2pcu(integer src_pcu_idx, integer src_bvc_idx,
3017 integer dst_pcu_idx, integer dst_bvc_idx)
3018runs on GlobalTest_CT
3019{
3020 var BssgpCellId cell_id_src := g_pcu[src_pcu_idx].cfg.bvc[src_bvc_idx].cell_id;
3021 var BssgpCellId cell_id_dst := g_pcu[dst_pcu_idx].cfg.bvc[dst_bvc_idx].cell_id;
3022 var template (value) RIM_Routing_Information ri_pcu_src;
3023 var template (value) RIM_Routing_Information ri_pcu_dst;
3024 var template (value) RAN_Information_RIM_Container cont;
3025
3026 log("Testing RIM PCU2PCU from PCU[", src_pcu_idx, "][", src_bvc_idx, "] to PCU[",
3027 dst_pcu_idx, "][", dst_bvc_idx, "]");
3028
3029 ri_pcu_src := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID,
3030 t_RIM_Routing_Address_cid(cell_id_src));
3031 ri_pcu_dst := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID,
3032 t_RIM_Routing_Address_cid(cell_id_dst));
3033 cont := ts_RAN_Information_RIM_Container(ts_RIM_Application_Identity(RIM_APP_ID_NACC),
3034 ts_RIM_Sequence_Number(0),
3035 ts_RIM_PDU_Indications(false, RIM_PDU_TYPE_STOP));
3036 f_rim_pcu2pcu(ts_PDU_BSSGP_RAN_INFORMATION(dst := ri_pcu_dst, src := ri_pcu_src, cont := cont),
3037 tr_PDU_BSSGP_RAN_INFORMATION(dst := ri_pcu_dst, src := ri_pcu_src, cont := cont),
3038 src_pcu_idx, dst_pcu_idx);
3039}
3040testcase TC_rim_info_pcu2pcu() runs on GlobalTest_CT
3041{
3042 var integer src_pcu_idx, dst_pcu_idx;
3043 var integer src_bvc_idx, dst_bvc_idx;
3044 f_init();
3045 f_global_init();
3046
3047 for (src_pcu_idx := 0; src_pcu_idx < lengthof(g_pcu); src_pcu_idx := src_pcu_idx + 1) {
3048 for (src_bvc_idx := 0; src_bvc_idx < lengthof(g_pcu[src_pcu_idx].cfg.bvc); src_bvc_idx := src_bvc_idx + 1) {
3049 for (dst_pcu_idx := 0; dst_pcu_idx < lengthof(g_pcu); dst_pcu_idx := dst_pcu_idx + 1) {
3050 if (dst_pcu_idx == src_pcu_idx) {
3051 continue;
3052 }
3053
3054 for (dst_bvc_idx := 0; dst_bvc_idx < lengthof(g_pcu[dst_pcu_idx].cfg.bvc);
3055dst_bvc_idx := dst_bvc_idx + 1) {
3056 f_TC_rim_info_pcu2pcu(src_pcu_idx, src_bvc_idx, dst_pcu_idx, dst_bvc_idx);
3057 }
3058 }
3059 }
3060 }
3061
3062 f_cleanup();
3063}
3064
Harald Welte04358652021-01-17 13:48:13 +01003065/***********************************************************************
3066 * STATUS handling
3067 ***********************************************************************/
3068
3069/* BSSGP STATUS PDU must be routed based on inner "PDU In Error" message */
3070
3071/* generate a TMSI with NRI matching sgsn_idx + nri_idx */
3072private function f_gen_tmsi_for_sgsn_nri(integer sgsn_idx, integer nri_idx) runs on test_CT return OCT4
3073{
3074 var integer nri := mp_sgsn_nri[sgsn_idx][nri_idx];
3075 return f_gen_tmsi(0, nri_v := nri, nri_bitlen := mp_nri_bitlength);
3076}
3077
3078/* generate a TLLI with NRI matching sgsn_idx + nri_idx */
3079private function f_gen_tlli_for_sgsn_nri(integer sgsn_idx, integer nri_idx) runs on test_CT return OCT4
3080{
3081 var OCT4 p_tmsi := f_gen_tmsi_for_sgsn_nri(sgsn_idx, nri_idx);
3082 return f_gprs_tlli_from_tmsi(p_tmsi, TLLI_LOCAL);
3083}
3084
3085/* STATUS in uplink direction; expect routing by its NRI */
3086private function f_TC_status_ul(integer pcu_idx, integer sgsn_idx, PDU_BSSGP inner)
3087runs on GlobalTest_CT
3088{
3089 var template (value) PDU_BSSGP tx := ts_BSSGP_STATUS(omit, BSSGP_CAUSE_EQUIMENT_FAILURE, inner);
3090 var template (present) PDU_BSSGP exp_rx :=
3091 tr_BSSGP_STATUS(omit, BSSGP_CAUSE_EQUIMENT_FAILURE,
3092 tx.pDU_BSSGP_STATUS.pDU_in_Error.erroneous_BSSGP_PDU);
3093
3094 f_global_pcu2sgsn(tx, exp_rx, pcu_idx, sgsn_idx);
3095}
3096
3097/* STATUS in uplink direction; expect routing by its NRI */
3098private function f_TC_status_dl(integer sgsn_idx, integer pcu_idx, PDU_BSSGP inner)
3099runs on GlobalTest_CT
3100{
3101 var template (value) PDU_BSSGP tx := ts_BSSGP_STATUS(omit, BSSGP_CAUSE_EQUIMENT_FAILURE, inner);
3102 var template (present) PDU_BSSGP exp_rx :=
3103 tr_BSSGP_STATUS(omit, BSSGP_CAUSE_EQUIMENT_FAILURE,
3104 tx.pDU_BSSGP_STATUS.pDU_in_Error.erroneous_BSSGP_PDU);
3105
3106 f_global_sgsn2pcu(tx, exp_rx, sgsn_idx, pcu_idx);
3107}
3108
3109/* STATUS in uplink direction on SIG-BVC containing a TLLI; expect routing by its NRI */
3110testcase TC_status_sig_ul_tlli() runs on GlobalTest_CT
3111{
3112 var integer sgsn_idx, nri_idx;
3113
3114 f_init();
3115 f_global_init();
3116
3117 for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx + 1) {
3118 for (nri_idx := 0; nri_idx < lengthof(mp_sgsn_nri[sgsn_idx]); nri_idx := nri_idx + 1) {
3119 /* some downlink PDU occurring on SIG-BVC with a TLLI */
3120 var OCT4 tlli := f_gen_tlli_for_sgsn_nri(sgsn_idx, nri_idx);
3121 var PDU_BSSGP inner := valueof(ts_BSSGP_FLUSH_LL(tlli, 2342));
3122
3123 f_TC_status_ul(0, sgsn_idx, inner);
3124 }
3125 }
3126
3127 f_cleanup();
3128}
3129
3130/* STATUS in uplink direction on SIG-BVC containing a TMSI; expect routing by its NRI */
3131testcase TC_status_sig_ul_tmsi() runs on GlobalTest_CT
3132{
3133 var integer sgsn_idx, nri_idx;
3134
3135 f_init();
3136 f_global_init();
3137
3138 for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx + 1) {
3139 for (nri_idx := 0; nri_idx < lengthof(mp_sgsn_nri[sgsn_idx]); nri_idx := nri_idx + 1) {
3140 /* some downlink PDU occurring on SIG-BVC with a TMSI */
3141 const hexstring imsi := '001010123456789'H
3142 var OCT4 tmsi := f_gen_tmsi_for_sgsn_nri(sgsn_idx, nri_idx);
3143 var BssgpBvci bvci := g_pcu[0].cfg.bvc[0].bvci;
3144 var PDU_BSSGP inner := valueof(ts_BSSGP_CS_PAGING_PTMSI(bvci, imsi, oct2int(tmsi)));
3145 f_TC_status_ul(0, sgsn_idx, inner);
3146 }
3147 }
3148
3149 f_cleanup();
3150}
3151
3152
3153/* STATUS in uplink direction on PTP-BVC containing a TLLI; expect routing by its NRI */
3154testcase TC_status_ptp_ul_tlli() runs on GlobalTest_CT
3155{
3156 var integer sgsn_idx, nri_idx;
3157
3158 f_init();
3159 f_global_init_ptp();
3160
3161 for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx + 1) {
3162 for (nri_idx := 0; nri_idx < lengthof(mp_sgsn_nri[sgsn_idx]); nri_idx := nri_idx + 1) {
3163 /* some downlink PDU occurring on PTP-BVC with a TLLI */
3164 var OCT4 tlli := f_gen_tlli_for_sgsn_nri(sgsn_idx, nri_idx);
3165 var PDU_BSSGP inner := valueof(ts_BSSGP_DL_UD(tlli, '2342'O));
3166
3167 f_TC_status_ul(0, sgsn_idx, inner);
3168 }
3169 }
3170
3171 f_cleanup();
3172}
3173
3174/* STATUS in uplink direction on PTP-BVC containing a TMSI; expect routing by its NRI */
3175testcase TC_status_ptp_ul_tmsi() runs on GlobalTest_CT
3176{
3177 var integer sgsn_idx, nri_idx;
3178
3179 f_init();
3180 f_global_init_ptp();
3181
3182 for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx + 1) {
3183 for (nri_idx := 0; nri_idx < lengthof(mp_sgsn_nri[sgsn_idx]); nri_idx := nri_idx + 1) {
3184 /* some downlink PDU occurring on PTP-BVC with a TMSI */
3185 const hexstring imsi := '001010123456789'H
3186 var OCT4 tmsi := f_gen_tmsi_for_sgsn_nri(sgsn_idx, nri_idx);
3187 var BssgpBvci bvci := g_pcu[0].cfg.bvc[0].bvci;
3188 var PDU_BSSGP inner := valueof(ts_BSSGP_CS_PAGING_PTMSI(bvci, imsi, oct2int(tmsi)));
3189 f_TC_status_ul(0, sgsn_idx, inner);
3190 }
3191 }
3192
3193 f_cleanup();
3194}
3195
3196/* STATUS in downlink direction in SIG-BVC containing a BVCI; expect routing by it */
3197testcase TC_status_sig_dl_bvci() runs on GlobalTest_CT
3198{
3199 var integer sgsn_idx, pcu_idx, bvc_idx;
3200
3201 f_init();
3202 f_global_init();
3203
3204 /* test each BVC in each PCU from each SGSN */
3205 for (pcu_idx := 0; pcu_idx < lengthof(g_pcu); pcu_idx := pcu_idx + 1) {
3206 for (bvc_idx := 0; bvc_idx < lengthof(g_pcu[pcu_idx].cfg.bvc); bvc_idx := bvc_idx + 1) {
3207 for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx + 1) {
3208 /* some uplink PDU occurring on SIG-BVC containing a BVCI */
3209 var BssgpBvci bvci := g_pcu[pcu_idx].cfg.bvc[bvc_idx].bvci;
3210 var PDU_BSSGP inner := valueof(ts_BSSGP_LLC_DISCARDED('12345678'O, 1, bvci, 23));
3211 f_TC_status_dl(sgsn_idx, pcu_idx, inner);
3212 }
3213 }
3214 }
3215
3216 f_cleanup();
3217}
3218
3219/* STATUS in downlink direction in PTP-BVC; expect routing by BVCI */
3220testcase TC_status_ptp_dl_bvci() runs on GlobalTest_CT
3221{
3222 var integer sgsn_idx, pcu_idx, bvc_idx;
3223
3224 f_init();
3225 f_global_init_ptp();
3226
3227 /* test each BVC in each PCU from each SGSN */
3228 for (pcu_idx := 0; pcu_idx < lengthof(g_pcu); pcu_idx := pcu_idx + 1) {
3229 for (bvc_idx := 0; bvc_idx < lengthof(g_pcu[pcu_idx].cfg.bvc); bvc_idx := bvc_idx + 1) {
3230 var BssgpBvci bvci := g_pcu[pcu_idx].cfg.bvc[bvc_idx].bvci;
3231 f_global_ptp_connect_pcu_bvci(pcu_idx, bvci);
3232 for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx + 1) {
3233 f_global_ptp_connect_sgsn_bvci(sgsn_idx, bvci);
3234
3235 /* some uplink PDU occurring on PTP-BVC */
3236 var BssgpCellId cell_id := g_pcu[pcu_idx].cfg.bvc[bvc_idx].cell_id;
3237 var PDU_BSSGP inner := valueof(ts_BSSGP_UL_UD('12345678'O, cell_id, '4223'O));
3238 f_TC_status_dl(sgsn_idx, pcu_idx, inner);
3239 }
3240 }
3241 }
3242
3243 f_cleanup();
3244}
3245
3246/* TODO: test case for DL-STATUS(SUSPEND/RESUME) containing RA-ID; expect routing by RA-ID */
3247/* TODO: test case for UL-STATUS(PAGING-by-IMSI) after sending an actual PAGIN-by-IMSI in DL first */
Harald Weltef86f1852021-01-16 21:56:17 +01003248
Daniel Willmann423d8f42020-09-08 18:58:22 +02003249control {
3250 execute( TC_BVC_bringup() );
Harald Welte92686012020-11-15 21:45:49 +01003251 execute( TC_ul_unitdata() );
Harald Welte78d8db92020-11-15 23:27:27 +01003252 execute( TC_dl_unitdata() );
Harald Welte6dc2ac42020-11-16 09:16:17 +01003253 execute( TC_ra_capability() );
Daniel Willmannace3ece2020-11-16 19:53:26 +01003254 execute( TC_ra_capability_upd() );
Daniel Willmann165d6612020-11-19 14:27:29 +01003255 execute( TC_radio_status() );
Harald Welte3148a962021-01-17 11:15:28 +01003256 execute( TC_radio_status_tmsi() );
3257 execute( TC_radio_status_imsi() );
Daniel Willmannfa67f492020-11-19 15:48:05 +01003258 execute( TC_suspend() );
Daniel Willmann087a33d2020-11-19 15:58:43 +01003259 execute( TC_resume() );
Harald Weltef8e5c5d2020-11-27 22:37:23 +01003260 execute( TC_trace() );
Harald Weltec0351d12020-11-27 22:49:02 +01003261 execute( TC_llc_discarded() );
Harald Weltef20af412020-11-28 16:11:11 +01003262 execute( TC_overload() );
Harald Welte239aa502020-11-24 23:14:20 +01003263 execute( TC_bvc_block_ptp() );
3264 execute( TC_bvc_unblock_ptp() );
Harald Welte60a8ec72020-11-25 17:12:53 +01003265 execute( TC_bvc_reset_ptp_from_bss() );
Harald Welte16786e92020-11-27 19:11:56 +01003266 execute( TC_bvc_reset_sig_from_bss() );
Harald Welte60a8ec72020-11-25 17:12:53 +01003267 execute( TC_bvc_reset_ptp_from_sgsn() );
Harald Welte16786e92020-11-27 19:11:56 +01003268 execute( TC_bvc_reset_sig_from_sgsn() );
Harald Weltef6e59b02020-12-08 08:29:09 +01003269 if (mp_enable_bss_load_sharing) {
Harald Weltef8ef0282020-11-18 12:16:59 +01003270 /* don't enable this by default, as we don't yet have any automatic test setup for FR with 4 NS-VC */
3271 execute( TC_load_sharing_dl() );
3272 }
Harald Welte0e188242020-11-22 21:46:48 +01003273
3274 /* PAGING-PS over PTP BVC */
3275 execute( TC_paging_ps_ptp_bss() );
3276 execute( TC_paging_ps_ptp_lac() );
Harald Welte7462a592020-11-23 22:07:07 +01003277 execute( TC_paging_ps_ptp_lac_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01003278 execute( TC_paging_ps_ptp_rac() );
Harald Welte7462a592020-11-23 22:07:07 +01003279 execute( TC_paging_ps_ptp_rac_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01003280 execute( TC_paging_ps_ptp_bvci() );
Harald Welteb5a04aa2021-01-16 13:04:40 +01003281 execute( TC_paging_ps_ptp_bvci_imsi() );
Harald Welte7462a592020-11-23 22:07:07 +01003282 execute( TC_paging_ps_ptp_bvci_unknown() );
Harald Weltecf200072021-01-16 15:20:46 +01003283 execute( TC_paging_ps_reject_ptp_bvci() );
3284 execute( TC_paging_ps_reject_ptp_bvci_imsi() );
Harald Welte7595d562021-01-16 19:09:20 +01003285 execute( TC_dummy_paging_ps_ptp() );
Harald Welte0e188242020-11-22 21:46:48 +01003286
3287 /* PAGING-PS over SIG BVC */
3288 execute( TC_paging_ps_sig_bss() );
3289 execute( TC_paging_ps_sig_lac() );
Harald Welte7462a592020-11-23 22:07:07 +01003290 execute( TC_paging_ps_sig_lac_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01003291 execute( TC_paging_ps_sig_rac() );
Harald Welte7462a592020-11-23 22:07:07 +01003292 execute( TC_paging_ps_sig_rac_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01003293 execute( TC_paging_ps_sig_bvci() );
Harald Welteb5a04aa2021-01-16 13:04:40 +01003294 execute( TC_paging_ps_sig_bvci_imsi() );
Harald Welte7462a592020-11-23 22:07:07 +01003295 execute( TC_paging_ps_sig_bvci_unknown() );
Harald Weltecf200072021-01-16 15:20:46 +01003296 execute( TC_paging_ps_reject_sig_bvci() );
3297 execute( TC_paging_ps_reject_sig_bvci_imsi() );
Harald Welte7595d562021-01-16 19:09:20 +01003298 execute( TC_dummy_paging_ps_sig() );
Harald Welte0e188242020-11-22 21:46:48 +01003299
3300 /* PAGING-CS over PTP BVC */
3301 execute( TC_paging_cs_ptp_bss() );
3302 execute( TC_paging_cs_ptp_lac() );
Harald Welte7462a592020-11-23 22:07:07 +01003303 execute( TC_paging_cs_ptp_lac_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01003304 execute( TC_paging_cs_ptp_rac() );
Harald Welte7462a592020-11-23 22:07:07 +01003305 execute( TC_paging_cs_ptp_rac_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01003306 execute( TC_paging_cs_ptp_bvci() );
Harald Welte7462a592020-11-23 22:07:07 +01003307 execute( TC_paging_cs_ptp_bvci_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01003308
3309 /* PAGING-CS over SIG BVC */
3310 execute( TC_paging_cs_sig_bss() );
3311 execute( TC_paging_cs_sig_lac() );
Harald Welte7462a592020-11-23 22:07:07 +01003312 execute( TC_paging_cs_sig_lac_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01003313 execute( TC_paging_cs_sig_rac() );
Harald Welte7462a592020-11-23 22:07:07 +01003314 execute( TC_paging_cs_sig_rac_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01003315 execute( TC_paging_cs_sig_bvci() );
Harald Welte7462a592020-11-23 22:07:07 +01003316 execute( TC_paging_cs_sig_bvci_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01003317
Harald Weltef86f1852021-01-16 21:56:17 +01003318 /* RAN Information Management */
3319 execute( TC_rim_info_req() );
3320 execute( TC_rim_info() );
3321 execute( TC_rim_info_ack() );
3322 execute( TC_rim_info_error() );
3323 execute( TC_rim_info_app_error() );
3324 execute( TC_rim_info_pcu2pcu() );
3325
Harald Welte0e188242020-11-22 21:46:48 +01003326
Daniel Willmann91a8e25b2020-11-24 14:50:59 +01003327 execute( TC_flush_ll() );
Harald Welte299aa482020-12-09 15:10:55 +01003328 execute( TC_fc_bvc() );
Harald Weltecc3894b2020-12-09 16:50:12 +01003329 execute( TC_fc_ms() );
Harald Welted6f89812021-01-16 18:57:49 +01003330 execute( TC_ms_reg_enq() );
Harald Welte04358652021-01-17 13:48:13 +01003331
3332 /* Uplink STATUS */
3333 execute( TC_status_sig_ul_tlli() );
3334 execute( TC_status_sig_ul_tmsi() );
3335 execute( TC_status_ptp_ul_tlli() );
3336 execute( TC_status_ptp_ul_tmsi() );
3337
3338 /* Downlink STATUS */
3339 execute( TC_status_sig_dl_bvci() );
3340 execute( TC_status_ptp_dl_bvci() );
Daniel Willmann423d8f42020-09-08 18:58:22 +02003341}
3342
3343
3344}