blob: 70c9c80e3a70a25a777325130914b4c24c9df9b9 [file] [log] [blame]
Harald Welte1733a382017-07-23 17:26:17 +02001module BSSGP_Emulation {
2 import from NS_Types all;
3 import from NS_Emulation all;
4 import from BSSGP_Types all;
Harald Weltee0abc472018-02-05 09:13:31 +01005 import from Osmocom_Gb_Types all;
Harald Welte1733a382017-07-23 17:26:17 +02006 import from IPL4asp_Types all;
7
8 type record BssgpStatusIndication {
9 Nsei nsei,
10 BssgpBvci bvci,
11 BvcState state
12 }
13
Harald Welte13d391e2017-07-23 19:52:33 +020014 template BssgpStatusIndication t_BssgpStsInd(template Nsei nsei, template BssgpBvci bvci, template BvcState state) := {
Harald Welte1733a382017-07-23 17:26:17 +020015 nsei := nsei,
16 bvci := bvci,
17 state := state
18 }
19
20 type enumerated BvcState {
21 BVC_S_BLOCKED,
22 BVC_S_UNBLOCKED
23 };
24
25 /* port from our (internal) point of view */
26 type port BSSGP_SP_PT message {
Harald Weltee0abc472018-02-05 09:13:31 +010027 in PDU_BSSGP;
28 out PDU_BSSGP,
Harald Welte1733a382017-07-23 17:26:17 +020029 NsStatusIndication,
30 BssgpStatusIndication,
31 ASP_Event;
32 } with { extension "internal" };
33
34 /* port from the user point of view */
35 type port BSSGP_PT message {
36 in ASP_Event,
37 NsStatusIndication,
38 BssgpStatusIndication,
Harald Weltee0abc472018-02-05 09:13:31 +010039 PDU_BSSGP;
40 out PDU_BSSGP;
Harald Welte1733a382017-07-23 17:26:17 +020041 } with { extension "internal" };
42
43 function BssgpStart() runs on BSSGP_CT {
44 f_init();
45 f_ScanEvents();
46 }
47
48 private function f_init() runs on BSSGP_CT {
49 /* Connect the UDP socket */
50 f_change_state(BVC_S_BLOCKED);
51 }
52
53 type component BSSGP_CT {
54 /* UDP port towards the bottom (IUT) */
55 port NS_PT BSCP;
56 /* NS-User SAP towards the user */
57 port BSSGP_SP_PT BSSGP_SP;
58
Harald Welte13d391e2017-07-23 19:52:33 +020059 var boolean g_sgsn_role := true;
Harald Welte1733a382017-07-23 17:26:17 +020060 var BvcState g_ptp_bvc_state := BVC_S_BLOCKED;
61 timer g_T1 := 15.0;
62 timer g_T2 := 60.0;
63 }
64
65 modulepar {
Harald Welte13d391e2017-07-23 19:52:33 +020066 Nsvci mp_nsei := 96;
67 Nsvci mp_bvci := 196;
Harald Weltee0abc472018-02-05 09:13:31 +010068 BssgpCellId mp_cellid := { ra_id := { lai := { mcc_mnc := '26242F'H, lac := 13135}, rac := 0 }, cell_id := 20960 };
Harald Welte1733a382017-07-23 17:26:17 +020069 };
70
Harald Weltee0abc472018-02-05 09:13:31 +010071 function f_BnsUdReq(template PDU_BSSGP pdu, BssgpBvci bvci := mp_bvci) return NsUnitdataRequest {
Harald Welte1733a382017-07-23 17:26:17 +020072 var NsUnitdataRequest udr := {
Harald Welte13d391e2017-07-23 19:52:33 +020073 bvci := bvci,
Harald Welte1733a382017-07-23 17:26:17 +020074 nsei := mp_nsei,
75 /* for some weird reason we get "Dynamic test case error: Text encoder: Encoding an
76 * unbound integer value." when trying to send the reocrd rather than the octetstring */
77 //sdu := omit,
78 //bssgp := valueof(pdu)
Harald Weltee0abc472018-02-05 09:13:31 +010079 sdu := enc_PDU_BSSGP(valueof(pdu)),
Harald Welte1733a382017-07-23 17:26:17 +020080 bssgp := omit
81 }
82 return udr;
83 }
84
Harald Weltee0abc472018-02-05 09:13:31 +010085 function f_BnsUdInd(template PDU_BSSGP pdu, template BssgpBvci bvci := mp_bvci) return template NsUnitdataIndication {
Harald Welte1733a382017-07-23 17:26:17 +020086 var template NsUnitdataIndication udi := {
Harald Welte13d391e2017-07-23 19:52:33 +020087 bvci := bvci,
Harald Welte1733a382017-07-23 17:26:17 +020088 nsei := mp_nsei,
89 sdu := *,
90 bssgp := pdu
91 }
92 return udi;
93 }
94
95 private function f_change_state(BvcState new_state) runs on BSSGP_CT {
96 log("BSSGP State Transition: ", g_ptp_bvc_state, " -> ", new_state);
97 g_ptp_bvc_state := new_state;
98 BSSGP_SP.send(t_BssgpStsInd(mp_nsei, mp_bvci, g_ptp_bvc_state));
99 }
100
101 private function f_sendReset() runs on BSSGP_CT {
Harald Weltee0abc472018-02-05 09:13:31 +0100102 var PDU_BSSGP pdu := valueof(ts_BVC_RESET(BSSGP_CAUSE_OM_INTERVENTION, mp_bvci, mp_cellid));
Harald Welte1733a382017-07-23 17:26:17 +0200103 log("PDU: ", pdu);
Harald Weltee0abc472018-02-05 09:13:31 +0100104 log("ENC: ", enc_PDU_BSSGP(pdu));
Harald Welte1733a382017-07-23 17:26:17 +0200105
Harald Welte13d391e2017-07-23 19:52:33 +0200106 /* BVC-RESET is always sent via the SIGNALLING BVCI, see Table 5.4.1 */
107 BSCP.send(f_BnsUdReq(pdu, 0));
Harald Welte1733a382017-07-23 17:26:17 +0200108 g_T2.start;
109 //f_change_state(BVC_S_WAIT_RESET);
110 }
111
112 private function f_sendUnblock() runs on BSSGP_CT {
Harald Welte13d391e2017-07-23 19:52:33 +0200113 BSCP.send(f_BnsUdReq(t_BVC_UNBLOCK(mp_bvci), 0));
Harald Welte1733a382017-07-23 17:26:17 +0200114 g_T1.start;
115 }
116
117 private function f_sendBlock(BssgpCause cause) runs on BSSGP_CT {
Harald Welte13d391e2017-07-23 19:52:33 +0200118 BSCP.send(f_BnsUdReq(t_BVC_BLOCK(mp_bvci, cause), 0));
Harald Welte1733a382017-07-23 17:26:17 +0200119 g_T1.start;
120 }
121
Harald Weltee0abc472018-02-05 09:13:31 +0100122 private function f_sendStatus(BssgpCause cause, PDU_BSSGP pdu) runs on BSSGP_CT {
Harald Welte13d391e2017-07-23 19:52:33 +0200123 /* FIXME: Make sure correct Signaling or PTP BVCI is used! */
Harald Weltee0abc472018-02-05 09:13:31 +0100124 BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(mp_bvci, cause, pdu)));
Harald Welte13d391e2017-07-23 19:52:33 +0200125 }
126
Harald Welte1733a382017-07-23 17:26:17 +0200127 altstep as_allstate() runs on BSSGP_CT {
128 var NsUnitdataIndication udi;
129 var NsStatusIndication nsi;
130 var ASP_Event evt;
131
132 /* Respond to BLOCK for wrong NSVCI */
Harald Welte13d391e2017-07-23 19:52:33 +0200133 [] BSCP.receive(f_BnsUdInd(t_BVC_BLOCK(?, ?), 0)) -> value udi {
Harald Welte1733a382017-07-23 17:26:17 +0200134 log("Rx BVC-BLOCK for unknown BVCI");
Harald Welte13d391e2017-07-23 19:52:33 +0200135 f_sendStatus(BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp);
Harald Welte1733a382017-07-23 17:26:17 +0200136 }
137
Harald Welte13d391e2017-07-23 19:52:33 +0200138 /* Respond to RESET with correct BVCI/CellID */
Harald Weltee0abc472018-02-05 09:13:31 +0100139 [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, mp_bvci, mp_cellid), 0)) -> value udi {
Harald Welte13d391e2017-07-23 19:52:33 +0200140 log("Rx BVC-RESET for Our BVCI=", mp_bvci);
Harald Weltee0abc472018-02-05 09:13:31 +0100141 BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(mp_bvci, mp_cellid), 0));
Harald Welte1733a382017-07-23 17:26:17 +0200142 f_change_state(BVC_S_UNBLOCKED);
Harald Welte13d391e2017-07-23 19:52:33 +0200143 }
144
145 /* Respond to RESET for signalling BVCI 0 */
Harald Weltee0abc472018-02-05 09:13:31 +0100146 [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, 0, mp_cellid), 0)) -> value udi {
Harald Welte13d391e2017-07-23 19:52:33 +0200147 log("Rx BVC-RESET for Signaling BVCI=0");
Harald Weltee0abc472018-02-05 09:13:31 +0100148 BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(0, mp_cellid), 0));
Harald Welte1733a382017-07-23 17:26:17 +0200149 }
150
151 /* Respond to RESET with wrong NSEI/NSVCI */
Harald Weltee0abc472018-02-05 09:13:31 +0100152 [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, ?, ?), 0)) -> value udi {
Harald Welte1733a382017-07-23 17:26:17 +0200153 log("Rx BVC-RESET for unknown BVCI");
Harald Welte13d391e2017-07-23 19:52:33 +0200154 f_sendStatus(BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp);
Harald Welte1733a382017-07-23 17:26:17 +0200155 }
156
157 /* default case of handling unknown PDUs */
Harald Welte13d391e2017-07-23 19:52:33 +0200158 [] BSCP.receive(f_BnsUdInd(?, ?)) -> value udi {
Harald Welte1733a382017-07-23 17:26:17 +0200159 log("Rx Unexpected BSSGP PDU ", udi.bssgp," in state ", g_ptp_bvc_state);
Harald Welte13d391e2017-07-23 19:52:33 +0200160 f_sendStatus(BSSGP_CAUSE_PDU_NOT_COMPATIBLE_WITH_PROTOCOL_STATE, udi.bssgp);
Harald Welte1733a382017-07-23 17:26:17 +0200161 }
162 /* Forwarding of ASP_Event and NsStatusIndication to user */
163 [] BSCP.receive(ASP_Event:?) -> value evt { BSSGP_SP.send(evt); }
164 [] BSCP.receive(NsStatusIndication:?) -> value nsi {
165 /* if we just became NS-unblocked, send a BCC-RESET */
166 if (nsi.old_state != NSE_S_ALIVE_UNBLOCKED and nsi.new_state == NSE_S_ALIVE_UNBLOCKED) {
Harald Welte13d391e2017-07-23 19:52:33 +0200167 if (g_sgsn_role == false) {
168 f_sendReset();
169 }
170 /* Idea: We coudl send BVC-UNBLOCK here like some SGSN do */
Harald Welte1733a382017-07-23 17:26:17 +0200171 }
172 BSSGP_SP.send(nsi);
173 }
174 }
175
176 private function f_ScanEvents() runs on BSSGP_CT {
177 var NsUnitdataIndication udi;
Harald Weltee0abc472018-02-05 09:13:31 +0100178 var PDU_BSSGP bs_pdu;
Harald Welte1733a382017-07-23 17:26:17 +0200179 var default d;
180
Harald Welte13d391e2017-07-23 19:52:33 +0200181
Harald Weltee0abc472018-02-05 09:13:31 +0100182 log("matching against ", tr_BVC_RESET(?, mp_bvci, mp_cellid));
Harald Welte13d391e2017-07-23 19:52:33 +0200183
Harald Welte1733a382017-07-23 17:26:17 +0200184 d := activate(as_allstate());
185
186 while (true) {
187 if (g_ptp_bvc_state == BVC_S_BLOCKED) {
188 alt {
189 [] g_T1.timeout {
190 f_sendUnblock();
191 }
192 [] BSCP.receive(f_BnsUdInd(t_BVC_UNBLOCK_ACK(mp_bvci))) {
193 g_T1.stop;
194 f_change_state(BVC_S_UNBLOCKED);
195 }
196 }
197 } else if (g_ptp_bvc_state == BVC_S_UNBLOCKED) {
198 alt {
199 /* bogus unblock, just respond with ACK */
Harald Welte13d391e2017-07-23 19:52:33 +0200200 [] BSCP.receive(f_BnsUdInd(t_BVC_UNBLOCK(mp_bvci), 0)) -> value udi {
201 BSCP.send(f_BnsUdReq(t_BVC_UNBLOCK_ACK(mp_bvci), 0));
Harald Welte1733a382017-07-23 17:26:17 +0200202 }
203 /* Respond to BLOCK with BLOCK-ACK + change state */
Harald Welte13d391e2017-07-23 19:52:33 +0200204 [] BSCP.receive(f_BnsUdInd(t_BVC_BLOCK(mp_bvci, ?), 0)) -> value udi {
205 BSCP.send(f_BnsUdReq(t_BVC_BLOCK_ACK(mp_bvci), 0));
Harald Welte1733a382017-07-23 17:26:17 +0200206 g_T1.stop;
207 f_change_state(BVC_S_BLOCKED);
208 }
209 [] g_T1.timeout {
210 f_sendBlock(BSSGP_CAUSE_OM_INTERVENTION);
211 }
Harald Welte13d391e2017-07-23 19:52:33 +0200212 [] BSCP.receive(f_BnsUdInd(t_BVC_BLOCK_ACK(mp_bvci), 0)) -> value udi {
Harald Welte1733a382017-07-23 17:26:17 +0200213 g_T1.stop;
214 f_change_state(BVC_S_BLOCKED);
215 }
Harald Weltee0abc472018-02-05 09:13:31 +0100216 [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET_ACK(mp_bvci, mp_cellid), 0)) -> value udi {
Harald Welte1733a382017-07-23 17:26:17 +0200217 g_T2.stop;
218 f_change_state(BVC_S_UNBLOCKED);
219 }
Harald Welte13d391e2017-07-23 19:52:33 +0200220
221 /* simply acknowledge all Flow Control Messages */
Harald Weltee0abc472018-02-05 09:13:31 +0100222/*
Harald Welte13d391e2017-07-23 19:52:33 +0200223 [g_sgsn_role] BSCP.receive(f_BnsUdInd(t_BVC_FC_BVC)) {
224 BSCP.send(f_BnsUdReq(t_BVC_FC_BVC_ACK));
225 }
226 [g_sgsn_role] BSCP.receive(f_BnsUdInd(t_BVC_FC_MS)) {
227 BSCP.send(f_BnsUdReq(t_BVC_FC_MS_ACK));
228 }
Harald Weltee0abc472018-02-05 09:13:31 +0100229*/
Harald Welte13d391e2017-07-23 19:52:33 +0200230
Harald Welte1733a382017-07-23 17:26:17 +0200231 /* BSSGP-UNITDATA PDUs from network to NS-UNITDATA.ind to user */
Harald Weltee0abc472018-02-05 09:13:31 +0100232 [not g_sgsn_role] BSCP.receive(f_BnsUdInd(tr_BSSGP_DL_UD)) -> value udi {
Harald Welte1733a382017-07-23 17:26:17 +0200233 BSSGP_SP.send(udi.bssgp);
234 }
Harald Weltee0abc472018-02-05 09:13:31 +0100235 [g_sgsn_role] BSCP.receive(f_BnsUdInd(tr_BSSGP_UL_UD)) -> value udi {
Harald Welte1733a382017-07-23 17:26:17 +0200236 BSSGP_SP.send(udi.bssgp);
237 }
238 /* pass virtually any PDU from user to NS-UNITDATA PDU on network */
Harald Weltee0abc472018-02-05 09:13:31 +0100239 [] BSSGP_SP.receive(PDU_BSSGP:?) -> value bs_pdu {
Harald Welte1733a382017-07-23 17:26:17 +0200240 BSCP.send(f_BnsUdReq(bs_pdu));
241 }
242
243 }
244 }
245
246 } /* while */
247 //deactivate(d);
248 }
249}