blob: 25b96cda34e27ea62212a96d45087d20d2994af3 [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;
5 import from BSSGP_Helper_Functions all;
6 import from IPL4asp_Types all;
7
8 type record BssgpStatusIndication {
9 Nsei nsei,
10 BssgpBvci bvci,
11 BvcState state
12 }
13
14 template BssgpStatusIndication t_BssgpStsInd(Nsei nsei, BssgpBvci bvci, BvcState state) := {
15 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 {
27 in BssgpPdu;
28 out BssgpPdu,
29 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,
39 BssgpPdu;
40 out BssgpPdu;
41 } 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
59 var BvcState g_ptp_bvc_state := BVC_S_BLOCKED;
60 timer g_T1 := 15.0;
61 timer g_T2 := 60.0;
62 }
63
64 modulepar {
65 Nsvci mp_nsei := 2342;
66 Nsvci mp_bvci := 2342;
67 BssgpCellId mp_cellid := { ra_id := { lai := { mcc_mnc := '234F04'H, lac := 200}, rac := 0 }, cell_id := 20960 };
68 };
69
70 function f_BnsUdReq(template BssgpPdu pdu) return NsUnitdataRequest {
71 var NsUnitdataRequest udr := {
72 bvci := mp_bvci,
73 nsei := mp_nsei,
74 /* for some weird reason we get "Dynamic test case error: Text encoder: Encoding an
75 * unbound integer value." when trying to send the reocrd rather than the octetstring */
76 //sdu := omit,
77 //bssgp := valueof(pdu)
78 sdu := f_BSSGP_compact_len(enc_BssgpPdu(valueof(pdu))),
79 bssgp := omit
80 }
81 return udr;
82 }
83
84 function f_BnsUdInd(template BssgpPdu pdu) return template NsUnitdataIndication {
85 var template NsUnitdataIndication udi := {
86 bvci := mp_bvci,
87 nsei := mp_nsei,
88 sdu := *,
89 bssgp := pdu
90 }
91 return udi;
92 }
93
94 private function f_change_state(BvcState new_state) runs on BSSGP_CT {
95 log("BSSGP State Transition: ", g_ptp_bvc_state, " -> ", new_state);
96 g_ptp_bvc_state := new_state;
97 BSSGP_SP.send(t_BssgpStsInd(mp_nsei, mp_bvci, g_ptp_bvc_state));
98 }
99
100 private function f_sendReset() runs on BSSGP_CT {
101 var BssgpPdu pdu := valueof(t_BVC_RESET(BSSGP_CAUSE_OM_INTERVENTION, mp_bvci, mp_cellid));
102 log("PDU: ", pdu);
103 log("ENC: ", enc_BssgpPdu(pdu));
104
105 BSCP.send(f_BnsUdReq(pdu));
106 g_T2.start;
107 //f_change_state(BVC_S_WAIT_RESET);
108 }
109
110 private function f_sendUnblock() runs on BSSGP_CT {
111 BSCP.send(f_BnsUdReq(t_BVC_UNBLOCK(mp_bvci)));
112 g_T1.start;
113 }
114
115 private function f_sendBlock(BssgpCause cause) runs on BSSGP_CT {
116 BSCP.send(f_BnsUdReq(t_BVC_BLOCK(mp_bvci, cause)));
117 g_T1.start;
118 }
119
120 altstep as_allstate() runs on BSSGP_CT {
121 var NsUnitdataIndication udi;
122 var NsStatusIndication nsi;
123 var ASP_Event evt;
124
125 /* Respond to BLOCK for wrong NSVCI */
126 [] BSCP.receive(f_BnsUdInd(t_BVC_BLOCK(?, ?))) -> value udi {
127 log("Rx BVC-BLOCK for unknown BVCI");
128 /* FIXME */
129 }
130
131 /* Respond to RESET with correct NSEI/NSVCI */
132 [] BSCP.receive(f_BnsUdInd(t_BVC_RESET(?, mp_bvci, mp_cellid))) -> value udi {
133 f_change_state(BVC_S_UNBLOCKED);
134 BSCP.send(f_BnsUdReq(t_BVC_RESET_ACK(mp_bvci, mp_cellid)));
135 }
136
137 /* Respond to RESET with wrong NSEI/NSVCI */
138 [] BSCP.receive(f_BnsUdInd(t_BVC_RESET(?, ?, ?))) -> value udi {
139 log("Rx BVC-RESET for unknown BVCI");
140 /* FIXME */
141 }
142
143 /* default case of handling unknown PDUs */
144 [] BSCP.receive(f_BnsUdInd(?)) -> value udi {
145 log("Rx Unexpected BSSGP PDU ", udi.bssgp," in state ", g_ptp_bvc_state);
146 BSCP.send(f_BnsUdReq(t_BSSGP_STATUS({
147 t_BSSGP_IE_Cause(BSSGP_CAUSE_PDU_NOT_COMPATIBLE_WITH_PROTOCOL_STATE),
148 t_BSSGP_IE_Bvci(mp_bvci), t_BSSGP_IE_PDU(udi.bssgp)})));
149 }
150 /* Forwarding of ASP_Event and NsStatusIndication to user */
151 [] BSCP.receive(ASP_Event:?) -> value evt { BSSGP_SP.send(evt); }
152 [] BSCP.receive(NsStatusIndication:?) -> value nsi {
153 /* if we just became NS-unblocked, send a BCC-RESET */
154 if (nsi.old_state != NSE_S_ALIVE_UNBLOCKED and nsi.new_state == NSE_S_ALIVE_UNBLOCKED) {
155 f_sendReset();
156 }
157 BSSGP_SP.send(nsi);
158 }
159 }
160
161 private function f_ScanEvents() runs on BSSGP_CT {
162 var NsUnitdataIndication udi;
163 var BssgpPdu bs_pdu;
164 var default d;
165
166 d := activate(as_allstate());
167
168 while (true) {
169 if (g_ptp_bvc_state == BVC_S_BLOCKED) {
170 alt {
171 [] g_T1.timeout {
172 f_sendUnblock();
173 }
174 [] BSCP.receive(f_BnsUdInd(t_BVC_UNBLOCK_ACK(mp_bvci))) {
175 g_T1.stop;
176 f_change_state(BVC_S_UNBLOCKED);
177 }
178 }
179 } else if (g_ptp_bvc_state == BVC_S_UNBLOCKED) {
180 alt {
181 /* bogus unblock, just respond with ACK */
182 [] BSCP.receive(f_BnsUdInd(t_BVC_UNBLOCK(mp_bvci))) -> value udi {
183 BSCP.send(f_BnsUdReq(t_BVC_UNBLOCK_ACK(mp_bvci)));
184 }
185 /* Respond to BLOCK with BLOCK-ACK + change state */
186 [] BSCP.receive(f_BnsUdInd(t_BVC_BLOCK(mp_bvci, ?))) -> value udi {
187 BSCP.send(f_BnsUdReq(t_BVC_BLOCK_ACK(mp_bvci)));
188 g_T1.stop;
189 f_change_state(BVC_S_BLOCKED);
190 }
191 [] g_T1.timeout {
192 f_sendBlock(BSSGP_CAUSE_OM_INTERVENTION);
193 }
194 [] BSCP.receive(f_BnsUdInd(t_BVC_BLOCK_ACK(mp_bvci))) -> value udi {
195 g_T1.stop;
196 f_change_state(BVC_S_BLOCKED);
197 }
198 [] BSCP.receive(f_BnsUdInd(t_BVC_RESET_ACK(mp_bvci, mp_cellid))) -> value udi {
199 g_T2.stop;
200 f_change_state(BVC_S_UNBLOCKED);
201 }
202 /* BSSGP-UNITDATA PDUs from network to NS-UNITDATA.ind to user */
203 [] BSCP.receive(f_BnsUdInd(tr_BSSGP_type(DL_UNITDATA))) -> value udi {
204 BSSGP_SP.send(udi.bssgp);
205 }
206 [] BSCP.receive(f_BnsUdInd(tr_BSSGP_type(UL_UNITDATA))) -> value udi {
207 BSSGP_SP.send(udi.bssgp);
208 }
209 /* pass virtually any PDU from user to NS-UNITDATA PDU on network */
210 [] BSSGP_SP.receive(BssgpPdu:?) -> value bs_pdu {
211 BSCP.send(f_BnsUdReq(bs_pdu));
212 }
213
214 }
215 }
216
217 } /* while */
218 //deactivate(d);
219 }
220}