blob: 0caa8bfd72e86888c03d7f8ccbb0e77c4a13c80a [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.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20#include <decoding.h>
21#include <rlc.h>
22#include <gprs_debug.h>
Pravin Kumarvel0a4a6c12016-10-17 11:00:57 +053023#include <egprs_rlc_compression.h>
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +020024
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010025extern "C" {
26#include <osmocom/core/utils.h>
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +010027#include <osmocom/core/bitcomp.h>
Tom Tsoudf698092016-07-11 17:05:19 -070028#include <osmocom/gprs/protocol/gsm_04_60.h>
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010029}
30
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +020031#include <arpa/inet.h>
32
33#include <errno.h>
34#include <string.h>
35
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010036#define LENGTH_TO_END 255
Alexander Couzensb82bd922016-05-30 17:30:10 +020037/*!
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010038 * \returns num extensions fields (num frames == offset) on success,
39 * -errno otherwise.
40 */
41static int parse_extensions_egprs(const uint8_t *data, unsigned int data_len,
42 unsigned int *offs,
43 bool is_last_block,
44 Decoding::RlcData *chunks, unsigned int chunks_size)
45{
46 const struct rlc_li_field_egprs *li;
47 uint8_t e;
48 unsigned int num_chunks = 0;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010049
50 e = 0;
51 while (!e) {
52 if (*offs > data_len) {
53 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
54 "but no more data\n");
55 return -EINVAL;
56 }
57
58 /* get new E */
59 li = (struct rlc_li_field_egprs *)&data[*offs];
60 e = li->e;
61 *offs += 1;
62
63 if (!chunks)
64 continue;
65
66 if (num_chunks == chunks_size) {
67 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
68 "but no more chunks possible\n");
69 return -ENOSPC;
70 }
Aravind Sirsikar22a90192016-09-15 17:24:49 +053071 if (li->li == 0 && num_chunks == 0) {
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010072 /* TS 44.060, table 10.4.14a.1, row 2a */
Aravind Sirsikar22a90192016-09-15 17:24:49 +053073 /* TS 44.060, table 10.4.14a.1, row 4 */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010074 chunks[num_chunks].length = 0;
75 chunks[num_chunks].is_complete = true;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010076 } else if (li->li == 127 && li->e == 1) {
77 /* TS 44.060, table 10.4.14a.1, row 3 & 5 */
78 /* only filling bytes left */
Mrinal Mishra0e636442016-11-28 19:46:50 +053079 LOGP(DRLCMACUL, LOGL_DEBUG, "UL DATA LI contains "
Thorsten Alteholz8bb79042018-10-06 10:42:58 +020080 "only filling bytes with extension octet: LI=%d, E=%d, count=%d\n",
Mrinal Mishra0e636442016-11-28 19:46:50 +053081 li->li, li->e, num_chunks);
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010082 break;
83 } else if (li->li > 0) {
84 /* TS 44.060, table 10.4.14a.1, row 1 & 2b */
85 chunks[num_chunks].length = li->li;
86 chunks[num_chunks].is_complete = true;
87 } else {
88 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI contains "
89 "invalid extension octet: LI=%d, E=%d, count=%d\n",
90 li->li, li->e, num_chunks);
91 return -EINVAL;
92 }
93
Mrinal Mishra0e636442016-11-28 19:46:50 +053094 LOGP(DRLCMACUL, LOGL_DEBUG, "UL DATA LI contains "
Thorsten Alteholz8bb79042018-10-06 10:42:58 +020095 "extension octet: LI=%d, E=%d, count=%d\n",
Mrinal Mishra0e636442016-11-28 19:46:50 +053096 li->li, li->e, num_chunks);
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010097 num_chunks += 1;
98
99 if (e == 1) {
100 /* There is space after the last chunk, add a final one */
101 if (num_chunks == chunks_size) {
102 LOGP(DRLCMACUL, LOGL_NOTICE,
103 "UL DATA LI possibly extended, "
104 "but no more chunks possible\n");
105 return -ENOSPC;
106 }
107
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100108 chunks[num_chunks].length = LENGTH_TO_END;
109 chunks[num_chunks].is_complete = is_last_block;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100110 num_chunks += 1;
111 }
112 }
113
114 return num_chunks;
115}
116
117static int parse_extensions_gprs(const uint8_t *data, unsigned int data_len,
118 unsigned int *offs,
119 bool is_last_block,
120 Decoding::RlcData *chunks, unsigned int chunks_size)
121{
122 const struct rlc_li_field *li;
123 uint8_t m, e;
124 unsigned int num_chunks = 0;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100125
126 e = 0;
127 while (!e) {
128 if (*offs > data_len) {
129 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
130 "but no more data\n");
131 return -EINVAL;
132 }
133
134 /* get new E */
135 li = (const struct rlc_li_field *)&data[*offs];
136 e = li->e;
137 m = li->m;
138 *offs += 1;
139
140 if (li->li == 0) {
141 /* TS 44.060, 10.4.14, par 6 */
142 e = 1;
143 m = 0;
144 }
145
146 /* TS 44.060, table 10.4.13.1 */
147 if (m == 0 && e == 0) {
148 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA "
149 "ignored, because M='0' and E='0'.\n");
150 return 0;
151 }
152
153 if (!chunks)
154 continue;
155
156 if (num_chunks == chunks_size) {
157 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
158 "but no more chunks possible\n");
159 return -ENOSPC;
160 }
161
162 if (li->li == 0)
163 /* e is 1 here */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100164 chunks[num_chunks].length = LENGTH_TO_END;
165 else
166 chunks[num_chunks].length = li->li;
167
168 chunks[num_chunks].is_complete = li->li || is_last_block;
169
Mrinal Mishra0e636442016-11-28 19:46:50 +0530170 LOGP(DRLCMACUL, LOGL_DEBUG, "UL DATA LI contains "
Thorsten Alteholz8bb79042018-10-06 10:42:58 +0200171 "extension octet: LI=%d, M=%d, E=%d, count=%d\n",
Mrinal Mishra0e636442016-11-28 19:46:50 +0530172 li->li, li->m, li->e, num_chunks);
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100173 num_chunks += 1;
174
175 if (e == 1 && m == 1) {
176 if (num_chunks == chunks_size) {
177 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
178 "but no more chunks possible\n");
179 return -ENOSPC;
180 }
181 /* TS 44.060, 10.4.13.1, row 4 */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100182 chunks[num_chunks].length = LENGTH_TO_END;
183 chunks[num_chunks].is_complete = is_last_block;
184 num_chunks += 1;
185 }
186 }
187
188 return num_chunks;
189}
190
191int Decoding::rlc_data_from_ul_data(
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200192 const struct gprs_rlc_data_block_info *rdbi, enum CodingScheme cs,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100193 const uint8_t *data, RlcData *chunks, unsigned int chunks_size,
194 uint32_t *tlli)
195{
196 uint8_t e;
197 unsigned int data_len = rdbi->data_len;
Jacob Erlbeckead5e472016-01-08 10:14:50 +0100198 int num_chunks = 0, i;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100199 unsigned int offs = 0;
200 bool is_last_block = (rdbi->cv == 0);
201
202 if (!chunks)
203 chunks_size = 0;
204
205 e = rdbi->e;
206 if (e) {
207 if (chunks_size > 0) {
Alexander Couzensb82bd922016-05-30 17:30:10 +0200208 /* Block without LI means it only contains data of one LLC PDU */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100209 chunks[num_chunks].offset = offs;
210 chunks[num_chunks].length = LENGTH_TO_END;
211 chunks[num_chunks].is_complete = is_last_block;
212 num_chunks += 1;
213 } else if (chunks) {
214 LOGP(DRLCMACUL, LOGL_NOTICE, "No extension, "
215 "but no more chunks possible\n");
216 return -ENOSPC;
217 }
Max8a8e0fb2019-03-25 16:32:50 +0100218 } else if (mcs_is_edge(cs)) {
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100219 /* if E is not set (LI follows), EGPRS */
220 num_chunks = parse_extensions_egprs(data, data_len, &offs,
221 is_last_block,
222 chunks, chunks_size);
223 } else {
224 /* if E is not set (LI follows), GPRS */
225 num_chunks = parse_extensions_gprs(data, data_len, &offs,
226 is_last_block,
227 chunks, chunks_size);
228 }
229
Jacob Erlbeckead5e472016-01-08 10:14:50 +0100230 if (num_chunks < 0)
231 return num_chunks;
232
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100233 /* TLLI */
234 if (rdbi->ti) {
235 uint32_t tlli_enc;
236 if (offs + 4 > data_len) {
237 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TLLI out of block "
238 "border\n");
239 return -EINVAL;
240 }
241
242 memcpy(&tlli_enc, data + offs, sizeof(tlli_enc));
Max8a8e0fb2019-03-25 16:32:50 +0100243 if (mcs_is_gprs(cs))
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100244 /* The TLLI is encoded in big endian for GPRS (see
245 * TS 44.060, figure 10.2.2.1, note) */
246 *tlli = be32toh(tlli_enc);
247 else
248 /* The TLLI is encoded in little endian for EGPRS (see
249 * TS 44.060, figure 10.3a.2.1, note 2) */
250 *tlli = le32toh(tlli_enc);
251
252 offs += sizeof(tlli_enc);
253 } else {
254 *tlli = 0;
255 }
256
257 /* PFI */
258 if (rdbi->pi) {
259 LOGP(DRLCMACUL, LOGL_ERROR, "ERROR: PFI not supported, "
260 "please disable in SYSTEM INFORMATION\n");
261 return -ENOTSUP;
262
263 /* TODO: Skip all extensions with E=0 (see TS 44.060, 10.4.11 */
264 }
265
Jacob Erlbeckead5e472016-01-08 10:14:50 +0100266 if (chunks_size == 0)
267 return num_chunks;
268
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100269 /* LLC */
270 for (i = 0; i < num_chunks; i++) {
271 chunks[i].offset = offs;
272 if (chunks[i].length == LENGTH_TO_END) {
273 if (offs == data_len) {
274 /* There is no place for an additional chunk,
275 * so drop it (this may happen with EGPRS since
276 * there is no M flag. */
277 num_chunks -= 1;
Alexander Couzensd302e4f2016-05-30 17:31:09 +0200278 break;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100279 }
280 chunks[i].length = data_len - offs;
281 }
282 offs += chunks[i].length;
283 if (offs > data_len) {
284 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA out of block "
Pau Espin Pedrolf861d312020-06-30 21:33:43 +0200285 "border, chunk idx: %d, offset: %u, size: %d, data_len: %u\n",
286 i, offs, chunks[i].length, data_len);
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100287 return -EINVAL;
288 }
289 }
290
291 return num_chunks;
292}
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +0200293
Pau Espin Pedrol8a35e642021-01-18 17:14:14 +0100294uint8_t get_ms_class_by_capability(MS_Radio_Access_capability_t *cap)
Holger Hans Peter Freytherfcbc7022013-10-26 17:38:37 +0200295{
296 int i;
297
298 for (i = 0; i < cap->Count_MS_RA_capability_value; i++) {
299 if (!cap->MS_RA_capability_value[i].u.Content.Exist_Multislot_capability)
300 continue;
301 if (!cap->MS_RA_capability_value[i].u.Content.Multislot_capability.Exist_GPRS_multislot_class)
302 continue;
303 return cap->MS_RA_capability_value[i].u.Content.Multislot_capability.GPRS_multislot_class;
304 }
305
306 return 0;
307}
308
Pau Espin Pedrol8a35e642021-01-18 17:14:14 +0100309uint8_t get_egprs_ms_class_by_capability(MS_Radio_Access_capability_t *cap)
Jacob Erlbeckc3c58042015-09-28 17:55:32 +0200310{
311 int i;
312
313 for (i = 0; i < cap->Count_MS_RA_capability_value; i++) {
314 if (!cap->MS_RA_capability_value[i].u.Content.Exist_Multislot_capability)
315 continue;
316 if (!cap->MS_RA_capability_value[i].u.Content.Multislot_capability.Exist_EGPRS_multislot_class)
317 continue;
318 return cap->MS_RA_capability_value[i].u.Content.Multislot_capability.EGPRS_multislot_class;
319 }
320
321 return 0;
322}
323
Holger Hans Peter Freytherdf6b4f52013-11-24 17:05:48 +0100324/**
325 * show_rbb needs to be an array with 65 elements
Daniel Willmann5e94cd42013-12-11 20:11:16 +0100326 * The index of the array is the bit position in the rbb
327 * (show_rbb[63] relates to BSN ssn-1)
Holger Hans Peter Freytherdf6b4f52013-11-24 17:05:48 +0100328 */
Jacob Erlbeckf2f24b02016-02-05 13:16:24 +0100329void Decoding::extract_rbb(const struct bitvec *rbb, char *show_rbb)
330{
331 unsigned int i;
332 for (i = 0; i < rbb->cur_bit; i++) {
333 uint8_t bit;
334 bit = bitvec_get_bit_pos(rbb, i);
335 show_rbb[i] = bit == 1 ? 'R' : 'I';
336 }
337
338 show_rbb[i] = '\0';
339}
340
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100341int Decoding::rlc_parse_ul_data_header(struct gprs_rlc_data_info *rlc,
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200342 const uint8_t *data, enum CodingScheme cs)
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100343{
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100344 unsigned int cur_bit = 0;
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200345 switch(mcs_header_type(cs)) {
Max51754b62019-03-13 17:14:13 +0100346 case HEADER_GPRS_DATA :
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530347 cur_bit = rlc_parse_ul_data_header_gprs(rlc, data, cs);
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100348 break;
Max51754b62019-03-13 17:14:13 +0100349 case HEADER_EGPRS_DATA_TYPE_3 :
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530350 cur_bit = rlc_parse_ul_data_header_egprs_type_3(rlc, data, cs);
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100351 break;
Max51754b62019-03-13 17:14:13 +0100352 case HEADER_EGPRS_DATA_TYPE_2 :
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530353 cur_bit = rlc_parse_ul_data_header_egprs_type_2(rlc, data, cs);
354 break;
Max51754b62019-03-13 17:14:13 +0100355 case HEADER_EGPRS_DATA_TYPE_1 :
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530356 cur_bit = rlc_parse_ul_data_header_egprs_type_1(rlc, data, cs);
357 break;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100358 default:
359 LOGP(DRLCMACDL, LOGL_ERROR,
360 "Decoding of uplink %s data blocks not yet supported.\n",
Max136ebcc2019-03-05 14:59:03 +0100361 mcs_name(cs));
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100362 return -ENOTSUP;
363 };
364
365 return cur_bit;
366}
367
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530368int Decoding::rlc_parse_ul_data_header_egprs_type_3(
369 struct gprs_rlc_data_info *rlc,
370 const uint8_t *data,
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200371 const enum CodingScheme &cs)
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530372{
373 int punct, punct2, with_padding, cps;
374 unsigned int e_ti_header, offs, cur_bit = 0;
375 const struct gprs_rlc_ul_header_egprs_3 *egprs3;
376
377 egprs3 = static_cast < struct gprs_rlc_ul_header_egprs_3 * >
378 ((void *)data);
379
Tom Tsoudf698092016-07-11 17:05:19 -0700380 cps = (egprs3->cps_hi << 0) | (egprs3->cps_lo << 2);
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530381 gprs_rlc_mcs_cps_decode(cps, cs, &punct, &punct2, &with_padding);
382 gprs_rlc_data_info_init_ul(rlc, cs, with_padding);
383
384 rlc->r = egprs3->r;
385 rlc->si = egprs3->si;
Tom Tsoudf698092016-07-11 17:05:19 -0700386 rlc->tfi = (egprs3->tfi_hi << 0) | (egprs3->tfi_lo << 2);
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530387 rlc->cps = cps;
388 rlc->rsb = egprs3->rsb;
389
390 rlc->num_data_blocks = 1;
391 rlc->block_info[0].cv = egprs3->cv;
392 rlc->block_info[0].pi = egprs3->pi;
393 rlc->block_info[0].spb = egprs3->spb;
394 rlc->block_info[0].bsn =
Tom Tsoudf698092016-07-11 17:05:19 -0700395 (egprs3->bsn1_hi << 0) | (egprs3->bsn1_lo << 5);
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530396
397 cur_bit += rlc->data_offs_bits[0] - 2;
398 offs = rlc->data_offs_bits[0] / 8;
399 OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 1);
400 e_ti_header = (data[offs-1] + (data[offs] << 8)) >> 7;
401 rlc->block_info[0].e = !!(e_ti_header & 0x01);
402 rlc->block_info[0].ti = !!(e_ti_header & 0x02);
403 cur_bit += 2;
404 /* skip data area */
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200405 cur_bit += mcs_max_data_block_bytes(cs) * 8;
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530406
407 return cur_bit;
408}
409
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530410int Decoding::rlc_parse_ul_data_header_egprs_type_2(
411 struct gprs_rlc_data_info *rlc,
412 const uint8_t *data,
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200413 const enum CodingScheme &cs)
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530414{
415 const struct gprs_rlc_ul_header_egprs_2 *egprs2;
416 unsigned int e_ti_header, offs, cur_bit = 0;
417 int punct, punct2, with_padding, cps;
418
419 egprs2 = static_cast < struct gprs_rlc_ul_header_egprs_2 * >
420 ((void *)data);
421
Tom Tsoudf698092016-07-11 17:05:19 -0700422 cps = (egprs2->cps_hi << 0) | (egprs2->cps_lo << 2);
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530423 gprs_rlc_mcs_cps_decode(cps, cs, &punct, &punct2, &with_padding);
424 gprs_rlc_data_info_init_ul(rlc, cs, with_padding);
425
426 rlc->r = egprs2->r;
427 rlc->si = egprs2->si;
Tom Tsoudf698092016-07-11 17:05:19 -0700428 rlc->tfi = (egprs2->tfi_hi << 0) | (egprs2->tfi_lo << 2);
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530429 rlc->cps = cps;
430 rlc->rsb = egprs2->rsb;
431
432 rlc->num_data_blocks = 1;
433 rlc->block_info[0].cv = egprs2->cv;
434 rlc->block_info[0].pi = egprs2->pi;
435 rlc->block_info[0].bsn =
Tom Tsoudf698092016-07-11 17:05:19 -0700436 (egprs2->bsn1_hi << 0) | (egprs2->bsn1_lo << 5);
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530437
438 cur_bit += rlc->data_offs_bits[0] - 2;
439
440 offs = rlc->data_offs_bits[0] / 8;
441 OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 7);
442
443 e_ti_header = (data[offs] & 0x60) >> 5;
444 rlc->block_info[0].e = !!(e_ti_header & 0x01);
445 rlc->block_info[0].ti = !!(e_ti_header & 0x02);
446 cur_bit += 2;
447
448 /* skip data area */
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200449 cur_bit += mcs_max_data_block_bytes(cs) * 8;
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530450
451 return cur_bit;
452}
453
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530454int Decoding::rlc_parse_ul_data_header_egprs_type_1(
455 struct gprs_rlc_data_info *rlc,
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200456 const uint8_t *data, const enum CodingScheme &cs)
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530457{
458 struct gprs_rlc_ul_header_egprs_1 *egprs1;
459 unsigned int e_ti_header, cur_bit = 0, offs;
460 int punct, punct2, with_padding;
461
462 egprs1 = static_cast < struct gprs_rlc_ul_header_egprs_1 * >
463 ((void *)data);
464 gprs_rlc_mcs_cps_decode(egprs1->cps, cs, &punct, &punct2,
465 &with_padding);
466 gprs_rlc_data_info_init_ul(rlc, cs, with_padding);
467
468 rlc->r = egprs1->r;
469 rlc->si = egprs1->si;
Tom Tsoudf698092016-07-11 17:05:19 -0700470 rlc->tfi = (egprs1->tfi_hi << 0) | (egprs1->tfi_lo << 2);
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530471 rlc->cps = egprs1->cps;
472 rlc->rsb = egprs1->rsb;
473 rlc->num_data_blocks = 2;
474 rlc->block_info[0].cv = egprs1->cv;
475 rlc->block_info[0].pi = egprs1->pi;
476 rlc->block_info[0].bsn =
Tom Tsoudf698092016-07-11 17:05:19 -0700477 (egprs1->bsn1_hi << 0) | (egprs1->bsn1_lo << 5);
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530478
479 cur_bit += rlc->data_offs_bits[0] - 2;
480 offs = rlc->data_offs_bits[0] / 8;
481 OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 0);
482
483 e_ti_header = data[offs - 1] >> 6;
484 rlc->block_info[0].e = (e_ti_header & 0x01);
485 rlc->block_info[0].ti = !!(e_ti_header & 0x02);
486 cur_bit += 2;
487
488 rlc->block_info[1].cv = egprs1->cv;
489 rlc->block_info[1].pi = egprs1->pi;
490 rlc->block_info[1].bsn = rlc->block_info[0].bsn +
Tom Tsoudf698092016-07-11 17:05:19 -0700491 ((egprs1->bsn2_hi << 0) | (egprs1->bsn2_lo << 2));
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530492 rlc->block_info[1].bsn = rlc->block_info[1].bsn & (RLC_EGPRS_SNS - 1);
493
494 if ((rlc->block_info[1].bsn != rlc->block_info[0].bsn) &&
495 (rlc->block_info[0].cv == 0))
496 rlc->block_info[0].cv = 1;
497
498 cur_bit = rlc->data_offs_bits[1] - 2;
499
500 offs = rlc->data_offs_bits[1] / 8;
501 OSMO_ASSERT(rlc->data_offs_bits[1] % 8 == 2);
502
503 e_ti_header = (data[offs] & (0x03));
504 rlc->block_info[1].e = (e_ti_header & 0x01);
505 rlc->block_info[1].ti = !!(e_ti_header & 0x02);
506 cur_bit += 2;
507 /* skip data area */
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200508 cur_bit += mcs_max_data_block_bytes(cs) * 8;
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530509
510 return cur_bit;
511}
512
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530513int Decoding::rlc_parse_ul_data_header_gprs(struct gprs_rlc_data_info *rlc,
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200514 const uint8_t *data, const enum CodingScheme &cs)
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530515{
516 const struct rlc_ul_header *gprs;
517 unsigned int cur_bit = 0;
518
519 gprs = static_cast < struct rlc_ul_header * >
520 ((void *)data);
521
522 gprs_rlc_data_info_init_ul(rlc, cs, false);
523
524 rlc->r = gprs->r;
525 rlc->si = gprs->si;
526 rlc->tfi = gprs->tfi;
527 rlc->cps = 0;
528 rlc->rsb = 0;
529 rlc->num_data_blocks = 1;
530 rlc->block_info[0].cv = gprs->cv;
531 rlc->block_info[0].pi = gprs->pi;
532 rlc->block_info[0].bsn = gprs->bsn;
533 rlc->block_info[0].e = gprs->e;
534 rlc->block_info[0].ti = gprs->ti;
535 rlc->block_info[0].spb = 0;
536 cur_bit += rlc->data_offs_bits[0];
537 /* skip data area */
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200538 cur_bit += mcs_max_data_block_bytes(cs) * 8;
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530539
540 return cur_bit;
541}
542
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100543/**
544 * \brief Copy LSB bitstream RLC data block to byte aligned buffer.
545 *
546 * Note that the bitstream is encoded in LSB first order, so the two octets
547 * 654321xx xxxxxx87 contain the octet 87654321 starting at bit position 3
548 * (LSB has bit position 1). This is a different order than the one used by
549 * CSN.1.
550 *
551 * \param data_block_idx The block index, 0..1 for header type 1, 0 otherwise
552 * \param src A pointer to the start of the RLC block (incl. the header)
553 * \param buffer A data area of a least the size of the RLC block
554 * \returns the number of bytes copied
555 */
556unsigned int Decoding::rlc_copy_to_aligned_buffer(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100557 const struct gprs_rlc_data_info *rlc,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100558 unsigned int data_block_idx,
559 const uint8_t *src, uint8_t *buffer)
560{
561 unsigned int hdr_bytes;
562 unsigned int extra_bits;
563 unsigned int i;
564
565 uint8_t c, last_c;
566 uint8_t *dst;
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100567 const struct gprs_rlc_data_block_info *rdbi;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100568
569 OSMO_ASSERT(data_block_idx < rlc->num_data_blocks);
570 rdbi = &rlc->block_info[data_block_idx];
571
572 hdr_bytes = rlc->data_offs_bits[data_block_idx] >> 3;
573 extra_bits = (rlc->data_offs_bits[data_block_idx] & 7);
574
575 if (extra_bits == 0) {
576 /* It is aligned already */
577 memmove(buffer, src + hdr_bytes, rdbi->data_len);
578 return rdbi->data_len;
579 }
580
581 dst = buffer;
582 src = src + hdr_bytes;
583 last_c = *(src++);
584
585 for (i = 0; i < rdbi->data_len; i++) {
586 c = src[i];
587 *(dst++) = (last_c >> extra_bits) | (c << (8 - extra_bits));
588 last_c = c;
589 }
590
591 return rdbi->data_len;
592}
593
594/**
595 * \brief Get a pointer to byte aligned RLC data.
596 *
597 * Since the RLC data may not be byte aligned to the RLC block data such that a
598 * single RLC data byte is spread over two RLC block bytes, this function
599 * eventually uses the provided buffer as data storage.
600 *
601 * \param src A pointer to the start of the RLC block (incl. the header)
602 * \param buffer A data area of a least the size of the RLC block
603 * \returns A pointer to the RLC data start within src if it is aligned, and
604 * buffer otherwise.
605 */
606const uint8_t *Decoding::rlc_get_data_aligned(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100607 const struct gprs_rlc_data_info *rlc,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100608 unsigned int data_block_idx,
609 const uint8_t *src, uint8_t *buffer)
610{
611 unsigned int hdr_bytes;
612 unsigned int extra_bits;
613
614 OSMO_ASSERT(data_block_idx < ARRAY_SIZE(rlc->data_offs_bits));
615
616 hdr_bytes = rlc->data_offs_bits[data_block_idx] >> 3;
617 extra_bits = (rlc->data_offs_bits[data_block_idx] & 7);
618
619 if (extra_bits == 0)
620 /* It is aligned already, return a pointer that refers to the
621 * original data. */
622 return src + hdr_bytes;
623
624 Decoding::rlc_copy_to_aligned_buffer(rlc, data_block_idx, src, buffer);
625 return buffer;
626}
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100627
628static int handle_final_ack(bitvec *bits, int *bsn_begin, int *bsn_end,
629 gprs_rlc_dl_window *window)
630{
631 int num_blocks, i;
632
633 num_blocks = window->mod_sns(window->v_s() - window->v_a());
634 for (i = 0; i < num_blocks; i++)
635 bitvec_set_bit(bits, ONE);
636
637 *bsn_begin = window->v_a();
638 *bsn_end = window->mod_sns(*bsn_begin + num_blocks);
639 return num_blocks;
640}
641
642int Decoding::decode_egprs_acknack_bits(const EGPRS_AckNack_Desc_t *desc,
643 bitvec *bits, int *bsn_begin, int *bsn_end, gprs_rlc_dl_window *window)
644{
645 int urbb_len = desc->URBB_LENGTH;
646 int crbb_len = 0;
647 int num_blocks = 0;
648 struct bitvec urbb;
649 int i;
650 bool have_bitmap;
651 int implicitly_acked_blocks;
652 int ssn = desc->STARTING_SEQUENCE_NUMBER;
Jacob Erlbeck2bef4db2016-01-20 14:33:11 +0100653 int rc;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100654
655 if (desc->FINAL_ACK_INDICATION)
656 return handle_final_ack(bits, bsn_begin, bsn_end, window);
657
658 if (desc->Exist_CRBB)
659 crbb_len = desc->CRBB_LENGTH;
660
661 have_bitmap = (urbb_len + crbb_len) > 0;
662
663 /*
664 * bow & bitmap present:
665 * V(A)-> [ 11111...11111 0 SSN-> BBBBB...BBBBB ] (SSN+Nbits) .... V(S)
666 * bow & not bitmap present:
667 * V(A)-> [ 11111...11111 ] . SSN .... V(S)
668 * not bow & bitmap present:
669 * V(A)-> ... [ 0 SSN-> BBBBB...BBBBB ](SSN+N) .... V(S)
670 * not bow & not bitmap present:
671 * V(A)-> ... [] . SSN .... V(S)
672 */
673
674 if (desc->BEGINNING_OF_WINDOW) {
675 implicitly_acked_blocks = window->mod_sns(ssn - 1 - window->v_a());
676
677 for (i = 0; i < implicitly_acked_blocks; i++)
678 bitvec_set_bit(bits, ONE);
679
680 num_blocks += implicitly_acked_blocks;
681 }
682
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100683 if (!have_bitmap)
684 goto aborted;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100685
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100686 /* next bit refers to V(Q) and thus is always zero (and not
687 * transmitted) */
688 bitvec_set_bit(bits, ZERO);
689 num_blocks += 1;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100690
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100691 if (crbb_len > 0) {
692 int old_len = bits->cur_bit;
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100693
Pravin Kumarvel0a4a6c12016-10-17 11:00:57 +0530694 LOGP(DRLCMACDL, LOGL_DEBUG, "Compress bitmap exists, "
695 "CRBB LEN = %d and Starting color code = %d",
696 desc->CRBB_LENGTH, desc->CRBB_STARTING_COLOR_CODE);
697 rc = egprs_compress::decompress_crbb(desc->CRBB_LENGTH,
698 desc->CRBB_STARTING_COLOR_CODE, desc->CRBB, bits);
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100699 if (rc < 0) {
700 LOGP(DRLCMACUL, LOGL_NOTICE,
Pravin Kumarvel0a4a6c12016-10-17 11:00:57 +0530701 "Failed to decode CRBB: length %d, data '%s'\n",
702 desc->CRBB_LENGTH, osmo_hexdump(
703 desc->CRBB, (desc->CRBB_LENGTH + 7)/8));
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100704 /* We don't know the SSN offset for the URBB,
705 * return what we have so far and assume the
706 * bitmap has stopped here */
707 goto aborted;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100708 }
709
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100710 LOGP(DRLCMACDL, LOGL_DEBUG,
711 "CRBB len: %d, decoded len: %d, cc: %d, crbb: '%s'\n",
712 desc->CRBB_LENGTH, bits->cur_bit - old_len,
713 desc->CRBB_STARTING_COLOR_CODE,
714 osmo_hexdump(
715 desc->CRBB, (desc->CRBB_LENGTH + 7)/8)
716 );
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100717
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100718 num_blocks += (bits->cur_bit - old_len);
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100719 }
720
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100721 urbb.cur_bit = 0;
722 urbb.data = (uint8_t *)desc->URBB;
723 urbb.data_len = sizeof(desc->URBB);
724
725 for (i = urbb_len; i > 0; i--) {
726 /*
727 * Set bit at the appropriate position (see 3GPP TS
728 * 44.060 12.3.1)
729 */
730 int is_ack = bitvec_get_bit_pos(&urbb, i-1);
731 bitvec_set_bit(bits, is_ack == 1 ? ONE : ZERO);
732 }
733 num_blocks += urbb_len;
734
735aborted:
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100736 *bsn_begin = window->v_a();
737 *bsn_end = window->mod_sns(*bsn_begin + num_blocks);
738
739 return num_blocks;
740}
Jacob Erlbeck192bf332016-02-05 13:10:29 +0100741
742int Decoding::decode_gprs_acknack_bits(const Ack_Nack_Description_t *desc,
743 bitvec *bits, int *bsn_begin, int *bsn_end, gprs_rlc_dl_window *window)
744{
745 int urbb_len = RLC_GPRS_WS;
746 int num_blocks;
747 struct bitvec urbb;
748
749 if (desc->FINAL_ACK_INDICATION)
750 return handle_final_ack(bits, bsn_begin, bsn_end, window);
751
752 *bsn_begin = window->v_a();
753 *bsn_end = desc->STARTING_SEQUENCE_NUMBER;
754
755 num_blocks = window->mod_sns(*bsn_end - *bsn_begin);
756
757 if (num_blocks < 0 || num_blocks > urbb_len) {
758 *bsn_end = *bsn_begin;
759 LOGP(DRLCMACUL, LOGL_NOTICE,
760 "Invalid GPRS Ack/Nack window %d:%d (length %d)\n",
761 *bsn_begin, *bsn_end, num_blocks);
762 return -EINVAL;
763 }
764
765 urbb.cur_bit = 0;
766 urbb.data = (uint8_t *)desc->RECEIVED_BLOCK_BITMAP;
767 urbb.data_len = sizeof(desc->RECEIVED_BLOCK_BITMAP);
768
769 /*
770 * TS 44.060, 12.3:
771 * BSN = (SSN - bit_number) modulo 128, for bit_number = 1 to 64.
772 * The BSN values represented range from (SSN - 1) mod 128 to (SSN - 64) mod 128.
773 *
774 * We are only interested in the range from V(A) to SSN-1 which is
775 * num_blocks large. The RBB is laid out as
776 * [SSN-1] [SSN-2] ... [V(A)] ... [SSN-64]
777 * so we want to start with [V(A)] and go backwards until we reach
778 * [SSN-1] to get the needed BSNs in an increasing order. Note that
779 * the bit numbers are counted from the end of the buffer.
780 */
781 for (int i = num_blocks; i > 0; i--) {
782 int is_ack = bitvec_get_bit_pos(&urbb, urbb_len - i);
783 bitvec_set_bit(bits, is_ack == 1 ? ONE : ZERO);
784 }
785
786 return num_blocks;
787}