blob: 931ff37b26df655b1134eca797fbf7535252c921 [file] [log] [blame]
Harald Welte1733a382017-07-23 17:26:17 +02001module BSSGP_Emulation {
Harald Welte1733a382017-07-23 17:26:17 +02002
Harald Welte34b5a952019-05-27 11:54:11 +02003/* BSSGP Emulation in TTCN-3
4 * (C) 2018-2019 Harald Welte <laforge@gnumonks.org>
5 * All rights reserved.
6 *
7 * Released under the terms of GNU General Public License, Version 2 or
8 * (at your option) any later version.
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 */
12
Harald Welte5ac31492018-02-15 20:39:13 +010013import from General_Types all;
14import from Osmocom_Types all;
Harald Welte853c0ad2018-02-15 17:45:29 +010015import from NS_Types all;
16import from NS_Emulation all;
17import from BSSGP_Types all;
18import from Osmocom_Gb_Types all;
19import from IPL4asp_Types all;
Harald Welte1733a382017-07-23 17:26:17 +020020
Harald Welte93331e72020-09-12 20:51:05 +020021#ifdef BSSGP_EM_L3
Harald Welte5ac31492018-02-15 20:39:13 +010022import from MobileL3_GMM_SM_Types all;
23import from MobileL3_Types all;
Harald Welte93331e72020-09-12 20:51:05 +020024#endif
Harald Welte5ac31492018-02-15 20:39:13 +010025
26import from LLC_Types all;
27import from LLC_Templates all;
28
Harald Weltea2526a82018-02-18 19:03:36 +010029import from SNDCP_Types all;
30
Harald Welte5ac31492018-02-15 20:39:13 +010031/***********************************************************************
32 * Communication between Client Components and Main Component
33 ***********************************************************************/
34
Harald Welte853c0ad2018-02-15 17:45:29 +010035type record BssgpStatusIndication {
36 Nsei nsei,
37 BssgpBvci bvci,
38 BvcState state
39}
40
41template BssgpStatusIndication t_BssgpStsInd(template Nsei nsei, template BssgpBvci bvci, template BvcState state) := {
42 nsei := nsei,
43 bvci := bvci,
44 state := state
45}
46
47type enumerated BvcState {
48 BVC_S_BLOCKED,
49 BVC_S_UNBLOCKED
50};
51
52/* port from our (internal) point of view */
53type port BSSGP_SP_PT message {
Harald Welte5ac31492018-02-15 20:39:13 +010054 in PDU_BSSGP,
Harald Welte93331e72020-09-12 20:51:05 +020055 PDU_LLC
56#ifdef BSSGP_EM_L3
57 ,
Harald Welte5ac31492018-02-15 20:39:13 +010058 PDU_L3_MS_SGSN,
Harald Welte93331e72020-09-12 20:51:05 +020059 PDU_L3_SGSN_MS
60#endif
61 ;
Harald Welte955aa942019-05-03 01:29:29 +020062 out PDU_BSSGP,
63 PDU_LLC,
64 PDU_SN,
Harald Welte853c0ad2018-02-15 17:45:29 +010065 NsStatusIndication,
66 BssgpStatusIndication,
Harald Welte93331e72020-09-12 20:51:05 +020067 ASP_Event
68#ifdef BSSGP_EM_L3
69 ,
Harald Welte5ac31492018-02-15 20:39:13 +010070 PDU_L3_MS_SGSN,
Harald Welte93331e72020-09-12 20:51:05 +020071 PDU_L3_SGSN_MS
72#endif
73 ;
Harald Welte853c0ad2018-02-15 17:45:29 +010074} with { extension "internal" };
75
76/* port from the user point of view */
77type port BSSGP_PT message {
78 in ASP_Event,
79 NsStatusIndication,
80 BssgpStatusIndication,
Harald Welte955aa942019-05-03 01:29:29 +020081 PDU_BSSGP,
82 PDU_LLC,
Harald Welte93331e72020-09-12 20:51:05 +020083 PDU_SN
84#ifdef BSSGP_EM_L3
85 ,
Harald Welte5ac31492018-02-15 20:39:13 +010086 PDU_L3_MS_SGSN,
Harald Welte93331e72020-09-12 20:51:05 +020087 PDU_L3_SGSN_MS
88#endif
89 ;
Harald Welte5ac31492018-02-15 20:39:13 +010090 out PDU_BSSGP,
Harald Welte93331e72020-09-12 20:51:05 +020091 PDU_LLC
92#ifdef BSSGP_EM_L3
93 ,
Harald Welte5ac31492018-02-15 20:39:13 +010094 PDU_L3_SGSN_MS,
Harald Welte93331e72020-09-12 20:51:05 +020095 PDU_L3_MS_SGSN
96#endif
97 ;
Harald Welte853c0ad2018-02-15 17:45:29 +010098} with { extension "internal" };
99
Harald Welte5ac31492018-02-15 20:39:13 +0100100signature BSSGP_register_client(hexstring imsi, OCT4 tlli, BssgpCellId cell_id);
101signature BSSGP_unregister_client(hexstring imsi);
Harald Weltef70997d2018-02-17 10:11:19 +0100102signature BSSGP_llgmm_assign(OCT4 tlli_old, OCT4 tlli);
Harald Welte5ac31492018-02-15 20:39:13 +0100103
104type port BSSGP_PROC_PT procedure {
Harald Weltef70997d2018-02-17 10:11:19 +0100105 inout BSSGP_register_client, BSSGP_unregister_client, BSSGP_llgmm_assign;
Harald Welte5ac31492018-02-15 20:39:13 +0100106} with { extension "internal" };
107
108
109/***********************************************************************
110 * Client Component for a single MS/TLLI
111 ***********************************************************************/
112
113type component BSSGP_Client_CT {
Alexander Couzens0e510e62018-07-28 23:06:00 +0200114 port BSSGP_PT BSSGP[3];
115 port BSSGP_PT BSSGP_SIG[3];
116 port BSSGP_PROC_PT BSSGP_PROC[3];
Harald Welte5ac31492018-02-15 20:39:13 +0100117};
118
119/***********************************************************************
120 * Main Component
121 ***********************************************************************/
122
123function BssgpStart(BssgpConfig cfg) runs on BSSGP_CT {
124 g_cfg := cfg;
Harald Welte853c0ad2018-02-15 17:45:29 +0100125 f_init();
126 f_ScanEvents();
127}
128
129private function f_init() runs on BSSGP_CT {
130 /* Connect the UDP socket */
131 f_change_state(BVC_S_BLOCKED);
132}
133
134type component BSSGP_CT {
Stefan Sperlingf82bbb62018-05-03 19:14:28 +0200135 /* UDP ports towards the bottom (IUT) */
Harald Welte853c0ad2018-02-15 17:45:29 +0100136 port NS_PT BSCP;
137 /* NS-User SAP towards the user */
138 port BSSGP_SP_PT BSSGP_SP;
Stefan Sperlingf82bbb62018-05-03 19:14:28 +0200139 port BSSGP_SP_PT BSSGP_SP_SIG;
Harald Welte5ac31492018-02-15 20:39:13 +0100140 port BSSGP_PROC_PT BSSGP_PROC;
Harald Welte853c0ad2018-02-15 17:45:29 +0100141
Harald Welte5ac31492018-02-15 20:39:13 +0100142 var BssgpConfig g_cfg;
143
Harald Welte853c0ad2018-02-15 17:45:29 +0100144 var BvcState g_ptp_bvc_state := BVC_S_BLOCKED;
145 timer g_T1 := 15.0;
146 timer g_T2 := 60.0;
Harald Welte5ac31492018-02-15 20:39:13 +0100147
148 var ClientEntity ClientTable[16];
Harald Welte853c0ad2018-02-15 17:45:29 +0100149}
150
Alexander Couzens6b449fb2018-07-31 14:19:36 +0200151type record length(16) of LLC_Entity LLC_Entities;
152
Harald Welte5ac31492018-02-15 20:39:13 +0100153type record ClientEntity {
154 OCT4 tlli,
155 OCT4 tlli_old optional,
156 hexstring imsi,
157 BssgpCellId cell_id,
158 BSSGP_Client_CT comp_ref,
159 /* LLC entities, one for each SAPI */
160 LLC_Entity llc[16]
Harald Welte853c0ad2018-02-15 17:45:29 +0100161};
162
Harald Welte5ac31492018-02-15 20:39:13 +0100163type record LLC_Entity {
164 boolean sgsn_role,
165 /* N(U) on transmit side for next PDU */
166 uint9_t n_u_tx_next,
167 /* N(U) on receive side, last PDU */
168 uint9_t n_u_rx_last optional
169};
170
Alexander Couzenscdfb7512018-07-31 15:37:14 +0200171function f_llc_create(boolean sgsn_role := false) return LLC_Entities {
172 var LLC_Entities llc;
173 for (var integer i := 0; i < 16; i := i+1) {
174 llc[i] := valueof(t_LLC_init(sgsn_role));
175 }
176 return llc;
177}
178
Harald Welte5ac31492018-02-15 20:39:13 +0100179private template LLC_Entity t_LLC_init(boolean sgsn_role := false) := {
180 sgsn_role := sgsn_role,
181 n_u_tx_next := 0,
182 n_u_rx_last := -
183}
184
Oliver Smithaac9b9c2019-09-02 08:36:36 +0200185type enumerated BssgpDecodeDepth {
186 BSSGP_DECODE_DEPTH_BSSGP,
187 BSSGP_DECODE_DEPTH_LLC,
Harald Welte93331e72020-09-12 20:51:05 +0200188 BSSGP_DECODE_DEPTH_SNDCP
189#ifdef BSSGP_EM_L3
190 ,
Oliver Smithaac9b9c2019-09-02 08:36:36 +0200191 BSSGP_DECODE_DEPTH_L3
Harald Welte93331e72020-09-12 20:51:05 +0200192#endif
Oliver Smithaac9b9c2019-09-02 08:36:36 +0200193};
194
Harald Welte5ac31492018-02-15 20:39:13 +0100195type record BssgpConfig {
196 Nsvci nsei,
197 Nsvci bvci,
198 BssgpCellId cell_id,
Oliver Smithaac9b9c2019-09-02 08:36:36 +0200199 boolean sgsn_role,
200 BssgpDecodeDepth depth
Harald Welte5ac31492018-02-15 20:39:13 +0100201};
202
203function f_BnsUdReq(template PDU_BSSGP pdu, BssgpBvci bvci)
204runs on BSSGP_CT return NsUnitdataRequest {
Harald Welte853c0ad2018-02-15 17:45:29 +0100205 var NsUnitdataRequest udr := {
Harald Welte1733a382017-07-23 17:26:17 +0200206 bvci := bvci,
Harald Welte5ac31492018-02-15 20:39:13 +0100207 nsei := g_cfg.nsei,
Harald Welte853c0ad2018-02-15 17:45:29 +0100208 /* for some weird reason we get "Dynamic test case error: Text encoder: Encoding an
209 * unbound integer value." when trying to send the reocrd rather than the octetstring */
210 //sdu := omit,
211 //bssgp := valueof(pdu)
212 sdu := enc_PDU_BSSGP(valueof(pdu)),
213 bssgp := omit
214 }
215 return udr;
216}
217
Harald Welte5ac31492018-02-15 20:39:13 +0100218function f_BnsUdInd(template PDU_BSSGP pdu, template BssgpBvci bvci)
219runs on BSSGP_CT return template NsUnitdataIndication {
Harald Welte853c0ad2018-02-15 17:45:29 +0100220 var template NsUnitdataIndication udi := {
221 bvci := bvci,
Harald Welte5ac31492018-02-15 20:39:13 +0100222 nsei := g_cfg.nsei,
Harald Welte853c0ad2018-02-15 17:45:29 +0100223 sdu := *,
224 bssgp := pdu
225 }
226 return udi;
227}
228
229private function f_change_state(BvcState new_state) runs on BSSGP_CT {
230 log("BSSGP State Transition: ", g_ptp_bvc_state, " -> ", new_state);
231 g_ptp_bvc_state := new_state;
Harald Welte5ac31492018-02-15 20:39:13 +0100232 for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
233 if (isbound(ClientTable[i].comp_ref)) {
234 BSSGP_SP.send(t_BssgpStsInd(g_cfg.nsei, g_cfg.bvci, g_ptp_bvc_state)) to ClientTable[i].comp_ref;
235 }
236 }
Harald Welte853c0ad2018-02-15 17:45:29 +0100237}
238
Harald Weltec967d0e2020-09-14 16:07:26 +0200239private function f_sendReset(BssgpBvci bvci) runs on BSSGP_CT {
240 var PDU_BSSGP pdu;
241
242 /* The Cell Identifier IE is mandatory in the BVC-RESET PDU sent from BSS to
243 * SGSN in order to reset a BVC corresponding to a PTP functional entity. The
244 * Cell Identifier IE shall not be used in any other BVC-RESET PDU. */
245 if (g_cfg.sgsn_role) {
246 pdu := valueof(ts_BVC_RESET(BSSGP_CAUSE_OM_INTERVENTION, bvci, omit));
247 } else {
248 pdu := valueof(ts_BVC_RESET(BSSGP_CAUSE_OM_INTERVENTION, bvci, g_cfg.cell_id));
249 }
Harald Welte853c0ad2018-02-15 17:45:29 +0100250 log("PDU: ", pdu);
251 log("ENC: ", enc_PDU_BSSGP(pdu));
252
253 /* BVC-RESET is always sent via the SIGNALLING BVCI, see Table 5.4.1 */
254 BSCP.send(f_BnsUdReq(pdu, 0));
255 g_T2.start;
256 //f_change_state(BVC_S_WAIT_RESET);
257}
258
259private function f_sendUnblock() runs on BSSGP_CT {
Harald Welte5ac31492018-02-15 20:39:13 +0100260 BSCP.send(f_BnsUdReq(t_BVC_UNBLOCK(g_cfg.bvci), 0));
Harald Welte853c0ad2018-02-15 17:45:29 +0100261 g_T1.start;
262}
263
264private function f_sendBlock(BssgpCause cause) runs on BSSGP_CT {
Harald Welte5ac31492018-02-15 20:39:13 +0100265 BSCP.send(f_BnsUdReq(t_BVC_BLOCK(g_cfg.bvci, cause), 0));
Harald Welte853c0ad2018-02-15 17:45:29 +0100266 g_T1.start;
267}
268
269private function f_sendStatus(BssgpCause cause, PDU_BSSGP pdu) runs on BSSGP_CT {
270 /* FIXME: Make sure correct Signaling or PTP BVCI is used! */
Harald Welte5ac31492018-02-15 20:39:13 +0100271 BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(g_cfg.bvci, cause, pdu), g_cfg.bvci));
272}
273
274/* attempt to extract the TLLI from a BSSGP PDU */
275function f_bssgp_get_tlli(PDU_BSSGP bssgp) return template OCT4 {
276 if (ischosen(bssgp.pDU_BSSGP_DL_UNITDATA)) {
277 return bssgp.pDU_BSSGP_DL_UNITDATA.tLLI_current;
278 } else if (ischosen(bssgp.pDU_BSSGP_UL_UNITDATA)) {
279 return bssgp.pDU_BSSGP_UL_UNITDATA.tLLI;
280 } else if (ischosen(bssgp.pDU_BSSGP_RA_CAPABILITY)) {
281 return bssgp.pDU_BSSGP_RA_CAPABILITY.tLLI.tLLI_Value;
282 } else if (ischosen(bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE)) {
283 return bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE.tLLI.tLLI_Value;
284 } else if (ischosen(bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE_ACK)) {
285 return bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE_ACK.tLLI.tLLI_Value;
286 } else if (ischosen(bssgp.pDU_BSSGP_RADIO_STATUS)) {
287 return bssgp.pDU_BSSGP_RADIO_STATUS.tLLI.tLLI_Value;
288 } else if (ischosen(bssgp.pDU_BSSGP_SUSPEND)) {
289 return bssgp.pDU_BSSGP_SUSPEND.tLLI.tLLI_Value;
290 } else if (ischosen(bssgp.pDU_BSSGP_SUSPEND_ACK)) {
291 return bssgp.pDU_BSSGP_SUSPEND_ACK.tLLI.tLLI_Value;
292 } else if (ischosen(bssgp.pDU_BSSGP_SUSPEND_NACK)) {
293 return bssgp.pDU_BSSGP_SUSPEND_NACK.tLLI.tLLI_Value;
294 } else if (ischosen(bssgp.pDU_BSSGP_RESUME)) {
295 return bssgp.pDU_BSSGP_RESUME.tLLI.tLLI_Value;
296 } else if (ischosen(bssgp.pDU_BSSGP_RESUME_ACK)) {
297 return bssgp.pDU_BSSGP_RESUME_ACK.tLLI.tLLI_Value;
298 } else if (ischosen(bssgp.pDU_BSSGP_RESUME_NACK)) {
299 return bssgp.pDU_BSSGP_RESUME_NACK.tLLI.tLLI_Value;
300 } else if (ischosen(bssgp.pDU_BSSGP_FLUSH_LL)) {
301 return bssgp.pDU_BSSGP_FLUSH_LL.tLLI.tLLI_Value;
302 } else if (ischosen(bssgp.pDU_BSSGP_FLUSH_LL_ACK)) {
303 return bssgp.pDU_BSSGP_FLUSH_LL_ACK.tLLI.tLLI_Value;
304 } else if (ischosen(bssgp.pDU_BSSGP_LLC_DISCARDED)) {
305 return bssgp.pDU_BSSGP_LLC_DISCARDED.tLLI.tLLI_Value;
306 } else if (ischosen(bssgp.pDU_BSSGP_LLC_DISCARDED)) {
307 return bssgp.pDU_BSSGP_LLC_DISCARDED.tLLI.tLLI_Value;
308 } else if (ischosen(bssgp.pDU_BSSGP_PAGING_CS) and
309 isvalue(bssgp.pDU_BSSGP_PAGING_CS.tLLI)) {
310 return bssgp.pDU_BSSGP_PAGING_CS.tLLI.tLLI_Value;
311 } else if (ischosen(bssgp.pDU_BSSGP_FLOW_CONTROL_MS)) {
312 return bssgp.pDU_BSSGP_FLOW_CONTROL_MS.tLLI.tLLI_Value;
313 } else if (ischosen(bssgp.pDU_BSSGP_FLOW_CONTROL_MS_ACK)) {
314 return bssgp.pDU_BSSGP_FLOW_CONTROL_MS_ACK.tLLI.tLLI_Value;
315 }
316 /* TODO: Handover, PFC, LCS */
317 return omit;
318}
319
320/*
321private function f_tbl_init() runs on BSSGP_CT {
322 var integer i;
323 for (i := 0; i < sizeof(ImsiTable); i := i+1) {
324 ImsiTable[i] := -;
325 }
326
327 for (i := 0; i < sizeof(TlliTable); i := i+1) {
328 TlliTable[i] := -;
329 }
330}
331*/
332
333private function f_tbl_client_add(hexstring imsi, OCT4 tlli, BssgpCellId cell_id, BSSGP_Client_CT vc_conn)
334runs on BSSGP_CT {
335 var integer i;
336 for (i := 0; i < sizeof(ClientTable); i := i+1) {
Harald Weltec7872fa2018-02-18 14:06:12 +0100337 if (not isvalue(ClientTable[i].comp_ref)) {
338 log("Adding Client=", vc_conn, ", IMSI=", imsi, ", TLLI=", tlli, ", index=", i);
Harald Welte5ac31492018-02-15 20:39:13 +0100339 ClientTable[i] := {
340 tlli := tlli,
341 tlli_old := omit,
342 imsi := imsi,
343 cell_id := cell_id,
344 comp_ref := vc_conn,
345 llc := -
346 };
347 for (var integer j := 0; j < sizeof(ClientTable[i].llc); j := j+1) {
348 ClientTable[i].llc[j] := valueof(t_LLC_init(g_cfg.sgsn_role));
349 }
350 return;
351 }
352 }
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200353 testcase.stop("Client Table full");
Harald Welte5ac31492018-02-15 20:39:13 +0100354}
355
356private function f_tbl_client_del(hexstring imsi, BSSGP_Client_CT vc_conn) runs on BSSGP_CT {
357 var integer i;
358 for (i := 0; i < sizeof(ClientTable); i := i+1) {
Harald Weltec7872fa2018-02-18 14:06:12 +0100359 if (isvalue(ClientTable[i].imsi) and ClientTable[i].imsi == imsi) {
Harald Welte5ac31492018-02-15 20:39:13 +0100360 if (ClientTable[i].comp_ref != vc_conn) {
Alexander Couzens2c153422018-06-12 18:10:30 +0200361 setverdict(fail, "Cannot unregister index=", i, " IMSI ", imsi, " registred to ",
Harald Welte5ac31492018-02-15 20:39:13 +0100362 ClientTable[i].comp_ref, " from ", vc_conn);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200363 mtc.stop;
Harald Welte5ac31492018-02-15 20:39:13 +0100364 }
365 log("Removing Client IMSI=", imsi, ", index=", i);
Alexander Couzens2c153422018-06-12 18:10:30 +0200366 ClientTable[i] := {
367 tlli := -,
368 tlli_old := omit,
369 imsi := ''H,
370 cell_id := -,
371 comp_ref := null,
372 llc := - };
Harald Welte5ac31492018-02-15 20:39:13 +0100373 return;
374 }
375 }
Alexander Couzens56101c92018-07-31 15:55:34 +0200376 log("Warning: Could not find client for IMSI ", imsi);
377 return;
Harald Welte5ac31492018-02-15 20:39:13 +0100378}
379
Harald Weltef70997d2018-02-17 10:11:19 +0100380/* TS 44.064 7.2.1.1 LLGMM-ASSIGN */
381private function f_tbl_client_llgmm_assign(OCT4 tlli_old, OCT4 tlli_new, BSSGP_Client_CT vc_conn)
382runs on BSSGP_CT {
383 var integer i := f_tbl_idx_by_comp(vc_conn);
384
385 if (tlli_old == 'FFFFFFFF'O and tlli_new != 'FFFFFFFF'O) {
386 /* TLLI assignment */
387 ClientTable[i].tlli := tlli_new;
388 ClientTable[i].tlli_old := omit;
389 } else if (tlli_old != 'FFFFFFFF'O and tlli_new != 'FFFFFFFF'O) {
390 /* TLLI change: both active */
391 ClientTable[i].tlli := tlli_new;
392 ClientTable[i].tlli_old := tlli_old;
393 } else if (tlli_old != 'FFFFFFFF'O and tlli_new == 'FFFFFFFF'O) {
394 /* TLLI unassignment: old shall be unassigned; new stays */
395 ClientTable[i].tlli_old := omit;
396 }
397}
398
Harald Welte5ac31492018-02-15 20:39:13 +0100399private function f_tbl_comp_by_imsi(hexstring imsi) runs on BSSGP_CT return BSSGP_Client_CT {
400 var integer i;
401 for (i := 0; i < sizeof(ClientTable); i := i+1) {
Harald Weltec7872fa2018-02-18 14:06:12 +0100402 if (isvalue(ClientTable[i].imsi) and isvalue(ClientTable[i].comp_ref)
Harald Welte5ac31492018-02-15 20:39:13 +0100403 and ClientTable[i].imsi == imsi) {
404 return ClientTable[i].comp_ref;
405 }
406 }
407 setverdict(fail, "Couldn't find Component for IMSI ", imsi);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200408 mtc.stop;
Harald Welte5ac31492018-02-15 20:39:13 +0100409}
410
411private function f_tbl_comp_by_tlli(OCT4 tlli) runs on BSSGP_CT return BSSGP_Client_CT {
412 var integer i;
413 for (i := 0; i < sizeof(ClientTable); i := i+1) {
Harald Weltec7872fa2018-02-18 14:06:12 +0100414 if (isvalue(ClientTable[i].comp_ref) and
415 (isvalue(ClientTable[i].tlli) and (ClientTable[i].tlli == tlli or
416 isvalue(ClientTable[i].tlli_old) and ClientTable[i].tlli_old == tlli) )) {
Harald Welte5ac31492018-02-15 20:39:13 +0100417 return ClientTable[i].comp_ref;
418 }
419 }
420 setverdict(fail, "Couldn't find Component for TLLI ", tlli);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200421 mtc.stop;
Harald Welte5ac31492018-02-15 20:39:13 +0100422}
423
424private function f_tbl_idx_by_comp(BSSGP_Client_CT comp_ref) runs on BSSGP_CT return integer {
425 var integer i;
426 for (i := 0; i < sizeof(ClientTable); i := i+1) {
Harald Weltec7872fa2018-02-18 14:06:12 +0100427 if (isvalue(ClientTable[i].comp_ref) and ClientTable[i].comp_ref == comp_ref) {
Harald Welte5ac31492018-02-15 20:39:13 +0100428 return i;
429 }
430 }
431 setverdict(fail, "Couldn't find Client for Component ", comp_ref);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200432 mtc.stop;
Harald Welte5ac31492018-02-15 20:39:13 +0100433}
434
435private function f_tbl_tlli_by_comp(BSSGP_Client_CT comp_ref) runs on BSSGP_CT return OCT4 {
436 var integer i;
437 for (i := 0; i < sizeof(ClientTable); i := i+1) {
Harald Weltec7872fa2018-02-18 14:06:12 +0100438 if (isvalue(ClientTable[i].tlli) and isvalue(ClientTable[i].comp_ref)
Harald Welte5ac31492018-02-15 20:39:13 +0100439 and ClientTable[i].comp_ref == comp_ref) {
440 return ClientTable[i].tlli;
441 }
442 }
443 setverdict(fail, "Couldn't find TLLI for Component ", comp_ref);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200444 mtc.stop;
Harald Welte853c0ad2018-02-15 17:45:29 +0100445}
446
Harald Weltec967d0e2020-09-14 16:07:26 +0200447private function f_send_bvc_reset_ack(BssgpBvci bvci) runs on BSSGP_CT {
448 /* The Cell Identifier IE is mandatory in the BVC-RESET-ACK PDU sent from BSS to
449 * SGSN in response to reset a BVC corresponding to a PTP functional entity. The Cell
450 * Identifier IE shall not be used in any other BVC-RESET-ACK PDU */
451 if (g_cfg.sgsn_role) {
452 BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(bvci, omit), 0));
453 } else {
454 BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(bvci, g_cfg.cell_id), 0));
455 }
456}
457
Harald Welte853c0ad2018-02-15 17:45:29 +0100458altstep as_allstate() runs on BSSGP_CT {
Harald Welte5ac31492018-02-15 20:39:13 +0100459 var BSSGP_Client_CT vc_conn;
Harald Welte853c0ad2018-02-15 17:45:29 +0100460 var NsUnitdataIndication udi;
461 var NsStatusIndication nsi;
462 var ASP_Event evt;
Harald Welte5ac31492018-02-15 20:39:13 +0100463 var hexstring imsi;
Harald Weltef70997d2018-02-17 10:11:19 +0100464 var OCT4 tlli, tlli_old;
Harald Welte5ac31492018-02-15 20:39:13 +0100465 var BssgpCellId cell_id;
Harald Welte853c0ad2018-02-15 17:45:29 +0100466
467 /* Respond to BLOCK for wrong NSVCI */
468 [] BSCP.receive(f_BnsUdInd(t_BVC_BLOCK(?, ?), 0)) -> value udi {
469 log("Rx BVC-BLOCK for unknown BVCI");
470 f_sendStatus(BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp);
Harald Welte1733a382017-07-23 17:26:17 +0200471 }
472
Harald Welte853c0ad2018-02-15 17:45:29 +0100473 /* Respond to RESET with correct BVCI/CellID */
Harald Welte5ac31492018-02-15 20:39:13 +0100474 [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, g_cfg.bvci, g_cfg.cell_id), 0)) -> value udi {
475 log("Rx BVC-RESET for Our BVCI=", g_cfg.bvci);
Harald Weltec967d0e2020-09-14 16:07:26 +0200476 f_send_bvc_reset_ack(g_cfg.bvci);
Harald Welte853c0ad2018-02-15 17:45:29 +0100477 f_change_state(BVC_S_UNBLOCKED);
Harald Welte1733a382017-07-23 17:26:17 +0200478 }
479
Harald Welte853c0ad2018-02-15 17:45:29 +0100480 /* Respond to RESET for signalling BVCI 0 */
Harald Welte5ac31492018-02-15 20:39:13 +0100481 [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, 0, g_cfg.cell_id), 0)) -> value udi {
Harald Welte853c0ad2018-02-15 17:45:29 +0100482 log("Rx BVC-RESET for Signaling BVCI=0");
Harald Weltec967d0e2020-09-14 16:07:26 +0200483 f_send_bvc_reset_ack(0);
Harald Welte1733a382017-07-23 17:26:17 +0200484 }
485
Harald Welte853c0ad2018-02-15 17:45:29 +0100486 /* Respond to RESET with wrong NSEI/NSVCI */
487 [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, ?, ?), 0)) -> value udi {
488 log("Rx BVC-RESET for unknown BVCI");
489 f_sendStatus(BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp);
Harald Welte1733a382017-07-23 17:26:17 +0200490 }
491
Harald Welte853c0ad2018-02-15 17:45:29 +0100492 /* default case of handling unknown PDUs */
493 [] BSCP.receive(f_BnsUdInd(?, ?)) -> value udi {
494 log("Rx Unexpected BSSGP PDU ", udi.bssgp," in state ", g_ptp_bvc_state);
495 f_sendStatus(BSSGP_CAUSE_PDU_NOT_COMPATIBLE_WITH_PROTOCOL_STATE, udi.bssgp);
Harald Welte1733a382017-07-23 17:26:17 +0200496 }
Harald Welte853c0ad2018-02-15 17:45:29 +0100497 /* Forwarding of ASP_Event and NsStatusIndication to user */
Harald Welte5ac31492018-02-15 20:39:13 +0100498 [] BSCP.receive(ASP_Event:?) -> value evt {
499 for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
500 if (isbound(ClientTable[i].comp_ref)) {
501 BSSGP_SP.send(evt) to ClientTable[i].comp_ref;
502 }
503 }
504 }
Harald Welte853c0ad2018-02-15 17:45:29 +0100505 [] BSCP.receive(NsStatusIndication:?) -> value nsi {
506 /* if we just became NS-unblocked, send a BCC-RESET */
507 if (nsi.old_state != NSE_S_ALIVE_UNBLOCKED and nsi.new_state == NSE_S_ALIVE_UNBLOCKED) {
Harald Welte5ac31492018-02-15 20:39:13 +0100508 if (g_cfg.sgsn_role == false) {
Harald Weltec967d0e2020-09-14 16:07:26 +0200509 f_sendReset(g_cfg.bvci);
Harald Welte1733a382017-07-23 17:26:17 +0200510 }
Harald Welte5ac31492018-02-15 20:39:13 +0100511 /* Idea: We could send BVC-UNBLOCK here like some SGSN do */
Harald Welte1733a382017-07-23 17:26:17 +0200512 }
Harald Welte5ac31492018-02-15 20:39:13 +0100513 for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
514 if (isbound(ClientTable[i].comp_ref)) {
515 BSSGP_SP.send(nsi) to ClientTable[i].comp_ref;
516 }
517 }
518 }
519
520 [] BSSGP_PROC.getcall(BSSGP_register_client:{?,?,?}) -> param(imsi, tlli, cell_id) sender vc_conn {
521 f_tbl_client_add(imsi, tlli, cell_id, vc_conn);
Harald Weltee32ad992018-05-31 22:17:46 +0200522 BSSGP_PROC.reply(BSSGP_register_client:{imsi, tlli, cell_id}) to vc_conn;
Harald Welte5ac31492018-02-15 20:39:13 +0100523 }
524 [] BSSGP_PROC.getcall(BSSGP_unregister_client:{?}) -> param(imsi) sender vc_conn {
525 f_tbl_client_del(imsi, vc_conn);
Harald Weltee32ad992018-05-31 22:17:46 +0200526 BSSGP_PROC.reply(BSSGP_unregister_client:{imsi}) to vc_conn;
Harald Welte5ac31492018-02-15 20:39:13 +0100527 }
Harald Weltef70997d2018-02-17 10:11:19 +0100528 [] BSSGP_PROC.getcall(BSSGP_llgmm_assign:{?,?}) -> param(tlli_old, tlli) sender vc_conn {
529 f_tbl_client_llgmm_assign(tlli_old, tlli, vc_conn);
Harald Weltee32ad992018-05-31 22:17:46 +0200530 BSSGP_PROC.reply(BSSGP_llgmm_assign:{tlli_old, tlli}) to vc_conn;
Harald Weltef70997d2018-02-17 10:11:19 +0100531 }
532
Harald Welte5ac31492018-02-15 20:39:13 +0100533}
534
535altstep as_blocked() runs on BSSGP_CT {
Harald Weltec27f6842018-03-02 21:40:03 +0100536 [g_T1.running] g_T1.timeout {
Harald Welte5ac31492018-02-15 20:39:13 +0100537 f_sendUnblock();
538 }
539 [] BSCP.receive(f_BnsUdInd(t_BVC_UNBLOCK_ACK(g_cfg.bvci), 0)) {
540 g_T1.stop;
541 f_change_state(BVC_S_UNBLOCKED);
542 }
543 [not g_cfg.sgsn_role] BSCP.receive(f_BnsUdInd(tr_BVC_RESET_ACK(g_cfg.bvci, omit), 0)) {
544 f_sendUnblock();
Harald Welte1733a382017-07-23 17:26:17 +0200545 }
Harald Welte853c0ad2018-02-15 17:45:29 +0100546}
Harald Welte1733a382017-07-23 17:26:17 +0200547
Harald Welte955aa942019-05-03 01:29:29 +0200548private function f_send_bssgp_dec(BssgpDecoded dec, BSSGP_Client_CT vc_conn, BSSGP_SP_PT pt := BSSGP_SP) runs on BSSGP_CT {
Harald Welte07cb87a2020-09-13 18:38:02 +0200549#ifdef BSSGP_EM_L3
Harald Welte955aa942019-05-03 01:29:29 +0200550 if (ispresent(dec.l3_mt)) {
551 pt.send(dec.l3_mt) to vc_conn;
552 } else if (ispresent(dec.l3_mo)) {
553 pt.send(dec.l3_mo) to vc_conn;
Harald Welte07cb87a2020-09-13 18:38:02 +0200554 } else
555#endif
556 if (ispresent(dec.sndcp)) {
Harald Welte955aa942019-05-03 01:29:29 +0200557 pt.send(dec.sndcp) to vc_conn;
558 } else if (ispresent(dec.llc)) {
559 pt.send(dec.llc) to vc_conn;
560 } else {
561 pt.send(dec.bssgp) to vc_conn;
562 }
563}
564
565
Harald Welte5ac31492018-02-15 20:39:13 +0100566altstep as_unblocked() runs on BSSGP_CT {
567 var BSSGP_Client_CT vc_conn;
Harald Welte853c0ad2018-02-15 17:45:29 +0100568 var NsUnitdataIndication udi;
569 var PDU_BSSGP bs_pdu;
Harald Welte752abba2018-02-18 19:42:17 +0100570 var PDU_LLC llc;
Harald Welte93331e72020-09-12 20:51:05 +0200571#ifdef BSSGP_EM_L3
Harald Welte5ac31492018-02-15 20:39:13 +0100572 var PDU_L3_MS_SGSN l3_mo;
573 var PDU_L3_SGSN_MS l3_mt;
Harald Welte93331e72020-09-12 20:51:05 +0200574#endif
Harald Welte1733a382017-07-23 17:26:17 +0200575
Harald Welte5ac31492018-02-15 20:39:13 +0100576 /* bogus unblock, just respond with ACK */
577 [] BSCP.receive(f_BnsUdInd(t_BVC_UNBLOCK(g_cfg.bvci), 0)) -> value udi {
578 BSCP.send(f_BnsUdReq(t_BVC_UNBLOCK_ACK(g_cfg.bvci), 0));
579 }
580 /* Respond to BLOCK with BLOCK-ACK + change state */
581 [] BSCP.receive(f_BnsUdInd(t_BVC_BLOCK(g_cfg.bvci, ?), 0)) -> value udi {
582 BSCP.send(f_BnsUdReq(t_BVC_BLOCK_ACK(g_cfg.bvci), 0));
583 g_T1.stop;
584 f_change_state(BVC_S_BLOCKED);
585 }
Harald Weltec27f6842018-03-02 21:40:03 +0100586 [g_T1.running] g_T1.timeout {
Harald Welte5ac31492018-02-15 20:39:13 +0100587 f_sendBlock(BSSGP_CAUSE_OM_INTERVENTION);
588 }
589 [] BSCP.receive(f_BnsUdInd(t_BVC_BLOCK_ACK(g_cfg.bvci), 0)) -> value udi {
590 g_T1.stop;
591 f_change_state(BVC_S_BLOCKED);
592 }
593 [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET_ACK(g_cfg.bvci, g_cfg.cell_id), 0)) -> value udi {
594 g_T2.stop;
595 f_change_state(BVC_S_UNBLOCKED);
596 }
Harald Welte13d391e2017-07-23 19:52:33 +0200597
Harald Welte5ac31492018-02-15 20:39:13 +0100598 /* simply acknowledge all Flow Control Messages */
Harald Welteedcdd902018-03-02 22:04:54 +0100599 [g_cfg.sgsn_role] BSCP.receive(f_BnsUdInd(tr_BVC_FC_BVC, g_cfg.bvci)) -> value udi {
600 var OCT1 tag := udi.bssgp.pDU_BSSGP_FLOW_CONTROL_BVC.tag.unstructured_Value;
601 BSCP.send(f_BnsUdReq(t_BVC_FC_BVC_ACK(tag), g_cfg.bvci));
Harald Welte5ac31492018-02-15 20:39:13 +0100602 }
Harald Welteedcdd902018-03-02 22:04:54 +0100603/*
604 [g_cfg.sgsn_role] BSCP.receive(f_BnsUdInd(t_BVC_FC_MS, g_cfg.bvci)) {
605 BSCP.send(f_BnsUdReq(t_BVC_FC_MS_ACK, g_cfg.bvci));
Harald Welte5ac31492018-02-15 20:39:13 +0100606 }
Harald Weltee0abc472018-02-05 09:13:31 +0100607*/
Harald Welte13d391e2017-07-23 19:52:33 +0200608
Harald Welte5ac31492018-02-15 20:39:13 +0100609 /* FIXME: CS PAGING: dispatch by IMSI */
Harald Welte1733a382017-07-23 17:26:17 +0200610
Harald Welte5ac31492018-02-15 20:39:13 +0100611 /* PS PAGING: dispatch by IMSI */
612 [] BSCP.receive(f_BnsUdInd(tr_BSSGP_PS_PAGING(g_cfg.bvci), g_cfg.bvci)) -> value udi {
613 var hexstring imsi := udi.bssgp.pDU_BSSGP_PAGING_PS.iMSI.digits
614 vc_conn := f_tbl_comp_by_imsi(imsi);
Harald Welte955aa942019-05-03 01:29:29 +0200615 f_send_bssgp_dec(f_dec_bssgp(udi.bssgp), vc_conn);
Harald Welte5ac31492018-02-15 20:39:13 +0100616 }
617
Harald Welte001b0da2019-03-21 21:30:47 +0100618 /* Any other PTP BSSGP message: If it has TLLi, route to component; otherwise broadcast */
Harald Welte5ac31492018-02-15 20:39:13 +0100619 [] BSCP.receive(f_BnsUdInd(?, g_cfg.bvci)) -> value udi {
620 var BssgpDecoded dec := f_dec_bssgp(udi.bssgp);
621 var template OCT4 tlli := f_bssgp_get_tlli(udi.bssgp);
622 if (isvalue(tlli)) {
623 vc_conn := f_tbl_comp_by_tlli(valueof(tlli));
Harald Welte955aa942019-05-03 01:29:29 +0200624 f_send_bssgp_dec(dec, vc_conn);
Harald Welte5ac31492018-02-15 20:39:13 +0100625 } else {
626 log("No TLLI: Broadcasting ", dec);
627 /* broadcast this message to all components */
628 // TITAN DOESN'T DO THIS, *SIGH*: "BSSGP_SP.send(dec) to all component;"
629 for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
630 if (isbound(ClientTable[i].comp_ref)) {
Harald Welte955aa942019-05-03 01:29:29 +0200631 f_send_bssgp_dec(dec, ClientTable[i].comp_ref);
Harald Welte5ac31492018-02-15 20:39:13 +0100632 }
633 }
Harald Welte853c0ad2018-02-15 17:45:29 +0100634 }
Harald Welte1733a382017-07-23 17:26:17 +0200635 }
Harald Welte853c0ad2018-02-15 17:45:29 +0100636
Harald Welte001b0da2019-03-21 21:30:47 +0100637 /* Any other SIG BSSGP message: If it has TLLi, route to component; otherwise broadcast */
638 [] BSCP.receive(f_BnsUdInd(?, 0)) -> value udi {
639 var BssgpDecoded dec := f_dec_bssgp(udi.bssgp);
640 var template OCT4 tlli := f_bssgp_get_tlli(udi.bssgp);
641 if (isvalue(tlli)) {
642 vc_conn := f_tbl_comp_by_tlli(valueof(tlli));
Harald Welte955aa942019-05-03 01:29:29 +0200643 f_send_bssgp_dec(dec, vc_conn, BSSGP_SP_SIG);
Harald Welte001b0da2019-03-21 21:30:47 +0100644 } else {
645 log("No TLLI: Broadcasting ", dec);
646 /* broadcast this message to all components */
647 // TITAN DOESN'T DO THIS, *SIGH*: "BSSGP_SP.send(dec) to all component;"
648 for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
649 if (isbound(ClientTable[i].comp_ref)) {
Oliver Smitha2cf8bd2019-08-30 11:48:00 +0200650 f_send_bssgp_dec(dec, ClientTable[i].comp_ref, BSSGP_SP_SIG);
Harald Welte001b0da2019-03-21 21:30:47 +0100651 }
652 }
653 }
654 }
655
656
Harald Welte1e5a02d2019-05-03 00:50:48 +0200657 /* ConnHdlr sends BSSGP on BVCI=0 port: forward it to BSSGP Codec Port */
Stefan Sperlingf82bbb62018-05-03 19:14:28 +0200658 [] BSSGP_SP_SIG.receive(PDU_BSSGP:?)-> value bs_pdu sender vc_conn {
659 BSCP.send(f_BnsUdReq(bs_pdu, 0));
660 }
661
Harald Welte1e5a02d2019-05-03 00:50:48 +0200662 /* ConnHdlr sends BSSGP on BVCI=PTP port: forward it to BSSGP Codec Port */
Harald Welte5ac31492018-02-15 20:39:13 +0100663 [] BSSGP_SP.receive(PDU_BSSGP:?) -> value bs_pdu sender vc_conn {
664 BSCP.send(f_BnsUdReq(bs_pdu, g_cfg.bvci));
665 }
666
Harald Welte93331e72020-09-12 20:51:05 +0200667#ifdef BSSGP_EM_L3
Harald Welte1e5a02d2019-05-03 00:50:48 +0200668 /* ConnHdlr sends L3: Encode and send as UL_UD / DL_UD */
Harald Welte5ac31492018-02-15 20:39:13 +0100669 [g_cfg.sgsn_role] BSSGP_SP.receive(PDU_L3_SGSN_MS:?) -> value l3_mt sender vc_conn {
670 var integer idx := f_tbl_idx_by_comp(vc_conn);
671 var octetstring l3_enc := enc_PDU_L3_SGSN_MS(l3_mt);
672 var BIT4 sapi := f_llc_sapi_by_l3_mt(l3_mt);
673 var integer n_u := f_llc_get_n_u_tx(ClientTable[idx].llc[bit2int(sapi)]);
674 var octetstring llc_enc := enc_PDU_LLC(valueof(ts_LLC_UI(l3_enc, sapi, '1'B, n_u)));
Harald Welte8d1d8932019-05-03 00:41:41 +0200675 BSCP.send(f_BnsUdReq(ts_BSSGP_DL_UD(ClientTable[idx].tlli, llc_enc), g_cfg.bvci));
Harald Welte5ac31492018-02-15 20:39:13 +0100676 }
Harald Welte425f7822019-05-03 00:48:46 +0200677 [not g_cfg.sgsn_role] BSSGP_SP.receive(PDU_L3_MS_SGSN:?) -> value l3_mo sender vc_conn {
678 var integer idx := f_tbl_idx_by_comp(vc_conn);
679 var octetstring l3_enc := enc_PDU_L3_MS_SGSN(l3_mo);
680 var BIT4 sapi := f_llc_sapi_by_l3_mo(l3_mo);
681 var integer n_u := f_llc_get_n_u_tx(ClientTable[idx].llc[bit2int(sapi)]);
682 var octetstring llc_enc := enc_PDU_LLC(valueof(ts_LLC_UI(l3_enc, sapi, '1'B, n_u)));
683 BSCP.send(f_BnsUdReq(ts_BSSGP_UL_UD(ClientTable[idx].tlli, ClientTable[idx].cell_id, llc_enc), g_cfg.bvci));
684 }
Harald Welte93331e72020-09-12 20:51:05 +0200685#endif
Harald Welte752abba2018-02-18 19:42:17 +0100686
Harald Welte1b85bf32019-05-03 00:49:25 +0200687 /* ConnHdlr sends raw LLC: Encode and send as UL_UD / DL_UD */
688 [not g_cfg.sgsn_role] BSSGP_SP.receive(PDU_LLC:?) -> value llc sender vc_conn {
Harald Welte752abba2018-02-18 19:42:17 +0100689 var integer idx := f_tbl_idx_by_comp(vc_conn);
690 var octetstring llc_enc := enc_PDU_LLC(llc);
691 BSCP.send(f_BnsUdReq(ts_BSSGP_UL_UD(ClientTable[idx].tlli, ClientTable[idx].cell_id, llc_enc), g_cfg.bvci));
692 }
Harald Welte1b85bf32019-05-03 00:49:25 +0200693 [g_cfg.sgsn_role] BSSGP_SP.receive(PDU_LLC:?) -> value llc sender vc_conn {
694 var integer idx := f_tbl_idx_by_comp(vc_conn);
695 var octetstring llc_enc := enc_PDU_LLC(llc);
696 BSCP.send(f_BnsUdReq(ts_BSSGP_DL_UD(ClientTable[idx].tlli, llc_enc), g_cfg.bvci));
697 }
698
Harald Welte853c0ad2018-02-15 17:45:29 +0100699}
700
Alexander Couzenscdfb7512018-07-31 15:37:14 +0200701function f_llc_get_n_u_tx(inout LLC_Entity llc) return uint9_t {
Harald Welte5ac31492018-02-15 20:39:13 +0100702 var uint9_t ret := llc.n_u_tx_next;
703 llc.n_u_tx_next := llc.n_u_tx_next + 1;
704 return ret;
705}
706
Harald Welte93331e72020-09-12 20:51:05 +0200707#ifdef BSSGP_EM_L3
Alexander Couzenscdfb7512018-07-31 15:37:14 +0200708function f_llc_sapi_by_l3_mo(PDU_L3_MS_SGSN l3_mo) return BIT4 {
Harald Welte5ac31492018-02-15 20:39:13 +0100709 if (ischosen(l3_mo.msgs.gprs_mm)) {
710 return c_LLC_SAPI_LLGMM;
711 } else if (ischosen(l3_mo.msgs.gprs_sm)) {
Harald Welted4719012018-02-17 16:45:06 +0100712 return c_LLC_SAPI_LLGMM;
Harald Welte5ac31492018-02-15 20:39:13 +0100713 } else if (ischosen(l3_mo.msgs.sms)) {
714 return c_LLC_SAPI_LLSMS;
715 }
716 setverdict(fail, "No LLC SAPI for ", l3_mo);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200717 mtc.stop;
Harald Welte5ac31492018-02-15 20:39:13 +0100718}
719
720private function f_llc_sapi_by_l3_mt(PDU_L3_SGSN_MS l3_mt) return BIT4 {
721 if (ischosen(l3_mt.msgs.gprs_mm)) {
722 return c_LLC_SAPI_LLGMM;
723 } else if (ischosen(l3_mt.msgs.gprs_sm)) {
Harald Welted4719012018-02-17 16:45:06 +0100724 return c_LLC_SAPI_LLGMM;
Harald Welte5ac31492018-02-15 20:39:13 +0100725 } else if (ischosen(l3_mt.msgs.sms)) {
726 return c_LLC_SAPI_LLSMS;
727 }
728 setverdict(fail, "No LLC SAPI for ", l3_mt);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200729 mtc.stop;
Harald Welte5ac31492018-02-15 20:39:13 +0100730}
Harald Welte93331e72020-09-12 20:51:05 +0200731#endif
Harald Welte5ac31492018-02-15 20:39:13 +0100732
733
734
735private function f_ScanEvents() runs on BSSGP_CT {
736 log("matching against ", tr_BVC_RESET(?, g_cfg.bvci, g_cfg.cell_id));
737
738 while (true) {
739 alt {
740 [g_ptp_bvc_state == BVC_S_BLOCKED] as_blocked();
741 [g_ptp_bvc_state == BVC_S_UNBLOCKED] as_unblocked();
742 [] as_allstate();
743 }
744 } /* while */
745}
746
747/* PDU_BSSGP enhanced with LLC and possibly L3 decoded payloads */
748type record BssgpDecoded {
749 PDU_BSSGP bssgp,
750 PDU_LLC llc optional,
Harald Welte93331e72020-09-12 20:51:05 +0200751#ifdef BSSGP_EM_L3
Harald Welte5ac31492018-02-15 20:39:13 +0100752 PDU_L3_MS_SGSN l3_mo optional,
Harald Weltea2526a82018-02-18 19:03:36 +0100753 PDU_L3_SGSN_MS l3_mt optional,
Harald Welte93331e72020-09-12 20:51:05 +0200754#endif
Harald Weltea2526a82018-02-18 19:03:36 +0100755 PDU_SN sndcp optional
Harald Welte5ac31492018-02-15 20:39:13 +0100756}
757
758/* Decode a PDU_BSSGP into a BssgpDecoded (i.e. with LLC/L3 decoded, as applicable) */
759private function f_dec_bssgp(PDU_BSSGP bssgp) runs on BSSGP_CT return BssgpDecoded {
760 var BssgpDecoded dec := {
761 bssgp := bssgp,
762 llc := omit,
Harald Welte93331e72020-09-12 20:51:05 +0200763#ifdef BSSGP_EM_L3
Harald Welte5ac31492018-02-15 20:39:13 +0100764 l3_mo := omit,
Harald Weltea2526a82018-02-18 19:03:36 +0100765 l3_mt := omit,
Harald Welte93331e72020-09-12 20:51:05 +0200766#endif
Harald Weltea2526a82018-02-18 19:03:36 +0100767 sndcp := omit
Harald Welte5ac31492018-02-15 20:39:13 +0100768 };
769
770 /* Decode LLC, if it is a PDU that contains LLC */
Oliver Smithaac9b9c2019-09-02 08:36:36 +0200771 if (g_cfg.depth >= BSSGP_DECODE_DEPTH_LLC) {
772 if (ischosen(bssgp.pDU_BSSGP_DL_UNITDATA)) {
773 dec.llc := dec_PDU_LLC(bssgp.pDU_BSSGP_DL_UNITDATA.lLC_PDU.lLC_PDU);
774 } else if (ischosen(bssgp.pDU_BSSGP_UL_UNITDATA)) {
775 dec.llc := dec_PDU_LLC(bssgp.pDU_BSSGP_UL_UNITDATA.lLC_PDU.lLC_PDU);
Harald Welte5ac31492018-02-15 20:39:13 +0100776 }
777 }
Harald Weltea2526a82018-02-18 19:03:36 +0100778
779 /* Decode SNDCP, if it is a LLC PDU containing user plane data */
Oliver Smithaac9b9c2019-09-02 08:36:36 +0200780 if (g_cfg.depth >= BSSGP_DECODE_DEPTH_SNDCP) {
781 if (isvalue(dec.llc) and match(dec.llc, tr_LLC_UI_USER)) {
782 dec.sndcp := dec_PDU_SN(dec.llc.pDU_LLC_UI.information_field_UI);
783 }
Harald Weltea2526a82018-02-18 19:03:36 +0100784 }
Oliver Smithaac9b9c2019-09-02 08:36:36 +0200785
Harald Welte93331e72020-09-12 20:51:05 +0200786#ifdef BSSGP_EM_L3
Oliver Smithaac9b9c2019-09-02 08:36:36 +0200787 /* Decode L3, if it is a LLC PDU containing L3 */
788 if (g_cfg.depth >= BSSGP_DECODE_DEPTH_L3) {
789 if (isvalue(dec.llc) and match(dec.llc, tr_LLC_UI_L3)) {
790 if (g_cfg.sgsn_role) {
791 dec.l3_mo := dec_PDU_L3_MS_SGSN(dec.llc.pDU_LLC_UI.information_field_UI);
792 } else {
793 dec.l3_mt := dec_PDU_L3_SGSN_MS(dec.llc.pDU_LLC_UI.information_field_UI);
794 }
795 }
796 }
Harald Welte93331e72020-09-12 20:51:05 +0200797#endif
Oliver Smithaac9b9c2019-09-02 08:36:36 +0200798
Harald Welte5ac31492018-02-15 20:39:13 +0100799 return dec;
800}
801
Alexander Couzens0e510e62018-07-28 23:06:00 +0200802function f_bssgp_client_register(hexstring imsi, OCT4 tlli, BssgpCellId cell_id, BSSGP_PROC_PT PT := BSSGP_PROC[0])
Harald Welte5ac31492018-02-15 20:39:13 +0100803runs on BSSGP_Client_CT {
804 PT.call(BSSGP_register_client:{imsi, tlli, cell_id}) {
805 [] PT.getreply(BSSGP_register_client:{imsi, tlli, cell_id}) {};
806 }
807}
808
Alexander Couzens0e510e62018-07-28 23:06:00 +0200809function f_bssgp_client_unregister(hexstring imsi, BSSGP_PROC_PT PT := BSSGP_PROC[0])
Harald Welte5ac31492018-02-15 20:39:13 +0100810runs on BSSGP_Client_CT {
811 PT.call(BSSGP_unregister_client:{imsi}) {
812 [] PT.getreply(BSSGP_unregister_client:{imsi}) {};
813 }
814}
815
Harald Weltef70997d2018-02-17 10:11:19 +0100816/* TS 44.064 7.2.1.1 LLGMM-ASSIGN */
Alexander Couzens0e510e62018-07-28 23:06:00 +0200817function f_bssgp_client_llgmm_assign(OCT4 tlli_old, OCT4 tlli_new, BSSGP_PROC_PT PT := BSSGP_PROC[0])
Harald Weltef70997d2018-02-17 10:11:19 +0100818runs on BSSGP_Client_CT {
819 PT.call(BSSGP_llgmm_assign:{tlli_old, tlli_new}) {
820 [] PT.getreply(BSSGP_llgmm_assign:{tlli_old, tlli_new}) {};
821 }
822}
823
Harald Welte5ac31492018-02-15 20:39:13 +0100824
Harald Welte1733a382017-07-23 17:26:17 +0200825}