blob: e6c07d75e99481f6dfd43585f94d51bd19360f32 [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 {
222 port BSSGP_PT PCU[NUM_PCU];
223 port BSSGP_PT PCU_SIG[NUM_PCU];
224 port BSSGP_PROC_PT PCU_PROC[NUM_PCU];
225 port BSSGP_PT SGSN[NUM_SGSN];
226 port BSSGP_PT SGSN_SIG[NUM_SGSN];
227 port BSSGP_PROC_PT SGSN_PROC[NUM_SGSN];
228
229 var BSSGP_ConnHdlrPars g_pars;
230 timer g_Tguard;
231 var LLC_Entities llc;
232}
233
234type record SGSN_ConnHdlrNetworkPars {
235 boolean expect_ptmsi,
236 boolean expect_auth,
237 boolean expect_ciph
238};
239
240type record BSSGP_ConnHdlrPars {
241 /* IMEI of the simulated ME */
242 hexstring imei,
243 /* IMSI of the simulated MS */
244 hexstring imsi,
245 /* MSISDN of the simulated MS (probably unused) */
246 hexstring msisdn,
247 /* P-TMSI allocated to the simulated MS */
248 OCT4 p_tmsi optional,
249 OCT3 p_tmsi_sig optional,
250 /* TLLI of the simulated MS */
251 OCT4 tlli,
252 OCT4 tlli_old optional,
253 RoutingAreaIdentificationV ra optional,
Harald Welte16357a92020-11-17 18:20:00 +0100254 GbInstances pcu,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200255 float t_guard
256};
257
258private function f_cellid_to_RAI(in BssgpCellId cell_id) return RoutingAreaIdentificationV {
259 /* mcc_mnc is encoded as of 24.008 10.5.5.15 */
260 var BcdMccMnc mcc_mnc := cell_id.ra_id.lai.mcc_mnc;
261
262 var RoutingAreaIdentificationV ret := {
263 mccDigit1 := mcc_mnc[0],
264 mccDigit2 := mcc_mnc[1],
265 mccDigit3 := mcc_mnc[2],
266 mncDigit3 := mcc_mnc[3],
267 mncDigit1 := mcc_mnc[4],
268 mncDigit2 := mcc_mnc[5],
269 lac := int2oct(cell_id.ra_id.lai.lac, 16),
270 rac := int2oct(cell_id.ra_id.rac, 8)
271 }
272 return ret;
273};
274
275private function f_init_gb_pcu(inout GbInstance gb, charstring id, integer offset) runs on test_CT {
Harald Welteb419d0e2020-11-16 16:45:05 +0100276 var charstring ns_id := id & "-NS(PCU[" & int2str(offset) & "])";
277 var charstring bssgp_id := id & "-BSSGP(PCU[" & int2str(offset) & "])";
278 gb.vc_NS := NS_CT.create(ns_id);
279 gb.vc_BSSGP := BSSGP_CT.create(bssgp_id);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200280 /* connect lower end of BSSGP emulation with NS upper port */
281 connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
282
Harald Welteb419d0e2020-11-16 16:45:05 +0100283 gb.vc_NS.start(NSStart(mp_nsconfig_pcu[offset], ns_id));
284 gb.vc_BSSGP.start(BssgpStart(gb.cfg, bssgp_id));
Daniel Willmann423d8f42020-09-08 18:58:22 +0200285
286 for (var integer i := 0; i < lengthof(gb.cfg.bvc); i := i + 1) {
287 connect(self:PROC, gb.vc_BSSGP:PROC);
288 gb.vc_BSSGP_BVC[i] := f_bssgp_get_bvci_ct(gb.cfg.bvc[i].bvci, PROC);
289 disconnect(self:PROC, gb.vc_BSSGP:PROC);
Harald Weltefbae83f2020-11-15 23:25:55 +0100290 connect(self:PCU_MGMT, gb.vc_BSSGP_BVC[i]:MGMT);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200291 }
292}
293
294private function f_init_gb_sgsn(inout GbInstance gb, charstring id, integer offset) runs on test_CT {
Harald Welteb419d0e2020-11-16 16:45:05 +0100295 var charstring ns_id := id & "-NS(SGSN[" & int2str(offset) & "])";
296 var charstring bssgp_id := id & "-BSSGP(SGSN[" & int2str(offset) & "])";
297 gb.vc_NS := NS_CT.create(ns_id);
298 gb.vc_BSSGP := BSSGP_CT.create(bssgp_id);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200299 /* connect lower end of BSSGP emulation with NS upper port */
300 connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
301
Harald Welteb419d0e2020-11-16 16:45:05 +0100302 gb.vc_NS.start(NSStart(mp_nsconfig_sgsn[offset], ns_id));
303 gb.vc_BSSGP.start(BssgpStart(gb.cfg, bssgp_id));
Daniel Willmann423d8f42020-09-08 18:58:22 +0200304
305 for (var integer i := 0; i < lengthof(gb.cfg.bvc); i := i + 1) {
306 connect(self:PROC, gb.vc_BSSGP:PROC);
307 gb.vc_BSSGP_BVC[i] := f_bssgp_get_bvci_ct(gb.cfg.bvc[i].bvci, PROC);
308 disconnect(self:PROC, gb.vc_BSSGP:PROC);
Harald Weltefbae83f2020-11-15 23:25:55 +0100309 connect(self:SGSN_MGMT, gb.vc_BSSGP_BVC[i]:MGMT);
Daniel Willmann423d8f42020-09-08 18:58:22 +0200310 }
311}
312
313
314private function f_init_vty() runs on test_CT {
315 map(self:GBPVTY, system:GBPVTY);
316 f_vty_set_prompts(GBPVTY);
317 f_vty_transceive(GBPVTY, "enable");
318}
319
Harald Weltefbae83f2020-11-15 23:25:55 +0100320type record of integer ro_integer;
321
322private function ro_integer_contains(ro_integer r, integer x) return boolean {
323 for (var integer j := 0; j < lengthof(r); j := j+1) {
324 if (r[j] == x) {
325 return true;
326 }
327 }
328 return false;
329}
330
Harald Welte6d63f742020-11-15 19:44:04 +0100331function f_init() runs on test_CT {
Harald Weltefbae83f2020-11-15 23:25:55 +0100332 var ro_integer bvci_unblocked := {};
333 var BssgpStatusIndication bsi;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200334 var integer i;
335
336 if (g_initialized == true) {
337 return;
338 }
339 g_initialized := true;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200340
341 g_sgsn[0].cfg := {
Harald Welte6d63f742020-11-15 19:44:04 +0100342 nsei := mp_nsconfig_sgsn[0].nsei,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200343 sgsn_role := true,
Harald Welte6d63f742020-11-15 19:44:04 +0100344 bvc := { }
345 }
346 for (i := 0; i < lengthof(mp_gbconfigs); i := i+1) {
347 g_pcu[i].cfg := mp_gbconfigs[i];
348 /* concatenate all the PCU-side BVCs for the SGSN side */
349 g_sgsn[0].cfg.bvc := g_sgsn[0].cfg.bvc & mp_gbconfigs[i].bvc;
350 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200351
352 f_init_vty();
Harald Welte6d63f742020-11-15 19:44:04 +0100353 for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
Harald Welteea1ba592020-11-17 18:05:13 +0100354 f_init_gb_sgsn(g_sgsn[i], "GbProxy_Test", i);
Harald Welte6d63f742020-11-15 19:44:04 +0100355 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200356 f_sleep(4.0);
Harald Welte6d63f742020-11-15 19:44:04 +0100357 for (i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
Harald Welteb419d0e2020-11-16 16:45:05 +0100358 f_init_gb_pcu(g_pcu[i], "GbProxy_Test", i);
Harald Welte6d63f742020-11-15 19:44:04 +0100359 }
Harald Weltefbae83f2020-11-15 23:25:55 +0100360
361 /* wait until all BVC are unblocked on both sides */
362 timer T := 5.0;
363 T.start;
364 alt {
365 [] SGSN_MGMT.receive(BssgpStatusIndication:{*, ?, BVC_S_UNBLOCKED}) -> value bsi {
366 bvci_unblocked := bvci_unblocked & { bsi.bvci };
367 if (lengthof(bvci_unblocked) != lengthof(g_sgsn[0].cfg.bvc)) {
368 repeat;
369 }
370 }
371 [] SGSN_MGMT.receive(BssgpStatusIndication:{*, ?, ?}) {
372 repeat;
373 }
374 [] SGSN_MGMT.receive {
375 setverdict(fail, "Received unexpected message on SGSN_MGMT");
376 mtc.stop;
377 }
378
379 [] PCU_MGMT.receive(BssgpStatusIndication:{*, ?, BVC_S_UNBLOCKED}) -> value bsi {
380 repeat;
381 }
382 [] PCU_MGMT.receive(BssgpStatusIndication:{*, ?, ?}) {
383 repeat;
384 }
385 [] PCU_MGMT.receive(BssgpResetIndication:{0}) {
386 repeat;
387 }
388 [] PCU_MGMT.receive {
389 setverdict(fail, "Received unexpected message on PCU_MGMT");
390 mtc.stop;
391 }
392
393 [] T.timeout {
394 setverdict(fail, "Timeout waiting for unblock of all BVCs");
395 mtc.stop;
396 }
397 }
398
399 /* iterate over list and check all BVCI */
400 for (i := 0; i < lengthof(g_sgsn[0].cfg.bvc); i := i+1) {
401 var BssgpBvci bvci := g_sgsn[0].cfg.bvc[i].bvci;
402 if (not ro_integer_contains(bvci_unblocked, bvci)) {
403 setverdict(fail, "BVCI=", bvci, " was not unblocked during start-up");
404 mtc.stop;
405 }
406 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200407}
408
409function f_cleanup() runs on test_CT {
410 self.stop;
411}
412
413type function void_fn(charstring id) runs on BSSGP_ConnHdlr;
414
415/* helper function to create, connect and start a BSSGP_ConnHdlr component */
Harald Welte6d63f742020-11-15 19:44:04 +0100416function f_start_handler(void_fn fn, charstring id, GbInstances pcu, GbInstances sgsn, integer imsi_suffix,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200417 float t_guard := 30.0)
418runs on test_CT return BSSGP_ConnHdlr {
419 var BSSGP_ConnHdlr vc_conn;
420
421 var BSSGP_ConnHdlrPars pars := {
422 imei := f_gen_imei(imsi_suffix),
423 imsi := f_gen_imsi(imsi_suffix),
424 msisdn := f_gen_msisdn(imsi_suffix),
425 p_tmsi := omit,
426 p_tmsi_sig := omit,
427 tlli := f_gprs_tlli_random(),
428 tlli_old := omit,
429 ra := omit,
Harald Welte16357a92020-11-17 18:20:00 +0100430 pcu := g_pcu,
Daniel Willmann423d8f42020-09-08 18:58:22 +0200431 t_guard := t_guard
432 };
433
434 vc_conn := BSSGP_ConnHdlr.create(id);
435 // PDU side
436 connect(vc_conn:PCU[0], pcu[0].vc_BSSGP_BVC[0]:BSSGP_SP);
437 connect(vc_conn:PCU_SIG[0], pcu[0].vc_BSSGP_BVC[0]:BSSGP_SP_SIG);
438 connect(vc_conn:PCU_PROC[0], pcu[0].vc_BSSGP_BVC[0]:BSSGP_PROC);
439 connect(vc_conn:PCU[1], pcu[1].vc_BSSGP_BVC[0]:BSSGP_SP);
440 connect(vc_conn:PCU_SIG[1], pcu[1].vc_BSSGP_BVC[0]:BSSGP_SP_SIG);
441 connect(vc_conn:PCU_PROC[1], pcu[1].vc_BSSGP_BVC[0]:BSSGP_PROC);
442 connect(vc_conn:PCU[2], pcu[2].vc_BSSGP_BVC[0]:BSSGP_SP);
443 connect(vc_conn:PCU_SIG[2], pcu[2].vc_BSSGP_BVC[0]:BSSGP_SP_SIG);
444 connect(vc_conn:PCU_PROC[2], pcu[2].vc_BSSGP_BVC[0]:BSSGP_PROC);
445 // SGSN side
446 connect(vc_conn:SGSN[0], sgsn[0].vc_BSSGP_BVC[0]:BSSGP_SP);
447 connect(vc_conn:SGSN_SIG[0], sgsn[0].vc_BSSGP_BVC[0]:BSSGP_SP_SIG);
448 connect(vc_conn:SGSN_PROC[0], sgsn[0].vc_BSSGP_BVC[0]:BSSGP_PROC);
449
450 vc_conn.start(f_handler_init(fn, id, pars));
451 return vc_conn;
452}
453
454private altstep as_Tguard() runs on BSSGP_ConnHdlr {
455 [] g_Tguard.timeout {
456 setverdict(fail, "Tguard timeout");
457 mtc.stop;
458 }
459}
460
461/* first function called in every ConnHdlr */
462private function f_handler_init(void_fn fn, charstring id, BSSGP_ConnHdlrPars pars)
463runs on BSSGP_ConnHdlr {
Harald Welte1e834f32020-11-15 20:02:59 +0100464 var integer i;
Daniel Willmann423d8f42020-09-08 18:58:22 +0200465 /* do some common stuff like setting up g_pars */
466 g_pars := pars;
467
468 llc := f_llc_create(false);
469
Harald Welte1e834f32020-11-15 20:02:59 +0100470 /* register for our IMSI + TLLI */
471 for (i := 0; i < sizeof(SGSN_PROC); i := i+1) {
472 f_client_register(g_pars.imsi, g_pars.tlli, SGSN_PROC[i]);
473 }
474 for (i := 0; i < sizeof(PCU_PROC); i := i+1) {
475 f_client_register(g_pars.imsi, g_pars.tlli, PCU_PROC[i]);
476 }
Daniel Willmann423d8f42020-09-08 18:58:22 +0200477
478 g_Tguard.start(pars.t_guard);
479 activate(as_Tguard());
480
481 /* call the user-supplied test case function */
482 fn.apply(id);
483}
484
Harald Welte1e834f32020-11-15 20:02:59 +0100485private function f_client_register(hexstring imsi, OCT4 tlli, BSSGP_PROC_PT PT)
486runs on BSSGP_ConnHdlr {
487 PT.call(BSSGP_register_client:{imsi, tlli}) {
488 [] PT.getreply(BSSGP_register_client:{imsi, tlli}) {};
489 }
490}
491
492private function f_client_unregister(hexstring imsi, BSSGP_PROC_PT PT)
493runs on BSSGP_ConnHdlr {
494 PT.call(BSSGP_unregister_client:{imsi}) {
495 [] PT.getreply(BSSGP_unregister_client:{imsi}) {};
496 }
497}
498
Harald Welte22ef5d92020-11-16 13:35:14 +0100499/* Send 'tx' on PTP-BVCI from PCU; expect 'rx' on SGSN */
500friend function f_pcu2sgsn(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
501 integer pcu_idx := 0, integer sgsn_idx := 0) runs on BSSGP_ConnHdlr {
502 var PDU_BSSGP rx;
503 timer T := 1.0;
504
505 PCU[pcu_idx].send(tx);
506 T.start;
507 alt {
508 [] SGSN[sgsn_idx].receive(exp_rx) {
509 setverdict(pass);
510 }
511 [] SGSN[sgsn_idx].receive(PDU_BSSGP:?) -> value rx {
512 setverdict(fail, "Unexpected BSSGP on SGSN side: ", rx);
513 mtc.stop;
514 }
515 [] T.timeout {
516 setverdict(fail, "Timeout waiting for BSSGP on SGSN side: ", rx);
517 mtc.stop;
518 }
519 }
520}
521
522/* Send 'tx' on PTP-BVCI from SGSN; expect 'rx' on PCU */
523friend function f_sgsn2pcu(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
524 integer sgsn_idx:= 0, integer pcu_idx := 0) runs on BSSGP_ConnHdlr {
525 var PDU_BSSGP rx;
526 timer T := 1.0;
527
528 SGSN[sgsn_idx].send(tx);
529 T.start;
530 alt {
531 [] PCU[pcu_idx].receive(exp_rx) {
532 setverdict(pass);
533 }
534 [] PCU[pcu_idx].receive(PDU_BSSGP:?) -> value rx {
535 setverdict(fail, "Unexpected BSSGP on PCU side: ", rx);
536 mtc.stop;
537 }
538 [] T.timeout {
539 setverdict(fail, "Timeout waiting for BSSGP on PCU side: ", rx);
540 mtc.stop;
541 }
542 }
543}
Harald Welte1e834f32020-11-15 20:02:59 +0100544
Daniel Willmann423d8f42020-09-08 18:58:22 +0200545/* TODO:
546 * Detach without Attach
547 * SM procedures without attach / RAU
548 * ATTACH / RAU
549 ** with / without authentication
550 ** with / without P-TMSI allocation
551 * re-transmissions of LLC frames
552 * PDP Context activation
553 ** with different GGSN config in SGSN VTY
554 ** with different PDP context type (v4/v6/v46)
555 ** timeout from GGSN
556 ** multiple / secondary PDP context
557 */
558
559private function f_TC_BVC_bringup(charstring id) runs on BSSGP_ConnHdlr {
560 f_sleep(5.0);
561 setverdict(pass);
562}
563
564testcase TC_BVC_bringup() runs on test_CT {
565 var BSSGP_ConnHdlr vc_conn;
566 f_init();
567
568 vc_conn := f_start_handler(refers(f_TC_BVC_bringup), testcasename(), g_pcu, g_sgsn, 51);
569 vc_conn.done;
570
571 f_cleanup();
572}
573
574friend function f_bssgp_suspend(integer ran_idx := 0) runs on BSSGP_ConnHdlr return OCT1 {
Harald Welte16357a92020-11-17 18:20:00 +0100575 var BssgpBvcConfig bvcc := g_pars.pcu[ran_idx].cfg.bvc[0];
Daniel Willmann423d8f42020-09-08 18:58:22 +0200576 timer T := 5.0;
577 var PDU_BSSGP rx_pdu;
Harald Welte16357a92020-11-17 18:20:00 +0100578 PCU_SIG[ran_idx].send(ts_BSSGP_SUSPEND(g_pars.tlli, bvcc.cell_id.ra_id));
Daniel Willmann423d8f42020-09-08 18:58:22 +0200579 T.start;
580 alt {
Harald Welte16357a92020-11-17 18:20:00 +0100581 [] 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 +0200582 return rx_pdu.pDU_BSSGP_SUSPEND_ACK.suspend_Reference_Number.suspend_Reference_Number_value;
583 }
Harald Welte16357a92020-11-17 18:20:00 +0100584 [] 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 +0200585 setverdict(fail, "SUSPEND-NACK in response to SUSPEND for TLLI ", g_pars.tlli);
586 mtc.stop;
587 }
588 [] T.timeout {
589 setverdict(fail, "No SUSPEND-ACK in response to SUSPEND for TLLI ", g_pars.tlli);
590 mtc.stop;
591 }
592 }
593 return '00'O;
594}
595
596friend function f_bssgp_resume(OCT1 susp_ref, integer ran_idx := 0) runs on BSSGP_ConnHdlr {
Harald Welte16357a92020-11-17 18:20:00 +0100597 var BssgpBvcConfig bvcc := g_pars.pcu[ran_idx].cfg.bvc[0];
Daniel Willmann423d8f42020-09-08 18:58:22 +0200598 timer T := 5.0;
Harald Welte16357a92020-11-17 18:20:00 +0100599 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 +0200600 T.start;
601 alt {
Harald Welte16357a92020-11-17 18:20:00 +0100602 [] PCU_SIG[ran_idx].receive(tr_BSSGP_RESUME_ACK(g_pars.tlli, bvcc.cell_id.ra_id));
603 [] PCU_SIG[ran_idx].receive(tr_BSSGP_RESUME_NACK(g_pars.tlli, bvcc.cell_id.ra_id, ?)) {
Daniel Willmann423d8f42020-09-08 18:58:22 +0200604 setverdict(fail, "RESUME-NACK in response to RESUME for TLLI ", g_pars.tlli);
605 mtc.stop;
606 }
607 [] T.timeout {
608 setverdict(fail, "No RESUME-ACK in response to SUSPEND for TLLI ", g_pars.tlli);
609 mtc.stop;
610 }
611 }
612}
613
614
Harald Welte92686012020-11-15 21:45:49 +0100615/* send uplink-unitdata of a variety of different sizes; expect it to show up on SGSN */
616private function f_TC_ul_unitdata(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte16357a92020-11-17 18:20:00 +0100617 var integer ran_idx := 0;
618 var BssgpBvcConfig bvcc := g_pars.pcu[ran_idx].cfg.bvc[0];
Harald Welte92686012020-11-15 21:45:49 +0100619 var integer i;
620
621 for (i := 0; i < 1024; i := i+1) {
622 var octetstring payload := f_rnd_octstring(i);
Harald Welte16357a92020-11-17 18:20:00 +0100623 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 +0100624 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
Harald Welte16357a92020-11-17 18:20:00 +0100625 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 +0100626
Harald Welte22ef5d92020-11-16 13:35:14 +0100627 f_pcu2sgsn(pdu_tx, pdu_rx);
Harald Welte92686012020-11-15 21:45:49 +0100628 }
629 setverdict(pass);
630}
631
632testcase TC_ul_unitdata() runs on test_CT
633{
634 var BSSGP_ConnHdlr vc_conn;
635 f_init();
636
637 vc_conn := f_start_handler(refers(f_TC_ul_unitdata), testcasename(), g_pcu, g_sgsn, 1);
638 vc_conn.done;
639 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
640
641 f_cleanup();
642}
643
Harald Welte78d8db92020-11-15 23:27:27 +0100644/* send downlink-unitdata of a variety of different sizes; expect it to show up on PCU */
645private function f_TC_dl_unitdata(charstring id) runs on BSSGP_ConnHdlr {
646 var integer i;
647
648 for (i := 0; i < 1024; i := i+1) {
649 var octetstring payload := f_rnd_octstring(i);
650 var template (value) PDU_BSSGP pdu_tx :=
651 ts_BSSGP_DL_UD(g_pars.tlli, payload, omit, ts_BSSGP_IMSI(g_pars.imsi));
652 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
653 var template (present) PDU_BSSGP pdu_rx :=
654 tr_BSSGP_DL_UD(g_pars.tlli, payload, tr_BSSGP_IMSI(g_pars.imsi));
655
Harald Welte22ef5d92020-11-16 13:35:14 +0100656 f_sgsn2pcu(pdu_tx, pdu_rx);
Harald Welte78d8db92020-11-15 23:27:27 +0100657 }
658 setverdict(pass);
659}
660
661testcase TC_dl_unitdata() runs on test_CT
662{
663 var BSSGP_ConnHdlr vc_conn;
664 f_init();
665
666 vc_conn := f_start_handler(refers(f_TC_dl_unitdata), testcasename(), g_pcu, g_sgsn, 2);
667 vc_conn.done;
668 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
669
670 f_cleanup();
671}
Harald Welte92686012020-11-15 21:45:49 +0100672
Harald Welte6dc2ac42020-11-16 09:16:17 +0100673private function f_TC_ra_capability(charstring id) runs on BSSGP_ConnHdlr {
674 var integer i;
675
676 for (i := 0; i < 10; i := i+1) {
677 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RA_CAP(g_pars.tlli, { ts_RaCapRec_BSSGP });
678 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
679 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RA_CAP(g_pars.tlli, { tr_RaCapRec_BSSGP })
680
Harald Welte22ef5d92020-11-16 13:35:14 +0100681 f_sgsn2pcu(pdu_tx, pdu_rx);
Harald Welte6dc2ac42020-11-16 09:16:17 +0100682 }
683 setverdict(pass);
684}
685testcase TC_ra_capability() runs on test_CT
686{
687 var BSSGP_ConnHdlr vc_conn;
688 f_init();
689
690 vc_conn := f_start_handler(refers(f_TC_ra_capability), testcasename(), g_pcu, g_sgsn, 3);
691 vc_conn.done;
692 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
693
694 f_cleanup();
695}
696
Daniel Willmannace3ece2020-11-16 19:53:26 +0100697private function f_TC_ra_capability_upd(charstring id) runs on BSSGP_ConnHdlr {
698 var integer i;
699 var OCT1 tag;
700 for (i := 0; i < 10; i := i+1) {
701 tag := int2oct(23 + i, 1);
702 var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RA_CAP_UPD(g_pars.tlli, tag);
703 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
704 var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RA_CAP_UPD(g_pars.tlli, tag)
705
706 f_pcu2sgsn(pdu_tx, pdu_rx);
707
708 pdu_tx := ts_BSSGP_RA_CAP_UPD_ACK(g_pars.tlli, tag, '42'O);
709 /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
710 pdu_rx := tr_BSSGP_RA_CAP_UPD_ACK(g_pars.tlli, tag, '42'O)
711
712 f_sgsn2pcu(pdu_tx, pdu_rx);
713 }
714 setverdict(pass);
715}
716testcase TC_ra_capability_upd() runs on test_CT
717{
718 var BSSGP_ConnHdlr vc_conn;
719 f_init();
720
721 vc_conn := f_start_handler(refers(f_TC_ra_capability_upd), testcasename(), g_pcu, g_sgsn, 3);
722 vc_conn.done;
723 /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
724
725 f_cleanup();
726}
727
Harald Welte6dc2ac42020-11-16 09:16:17 +0100728
729
730
Daniel Willmann423d8f42020-09-08 18:58:22 +0200731control {
732 execute( TC_BVC_bringup() );
Harald Welte92686012020-11-15 21:45:49 +0100733 execute( TC_ul_unitdata() );
Harald Welte78d8db92020-11-15 23:27:27 +0100734 execute( TC_dl_unitdata() );
Harald Welte6dc2ac42020-11-16 09:16:17 +0100735 execute( TC_ra_capability() );
Daniel Willmannace3ece2020-11-16 19:53:26 +0100736 execute( TC_ra_capability_upd() );
Daniel Willmann423d8f42020-09-08 18:58:22 +0200737}
738
739
740}