blob: ca44a0258e0963c7985049e8317c6fdbcfdbfa98 [file] [log] [blame]
Harald Welte34b5a952019-05-27 11:54:11 +02001/* GPRS-NS Emulation in TTCN-3
Harald Weltebe7afce2021-01-17 22:04:36 +01002 * (C) 2018-2021 Harald Welte <laforge@gnumonks.org>
Harald Welte34b5a952019-05-27 11:54:11 +02003 * contributions by sysmocom - s.f.m.c. GmbH
4 * All rights reserved.
5 *
6 * Released under the terms of GNU General Public License, Version 2 or
7 * (at your option) any later version.
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
Harald Welte6fff3642017-07-22 21:36:13 +020012module NS_Emulation {
Harald Welte90f19742020-11-06 19:34:40 +010013 import from Misc_Helpers all;
Harald Welte6fff3642017-07-22 21:36:13 +020014 import from NS_Types all;
15 import from BSSGP_Types all;
Harald Welte867243a2020-09-13 18:32:32 +020016 import from Osmocom_Types all;
Harald Weltee0abc472018-02-05 09:13:31 +010017 import from Osmocom_Gb_Types all;
Harald Welte013d65a2020-09-13 14:41:31 +020018 import from NS_Provider_IPL4 all;
Harald Welte867243a2020-09-13 18:32:32 +020019#ifdef NS_EMULATION_FR
20 import from NS_Provider_FR all;
21#endif
Harald Welte6fff3642017-07-22 21:36:13 +020022 import from IPL4asp_Types all;
23
24 type record NsUnitdataRequest {
25 BssgpBvci bvci,
26 Nsei nsei,
Harald Weltec4505522020-11-11 18:55:09 +010027 integer lsp,
Harald Welte6e594f22017-07-23 16:19:35 +020028 octetstring sdu optional,
Harald Weltee0abc472018-02-05 09:13:31 +010029 PDU_BSSGP bssgp optional
Harald Welte6e594f22017-07-23 16:19:35 +020030 }
31
Harald Weltec4505522020-11-11 18:55:09 +010032 template NsUnitdataRequest tr_NsUdReq(template Nsei nsei, template BssgpBvci bvci, template integer lsp,
33 template octetstring sdu, template PDU_BSSGP bssgp) := {
Harald Welte90f19742020-11-06 19:34:40 +010034 bvci := bvci,
35 nsei := nsei,
Harald Weltec4505522020-11-11 18:55:09 +010036 lsp := lsp,
Harald Welte90f19742020-11-06 19:34:40 +010037 sdu := sdu,
38 bssgp := bssgp
39 }
40
41 template (value) NsUnitdataRequest ts_NsUdReq(template (value) Nsei nsei,
42 template (value) BssgpBvci bvci,
Harald Weltec4505522020-11-11 18:55:09 +010043 template (value) integer lsp,
Harald Welte90f19742020-11-06 19:34:40 +010044 template (omit) octetstring sdu,
45 template (omit) PDU_BSSGP bssgp) := {
Harald Welte6e594f22017-07-23 16:19:35 +020046 bvci := bvci,
47 nsei := nsei,
Harald Weltec4505522020-11-11 18:55:09 +010048 lsp := lsp,
Harald Welte6e594f22017-07-23 16:19:35 +020049 sdu := sdu,
50 bssgp := bssgp
Harald Welte6fff3642017-07-22 21:36:13 +020051 }
52
53 type record NsUnitdataIndication {
54 BssgpBvci bvci,
55 Nsei nsei,
Harald Welte80a249a2020-11-17 19:57:40 +010056 Nsvci nsvci,
Harald Welte6e594f22017-07-23 16:19:35 +020057 octetstring sdu optional,
Harald Weltee0abc472018-02-05 09:13:31 +010058 PDU_BSSGP bssgp optional
Harald Welte6e594f22017-07-23 16:19:35 +020059 }
60
Harald Welte90f19742020-11-06 19:34:40 +010061 template (present) NsUnitdataIndication tr_NsUdInd(template (present) Nsei nsei,
62 template (present) BssgpBvci bvci,
63 template octetstring sdu) := {
64 bvci := bvci,
65 nsei := nsei,
Harald Welte80a249a2020-11-17 19:57:40 +010066 nsvci := ?,
Harald Welte90f19742020-11-06 19:34:40 +010067 sdu := sdu,
68 bssgp := ?
69 }
70
Harald Welte80a249a2020-11-17 19:57:40 +010071 template (value) NsUnitdataIndication ts_NsUdInd(Nsei nsei, Nsvci nsvci, BssgpBvci bvci, octetstring sdu) := {
Harald Welte6e594f22017-07-23 16:19:35 +020072 bvci := bvci,
73 nsei := nsei,
Harald Welte80a249a2020-11-17 19:57:40 +010074 nsvci := nsvci,
Harald Welte6e594f22017-07-23 16:19:35 +020075 sdu := sdu,
Harald Weltee0abc472018-02-05 09:13:31 +010076 bssgp := dec_PDU_BSSGP(sdu)
Harald Welte6e594f22017-07-23 16:19:35 +020077 }
78
79 type record NsStatusIndication {
80 Nsei nsei,
81 Nsvci nsvci,
Harald Welte90f19742020-11-06 19:34:40 +010082 NsvcState old_state,
Harald Weltedc0a0902020-11-10 21:03:29 +010083 NsvcState new_state,
84 boolean first_or_last
Harald Welte6e594f22017-07-23 16:19:35 +020085 }
86
Harald Welte90f19742020-11-06 19:34:40 +010087 template (present) NsStatusIndication tr_NsStsInd(template (present) Nsei nsei := ?,
88 template (present) Nsvci nsvci := ?,
89 template (present) NsvcState old_state := ?,
Harald Weltedc0a0902020-11-10 21:03:29 +010090 template (present) NsvcState state := ?,
91 template (present) boolean first_or_last := ?) := {
Harald Welte6e594f22017-07-23 16:19:35 +020092 nsei := nsei,
93 nsvci := nsvci,
94 old_state := old_state,
Harald Weltedc0a0902020-11-10 21:03:29 +010095 new_state := state,
96 first_or_last := first_or_last
Harald Welte6fff3642017-07-22 21:36:13 +020097 }
98
Harald Welte90f19742020-11-06 19:34:40 +010099
Harald Weltedc0a0902020-11-10 21:03:29 +0100100 template (value) NsStatusIndication ts_NsStsInd(Nsei nsei, Nsvci nsvci, NsvcState old_state, NsvcState state,
101 boolean first_or_last := false) := {
Harald Welte90f19742020-11-06 19:34:40 +0100102 nsei := nsei,
103 nsvci := nsvci,
104 old_state := old_state,
Harald Weltedc0a0902020-11-10 21:03:29 +0100105 new_state := state,
106 first_or_last := first_or_last
Harald Welte90f19742020-11-06 19:34:40 +0100107 }
108
109 type enumerated NsvcState {
Harald Welte3f820892021-01-19 18:19:23 +0100110 NSVC_S_DISABLED, /* administratively disabled */
Harald Welte90f19742020-11-06 19:34:40 +0100111 NSVC_S_DEAD_BLOCKED,
112 NSVC_S_WAIT_RESET,
113 NSVC_S_ALIVE_BLOCKED,
114 NSVC_S_ALIVE_UNBLOCKED
Harald Welte6e594f22017-07-23 16:19:35 +0200115 }
Harald Welte6fff3642017-07-22 21:36:13 +0200116
117 /* port from our (internal) point of view */
118 type port NS_SP_PT message {
119 in NsUnitdataRequest;
120 out NsUnitdataIndication,
Harald Welte013d65a2020-09-13 14:41:31 +0200121 NsStatusIndication;
Harald Welte6fff3642017-07-22 21:36:13 +0200122 } with { extension "internal" };
123
124 /* port from the user point of view */
125 type port NS_PT message {
126 in ASP_Event,
Harald Welte6e594f22017-07-23 16:19:35 +0200127 NsStatusIndication,
Harald Welte6fff3642017-07-22 21:36:13 +0200128 NsUnitdataIndication;
129 out NsUnitdataRequest;
130 } with { extension "internal" };
131
Harald Welte3f820892021-01-19 18:19:23 +0100132 /* port from our (internal) point of view */
133 type port NS_CTRL_SP_PT message {
134 in NsDisableVcRequest,
135 NsEnableVcRequest;
136 } with { extension "internal" };
137
138 /* port from the user point of view */
139 type port NS_CTRL_PT message {
140 out NsEnableVcRequest,
141 NsDisableVcRequest;
142 } with { extension "internal" };
143
144 type record NsDisableVcRequest {
145 Nsvci nsvci
146 };
147 type record NsEnableVcRequest {
148 Nsvci nsvci
149 };
150
Harald Welte013d65a2020-09-13 14:41:31 +0200151 type component NS_Provider_CT {
152 /* upper port, facing to NS_Emulation:NSCP */
153 port NS_PROVIDER_PT NSE;
154 /* lower layer ports (UDP/IP, Frame Relay) are added in derived components */
155 };
156
Harald Weltebd612cd2020-09-14 09:42:28 +0200157 type enumerated NS_Provider_LinkStatus {
158 NS_PROV_LINK_STATUS_UP,
159 NS_PROV_LINK_STATUS_DOWN
160 };
161 type union NS_Provider_Evt {
162 NS_Provider_LinkStatus link_status
163 };
164
Harald Welte013d65a2020-09-13 14:41:31 +0200165 /* port between NS_Provider and NS_CT */
166 type port NS_PROVIDER_PT message {
Harald Weltebd612cd2020-09-14 09:42:28 +0200167 inout PDU_NS, NS_Provider_Evt;
Harald Welte013d65a2020-09-13 14:41:31 +0200168 } with { extension "internal" };
169
Harald Welte90f19742020-11-06 19:34:40 +0100170 type record NSVCConfigurationIP {
171 AddressFamily address_family,
172 PortNumber local_udp_port,
173 charstring local_ip,
174 PortNumber remote_udp_port,
Harald Weltebe7afce2021-01-17 22:04:36 +0100175 charstring remote_ip,
176 uint8_t data_weight,
177 uint8_t signalling_weight
Harald Welte90f19742020-11-06 19:34:40 +0100178 };
179 type record NSVCConfigurationFR {
180 charstring netdev, /* HDLC net-device for AF_PACKET socket */
181 integer dlci
182 };
183 type union NSVCConfigurationP {
184 NSVCConfigurationIP ip,
185 NSVCConfigurationFR fr
186 };
187 type record NSVCConfiguration {
188 NSVCConfigurationP provider,
189 Nsvci nsvci
190 };
191 type record of NSVCConfiguration NSVCConfigurations;
192 type record NSConfiguration {
193 Nsvci nsei,
194 boolean role_sgsn,
195 boolean handle_sns,
196 NSVCConfigurations nsvc
197 }
198
199 /***********************************************************************
200 * per NS-VCG component. Exists once per [peer of] NSE
201 ***********************************************************************/
202
Harald Welte6fff3642017-07-22 21:36:13 +0200203 type component NS_CT {
Harald Welte90f19742020-11-06 19:34:40 +0100204 /* NS-User SAP towards the user */
205 port NS_SP_PT NS_SP;
206
207 /* port towards the per-NSVC components */
Harald Welte1308dbb2021-01-18 18:19:38 +0100208 port NSint_PT NSVC;
Harald Welte90f19742020-11-06 19:34:40 +0100209
Harald Welte3f820892021-01-19 18:19:23 +0100210 /* control port, used to manipulate at runtime */
211 port NS_CTRL_SP_PT NS_CTRL;
212
Harald Welte90f19742020-11-06 19:34:40 +0100213 /* all of the NS configuration a user passes to us */
214 var NSConfiguration g_config;
215 var charstring g_id;
216
217 /* references to the per-NSVC components */
218 var NsvcTable g_nsvcs := {};
Harald Weltec4505522020-11-11 18:55:09 +0100219 /* list of indexes to g_nsvcs[] of currently unblocked NSVCs */
Harald Welteaaa0dfd2021-02-04 16:58:53 +0100220 var Osmocom_Types.ro_integer g_unblocked_nsvcs_sig := {};
221 var Osmocom_Types.ro_integer g_unblocked_nsvcs_data := {};
Harald Welte90f19742020-11-06 19:34:40 +0100222 };
223 type record NsvcTableEntry {
Harald Weltebe7afce2021-01-17 22:04:36 +0100224 NSVCConfiguration cfg,
Harald Welte90f19742020-11-06 19:34:40 +0100225 NSVC_CT vc_conn,
226 NsvcState state
227 };
228 type record of NsvcTableEntry NsvcTable;
229
Harald Welte1308dbb2021-01-18 18:19:38 +0100230 /* internal port from the NS-VC point of view */
231 type port NSint_SP_PT message {
232 in NsUnitdataRequest,
233 SnsRequest,
234 NsCtrlRequest;
235 out NsUnitdataIndication,
236 SnsIndication,
237 NsStatusIndication;
238 } with { extension "internal" };
239
240 /* internal port from the NS-VCG point of view */
241 type port NSint_PT message {
242 in ASP_Event,
243 NsStatusIndication,
244 SnsIndication,
245 NsUnitdataIndication;
246 out NsUnitdataRequest,
247 SnsRequest,
248 NsCtrlRequest;
249 } with { extension "internal" };
250
251 /* Used by NS-VC to report reception of a SNS PDU to NS-VCG */
252 type record SnsIndication {
253 Nsvci nsvci,
254 PDU_NS ns
255 };
256
257 /* Used by NS-VCG to request transmission of a SNS PDU via a NS-VC */
258 type record SnsRequest {
259 Nsvci nsvci,
260 PDU_NS ns
261 };
262
263 type enumerated NsCtrlRequest {
Harald Welte3f820892021-01-19 18:19:23 +0100264 StartAliveProcedure (0),
265 DisableReq (1), /* administratively disable NS-VC */
266 EnableReq (2) /* administratively enable NS-VC */
Harald Welte1308dbb2021-01-18 18:19:38 +0100267 };
268
Harald Welte90f19742020-11-06 19:34:40 +0100269 /* add one NSVC (component and table entry */
270 function f_nsvc_add(NSVCConfiguration nsvc_cfg) runs on NS_CT {
271 var charstring nsvc_id := g_id & "-NSVCI" & int2str(nsvc_cfg.nsvci);
272 var NsvcTableEntry te;
273
Harald Weltebe7afce2021-01-17 22:04:36 +0100274 te.cfg := nsvc_cfg;
Harald Welte90f19742020-11-06 19:34:40 +0100275 te.vc_conn := NSVC_CT.create(nsvc_id);
276 te.state := NSVC_S_DEAD_BLOCKED;
277
278 connect(self:NSVC, te.vc_conn:NS_SP);
279 te.vc_conn.start(NSVCStart(nsvc_cfg, g_config, nsvc_id));
280
281 g_nsvcs := g_nsvcs & { te };
Harald Weltec4505522020-11-11 18:55:09 +0100282 /* no need to add to g_unblocked_nsvcs, as state is always DEAD_BLOCKED above */
Harald Welte90f19742020-11-06 19:34:40 +0100283 }
284
285 function f_nsvc_find_idx(Nsvci nsvci) runs on NS_CT return integer {
286 var integer i;
287 for (i := 0; i < lengthof(g_nsvcs); i := i+1) {
Harald Weltebe7afce2021-01-17 22:04:36 +0100288 if (g_nsvcs[i].cfg.nsvci == nsvci) {
Harald Welte90f19742020-11-06 19:34:40 +0100289 return i;
290 }
291 }
292 return -1;
293 }
294
295 function f_nsvc_find(Nsvci nsvci) runs on NS_CT return NSVC_CT {
296 var integer i := f_nsvc_find_idx(nsvci);
297 if (i < 0) {
298 return null;
299 } else {
300 return g_nsvcs[i].vc_conn;
301 }
302 }
303
304 function f_nsvc_update_state(Nsvci nsvci, NsvcState state) runs on NS_CT {
305 var integer i := f_nsvc_find_idx(nsvci);
306 if (i < 0) {
307 return;
308 }
Harald Weltec4505522020-11-11 18:55:09 +0100309 if (g_nsvcs[i].state != NSVC_S_ALIVE_UNBLOCKED and state == NSVC_S_ALIVE_UNBLOCKED) {
310 /* add index to list of unblocked NSVCs */
Harald Weltebe7afce2021-01-17 22:04:36 +0100311 if (not ischosen(g_nsvcs[i].cfg.provider.ip) or
312 g_nsvcs[i].cfg.provider.ip.signalling_weight > 0) {
313 g_unblocked_nsvcs_sig := g_unblocked_nsvcs_sig & {i};
314 }
315 if (not ischosen(g_nsvcs[i].cfg.provider.ip) or
316 g_nsvcs[i].cfg.provider.ip.data_weight > 0) {
317 g_unblocked_nsvcs_data := g_unblocked_nsvcs_data & {i};
318 }
Harald Weltec4505522020-11-11 18:55:09 +0100319 } else if (g_nsvcs[i].state == NSVC_S_ALIVE_UNBLOCKED and state != NSVC_S_ALIVE_UNBLOCKED) {
320 /* remove index to list of unblocked NSVCs */
Harald Welteaaa0dfd2021-02-04 16:58:53 +0100321 var Osmocom_Types.ro_integer new_unblocked_nsvcs_sig := {};
Harald Weltebe7afce2021-01-17 22:04:36 +0100322 for (var integer j := 0; j < lengthof(g_unblocked_nsvcs_sig); j := j+1) {
323 if (g_unblocked_nsvcs_sig[j] != i) {
324 new_unblocked_nsvcs_sig := new_unblocked_nsvcs_sig & {j};
Harald Weltec4505522020-11-11 18:55:09 +0100325 }
326 }
Harald Weltebe7afce2021-01-17 22:04:36 +0100327 g_unblocked_nsvcs_sig := new_unblocked_nsvcs_sig;
328
Harald Welteaaa0dfd2021-02-04 16:58:53 +0100329 var Osmocom_Types.ro_integer new_unblocked_nsvcs_data := {};
Harald Weltebe7afce2021-01-17 22:04:36 +0100330 for (var integer j := 0; j < lengthof(g_unblocked_nsvcs_data); j := j+1) {
331 if (g_unblocked_nsvcs_data[j] != i) {
332 new_unblocked_nsvcs_data := new_unblocked_nsvcs_data & {j};
333 }
334 }
335 g_unblocked_nsvcs_data := new_unblocked_nsvcs_data;
336
Harald Weltec4505522020-11-11 18:55:09 +0100337 }
Harald Welte90f19742020-11-06 19:34:40 +0100338 g_nsvcs[i].state := state;
339 }
340
341 function NSStart(NSConfiguration init_config, charstring id := testcasename()) runs on NS_CT {
342 g_config := init_config;
343 g_id := id;
344
345 /* iterate over list of NS-VCs and start per-NSVC components */
346 for (var integer i := 0; i < lengthof(g_config.nsvc); i := i+1) {
347 var NSVCConfiguration nsvc_cfg := g_config.nsvc[i];
348 f_nsvc_add(nsvc_cfg);
349 }
350
351 while (true) {
352 alt {
353 [] as_ns_common() {}
354 }
355 }
356 }
357
Harald Weltedc0a0902020-11-10 21:03:29 +0100358 function f_count_nsvcs_in_state(template NsvcState state := ?) runs on NS_CT return integer {
359 var integer i;
360 var integer res := 0;
361 for (i := 0; i < lengthof(g_nsvcs); i := i+1) {
362 if (match(g_nsvcs[i].state, state)) {
363 res := res + 1;
364 }
365 }
366 return res;
367 }
368
Harald Welte90f19742020-11-06 19:34:40 +0100369 private altstep as_ns_common() runs on NS_CT {
370 var NsStatusIndication rx_nssi;
371 var NsUnitdataIndication rx_nsudi;
372 var NsUnitdataRequest rx_nsudr;
Harald Welte3f820892021-01-19 18:19:23 +0100373 var NsDisableVcRequest rx_disar;
374 var NsEnableVcRequest rx_enar;
Harald Welte90f19742020-11-06 19:34:40 +0100375 /* pass from NS-VCs up to user */
Harald Weltedc0a0902020-11-10 21:03:29 +0100376 [] NSVC.receive(tr_NsStsInd(g_config.nsei, ?, ?, NSVC_S_ALIVE_UNBLOCKED)) -> value rx_nssi {
377 /* check if this one is the first to be unblocked */
378 var integer num_nsvc_unblocked := f_count_nsvcs_in_state(NSVC_S_ALIVE_UNBLOCKED);
379 f_nsvc_update_state(rx_nssi.nsvci, rx_nssi.new_state);
380 if (num_nsvc_unblocked == 0) {
381 rx_nssi.first_or_last := true;
382 }
383 NS_SP.send(rx_nssi);
384 }
385 [] NSVC.receive(tr_NsStsInd(g_config.nsei, ?, ?, NSVC_S_DEAD_BLOCKED)) -> value rx_nssi {
386 f_nsvc_update_state(rx_nssi.nsvci, rx_nssi.new_state);
387 /* check if this one is the last to be blocked */
388 var integer num_nsvc_unblocked := f_count_nsvcs_in_state(NSVC_S_ALIVE_UNBLOCKED);
389 if (num_nsvc_unblocked == 0) {
390 rx_nssi.first_or_last := true;
391 }
392 NS_SP.send(rx_nssi);
393 }
394 [] NSVC.receive(tr_NsStsInd(g_config.nsei, ?, ?, ?)) -> value rx_nssi {
Harald Welte90f19742020-11-06 19:34:40 +0100395 f_nsvc_update_state(rx_nssi.nsvci, rx_nssi.new_state);
396 NS_SP.send(rx_nssi);
397 }
398 [] NSVC.receive(tr_NsStsInd) -> value rx_nssi {
399 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
400 log2str("Received NsStatusInd for invalid NSEI: ", rx_nssi));
401 }
402 [] NSVC.receive(tr_NsUdInd(g_config.nsei, ?, ?)) -> value rx_nsudi {
403 NS_SP.send(rx_nsudi);
404 }
Harald Welte1308dbb2021-01-18 18:19:38 +0100405
406 [g_config.handle_sns and g_config.role_sgsn] as_vcg_sns_sgsn();
407
Harald Welte90f19742020-11-06 19:34:40 +0100408 [] NSVC.receive(tr_NsUdInd(?, ?, ?)) -> value rx_nsudi {
409 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
410 log2str("Received UnitDataInd for invalid NSEI: ", rx_nsudi));
411 }
412 /* from user down to NS-VC */
Harald Welte3f820892021-01-19 18:19:23 +0100413 [] NS_CTRL.receive(NsDisableVcRequest:?) -> value rx_disar {
414 var integer nsvc_idx := f_nsvc_find_idx(rx_disar.nsvci);
415 NSVC.send(NsCtrlRequest:DisableReq) to g_nsvcs[nsvc_idx].vc_conn;
416 }
417 [] NS_CTRL.receive(NsEnableVcRequest:?) -> value rx_enar {
418 var integer nsvc_idx := f_nsvc_find_idx(rx_enar.nsvci);
419 NSVC.send(NsCtrlRequest:EnableReq) to g_nsvcs[nsvc_idx].vc_conn;
420 }
Harald Weltebe7afce2021-01-17 22:04:36 +0100421 [] NS_SP.receive(tr_NsUdReq(g_config.nsei, 0, ?, ?, *)) -> value rx_nsudr {
Harald Weltec4505522020-11-11 18:55:09 +0100422 /* load distribution function */
Harald Weltebe7afce2021-01-17 22:04:36 +0100423 var integer nsvc_idx := g_unblocked_nsvcs_sig[rx_nsudr.lsp mod lengthof(g_unblocked_nsvcs_sig)];
Harald Weltec4505522020-11-11 18:55:09 +0100424 NSVC.send(rx_nsudr) to g_nsvcs[nsvc_idx].vc_conn;
Harald Welte90f19742020-11-06 19:34:40 +0100425 }
Harald Weltebe7afce2021-01-17 22:04:36 +0100426 [] NS_SP.receive(tr_NsUdReq(g_config.nsei, ?, ?, ?, *)) -> value rx_nsudr {
427 /* load distribution function */
428 var integer nsvc_idx := g_unblocked_nsvcs_data[rx_nsudr.lsp mod lengthof(g_unblocked_nsvcs_data)];
429 NSVC.send(rx_nsudr) to g_nsvcs[nsvc_idx].vc_conn;
430 }
431
Harald Weltec4505522020-11-11 18:55:09 +0100432 [] NS_SP.receive(tr_NsUdReq(?, ?, ?, ?, *)) -> value rx_nsudr {
Harald Welte90f19742020-11-06 19:34:40 +0100433 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
434 log2str("Received NsUnitdataReq for invalid NSEI: ", rx_nsudr));
435 }
436 }
437
Harald Welte1308dbb2021-01-18 18:19:38 +0100438 /* generate a list of v4 + v6 endpoints based on the NSVConfigurations. This is not strictly
439 * accurate, as we should create a list of _endpoints_, while we actually create a list of
440 * NSVCs. Those are only identical as long as our peer only implements one endpoint */
441 private function gen_sns_ip_elems(out template (omit) IP4_Elements v4_out,
442 out template (omit) IP6_Elements v6_out) runs on NS_CT {
443 var integer i;
444 var IP4_Elements v4 := {};
445 var IP6_Elements v6 := {};
446
447 for (i := 0; i < lengthof(g_config.nsvc); i := i + 1) {
448 var NSVCConfiguration nsvc_cfg := g_config.nsvc[i];
449 if (not ischosen(nsvc_cfg.provider.ip)) {
450 continue;
451 }
452 if (nsvc_cfg.provider.ip.address_family == AF_INET) {
453 v4 := v4 & { valueof(ts_SNS_IPv4(nsvc_cfg.provider.ip.local_ip,
Harald Weltebe7afce2021-01-17 22:04:36 +0100454 nsvc_cfg.provider.ip.local_udp_port,
455 nsvc_cfg.provider.ip.signalling_weight,
456 nsvc_cfg.provider.ip.data_weight)) };
Harald Welte1308dbb2021-01-18 18:19:38 +0100457 } else if (nsvc_cfg.provider.ip.address_family == AF_INET6) {
458 v6 := v6 & { valueof(ts_SNS_IPv6(nsvc_cfg.provider.ip.local_ip,
Harald Weltebe7afce2021-01-17 22:04:36 +0100459 nsvc_cfg.provider.ip.local_udp_port,
460 nsvc_cfg.provider.ip.signalling_weight,
461 nsvc_cfg.provider.ip.data_weight)) };
Harald Welte1308dbb2021-01-18 18:19:38 +0100462 }
463 }
464
465 /* we must not return empty lists, but 'omit' as otherwise we get wrong SNS IEs */
466 if (lengthof(v4) == 0) {
467 v4_out := omit;
468 } else {
469 v4_out := v4;
470 }
471 if (lengthof(v6) == 0) {
472 v6_out := omit;
473 } else {
474 v6_out := v6;
475 }
476 }
477
478 /* simple IP Sub-Network Service responder for the SGSN side. This is not a full implementation
479 * of the protocol, merely sufficient to make the PCU/BSS side happy to proceed */
480 private altstep as_vcg_sns_sgsn() runs on NS_CT {
481 var SnsIndication sind;
482 var NSVC_CT vc;
483 [] NSVC.receive(SnsIndication:{?, tr_SNS_SIZE(g_config.nsei)}) -> value sind sender vc {
484 /* blindly acknowledge whatever the PCU sends */
485 NSVC.send(SnsRequest:{sind.nsvci, ts_SNS_SIZE_ACK(g_config.nsei, omit)}) to vc;
486 }
487 /* FIXME: We assume our peer has only one endpoint */
488 [] NSVC.receive(SnsIndication:{?, tr_SNS_CONFIG(g_config.nsei, true,
489 {tr_SNS_IPv4(g_config.nsvc[0].provider.ip.remote_ip,
490 g_config.nsvc[0].provider.ip.remote_udp_port)})})
491 -> value sind sender vc {
492 /* blindly acknowledge whatever the PCU sends */
493 NSVC.send(SnsRequest:{sind.nsvci, ts_SNS_CONFIG_ACK(g_config.nsei, omit)}) to vc;
494 /* send a SNS-CONFIG in response and expect a SNS-CONFIG-ACK */
495 var template (omit) IP4_Elements v4;
496 var template (omit) IP6_Elements v6;
497 gen_sns_ip_elems(v4, v6);
498 NSVC.send(SnsRequest:{sind.nsvci,
499 ts_SNS_CONFIG(g_config.nsei, true, v4, v6)}) to vc;
500 alt {
501 [] NSVC.receive(SnsIndication:{sind.nsvci,
502 tr_SNS_CONFIG_ACK(g_config.nsei, omit)}) from vc {
503 /* success */
504 log("SNS Config succeeded. Sending Alive");
505 /* inform all NS-VC that they are now considered alive */
506 for (var integer i := 0; i < lengthof(g_nsvcs); i := i+1) {
507 NSVC.send(NsCtrlRequest:StartAliveProcedure) to g_nsvcs[i].vc_conn;
508 }
509 }
510 [] NSVC.receive(SnsIndication:{sind.nsvci,
511 tr_SNS_CONFIG_ACK(g_config.nsei, ?)}) from vc {
512 setverdict(fail, "Unexpected SNS-CONFIG-NACK");
513 self.stop;
514 }
515 }
516 }
517 [] NSVC.receive(SnsIndication:{?, tr_SNS_CONFIG(g_config.nsei, false, ?)}) { /* ignore */}
518 [] NSVC.receive(SnsIndication:{?, tr_SNS_CONFIG(g_config.nsei, true, ?)}) {
519 setverdict(fail, "Unexpected SNS-CONFIG content");
520 self.stop;
521 }
522 [] NSVC.receive(SnsIndication:{?, tr_SNS_CONFIG(?, ?, ?)}) {
523 setverdict(fail, "SNS-CONFIG from unexpected NSEI");
524 self.stop;
525 }
526 }
527
Harald Welte90f19742020-11-06 19:34:40 +0100528 /***********************************************************************
529 per-NSVC component. Exists once for each NS-VC in the NS-VCG
530 ***********************************************************************/
531
532 type component NSVC_CT {
Harald Welte6fff3642017-07-22 21:36:13 +0200533 /* UDP port towards the bottom (IUT) */
Harald Welte013d65a2020-09-13 14:41:31 +0200534 port NS_PROVIDER_PT NSCP;
535 var NS_Provider_IPL4_CT vc_NSP_IP;
Harald Welte867243a2020-09-13 18:32:32 +0200536#ifdef NS_EMULATION_FR
537 var NS_Provider_FR_CT vc_NSP_FR;
538#endif
Harald Welte013d65a2020-09-13 14:41:31 +0200539
Harald Welte90f19742020-11-06 19:34:40 +0100540 /* port towards the NS_CT */
Harald Welte1308dbb2021-01-18 18:19:38 +0100541 port NSint_SP_PT NS_SP;
Harald Welte6fff3642017-07-22 21:36:13 +0200542
Harald Welte90f19742020-11-06 19:34:40 +0100543 /* configuration passed by the user */
544 var NSVCConfiguration g_nsvc_config;
545 /* we cannot access the NS_CT.config and hence need to copy those */
546 var NSConfiguration g_config;
Alexander Couzens2c12b242018-07-31 00:30:11 +0200547
Harald Welte90f19742020-11-06 19:34:40 +0100548 var NsvcState vc_state := NSVC_S_DEAD_BLOCKED;
Harald Welte6e594f22017-07-23 16:19:35 +0200549
550 timer Tns_alive := 3.0;
551 timer Tns_test := 10.0;
552 timer Tns_block := 10.0;
Harald Welte3dd83552020-09-14 11:38:01 +0200553 timer Tns_reset := 10.0;
Harald Welte6fff3642017-07-22 21:36:13 +0200554 }
555
Harald Welte90f19742020-11-06 19:34:40 +0100556 function NSVCStart(NSVCConfiguration init_config, NSConfiguration init_g_config, charstring id := testcasename()) runs on NSVC_CT {
557 g_nsvc_config := init_config;
558 g_config := init_g_config;
559 f_init(id & "-NSVCemu" & int2str(g_nsvc_config.nsvci));
560 f_ScanEvents();
Alexander Couzens2c12b242018-07-31 00:30:11 +0200561 }
Harald Welte6fff3642017-07-22 21:36:13 +0200562
Harald Welte90f19742020-11-06 19:34:40 +0100563 private function f_init(charstring id) runs on NSVC_CT {
Harald Welte90f19742020-11-06 19:34:40 +0100564 if (ischosen(g_nsvc_config.provider.ip)) {
565 /* Connect the UDP socket */
566 vc_NSP_IP := NS_Provider_IPL4_CT.create(id & "-provIP");
567 connect(self:NSCP, vc_NSP_IP:NSE);
568 vc_NSP_IP.start(NS_Provider_IPL4.main(g_nsvc_config, g_config, id));
569#ifdef NS_EMULATION_FR
570 } else if (ischosen(g_nsvc_config.provider.fr)) {
571 vc_NSP_FR := NS_Provider_FR_CT.create(id & "-provFR");
572 connect(self:NSCP, vc_NSP_FR:NSE);
573 vc_NSP_FR.start(NS_Provider_FR.main(g_nsvc_config, g_config, id));
574#endif
Harald Weltee15299a2020-11-17 17:30:09 +0100575 } else {
576 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unsupported NS provider");
Harald Welte90f19742020-11-06 19:34:40 +0100577 }
578
579 f_change_state(NSVC_S_DEAD_BLOCKED);
Harald Welte6fff3642017-07-22 21:36:13 +0200580 }
581
Harald Welte90f19742020-11-06 19:34:40 +0100582 private function f_change_state(NsvcState new_state) runs on NSVC_CT {
583 var NsvcState old_state := vc_state;
584 vc_state := new_state;
585 log("NSVC ", g_nsvc_config.nsvci, " State Transition: ", old_state, " -> ", new_state);
586 NS_SP.send(ts_NsStsInd(g_config.nsei, g_nsvc_config.nsvci, old_state, new_state));
587 }
588
589 private function f_sendReset() runs on NSVC_CT {
590 NSCP.send(ts_NS_RESET(NS_CAUSE_OM_INTERVENTION, g_nsvc_config.nsvci, g_config.nsei));
Harald Welte3dd83552020-09-14 11:38:01 +0200591 Tns_reset.start;
Harald Welte90f19742020-11-06 19:34:40 +0100592 vc_state := NSVC_S_WAIT_RESET;
Harald Welte6fff3642017-07-22 21:36:13 +0200593 }
594
Harald Welte90f19742020-11-06 19:34:40 +0100595 private function f_sendAlive() runs on NSVC_CT {
Harald Welte013d65a2020-09-13 14:41:31 +0200596 NSCP.send(t_NS_ALIVE);
Harald Welte6e594f22017-07-23 16:19:35 +0200597 Tns_alive.start;
598 }
599
Harald Welte90f19742020-11-06 19:34:40 +0100600 private function f_sendUnblock() runs on NSVC_CT {
Harald Welte013d65a2020-09-13 14:41:31 +0200601 NSCP.send(t_NS_UNBLOCK);
Harald Welte6e594f22017-07-23 16:19:35 +0200602 Tns_block.start;
603 }
604
Harald Welte90f19742020-11-06 19:34:40 +0100605 private function f_sendBlock(NsCause cause) runs on NSVC_CT {
606 NSCP.send(ts_NS_BLOCK(cause, g_nsvc_config.nsvci));
Harald Welte6e594f22017-07-23 16:19:35 +0200607 Tns_block.start;
608 }
609
Harald Welte90f19742020-11-06 19:34:40 +0100610 private altstep as_allstate() runs on NSVC_CT {
Harald Welte013d65a2020-09-13 14:41:31 +0200611 var PDU_NS rf;
Harald Welte6e594f22017-07-23 16:19:35 +0200612 var ASP_Event evt;
613
Harald Weltec0c67ff2021-02-03 19:26:30 +0100614 [] NSCP.receive(NS_Provider_Evt:{link_status:=NS_PROV_LINK_STATUS_DOWN}) {
615 log("Provider Link went down");
616 Tns_test.stop;
617 Tns_alive.stop;
618 f_change_state(NSVC_S_DEAD_BLOCKED);
619 }
620
Harald Welte3f820892021-01-19 18:19:23 +0100621 [] NS_SP.receive(NsCtrlRequest:DisableReq) {
622 /* To make NS-VCG remove us from list of active NS-VC */
623 f_change_state(NSVC_S_DEAD_BLOCKED);
624 log("Disabling NSVC on user request");
625 f_change_state(NSVC_S_DISABLED);
626 Tns_test.stop;
627 Tns_alive.stop;
628 }
629
Harald Welte6e594f22017-07-23 16:19:35 +0200630 /* transition to DEAD if t_alive times out */
Harald Welte9a7c5122020-09-14 11:35:57 +0200631 [] Tns_alive.timeout {
632 log("Tns-alive expired: changing to DEAD_BLOCKED + starting Tns-test");
Harald Welte90f19742020-11-06 19:34:40 +0100633 f_change_state(NSVC_S_DEAD_BLOCKED);
Harald Welte6e594f22017-07-23 16:19:35 +0200634 Tns_test.start;
Harald Welte6fff3642017-07-22 21:36:13 +0200635 }
Harald Welte6fff3642017-07-22 21:36:13 +0200636
Harald Welte9a7c5122020-09-14 11:35:57 +0200637 [] Tns_test.timeout {
Harald Welte6e594f22017-07-23 16:19:35 +0200638 log("Tns-test expired: sending NS-ALIVE");
639 f_sendAlive();
Harald Welte6fff3642017-07-22 21:36:13 +0200640 }
Harald Welte6fff3642017-07-22 21:36:13 +0200641
Harald Welte6e594f22017-07-23 16:19:35 +0200642 /* Stop t_alive when receiving ALIVE-ACK */
Harald Welte9a7c5122020-09-14 11:35:57 +0200643 [Tns_alive.running] NSCP.receive(t_NS_ALIVE_ACK) {
Daniel Willmann654f85e2020-10-12 18:10:06 +0200644 log("Rx NS-ALIVE-ACK: stopping Tns-alive; starting Tns-test");
Harald Welte6e594f22017-07-23 16:19:35 +0200645 Tns_alive.stop;
646 Tns_test.start;
647 }
Harald Welte6fff3642017-07-22 21:36:13 +0200648
Harald Welte6e594f22017-07-23 16:19:35 +0200649 /* respond to NS-ALIVE with NS-ALIVE-ACK */
Harald Welte013d65a2020-09-13 14:41:31 +0200650 [] NSCP.receive(t_NS_ALIVE) {
651 NSCP.send(t_NS_ALIVE_ACK);
Harald Welte6e594f22017-07-23 16:19:35 +0200652 }
653
654 /* Respond to BLOCK for wrong NSVCI */
Harald Welte013d65a2020-09-13 14:41:31 +0200655 [] NSCP.receive(tr_NS_BLOCK(?, ?)) -> value rf {
Harald Welte6e594f22017-07-23 16:19:35 +0200656 log("Rx NS-BLOCK for unknown NSVCI");
657 /* FIXME */
658 }
659
Harald Welte90f19742020-11-06 19:34:40 +0100660 [not g_config.handle_sns] as_handle_reset();
Harald Welte6e594f22017-07-23 16:19:35 +0200661
Harald Welte1308dbb2021-01-18 18:19:38 +0100662 [g_config.handle_sns and ischosen(g_nsvc_config.provider.ip)] as_nsvc_sns();
Harald Welte5e514fa2018-07-05 00:01:45 +0200663
Harald Welte4998a092021-02-04 14:30:47 +0100664 /* log + ignore NS-STATUS; must not create another NS-STATUS in response */
665 [] NSCP.receive(tr_NS_STATUS(?)) -> value rf {
666 log("Rx NS-STATUS ", rf," in state ", vc_state);
667 }
Harald Welte6e594f22017-07-23 16:19:35 +0200668 /* default case of handling unknown PDUs */
Harald Welte013d65a2020-09-13 14:41:31 +0200669 [] NSCP.receive(PDU_NS: ?) -> value rf {
Harald Welte90f19742020-11-06 19:34:40 +0100670 log("Rx Unexpected NS PDU ", rf," in state ", vc_state);
Harald Welte013d65a2020-09-13 14:41:31 +0200671 NSCP.send(ts_NS_STATUS(NS_CAUSE_PDU_NOT_COMPATIBLE_WITH_PROTOCOL_STATE, rf));
Harald Welte6e594f22017-07-23 16:19:35 +0200672 }
Harald Welte6fff3642017-07-22 21:36:13 +0200673 }
674
Harald Welte3f820892021-01-19 18:19:23 +0100675 private altstep as_disabled() runs on NSVC_CT {
676 [g_config.handle_sns == true] NS_SP.receive(NsCtrlRequest:EnableReq) {
677 f_change_state(NSVC_S_ALIVE_UNBLOCKED);
678 f_sendAlive();
679 Tns_test.start;
680 }
681 [g_config.handle_sns == false] NS_SP.receive(NsCtrlRequest:EnableReq) {
682 f_change_state(NSVC_S_DEAD_BLOCKED);
683 Tns_test.start;
684 }
685 /* drop any received messages while in this state */
686 [] NSCP.receive {
687 log("Dropping inbound NS mesage as NS-VC is disabled");
688 }
689 [] NS_SP.receive {
690 log("Dropping user primitive as NS-VC is disabled");
691 }
692 }
693
Harald Welte90f19742020-11-06 19:34:40 +0100694 private altstep as_handle_reset() runs on NSVC_CT {
Daniel Willmann654f85e2020-10-12 18:10:06 +0200695 var PDU_NS rf;
696
Harald Welte90f19742020-11-06 19:34:40 +0100697 [g_config.role_sgsn] NSCP.receive(NS_Provider_Evt:{link_status:=NS_PROV_LINK_STATUS_UP}) {
Daniel Willmann654f85e2020-10-12 18:10:06 +0200698 log("Provider Link came up: waiting for NS-RESET");
699 }
700
Harald Welte90f19742020-11-06 19:34:40 +0100701 [not g_config.role_sgsn] NSCP.receive(NS_Provider_Evt:{link_status:=NS_PROV_LINK_STATUS_UP}) {
Daniel Willmann654f85e2020-10-12 18:10:06 +0200702 log("Provider Link came up: sending NS-RESET");
703 f_sendReset();
704 }
705
706 /* Respond to RESET with correct NSEI/NSVCI */
Harald Welte90f19742020-11-06 19:34:40 +0100707 [] NSCP.receive(tr_NS_RESET(?, g_nsvc_config.nsvci, g_config.nsei)) -> value rf {
708 f_change_state(NSVC_S_ALIVE_BLOCKED);
709 NSCP.send(ts_NS_RESET_ACK(g_nsvc_config.nsvci, g_config.nsei));
Daniel Willmann654f85e2020-10-12 18:10:06 +0200710 log("Rx NS-RESET: Sending NS-ALIVE");
711 f_sendAlive();
712 Tns_test.start;
713 }
714
715 /* Respond to RESET with wrong NSEI/NSVCI */
716 [] NSCP.receive(tr_NS_RESET(?, ?, ?)) -> value rf {
717 log("Rx NS-RESET for unknown NSEI/NSVCI");
718 /* FIXME */
719 }
720 }
721
Harald Welte1308dbb2021-01-18 18:19:38 +0100722 private altstep as_nsvc_sns() runs on NSVC_CT {
Harald Welte013d65a2020-09-13 14:41:31 +0200723 var PDU_NS rf;
Harald Welte1308dbb2021-01-18 18:19:38 +0100724 var SnsRequest sreq;
Alexander Couzensd5338902020-12-21 18:41:21 +0100725 [] NSCP.receive(NS_Provider_Evt:{link_status:=NS_PROV_LINK_STATUS_UP}) {
726 log("Provider Link came up. Waiting for SNS Size");
Harald Welte1308dbb2021-01-18 18:19:38 +0100727 }
Daniel Willmann654f85e2020-10-12 18:10:06 +0200728
Harald Welte1308dbb2021-01-18 18:19:38 +0100729 /* pass up to NS-VCG */
730 [] NSCP.receive(tr_SNS(g_config.nsei)) -> value rf {
731 NS_SP.send(SnsIndication:{g_nsvc_config.nsvci, rf});
Harald Welte5e514fa2018-07-05 00:01:45 +0200732 }
Harald Welte1308dbb2021-01-18 18:19:38 +0100733 [] NSCP.receive(tr_SNS(?)) -> value rf {
734 setverdict(fail, "SNS from unexpected NSEI: ", rf);
Harald Welte5e514fa2018-07-05 00:01:45 +0200735 self.stop;
736 }
Harald Welte1308dbb2021-01-18 18:19:38 +0100737 [] NS_SP.receive(SnsRequest:{g_nsvc_config.nsvci, ?}) -> value sreq {
738 NSCP.send(sreq.ns);
Harald Welte5e514fa2018-07-05 00:01:45 +0200739 }
Harald Welte1308dbb2021-01-18 18:19:38 +0100740 [] NS_SP.receive(SnsRequest:?) -> value sreq {
741 setverdict(fail, "Unexpected SNS from NSVC: ", sreq);
Harald Welte5e514fa2018-07-05 00:01:45 +0200742 self.stop;
743 }
Harald Welte1308dbb2021-01-18 18:19:38 +0100744 [] NS_SP.receive(NsCtrlRequest:StartAliveProcedure) {
745 f_change_state(NSVC_S_ALIVE_UNBLOCKED);
746 f_sendAlive();
747 Tns_test.start;
Harald Welte5e514fa2018-07-05 00:01:45 +0200748 }
749 }
750
Harald Welte90f19742020-11-06 19:34:40 +0100751 private altstep as_alive_blocked() runs on NSVC_CT {
Harald Welte4a6a6632020-09-14 09:58:53 +0200752 var PDU_NS rf;
753 /* bogus block, just respond with ACK */
Harald Welte90f19742020-11-06 19:34:40 +0100754 [] NSCP.receive(tr_NS_BLOCK(?, g_nsvc_config.nsvci)) -> value rf {
755 NSCP.send(ts_NS_BLOCK_ACK(g_nsvc_config.nsvci));
Harald Welte4a6a6632020-09-14 09:58:53 +0200756 }
757 /* Respond to UNBLOCK with UNBLOCK-ACK + change state */
758 [] NSCP.receive(t_NS_UNBLOCK) -> value rf {
759 NSCP.send(t_NS_UNBLOCK_ACK);
760 Tns_block.stop;
Harald Welte90f19742020-11-06 19:34:40 +0100761 f_change_state(NSVC_S_ALIVE_UNBLOCKED);
Harald Welte4a6a6632020-09-14 09:58:53 +0200762 }
763 [] NSCP.receive(t_NS_UNBLOCK_ACK) -> value rf {
764 Tns_block.stop;
Harald Welte90f19742020-11-06 19:34:40 +0100765 f_change_state(NSVC_S_ALIVE_UNBLOCKED);
Harald Welte4a6a6632020-09-14 09:58:53 +0200766 }
Harald Welteda9d9382020-12-07 15:53:57 +0100767 /* tolerate a late NS-BLOCK-ACK from peer */
768 [] NSCP.receive(tr_NS_BLOCK_ACK(g_nsvc_config.nsvci)) -> value rf {
769 }
Harald Welte4a6a6632020-09-14 09:58:53 +0200770 [] Tns_block.timeout {
771 /* repeat unblock transmission */
772 f_sendUnblock();
773 }
774 }
775
Harald Welte90f19742020-11-06 19:34:40 +0100776 private altstep as_alive_unblocked() runs on NSVC_CT {
Harald Welte6fff3642017-07-22 21:36:13 +0200777 var NsUnitdataRequest ud_req;
Harald Welte013d65a2020-09-13 14:41:31 +0200778 var PDU_NS rf;
Harald Welte4a6a6632020-09-14 09:58:53 +0200779 /* bogus unblock, just respond with ACK */
780 [] NSCP.receive(t_NS_UNBLOCK) -> value rf {
781 NSCP.send(t_NS_UNBLOCK_ACK);
782 }
783 /* Respond to BLOCK with BLOCK-ACK + change state */
Harald Welte90f19742020-11-06 19:34:40 +0100784 [] NSCP.receive(tr_NS_BLOCK(?, g_nsvc_config.nsvci)) -> value rf {
785 NSCP.send(ts_NS_BLOCK_ACK(g_nsvc_config.nsvci));
Harald Welte4a6a6632020-09-14 09:58:53 +0200786 Tns_block.stop;
Harald Welte90f19742020-11-06 19:34:40 +0100787 f_change_state(NSVC_S_ALIVE_BLOCKED);
Harald Welte4a6a6632020-09-14 09:58:53 +0200788 }
Harald Welte90f19742020-11-06 19:34:40 +0100789 [] NSCP.receive(tr_NS_BLOCK_ACK(g_nsvc_config.nsvci)) -> value rf {
Harald Welte4a6a6632020-09-14 09:58:53 +0200790 Tns_block.stop;
791 }
Harald Welteda9d9382020-12-07 15:53:57 +0100792 /* tolerate a late NS-UNBLOCK-ACK from peer */
793 [] NSCP.receive(t_NS_UNBLOCK_ACK) -> value rf {
794 }
Harald Weltebe7afce2021-01-17 22:04:36 +0100795
796 [not ischosen(g_nsvc_config.provider.ip) or
797 g_nsvc_config.provider.ip.data_weight > 0] as_alive_unblocked_data();
798
799 [not ischosen(g_nsvc_config.provider.ip) or
800 g_nsvc_config.provider.ip.signalling_weight > 0] as_alive_unblocked_sig();
801
802 /* catch any violations of above rule */
803 [ischosen(g_nsvc_config.provider.ip)] NSCP.receive(tr_NS_UNITDATA(?, ?, ?)) -> value rf {
804 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
805 log2str("Unexpected Rx NS-UNITDATA on NSVC with data_weight=",
806 g_nsvc_config.provider.ip.data_weight, ", sig_weight=",
807 g_nsvc_config.provider.ip.signalling_weight, ": ", rf));
808 }
809 [ischosen(g_nsvc_config.provider.ip)] NS_SP.receive(tr_NsUdReq(g_config.nsei, ?, ?, *, *)) -> value ud_req {
810 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
811 log2str("Unexpected Rx TX-UNITDATA on NSVC with data_weight=",
812 g_nsvc_config.provider.ip.data_weight, ", sig_weight=",
813 g_nsvc_config.provider.ip.signalling_weight, ": ", ud_req));
814 }
815 }
816
817 /* user data transfer; only permitted for some NS-VC */
818 private altstep as_alive_unblocked_data() runs on NSVC_CT {
819 var NsUnitdataRequest ud_req;
820 var PDU_NS rf;
Harald Welte4a6a6632020-09-14 09:58:53 +0200821 /* NS-UNITDATA PDU from network to NS-UNITDATA.ind to user */
Harald Weltebe7afce2021-01-17 22:04:36 +0100822 [] NSCP.receive(tr_NS_UNITDATA_User(?, ?)) -> value rf {
Harald Welte80a249a2020-11-17 19:57:40 +0100823 NS_SP.send(ts_NsUdInd(g_config.nsei, g_nsvc_config.nsvci,
Harald Welte4a6a6632020-09-14 09:58:53 +0200824 oct2int(rf.pDU_NS_Unitdata.bVCI),
825 rf.pDU_NS_Unitdata.nS_SDU));
826 }
827 /* NS-UNITDATA.req from user to NS-UNITDATA PDU on network */
Harald Weltebe7afce2021-01-17 22:04:36 +0100828 [] NS_SP.receive(tr_NsUdReq(g_config.nsei, t_BssgpBvciUser, ?, ?, omit)) -> value ud_req {
Harald Welte4a6a6632020-09-14 09:58:53 +0200829 /* using raw octetstring PDU */
830 NSCP.send(ts_NS_UNITDATA(t_SduCtrlB, ud_req.bvci, ud_req.sdu));
831 }
Harald Weltebe7afce2021-01-17 22:04:36 +0100832 [] NS_SP.receive(tr_NsUdReq(g_config.nsei, t_BssgpBvciUser, ?, omit, ?)) -> value ud_req {
833 /* using decoded BSSGP PDU that we need to encode first */
834 var octetstring enc := enc_PDU_BSSGP(ud_req.bssgp);
835 NSCP.send(ts_NS_UNITDATA(t_SduCtrlB, ud_req.bvci, enc));
836 }
837 }
838
839 /* signalling (BVCI=0) transfer; only permitted for some NS-VC */
840 private altstep as_alive_unblocked_sig() runs on NSVC_CT {
841 var NsUnitdataRequest ud_req;
842 var PDU_NS rf;
843 /* NS-UNITDATA PDU from network to NS-UNITDATA.ind to user */
844 [] NSCP.receive(tr_NS_UNITDATA(?, 0, ?)) -> value rf {
845 NS_SP.send(ts_NsUdInd(g_config.nsei, g_nsvc_config.nsvci,
846 oct2int(rf.pDU_NS_Unitdata.bVCI),
847 rf.pDU_NS_Unitdata.nS_SDU));
848 }
849 /* NS-UNITDATA.req from user to NS-UNITDATA PDU on network */
850 [] NS_SP.receive(tr_NsUdReq(g_config.nsei, 0, ?, ?, omit)) -> value ud_req {
851 /* using raw octetstring PDU */
852 NSCP.send(ts_NS_UNITDATA(t_SduCtrlB, ud_req.bvci, ud_req.sdu));
853 }
854 [] NS_SP.receive(tr_NsUdReq(g_config.nsei, 0, ?, omit, ?)) -> value ud_req {
Harald Welte4a6a6632020-09-14 09:58:53 +0200855 /* using decoded BSSGP PDU that we need to encode first */
856 var octetstring enc := enc_PDU_BSSGP(ud_req.bssgp);
857 NSCP.send(ts_NS_UNITDATA(t_SduCtrlB, ud_req.bvci, enc));
858 }
859 }
Harald Welte6e594f22017-07-23 16:19:35 +0200860
Harald Welte90f19742020-11-06 19:34:40 +0100861 private altstep as_wait_reset() runs on NSVC_CT {
Harald Welte4a6a6632020-09-14 09:58:53 +0200862 var PDU_NS rf;
Harald Welte3dd83552020-09-14 11:38:01 +0200863 [] Tns_reset.timeout {
864 /* If the sending entity of an NS-RESET PDU receives no NS-RESET-ACK PDU before timer
865 * Tns-reset expires the corresponding NS-VCs shall remain blocked and dead and the
866 * entire reset procedure shall be repeated */
867 f_sendReset();
868 }
Harald Welte90f19742020-11-06 19:34:40 +0100869 [] NSCP.receive(tr_NS_RESET_ACK(g_nsvc_config.nsvci, g_config.nsei)) -> value rf {
Harald Welte3dd83552020-09-14 11:38:01 +0200870 Tns_reset.stop;
Harald Welte90f19742020-11-06 19:34:40 +0100871 f_change_state(NSVC_S_ALIVE_BLOCKED);
Harald Welte4a6a6632020-09-14 09:58:53 +0200872 f_sendAlive();
873 f_sendUnblock();
874 }
875 }
Harald Welte6fff3642017-07-22 21:36:13 +0200876
Harald Welte90f19742020-11-06 19:34:40 +0100877 private function f_ScanEvents() runs on NSVC_CT {
Harald Welte4a6a6632020-09-14 09:58:53 +0200878 var PDU_NS rf;
Harald Welte6fff3642017-07-22 21:36:13 +0200879 while (true) {
Harald Welte6fff3642017-07-22 21:36:13 +0200880 alt {
Harald Welte90f19742020-11-06 19:34:40 +0100881 [vc_state == NSVC_S_WAIT_RESET] as_wait_reset();
882 [vc_state == NSVC_S_ALIVE_BLOCKED] as_alive_blocked();
883 [vc_state == NSVC_S_ALIVE_UNBLOCKED] as_alive_unblocked();
Harald Welte3f820892021-01-19 18:19:23 +0100884 [vc_state == NSVC_S_DISABLED] as_disabled();
885 [vc_state != NSVC_S_DISABLED] as_allstate();
Harald Welte6fff3642017-07-22 21:36:13 +0200886 }
887 }
Harald Welte6fff3642017-07-22 21:36:13 +0200888 }
889}