blob: 9b883c79d9619e7fde565b2bdca76a2141511f1e [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,
68 local_ip := "127.0.0.1",
69 remote_udp_port := 23000,
70 remote_ip := "127.0.0.1"
71 }
72 },
73 nsvci := 101
74 }
75 }
Harald Welteb978ed62020-12-12 14:01:11 +010076 }, {
77 nsei := 102,
78 role_sgsn := true,
79 handle_sns := false,
80 nsvc := {
81 {
82 provider := {
83 ip := {
84 address_family := AF_INET,
85 local_udp_port := 8888,
86 local_ip := "127.0.0.1",
87 remote_udp_port := 23000,
88 remote_ip := "127.0.0.1"
89 }
90 },
91 nsvci := 102
92 }
93 }
Daniel Willmann423d8f42020-09-08 18:58:22 +020094 }
95 };
Daniel Willmann2c9300f2020-12-01 10:54:08 +010096 /* BSS NSEI start at 2000 + x
97 * NSVCI start from value of NSEI + 100
98 * UDP port is NSVCI * 10 */
Harald Welte6d63f742020-11-15 19:44:04 +010099 NSConfigurations mp_nsconfig_pcu := {
Daniel Willmann423d8f42020-09-08 18:58:22 +0200100 {
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100101 nsei := 2001,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200102 role_sgsn := false,
Harald Welte90f19742020-11-06 19:34:40 +0100103 handle_sns := false,
104 nsvc := {
105 {
106 provider := {
107 ip := {
108 address_family := AF_INET,
109 local_udp_port := 21010,
110 local_ip := "127.0.0.1",
111 remote_udp_port := 23000,
112 remote_ip := "127.0.0.1"
113 }
114 },
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100115 nsvci := 2101
Harald Welte90f19742020-11-06 19:34:40 +0100116 }
117 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200118 },
119 {
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100120 nsei := 2002,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200121 role_sgsn := false,
Harald Welte90f19742020-11-06 19:34:40 +0100122 handle_sns := false,
123 nsvc := {
124 {
125 provider := {
126 ip := {
127 address_family := AF_INET,
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100128 local_udp_port := 21020,
Harald Welte90f19742020-11-06 19:34:40 +0100129 local_ip := "127.0.0.1",
130 remote_udp_port := 23000,
131 remote_ip := "127.0.0.1"
132 }
133 },
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100134 nsvci := 2102
Harald Welte90f19742020-11-06 19:34:40 +0100135 }
136 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200137 },
138 {
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100139 nsei := 2003,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200140 role_sgsn := false,
Harald Welte90f19742020-11-06 19:34:40 +0100141 handle_sns := false,
142 nsvc := {
143 {
144 provider := {
145 ip := {
146 address_family := AF_INET,
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100147 local_udp_port := 21030,
Harald Welte90f19742020-11-06 19:34:40 +0100148 local_ip := "127.0.0.1",
149 remote_udp_port := 23000,
150 remote_ip := "127.0.0.1"
151 }
152 },
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100153 nsvci := 2103
Harald Welte90f19742020-11-06 19:34:40 +0100154 }
155 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200156 }
157 };
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100158 /* BVCI are NSEI*10 + x
159 * The first NSE only has one BVC, the second one 2 and so on
160 * The Cell ID is BVCI + 10000
161 * LAC/RAC are configured in such a way that:
162 * LAC 13135 is present once in NSE(2001), twice in NSE(2002) and once in NSE(2003)
163 * LAC 13300 is present twice in NSE(2003)
164 * RAI 13135-1 is present in NSE(2002) and NSE(2003)
165 * RAI 13300-0 is present twice in NSE(2003)
166 */
Harald Welte6d63f742020-11-15 19:44:04 +0100167 BssgpConfigs mp_gbconfigs := {
168 {
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100169 nsei := 2001,
Harald Welte6d63f742020-11-15 19:44:04 +0100170 sgsn_role := false,
171 bvc := {
172 {
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100173 bvci := 20011,
Harald Welte6d63f742020-11-15 19:44:04 +0100174 cell_id := {
175 ra_id := {
176 lai := {
177 mcc_mnc := c_mcc_mnc,
178 lac := 13135
179 },
180 rac := 0
181 },
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100182 cell_id := 30011
Harald Welte6d63f742020-11-15 19:44:04 +0100183 },
184 depth := BSSGP_DECODE_DEPTH_BSSGP,
185 create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
186 }
187 }
188 }, {
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100189 nsei := 2002,
Harald Welte6d63f742020-11-15 19:44:04 +0100190 sgsn_role := false,
191 bvc := {
192 {
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100193 bvci := 20021,
Harald Welte6d63f742020-11-15 19:44:04 +0100194 cell_id := {
195 ra_id := {
196 lai := {
197 mcc_mnc := c_mcc_mnc,
Harald Welte0e188242020-11-22 21:46:48 +0100198 lac := 13135
Harald Welte6d63f742020-11-15 19:44:04 +0100199 },
Harald Welte0e188242020-11-22 21:46:48 +0100200 rac := 1
Harald Welte6d63f742020-11-15 19:44:04 +0100201 },
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100202 cell_id := 30021
203 },
204 depth := BSSGP_DECODE_DEPTH_BSSGP,
205 create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
206 },
207 {
208 bvci := 20022,
209 cell_id := {
210 ra_id := {
211 lai := {
212 mcc_mnc := c_mcc_mnc,
213 lac := 13135
214 },
215 rac := 2
216 },
217 cell_id := 30022
Harald Welte6d63f742020-11-15 19:44:04 +0100218 },
219 depth := BSSGP_DECODE_DEPTH_BSSGP,
220 create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
221 }
222 }
223 }, {
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100224 nsei := 2003,
Harald Welte6d63f742020-11-15 19:44:04 +0100225 sgsn_role := false,
226 bvc := {
227 {
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100228 bvci := 20031,
229 cell_id := {
230 ra_id := {
231 lai := {
232 mcc_mnc := c_mcc_mnc,
233 lac := 13135
234 },
235 rac := 1
236 },
237 cell_id := 30031
238 },
239 depth := BSSGP_DECODE_DEPTH_BSSGP,
240 create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
241 },
242 {
243 bvci := 20032,
Harald Welte6d63f742020-11-15 19:44:04 +0100244 cell_id := {
245 ra_id := {
246 lai := {
247 mcc_mnc := c_mcc_mnc,
248 lac := 13300
249 },
250 rac := 0
251 },
Daniel Willmann2c9300f2020-12-01 10:54:08 +0100252 cell_id := 30032
253 },
254 depth := BSSGP_DECODE_DEPTH_BSSGP,
255 create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
256 },
257 {
258 bvci := 20033,
259 cell_id := {
260 ra_id := {
261 lai := {
262 mcc_mnc := c_mcc_mnc,
263 lac := 13300
264 },
265 rac := 0
266 },
267 cell_id := 30033
Harald Welte6d63f742020-11-15 19:44:04 +0100268 },
269 depth := BSSGP_DECODE_DEPTH_BSSGP,
270 create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
271 }
272 }
273 }
274 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200275};
276
Daniel Willmann423d8f42020-09-08 18:58:22 +0200277type record GbInstance {
278 NS_CT vc_NS,
279 BSSGP_CT vc_BSSGP,
Harald Welte67dc8c22020-11-17 18:32:29 +0100280 BSSGP_BVC_CTs vc_BSSGP_BVC,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200281 BssgpConfig cfg
282};
Harald Welte67dc8c22020-11-17 18:32:29 +0100283type record of BSSGP_BVC_CT BSSGP_BVC_CTs
Daniel Willmann423d8f42020-09-08 18:58:22 +0200284
285const integer NUM_PCU := 3;
Harald Welte6d63f742020-11-15 19:44:04 +0100286type record of GbInstance GbInstances;
287type record of BssgpConfig BssgpConfigs;
288type record of NSConfiguration NSConfigurations;
289type record of BssgpCellId BssgpCellIds;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200290
Harald Welteb978ed62020-12-12 14:01:11 +0100291const integer NUM_SGSN := 2;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200292
293type component test_CT {
Harald Welte6d63f742020-11-15 19:44:04 +0100294 var GbInstances g_pcu;
295 var GbInstances g_sgsn;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200296
297 port BSSGP_CT_PROC_PT PROC;
298
Harald Weltefbae83f2020-11-15 23:25:55 +0100299 port BSSGP_BVC_MGMT_PT SGSN_MGMT;
300 port BSSGP_BVC_MGMT_PT PCU_MGMT;
301
Daniel Willmann423d8f42020-09-08 18:58:22 +0200302 port TELNETasp_PT GBPVTY;
303
304 var boolean g_initialized := false;
305 var boolean g_use_echo := false;
Harald Welte16786e92020-11-27 19:11:56 +0100306
307 var ro_integer g_roi := {};
Harald Welte425d3762020-12-09 14:33:18 +0100308 timer g_Tguard;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200309};
310
311type component BSSGP_ConnHdlr {
Harald Welte3dd21b32020-11-17 19:21:00 +0100312 /* array of per-BVC ports on the PCU side */
Harald Welte158becf2020-12-09 12:32:32 +0100313 port BSSGP_PT PCU_PTP[NUM_PCU];
Daniel Willmann423d8f42020-09-08 18:58:22 +0200314 port BSSGP_PT PCU_SIG[NUM_PCU];
315 port BSSGP_PROC_PT PCU_PROC[NUM_PCU];
Harald Welte3dd21b32020-11-17 19:21:00 +0100316 /* component reference to the component to which we're currently connected */
317 var BSSGP_BVC_CT pcu_ct[NUM_PCU];
Harald Welte0e188242020-11-22 21:46:48 +0100318 /* BSSGP BVC configuration of the component to which we're currently connected */
319 var BssgpBvcConfig pcu_bvc_cfg[NUM_PCU];
Harald Welte3dd21b32020-11-17 19:21:00 +0100320
321 /* array of per-BVC ports on the SGSN side */
Harald Welte158becf2020-12-09 12:32:32 +0100322 port BSSGP_PT SGSN_PTP[NUM_SGSN];
Daniel Willmann423d8f42020-09-08 18:58:22 +0200323 port BSSGP_PT SGSN_SIG[NUM_SGSN];
324 port BSSGP_PROC_PT SGSN_PROC[NUM_SGSN];
Harald Welte3dd21b32020-11-17 19:21:00 +0100325 /* component reference to the component to which we're currently connected */
326 var BSSGP_BVC_CT sgsn_ct[NUM_PCU];
Daniel Willmann423d8f42020-09-08 18:58:22 +0200327
328 var BSSGP_ConnHdlrPars g_pars;
329 timer g_Tguard;
330 var LLC_Entities llc;
Harald Welte0e188242020-11-22 21:46:48 +0100331
332 var ro_integer g_roi := {};
Daniel Willmann423d8f42020-09-08 18:58:22 +0200333}
334
335type record SGSN_ConnHdlrNetworkPars {
336 boolean expect_ptmsi,
337 boolean expect_auth,
338 boolean expect_ciph
339};
340
341type record BSSGP_ConnHdlrPars {
342 /* IMEI of the simulated ME */
343 hexstring imei,
344 /* IMSI of the simulated MS */
345 hexstring imsi,
346 /* MSISDN of the simulated MS (probably unused) */
347 hexstring msisdn,
348 /* P-TMSI allocated to the simulated MS */
349 OCT4 p_tmsi optional,
350 OCT3 p_tmsi_sig optional,
351 /* TLLI of the simulated MS */
352 OCT4 tlli,
353 OCT4 tlli_old optional,
354 RoutingAreaIdentificationV ra optional,
Harald Welte16357a92020-11-17 18:20:00 +0100355 GbInstances pcu,
Harald Welte3dd21b32020-11-17 19:21:00 +0100356 GbInstances sgsn,
Harald Weltec5f486b2021-01-16 11:07:01 +0100357 /* The SGSN index to be used within the test */
358 integer sgsn_idx,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200359 float t_guard
360};
361
362private function f_cellid_to_RAI(in BssgpCellId cell_id) return RoutingAreaIdentificationV {
363 /* mcc_mnc is encoded as of 24.008 10.5.5.15 */
364 var BcdMccMnc mcc_mnc := cell_id.ra_id.lai.mcc_mnc;
365
366 var RoutingAreaIdentificationV ret := {
367 mccDigit1 := mcc_mnc[0],
368 mccDigit2 := mcc_mnc[1],
369 mccDigit3 := mcc_mnc[2],
370 mncDigit3 := mcc_mnc[3],
371 mncDigit1 := mcc_mnc[4],
372 mncDigit2 := mcc_mnc[5],
373 lac := int2oct(cell_id.ra_id.lai.lac, 16),
374 rac := int2oct(cell_id.ra_id.rac, 8)
375 }
376 return ret;
377};
378
Harald Welte95339432020-12-02 18:50:52 +0100379private function f_fix_create_cb(inout BssgpConfig cfg)
380{
381 for (var integer i := 0; i < lengthof(cfg.bvc); i := i + 1) {
382 if (not isbound(cfg.bvc[i].create_cb)) {
383 cfg.bvc[i].create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
384 }
385 }
386}
387
Daniel Willmann423d8f42020-09-08 18:58:22 +0200388private function f_init_gb_pcu(inout GbInstance gb, charstring id, integer offset) runs on test_CT {
Harald Welteb419d0e2020-11-16 16:45:05 +0100389 var charstring ns_id := id & "-NS(PCU[" & int2str(offset) & "])";
390 var charstring bssgp_id := id & "-BSSGP(PCU[" & int2str(offset) & "])";
391 gb.vc_NS := NS_CT.create(ns_id);
392 gb.vc_BSSGP := BSSGP_CT.create(bssgp_id);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200393 /* connect lower end of BSSGP emulation with NS upper port */
394 connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
395
Harald Welteb419d0e2020-11-16 16:45:05 +0100396 gb.vc_NS.start(NSStart(mp_nsconfig_pcu[offset], ns_id));
397 gb.vc_BSSGP.start(BssgpStart(gb.cfg, bssgp_id));
Daniel Willmann423d8f42020-09-08 18:58:22 +0200398
399 for (var integer i := 0; i < lengthof(gb.cfg.bvc); i := i + 1) {
Harald Welteb978ed62020-12-12 14:01:11 +0100400 /* obtain the component reference of the BSSGP_BVC_CT for each PTP BVC */
Daniel Willmann423d8f42020-09-08 18:58:22 +0200401 connect(self:PROC, gb.vc_BSSGP:PROC);
402 gb.vc_BSSGP_BVC[i] := f_bssgp_get_bvci_ct(gb.cfg.bvc[i].bvci, PROC);
403 disconnect(self:PROC, gb.vc_BSSGP:PROC);
Harald Welteb978ed62020-12-12 14:01:11 +0100404 /* connect all of the per-BVC MGMT ports to our PCU_MGMT port (1:N) */
Harald Weltefbae83f2020-11-15 23:25:55 +0100405 connect(self:PCU_MGMT, gb.vc_BSSGP_BVC[i]:MGMT);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200406 }
Harald Welteb978ed62020-12-12 14:01:11 +0100407 /* connect all of the BSSGP/NSE global MGMT port to our PCU_MGMT port (1:N) */
Harald Welte16786e92020-11-27 19:11:56 +0100408 connect(self:PCU_MGMT, gb.vc_BSSGP:MGMT);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200409}
410
411private function f_init_gb_sgsn(inout GbInstance gb, charstring id, integer offset) runs on test_CT {
Harald Welteb419d0e2020-11-16 16:45:05 +0100412 var charstring ns_id := id & "-NS(SGSN[" & int2str(offset) & "])";
413 var charstring bssgp_id := id & "-BSSGP(SGSN[" & int2str(offset) & "])";
414 gb.vc_NS := NS_CT.create(ns_id);
415 gb.vc_BSSGP := BSSGP_CT.create(bssgp_id);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200416 /* connect lower end of BSSGP emulation with NS upper port */
417 connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
418
Harald Welteb419d0e2020-11-16 16:45:05 +0100419 gb.vc_NS.start(NSStart(mp_nsconfig_sgsn[offset], ns_id));
420 gb.vc_BSSGP.start(BssgpStart(gb.cfg, bssgp_id));
Daniel Willmann423d8f42020-09-08 18:58:22 +0200421
422 for (var integer i := 0; i < lengthof(gb.cfg.bvc); i := i + 1) {
Harald Welteb978ed62020-12-12 14:01:11 +0100423 /* obtain the component reference of the BSSGP_BVC_CT for each PTP BVC */
Daniel Willmann423d8f42020-09-08 18:58:22 +0200424 connect(self:PROC, gb.vc_BSSGP:PROC);
425 gb.vc_BSSGP_BVC[i] := f_bssgp_get_bvci_ct(gb.cfg.bvc[i].bvci, PROC);
426 disconnect(self:PROC, gb.vc_BSSGP:PROC);
Harald Welteb978ed62020-12-12 14:01:11 +0100427 /* connect all of the per-BVC MGMT ports to our SGSN_MGMT port (1:N) */
Harald Weltefbae83f2020-11-15 23:25:55 +0100428 connect(self:SGSN_MGMT, gb.vc_BSSGP_BVC[i]:MGMT);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200429 }
Harald Welteb978ed62020-12-12 14:01:11 +0100430 /* connect all of the BSSGP/NSE global MGMT port to our SGSN_MGMT port (1:N) */
Harald Welte16786e92020-11-27 19:11:56 +0100431 connect(self:SGSN_MGMT, gb.vc_BSSGP:MGMT);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200432}
433
434
Harald Welteb9f0fdc2020-12-09 14:44:50 +0100435private function f_destroy_gb(inout GbInstance gb) runs on test_CT {
436 gb.vc_NS.stop;
437 gb.vc_BSSGP.stop;
438
439 for (var integer i := 0; i < lengthof(gb.cfg.bvc); i := i + 1) {
440 gb.vc_BSSGP_BVC[i].stop;
441 }
442}
443
Daniel Willmann423d8f42020-09-08 18:58:22 +0200444private function f_init_vty() runs on test_CT {
445 map(self:GBPVTY, system:GBPVTY);
446 f_vty_set_prompts(GBPVTY);
447 f_vty_transceive(GBPVTY, "enable");
448}
449
Harald Weltefbae83f2020-11-15 23:25:55 +0100450type record of integer ro_integer;
451
452private function ro_integer_contains(ro_integer r, integer x) return boolean {
453 for (var integer j := 0; j < lengthof(r); j := j+1) {
454 if (r[j] == x) {
455 return true;
456 }
457 }
458 return false;
459}
460
Harald Welteb978ed62020-12-12 14:01:11 +0100461private type record of ro_integer roro_integer;
462
463/* count the number of unblocked BVCI for each SGSN NSE */
464private altstep as_count_unblocked4nse(integer sgsn_idx, inout roro_integer bvci_unblocked)
465runs on test_CT {
466 var BssgpStatusIndication bsi;
467 [] SGSN_MGMT.receive(BssgpStatusIndication:{g_sgsn[sgsn_idx].cfg.nsei, ?, BVC_S_UNBLOCKED}) -> value bsi {
468 bvci_unblocked[sgsn_idx] := bvci_unblocked[sgsn_idx] & { bsi.bvci };
469 /* 'repeat' until sufficient number of BVC-rest has been received on all SGSNs */
470 for (var integer i := 0; i < lengthof(bvci_unblocked); i := i+1) {
471 if (lengthof(bvci_unblocked[i]) < lengthof(g_sgsn[i].cfg.bvc)) {
472 repeat;
473 }
474 }
475 }
476}
477
Harald Welte425d3762020-12-09 14:33:18 +0100478function f_init(float t_guard := 30.0) runs on test_CT {
Harald Welteb978ed62020-12-12 14:01:11 +0100479 var roro_integer bvci_unblocked;
Harald Weltefbae83f2020-11-15 23:25:55 +0100480 var BssgpStatusIndication bsi;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200481 var integer i;
482
483 if (g_initialized == true) {
484 return;
485 }
486 g_initialized := true;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200487
Harald Welte425d3762020-12-09 14:33:18 +0100488 g_Tguard.start(t_guard);
489 activate(as_gTguard(g_Tguard));
490
Harald Welteb978ed62020-12-12 14:01:11 +0100491 var BssgpBvcConfigs bvcs := { };
Harald Welte6d63f742020-11-15 19:44:04 +0100492 for (i := 0; i < lengthof(mp_gbconfigs); i := i+1) {
493 g_pcu[i].cfg := mp_gbconfigs[i];
Harald Welte95339432020-12-02 18:50:52 +0100494 /* make sure all have a proper crate_cb, which cannot be specified in config file */
495 f_fix_create_cb(g_pcu[i].cfg);
Harald Welte6d63f742020-11-15 19:44:04 +0100496 /* concatenate all the PCU-side BVCs for the SGSN side */
Harald Welteb978ed62020-12-12 14:01:11 +0100497 bvcs := bvcs & g_pcu[i].cfg.bvc;
498 }
499
500 for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
501 g_sgsn[i].cfg := {
502 nsei := mp_nsconfig_sgsn[i].nsei,
503 sgsn_role := true,
504 bvc := bvcs
505 }
Harald Welte6d63f742020-11-15 19:44:04 +0100506 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200507
508 f_init_vty();
Harald Welte6d63f742020-11-15 19:44:04 +0100509 for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
Daniel Willmann443fc572020-11-18 13:26:57 +0100510 f_vty_transceive(GBPVTY, "nsvc nsei " & int2str(g_sgsn[i].cfg.nsei) & " force-unconfigured");
Daniel Willmannad93c052020-12-04 14:14:38 +0100511 }
512 for (i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
513 f_vty_transceive(GBPVTY, "nsvc nsei " & int2str(g_pcu[i].cfg.nsei) & " force-unconfigured");
514 f_vty_transceive(GBPVTY, "delete-gbproxy-peer " & int2str(g_pcu[i].cfg.nsei) & " only-bvc");
515 }
516
517 for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
Harald Welteea1ba592020-11-17 18:05:13 +0100518 f_init_gb_sgsn(g_sgsn[i], "GbProxy_Test", i);
Harald Welte6d63f742020-11-15 19:44:04 +0100519 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200520 f_sleep(4.0);
Harald Welte6d63f742020-11-15 19:44:04 +0100521 for (i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
Harald Welteb419d0e2020-11-16 16:45:05 +0100522 f_init_gb_pcu(g_pcu[i], "GbProxy_Test", i);
Harald Welte6d63f742020-11-15 19:44:04 +0100523 }
Harald Weltefbae83f2020-11-15 23:25:55 +0100524
Harald Welteb978ed62020-12-12 14:01:11 +0100525 for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
526 bvci_unblocked[i] := {};
527 }
528
Harald Weltefbae83f2020-11-15 23:25:55 +0100529 /* wait until all BVC are unblocked on both sides */
Harald Welted2801272020-11-17 19:22:58 +0100530 timer T := 15.0;
Harald Weltefbae83f2020-11-15 23:25:55 +0100531 T.start;
532 alt {
Harald Welteb978ed62020-12-12 14:01:11 +0100533 /* TODO: We need to add more lines if NUM_SGSN increases. Activating default altsteps
534 * unfortunately doesn't work as we want to access the local variable bvci_unblocked. */
535 [] as_count_unblocked4nse(0, bvci_unblocked);
536 [lengthof(g_sgsn) > 1] as_count_unblocked4nse(1, bvci_unblocked);
Harald Weltefbae83f2020-11-15 23:25:55 +0100537 [] SGSN_MGMT.receive(BssgpStatusIndication:{*, ?, ?}) {
538 repeat;
539 }
Harald Welte3c905152020-11-26 20:56:09 +0100540 [] SGSN_MGMT.receive(BssgpResetIndication:?) {
541 repeat;
542 }
Harald Weltefbae83f2020-11-15 23:25:55 +0100543 [] SGSN_MGMT.receive {
544 setverdict(fail, "Received unexpected message on SGSN_MGMT");
545 mtc.stop;
546 }
547
548 [] PCU_MGMT.receive(BssgpStatusIndication:{*, ?, BVC_S_UNBLOCKED}) -> value bsi {
549 repeat;
550 }
551 [] PCU_MGMT.receive(BssgpStatusIndication:{*, ?, ?}) {
552 repeat;
553 }
554 [] PCU_MGMT.receive(BssgpResetIndication:{0}) {
555 repeat;
556 }
557 [] PCU_MGMT.receive {
558 setverdict(fail, "Received unexpected message on PCU_MGMT");
559 mtc.stop;
560 }
561
562 [] T.timeout {
Harald Welte6929e322020-12-12 13:10:45 +0100563 setverdict(fail, "Timeout waiting for unblock of all BVCs on SGSN side; ",
Harald Welteb978ed62020-12-12 14:01:11 +0100564 "unblocked so far: ", bvci_unblocked);
Harald Welte6929e322020-12-12 13:10:45 +0100565 /* don't stop here but print below analysis */
Harald Weltefbae83f2020-11-15 23:25:55 +0100566 }
567 }
568
Harald Welteb978ed62020-12-12 14:01:11 +0100569 for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
570 /* iterate over list and check all BVCI */
571 for (var integer j := 0; j < lengthof(g_sgsn[i].cfg.bvc); j := j+1) {
572 var BssgpBvci bvci := g_sgsn[i].cfg.bvc[j].bvci;
573 if (not ro_integer_contains(bvci_unblocked[i], bvci)) {
574 setverdict(fail, "SGSN ", i, " BVCI=", bvci, " was not unblocked during start-up");
575 mtc.stop;
576 }
Harald Weltefbae83f2020-11-15 23:25:55 +0100577 }
578 }
Harald Welte425d3762020-12-09 14:33:18 +0100579
580 /* re-start guard timer after all BVCs are up, so it only counts the actual test case */
581 g_Tguard.start(t_guard);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200582}
583
584function f_cleanup() runs on test_CT {
Harald Welteb9f0fdc2020-12-09 14:44:50 +0100585 var integer i;
586
Daniel Willmann491af2a2021-01-08 01:32:51 +0100587 /* To avoid a dynamic test case error we need to prevent messages arriving on unconnected
588 * ports. Waiting here ensures that any messages "in flight" will be delivered to the port
589 * before the component is shutdown and disconnected. */
590 f_sleep(0.2);
591
Harald Welteb9f0fdc2020-12-09 14:44:50 +0100592 for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
593 f_destroy_gb(g_sgsn[i]);
594 }
595 for (i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
596 f_destroy_gb(g_pcu[i]);
597 }
598
599 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200600}
601
602type function void_fn(charstring id) runs on BSSGP_ConnHdlr;
603
604/* helper function to create, connect and start a BSSGP_ConnHdlr component */
Harald Welte207166c2021-01-16 12:52:30 +0100605function f_start_handler(void_fn fn, charstring id, integer imsi_suffix, float t_guard := 30.0,
606 integer sgsn_idx := 0, integer nri_idx := 0, boolean have_ptmsi := true)
Daniel Willmann423d8f42020-09-08 18:58:22 +0200607runs on test_CT return BSSGP_ConnHdlr {
608 var BSSGP_ConnHdlr vc_conn;
Harald Weltec5f486b2021-01-16 11:07:01 +0100609 var integer nri := mp_sgsn_nri[sgsn_idx][nri_idx];
Harald Welte77218d02021-01-15 19:59:15 +0100610 var OCT4 p_tmsi := f_gen_tmsi(imsi_suffix, nri_v := nri, nri_bitlen := mp_nri_bitlength);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200611
612 var BSSGP_ConnHdlrPars pars := {
613 imei := f_gen_imei(imsi_suffix),
614 imsi := f_gen_imsi(imsi_suffix),
615 msisdn := f_gen_msisdn(imsi_suffix),
Harald Weltedbd5e672021-01-14 21:03:14 +0100616 p_tmsi := p_tmsi,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200617 p_tmsi_sig := omit,
Harald Weltedbd5e672021-01-14 21:03:14 +0100618 tlli := f_gprs_tlli_from_tmsi(p_tmsi, TLLI_LOCAL),
Daniel Willmann423d8f42020-09-08 18:58:22 +0200619 tlli_old := omit,
620 ra := omit,
Harald Welte2ecbca82021-01-16 11:23:09 +0100621 pcu := g_pcu,
622 sgsn := g_sgsn,
Harald Weltec5f486b2021-01-16 11:07:01 +0100623 sgsn_idx := sgsn_idx,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200624 t_guard := t_guard
625 };
Harald Welte207166c2021-01-16 12:52:30 +0100626 if (not have_ptmsi) {
627 pars.p_tmsi := omit;
628 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200629
630 vc_conn := BSSGP_ConnHdlr.create(id);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200631
632 vc_conn.start(f_handler_init(fn, id, pars));
633 return vc_conn;
634}
635
Harald Welte207166c2021-01-16 12:52:30 +0100636function f_start_handlers(void_fn fn, charstring id, integer imsi_suffix, float t_guard := 30.0,
637 boolean have_ptmsi := true)
Harald Weltec5f486b2021-01-16 11:07:01 +0100638runs on test_CT
639{
640 var integer sgsn_idx, nri_idx;
641 for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx:=sgsn_idx+1) {
642 for (nri_idx := 0; nri_idx < lengthof(mp_sgsn_nri[sgsn_idx]); nri_idx:=nri_idx+1) {
643 var integer extd_imsi_suffix := 1000*sgsn_idx + 100*nri_idx;
644 var BSSGP_ConnHdlr vc_conn;
Harald Welte207166c2021-01-16 12:52:30 +0100645 vc_conn := f_start_handler(fn, id, extd_imsi_suffix, t_guard, sgsn_idx, nri_idx,
646 have_ptmsi);
Harald Weltec5f486b2021-01-16 11:07:01 +0100647 /* Idea: we could also run them in parallel ? */
648 vc_conn.done;
649 }
650 }
651}
652
Harald Welte3dd21b32020-11-17 19:21:00 +0100653/* 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 +0100654private function f_connect_to_pcu_bvc(integer port_idx, integer nse_idx, integer bvc_idx)
655runs on BSSGP_ConnHdlr {
656 var BSSGP_BVC_CT bvc_ct := g_pars.pcu[nse_idx].vc_BSSGP_BVC[bvc_idx]
Harald Welte158becf2020-12-09 12:32:32 +0100657 if (PCU_PTP[port_idx].checkstate("Connected")) {
Harald Welte3dd21b32020-11-17 19:21:00 +0100658 /* unregister + disconnect from old BVC */
659 f_client_unregister(g_pars.imsi, PCU_PROC[port_idx]);
Harald Welte158becf2020-12-09 12:32:32 +0100660 disconnect(self:PCU_PTP[port_idx], pcu_ct[port_idx]:BSSGP_SP);
Harald Welte3dd21b32020-11-17 19:21:00 +0100661 disconnect(self:PCU_SIG[port_idx], pcu_ct[port_idx]:BSSGP_SP_SIG);
662 disconnect(self:PCU_PROC[port_idx], pcu_ct[port_idx]:BSSGP_PROC);
663 }
664 /* connect to new BVC and register us */
Harald Welte158becf2020-12-09 12:32:32 +0100665 connect(self:PCU_PTP[port_idx], bvc_ct:BSSGP_SP);
Harald Welte3dd21b32020-11-17 19:21:00 +0100666 connect(self:PCU_SIG[port_idx], bvc_ct:BSSGP_SP_SIG);
667 connect(self:PCU_PROC[port_idx], bvc_ct:BSSGP_PROC);
668 f_client_register(g_pars.imsi, g_pars.tlli, PCU_PROC[port_idx]);
669 pcu_ct[port_idx] := bvc_ct;
Harald Welte0e188242020-11-22 21:46:48 +0100670 pcu_bvc_cfg[port_idx] := g_pars.pcu[nse_idx].cfg.bvc[bvc_idx];
Harald Welte3dd21b32020-11-17 19:21:00 +0100671}
672
673/* Connect the SGSN-side per-BVC ports (SGSN/SGSN_SIG/SGSN_PROC) array slot 'port_idx' to specified per-BVC component */
674private 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 +0100675 if (SGSN_PTP[port_idx].checkstate("Connected")) {
Harald Welte3dd21b32020-11-17 19:21:00 +0100676 /* unregister + disconnect from old BVC */
677 f_client_unregister(g_pars.imsi, SGSN_PROC[port_idx]);
Harald Welte158becf2020-12-09 12:32:32 +0100678 disconnect(self:SGSN_PTP[port_idx], sgsn_ct[port_idx]:BSSGP_SP);
Harald Welte3dd21b32020-11-17 19:21:00 +0100679 disconnect(self:SGSN_SIG[port_idx], sgsn_ct[port_idx]:BSSGP_SP_SIG);
680 disconnect(self:SGSN_PROC[port_idx], sgsn_ct[port_idx]:BSSGP_PROC);
681 }
682 /* connect to new BVC and register us */
Harald Welte158becf2020-12-09 12:32:32 +0100683 connect(self:SGSN_PTP[port_idx], bvc_ct:BSSGP_SP);
Harald Welte3dd21b32020-11-17 19:21:00 +0100684 connect(self:SGSN_SIG[port_idx], bvc_ct:BSSGP_SP_SIG);
685 connect(self:SGSN_PROC[port_idx], bvc_ct:BSSGP_PROC);
686 f_client_register(g_pars.imsi, g_pars.tlli, SGSN_PROC[port_idx]);
687 sgsn_ct[port_idx] := bvc_ct;
688}
689
Harald Welte425d3762020-12-09 14:33:18 +0100690private altstep as_gTguard(timer Tguard) {
691 [] Tguard.timeout {
Daniel Willmann423d8f42020-09-08 18:58:22 +0200692 setverdict(fail, "Tguard timeout");
693 mtc.stop;
694 }
695}
696
697/* first function called in every ConnHdlr */
698private function f_handler_init(void_fn fn, charstring id, BSSGP_ConnHdlrPars pars)
699runs on BSSGP_ConnHdlr {
Harald Welte1e834f32020-11-15 20:02:59 +0100700 var integer i;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200701 /* do some common stuff like setting up g_pars */
702 g_pars := pars;
703
704 llc := f_llc_create(false);
705
Harald Welte3dd21b32020-11-17 19:21:00 +0100706 /* default connections on PCU side: First BVC of each NSE/PCU */
707 for (i := 0; i < lengthof(g_pars.pcu); i := i+1) {
Harald Welte0e188242020-11-22 21:46:48 +0100708 f_connect_to_pcu_bvc(port_idx := i, nse_idx := i, bvc_idx := 0);
Harald Welte1e834f32020-11-15 20:02:59 +0100709 }
Harald Welte3dd21b32020-11-17 19:21:00 +0100710
711 /* default connections on SGSN side: First BVC of each NSE/SGSN */
712 for (i := 0; i < lengthof(g_pars.sgsn); i := i+1) {
713 f_connect_to_sgsn_bvc(i, g_pars.sgsn[i].vc_BSSGP_BVC[0]);
Harald Welte1e834f32020-11-15 20:02:59 +0100714 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200715
716 g_Tguard.start(pars.t_guard);
Harald Welte425d3762020-12-09 14:33:18 +0100717 activate(as_gTguard(g_Tguard));
Daniel Willmann423d8f42020-09-08 18:58:22 +0200718
719 /* call the user-supplied test case function */
720 fn.apply(id);
Harald Welteb33fb592021-01-16 12:50:56 +0100721
722 for (i := 0; i < NUM_SGSN; i := i+1) {
723 if (SGSN_PROC[i].checkstate("Connected")) {
724 f_client_unregister(g_pars.imsi, SGSN_PROC[i])
725 }
726 }
727
728 for (i := 0; i < NUM_PCU; i := i+1) {
729 if (PCU_PROC[i].checkstate("Connected")) {
730 f_client_unregister(g_pars.imsi, PCU_PROC[i])
731 }
732 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200733}
734
Harald Welte1e834f32020-11-15 20:02:59 +0100735private function f_client_register(hexstring imsi, OCT4 tlli, BSSGP_PROC_PT PT)
736runs on BSSGP_ConnHdlr {
737 PT.call(BSSGP_register_client:{imsi, tlli}) {
738 [] PT.getreply(BSSGP_register_client:{imsi, tlli}) {};
739 }
740}
741
742private function f_client_unregister(hexstring imsi, BSSGP_PROC_PT PT)
743runs on BSSGP_ConnHdlr {
744 PT.call(BSSGP_unregister_client:{imsi}) {
745 [] PT.getreply(BSSGP_unregister_client:{imsi}) {};
746 }
747}
748
Harald Welte22ef5d92020-11-16 13:35:14 +0100749/* Send 'tx' on PTP-BVCI from PCU; expect 'rx' on SGSN */
750friend function f_pcu2sgsn(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
Harald Weltec5f486b2021-01-16 11:07:01 +0100751 integer pcu_idx := 0, boolean use_sig := false) runs on BSSGP_ConnHdlr {
752 var integer sgsn_idx := g_pars.sgsn_idx;
Harald Welte22ef5d92020-11-16 13:35:14 +0100753 var PDU_BSSGP rx;
754 timer T := 1.0;
755
Daniel Willmann4798fd72020-11-24 16:23:29 +0100756 if (use_sig) {
757 PCU_SIG[pcu_idx].send(tx);
758 } else {
Harald Welte158becf2020-12-09 12:32:32 +0100759 PCU_PTP[pcu_idx].send(tx);
Daniel Willmann4798fd72020-11-24 16:23:29 +0100760 }
761
Harald Welte22ef5d92020-11-16 13:35:14 +0100762 T.start;
763 alt {
Daniel Willmann4798fd72020-11-24 16:23:29 +0100764 [use_sig] SGSN_SIG[sgsn_idx].receive(exp_rx) {
765 setverdict(pass);
766 }
Harald Welte158becf2020-12-09 12:32:32 +0100767 [not use_sig] SGSN_PTP[sgsn_idx].receive(exp_rx) {
Harald Welte22ef5d92020-11-16 13:35:14 +0100768 setverdict(pass);
769 }
Harald Welte158becf2020-12-09 12:32:32 +0100770 [] SGSN_PTP[sgsn_idx].receive(PDU_BSSGP:?) -> value rx {
Harald Weltec5f486b2021-01-16 11:07:01 +0100771 setverdict(fail, "Unexpected BSSGP on SGSN[", sgsn_idx, "] side: ", rx);
Harald Welte22ef5d92020-11-16 13:35:14 +0100772 mtc.stop;
773 }
Daniel Willmann4798fd72020-11-24 16:23:29 +0100774 [] SGSN_SIG[sgsn_idx].receive(PDU_BSSGP:?) -> value rx {
Harald Weltec5f486b2021-01-16 11:07:01 +0100775 setverdict(fail, "Unexpected SIG BSSGP on SGSN[", sgsn_idx, "] side: ", rx);
Daniel Willmann4798fd72020-11-24 16:23:29 +0100776 mtc.stop;
777 }
Harald Welte22ef5d92020-11-16 13:35:14 +0100778 [] T.timeout {
Harald Weltec5f486b2021-01-16 11:07:01 +0100779 setverdict(fail, "Timeout waiting for BSSGP on SGSN[", sgsn_idx, "] side: ", exp_rx);
Harald Welte22ef5d92020-11-16 13:35:14 +0100780 mtc.stop;
781 }
782 }
783}
784
785/* Send 'tx' on PTP-BVCI from SGSN; expect 'rx' on PCU */
786friend function f_sgsn2pcu(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
Harald Weltec5f486b2021-01-16 11:07:01 +0100787 integer pcu_idx := 0, boolean use_sig := false) runs on BSSGP_ConnHdlr {
788 var integer sgsn_idx := g_pars.sgsn_idx;
Harald Welte22ef5d92020-11-16 13:35:14 +0100789 var PDU_BSSGP rx;
790 timer T := 1.0;
791
Daniel Willmann4798fd72020-11-24 16:23:29 +0100792 if (use_sig) {
793 SGSN_SIG[sgsn_idx].send(tx);
794 } else {
Harald Welte158becf2020-12-09 12:32:32 +0100795 SGSN_PTP[sgsn_idx].send(tx);
Daniel Willmann4798fd72020-11-24 16:23:29 +0100796 }
797
Harald Welte22ef5d92020-11-16 13:35:14 +0100798 T.start;
799 alt {
Daniel Willmann4798fd72020-11-24 16:23:29 +0100800 [use_sig] PCU_SIG[pcu_idx].receive(exp_rx) {
801 setverdict(pass);
802 }
Harald Welte158becf2020-12-09 12:32:32 +0100803 [not use_sig] PCU_PTP[pcu_idx].receive(exp_rx) {
Harald Welte22ef5d92020-11-16 13:35:14 +0100804 setverdict(pass);
805 }
Harald Welte158becf2020-12-09 12:32:32 +0100806 [] PCU_PTP[pcu_idx].receive(PDU_BSSGP:?) -> value rx {
Harald Welte22ef5d92020-11-16 13:35:14 +0100807 setverdict(fail, "Unexpected BSSGP on PCU side: ", rx);
808 mtc.stop;
809 }
Daniel Willmann4798fd72020-11-24 16:23:29 +0100810 [] PCU_SIG[pcu_idx].receive(PDU_BSSGP:?) -> value rx {
811 setverdict(fail, "Unexpected SIG BSSGP on PCU side: ", rx);
812 mtc.stop;
813 }
Harald Welte22ef5d92020-11-16 13:35:14 +0100814 [] T.timeout {
Harald Welte8b326412020-11-29 16:05:38 +0100815 setverdict(fail, "Timeout waiting for BSSGP on PCU side: ", exp_rx);
Harald Welte22ef5d92020-11-16 13:35:14 +0100816 mtc.stop;
817 }
818 }
819}
Harald Welte1e834f32020-11-15 20:02:59 +0100820
Harald Welte3807ed12020-11-24 19:05:22 +0100821/***********************************************************************
822 * GlobaLTest_CT: Using the per-NSE GLOBAL ports on PCU + SGSN side
823 ***********************************************************************/
824
825type component GlobalTest_CT extends test_CT {
826 port BSSGP_PT G_PCU[NUM_PCU];
827 port BSSGP_PT G_SGSN[NUM_SGSN];
828};
829
Harald Welte299aa482020-12-09 15:10:55 +0100830/* connect the signaling BVC of each NSE to the G_PCU / G_SGSN ports */
Harald Welte3807ed12020-11-24 19:05:22 +0100831private function f_global_init() runs on GlobalTest_CT {
832 var integer i;
833 for (i := 0; i < lengthof(g_sgsn); i := i+1) {
834 connect(self:G_SGSN[i], g_sgsn[i].vc_BSSGP:GLOBAL);
835 }
836 for (i := 0; i < lengthof(g_pcu); i := i+1) {
837 connect(self:G_PCU[i], g_pcu[i].vc_BSSGP:GLOBAL);
838 }
839}
840
Harald Welte299aa482020-12-09 15:10:55 +0100841/* connect the first PTP BVC of each NSE to the G_PCU / G_SGSN ports */
842private function f_global_init_ptp() runs on GlobalTest_CT {
843 var integer i;
844 for (i := 0; i < lengthof(g_sgsn); i := i+1) {
845 connect(self:G_SGSN[i], g_sgsn[i].vc_BSSGP_BVC[0]:GLOBAL);
846 }
847 for (i := 0; i < lengthof(g_pcu); i := i+1) {
848 connect(self:G_PCU[i], g_pcu[i].vc_BSSGP_BVC[0]:GLOBAL);
849 }
850}
851
Harald Welte3807ed12020-11-24 19:05:22 +0100852/* Send 'tx' on PTP-BVCI from PCU; expect 'rx' on SGSN */
853friend function f_global_pcu2sgsn(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
854 integer pcu_idx := 0, integer sgsn_idx := 0) runs on GlobalTest_CT {
855 var PDU_BSSGP rx;
856 timer T := 1.0;
857
858 G_PCU[pcu_idx].send(tx);
859 T.start;
860 alt {
861 [] G_SGSN[sgsn_idx].receive(exp_rx) {
862 setverdict(pass);
863 }
864 [] G_SGSN[sgsn_idx].receive(PDU_BSSGP:?) -> value rx {
865 setverdict(fail, "Unexpected BSSGP on SGSN side: ", rx);
866 mtc.stop;
867 }
868 [] T.timeout {
Harald Weltedc805c02020-12-11 10:59:17 +0100869 setverdict(fail, "Timeout waiting for BSSGP on SGSN side: ", exp_rx);
Harald Welte3807ed12020-11-24 19:05:22 +0100870 mtc.stop;
871 }
872 }
873}
874
875/* Send 'tx' on PTP-BVCI from SGSN; expect 'rx' on PCU */
876friend function f_global_sgsn2pcu(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
877 integer sgsn_idx := 0, integer pcu_idx := 0) runs on GlobalTest_CT {
878 var PDU_BSSGP rx;
879 timer T := 1.0;
880
881 G_SGSN[sgsn_idx].send(tx);
882 T.start;
883 alt {
884 [] G_PCU[pcu_idx].receive(exp_rx) {
885 setverdict(pass);
886 }
887 [] G_PCU[pcu_idx].receive(PDU_BSSGP:?) -> value rx {
888 setverdict(fail, "Unexpected BSSGP on PCU side: ", rx);
889 mtc.stop;
890 }
891 [] T.timeout {
Harald Weltedc805c02020-12-11 10:59:17 +0100892 setverdict(fail, "Timeout waiting for BSSGP on PCU side: ", exp_rx);
Harald Welte3807ed12020-11-24 19:05:22 +0100893 mtc.stop;
894 }
895 }
896}
897
898
Daniel Willmann423d8f42020-09-08 18:58:22 +0200899/* TODO:
900 * Detach without Attach
901 * SM procedures without attach / RAU
902 * ATTACH / RAU
903 ** with / without authentication
904 ** with / without P-TMSI allocation
905 * re-transmissions of LLC frames
906 * PDP Context activation
907 ** with different GGSN config in SGSN VTY
908 ** with different PDP context type (v4/v6/v46)
909 ** timeout from GGSN
910 ** multiple / secondary PDP context
911 */
912
913private function f_TC_BVC_bringup(charstring id) runs on BSSGP_ConnHdlr {
914 f_sleep(5.0);
915 setverdict(pass);
916}
917
918testcase TC_BVC_bringup() runs on test_CT {
Daniel Willmann423d8f42020-09-08 18:58:22 +0200919 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +0100920 f_start_handlers(refers(f_TC_BVC_bringup), testcasename(), 51);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200921 f_cleanup();
922}
923
924friend function f_bssgp_suspend(integer ran_idx := 0) runs on BSSGP_ConnHdlr return OCT1 {
Harald Welte16357a92020-11-17 18:20:00 +0100925 var BssgpBvcConfig bvcc := g_pars.pcu[ran_idx].cfg.bvc[0];
Daniel Willmann423d8f42020-09-08 18:58:22 +0200926 timer T := 5.0;
927 var PDU_BSSGP rx_pdu;
Harald Welte16357a92020-11-17 18:20:00 +0100928 PCU_SIG[ran_idx].send(ts_BSSGP_SUSPEND(g_pars.tlli, bvcc.cell_id.ra_id));
Daniel Willmann423d8f42020-09-08 18:58:22 +0200929 T.start;
930 alt {
Harald Welte16357a92020-11-17 18:20:00 +0100931 [] 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 +0200932 return rx_pdu.pDU_BSSGP_SUSPEND_ACK.suspend_Reference_Number.suspend_Reference_Number_value;
933 }
Harald Welte16357a92020-11-17 18:20:00 +0100934 [] 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 +0200935 setverdict(fail, "SUSPEND-NACK in response to SUSPEND for TLLI ", g_pars.tlli);
936 mtc.stop;
937 }
938 [] T.timeout {
939 setverdict(fail, "No SUSPEND-ACK in response to SUSPEND for TLLI ", g_pars.tlli);
940 mtc.stop;
941 }
942 }
943 return '00'O;
944}
945
946friend function f_bssgp_resume(OCT1 susp_ref, integer ran_idx := 0) runs on BSSGP_ConnHdlr {
Harald Welte16357a92020-11-17 18:20:00 +0100947 var BssgpBvcConfig bvcc := g_pars.pcu[ran_idx].cfg.bvc[0];
Daniel Willmann423d8f42020-09-08 18:58:22 +0200948 timer T := 5.0;
Harald Welte16357a92020-11-17 18:20:00 +0100949 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 +0200950 T.start;
951 alt {
Harald Welte16357a92020-11-17 18:20:00 +0100952 [] PCU_SIG[ran_idx].receive(tr_BSSGP_RESUME_ACK(g_pars.tlli, bvcc.cell_id.ra_id));
953 [] PCU_SIG[ran_idx].receive(tr_BSSGP_RESUME_NACK(g_pars.tlli, bvcc.cell_id.ra_id, ?)) {
Daniel Willmann423d8f42020-09-08 18:58:22 +0200954 setverdict(fail, "RESUME-NACK in response to RESUME for TLLI ", g_pars.tlli);
955 mtc.stop;
956 }
957 [] T.timeout {
958 setverdict(fail, "No RESUME-ACK in response to SUSPEND for TLLI ", g_pars.tlli);
959 mtc.stop;
960 }
961 }
962}
963
964
Harald Welte92686012020-11-15 21:45:49 +0100965/* send uplink-unitdata of a variety of different sizes; expect it to show up on SGSN */
966private function f_TC_ul_unitdata(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte16357a92020-11-17 18:20:00 +0100967 var integer ran_idx := 0;
968 var BssgpBvcConfig bvcc := g_pars.pcu[ran_idx].cfg.bvc[0];
Harald Welte92686012020-11-15 21:45:49 +0100969 var integer i;
970
Harald Welte0d5fceb2020-11-29 16:04:07 +0100971 for (i := 0; i < max_fr_info_size-4; i := i+4) {
Harald Welte92686012020-11-15 21:45:49 +0100972 var octetstring payload := f_rnd_octstring(i);
Harald Welte16357a92020-11-17 18:20:00 +0100973 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 +0100974 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
Harald Welte16357a92020-11-17 18:20:00 +0100975 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 +0100976
Harald Welte0d5fceb2020-11-29 16:04:07 +0100977 log("UL-UNITDATA(payload_size=", i);
Harald Welte22ef5d92020-11-16 13:35:14 +0100978 f_pcu2sgsn(pdu_tx, pdu_rx);
Harald Welte92686012020-11-15 21:45:49 +0100979 }
980 setverdict(pass);
981}
982
983testcase TC_ul_unitdata() runs on test_CT
984{
Harald Welte92686012020-11-15 21:45:49 +0100985 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +0100986 f_start_handlers(refers(f_TC_ul_unitdata), testcasename(), 1);
Harald Welte92686012020-11-15 21:45:49 +0100987 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
Harald Welte92686012020-11-15 21:45:49 +0100988 f_cleanup();
989}
990
Harald Welte78d8db92020-11-15 23:27:27 +0100991/* send downlink-unitdata of a variety of different sizes; expect it to show up on PCU */
992private function f_TC_dl_unitdata(charstring id) runs on BSSGP_ConnHdlr {
993 var integer i;
994
Harald Welte0d5fceb2020-11-29 16:04:07 +0100995 for (i := 0; i < max_fr_info_size-4; i := i+4) {
Harald Welte78d8db92020-11-15 23:27:27 +0100996 var octetstring payload := f_rnd_octstring(i);
997 var template (value) PDU_BSSGP pdu_tx :=
998 ts_BSSGP_DL_UD(g_pars.tlli, payload, omit, ts_BSSGP_IMSI(g_pars.imsi));
999 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1000 var template (present) PDU_BSSGP pdu_rx :=
1001 tr_BSSGP_DL_UD(g_pars.tlli, payload, tr_BSSGP_IMSI(g_pars.imsi));
1002
Harald Welte0d5fceb2020-11-29 16:04:07 +01001003 log("DL-UNITDATA(payload_size=", i);
Harald Welte22ef5d92020-11-16 13:35:14 +01001004 f_sgsn2pcu(pdu_tx, pdu_rx);
Harald Welte78d8db92020-11-15 23:27:27 +01001005 }
1006 setverdict(pass);
1007}
1008
1009testcase TC_dl_unitdata() runs on test_CT
1010{
Harald Welte78d8db92020-11-15 23:27:27 +01001011 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001012 f_start_handlers(refers(f_TC_dl_unitdata), testcasename(), 2);
Harald Welte78d8db92020-11-15 23:27:27 +01001013 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
Harald Welte78d8db92020-11-15 23:27:27 +01001014 f_cleanup();
1015}
Harald Welte92686012020-11-15 21:45:49 +01001016
Harald Welte6dc2ac42020-11-16 09:16:17 +01001017private function f_TC_ra_capability(charstring id) runs on BSSGP_ConnHdlr {
1018 var integer i;
1019
1020 for (i := 0; i < 10; i := i+1) {
1021 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RA_CAP(g_pars.tlli, { ts_RaCapRec_BSSGP });
1022 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1023 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RA_CAP(g_pars.tlli, { tr_RaCapRec_BSSGP })
1024
Harald Welte22ef5d92020-11-16 13:35:14 +01001025 f_sgsn2pcu(pdu_tx, pdu_rx);
Harald Welte6dc2ac42020-11-16 09:16:17 +01001026 }
1027 setverdict(pass);
1028}
1029testcase TC_ra_capability() runs on test_CT
1030{
Harald Welte6dc2ac42020-11-16 09:16:17 +01001031 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001032 f_start_handlers(refers(f_TC_ra_capability), testcasename(), 3);
Harald Welte6dc2ac42020-11-16 09:16:17 +01001033 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
Harald Welte6dc2ac42020-11-16 09:16:17 +01001034 f_cleanup();
1035}
1036
Daniel Willmannace3ece2020-11-16 19:53:26 +01001037private function f_TC_ra_capability_upd(charstring id) runs on BSSGP_ConnHdlr {
1038 var integer i;
1039 var OCT1 tag;
1040 for (i := 0; i < 10; i := i+1) {
1041 tag := int2oct(23 + i, 1);
1042 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RA_CAP_UPD(g_pars.tlli, tag);
1043 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1044 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RA_CAP_UPD(g_pars.tlli, tag)
1045
1046 f_pcu2sgsn(pdu_tx, pdu_rx);
1047
1048 pdu_tx := ts_BSSGP_RA_CAP_UPD_ACK(g_pars.tlli, tag, '42'O);
1049 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1050 pdu_rx := tr_BSSGP_RA_CAP_UPD_ACK(g_pars.tlli, tag, '42'O)
1051
1052 f_sgsn2pcu(pdu_tx, pdu_rx);
1053 }
1054 setverdict(pass);
1055}
1056testcase TC_ra_capability_upd() runs on test_CT
1057{
Daniel Willmannace3ece2020-11-16 19:53:26 +01001058 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001059 f_start_handlers(refers(f_TC_ra_capability_upd), testcasename(), 4);
Daniel Willmannace3ece2020-11-16 19:53:26 +01001060 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
Daniel Willmannace3ece2020-11-16 19:53:26 +01001061 f_cleanup();
1062}
1063
Daniel Willmann165d6612020-11-19 14:27:29 +01001064private function f_TC_radio_status(charstring id) runs on BSSGP_ConnHdlr {
1065 var integer i;
1066 var BssgpRadioCause cause := BSSGP_RADIO_CAUSE_CONTACT_LOST;
1067 for (i := 0; i < 10; i := i+1) {
1068 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RADIO_STATUS(g_pars.tlli, cause);
1069 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1070 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RADIO_STATUS(g_pars.tlli, cause)
1071
1072 f_pcu2sgsn(pdu_tx, pdu_rx);
1073 }
1074 setverdict(pass);
1075}
1076testcase TC_radio_status() runs on test_CT
1077{
Daniel Willmann165d6612020-11-19 14:27:29 +01001078 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001079 f_start_handlers(refers(f_TC_radio_status), testcasename(), 5);
Daniel Willmann165d6612020-11-19 14:27:29 +01001080 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
Daniel Willmann165d6612020-11-19 14:27:29 +01001081 f_cleanup();
1082}
1083
Harald Welte99ed5072021-01-15 20:38:58 +01001084private function f_suspend_one(integer sgsn_idx, integer nri_idx, integer pcu_idx, integer bvc_idx,
1085 integer suffix)
Harald Welte00963752021-01-15 20:33:11 +01001086runs on GlobalTest_CT
1087{
1088 var RoutingAreaIdentification ra_id := g_pcu[pcu_idx].cfg.bvc[bvc_idx].cell_id.ra_id;
Harald Welte99ed5072021-01-15 20:38:58 +01001089 var OCT4 p_tmsi := f_gen_tmsi(suffix, nri_v := mp_sgsn_nri[sgsn_idx][nri_idx],
1090 nri_bitlen := mp_nri_bitlength);
1091 var OCT4 tlli := f_gprs_tlli_from_tmsi(p_tmsi, TLLI_LOCAL);
Harald Welte00963752021-01-15 20:33:11 +01001092 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_SUSPEND(tlli, ra_id);
1093 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1094 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_SUSPEND(tlli, ra_id);
1095 f_global_pcu2sgsn(pdu_tx, pdu_rx, pcu_idx, sgsn_idx);
1096
1097 pdu_tx := ts_BSSGP_SUSPEND_ACK(tlli, ra_id, int2oct(suffix, 1));
1098 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1099 pdu_rx := tr_BSSGP_SUSPEND_ACK(tlli, ra_id, int2oct(suffix, 1));
1100 f_global_sgsn2pcu(pdu_tx, pdu_rx, sgsn_idx, pcu_idx);
1101
1102 pdu_tx := ts_BSSGP_SUSPEND(tlli, ra_id);
1103 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1104 pdu_rx := tr_BSSGP_SUSPEND(tlli, ra_id);
1105 f_global_pcu2sgsn(pdu_tx, pdu_rx, pcu_idx, sgsn_idx);
1106
1107 /* These messages are simple passed through so just also test sending NACK */
1108 pdu_tx := ts_BSSGP_SUSPEND_NACK(tlli, ra_id, BSSGP_CAUSE_UNKNOWN_MS);
1109 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1110 pdu_rx := tr_BSSGP_SUSPEND_NACK(tlli, ra_id, BSSGP_CAUSE_UNKNOWN_MS);
1111 f_global_sgsn2pcu(pdu_tx, pdu_rx, sgsn_idx, pcu_idx);
1112}
1113
Harald Weltec5c33732021-01-15 21:04:35 +01001114private function f_TC_suspend(integer sgsn_idx, integer nri_idx, integer pcu_idx, integer bvc_idx)
1115runs on GlobalTest_CT {
Daniel Willmannfa67f492020-11-19 15:48:05 +01001116 var integer i;
Daniel Willmann165d6612020-11-19 14:27:29 +01001117
Daniel Willmannfa67f492020-11-19 15:48:05 +01001118 for (i := 0; i < 10; i := i+1) {
Harald Weltec5c33732021-01-15 21:04:35 +01001119 f_suspend_one(sgsn_idx, nri_idx, pcu_idx, bvc_idx, suffix := i);
Daniel Willmannfa67f492020-11-19 15:48:05 +01001120 }
1121 setverdict(pass);
1122}
Harald Welte3807ed12020-11-24 19:05:22 +01001123testcase TC_suspend() runs on GlobalTest_CT
Daniel Willmannfa67f492020-11-19 15:48:05 +01001124{
Harald Weltec5c33732021-01-15 21:04:35 +01001125 var integer sgsn_idx, nri_idx;
Daniel Willmannfa67f492020-11-19 15:48:05 +01001126 f_init();
Harald Welte3807ed12020-11-24 19:05:22 +01001127 f_global_init();
Harald Weltec5c33732021-01-15 21:04:35 +01001128 for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx+1) {
1129 for (nri_idx := 0; nri_idx < lengthof(mp_sgsn_nri[sgsn_idx]); nri_idx := nri_idx+1) {
1130 f_TC_suspend(sgsn_idx, nri_idx, pcu_idx:=0, bvc_idx:=0);
1131 }
1132 }
Daniel Willmannfa67f492020-11-19 15:48:05 +01001133 f_cleanup();
1134}
Harald Welte6dc2ac42020-11-16 09:16:17 +01001135
Harald Welte99ed5072021-01-15 20:38:58 +01001136private function f_resume_one(integer sgsn_idx, integer nri_idx, integer pcu_idx, integer bvc_idx,
1137 integer suffix)
Harald Welte00963752021-01-15 20:33:11 +01001138runs on GlobalTest_CT
1139{
1140 var RoutingAreaIdentification ra_id := g_pcu[pcu_idx].cfg.bvc[bvc_idx].cell_id.ra_id;
Harald Welte99ed5072021-01-15 20:38:58 +01001141 var OCT4 p_tmsi := f_gen_tmsi(suffix, nri_v := mp_sgsn_nri[sgsn_idx][nri_idx],
1142 nri_bitlen := mp_nri_bitlength);
1143 var OCT4 tlli := f_gprs_tlli_from_tmsi(p_tmsi, TLLI_LOCAL);
Harald Welte00963752021-01-15 20:33:11 +01001144 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RESUME(tlli, ra_id, int2oct(suffix, 1));
1145 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1146 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RESUME(tlli, ra_id, int2oct(suffix, 1));
1147 f_global_pcu2sgsn(pdu_tx, pdu_rx, pcu_idx, sgsn_idx);
1148
1149 pdu_tx := ts_BSSGP_RESUME_ACK(tlli, ra_id);
1150 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1151 pdu_rx := tr_BSSGP_RESUME_ACK(tlli, ra_id);
1152 f_global_sgsn2pcu(pdu_tx, pdu_rx, sgsn_idx, pcu_idx);
1153
1154 pdu_tx := ts_BSSGP_RESUME(tlli, ra_id, int2oct(suffix, 1));
1155 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1156 pdu_rx := tr_BSSGP_RESUME(tlli, ra_id, int2oct(suffix, 1));
1157 f_global_pcu2sgsn(pdu_tx, pdu_rx, pcu_idx, sgsn_idx);
1158
1159 /* These messages are simple passed through so just also test sending NACK */
1160 pdu_tx := ts_BSSGP_RESUME_NACK(tlli, ra_id, BSSGP_CAUSE_UNKNOWN_MS);
1161 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
1162 pdu_rx := tr_BSSGP_RESUME_NACK(tlli, ra_id, BSSGP_CAUSE_UNKNOWN_MS);
1163 f_global_sgsn2pcu(pdu_tx, pdu_rx, sgsn_idx, pcu_idx);
1164}
1165
Harald Weltec5c33732021-01-15 21:04:35 +01001166private function f_TC_resume(integer sgsn_idx, integer nri_idx, integer pcu_idx, integer bvc_idx)
1167runs on GlobalTest_CT {
Daniel Willmann087a33d2020-11-19 15:58:43 +01001168 var integer i;
1169
Daniel Willmann087a33d2020-11-19 15:58:43 +01001170 for (i := 0; i < 10; i := i+1) {
Harald Weltec5c33732021-01-15 21:04:35 +01001171 f_resume_one(sgsn_idx, nri_idx, pcu_idx, bvc_idx, suffix := i);
Daniel Willmann087a33d2020-11-19 15:58:43 +01001172 }
1173 setverdict(pass);
1174}
Harald Welte3807ed12020-11-24 19:05:22 +01001175testcase TC_resume() runs on GlobalTest_CT
Daniel Willmann087a33d2020-11-19 15:58:43 +01001176{
Harald Weltec5c33732021-01-15 21:04:35 +01001177 var integer sgsn_idx, nri_idx;
Daniel Willmann087a33d2020-11-19 15:58:43 +01001178 f_init();
Harald Welte3807ed12020-11-24 19:05:22 +01001179 f_global_init();
Harald Weltec5c33732021-01-15 21:04:35 +01001180 for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx+1) {
1181 for (nri_idx := 0; nri_idx < lengthof(mp_sgsn_nri[sgsn_idx]); nri_idx := nri_idx+1) {
1182 f_TC_resume(sgsn_idx, nri_idx, pcu_idx:=0, bvc_idx:=0);
1183 }
1184 }
Daniel Willmann087a33d2020-11-19 15:58:43 +01001185 f_cleanup();
1186}
1187
Harald Weltef8ef0282020-11-18 12:16:59 +01001188/* test the load-sharing between multiple NS-VC on the BSS side */
1189private function f_TC_dl_ud_unidir(charstring id) runs on BSSGP_ConnHdlr {
1190 var integer i;
1191
1192 for (i := 0; i < 10; i := i+1) {
1193 var octetstring payload := f_rnd_octstring(i);
1194 var template (value) PDU_BSSGP pdu_tx :=
1195 ts_BSSGP_DL_UD(g_pars.tlli, payload, omit, ts_BSSGP_IMSI(g_pars.imsi));
Harald Welte09a1ce42021-01-16 11:18:38 +01001196 SGSN_PTP[g_pars.sgsn_idx].send(pdu_tx);
Harald Weltef8ef0282020-11-18 12:16:59 +01001197 }
1198 setverdict(pass);
1199}
Harald Welte09a1ce42021-01-16 11:18:38 +01001200
1201private function f_TC_load_sharing_dl(integer sgsn_idx) runs on test_CT_NS
Harald Weltef8ef0282020-11-18 12:16:59 +01001202{
1203 const integer num_ue := 10;
1204 var BSSGP_ConnHdlr vc_conn[num_ue];
Harald Weltef8ef0282020-11-18 12:16:59 +01001205 /* all BVC are now fully brought up. We disconnect BSSGP from NS on the BSS
1206 * side so we get the raw NsUnitdataIndication and hence observe different
1207 * NSVCI */
1208 disconnect(g_pcu[0].vc_NS:NS_SP, g_pcu[0].vc_BSSGP:BSCP);
1209 connect(g_pcu[0].vc_NS:NS_SP, self:NS);
1210
1211 /* there may still be some NS-VCs coming up? After all, the BVC-RESET succeeds after the first
1212 * of the NS-VC is ALIVE/UNBLOCKED */
1213 f_sleep(3.0);
1214
1215 /* start parallel components generating DL-UNITDATA from the SGSN side */
1216 for (var integer i:= 0; i < num_ue; i := i+1) {
Harald Welte2ecbca82021-01-16 11:23:09 +01001217 vc_conn[i] := f_start_handler(refers(f_TC_dl_ud_unidir), testcasename(),
Harald Welte09a1ce42021-01-16 11:18:38 +01001218 5+i, 30.0, sgsn_idx);
Harald Weltef8ef0282020-11-18 12:16:59 +01001219 }
1220
1221 /* now start counting all the messages that were queued before */
1222 /* TODO: We have a hard-coded assumption of 4 NS-VC in one NSE/NS-VCG here! */
1223 var ro_integer rx_count := { 0, 0, 0, 0 };
1224 timer T := 2.0;
1225 T.start;
1226 alt {
1227 [] as_NsUdiCount(0, rx_count);
1228 [] as_NsUdiCount(1, rx_count);
1229 [] as_NsUdiCount(2, rx_count);
1230 [] as_NsUdiCount(3, rx_count);
1231 [] NS.receive(NsUnitdataIndication:{0,?,?,*,*}) { repeat; } /* signaling BVC */
1232 [] NS.receive(NsStatusIndication:?) { repeat; }
1233 [] NS.receive {
1234 setverdict(fail, "Rx unexpected NS");
1235 mtc.stop;
1236 }
1237 [] T.timeout {
1238 }
1239 }
1240 for (var integer i := 0; i < lengthof(rx_count); i := i+1) {
1241 log("Rx on NSVCI ", mp_nsconfig_pcu[0].nsvc[i].nsvci, ": ", rx_count[i]);
1242 if (rx_count[i] == 0) {
1243 setverdict(fail, "Data not shared over all NSVC");
1244 }
1245 }
Harald Welte09a1ce42021-01-16 11:18:38 +01001246}
1247
1248testcase TC_load_sharing_dl() runs on test_CT_NS
1249{
1250 var integer sgsn_idx, nri_idx;
1251 f_init();
1252 for (sgsn_idx:=0; sgsn_idx < NUM_SGSN; sgsn_idx:=sgsn_idx+1) {
1253 f_TC_load_sharing_dl(sgsn_idx);
1254 }
Harald Weltef8ef0282020-11-18 12:16:59 +01001255 setverdict(pass);
1256}
1257private altstep as_NsUdiCount(integer nsvc_idx, inout ro_integer roi) runs on test_CT_NS {
1258 var NsUnitdataIndication udi;
1259 var BssgpBvcConfig bvcc := g_pcu[0].cfg.bvc[0];
1260 [] NS.receive(NsUnitdataIndication:{bvcc.bvci, g_pcu[0].cfg.nsei, mp_nsconfig_pcu[0].nsvc[nsvc_idx].nsvci, *, *}) -> value udi {
1261 roi[nsvc_idx] := roi[nsvc_idx] + 1;
1262 repeat;
1263 }
1264}
1265type component test_CT_NS extends test_CT {
1266 port NS_PT NS;
1267};
1268
1269
Harald Welte0e188242020-11-22 21:46:48 +01001270/***********************************************************************
1271 * PAGING PS procedure
1272 ***********************************************************************/
1273
1274private function f_send_paging_ps(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
1275 boolean use_sig := false)
1276runs on BSSGP_ConnHdlr return template (present) PDU_BSSGP {
1277 var template (value) PDU_BSSGP pdu_tx;
1278 var template (present) PDU_BSSGP pdu_rx;
1279 /* we always specify '0' as BVCI in the templates below, as we override it with
1280 * 'p4' later anyway */
1281 pdu_rx := tr_BSSGP_PS_PAGING(0);
1282 pdu_rx.pDU_BSSGP_PAGING_PS.iMSI := tr_BSSGP_IMSI(g_pars.imsi);
1283 if (ispresent(g_pars.p_tmsi)) {
1284 pdu_tx := ts_BSSGP_PS_PAGING_PTMSI(0, g_pars.imsi, oct2int(g_pars.p_tmsi));
1285 pdu_rx.pDU_BSSGP_PAGING_PS.pTMSI := tr_BSSGP_TMSI(oct2int(g_pars.p_tmsi));
1286 } else {
1287 pdu_tx := ts_BSSGP_PS_PAGING_IMSI(0, g_pars.imsi);
1288 pdu_rx.pDU_BSSGP_PAGING_PS.pTMSI := omit;
1289 }
1290 pdu_tx.pDU_BSSGP_PAGING_PS.paging_Field4 := p4;
1291 pdu_rx.pDU_BSSGP_PAGING_PS.paging_Field4 := p4;
1292 if (use_sig == false) {
Harald Welte158becf2020-12-09 12:32:32 +01001293 SGSN_PTP[sgsn_idx].send(pdu_tx);
Harald Welte0e188242020-11-22 21:46:48 +01001294 } else {
1295 SGSN_SIG[sgsn_idx].send(pdu_tx);
1296 }
1297 return pdu_rx;
1298}
1299
1300/* send paging defined by 'p4' on given SGSN-side index (ptp or signaling) and expect one paging to arrive on
1301 * specified PCU index */
1302private function f_send_paging_ps_exp_one_bss(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
1303 boolean use_sig := false,integer pcu_idx := 0)
1304runs on BSSGP_ConnHdlr {
1305 var template (present) PDU_BSSGP exp_rx;
Daniel Willmann1a859712020-12-04 00:59:45 +01001306 var boolean test_done := false;
Harald Welte0e188242020-11-22 21:46:48 +01001307 /* doesn't really make sense: Sending to a single BVCI means the message ends up
1308 * at that BVC (cell) only, and paging all over the BSS area is not possible */
1309 exp_rx := f_send_paging_ps(p4, sgsn_idx, use_sig);
1310 /* Expect paging to propagate to the one BSS addressed by the BVCI only */
1311 timer T := 2.0;
1312 T.start;
1313 alt {
Harald Welte158becf2020-12-09 12:32:32 +01001314 [not use_sig and not test_done] PCU_PTP[pcu_idx].receive(exp_rx) {
Harald Welte0e188242020-11-22 21:46:48 +01001315 setverdict(pass);
Daniel Willmann1a859712020-12-04 00:59:45 +01001316 test_done := true;
Harald Welte0e188242020-11-22 21:46:48 +01001317 repeat;
1318 }
1319 [not use_sig] PCU_SIG[pcu_idx].receive(exp_rx) {
1320 setverdict(fail, "Received paging on SIGNALING BVC, expected PTP BVC");
1321 }
Daniel Willmann1a859712020-12-04 00:59:45 +01001322 [use_sig and not test_done] PCU_SIG[pcu_idx].receive(exp_rx) {
Harald Welte0e188242020-11-22 21:46:48 +01001323 setverdict(pass);
Daniel Willmann1a859712020-12-04 00:59:45 +01001324 test_done := true;
Harald Welte0e188242020-11-22 21:46:48 +01001325 repeat;
1326 }
Harald Welte158becf2020-12-09 12:32:32 +01001327 [use_sig] PCU_PTP[pcu_idx].receive(exp_rx) {
Harald Welte0e188242020-11-22 21:46:48 +01001328 setverdict(fail, "Received paging on PTP BVC, expected SIGNALING BVC");
1329 }
Harald Welte158becf2020-12-09 12:32:32 +01001330 [] any from PCU_PTP.receive(exp_rx) {
Harald Welte0e188242020-11-22 21:46:48 +01001331 setverdict(fail, "Paging received on unexpected BVC");
1332 }
1333 [] any from PCU_SIG.receive(exp_rx) {
1334 setverdict(fail, "Paging received on unexpected BVC");
1335 }
Harald Welte158becf2020-12-09 12:32:32 +01001336 [] any from PCU_PTP.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}) {
Harald Welte0e188242020-11-22 21:46:48 +01001337 setverdict(fail, "Different Paging than expected received PTP BVC");
1338 }
1339 [] any from PCU_SIG.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}) {
1340 setverdict(fail, "Different Paging than expected on SIGNALING BVC");
1341 }
Daniel Willmann1a859712020-12-04 00:59:45 +01001342 [not test_done] T.timeout {
1343 setverdict(fail, "Timeout waiting for paging");
1344 }
1345 [test_done] T.timeout;
Harald Welte0e188242020-11-22 21:46:48 +01001346 }
1347}
1348
Harald Welte7462a592020-11-23 22:07:07 +01001349/* send a PS-PAGING but don't expect it to show up on any PTP or SIG BVC */
1350private function f_send_paging_ps_exp_no_bss(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
1351 boolean use_sig := false)
1352runs on BSSGP_ConnHdlr {
1353 var template (present) PDU_BSSGP exp_rx;
1354 exp_rx := f_send_paging_ps(p4, sgsn_idx, use_sig);
1355 /* Expect paging to propagate to no BSS */
1356 timer T := 2.0;
1357 T.start;
1358 alt {
Harald Welte158becf2020-12-09 12:32:32 +01001359 [] any from PCU_PTP.receive(exp_rx) {
Harald Welte7462a592020-11-23 22:07:07 +01001360 setverdict(fail, "Paging received on unexpected BVC");
1361 }
1362 [] any from PCU_SIG.receive(exp_rx) {
1363 setverdict(fail, "Paging received on unexpected BVC");
1364 }
Harald Welte158becf2020-12-09 12:32:32 +01001365 [] any from PCU_PTP.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}) {
Harald Welte7462a592020-11-23 22:07:07 +01001366 setverdict(fail, "Different Paging received on PTP BVC");
1367 }
1368 [] any from PCU_SIG.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}) {
1369 setverdict(fail, "Different Paging received on SIGNALING BVC");
1370 }
1371 [] T.timeout {
1372 setverdict(pass);
1373 }
1374 }
1375}
1376
Harald Welte0e188242020-11-22 21:46:48 +01001377private function f_TC_paging_ps_ptp_bss(charstring id) runs on BSSGP_ConnHdlr
1378{
1379 /* doesn't really make sense: Sending to a single BVCI means the message ends up
1380 * at that BVC (cell) only, and paging all over the BSS area is not possible */
1381 f_send_paging_ps_exp_one_bss(ts_BssgpP4BssArea, 0, false, 0);
1382}
1383testcase TC_paging_ps_ptp_bss() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001384 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001385 f_start_handlers(refers(f_TC_paging_ps_ptp_bss), testcasename(), 9);
Harald Welte0e188242020-11-22 21:46:48 +01001386 f_cleanup();
1387}
1388
1389/* PS-PAGING on PTP-BVC for Location Area */
1390private function f_TC_paging_ps_ptp_lac(charstring id) runs on BSSGP_ConnHdlr
1391{
1392 var template (present) PDU_BSSGP exp_rx;
1393 /* doesn't really make sense: Sending to a single BVCI means the message ends up
1394 * at that BVC (cell) only, and paging all over the BSS area is not possible */
1395 f_send_paging_ps_exp_one_bss(ts_BssgpP4LAC(pcu_bvc_cfg[0].cell_id.ra_id.lai), 0, false, 0);
1396}
1397testcase TC_paging_ps_ptp_lac() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001398 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001399 f_start_handlers(refers(f_TC_paging_ps_ptp_lac), testcasename(), 10);
Harald Welte0e188242020-11-22 21:46:48 +01001400 f_cleanup();
1401}
1402
Harald Welte7462a592020-11-23 22:07:07 +01001403/* PS-PAGING on PTP-BVC for unknown Location Area */
1404private function f_TC_paging_ps_ptp_lac_unknown(charstring id) runs on BSSGP_ConnHdlr
1405{
1406 var GSM_Types.LocationAreaIdentification unknown_la := {
1407 mcc_mnc := '567F99'H,
1408 lac := 33333
1409 };
1410 /* as it's sent on the PTP BVC, we expect it to pass even for unknown LAC */
1411 f_send_paging_ps_exp_one_bss(ts_BssgpP4LAC(unknown_la), 0, false, 0);
1412}
1413testcase TC_paging_ps_ptp_lac_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01001414 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001415 f_start_handlers(refers(f_TC_paging_ps_ptp_lac_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01001416 f_cleanup();
1417}
1418
Harald Welte0e188242020-11-22 21:46:48 +01001419/* PS-PAGING on PTP-BVC for Routeing Area */
1420private function f_TC_paging_ps_ptp_rac(charstring id) runs on BSSGP_ConnHdlr
1421{
1422 /* doesn't really make sense: Sending to a single BVCI means the message ends up
1423 * at that BVC (cell) only, and paging all over the BSS area is not possible */
1424 f_send_paging_ps_exp_one_bss(ts_BssgpP4RAC(pcu_bvc_cfg[0].cell_id.ra_id), 0, false, 0);
1425}
1426testcase TC_paging_ps_ptp_rac() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001427 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001428 f_start_handlers(refers(f_TC_paging_ps_ptp_rac), testcasename(), 11);
Harald Welte0e188242020-11-22 21:46:48 +01001429 f_cleanup();
1430}
1431
Harald Welte7462a592020-11-23 22:07:07 +01001432/* PS-PAGING on PTP-BVC for unknown Routeing Area */
1433private function f_TC_paging_ps_ptp_rac_unknown(charstring id) runs on BSSGP_ConnHdlr
1434{
1435 var RoutingAreaIdentification unknown_ra := {
1436 lai := {
1437 mcc_mnc := '567F99'H,
1438 lac := 33333
1439 },
1440 rac := 254
1441 };
1442 /* as it's sent on the PTP BVC, we expect it to pass even for unknown RAC */
1443 f_send_paging_ps_exp_one_bss(ts_BssgpP4RAC(unknown_ra), 0, false, 0);
1444}
1445testcase TC_paging_ps_ptp_rac_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01001446 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001447 f_start_handlers(refers(f_TC_paging_ps_ptp_rac_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01001448 f_cleanup();
1449}
1450
Harald Welte0e188242020-11-22 21:46:48 +01001451/* PS-PAGING on PTP-BVC for BVCI (one cell) */
1452private function f_TC_paging_ps_ptp_bvci(charstring id) runs on BSSGP_ConnHdlr
1453{
1454 /* this should be the normal case for MS in READY MM state after a lower layer failure */
1455 f_send_paging_ps_exp_one_bss(ts_BssgpP4Bvci(pcu_bvc_cfg[0].bvci), 0, false, 0);
1456}
1457testcase TC_paging_ps_ptp_bvci() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001458 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001459 f_start_handlers(refers(f_TC_paging_ps_ptp_bvci), testcasename(), 12);
Harald Welte0e188242020-11-22 21:46:48 +01001460 f_cleanup();
1461}
1462
Harald Welteb5a04aa2021-01-16 13:04:40 +01001463
1464/* PS-PAGING on PTP-BVC for BVCI (one cell) using IMSI only (no P-TMSI allocated) */
1465testcase TC_paging_ps_ptp_bvci_imsi() runs on test_CT {
1466 f_init();
1467 f_start_handlers(refers(f_TC_paging_ps_ptp_bvci), testcasename(), 12, have_ptmsi:=false);
1468 f_cleanup();
1469}
1470
Harald Weltecf200072021-01-16 15:20:46 +01001471/* Rejected PS-PAGING on PTP-BVC for BVCI (one cell) */
1472testcase TC_paging_ps_reject_ptp_bvci() runs on test_CT {
1473 f_init();
1474 f_start_handlers(refers(f_TC_paging_ps_reject_ptp_bvci), testcasename(), 16);
1475 f_cleanup();
1476}
1477
1478/* Rejected PS-PAGING on PTP-BVC for BVCI (one cell) using IMSI only (no P-TMSI allocated) */
1479private function f_TC_paging_ps_reject_ptp_bvci(charstring id) runs on BSSGP_ConnHdlr
1480{
1481 /* first send the PS-PAGING from SGSN -> PCU */
1482 f_send_paging_ps_exp_one_bss(ts_BssgpP4Bvci(pcu_bvc_cfg[0].bvci), 0, false, 0);
1483 /* then simulate the PS-PAGING-REJECT from the PCU */
1484 f_send_paging_ps_rej(use_sig:=false);
1485}
1486testcase TC_paging_ps_reject_ptp_bvci_imsi() runs on test_CT {
1487 f_init();
1488 f_start_handlers(refers(f_TC_paging_ps_reject_ptp_bvci), testcasename(), 16, have_ptmsi:=false);
1489 f_cleanup();
1490}
Harald Welteb5a04aa2021-01-16 13:04:40 +01001491
Harald Welte7462a592020-11-23 22:07:07 +01001492/* PS-PAGING on PTP-BVC for unknown BVCI */
1493private function f_TC_paging_ps_ptp_bvci_unknown(charstring id) runs on BSSGP_ConnHdlr
1494{
1495 /* as it's sent on the PTP BVC, we expect it to pass even for unknown BVCI */
1496 f_send_paging_ps_exp_one_bss(ts_BssgpP4Bvci(33333), 0, false, 0);
1497}
1498testcase TC_paging_ps_ptp_bvci_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01001499 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001500 f_start_handlers(refers(f_TC_paging_ps_ptp_bvci_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01001501 f_cleanup();
1502}
1503
Harald Welte7595d562021-01-16 19:09:20 +01001504/* DUMMY PAGING PS on PTP BVC */
1505private function f_TC_dummy_paging_ps_ptp(charstring id) runs on BSSGP_ConnHdlr
1506{
1507 f_sgsn2pcu(ts_BSSGP_DUMMY_PAGING_PS(g_pars.imsi, omit),
1508 tr_BSSGP_DUMMY_PAGING_PS(g_pars.imsi, omit), use_sig := false);
1509 f_pcu2sgsn(ts_BSSGP_DUMMY_PAGING_PS_RESP(g_pars.imsi, 1, 5),
1510 tr_BSSGP_DUMMY_PAGING_PS_RESP(g_pars.imsi, 1, 5), use_sig := false)
1511}
1512testcase TC_dummy_paging_ps_ptp() runs on test_CT {
1513 f_init();
1514 f_start_handlers(refers(f_TC_dummy_paging_ps_ptp), testcasename(), 11);
1515 f_cleanup();
1516}
1517
Harald Welte0e188242020-11-22 21:46:48 +01001518/* altstep for expecting BSSGP PDU on signaling BVC of given pcu_idx + storing in 'roi' */
1519private altstep as_paging_sig_pcu(integer pcu_idx, template (present) PDU_BSSGP exp_rx, inout ro_integer roi)
1520runs on BSSGP_ConnHdlr {
1521[] PCU_SIG[pcu_idx].receive(exp_rx) {
1522 if (ro_integer_contains(roi, pcu_idx)) {
1523 setverdict(fail, "Received multiple paging on same SIG BVC");
1524 }
1525 roi := roi & { pcu_idx };
1526 repeat;
1527 }
Harald Welte158becf2020-12-09 12:32:32 +01001528[] PCU_PTP[pcu_idx].receive(exp_rx) {
Harald Welte0e188242020-11-22 21:46:48 +01001529 setverdict(fail, "Received paging on PTP BVC, expected SIGNALING BVC");
1530 }
1531[] PCU_SIG[pcu_idx].receive(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}) {
1532 setverdict(fail, "Different Paging than expected received SIGNALING BVC");
1533 }
Harald Welte158becf2020-12-09 12:32:32 +01001534[] PCU_PTP[pcu_idx].receive(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}) {
Harald Welte0e188242020-11-22 21:46:48 +01001535 setverdict(fail, "Different Paging than expected received PTP BVC");
1536 }
1537}
1538
1539type record of default ro_default;
1540
1541/* send PS-PAGING on SIG BVC, expect it to arrive on given list of PCU indexes */
1542private function f_send_paging_ps_exp_multi(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
1543 ro_integer exp_on_pcu_idx) runs on BSSGP_ConnHdlr
1544{
1545 var template (present) PDU_BSSGP exp_rx;
Daniel Willmann193e1a02021-01-17 12:55:53 +01001546 exp_rx := f_send_paging_ps(p4, sgsn_idx, true);
Harald Welte0e188242020-11-22 21:46:48 +01001547
1548 /* FIXME: make sure the relevant BVCs/BSS are connected to the ports! */
1549 var ro_default defaults := {};
1550 for (var integer i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
1551 var default d := activate(as_paging_sig_pcu(i, exp_rx, g_roi));
1552 defaults := defaults & { d };
1553 }
1554 f_sleep(2.0);
1555 for (var integer i := 0; i < lengthof(defaults); i := i+1) {
1556 deactivate(defaults[i]);
1557 }
1558 log("Paging received on PCU ", g_roi);
1559
1560 for (var integer i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
1561 var boolean rx_on_i := ro_integer_contains(g_roi, i);
1562 var boolean exp_on_i := ro_integer_contains(exp_on_pcu_idx, i);
1563 if (exp_on_i and not rx_on_i) {
1564 setverdict(fail, "PS-PAGING not received on ", mp_nsconfig_pcu[i].nsei);
1565 }
1566 if (not exp_on_i and rx_on_i) {
1567 setverdict(fail, "PS-PAGING not expected but received on ", mp_nsconfig_pcu[i].nsei);
1568 }
1569 }
1570 setverdict(pass);
1571}
1572
Harald Weltecf200072021-01-16 15:20:46 +01001573/* Send PAGING-PS-REJECT on SIG BVC, expect it to arrive on the "right" SGSN */
1574private function f_send_paging_ps_rej(boolean use_sig := true, integer pcu_idx := 0) runs on BSSGP_ConnHdlr
1575{
1576 var template (value) PDU_BSSGP pdu_tx;
1577 var template (present) PDU_BSSGP exp_rx;
1578 var PDU_BSSGP pdu_rx;
1579 timer T := 5.0;
1580 var template (omit) GsmTmsi tmsi_int := omit;
1581
1582 if (ispresent(g_pars.p_tmsi)) {
1583 tmsi_int := oct2int(g_pars.p_tmsi);
1584 }
1585
1586 pdu_tx := ts_BSSGP_PAGING_PS_REJ(g_pars.imsi, 23, 42, tmsi_int);
1587 exp_rx := tr_BSSGP_PAGING_PS_REJ(g_pars.imsi, 23, 42, tmsi_int);
1588
1589 if (use_sig) {
1590 PCU_SIG[pcu_idx].send(pdu_tx);
1591 } else {
1592 PCU_PTP[pcu_idx].send(pdu_tx);
1593 }
1594 T.start;
1595 alt {
1596 [use_sig] SGSN_SIG[g_pars.sgsn_idx].receive(exp_rx) -> value pdu_rx {
1597 setverdict(pass);
1598 }
1599 [use_sig] SGSN_SIG[g_pars.sgsn_idx].receive {
1600 setverdict(fail, "Unexpected PDU on SGSN");
1601 }
1602 [use_sig] any from SGSN_SIG.receive(exp_rx) -> value pdu_rx {
1603 setverdict(fail, "PAGING-PS-REJECT arrived on wrong SGSN");
1604 }
1605 [not use_sig] SGSN_PTP[g_pars.sgsn_idx].receive(exp_rx) -> value pdu_rx {
1606 setverdict(pass);
1607 }
1608 [not use_sig] SGSN_PTP[g_pars.sgsn_idx].receive {
1609 setverdict(fail, "Unexpected PDU on SGSN");
1610 }
1611 [not use_sig] any from SGSN_PTP.receive(exp_rx) -> value pdu_rx {
1612 setverdict(fail, "PAGING-PS-REJECT arrived on wrong SGSN");
1613 }
1614 [] T.timeout {
1615 setverdict(fail, "Timeout waiting for PAGING-PS-REJECT");
1616 }
1617 }
1618}
1619
Harald Welte0e188242020-11-22 21:46:48 +01001620/* PS-PAGING on SIG-BVC for BSS Area */
1621private function f_TC_paging_ps_sig_bss(charstring id) runs on BSSGP_ConnHdlr
1622{
1623 /* we expect the paging to arrive on all three NSE */
1624 f_send_paging_ps_exp_multi(ts_BssgpP4BssArea, 0, {0, 1, 2});
1625}
1626testcase TC_paging_ps_sig_bss() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001627 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001628 f_start_handlers(refers(f_TC_paging_ps_sig_bss), testcasename(), 13);
Harald Welte0e188242020-11-22 21:46:48 +01001629 f_cleanup();
1630}
1631
1632/* PS-PAGING on SIG-BVC for Location Area */
1633private function f_TC_paging_ps_sig_lac(charstring id) runs on BSSGP_ConnHdlr
1634{
Daniel Willmann2c9300f2020-12-01 10:54:08 +01001635 /* The first LAC (13135) is shared by all three NSEs */
1636 f_send_paging_ps_exp_multi(ts_BssgpP4LAC(pcu_bvc_cfg[0].cell_id.ra_id.lai), 0, {0, 1, 2});
1637 /* Reset state */
1638 g_roi := {};
1639 /* Make LAC (13300) available on pcu index 2 */
1640 f_connect_to_pcu_bvc(port_idx := 2, nse_idx := 2, bvc_idx := 1);
1641 f_send_paging_ps_exp_multi(ts_BssgpP4LAC(pcu_bvc_cfg[2].cell_id.ra_id.lai), 0, {2});
Harald Welte0e188242020-11-22 21:46:48 +01001642}
1643testcase TC_paging_ps_sig_lac() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001644 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001645 f_start_handlers(refers(f_TC_paging_ps_sig_lac), testcasename(), 14);
Harald Welte0e188242020-11-22 21:46:48 +01001646 f_cleanup();
1647}
1648
Harald Welte7462a592020-11-23 22:07:07 +01001649/* PS-PAGING on SIG-BVC for unknown Location Area */
1650private function f_TC_paging_ps_sig_lac_unknown(charstring id) runs on BSSGP_ConnHdlr
1651{
1652 var GSM_Types.LocationAreaIdentification unknown_la := {
1653 mcc_mnc := '567F99'H,
1654 lac := 33333
1655 };
1656 f_send_paging_ps_exp_no_bss(ts_BssgpP4LAC(unknown_la), 0, true);
1657}
1658testcase TC_paging_ps_sig_lac_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01001659 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001660 f_start_handlers(refers(f_TC_paging_ps_sig_lac_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01001661 f_cleanup();
1662}
1663
Harald Welte0e188242020-11-22 21:46:48 +01001664/* PS-PAGING on SIG-BVC for Routeing Area */
1665private function f_TC_paging_ps_sig_rac(charstring id) runs on BSSGP_ConnHdlr
1666{
Daniel Willmann2c9300f2020-12-01 10:54:08 +01001667 /* Only PCU index 0 has a matching BVC with the RA ID */
Harald Welte0e188242020-11-22 21:46:48 +01001668 f_send_paging_ps_exp_multi(ts_BssgpP4RAC(pcu_bvc_cfg[0].cell_id.ra_id), 0, {0});
Daniel Willmann2c9300f2020-12-01 10:54:08 +01001669 g_roi := {};
1670 /* PCU index 1 and 2 have a matching BVC with the RA ID */
1671 f_send_paging_ps_exp_multi(ts_BssgpP4RAC(pcu_bvc_cfg[2].cell_id.ra_id), 0, {1, 2});
1672 g_roi := {};
1673 /* PCU index 2 has two matching BVCs with the RA ID */
1674 f_connect_to_pcu_bvc(port_idx := 2, nse_idx := 2, bvc_idx := 1);
1675 f_send_paging_ps_exp_multi(ts_BssgpP4RAC(pcu_bvc_cfg[2].cell_id.ra_id), 0, {2});
Harald Welte0e188242020-11-22 21:46:48 +01001676}
1677testcase TC_paging_ps_sig_rac() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001678 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001679 f_start_handlers(refers(f_TC_paging_ps_sig_rac), testcasename(), 15);
Harald Welte0e188242020-11-22 21:46:48 +01001680 f_cleanup();
1681}
1682
Harald Welte7462a592020-11-23 22:07:07 +01001683/* PS-PAGING on SIG-BVC for unknown Routeing Area */
1684private function f_TC_paging_ps_sig_rac_unknown(charstring id) runs on BSSGP_ConnHdlr
1685{
1686 var RoutingAreaIdentification unknown_ra := {
1687 lai := {
1688 mcc_mnc := '567F99'H,
1689 lac := 33333
1690 },
1691 rac := 254
1692 };
1693 f_send_paging_ps_exp_no_bss(ts_BssgpP4RAC(unknown_ra), 0, true);
1694}
1695testcase TC_paging_ps_sig_rac_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01001696 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001697 f_start_handlers(refers(f_TC_paging_ps_sig_rac_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01001698 f_cleanup();
1699}
1700
Harald Welte0e188242020-11-22 21:46:48 +01001701/* PS-PAGING on SIG-BVC for BVCI (one cell) */
1702private function f_TC_paging_ps_sig_bvci(charstring id) runs on BSSGP_ConnHdlr
1703{
1704 f_send_paging_ps_exp_multi(ts_BssgpP4Bvci(pcu_bvc_cfg[0].bvci), 0, {0});
1705}
1706testcase TC_paging_ps_sig_bvci() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001707 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001708 f_start_handlers(refers(f_TC_paging_ps_sig_bvci), testcasename(), 16);
Harald Welte0e188242020-11-22 21:46:48 +01001709 f_cleanup();
1710}
1711
Harald Welteb5a04aa2021-01-16 13:04:40 +01001712/* PS-PAGING on SIG-BVC for BVCI (one cell) using IMSI only (no P-TMSI allocated) */
1713testcase TC_paging_ps_sig_bvci_imsi() runs on test_CT {
1714 f_init();
1715 f_start_handlers(refers(f_TC_paging_ps_sig_bvci), testcasename(), 16, have_ptmsi:=false);
1716 f_cleanup();
1717}
1718
Harald Weltecf200072021-01-16 15:20:46 +01001719/* Rejected PS-PAGING on SIG-BVC for BVCI (one cell) */
1720private function f_TC_paging_ps_reject_sig_bvci(charstring id) runs on BSSGP_ConnHdlr
1721{
1722 /* first send the PS-PAGING from SGSN -> PCU */
1723 f_send_paging_ps_exp_multi(ts_BssgpP4Bvci(pcu_bvc_cfg[0].bvci), 0, {0});
1724 /* then simulate the PS-PAGING-REJECT from the PCU */
1725 f_send_paging_ps_rej(use_sig:=true);
1726
1727}
1728testcase TC_paging_ps_reject_sig_bvci() runs on test_CT {
1729 f_init();
1730 f_start_handlers(refers(f_TC_paging_ps_reject_sig_bvci), testcasename(), 16);
1731 f_cleanup();
1732}
1733
1734/* Rejected PS-PAGING on SIG-BVC for BVCI (one cell) using IMSI only (no P-TMSI allocated) */
1735testcase TC_paging_ps_reject_sig_bvci_imsi() runs on test_CT {
1736 f_init();
1737 f_start_handlers(refers(f_TC_paging_ps_reject_sig_bvci), testcasename(), 16, have_ptmsi:=false);
1738 f_cleanup();
1739}
1740
Harald Welte7462a592020-11-23 22:07:07 +01001741/* PS-PAGING on SIG-BVC for unknown BVCI */
1742private function f_TC_paging_ps_sig_bvci_unknown(charstring id) runs on BSSGP_ConnHdlr
1743{
1744 f_send_paging_ps_exp_no_bss(ts_BssgpP4Bvci(33333), 0, true);
1745}
1746testcase TC_paging_ps_sig_bvci_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01001747 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001748 f_start_handlers(refers(f_TC_paging_ps_sig_bvci_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01001749 f_cleanup();
1750}
1751
Harald Welte7595d562021-01-16 19:09:20 +01001752/* DUMMY PAGING PS on SIG BVC */
1753private function f_TC_dummy_paging_ps_sig(charstring id) runs on BSSGP_ConnHdlr
1754{
1755 f_sgsn2pcu(ts_BSSGP_DUMMY_PAGING_PS(g_pars.imsi, omit),
1756 tr_BSSGP_DUMMY_PAGING_PS(g_pars.imsi, omit), use_sig := true);
1757 f_pcu2sgsn(ts_BSSGP_DUMMY_PAGING_PS_RESP(g_pars.imsi, 1, 5),
1758 tr_BSSGP_DUMMY_PAGING_PS_RESP(g_pars.imsi, 1, 5), use_sig := true)
1759}
1760testcase TC_dummy_paging_ps_sig() runs on test_CT {
1761 f_init();
1762 f_start_handlers(refers(f_TC_dummy_paging_ps_sig), testcasename(), 11);
1763 f_cleanup();
1764}
1765
Harald Welte7462a592020-11-23 22:07:07 +01001766
Harald Welte0e188242020-11-22 21:46:48 +01001767
1768/***********************************************************************
1769 * PAGING CS procedure
1770 ***********************************************************************/
1771
1772private function f_send_paging_cs(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
1773 boolean use_sig := false)
1774runs on BSSGP_ConnHdlr return template (present) PDU_BSSGP {
1775 var template (value) PDU_BSSGP pdu_tx;
1776 var template (present) PDU_BSSGP pdu_rx;
1777 /* we always specify '0' as BVCI in the templates below, as we override it with
1778 * 'p4' later anyway */
1779 pdu_rx := tr_BSSGP_CS_PAGING(0);
1780 pdu_rx.pDU_BSSGP_PAGING_CS.iMSI := tr_BSSGP_IMSI(g_pars.imsi);
1781 if (ispresent(g_pars.p_tmsi)) {
1782 pdu_tx := ts_BSSGP_CS_PAGING_PTMSI(0, g_pars.imsi, oct2int(g_pars.p_tmsi));
1783 pdu_rx.pDU_BSSGP_PAGING_CS.tMSI := tr_BSSGP_TMSI(oct2int(g_pars.p_tmsi));
1784 } else {
1785 pdu_tx := ts_BSSGP_CS_PAGING_IMSI(0, g_pars.imsi);
1786 pdu_rx.pDU_BSSGP_PAGING_CS.tMSI := omit;
1787 }
1788 pdu_tx.pDU_BSSGP_PAGING_CS.paging_Field4 := p4;
1789 pdu_rx.pDU_BSSGP_PAGING_CS.paging_Field4 := p4;
1790 if (use_sig == false) {
Harald Welte158becf2020-12-09 12:32:32 +01001791 SGSN_PTP[sgsn_idx].send(pdu_tx);
Harald Welte0e188242020-11-22 21:46:48 +01001792 } else {
1793 SGSN_SIG[sgsn_idx].send(pdu_tx);
1794 }
1795 return pdu_rx;
1796}
1797
1798/* send paging defined by 'p4' on given SGSN-side index (ptp or signaling) and expect one paging to arrive on
1799 * specified PCU index */
1800private function f_send_paging_cs_exp_one_bss(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
1801 boolean use_sig := false,integer pcu_idx := 0)
1802runs on BSSGP_ConnHdlr {
1803 var template (present) PDU_BSSGP exp_rx;
Daniel Willmann1a859712020-12-04 00:59:45 +01001804 var boolean test_done := false;
Harald Welte0e188242020-11-22 21:46:48 +01001805 /* doesn't really make sense: Sending to a single BVCI means the message ends up
1806 * at that BVC (cell) only, and paging all over the BSS area is not possible */
1807 exp_rx := f_send_paging_cs(p4, sgsn_idx, use_sig);
1808 /* Expect paging to propagate to the one BSS addressed by the BVCI only */
1809 timer T := 2.0;
1810 T.start;
1811 alt {
Harald Welte158becf2020-12-09 12:32:32 +01001812 [not use_sig and not test_done] PCU_PTP[pcu_idx].receive(exp_rx) {
Harald Welte0e188242020-11-22 21:46:48 +01001813 setverdict(pass);
Daniel Willmann1a859712020-12-04 00:59:45 +01001814 test_done := true;
Harald Welte0e188242020-11-22 21:46:48 +01001815 repeat;
1816 }
1817 [not use_sig] PCU_SIG[pcu_idx].receive(exp_rx) {
1818 setverdict(fail, "Received paging on SIGNALING BVC, expected PTP BVC");
1819 }
Daniel Willmann1a859712020-12-04 00:59:45 +01001820 [use_sig and not test_done] PCU_SIG[pcu_idx].receive(exp_rx) {
Harald Welte0e188242020-11-22 21:46:48 +01001821 setverdict(pass);
Daniel Willmann1a859712020-12-04 00:59:45 +01001822 test_done := true;
Harald Welte0e188242020-11-22 21:46:48 +01001823 repeat;
1824 }
Harald Welte158becf2020-12-09 12:32:32 +01001825 [use_sig] PCU_PTP[pcu_idx].receive(exp_rx) {
Harald Welte0e188242020-11-22 21:46:48 +01001826 setverdict(fail, "Received paging on PTP BVC, expected SIGNALING BVC");
1827 }
Harald Welte158becf2020-12-09 12:32:32 +01001828 [] any from PCU_PTP.receive(exp_rx) {
Harald Welte0e188242020-11-22 21:46:48 +01001829 setverdict(fail, "Paging received on unexpected BVC");
1830 }
1831 [] any from PCU_SIG.receive(exp_rx) {
1832 setverdict(fail, "Paging received on unexpected BVC");
1833 }
Harald Welte158becf2020-12-09 12:32:32 +01001834 [] any from PCU_PTP.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_CS:=?}) {
Harald Welte0e188242020-11-22 21:46:48 +01001835 setverdict(fail, "Different Paging than expected received PTP BVC");
1836 }
1837 [] any from PCU_SIG.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_CS:=?}) {
1838 setverdict(fail, "Different Paging than expected on SIGNALING BVC");
1839 }
Daniel Willmann1a859712020-12-04 00:59:45 +01001840 [not test_done] T.timeout {
1841 setverdict(fail, "Timeout while waiting for paging")
1842 }
1843 [test_done] T.timeout;
Harald Welte0e188242020-11-22 21:46:48 +01001844 }
1845}
1846
Harald Welte7462a592020-11-23 22:07:07 +01001847/* send a CS-PAGING but don't expect it to show up on any PTP or SIG BVC */
1848private function f_send_paging_cs_exp_no_bss(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
1849 boolean use_sig := false)
1850runs on BSSGP_ConnHdlr {
1851 var template (present) PDU_BSSGP exp_rx;
1852 exp_rx := f_send_paging_cs(p4, sgsn_idx, use_sig);
1853 /* Expect paging to propagate to no BSS */
1854 timer T := 2.0;
1855 T.start;
1856 alt {
Harald Welte158becf2020-12-09 12:32:32 +01001857 [] any from PCU_PTP.receive(exp_rx) {
Harald Welte7462a592020-11-23 22:07:07 +01001858 setverdict(fail, "Paging received on unexpected BVC");
1859 }
1860 [] any from PCU_SIG.receive(exp_rx) {
1861 setverdict(fail, "Paging received on unexpected BVC");
1862 }
Harald Welte158becf2020-12-09 12:32:32 +01001863 [] any from PCU_PTP.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_CS:=?}) {
Harald Welte7462a592020-11-23 22:07:07 +01001864 setverdict(fail, "Different Paging received on PTP BVC");
1865 }
1866 [] any from PCU_SIG.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_CS:=?}) {
1867 setverdict(fail, "Different Paging received on SIGNALING BVC");
1868 }
1869 [] T.timeout {
1870 setverdict(pass);
1871 }
1872 }
1873}
1874
Harald Welte0e188242020-11-22 21:46:48 +01001875private function f_TC_paging_cs_ptp_bss(charstring id) runs on BSSGP_ConnHdlr
1876{
1877 /* doesn't really make sense: Sending to a single BVCI means the message ends up
1878 * at that BVC (cell) only, and paging all over the BSS area is not possible */
1879 f_send_paging_cs_exp_one_bss(ts_BssgpP4BssArea, 0, false, 0);
1880}
1881testcase TC_paging_cs_ptp_bss() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001882 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001883 f_start_handlers(refers(f_TC_paging_cs_ptp_bss), testcasename(), 17);
Harald Welte0e188242020-11-22 21:46:48 +01001884 f_cleanup();
1885}
1886
1887/* CS-PAGING on PTP-BVC for Location Area */
1888private function f_TC_paging_cs_ptp_lac(charstring id) runs on BSSGP_ConnHdlr
1889{
1890 var template (present) PDU_BSSGP exp_rx;
1891 /* doesn't really make sense: Sending to a single BVCI means the message ends up
1892 * at that BVC (cell) only, and paging all over the BSS area is not possible */
1893 f_send_paging_cs_exp_one_bss(ts_BssgpP4LAC(pcu_bvc_cfg[0].cell_id.ra_id.lai), 0, false, 0);
1894}
1895testcase TC_paging_cs_ptp_lac() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001896 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001897 f_start_handlers(refers(f_TC_paging_cs_ptp_lac), testcasename(), 18);
Harald Welte0e188242020-11-22 21:46:48 +01001898 f_cleanup();
1899}
1900
Harald Welte7462a592020-11-23 22:07:07 +01001901/* CS-PAGING on PTP-BVC for unknown Location Area */
1902private function f_TC_paging_cs_ptp_lac_unknown(charstring id) runs on BSSGP_ConnHdlr
1903{
1904 var GSM_Types.LocationAreaIdentification unknown_la := {
1905 mcc_mnc := '567F99'H,
1906 lac := 33333
1907 };
1908 /* as it's sent on the PTP BVC, we expect it to pass even for unknown LAC */
1909 f_send_paging_cs_exp_one_bss(ts_BssgpP4LAC(unknown_la), 0, false, 0);
1910}
1911testcase TC_paging_cs_ptp_lac_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01001912 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001913 f_start_handlers(refers(f_TC_paging_cs_ptp_lac_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01001914 f_cleanup();
1915}
1916
Harald Welte0e188242020-11-22 21:46:48 +01001917/* CS-PAGING on PTP-BVC for Routeing Area */
1918private function f_TC_paging_cs_ptp_rac(charstring id) runs on BSSGP_ConnHdlr
1919{
1920 /* doesn't really make sense: Sending to a single BVCI means the message ends up
1921 * at that BVC (cell) only, and paging all over the BSS area is not possible */
1922 f_send_paging_cs_exp_one_bss(ts_BssgpP4RAC(pcu_bvc_cfg[0].cell_id.ra_id), 0, false, 0);
1923}
1924testcase TC_paging_cs_ptp_rac() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001925 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001926 f_start_handlers(refers(f_TC_paging_cs_ptp_rac), testcasename(), 19);
Harald Welte0e188242020-11-22 21:46:48 +01001927 f_cleanup();
1928}
1929
Harald Welte7462a592020-11-23 22:07:07 +01001930/* CS-PAGING on PTP-BVC for unknown Routeing Area */
1931private function f_TC_paging_cs_ptp_rac_unknown(charstring id) runs on BSSGP_ConnHdlr
1932{
1933 var RoutingAreaIdentification unknown_ra := {
1934 lai := {
1935 mcc_mnc := '567F99'H,
1936 lac := 33333
1937 },
1938 rac := 254
1939 };
1940 /* as it's sent on the PTP BVC, we expect it to pass even for unknown RAC */
1941 f_send_paging_cs_exp_one_bss(ts_BssgpP4RAC(unknown_ra), 0, false, 0);
1942}
1943testcase TC_paging_cs_ptp_rac_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01001944 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001945 f_start_handlers(refers(f_TC_paging_cs_ptp_rac_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01001946 f_cleanup();
1947}
1948
Harald Welte0e188242020-11-22 21:46:48 +01001949/* CS-PAGING on PTP-BVC for BVCI (one cell) */
1950private function f_TC_paging_cs_ptp_bvci(charstring id) runs on BSSGP_ConnHdlr
1951{
1952 /* this should be the normal case for MS in READY MM state after a lower layer failure */
1953 f_send_paging_cs_exp_one_bss(ts_BssgpP4Bvci(pcu_bvc_cfg[0].bvci), 0, false, 0);
1954}
1955testcase TC_paging_cs_ptp_bvci() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01001956 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001957 f_start_handlers(refers(f_TC_paging_cs_ptp_bvci), testcasename(), 20);
Harald Welte0e188242020-11-22 21:46:48 +01001958 f_cleanup();
1959}
1960
Harald Welte7462a592020-11-23 22:07:07 +01001961/* CS-PAGING on PTP-BVC for unknown BVCI */
1962private function f_TC_paging_cs_ptp_bvci_unknown(charstring id) runs on BSSGP_ConnHdlr
1963{
1964 /* as it's sent on the PTP BVC, we expect it to pass even for unknown BVCI */
1965 f_send_paging_cs_exp_one_bss(ts_BssgpP4Bvci(33333), 0, false, 0);
1966}
1967testcase TC_paging_cs_ptp_bvci_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01001968 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01001969 f_start_handlers(refers(f_TC_paging_cs_ptp_bvci_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01001970 f_cleanup();
1971}
1972
Harald Welte0e188242020-11-22 21:46:48 +01001973/* send CS-PAGING on SIG BVC, expect it to arrive on given list of PCU indexes */
1974private function f_send_paging_cs_exp_multi(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
1975 ro_integer exp_on_pcu_idx) runs on BSSGP_ConnHdlr
1976{
1977 var template (present) PDU_BSSGP exp_rx;
1978 exp_rx := f_send_paging_cs(p4, 0, true);
1979
1980 /* FIXME: make sure the relevant BVCs/BSS are connected to the ports! */
1981 var ro_default defaults := {};
1982 for (var integer i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
1983 var default d := activate(as_paging_sig_pcu(i, exp_rx, g_roi));
1984 defaults := defaults & { d };
1985 }
1986 f_sleep(2.0);
1987 for (var integer i := 0; i < lengthof(defaults); i := i+1) {
1988 deactivate(defaults[i]);
1989 }
1990 log("Paging received on PCU ", g_roi);
1991
1992 for (var integer i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
1993 var boolean rx_on_i := ro_integer_contains(g_roi, i);
1994 var boolean exp_on_i := ro_integer_contains(exp_on_pcu_idx, i);
1995 if (exp_on_i and not rx_on_i) {
1996 setverdict(fail, "PS-PAGING not received on ", mp_nsconfig_pcu[i].nsei);
1997 }
1998 if (not exp_on_i and rx_on_i) {
1999 setverdict(fail, "PS-PAGING not expected but received on ", mp_nsconfig_pcu[i].nsei);
2000 }
2001 }
2002 setverdict(pass);
2003}
2004
2005/* CS-PAGING on SIG-BVC for BSS Area */
2006private function f_TC_paging_cs_sig_bss(charstring id) runs on BSSGP_ConnHdlr
2007{
2008 /* we expect the paging to arrive on all three NSE */
2009 f_send_paging_cs_exp_multi(ts_BssgpP4BssArea, 0, {0, 1, 2});
2010}
2011testcase TC_paging_cs_sig_bss() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01002012 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002013 f_start_handlers(refers(f_TC_paging_cs_sig_bss), testcasename(), 13);
Harald Welte0e188242020-11-22 21:46:48 +01002014 f_cleanup();
2015}
2016
2017/* CS-PAGING on SIG-BVC for Location Area */
2018private function f_TC_paging_cs_sig_lac(charstring id) runs on BSSGP_ConnHdlr
2019{
Daniel Willmannd4fb73c2020-12-07 13:57:17 +01002020 /* The first LAC (13135) is shared by all three NSEs */
2021 f_send_paging_cs_exp_multi(ts_BssgpP4LAC(pcu_bvc_cfg[0].cell_id.ra_id.lai), 0, {0, 1, 2});
2022 /* Reset state */
2023 g_roi := {};
2024 /* Make LAC (13300) available on pcu index 2 */
2025 f_connect_to_pcu_bvc(port_idx := 2, nse_idx := 2, bvc_idx := 1);
2026 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 +01002027}
2028testcase TC_paging_cs_sig_lac() runs on test_CT {
Harald Welte0e188242020-11-22 21:46:48 +01002029 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002030 f_start_handlers(refers(f_TC_paging_cs_sig_lac), testcasename(), 14);
Harald Welte0e188242020-11-22 21:46:48 +01002031 f_cleanup();
2032}
2033
Harald Welte7462a592020-11-23 22:07:07 +01002034/* CS-PAGING on SIG-BVC for unknown Location Area */
2035private function f_TC_paging_cs_sig_lac_unknown(charstring id) runs on BSSGP_ConnHdlr
2036{
2037 var GSM_Types.LocationAreaIdentification unknown_la := {
2038 mcc_mnc := '567F99'H,
2039 lac := 33333
2040 };
2041 f_send_paging_cs_exp_no_bss(ts_BssgpP4LAC(unknown_la), 0, true);
2042}
2043testcase TC_paging_cs_sig_lac_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01002044 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002045 f_start_handlers(refers(f_TC_paging_cs_sig_lac_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01002046 f_cleanup();
2047}
2048
Harald Welte0e188242020-11-22 21:46:48 +01002049/* CS-PAGING on SIG-BVC for Routeing Area */
2050private function f_TC_paging_cs_sig_rac(charstring id) runs on BSSGP_ConnHdlr
2051{
Daniel Willmannd4fb73c2020-12-07 13:57:17 +01002052 /* Only PCU index 0 has a matching BVC with the RA ID */
Harald Welte0e188242020-11-22 21:46:48 +01002053 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 +01002054 g_roi := {};
2055 /* PCU index 1 and 2 have a matching BVC with the RA ID */
2056 f_send_paging_cs_exp_multi(ts_BssgpP4RAC(pcu_bvc_cfg[2].cell_id.ra_id), 0, {1, 2});
2057 g_roi := {};
2058 /* PCU index 2 has two matching BVCs with the RA ID */
2059 f_connect_to_pcu_bvc(port_idx := 2, nse_idx := 2, bvc_idx := 1);
2060 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 +01002061}
2062testcase TC_paging_cs_sig_rac() 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_sig_rac), testcasename(), 15);
Harald Welte0e188242020-11-22 21:46:48 +01002065 f_cleanup();
2066}
2067
Harald Welte7462a592020-11-23 22:07:07 +01002068/* CS-PAGING on SIG-BVC for unknown Routeing Area */
2069private function f_TC_paging_cs_sig_rac_unknown(charstring id) runs on BSSGP_ConnHdlr
2070{
2071 var RoutingAreaIdentification unknown_ra := {
2072 lai := {
2073 mcc_mnc := '567F99'H,
2074 lac := 33333
2075 },
2076 rac := 254
2077 };
2078 f_send_paging_cs_exp_no_bss(ts_BssgpP4RAC(unknown_ra), 0, true);
2079}
2080testcase TC_paging_cs_sig_rac_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01002081 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002082 f_start_handlers(refers(f_TC_paging_cs_sig_rac_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01002083 f_cleanup();
2084}
2085
Harald Welte0e188242020-11-22 21:46:48 +01002086/* CS-PAGING on SIG-BVC for BVCI (one cell) */
2087private function f_TC_paging_cs_sig_bvci(charstring id) runs on BSSGP_ConnHdlr
2088{
2089 f_send_paging_cs_exp_multi(ts_BssgpP4Bvci(pcu_bvc_cfg[0].bvci), 0, {0});
2090}
2091testcase TC_paging_cs_sig_bvci() 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_sig_bvci), testcasename(), 16);
Harald Welte0e188242020-11-22 21:46:48 +01002094 f_cleanup();
2095}
2096
Harald Welte7462a592020-11-23 22:07:07 +01002097/* CS-PAGING on SIG-BVC for unknown BVCI */
2098private function f_TC_paging_cs_sig_bvci_unknown(charstring id) runs on BSSGP_ConnHdlr
2099{
2100 f_send_paging_cs_exp_no_bss(ts_BssgpP4Bvci(33333), 0, true);
2101}
2102testcase TC_paging_cs_sig_bvci_unknown() runs on test_CT {
Harald Welte7462a592020-11-23 22:07:07 +01002103 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002104 f_start_handlers(refers(f_TC_paging_cs_sig_bvci_unknown), testcasename(), 11);
Harald Welte7462a592020-11-23 22:07:07 +01002105 f_cleanup();
2106}
2107
Harald Welte4f91c3b2020-12-09 12:25:51 +01002108/***********************************************************************
2109 * FLUSH-LL procedure
2110 ***********************************************************************/
2111
Daniel Willmann91a8e25b2020-11-24 14:50:59 +01002112private function f_TC_flush_ll(charstring id) runs on BSSGP_ConnHdlr {
2113 var BssgpBvci bvci := g_pars.pcu[0].cfg.bvc[0].bvci;
2114 var integer i;
2115 for (i := 0; i < 10; i := i+1) {
2116 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_FLUSH_LL(g_pars.tlli, bvci, bvci_new := bvci);
2117 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
2118 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_FLUSH_LL(g_pars.tlli, bvci, bvci_new := bvci);
2119
2120 f_sgsn2pcu(pdu_tx, pdu_rx, use_sig := true);
2121
2122 pdu_tx := ts_BSSGP_FLUSH_LL_ACK(g_pars.tlli, int2oct(0, 1), 23, bvci_new := bvci);
2123 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
2124 pdu_rx := tr_BSSGP_FLUSH_LL_ACK(g_pars.tlli, int2oct(0, 1), 23, bvci_new := bvci);
2125
2126 f_pcu2sgsn(pdu_tx, pdu_rx, use_sig := true);
2127 }
2128 setverdict(pass);
2129}
2130testcase TC_flush_ll() runs on test_CT
2131{
Daniel Willmann91a8e25b2020-11-24 14:50:59 +01002132 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002133 f_start_handlers(refers(f_TC_flush_ll), testcasename(), 6);
Daniel Willmann91a8e25b2020-11-24 14:50:59 +01002134 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
Daniel Willmann91a8e25b2020-11-24 14:50:59 +01002135 f_cleanup();
2136}
Harald Welte6dc2ac42020-11-16 09:16:17 +01002137
Harald Welte4f91c3b2020-12-09 12:25:51 +01002138/***********************************************************************
2139 * SGSN-INVOKE-TRACE procedure
2140 ***********************************************************************/
2141
Harald Weltef8e5c5d2020-11-27 22:37:23 +01002142private altstep as_bssgp_g_pcu_count(integer pcu_idx, template (present) PDU_BSSGP exp_rx, inout ro_integer roi)
2143runs on GlobalTest_CT {
2144[] G_PCU[pcu_idx].receive(exp_rx) from g_pcu[pcu_idx].vc_BSSGP {
2145 if (ro_integer_contains(roi, pcu_idx)) {
2146 setverdict(fail, "Received multiple on same SIG BVC");
2147 }
2148 roi := roi & { pcu_idx };
2149 repeat;
2150 }
2151}
2152/* send a INVOKE-TRACE from SGSN and expect to receive a copy on each NSE */
2153testcase TC_trace() runs on GlobalTest_CT
2154{
2155 var BSSGP_ConnHdlr vc_conn;
2156 f_init();
2157 f_global_init();
2158
2159 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_INVOKE_TRACE('23'O, '4321'O);
2160 var template (present) PDU_BSSGP exp_rx := ts_BSSGP_INVOKE_TRACE('23'O, '4321'O);
2161
2162 var ro_default defaults := {};
2163 for (var integer i := 0; i < lengthof(g_pcu); i := i+1) {
2164 activate(as_bssgp_g_pcu_count(i, exp_rx, g_roi));
2165 }
2166 G_SGSN[0].send(pdu_tx);
2167 f_sleep(2.0);
2168 for (var integer i := 0; i < lengthof(defaults); i := i+1) {
2169 deactivate(defaults[i]);
2170 }
2171
2172 for (var integer i := 0; i < lengthof(g_pcu); i := i+1) {
2173 if (not ro_integer_contains(g_roi, i)) {
2174 setverdict(fail, "Failed to receive TRACE on PCU index ", i);
2175 }
2176 }
2177 setverdict(pass);
2178
2179 f_cleanup();
2180}
2181
Harald Welte4f91c3b2020-12-09 12:25:51 +01002182/***********************************************************************
2183 * LLC-DISCARDED procedure
2184 ***********************************************************************/
2185
Harald Weltec0351d12020-11-27 22:49:02 +01002186private function f_TC_llc_discarded(charstring id) runs on BSSGP_ConnHdlr {
2187 var BssgpBvci bvci := g_pars.pcu[0].cfg.bvc[0].bvci;
2188
2189 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_LLC_DISCARDED(g_pars.tlli, 23, bvci, 2342);
2190 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
2191 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_LLC_DISCARDED(g_pars.tlli, 23, bvci, 2342);
2192
2193 f_pcu2sgsn(pdu_tx, pdu_rx, use_sig := true);
2194
2195 setverdict(pass);
2196}
2197/* Send a LLC-DISCARDED from BSS side and expect it to show up on SGSN (SIG BVC) */
2198testcase TC_llc_discarded() runs on test_CT
2199{
Harald Weltec0351d12020-11-27 22:49:02 +01002200 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002201 f_start_handlers(refers(f_TC_llc_discarded), testcasename(), 6);
Harald Weltec0351d12020-11-27 22:49:02 +01002202 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
Harald Weltec0351d12020-11-27 22:49:02 +01002203 f_cleanup();
2204}
2205
Harald Welte4f91c3b2020-12-09 12:25:51 +01002206/***********************************************************************
2207 * OVERLOAD procedure
2208 ***********************************************************************/
2209
Harald Weltef20af412020-11-28 16:11:11 +01002210/* Send an OVERLOAD from SGSN side and expect it to show up on each PCU (SIG BVC) */
2211testcase TC_overload() runs on GlobalTest_CT
2212{
2213 f_init();
2214 f_global_init();
2215
2216 var template (value) PDU_BSSGP pdu_tx := ts_OVERLOAD('1'B);
2217 var template (present) PDU_BSSGP exp_rx := tr_OVERLOAD('1'B);
2218
2219 var ro_default defaults := {};
2220 for (var integer i := 0; i < lengthof(g_pcu); i := i+1) {
2221 activate(as_bssgp_g_pcu_count(i, exp_rx, g_roi));
2222 }
2223 G_SGSN[0].send(pdu_tx);
2224 f_sleep(2.0);
2225 for (var integer i := 0; i < lengthof(defaults); i := i+1) {
2226 deactivate(defaults[i]);
2227 }
2228
2229 for (var integer i := 0; i < lengthof(g_pcu); i := i+1) {
2230 if (not ro_integer_contains(g_roi, i)) {
2231 setverdict(fail, "Failed to receive OVERLOAD on PCU index ", i);
2232 }
2233 }
2234 setverdict(pass);
2235
2236 f_cleanup();
2237}
2238
Harald Welte4f91c3b2020-12-09 12:25:51 +01002239/***********************************************************************
2240 * BVC-BLOCK / BVC-UNBLOCK procedure
2241 ***********************************************************************/
2242
Harald Welte239aa502020-11-24 23:14:20 +01002243private function f_block_ptp_bvc_from_pcu(integer pcu_idx, integer bvc_idx) runs on test_CT
2244{
2245 var BSSGP_BVC_CT bvc_ct := g_pcu[pcu_idx].vc_BSSGP_BVC[bvc_idx];
2246 var BssgpBvcConfig bvc_cfg := g_pcu[pcu_idx].cfg.bvc[bvc_idx];
2247 var Nsei nsei_pcu := g_pcu[pcu_idx].cfg.nsei;
2248
2249 SGSN_MGMT.clear;
2250 PCU_MGMT.clear;
2251
2252 /* block the PTP BVC from the PCU side */
2253 PCU_MGMT.send(BssgpBlockRequest:{cause:=BSSGP_CAUSE_OM_INTERVENTION}) to bvc_ct;
2254 /* expect state on both PCU and SGSN side to change */
2255 interleave {
2256 [] PCU_MGMT.receive(tr_BssgpStsInd(nsei_pcu, bvc_cfg.bvci, BVC_S_BLOCKED)) from bvc_ct;
2257 [] SGSN_MGMT.receive(tr_BssgpStsInd(*, bvc_cfg.bvci, BVC_S_BLOCKED));
2258 }
2259 setverdict(pass);
2260}
2261testcase TC_bvc_block_ptp() runs on test_CT
2262{
2263 f_init();
2264 f_sleep(1.0);
2265 f_block_ptp_bvc_from_pcu(0, 0);
2266 f_cleanup();
2267}
2268
2269private function f_unblock_ptp_bvc_from_pcu(integer pcu_idx, integer bvc_idx) runs on test_CT
2270{
2271 var BSSGP_BVC_CT bvc_ct := g_pcu[pcu_idx].vc_BSSGP_BVC[bvc_idx];
2272 var BssgpBvcConfig bvc_cfg := g_pcu[pcu_idx].cfg.bvc[bvc_idx];
2273 var Nsei nsei_pcu := g_pcu[pcu_idx].cfg.nsei;
2274
2275 SGSN_MGMT.clear;
2276 PCU_MGMT.clear;
2277
2278 /* block the PTP BVC from the PCU side */
2279 PCU_MGMT.send(BssgpUnblockRequest:{}) to bvc_ct;
2280 /* expect state on both PCU and SGSN side to change */
2281 interleave {
2282 [] PCU_MGMT.receive(tr_BssgpStsInd(nsei_pcu, bvc_cfg.bvci, BVC_S_UNBLOCKED)) from bvc_ct;
2283 [] SGSN_MGMT.receive(tr_BssgpStsInd(*, bvc_cfg.bvci, BVC_S_UNBLOCKED));
2284 }
2285 setverdict(pass);
2286}
2287testcase TC_bvc_unblock_ptp() runs on test_CT
2288{
2289 f_init();
2290 f_sleep(1.0);
2291 f_block_ptp_bvc_from_pcu(0, 0);
2292 f_sleep(1.0);
2293 f_unblock_ptp_bvc_from_pcu(0, 0);
2294 f_cleanup();
2295}
2296
Harald Welte4f91c3b2020-12-09 12:25:51 +01002297/***********************************************************************
2298 * BVC-RESET procedure
2299 ***********************************************************************/
2300
Harald Welte60a8ec72020-11-25 17:12:53 +01002301private altstep as_ignore_status(BSSGP_BVC_MGMT_PT pt) {
2302[] pt.receive(BssgpStatusIndication:?) { repeat; }
2303}
2304private function f_get_sgsn_bvc_ct(integer sgsn_idx, BssgpBvci bvci) runs on test_CT return BSSGP_BVC_CT {
2305 for (var integer i := 0; i < lengthof(g_sgsn[sgsn_idx].cfg.bvc); i := i+1) {
2306 if (g_sgsn[sgsn_idx].cfg.bvc[i].bvci == bvci) {
2307 return g_sgsn[sgsn_idx].vc_BSSGP_BVC[i];
2308 }
2309 }
2310 return null;
2311}
2312private function f_reset_ptp_bvc_from_pcu(integer pcu_idx, integer bvc_idx) runs on test_CT
2313{
2314 var BSSGP_BVC_CT pcu_bvc_ct := g_pcu[pcu_idx].vc_BSSGP_BVC[bvc_idx];
2315 var BssgpBvcConfig bvc_cfg := g_pcu[pcu_idx].cfg.bvc[bvc_idx];
2316 var Nsei nsei_pcu := g_pcu[pcu_idx].cfg.nsei;
2317 var BSSGP_BVC_CT sgsn_bvc_ct := f_get_sgsn_bvc_ct(0, bvc_cfg.bvci);
2318 var default d;
2319
2320 SGSN_MGMT.clear;
2321 PCU_MGMT.clear;
2322
2323 /* block the PTP BVC from the PCU side */
2324 PCU_MGMT.send(BssgpResetRequest:{cause:=BSSGP_CAUSE_OM_INTERVENTION}) to pcu_bvc_ct;
2325 /* expect state on both PCU and SGSN side to change */
2326 d := activate(as_ignore_status(SGSN_MGMT));
2327 interleave {
2328 [] PCU_MGMT.receive(tr_BssgpStsInd(nsei_pcu, bvc_cfg.bvci, BVC_S_BLOCKED)) from pcu_bvc_ct;
2329 [] SGSN_MGMT.receive(BssgpResetIndication:{bvc_cfg.bvci}) from sgsn_bvc_ct;
2330 }
2331 deactivate(d);
2332 setverdict(pass);
2333}
2334/* Send a BVC-RESET for a PTP BVC from the BSS side: expect it to propagate */
2335testcase TC_bvc_reset_ptp_from_bss() runs on test_CT
2336{
2337 f_init();
2338 f_sleep(3.0);
2339 f_reset_ptp_bvc_from_pcu(0, 0);
2340 f_cleanup();
2341}
2342
Harald Welte16786e92020-11-27 19:11:56 +01002343private altstep as_count_bvc_block(integer sgsn_idx, BssgpBvci bvci, inout ro_integer roi)
2344runs on test_CT {
2345 var BSSGP_BVC_CT sgsn_bvc_ct := f_get_sgsn_bvc_ct(sgsn_idx, bvci);
2346 [] SGSN_MGMT.receive(tr_BssgpStsInd(?, bvci, BVC_S_BLOCKED)) from sgsn_bvc_ct {
2347 roi := roi & { bvci };
Harald Welteb2647f72020-12-07 14:36:35 +01002348 repeat;
Harald Welte16786e92020-11-27 19:11:56 +01002349 }
2350}
2351/* reset the signaling BVC from one BSS; expect no signaling BVC reset on SGSN; but BVC-BLOCK for PTP */
2352testcase TC_bvc_reset_sig_from_bss() runs on test_CT {
2353
2354 f_init();
2355 f_sleep(3.0);
2356
2357 /* Start BVC-RESET procedure for BVCI=0 */
2358 PCU_MGMT.send(BssgpResetRequest:{cause:=BSSGP_CAUSE_OM_INTERVENTION}) to g_pcu[0].vc_BSSGP;
2359
2360 /* Activate altsteps: One for each PTP BVC within that PCUs NSE */
2361 var ro_default defaults := {};
2362 for (var integer i := 0; i < lengthof(g_pcu[0].cfg.bvc); i := i+1) {
2363 var BssgpBvcConfig bvcc := g_pcu[0].cfg.bvc[i];
2364 var default d := activate(as_count_bvc_block(0, bvcc.bvci, g_roi));
2365 defaults := defaults & { d };
2366 }
2367
2368 timer T := 3.0;
2369 T.start;
2370 alt {
2371 [] SGSN_MGMT.receive(BssgpResetIndication:{0}) {
2372 setverdict(fail, "BSS-side Reset of BVCI=0 should not propagate");
2373 }
2374 [] T.timeout;
2375 }
2376
2377 for (var integer i := 0; i < lengthof(defaults); i := i+1) {
2378 deactivate(defaults[i]);
2379 }
2380
2381 /* check if BVC-block was received on all expected BVC */
2382 for (var integer i := 0; i < lengthof(g_pcu[0].cfg.bvc); i := i+1) {
2383 var BssgpBvcConfig bvcc := g_pcu[0].cfg.bvc[i];
2384 if (not ro_integer_contains(g_roi, bvcc.bvci)) {
2385 setverdict(fail, "Missing SGSN-side BVC-BLOCK of BVCI=", bvcc.bvci);
2386 }
2387 }
2388
2389 /* check if BVC-block was not received on any unexpected BVC is not required as
2390 * such a message would basically run into 'no matching clause' */
Daniel Willmannf2590212020-12-04 14:20:50 +01002391 setverdict(pass);
Harald Welte16786e92020-11-27 19:11:56 +01002392 f_cleanup();
2393}
2394
Harald Welte60a8ec72020-11-25 17:12:53 +01002395private function f_reset_ptp_bvc_from_sgsn(integer pcu_idx, integer bvc_idx) runs on test_CT
2396{
2397 var BSSGP_BVC_CT pcu_bvc_ct := g_pcu[pcu_idx].vc_BSSGP_BVC[bvc_idx];
2398 var BssgpBvcConfig bvc_cfg := g_pcu[pcu_idx].cfg.bvc[bvc_idx];
2399 var Nsei nsei_pcu := g_pcu[pcu_idx].cfg.nsei;
2400 var BSSGP_BVC_CT sgsn_bvc_ct := f_get_sgsn_bvc_ct(0, bvc_cfg.bvci);
2401 var default d;
2402
2403 SGSN_MGMT.clear;
2404 PCU_MGMT.clear;
2405
2406 /* block the PTP BVC from the PCU side */
2407 SGSN_MGMT.send(BssgpResetRequest:{cause:=BSSGP_CAUSE_OM_INTERVENTION}) to sgsn_bvc_ct;
2408 /* expect state on both PCU and SGSN side to change */
2409 d := activate(as_ignore_status(PCU_MGMT));
2410 interleave {
2411 [] SGSN_MGMT.receive(tr_BssgpStsInd(?, bvc_cfg.bvci, BVC_S_BLOCKED)) from sgsn_bvc_ct;
2412 [] PCU_MGMT.receive(BssgpResetIndication:{bvc_cfg.bvci}) from pcu_bvc_ct;
2413 }
2414 deactivate(d);
2415 setverdict(pass);
2416}
2417/* Send a BVC-RESET for a PTP BVC from the SGSN side: expect it to propagate */
2418testcase TC_bvc_reset_ptp_from_sgsn() runs on test_CT
2419{
2420 f_init();
2421 f_sleep(3.0);
2422 f_reset_ptp_bvc_from_sgsn(0, 0);
2423 f_cleanup();
2424}
2425
Daniel Willmannef7015f2021-01-08 00:43:56 +01002426private altstep as_ignore_mgmt(BSSGP_BVC_MGMT_PT pt) {
2427 [] pt.receive {repeat; }
2428}
2429
Harald Welte16786e92020-11-27 19:11:56 +01002430private altstep as_count_bvc0_block(integer pcu_idx, Nsei nsei, inout ro_integer roi)
2431runs on test_CT {
2432 var BSSGP_CT pcu_ct := g_pcu[pcu_idx].vc_BSSGP;
2433 [] PCU_MGMT.receive(BssgpResetIndication:{0}) from pcu_ct {
2434 roi := roi & { nsei };
Daniel Willmannef7015f2021-01-08 00:43:56 +01002435 repeat;
Harald Welte16786e92020-11-27 19:11:56 +01002436 }
2437}
Daniel Willmannef7015f2021-01-08 00:43:56 +01002438
Harald Welte16786e92020-11-27 19:11:56 +01002439/* reset the signaling BVC from the SGSN; expect all signaling BVC on all BSS to be reset */
2440testcase TC_bvc_reset_sig_from_sgsn() runs on test_CT {
2441
2442 f_init();
2443 f_sleep(3.0);
2444
Daniel Willmannef7015f2021-01-08 00:43:56 +01002445 SGSN_MGMT.clear;
2446 PCU_MGMT.clear;
2447
Harald Welte16786e92020-11-27 19:11:56 +01002448 /* Start BVC-RESET procedure for BVCI=0 */
2449 SGSN_MGMT.send(BssgpResetRequest:{cause:=BSSGP_CAUSE_OM_INTERVENTION}) to g_sgsn[0].vc_BSSGP;
2450
Daniel Willmannef7015f2021-01-08 00:43:56 +01002451 /* Defaults match in reverse activation order, this one is a catch-all for Status indications
2452 * and reset indications sent from other components (like the ptp_bvcs). If we don't drain
2453 * the port and a different message sits at the front we wait forever and fail the test.
2454 */
2455 var ro_default defaults := { activate(as_ignore_mgmt(PCU_MGMT)) };
2456
Harald Welte16786e92020-11-27 19:11:56 +01002457 /* Activate altsteps: One for each PCU NSE */
Harald Welte16786e92020-11-27 19:11:56 +01002458 for (var integer i := 0; i < lengthof(g_pcu); i := i+1) {
2459 var NSConfiguration nscfg := mp_nsconfig_pcu[i];
2460 var default d := activate(as_count_bvc0_block(i, nscfg.nsei, g_roi));
2461 defaults := defaults & { d };
2462 }
2463
2464 f_sleep(3.0);
2465
2466 for (var integer i := 0; i < lengthof(defaults); i := i+1) {
2467 deactivate(defaults[i]);
2468 }
2469
2470 /* check if BVC-block was received on all expected BVC */
2471 for (var integer i := 0; i < lengthof(g_pcu); i := i+1) {
2472 var NSConfiguration nscfg := mp_nsconfig_pcu[i];
2473 if (not ro_integer_contains(g_roi, nscfg.nsei)) {
2474 setverdict(fail, "Missing PCU-side BVC-RESET of BVCI=0 on PCU index ", i);
2475 }
2476 }
2477
2478 /* check if BVC-block was not received on any unexpected BVC is not required as
2479 * such a message would basically run into 'no matching clause' */
2480
2481 f_cleanup();
2482}
2483
Harald Welte299aa482020-12-09 15:10:55 +01002484/***********************************************************************
2485 * FLOW-CONTROL-BVC procedure
2486 ***********************************************************************/
2487
2488private altstep as_g_count_sgsn(integer sgsn_idx, inout ro_integer roi,
2489 template PDU_BSSGP exp_rx, template (omit) PDU_BSSGP tx_reply)
2490runs on GlobalTest_CT {
2491 [] G_SGSN[sgsn_idx].receive(exp_rx) {
2492 roi := roi & { sgsn_idx };
2493 if (ispresent(tx_reply)) {
2494 G_SGSN[sgsn_idx].send(tx_reply);
2495 }
Harald Welte5fb01742021-01-15 21:07:52 +01002496 repeat;
Harald Welte299aa482020-12-09 15:10:55 +01002497 }
2498}
2499/* Send FC-BVC from simulated PCU; expect each SGSN to receive it; expect PCU to receive ACK */
2500testcase TC_fc_bvc() runs on GlobalTest_CT
2501{
2502 f_init();
2503 f_global_init_ptp();
2504
2505 var template (value) PDU_BSSGP pdu_tx := t_BVC_FC_BVC(10240, 2000, 1024, 1000, '01'O);
2506 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
2507 var template (present) PDU_BSSGP pdu_rx := tr_BVC_FC_BVC(10240, 2000, 1024, 1000, '01'O);
2508 var template (omit) PDU_BSSGP ack_tx :=
2509 t_BVC_FC_BVC_ACK(pdu_tx.pDU_BSSGP_FLOW_CONTROL_BVC.tag.unstructured_Value);
2510
2511 /* Send a FC-BVC from BSS to gbproxy, expect an ACK in response */
2512 G_PCU[0].send(pdu_tx);
2513
2514 /* Activate altsteps: One for each SGSN-side PTP BVC port */
2515 var ro_default defaults := {};
2516 for (var integer i := 0; i < lengthof(g_sgsn); i := i+1) {
2517 var default d := activate(as_g_count_sgsn(i, g_roi, pdu_rx, ack_tx));
2518 defaults := defaults & { d };
2519 }
2520
2521 f_sleep(3.0);
2522
2523 for (var integer i := 0; i < lengthof(defaults); i := i+1) {
2524 deactivate(defaults[i]);
2525 }
2526
2527 /* check if BVC-block was received on all expected BVC */
2528 for (var integer i := 0; i < lengthof(g_sgsn); i := i+1) {
2529 if (not ro_integer_contains(g_roi, i)) {
2530 setverdict(fail, "Missing BVC-FLOW-CONTROL on SGSN index ", i);
2531 }
2532 }
2533
2534 /* Expect ACK on PCU side */
2535 G_PCU[0].receive(ack_tx);
2536
2537 setverdict(pass);
2538
2539 f_cleanup();
2540}
2541
Harald Weltecc3894b2020-12-09 16:50:12 +01002542/***********************************************************************
2543 * FLOW-CONTROL-MS procedure
2544 ***********************************************************************/
2545
2546private function f_TC_fc_ms(charstring id) runs on BSSGP_ConnHdlr {
2547 var BssgpBvci bvci := g_pars.pcu[0].cfg.bvc[0].bvci;
2548
2549 var template (value) PDU_BSSGP fc_tx := ts_BVC_FC_MS(g_pars.tlli, 100, 200, '12'O);
2550 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
2551 var template (present) PDU_BSSGP fc_rx := tr_BVC_FC_MS(g_pars.tlli, 100, 200, '12'O);
2552 var template (value) PDU_BSSGP ack_tx := ts_BVC_FC_MS_ACK(g_pars.tlli, '12'O);
2553
2554 f_pcu2sgsn(fc_tx, fc_rx, use_sig := false);
2555 f_sgsn2pcu(ack_tx, ack_tx, use_sig := false);
2556
2557 setverdict(pass);
2558}
2559/* Send a FLOW-CONTROL-MS from BSS side and expect it to show up on SGSN (PTP BVC) */
2560testcase TC_fc_ms() runs on test_CT
2561{
Harald Weltecc3894b2020-12-09 16:50:12 +01002562 f_init();
Harald Welte2ecbca82021-01-16 11:23:09 +01002563 f_start_handlers(refers(f_TC_fc_ms), testcasename(), 21);
Harald Weltecc3894b2020-12-09 16:50:12 +01002564 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
Harald Weltecc3894b2020-12-09 16:50:12 +01002565 f_cleanup();
2566}
2567
Harald Welted6f89812021-01-16 18:57:49 +01002568/***********************************************************************
2569 * MS-REGISTRATION ENQUIRY procedure
2570 ***********************************************************************/
Harald Weltecc3894b2020-12-09 16:50:12 +01002571
Harald Welted6f89812021-01-16 18:57:49 +01002572private function f_TC_ms_reg_enq(charstring id) runs on BSSGP_ConnHdlr
2573{
2574 f_pcu2sgsn(ts_BSSGP_MS_REG_ENQ(g_pars.imsi), tr_BSSGP_MS_REG_ENQ(g_pars.imsi), use_sig := true);
2575 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);
2576}
2577testcase TC_ms_reg_enq() runs on test_CT
2578{
2579 f_init();
2580 f_start_handlers(refers(f_TC_ms_reg_enq), testcasename(), 22);
2581 f_cleanup();
2582}
Harald Welte299aa482020-12-09 15:10:55 +01002583
Daniel Willmann423d8f42020-09-08 18:58:22 +02002584control {
2585 execute( TC_BVC_bringup() );
Harald Welte92686012020-11-15 21:45:49 +01002586 execute( TC_ul_unitdata() );
Harald Welte78d8db92020-11-15 23:27:27 +01002587 execute( TC_dl_unitdata() );
Harald Welte6dc2ac42020-11-16 09:16:17 +01002588 execute( TC_ra_capability() );
Daniel Willmannace3ece2020-11-16 19:53:26 +01002589 execute( TC_ra_capability_upd() );
Daniel Willmann165d6612020-11-19 14:27:29 +01002590 execute( TC_radio_status() );
Daniel Willmannfa67f492020-11-19 15:48:05 +01002591 execute( TC_suspend() );
Daniel Willmann087a33d2020-11-19 15:58:43 +01002592 execute( TC_resume() );
Harald Weltef8e5c5d2020-11-27 22:37:23 +01002593 execute( TC_trace() );
Harald Weltec0351d12020-11-27 22:49:02 +01002594 execute( TC_llc_discarded() );
Harald Weltef20af412020-11-28 16:11:11 +01002595 execute( TC_overload() );
Harald Welte239aa502020-11-24 23:14:20 +01002596 execute( TC_bvc_block_ptp() );
2597 execute( TC_bvc_unblock_ptp() );
Harald Welte60a8ec72020-11-25 17:12:53 +01002598 execute( TC_bvc_reset_ptp_from_bss() );
Harald Welte16786e92020-11-27 19:11:56 +01002599 execute( TC_bvc_reset_sig_from_bss() );
Harald Welte60a8ec72020-11-25 17:12:53 +01002600 execute( TC_bvc_reset_ptp_from_sgsn() );
Harald Welte16786e92020-11-27 19:11:56 +01002601 execute( TC_bvc_reset_sig_from_sgsn() );
Harald Weltef6e59b02020-12-08 08:29:09 +01002602 if (mp_enable_bss_load_sharing) {
Harald Weltef8ef0282020-11-18 12:16:59 +01002603 /* don't enable this by default, as we don't yet have any automatic test setup for FR with 4 NS-VC */
2604 execute( TC_load_sharing_dl() );
2605 }
Harald Welte0e188242020-11-22 21:46:48 +01002606
2607 /* PAGING-PS over PTP BVC */
2608 execute( TC_paging_ps_ptp_bss() );
2609 execute( TC_paging_ps_ptp_lac() );
Harald Welte7462a592020-11-23 22:07:07 +01002610 execute( TC_paging_ps_ptp_lac_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01002611 execute( TC_paging_ps_ptp_rac() );
Harald Welte7462a592020-11-23 22:07:07 +01002612 execute( TC_paging_ps_ptp_rac_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01002613 execute( TC_paging_ps_ptp_bvci() );
Harald Welteb5a04aa2021-01-16 13:04:40 +01002614 execute( TC_paging_ps_ptp_bvci_imsi() );
Harald Welte7462a592020-11-23 22:07:07 +01002615 execute( TC_paging_ps_ptp_bvci_unknown() );
Harald Weltecf200072021-01-16 15:20:46 +01002616 execute( TC_paging_ps_reject_ptp_bvci() );
2617 execute( TC_paging_ps_reject_ptp_bvci_imsi() );
Harald Welte7595d562021-01-16 19:09:20 +01002618 execute( TC_dummy_paging_ps_ptp() );
Harald Welte0e188242020-11-22 21:46:48 +01002619
2620 /* PAGING-PS over SIG BVC */
2621 execute( TC_paging_ps_sig_bss() );
2622 execute( TC_paging_ps_sig_lac() );
Harald Welte7462a592020-11-23 22:07:07 +01002623 execute( TC_paging_ps_sig_lac_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01002624 execute( TC_paging_ps_sig_rac() );
Harald Welte7462a592020-11-23 22:07:07 +01002625 execute( TC_paging_ps_sig_rac_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01002626 execute( TC_paging_ps_sig_bvci() );
Harald Welteb5a04aa2021-01-16 13:04:40 +01002627 execute( TC_paging_ps_sig_bvci_imsi() );
Harald Welte7462a592020-11-23 22:07:07 +01002628 execute( TC_paging_ps_sig_bvci_unknown() );
Harald Weltecf200072021-01-16 15:20:46 +01002629 execute( TC_paging_ps_reject_sig_bvci() );
2630 execute( TC_paging_ps_reject_sig_bvci_imsi() );
Harald Welte7595d562021-01-16 19:09:20 +01002631 execute( TC_dummy_paging_ps_sig() );
Harald Welte0e188242020-11-22 21:46:48 +01002632
2633 /* PAGING-CS over PTP BVC */
2634 execute( TC_paging_cs_ptp_bss() );
2635 execute( TC_paging_cs_ptp_lac() );
Harald Welte7462a592020-11-23 22:07:07 +01002636 execute( TC_paging_cs_ptp_lac_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01002637 execute( TC_paging_cs_ptp_rac() );
Harald Welte7462a592020-11-23 22:07:07 +01002638 execute( TC_paging_cs_ptp_rac_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01002639 execute( TC_paging_cs_ptp_bvci() );
Harald Welte7462a592020-11-23 22:07:07 +01002640 execute( TC_paging_cs_ptp_bvci_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01002641
2642 /* PAGING-CS over SIG BVC */
2643 execute( TC_paging_cs_sig_bss() );
2644 execute( TC_paging_cs_sig_lac() );
Harald Welte7462a592020-11-23 22:07:07 +01002645 execute( TC_paging_cs_sig_lac_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01002646 execute( TC_paging_cs_sig_rac() );
Harald Welte7462a592020-11-23 22:07:07 +01002647 execute( TC_paging_cs_sig_rac_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01002648 execute( TC_paging_cs_sig_bvci() );
Harald Welte7462a592020-11-23 22:07:07 +01002649 execute( TC_paging_cs_sig_bvci_unknown() );
Harald Welte0e188242020-11-22 21:46:48 +01002650
2651
Daniel Willmann91a8e25b2020-11-24 14:50:59 +01002652 execute( TC_flush_ll() );
Harald Welte299aa482020-12-09 15:10:55 +01002653 execute( TC_fc_bvc() );
Harald Weltecc3894b2020-12-09 16:50:12 +01002654 execute( TC_fc_ms() );
Harald Welted6f89812021-01-16 18:57:49 +01002655 execute( TC_ms_reg_enq() );
Daniel Willmann423d8f42020-09-08 18:58:22 +02002656}
2657
2658
2659}