2 * (C) 2017-2018 by sysmocom - s.f.m.c. GmbH, Author: Max <msuraev@sysmocom.de>
3 * (C) 2018 by Vadim Yanitskiy <axilirator@gmail.com>
4 * (C) 2011-2012 by Luca Melette <luca@srlabs.de>
8 * SPDX-License-Identifier: GPL-2.0+
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
30 #include <osmocom/core/gsmtap.h>
32 #include "l1ctl_proto.h"
36 static struct gprs_tbf tbf_table
[32 * 2];
38 static inline int too_old(uint32_t current_fn
, uint32_t test_fn
)
40 uint32_t delta
= (current_fn
- test_fn
) & 0xffffffff;
42 /* More and less 30 seconds from now */
43 return abs(delta
) > OLD_TIME
;
46 static inline int bsn_is_next(uint8_t first
, uint8_t second
)
48 return ((first
+ 1) % 128) == second
;
51 void print_pkt(uint8_t *msg
, size_t len
)
56 for (i
= 0; i
< len
; i
++)
57 printf("%.02x", msg
[i
]);
61 void process_blocks(struct gprs_tbf
*t
, bool ul
)
63 uint8_t llc_data
[65536], llc_first_bsn
, llc_last_bsn
= 0;
64 unsigned skip
, llc_len
= 0;
65 uint8_t bsn
, bsn2
, li_off
;
70 /* Get current "time", oldest unreassembled frag */
72 while (t
->frags
[bsn
].len
== 0) {
73 bsn
= (bsn
+ 1) % 128;
74 if (bsn
== t
->start_bsn
) {
75 printf("no valid blocks in current TBF!\n");
80 current_fn
= t
->frags
[bsn
].fn
;
83 /* Walk through fragments, mark reassembled/used blocks */
85 for (bsn
= t
->start_bsn
; bsn
!= ((t
->last_bsn
+ 1) % 128); bsn
= (bsn
+ 1) % 128) {
86 /* Get fragment descriptor */
89 printf(" bsn %d ", bsn
);
92 /* Already processed or null */
101 /* Check fragment age */
102 if (too_old(current_fn
, f
->fn
)) {
103 printf("old segment\n");
113 if (llc_len
&& !bsn_is_next(llc_last_bsn
, bsn
)) {
114 printf("missing bsn, previous %d\n", llc_last_bsn
);
121 /* Check for multiple blocks/parts */
122 if (f
->n_blocks
== 0) {
123 /* Check if first part of message */
127 /* Append data to buffer */
128 memcpy(&llc_data
[llc_len
], f
->data
, f
->len
);
134 /* Last TBF block? (very rare condition) */
136 printf("end of TBF\n");
138 print_pkt(llc_data
, llc_len
);
140 gsmtap_send_llc(llc_data
, llc_len
, ul
);
142 /* Reset all fragments */
143 for (bsn2
= 0; bsn2
< 128; bsn2
++) {
149 /* Reset buffer state */
154 /* Multiple data parts */
157 for (i
= 0; i
< f
->n_blocks
; i
++) {
158 printf("\nlime %d\n", i
);
163 printf("\nlime error!\n");
171 /* Append data to buffer */
172 memcpy(&llc_data
[llc_len
], &f
->data
[li_off
], l
->li
);
178 if (!l
->e
|| !l
->m
|| (l
->e
&& l
->m
)) {
179 /* Message ends here */
180 printf("end of message reached\n");
182 print_pkt(llc_data
, llc_len
);
184 gsmtap_send_llc(llc_data
, llc_len
, ul
);
186 /* Mark frags as used */
188 if (llc_first_bsn
!= bsn
) {
201 /* Is spare data valid? */
204 printf("spare and buffer not empty!\n");
205 print_pkt(llc_data
, llc_len
);
208 if ((f
->len
> li_off
) && (f
->len
-li_off
< 65536)) {
209 memcpy(llc_data
, &f
->data
[li_off
], f
->len
-li_off
);
210 llc_len
= f
->len
- li_off
;
220 /* Shift window if needed */
221 if (((t
->last_bsn
- t
->start_bsn
) % 128) > 64) {
222 t
->start_bsn
= (t
->last_bsn
- 64) % 128;
223 printf("shifting window\n");
228 void rlc_data_handler(struct gprs_message
*gm
)
231 uint8_t tfi
, bsn
, cv
= 1, fbi
= 0;
232 uint32_t d_same_bsn
, d_last_bsn
;
233 struct gprs_tbf
*t
, *t_prev
;
237 tfi
= (gm
->msg
[1] & 0x3e) >> 1;
238 bsn
= (gm
->msg
[2] & 0xfe) >> 1;
240 /* Get "end of TBF" according to direction */
241 ul
= !!(gm
->arfcn
& GSMTAP_ARFCN_F_UPLINK
);
243 cv
= (gm
->msg
[0] & 0x3c) >> 2;
244 printf("TFI %d BSN %d CV %d ", tfi
, bsn
, cv
);
246 fbi
= (gm
->msg
[1] & 0x01);
247 printf("TFI %d BSN %d FBI %d ", tfi
, bsn
, fbi
);
250 /* Get TBF descriptor for TFI,UL couple */
251 t
= &tbf_table
[2 * tfi
+ ul
];
253 d_same_bsn
= (gm
->fn
- t
->frags
[bsn
].fn
) & 0xffffffff;
254 d_last_bsn
= (gm
->fn
- t
->frags
[t
->last_bsn
].fn
) & 0xffffffff;
255 d_bsn
= (bsn
- t
->last_bsn
) % 128;
257 printf("\nfn_same_bsn %d fn_last_bsn %d delta_bsn %d old_len %d\n",
258 d_same_bsn
, d_last_bsn
, d_bsn
, t
->frags
[bsn
].len
);
260 /* New / old fragment decision */
261 if (d_same_bsn
> OLD_TIME
) {
262 if (d_last_bsn
> OLD_TIME
) {
263 /* New TBF is starting, close old one... */
264 t_prev
= &tbf_table
[2 * ((tfi
+ 1) % 32) + ul
];
265 printf("clearing TBF %d, first %d last %d\n",
266 (tfi
+ 1) % 32, t_prev
->start_bsn
, t_prev
->last_bsn
);
267 f
= &t_prev
->frags
[t_prev
->last_bsn
];
269 /* ...only if data is present */
272 process_blocks(t_prev
, ul
);
275 printf("new TBF, starting from %d\n", bsn
);
278 memset(t
->frags
, 0, 128 * sizeof(struct gprs_frag
));
280 /* Fresh frag, current TBF */
281 if ((d_bsn
>= 0) || (d_bsn
< -64)) {
285 /* Out of sequence / duplicate */
286 t
->frags
[bsn
].fn
= gm
->fn
;
287 printf("duplicate\n");
293 if (d_last_bsn
> OLD_TIME
) {
294 printf("fucking error last_bsn!\n");
298 /* Fresh frag, current TBF */
300 printf("fucking error d_bsn!\n");
309 t
->frags
[bsn
].fn
= gm
->fn
;
310 printf("duplicate2\n");
318 /* Get fragment struct for current BSN */
321 /* Scan for LI_M_E entries */
324 while (!(gm
->msg
[off
++] & 0x01)) {
325 l
= &f
->blocks
[f
->n_blocks
++];
326 l
->li
= (gm
->msg
[off
] & 0xfc) >> 2;
327 l
->m
= (gm
->msg
[off
] & 0x02) >> 1;
328 l
->e
= (gm
->msg
[off
] & 0x01);
333 f
->last
= (!cv
|| fbi
) ? 1 : 0;
335 /* Optional fields for uplink, indicated in TI and PI */
337 if (gm
->msg
[1] & 0x01) {
338 printf("TLLI 0x%.02x%.02x%.02x%.02x ", gm
->msg
[off
],
339 gm
->msg
[off
+1], gm
->msg
[off
+ 2], gm
->msg
[off
+ 3]);
342 if (gm
->msg
[1] & 0x40) {
343 printf("PFI %d ", gm
->msg
[off
]);
348 /* Copy data part of message */
349 f
->len
= gm
->len
- off
;
351 memcpy(f
->data
, &gm
->msg
[off
], f
->len
);
353 process_blocks(t
, ul
);
356 int rlc_type_handler(struct gprs_message
*gm
)
358 bool ul
= !!(gm
->arfcn
& GSMTAP_ARFCN_F_UPLINK
);
359 uint8_t rlc_type
= (gm
->msg
[0] & 0xc0) >> 6;
362 /* Determine the RLC type */
365 printf("TS %d ", gm
->tn
);
381 printf("unknown (M)CS ");
384 printf(ul
? "UL " : "DL ");
386 gsmtap_send_rlcmac(gm
->msg
, gm
->len
, gm
->tn
, ul
);
389 rlc_data_handler(gm
);
397 gsmtap_send_rlcmac(gm
->msg
, gm
->len
, gm
->tn
,
398 !!(gm
->arfcn
& GSMTAP_ARFCN_F_UPLINK
));
404 printf("RLC type: reserved\n");
409 printf("Unrecognized RLC type: %d\n", rlc_type
);