blob: 05a730b98ccb1b512011d065dbcef0aabaadc38e [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
239private function f_sendReset() runs on BSSGP_CT {
Harald Welte5ac31492018-02-15 20:39:13 +0100240 var PDU_BSSGP pdu := valueof(ts_BVC_RESET(BSSGP_CAUSE_OM_INTERVENTION, g_cfg.bvci, g_cfg.cell_id));
Harald Welte853c0ad2018-02-15 17:45:29 +0100241 log("PDU: ", pdu);
242 log("ENC: ", enc_PDU_BSSGP(pdu));
243
244 /* BVC-RESET is always sent via the SIGNALLING BVCI, see Table 5.4.1 */
245 BSCP.send(f_BnsUdReq(pdu, 0));
246 g_T2.start;
247 //f_change_state(BVC_S_WAIT_RESET);
248}
249
250private function f_sendUnblock() runs on BSSGP_CT {
Harald Welte5ac31492018-02-15 20:39:13 +0100251 BSCP.send(f_BnsUdReq(t_BVC_UNBLOCK(g_cfg.bvci), 0));
Harald Welte853c0ad2018-02-15 17:45:29 +0100252 g_T1.start;
253}
254
255private function f_sendBlock(BssgpCause cause) runs on BSSGP_CT {
Harald Welte5ac31492018-02-15 20:39:13 +0100256 BSCP.send(f_BnsUdReq(t_BVC_BLOCK(g_cfg.bvci, cause), 0));
Harald Welte853c0ad2018-02-15 17:45:29 +0100257 g_T1.start;
258}
259
260private function f_sendStatus(BssgpCause cause, PDU_BSSGP pdu) runs on BSSGP_CT {
261 /* FIXME: Make sure correct Signaling or PTP BVCI is used! */
Harald Welte5ac31492018-02-15 20:39:13 +0100262 BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(g_cfg.bvci, cause, pdu), g_cfg.bvci));
263}
264
265/* attempt to extract the TLLI from a BSSGP PDU */
266function f_bssgp_get_tlli(PDU_BSSGP bssgp) return template OCT4 {
267 if (ischosen(bssgp.pDU_BSSGP_DL_UNITDATA)) {
268 return bssgp.pDU_BSSGP_DL_UNITDATA.tLLI_current;
269 } else if (ischosen(bssgp.pDU_BSSGP_UL_UNITDATA)) {
270 return bssgp.pDU_BSSGP_UL_UNITDATA.tLLI;
271 } else if (ischosen(bssgp.pDU_BSSGP_RA_CAPABILITY)) {
272 return bssgp.pDU_BSSGP_RA_CAPABILITY.tLLI.tLLI_Value;
273 } else if (ischosen(bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE)) {
274 return bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE.tLLI.tLLI_Value;
275 } else if (ischosen(bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE_ACK)) {
276 return bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE_ACK.tLLI.tLLI_Value;
277 } else if (ischosen(bssgp.pDU_BSSGP_RADIO_STATUS)) {
278 return bssgp.pDU_BSSGP_RADIO_STATUS.tLLI.tLLI_Value;
279 } else if (ischosen(bssgp.pDU_BSSGP_SUSPEND)) {
280 return bssgp.pDU_BSSGP_SUSPEND.tLLI.tLLI_Value;
281 } else if (ischosen(bssgp.pDU_BSSGP_SUSPEND_ACK)) {
282 return bssgp.pDU_BSSGP_SUSPEND_ACK.tLLI.tLLI_Value;
283 } else if (ischosen(bssgp.pDU_BSSGP_SUSPEND_NACK)) {
284 return bssgp.pDU_BSSGP_SUSPEND_NACK.tLLI.tLLI_Value;
285 } else if (ischosen(bssgp.pDU_BSSGP_RESUME)) {
286 return bssgp.pDU_BSSGP_RESUME.tLLI.tLLI_Value;
287 } else if (ischosen(bssgp.pDU_BSSGP_RESUME_ACK)) {
288 return bssgp.pDU_BSSGP_RESUME_ACK.tLLI.tLLI_Value;
289 } else if (ischosen(bssgp.pDU_BSSGP_RESUME_NACK)) {
290 return bssgp.pDU_BSSGP_RESUME_NACK.tLLI.tLLI_Value;
291 } else if (ischosen(bssgp.pDU_BSSGP_FLUSH_LL)) {
292 return bssgp.pDU_BSSGP_FLUSH_LL.tLLI.tLLI_Value;
293 } else if (ischosen(bssgp.pDU_BSSGP_FLUSH_LL_ACK)) {
294 return bssgp.pDU_BSSGP_FLUSH_LL_ACK.tLLI.tLLI_Value;
295 } else if (ischosen(bssgp.pDU_BSSGP_LLC_DISCARDED)) {
296 return bssgp.pDU_BSSGP_LLC_DISCARDED.tLLI.tLLI_Value;
297 } else if (ischosen(bssgp.pDU_BSSGP_LLC_DISCARDED)) {
298 return bssgp.pDU_BSSGP_LLC_DISCARDED.tLLI.tLLI_Value;
299 } else if (ischosen(bssgp.pDU_BSSGP_PAGING_CS) and
300 isvalue(bssgp.pDU_BSSGP_PAGING_CS.tLLI)) {
301 return bssgp.pDU_BSSGP_PAGING_CS.tLLI.tLLI_Value;
302 } else if (ischosen(bssgp.pDU_BSSGP_FLOW_CONTROL_MS)) {
303 return bssgp.pDU_BSSGP_FLOW_CONTROL_MS.tLLI.tLLI_Value;
304 } else if (ischosen(bssgp.pDU_BSSGP_FLOW_CONTROL_MS_ACK)) {
305 return bssgp.pDU_BSSGP_FLOW_CONTROL_MS_ACK.tLLI.tLLI_Value;
306 }
307 /* TODO: Handover, PFC, LCS */
308 return omit;
309}
310
311/*
312private function f_tbl_init() runs on BSSGP_CT {
313 var integer i;
314 for (i := 0; i < sizeof(ImsiTable); i := i+1) {
315 ImsiTable[i] := -;
316 }
317
318 for (i := 0; i < sizeof(TlliTable); i := i+1) {
319 TlliTable[i] := -;
320 }
321}
322*/
323
324private function f_tbl_client_add(hexstring imsi, OCT4 tlli, BssgpCellId cell_id, BSSGP_Client_CT vc_conn)
325runs on BSSGP_CT {
326 var integer i;
327 for (i := 0; i < sizeof(ClientTable); i := i+1) {
Harald Weltec7872fa2018-02-18 14:06:12 +0100328 if (not isvalue(ClientTable[i].comp_ref)) {
329 log("Adding Client=", vc_conn, ", IMSI=", imsi, ", TLLI=", tlli, ", index=", i);
Harald Welte5ac31492018-02-15 20:39:13 +0100330 ClientTable[i] := {
331 tlli := tlli,
332 tlli_old := omit,
333 imsi := imsi,
334 cell_id := cell_id,
335 comp_ref := vc_conn,
336 llc := -
337 };
338 for (var integer j := 0; j < sizeof(ClientTable[i].llc); j := j+1) {
339 ClientTable[i].llc[j] := valueof(t_LLC_init(g_cfg.sgsn_role));
340 }
341 return;
342 }
343 }
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200344 testcase.stop("Client Table full");
Harald Welte5ac31492018-02-15 20:39:13 +0100345}
346
347private function f_tbl_client_del(hexstring imsi, BSSGP_Client_CT vc_conn) runs on BSSGP_CT {
348 var integer i;
349 for (i := 0; i < sizeof(ClientTable); i := i+1) {
Harald Weltec7872fa2018-02-18 14:06:12 +0100350 if (isvalue(ClientTable[i].imsi) and ClientTable[i].imsi == imsi) {
Harald Welte5ac31492018-02-15 20:39:13 +0100351 if (ClientTable[i].comp_ref != vc_conn) {
Alexander Couzens2c153422018-06-12 18:10:30 +0200352 setverdict(fail, "Cannot unregister index=", i, " IMSI ", imsi, " registred to ",
Harald Welte5ac31492018-02-15 20:39:13 +0100353 ClientTable[i].comp_ref, " from ", vc_conn);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200354 mtc.stop;
Harald Welte5ac31492018-02-15 20:39:13 +0100355 }
356 log("Removing Client IMSI=", imsi, ", index=", i);
Alexander Couzens2c153422018-06-12 18:10:30 +0200357 ClientTable[i] := {
358 tlli := -,
359 tlli_old := omit,
360 imsi := ''H,
361 cell_id := -,
362 comp_ref := null,
363 llc := - };
Harald Welte5ac31492018-02-15 20:39:13 +0100364 return;
365 }
366 }
Alexander Couzens56101c92018-07-31 15:55:34 +0200367 log("Warning: Could not find client for IMSI ", imsi);
368 return;
Harald Welte5ac31492018-02-15 20:39:13 +0100369}
370
Harald Weltef70997d2018-02-17 10:11:19 +0100371/* TS 44.064 7.2.1.1 LLGMM-ASSIGN */
372private function f_tbl_client_llgmm_assign(OCT4 tlli_old, OCT4 tlli_new, BSSGP_Client_CT vc_conn)
373runs on BSSGP_CT {
374 var integer i := f_tbl_idx_by_comp(vc_conn);
375
376 if (tlli_old == 'FFFFFFFF'O and tlli_new != 'FFFFFFFF'O) {
377 /* TLLI assignment */
378 ClientTable[i].tlli := tlli_new;
379 ClientTable[i].tlli_old := omit;
380 } else if (tlli_old != 'FFFFFFFF'O and tlli_new != 'FFFFFFFF'O) {
381 /* TLLI change: both active */
382 ClientTable[i].tlli := tlli_new;
383 ClientTable[i].tlli_old := tlli_old;
384 } else if (tlli_old != 'FFFFFFFF'O and tlli_new == 'FFFFFFFF'O) {
385 /* TLLI unassignment: old shall be unassigned; new stays */
386 ClientTable[i].tlli_old := omit;
387 }
388}
389
Harald Welte5ac31492018-02-15 20:39:13 +0100390private function f_tbl_comp_by_imsi(hexstring imsi) runs on BSSGP_CT return BSSGP_Client_CT {
391 var integer i;
392 for (i := 0; i < sizeof(ClientTable); i := i+1) {
Harald Weltec7872fa2018-02-18 14:06:12 +0100393 if (isvalue(ClientTable[i].imsi) and isvalue(ClientTable[i].comp_ref)
Harald Welte5ac31492018-02-15 20:39:13 +0100394 and ClientTable[i].imsi == imsi) {
395 return ClientTable[i].comp_ref;
396 }
397 }
398 setverdict(fail, "Couldn't find Component for IMSI ", imsi);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200399 mtc.stop;
Harald Welte5ac31492018-02-15 20:39:13 +0100400}
401
402private function f_tbl_comp_by_tlli(OCT4 tlli) runs on BSSGP_CT return BSSGP_Client_CT {
403 var integer i;
404 for (i := 0; i < sizeof(ClientTable); i := i+1) {
Harald Weltec7872fa2018-02-18 14:06:12 +0100405 if (isvalue(ClientTable[i].comp_ref) and
406 (isvalue(ClientTable[i].tlli) and (ClientTable[i].tlli == tlli or
407 isvalue(ClientTable[i].tlli_old) and ClientTable[i].tlli_old == tlli) )) {
Harald Welte5ac31492018-02-15 20:39:13 +0100408 return ClientTable[i].comp_ref;
409 }
410 }
411 setverdict(fail, "Couldn't find Component for TLLI ", tlli);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200412 mtc.stop;
Harald Welte5ac31492018-02-15 20:39:13 +0100413}
414
415private function f_tbl_idx_by_comp(BSSGP_Client_CT comp_ref) runs on BSSGP_CT return integer {
416 var integer i;
417 for (i := 0; i < sizeof(ClientTable); i := i+1) {
Harald Weltec7872fa2018-02-18 14:06:12 +0100418 if (isvalue(ClientTable[i].comp_ref) and ClientTable[i].comp_ref == comp_ref) {
Harald Welte5ac31492018-02-15 20:39:13 +0100419 return i;
420 }
421 }
422 setverdict(fail, "Couldn't find Client for Component ", comp_ref);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200423 mtc.stop;
Harald Welte5ac31492018-02-15 20:39:13 +0100424}
425
426private function f_tbl_tlli_by_comp(BSSGP_Client_CT comp_ref) runs on BSSGP_CT return OCT4 {
427 var integer i;
428 for (i := 0; i < sizeof(ClientTable); i := i+1) {
Harald Weltec7872fa2018-02-18 14:06:12 +0100429 if (isvalue(ClientTable[i].tlli) and isvalue(ClientTable[i].comp_ref)
Harald Welte5ac31492018-02-15 20:39:13 +0100430 and ClientTable[i].comp_ref == comp_ref) {
431 return ClientTable[i].tlli;
432 }
433 }
434 setverdict(fail, "Couldn't find TLLI for Component ", comp_ref);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200435 mtc.stop;
Harald Welte853c0ad2018-02-15 17:45:29 +0100436}
437
438altstep as_allstate() runs on BSSGP_CT {
Harald Welte5ac31492018-02-15 20:39:13 +0100439 var BSSGP_Client_CT vc_conn;
Harald Welte853c0ad2018-02-15 17:45:29 +0100440 var NsUnitdataIndication udi;
441 var NsStatusIndication nsi;
442 var ASP_Event evt;
Harald Welte5ac31492018-02-15 20:39:13 +0100443 var hexstring imsi;
Harald Weltef70997d2018-02-17 10:11:19 +0100444 var OCT4 tlli, tlli_old;
Harald Welte5ac31492018-02-15 20:39:13 +0100445 var BssgpCellId cell_id;
Harald Welte853c0ad2018-02-15 17:45:29 +0100446
447 /* Respond to BLOCK for wrong NSVCI */
448 [] BSCP.receive(f_BnsUdInd(t_BVC_BLOCK(?, ?), 0)) -> value udi {
449 log("Rx BVC-BLOCK for unknown BVCI");
450 f_sendStatus(BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp);
Harald Welte1733a382017-07-23 17:26:17 +0200451 }
452
Harald Welte853c0ad2018-02-15 17:45:29 +0100453 /* Respond to RESET with correct BVCI/CellID */
Harald Welte5ac31492018-02-15 20:39:13 +0100454 [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, g_cfg.bvci, g_cfg.cell_id), 0)) -> value udi {
455 log("Rx BVC-RESET for Our BVCI=", g_cfg.bvci);
456 BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(g_cfg.bvci, g_cfg.cell_id), 0));
Harald Welte853c0ad2018-02-15 17:45:29 +0100457 f_change_state(BVC_S_UNBLOCKED);
Harald Welte1733a382017-07-23 17:26:17 +0200458 }
459
Harald Welte853c0ad2018-02-15 17:45:29 +0100460 /* Respond to RESET for signalling BVCI 0 */
Harald Welte5ac31492018-02-15 20:39:13 +0100461 [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, 0, g_cfg.cell_id), 0)) -> value udi {
Harald Welte853c0ad2018-02-15 17:45:29 +0100462 log("Rx BVC-RESET for Signaling BVCI=0");
Harald Welte5ac31492018-02-15 20:39:13 +0100463 BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(0, g_cfg.cell_id), 0));
Harald Welte1733a382017-07-23 17:26:17 +0200464 }
465
Harald Welte853c0ad2018-02-15 17:45:29 +0100466 /* Respond to RESET with wrong NSEI/NSVCI */
467 [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, ?, ?), 0)) -> value udi {
468 log("Rx BVC-RESET for unknown BVCI");
469 f_sendStatus(BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp);
Harald Welte1733a382017-07-23 17:26:17 +0200470 }
471
Harald Welte853c0ad2018-02-15 17:45:29 +0100472 /* default case of handling unknown PDUs */
473 [] BSCP.receive(f_BnsUdInd(?, ?)) -> value udi {
474 log("Rx Unexpected BSSGP PDU ", udi.bssgp," in state ", g_ptp_bvc_state);
475 f_sendStatus(BSSGP_CAUSE_PDU_NOT_COMPATIBLE_WITH_PROTOCOL_STATE, udi.bssgp);
Harald Welte1733a382017-07-23 17:26:17 +0200476 }
Harald Welte853c0ad2018-02-15 17:45:29 +0100477 /* Forwarding of ASP_Event and NsStatusIndication to user */
Harald Welte5ac31492018-02-15 20:39:13 +0100478 [] BSCP.receive(ASP_Event:?) -> value evt {
479 for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
480 if (isbound(ClientTable[i].comp_ref)) {
481 BSSGP_SP.send(evt) to ClientTable[i].comp_ref;
482 }
483 }
484 }
Harald Welte853c0ad2018-02-15 17:45:29 +0100485 [] BSCP.receive(NsStatusIndication:?) -> value nsi {
486 /* if we just became NS-unblocked, send a BCC-RESET */
487 if (nsi.old_state != NSE_S_ALIVE_UNBLOCKED and nsi.new_state == NSE_S_ALIVE_UNBLOCKED) {
Harald Welte5ac31492018-02-15 20:39:13 +0100488 if (g_cfg.sgsn_role == false) {
Harald Welte853c0ad2018-02-15 17:45:29 +0100489 f_sendReset();
Harald Welte1733a382017-07-23 17:26:17 +0200490 }
Harald Welte5ac31492018-02-15 20:39:13 +0100491 /* Idea: We could send BVC-UNBLOCK here like some SGSN do */
Harald Welte1733a382017-07-23 17:26:17 +0200492 }
Harald Welte5ac31492018-02-15 20:39:13 +0100493 for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
494 if (isbound(ClientTable[i].comp_ref)) {
495 BSSGP_SP.send(nsi) to ClientTable[i].comp_ref;
496 }
497 }
498 }
499
500 [] BSSGP_PROC.getcall(BSSGP_register_client:{?,?,?}) -> param(imsi, tlli, cell_id) sender vc_conn {
501 f_tbl_client_add(imsi, tlli, cell_id, vc_conn);
Harald Weltee32ad992018-05-31 22:17:46 +0200502 BSSGP_PROC.reply(BSSGP_register_client:{imsi, tlli, cell_id}) to vc_conn;
Harald Welte5ac31492018-02-15 20:39:13 +0100503 }
504 [] BSSGP_PROC.getcall(BSSGP_unregister_client:{?}) -> param(imsi) sender vc_conn {
505 f_tbl_client_del(imsi, vc_conn);
Harald Weltee32ad992018-05-31 22:17:46 +0200506 BSSGP_PROC.reply(BSSGP_unregister_client:{imsi}) to vc_conn;
Harald Welte5ac31492018-02-15 20:39:13 +0100507 }
Harald Weltef70997d2018-02-17 10:11:19 +0100508 [] BSSGP_PROC.getcall(BSSGP_llgmm_assign:{?,?}) -> param(tlli_old, tlli) sender vc_conn {
509 f_tbl_client_llgmm_assign(tlli_old, tlli, vc_conn);
Harald Weltee32ad992018-05-31 22:17:46 +0200510 BSSGP_PROC.reply(BSSGP_llgmm_assign:{tlli_old, tlli}) to vc_conn;
Harald Weltef70997d2018-02-17 10:11:19 +0100511 }
512
Harald Welte5ac31492018-02-15 20:39:13 +0100513}
514
515altstep as_blocked() runs on BSSGP_CT {
Harald Weltec27f6842018-03-02 21:40:03 +0100516 [g_T1.running] g_T1.timeout {
Harald Welte5ac31492018-02-15 20:39:13 +0100517 f_sendUnblock();
518 }
519 [] BSCP.receive(f_BnsUdInd(t_BVC_UNBLOCK_ACK(g_cfg.bvci), 0)) {
520 g_T1.stop;
521 f_change_state(BVC_S_UNBLOCKED);
522 }
523 [not g_cfg.sgsn_role] BSCP.receive(f_BnsUdInd(tr_BVC_RESET_ACK(g_cfg.bvci, omit), 0)) {
524 f_sendUnblock();
Harald Welte1733a382017-07-23 17:26:17 +0200525 }
Harald Welte853c0ad2018-02-15 17:45:29 +0100526}
Harald Welte1733a382017-07-23 17:26:17 +0200527
Harald Welte955aa942019-05-03 01:29:29 +0200528private function f_send_bssgp_dec(BssgpDecoded dec, BSSGP_Client_CT vc_conn, BSSGP_SP_PT pt := BSSGP_SP) runs on BSSGP_CT {
529 if (ispresent(dec.l3_mt)) {
530 pt.send(dec.l3_mt) to vc_conn;
531 } else if (ispresent(dec.l3_mo)) {
532 pt.send(dec.l3_mo) to vc_conn;
533 } else if (ispresent(dec.sndcp)) {
534 pt.send(dec.sndcp) to vc_conn;
535 } else if (ispresent(dec.llc)) {
536 pt.send(dec.llc) to vc_conn;
537 } else {
538 pt.send(dec.bssgp) to vc_conn;
539 }
540}
541
542
Harald Welte5ac31492018-02-15 20:39:13 +0100543altstep as_unblocked() runs on BSSGP_CT {
544 var BSSGP_Client_CT vc_conn;
Harald Welte853c0ad2018-02-15 17:45:29 +0100545 var NsUnitdataIndication udi;
546 var PDU_BSSGP bs_pdu;
Harald Welte752abba2018-02-18 19:42:17 +0100547 var PDU_LLC llc;
Harald Welte93331e72020-09-12 20:51:05 +0200548#ifdef BSSGP_EM_L3
Harald Welte5ac31492018-02-15 20:39:13 +0100549 var PDU_L3_MS_SGSN l3_mo;
550 var PDU_L3_SGSN_MS l3_mt;
Harald Welte93331e72020-09-12 20:51:05 +0200551#endif
Harald Welte1733a382017-07-23 17:26:17 +0200552
Harald Welte5ac31492018-02-15 20:39:13 +0100553 /* bogus unblock, just respond with ACK */
554 [] BSCP.receive(f_BnsUdInd(t_BVC_UNBLOCK(g_cfg.bvci), 0)) -> value udi {
555 BSCP.send(f_BnsUdReq(t_BVC_UNBLOCK_ACK(g_cfg.bvci), 0));
556 }
557 /* Respond to BLOCK with BLOCK-ACK + change state */
558 [] BSCP.receive(f_BnsUdInd(t_BVC_BLOCK(g_cfg.bvci, ?), 0)) -> value udi {
559 BSCP.send(f_BnsUdReq(t_BVC_BLOCK_ACK(g_cfg.bvci), 0));
560 g_T1.stop;
561 f_change_state(BVC_S_BLOCKED);
562 }
Harald Weltec27f6842018-03-02 21:40:03 +0100563 [g_T1.running] g_T1.timeout {
Harald Welte5ac31492018-02-15 20:39:13 +0100564 f_sendBlock(BSSGP_CAUSE_OM_INTERVENTION);
565 }
566 [] BSCP.receive(f_BnsUdInd(t_BVC_BLOCK_ACK(g_cfg.bvci), 0)) -> value udi {
567 g_T1.stop;
568 f_change_state(BVC_S_BLOCKED);
569 }
570 [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET_ACK(g_cfg.bvci, g_cfg.cell_id), 0)) -> value udi {
571 g_T2.stop;
572 f_change_state(BVC_S_UNBLOCKED);
573 }
Harald Welte13d391e2017-07-23 19:52:33 +0200574
Harald Welte5ac31492018-02-15 20:39:13 +0100575 /* simply acknowledge all Flow Control Messages */
Harald Welteedcdd902018-03-02 22:04:54 +0100576 [g_cfg.sgsn_role] BSCP.receive(f_BnsUdInd(tr_BVC_FC_BVC, g_cfg.bvci)) -> value udi {
577 var OCT1 tag := udi.bssgp.pDU_BSSGP_FLOW_CONTROL_BVC.tag.unstructured_Value;
578 BSCP.send(f_BnsUdReq(t_BVC_FC_BVC_ACK(tag), g_cfg.bvci));
Harald Welte5ac31492018-02-15 20:39:13 +0100579 }
Harald Welteedcdd902018-03-02 22:04:54 +0100580/*
581 [g_cfg.sgsn_role] BSCP.receive(f_BnsUdInd(t_BVC_FC_MS, g_cfg.bvci)) {
582 BSCP.send(f_BnsUdReq(t_BVC_FC_MS_ACK, g_cfg.bvci));
Harald Welte5ac31492018-02-15 20:39:13 +0100583 }
Harald Weltee0abc472018-02-05 09:13:31 +0100584*/
Harald Welte13d391e2017-07-23 19:52:33 +0200585
Harald Welte5ac31492018-02-15 20:39:13 +0100586 /* FIXME: CS PAGING: dispatch by IMSI */
Harald Welte1733a382017-07-23 17:26:17 +0200587
Harald Welte5ac31492018-02-15 20:39:13 +0100588 /* PS PAGING: dispatch by IMSI */
589 [] BSCP.receive(f_BnsUdInd(tr_BSSGP_PS_PAGING(g_cfg.bvci), g_cfg.bvci)) -> value udi {
590 var hexstring imsi := udi.bssgp.pDU_BSSGP_PAGING_PS.iMSI.digits
591 vc_conn := f_tbl_comp_by_imsi(imsi);
Harald Welte955aa942019-05-03 01:29:29 +0200592 f_send_bssgp_dec(f_dec_bssgp(udi.bssgp), vc_conn);
Harald Welte5ac31492018-02-15 20:39:13 +0100593 }
594
Harald Welte001b0da2019-03-21 21:30:47 +0100595 /* Any other PTP BSSGP message: If it has TLLi, route to component; otherwise broadcast */
Harald Welte5ac31492018-02-15 20:39:13 +0100596 [] BSCP.receive(f_BnsUdInd(?, g_cfg.bvci)) -> value udi {
597 var BssgpDecoded dec := f_dec_bssgp(udi.bssgp);
598 var template OCT4 tlli := f_bssgp_get_tlli(udi.bssgp);
599 if (isvalue(tlli)) {
600 vc_conn := f_tbl_comp_by_tlli(valueof(tlli));
Harald Welte955aa942019-05-03 01:29:29 +0200601 f_send_bssgp_dec(dec, vc_conn);
Harald Welte5ac31492018-02-15 20:39:13 +0100602 } else {
603 log("No TLLI: Broadcasting ", dec);
604 /* broadcast this message to all components */
605 // TITAN DOESN'T DO THIS, *SIGH*: "BSSGP_SP.send(dec) to all component;"
606 for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
607 if (isbound(ClientTable[i].comp_ref)) {
Harald Welte955aa942019-05-03 01:29:29 +0200608 f_send_bssgp_dec(dec, ClientTable[i].comp_ref);
Harald Welte5ac31492018-02-15 20:39:13 +0100609 }
610 }
Harald Welte853c0ad2018-02-15 17:45:29 +0100611 }
Harald Welte1733a382017-07-23 17:26:17 +0200612 }
Harald Welte853c0ad2018-02-15 17:45:29 +0100613
Harald Welte001b0da2019-03-21 21:30:47 +0100614 /* Any other SIG BSSGP message: If it has TLLi, route to component; otherwise broadcast */
615 [] BSCP.receive(f_BnsUdInd(?, 0)) -> value udi {
616 var BssgpDecoded dec := f_dec_bssgp(udi.bssgp);
617 var template OCT4 tlli := f_bssgp_get_tlli(udi.bssgp);
618 if (isvalue(tlli)) {
619 vc_conn := f_tbl_comp_by_tlli(valueof(tlli));
Harald Welte955aa942019-05-03 01:29:29 +0200620 f_send_bssgp_dec(dec, vc_conn, BSSGP_SP_SIG);
Harald Welte001b0da2019-03-21 21:30:47 +0100621 } else {
622 log("No TLLI: Broadcasting ", dec);
623 /* broadcast this message to all components */
624 // TITAN DOESN'T DO THIS, *SIGH*: "BSSGP_SP.send(dec) to all component;"
625 for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
626 if (isbound(ClientTable[i].comp_ref)) {
Oliver Smitha2cf8bd2019-08-30 11:48:00 +0200627 f_send_bssgp_dec(dec, ClientTable[i].comp_ref, BSSGP_SP_SIG);
Harald Welte001b0da2019-03-21 21:30:47 +0100628 }
629 }
630 }
631 }
632
633
Harald Welte1e5a02d2019-05-03 00:50:48 +0200634 /* ConnHdlr sends BSSGP on BVCI=0 port: forward it to BSSGP Codec Port */
Stefan Sperlingf82bbb62018-05-03 19:14:28 +0200635 [] BSSGP_SP_SIG.receive(PDU_BSSGP:?)-> value bs_pdu sender vc_conn {
636 BSCP.send(f_BnsUdReq(bs_pdu, 0));
637 }
638
Harald Welte1e5a02d2019-05-03 00:50:48 +0200639 /* ConnHdlr sends BSSGP on BVCI=PTP port: forward it to BSSGP Codec Port */
Harald Welte5ac31492018-02-15 20:39:13 +0100640 [] BSSGP_SP.receive(PDU_BSSGP:?) -> value bs_pdu sender vc_conn {
641 BSCP.send(f_BnsUdReq(bs_pdu, g_cfg.bvci));
642 }
643
Harald Welte93331e72020-09-12 20:51:05 +0200644#ifdef BSSGP_EM_L3
Harald Welte1e5a02d2019-05-03 00:50:48 +0200645 /* ConnHdlr sends L3: Encode and send as UL_UD / DL_UD */
Harald Welte5ac31492018-02-15 20:39:13 +0100646 [g_cfg.sgsn_role] BSSGP_SP.receive(PDU_L3_SGSN_MS:?) -> value l3_mt sender vc_conn {
647 var integer idx := f_tbl_idx_by_comp(vc_conn);
648 var octetstring l3_enc := enc_PDU_L3_SGSN_MS(l3_mt);
649 var BIT4 sapi := f_llc_sapi_by_l3_mt(l3_mt);
650 var integer n_u := f_llc_get_n_u_tx(ClientTable[idx].llc[bit2int(sapi)]);
651 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 +0200652 BSCP.send(f_BnsUdReq(ts_BSSGP_DL_UD(ClientTable[idx].tlli, llc_enc), g_cfg.bvci));
Harald Welte5ac31492018-02-15 20:39:13 +0100653 }
Harald Welte425f7822019-05-03 00:48:46 +0200654 [not g_cfg.sgsn_role] BSSGP_SP.receive(PDU_L3_MS_SGSN:?) -> value l3_mo sender vc_conn {
655 var integer idx := f_tbl_idx_by_comp(vc_conn);
656 var octetstring l3_enc := enc_PDU_L3_MS_SGSN(l3_mo);
657 var BIT4 sapi := f_llc_sapi_by_l3_mo(l3_mo);
658 var integer n_u := f_llc_get_n_u_tx(ClientTable[idx].llc[bit2int(sapi)]);
659 var octetstring llc_enc := enc_PDU_LLC(valueof(ts_LLC_UI(l3_enc, sapi, '1'B, n_u)));
660 BSCP.send(f_BnsUdReq(ts_BSSGP_UL_UD(ClientTable[idx].tlli, ClientTable[idx].cell_id, llc_enc), g_cfg.bvci));
661 }
Harald Welte93331e72020-09-12 20:51:05 +0200662#endif
Harald Welte752abba2018-02-18 19:42:17 +0100663
Harald Welte1b85bf32019-05-03 00:49:25 +0200664 /* ConnHdlr sends raw LLC: Encode and send as UL_UD / DL_UD */
665 [not g_cfg.sgsn_role] BSSGP_SP.receive(PDU_LLC:?) -> value llc sender vc_conn {
Harald Welte752abba2018-02-18 19:42:17 +0100666 var integer idx := f_tbl_idx_by_comp(vc_conn);
667 var octetstring llc_enc := enc_PDU_LLC(llc);
668 BSCP.send(f_BnsUdReq(ts_BSSGP_UL_UD(ClientTable[idx].tlli, ClientTable[idx].cell_id, llc_enc), g_cfg.bvci));
669 }
Harald Welte1b85bf32019-05-03 00:49:25 +0200670 [g_cfg.sgsn_role] BSSGP_SP.receive(PDU_LLC:?) -> value llc sender vc_conn {
671 var integer idx := f_tbl_idx_by_comp(vc_conn);
672 var octetstring llc_enc := enc_PDU_LLC(llc);
673 BSCP.send(f_BnsUdReq(ts_BSSGP_DL_UD(ClientTable[idx].tlli, llc_enc), g_cfg.bvci));
674 }
675
Harald Welte853c0ad2018-02-15 17:45:29 +0100676}
677
Alexander Couzenscdfb7512018-07-31 15:37:14 +0200678function f_llc_get_n_u_tx(inout LLC_Entity llc) return uint9_t {
Harald Welte5ac31492018-02-15 20:39:13 +0100679 var uint9_t ret := llc.n_u_tx_next;
680 llc.n_u_tx_next := llc.n_u_tx_next + 1;
681 return ret;
682}
683
Harald Welte93331e72020-09-12 20:51:05 +0200684#ifdef BSSGP_EM_L3
Alexander Couzenscdfb7512018-07-31 15:37:14 +0200685function f_llc_sapi_by_l3_mo(PDU_L3_MS_SGSN l3_mo) return BIT4 {
Harald Welte5ac31492018-02-15 20:39:13 +0100686 if (ischosen(l3_mo.msgs.gprs_mm)) {
687 return c_LLC_SAPI_LLGMM;
688 } else if (ischosen(l3_mo.msgs.gprs_sm)) {
Harald Welted4719012018-02-17 16:45:06 +0100689 return c_LLC_SAPI_LLGMM;
Harald Welte5ac31492018-02-15 20:39:13 +0100690 } else if (ischosen(l3_mo.msgs.sms)) {
691 return c_LLC_SAPI_LLSMS;
692 }
693 setverdict(fail, "No LLC SAPI for ", l3_mo);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200694 mtc.stop;
Harald Welte5ac31492018-02-15 20:39:13 +0100695}
696
697private function f_llc_sapi_by_l3_mt(PDU_L3_SGSN_MS l3_mt) return BIT4 {
698 if (ischosen(l3_mt.msgs.gprs_mm)) {
699 return c_LLC_SAPI_LLGMM;
700 } else if (ischosen(l3_mt.msgs.gprs_sm)) {
Harald Welted4719012018-02-17 16:45:06 +0100701 return c_LLC_SAPI_LLGMM;
Harald Welte5ac31492018-02-15 20:39:13 +0100702 } else if (ischosen(l3_mt.msgs.sms)) {
703 return c_LLC_SAPI_LLSMS;
704 }
705 setverdict(fail, "No LLC SAPI for ", l3_mt);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200706 mtc.stop;
Harald Welte5ac31492018-02-15 20:39:13 +0100707}
Harald Welte93331e72020-09-12 20:51:05 +0200708#endif
Harald Welte5ac31492018-02-15 20:39:13 +0100709
710
711
712private function f_ScanEvents() runs on BSSGP_CT {
713 log("matching against ", tr_BVC_RESET(?, g_cfg.bvci, g_cfg.cell_id));
714
715 while (true) {
716 alt {
717 [g_ptp_bvc_state == BVC_S_BLOCKED] as_blocked();
718 [g_ptp_bvc_state == BVC_S_UNBLOCKED] as_unblocked();
719 [] as_allstate();
720 }
721 } /* while */
722}
723
724/* PDU_BSSGP enhanced with LLC and possibly L3 decoded payloads */
725type record BssgpDecoded {
726 PDU_BSSGP bssgp,
727 PDU_LLC llc optional,
Harald Welte93331e72020-09-12 20:51:05 +0200728#ifdef BSSGP_EM_L3
Harald Welte5ac31492018-02-15 20:39:13 +0100729 PDU_L3_MS_SGSN l3_mo optional,
Harald Weltea2526a82018-02-18 19:03:36 +0100730 PDU_L3_SGSN_MS l3_mt optional,
Harald Welte93331e72020-09-12 20:51:05 +0200731#endif
Harald Weltea2526a82018-02-18 19:03:36 +0100732 PDU_SN sndcp optional
Harald Welte5ac31492018-02-15 20:39:13 +0100733}
734
735/* Decode a PDU_BSSGP into a BssgpDecoded (i.e. with LLC/L3 decoded, as applicable) */
736private function f_dec_bssgp(PDU_BSSGP bssgp) runs on BSSGP_CT return BssgpDecoded {
737 var BssgpDecoded dec := {
738 bssgp := bssgp,
739 llc := omit,
Harald Welte93331e72020-09-12 20:51:05 +0200740#ifdef BSSGP_EM_L3
Harald Welte5ac31492018-02-15 20:39:13 +0100741 l3_mo := omit,
Harald Weltea2526a82018-02-18 19:03:36 +0100742 l3_mt := omit,
Harald Welte93331e72020-09-12 20:51:05 +0200743#endif
Harald Weltea2526a82018-02-18 19:03:36 +0100744 sndcp := omit
Harald Welte5ac31492018-02-15 20:39:13 +0100745 };
746
747 /* Decode LLC, if it is a PDU that contains LLC */
Oliver Smithaac9b9c2019-09-02 08:36:36 +0200748 if (g_cfg.depth >= BSSGP_DECODE_DEPTH_LLC) {
749 if (ischosen(bssgp.pDU_BSSGP_DL_UNITDATA)) {
750 dec.llc := dec_PDU_LLC(bssgp.pDU_BSSGP_DL_UNITDATA.lLC_PDU.lLC_PDU);
751 } else if (ischosen(bssgp.pDU_BSSGP_UL_UNITDATA)) {
752 dec.llc := dec_PDU_LLC(bssgp.pDU_BSSGP_UL_UNITDATA.lLC_PDU.lLC_PDU);
Harald Welte5ac31492018-02-15 20:39:13 +0100753 }
754 }
Harald Weltea2526a82018-02-18 19:03:36 +0100755
756 /* Decode SNDCP, if it is a LLC PDU containing user plane data */
Oliver Smithaac9b9c2019-09-02 08:36:36 +0200757 if (g_cfg.depth >= BSSGP_DECODE_DEPTH_SNDCP) {
758 if (isvalue(dec.llc) and match(dec.llc, tr_LLC_UI_USER)) {
759 dec.sndcp := dec_PDU_SN(dec.llc.pDU_LLC_UI.information_field_UI);
760 }
Harald Weltea2526a82018-02-18 19:03:36 +0100761 }
Oliver Smithaac9b9c2019-09-02 08:36:36 +0200762
Harald Welte93331e72020-09-12 20:51:05 +0200763#ifdef BSSGP_EM_L3
Oliver Smithaac9b9c2019-09-02 08:36:36 +0200764 /* Decode L3, if it is a LLC PDU containing L3 */
765 if (g_cfg.depth >= BSSGP_DECODE_DEPTH_L3) {
766 if (isvalue(dec.llc) and match(dec.llc, tr_LLC_UI_L3)) {
767 if (g_cfg.sgsn_role) {
768 dec.l3_mo := dec_PDU_L3_MS_SGSN(dec.llc.pDU_LLC_UI.information_field_UI);
769 } else {
770 dec.l3_mt := dec_PDU_L3_SGSN_MS(dec.llc.pDU_LLC_UI.information_field_UI);
771 }
772 }
773 }
Harald Welte93331e72020-09-12 20:51:05 +0200774#endif
Oliver Smithaac9b9c2019-09-02 08:36:36 +0200775
Harald Welte5ac31492018-02-15 20:39:13 +0100776 return dec;
777}
778
Alexander Couzens0e510e62018-07-28 23:06:00 +0200779function 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 +0100780runs on BSSGP_Client_CT {
781 PT.call(BSSGP_register_client:{imsi, tlli, cell_id}) {
782 [] PT.getreply(BSSGP_register_client:{imsi, tlli, cell_id}) {};
783 }
784}
785
Alexander Couzens0e510e62018-07-28 23:06:00 +0200786function f_bssgp_client_unregister(hexstring imsi, BSSGP_PROC_PT PT := BSSGP_PROC[0])
Harald Welte5ac31492018-02-15 20:39:13 +0100787runs on BSSGP_Client_CT {
788 PT.call(BSSGP_unregister_client:{imsi}) {
789 [] PT.getreply(BSSGP_unregister_client:{imsi}) {};
790 }
791}
792
Harald Weltef70997d2018-02-17 10:11:19 +0100793/* TS 44.064 7.2.1.1 LLGMM-ASSIGN */
Alexander Couzens0e510e62018-07-28 23:06:00 +0200794function 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 +0100795runs on BSSGP_Client_CT {
796 PT.call(BSSGP_llgmm_assign:{tlli_old, tlli_new}) {
797 [] PT.getreply(BSSGP_llgmm_assign:{tlli_old, tlli_new}) {};
798 }
799}
800
Harald Welte5ac31492018-02-15 20:39:13 +0100801
Harald Welte1733a382017-07-23 17:26:17 +0200802}