blob: bf777cc87dece02165db004479d720aeafc2c95f [file] [log] [blame]
Daniel Willmann423d8f42020-09-08 18:58:22 +02001module GBProxy_Tests {
2
3/* Osmocom GBProxy test suite in TTCN-3
4 * (C) 2020 sysmocom - s.f.m.c. GmbH
5 * All rights reserved.
6 *
7 * Author: Daniel Willmann <dwillmann@sysmocom.de>
8
9 * Released under the terms of GNU General Public License, Version 2 or
10 * (at your option) any later version.
11 *
12 * SPDX-License-Identifier: GPL-2.0-or-later
13 */
14
15import from General_Types all;
16import from Osmocom_Types all;
17import from GSM_Types all;
18import from Native_Functions all;
19import from NS_Types all;
20import from NS_Emulation all;
21import from BSSGP_Types all;
22import from BSSGP_Emulation all;
23import from SCCPasp_Types all;
24import from Osmocom_Gb_Types all;
25
26import from MobileL3_CommonIE_Types all;
27import from MobileL3_GMM_SM_Types all;
28import from MobileL3_Types all;
29import from L3_Templates all;
30import from L3_Common all;
31
32import from TELNETasp_PortType all;
33import from Osmocom_VTY_Functions all;
34
35import from LLC_Types all;
36import from LLC_Templates all;
37
38import from GSM_RR_Types all;
39
Harald Welte6d63f742020-11-15 19:44:04 +010040/* mcc_mnc is 24.008 10.5.5.15 encoded. 262 42 */
41const BcdMccMnc c_mcc_mnc := '262F42'H;
42
Daniel Willmann423d8f42020-09-08 18:58:22 +020043modulepar {
44 /* IP/port on which we run our internal GSUP/HLR emulation */
Harald Welte6d63f742020-11-15 19:44:04 +010045 NSConfigurations mp_nsconfig_sgsn := {
Daniel Willmann423d8f42020-09-08 18:58:22 +020046 {
Daniel Willmann423d8f42020-09-08 18:58:22 +020047 nsei := 101,
48 role_sgsn := true,
Harald Welte90f19742020-11-06 19:34:40 +010049 handle_sns := false,
50 nsvc := {
51 {
52 provider := {
53 ip := {
54 address_family := AF_INET,
55 local_udp_port := 7777,
56 local_ip := "127.0.0.1",
57 remote_udp_port := 23000,
58 remote_ip := "127.0.0.1"
59 }
60 },
61 nsvci := 101
62 }
63 }
Daniel Willmann423d8f42020-09-08 18:58:22 +020064 }
65 };
Harald Welte6d63f742020-11-15 19:44:04 +010066 NSConfigurations mp_nsconfig_pcu := {
Daniel Willmann423d8f42020-09-08 18:58:22 +020067 {
Daniel Willmann423d8f42020-09-08 18:58:22 +020068 nsei := 96,
69 role_sgsn := false,
Harald Welte90f19742020-11-06 19:34:40 +010070 handle_sns := false,
71 nsvc := {
72 {
73 provider := {
74 ip := {
75 address_family := AF_INET,
76 local_udp_port := 21010,
77 local_ip := "127.0.0.1",
78 remote_udp_port := 23000,
79 remote_ip := "127.0.0.1"
80 }
81 },
82 nsvci := 97
83 }
84 }
Daniel Willmann423d8f42020-09-08 18:58:22 +020085 },
86 {
Daniel Willmann423d8f42020-09-08 18:58:22 +020087 nsei := 97,
88 role_sgsn := false,
Harald Welte90f19742020-11-06 19:34:40 +010089 handle_sns := false,
90 nsvc := {
91 {
92 provider := {
93 ip := {
94 address_family := AF_INET,
95 local_udp_port := 21011,
96 local_ip := "127.0.0.1",
97 remote_udp_port := 23000,
98 remote_ip := "127.0.0.1"
99 }
100 },
101 nsvci := 98
102 }
103 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200104 },
105 {
Daniel Willmann423d8f42020-09-08 18:58:22 +0200106 nsei := 98,
107 role_sgsn := false,
Harald Welte90f19742020-11-06 19:34:40 +0100108 handle_sns := false,
109 nsvc := {
110 {
111 provider := {
112 ip := {
113 address_family := AF_INET,
114 local_udp_port := 21012,
115 local_ip := "127.0.0.1",
116 remote_udp_port := 23000,
117 remote_ip := "127.0.0.1"
118 }
119 },
120 nsvci := 99
121 }
122 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200123 }
124 };
Harald Welte6d63f742020-11-15 19:44:04 +0100125 BssgpConfigs mp_gbconfigs := {
126 {
127 nsei := 96,
128 sgsn_role := false,
129 bvc := {
130 {
131 bvci := 196,
132 cell_id := {
133 ra_id := {
134 lai := {
135 mcc_mnc := c_mcc_mnc,
136 lac := 13135
137 },
138 rac := 0
139 },
140 cell_id := 20960
141 },
142 depth := BSSGP_DECODE_DEPTH_BSSGP,
143 create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
144 }
145 }
146 }, {
147 nsei := 97,
148 sgsn_role := false,
149 bvc := {
150 {
151 bvci := 210,
152 cell_id := {
153 ra_id := {
154 lai := {
155 mcc_mnc := c_mcc_mnc,
156 lac := 13200
157 },
158 rac := 0
159 },
160 cell_id := 20961
161 },
162 depth := BSSGP_DECODE_DEPTH_BSSGP,
163 create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
164 }
165 }
166 }, {
167 nsei := 98,
168 sgsn_role := false,
169 bvc := {
170 {
171 bvci := 220,
172 cell_id := {
173 ra_id := {
174 lai := {
175 mcc_mnc := c_mcc_mnc,
176 lac := 13300
177 },
178 rac := 0
179 },
180 cell_id := 20962
181 },
182 depth := BSSGP_DECODE_DEPTH_BSSGP,
183 create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
184 }
185 }
186 }
187 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200188};
189
Daniel Willmann423d8f42020-09-08 18:58:22 +0200190type record GbInstance {
191 NS_CT vc_NS,
192 BSSGP_CT vc_BSSGP,
Harald Welte67dc8c22020-11-17 18:32:29 +0100193 BSSGP_BVC_CTs vc_BSSGP_BVC,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200194 BssgpConfig cfg
195};
Harald Welte67dc8c22020-11-17 18:32:29 +0100196type record of BSSGP_BVC_CT BSSGP_BVC_CTs
Daniel Willmann423d8f42020-09-08 18:58:22 +0200197
198const integer NUM_PCU := 3;
Harald Welte6d63f742020-11-15 19:44:04 +0100199type record of GbInstance GbInstances;
200type record of BssgpConfig BssgpConfigs;
201type record of NSConfiguration NSConfigurations;
202type record of BssgpCellId BssgpCellIds;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200203
204const integer NUM_SGSN := 1;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200205
206type component test_CT {
Harald Welte6d63f742020-11-15 19:44:04 +0100207 var GbInstances g_pcu;
208 var GbInstances g_sgsn;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200209
210 port BSSGP_CT_PROC_PT PROC;
211
Harald Weltefbae83f2020-11-15 23:25:55 +0100212 port BSSGP_BVC_MGMT_PT SGSN_MGMT;
213 port BSSGP_BVC_MGMT_PT PCU_MGMT;
214
Daniel Willmann423d8f42020-09-08 18:58:22 +0200215 port TELNETasp_PT GBPVTY;
216
217 var boolean g_initialized := false;
218 var boolean g_use_echo := false;
219};
220
221type component BSSGP_ConnHdlr {
Harald Welte3dd21b32020-11-17 19:21:00 +0100222 /* array of per-BVC ports on the PCU side */
Daniel Willmann423d8f42020-09-08 18:58:22 +0200223 port BSSGP_PT PCU[NUM_PCU];
224 port BSSGP_PT PCU_SIG[NUM_PCU];
225 port BSSGP_PROC_PT PCU_PROC[NUM_PCU];
Harald Welte3dd21b32020-11-17 19:21:00 +0100226 /* component reference to the component to which we're currently connected */
227 var BSSGP_BVC_CT pcu_ct[NUM_PCU];
228
229 /* array of per-BVC ports on the SGSN side */
Daniel Willmann423d8f42020-09-08 18:58:22 +0200230 port BSSGP_PT SGSN[NUM_SGSN];
231 port BSSGP_PT SGSN_SIG[NUM_SGSN];
232 port BSSGP_PROC_PT SGSN_PROC[NUM_SGSN];
Harald Welte3dd21b32020-11-17 19:21:00 +0100233 /* component reference to the component to which we're currently connected */
234 var BSSGP_BVC_CT sgsn_ct[NUM_PCU];
Daniel Willmann423d8f42020-09-08 18:58:22 +0200235
236 var BSSGP_ConnHdlrPars g_pars;
237 timer g_Tguard;
238 var LLC_Entities llc;
239}
240
241type record SGSN_ConnHdlrNetworkPars {
242 boolean expect_ptmsi,
243 boolean expect_auth,
244 boolean expect_ciph
245};
246
247type record BSSGP_ConnHdlrPars {
248 /* IMEI of the simulated ME */
249 hexstring imei,
250 /* IMSI of the simulated MS */
251 hexstring imsi,
252 /* MSISDN of the simulated MS (probably unused) */
253 hexstring msisdn,
254 /* P-TMSI allocated to the simulated MS */
255 OCT4 p_tmsi optional,
256 OCT3 p_tmsi_sig optional,
257 /* TLLI of the simulated MS */
258 OCT4 tlli,
259 OCT4 tlli_old optional,
260 RoutingAreaIdentificationV ra optional,
Harald Welte16357a92020-11-17 18:20:00 +0100261 GbInstances pcu,
Harald Welte3dd21b32020-11-17 19:21:00 +0100262 GbInstances sgsn,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200263 float t_guard
264};
265
266private function f_cellid_to_RAI(in BssgpCellId cell_id) return RoutingAreaIdentificationV {
267 /* mcc_mnc is encoded as of 24.008 10.5.5.15 */
268 var BcdMccMnc mcc_mnc := cell_id.ra_id.lai.mcc_mnc;
269
270 var RoutingAreaIdentificationV ret := {
271 mccDigit1 := mcc_mnc[0],
272 mccDigit2 := mcc_mnc[1],
273 mccDigit3 := mcc_mnc[2],
274 mncDigit3 := mcc_mnc[3],
275 mncDigit1 := mcc_mnc[4],
276 mncDigit2 := mcc_mnc[5],
277 lac := int2oct(cell_id.ra_id.lai.lac, 16),
278 rac := int2oct(cell_id.ra_id.rac, 8)
279 }
280 return ret;
281};
282
283private function f_init_gb_pcu(inout GbInstance gb, charstring id, integer offset) runs on test_CT {
Harald Welteb419d0e2020-11-16 16:45:05 +0100284 var charstring ns_id := id & "-NS(PCU[" & int2str(offset) & "])";
285 var charstring bssgp_id := id & "-BSSGP(PCU[" & int2str(offset) & "])";
286 gb.vc_NS := NS_CT.create(ns_id);
287 gb.vc_BSSGP := BSSGP_CT.create(bssgp_id);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200288 /* connect lower end of BSSGP emulation with NS upper port */
289 connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
290
Harald Welteb419d0e2020-11-16 16:45:05 +0100291 gb.vc_NS.start(NSStart(mp_nsconfig_pcu[offset], ns_id));
292 gb.vc_BSSGP.start(BssgpStart(gb.cfg, bssgp_id));
Daniel Willmann423d8f42020-09-08 18:58:22 +0200293
294 for (var integer i := 0; i < lengthof(gb.cfg.bvc); i := i + 1) {
295 connect(self:PROC, gb.vc_BSSGP:PROC);
296 gb.vc_BSSGP_BVC[i] := f_bssgp_get_bvci_ct(gb.cfg.bvc[i].bvci, PROC);
297 disconnect(self:PROC, gb.vc_BSSGP:PROC);
Harald Weltefbae83f2020-11-15 23:25:55 +0100298 connect(self:PCU_MGMT, gb.vc_BSSGP_BVC[i]:MGMT);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200299 }
300}
301
302private function f_init_gb_sgsn(inout GbInstance gb, charstring id, integer offset) runs on test_CT {
Harald Welteb419d0e2020-11-16 16:45:05 +0100303 var charstring ns_id := id & "-NS(SGSN[" & int2str(offset) & "])";
304 var charstring bssgp_id := id & "-BSSGP(SGSN[" & int2str(offset) & "])";
305 gb.vc_NS := NS_CT.create(ns_id);
306 gb.vc_BSSGP := BSSGP_CT.create(bssgp_id);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200307 /* connect lower end of BSSGP emulation with NS upper port */
308 connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
309
Harald Welteb419d0e2020-11-16 16:45:05 +0100310 gb.vc_NS.start(NSStart(mp_nsconfig_sgsn[offset], ns_id));
311 gb.vc_BSSGP.start(BssgpStart(gb.cfg, bssgp_id));
Daniel Willmann423d8f42020-09-08 18:58:22 +0200312
313 for (var integer i := 0; i < lengthof(gb.cfg.bvc); i := i + 1) {
314 connect(self:PROC, gb.vc_BSSGP:PROC);
315 gb.vc_BSSGP_BVC[i] := f_bssgp_get_bvci_ct(gb.cfg.bvc[i].bvci, PROC);
316 disconnect(self:PROC, gb.vc_BSSGP:PROC);
Harald Weltefbae83f2020-11-15 23:25:55 +0100317 connect(self:SGSN_MGMT, gb.vc_BSSGP_BVC[i]:MGMT);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200318 }
319}
320
321
322private function f_init_vty() runs on test_CT {
323 map(self:GBPVTY, system:GBPVTY);
324 f_vty_set_prompts(GBPVTY);
325 f_vty_transceive(GBPVTY, "enable");
326}
327
Harald Weltefbae83f2020-11-15 23:25:55 +0100328type record of integer ro_integer;
329
330private function ro_integer_contains(ro_integer r, integer x) return boolean {
331 for (var integer j := 0; j < lengthof(r); j := j+1) {
332 if (r[j] == x) {
333 return true;
334 }
335 }
336 return false;
337}
338
Harald Welte6d63f742020-11-15 19:44:04 +0100339function f_init() runs on test_CT {
Harald Weltefbae83f2020-11-15 23:25:55 +0100340 var ro_integer bvci_unblocked := {};
341 var BssgpStatusIndication bsi;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200342 var integer i;
343
344 if (g_initialized == true) {
345 return;
346 }
347 g_initialized := true;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200348
349 g_sgsn[0].cfg := {
Harald Welte6d63f742020-11-15 19:44:04 +0100350 nsei := mp_nsconfig_sgsn[0].nsei,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200351 sgsn_role := true,
Harald Welte6d63f742020-11-15 19:44:04 +0100352 bvc := { }
353 }
354 for (i := 0; i < lengthof(mp_gbconfigs); i := i+1) {
355 g_pcu[i].cfg := mp_gbconfigs[i];
356 /* concatenate all the PCU-side BVCs for the SGSN side */
357 g_sgsn[0].cfg.bvc := g_sgsn[0].cfg.bvc & mp_gbconfigs[i].bvc;
358 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200359
360 f_init_vty();
Harald Welte6d63f742020-11-15 19:44:04 +0100361 for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
Daniel Willmann443fc572020-11-18 13:26:57 +0100362 f_vty_transceive(GBPVTY, "nsvc nsei " & int2str(g_sgsn[i].cfg.nsei) & " force-unconfigured");
Harald Welteea1ba592020-11-17 18:05:13 +0100363 f_init_gb_sgsn(g_sgsn[i], "GbProxy_Test", i);
Harald Welte6d63f742020-11-15 19:44:04 +0100364 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200365 f_sleep(4.0);
Harald Welte6d63f742020-11-15 19:44:04 +0100366 for (i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
Harald Welteb419d0e2020-11-16 16:45:05 +0100367 f_init_gb_pcu(g_pcu[i], "GbProxy_Test", i);
Harald Welte6d63f742020-11-15 19:44:04 +0100368 }
Harald Weltefbae83f2020-11-15 23:25:55 +0100369
370 /* wait until all BVC are unblocked on both sides */
Harald Welted2801272020-11-17 19:22:58 +0100371 timer T := 15.0;
Harald Weltefbae83f2020-11-15 23:25:55 +0100372 T.start;
373 alt {
374 [] SGSN_MGMT.receive(BssgpStatusIndication:{*, ?, BVC_S_UNBLOCKED}) -> value bsi {
375 bvci_unblocked := bvci_unblocked & { bsi.bvci };
376 if (lengthof(bvci_unblocked) != lengthof(g_sgsn[0].cfg.bvc)) {
377 repeat;
378 }
379 }
380 [] SGSN_MGMT.receive(BssgpStatusIndication:{*, ?, ?}) {
381 repeat;
382 }
383 [] SGSN_MGMT.receive {
384 setverdict(fail, "Received unexpected message on SGSN_MGMT");
385 mtc.stop;
386 }
387
388 [] PCU_MGMT.receive(BssgpStatusIndication:{*, ?, BVC_S_UNBLOCKED}) -> value bsi {
389 repeat;
390 }
391 [] PCU_MGMT.receive(BssgpStatusIndication:{*, ?, ?}) {
392 repeat;
393 }
394 [] PCU_MGMT.receive(BssgpResetIndication:{0}) {
395 repeat;
396 }
397 [] PCU_MGMT.receive {
398 setverdict(fail, "Received unexpected message on PCU_MGMT");
399 mtc.stop;
400 }
401
402 [] T.timeout {
403 setverdict(fail, "Timeout waiting for unblock of all BVCs");
404 mtc.stop;
405 }
406 }
407
408 /* iterate over list and check all BVCI */
409 for (i := 0; i < lengthof(g_sgsn[0].cfg.bvc); i := i+1) {
410 var BssgpBvci bvci := g_sgsn[0].cfg.bvc[i].bvci;
411 if (not ro_integer_contains(bvci_unblocked, bvci)) {
412 setverdict(fail, "BVCI=", bvci, " was not unblocked during start-up");
413 mtc.stop;
414 }
415 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200416}
417
418function f_cleanup() runs on test_CT {
419 self.stop;
420}
421
422type function void_fn(charstring id) runs on BSSGP_ConnHdlr;
423
424/* helper function to create, connect and start a BSSGP_ConnHdlr component */
Harald Welte6d63f742020-11-15 19:44:04 +0100425function f_start_handler(void_fn fn, charstring id, GbInstances pcu, GbInstances sgsn, integer imsi_suffix,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200426 float t_guard := 30.0)
427runs on test_CT return BSSGP_ConnHdlr {
428 var BSSGP_ConnHdlr vc_conn;
429
430 var BSSGP_ConnHdlrPars pars := {
431 imei := f_gen_imei(imsi_suffix),
432 imsi := f_gen_imsi(imsi_suffix),
433 msisdn := f_gen_msisdn(imsi_suffix),
434 p_tmsi := omit,
435 p_tmsi_sig := omit,
436 tlli := f_gprs_tlli_random(),
437 tlli_old := omit,
438 ra := omit,
Harald Welte16357a92020-11-17 18:20:00 +0100439 pcu := g_pcu,
Harald Welte3dd21b32020-11-17 19:21:00 +0100440 sgsn := g_sgsn,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200441 t_guard := t_guard
442 };
443
444 vc_conn := BSSGP_ConnHdlr.create(id);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200445
446 vc_conn.start(f_handler_init(fn, id, pars));
447 return vc_conn;
448}
449
Harald Welte3dd21b32020-11-17 19:21:00 +0100450/* Connect the PCU-side per-BVC ports (PCU/PCU_SIG/PCU_PROC) array slot 'port_idx' to specified per-BVC component */
451private function f_connect_to_pcu_bvc(integer port_idx, BSSGP_BVC_CT bvc_ct) runs on BSSGP_ConnHdlr {
452 if (PCU[port_idx].checkstate("Connected")) {
453 /* unregister + disconnect from old BVC */
454 f_client_unregister(g_pars.imsi, PCU_PROC[port_idx]);
455 disconnect(self:PCU[port_idx], pcu_ct[port_idx]:BSSGP_SP);
456 disconnect(self:PCU_SIG[port_idx], pcu_ct[port_idx]:BSSGP_SP_SIG);
457 disconnect(self:PCU_PROC[port_idx], pcu_ct[port_idx]:BSSGP_PROC);
458 }
459 /* connect to new BVC and register us */
460 connect(self:PCU[port_idx], bvc_ct:BSSGP_SP);
461 connect(self:PCU_SIG[port_idx], bvc_ct:BSSGP_SP_SIG);
462 connect(self:PCU_PROC[port_idx], bvc_ct:BSSGP_PROC);
463 f_client_register(g_pars.imsi, g_pars.tlli, PCU_PROC[port_idx]);
464 pcu_ct[port_idx] := bvc_ct;
465}
466
467/* Connect the SGSN-side per-BVC ports (SGSN/SGSN_SIG/SGSN_PROC) array slot 'port_idx' to specified per-BVC component */
468private function f_connect_to_sgsn_bvc(integer port_idx, BSSGP_BVC_CT bvc_ct) runs on BSSGP_ConnHdlr {
469 if (SGSN[port_idx].checkstate("Connected")) {
470 /* unregister + disconnect from old BVC */
471 f_client_unregister(g_pars.imsi, SGSN_PROC[port_idx]);
472 disconnect(self:SGSN[port_idx], sgsn_ct[port_idx]:BSSGP_SP);
473 disconnect(self:SGSN_SIG[port_idx], sgsn_ct[port_idx]:BSSGP_SP_SIG);
474 disconnect(self:SGSN_PROC[port_idx], sgsn_ct[port_idx]:BSSGP_PROC);
475 }
476 /* connect to new BVC and register us */
477 connect(self:SGSN[port_idx], bvc_ct:BSSGP_SP);
478 connect(self:SGSN_SIG[port_idx], bvc_ct:BSSGP_SP_SIG);
479 connect(self:SGSN_PROC[port_idx], bvc_ct:BSSGP_PROC);
480 f_client_register(g_pars.imsi, g_pars.tlli, SGSN_PROC[port_idx]);
481 sgsn_ct[port_idx] := bvc_ct;
482}
483
Daniel Willmann423d8f42020-09-08 18:58:22 +0200484private altstep as_Tguard() runs on BSSGP_ConnHdlr {
485 [] g_Tguard.timeout {
486 setverdict(fail, "Tguard timeout");
487 mtc.stop;
488 }
489}
490
491/* first function called in every ConnHdlr */
492private function f_handler_init(void_fn fn, charstring id, BSSGP_ConnHdlrPars pars)
493runs on BSSGP_ConnHdlr {
Harald Welte1e834f32020-11-15 20:02:59 +0100494 var integer i;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200495 /* do some common stuff like setting up g_pars */
496 g_pars := pars;
497
498 llc := f_llc_create(false);
499
Harald Welte3dd21b32020-11-17 19:21:00 +0100500 /* default connections on PCU side: First BVC of each NSE/PCU */
501 for (i := 0; i < lengthof(g_pars.pcu); i := i+1) {
502 f_connect_to_pcu_bvc(i, g_pars.pcu[i].vc_BSSGP_BVC[0]);
Harald Welte1e834f32020-11-15 20:02:59 +0100503 }
Harald Welte3dd21b32020-11-17 19:21:00 +0100504
505 /* default connections on SGSN side: First BVC of each NSE/SGSN */
506 for (i := 0; i < lengthof(g_pars.sgsn); i := i+1) {
507 f_connect_to_sgsn_bvc(i, g_pars.sgsn[i].vc_BSSGP_BVC[0]);
Harald Welte1e834f32020-11-15 20:02:59 +0100508 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200509
510 g_Tguard.start(pars.t_guard);
511 activate(as_Tguard());
512
513 /* call the user-supplied test case function */
514 fn.apply(id);
515}
516
Harald Welte1e834f32020-11-15 20:02:59 +0100517private function f_client_register(hexstring imsi, OCT4 tlli, BSSGP_PROC_PT PT)
518runs on BSSGP_ConnHdlr {
519 PT.call(BSSGP_register_client:{imsi, tlli}) {
520 [] PT.getreply(BSSGP_register_client:{imsi, tlli}) {};
521 }
522}
523
524private function f_client_unregister(hexstring imsi, BSSGP_PROC_PT PT)
525runs on BSSGP_ConnHdlr {
526 PT.call(BSSGP_unregister_client:{imsi}) {
527 [] PT.getreply(BSSGP_unregister_client:{imsi}) {};
528 }
529}
530
Harald Welte22ef5d92020-11-16 13:35:14 +0100531/* Send 'tx' on PTP-BVCI from PCU; expect 'rx' on SGSN */
532friend function f_pcu2sgsn(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
533 integer pcu_idx := 0, integer sgsn_idx := 0) runs on BSSGP_ConnHdlr {
534 var PDU_BSSGP rx;
535 timer T := 1.0;
536
537 PCU[pcu_idx].send(tx);
538 T.start;
539 alt {
540 [] SGSN[sgsn_idx].receive(exp_rx) {
541 setverdict(pass);
542 }
543 [] SGSN[sgsn_idx].receive(PDU_BSSGP:?) -> value rx {
544 setverdict(fail, "Unexpected BSSGP on SGSN side: ", rx);
545 mtc.stop;
546 }
547 [] T.timeout {
548 setverdict(fail, "Timeout waiting for BSSGP on SGSN side: ", rx);
549 mtc.stop;
550 }
551 }
552}
553
554/* Send 'tx' on PTP-BVCI from SGSN; expect 'rx' on PCU */
555friend function f_sgsn2pcu(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
556 integer sgsn_idx:= 0, integer pcu_idx := 0) runs on BSSGP_ConnHdlr {
557 var PDU_BSSGP rx;
558 timer T := 1.0;
559
560 SGSN[sgsn_idx].send(tx);
561 T.start;
562 alt {
563 [] PCU[pcu_idx].receive(exp_rx) {
564 setverdict(pass);
565 }
566 [] PCU[pcu_idx].receive(PDU_BSSGP:?) -> value rx {
567 setverdict(fail, "Unexpected BSSGP on PCU side: ", rx);
568 mtc.stop;
569 }
570 [] T.timeout {
571 setverdict(fail, "Timeout waiting for BSSGP on PCU side: ", rx);
572 mtc.stop;
573 }
574 }
575}
Harald Welte1e834f32020-11-15 20:02:59 +0100576
Daniel Willmann423d8f42020-09-08 18:58:22 +0200577/* TODO:
578 * Detach without Attach
579 * SM procedures without attach / RAU
580 * ATTACH / RAU
581 ** with / without authentication
582 ** with / without P-TMSI allocation
583 * re-transmissions of LLC frames
584 * PDP Context activation
585 ** with different GGSN config in SGSN VTY
586 ** with different PDP context type (v4/v6/v46)
587 ** timeout from GGSN
588 ** multiple / secondary PDP context
589 */
590
591private function f_TC_BVC_bringup(charstring id) runs on BSSGP_ConnHdlr {
592 f_sleep(5.0);
593 setverdict(pass);
594}
595
596testcase TC_BVC_bringup() runs on test_CT {
597 var BSSGP_ConnHdlr vc_conn;
598 f_init();
599
600 vc_conn := f_start_handler(refers(f_TC_BVC_bringup), testcasename(), g_pcu, g_sgsn, 51);
601 vc_conn.done;
602
603 f_cleanup();
604}
605
606friend function f_bssgp_suspend(integer ran_idx := 0) runs on BSSGP_ConnHdlr return OCT1 {
Harald Welte16357a92020-11-17 18:20:00 +0100607 var BssgpBvcConfig bvcc := g_pars.pcu[ran_idx].cfg.bvc[0];
Daniel Willmann423d8f42020-09-08 18:58:22 +0200608 timer T := 5.0;
609 var PDU_BSSGP rx_pdu;
Harald Welte16357a92020-11-17 18:20:00 +0100610 PCU_SIG[ran_idx].send(ts_BSSGP_SUSPEND(g_pars.tlli, bvcc.cell_id.ra_id));
Daniel Willmann423d8f42020-09-08 18:58:22 +0200611 T.start;
612 alt {
Harald Welte16357a92020-11-17 18:20:00 +0100613 [] 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 +0200614 return rx_pdu.pDU_BSSGP_SUSPEND_ACK.suspend_Reference_Number.suspend_Reference_Number_value;
615 }
Harald Welte16357a92020-11-17 18:20:00 +0100616 [] 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 +0200617 setverdict(fail, "SUSPEND-NACK in response to SUSPEND for TLLI ", g_pars.tlli);
618 mtc.stop;
619 }
620 [] T.timeout {
621 setverdict(fail, "No SUSPEND-ACK in response to SUSPEND for TLLI ", g_pars.tlli);
622 mtc.stop;
623 }
624 }
625 return '00'O;
626}
627
628friend function f_bssgp_resume(OCT1 susp_ref, integer ran_idx := 0) runs on BSSGP_ConnHdlr {
Harald Welte16357a92020-11-17 18:20:00 +0100629 var BssgpBvcConfig bvcc := g_pars.pcu[ran_idx].cfg.bvc[0];
Daniel Willmann423d8f42020-09-08 18:58:22 +0200630 timer T := 5.0;
Harald Welte16357a92020-11-17 18:20:00 +0100631 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 +0200632 T.start;
633 alt {
Harald Welte16357a92020-11-17 18:20:00 +0100634 [] PCU_SIG[ran_idx].receive(tr_BSSGP_RESUME_ACK(g_pars.tlli, bvcc.cell_id.ra_id));
635 [] PCU_SIG[ran_idx].receive(tr_BSSGP_RESUME_NACK(g_pars.tlli, bvcc.cell_id.ra_id, ?)) {
Daniel Willmann423d8f42020-09-08 18:58:22 +0200636 setverdict(fail, "RESUME-NACK in response to RESUME for TLLI ", g_pars.tlli);
637 mtc.stop;
638 }
639 [] T.timeout {
640 setverdict(fail, "No RESUME-ACK in response to SUSPEND for TLLI ", g_pars.tlli);
641 mtc.stop;
642 }
643 }
644}
645
646
Harald Welte92686012020-11-15 21:45:49 +0100647/* send uplink-unitdata of a variety of different sizes; expect it to show up on SGSN */
648private function f_TC_ul_unitdata(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte16357a92020-11-17 18:20:00 +0100649 var integer ran_idx := 0;
650 var BssgpBvcConfig bvcc := g_pars.pcu[ran_idx].cfg.bvc[0];
Harald Welte92686012020-11-15 21:45:49 +0100651 var integer i;
652
653 for (i := 0; i < 1024; i := i+1) {
654 var octetstring payload := f_rnd_octstring(i);
Harald Welte16357a92020-11-17 18:20:00 +0100655 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 +0100656 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
Harald Welte16357a92020-11-17 18:20:00 +0100657 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 +0100658
Harald Welte22ef5d92020-11-16 13:35:14 +0100659 f_pcu2sgsn(pdu_tx, pdu_rx);
Harald Welte92686012020-11-15 21:45:49 +0100660 }
661 setverdict(pass);
662}
663
664testcase TC_ul_unitdata() runs on test_CT
665{
666 var BSSGP_ConnHdlr vc_conn;
667 f_init();
668
669 vc_conn := f_start_handler(refers(f_TC_ul_unitdata), testcasename(), g_pcu, g_sgsn, 1);
670 vc_conn.done;
671 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
672
673 f_cleanup();
674}
675
Harald Welte78d8db92020-11-15 23:27:27 +0100676/* send downlink-unitdata of a variety of different sizes; expect it to show up on PCU */
677private function f_TC_dl_unitdata(charstring id) runs on BSSGP_ConnHdlr {
678 var integer i;
679
680 for (i := 0; i < 1024; i := i+1) {
681 var octetstring payload := f_rnd_octstring(i);
682 var template (value) PDU_BSSGP pdu_tx :=
683 ts_BSSGP_DL_UD(g_pars.tlli, payload, omit, ts_BSSGP_IMSI(g_pars.imsi));
684 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
685 var template (present) PDU_BSSGP pdu_rx :=
686 tr_BSSGP_DL_UD(g_pars.tlli, payload, tr_BSSGP_IMSI(g_pars.imsi));
687
Harald Welte22ef5d92020-11-16 13:35:14 +0100688 f_sgsn2pcu(pdu_tx, pdu_rx);
Harald Welte78d8db92020-11-15 23:27:27 +0100689 }
690 setverdict(pass);
691}
692
693testcase TC_dl_unitdata() runs on test_CT
694{
695 var BSSGP_ConnHdlr vc_conn;
696 f_init();
697
698 vc_conn := f_start_handler(refers(f_TC_dl_unitdata), testcasename(), g_pcu, g_sgsn, 2);
699 vc_conn.done;
700 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
701
702 f_cleanup();
703}
Harald Welte92686012020-11-15 21:45:49 +0100704
Harald Welte6dc2ac42020-11-16 09:16:17 +0100705private function f_TC_ra_capability(charstring id) runs on BSSGP_ConnHdlr {
706 var integer i;
707
708 for (i := 0; i < 10; i := i+1) {
709 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RA_CAP(g_pars.tlli, { ts_RaCapRec_BSSGP });
710 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
711 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RA_CAP(g_pars.tlli, { tr_RaCapRec_BSSGP })
712
Harald Welte22ef5d92020-11-16 13:35:14 +0100713 f_sgsn2pcu(pdu_tx, pdu_rx);
Harald Welte6dc2ac42020-11-16 09:16:17 +0100714 }
715 setverdict(pass);
716}
717testcase TC_ra_capability() runs on test_CT
718{
719 var BSSGP_ConnHdlr vc_conn;
720 f_init();
721
722 vc_conn := f_start_handler(refers(f_TC_ra_capability), testcasename(), g_pcu, g_sgsn, 3);
723 vc_conn.done;
724 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
725
726 f_cleanup();
727}
728
Daniel Willmannace3ece2020-11-16 19:53:26 +0100729private function f_TC_ra_capability_upd(charstring id) runs on BSSGP_ConnHdlr {
730 var integer i;
731 var OCT1 tag;
732 for (i := 0; i < 10; i := i+1) {
733 tag := int2oct(23 + i, 1);
734 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RA_CAP_UPD(g_pars.tlli, tag);
735 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
736 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RA_CAP_UPD(g_pars.tlli, tag)
737
738 f_pcu2sgsn(pdu_tx, pdu_rx);
739
740 pdu_tx := ts_BSSGP_RA_CAP_UPD_ACK(g_pars.tlli, tag, '42'O);
741 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
742 pdu_rx := tr_BSSGP_RA_CAP_UPD_ACK(g_pars.tlli, tag, '42'O)
743
744 f_sgsn2pcu(pdu_tx, pdu_rx);
745 }
746 setverdict(pass);
747}
748testcase TC_ra_capability_upd() runs on test_CT
749{
750 var BSSGP_ConnHdlr vc_conn;
751 f_init();
752
Daniel Willmann54833f22020-11-19 15:43:52 +0100753 vc_conn := f_start_handler(refers(f_TC_ra_capability_upd), testcasename(), g_pcu, g_sgsn, 4);
Daniel Willmannace3ece2020-11-16 19:53:26 +0100754 vc_conn.done;
755 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
756
757 f_cleanup();
758}
759
Daniel Willmann165d6612020-11-19 14:27:29 +0100760private function f_TC_radio_status(charstring id) runs on BSSGP_ConnHdlr {
761 var integer i;
762 var BssgpRadioCause cause := BSSGP_RADIO_CAUSE_CONTACT_LOST;
763 for (i := 0; i < 10; i := i+1) {
764 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RADIO_STATUS(g_pars.tlli, cause);
765 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
766 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RADIO_STATUS(g_pars.tlli, cause)
767
768 f_pcu2sgsn(pdu_tx, pdu_rx);
769 }
770 setverdict(pass);
771}
772testcase TC_radio_status() runs on test_CT
773{
774 var BSSGP_ConnHdlr vc_conn;
775 f_init();
776
Daniel Willmann54833f22020-11-19 15:43:52 +0100777 vc_conn := f_start_handler(refers(f_TC_radio_status), testcasename(), g_pcu, g_sgsn, 5);
Daniel Willmann165d6612020-11-19 14:27:29 +0100778 vc_conn.done;
779 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
780
781 f_cleanup();
782}
783
Daniel Willmannfa67f492020-11-19 15:48:05 +0100784private function f_TC_suspend(charstring id) runs on BSSGP_ConnHdlr {
785 var integer i;
Daniel Willmann165d6612020-11-19 14:27:29 +0100786
Daniel Willmannfa67f492020-11-19 15:48:05 +0100787 /* TODO: Generate RA ID for each ConnHdlr */
788 var RoutingAreaIdentification ra_id := g_pars.pcu[0].cfg.bvc[0].cell_id.ra_id;
789 for (i := 0; i < 10; i := i+1) {
790
791 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_SUSPEND(g_pars.tlli, ra_id);
792 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
793 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_SUSPEND(g_pars.tlli, ra_id);
794
795 f_pcu2sgsn(pdu_tx, pdu_rx);
796
797 pdu_tx := ts_BSSGP_SUSPEND_ACK(g_pars.tlli, ra_id, int2oct(i, 1));
798 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
799 pdu_rx := tr_BSSGP_SUSPEND_ACK(g_pars.tlli, ra_id, int2oct(i, 1));
800
801 f_sgsn2pcu(pdu_tx, pdu_rx);
802
803 /* These messages are simple passed through so just also test sending NACK */
804 pdu_tx := ts_BSSGP_SUSPEND_NACK(g_pars.tlli, ra_id, BSSGP_CAUSE_UNKNOWN_MS);
805 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
806 pdu_rx := tr_BSSGP_SUSPEND_NACK(g_pars.tlli, ra_id, BSSGP_CAUSE_UNKNOWN_MS);
807
808 f_sgsn2pcu(pdu_tx, pdu_rx);
809 }
810 setverdict(pass);
811}
812testcase TC_suspend() runs on test_CT
813{
814 var BSSGP_ConnHdlr vc_conn;
815 f_init();
816
817 vc_conn := f_start_handler(refers(f_TC_suspend), testcasename(), g_pcu, g_sgsn, 6);
818 vc_conn.done;
819 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
820
821 f_cleanup();
822}
Harald Welte6dc2ac42020-11-16 09:16:17 +0100823
Daniel Willmann087a33d2020-11-19 15:58:43 +0100824private function f_TC_resume(charstring id) runs on BSSGP_ConnHdlr {
825 var integer i;
826
827 /* TODO: Generate RA ID for each ConnHdlr */
828 var RoutingAreaIdentification ra_id := g_pars.pcu[0].cfg.bvc[0].cell_id.ra_id;
829 for (i := 0; i < 10; i := i+1) {
830
831 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RESUME(g_pars.tlli, ra_id, int2oct(i, 1));
832 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
833 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RESUME(g_pars.tlli, ra_id, int2oct(i, 1));
834
835 f_pcu2sgsn(pdu_tx, pdu_rx);
836
837 pdu_tx := ts_BSSGP_RESUME_ACK(g_pars.tlli, ra_id);
838 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
839 pdu_rx := tr_BSSGP_RESUME_ACK(g_pars.tlli, ra_id);
840
841 f_sgsn2pcu(pdu_tx, pdu_rx);
842
843 /* These messages are simple passed through so just also test sending NACK */
844 pdu_tx := ts_BSSGP_RESUME_NACK(g_pars.tlli, ra_id, BSSGP_CAUSE_UNKNOWN_MS);
845 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
846 pdu_rx := tr_BSSGP_RESUME_NACK(g_pars.tlli, ra_id, BSSGP_CAUSE_UNKNOWN_MS);
847
848 f_sgsn2pcu(pdu_tx, pdu_rx);
849 }
850 setverdict(pass);
851}
852testcase TC_resume() runs on test_CT
853{
854 var BSSGP_ConnHdlr vc_conn;
855 f_init();
856
857 vc_conn := f_start_handler(refers(f_TC_resume), testcasename(), g_pcu, g_sgsn, 6);
858 vc_conn.done;
859 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
860
861 f_cleanup();
862}
863
Harald Welte6dc2ac42020-11-16 09:16:17 +0100864
Daniel Willmann423d8f42020-09-08 18:58:22 +0200865control {
866 execute( TC_BVC_bringup() );
Harald Welte92686012020-11-15 21:45:49 +0100867 execute( TC_ul_unitdata() );
Harald Welte78d8db92020-11-15 23:27:27 +0100868 execute( TC_dl_unitdata() );
Harald Welte6dc2ac42020-11-16 09:16:17 +0100869 execute( TC_ra_capability() );
Daniel Willmannace3ece2020-11-16 19:53:26 +0100870 execute( TC_ra_capability_upd() );
Daniel Willmann165d6612020-11-19 14:27:29 +0100871 execute( TC_radio_status() );
Daniel Willmannfa67f492020-11-19 15:48:05 +0100872 execute( TC_suspend() );
Daniel Willmann087a33d2020-11-19 15:58:43 +0100873 execute( TC_resume() );
Daniel Willmann423d8f42020-09-08 18:58:22 +0200874}
875
876
877}