blob: 000f5845908268ae293b573ffeee85780493e3f8 [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
40modulepar {
41 /* IP/port on which we run our internal GSUP/HLR emulation */
42 NSConfigurations_SGSN mp_nsconfig_sgsn := {
43 {
44 provider := {
45 ip := {
46 address_family := AF_INET,
47 local_udp_port := 7777,
48 local_ip := "127.0.0.1",
49 remote_udp_port := 23000,
50 remote_ip := "127.0.0.1"
51 }
52 },
53 nsvci := 101,
54 nsei := 101,
55 role_sgsn := true,
56 handle_sns := true
57 }
58 };
59 NSConfigurations_PCU mp_nsconfig_pcu := {
60 {
61 provider := {
62 ip := {
63 address_family := AF_INET,
64 local_udp_port := 21010,
65 local_ip := "127.0.0.1",
66 remote_udp_port := 23000,
67 remote_ip := "127.0.0.1"
68 }
69 },
70 nsvci := 97,
71 nsei := 96,
72 role_sgsn := false,
73 handle_sns := false
74 },
75 {
76 provider := {
77 ip := {
78 address_family := AF_INET,
79 local_udp_port := 21011,
80 local_ip := "127.0.0.1",
81 remote_udp_port := 23000,
82 remote_ip := "127.0.0.1"
83 }
84 },
85 nsvci := 98,
86 nsei := 97,
87 role_sgsn := false,
88 handle_sns := false
89 },
90 {
91 provider := {
92 ip := {
93 address_family := AF_INET,
94 local_udp_port := 21012,
95 local_ip := "127.0.0.1",
96 remote_udp_port := 23000,
97 remote_ip := "127.0.0.1"
98 }
99 },
100 nsvci := 99,
101 nsei := 98,
102 role_sgsn := false,
103 handle_sns := false
104 }
105 };
106};
107
108const integer NUM_BVC_PER_NSE := 3;
109type record GbInstance {
110 NS_CT vc_NS,
111 BSSGP_CT vc_BSSGP,
112 BSSGP_BVC_CT vc_BSSGP_BVC[NUM_BVC_PER_NSE],
113 BssgpConfig cfg
114};
115
116const integer NUM_PCU := 3;
117type record length(NUM_PCU) of GbInstance GbInstances_PCU;
118type record length(NUM_PCU) of NSConfiguration NSConfigurations_PCU;
119type record length(NUM_PCU) of BssgpCellId BssgpCellIds;
120
121const integer NUM_SGSN := 1;
122type record length(NUM_SGSN) of GbInstance GbInstances_SGSN;
123type record length(NUM_SGSN) of NSConfiguration NSConfigurations_SGSN;
124
125type component test_CT {
126 var GbInstances_PCU g_pcu;
127 var GbInstances_SGSN g_sgsn;
128
129 port BSSGP_CT_PROC_PT PROC;
130
131 port TELNETasp_PT GBPVTY;
132
133 var boolean g_initialized := false;
134 var boolean g_use_echo := false;
135};
136
137type component BSSGP_ConnHdlr {
138 port BSSGP_PT PCU[NUM_PCU];
139 port BSSGP_PT PCU_SIG[NUM_PCU];
140 port BSSGP_PROC_PT PCU_PROC[NUM_PCU];
141 port BSSGP_PT SGSN[NUM_SGSN];
142 port BSSGP_PT SGSN_SIG[NUM_SGSN];
143 port BSSGP_PROC_PT SGSN_PROC[NUM_SGSN];
144
145 var BSSGP_ConnHdlrPars g_pars;
146 timer g_Tguard;
147 var LLC_Entities llc;
148}
149
150type record SGSN_ConnHdlrNetworkPars {
151 boolean expect_ptmsi,
152 boolean expect_auth,
153 boolean expect_ciph
154};
155
156type record BSSGP_ConnHdlrPars {
157 /* IMEI of the simulated ME */
158 hexstring imei,
159 /* IMSI of the simulated MS */
160 hexstring imsi,
161 /* MSISDN of the simulated MS (probably unused) */
162 hexstring msisdn,
163 /* P-TMSI allocated to the simulated MS */
164 OCT4 p_tmsi optional,
165 OCT3 p_tmsi_sig optional,
166 /* TLLI of the simulated MS */
167 OCT4 tlli,
168 OCT4 tlli_old optional,
169 RoutingAreaIdentificationV ra optional,
170 BssgpCellIds bssgp_cell_id,
171 float t_guard
172};
173
174private function f_cellid_to_RAI(in BssgpCellId cell_id) return RoutingAreaIdentificationV {
175 /* mcc_mnc is encoded as of 24.008 10.5.5.15 */
176 var BcdMccMnc mcc_mnc := cell_id.ra_id.lai.mcc_mnc;
177
178 var RoutingAreaIdentificationV ret := {
179 mccDigit1 := mcc_mnc[0],
180 mccDigit2 := mcc_mnc[1],
181 mccDigit3 := mcc_mnc[2],
182 mncDigit3 := mcc_mnc[3],
183 mncDigit1 := mcc_mnc[4],
184 mncDigit2 := mcc_mnc[5],
185 lac := int2oct(cell_id.ra_id.lai.lac, 16),
186 rac := int2oct(cell_id.ra_id.rac, 8)
187 }
188 return ret;
189};
190
191private function f_init_gb_pcu(inout GbInstance gb, charstring id, integer offset) runs on test_CT {
192 gb.vc_NS := NS_CT.create(id & "-NS(PCU)" & int2str(offset));
193 gb.vc_BSSGP := BSSGP_CT.create(id & "-BSSGP(PCU)" & int2str(offset));
194 /* connect lower end of BSSGP emulation with NS upper port */
195 connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
196
197 gb.vc_NS.start(NSStart(mp_nsconfig_pcu[offset]));
198 gb.vc_BSSGP.start(BssgpStart(gb.cfg, id));
199
200 for (var integer i := 0; i < lengthof(gb.cfg.bvc); i := i + 1) {
201 connect(self:PROC, gb.vc_BSSGP:PROC);
202 gb.vc_BSSGP_BVC[i] := f_bssgp_get_bvci_ct(gb.cfg.bvc[i].bvci, PROC);
203 disconnect(self:PROC, gb.vc_BSSGP:PROC);
204 }
205}
206
207private function f_init_gb_sgsn(inout GbInstance gb, charstring id, integer offset) runs on test_CT {
208 gb.vc_NS := NS_CT.create(id & "-NS(SGSN)" & int2str(offset));
209 gb.vc_BSSGP := BSSGP_CT.create(id & "-BSSGP(SGSN)" & int2str(offset));
210 /* connect lower end of BSSGP emulation with NS upper port */
211 connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
212
213 gb.vc_NS.start(NSStart(mp_nsconfig_sgsn[offset]));
214 gb.vc_BSSGP.start(BssgpStart(gb.cfg, id));
215
216 for (var integer i := 0; i < lengthof(gb.cfg.bvc); i := i + 1) {
217 connect(self:PROC, gb.vc_BSSGP:PROC);
218 gb.vc_BSSGP_BVC[i] := f_bssgp_get_bvci_ct(gb.cfg.bvc[i].bvci, PROC);
219 disconnect(self:PROC, gb.vc_BSSGP:PROC);
220 }
221}
222
223
224private function f_init_vty() runs on test_CT {
225 map(self:GBPVTY, system:GBPVTY);
226 f_vty_set_prompts(GBPVTY);
227 f_vty_transceive(GBPVTY, "enable");
228}
229
230/* mcc_mnc is 24.008 10.5.5.15 encoded. 262 42 */
231function f_init(BcdMccMnc mcc_mnc := '262F42'H) runs on test_CT {
232 var integer i;
233
234 if (g_initialized == true) {
235 return;
236 }
237 g_initialized := true;
238 g_pcu[0].cfg := {
239 nsei := 96,
240 sgsn_role := false,
241 bvc := { {
242 bvci := 196,
243 cell_id := {
244 ra_id := {
245 lai := {
246 mcc_mnc := mcc_mnc, lac := 13135},
247 rac := 0
248 },
249 cell_id := 20960
250 },
251 depth := BSSGP_DECODE_DEPTH_BSSGP
252 } }
253 };
254 g_pcu[1].cfg := {
255 nsei := 97,
256 sgsn_role := false,
257 bvc := { {
258 bvci := 210,
259 cell_id := {
260 ra_id := {
261 lai := {
262 mcc_mnc := mcc_mnc, lac := 13200},
263 rac := 0
264 },
265 cell_id := 20961
266 },
267 depth := BSSGP_DECODE_DEPTH_BSSGP
268 } }
269 };
270 g_pcu[2].cfg := {
271 nsei := 98,
272 sgsn_role := false,
273 bvc := { {
274 bvci := 220,
275 cell_id := {
276 ra_id := {
277 lai := {
278 mcc_mnc := mcc_mnc, lac := 13300},
279 rac := 0
280 },
281 cell_id := 20962
282 },
283 depth := BSSGP_DECODE_DEPTH_BSSGP
284 } }
285 };
286
287 g_sgsn[0].cfg := {
288 nsei := 101,
289 sgsn_role := true,
290 bvc := {
291 {
292 bvci := 196,
293 cell_id := {
294 ra_id := {
295 lai := {
296 mcc_mnc := mcc_mnc, lac := 13135},
297 rac := 0
298 },
299 cell_id := 20960
300 },
301 depth := BSSGP_DECODE_DEPTH_BSSGP
302 },
303 {
304 bvci := 210,
305 cell_id := {
306 ra_id := {
307 lai := {
308 mcc_mnc := mcc_mnc, lac := 13200},
309 rac := 0
310 },
311 cell_id := 20961
312 },
313 depth := BSSGP_DECODE_DEPTH_BSSGP
314 },
315 {
316 bvci := 220,
317 cell_id := {
318 ra_id := {
319 lai := {
320 mcc_mnc := mcc_mnc, lac := 13300},
321 rac := 0
322 },
323 cell_id := 20962
324 },
325 depth := BSSGP_DECODE_DEPTH_BSSGP
326 }
327 }
328 };
329
330 f_init_vty();
331 f_init_gb_sgsn(g_sgsn[0], "GbProxy_Test-SGSN0", 0);
332 f_sleep(4.0);
333 f_init_gb_pcu(g_pcu[0], "GbProxy_Test-PCU0", 0);
334 f_init_gb_pcu(g_pcu[1], "GbProxy_Test-PCU1", 1);
335 f_init_gb_pcu(g_pcu[2], "GbProxy_Test-PCU2", 2);
336}
337
338function f_cleanup() runs on test_CT {
339 self.stop;
340}
341
342type function void_fn(charstring id) runs on BSSGP_ConnHdlr;
343
344/* helper function to create, connect and start a BSSGP_ConnHdlr component */
345function f_start_handler(void_fn fn, charstring id, GbInstances_PCU pcu, GbInstances_SGSN sgsn, integer imsi_suffix,
346 float t_guard := 30.0)
347runs on test_CT return BSSGP_ConnHdlr {
348 var BSSGP_ConnHdlr vc_conn;
349
350 var BSSGP_ConnHdlrPars pars := {
351 imei := f_gen_imei(imsi_suffix),
352 imsi := f_gen_imsi(imsi_suffix),
353 msisdn := f_gen_msisdn(imsi_suffix),
354 p_tmsi := omit,
355 p_tmsi_sig := omit,
356 tlli := f_gprs_tlli_random(),
357 tlli_old := omit,
358 ra := omit,
359 bssgp_cell_id := { pcu[0].cfg.bvc[0].cell_id, pcu[1].cfg.bvc[0].cell_id, pcu[2].cfg.bvc[0].cell_id },
360 t_guard := t_guard
361 };
362
363 vc_conn := BSSGP_ConnHdlr.create(id);
364 // PDU side
365 connect(vc_conn:PCU[0], pcu[0].vc_BSSGP_BVC[0]:BSSGP_SP);
366 connect(vc_conn:PCU_SIG[0], pcu[0].vc_BSSGP_BVC[0]:BSSGP_SP_SIG);
367 connect(vc_conn:PCU_PROC[0], pcu[0].vc_BSSGP_BVC[0]:BSSGP_PROC);
368 connect(vc_conn:PCU[1], pcu[1].vc_BSSGP_BVC[0]:BSSGP_SP);
369 connect(vc_conn:PCU_SIG[1], pcu[1].vc_BSSGP_BVC[0]:BSSGP_SP_SIG);
370 connect(vc_conn:PCU_PROC[1], pcu[1].vc_BSSGP_BVC[0]:BSSGP_PROC);
371 connect(vc_conn:PCU[2], pcu[2].vc_BSSGP_BVC[0]:BSSGP_SP);
372 connect(vc_conn:PCU_SIG[2], pcu[2].vc_BSSGP_BVC[0]:BSSGP_SP_SIG);
373 connect(vc_conn:PCU_PROC[2], pcu[2].vc_BSSGP_BVC[0]:BSSGP_PROC);
374 // SGSN side
375 connect(vc_conn:SGSN[0], sgsn[0].vc_BSSGP_BVC[0]:BSSGP_SP);
376 connect(vc_conn:SGSN_SIG[0], sgsn[0].vc_BSSGP_BVC[0]:BSSGP_SP_SIG);
377 connect(vc_conn:SGSN_PROC[0], sgsn[0].vc_BSSGP_BVC[0]:BSSGP_PROC);
378
379 vc_conn.start(f_handler_init(fn, id, pars));
380 return vc_conn;
381}
382
383private altstep as_Tguard() runs on BSSGP_ConnHdlr {
384 [] g_Tguard.timeout {
385 setverdict(fail, "Tguard timeout");
386 mtc.stop;
387 }
388}
389
390/* first function called in every ConnHdlr */
391private function f_handler_init(void_fn fn, charstring id, BSSGP_ConnHdlrPars pars)
392runs on BSSGP_ConnHdlr {
393 /* do some common stuff like setting up g_pars */
394 g_pars := pars;
395
396 llc := f_llc_create(false);
397
398
399 g_Tguard.start(pars.t_guard);
400 activate(as_Tguard());
401
402 /* call the user-supplied test case function */
403 fn.apply(id);
404}
405
406/* TODO:
407 * Detach without Attach
408 * SM procedures without attach / RAU
409 * ATTACH / RAU
410 ** with / without authentication
411 ** with / without P-TMSI allocation
412 * re-transmissions of LLC frames
413 * PDP Context activation
414 ** with different GGSN config in SGSN VTY
415 ** with different PDP context type (v4/v6/v46)
416 ** timeout from GGSN
417 ** multiple / secondary PDP context
418 */
419
420private function f_TC_BVC_bringup(charstring id) runs on BSSGP_ConnHdlr {
421 f_sleep(5.0);
422 setverdict(pass);
423}
424
425testcase TC_BVC_bringup() runs on test_CT {
426 var BSSGP_ConnHdlr vc_conn;
427 f_init();
428
429 vc_conn := f_start_handler(refers(f_TC_BVC_bringup), testcasename(), g_pcu, g_sgsn, 51);
430 vc_conn.done;
431
432 f_cleanup();
433}
434
435friend function f_bssgp_suspend(integer ran_idx := 0) runs on BSSGP_ConnHdlr return OCT1 {
436 timer T := 5.0;
437 var PDU_BSSGP rx_pdu;
438 PCU_SIG[ran_idx].send(ts_BSSGP_SUSPEND(g_pars.tlli, g_pars.bssgp_cell_id[ran_idx].ra_id));
439 T.start;
440 alt {
441 [] PCU_SIG[ran_idx].receive(tr_BSSGP_SUSPEND_ACK(g_pars.tlli, g_pars.bssgp_cell_id[ran_idx].ra_id, ?)) -> value rx_pdu {
442 return rx_pdu.pDU_BSSGP_SUSPEND_ACK.suspend_Reference_Number.suspend_Reference_Number_value;
443 }
444 [] PCU_SIG[ran_idx].receive(tr_BSSGP_SUSPEND_NACK(g_pars.tlli, g_pars.bssgp_cell_id[ran_idx].ra_id, ?)) -> value rx_pdu {
445 setverdict(fail, "SUSPEND-NACK in response to SUSPEND for TLLI ", g_pars.tlli);
446 mtc.stop;
447 }
448 [] T.timeout {
449 setverdict(fail, "No SUSPEND-ACK in response to SUSPEND for TLLI ", g_pars.tlli);
450 mtc.stop;
451 }
452 }
453 return '00'O;
454}
455
456friend function f_bssgp_resume(OCT1 susp_ref, integer ran_idx := 0) runs on BSSGP_ConnHdlr {
457 timer T := 5.0;
458 PCU_SIG[ran_idx].send(ts_BSSGP_RESUME(g_pars.tlli, g_pars.bssgp_cell_id[ran_idx].ra_id, susp_ref));
459 T.start;
460 alt {
461 [] PCU_SIG[ran_idx].receive(tr_BSSGP_RESUME_ACK(g_pars.tlli, g_pars.bssgp_cell_id[ran_idx].ra_id));
462 [] PCU_SIG[ran_idx].receive(tr_BSSGP_RESUME_NACK(g_pars.tlli, g_pars.bssgp_cell_id[ran_idx].ra_id,
463?)) {
464 setverdict(fail, "RESUME-NACK in response to RESUME for TLLI ", g_pars.tlli);
465 mtc.stop;
466 }
467 [] T.timeout {
468 setverdict(fail, "No RESUME-ACK in response to SUSPEND for TLLI ", g_pars.tlli);
469 mtc.stop;
470 }
471 }
472}
473
474
475control {
476 execute( TC_BVC_bringup() );
477}
478
479
480}