blob: fd5a6640bc5594178d8ec52d54e725b876ef42f2 [file] [log] [blame]
Harald Welte96a33b02018-02-04 10:36:22 +01001module SGSN_Tests {
2
3import from General_Types all;
4import from Osmocom_Types all;
5import from NS_Types all;
6import from NS_Emulation all;
7import from BSSGP_Types all;
8import from BSSGP_Emulation all;
Harald Welte5ac31492018-02-15 20:39:13 +01009import from Osmocom_Gb_Types all;
10
11import from MobileL3_CommonIE_Types all;
12import from MobileL3_GMM_SM_Types all;
13import from MobileL3_Types all;
14import from L3_Templates all;
15import from L3_Common all;
16
17import from GSUP_Emulation all;
18import from GSUP_Types all;
19import from IPA_Emulation all;
20
21modulepar {
22 /* IP/port on which we run our internal GSUP/HLR emulation */
23 charstring mp_hlr_ip := "127.0.0.1";
24 integer mp_hlr_port := 4222;
25};
26
27type record GbInstance {
28 NS_CT vc_NS,
29 BSSGP_CT vc_BSSGP,
30 BssgpConfig cfg
31};
Harald Welte96a33b02018-02-04 10:36:22 +010032
33type component test_CT {
Harald Welte5ac31492018-02-15 20:39:13 +010034 var GbInstance g_gb[3];
Harald Welte96a33b02018-02-04 10:36:22 +010035
Harald Welte5ac31492018-02-15 20:39:13 +010036 var GSUP_Emulation_CT vc_GSUP;
37 var IPA_Emulation_CT vc_GSUP_IPA;
38 /* only to get events from IPA underneath GSUP */
39 port IPA_CTRL_PT GSUP_IPA_EVENT;
Harald Welte96a33b02018-02-04 10:36:22 +010040
41 var boolean g_initialized := false;
42};
43
Harald Welte5ac31492018-02-15 20:39:13 +010044type component BSSGP_ConnHdlr extends BSSGP_Client_CT, GSUP_ConnHdlr {
45 var BSSGP_ConnHdlrPars g_pars;
Harald Welte62e29582018-02-16 21:17:11 +010046 timer g_Tguard;
Harald Welte5ac31492018-02-15 20:39:13 +010047}
48
49type record SGSN_ConnHdlrNetworkPars {
50 boolean expect_ptmsi,
51 boolean expect_auth,
52 boolean expect_ciph
53};
54
55type record BSSGP_ConnHdlrPars {
56 /* IMEI of the simulated ME */
57 hexstring imei,
58 /* IMEI of the simulated MS */
59 hexstring imsi,
60 /* MSISDN of the simulated MS (probably unused) */
61 hexstring msisdn,
62 /* P-TMSI allocated to the simulated MS */
63 OCT4 p_tmsi optional,
64 /* TLLI of the simulated MS */
65 OCT4 tlli,
66 RoutingAreaIdentificationV ra optional,
67 BssgpCellId bssgp_cell_id,
68 AuthVector vec optional,
Harald Welte62e29582018-02-16 21:17:11 +010069 SGSN_ConnHdlrNetworkPars net,
70 float t_guard
Harald Welte5ac31492018-02-15 20:39:13 +010071};
72
Harald Welte5ac31492018-02-15 20:39:13 +010073private function f_init_gb(inout GbInstance gb) runs on test_CT {
74 gb.vc_NS := NS_CT.create;
75 gb.vc_BSSGP := BSSGP_CT.create;
76 /* connect lower end of BSSGP emulation with NS upper port */
77 connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
78 /* connect lower end of NS emulation to NS codec port (on top of IPL4) */
79 map(gb.vc_NS:NSCP, system:NS_CODEC_PORT);
80
81 gb.vc_NS.start(NSStart());
82 gb.vc_BSSGP.start(BssgpStart(gb.cfg));
83}
84
85private function f_init_gsup(charstring id) runs on test_CT {
86 id := id & "-GSUP";
87 var GsupOps ops := {
88 create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
89 };
90
91 vc_GSUP_IPA := IPA_Emulation_CT.create(id & "-IPA");
92 vc_GSUP := GSUP_Emulation_CT.create(id);
93
94 map(vc_GSUP_IPA:IPA_PORT, system:IPA_CODEC_PT);
95 connect(vc_GSUP:GSUP, vc_GSUP_IPA:IPA_GSUP_PORT);
96 /* we use this hack to get events like ASP_IPA_EVENT_UP */
97 connect(vc_GSUP_IPA:IPA_CTRL_PORT, self:GSUP_IPA_EVENT);
98
99 vc_GSUP.start(GSUP_Emulation.main(ops, id));
100 vc_GSUP_IPA.start(IPA_Emulation.main_server(mp_hlr_ip, mp_hlr_port));
101
102 /* wait for incoming connection to GSUP port before proceeding */
103 timer T := 10.0;
104 T.start;
105 alt {
106 [] GSUP_IPA_EVENT.receive(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_UP)) { }
107 [] T.timeout {
108 setverdict(fail, "No connection to GSUP Port");
109 self.stop;
110 }
111 }
112}
113
Harald Welte96a33b02018-02-04 10:36:22 +0100114function f_init() runs on test_CT {
115 if (g_initialized == true) {
116 return;
117 }
118 g_initialized := true;
Harald Welte5ac31492018-02-15 20:39:13 +0100119 g_gb[0].cfg := {
120 nsei := 96,
121 bvci := 196,
122 cell_id := {
123 ra_id := {
124 lai := {
125 mcc_mnc := '26242F'H, lac := 13135},
126 rac := 0
127 },
128 cell_id := 20960
129 },
130 sgsn_role := false
131 };
Harald Welte96a33b02018-02-04 10:36:22 +0100132
Harald Welte5ac31492018-02-15 20:39:13 +0100133 f_init_gb(g_gb[0]);
134 f_init_gsup("SGSN_Test");
135}
Harald Welte96a33b02018-02-04 10:36:22 +0100136
Harald Welte5ac31492018-02-15 20:39:13 +0100137type function void_fn(charstring id) runs on BSSGP_ConnHdlr;
138
139/* helper function to create, connect and start a BSSGP_ConnHdlr component */
Harald Welte62e29582018-02-16 21:17:11 +0100140function f_start_handler(void_fn fn, charstring id, GbInstance gb, integer imsi_suffix,
141 float t_guard := 30.0)
Harald Welte5ac31492018-02-15 20:39:13 +0100142runs on test_CT return BSSGP_ConnHdlr {
143 var BSSGP_ConnHdlr vc_conn;
144 var SGSN_ConnHdlrNetworkPars net_pars := {
145 expect_ptmsi := true,
146 expect_auth := true,
147 expect_ciph := false
148 };
149 var BSSGP_ConnHdlrPars pars := {
150 imei := f_gen_imei(imsi_suffix),
151 imsi := f_gen_imsi(imsi_suffix),
152 msisdn := f_gen_msisdn(imsi_suffix),
153 p_tmsi := omit,
Harald Welte14a0f942018-02-16 20:42:23 +0100154 tlli := f_gprs_tlli_random(),
Harald Welte5ac31492018-02-15 20:39:13 +0100155 ra := omit,
156 bssgp_cell_id := gb.cfg.cell_id,
157 vec := omit,
Harald Welte62e29582018-02-16 21:17:11 +0100158 net := net_pars,
159 t_guard := t_guard
Harald Welte5ac31492018-02-15 20:39:13 +0100160 };
161
162 vc_conn := BSSGP_ConnHdlr.create(id);
163 connect(vc_conn:BSSGP, gb.vc_BSSGP:BSSGP_SP);
164 connect(vc_conn:BSSGP_PROC, gb.vc_BSSGP:BSSGP_PROC);
165
166 connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT);
167 connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);
168
169 vc_conn.start(f_handler_init(fn, id, pars));
170 return vc_conn;
171}
172
Harald Welte62e29582018-02-16 21:17:11 +0100173private altstep as_Tguard() runs on BSSGP_ConnHdlr {
174 [] g_Tguard.timeout {
175 setverdict(fail, "Tguard timeout");
176 self.stop;
177 }
178}
179
Harald Welte5ac31492018-02-15 20:39:13 +0100180/* first function called in every ConnHdlr */
181private function f_handler_init(void_fn fn, charstring id, BSSGP_ConnHdlrPars pars)
182runs on BSSGP_ConnHdlr {
183 /* do some common stuff like setting up g_pars */
184 g_pars := pars;
185
186 /* register with BSSGP core */
187 f_bssgp_client_register(g_pars.imsi, g_pars.tlli, g_pars.bssgp_cell_id);
188 /* tell GSUP dispatcher to send this IMSI to us */
189 f_create_gsup_expect(hex2str(g_pars.imsi));
190
Harald Welte62e29582018-02-16 21:17:11 +0100191 g_Tguard.start(pars.t_guard);
192 activate(as_Tguard());
193
Harald Welte5ac31492018-02-15 20:39:13 +0100194 /* call the user-supplied test case function */
195 fn.apply(id);
196 f_bssgp_client_unregister(g_pars.imsi);
Harald Welte96a33b02018-02-04 10:36:22 +0100197}
198
199/* TODO:
200 * RAU without Attach
201 * Detach without Attach
202 * SM procedures without attach / RAU
203 * ATTACH / RAU
204 ** with / without authentication
205 ** with / without P-TMSI allocation
206 ** timeout from HLR on SAI
207 ** timeout from HLR on UL
208 ** reject from HLR on SAI
209 ** reject from HLR on UL
210 * re-transmissions of LLC frames
211 * PDP Context activation
212 ** with different GGSN config in SGSN VTY
213 ** with different PDP context type (v4/v6/v46)
214 ** timeout from GGSN
215 ** reject from GGSN
216 */
217
218testcase TC_wait_ns_up() runs on test_CT {
219 f_init();
220 f_sleep(20.0);
221}
222
Harald Welte5ac31492018-02-15 20:39:13 +0100223altstep as_mm_identity() runs on BSSGP_ConnHdlr {
224 var MobileIdentityLV mi;
225 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ID_REQ('001'B))) {
226 mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
227 BSSGP.send(ts_GMM_ID_RESP(mi));
228 repeat;
229 }
230 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ID_REQ('010'B))) {
231 mi := valueof(ts_MI_IMEI_LV(g_pars.imei));
232 BSSGP.send(ts_GMM_ID_RESP(mi));
233 repeat;
234 }
235}
Harald Welte96a33b02018-02-04 10:36:22 +0100236
Harald Welte5ac31492018-02-15 20:39:13 +0100237function f_gmm_auth () runs on BSSGP_ConnHdlr {
238 var BssgpDecoded bd;
239 var PDU_L3_MS_SGSN l3_mo;
240 var PDU_L3_SGSN_MS l3_mt;
241 var default di := activate(as_mm_identity());
242 if (g_pars.net.expect_auth) {
243 g_pars.vec := f_gen_auth_vec_2g();
244 var GSUP_IE auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G(g_pars.vec.rand,
245 g_pars.vec.sres,
246 g_pars.vec.kc));
247 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
248 GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
249 BSSGP.receive(tr_BD_L3_MT(tr_GMM_AUTH_REQ(g_pars.vec.rand))) -> value bd;
250 l3_mt := bd.l3_mt;
251 var BIT4 ac_ref := l3_mt.msgs.gprs_mm.authenticationAndCipheringRequest.acReferenceNumber.valueField;
252 l3_mo := valueof(ts_GMM_AUTH_RESP_2G(ac_ref, g_pars.vec.sres));
253 if (ispresent(l3_mt.msgs.gprs_mm.authenticationAndCipheringRequest.imeisvRequest) and
254 l3_mt.msgs.gprs_mm.authenticationAndCipheringRequest.imeisvRequest.valueField == '001'B) {
255 l3_mo.msgs.gprs_mm.authenticationAndCipheringResponse.imeisv :=
256 valueof(ts_MI_IMEISV_TLV(g_pars.imei & '0'H));
257 }
258 BSSGP.send(l3_mo);
259 }
260 deactivate(di);
261}
262
Harald Welte5a4fa042018-02-16 20:59:21 +0100263function f_random_RAI(HEX0_3n mcc := '262'H, HEX0_3n mnc := '42'H) return RoutingAreaIdentificationV {
264 return f_RAI(mcc, mnc, f_rnd_octstring(2), f_rnd_octstring(1));
265}
266
Harald Welte5ac31492018-02-15 20:39:13 +0100267private function f_TC_attach(charstring id) runs on BSSGP_ConnHdlr {
268 var MobileIdentityLV mi;
Harald Welte5a4fa042018-02-16 20:59:21 +0100269 var RoutingAreaIdentificationV old_ra := f_random_RAI();
Harald Welte5ac31492018-02-15 20:39:13 +0100270
271 if (ispresent(g_pars.p_tmsi)) {
272 mi := valueof(ts_MI_TMSI_LV(g_pars.p_tmsi));
273 } else {
274 mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
275 }
276
277 BSSGP.send(ts_GMM_ATTACH_REQ(mi, old_ra, false, false, omit, omit));
278 f_gmm_auth();
279 /* Expect MSC to perform LU with HLR */
280 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
281 GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
282 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
283 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
284
285 BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_ACCEPT(?, ?, ?)));
286 BSSGP.send(ts_GMM_ATTACH_COMPL);
Harald Welte5a4fa042018-02-16 20:59:21 +0100287 setverdict(pass);
Harald Welte5ac31492018-02-15 20:39:13 +0100288}
289
290testcase TC_attach() runs on test_CT {
291 var BSSGP_ConnHdlr vc_conn;
292 f_init();
293 f_sleep(1.0);
294 vc_conn := f_start_handler(refers(f_TC_attach), testcasename(), g_gb[0], 1);
295 vc_conn.done;
296}
297
Harald Welte5b7c8122018-02-16 21:48:17 +0100298/* MS never responds to ID REQ, expect ATTACH REJECT */
299private function f_TC_attach_auth_id_timeout(charstring id) runs on BSSGP_ConnHdlr {
300 var MobileIdentityLV mi;
301 var RoutingAreaIdentificationV old_ra := f_random_RAI();
302
303 if (ispresent(g_pars.p_tmsi)) {
304 mi := valueof(ts_MI_TMSI_LV(g_pars.p_tmsi));
305 } else {
306 mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
307 }
308
309 BSSGP.send(ts_GMM_ATTACH_REQ(mi, old_ra, false, false, omit, omit));
310 alt {
311 [] BSSGP.receive(tr_BD_L3(tr_GMM_ID_REQ(?))) {
312 /* don't send ID Response */
313 repeat;
314 }
315 [] BSSGP.receive(tr_BD_L3(tr_GMM_ATTACH_REJECT('09'O))) {
316 setverdict(pass);
317 }
318 [] BSSGP.receive(tr_BD_L3(tr_GMM_ATTACH_REJECT(?))) {
319 setverdict(fail, "Wrong Attach Reject Cause");
320 }
321 }
322}
323testcase TC_attach_auth_id_timeout() runs on test_CT {
324 var BSSGP_ConnHdlr vc_conn;
325 f_init();
326 vc_conn := f_start_handler(refers(f_TC_attach_auth_id_timeout), testcasename(), g_gb[0], 2, 40.0);
327 vc_conn.done;
328}
329
330/* HLR never responds to SAI REQ, expect ATTACH REJECT */
331private function f_TC_attach_auth_sai_timeout(charstring id) runs on BSSGP_ConnHdlr {
332 var MobileIdentityLV mi;
333 var RoutingAreaIdentificationV old_ra := f_random_RAI();
334
335 if (ispresent(g_pars.p_tmsi)) {
336 mi := valueof(ts_MI_TMSI_LV(g_pars.p_tmsi));
337 } else {
338 mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
339 }
340
341 BSSGP.send(ts_GMM_ATTACH_REQ(mi, old_ra, false, false, omit, omit));
342 alt {
343 [] as_mm_identity();
344 [] GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi)); { }
345 }
346 /* don't send SAI-response from HLR */
347 BSSGP.receive(tr_BD_L3(tr_GMM_ATTACH_REJECT(?)));
348 setverdict(pass);
349}
350testcase TC_attach_auth_sai_timeout() runs on test_CT {
351 var BSSGP_ConnHdlr vc_conn;
352 f_init();
353 vc_conn := f_start_handler(refers(f_TC_attach_auth_sai_timeout), testcasename(), g_gb[0], 3);
354 vc_conn.done;
355}
356
357/* HLR never responds to UL REQ, expect ATTACH REJECT */
358private function f_TC_attach_gsup_lu_timeout(charstring id) runs on BSSGP_ConnHdlr {
359 var MobileIdentityLV mi;
360 var RoutingAreaIdentificationV old_ra := f_random_RAI();
361
362 if (ispresent(g_pars.p_tmsi)) {
363 mi := valueof(ts_MI_TMSI_LV(g_pars.p_tmsi));
364 } else {
365 mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
366 }
367
368 BSSGP.send(ts_GMM_ATTACH_REQ(mi, old_ra, false, false, omit, omit));
369 f_gmm_auth();
370 /* Expect MSC to perform LU with HLR */
371 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
372 /* Never follow-up with ISD_REQ or UL_RES */
373 alt {
374 [] BSSGP.receive(tr_BD_L3(tr_GMM_ATTACH_REJECT(?))) {
375 setverdict(pass);
376 }
377 [] BSSGP.receive(tr_BD_L3(tr_GMM_ATTACH_ACCEPT(?, ?, ?))) {
378 setverdict(fail);
379 }
380 }
381}
382testcase TC_attach_gsup_lu_timeout() runs on test_CT {
383 var BSSGP_ConnHdlr vc_conn;
384 f_init();
385 f_sleep(1.0);
386 vc_conn := f_start_handler(refers(f_TC_attach_gsup_lu_timeout), testcasename(), g_gb[0], 4);
387 vc_conn.done;
388}
389
390
Harald Welte5ac31492018-02-15 20:39:13 +0100391
392control {
Harald Welte5b7c8122018-02-16 21:48:17 +0100393 execute( TC_attach() );
394 execute( TC_attach_auth_id_timeout() );
395 execute( TC_attach_auth_sai_timeout() );
396 execute( TC_attach_gsup_lu_timeout() );
Harald Welte5ac31492018-02-15 20:39:13 +0100397}
Harald Welte96a33b02018-02-04 10:36:22 +0100398
399
400
401}