blob: a853c6d68408d617f829ded7a2f00805c27530ca [file] [log] [blame]
Harald Welte96a33b02018-02-04 10:36:22 +01001module SGSN_Tests {
2
3import from General_Types all;
4import from Osmocom_Types all;
Harald Welte37692d82018-02-18 15:21:34 +01005import from Native_Functions all;
Harald Welte96a33b02018-02-04 10:36:22 +01006import from NS_Types all;
7import from NS_Emulation all;
8import from BSSGP_Types all;
9import from BSSGP_Emulation all;
Harald Welte5ac31492018-02-15 20:39:13 +010010import from Osmocom_Gb_Types all;
11
12import from MobileL3_CommonIE_Types all;
13import from MobileL3_GMM_SM_Types all;
14import from MobileL3_Types all;
15import from L3_Templates all;
16import from L3_Common all;
17
18import from GSUP_Emulation all;
19import from GSUP_Types all;
20import from IPA_Emulation all;
21
Harald Welteeded9ad2018-02-17 20:57:34 +010022import from GTP_Emulation all;
23import from GTP_Templates all;
24import from GTP_CodecPort all;
25import from GTPC_Types all;
26import from GTPU_Types all;
27
Harald Weltea2526a82018-02-18 19:03:36 +010028import from LLC_Types all;
29import from LLC_Templates all;
30
31import from SNDCP_Types all;
32
Harald Weltebd194722018-02-16 22:11:08 +010033import from TELNETasp_PortType all;
34import from Osmocom_VTY_Functions all;
35
Harald Welteeded9ad2018-02-17 20:57:34 +010036
Harald Welte5ac31492018-02-15 20:39:13 +010037modulepar {
38 /* IP/port on which we run our internal GSUP/HLR emulation */
39 charstring mp_hlr_ip := "127.0.0.1";
40 integer mp_hlr_port := 4222;
Harald Welteeded9ad2018-02-17 20:57:34 +010041 charstring mp_ggsn_ip := "127.0.0.2";
Harald Welte5ac31492018-02-15 20:39:13 +010042};
43
44type record GbInstance {
45 NS_CT vc_NS,
46 BSSGP_CT vc_BSSGP,
47 BssgpConfig cfg
48};
Harald Welte96a33b02018-02-04 10:36:22 +010049
50type component test_CT {
Harald Welte5ac31492018-02-15 20:39:13 +010051 var GbInstance g_gb[3];
Harald Welte96a33b02018-02-04 10:36:22 +010052
Harald Welte5ac31492018-02-15 20:39:13 +010053 var GSUP_Emulation_CT vc_GSUP;
54 var IPA_Emulation_CT vc_GSUP_IPA;
55 /* only to get events from IPA underneath GSUP */
56 port IPA_CTRL_PT GSUP_IPA_EVENT;
Harald Welte96a33b02018-02-04 10:36:22 +010057
Harald Welteeded9ad2018-02-17 20:57:34 +010058 var GTP_Emulation_CT vc_GTP;
59
Harald Weltebd194722018-02-16 22:11:08 +010060 port TELNETasp_PT SGSNVTY;
61
Harald Welte96a33b02018-02-04 10:36:22 +010062 var boolean g_initialized := false;
63};
64
Harald Welteeded9ad2018-02-17 20:57:34 +010065type component BSSGP_ConnHdlr extends BSSGP_Client_CT, GSUP_ConnHdlr, GTP_ConnHdlr {
Harald Welte5ac31492018-02-15 20:39:13 +010066 var BSSGP_ConnHdlrPars g_pars;
Harald Welte62e29582018-02-16 21:17:11 +010067 timer g_Tguard;
Harald Welte5ac31492018-02-15 20:39:13 +010068}
69
70type record SGSN_ConnHdlrNetworkPars {
71 boolean expect_ptmsi,
72 boolean expect_auth,
73 boolean expect_ciph
74};
75
76type record BSSGP_ConnHdlrPars {
77 /* IMEI of the simulated ME */
78 hexstring imei,
79 /* IMEI of the simulated MS */
80 hexstring imsi,
81 /* MSISDN of the simulated MS (probably unused) */
82 hexstring msisdn,
83 /* P-TMSI allocated to the simulated MS */
84 OCT4 p_tmsi optional,
Harald Welte04683d02018-02-16 22:43:45 +010085 OCT3 p_tmsi_sig optional,
Harald Welte5ac31492018-02-15 20:39:13 +010086 /* TLLI of the simulated MS */
87 OCT4 tlli,
Harald Weltef70997d2018-02-17 10:11:19 +010088 OCT4 tlli_old optional,
Harald Welte5ac31492018-02-15 20:39:13 +010089 RoutingAreaIdentificationV ra optional,
90 BssgpCellId bssgp_cell_id,
91 AuthVector vec optional,
Harald Welte62e29582018-02-16 21:17:11 +010092 SGSN_ConnHdlrNetworkPars net,
93 float t_guard
Harald Welte5ac31492018-02-15 20:39:13 +010094};
95
Harald Welte3fdbe822018-02-18 19:10:18 +010096private function f_init_gb(inout GbInstance gb, charstring id) runs on test_CT {
97 gb.vc_NS := NS_CT.create(id & "-NS");
98 gb.vc_BSSGP := BSSGP_CT.create(id & "-BSSGP");
Harald Welte5ac31492018-02-15 20:39:13 +010099 /* connect lower end of BSSGP emulation with NS upper port */
100 connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
101 /* connect lower end of NS emulation to NS codec port (on top of IPL4) */
102 map(gb.vc_NS:NSCP, system:NS_CODEC_PORT);
103
104 gb.vc_NS.start(NSStart());
105 gb.vc_BSSGP.start(BssgpStart(gb.cfg));
106}
107
108private function f_init_gsup(charstring id) runs on test_CT {
109 id := id & "-GSUP";
110 var GsupOps ops := {
111 create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
112 };
113
114 vc_GSUP_IPA := IPA_Emulation_CT.create(id & "-IPA");
115 vc_GSUP := GSUP_Emulation_CT.create(id);
116
117 map(vc_GSUP_IPA:IPA_PORT, system:IPA_CODEC_PT);
118 connect(vc_GSUP:GSUP, vc_GSUP_IPA:IPA_GSUP_PORT);
119 /* we use this hack to get events like ASP_IPA_EVENT_UP */
120 connect(vc_GSUP_IPA:IPA_CTRL_PORT, self:GSUP_IPA_EVENT);
121
122 vc_GSUP.start(GSUP_Emulation.main(ops, id));
123 vc_GSUP_IPA.start(IPA_Emulation.main_server(mp_hlr_ip, mp_hlr_port));
124
125 /* wait for incoming connection to GSUP port before proceeding */
126 timer T := 10.0;
127 T.start;
128 alt {
129 [] GSUP_IPA_EVENT.receive(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_UP)) { }
130 [] T.timeout {
131 setverdict(fail, "No connection to GSUP Port");
132 self.stop;
133 }
134 }
135}
136
Harald Welteeded9ad2018-02-17 20:57:34 +0100137private function f_init_gtp(charstring id) runs on test_CT {
138 id := id & "-GTP";
139
140 var GtpEmulationCfg gtp_cfg := {
141 gtpc_bind_ip := mp_ggsn_ip,
142 gtpc_bind_port := GTP1C_PORT,
143 gtpu_bind_ip := mp_ggsn_ip,
144 gtpu_bind_port := GTP1U_PORT,
145 sgsn_role := false
146 };
147
148 vc_GTP := GTP_Emulation_CT.create(id);
149 vc_GTP.start(GTP_Emulation.main(gtp_cfg));
150}
151
Harald Weltebd194722018-02-16 22:11:08 +0100152private function f_init_vty() runs on test_CT {
153 map(self:SGSNVTY, system:SGSNVTY);
154 f_vty_set_prompts(SGSNVTY);
155 f_vty_transceive(SGSNVTY, "enable");
156 f_vty_config(SGSNVTY, "sgsn", "auth-policy remote");
157}
158
159
Harald Welte96a33b02018-02-04 10:36:22 +0100160function f_init() runs on test_CT {
161 if (g_initialized == true) {
162 return;
163 }
164 g_initialized := true;
Harald Welte5ac31492018-02-15 20:39:13 +0100165 g_gb[0].cfg := {
166 nsei := 96,
167 bvci := 196,
168 cell_id := {
169 ra_id := {
170 lai := {
171 mcc_mnc := '26242F'H, lac := 13135},
172 rac := 0
173 },
174 cell_id := 20960
175 },
176 sgsn_role := false
177 };
Harald Welte96a33b02018-02-04 10:36:22 +0100178
Harald Welte3fdbe822018-02-18 19:10:18 +0100179 f_init_gb(g_gb[0], "SGSN_Test-Gb0");
Harald Welte5ac31492018-02-15 20:39:13 +0100180 f_init_gsup("SGSN_Test");
Harald Welteeded9ad2018-02-17 20:57:34 +0100181 f_init_gtp("SGSN_Test");
Harald Weltebd194722018-02-16 22:11:08 +0100182 f_init_vty();
Harald Welte5ac31492018-02-15 20:39:13 +0100183}
Harald Welte96a33b02018-02-04 10:36:22 +0100184
Harald Welte5ac31492018-02-15 20:39:13 +0100185type function void_fn(charstring id) runs on BSSGP_ConnHdlr;
186
187/* helper function to create, connect and start a BSSGP_ConnHdlr component */
Harald Welte62e29582018-02-16 21:17:11 +0100188function f_start_handler(void_fn fn, charstring id, GbInstance gb, integer imsi_suffix,
189 float t_guard := 30.0)
Harald Welte5ac31492018-02-15 20:39:13 +0100190runs on test_CT return BSSGP_ConnHdlr {
191 var BSSGP_ConnHdlr vc_conn;
192 var SGSN_ConnHdlrNetworkPars net_pars := {
193 expect_ptmsi := true,
194 expect_auth := true,
195 expect_ciph := false
196 };
197 var BSSGP_ConnHdlrPars pars := {
198 imei := f_gen_imei(imsi_suffix),
199 imsi := f_gen_imsi(imsi_suffix),
200 msisdn := f_gen_msisdn(imsi_suffix),
201 p_tmsi := omit,
Harald Welte04683d02018-02-16 22:43:45 +0100202 p_tmsi_sig := omit,
Harald Welte14a0f942018-02-16 20:42:23 +0100203 tlli := f_gprs_tlli_random(),
Harald Weltef70997d2018-02-17 10:11:19 +0100204 tlli_old := omit,
Harald Welte5ac31492018-02-15 20:39:13 +0100205 ra := omit,
206 bssgp_cell_id := gb.cfg.cell_id,
207 vec := omit,
Harald Welte62e29582018-02-16 21:17:11 +0100208 net := net_pars,
209 t_guard := t_guard
Harald Welte5ac31492018-02-15 20:39:13 +0100210 };
211
212 vc_conn := BSSGP_ConnHdlr.create(id);
213 connect(vc_conn:BSSGP, gb.vc_BSSGP:BSSGP_SP);
214 connect(vc_conn:BSSGP_PROC, gb.vc_BSSGP:BSSGP_PROC);
215
216 connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT);
217 connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);
218
Harald Welteeded9ad2018-02-17 20:57:34 +0100219 connect(vc_conn:GTP, vc_GTP:CLIENT);
220 connect(vc_conn:GTP_PROC, vc_GTP:CLIENT_PROC);
221
Harald Welte5ac31492018-02-15 20:39:13 +0100222 vc_conn.start(f_handler_init(fn, id, pars));
223 return vc_conn;
224}
225
Harald Welte62e29582018-02-16 21:17:11 +0100226private altstep as_Tguard() runs on BSSGP_ConnHdlr {
227 [] g_Tguard.timeout {
228 setverdict(fail, "Tguard timeout");
229 self.stop;
230 }
231}
232
Harald Welte5ac31492018-02-15 20:39:13 +0100233/* first function called in every ConnHdlr */
234private function f_handler_init(void_fn fn, charstring id, BSSGP_ConnHdlrPars pars)
235runs on BSSGP_ConnHdlr {
236 /* do some common stuff like setting up g_pars */
237 g_pars := pars;
238
239 /* register with BSSGP core */
240 f_bssgp_client_register(g_pars.imsi, g_pars.tlli, g_pars.bssgp_cell_id);
241 /* tell GSUP dispatcher to send this IMSI to us */
242 f_create_gsup_expect(hex2str(g_pars.imsi));
Harald Welteeded9ad2018-02-17 20:57:34 +0100243 /* tell GTP dispatcher to send this IMSI to us */
244 f_gtp_register_imsi(g_pars.imsi);
Harald Welte5ac31492018-02-15 20:39:13 +0100245
Harald Welte62e29582018-02-16 21:17:11 +0100246 g_Tguard.start(pars.t_guard);
247 activate(as_Tguard());
248
Harald Welte5ac31492018-02-15 20:39:13 +0100249 /* call the user-supplied test case function */
250 fn.apply(id);
251 f_bssgp_client_unregister(g_pars.imsi);
Harald Welte96a33b02018-02-04 10:36:22 +0100252}
253
254/* TODO:
Harald Welte96a33b02018-02-04 10:36:22 +0100255 * Detach without Attach
256 * SM procedures without attach / RAU
257 * ATTACH / RAU
258 ** with / without authentication
259 ** with / without P-TMSI allocation
Harald Welte96a33b02018-02-04 10:36:22 +0100260 * re-transmissions of LLC frames
261 * PDP Context activation
262 ** with different GGSN config in SGSN VTY
263 ** with different PDP context type (v4/v6/v46)
264 ** timeout from GGSN
Harald Welte6f203162018-02-18 22:04:55 +0100265 ** multiple / secondary PDP context
Harald Welte96a33b02018-02-04 10:36:22 +0100266 */
267
268testcase TC_wait_ns_up() runs on test_CT {
269 f_init();
270 f_sleep(20.0);
271}
272
Harald Welte5ac31492018-02-15 20:39:13 +0100273altstep as_mm_identity() runs on BSSGP_ConnHdlr {
274 var MobileIdentityLV mi;
275 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ID_REQ('001'B))) {
276 mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
277 BSSGP.send(ts_GMM_ID_RESP(mi));
278 repeat;
279 }
280 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ID_REQ('010'B))) {
281 mi := valueof(ts_MI_IMEI_LV(g_pars.imei));
282 BSSGP.send(ts_GMM_ID_RESP(mi));
283 repeat;
284 }
285}
Harald Welte96a33b02018-02-04 10:36:22 +0100286
Harald Welte311ec272018-02-17 09:40:03 +0100287/* perform GMM authentication (if expected) */
Harald Welte5ac31492018-02-15 20:39:13 +0100288function f_gmm_auth () runs on BSSGP_ConnHdlr {
289 var BssgpDecoded bd;
290 var PDU_L3_MS_SGSN l3_mo;
291 var PDU_L3_SGSN_MS l3_mt;
292 var default di := activate(as_mm_identity());
293 if (g_pars.net.expect_auth) {
294 g_pars.vec := f_gen_auth_vec_2g();
295 var GSUP_IE auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G(g_pars.vec.rand,
296 g_pars.vec.sres,
297 g_pars.vec.kc));
298 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
299 GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
300 BSSGP.receive(tr_BD_L3_MT(tr_GMM_AUTH_REQ(g_pars.vec.rand))) -> value bd;
301 l3_mt := bd.l3_mt;
302 var BIT4 ac_ref := l3_mt.msgs.gprs_mm.authenticationAndCipheringRequest.acReferenceNumber.valueField;
303 l3_mo := valueof(ts_GMM_AUTH_RESP_2G(ac_ref, g_pars.vec.sres));
304 if (ispresent(l3_mt.msgs.gprs_mm.authenticationAndCipheringRequest.imeisvRequest) and
305 l3_mt.msgs.gprs_mm.authenticationAndCipheringRequest.imeisvRequest.valueField == '001'B) {
306 l3_mo.msgs.gprs_mm.authenticationAndCipheringResponse.imeisv :=
307 valueof(ts_MI_IMEISV_TLV(g_pars.imei & '0'H));
308 }
309 BSSGP.send(l3_mo);
Harald Welte76dee092018-02-16 22:12:59 +0100310 } else {
311 /* wait for identity procedure */
312 f_sleep(1.0);
Harald Welte5ac31492018-02-15 20:39:13 +0100313 }
Harald Welte76dee092018-02-16 22:12:59 +0100314
Harald Welte5ac31492018-02-15 20:39:13 +0100315 deactivate(di);
316}
317
Harald Weltef70997d2018-02-17 10:11:19 +0100318function f_upd_ptmsi_and_tlli(OCT4 p_tmsi) runs on BSSGP_ConnHdlr {
319 g_pars.p_tmsi := p_tmsi;
320 /* update TLLI */
321 g_pars.tlli_old := g_pars.tlli;
322 g_pars.tlli := g_pars.p_tmsi or4b 'c0000000'O;
323 f_bssgp_client_llgmm_assign(g_pars.tlli_old, g_pars.tlli);
324}
325
Harald Welte04683d02018-02-16 22:43:45 +0100326function f_process_attach_accept(PDU_GMM_AttachAccept aa) runs on BSSGP_ConnHdlr {
327 /* mandatory IE */
328 g_pars.ra := aa.routingAreaIdentification;
329 if (ispresent(aa.allocatedPTMSI)) {
330 if (not g_pars.net.expect_ptmsi) {
331 setverdict(fail, "unexpected P-TMSI allocation");
332 self.stop;
333 }
Harald Weltef70997d2018-02-17 10:11:19 +0100334 f_upd_ptmsi_and_tlli(aa.allocatedPTMSI.mobileIdentityLV.mobileIdentityV.oddEvenInd_identity.tmsi_ptmsi.octets);
Harald Welte04683d02018-02-16 22:43:45 +0100335 }
336 if (ispresent(aa.msIdentity)) {
337 setverdict(fail, "unexpected TMSI allocation in non-combined attach");
338 self.stop;
339 }
340 /* P-TMSI.sig */
341 if (ispresent(aa.ptmsiSignature)) {
342 g_pars.p_tmsi_sig := aa.ptmsiSignature.valueField;
343 }
344 /* updateTimer */
345 // aa.readyTimer
346 /* T3302, T3319, T3323, T3312_ext, T3324 */
347}
348
Harald Welte91636de2018-02-17 10:16:14 +0100349function f_process_rau_accept(PDU_GMM_RoutingAreaUpdateAccept ra) runs on BSSGP_ConnHdlr {
350 /* mandatory IE */
351 g_pars.ra := ra.routingAreaId;
352 if (ispresent(ra.allocatedPTMSI)) {
353 if (not g_pars.net.expect_ptmsi) {
354 setverdict(fail, "unexpected P-TMSI allocation");
355 self.stop;
356 }
357 f_upd_ptmsi_and_tlli(ra.allocatedPTMSI.mobileIdentityLV.mobileIdentityV.oddEvenInd_identity.tmsi_ptmsi.octets);
358 }
359 if (ispresent(ra.msIdentity)) {
360 setverdict(fail, "unexpected TMSI allocation in non-combined attach");
361 self.stop;
362 }
363 /* P-TMSI.sig */
364 if (ispresent(ra.ptmsiSignature)) {
365 g_pars.p_tmsi_sig := ra.ptmsiSignature.valueField;
366 }
367 /* updateTimer */
368 // aa.readyTimer
369 /* T3302, T3319, T3323, T3312_ext, T3324 */
370}
371
372
Harald Welte5a4fa042018-02-16 20:59:21 +0100373function f_random_RAI(HEX0_3n mcc := '262'H, HEX0_3n mnc := '42'H) return RoutingAreaIdentificationV {
374 return f_RAI(mcc, mnc, f_rnd_octstring(2), f_rnd_octstring(1));
375}
376
Harald Welte23178c52018-02-17 09:36:33 +0100377/* return a MobileIdentityLV: P-TMSI if we have one, IMSI otherwise */
378private function f_mi_get_lv() runs on BSSGP_ConnHdlr return MobileIdentityLV {
379 if (ispresent(g_pars.p_tmsi)) {
380 return valueof(ts_MI_TMSI_LV(g_pars.p_tmsi));
381 } else {
382 return valueof(ts_MI_IMSI_LV(g_pars.imsi));
383 }
384}
385
Harald Welte311ec272018-02-17 09:40:03 +0100386private function f_gmm_gsup_lu_isd() runs on BSSGP_ConnHdlr {
Harald Welteeded9ad2018-02-17 20:57:34 +0100387 var GSUP_PDU gsup;
Harald Welte311ec272018-02-17 09:40:03 +0100388 /* Expect MSC to perform LU with HLR */
389 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
Harald Welteeded9ad2018-02-17 20:57:34 +0100390 gsup := valueof(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
391 gsup.ies := gsup.ies & { valueof(ts_GSUP_IE_PdpInfo(char2oct("*"), '0121'O, ''O)) };
392 GSUP.send(gsup);
Harald Welte311ec272018-02-17 09:40:03 +0100393 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
394 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
395}
396
Harald Welte5ac31492018-02-15 20:39:13 +0100397private function f_TC_attach(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte04683d02018-02-16 22:43:45 +0100398 var BssgpDecoded bd;
Harald Welte5a4fa042018-02-16 20:59:21 +0100399 var RoutingAreaIdentificationV old_ra := f_random_RAI();
Harald Welte5ac31492018-02-15 20:39:13 +0100400
Harald Welte23178c52018-02-17 09:36:33 +0100401 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welte5ac31492018-02-15 20:39:13 +0100402 f_gmm_auth();
403 /* Expect MSC to perform LU with HLR */
Harald Welte311ec272018-02-17 09:40:03 +0100404 f_gmm_gsup_lu_isd();
Harald Welte5ac31492018-02-15 20:39:13 +0100405
Harald Welte04683d02018-02-16 22:43:45 +0100406 BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?))) -> value bd {
407 f_process_attach_accept(bd.l3_mt.msgs.gprs_mm.attachAccept);
408 }
409 /* FIXME: Extract P-TMSI, if any. Only send Complete if necessary */
Harald Welte5ac31492018-02-15 20:39:13 +0100410 BSSGP.send(ts_GMM_ATTACH_COMPL);
Harald Welte5a4fa042018-02-16 20:59:21 +0100411 setverdict(pass);
Harald Welte5ac31492018-02-15 20:39:13 +0100412}
413
414testcase TC_attach() runs on test_CT {
415 var BSSGP_ConnHdlr vc_conn;
416 f_init();
417 f_sleep(1.0);
418 vc_conn := f_start_handler(refers(f_TC_attach), testcasename(), g_gb[0], 1);
419 vc_conn.done;
420}
421
Harald Welte5b7c8122018-02-16 21:48:17 +0100422/* MS never responds to ID REQ, expect ATTACH REJECT */
423private function f_TC_attach_auth_id_timeout(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte5b7c8122018-02-16 21:48:17 +0100424 var RoutingAreaIdentificationV old_ra := f_random_RAI();
425
Harald Welte23178c52018-02-17 09:36:33 +0100426 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welte5b7c8122018-02-16 21:48:17 +0100427 alt {
Harald Welte1967d472018-02-16 21:54:21 +0100428 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ID_REQ(?))) {
Harald Welte5b7c8122018-02-16 21:48:17 +0100429 /* don't send ID Response */
430 repeat;
431 }
Harald Welte1967d472018-02-16 21:54:21 +0100432 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT('09'O))) {
Harald Welte5b7c8122018-02-16 21:48:17 +0100433 setverdict(pass);
434 }
Harald Welte1967d472018-02-16 21:54:21 +0100435 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT(?))) {
Harald Welte5b7c8122018-02-16 21:48:17 +0100436 setverdict(fail, "Wrong Attach Reject Cause");
437 }
438 }
439}
440testcase TC_attach_auth_id_timeout() runs on test_CT {
441 var BSSGP_ConnHdlr vc_conn;
442 f_init();
443 vc_conn := f_start_handler(refers(f_TC_attach_auth_id_timeout), testcasename(), g_gb[0], 2, 40.0);
444 vc_conn.done;
445}
446
447/* HLR never responds to SAI REQ, expect ATTACH REJECT */
448private function f_TC_attach_auth_sai_timeout(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte5b7c8122018-02-16 21:48:17 +0100449 var RoutingAreaIdentificationV old_ra := f_random_RAI();
450
Harald Welte23178c52018-02-17 09:36:33 +0100451 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welte5b7c8122018-02-16 21:48:17 +0100452 alt {
453 [] as_mm_identity();
454 [] GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi)); { }
455 }
456 /* don't send SAI-response from HLR */
Harald Welte1967d472018-02-16 21:54:21 +0100457 BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT(?)));
Harald Welte5b7c8122018-02-16 21:48:17 +0100458 setverdict(pass);
459}
460testcase TC_attach_auth_sai_timeout() runs on test_CT {
461 var BSSGP_ConnHdlr vc_conn;
462 f_init();
463 vc_conn := f_start_handler(refers(f_TC_attach_auth_sai_timeout), testcasename(), g_gb[0], 3);
464 vc_conn.done;
465}
466
Harald Weltefe253882018-02-17 09:25:00 +0100467/* HLR rejects SAI, expect ATTACH REJECT */
468private function f_TC_attach_auth_sai_reject(charstring id) runs on BSSGP_ConnHdlr {
Harald Weltefe253882018-02-17 09:25:00 +0100469 var RoutingAreaIdentificationV old_ra := f_random_RAI();
470
Harald Welte23178c52018-02-17 09:36:33 +0100471 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Weltefe253882018-02-17 09:25:00 +0100472 alt {
473 [] as_mm_identity();
474 [] GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi)); {
475 GSUP.send(ts_GSUP_SAI_ERR(g_pars.imsi, 23));
476 }
477 }
478 BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT(?)));
479 setverdict(pass);
480}
481testcase TC_attach_auth_sai_reject() runs on test_CT {
482 var BSSGP_ConnHdlr vc_conn;
483 f_init();
Harald Welteb7c14e92018-02-17 09:29:16 +0100484 vc_conn := f_start_handler(refers(f_TC_attach_auth_sai_reject), testcasename(), g_gb[0], 4);
Harald Weltefe253882018-02-17 09:25:00 +0100485 vc_conn.done;
486}
487
Harald Welte5b7c8122018-02-16 21:48:17 +0100488/* HLR never responds to UL REQ, expect ATTACH REJECT */
489private function f_TC_attach_gsup_lu_timeout(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte04683d02018-02-16 22:43:45 +0100490 var BssgpDecoded bd;
Harald Welte5b7c8122018-02-16 21:48:17 +0100491 var RoutingAreaIdentificationV old_ra := f_random_RAI();
492
Harald Welte23178c52018-02-17 09:36:33 +0100493 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welte5b7c8122018-02-16 21:48:17 +0100494 f_gmm_auth();
495 /* Expect MSC to perform LU with HLR */
496 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
497 /* Never follow-up with ISD_REQ or UL_RES */
498 alt {
Harald Welte1967d472018-02-16 21:54:21 +0100499 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT(?))) {
Harald Welte5b7c8122018-02-16 21:48:17 +0100500 setverdict(pass);
501 }
Harald Welte04683d02018-02-16 22:43:45 +0100502 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?))) -> value bd {
503 f_process_attach_accept(bd.l3_mt.msgs.gprs_mm.attachAccept);
Harald Welte5b7c8122018-02-16 21:48:17 +0100504 setverdict(fail);
505 }
506 }
507}
508testcase TC_attach_gsup_lu_timeout() runs on test_CT {
509 var BSSGP_ConnHdlr vc_conn;
510 f_init();
511 f_sleep(1.0);
Harald Welteb7c14e92018-02-17 09:29:16 +0100512 vc_conn := f_start_handler(refers(f_TC_attach_gsup_lu_timeout), testcasename(), g_gb[0], 5);
Harald Welte5b7c8122018-02-16 21:48:17 +0100513 vc_conn.done;
514}
515
Harald Welteb7c14e92018-02-17 09:29:16 +0100516/* HLR rejects UL REQ, expect ATTACH REJECT */
517private function f_TC_attach_gsup_lu_reject(charstring id) runs on BSSGP_ConnHdlr {
518 var BssgpDecoded bd;
Harald Welteb7c14e92018-02-17 09:29:16 +0100519 var RoutingAreaIdentificationV old_ra := f_random_RAI();
520
Harald Welte23178c52018-02-17 09:36:33 +0100521 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welteb7c14e92018-02-17 09:29:16 +0100522 f_gmm_auth();
523 /* Expect MSC to perform LU with HLR */
524 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi)) {
525 GSUP.send(ts_GSUP_UL_ERR(g_pars.imsi, 0));
526 }
527 alt {
528 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT(?))) {
529 setverdict(pass);
530 }
531 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?))) -> value bd {
532 f_process_attach_accept(bd.l3_mt.msgs.gprs_mm.attachAccept);
533 setverdict(fail);
534 }
535 }
536}
537testcase TC_attach_gsup_lu_reject() runs on test_CT {
538 var BSSGP_ConnHdlr vc_conn;
539 f_init();
540 f_sleep(1.0);
541 vc_conn := f_start_handler(refers(f_TC_attach_gsup_lu_reject), testcasename(), g_gb[0], 6);
542 vc_conn.done;
543}
544
545
Harald Welte3823e2e2018-02-16 21:53:48 +0100546/* Attempt of combined GPRS + IMSI attach: network should ACK only GPRS attach */
547private function f_TC_attach_combined(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte04683d02018-02-16 22:43:45 +0100548 var BssgpDecoded bd;
Harald Welte3823e2e2018-02-16 21:53:48 +0100549 var RoutingAreaIdentificationV old_ra := f_random_RAI();
550
Harald Welte23178c52018-02-17 09:36:33 +0100551 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, true, false, omit, omit));
Harald Welte3823e2e2018-02-16 21:53:48 +0100552 f_gmm_auth();
553 /* Expect MSC to perform LU with HLR */
Harald Welte311ec272018-02-17 09:40:03 +0100554 f_gmm_gsup_lu_isd();
Harald Welte3823e2e2018-02-16 21:53:48 +0100555
Harald Welte04683d02018-02-16 22:43:45 +0100556 BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?))) -> value bd {
557 f_process_attach_accept(bd.l3_mt.msgs.gprs_mm.attachAccept);
558 }
Harald Welte3823e2e2018-02-16 21:53:48 +0100559 BSSGP.send(ts_GMM_ATTACH_COMPL);
560 setverdict(pass);
561}
Harald Welte3823e2e2018-02-16 21:53:48 +0100562testcase TC_attach_combined() runs on test_CT {
563 var BSSGP_ConnHdlr vc_conn;
564 f_init();
565 f_sleep(1.0);
Harald Welteb7c14e92018-02-17 09:29:16 +0100566 vc_conn := f_start_handler(refers(f_TC_attach_combined), testcasename(), g_gb[0], 7);
Harald Welte3823e2e2018-02-16 21:53:48 +0100567 vc_conn.done;
568}
569
Harald Welte76dee092018-02-16 22:12:59 +0100570/* Attempt of GPRS ATTACH in 'accept all' mode */
571private function f_TC_attach_accept_all(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte04683d02018-02-16 22:43:45 +0100572 var BssgpDecoded bd;
Harald Welte76dee092018-02-16 22:12:59 +0100573 var RoutingAreaIdentificationV old_ra := f_random_RAI();
574
575 g_pars.net.expect_auth := false;
576
Harald Welte23178c52018-02-17 09:36:33 +0100577 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welte76dee092018-02-16 22:12:59 +0100578 f_gmm_auth();
Harald Welte04683d02018-02-16 22:43:45 +0100579 BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?))) -> value bd {
580 f_process_attach_accept(bd.l3_mt.msgs.gprs_mm.attachAccept);
581 }
Harald Welte76dee092018-02-16 22:12:59 +0100582 BSSGP.send(ts_GMM_ATTACH_COMPL);
583 setverdict(pass);
584}
585testcase TC_attach_accept_all() runs on test_CT {
586 var BSSGP_ConnHdlr vc_conn;
587 f_init();
588 f_sleep(1.0);
589 f_vty_config(SGSNVTY, "sgsn", "auth-policy accept-all");
Harald Welteb7c14e92018-02-17 09:29:16 +0100590 vc_conn := f_start_handler(refers(f_TC_attach_accept_all), testcasename(), g_gb[0], 8);
Harald Welte76dee092018-02-16 22:12:59 +0100591 vc_conn.done;
592}
Harald Welte5b7c8122018-02-16 21:48:17 +0100593
Harald Welteb2124b22018-02-16 22:26:56 +0100594/* Attempt of GPRS ATTACH in 'accept all' mode */
595private function f_TC_attach_closed_foreign(charstring id) runs on BSSGP_ConnHdlr {
Harald Welteb2124b22018-02-16 22:26:56 +0100596 var RoutingAreaIdentificationV old_ra := f_random_RAI();
597
598 /* Simulate a foreign IMSI */
599 g_pars.imsi := '001010123456789'H;
600 f_bssgp_client_register(g_pars.imsi, g_pars.tlli, g_pars.bssgp_cell_id);
601
602 g_pars.net.expect_auth := false;
603
Harald Welte23178c52018-02-17 09:36:33 +0100604 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welteb2124b22018-02-16 22:26:56 +0100605 alt {
606 [] as_mm_identity();
607 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT('07'O))) {
608 setverdict(pass);
609 }
610 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT(?))) {
611 setverdict(pass);
612 }
613 }
614}
615testcase TC_attach_closed() runs on test_CT {
616 var BSSGP_ConnHdlr vc_conn;
617 f_init();
618 f_sleep(1.0);
619 f_vty_config(SGSNVTY, "sgsn", "auth-policy closed");
620 /* test with foreign IMSI: Must Reject */
Harald Welteb7c14e92018-02-17 09:29:16 +0100621 vc_conn := f_start_handler(refers(f_TC_attach_closed_foreign), testcasename(), g_gb[0], 9);
Harald Welteb2124b22018-02-16 22:26:56 +0100622 vc_conn.done;
623 /* test with home IMSI: Must Accept */
Harald Welteb7c14e92018-02-17 09:29:16 +0100624 vc_conn := f_start_handler(refers(f_TC_attach_accept_all), testcasename(), g_gb[0], 10);
Harald Welteb2124b22018-02-16 22:26:56 +0100625 vc_conn.done;
626}
627
Harald Welte04683d02018-02-16 22:43:45 +0100628/* Routing Area Update from Unknown TLLI -> REJECT */
629private function f_TC_rau_unknown(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte04683d02018-02-16 22:43:45 +0100630 var RoutingAreaIdentificationV old_ra := f_random_RAI();
631
Harald Welte23178c52018-02-17 09:36:33 +0100632 BSSGP.send(ts_GMM_RAU_REQ(f_mi_get_lv(), GPRS_UPD_T_RA, old_ra, false, omit, omit));
Harald Welte04683d02018-02-16 22:43:45 +0100633 alt {
634 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_RAU_REJECT('0a'O))) {
635 setverdict(pass);
636 }
637 /* FIXME: Expect XID RESET? */
638 [] BSSGP.receive { repeat; }
639 }
640}
641testcase TC_rau_unknown() runs on test_CT {
642 var BSSGP_ConnHdlr vc_conn;
643 f_init();
644 f_sleep(1.0);
Harald Welteb7c14e92018-02-17 09:29:16 +0100645 vc_conn := f_start_handler(refers(f_TC_rau_unknown), testcasename(), g_gb[0], 11);
Harald Welte04683d02018-02-16 22:43:45 +0100646 vc_conn.done;
647}
648
Harald Welte91636de2018-02-17 10:16:14 +0100649private function f_TC_attach_rau(charstring id) runs on BSSGP_ConnHdlr {
650 var BssgpDecoded bd;
651
652 /* first perform regular attach */
653 f_TC_attach(id);
654
655 /* then send RAU */
656 BSSGP.send(ts_GMM_RAU_REQ(f_mi_get_lv(), GPRS_UPD_T_RA, g_pars.ra, false, omit, omit));
657 alt {
658 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_RAU_ACCEPT)) -> value bd {
659 f_process_rau_accept(bd.l3_mt.msgs.gprs_mm.routingAreaUpdateAccept);
660 setverdict(pass);
661 }
662 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_RAU_REJECT)) {
663 setverdict(fail, "Unexpected RAU Reject");
664 }
665 [] BSSGP.receive { repeat; }
666 }
667}
668testcase TC_attach_rau() runs on test_CT {
669 var BSSGP_ConnHdlr vc_conn;
670 f_init();
671 f_sleep(1.0);
672 vc_conn := f_start_handler(refers(f_TC_attach_rau), testcasename(), g_gb[0], 12);
673 vc_conn.done;
674}
Harald Welte04683d02018-02-16 22:43:45 +0100675
Harald Welte6abb9fe2018-02-17 15:24:48 +0100676/* general GPRS DETACH helper */
677function f_detach_mo(BIT3 detach_type, boolean power_off, boolean expect_purge) runs on BSSGP_ConnHdlr {
678 var BssgpDecoded bd;
679 timer T := 5.0;
680 BSSGP.send(ts_GMM_DET_REQ_MO(detach_type, power_off));
681 if (expect_purge) {
682 GSUP.receive(tr_GSUP_PURGE_MS_REQ(g_pars.imsi, OSMO_GSUP_CN_DOMAIN_PS));
683 GSUP.send(ts_GSUP_PURGE_MS_RES(g_pars.imsi));
684 }
685 T.start;
686 alt {
687 [not expect_purge] GSUP.receive(tr_GSUP_PURGE_MS_REQ(?)) {
688 setverdict(fail, "Unexpected GSUP PURGE MS for unregistered TLLI");
689 }
690 [power_off] BSSGP.receive(tr_BD_L3_MT(tr_GMM_DET_ACCEPT_MT)) -> value bd {
691 g_pars.ra := omit;
692 setverdict(fail, "Unexpected ATTACH ACCEPT in no-power-off DETACH");
693 /* TODO: check if any PDP contexts are deactivated on network side? */
694 }
695 [power_off] T.timeout {
696 setverdict(pass);
697 }
698 [not power_off] BSSGP.receive(tr_BD_L3_MT(tr_GMM_DET_ACCEPT_MT)) -> value bd {
699 g_pars.ra := omit;
700 setverdict(pass);
701 /* TODO: check if any PDP contexts are deactivated on network side? */
702 }
703 [] BSSGP.receive { repeat; }
704 }
705}
706
707/* IMSI DETACH (non-power-off) for unknown TLLI */
708private function f_TC_detach_unknown_nopoweroff(charstring id) runs on BSSGP_ConnHdlr {
709 f_detach_mo(c_GMM_DTT_MO_GPRS, false, false);
710}
711testcase TC_detach_unknown_nopoweroff() runs on test_CT {
712 var BSSGP_ConnHdlr vc_conn;
713 f_init();
714 f_sleep(1.0);
715 vc_conn := f_start_handler(refers(f_TC_detach_unknown_nopoweroff), testcasename(), g_gb[0], 13);
716 vc_conn.done;
717}
718
719/* IMSI DETACH (power-off) for unknown TLLI */
720private function f_TC_detach_unknown_poweroff(charstring id) runs on BSSGP_ConnHdlr {
721 f_detach_mo(c_GMM_DTT_MO_GPRS, true, false);
722}
723testcase TC_detach_unknown_poweroff() runs on test_CT {
724 var BSSGP_ConnHdlr vc_conn;
725 f_init();
726 f_sleep(1.0);
727 vc_conn := f_start_handler(refers(f_TC_detach_unknown_poweroff), testcasename(), g_gb[0], 14);
728 vc_conn.done;
729}
730
731/* IMSI DETACH (non-power-off) for known TLLI */
732private function f_TC_detach_nopoweroff(charstring id) runs on BSSGP_ConnHdlr {
733 /* first perform regular attach */
734 f_TC_attach(id);
735
736 f_detach_mo(c_GMM_DTT_MO_GPRS, false, true);
737}
738testcase TC_detach_nopoweroff() runs on test_CT {
739 var BSSGP_ConnHdlr vc_conn;
740 f_init();
741 f_sleep(1.0);
742 vc_conn := f_start_handler(refers(f_TC_detach_nopoweroff), testcasename(), g_gb[0], 15);
743 vc_conn.done;
744}
745
746/* IMSI DETACH (power-off) for known TLLI */
747private function f_TC_detach_poweroff(charstring id) runs on BSSGP_ConnHdlr {
748 /* first perform regular attach */
749 f_TC_attach(id);
750
751 f_detach_mo(c_GMM_DTT_MO_GPRS, true, true);
752}
753testcase TC_detach_poweroff() runs on test_CT {
754 var BSSGP_ConnHdlr vc_conn;
755 f_init();
756 f_sleep(1.0);
757 vc_conn := f_start_handler(refers(f_TC_detach_poweroff), testcasename(), g_gb[0], 16);
758 vc_conn.done;
759}
760
Harald Welteeded9ad2018-02-17 20:57:34 +0100761type record PdpActPars {
Harald Welte822f9102018-02-18 20:39:06 +0100762 BIT3 tid, /* L3 Transaction ID */
763 BIT4 nsapi, /* SNDCP NSAPI */
764 BIT4 sapi, /* LLC SAPI */
765 QoSV qos, /* QoS parameters */
766 PDPAddressV addr, /* IP address */
767 octetstring apn optional, /* APN name */
768 ProtocolConfigOptionsV pco optional, /* protoco config opts */
769 OCT1 exp_rej_cause optional, /* expected SM reject cause */
Harald Welte1d6ae932018-02-18 21:24:44 +0100770 OCT1 gtp_resp_cause, /* GTP response cause */
Harald Welte822f9102018-02-18 20:39:06 +0100771 OCT4 chg_id, /* GTP Charging Identifier */
Harald Welte6abb9fe2018-02-17 15:24:48 +0100772
Harald Welte822f9102018-02-18 20:39:06 +0100773 OCT4 ggsn_tei_c, /* GGSN TEI Control*/
774 OCT4 ggsn_tei_u, /* GGSN TEI User */
775 octetstring ggsn_ip_c, /* GGSN IP Control */
776 octetstring ggsn_ip_u, /* GGSN IP User */
Harald Welteeded9ad2018-02-17 20:57:34 +0100777
Harald Welte822f9102018-02-18 20:39:06 +0100778 OCT4 sgsn_tei_c optional, /* SGSN TEI Control */
779 OCT4 sgsn_tei_u optional, /* SGSN TEI User */
780 octetstring sgsn_ip_c optional, /* SGSN IP Control */
781 octetstring sgsn_ip_u optional /* SGSN IP USer */
Harald Welteeded9ad2018-02-17 20:57:34 +0100782};
783
Harald Welte5b5ca1b2018-02-18 21:25:03 +0100784
785private function f_process_gtp_ctx_act_req(inout PdpActPars apars, PDU_GTPC gtpc) runs on BSSGP_ConnHdlr {
786 var GTPC_PDUs gtpc_rx := gtpc.gtpc_pdu;
787 apars.sgsn_tei_c := gtpc_rx.createPDPContextRequest.teidControlPlane.teidControlPlane;
788 apars.sgsn_tei_u := gtpc_rx.createPDPContextRequest.teidDataI.teidDataI;
789 apars.sgsn_ip_c := gtpc_rx.createPDPContextRequest.sgsn_addr_signalling.addressf;
790 apars.sgsn_ip_u := gtpc_rx.createPDPContextRequest.sgsn_addr_traffic.addressf;
791 f_gtp_register_teid(apars.ggsn_tei_c);
792 f_gtp_register_teid(apars.ggsn_tei_u);
793}
794
Harald Welte37692d82018-02-18 15:21:34 +0100795function f_pdp_ctx_act(inout PdpActPars apars) runs on BSSGP_ConnHdlr {
Harald Welteeded9ad2018-02-17 20:57:34 +0100796 var boolean exp_rej := ispresent(apars.exp_rej_cause);
797 var Gtp1cUnitdata g_ud;
798
799 BSSGP.send(ts_SM_ACT_PDP_REQ(apars.tid, apars.nsapi, apars.sapi, apars.qos, apars.addr,
800 apars.apn, apars.pco));
Harald Welte5b5ca1b2018-02-18 21:25:03 +0100801 GTP.receive(tr_GTPC_MsgType(?, createPDPContextRequest, ?)) -> value g_ud {
802 f_process_gtp_ctx_act_req(apars, g_ud.gtpc);
803 var integer seq_nr := oct2int(g_ud.gtpc.opt_part.sequenceNumber);
804 GTP.send(ts_GTPC_CreatePdpResp(g_ud.peer, seq_nr,
805 apars.sgsn_tei_c, apars.gtp_resp_cause,
806 apars.ggsn_tei_c, apars.ggsn_tei_u,
807 apars.nsapi,
808 apars.ggsn_ip_c, apars.ggsn_ip_u, apars.chg_id));
Harald Welteeded9ad2018-02-17 20:57:34 +0100809 }
810 alt {
Harald Welte28307082018-02-18 12:14:18 +0100811 [exp_rej] BSSGP.receive(tr_BD_L3_MT(tr_SM_ACT_PDP_REJ(apars.tid, apars.exp_rej_cause))) {
Harald Welteeded9ad2018-02-17 20:57:34 +0100812 setverdict(pass);
813 }
Harald Welte28307082018-02-18 12:14:18 +0100814 [exp_rej] BSSGP.receive(tr_BD_L3_MT(tr_SM_ACT_PDP_ACCEPT)) {
Harald Welteeded9ad2018-02-17 20:57:34 +0100815 setverdict(fail, "Unexpected PDP CTX ACT ACC");
816 }
Harald Welte28307082018-02-18 12:14:18 +0100817 [not exp_rej] BSSGP.receive(tr_BD_L3_MT(tr_SM_ACT_PDP_REJ(apars.tid, ?))) {
Harald Welteeded9ad2018-02-17 20:57:34 +0100818 setverdict(fail, "Unexpected PDP CTX ACT FAIL");
819 }
Harald Welte28307082018-02-18 12:14:18 +0100820 [not exp_rej] BSSGP.receive(tr_BD_L3_MT(tr_SM_ACT_PDP_ACCEPT(apars.tid, apars.sapi))) {
Harald Welteeded9ad2018-02-17 20:57:34 +0100821 setverdict(pass);
822 }
Harald Welte5b5ca1b2018-02-18 21:25:03 +0100823 [] as_xid(apars);
Harald Welteeded9ad2018-02-17 20:57:34 +0100824 }
825}
826
Harald Welte6f203162018-02-18 22:04:55 +0100827function f_pdp_ctx_deact_mo(inout PdpActPars apars, OCT1 cause) runs on BSSGP_ConnHdlr {
828 var boolean exp_rej := ispresent(apars.exp_rej_cause);
829 var Gtp1cUnitdata g_ud;
830
831 BSSGP.send(ts_SM_DEACT_PDP_REQ_MO(apars.tid, cause, false, omit));
832 GTP.receive(tr_GTPC_MsgType(?, deletePDPContextRequest, apars.ggsn_tei_c)) -> value g_ud {
833 var integer seq_nr := oct2int(g_ud.gtpc.opt_part.sequenceNumber);
834 BSSGP.clear;
835 GTP.send(ts_GTPC_DeletePdpResp(g_ud.peer, seq_nr, apars.sgsn_tei_c, '7F'O));
836 }
837 alt {
838 [] BSSGP.receive(tr_BD_L3_MT(tr_SM_DEACT_PDP_ACCEPT_MT(apars.tid))) {
839 setverdict(pass);
840 }
841 [] as_xid(apars);
842 }
843}
844
Harald Welte57b9b7f2018-02-18 22:28:13 +0100845function f_pdp_ctx_deact_mt(inout PdpActPars apars, OCT1 cause) runs on BSSGP_ConnHdlr {
846 var Gtp1cUnitdata g_ud;
847 var integer seq_nr := 23;
848 var GtpPeer peer := valueof(ts_GtpPeerC(apars.sgsn_ip_c));
849
850 BSSGP.clear;
851 GTP.send(ts_GTPC_DeletePDP(peer, seq_nr, apars.sgsn_tei_c, apars.nsapi, omit));
852
853 interleave {
854 [] BSSGP.receive(tr_BD_L3_MT(tr_SM_DEACT_PDP_REQ_MT(apars.tid, ?))) {
855 BSSGP.send(ts_SM_DEACT_PDP_ACCEPT_MO(apars.tid));
856 }
857 [] GTP.receive(tr_GTPC_MsgType(?, deletePDPContextResponse, apars.ggsn_tei_c)) { }
858 }
859}
860
Harald Welte6f203162018-02-18 22:04:55 +0100861
Harald Welteeded9ad2018-02-17 20:57:34 +0100862/* Table 10.5.156/3GPP TS 24.008 */
863template (value) QoSV t_QosDefault := {
864 reliabilityClass := '011'B, /* unacknowledged GTP+LLC, acknowledged RLC */
865 delayClass := '100'B, /* best effort */
866 spare1 := '00'B,
867 precedenceClass := '010'B, /* normal */
868 spare2 := '0'B,
869 peakThroughput := '0000'B, /* subscribed */
870 meanThroughput := '00000'B, /* subscribed */
871 spare3 := '000'B,
872 deliverErroneusSDU := omit,
873 deliveryOrder := omit,
874 trafficClass := omit,
875 maxSDUSize := omit,
876 maxBitrateUplink := omit,
877 maxBitrateDownlink := omit,
878 sduErrorRatio := omit,
879 residualBER := omit,
880 trafficHandlingPriority := omit,
881 transferDelay := omit,
882 guaranteedBitRateUplink := omit,
883 guaranteedBitRateDownlink := omit,
884 sourceStatisticsDescriptor := omit,
885 signallingIndication := omit,
886 spare4 := omit,
887 maxBitrateDownlinkExt := omit,
888 guaranteedBitRateDownlinkExt := omit,
889 maxBitrateUplinkExt := omit,
890 guaranteedBitRateUplinkExt := omit,
891 maxBitrateDownlinkExt2 := omit,
892 guaranteedBitRateDownlinkExt2 := omit,
893 maxBitrateUplinkExt2 := omit,
894 guaranteedBitRateUplinkExt2 := omit
895}
896
897/* 10.5.6.4 / 3GPP TS 24.008 */
898template (value) PDPAddressV t_AddrIPv4dyn := {
899 pdpTypeOrg := '0001'B, /* IETF */
900 spare := '0000'B,
901 pdpTypeNum := '21'O, /* IPv4 */
902 addressInfo := omit
903}
904template (value) PDPAddressV t_AddrIPv6dyn := {
905 pdpTypeOrg := '0001'B, /* IETF */
906 spare := '0000'B,
907 pdpTypeNum := '53'O, /* IPv6 */
908 addressInfo := omit
909}
910
Harald Welte37692d82018-02-18 15:21:34 +0100911template (value) PdpActPars t_PdpActPars(charstring ggsn_ip) := {
Harald Welteeded9ad2018-02-17 20:57:34 +0100912 tid := '000'B,
913 nsapi := '0101'B, /* < 5 are reserved */
914 sapi := '0011'B, /* 3/5/9/11 */
915 qos := t_QosDefault,
916 addr := t_AddrIPv4dyn,
917 apn := omit,
918 pco := omit,
919 exp_rej_cause := omit,
Harald Welte1d6ae932018-02-18 21:24:44 +0100920 gtp_resp_cause := int2oct(128, 1),
921 chg_id := f_rnd_octstring(4),
Harald Welteeded9ad2018-02-17 20:57:34 +0100922
923 /* FIXME: make below dynamic !! */
Harald Welte1d6ae932018-02-18 21:24:44 +0100924 ggsn_tei_c := f_rnd_octstring(4),
925 ggsn_tei_u := f_rnd_octstring(4),
Harald Welte37692d82018-02-18 15:21:34 +0100926 ggsn_ip_c := f_inet_addr(ggsn_ip),
927 ggsn_ip_u := f_inet_addr(ggsn_ip),
Harald Welteeded9ad2018-02-17 20:57:34 +0100928
Harald Welteeded9ad2018-02-17 20:57:34 +0100929 sgsn_tei_c := omit,
Harald Weltef8af5d62018-02-18 15:06:42 +0100930 sgsn_tei_u := omit,
931 sgsn_ip_c := omit,
932 sgsn_ip_u := omit
Harald Welteeded9ad2018-02-17 20:57:34 +0100933}
934
Harald Welte37692d82018-02-18 15:21:34 +0100935template (value) GtpPeer ts_GtpPeerU(octetstring ip) := {
936 connId := 1,
937 remName := f_inet_ntoa(ip),
938 remPort := GTP1U_PORT
939}
940
941template (value) GtpPeer ts_GtpPeerC(octetstring ip) := {
942 connId := 1,
943 remName := f_inet_ntoa(ip),
944 remPort := GTP1C_PORT
945}
946
947private function f_gtpu_send(inout PdpActPars apars, octetstring payload) runs on BSSGP_ConnHdlr {
948 var GtpPeer peer := valueof(ts_GtpPeerU(apars.sgsn_ip_u));
949 GTP.send(ts_GTP1U_GPDU(peer, 0 /*seq*/, apars.sgsn_tei_u, payload));
950}
951
952private altstep as_xid(PdpActPars apars) runs on BSSGP_ConnHdlr {
953 [] BSSGP.receive(tr_BD_LLC(tr_LLC_XID(?, apars.sapi))) {
954 repeat;
955 }
956}
957
958template PDU_SN tr_SN_UD(template BIT4 nsapi, template octetstring payload) := {
959 pDU_SN_UNITDATA := {
960 nsapi := nsapi,
961 moreBit := ?,
962 snPduType := '1'B,
963 firstSegmentIndicator := ?,
964 spareBit := ?,
965 pcomp := ?,
966 dcomp := ?,
967 npduNumber := ?,
968 segmentNumber := ?,
969 npduNumberContinued := ?,
970 dataSegmentSnUnitdataPdu := payload
971 }
972}
973
974/* simple case: single segment, no compression */
975template (value) PDU_SN ts_SN_UD(BIT4 nsapi, octetstring payload) := {
976 pDU_SN_UNITDATA := {
977 nsapi := nsapi,
978 moreBit := '0'B,
979 snPduType := '1'B,
980 firstSegmentIndicator := '1'B,
981 spareBit := '0'B,
982 pcomp := '0000'B,
983 dcomp := '0000'B,
984 npduNumber := '0000'B,
985 segmentNumber := '0000'B,
986 npduNumberContinued := '00'O,
987 dataSegmentSnUnitdataPdu := payload
988 }
989}
990
991/* Transceive given 'payload' as MT message from GTP -> OsmoSGSN -> Gb */
992private function f_gtpu_xceive_mt(inout PdpActPars apars, octetstring payload) runs on BSSGP_ConnHdlr {
993 /* Send PDU via GTP from our simulated GGSN to the SGSN */
994 f_gtpu_send(apars, payload);
995 /* Expect PDU via BSSGP/LLC on simulated PCU from SGSN */
996 alt {
997 [] as_xid(apars);
998 [] BSSGP.receive(tr_BD_SNDCP(apars.sapi, tr_SN_UD(apars.nsapi, payload)));
999 }
1000}
1001
1002private function f_gtpu_xceive_mo(inout PdpActPars apars, octetstring payload) runs on BSSGP_ConnHdlr {
1003 /* Send PDU via SNDCP/LLC/BSSGP/NS via simulated MS/PCU to the SGSN */
1004 var GtpPeer peer := valueof(ts_GtpPeerU(apars.sgsn_ip_u));
1005 var PDU_SN sndcp := valueof(ts_SN_UD(apars.nsapi, payload));
1006 BSSGP.send(ts_LLC_UI(enc_PDU_SN(sndcp), apars.sapi, '0'B, 0));
1007 f_gtpu_send(apars, payload);
1008 /* Expect PDU via GTP from SGSN on simulated GGSN */
1009 alt {
1010 [] GTP.receive(tr_GTPU_GPDU(peer, apars.ggsn_tei_u, payload));
1011 }
1012}
1013
Harald Welteeded9ad2018-02-17 20:57:34 +01001014private function f_TC_attach_pdp_act(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte37692d82018-02-18 15:21:34 +01001015 var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
Harald Welteeded9ad2018-02-17 20:57:34 +01001016
1017 /* first perform regular attach */
1018 f_TC_attach(id);
1019
1020 f_pdp_ctx_act(apars);
1021}
1022testcase TC_attach_pdp_act() runs on test_CT {
1023 var BSSGP_ConnHdlr vc_conn;
1024 f_init();
1025 vc_conn := f_start_handler(refers(f_TC_attach_pdp_act), testcasename(), g_gb[0], 17);
1026 vc_conn.done;
1027}
Harald Welteb2124b22018-02-16 22:26:56 +01001028
Harald Welte835b15f2018-02-18 14:39:11 +01001029/* PDP Context activation for not-attached subscriber; expect fail */
1030private function f_TC_pdp_act_unattached(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte37692d82018-02-18 15:21:34 +01001031 var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
Harald Welte835b15f2018-02-18 14:39:11 +01001032 BSSGP.send(ts_SM_ACT_PDP_REQ(apars.tid, apars.nsapi, apars.sapi, apars.qos, apars.addr,
1033 apars.apn, apars.pco));
1034 alt {
1035 /* We might want toalso actually expect a PDPC CTX ACT REJ? */
1036 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_DET_REQ_MT(?, ?))) {
1037 setverdict(pass);
1038 }
1039 [] GTP.receive(tr_GTPC_MsgType(?, createPDPContextRequest, ?)) {
1040 setverdict(fail, "Unexpected GTP PDP CTX ACT");
1041 }
1042 [] BSSGP.receive(tr_BD_L3_MT(tr_SM_ACT_PDP_ACCEPT(?, ?))) {
1043 setverdict(fail, "Unexpected SM PDP CTX ACT ACK");
1044 }
1045 [] BSSGP.receive { repeat; }
1046 }
1047}
1048testcase TC_pdp_act_unattached() runs on test_CT {
1049 var BSSGP_ConnHdlr vc_conn;
1050 f_init();
1051 vc_conn := f_start_handler(refers(f_TC_pdp_act_unattached), testcasename(), g_gb[0], 18);
1052 vc_conn.done;
1053}
1054
Harald Welte37692d82018-02-18 15:21:34 +01001055/* ATTACH + PDP CTX ACT + user plane traffic */
1056private function f_TC_attach_pdp_act_user(charstring id) runs on BSSGP_ConnHdlr {
1057 var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
1058
1059 /* first perform regular attach */
1060 f_TC_attach(id);
1061 /* then activate PDP context */
1062 f_pdp_ctx_act(apars);
1063 /* then transceive a downlink PDU */
1064 f_gtpu_xceive_mt(apars, f_rnd_octstring(100));
1065 f_gtpu_xceive_mo(apars, f_rnd_octstring(200));
1066}
1067testcase TC_attach_pdp_act_user() runs on test_CT {
1068 var BSSGP_ConnHdlr vc_conn;
1069 f_init();
1070 vc_conn := f_start_handler(refers(f_TC_attach_pdp_act_user), testcasename(), g_gb[0], 19);
1071 vc_conn.done;
1072}
1073
Harald Welte5b5ca1b2018-02-18 21:25:03 +01001074/* ATTACH + PDP CTX ACT; reject from GGSN */
1075private function f_TC_attach_pdp_act_ggsn_reject(charstring id) runs on BSSGP_ConnHdlr {
1076 var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
1077
1078 apars.gtp_resp_cause := int2oct(199, 1); /* no resources available */
1079 apars.exp_rej_cause := '1a'O; /* insufficient resources */
1080
1081 /* first perform regular attach */
1082 f_TC_attach(id);
1083 /* then activate PDP context */
1084 f_pdp_ctx_act(apars);
1085}
1086testcase TC_attach_pdp_act_ggsn_reject() runs on test_CT {
1087 var BSSGP_ConnHdlr vc_conn;
1088 f_init();
1089 vc_conn := f_start_handler(refers(f_TC_attach_pdp_act_ggsn_reject), testcasename(), g_gb[0], 20);
1090 vc_conn.done;
1091}
Harald Welte835b15f2018-02-18 14:39:11 +01001092
Harald Welte6f203162018-02-18 22:04:55 +01001093/* ATTACH + PDP CTX ACT + user plane traffic + PDP CTX DEACT in MO direction */
1094private function f_TC_attach_pdp_act_user_deact_mo(charstring id) runs on BSSGP_ConnHdlr {
1095 var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
1096
1097 /* first perform regular attach */
1098 f_TC_attach(id);
1099 /* then activate PDP context */
1100 f_pdp_ctx_act(apars);
1101 /* then transceive a downlink PDU */
1102 f_gtpu_xceive_mt(apars, f_rnd_octstring(100));
1103 f_gtpu_xceive_mo(apars, f_rnd_octstring(200));
1104
1105 f_pdp_ctx_deact_mo(apars, '00'O);
1106}
1107testcase TC_attach_pdp_act_user_deact_mo() runs on test_CT {
1108 var BSSGP_ConnHdlr vc_conn;
1109 f_init();
1110 vc_conn := f_start_handler(refers(f_TC_attach_pdp_act_user_deact_mo), testcasename(), g_gb[0], 21);
1111 vc_conn.done;
1112}
1113
Harald Welte57b9b7f2018-02-18 22:28:13 +01001114/* ATTACH + PDP CTX ACT + user plane traffic + PDP CTX DEACT in MT direction */
1115private function f_TC_attach_pdp_act_user_deact_mt(charstring id) runs on BSSGP_ConnHdlr {
1116 var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
1117
1118 /* first perform regular attach */
1119 f_TC_attach(id);
1120 /* then activate PDP context */
1121 f_pdp_ctx_act(apars);
1122 /* then transceive a downlink PDU */
1123 f_gtpu_xceive_mt(apars, f_rnd_octstring(100));
1124 f_gtpu_xceive_mo(apars, f_rnd_octstring(200));
1125
1126 f_pdp_ctx_deact_mt(apars, '00'O);
1127}
1128testcase TC_attach_pdp_act_user_deact_mt() runs on test_CT {
1129 var BSSGP_ConnHdlr vc_conn;
1130 f_init();
1131 vc_conn := f_start_handler(refers(f_TC_attach_pdp_act_user_deact_mt), testcasename(), g_gb[0], 22);
1132 vc_conn.done;
1133}
1134
1135
Harald Welte5ac31492018-02-15 20:39:13 +01001136
1137control {
Harald Welte5b7c8122018-02-16 21:48:17 +01001138 execute( TC_attach() );
1139 execute( TC_attach_auth_id_timeout() );
1140 execute( TC_attach_auth_sai_timeout() );
Harald Weltefe253882018-02-17 09:25:00 +01001141 execute( TC_attach_auth_sai_reject() );
Harald Welte5b7c8122018-02-16 21:48:17 +01001142 execute( TC_attach_gsup_lu_timeout() );
Harald Welteb7c14e92018-02-17 09:29:16 +01001143 execute( TC_attach_gsup_lu_reject() );
Harald Welte3823e2e2018-02-16 21:53:48 +01001144 execute( TC_attach_combined() );
Harald Welte76dee092018-02-16 22:12:59 +01001145 execute( TC_attach_accept_all() );
Harald Welteb2124b22018-02-16 22:26:56 +01001146 execute( TC_attach_closed() );
Harald Welte04683d02018-02-16 22:43:45 +01001147 execute( TC_rau_unknown() );
Harald Welte91636de2018-02-17 10:16:14 +01001148 execute( TC_attach_rau() );
Harald Welte6abb9fe2018-02-17 15:24:48 +01001149 execute( TC_detach_unknown_nopoweroff() );
1150 execute( TC_detach_unknown_poweroff() );
1151 execute( TC_detach_nopoweroff() );
1152 execute( TC_detach_poweroff() );
Harald Welteeded9ad2018-02-17 20:57:34 +01001153 execute( TC_attach_pdp_act() );
Harald Welte835b15f2018-02-18 14:39:11 +01001154 execute( TC_pdp_act_unattached() );
Harald Welte37692d82018-02-18 15:21:34 +01001155 execute( TC_attach_pdp_act_user() );
Harald Welte5b5ca1b2018-02-18 21:25:03 +01001156 execute( TC_attach_pdp_act_ggsn_reject() );
Harald Welte6f203162018-02-18 22:04:55 +01001157 execute( TC_attach_pdp_act_user_deact_mo() );
Harald Welte57b9b7f2018-02-18 22:28:13 +01001158 execute( TC_attach_pdp_act_user_deact_mt() );
Harald Welte5ac31492018-02-15 20:39:13 +01001159}
Harald Welte96a33b02018-02-04 10:36:22 +01001160
1161
1162
1163}