blob: ca0c720ec13f8f1952ddcae553c5a2fecce5c025 [file] [log] [blame]
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +02001/* decoding
2 *
3 * Copyright (C) 2012 Ivan Klyuchnikov
4 * Copyright (C) 2012 Andreas Eversberg <jolly@eversberg.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +020015 */
16#include <decoding.h>
17#include <rlc.h>
18#include <gprs_debug.h>
Pravin Kumarvel0a4a6c12016-10-17 11:00:57 +053019#include <egprs_rlc_compression.h>
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +020020
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010021extern "C" {
22#include <osmocom/core/utils.h>
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +010023#include <osmocom/core/bitcomp.h>
Tom Tsoudf698092016-07-11 17:05:19 -070024#include <osmocom/gprs/protocol/gsm_04_60.h>
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010025}
26
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +020027#include <arpa/inet.h>
28
29#include <errno.h>
30#include <string.h>
31
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010032#define LENGTH_TO_END 255
Alexander Couzensb82bd922016-05-30 17:30:10 +020033/*!
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010034 * \returns num extensions fields (num frames == offset) on success,
35 * -errno otherwise.
36 */
37static int parse_extensions_egprs(const uint8_t *data, unsigned int data_len,
38 unsigned int *offs,
39 bool is_last_block,
40 Decoding::RlcData *chunks, unsigned int chunks_size)
41{
42 const struct rlc_li_field_egprs *li;
43 uint8_t e;
44 unsigned int num_chunks = 0;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010045
46 e = 0;
47 while (!e) {
48 if (*offs > data_len) {
49 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
50 "but no more data\n");
51 return -EINVAL;
52 }
53
54 /* get new E */
55 li = (struct rlc_li_field_egprs *)&data[*offs];
56 e = li->e;
57 *offs += 1;
58
59 if (!chunks)
60 continue;
61
62 if (num_chunks == chunks_size) {
63 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
64 "but no more chunks possible\n");
65 return -ENOSPC;
66 }
Aravind Sirsikar22a90192016-09-15 17:24:49 +053067 if (li->li == 0 && num_chunks == 0) {
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010068 /* TS 44.060, table 10.4.14a.1, row 2a */
Aravind Sirsikar22a90192016-09-15 17:24:49 +053069 /* TS 44.060, table 10.4.14a.1, row 4 */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010070 chunks[num_chunks].length = 0;
71 chunks[num_chunks].is_complete = true;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010072 } else if (li->li == 127 && li->e == 1) {
73 /* TS 44.060, table 10.4.14a.1, row 3 & 5 */
74 /* only filling bytes left */
Mrinal Mishra0e636442016-11-28 19:46:50 +053075 LOGP(DRLCMACUL, LOGL_DEBUG, "UL DATA LI contains "
Thorsten Alteholz8bb79042018-10-06 10:42:58 +020076 "only filling bytes with extension octet: LI=%d, E=%d, count=%d\n",
Mrinal Mishra0e636442016-11-28 19:46:50 +053077 li->li, li->e, num_chunks);
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010078 break;
79 } else if (li->li > 0) {
80 /* TS 44.060, table 10.4.14a.1, row 1 & 2b */
81 chunks[num_chunks].length = li->li;
82 chunks[num_chunks].is_complete = true;
83 } else {
84 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI contains "
85 "invalid extension octet: LI=%d, E=%d, count=%d\n",
86 li->li, li->e, num_chunks);
87 return -EINVAL;
88 }
89
Mrinal Mishra0e636442016-11-28 19:46:50 +053090 LOGP(DRLCMACUL, LOGL_DEBUG, "UL DATA LI contains "
Thorsten Alteholz8bb79042018-10-06 10:42:58 +020091 "extension octet: LI=%d, E=%d, count=%d\n",
Mrinal Mishra0e636442016-11-28 19:46:50 +053092 li->li, li->e, num_chunks);
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010093 num_chunks += 1;
94
95 if (e == 1) {
96 /* There is space after the last chunk, add a final one */
97 if (num_chunks == chunks_size) {
98 LOGP(DRLCMACUL, LOGL_NOTICE,
99 "UL DATA LI possibly extended, "
100 "but no more chunks possible\n");
101 return -ENOSPC;
102 }
103
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100104 chunks[num_chunks].length = LENGTH_TO_END;
105 chunks[num_chunks].is_complete = is_last_block;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100106 num_chunks += 1;
107 }
108 }
109
110 return num_chunks;
111}
112
113static int parse_extensions_gprs(const uint8_t *data, unsigned int data_len,
114 unsigned int *offs,
115 bool is_last_block,
116 Decoding::RlcData *chunks, unsigned int chunks_size)
117{
118 const struct rlc_li_field *li;
119 uint8_t m, e;
120 unsigned int num_chunks = 0;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100121
122 e = 0;
123 while (!e) {
124 if (*offs > data_len) {
125 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
126 "but no more data\n");
127 return -EINVAL;
128 }
129
130 /* get new E */
131 li = (const struct rlc_li_field *)&data[*offs];
132 e = li->e;
133 m = li->m;
134 *offs += 1;
135
136 if (li->li == 0) {
137 /* TS 44.060, 10.4.14, par 6 */
138 e = 1;
139 m = 0;
140 }
141
142 /* TS 44.060, table 10.4.13.1 */
143 if (m == 0 && e == 0) {
144 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA "
145 "ignored, because M='0' and E='0'.\n");
146 return 0;
147 }
148
149 if (!chunks)
150 continue;
151
152 if (num_chunks == chunks_size) {
153 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
154 "but no more chunks possible\n");
155 return -ENOSPC;
156 }
157
158 if (li->li == 0)
159 /* e is 1 here */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100160 chunks[num_chunks].length = LENGTH_TO_END;
161 else
162 chunks[num_chunks].length = li->li;
163
164 chunks[num_chunks].is_complete = li->li || is_last_block;
165
Mrinal Mishra0e636442016-11-28 19:46:50 +0530166 LOGP(DRLCMACUL, LOGL_DEBUG, "UL DATA LI contains "
Thorsten Alteholz8bb79042018-10-06 10:42:58 +0200167 "extension octet: LI=%d, M=%d, E=%d, count=%d\n",
Mrinal Mishra0e636442016-11-28 19:46:50 +0530168 li->li, li->m, li->e, num_chunks);
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100169 num_chunks += 1;
170
171 if (e == 1 && m == 1) {
172 if (num_chunks == chunks_size) {
173 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
174 "but no more chunks possible\n");
175 return -ENOSPC;
176 }
177 /* TS 44.060, 10.4.13.1, row 4 */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100178 chunks[num_chunks].length = LENGTH_TO_END;
179 chunks[num_chunks].is_complete = is_last_block;
180 num_chunks += 1;
181 }
182 }
183
184 return num_chunks;
185}
186
187int Decoding::rlc_data_from_ul_data(
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200188 const struct gprs_rlc_data_block_info *rdbi, enum CodingScheme cs,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100189 const uint8_t *data, RlcData *chunks, unsigned int chunks_size,
190 uint32_t *tlli)
191{
192 uint8_t e;
193 unsigned int data_len = rdbi->data_len;
Jacob Erlbeckead5e472016-01-08 10:14:50 +0100194 int num_chunks = 0, i;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100195 unsigned int offs = 0;
196 bool is_last_block = (rdbi->cv == 0);
197
198 if (!chunks)
199 chunks_size = 0;
200
201 e = rdbi->e;
202 if (e) {
203 if (chunks_size > 0) {
Alexander Couzensb82bd922016-05-30 17:30:10 +0200204 /* Block without LI means it only contains data of one LLC PDU */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100205 chunks[num_chunks].offset = offs;
206 chunks[num_chunks].length = LENGTH_TO_END;
207 chunks[num_chunks].is_complete = is_last_block;
208 num_chunks += 1;
209 } else if (chunks) {
210 LOGP(DRLCMACUL, LOGL_NOTICE, "No extension, "
211 "but no more chunks possible\n");
212 return -ENOSPC;
213 }
Max8a8e0fb2019-03-25 16:32:50 +0100214 } else if (mcs_is_edge(cs)) {
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100215 /* if E is not set (LI follows), EGPRS */
216 num_chunks = parse_extensions_egprs(data, data_len, &offs,
217 is_last_block,
218 chunks, chunks_size);
219 } else {
220 /* if E is not set (LI follows), GPRS */
221 num_chunks = parse_extensions_gprs(data, data_len, &offs,
222 is_last_block,
223 chunks, chunks_size);
224 }
225
Jacob Erlbeckead5e472016-01-08 10:14:50 +0100226 if (num_chunks < 0)
227 return num_chunks;
228
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100229 /* TLLI */
230 if (rdbi->ti) {
231 uint32_t tlli_enc;
232 if (offs + 4 > data_len) {
233 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TLLI out of block "
234 "border\n");
235 return -EINVAL;
236 }
237
238 memcpy(&tlli_enc, data + offs, sizeof(tlli_enc));
Max8a8e0fb2019-03-25 16:32:50 +0100239 if (mcs_is_gprs(cs))
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100240 /* The TLLI is encoded in big endian for GPRS (see
241 * TS 44.060, figure 10.2.2.1, note) */
242 *tlli = be32toh(tlli_enc);
243 else
244 /* The TLLI is encoded in little endian for EGPRS (see
245 * TS 44.060, figure 10.3a.2.1, note 2) */
246 *tlli = le32toh(tlli_enc);
247
248 offs += sizeof(tlli_enc);
249 } else {
250 *tlli = 0;
251 }
252
253 /* PFI */
254 if (rdbi->pi) {
255 LOGP(DRLCMACUL, LOGL_ERROR, "ERROR: PFI not supported, "
256 "please disable in SYSTEM INFORMATION\n");
257 return -ENOTSUP;
258
259 /* TODO: Skip all extensions with E=0 (see TS 44.060, 10.4.11 */
260 }
261
Jacob Erlbeckead5e472016-01-08 10:14:50 +0100262 if (chunks_size == 0)
263 return num_chunks;
264
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100265 /* LLC */
266 for (i = 0; i < num_chunks; i++) {
267 chunks[i].offset = offs;
268 if (chunks[i].length == LENGTH_TO_END) {
269 if (offs == data_len) {
270 /* There is no place for an additional chunk,
271 * so drop it (this may happen with EGPRS since
272 * there is no M flag. */
273 num_chunks -= 1;
Alexander Couzensd302e4f2016-05-30 17:31:09 +0200274 break;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100275 }
276 chunks[i].length = data_len - offs;
277 }
278 offs += chunks[i].length;
279 if (offs > data_len) {
280 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA out of block "
Pau Espin Pedrolf861d312020-06-30 21:33:43 +0200281 "border, chunk idx: %d, offset: %u, size: %d, data_len: %u\n",
282 i, offs, chunks[i].length, data_len);
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100283 return -EINVAL;
284 }
285 }
286
287 return num_chunks;
288}
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +0200289
Pau Espin Pedrol8a35e642021-01-18 17:14:14 +0100290uint8_t get_ms_class_by_capability(MS_Radio_Access_capability_t *cap)
Holger Hans Peter Freytherfcbc7022013-10-26 17:38:37 +0200291{
292 int i;
293
294 for (i = 0; i < cap->Count_MS_RA_capability_value; i++) {
295 if (!cap->MS_RA_capability_value[i].u.Content.Exist_Multislot_capability)
296 continue;
297 if (!cap->MS_RA_capability_value[i].u.Content.Multislot_capability.Exist_GPRS_multislot_class)
298 continue;
299 return cap->MS_RA_capability_value[i].u.Content.Multislot_capability.GPRS_multislot_class;
300 }
301
302 return 0;
303}
304
Pau Espin Pedrol8a35e642021-01-18 17:14:14 +0100305uint8_t get_egprs_ms_class_by_capability(MS_Radio_Access_capability_t *cap)
Jacob Erlbeckc3c58042015-09-28 17:55:32 +0200306{
307 int i;
308
309 for (i = 0; i < cap->Count_MS_RA_capability_value; i++) {
310 if (!cap->MS_RA_capability_value[i].u.Content.Exist_Multislot_capability)
311 continue;
312 if (!cap->MS_RA_capability_value[i].u.Content.Multislot_capability.Exist_EGPRS_multislot_class)
313 continue;
314 return cap->MS_RA_capability_value[i].u.Content.Multislot_capability.EGPRS_multislot_class;
315 }
316
317 return 0;
318}
319
Holger Hans Peter Freytherdf6b4f52013-11-24 17:05:48 +0100320/**
321 * show_rbb needs to be an array with 65 elements
Daniel Willmann5e94cd42013-12-11 20:11:16 +0100322 * The index of the array is the bit position in the rbb
323 * (show_rbb[63] relates to BSN ssn-1)
Holger Hans Peter Freytherdf6b4f52013-11-24 17:05:48 +0100324 */
Jacob Erlbeckf2f24b02016-02-05 13:16:24 +0100325void Decoding::extract_rbb(const struct bitvec *rbb, char *show_rbb)
326{
327 unsigned int i;
328 for (i = 0; i < rbb->cur_bit; i++) {
329 uint8_t bit;
330 bit = bitvec_get_bit_pos(rbb, i);
331 show_rbb[i] = bit == 1 ? 'R' : 'I';
332 }
333
334 show_rbb[i] = '\0';
335}
336
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100337int Decoding::rlc_parse_ul_data_header(struct gprs_rlc_data_info *rlc,
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200338 const uint8_t *data, enum CodingScheme cs)
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100339{
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100340 unsigned int cur_bit = 0;
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200341 switch(mcs_header_type(cs)) {
Max51754b62019-03-13 17:14:13 +0100342 case HEADER_GPRS_DATA :
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530343 cur_bit = rlc_parse_ul_data_header_gprs(rlc, data, cs);
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100344 break;
Max51754b62019-03-13 17:14:13 +0100345 case HEADER_EGPRS_DATA_TYPE_3 :
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530346 cur_bit = rlc_parse_ul_data_header_egprs_type_3(rlc, data, cs);
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100347 break;
Max51754b62019-03-13 17:14:13 +0100348 case HEADER_EGPRS_DATA_TYPE_2 :
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530349 cur_bit = rlc_parse_ul_data_header_egprs_type_2(rlc, data, cs);
350 break;
Max51754b62019-03-13 17:14:13 +0100351 case HEADER_EGPRS_DATA_TYPE_1 :
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530352 cur_bit = rlc_parse_ul_data_header_egprs_type_1(rlc, data, cs);
353 break;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100354 default:
355 LOGP(DRLCMACDL, LOGL_ERROR,
356 "Decoding of uplink %s data blocks not yet supported.\n",
Max136ebcc2019-03-05 14:59:03 +0100357 mcs_name(cs));
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100358 return -ENOTSUP;
359 };
360
361 return cur_bit;
362}
363
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530364int Decoding::rlc_parse_ul_data_header_egprs_type_3(
365 struct gprs_rlc_data_info *rlc,
366 const uint8_t *data,
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200367 const enum CodingScheme &cs)
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530368{
369 int punct, punct2, with_padding, cps;
370 unsigned int e_ti_header, offs, cur_bit = 0;
371 const struct gprs_rlc_ul_header_egprs_3 *egprs3;
372
373 egprs3 = static_cast < struct gprs_rlc_ul_header_egprs_3 * >
374 ((void *)data);
375
Tom Tsoudf698092016-07-11 17:05:19 -0700376 cps = (egprs3->cps_hi << 0) | (egprs3->cps_lo << 2);
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530377 gprs_rlc_mcs_cps_decode(cps, cs, &punct, &punct2, &with_padding);
378 gprs_rlc_data_info_init_ul(rlc, cs, with_padding);
379
380 rlc->r = egprs3->r;
381 rlc->si = egprs3->si;
Tom Tsoudf698092016-07-11 17:05:19 -0700382 rlc->tfi = (egprs3->tfi_hi << 0) | (egprs3->tfi_lo << 2);
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530383 rlc->cps = cps;
384 rlc->rsb = egprs3->rsb;
385
386 rlc->num_data_blocks = 1;
387 rlc->block_info[0].cv = egprs3->cv;
388 rlc->block_info[0].pi = egprs3->pi;
389 rlc->block_info[0].spb = egprs3->spb;
390 rlc->block_info[0].bsn =
Tom Tsoudf698092016-07-11 17:05:19 -0700391 (egprs3->bsn1_hi << 0) | (egprs3->bsn1_lo << 5);
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530392
393 cur_bit += rlc->data_offs_bits[0] - 2;
394 offs = rlc->data_offs_bits[0] / 8;
395 OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 1);
396 e_ti_header = (data[offs-1] + (data[offs] << 8)) >> 7;
397 rlc->block_info[0].e = !!(e_ti_header & 0x01);
398 rlc->block_info[0].ti = !!(e_ti_header & 0x02);
399 cur_bit += 2;
400 /* skip data area */
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200401 cur_bit += mcs_max_data_block_bytes(cs) * 8;
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530402
403 return cur_bit;
404}
405
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530406int Decoding::rlc_parse_ul_data_header_egprs_type_2(
407 struct gprs_rlc_data_info *rlc,
408 const uint8_t *data,
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200409 const enum CodingScheme &cs)
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530410{
411 const struct gprs_rlc_ul_header_egprs_2 *egprs2;
412 unsigned int e_ti_header, offs, cur_bit = 0;
413 int punct, punct2, with_padding, cps;
414
415 egprs2 = static_cast < struct gprs_rlc_ul_header_egprs_2 * >
416 ((void *)data);
417
Tom Tsoudf698092016-07-11 17:05:19 -0700418 cps = (egprs2->cps_hi << 0) | (egprs2->cps_lo << 2);
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530419 gprs_rlc_mcs_cps_decode(cps, cs, &punct, &punct2, &with_padding);
420 gprs_rlc_data_info_init_ul(rlc, cs, with_padding);
421
422 rlc->r = egprs2->r;
423 rlc->si = egprs2->si;
Tom Tsoudf698092016-07-11 17:05:19 -0700424 rlc->tfi = (egprs2->tfi_hi << 0) | (egprs2->tfi_lo << 2);
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530425 rlc->cps = cps;
426 rlc->rsb = egprs2->rsb;
427
428 rlc->num_data_blocks = 1;
429 rlc->block_info[0].cv = egprs2->cv;
430 rlc->block_info[0].pi = egprs2->pi;
431 rlc->block_info[0].bsn =
Tom Tsoudf698092016-07-11 17:05:19 -0700432 (egprs2->bsn1_hi << 0) | (egprs2->bsn1_lo << 5);
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530433
434 cur_bit += rlc->data_offs_bits[0] - 2;
435
436 offs = rlc->data_offs_bits[0] / 8;
437 OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 7);
438
439 e_ti_header = (data[offs] & 0x60) >> 5;
440 rlc->block_info[0].e = !!(e_ti_header & 0x01);
441 rlc->block_info[0].ti = !!(e_ti_header & 0x02);
442 cur_bit += 2;
443
444 /* skip data area */
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200445 cur_bit += mcs_max_data_block_bytes(cs) * 8;
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530446
447 return cur_bit;
448}
449
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530450int Decoding::rlc_parse_ul_data_header_egprs_type_1(
451 struct gprs_rlc_data_info *rlc,
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200452 const uint8_t *data, const enum CodingScheme &cs)
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530453{
454 struct gprs_rlc_ul_header_egprs_1 *egprs1;
455 unsigned int e_ti_header, cur_bit = 0, offs;
456 int punct, punct2, with_padding;
457
458 egprs1 = static_cast < struct gprs_rlc_ul_header_egprs_1 * >
459 ((void *)data);
460 gprs_rlc_mcs_cps_decode(egprs1->cps, cs, &punct, &punct2,
461 &with_padding);
462 gprs_rlc_data_info_init_ul(rlc, cs, with_padding);
463
464 rlc->r = egprs1->r;
465 rlc->si = egprs1->si;
Tom Tsoudf698092016-07-11 17:05:19 -0700466 rlc->tfi = (egprs1->tfi_hi << 0) | (egprs1->tfi_lo << 2);
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530467 rlc->cps = egprs1->cps;
468 rlc->rsb = egprs1->rsb;
469 rlc->num_data_blocks = 2;
470 rlc->block_info[0].cv = egprs1->cv;
471 rlc->block_info[0].pi = egprs1->pi;
472 rlc->block_info[0].bsn =
Tom Tsoudf698092016-07-11 17:05:19 -0700473 (egprs1->bsn1_hi << 0) | (egprs1->bsn1_lo << 5);
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530474
475 cur_bit += rlc->data_offs_bits[0] - 2;
476 offs = rlc->data_offs_bits[0] / 8;
477 OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 0);
478
479 e_ti_header = data[offs - 1] >> 6;
480 rlc->block_info[0].e = (e_ti_header & 0x01);
481 rlc->block_info[0].ti = !!(e_ti_header & 0x02);
482 cur_bit += 2;
483
484 rlc->block_info[1].cv = egprs1->cv;
485 rlc->block_info[1].pi = egprs1->pi;
486 rlc->block_info[1].bsn = rlc->block_info[0].bsn +
Tom Tsoudf698092016-07-11 17:05:19 -0700487 ((egprs1->bsn2_hi << 0) | (egprs1->bsn2_lo << 2));
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530488 rlc->block_info[1].bsn = rlc->block_info[1].bsn & (RLC_EGPRS_SNS - 1);
489
490 if ((rlc->block_info[1].bsn != rlc->block_info[0].bsn) &&
491 (rlc->block_info[0].cv == 0))
492 rlc->block_info[0].cv = 1;
493
494 cur_bit = rlc->data_offs_bits[1] - 2;
495
496 offs = rlc->data_offs_bits[1] / 8;
497 OSMO_ASSERT(rlc->data_offs_bits[1] % 8 == 2);
498
499 e_ti_header = (data[offs] & (0x03));
500 rlc->block_info[1].e = (e_ti_header & 0x01);
501 rlc->block_info[1].ti = !!(e_ti_header & 0x02);
502 cur_bit += 2;
503 /* skip data area */
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200504 cur_bit += mcs_max_data_block_bytes(cs) * 8;
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530505
506 return cur_bit;
507}
508
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530509int Decoding::rlc_parse_ul_data_header_gprs(struct gprs_rlc_data_info *rlc,
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200510 const uint8_t *data, const enum CodingScheme &cs)
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530511{
512 const struct rlc_ul_header *gprs;
513 unsigned int cur_bit = 0;
514
515 gprs = static_cast < struct rlc_ul_header * >
516 ((void *)data);
517
518 gprs_rlc_data_info_init_ul(rlc, cs, false);
519
520 rlc->r = gprs->r;
521 rlc->si = gprs->si;
522 rlc->tfi = gprs->tfi;
523 rlc->cps = 0;
524 rlc->rsb = 0;
525 rlc->num_data_blocks = 1;
526 rlc->block_info[0].cv = gprs->cv;
527 rlc->block_info[0].pi = gprs->pi;
528 rlc->block_info[0].bsn = gprs->bsn;
529 rlc->block_info[0].e = gprs->e;
530 rlc->block_info[0].ti = gprs->ti;
531 rlc->block_info[0].spb = 0;
532 cur_bit += rlc->data_offs_bits[0];
533 /* skip data area */
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200534 cur_bit += mcs_max_data_block_bytes(cs) * 8;
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530535
536 return cur_bit;
537}
538
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100539/**
540 * \brief Copy LSB bitstream RLC data block to byte aligned buffer.
541 *
542 * Note that the bitstream is encoded in LSB first order, so the two octets
543 * 654321xx xxxxxx87 contain the octet 87654321 starting at bit position 3
544 * (LSB has bit position 1). This is a different order than the one used by
545 * CSN.1.
546 *
547 * \param data_block_idx The block index, 0..1 for header type 1, 0 otherwise
548 * \param src A pointer to the start of the RLC block (incl. the header)
549 * \param buffer A data area of a least the size of the RLC block
550 * \returns the number of bytes copied
551 */
552unsigned int Decoding::rlc_copy_to_aligned_buffer(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100553 const struct gprs_rlc_data_info *rlc,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100554 unsigned int data_block_idx,
555 const uint8_t *src, uint8_t *buffer)
556{
557 unsigned int hdr_bytes;
558 unsigned int extra_bits;
559 unsigned int i;
560
561 uint8_t c, last_c;
562 uint8_t *dst;
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100563 const struct gprs_rlc_data_block_info *rdbi;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100564
565 OSMO_ASSERT(data_block_idx < rlc->num_data_blocks);
566 rdbi = &rlc->block_info[data_block_idx];
567
568 hdr_bytes = rlc->data_offs_bits[data_block_idx] >> 3;
569 extra_bits = (rlc->data_offs_bits[data_block_idx] & 7);
570
571 if (extra_bits == 0) {
572 /* It is aligned already */
573 memmove(buffer, src + hdr_bytes, rdbi->data_len);
574 return rdbi->data_len;
575 }
576
577 dst = buffer;
578 src = src + hdr_bytes;
579 last_c = *(src++);
580
581 for (i = 0; i < rdbi->data_len; i++) {
582 c = src[i];
583 *(dst++) = (last_c >> extra_bits) | (c << (8 - extra_bits));
584 last_c = c;
585 }
586
587 return rdbi->data_len;
588}
589
590/**
591 * \brief Get a pointer to byte aligned RLC data.
592 *
593 * Since the RLC data may not be byte aligned to the RLC block data such that a
594 * single RLC data byte is spread over two RLC block bytes, this function
595 * eventually uses the provided buffer as data storage.
596 *
597 * \param src A pointer to the start of the RLC block (incl. the header)
598 * \param buffer A data area of a least the size of the RLC block
599 * \returns A pointer to the RLC data start within src if it is aligned, and
600 * buffer otherwise.
601 */
602const uint8_t *Decoding::rlc_get_data_aligned(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100603 const struct gprs_rlc_data_info *rlc,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100604 unsigned int data_block_idx,
605 const uint8_t *src, uint8_t *buffer)
606{
607 unsigned int hdr_bytes;
608 unsigned int extra_bits;
609
610 OSMO_ASSERT(data_block_idx < ARRAY_SIZE(rlc->data_offs_bits));
611
612 hdr_bytes = rlc->data_offs_bits[data_block_idx] >> 3;
613 extra_bits = (rlc->data_offs_bits[data_block_idx] & 7);
614
615 if (extra_bits == 0)
616 /* It is aligned already, return a pointer that refers to the
617 * original data. */
618 return src + hdr_bytes;
619
620 Decoding::rlc_copy_to_aligned_buffer(rlc, data_block_idx, src, buffer);
621 return buffer;
622}
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100623
624static int handle_final_ack(bitvec *bits, int *bsn_begin, int *bsn_end,
625 gprs_rlc_dl_window *window)
626{
627 int num_blocks, i;
628
629 num_blocks = window->mod_sns(window->v_s() - window->v_a());
630 for (i = 0; i < num_blocks; i++)
631 bitvec_set_bit(bits, ONE);
632
633 *bsn_begin = window->v_a();
634 *bsn_end = window->mod_sns(*bsn_begin + num_blocks);
635 return num_blocks;
636}
637
638int Decoding::decode_egprs_acknack_bits(const EGPRS_AckNack_Desc_t *desc,
639 bitvec *bits, int *bsn_begin, int *bsn_end, gprs_rlc_dl_window *window)
640{
641 int urbb_len = desc->URBB_LENGTH;
642 int crbb_len = 0;
643 int num_blocks = 0;
644 struct bitvec urbb;
645 int i;
646 bool have_bitmap;
647 int implicitly_acked_blocks;
648 int ssn = desc->STARTING_SEQUENCE_NUMBER;
Jacob Erlbeck2bef4db2016-01-20 14:33:11 +0100649 int rc;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100650
651 if (desc->FINAL_ACK_INDICATION)
652 return handle_final_ack(bits, bsn_begin, bsn_end, window);
653
654 if (desc->Exist_CRBB)
655 crbb_len = desc->CRBB_LENGTH;
656
657 have_bitmap = (urbb_len + crbb_len) > 0;
658
659 /*
660 * bow & bitmap present:
661 * V(A)-> [ 11111...11111 0 SSN-> BBBBB...BBBBB ] (SSN+Nbits) .... V(S)
662 * bow & not bitmap present:
663 * V(A)-> [ 11111...11111 ] . SSN .... V(S)
664 * not bow & bitmap present:
665 * V(A)-> ... [ 0 SSN-> BBBBB...BBBBB ](SSN+N) .... V(S)
666 * not bow & not bitmap present:
667 * V(A)-> ... [] . SSN .... V(S)
668 */
669
670 if (desc->BEGINNING_OF_WINDOW) {
671 implicitly_acked_blocks = window->mod_sns(ssn - 1 - window->v_a());
672
673 for (i = 0; i < implicitly_acked_blocks; i++)
674 bitvec_set_bit(bits, ONE);
675
676 num_blocks += implicitly_acked_blocks;
677 }
678
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100679 if (!have_bitmap)
680 goto aborted;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100681
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100682 /* next bit refers to V(Q) and thus is always zero (and not
683 * transmitted) */
684 bitvec_set_bit(bits, ZERO);
685 num_blocks += 1;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100686
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100687 if (crbb_len > 0) {
688 int old_len = bits->cur_bit;
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100689
Pravin Kumarvel0a4a6c12016-10-17 11:00:57 +0530690 LOGP(DRLCMACDL, LOGL_DEBUG, "Compress bitmap exists, "
691 "CRBB LEN = %d and Starting color code = %d",
692 desc->CRBB_LENGTH, desc->CRBB_STARTING_COLOR_CODE);
693 rc = egprs_compress::decompress_crbb(desc->CRBB_LENGTH,
694 desc->CRBB_STARTING_COLOR_CODE, desc->CRBB, bits);
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100695 if (rc < 0) {
696 LOGP(DRLCMACUL, LOGL_NOTICE,
Pravin Kumarvel0a4a6c12016-10-17 11:00:57 +0530697 "Failed to decode CRBB: length %d, data '%s'\n",
698 desc->CRBB_LENGTH, osmo_hexdump(
699 desc->CRBB, (desc->CRBB_LENGTH + 7)/8));
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100700 /* We don't know the SSN offset for the URBB,
701 * return what we have so far and assume the
702 * bitmap has stopped here */
703 goto aborted;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100704 }
705
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100706 LOGP(DRLCMACDL, LOGL_DEBUG,
707 "CRBB len: %d, decoded len: %d, cc: %d, crbb: '%s'\n",
708 desc->CRBB_LENGTH, bits->cur_bit - old_len,
709 desc->CRBB_STARTING_COLOR_CODE,
710 osmo_hexdump(
711 desc->CRBB, (desc->CRBB_LENGTH + 7)/8)
712 );
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100713
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100714 num_blocks += (bits->cur_bit - old_len);
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100715 }
716
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100717 urbb.cur_bit = 0;
718 urbb.data = (uint8_t *)desc->URBB;
719 urbb.data_len = sizeof(desc->URBB);
720
721 for (i = urbb_len; i > 0; i--) {
722 /*
723 * Set bit at the appropriate position (see 3GPP TS
724 * 44.060 12.3.1)
725 */
726 int is_ack = bitvec_get_bit_pos(&urbb, i-1);
727 bitvec_set_bit(bits, is_ack == 1 ? ONE : ZERO);
728 }
729 num_blocks += urbb_len;
730
731aborted:
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100732 *bsn_begin = window->v_a();
733 *bsn_end = window->mod_sns(*bsn_begin + num_blocks);
734
735 return num_blocks;
736}
Jacob Erlbeck192bf332016-02-05 13:10:29 +0100737
738int Decoding::decode_gprs_acknack_bits(const Ack_Nack_Description_t *desc,
739 bitvec *bits, int *bsn_begin, int *bsn_end, gprs_rlc_dl_window *window)
740{
741 int urbb_len = RLC_GPRS_WS;
742 int num_blocks;
743 struct bitvec urbb;
744
745 if (desc->FINAL_ACK_INDICATION)
746 return handle_final_ack(bits, bsn_begin, bsn_end, window);
747
748 *bsn_begin = window->v_a();
749 *bsn_end = desc->STARTING_SEQUENCE_NUMBER;
750
751 num_blocks = window->mod_sns(*bsn_end - *bsn_begin);
752
753 if (num_blocks < 0 || num_blocks > urbb_len) {
754 *bsn_end = *bsn_begin;
755 LOGP(DRLCMACUL, LOGL_NOTICE,
756 "Invalid GPRS Ack/Nack window %d:%d (length %d)\n",
757 *bsn_begin, *bsn_end, num_blocks);
758 return -EINVAL;
759 }
760
761 urbb.cur_bit = 0;
762 urbb.data = (uint8_t *)desc->RECEIVED_BLOCK_BITMAP;
763 urbb.data_len = sizeof(desc->RECEIVED_BLOCK_BITMAP);
764
765 /*
766 * TS 44.060, 12.3:
767 * BSN = (SSN - bit_number) modulo 128, for bit_number = 1 to 64.
768 * The BSN values represented range from (SSN - 1) mod 128 to (SSN - 64) mod 128.
769 *
770 * We are only interested in the range from V(A) to SSN-1 which is
771 * num_blocks large. The RBB is laid out as
772 * [SSN-1] [SSN-2] ... [V(A)] ... [SSN-64]
773 * so we want to start with [V(A)] and go backwards until we reach
774 * [SSN-1] to get the needed BSNs in an increasing order. Note that
775 * the bit numbers are counted from the end of the buffer.
776 */
777 for (int i = num_blocks; i > 0; i--) {
778 int is_ack = bitvec_get_bit_pos(&urbb, urbb_len - i);
779 bitvec_set_bit(bits, is_ack == 1 ? ONE : ZERO);
780 }
781
782 return num_blocks;
783}