blob: 68e0bef8c68324d3b9db6bf4dc73e15d6602d9ee [file] [log] [blame]
Harald Weltef6dd64d2017-11-19 12:09:51 +01001module MSC_Tests {
2
3import from General_Types all;
4import from Osmocom_Types all;
5
6import from M3UA_Types all;
7import from M3UA_Emulation all;
8
9import from MTP3asp_Types all;
10import from MTP3asp_PortType all;
11
12import from SCCPasp_Types all;
13import from SCCP_Types all;
14import from SCCP_Emulation all;
15
16import from SCTPasp_Types all;
17import from SCTPasp_PortType all;
18
Harald Weltea49e36e2018-01-21 19:29:33 +010019import from Osmocom_CTRL_Functions all;
20import from Osmocom_CTRL_Types all;
21import from Osmocom_CTRL_Adapter all;
22
23import from MNCC_Emulation all;
24
25import from GSUP_Emulation all;
26import from GSUP_Types all;
27import from IPA_Emulation all;
28
Harald Weltef6dd64d2017-11-19 12:09:51 +010029import from BSSAP_Types all;
Harald Weltea49e36e2018-01-21 19:29:33 +010030import from BSSAP_Adapter all;
31import from BSSAP_CodecPort all;
32import from BSSMAP_Templates all;
33import from BSSMAP_Emulation all;
34import from BSC_ConnectionHandler all;
Harald Weltef6dd64d2017-11-19 12:09:51 +010035
Harald Weltea49e36e2018-01-21 19:29:33 +010036import from MobileL3_Types all;
37import from MobileL3_CommonIE_Types all;
38import from L3_Templates all;
Harald Weltef6dd64d2017-11-19 12:09:51 +010039
Harald Weltef6dd64d2017-11-19 12:09:51 +010040
Harald Weltea49e36e2018-01-21 19:29:33 +010041type component MTC_CT extends BSSAP_Adapter_CT, CTRL_Adapter_CT {
Harald Weltef6dd64d2017-11-19 12:09:51 +010042 var boolean g_initialized := false;
Harald Weltea49e36e2018-01-21 19:29:33 +010043
44 /* no 'adapter_CT' for MNCC or GSUP */
45 var MNCC_Emulation_CT vc_MNCC;
46 var GSUP_Emulation_CT vc_GSUP;
47 var IPA_Emulation_CT vc_GSUP_IPA;
48
49 /* only to get events from IPA underneath GSUP */
50 port IPA_CTRL_PT GSUP_IPA_EVENT;
Harald Weltef6dd64d2017-11-19 12:09:51 +010051}
52
53modulepar {
Harald Weltea49e36e2018-01-21 19:29:33 +010054 /* remote parameters of IUT */
55 charstring mp_msc_ip := "127.0.0.1";
56 integer mp_msc_ctrl_port := 4255;
57 integer mp_msc_vty_port := 4254;
Harald Weltef6dd64d2017-11-19 12:09:51 +010058
Harald Weltea49e36e2018-01-21 19:29:33 +010059 /* local parameters of emulated HLR */
60 charstring mp_hlr_ip := "127.0.0.1";
61 integer mp_hlr_port := 4222;
Harald Weltef6dd64d2017-11-19 12:09:51 +010062
Harald Weltea49e36e2018-01-21 19:29:33 +010063 charstring mp_msc_mncc := "/tmp/mncc";
Harald Weltef6dd64d2017-11-19 12:09:51 +010064}
65
66
Harald Weltea49e36e2018-01-21 19:29:33 +010067function f_init_mncc(charstring id) runs on MTC_CT {
68 id := id & "-MNCC";
69 var MnccOps ops := {
70 create_cb := refers(MNCC_Emulation.ExpectedCreateCallback),
71 unitdata_cb := refers(MNCC_Emulation.DummyUnitdataCallback)
72 }
73
74 vc_MNCC := MNCC_Emulation_CT.create(id);
75 map(vc_MNCC:MNCC, system:MNCC_CODEC_PT);
76 vc_MNCC.start(MNCC_Emulation.main(ops, id, mp_msc_mncc));
Harald Weltef6dd64d2017-11-19 12:09:51 +010077}
78
Harald Weltea49e36e2018-01-21 19:29:33 +010079function f_init_gsup(charstring id) runs on MTC_CT {
80 id := id & "-GSUP";
81 var GsupOps ops := {
82 create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
83 }
84
85 vc_GSUP_IPA := IPA_Emulation_CT.create(id & "-IPA");
86 vc_GSUP := GSUP_Emulation_CT.create(id);
87
88 map(vc_GSUP_IPA:IPA_PORT, system:IPA_CODEC_PT);
89 connect(vc_GSUP:GSUP, vc_GSUP_IPA:IPA_GSUP_PORT);
90 /* we use this hack to get events like ASP_IPA_EVENT_UP */
91 connect(vc_GSUP_IPA:IPA_CTRL_PORT, self:GSUP_IPA_EVENT);
92
93 vc_GSUP.start(GSUP_Emulation.main(ops, id));
94 vc_GSUP_IPA.start(IPA_Emulation.main_server(mp_hlr_ip, mp_hlr_port));
95
96 /* wait for incoming connection to GSUP port before proceeding */
97 timer T := 10.0;
98 T.start;
99 alt {
100 [] GSUP_IPA_EVENT.receive(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_UP)) { }
101 [] T.timeout {
102 setverdict(inconc, "No connection to GSUP Port");
103 self.stop
104 }
105 }
Harald Weltef6dd64d2017-11-19 12:09:51 +0100106}
107
Harald Weltea49e36e2018-01-21 19:29:33 +0100108function f_init() runs on MTC_CT {
Harald Weltef6dd64d2017-11-19 12:09:51 +0100109
110 if (g_initialized == true) {
111 return;
112 }
113 g_initialized := true;
114
Harald Weltea49e36e2018-01-21 19:29:33 +0100115 f_bssap_init("MSC_Test", BSC_BssmapOps);
116 f_ipa_ctrl_start(mp_msc_ip, mp_msc_ctrl_port);
117 f_init_mncc("MSC_Test");
118 f_init_gsup("MSC_Test");
Harald Weltef6dd64d2017-11-19 12:09:51 +0100119}
120
121template PDU_BSSAP ts_BSSAP_BSSMAP := {
122 discriminator := '0'B,
123 spare := '0000000'B,
124 dlci := omit,
125 lengthIndicator := 0, /* overwritten by codec */
126 pdu := ?
127}
128
129template PDU_BSSAP tr_BSSAP_BSSMAP := {
130 discriminator := '0'B,
131 spare := '0000000'B,
132 dlci := omit,
133 lengthIndicator := ?,
134 pdu := {
135 bssmap := ?
136 }
137}
138
139
140type integer BssmapCause;
141
142template (value) BSSMAP_IE_Cause ts_BSSMAP_IE_Cause(BssmapCause val) := {
143 elementIdentifier := '04'O,
144 lengthIndicator := 0,
145 causeValue := int2bit(val, 7),
146 extensionCauseValue := '0'B,
147 spare1 := omit
148}
149
150template (value) PDU_BSSAP ts_BSSMAP_Reset(BssmapCause cause) modifies ts_BSSAP_BSSMAP := {
151 pdu := {
152 bssmap := {
153 reset := {
154 messageType := '30'O,
155 cause := ts_BSSMAP_IE_Cause(cause),
156 a_InterfaceSelectorForReset := omit
157 }
158 }
159 }
160}
161
162template (value) PDU_BSSAP ts_BSSMAP_ResetAck modifies ts_BSSAP_BSSMAP := {
163 pdu := {
164 bssmap := {
165 resetAck := {
166 messageType := '31'O,
167 a_InterfaceSelectorForReset := omit
168 }
169 }
170 }
171}
172
173template PDU_BSSAP tr_BSSMAP_ResetAck modifies tr_BSSAP_BSSMAP := {
174 pdu := {
175 bssmap := {
176 resetAck := {
177 messageType := '31'O,
178 a_InterfaceSelectorForReset := *
179 }
180 }
181 }
182}
183
184template BSSMAP_IE_CellIdentifier ts_BSSMAP_IE_CellID := {
185 elementIdentifier := '05'O,
186 lengthIndicator := 0,
187 cellIdentifierDiscriminator := '0000'B,
188 spare1_4 := '0000'B,
189 cellIdentification := ?
190}
191
192type uint16_t BssmapLAC;
193type uint16_t BssmapCI;
194
195/*
196template BSSMAP_IE_CellIdentifier ts_CellId_CGI(mcc, mnc, lac, ci)
197modifies ts_BSSMAP_IE_CellID := {
198 cellIdentification := {
199 cI_LAC_CGI := {
200 mnc_mcc := FIXME,
201 lac := int2oct(lac, 2),
202 ci := int2oct(ci, 2)
203 }
204 }
205}
206*/
207
208template BSSMAP_IE_CellIdentifier ts_CellID_LAC_CI(BssmapLAC lac, BssmapCI ci)
209modifies ts_BSSMAP_IE_CellID := {
210 cellIdentification := {
211 cI_LAC_CI := {
212 lac := int2oct(lac, 2),
213 ci := int2oct(ci, 2)
214 }
215 }
216}
217
218template BSSMAP_IE_CellIdentifier ts_CellId_CI(BssmapCI ci)
219modifies ts_BSSMAP_IE_CellID := {
220 cellIdentification := {
221 cI_CI := int2oct(ci, 2)
222 }
223}
224
225template BSSMAP_IE_CellIdentifier ts_CellId_none
226modifies ts_BSSMAP_IE_CellID := {
227 cellIdentification := {
228 cI_noCell := ''O
229 }
230}
231
232
233template BSSMAP_IE_Layer3Information ts_BSSMAP_IE_L3Info(octetstring l3info) := {
234 elementIdentifier := '17'O,
235 lengthIndicator := 0,
236 layer3info := l3info
237}
238
239template PDU_BSSAP ts_BSSMAP_ComplL3(BSSMAP_IE_CellIdentifier cell_id, octetstring l3_info)
240modifies ts_BSSAP_BSSMAP := {
241 pdu := {
242 bssmap := {
243 completeLayer3Information := {
244 messageType := '57'O,
245 cellIdentifier := cell_id,
246 layer3Information := ts_BSSMAP_IE_L3Info(l3_info),
247 chosenChannel := omit,
248 lSAIdentifier := omit,
249 aPDU := omit,
250 codecList := omit,
251 redirectAttemptFlag := omit,
252 sendSequenceNumber := omit,
253 iMSI := omit
254 }
255 }
256 }
257}
258
259template PDU_BSSAP ts_BSSMAP_HandoReq(BssmapCause cause, BSSMAP_IE_CellIdentifierList cid_list)
260modifies ts_BSSAP_BSSMAP := {
261 pdu := {
262 bssmap := {
263 handoverRequired := {
264 messageType := '11'O,
265 cause := ts_BSSMAP_IE_Cause(cause),
266 responseRequest := omit,
267 cellIdentifierList := cid_list,
268 circuitPoolList := omit,
269 currentChannelType1 := omit,
270 speechVersion := omit,
271 queueingIndicator := omit,
272 oldToNewBSSInfo := omit,
273 sourceToTargetRNCTransparentInfo := omit,
274 sourceToTargetRNCTransparentInfoCDMA := omit,
275 gERANClassmark := omit,
276 talkerPriority := omit,
277 speechCodec := omit,
278 cSG_Identifier := omit
279 }
280 }
281 }
282}
283
284// enc_PDU_BSSAP
285
286function f_send_BSSAP_UNITDATA(template PDU_BSSAP bssap) runs on MTC_CT {
Harald Weltea49e36e2018-01-21 19:29:33 +0100287 BSSAP.send(ts_BSSAP_UNITDATA_req(g_sccp_addr_peer, g_sccp_addr_own, bssap))
Harald Weltef6dd64d2017-11-19 12:09:51 +0100288}
289
Harald Weltea49e36e2018-01-21 19:29:33 +0100290type function void_fn(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100291
Harald Weltea49e36e2018-01-21 19:29:33 +0100292function f_gen_imsi(hexstring prefix, integer suffix) return hexstring {
293 var integer suffix_len := 15 - lengthof(prefix);
294 suffix_len := suffix_len-1; /* FIXME: fix odd IMSI length */
295 return prefix & int2hex(suffix, suffix_len);
296}
297
298function f_gen_msisdn(hexstring prefix, integer suffix) return hexstring {
299 var integer suffix_len := 12 - lengthof(prefix);
300 return prefix & int2hex(suffix, suffix_len);
301}
302
303/* FIXME: move into BSC_ConnectionHandler? */
304function f_start_handler(void_fn fn, charstring id, integer imsi_suffix) runs on MTC_CT return BSC_ConnHdlr {
305 var BSC_ConnHdlr vc_conn;
306 var BSC_ConnHdlrPars pars := {
307 sccp_addr_own := g_sccp_addr_own,
308 sccp_addr_peer := g_sccp_addr_peer,
309 cell_id := valueof(ts_CellId_CGI('262'H, '042'H, 23, 42)),
310 imsi := f_gen_imsi('26242'H, imsi_suffix),
Harald Welte82600572018-01-21 20:54:08 +0100311 msisdn := f_gen_msisdn('491239999'H, imsi_suffix),
312 cm2 := valueof(ts_CM2_default),
313 cm3 := omit
Harald Weltea49e36e2018-01-21 19:29:33 +0100314 };
315
316 vc_conn := BSC_ConnHdlr.create(id);
317 /* BSSMAP part / A interface */
318 connect(vc_conn:BSSAP, vc_BSSMAP:CLIENT);
319 connect(vc_conn:BSSAP_PROC, vc_BSSMAP:PROC);
320 /* MNCC part */
321 connect(vc_conn:MNCC, vc_MNCC:MNCC_CLIENT);
322 connect(vc_conn:MNCC_PROC, vc_MNCC:MNCC_PROC);
323 /* GSUP part */
324 connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT);
325 connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);
326
327 vc_conn.start(derefers(fn)(id, pars));
328 return vc_conn;
329}
330
331function f_sleep(float seconds) {
332 timer T := seconds;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100333 T.start;
334 T.timeout;
Harald Weltea49e36e2018-01-21 19:29:33 +0100335}
Harald Weltef6dd64d2017-11-19 12:09:51 +0100336
Harald Weltea49e36e2018-01-21 19:29:33 +0100337private function f_tc_lu_imsi_noauth_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
338 g_pars := pars;
Harald Welte8a121b32018-01-22 03:00:41 +0100339 f_perform_lu(false, true, true);
Harald Weltea49e36e2018-01-21 19:29:33 +0100340}
Harald Weltea49e36e2018-01-21 19:29:33 +0100341testcase TC_lu_imsi_noauth_tmsi() runs on MTC_CT {
342 var BSC_ConnHdlr vc_conn;
343 f_init();
344
345 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_tmsi), testcasename(), 1);
346 vc_conn.done;
347}
348
349private function f_tc_lu_imsi_noauth_notmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
350 g_pars := pars;
Harald Welte8a121b32018-01-22 03:00:41 +0100351 f_perform_lu(false, false, true);
Harald Weltea49e36e2018-01-21 19:29:33 +0100352}
Harald Weltea49e36e2018-01-21 19:29:33 +0100353testcase TC_lu_imsi_noauth_notmsi() runs on MTC_CT {
354 var BSC_ConnHdlr vc_conn;
355 f_init();
356
357 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_notmsi), testcasename(), 2);
358 vc_conn.done;
359}
360
361/* Do LU by IMSI, refuse it on GSUP and expect LU REJ back to MS */
362private function f_tc_lu_imsi_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
363 g_pars := pars;
364 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
365
366 f_create_gsup_expect(hex2str(g_pars.imsi));
367 f_bssap_compl_l3(l3_lu);
368 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
369 GSUP.send(ts_GSUP_UL_ERR(g_pars.imsi, 23));
370 alt {
371 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej(int2oct(23,1)))) { }
372 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
373 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
374 self.stop;
375 }
376 }
377 BSSAP.receive(tr_BSSMAP_ClearCommand);
378 BSSAP.send(ts_BSSMAP_ClearComplete);
379 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
380 setverdict(pass);
381}
382testcase TC_lu_imsi_reject() runs on MTC_CT {
383 var BSC_ConnHdlr vc_conn;
384 f_init();
385
386 vc_conn := f_start_handler(refers(f_tc_lu_imsi_reject), testcasename(), 3);
387 vc_conn.done;
388}
389
390/* Do LU by IMSI, timeout on GSUP */
391private function f_tc_lu_imsi_timeout_gsup(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
392 g_pars := pars;
393 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
394
395 f_create_gsup_expect(hex2str(g_pars.imsi));
396 f_bssap_compl_l3(l3_lu);
397 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
398 /* Normally the HLR would need to respond here, but we decide to force a timeout here */
399 alt {
400 /* FIXME: Expect specific reject cause */
401 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) { }
402 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
403 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
404 self.stop;
405 }
406 }
407 BSSAP.receive(tr_BSSMAP_ClearCommand);
408 BSSAP.send(ts_BSSMAP_ClearComplete);
409 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
410 setverdict(pass);
411}
412testcase TC_lu_imsi_timeout_gsup() runs on MTC_CT {
413 var BSC_ConnHdlr vc_conn;
414 f_init();
415
416 vc_conn := f_start_handler(refers(f_tc_lu_imsi_timeout_gsup), testcasename(), 4);
417 vc_conn.done;
418}
419
420
421/* Send CM SERVICE REQ for IMSI that has never performed LU before */
422private function f_tc_cmserv_imsi_unknown(charstring id, BSC_ConnHdlrPars pars)
423runs on BSC_ConnHdlr {
424
425 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
426 var BSSMAP_IE_CellIdentifier cell_id := valueof(ts_CellId_CGI('262'H, '042'H, 23, 42));
427 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ('0001'B, mi));
428
429 f_create_gsup_expect(hex2str(g_pars.imsi));
430
431 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
432 f_bssap_compl_l3(l3_info);
433
434 timer T := 10.0;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100435 T.start;
436 alt {
Harald Weltea49e36e2018-01-21 19:29:33 +0100437 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ)) { }
438 //[] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_ACC)) { }
439 [] BSSAP.receive { setverdict(fail, "Received unexpected BSSAP"); }
440 [] GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi)) {
441 setverdict(fail, "Unexpected GSUP UL REQ");
442 }
443 [] T.timeout { setverdict(inconc, "Timeout waiting for CM SERV REQ"); }
Harald Weltef6dd64d2017-11-19 12:09:51 +0100444 }
445
Harald Weltea49e36e2018-01-21 19:29:33 +0100446 alt {
447 [] BSSAP.receive(tr_BSSMAP_ClearCommand) {
448 setverdict(pass);
449 }
450 [] BSSAP.receive { setverdict(fail, "Received unexpected BSSAP"); }
451 [] T.timeout { setverdict(inconc, "Timeout waiting for CM SERV REQ"); }
452 }
Harald Weltef6dd64d2017-11-19 12:09:51 +0100453}
Harald Weltea49e36e2018-01-21 19:29:33 +0100454testcase TC_cmserv_imsi_unknown() runs on MTC_CT {
455 var BSC_ConnHdlr vc_conn;
456 f_init();
457 vc_conn := f_start_handler(refers(f_tc_cmserv_imsi_unknown), testcasename(), 5);
458 vc_conn.done;
459}
460
461
Harald Weltef6dd64d2017-11-19 12:09:51 +0100462
463
464control {
Harald Weltea49e36e2018-01-21 19:29:33 +0100465 execute( TC_cmserv_imsi_unknown() );
466 execute( TC_lu_imsi_noauth_tmsi() );
467 //execute( TC_lu_imsi_noauth_notmsi() );
468 execute( TC_lu_imsi_reject() );
469 execute( TC_lu_imsi_timeout_gsup() );
Harald Weltef6dd64d2017-11-19 12:09:51 +0100470}
471
472
473}