blob: 51ac650a19c56a8c656c81840dbe0d515375da17 [file] [log] [blame]
Harald Welte28d943e2017-11-25 15:00:50 +01001module MSC_ConnectionHandler {
2
3import from General_Types all;
4import from Osmocom_Types all;
Harald Weltec1a2fff2017-12-17 11:06:19 +01005import from GSM_Types all;
Harald Welte28d943e2017-11-25 15:00:50 +01006import from SCCPasp_Types all;
7import from BSSAP_Types all;
8import from BSSMAP_Emulation all;
9import from BSSMAP_Templates all;
10
11import from MGCP_Types all;
12import from MGCP_Templates all;
13import from SDP_Types all;
14
Harald Weltec1a2fff2017-12-17 11:06:19 +010015import from RSL_Emulation all;
16import from RSL_Types all;
17
18import from MobileL3_Types all;
19import from MobileL3_CommonIE_Types all;
20//import from MobileL3_RRM_Types all;
21import from L3_Templates all;
22
23
Harald Welte28d943e2017-11-25 15:00:50 +010024/* this component represents a single subscriber connection at the MSC.
25 * There is a 1:1 mapping between SCCP connections and BSSAP_ConnHdlr components.
26 * We inherit all component variables, ports, functions, ... from BSSAP_ConnHdlr */
Harald Weltec1a2fff2017-12-17 11:06:19 +010027type component MSC_ConnHdlr extends BSSAP_ConnHdlr, RSL_DchanHdlr {
Harald Welte28d943e2017-11-25 15:00:50 +010028 /* SCCP Connecction Identifier for the underlying SCCP connection */
29 var integer g_sccp_conn_id;
30
Harald Weltec1a2fff2017-12-17 11:06:19 +010031 /* procedure port back to our parent (BSSMAP_Emulation_CT) for control */
32 port BSSMAPEM_PROC_PT BSSMAPEM;
Harald Welte28d943e2017-11-25 15:00:50 +010033
Harald Weltec1a2fff2017-12-17 11:06:19 +010034 var MSC_State g_state := MSC_STATE_NONE;
Harald Welte28d943e2017-11-25 15:00:50 +010035}
36
37/* Callback function from general BSSMAP_Emulation whenever a connectionless
38 * BSSMAP message arrives. Can retunr a PDU_BSSAP that should be sent in return */
39private function UnitdataCallback(PDU_BSSAP bssap)
40runs on BSSMAP_Emulation_CT return template PDU_BSSAP {
41 var template PDU_BSSAP resp := omit;
42
Harald Weltec1a2fff2017-12-17 11:06:19 +010043 /* answer all RESET with a RESET ACK */
Harald Welte28d943e2017-11-25 15:00:50 +010044 if (match(bssap, tr_BSSMAP_Reset)) {
45 resp := ts_BSSMAP_ResetAck;
46 }
47
48 return resp;
49}
50
51const BssmapOps MSC_BssmapOps := {
Harald Weltec1a2fff2017-12-17 11:06:19 +010052 create_cb := refers(BSSMAP_Emulation.ExpectedCreateCallback),
Harald Welte28d943e2017-11-25 15:00:50 +010053 unitdata_cb := refers(UnitdataCallback)
54}
55
56type enumerated MSC_State {
57 MSC_STATE_NONE,
58 MSC_STATE_WAIT_ASS_COMPL,
59 MSC_STATE_WAIT_CRCX_ACK,
60 MSC_STATE_WAIT_MDCX_ACK,
61 MSC_STATE_WAIT_CLEAR_COMPL,
62 MSC_STATE_WAIT_DLCX_ACK
63}
64
Harald Weltec1a2fff2017-12-17 11:06:19 +010065/* register an expect with the BSSMAP core */
66private function f_create_exp(octetstring l3_enc) runs on MSC_ConnHdlr {
67 BSSMAPEM.call(BSSMAPEM_register:{l3_enc, self}) {
68 [] BSSMAPEM.getreply(BSSMAPEM_register:{?, ?}) {};
Harald Welte28d943e2017-11-25 15:00:50 +010069 }
70}
71
Harald Weltec1a2fff2017-12-17 11:06:19 +010072type record TestHdlrParams {
73 OCT1 ra,
74 GsmFrameNumber fn,
75 hexstring imsi,
76 RslLinkId link_id
77};
78
79template (value) TestHdlrParams t_def_TestHdlrPars := {
80 ra := '23'O,
81 fn := 23,
82 imsi := '001019876543210'H,
83 link_id := valueof(ts_RslLinkID_DCCH(0))
84}
85
86function f_create_chan_and_exp(TestHdlrParams pars) runs on MSC_ConnHdlr {
87 var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(pars.imsi));
88 var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ('0001'B, mi));
89 var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
90
91 /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
92 RSL_Emulation.f_chan_est(pars.ra, l3_enc, pars.link_id, pars.fn);
93 f_create_exp(l3_enc);
94}
95
96function f_rsl_reply(template PDU_ML3_MS_NW l3, RSL_Message orig) runs on MSC_ConnHdlr {
97 var RslChannelNr chan_nr := orig.ies[0].body.chan_nr;
Harald Welte1a40de62017-12-23 02:28:34 +010098 var RslLinkId link_id;
Harald Welte8d5eead2017-12-17 18:56:45 +010099 if (orig.msg_type == RSL_MT_ENCR_CMD) {
100 link_id := orig.ies[2].body.link_id;
101 } else {
102 link_id := orig.ies[1].body.link_id;
103 }
Harald Weltec1a2fff2017-12-17 11:06:19 +0100104 RSL.send(ts_RSL_DATA_IND(chan_nr, link_id, enc_PDU_ML3_MS_NW(valueof(l3))));
105}
106
Harald Welte73cd2712017-12-17 00:44:52 +0100107function f_cipher_mode(OCT1 alg, OCT8 key, template OCT16 kc128 := omit) runs on MSC_ConnHdlr {
108 var PDU_BSSAP bssap;
109 var RSL_Message rsl;
110
111 if (isvalue(kc128)) {
112 BSSAP.send(ts_BSSMAP_CipherModeCmdKc128(alg, key, valueof(kc128)));
113 } else {
114 BSSAP.send(ts_BSSMAP_CipherModeCmd(alg, key));
115 }
116 alt {
117 /* RSL/UE Side */
118 [] RSL.receive(tr_RSL_ENCR_CMD(g_chan_nr, ?, alg, key)) -> value rsl {
119 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[3].body.l3_info.payload);
120 log("Rx L3 from net: ", l3);
121 if (ischosen(l3.msgs.rrm.cipheringModeCommand)) {
122 f_rsl_reply(ts_RRM_CiphModeCompl, rsl);
123 }
124 repeat;
125 }
126 [] BSSAP.receive(tr_BSSMAP_CipherModeCompl) -> value bssap {
127 // bssap.bssmap.cipherModeComplete.chosenEncryptionAlgorithm.algoritmhIdentifier
128 setverdict(pass);
129 }
130 [] BSSAP.receive(tr_BSSMAP_CipherModeRej) -> value bssap {
131 setverdict(fail, "Ciphering Mode Reject");
132 }
133 }
134}
135
Harald Weltec1a2fff2017-12-17 11:06:19 +0100136/* establish a channel fully, expecting an assignment matching 'exp' */
137function f_establish_fully(TestHdlrParams pars, PDU_BSSAP ass_cmd, template PDU_BSSAP exp_ass_cpl)
138runs on MSC_ConnHdlr return PDU_BSSAP {
139 var PDU_BSSAP bssap;
140 var RSL_Message rsl;
141 timer T := 10.0;
142 var boolean exp_compl := ischosen(exp_ass_cpl.pdu.bssmap.assignmentComplete);
Harald Welte82d2b872017-12-16 23:36:23 +0100143 var boolean crcx_seen := false;
144 var boolean rr_modify_seen := false;
Harald Weltec1a2fff2017-12-17 11:06:19 +0100145
146 f_create_chan_and_exp(pars);
147 /* we should now have a COMPL_L3 at the MSC */
148
149 BSSAP.receive(tr_BSSMAP_ComplL3);
150 BSSAP.send(ass_cmd);
151 alt {
152 /* if we receive exactly what we expected, always return + pass */
153 [] BSSAP.receive(exp_ass_cpl) -> value bssap {
154 setverdict(pass);
155 return bssap;
156 }
Harald Welte82d2b872017-12-16 23:36:23 +0100157 [rr_modify_seen == false] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
Harald Weltec1a2fff2017-12-17 11:06:19 +0100158 var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
159 log("Rx L3 from net: ", l3);
160 if (ischosen(l3.msgs.rrm.channelModeModify)) {
161 f_rsl_reply(ts_RRM_ModeModifyAck(l3.msgs.rrm.channelModeModify.channelDescription,
162 l3.msgs.rrm.channelModeModify.channelMode), rsl);
Harald Welte82d2b872017-12-16 23:36:23 +0100163 rr_modify_seen := true;
Harald Weltec1a2fff2017-12-17 11:06:19 +0100164 }
165 repeat;
166 }
Harald Welte82d2b872017-12-16 23:36:23 +0100167 [rr_modify_seen] RSL.receive(tr_RSL_MsgTypeD(RSL_MT_MODE_MODIFY_REQ)) -> value rsl {
Harald Weltec1a2fff2017-12-17 11:06:19 +0100168 RSL.send(ts_RSL_MODE_MODIFY_ACK(g_chan_nr));
169 repeat;
170 }
Harald Welte82d2b872017-12-16 23:36:23 +0100171 [crcx_seen == false] RSL.receive(tr_RSL_IPA_CRCX(g_chan_nr)) -> value rsl {
Harald Weltec1a2fff2017-12-17 11:06:19 +0100172 RSL.send(ts_RSL_IPA_CRCX_ACK(g_chan_nr, 1, 1, 1, 1));
Harald Welte82d2b872017-12-16 23:36:23 +0100173 crcx_seen := true;
Harald Weltec1a2fff2017-12-17 11:06:19 +0100174 repeat;
175 }
Harald Welte82d2b872017-12-16 23:36:23 +0100176 [crcx_seen] RSL.receive(tr_RSL_IPA_MDCX(g_chan_nr, ?)) -> value rsl{
Harald Weltec1a2fff2017-12-17 11:06:19 +0100177 RSL.send(ts_RSL_IPA_MDCX_ACK(g_chan_nr, 1, 1, 1, 1));
178 repeat;
179 }
180 [exp_compl] BSSAP.receive(tr_BSSMAP_AssignmentComplete) {
181 setverdict(fail, "Received non-matching ASSIGNMENT COMPLETE");
182 }
183 [exp_compl] BSSAP.receive(tr_BSSMAP_AssignmentFail) {
184 setverdict(fail, "Received unexpected ASSIGNMENT FAIL");
185 }
186 [not exp_compl] BSSAP.receive(tr_BSSMAP_AssignmentComplete) {
187 setverdict(fail, "Received unexpected ASSIGNMENT COMPLETE");
188 }
189 [not exp_compl] BSSAP.receive(tr_BSSMAP_AssignmentFail) {
190 setverdict(fail, "Received non-matching ASSIGNMENT FAIL");
191 }
192 [] T.timeout {
193 setverdict(inconc, "Timeout waiting for ASSIGNMENT COMPLETE");
194 }
195 }
196
197 self.stop;
198}
199
200
Harald Welte28d943e2017-11-25 15:00:50 +0100201}