blob: 5b5628e8875b3c572f8e541e8f10f7cdedd92521 [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 Welte5ac31492018-02-15 20:39:13 +010021import from MobileL3_GMM_SM_Types all;
22import from MobileL3_Types all;
23
24import from LLC_Types all;
25import from LLC_Templates all;
26
Harald Weltea2526a82018-02-18 19:03:36 +010027import from SNDCP_Types all;
28
Harald Welte5ac31492018-02-15 20:39:13 +010029/***********************************************************************
30 * Communication between Client Components and Main Component
31 ***********************************************************************/
32
Harald Welte853c0ad2018-02-15 17:45:29 +010033type record BssgpStatusIndication {
34 Nsei nsei,
35 BssgpBvci bvci,
36 BvcState state
37}
38
39template BssgpStatusIndication t_BssgpStsInd(template Nsei nsei, template BssgpBvci bvci, template BvcState state) := {
40 nsei := nsei,
41 bvci := bvci,
42 state := state
43}
44
45type enumerated BvcState {
46 BVC_S_BLOCKED,
47 BVC_S_UNBLOCKED
48};
49
50/* port from our (internal) point of view */
51type port BSSGP_SP_PT message {
Harald Welte5ac31492018-02-15 20:39:13 +010052 in PDU_BSSGP,
Harald Welte752abba2018-02-18 19:42:17 +010053 PDU_LLC,
Harald Welte5ac31492018-02-15 20:39:13 +010054 PDU_L3_MS_SGSN,
55 PDU_L3_SGSN_MS;
56 out BssgpDecoded,
Harald Welte853c0ad2018-02-15 17:45:29 +010057 NsStatusIndication,
58 BssgpStatusIndication,
Harald Welte5ac31492018-02-15 20:39:13 +010059 ASP_Event,
60 PDU_L3_MS_SGSN,
61 PDU_L3_SGSN_MS;
Harald Welte853c0ad2018-02-15 17:45:29 +010062} with { extension "internal" };
63
64/* port from the user point of view */
65type port BSSGP_PT message {
66 in ASP_Event,
67 NsStatusIndication,
68 BssgpStatusIndication,
Harald Welte5ac31492018-02-15 20:39:13 +010069 BssgpDecoded,
70 PDU_L3_MS_SGSN,
71 PDU_L3_SGSN_MS;
72 out PDU_BSSGP,
Harald Welte752abba2018-02-18 19:42:17 +010073 PDU_LLC,
Harald Welte5ac31492018-02-15 20:39:13 +010074 PDU_L3_SGSN_MS,
75 PDU_L3_MS_SGSN;
Harald Welte853c0ad2018-02-15 17:45:29 +010076} with { extension "internal" };
77
Harald Welte5ac31492018-02-15 20:39:13 +010078signature BSSGP_register_client(hexstring imsi, OCT4 tlli, BssgpCellId cell_id);
79signature BSSGP_unregister_client(hexstring imsi);
Harald Weltef70997d2018-02-17 10:11:19 +010080signature BSSGP_llgmm_assign(OCT4 tlli_old, OCT4 tlli);
Harald Welte5ac31492018-02-15 20:39:13 +010081
82type port BSSGP_PROC_PT procedure {
Harald Weltef70997d2018-02-17 10:11:19 +010083 inout BSSGP_register_client, BSSGP_unregister_client, BSSGP_llgmm_assign;
Harald Welte5ac31492018-02-15 20:39:13 +010084} with { extension "internal" };
85
86
87/***********************************************************************
88 * Client Component for a single MS/TLLI
89 ***********************************************************************/
90
91type component BSSGP_Client_CT {
Alexander Couzens0e510e62018-07-28 23:06:00 +020092 port BSSGP_PT BSSGP[3];
93 port BSSGP_PT BSSGP_SIG[3];
94 port BSSGP_PROC_PT BSSGP_PROC[3];
Harald Welte5ac31492018-02-15 20:39:13 +010095};
96
97/***********************************************************************
98 * Main Component
99 ***********************************************************************/
100
101function BssgpStart(BssgpConfig cfg) runs on BSSGP_CT {
102 g_cfg := cfg;
Harald Welte853c0ad2018-02-15 17:45:29 +0100103 f_init();
104 f_ScanEvents();
105}
106
107private function f_init() runs on BSSGP_CT {
108 /* Connect the UDP socket */
109 f_change_state(BVC_S_BLOCKED);
110}
111
112type component BSSGP_CT {
Stefan Sperlingf82bbb62018-05-03 19:14:28 +0200113 /* UDP ports towards the bottom (IUT) */
Harald Welte853c0ad2018-02-15 17:45:29 +0100114 port NS_PT BSCP;
115 /* NS-User SAP towards the user */
116 port BSSGP_SP_PT BSSGP_SP;
Stefan Sperlingf82bbb62018-05-03 19:14:28 +0200117 port BSSGP_SP_PT BSSGP_SP_SIG;
Harald Welte5ac31492018-02-15 20:39:13 +0100118 port BSSGP_PROC_PT BSSGP_PROC;
Harald Welte853c0ad2018-02-15 17:45:29 +0100119
Harald Welte5ac31492018-02-15 20:39:13 +0100120 var BssgpConfig g_cfg;
121
Harald Welte853c0ad2018-02-15 17:45:29 +0100122 var BvcState g_ptp_bvc_state := BVC_S_BLOCKED;
123 timer g_T1 := 15.0;
124 timer g_T2 := 60.0;
Harald Welte5ac31492018-02-15 20:39:13 +0100125
126 var ClientEntity ClientTable[16];
Harald Welte853c0ad2018-02-15 17:45:29 +0100127}
128
Alexander Couzens6b449fb2018-07-31 14:19:36 +0200129type record length(16) of LLC_Entity LLC_Entities;
130
Harald Welte5ac31492018-02-15 20:39:13 +0100131type record ClientEntity {
132 OCT4 tlli,
133 OCT4 tlli_old optional,
134 hexstring imsi,
135 BssgpCellId cell_id,
136 BSSGP_Client_CT comp_ref,
137 /* LLC entities, one for each SAPI */
138 LLC_Entity llc[16]
Harald Welte853c0ad2018-02-15 17:45:29 +0100139};
140
Harald Welte5ac31492018-02-15 20:39:13 +0100141type record LLC_Entity {
142 boolean sgsn_role,
143 /* N(U) on transmit side for next PDU */
144 uint9_t n_u_tx_next,
145 /* N(U) on receive side, last PDU */
146 uint9_t n_u_rx_last optional
147};
148
Alexander Couzenscdfb7512018-07-31 15:37:14 +0200149function f_llc_create(boolean sgsn_role := false) return LLC_Entities {
150 var LLC_Entities llc;
151 for (var integer i := 0; i < 16; i := i+1) {
152 llc[i] := valueof(t_LLC_init(sgsn_role));
153 }
154 return llc;
155}
156
Harald Welte5ac31492018-02-15 20:39:13 +0100157private template LLC_Entity t_LLC_init(boolean sgsn_role := false) := {
158 sgsn_role := sgsn_role,
159 n_u_tx_next := 0,
160 n_u_rx_last := -
161}
162
163type record BssgpConfig {
164 Nsvci nsei,
165 Nsvci bvci,
166 BssgpCellId cell_id,
167 boolean sgsn_role
168};
169
170function f_BnsUdReq(template PDU_BSSGP pdu, BssgpBvci bvci)
171runs on BSSGP_CT return NsUnitdataRequest {
Harald Welte853c0ad2018-02-15 17:45:29 +0100172 var NsUnitdataRequest udr := {
Harald Welte1733a382017-07-23 17:26:17 +0200173 bvci := bvci,
Harald Welte5ac31492018-02-15 20:39:13 +0100174 nsei := g_cfg.nsei,
Harald Welte853c0ad2018-02-15 17:45:29 +0100175 /* for some weird reason we get "Dynamic test case error: Text encoder: Encoding an
176 * unbound integer value." when trying to send the reocrd rather than the octetstring */
177 //sdu := omit,
178 //bssgp := valueof(pdu)
179 sdu := enc_PDU_BSSGP(valueof(pdu)),
180 bssgp := omit
181 }
182 return udr;
183}
184
Harald Welte5ac31492018-02-15 20:39:13 +0100185function f_BnsUdInd(template PDU_BSSGP pdu, template BssgpBvci bvci)
186runs on BSSGP_CT return template NsUnitdataIndication {
Harald Welte853c0ad2018-02-15 17:45:29 +0100187 var template NsUnitdataIndication udi := {
188 bvci := bvci,
Harald Welte5ac31492018-02-15 20:39:13 +0100189 nsei := g_cfg.nsei,
Harald Welte853c0ad2018-02-15 17:45:29 +0100190 sdu := *,
191 bssgp := pdu
192 }
193 return udi;
194}
195
196private function f_change_state(BvcState new_state) runs on BSSGP_CT {
197 log("BSSGP State Transition: ", g_ptp_bvc_state, " -> ", new_state);
198 g_ptp_bvc_state := new_state;
Harald Welte5ac31492018-02-15 20:39:13 +0100199 for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
200 if (isbound(ClientTable[i].comp_ref)) {
201 BSSGP_SP.send(t_BssgpStsInd(g_cfg.nsei, g_cfg.bvci, g_ptp_bvc_state)) to ClientTable[i].comp_ref;
202 }
203 }
Harald Welte853c0ad2018-02-15 17:45:29 +0100204}
205
206private function f_sendReset() runs on BSSGP_CT {
Harald Welte5ac31492018-02-15 20:39:13 +0100207 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 +0100208 log("PDU: ", pdu);
209 log("ENC: ", enc_PDU_BSSGP(pdu));
210
211 /* BVC-RESET is always sent via the SIGNALLING BVCI, see Table 5.4.1 */
212 BSCP.send(f_BnsUdReq(pdu, 0));
213 g_T2.start;
214 //f_change_state(BVC_S_WAIT_RESET);
215}
216
217private function f_sendUnblock() runs on BSSGP_CT {
Harald Welte5ac31492018-02-15 20:39:13 +0100218 BSCP.send(f_BnsUdReq(t_BVC_UNBLOCK(g_cfg.bvci), 0));
Harald Welte853c0ad2018-02-15 17:45:29 +0100219 g_T1.start;
220}
221
222private function f_sendBlock(BssgpCause cause) runs on BSSGP_CT {
Harald Welte5ac31492018-02-15 20:39:13 +0100223 BSCP.send(f_BnsUdReq(t_BVC_BLOCK(g_cfg.bvci, cause), 0));
Harald Welte853c0ad2018-02-15 17:45:29 +0100224 g_T1.start;
225}
226
227private function f_sendStatus(BssgpCause cause, PDU_BSSGP pdu) runs on BSSGP_CT {
228 /* FIXME: Make sure correct Signaling or PTP BVCI is used! */
Harald Welte5ac31492018-02-15 20:39:13 +0100229 BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(g_cfg.bvci, cause, pdu), g_cfg.bvci));
230}
231
232/* attempt to extract the TLLI from a BSSGP PDU */
233function f_bssgp_get_tlli(PDU_BSSGP bssgp) return template OCT4 {
234 if (ischosen(bssgp.pDU_BSSGP_DL_UNITDATA)) {
235 return bssgp.pDU_BSSGP_DL_UNITDATA.tLLI_current;
236 } else if (ischosen(bssgp.pDU_BSSGP_UL_UNITDATA)) {
237 return bssgp.pDU_BSSGP_UL_UNITDATA.tLLI;
238 } else if (ischosen(bssgp.pDU_BSSGP_RA_CAPABILITY)) {
239 return bssgp.pDU_BSSGP_RA_CAPABILITY.tLLI.tLLI_Value;
240 } else if (ischosen(bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE)) {
241 return bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE.tLLI.tLLI_Value;
242 } else if (ischosen(bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE_ACK)) {
243 return bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE_ACK.tLLI.tLLI_Value;
244 } else if (ischosen(bssgp.pDU_BSSGP_RADIO_STATUS)) {
245 return bssgp.pDU_BSSGP_RADIO_STATUS.tLLI.tLLI_Value;
246 } else if (ischosen(bssgp.pDU_BSSGP_SUSPEND)) {
247 return bssgp.pDU_BSSGP_SUSPEND.tLLI.tLLI_Value;
248 } else if (ischosen(bssgp.pDU_BSSGP_SUSPEND_ACK)) {
249 return bssgp.pDU_BSSGP_SUSPEND_ACK.tLLI.tLLI_Value;
250 } else if (ischosen(bssgp.pDU_BSSGP_SUSPEND_NACK)) {
251 return bssgp.pDU_BSSGP_SUSPEND_NACK.tLLI.tLLI_Value;
252 } else if (ischosen(bssgp.pDU_BSSGP_RESUME)) {
253 return bssgp.pDU_BSSGP_RESUME.tLLI.tLLI_Value;
254 } else if (ischosen(bssgp.pDU_BSSGP_RESUME_ACK)) {
255 return bssgp.pDU_BSSGP_RESUME_ACK.tLLI.tLLI_Value;
256 } else if (ischosen(bssgp.pDU_BSSGP_RESUME_NACK)) {
257 return bssgp.pDU_BSSGP_RESUME_NACK.tLLI.tLLI_Value;
258 } else if (ischosen(bssgp.pDU_BSSGP_FLUSH_LL)) {
259 return bssgp.pDU_BSSGP_FLUSH_LL.tLLI.tLLI_Value;
260 } else if (ischosen(bssgp.pDU_BSSGP_FLUSH_LL_ACK)) {
261 return bssgp.pDU_BSSGP_FLUSH_LL_ACK.tLLI.tLLI_Value;
262 } else if (ischosen(bssgp.pDU_BSSGP_LLC_DISCARDED)) {
263 return bssgp.pDU_BSSGP_LLC_DISCARDED.tLLI.tLLI_Value;
264 } else if (ischosen(bssgp.pDU_BSSGP_LLC_DISCARDED)) {
265 return bssgp.pDU_BSSGP_LLC_DISCARDED.tLLI.tLLI_Value;
266 } else if (ischosen(bssgp.pDU_BSSGP_PAGING_CS) and
267 isvalue(bssgp.pDU_BSSGP_PAGING_CS.tLLI)) {
268 return bssgp.pDU_BSSGP_PAGING_CS.tLLI.tLLI_Value;
269 } else if (ischosen(bssgp.pDU_BSSGP_FLOW_CONTROL_MS)) {
270 return bssgp.pDU_BSSGP_FLOW_CONTROL_MS.tLLI.tLLI_Value;
271 } else if (ischosen(bssgp.pDU_BSSGP_FLOW_CONTROL_MS_ACK)) {
272 return bssgp.pDU_BSSGP_FLOW_CONTROL_MS_ACK.tLLI.tLLI_Value;
273 }
274 /* TODO: Handover, PFC, LCS */
275 return omit;
276}
277
278/*
279private function f_tbl_init() runs on BSSGP_CT {
280 var integer i;
281 for (i := 0; i < sizeof(ImsiTable); i := i+1) {
282 ImsiTable[i] := -;
283 }
284
285 for (i := 0; i < sizeof(TlliTable); i := i+1) {
286 TlliTable[i] := -;
287 }
288}
289*/
290
291private function f_tbl_client_add(hexstring imsi, OCT4 tlli, BssgpCellId cell_id, BSSGP_Client_CT vc_conn)
292runs on BSSGP_CT {
293 var integer i;
294 for (i := 0; i < sizeof(ClientTable); i := i+1) {
Harald Weltec7872fa2018-02-18 14:06:12 +0100295 if (not isvalue(ClientTable[i].comp_ref)) {
296 log("Adding Client=", vc_conn, ", IMSI=", imsi, ", TLLI=", tlli, ", index=", i);
Harald Welte5ac31492018-02-15 20:39:13 +0100297 ClientTable[i] := {
298 tlli := tlli,
299 tlli_old := omit,
300 imsi := imsi,
301 cell_id := cell_id,
302 comp_ref := vc_conn,
303 llc := -
304 };
305 for (var integer j := 0; j < sizeof(ClientTable[i].llc); j := j+1) {
306 ClientTable[i].llc[j] := valueof(t_LLC_init(g_cfg.sgsn_role));
307 }
308 return;
309 }
310 }
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200311 testcase.stop("Client Table full");
Harald Welte5ac31492018-02-15 20:39:13 +0100312}
313
314private function f_tbl_client_del(hexstring imsi, BSSGP_Client_CT vc_conn) runs on BSSGP_CT {
315 var integer i;
316 for (i := 0; i < sizeof(ClientTable); i := i+1) {
Harald Weltec7872fa2018-02-18 14:06:12 +0100317 if (isvalue(ClientTable[i].imsi) and ClientTable[i].imsi == imsi) {
Harald Welte5ac31492018-02-15 20:39:13 +0100318 if (ClientTable[i].comp_ref != vc_conn) {
Alexander Couzens2c153422018-06-12 18:10:30 +0200319 setverdict(fail, "Cannot unregister index=", i, " IMSI ", imsi, " registred to ",
Harald Welte5ac31492018-02-15 20:39:13 +0100320 ClientTable[i].comp_ref, " from ", vc_conn);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200321 mtc.stop;
Harald Welte5ac31492018-02-15 20:39:13 +0100322 }
323 log("Removing Client IMSI=", imsi, ", index=", i);
Alexander Couzens2c153422018-06-12 18:10:30 +0200324 ClientTable[i] := {
325 tlli := -,
326 tlli_old := omit,
327 imsi := ''H,
328 cell_id := -,
329 comp_ref := null,
330 llc := - };
Harald Welte5ac31492018-02-15 20:39:13 +0100331 return;
332 }
333 }
Alexander Couzens56101c92018-07-31 15:55:34 +0200334 log("Warning: Could not find client for IMSI ", imsi);
335 return;
Harald Welte5ac31492018-02-15 20:39:13 +0100336}
337
Harald Weltef70997d2018-02-17 10:11:19 +0100338/* TS 44.064 7.2.1.1 LLGMM-ASSIGN */
339private function f_tbl_client_llgmm_assign(OCT4 tlli_old, OCT4 tlli_new, BSSGP_Client_CT vc_conn)
340runs on BSSGP_CT {
341 var integer i := f_tbl_idx_by_comp(vc_conn);
342
343 if (tlli_old == 'FFFFFFFF'O and tlli_new != 'FFFFFFFF'O) {
344 /* TLLI assignment */
345 ClientTable[i].tlli := tlli_new;
346 ClientTable[i].tlli_old := omit;
347 } else if (tlli_old != 'FFFFFFFF'O and tlli_new != 'FFFFFFFF'O) {
348 /* TLLI change: both active */
349 ClientTable[i].tlli := tlli_new;
350 ClientTable[i].tlli_old := tlli_old;
351 } else if (tlli_old != 'FFFFFFFF'O and tlli_new == 'FFFFFFFF'O) {
352 /* TLLI unassignment: old shall be unassigned; new stays */
353 ClientTable[i].tlli_old := omit;
354 }
355}
356
Harald Welte5ac31492018-02-15 20:39:13 +0100357private function f_tbl_comp_by_imsi(hexstring imsi) runs on BSSGP_CT return BSSGP_Client_CT {
358 var integer i;
359 for (i := 0; i < sizeof(ClientTable); i := i+1) {
Harald Weltec7872fa2018-02-18 14:06:12 +0100360 if (isvalue(ClientTable[i].imsi) and isvalue(ClientTable[i].comp_ref)
Harald Welte5ac31492018-02-15 20:39:13 +0100361 and ClientTable[i].imsi == imsi) {
362 return ClientTable[i].comp_ref;
363 }
364 }
365 setverdict(fail, "Couldn't find Component for IMSI ", imsi);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200366 mtc.stop;
Harald Welte5ac31492018-02-15 20:39:13 +0100367}
368
369private function f_tbl_comp_by_tlli(OCT4 tlli) runs on BSSGP_CT return BSSGP_Client_CT {
370 var integer i;
371 for (i := 0; i < sizeof(ClientTable); i := i+1) {
Harald Weltec7872fa2018-02-18 14:06:12 +0100372 if (isvalue(ClientTable[i].comp_ref) and
373 (isvalue(ClientTable[i].tlli) and (ClientTable[i].tlli == tlli or
374 isvalue(ClientTable[i].tlli_old) and ClientTable[i].tlli_old == tlli) )) {
Harald Welte5ac31492018-02-15 20:39:13 +0100375 return ClientTable[i].comp_ref;
376 }
377 }
378 setverdict(fail, "Couldn't find Component for TLLI ", tlli);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200379 mtc.stop;
Harald Welte5ac31492018-02-15 20:39:13 +0100380}
381
382private function f_tbl_idx_by_comp(BSSGP_Client_CT comp_ref) runs on BSSGP_CT return integer {
383 var integer i;
384 for (i := 0; i < sizeof(ClientTable); i := i+1) {
Harald Weltec7872fa2018-02-18 14:06:12 +0100385 if (isvalue(ClientTable[i].comp_ref) and ClientTable[i].comp_ref == comp_ref) {
Harald Welte5ac31492018-02-15 20:39:13 +0100386 return i;
387 }
388 }
389 setverdict(fail, "Couldn't find Client for Component ", comp_ref);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200390 mtc.stop;
Harald Welte5ac31492018-02-15 20:39:13 +0100391}
392
393private function f_tbl_tlli_by_comp(BSSGP_Client_CT comp_ref) runs on BSSGP_CT return OCT4 {
394 var integer i;
395 for (i := 0; i < sizeof(ClientTable); i := i+1) {
Harald Weltec7872fa2018-02-18 14:06:12 +0100396 if (isvalue(ClientTable[i].tlli) and isvalue(ClientTable[i].comp_ref)
Harald Welte5ac31492018-02-15 20:39:13 +0100397 and ClientTable[i].comp_ref == comp_ref) {
398 return ClientTable[i].tlli;
399 }
400 }
401 setverdict(fail, "Couldn't find TLLI for Component ", comp_ref);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200402 mtc.stop;
Harald Welte853c0ad2018-02-15 17:45:29 +0100403}
404
405altstep as_allstate() runs on BSSGP_CT {
Harald Welte5ac31492018-02-15 20:39:13 +0100406 var BSSGP_Client_CT vc_conn;
Harald Welte853c0ad2018-02-15 17:45:29 +0100407 var NsUnitdataIndication udi;
408 var NsStatusIndication nsi;
409 var ASP_Event evt;
Harald Welte5ac31492018-02-15 20:39:13 +0100410 var hexstring imsi;
Harald Weltef70997d2018-02-17 10:11:19 +0100411 var OCT4 tlli, tlli_old;
Harald Welte5ac31492018-02-15 20:39:13 +0100412 var BssgpCellId cell_id;
Harald Welte853c0ad2018-02-15 17:45:29 +0100413
414 /* Respond to BLOCK for wrong NSVCI */
415 [] BSCP.receive(f_BnsUdInd(t_BVC_BLOCK(?, ?), 0)) -> value udi {
416 log("Rx BVC-BLOCK for unknown BVCI");
417 f_sendStatus(BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp);
Harald Welte1733a382017-07-23 17:26:17 +0200418 }
419
Harald Welte853c0ad2018-02-15 17:45:29 +0100420 /* Respond to RESET with correct BVCI/CellID */
Harald Welte5ac31492018-02-15 20:39:13 +0100421 [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, g_cfg.bvci, g_cfg.cell_id), 0)) -> value udi {
422 log("Rx BVC-RESET for Our BVCI=", g_cfg.bvci);
423 BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(g_cfg.bvci, g_cfg.cell_id), 0));
Harald Welte853c0ad2018-02-15 17:45:29 +0100424 f_change_state(BVC_S_UNBLOCKED);
Harald Welte1733a382017-07-23 17:26:17 +0200425 }
426
Harald Welte853c0ad2018-02-15 17:45:29 +0100427 /* Respond to RESET for signalling BVCI 0 */
Harald Welte5ac31492018-02-15 20:39:13 +0100428 [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, 0, g_cfg.cell_id), 0)) -> value udi {
Harald Welte853c0ad2018-02-15 17:45:29 +0100429 log("Rx BVC-RESET for Signaling BVCI=0");
Harald Welte5ac31492018-02-15 20:39:13 +0100430 BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(0, g_cfg.cell_id), 0));
Harald Welte1733a382017-07-23 17:26:17 +0200431 }
432
Harald Welte853c0ad2018-02-15 17:45:29 +0100433 /* Respond to RESET with wrong NSEI/NSVCI */
434 [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, ?, ?), 0)) -> value udi {
435 log("Rx BVC-RESET for unknown BVCI");
436 f_sendStatus(BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp);
Harald Welte1733a382017-07-23 17:26:17 +0200437 }
438
Harald Welte853c0ad2018-02-15 17:45:29 +0100439 /* default case of handling unknown PDUs */
440 [] BSCP.receive(f_BnsUdInd(?, ?)) -> value udi {
441 log("Rx Unexpected BSSGP PDU ", udi.bssgp," in state ", g_ptp_bvc_state);
442 f_sendStatus(BSSGP_CAUSE_PDU_NOT_COMPATIBLE_WITH_PROTOCOL_STATE, udi.bssgp);
Harald Welte1733a382017-07-23 17:26:17 +0200443 }
Harald Welte853c0ad2018-02-15 17:45:29 +0100444 /* Forwarding of ASP_Event and NsStatusIndication to user */
Harald Welte5ac31492018-02-15 20:39:13 +0100445 [] BSCP.receive(ASP_Event:?) -> value evt {
446 for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
447 if (isbound(ClientTable[i].comp_ref)) {
448 BSSGP_SP.send(evt) to ClientTable[i].comp_ref;
449 }
450 }
451 }
Harald Welte853c0ad2018-02-15 17:45:29 +0100452 [] BSCP.receive(NsStatusIndication:?) -> value nsi {
453 /* if we just became NS-unblocked, send a BCC-RESET */
454 if (nsi.old_state != NSE_S_ALIVE_UNBLOCKED and nsi.new_state == NSE_S_ALIVE_UNBLOCKED) {
Harald Welte5ac31492018-02-15 20:39:13 +0100455 if (g_cfg.sgsn_role == false) {
Harald Welte853c0ad2018-02-15 17:45:29 +0100456 f_sendReset();
Harald Welte1733a382017-07-23 17:26:17 +0200457 }
Harald Welte5ac31492018-02-15 20:39:13 +0100458 /* Idea: We could send BVC-UNBLOCK here like some SGSN do */
Harald Welte1733a382017-07-23 17:26:17 +0200459 }
Harald Welte5ac31492018-02-15 20:39:13 +0100460 for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
461 if (isbound(ClientTable[i].comp_ref)) {
462 BSSGP_SP.send(nsi) to ClientTable[i].comp_ref;
463 }
464 }
465 }
466
467 [] BSSGP_PROC.getcall(BSSGP_register_client:{?,?,?}) -> param(imsi, tlli, cell_id) sender vc_conn {
468 f_tbl_client_add(imsi, tlli, cell_id, vc_conn);
Harald Weltee32ad992018-05-31 22:17:46 +0200469 BSSGP_PROC.reply(BSSGP_register_client:{imsi, tlli, cell_id}) to vc_conn;
Harald Welte5ac31492018-02-15 20:39:13 +0100470 }
471 [] BSSGP_PROC.getcall(BSSGP_unregister_client:{?}) -> param(imsi) sender vc_conn {
472 f_tbl_client_del(imsi, vc_conn);
Harald Weltee32ad992018-05-31 22:17:46 +0200473 BSSGP_PROC.reply(BSSGP_unregister_client:{imsi}) to vc_conn;
Harald Welte5ac31492018-02-15 20:39:13 +0100474 }
Harald Weltef70997d2018-02-17 10:11:19 +0100475 [] BSSGP_PROC.getcall(BSSGP_llgmm_assign:{?,?}) -> param(tlli_old, tlli) sender vc_conn {
476 f_tbl_client_llgmm_assign(tlli_old, tlli, vc_conn);
Harald Weltee32ad992018-05-31 22:17:46 +0200477 BSSGP_PROC.reply(BSSGP_llgmm_assign:{tlli_old, tlli}) to vc_conn;
Harald Weltef70997d2018-02-17 10:11:19 +0100478 }
479
Harald Welte5ac31492018-02-15 20:39:13 +0100480}
481
482altstep as_blocked() runs on BSSGP_CT {
Harald Weltec27f6842018-03-02 21:40:03 +0100483 [g_T1.running] g_T1.timeout {
Harald Welte5ac31492018-02-15 20:39:13 +0100484 f_sendUnblock();
485 }
486 [] BSCP.receive(f_BnsUdInd(t_BVC_UNBLOCK_ACK(g_cfg.bvci), 0)) {
487 g_T1.stop;
488 f_change_state(BVC_S_UNBLOCKED);
489 }
490 [not g_cfg.sgsn_role] BSCP.receive(f_BnsUdInd(tr_BVC_RESET_ACK(g_cfg.bvci, omit), 0)) {
491 f_sendUnblock();
Harald Welte1733a382017-07-23 17:26:17 +0200492 }
Harald Welte853c0ad2018-02-15 17:45:29 +0100493}
Harald Welte1733a382017-07-23 17:26:17 +0200494
Harald Welte5ac31492018-02-15 20:39:13 +0100495altstep as_unblocked() runs on BSSGP_CT {
496 var BSSGP_Client_CT vc_conn;
Harald Welte853c0ad2018-02-15 17:45:29 +0100497 var NsUnitdataIndication udi;
498 var PDU_BSSGP bs_pdu;
Harald Welte752abba2018-02-18 19:42:17 +0100499 var PDU_LLC llc;
Harald Welte5ac31492018-02-15 20:39:13 +0100500 var PDU_L3_MS_SGSN l3_mo;
501 var PDU_L3_SGSN_MS l3_mt;
Harald Welte1733a382017-07-23 17:26:17 +0200502
Harald Welte5ac31492018-02-15 20:39:13 +0100503 /* bogus unblock, just respond with ACK */
504 [] BSCP.receive(f_BnsUdInd(t_BVC_UNBLOCK(g_cfg.bvci), 0)) -> value udi {
505 BSCP.send(f_BnsUdReq(t_BVC_UNBLOCK_ACK(g_cfg.bvci), 0));
506 }
507 /* Respond to BLOCK with BLOCK-ACK + change state */
508 [] BSCP.receive(f_BnsUdInd(t_BVC_BLOCK(g_cfg.bvci, ?), 0)) -> value udi {
509 BSCP.send(f_BnsUdReq(t_BVC_BLOCK_ACK(g_cfg.bvci), 0));
510 g_T1.stop;
511 f_change_state(BVC_S_BLOCKED);
512 }
Harald Weltec27f6842018-03-02 21:40:03 +0100513 [g_T1.running] g_T1.timeout {
Harald Welte5ac31492018-02-15 20:39:13 +0100514 f_sendBlock(BSSGP_CAUSE_OM_INTERVENTION);
515 }
516 [] BSCP.receive(f_BnsUdInd(t_BVC_BLOCK_ACK(g_cfg.bvci), 0)) -> value udi {
517 g_T1.stop;
518 f_change_state(BVC_S_BLOCKED);
519 }
520 [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET_ACK(g_cfg.bvci, g_cfg.cell_id), 0)) -> value udi {
521 g_T2.stop;
522 f_change_state(BVC_S_UNBLOCKED);
523 }
Harald Welte13d391e2017-07-23 19:52:33 +0200524
Harald Welte5ac31492018-02-15 20:39:13 +0100525 /* simply acknowledge all Flow Control Messages */
Harald Welteedcdd902018-03-02 22:04:54 +0100526 [g_cfg.sgsn_role] BSCP.receive(f_BnsUdInd(tr_BVC_FC_BVC, g_cfg.bvci)) -> value udi {
527 var OCT1 tag := udi.bssgp.pDU_BSSGP_FLOW_CONTROL_BVC.tag.unstructured_Value;
528 BSCP.send(f_BnsUdReq(t_BVC_FC_BVC_ACK(tag), g_cfg.bvci));
Harald Welte5ac31492018-02-15 20:39:13 +0100529 }
Harald Welteedcdd902018-03-02 22:04:54 +0100530/*
531 [g_cfg.sgsn_role] BSCP.receive(f_BnsUdInd(t_BVC_FC_MS, g_cfg.bvci)) {
532 BSCP.send(f_BnsUdReq(t_BVC_FC_MS_ACK, g_cfg.bvci));
Harald Welte5ac31492018-02-15 20:39:13 +0100533 }
Harald Weltee0abc472018-02-05 09:13:31 +0100534*/
Harald Welte13d391e2017-07-23 19:52:33 +0200535
Harald Welte5ac31492018-02-15 20:39:13 +0100536 /* FIXME: CS PAGING: dispatch by IMSI */
Harald Welte1733a382017-07-23 17:26:17 +0200537
Harald Welte5ac31492018-02-15 20:39:13 +0100538 /* PS PAGING: dispatch by IMSI */
539 [] BSCP.receive(f_BnsUdInd(tr_BSSGP_PS_PAGING(g_cfg.bvci), g_cfg.bvci)) -> value udi {
540 var hexstring imsi := udi.bssgp.pDU_BSSGP_PAGING_PS.iMSI.digits
541 vc_conn := f_tbl_comp_by_imsi(imsi);
542 BSSGP_SP.send(f_dec_bssgp(udi.bssgp)) to vc_conn;
543 }
544
Harald Welte001b0da2019-03-21 21:30:47 +0100545 /* Any other PTP BSSGP message: If it has TLLi, route to component; otherwise broadcast */
Harald Welte5ac31492018-02-15 20:39:13 +0100546 [] BSCP.receive(f_BnsUdInd(?, g_cfg.bvci)) -> value udi {
547 var BssgpDecoded dec := f_dec_bssgp(udi.bssgp);
548 var template OCT4 tlli := f_bssgp_get_tlli(udi.bssgp);
549 if (isvalue(tlli)) {
550 vc_conn := f_tbl_comp_by_tlli(valueof(tlli));
551 BSSGP_SP.send(dec) to vc_conn;
552 } else {
553 log("No TLLI: Broadcasting ", dec);
554 /* broadcast this message to all components */
555 // TITAN DOESN'T DO THIS, *SIGH*: "BSSGP_SP.send(dec) to all component;"
556 for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
557 if (isbound(ClientTable[i].comp_ref)) {
558 BSSGP_SP.send(dec) to ClientTable[i].comp_ref;
559 }
560 }
Harald Welte853c0ad2018-02-15 17:45:29 +0100561 }
Harald Welte1733a382017-07-23 17:26:17 +0200562 }
Harald Welte853c0ad2018-02-15 17:45:29 +0100563
Harald Welte001b0da2019-03-21 21:30:47 +0100564 /* Any other SIG BSSGP message: If it has TLLi, route to component; otherwise broadcast */
565 [] BSCP.receive(f_BnsUdInd(?, 0)) -> value udi {
566 var BssgpDecoded dec := f_dec_bssgp(udi.bssgp);
567 var template OCT4 tlli := f_bssgp_get_tlli(udi.bssgp);
568 if (isvalue(tlli)) {
569 vc_conn := f_tbl_comp_by_tlli(valueof(tlli));
570 BSSGP_SP_SIG.send(dec) to vc_conn;
571 } else {
572 log("No TLLI: Broadcasting ", dec);
573 /* broadcast this message to all components */
574 // TITAN DOESN'T DO THIS, *SIGH*: "BSSGP_SP.send(dec) to all component;"
575 for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
576 if (isbound(ClientTable[i].comp_ref)) {
577 BSSGP_SP_SIG.send(dec) to ClientTable[i].comp_ref;
578 }
579 }
580 }
581 }
582
583
Harald Welte1e5a02d2019-05-03 00:50:48 +0200584 /* ConnHdlr sends BSSGP on BVCI=0 port: forward it to BSSGP Codec Port */
Stefan Sperlingf82bbb62018-05-03 19:14:28 +0200585 [] BSSGP_SP_SIG.receive(PDU_BSSGP:?)-> value bs_pdu sender vc_conn {
586 BSCP.send(f_BnsUdReq(bs_pdu, 0));
587 }
588
Harald Welte1e5a02d2019-05-03 00:50:48 +0200589 /* ConnHdlr sends BSSGP on BVCI=PTP port: forward it to BSSGP Codec Port */
Harald Welte5ac31492018-02-15 20:39:13 +0100590 [] BSSGP_SP.receive(PDU_BSSGP:?) -> value bs_pdu sender vc_conn {
591 BSCP.send(f_BnsUdReq(bs_pdu, g_cfg.bvci));
592 }
593
Harald Welte1e5a02d2019-05-03 00:50:48 +0200594 /* ConnHdlr sends L3: Encode and send as UL_UD / DL_UD */
Harald Welte5ac31492018-02-15 20:39:13 +0100595 [g_cfg.sgsn_role] BSSGP_SP.receive(PDU_L3_SGSN_MS:?) -> value l3_mt sender vc_conn {
596 var integer idx := f_tbl_idx_by_comp(vc_conn);
597 var octetstring l3_enc := enc_PDU_L3_SGSN_MS(l3_mt);
598 var BIT4 sapi := f_llc_sapi_by_l3_mt(l3_mt);
599 var integer n_u := f_llc_get_n_u_tx(ClientTable[idx].llc[bit2int(sapi)]);
600 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 +0200601 BSCP.send(f_BnsUdReq(ts_BSSGP_DL_UD(ClientTable[idx].tlli, llc_enc), g_cfg.bvci));
Harald Welte5ac31492018-02-15 20:39:13 +0100602 }
Harald Welte425f7822019-05-03 00:48:46 +0200603 [not g_cfg.sgsn_role] BSSGP_SP.receive(PDU_L3_MS_SGSN:?) -> value l3_mo sender vc_conn {
604 var integer idx := f_tbl_idx_by_comp(vc_conn);
605 var octetstring l3_enc := enc_PDU_L3_MS_SGSN(l3_mo);
606 var BIT4 sapi := f_llc_sapi_by_l3_mo(l3_mo);
607 var integer n_u := f_llc_get_n_u_tx(ClientTable[idx].llc[bit2int(sapi)]);
608 var octetstring llc_enc := enc_PDU_LLC(valueof(ts_LLC_UI(l3_enc, sapi, '1'B, n_u)));
609 BSCP.send(f_BnsUdReq(ts_BSSGP_UL_UD(ClientTable[idx].tlli, ClientTable[idx].cell_id, llc_enc), g_cfg.bvci));
610 }
Harald Welte752abba2018-02-18 19:42:17 +0100611
Harald Welte1b85bf32019-05-03 00:49:25 +0200612 /* ConnHdlr sends raw LLC: Encode and send as UL_UD / DL_UD */
613 [not g_cfg.sgsn_role] BSSGP_SP.receive(PDU_LLC:?) -> value llc sender vc_conn {
Harald Welte752abba2018-02-18 19:42:17 +0100614 var integer idx := f_tbl_idx_by_comp(vc_conn);
615 var octetstring llc_enc := enc_PDU_LLC(llc);
616 BSCP.send(f_BnsUdReq(ts_BSSGP_UL_UD(ClientTable[idx].tlli, ClientTable[idx].cell_id, llc_enc), g_cfg.bvci));
617 }
Harald Welte1b85bf32019-05-03 00:49:25 +0200618 [g_cfg.sgsn_role] BSSGP_SP.receive(PDU_LLC:?) -> value llc sender vc_conn {
619 var integer idx := f_tbl_idx_by_comp(vc_conn);
620 var octetstring llc_enc := enc_PDU_LLC(llc);
621 BSCP.send(f_BnsUdReq(ts_BSSGP_DL_UD(ClientTable[idx].tlli, llc_enc), g_cfg.bvci));
622 }
623
Harald Welte853c0ad2018-02-15 17:45:29 +0100624}
625
Alexander Couzenscdfb7512018-07-31 15:37:14 +0200626function f_llc_get_n_u_tx(inout LLC_Entity llc) return uint9_t {
Harald Welte5ac31492018-02-15 20:39:13 +0100627 var uint9_t ret := llc.n_u_tx_next;
628 llc.n_u_tx_next := llc.n_u_tx_next + 1;
629 return ret;
630}
631
Alexander Couzenscdfb7512018-07-31 15:37:14 +0200632function f_llc_sapi_by_l3_mo(PDU_L3_MS_SGSN l3_mo) return BIT4 {
Harald Welte5ac31492018-02-15 20:39:13 +0100633 if (ischosen(l3_mo.msgs.gprs_mm)) {
634 return c_LLC_SAPI_LLGMM;
635 } else if (ischosen(l3_mo.msgs.gprs_sm)) {
Harald Welted4719012018-02-17 16:45:06 +0100636 return c_LLC_SAPI_LLGMM;
Harald Welte5ac31492018-02-15 20:39:13 +0100637 } else if (ischosen(l3_mo.msgs.sms)) {
638 return c_LLC_SAPI_LLSMS;
639 }
640 setverdict(fail, "No LLC SAPI for ", l3_mo);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200641 mtc.stop;
Harald Welte5ac31492018-02-15 20:39:13 +0100642}
643
644private function f_llc_sapi_by_l3_mt(PDU_L3_SGSN_MS l3_mt) return BIT4 {
645 if (ischosen(l3_mt.msgs.gprs_mm)) {
646 return c_LLC_SAPI_LLGMM;
647 } else if (ischosen(l3_mt.msgs.gprs_sm)) {
Harald Welted4719012018-02-17 16:45:06 +0100648 return c_LLC_SAPI_LLGMM;
Harald Welte5ac31492018-02-15 20:39:13 +0100649 } else if (ischosen(l3_mt.msgs.sms)) {
650 return c_LLC_SAPI_LLSMS;
651 }
652 setverdict(fail, "No LLC SAPI for ", l3_mt);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200653 mtc.stop;
Harald Welte5ac31492018-02-15 20:39:13 +0100654}
655
656
657
658private function f_ScanEvents() runs on BSSGP_CT {
659 log("matching against ", tr_BVC_RESET(?, g_cfg.bvci, g_cfg.cell_id));
660
661 while (true) {
662 alt {
663 [g_ptp_bvc_state == BVC_S_BLOCKED] as_blocked();
664 [g_ptp_bvc_state == BVC_S_UNBLOCKED] as_unblocked();
665 [] as_allstate();
666 }
667 } /* while */
668}
669
670/* PDU_BSSGP enhanced with LLC and possibly L3 decoded payloads */
671type record BssgpDecoded {
672 PDU_BSSGP bssgp,
673 PDU_LLC llc optional,
674 PDU_L3_MS_SGSN l3_mo optional,
Harald Weltea2526a82018-02-18 19:03:36 +0100675 PDU_L3_SGSN_MS l3_mt optional,
676 PDU_SN sndcp optional
Harald Welte5ac31492018-02-15 20:39:13 +0100677}
678
679/* Decode a PDU_BSSGP into a BssgpDecoded (i.e. with LLC/L3 decoded, as applicable) */
680private function f_dec_bssgp(PDU_BSSGP bssgp) runs on BSSGP_CT return BssgpDecoded {
681 var BssgpDecoded dec := {
682 bssgp := bssgp,
683 llc := omit,
684 l3_mo := omit,
Harald Weltea2526a82018-02-18 19:03:36 +0100685 l3_mt := omit,
686 sndcp := omit
Harald Welte5ac31492018-02-15 20:39:13 +0100687 };
688
689 /* Decode LLC, if it is a PDU that contains LLC */
690 if (ischosen(bssgp.pDU_BSSGP_DL_UNITDATA)) {
691 dec.llc := dec_PDU_LLC(bssgp.pDU_BSSGP_DL_UNITDATA.lLC_PDU.lLC_PDU);
692 } else if (ischosen(bssgp.pDU_BSSGP_UL_UNITDATA)) {
693 dec.llc := dec_PDU_LLC(bssgp.pDU_BSSGP_UL_UNITDATA.lLC_PDU.lLC_PDU);
694 }
695
696 /* Decode L3, if it is a LLC PDU containing L3 */
697 if (isvalue(dec.llc) and match(dec.llc, tr_LLC_UI_L3)) {
698 if (g_cfg.sgsn_role) {
699 dec.l3_mo := dec_PDU_L3_MS_SGSN(dec.llc.pDU_LLC_UI.information_field_UI);
700 } else {
701 dec.l3_mt := dec_PDU_L3_SGSN_MS(dec.llc.pDU_LLC_UI.information_field_UI);
702 }
703 }
Harald Weltea2526a82018-02-18 19:03:36 +0100704
705 /* Decode SNDCP, if it is a LLC PDU containing user plane data */
706 if (isvalue(dec.llc) and match(dec.llc, tr_LLC_UI_USER)) {
707 dec.sndcp := dec_PDU_SN(dec.llc.pDU_LLC_UI.information_field_UI);
708 }
Harald Welte5ac31492018-02-15 20:39:13 +0100709 return dec;
710}
711
Alexander Couzens0e510e62018-07-28 23:06:00 +0200712function 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 +0100713runs on BSSGP_Client_CT {
714 PT.call(BSSGP_register_client:{imsi, tlli, cell_id}) {
715 [] PT.getreply(BSSGP_register_client:{imsi, tlli, cell_id}) {};
716 }
717}
718
Alexander Couzens0e510e62018-07-28 23:06:00 +0200719function f_bssgp_client_unregister(hexstring imsi, BSSGP_PROC_PT PT := BSSGP_PROC[0])
Harald Welte5ac31492018-02-15 20:39:13 +0100720runs on BSSGP_Client_CT {
721 PT.call(BSSGP_unregister_client:{imsi}) {
722 [] PT.getreply(BSSGP_unregister_client:{imsi}) {};
723 }
724}
725
Harald Weltef70997d2018-02-17 10:11:19 +0100726/* TS 44.064 7.2.1.1 LLGMM-ASSIGN */
Alexander Couzens0e510e62018-07-28 23:06:00 +0200727function 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 +0100728runs on BSSGP_Client_CT {
729 PT.call(BSSGP_llgmm_assign:{tlli_old, tlli_new}) {
730 [] PT.getreply(BSSGP_llgmm_assign:{tlli_old, tlli_new}) {};
731 }
732}
733
Harald Welte5ac31492018-02-15 20:39:13 +0100734template BssgpDecoded tr_BD_BSSGP(template PDU_BSSGP bg) := {
735 bssgp := bg,
736 llc := *,
737 l3_mo := *,
Harald Weltea2526a82018-02-18 19:03:36 +0100738 l3_mt := *,
739 sndcp := *
740}
741
742template BssgpDecoded tr_BD_LLC(template PDU_LLC llc) := {
743 bssgp := ?,
744 llc := llc,
745 l3_mo := *,
746 l3_mt := *,
747 sndcp := *
Harald Welte5ac31492018-02-15 20:39:13 +0100748}
749
Harald Welte5ac31492018-02-15 20:39:13 +0100750template BssgpDecoded tr_BD_L3_MT(template PDU_L3_SGSN_MS mt) := {
751 bssgp := ?,
752 llc := ?,
753 l3_mo := omit,
Harald Weltea2526a82018-02-18 19:03:36 +0100754 l3_mt := mt,
755 sndcp := omit
Harald Welte5ac31492018-02-15 20:39:13 +0100756}
757
758template BssgpDecoded tr_BD_L3_MO(template PDU_L3_MS_SGSN mo) := {
759 bssgp := ?,
760 llc := ?,
761 l3_mo := mo,
Harald Weltea2526a82018-02-18 19:03:36 +0100762 l3_mt := omit,
763 sndcp := omit
Harald Welte5ac31492018-02-15 20:39:13 +0100764}
765
Harald Welte37692d82018-02-18 15:21:34 +0100766template BssgpDecoded tr_BD_SNDCP(template BIT4 sapi, template PDU_SN sn) := {
767 bssgp := ?,
768 llc := tr_LLC_UI(?, sapi),
769 l3_mo := omit,
770 l3_mt := omit,
771 sndcp := sn
772}
773
774
Harald Welte5ac31492018-02-15 20:39:13 +0100775
776
Harald Welte1733a382017-07-23 17:26:17 +0200777}