blob: 79aa16688776db6d6ba712e7b454392257b1c6ef [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
Neels Hofmeyr8df7d152018-03-14 19:03:28 +010036import from GSM_RR_Types all;
37
Harald Welteeded9ad2018-02-17 20:57:34 +010038
Harald Welte5ac31492018-02-15 20:39:13 +010039modulepar {
40 /* IP/port on which we run our internal GSUP/HLR emulation */
41 charstring mp_hlr_ip := "127.0.0.1";
42 integer mp_hlr_port := 4222;
Harald Welteeded9ad2018-02-17 20:57:34 +010043 charstring mp_ggsn_ip := "127.0.0.2";
Harald Welte5ac31492018-02-15 20:39:13 +010044};
45
46type record GbInstance {
47 NS_CT vc_NS,
48 BSSGP_CT vc_BSSGP,
49 BssgpConfig cfg
50};
Harald Welte96a33b02018-02-04 10:36:22 +010051
52type component test_CT {
Harald Welte5ac31492018-02-15 20:39:13 +010053 var GbInstance g_gb[3];
Harald Welte96a33b02018-02-04 10:36:22 +010054
Harald Welte5ac31492018-02-15 20:39:13 +010055 var GSUP_Emulation_CT vc_GSUP;
56 var IPA_Emulation_CT vc_GSUP_IPA;
57 /* only to get events from IPA underneath GSUP */
58 port IPA_CTRL_PT GSUP_IPA_EVENT;
Harald Welte96a33b02018-02-04 10:36:22 +010059
Harald Welteeded9ad2018-02-17 20:57:34 +010060 var GTP_Emulation_CT vc_GTP;
61
Harald Weltebd194722018-02-16 22:11:08 +010062 port TELNETasp_PT SGSNVTY;
63
Harald Welte96a33b02018-02-04 10:36:22 +010064 var boolean g_initialized := false;
65};
66
Harald Welteeded9ad2018-02-17 20:57:34 +010067type component BSSGP_ConnHdlr extends BSSGP_Client_CT, GSUP_ConnHdlr, GTP_ConnHdlr {
Harald Welte5ac31492018-02-15 20:39:13 +010068 var BSSGP_ConnHdlrPars g_pars;
Harald Welte62e29582018-02-16 21:17:11 +010069 timer g_Tguard;
Harald Welte5ac31492018-02-15 20:39:13 +010070}
71
72type record SGSN_ConnHdlrNetworkPars {
73 boolean expect_ptmsi,
74 boolean expect_auth,
75 boolean expect_ciph
76};
77
78type record BSSGP_ConnHdlrPars {
79 /* IMEI of the simulated ME */
80 hexstring imei,
81 /* IMEI of the simulated MS */
82 hexstring imsi,
83 /* MSISDN of the simulated MS (probably unused) */
84 hexstring msisdn,
85 /* P-TMSI allocated to the simulated MS */
86 OCT4 p_tmsi optional,
Harald Welte04683d02018-02-16 22:43:45 +010087 OCT3 p_tmsi_sig optional,
Harald Welte5ac31492018-02-15 20:39:13 +010088 /* TLLI of the simulated MS */
89 OCT4 tlli,
Harald Weltef70997d2018-02-17 10:11:19 +010090 OCT4 tlli_old optional,
Harald Welte5ac31492018-02-15 20:39:13 +010091 RoutingAreaIdentificationV ra optional,
92 BssgpCellId bssgp_cell_id,
93 AuthVector vec optional,
Harald Welte62e29582018-02-16 21:17:11 +010094 SGSN_ConnHdlrNetworkPars net,
95 float t_guard
Harald Welte5ac31492018-02-15 20:39:13 +010096};
97
Harald Welte3fdbe822018-02-18 19:10:18 +010098private function f_init_gb(inout GbInstance gb, charstring id) runs on test_CT {
99 gb.vc_NS := NS_CT.create(id & "-NS");
100 gb.vc_BSSGP := BSSGP_CT.create(id & "-BSSGP");
Harald Welte5ac31492018-02-15 20:39:13 +0100101 /* connect lower end of BSSGP emulation with NS upper port */
102 connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
103 /* connect lower end of NS emulation to NS codec port (on top of IPL4) */
104 map(gb.vc_NS:NSCP, system:NS_CODEC_PORT);
105
106 gb.vc_NS.start(NSStart());
107 gb.vc_BSSGP.start(BssgpStart(gb.cfg));
108}
109
110private function f_init_gsup(charstring id) runs on test_CT {
111 id := id & "-GSUP";
112 var GsupOps ops := {
113 create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
114 };
115
116 vc_GSUP_IPA := IPA_Emulation_CT.create(id & "-IPA");
117 vc_GSUP := GSUP_Emulation_CT.create(id);
118
119 map(vc_GSUP_IPA:IPA_PORT, system:IPA_CODEC_PT);
120 connect(vc_GSUP:GSUP, vc_GSUP_IPA:IPA_GSUP_PORT);
121 /* we use this hack to get events like ASP_IPA_EVENT_UP */
122 connect(vc_GSUP_IPA:IPA_CTRL_PORT, self:GSUP_IPA_EVENT);
123
124 vc_GSUP.start(GSUP_Emulation.main(ops, id));
125 vc_GSUP_IPA.start(IPA_Emulation.main_server(mp_hlr_ip, mp_hlr_port));
126
127 /* wait for incoming connection to GSUP port before proceeding */
128 timer T := 10.0;
129 T.start;
130 alt {
131 [] GSUP_IPA_EVENT.receive(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_UP)) { }
132 [] T.timeout {
133 setverdict(fail, "No connection to GSUP Port");
134 self.stop;
135 }
136 }
137}
138
Harald Welteeded9ad2018-02-17 20:57:34 +0100139private function f_init_gtp(charstring id) runs on test_CT {
140 id := id & "-GTP";
141
142 var GtpEmulationCfg gtp_cfg := {
143 gtpc_bind_ip := mp_ggsn_ip,
144 gtpc_bind_port := GTP1C_PORT,
145 gtpu_bind_ip := mp_ggsn_ip,
146 gtpu_bind_port := GTP1U_PORT,
147 sgsn_role := false
148 };
149
150 vc_GTP := GTP_Emulation_CT.create(id);
151 vc_GTP.start(GTP_Emulation.main(gtp_cfg));
152}
153
Harald Weltebd194722018-02-16 22:11:08 +0100154private function f_init_vty() runs on test_CT {
155 map(self:SGSNVTY, system:SGSNVTY);
156 f_vty_set_prompts(SGSNVTY);
157 f_vty_transceive(SGSNVTY, "enable");
158 f_vty_config(SGSNVTY, "sgsn", "auth-policy remote");
159}
160
161
Neels Hofmeyr8df7d152018-03-14 19:03:28 +0100162function f_init(BcdMccMnc mcc_mnc := '26242F'H) runs on test_CT {
Harald Welte96a33b02018-02-04 10:36:22 +0100163 if (g_initialized == true) {
164 return;
165 }
166 g_initialized := true;
Harald Welte5ac31492018-02-15 20:39:13 +0100167 g_gb[0].cfg := {
168 nsei := 96,
169 bvci := 196,
170 cell_id := {
171 ra_id := {
172 lai := {
Neels Hofmeyr8df7d152018-03-14 19:03:28 +0100173 mcc_mnc := mcc_mnc, lac := 13135},
Harald Welte5ac31492018-02-15 20:39:13 +0100174 rac := 0
175 },
176 cell_id := 20960
177 },
178 sgsn_role := false
179 };
Harald Welte96a33b02018-02-04 10:36:22 +0100180
Harald Welte3fdbe822018-02-18 19:10:18 +0100181 f_init_gb(g_gb[0], "SGSN_Test-Gb0");
Harald Welte5ac31492018-02-15 20:39:13 +0100182 f_init_gsup("SGSN_Test");
Harald Welteeded9ad2018-02-17 20:57:34 +0100183 f_init_gtp("SGSN_Test");
Harald Weltebd194722018-02-16 22:11:08 +0100184 f_init_vty();
Harald Welte5ac31492018-02-15 20:39:13 +0100185}
Harald Welte96a33b02018-02-04 10:36:22 +0100186
Harald Welte5ac31492018-02-15 20:39:13 +0100187type function void_fn(charstring id) runs on BSSGP_ConnHdlr;
188
189/* helper function to create, connect and start a BSSGP_ConnHdlr component */
Harald Welte62e29582018-02-16 21:17:11 +0100190function f_start_handler(void_fn fn, charstring id, GbInstance gb, integer imsi_suffix,
191 float t_guard := 30.0)
Harald Welte5ac31492018-02-15 20:39:13 +0100192runs on test_CT return BSSGP_ConnHdlr {
193 var BSSGP_ConnHdlr vc_conn;
194 var SGSN_ConnHdlrNetworkPars net_pars := {
195 expect_ptmsi := true,
196 expect_auth := true,
197 expect_ciph := false
198 };
199 var BSSGP_ConnHdlrPars pars := {
200 imei := f_gen_imei(imsi_suffix),
201 imsi := f_gen_imsi(imsi_suffix),
202 msisdn := f_gen_msisdn(imsi_suffix),
203 p_tmsi := omit,
Harald Welte04683d02018-02-16 22:43:45 +0100204 p_tmsi_sig := omit,
Harald Welte14a0f942018-02-16 20:42:23 +0100205 tlli := f_gprs_tlli_random(),
Harald Weltef70997d2018-02-17 10:11:19 +0100206 tlli_old := omit,
Harald Welte5ac31492018-02-15 20:39:13 +0100207 ra := omit,
208 bssgp_cell_id := gb.cfg.cell_id,
209 vec := omit,
Harald Welte62e29582018-02-16 21:17:11 +0100210 net := net_pars,
211 t_guard := t_guard
Harald Welte5ac31492018-02-15 20:39:13 +0100212 };
213
214 vc_conn := BSSGP_ConnHdlr.create(id);
215 connect(vc_conn:BSSGP, gb.vc_BSSGP:BSSGP_SP);
216 connect(vc_conn:BSSGP_PROC, gb.vc_BSSGP:BSSGP_PROC);
217
218 connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT);
219 connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);
220
Harald Welteeded9ad2018-02-17 20:57:34 +0100221 connect(vc_conn:GTP, vc_GTP:CLIENT);
222 connect(vc_conn:GTP_PROC, vc_GTP:CLIENT_PROC);
223
Harald Welte5ac31492018-02-15 20:39:13 +0100224 vc_conn.start(f_handler_init(fn, id, pars));
225 return vc_conn;
226}
227
Harald Welte62e29582018-02-16 21:17:11 +0100228private altstep as_Tguard() runs on BSSGP_ConnHdlr {
229 [] g_Tguard.timeout {
230 setverdict(fail, "Tguard timeout");
231 self.stop;
232 }
233}
234
Harald Welte5ac31492018-02-15 20:39:13 +0100235/* first function called in every ConnHdlr */
236private function f_handler_init(void_fn fn, charstring id, BSSGP_ConnHdlrPars pars)
237runs on BSSGP_ConnHdlr {
238 /* do some common stuff like setting up g_pars */
239 g_pars := pars;
240
241 /* register with BSSGP core */
242 f_bssgp_client_register(g_pars.imsi, g_pars.tlli, g_pars.bssgp_cell_id);
243 /* tell GSUP dispatcher to send this IMSI to us */
244 f_create_gsup_expect(hex2str(g_pars.imsi));
Harald Welteeded9ad2018-02-17 20:57:34 +0100245 /* tell GTP dispatcher to send this IMSI to us */
246 f_gtp_register_imsi(g_pars.imsi);
Harald Welte5ac31492018-02-15 20:39:13 +0100247
Harald Welte62e29582018-02-16 21:17:11 +0100248 g_Tguard.start(pars.t_guard);
249 activate(as_Tguard());
250
Harald Welte5ac31492018-02-15 20:39:13 +0100251 /* call the user-supplied test case function */
252 fn.apply(id);
253 f_bssgp_client_unregister(g_pars.imsi);
Harald Welte96a33b02018-02-04 10:36:22 +0100254}
255
256/* TODO:
Harald Welte96a33b02018-02-04 10:36:22 +0100257 * Detach without Attach
258 * SM procedures without attach / RAU
259 * ATTACH / RAU
260 ** with / without authentication
261 ** with / without P-TMSI allocation
Harald Welte96a33b02018-02-04 10:36:22 +0100262 * re-transmissions of LLC frames
263 * PDP Context activation
264 ** with different GGSN config in SGSN VTY
265 ** with different PDP context type (v4/v6/v46)
266 ** timeout from GGSN
Harald Welte6f203162018-02-18 22:04:55 +0100267 ** multiple / secondary PDP context
Harald Welte96a33b02018-02-04 10:36:22 +0100268 */
269
270testcase TC_wait_ns_up() runs on test_CT {
271 f_init();
272 f_sleep(20.0);
273}
274
Harald Welte5ac31492018-02-15 20:39:13 +0100275altstep as_mm_identity() runs on BSSGP_ConnHdlr {
Neels Hofmeyr8df7d152018-03-14 19:03:28 +0100276 var MobileL3_CommonIE_Types.MobileIdentityLV mi;
Harald Welte5ac31492018-02-15 20:39:13 +0100277 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ID_REQ('001'B))) {
278 mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
279 BSSGP.send(ts_GMM_ID_RESP(mi));
280 repeat;
281 }
282 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ID_REQ('010'B))) {
283 mi := valueof(ts_MI_IMEI_LV(g_pars.imei));
284 BSSGP.send(ts_GMM_ID_RESP(mi));
285 repeat;
286 }
287}
Harald Welte96a33b02018-02-04 10:36:22 +0100288
Harald Welte311ec272018-02-17 09:40:03 +0100289/* perform GMM authentication (if expected) */
Harald Welte5ac31492018-02-15 20:39:13 +0100290function f_gmm_auth () runs on BSSGP_ConnHdlr {
291 var BssgpDecoded bd;
292 var PDU_L3_MS_SGSN l3_mo;
293 var PDU_L3_SGSN_MS l3_mt;
294 var default di := activate(as_mm_identity());
295 if (g_pars.net.expect_auth) {
296 g_pars.vec := f_gen_auth_vec_2g();
297 var GSUP_IE auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G(g_pars.vec.rand,
298 g_pars.vec.sres,
299 g_pars.vec.kc));
300 GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
301 GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
302 BSSGP.receive(tr_BD_L3_MT(tr_GMM_AUTH_REQ(g_pars.vec.rand))) -> value bd;
303 l3_mt := bd.l3_mt;
304 var BIT4 ac_ref := l3_mt.msgs.gprs_mm.authenticationAndCipheringRequest.acReferenceNumber.valueField;
305 l3_mo := valueof(ts_GMM_AUTH_RESP_2G(ac_ref, g_pars.vec.sres));
306 if (ispresent(l3_mt.msgs.gprs_mm.authenticationAndCipheringRequest.imeisvRequest) and
307 l3_mt.msgs.gprs_mm.authenticationAndCipheringRequest.imeisvRequest.valueField == '001'B) {
308 l3_mo.msgs.gprs_mm.authenticationAndCipheringResponse.imeisv :=
309 valueof(ts_MI_IMEISV_TLV(g_pars.imei & '0'H));
310 }
311 BSSGP.send(l3_mo);
Harald Welte76dee092018-02-16 22:12:59 +0100312 } else {
313 /* wait for identity procedure */
314 f_sleep(1.0);
Harald Welte5ac31492018-02-15 20:39:13 +0100315 }
Harald Welte76dee092018-02-16 22:12:59 +0100316
Harald Welte5ac31492018-02-15 20:39:13 +0100317 deactivate(di);
318}
319
Harald Weltef70997d2018-02-17 10:11:19 +0100320function f_upd_ptmsi_and_tlli(OCT4 p_tmsi) runs on BSSGP_ConnHdlr {
321 g_pars.p_tmsi := p_tmsi;
322 /* update TLLI */
323 g_pars.tlli_old := g_pars.tlli;
324 g_pars.tlli := g_pars.p_tmsi or4b 'c0000000'O;
325 f_bssgp_client_llgmm_assign(g_pars.tlli_old, g_pars.tlli);
326}
327
Harald Welte04683d02018-02-16 22:43:45 +0100328function f_process_attach_accept(PDU_GMM_AttachAccept aa) runs on BSSGP_ConnHdlr {
329 /* mandatory IE */
Neels Hofmeyr8df7d152018-03-14 19:03:28 +0100330 var hexstring aa_plmn := f_RAI_to_plmn_hexstr(aa.routingAreaIdentification);
331 if (not (g_pars.bssgp_cell_id.ra_id.lai.mcc_mnc == aa_plmn)) {
332 setverdict(fail, "mismatching PLMN in Attach Accept: " & hex2str(aa_plmn)
333 & "; expected " & hex2str(g_pars.bssgp_cell_id.ra_id.lai.mcc_mnc));
334 self.stop;
335 }
Harald Welte04683d02018-02-16 22:43:45 +0100336 g_pars.ra := aa.routingAreaIdentification;
337 if (ispresent(aa.allocatedPTMSI)) {
338 if (not g_pars.net.expect_ptmsi) {
339 setverdict(fail, "unexpected P-TMSI allocation");
340 self.stop;
341 }
Harald Weltef70997d2018-02-17 10:11:19 +0100342 f_upd_ptmsi_and_tlli(aa.allocatedPTMSI.mobileIdentityLV.mobileIdentityV.oddEvenInd_identity.tmsi_ptmsi.octets);
Harald Welte04683d02018-02-16 22:43:45 +0100343 }
344 if (ispresent(aa.msIdentity)) {
345 setverdict(fail, "unexpected TMSI allocation in non-combined attach");
346 self.stop;
347 }
348 /* P-TMSI.sig */
349 if (ispresent(aa.ptmsiSignature)) {
350 g_pars.p_tmsi_sig := aa.ptmsiSignature.valueField;
351 }
352 /* updateTimer */
353 // aa.readyTimer
354 /* T3302, T3319, T3323, T3312_ext, T3324 */
355}
356
Harald Welte91636de2018-02-17 10:16:14 +0100357function f_process_rau_accept(PDU_GMM_RoutingAreaUpdateAccept ra) runs on BSSGP_ConnHdlr {
358 /* mandatory IE */
359 g_pars.ra := ra.routingAreaId;
360 if (ispresent(ra.allocatedPTMSI)) {
361 if (not g_pars.net.expect_ptmsi) {
362 setverdict(fail, "unexpected P-TMSI allocation");
363 self.stop;
364 }
365 f_upd_ptmsi_and_tlli(ra.allocatedPTMSI.mobileIdentityLV.mobileIdentityV.oddEvenInd_identity.tmsi_ptmsi.octets);
366 }
367 if (ispresent(ra.msIdentity)) {
368 setverdict(fail, "unexpected TMSI allocation in non-combined attach");
369 self.stop;
370 }
371 /* P-TMSI.sig */
372 if (ispresent(ra.ptmsiSignature)) {
373 g_pars.p_tmsi_sig := ra.ptmsiSignature.valueField;
374 }
375 /* updateTimer */
376 // aa.readyTimer
377 /* T3302, T3319, T3323, T3312_ext, T3324 */
378}
379
380
Harald Welte5a4fa042018-02-16 20:59:21 +0100381function f_random_RAI(HEX0_3n mcc := '262'H, HEX0_3n mnc := '42'H) return RoutingAreaIdentificationV {
382 return f_RAI(mcc, mnc, f_rnd_octstring(2), f_rnd_octstring(1));
383}
384
Harald Welte23178c52018-02-17 09:36:33 +0100385/* return a MobileIdentityLV: P-TMSI if we have one, IMSI otherwise */
Neels Hofmeyr8df7d152018-03-14 19:03:28 +0100386private function f_mi_get_lv() runs on BSSGP_ConnHdlr return MobileL3_CommonIE_Types.MobileIdentityLV {
Harald Welte23178c52018-02-17 09:36:33 +0100387 if (ispresent(g_pars.p_tmsi)) {
388 return valueof(ts_MI_TMSI_LV(g_pars.p_tmsi));
389 } else {
390 return valueof(ts_MI_IMSI_LV(g_pars.imsi));
391 }
392}
393
Harald Welte311ec272018-02-17 09:40:03 +0100394private function f_gmm_gsup_lu_isd() runs on BSSGP_ConnHdlr {
Harald Welteeded9ad2018-02-17 20:57:34 +0100395 var GSUP_PDU gsup;
Harald Welte311ec272018-02-17 09:40:03 +0100396 /* Expect MSC to perform LU with HLR */
397 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
Harald Welteeded9ad2018-02-17 20:57:34 +0100398 gsup := valueof(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
399 gsup.ies := gsup.ies & { valueof(ts_GSUP_IE_PdpInfo(char2oct("*"), '0121'O, ''O)) };
400 GSUP.send(gsup);
Harald Welte311ec272018-02-17 09:40:03 +0100401 GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
402 GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
403}
404
Harald Welte5ac31492018-02-15 20:39:13 +0100405private function f_TC_attach(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte04683d02018-02-16 22:43:45 +0100406 var BssgpDecoded bd;
Harald Welte5a4fa042018-02-16 20:59:21 +0100407 var RoutingAreaIdentificationV old_ra := f_random_RAI();
Harald Welte5ac31492018-02-15 20:39:13 +0100408
Harald Welte23178c52018-02-17 09:36:33 +0100409 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welte5ac31492018-02-15 20:39:13 +0100410 f_gmm_auth();
411 /* Expect MSC to perform LU with HLR */
Harald Welte311ec272018-02-17 09:40:03 +0100412 f_gmm_gsup_lu_isd();
Harald Welte5ac31492018-02-15 20:39:13 +0100413
Harald Welte04683d02018-02-16 22:43:45 +0100414 BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?))) -> value bd {
415 f_process_attach_accept(bd.l3_mt.msgs.gprs_mm.attachAccept);
416 }
417 /* FIXME: Extract P-TMSI, if any. Only send Complete if necessary */
Harald Welte5ac31492018-02-15 20:39:13 +0100418 BSSGP.send(ts_GMM_ATTACH_COMPL);
Harald Welte5a4fa042018-02-16 20:59:21 +0100419 setverdict(pass);
Harald Welte5ac31492018-02-15 20:39:13 +0100420}
421
422testcase TC_attach() runs on test_CT {
423 var BSSGP_ConnHdlr vc_conn;
424 f_init();
425 f_sleep(1.0);
426 vc_conn := f_start_handler(refers(f_TC_attach), testcasename(), g_gb[0], 1);
427 vc_conn.done;
428}
429
Neels Hofmeyr8df7d152018-03-14 19:03:28 +0100430testcase TC_attach_mnc3() runs on test_CT {
431 var BSSGP_ConnHdlr vc_conn;
432 f_init('023042'H);
433 f_sleep(1.0);
434 vc_conn := f_start_handler(refers(f_TC_attach), testcasename(), g_gb[0], 1001);
435 vc_conn.done;
436}
437
Harald Welte5b7c8122018-02-16 21:48:17 +0100438/* MS never responds to ID REQ, expect ATTACH REJECT */
439private function f_TC_attach_auth_id_timeout(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte5b7c8122018-02-16 21:48:17 +0100440 var RoutingAreaIdentificationV old_ra := f_random_RAI();
441
Harald Welte23178c52018-02-17 09:36:33 +0100442 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welte5b7c8122018-02-16 21:48:17 +0100443 alt {
Harald Welte1967d472018-02-16 21:54:21 +0100444 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ID_REQ(?))) {
Harald Welte5b7c8122018-02-16 21:48:17 +0100445 /* don't send ID Response */
446 repeat;
447 }
Harald Welte1967d472018-02-16 21:54:21 +0100448 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT('09'O))) {
Harald Welte5b7c8122018-02-16 21:48:17 +0100449 setverdict(pass);
450 }
Harald Welte1967d472018-02-16 21:54:21 +0100451 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT(?))) {
Harald Welte5b7c8122018-02-16 21:48:17 +0100452 setverdict(fail, "Wrong Attach Reject Cause");
453 }
454 }
455}
456testcase TC_attach_auth_id_timeout() runs on test_CT {
457 var BSSGP_ConnHdlr vc_conn;
458 f_init();
459 vc_conn := f_start_handler(refers(f_TC_attach_auth_id_timeout), testcasename(), g_gb[0], 2, 40.0);
460 vc_conn.done;
461}
462
463/* HLR never responds to SAI REQ, expect ATTACH REJECT */
464private function f_TC_attach_auth_sai_timeout(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte5b7c8122018-02-16 21:48:17 +0100465 var RoutingAreaIdentificationV old_ra := f_random_RAI();
466
Harald Welte23178c52018-02-17 09:36:33 +0100467 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welte5b7c8122018-02-16 21:48:17 +0100468 alt {
469 [] as_mm_identity();
470 [] GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi)); { }
471 }
472 /* don't send SAI-response from HLR */
Harald Welte1967d472018-02-16 21:54:21 +0100473 BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT(?)));
Harald Welte5b7c8122018-02-16 21:48:17 +0100474 setverdict(pass);
475}
476testcase TC_attach_auth_sai_timeout() runs on test_CT {
477 var BSSGP_ConnHdlr vc_conn;
478 f_init();
479 vc_conn := f_start_handler(refers(f_TC_attach_auth_sai_timeout), testcasename(), g_gb[0], 3);
480 vc_conn.done;
481}
482
Harald Weltefe253882018-02-17 09:25:00 +0100483/* HLR rejects SAI, expect ATTACH REJECT */
484private function f_TC_attach_auth_sai_reject(charstring id) runs on BSSGP_ConnHdlr {
Harald Weltefe253882018-02-17 09:25:00 +0100485 var RoutingAreaIdentificationV old_ra := f_random_RAI();
486
Harald Welte23178c52018-02-17 09:36:33 +0100487 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Weltefe253882018-02-17 09:25:00 +0100488 alt {
489 [] as_mm_identity();
490 [] GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi)); {
491 GSUP.send(ts_GSUP_SAI_ERR(g_pars.imsi, 23));
492 }
493 }
494 BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT(?)));
495 setverdict(pass);
496}
497testcase TC_attach_auth_sai_reject() runs on test_CT {
498 var BSSGP_ConnHdlr vc_conn;
499 f_init();
Harald Welteb7c14e92018-02-17 09:29:16 +0100500 vc_conn := f_start_handler(refers(f_TC_attach_auth_sai_reject), testcasename(), g_gb[0], 4);
Harald Weltefe253882018-02-17 09:25:00 +0100501 vc_conn.done;
502}
503
Harald Welte5b7c8122018-02-16 21:48:17 +0100504/* HLR never responds to UL REQ, expect ATTACH REJECT */
505private function f_TC_attach_gsup_lu_timeout(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte04683d02018-02-16 22:43:45 +0100506 var BssgpDecoded bd;
Harald Welte5b7c8122018-02-16 21:48:17 +0100507 var RoutingAreaIdentificationV old_ra := f_random_RAI();
508
Harald Welte23178c52018-02-17 09:36:33 +0100509 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welte5b7c8122018-02-16 21:48:17 +0100510 f_gmm_auth();
511 /* Expect MSC to perform LU with HLR */
512 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
513 /* Never follow-up with ISD_REQ or UL_RES */
514 alt {
Harald Welte1967d472018-02-16 21:54:21 +0100515 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT(?))) {
Harald Welte5b7c8122018-02-16 21:48:17 +0100516 setverdict(pass);
517 }
Harald Welte04683d02018-02-16 22:43:45 +0100518 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?))) -> value bd {
519 f_process_attach_accept(bd.l3_mt.msgs.gprs_mm.attachAccept);
Harald Welte5b7c8122018-02-16 21:48:17 +0100520 setverdict(fail);
521 }
522 }
523}
524testcase TC_attach_gsup_lu_timeout() runs on test_CT {
525 var BSSGP_ConnHdlr vc_conn;
526 f_init();
527 f_sleep(1.0);
Harald Welteb7c14e92018-02-17 09:29:16 +0100528 vc_conn := f_start_handler(refers(f_TC_attach_gsup_lu_timeout), testcasename(), g_gb[0], 5);
Harald Welte5b7c8122018-02-16 21:48:17 +0100529 vc_conn.done;
530}
531
Harald Welteb7c14e92018-02-17 09:29:16 +0100532/* HLR rejects UL REQ, expect ATTACH REJECT */
533private function f_TC_attach_gsup_lu_reject(charstring id) runs on BSSGP_ConnHdlr {
534 var BssgpDecoded bd;
Harald Welteb7c14e92018-02-17 09:29:16 +0100535 var RoutingAreaIdentificationV old_ra := f_random_RAI();
536
Harald Welte23178c52018-02-17 09:36:33 +0100537 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welteb7c14e92018-02-17 09:29:16 +0100538 f_gmm_auth();
539 /* Expect MSC to perform LU with HLR */
540 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi)) {
541 GSUP.send(ts_GSUP_UL_ERR(g_pars.imsi, 0));
542 }
543 alt {
544 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT(?))) {
545 setverdict(pass);
546 }
547 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?))) -> value bd {
548 f_process_attach_accept(bd.l3_mt.msgs.gprs_mm.attachAccept);
549 setverdict(fail);
550 }
551 }
552}
553testcase TC_attach_gsup_lu_reject() runs on test_CT {
554 var BSSGP_ConnHdlr vc_conn;
555 f_init();
556 f_sleep(1.0);
557 vc_conn := f_start_handler(refers(f_TC_attach_gsup_lu_reject), testcasename(), g_gb[0], 6);
558 vc_conn.done;
559}
560
561
Harald Welte3823e2e2018-02-16 21:53:48 +0100562/* Attempt of combined GPRS + IMSI attach: network should ACK only GPRS attach */
563private function f_TC_attach_combined(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte04683d02018-02-16 22:43:45 +0100564 var BssgpDecoded bd;
Harald Welte3823e2e2018-02-16 21:53:48 +0100565 var RoutingAreaIdentificationV old_ra := f_random_RAI();
566
Harald Welte23178c52018-02-17 09:36:33 +0100567 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, true, false, omit, omit));
Harald Welte3823e2e2018-02-16 21:53:48 +0100568 f_gmm_auth();
569 /* Expect MSC to perform LU with HLR */
Harald Welte311ec272018-02-17 09:40:03 +0100570 f_gmm_gsup_lu_isd();
Harald Welte3823e2e2018-02-16 21:53:48 +0100571
Harald Welte04683d02018-02-16 22:43:45 +0100572 BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?))) -> value bd {
573 f_process_attach_accept(bd.l3_mt.msgs.gprs_mm.attachAccept);
574 }
Harald Welte3823e2e2018-02-16 21:53:48 +0100575 BSSGP.send(ts_GMM_ATTACH_COMPL);
576 setverdict(pass);
577}
Harald Welte3823e2e2018-02-16 21:53:48 +0100578testcase TC_attach_combined() runs on test_CT {
579 var BSSGP_ConnHdlr vc_conn;
580 f_init();
581 f_sleep(1.0);
Harald Welteb7c14e92018-02-17 09:29:16 +0100582 vc_conn := f_start_handler(refers(f_TC_attach_combined), testcasename(), g_gb[0], 7);
Harald Welte3823e2e2018-02-16 21:53:48 +0100583 vc_conn.done;
584}
585
Harald Welte76dee092018-02-16 22:12:59 +0100586/* Attempt of GPRS ATTACH in 'accept all' mode */
587private function f_TC_attach_accept_all(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte04683d02018-02-16 22:43:45 +0100588 var BssgpDecoded bd;
Harald Welte76dee092018-02-16 22:12:59 +0100589 var RoutingAreaIdentificationV old_ra := f_random_RAI();
590
591 g_pars.net.expect_auth := false;
592
Harald Welte23178c52018-02-17 09:36:33 +0100593 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welte76dee092018-02-16 22:12:59 +0100594 f_gmm_auth();
Harald Welte04683d02018-02-16 22:43:45 +0100595 BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?))) -> value bd {
596 f_process_attach_accept(bd.l3_mt.msgs.gprs_mm.attachAccept);
597 }
Harald Welte76dee092018-02-16 22:12:59 +0100598 BSSGP.send(ts_GMM_ATTACH_COMPL);
599 setverdict(pass);
600}
601testcase TC_attach_accept_all() runs on test_CT {
602 var BSSGP_ConnHdlr vc_conn;
603 f_init();
604 f_sleep(1.0);
605 f_vty_config(SGSNVTY, "sgsn", "auth-policy accept-all");
Harald Welteb7c14e92018-02-17 09:29:16 +0100606 vc_conn := f_start_handler(refers(f_TC_attach_accept_all), testcasename(), g_gb[0], 8);
Harald Welte76dee092018-02-16 22:12:59 +0100607 vc_conn.done;
608}
Harald Welte5b7c8122018-02-16 21:48:17 +0100609
Harald Welteb2124b22018-02-16 22:26:56 +0100610/* Attempt of GPRS ATTACH in 'accept all' mode */
611private function f_TC_attach_closed_foreign(charstring id) runs on BSSGP_ConnHdlr {
Harald Welteb2124b22018-02-16 22:26:56 +0100612 var RoutingAreaIdentificationV old_ra := f_random_RAI();
613
614 /* Simulate a foreign IMSI */
615 g_pars.imsi := '001010123456789'H;
616 f_bssgp_client_register(g_pars.imsi, g_pars.tlli, g_pars.bssgp_cell_id);
617
618 g_pars.net.expect_auth := false;
619
Harald Welte23178c52018-02-17 09:36:33 +0100620 BSSGP.send(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit));
Harald Welteb2124b22018-02-16 22:26:56 +0100621 alt {
622 [] as_mm_identity();
623 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT('07'O))) {
624 setverdict(pass);
625 }
626 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_ATTACH_REJECT(?))) {
627 setverdict(pass);
628 }
629 }
630}
631testcase TC_attach_closed() runs on test_CT {
632 var BSSGP_ConnHdlr vc_conn;
633 f_init();
634 f_sleep(1.0);
635 f_vty_config(SGSNVTY, "sgsn", "auth-policy closed");
636 /* test with foreign IMSI: Must Reject */
Harald Welteb7c14e92018-02-17 09:29:16 +0100637 vc_conn := f_start_handler(refers(f_TC_attach_closed_foreign), testcasename(), g_gb[0], 9);
Harald Welteb2124b22018-02-16 22:26:56 +0100638 vc_conn.done;
639 /* test with home IMSI: Must Accept */
Harald Welteb7c14e92018-02-17 09:29:16 +0100640 vc_conn := f_start_handler(refers(f_TC_attach_accept_all), testcasename(), g_gb[0], 10);
Harald Welteb2124b22018-02-16 22:26:56 +0100641 vc_conn.done;
642}
643
Harald Welte04683d02018-02-16 22:43:45 +0100644/* Routing Area Update from Unknown TLLI -> REJECT */
645private function f_TC_rau_unknown(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte04683d02018-02-16 22:43:45 +0100646 var RoutingAreaIdentificationV old_ra := f_random_RAI();
647
Harald Welte23178c52018-02-17 09:36:33 +0100648 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 +0100649 alt {
650 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_RAU_REJECT('0a'O))) {
651 setverdict(pass);
652 }
653 /* FIXME: Expect XID RESET? */
654 [] BSSGP.receive { repeat; }
655 }
656}
657testcase TC_rau_unknown() runs on test_CT {
658 var BSSGP_ConnHdlr vc_conn;
659 f_init();
660 f_sleep(1.0);
Harald Welteb7c14e92018-02-17 09:29:16 +0100661 vc_conn := f_start_handler(refers(f_TC_rau_unknown), testcasename(), g_gb[0], 11);
Harald Welte04683d02018-02-16 22:43:45 +0100662 vc_conn.done;
663}
664
Harald Welte91636de2018-02-17 10:16:14 +0100665private function f_TC_attach_rau(charstring id) runs on BSSGP_ConnHdlr {
666 var BssgpDecoded bd;
667
668 /* first perform regular attach */
669 f_TC_attach(id);
670
671 /* then send RAU */
672 BSSGP.send(ts_GMM_RAU_REQ(f_mi_get_lv(), GPRS_UPD_T_RA, g_pars.ra, false, omit, omit));
673 alt {
674 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_RAU_ACCEPT)) -> value bd {
675 f_process_rau_accept(bd.l3_mt.msgs.gprs_mm.routingAreaUpdateAccept);
676 setverdict(pass);
677 }
678 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_RAU_REJECT)) {
679 setverdict(fail, "Unexpected RAU Reject");
680 }
681 [] BSSGP.receive { repeat; }
682 }
683}
684testcase TC_attach_rau() runs on test_CT {
685 var BSSGP_ConnHdlr vc_conn;
686 f_init();
687 f_sleep(1.0);
688 vc_conn := f_start_handler(refers(f_TC_attach_rau), testcasename(), g_gb[0], 12);
689 vc_conn.done;
690}
Harald Welte04683d02018-02-16 22:43:45 +0100691
Harald Welte6abb9fe2018-02-17 15:24:48 +0100692/* general GPRS DETACH helper */
693function f_detach_mo(BIT3 detach_type, boolean power_off, boolean expect_purge) runs on BSSGP_ConnHdlr {
694 var BssgpDecoded bd;
695 timer T := 5.0;
696 BSSGP.send(ts_GMM_DET_REQ_MO(detach_type, power_off));
697 if (expect_purge) {
698 GSUP.receive(tr_GSUP_PURGE_MS_REQ(g_pars.imsi, OSMO_GSUP_CN_DOMAIN_PS));
699 GSUP.send(ts_GSUP_PURGE_MS_RES(g_pars.imsi));
700 }
701 T.start;
702 alt {
703 [not expect_purge] GSUP.receive(tr_GSUP_PURGE_MS_REQ(?)) {
704 setverdict(fail, "Unexpected GSUP PURGE MS for unregistered TLLI");
705 }
706 [power_off] BSSGP.receive(tr_BD_L3_MT(tr_GMM_DET_ACCEPT_MT)) -> value bd {
707 g_pars.ra := omit;
708 setverdict(fail, "Unexpected ATTACH ACCEPT in no-power-off DETACH");
709 /* TODO: check if any PDP contexts are deactivated on network side? */
710 }
711 [power_off] T.timeout {
712 setverdict(pass);
713 }
714 [not power_off] BSSGP.receive(tr_BD_L3_MT(tr_GMM_DET_ACCEPT_MT)) -> value bd {
715 g_pars.ra := omit;
716 setverdict(pass);
717 /* TODO: check if any PDP contexts are deactivated on network side? */
718 }
719 [] BSSGP.receive { repeat; }
720 }
721}
722
723/* IMSI DETACH (non-power-off) for unknown TLLI */
724private function f_TC_detach_unknown_nopoweroff(charstring id) runs on BSSGP_ConnHdlr {
725 f_detach_mo(c_GMM_DTT_MO_GPRS, false, false);
726}
727testcase TC_detach_unknown_nopoweroff() runs on test_CT {
728 var BSSGP_ConnHdlr vc_conn;
729 f_init();
730 f_sleep(1.0);
731 vc_conn := f_start_handler(refers(f_TC_detach_unknown_nopoweroff), testcasename(), g_gb[0], 13);
732 vc_conn.done;
733}
734
735/* IMSI DETACH (power-off) for unknown TLLI */
736private function f_TC_detach_unknown_poweroff(charstring id) runs on BSSGP_ConnHdlr {
737 f_detach_mo(c_GMM_DTT_MO_GPRS, true, false);
738}
739testcase TC_detach_unknown_poweroff() runs on test_CT {
740 var BSSGP_ConnHdlr vc_conn;
741 f_init();
742 f_sleep(1.0);
743 vc_conn := f_start_handler(refers(f_TC_detach_unknown_poweroff), testcasename(), g_gb[0], 14);
744 vc_conn.done;
745}
746
747/* IMSI DETACH (non-power-off) for known TLLI */
748private function f_TC_detach_nopoweroff(charstring id) runs on BSSGP_ConnHdlr {
749 /* first perform regular attach */
750 f_TC_attach(id);
751
752 f_detach_mo(c_GMM_DTT_MO_GPRS, false, true);
753}
754testcase TC_detach_nopoweroff() runs on test_CT {
755 var BSSGP_ConnHdlr vc_conn;
756 f_init();
757 f_sleep(1.0);
758 vc_conn := f_start_handler(refers(f_TC_detach_nopoweroff), testcasename(), g_gb[0], 15);
759 vc_conn.done;
760}
761
762/* IMSI DETACH (power-off) for known TLLI */
763private function f_TC_detach_poweroff(charstring id) runs on BSSGP_ConnHdlr {
764 /* first perform regular attach */
765 f_TC_attach(id);
766
767 f_detach_mo(c_GMM_DTT_MO_GPRS, true, true);
768}
769testcase TC_detach_poweroff() runs on test_CT {
770 var BSSGP_ConnHdlr vc_conn;
771 f_init();
772 f_sleep(1.0);
773 vc_conn := f_start_handler(refers(f_TC_detach_poweroff), testcasename(), g_gb[0], 16);
774 vc_conn.done;
775}
776
Harald Welteeded9ad2018-02-17 20:57:34 +0100777type record PdpActPars {
Harald Welte822f9102018-02-18 20:39:06 +0100778 BIT3 tid, /* L3 Transaction ID */
779 BIT4 nsapi, /* SNDCP NSAPI */
780 BIT4 sapi, /* LLC SAPI */
781 QoSV qos, /* QoS parameters */
782 PDPAddressV addr, /* IP address */
783 octetstring apn optional, /* APN name */
784 ProtocolConfigOptionsV pco optional, /* protoco config opts */
785 OCT1 exp_rej_cause optional, /* expected SM reject cause */
Harald Welte1d6ae932018-02-18 21:24:44 +0100786 OCT1 gtp_resp_cause, /* GTP response cause */
Harald Welte822f9102018-02-18 20:39:06 +0100787 OCT4 chg_id, /* GTP Charging Identifier */
Harald Welte6abb9fe2018-02-17 15:24:48 +0100788
Harald Welte822f9102018-02-18 20:39:06 +0100789 OCT4 ggsn_tei_c, /* GGSN TEI Control*/
790 OCT4 ggsn_tei_u, /* GGSN TEI User */
791 octetstring ggsn_ip_c, /* GGSN IP Control */
792 octetstring ggsn_ip_u, /* GGSN IP User */
Harald Welteeded9ad2018-02-17 20:57:34 +0100793
Harald Welte822f9102018-02-18 20:39:06 +0100794 OCT4 sgsn_tei_c optional, /* SGSN TEI Control */
795 OCT4 sgsn_tei_u optional, /* SGSN TEI User */
796 octetstring sgsn_ip_c optional, /* SGSN IP Control */
797 octetstring sgsn_ip_u optional /* SGSN IP USer */
Harald Welteeded9ad2018-02-17 20:57:34 +0100798};
799
Harald Welte5b5ca1b2018-02-18 21:25:03 +0100800
801private function f_process_gtp_ctx_act_req(inout PdpActPars apars, PDU_GTPC gtpc) runs on BSSGP_ConnHdlr {
802 var GTPC_PDUs gtpc_rx := gtpc.gtpc_pdu;
803 apars.sgsn_tei_c := gtpc_rx.createPDPContextRequest.teidControlPlane.teidControlPlane;
804 apars.sgsn_tei_u := gtpc_rx.createPDPContextRequest.teidDataI.teidDataI;
805 apars.sgsn_ip_c := gtpc_rx.createPDPContextRequest.sgsn_addr_signalling.addressf;
806 apars.sgsn_ip_u := gtpc_rx.createPDPContextRequest.sgsn_addr_traffic.addressf;
807 f_gtp_register_teid(apars.ggsn_tei_c);
808 f_gtp_register_teid(apars.ggsn_tei_u);
809}
810
Harald Welte37692d82018-02-18 15:21:34 +0100811function f_pdp_ctx_act(inout PdpActPars apars) runs on BSSGP_ConnHdlr {
Harald Welteeded9ad2018-02-17 20:57:34 +0100812 var boolean exp_rej := ispresent(apars.exp_rej_cause);
813 var Gtp1cUnitdata g_ud;
814
815 BSSGP.send(ts_SM_ACT_PDP_REQ(apars.tid, apars.nsapi, apars.sapi, apars.qos, apars.addr,
816 apars.apn, apars.pco));
Harald Welte5b5ca1b2018-02-18 21:25:03 +0100817 GTP.receive(tr_GTPC_MsgType(?, createPDPContextRequest, ?)) -> value g_ud {
818 f_process_gtp_ctx_act_req(apars, g_ud.gtpc);
819 var integer seq_nr := oct2int(g_ud.gtpc.opt_part.sequenceNumber);
820 GTP.send(ts_GTPC_CreatePdpResp(g_ud.peer, seq_nr,
821 apars.sgsn_tei_c, apars.gtp_resp_cause,
822 apars.ggsn_tei_c, apars.ggsn_tei_u,
823 apars.nsapi,
824 apars.ggsn_ip_c, apars.ggsn_ip_u, apars.chg_id));
Harald Welteeded9ad2018-02-17 20:57:34 +0100825 }
826 alt {
Harald Welte28307082018-02-18 12:14:18 +0100827 [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 +0100828 setverdict(pass);
829 }
Harald Welte28307082018-02-18 12:14:18 +0100830 [exp_rej] BSSGP.receive(tr_BD_L3_MT(tr_SM_ACT_PDP_ACCEPT)) {
Harald Welteeded9ad2018-02-17 20:57:34 +0100831 setverdict(fail, "Unexpected PDP CTX ACT ACC");
832 }
Harald Welte28307082018-02-18 12:14:18 +0100833 [not exp_rej] BSSGP.receive(tr_BD_L3_MT(tr_SM_ACT_PDP_REJ(apars.tid, ?))) {
Harald Welteeded9ad2018-02-17 20:57:34 +0100834 setverdict(fail, "Unexpected PDP CTX ACT FAIL");
835 }
Harald Welte28307082018-02-18 12:14:18 +0100836 [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 +0100837 setverdict(pass);
838 }
Harald Welte5b5ca1b2018-02-18 21:25:03 +0100839 [] as_xid(apars);
Harald Welteeded9ad2018-02-17 20:57:34 +0100840 }
841}
842
Harald Welte6f203162018-02-18 22:04:55 +0100843function f_pdp_ctx_deact_mo(inout PdpActPars apars, OCT1 cause) runs on BSSGP_ConnHdlr {
844 var boolean exp_rej := ispresent(apars.exp_rej_cause);
845 var Gtp1cUnitdata g_ud;
846
847 BSSGP.send(ts_SM_DEACT_PDP_REQ_MO(apars.tid, cause, false, omit));
848 GTP.receive(tr_GTPC_MsgType(?, deletePDPContextRequest, apars.ggsn_tei_c)) -> value g_ud {
849 var integer seq_nr := oct2int(g_ud.gtpc.opt_part.sequenceNumber);
850 BSSGP.clear;
851 GTP.send(ts_GTPC_DeletePdpResp(g_ud.peer, seq_nr, apars.sgsn_tei_c, '7F'O));
852 }
853 alt {
854 [] BSSGP.receive(tr_BD_L3_MT(tr_SM_DEACT_PDP_ACCEPT_MT(apars.tid))) {
855 setverdict(pass);
856 }
857 [] as_xid(apars);
858 }
859}
860
Harald Welte57b9b7f2018-02-18 22:28:13 +0100861function f_pdp_ctx_deact_mt(inout PdpActPars apars, OCT1 cause) runs on BSSGP_ConnHdlr {
862 var Gtp1cUnitdata g_ud;
863 var integer seq_nr := 23;
864 var GtpPeer peer := valueof(ts_GtpPeerC(apars.sgsn_ip_c));
865
866 BSSGP.clear;
867 GTP.send(ts_GTPC_DeletePDP(peer, seq_nr, apars.sgsn_tei_c, apars.nsapi, omit));
868
869 interleave {
870 [] BSSGP.receive(tr_BD_L3_MT(tr_SM_DEACT_PDP_REQ_MT(apars.tid, ?))) {
871 BSSGP.send(ts_SM_DEACT_PDP_ACCEPT_MO(apars.tid));
872 }
873 [] GTP.receive(tr_GTPC_MsgType(?, deletePDPContextResponse, apars.ggsn_tei_c)) { }
874 }
875}
876
Harald Welte6f203162018-02-18 22:04:55 +0100877
Harald Welteeded9ad2018-02-17 20:57:34 +0100878/* Table 10.5.156/3GPP TS 24.008 */
879template (value) QoSV t_QosDefault := {
880 reliabilityClass := '011'B, /* unacknowledged GTP+LLC, acknowledged RLC */
881 delayClass := '100'B, /* best effort */
882 spare1 := '00'B,
883 precedenceClass := '010'B, /* normal */
884 spare2 := '0'B,
885 peakThroughput := '0000'B, /* subscribed */
886 meanThroughput := '00000'B, /* subscribed */
887 spare3 := '000'B,
888 deliverErroneusSDU := omit,
889 deliveryOrder := omit,
890 trafficClass := omit,
891 maxSDUSize := omit,
892 maxBitrateUplink := omit,
893 maxBitrateDownlink := omit,
894 sduErrorRatio := omit,
895 residualBER := omit,
896 trafficHandlingPriority := omit,
897 transferDelay := omit,
898 guaranteedBitRateUplink := omit,
899 guaranteedBitRateDownlink := omit,
900 sourceStatisticsDescriptor := omit,
901 signallingIndication := omit,
902 spare4 := omit,
903 maxBitrateDownlinkExt := omit,
904 guaranteedBitRateDownlinkExt := omit,
905 maxBitrateUplinkExt := omit,
906 guaranteedBitRateUplinkExt := omit,
907 maxBitrateDownlinkExt2 := omit,
908 guaranteedBitRateDownlinkExt2 := omit,
909 maxBitrateUplinkExt2 := omit,
910 guaranteedBitRateUplinkExt2 := omit
911}
912
913/* 10.5.6.4 / 3GPP TS 24.008 */
914template (value) PDPAddressV t_AddrIPv4dyn := {
915 pdpTypeOrg := '0001'B, /* IETF */
916 spare := '0000'B,
917 pdpTypeNum := '21'O, /* IPv4 */
918 addressInfo := omit
919}
920template (value) PDPAddressV t_AddrIPv6dyn := {
921 pdpTypeOrg := '0001'B, /* IETF */
922 spare := '0000'B,
923 pdpTypeNum := '53'O, /* IPv6 */
924 addressInfo := omit
925}
926
Harald Welte37692d82018-02-18 15:21:34 +0100927template (value) PdpActPars t_PdpActPars(charstring ggsn_ip) := {
Harald Welteeded9ad2018-02-17 20:57:34 +0100928 tid := '000'B,
929 nsapi := '0101'B, /* < 5 are reserved */
930 sapi := '0011'B, /* 3/5/9/11 */
931 qos := t_QosDefault,
932 addr := t_AddrIPv4dyn,
933 apn := omit,
934 pco := omit,
935 exp_rej_cause := omit,
Harald Welte1d6ae932018-02-18 21:24:44 +0100936 gtp_resp_cause := int2oct(128, 1),
937 chg_id := f_rnd_octstring(4),
Harald Welteeded9ad2018-02-17 20:57:34 +0100938
939 /* FIXME: make below dynamic !! */
Harald Welte1d6ae932018-02-18 21:24:44 +0100940 ggsn_tei_c := f_rnd_octstring(4),
941 ggsn_tei_u := f_rnd_octstring(4),
Harald Welte37692d82018-02-18 15:21:34 +0100942 ggsn_ip_c := f_inet_addr(ggsn_ip),
943 ggsn_ip_u := f_inet_addr(ggsn_ip),
Harald Welteeded9ad2018-02-17 20:57:34 +0100944
Harald Welteeded9ad2018-02-17 20:57:34 +0100945 sgsn_tei_c := omit,
Harald Weltef8af5d62018-02-18 15:06:42 +0100946 sgsn_tei_u := omit,
947 sgsn_ip_c := omit,
948 sgsn_ip_u := omit
Harald Welteeded9ad2018-02-17 20:57:34 +0100949}
950
Harald Welte37692d82018-02-18 15:21:34 +0100951template (value) GtpPeer ts_GtpPeerU(octetstring ip) := {
952 connId := 1,
953 remName := f_inet_ntoa(ip),
954 remPort := GTP1U_PORT
955}
956
957template (value) GtpPeer ts_GtpPeerC(octetstring ip) := {
958 connId := 1,
959 remName := f_inet_ntoa(ip),
960 remPort := GTP1C_PORT
961}
962
963private function f_gtpu_send(inout PdpActPars apars, octetstring payload) runs on BSSGP_ConnHdlr {
964 var GtpPeer peer := valueof(ts_GtpPeerU(apars.sgsn_ip_u));
965 GTP.send(ts_GTP1U_GPDU(peer, 0 /*seq*/, apars.sgsn_tei_u, payload));
966}
967
968private altstep as_xid(PdpActPars apars) runs on BSSGP_ConnHdlr {
969 [] BSSGP.receive(tr_BD_LLC(tr_LLC_XID(?, apars.sapi))) {
970 repeat;
971 }
972}
973
974template PDU_SN tr_SN_UD(template BIT4 nsapi, template octetstring payload) := {
975 pDU_SN_UNITDATA := {
976 nsapi := nsapi,
977 moreBit := ?,
978 snPduType := '1'B,
979 firstSegmentIndicator := ?,
980 spareBit := ?,
981 pcomp := ?,
982 dcomp := ?,
983 npduNumber := ?,
984 segmentNumber := ?,
985 npduNumberContinued := ?,
986 dataSegmentSnUnitdataPdu := payload
987 }
988}
989
990/* simple case: single segment, no compression */
991template (value) PDU_SN ts_SN_UD(BIT4 nsapi, octetstring payload) := {
992 pDU_SN_UNITDATA := {
993 nsapi := nsapi,
994 moreBit := '0'B,
995 snPduType := '1'B,
996 firstSegmentIndicator := '1'B,
997 spareBit := '0'B,
998 pcomp := '0000'B,
999 dcomp := '0000'B,
1000 npduNumber := '0000'B,
1001 segmentNumber := '0000'B,
1002 npduNumberContinued := '00'O,
1003 dataSegmentSnUnitdataPdu := payload
1004 }
1005}
1006
1007/* Transceive given 'payload' as MT message from GTP -> OsmoSGSN -> Gb */
1008private function f_gtpu_xceive_mt(inout PdpActPars apars, octetstring payload) runs on BSSGP_ConnHdlr {
1009 /* Send PDU via GTP from our simulated GGSN to the SGSN */
1010 f_gtpu_send(apars, payload);
1011 /* Expect PDU via BSSGP/LLC on simulated PCU from SGSN */
1012 alt {
1013 [] as_xid(apars);
1014 [] BSSGP.receive(tr_BD_SNDCP(apars.sapi, tr_SN_UD(apars.nsapi, payload)));
1015 }
1016}
1017
1018private function f_gtpu_xceive_mo(inout PdpActPars apars, octetstring payload) runs on BSSGP_ConnHdlr {
1019 /* Send PDU via SNDCP/LLC/BSSGP/NS via simulated MS/PCU to the SGSN */
1020 var GtpPeer peer := valueof(ts_GtpPeerU(apars.sgsn_ip_u));
1021 var PDU_SN sndcp := valueof(ts_SN_UD(apars.nsapi, payload));
1022 BSSGP.send(ts_LLC_UI(enc_PDU_SN(sndcp), apars.sapi, '0'B, 0));
1023 f_gtpu_send(apars, payload);
1024 /* Expect PDU via GTP from SGSN on simulated GGSN */
1025 alt {
1026 [] GTP.receive(tr_GTPU_GPDU(peer, apars.ggsn_tei_u, payload));
1027 }
1028}
1029
Harald Welteeded9ad2018-02-17 20:57:34 +01001030private function f_TC_attach_pdp_act(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte37692d82018-02-18 15:21:34 +01001031 var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
Harald Welteeded9ad2018-02-17 20:57:34 +01001032
1033 /* first perform regular attach */
1034 f_TC_attach(id);
1035
1036 f_pdp_ctx_act(apars);
1037}
1038testcase TC_attach_pdp_act() runs on test_CT {
1039 var BSSGP_ConnHdlr vc_conn;
1040 f_init();
1041 vc_conn := f_start_handler(refers(f_TC_attach_pdp_act), testcasename(), g_gb[0], 17);
1042 vc_conn.done;
1043}
Harald Welteb2124b22018-02-16 22:26:56 +01001044
Harald Welte835b15f2018-02-18 14:39:11 +01001045/* PDP Context activation for not-attached subscriber; expect fail */
1046private function f_TC_pdp_act_unattached(charstring id) runs on BSSGP_ConnHdlr {
Harald Welte37692d82018-02-18 15:21:34 +01001047 var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
Harald Welte835b15f2018-02-18 14:39:11 +01001048 BSSGP.send(ts_SM_ACT_PDP_REQ(apars.tid, apars.nsapi, apars.sapi, apars.qos, apars.addr,
1049 apars.apn, apars.pco));
1050 alt {
1051 /* We might want toalso actually expect a PDPC CTX ACT REJ? */
1052 [] BSSGP.receive(tr_BD_L3_MT(tr_GMM_DET_REQ_MT(?, ?))) {
1053 setverdict(pass);
1054 }
1055 [] GTP.receive(tr_GTPC_MsgType(?, createPDPContextRequest, ?)) {
1056 setverdict(fail, "Unexpected GTP PDP CTX ACT");
1057 }
1058 [] BSSGP.receive(tr_BD_L3_MT(tr_SM_ACT_PDP_ACCEPT(?, ?))) {
1059 setverdict(fail, "Unexpected SM PDP CTX ACT ACK");
1060 }
1061 [] BSSGP.receive { repeat; }
1062 }
1063}
1064testcase TC_pdp_act_unattached() runs on test_CT {
1065 var BSSGP_ConnHdlr vc_conn;
1066 f_init();
1067 vc_conn := f_start_handler(refers(f_TC_pdp_act_unattached), testcasename(), g_gb[0], 18);
1068 vc_conn.done;
1069}
1070
Harald Welte37692d82018-02-18 15:21:34 +01001071/* ATTACH + PDP CTX ACT + user plane traffic */
1072private function f_TC_attach_pdp_act_user(charstring id) runs on BSSGP_ConnHdlr {
1073 var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
1074
1075 /* first perform regular attach */
1076 f_TC_attach(id);
1077 /* then activate PDP context */
1078 f_pdp_ctx_act(apars);
1079 /* then transceive a downlink PDU */
1080 f_gtpu_xceive_mt(apars, f_rnd_octstring(100));
1081 f_gtpu_xceive_mo(apars, f_rnd_octstring(200));
1082}
1083testcase TC_attach_pdp_act_user() runs on test_CT {
1084 var BSSGP_ConnHdlr vc_conn;
1085 f_init();
1086 vc_conn := f_start_handler(refers(f_TC_attach_pdp_act_user), testcasename(), g_gb[0], 19);
1087 vc_conn.done;
1088}
1089
Harald Welte5b5ca1b2018-02-18 21:25:03 +01001090/* ATTACH + PDP CTX ACT; reject from GGSN */
1091private function f_TC_attach_pdp_act_ggsn_reject(charstring id) runs on BSSGP_ConnHdlr {
1092 var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
1093
1094 apars.gtp_resp_cause := int2oct(199, 1); /* no resources available */
1095 apars.exp_rej_cause := '1a'O; /* insufficient resources */
1096
1097 /* first perform regular attach */
1098 f_TC_attach(id);
1099 /* then activate PDP context */
1100 f_pdp_ctx_act(apars);
1101}
1102testcase TC_attach_pdp_act_ggsn_reject() runs on test_CT {
1103 var BSSGP_ConnHdlr vc_conn;
1104 f_init();
1105 vc_conn := f_start_handler(refers(f_TC_attach_pdp_act_ggsn_reject), testcasename(), g_gb[0], 20);
1106 vc_conn.done;
1107}
Harald Welte835b15f2018-02-18 14:39:11 +01001108
Harald Welte6f203162018-02-18 22:04:55 +01001109/* ATTACH + PDP CTX ACT + user plane traffic + PDP CTX DEACT in MO direction */
1110private function f_TC_attach_pdp_act_user_deact_mo(charstring id) runs on BSSGP_ConnHdlr {
1111 var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
1112
1113 /* first perform regular attach */
1114 f_TC_attach(id);
1115 /* then activate PDP context */
1116 f_pdp_ctx_act(apars);
1117 /* then transceive a downlink PDU */
1118 f_gtpu_xceive_mt(apars, f_rnd_octstring(100));
1119 f_gtpu_xceive_mo(apars, f_rnd_octstring(200));
1120
1121 f_pdp_ctx_deact_mo(apars, '00'O);
1122}
1123testcase TC_attach_pdp_act_user_deact_mo() runs on test_CT {
1124 var BSSGP_ConnHdlr vc_conn;
1125 f_init();
1126 vc_conn := f_start_handler(refers(f_TC_attach_pdp_act_user_deact_mo), testcasename(), g_gb[0], 21);
1127 vc_conn.done;
1128}
1129
Harald Welte57b9b7f2018-02-18 22:28:13 +01001130/* ATTACH + PDP CTX ACT + user plane traffic + PDP CTX DEACT in MT direction */
1131private function f_TC_attach_pdp_act_user_deact_mt(charstring id) runs on BSSGP_ConnHdlr {
1132 var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
1133
1134 /* first perform regular attach */
1135 f_TC_attach(id);
1136 /* then activate PDP context */
1137 f_pdp_ctx_act(apars);
1138 /* then transceive a downlink PDU */
1139 f_gtpu_xceive_mt(apars, f_rnd_octstring(100));
1140 f_gtpu_xceive_mo(apars, f_rnd_octstring(200));
1141
1142 f_pdp_ctx_deact_mt(apars, '00'O);
1143}
1144testcase TC_attach_pdp_act_user_deact_mt() runs on test_CT {
1145 var BSSGP_ConnHdlr vc_conn;
1146 f_init();
1147 vc_conn := f_start_handler(refers(f_TC_attach_pdp_act_user_deact_mt), testcasename(), g_gb[0], 22);
1148 vc_conn.done;
1149}
1150
1151
Harald Welte5ac31492018-02-15 20:39:13 +01001152
1153control {
Harald Welte5b7c8122018-02-16 21:48:17 +01001154 execute( TC_attach() );
Neels Hofmeyr8df7d152018-03-14 19:03:28 +01001155 execute( TC_attach_mnc3() );
Harald Welte5b7c8122018-02-16 21:48:17 +01001156 execute( TC_attach_auth_id_timeout() );
1157 execute( TC_attach_auth_sai_timeout() );
Harald Weltefe253882018-02-17 09:25:00 +01001158 execute( TC_attach_auth_sai_reject() );
Harald Welte5b7c8122018-02-16 21:48:17 +01001159 execute( TC_attach_gsup_lu_timeout() );
Harald Welteb7c14e92018-02-17 09:29:16 +01001160 execute( TC_attach_gsup_lu_reject() );
Harald Welte3823e2e2018-02-16 21:53:48 +01001161 execute( TC_attach_combined() );
Harald Welte76dee092018-02-16 22:12:59 +01001162 execute( TC_attach_accept_all() );
Harald Welteb2124b22018-02-16 22:26:56 +01001163 execute( TC_attach_closed() );
Harald Welte04683d02018-02-16 22:43:45 +01001164 execute( TC_rau_unknown() );
Harald Welte91636de2018-02-17 10:16:14 +01001165 execute( TC_attach_rau() );
Harald Welte6abb9fe2018-02-17 15:24:48 +01001166 execute( TC_detach_unknown_nopoweroff() );
1167 execute( TC_detach_unknown_poweroff() );
1168 execute( TC_detach_nopoweroff() );
1169 execute( TC_detach_poweroff() );
Harald Welteeded9ad2018-02-17 20:57:34 +01001170 execute( TC_attach_pdp_act() );
Harald Welte835b15f2018-02-18 14:39:11 +01001171 execute( TC_pdp_act_unattached() );
Harald Welte37692d82018-02-18 15:21:34 +01001172 execute( TC_attach_pdp_act_user() );
Harald Welte5b5ca1b2018-02-18 21:25:03 +01001173 execute( TC_attach_pdp_act_ggsn_reject() );
Harald Welte6f203162018-02-18 22:04:55 +01001174 execute( TC_attach_pdp_act_user_deact_mo() );
Harald Welte57b9b7f2018-02-18 22:28:13 +01001175 execute( TC_attach_pdp_act_user_deact_mt() );
Harald Welte5ac31492018-02-15 20:39:13 +01001176}
Harald Welte96a33b02018-02-04 10:36:22 +01001177
1178
1179
1180}