blob: 0acfdb2ba00bc8df856a197b1f9bd2017b7951e6 [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;
339 f_perform_lu(false, true);
340}
341
342testcase TC_lu_imsi_noauth_tmsi() runs on MTC_CT {
343 var BSC_ConnHdlr vc_conn;
344 f_init();
345
346 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_tmsi), testcasename(), 1);
347 vc_conn.done;
348}
349
350private function f_tc_lu_imsi_noauth_notmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
351 g_pars := pars;
352 f_perform_lu(false, false);
353}
354
355testcase TC_lu_imsi_noauth_notmsi() runs on MTC_CT {
356 var BSC_ConnHdlr vc_conn;
357 f_init();
358
359 vc_conn := f_start_handler(refers(f_tc_lu_imsi_noauth_notmsi), testcasename(), 2);
360 vc_conn.done;
361}
362
363/* Do LU by IMSI, refuse it on GSUP and expect LU REJ back to MS */
364private function f_tc_lu_imsi_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
365 g_pars := pars;
366 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
367
368 f_create_gsup_expect(hex2str(g_pars.imsi));
369 f_bssap_compl_l3(l3_lu);
370 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
371 GSUP.send(ts_GSUP_UL_ERR(g_pars.imsi, 23));
372 alt {
373 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej(int2oct(23,1)))) { }
374 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
375 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
376 self.stop;
377 }
378 }
379 BSSAP.receive(tr_BSSMAP_ClearCommand);
380 BSSAP.send(ts_BSSMAP_ClearComplete);
381 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
382 setverdict(pass);
383}
384testcase TC_lu_imsi_reject() runs on MTC_CT {
385 var BSC_ConnHdlr vc_conn;
386 f_init();
387
388 vc_conn := f_start_handler(refers(f_tc_lu_imsi_reject), testcasename(), 3);
389 vc_conn.done;
390}
391
392/* Do LU by IMSI, timeout on GSUP */
393private function f_tc_lu_imsi_timeout_gsup(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
394 g_pars := pars;
395 var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
396
397 f_create_gsup_expect(hex2str(g_pars.imsi));
398 f_bssap_compl_l3(l3_lu);
399 GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
400 /* Normally the HLR would need to respond here, but we decide to force a timeout here */
401 alt {
402 /* FIXME: Expect specific reject cause */
403 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) { }
404 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
405 setverdict(fail, "Expecting LU REJ, but got ACCEPT");
406 self.stop;
407 }
408 }
409 BSSAP.receive(tr_BSSMAP_ClearCommand);
410 BSSAP.send(ts_BSSMAP_ClearComplete);
411 BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
412 setverdict(pass);
413}
414testcase TC_lu_imsi_timeout_gsup() runs on MTC_CT {
415 var BSC_ConnHdlr vc_conn;
416 f_init();
417
418 vc_conn := f_start_handler(refers(f_tc_lu_imsi_timeout_gsup), testcasename(), 4);
419 vc_conn.done;
420}
421
422
423/* Send CM SERVICE REQ for IMSI that has never performed LU before */
424private function f_tc_cmserv_imsi_unknown(charstring id, BSC_ConnHdlrPars pars)
425runs on BSC_ConnHdlr {
426
427 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
428 var BSSMAP_IE_CellIdentifier cell_id := valueof(ts_CellId_CGI('262'H, '042'H, 23, 42));
429 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ('0001'B, mi));
430
431 f_create_gsup_expect(hex2str(g_pars.imsi));
432
433 /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
434 f_bssap_compl_l3(l3_info);
435
436 timer T := 10.0;
Harald Weltef6dd64d2017-11-19 12:09:51 +0100437 T.start;
438 alt {
Harald Weltea49e36e2018-01-21 19:29:33 +0100439 [] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ)) { }
440 //[] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_ACC)) { }
441 [] BSSAP.receive { setverdict(fail, "Received unexpected BSSAP"); }
442 [] GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi)) {
443 setverdict(fail, "Unexpected GSUP UL REQ");
444 }
445 [] T.timeout { setverdict(inconc, "Timeout waiting for CM SERV REQ"); }
Harald Weltef6dd64d2017-11-19 12:09:51 +0100446 }
447
Harald Weltea49e36e2018-01-21 19:29:33 +0100448 alt {
449 [] BSSAP.receive(tr_BSSMAP_ClearCommand) {
450 setverdict(pass);
451 }
452 [] BSSAP.receive { setverdict(fail, "Received unexpected BSSAP"); }
453 [] T.timeout { setverdict(inconc, "Timeout waiting for CM SERV REQ"); }
454 }
Harald Weltef6dd64d2017-11-19 12:09:51 +0100455}
Harald Weltea49e36e2018-01-21 19:29:33 +0100456testcase TC_cmserv_imsi_unknown() runs on MTC_CT {
457 var BSC_ConnHdlr vc_conn;
458 f_init();
459 vc_conn := f_start_handler(refers(f_tc_cmserv_imsi_unknown), testcasename(), 5);
460 vc_conn.done;
461}
462
463
Harald Weltef6dd64d2017-11-19 12:09:51 +0100464
465
466control {
Harald Weltea49e36e2018-01-21 19:29:33 +0100467 execute( TC_cmserv_imsi_unknown() );
468 execute( TC_lu_imsi_noauth_tmsi() );
469 //execute( TC_lu_imsi_noauth_notmsi() );
470 execute( TC_lu_imsi_reject() );
471 execute( TC_lu_imsi_timeout_gsup() );
Harald Weltef6dd64d2017-11-19 12:09:51 +0100472}
473
474
475}