blob: f4cd880293a44cb78353e8265042d723141e96ff [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>
23
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010024extern "C" {
25#include <osmocom/core/utils.h>
26}
27
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +020028#include <arpa/inet.h>
29
30#include <errno.h>
31#include <string.h>
32
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010033#define LENGTH_TO_END 255
34/*
35 * \returns num extensions fields (num frames == offset) on success,
36 * -errno otherwise.
37 */
38static int parse_extensions_egprs(const uint8_t *data, unsigned int data_len,
39 unsigned int *offs,
40 bool is_last_block,
41 Decoding::RlcData *chunks, unsigned int chunks_size)
42{
43 const struct rlc_li_field_egprs *li;
44 uint8_t e;
45 unsigned int num_chunks = 0;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010046
47 e = 0;
48 while (!e) {
49 if (*offs > data_len) {
50 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
51 "but no more data\n");
52 return -EINVAL;
53 }
54
55 /* get new E */
56 li = (struct rlc_li_field_egprs *)&data[*offs];
57 e = li->e;
58 *offs += 1;
59
60 if (!chunks)
61 continue;
62
63 if (num_chunks == chunks_size) {
64 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
65 "but no more chunks possible\n");
66 return -ENOSPC;
67 }
68 if (li->li == 0 && num_chunks == 0 && li->e == 0) {
69 /* TS 44.060, table 10.4.14a.1, row 2a */
70 chunks[num_chunks].length = 0;
71 chunks[num_chunks].is_complete = true;
72 } else if (li->li == 0 && num_chunks == 0 && li->e == 1) {
73 /* TS 44.060, table 10.4.14a.1, row 4 */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010074 chunks[num_chunks].length = LENGTH_TO_END;
75 chunks[num_chunks].is_complete = is_last_block;
76 } 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 */
79 break;
80 } else if (li->li > 0) {
81 /* TS 44.060, table 10.4.14a.1, row 1 & 2b */
82 chunks[num_chunks].length = li->li;
83 chunks[num_chunks].is_complete = true;
84 } else {
85 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI contains "
86 "invalid extension octet: LI=%d, E=%d, count=%d\n",
87 li->li, li->e, num_chunks);
88 return -EINVAL;
89 }
90
91 num_chunks += 1;
92
93 if (e == 1) {
94 /* There is space after the last chunk, add a final one */
95 if (num_chunks == chunks_size) {
96 LOGP(DRLCMACUL, LOGL_NOTICE,
97 "UL DATA LI possibly extended, "
98 "but no more chunks possible\n");
99 return -ENOSPC;
100 }
101
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100102 chunks[num_chunks].length = LENGTH_TO_END;
103 chunks[num_chunks].is_complete = is_last_block;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100104 num_chunks += 1;
105 }
106 }
107
108 return num_chunks;
109}
110
111static int parse_extensions_gprs(const uint8_t *data, unsigned int data_len,
112 unsigned int *offs,
113 bool is_last_block,
114 Decoding::RlcData *chunks, unsigned int chunks_size)
115{
116 const struct rlc_li_field *li;
117 uint8_t m, e;
118 unsigned int num_chunks = 0;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100119
120 e = 0;
121 while (!e) {
122 if (*offs > data_len) {
123 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
124 "but no more data\n");
125 return -EINVAL;
126 }
127
128 /* get new E */
129 li = (const struct rlc_li_field *)&data[*offs];
130 e = li->e;
131 m = li->m;
132 *offs += 1;
133
134 if (li->li == 0) {
135 /* TS 44.060, 10.4.14, par 6 */
136 e = 1;
137 m = 0;
138 }
139
140 /* TS 44.060, table 10.4.13.1 */
141 if (m == 0 && e == 0) {
142 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA "
143 "ignored, because M='0' and E='0'.\n");
144 return 0;
145 }
146
147 if (!chunks)
148 continue;
149
150 if (num_chunks == chunks_size) {
151 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
152 "but no more chunks possible\n");
153 return -ENOSPC;
154 }
155
156 if (li->li == 0)
157 /* e is 1 here */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100158 chunks[num_chunks].length = LENGTH_TO_END;
159 else
160 chunks[num_chunks].length = li->li;
161
162 chunks[num_chunks].is_complete = li->li || is_last_block;
163
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100164 num_chunks += 1;
165
166 if (e == 1 && m == 1) {
167 if (num_chunks == chunks_size) {
168 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
169 "but no more chunks possible\n");
170 return -ENOSPC;
171 }
172 /* TS 44.060, 10.4.13.1, row 4 */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100173 chunks[num_chunks].length = LENGTH_TO_END;
174 chunks[num_chunks].is_complete = is_last_block;
175 num_chunks += 1;
176 }
177 }
178
179 return num_chunks;
180}
181
182int Decoding::rlc_data_from_ul_data(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100183 const struct gprs_rlc_data_block_info *rdbi, GprsCodingScheme cs,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100184 const uint8_t *data, RlcData *chunks, unsigned int chunks_size,
185 uint32_t *tlli)
186{
187 uint8_t e;
188 unsigned int data_len = rdbi->data_len;
Jacob Erlbeckead5e472016-01-08 10:14:50 +0100189 int num_chunks = 0, i;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100190 unsigned int offs = 0;
191 bool is_last_block = (rdbi->cv == 0);
192
193 if (!chunks)
194 chunks_size = 0;
195
196 e = rdbi->e;
197 if (e) {
198 if (chunks_size > 0) {
199 chunks[num_chunks].offset = offs;
200 chunks[num_chunks].length = LENGTH_TO_END;
201 chunks[num_chunks].is_complete = is_last_block;
202 num_chunks += 1;
203 } else if (chunks) {
204 LOGP(DRLCMACUL, LOGL_NOTICE, "No extension, "
205 "but no more chunks possible\n");
206 return -ENOSPC;
207 }
208 } else if (cs.isEgprs()) {
209 /* if E is not set (LI follows), EGPRS */
210 num_chunks = parse_extensions_egprs(data, data_len, &offs,
211 is_last_block,
212 chunks, chunks_size);
213 } else {
214 /* if E is not set (LI follows), GPRS */
215 num_chunks = parse_extensions_gprs(data, data_len, &offs,
216 is_last_block,
217 chunks, chunks_size);
218 }
219
Jacob Erlbeckead5e472016-01-08 10:14:50 +0100220 if (num_chunks < 0)
221 return num_chunks;
222
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100223 /* TLLI */
224 if (rdbi->ti) {
225 uint32_t tlli_enc;
226 if (offs + 4 > data_len) {
227 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TLLI out of block "
228 "border\n");
229 return -EINVAL;
230 }
231
232 memcpy(&tlli_enc, data + offs, sizeof(tlli_enc));
233 if (cs.isGprs())
234 /* The TLLI is encoded in big endian for GPRS (see
235 * TS 44.060, figure 10.2.2.1, note) */
236 *tlli = be32toh(tlli_enc);
237 else
238 /* The TLLI is encoded in little endian for EGPRS (see
239 * TS 44.060, figure 10.3a.2.1, note 2) */
240 *tlli = le32toh(tlli_enc);
241
242 offs += sizeof(tlli_enc);
243 } else {
244 *tlli = 0;
245 }
246
247 /* PFI */
248 if (rdbi->pi) {
249 LOGP(DRLCMACUL, LOGL_ERROR, "ERROR: PFI not supported, "
250 "please disable in SYSTEM INFORMATION\n");
251 return -ENOTSUP;
252
253 /* TODO: Skip all extensions with E=0 (see TS 44.060, 10.4.11 */
254 }
255
Jacob Erlbeckead5e472016-01-08 10:14:50 +0100256 if (chunks_size == 0)
257 return num_chunks;
258
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100259 /* LLC */
260 for (i = 0; i < num_chunks; i++) {
261 chunks[i].offset = offs;
262 if (chunks[i].length == LENGTH_TO_END) {
263 if (offs == data_len) {
264 /* There is no place for an additional chunk,
265 * so drop it (this may happen with EGPRS since
266 * there is no M flag. */
267 num_chunks -= 1;
268 break;;
269 }
270 chunks[i].length = data_len - offs;
271 }
272 offs += chunks[i].length;
273 if (offs > data_len) {
274 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA out of block "
275 "border, chunk idx: %d, size: %d\n",
276 i, chunks[i].length);
277 return -EINVAL;
278 }
279 }
280
281 return num_chunks;
282}
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +0200283
Holger Hans Peter Freytherfcbc7022013-10-26 17:38:37 +0200284uint8_t Decoding::get_ms_class_by_capability(MS_Radio_Access_capability_t *cap)
285{
286 int i;
287
288 for (i = 0; i < cap->Count_MS_RA_capability_value; i++) {
289 if (!cap->MS_RA_capability_value[i].u.Content.Exist_Multislot_capability)
290 continue;
291 if (!cap->MS_RA_capability_value[i].u.Content.Multislot_capability.Exist_GPRS_multislot_class)
292 continue;
293 return cap->MS_RA_capability_value[i].u.Content.Multislot_capability.GPRS_multislot_class;
294 }
295
296 return 0;
297}
298
Jacob Erlbeckc3c58042015-09-28 17:55:32 +0200299uint8_t Decoding::get_egprs_ms_class_by_capability(MS_Radio_Access_capability_t *cap)
300{
301 int i;
302
303 for (i = 0; i < cap->Count_MS_RA_capability_value; i++) {
304 if (!cap->MS_RA_capability_value[i].u.Content.Exist_Multislot_capability)
305 continue;
306 if (!cap->MS_RA_capability_value[i].u.Content.Multislot_capability.Exist_EGPRS_multislot_class)
307 continue;
308 return cap->MS_RA_capability_value[i].u.Content.Multislot_capability.EGPRS_multislot_class;
309 }
310
311 return 0;
312}
313
Holger Hans Peter Freytherdf6b4f52013-11-24 17:05:48 +0100314/**
315 * show_rbb needs to be an array with 65 elements
Daniel Willmann5e94cd42013-12-11 20:11:16 +0100316 * The index of the array is the bit position in the rbb
317 * (show_rbb[63] relates to BSN ssn-1)
Holger Hans Peter Freytherdf6b4f52013-11-24 17:05:48 +0100318 */
319void Decoding::extract_rbb(const uint8_t *rbb, char *show_rbb)
320{
Daniel Willmann5e94cd42013-12-11 20:11:16 +0100321 for (int i = 0; i < 64; i++) {
Holger Hans Peter Freytherdf6b4f52013-11-24 17:05:48 +0100322 uint8_t bit;
323
Daniel Willmann5e94cd42013-12-11 20:11:16 +0100324 bit = !!(rbb[i/8] & (1<<(7-i%8)));
Daniel Willmann6f7cb2c2013-12-11 14:25:20 +0100325 show_rbb[i] = bit ? 'R' : 'I';
Holger Hans Peter Freytherdf6b4f52013-11-24 17:05:48 +0100326 }
327
328 show_rbb[64] = '\0';
329}
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100330
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100331int Decoding::rlc_parse_ul_data_header(struct gprs_rlc_data_info *rlc,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100332 const uint8_t *data, GprsCodingScheme cs)
333{
334 const struct gprs_rlc_ul_header_egprs_3 *egprs3;
335 const struct rlc_ul_header *gprs;
336 unsigned int e_ti_header;
337 unsigned int cur_bit = 0;
338 unsigned int data_len = 0;
339
340 rlc->cs = cs;
341
342 data_len = cs.maxDataBlockBytes();
343
344 switch(cs.headerTypeData()) {
345 case GprsCodingScheme::HEADER_GPRS_DATA:
346 gprs = static_cast<struct rlc_ul_header *>
347 ((void *)data);
348 rlc->r = gprs->r;
349 rlc->si = gprs->si;
350 rlc->tfi = gprs->tfi;
351 rlc->cps = 0;
352 rlc->rsb = 0;
353
354 rlc->num_data_blocks = 1;
355 rlc->block_info[0].cv = gprs->cv;
356 rlc->block_info[0].pi = gprs->pi;
357 rlc->block_info[0].bsn = gprs->bsn;
358 rlc->block_info[0].e = gprs->e;
359 rlc->block_info[0].ti = gprs->ti;
360 rlc->block_info[0].spb = 0;
361
362 cur_bit += 3 * 8;
363
364 rlc->data_offs_bits[0] = cur_bit;
365 rlc->block_info[0].data_len = data_len;
366 cur_bit += data_len * 8;
367
368 break;
369 case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3:
370 egprs3 = static_cast<struct gprs_rlc_ul_header_egprs_3 *>
371 ((void *)data);
372 rlc->r = egprs3->r;
373 rlc->si = egprs3->si;
374 rlc->tfi = (egprs3->tfi_a << 0) | (egprs3->tfi_b << 2);
375 rlc->cps = (egprs3->cps_a << 0) | (egprs3->cps_b << 2);
376 rlc->rsb = egprs3->rsb;
377
378 rlc->num_data_blocks = 1;
379 rlc->block_info[0].cv = egprs3->cv;
380 rlc->block_info[0].pi = egprs3->pi;
381 rlc->block_info[0].spb = egprs3->spb;
382 rlc->block_info[0].bsn =
383 (egprs3->bsn1_a << 0) | (egprs3->bsn1_b << 5);
384
385 cur_bit += 3 * 8 + 7;
386
387 e_ti_header = (data[3] + (data[4] << 8)) >> 7;
388 rlc->block_info[0].e = !!(e_ti_header & 0x01);
389 rlc->block_info[0].ti = !!(e_ti_header & 0x02);
390 cur_bit += 2;
391
392 rlc->data_offs_bits[0] = cur_bit;
393 rlc->block_info[0].data_len = data_len;
394 cur_bit += data_len * 8;
395
396 break;
397
398 case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1:
399 case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2:
400 /* TODO: Support both header types */
401 /* fall through */
402 default:
403 LOGP(DRLCMACDL, LOGL_ERROR,
404 "Decoding of uplink %s data blocks not yet supported.\n",
405 cs.name());
406 return -ENOTSUP;
407 };
408
409 return cur_bit;
410}
411
412/**
413 * \brief Copy LSB bitstream RLC data block to byte aligned buffer.
414 *
415 * Note that the bitstream is encoded in LSB first order, so the two octets
416 * 654321xx xxxxxx87 contain the octet 87654321 starting at bit position 3
417 * (LSB has bit position 1). This is a different order than the one used by
418 * CSN.1.
419 *
420 * \param data_block_idx The block index, 0..1 for header type 1, 0 otherwise
421 * \param src A pointer to the start of the RLC block (incl. the header)
422 * \param buffer A data area of a least the size of the RLC block
423 * \returns the number of bytes copied
424 */
425unsigned int Decoding::rlc_copy_to_aligned_buffer(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100426 const struct gprs_rlc_data_info *rlc,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100427 unsigned int data_block_idx,
428 const uint8_t *src, uint8_t *buffer)
429{
430 unsigned int hdr_bytes;
431 unsigned int extra_bits;
432 unsigned int i;
433
434 uint8_t c, last_c;
435 uint8_t *dst;
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100436 const struct gprs_rlc_data_block_info *rdbi;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100437
438 OSMO_ASSERT(data_block_idx < rlc->num_data_blocks);
439 rdbi = &rlc->block_info[data_block_idx];
440
441 hdr_bytes = rlc->data_offs_bits[data_block_idx] >> 3;
442 extra_bits = (rlc->data_offs_bits[data_block_idx] & 7);
443
444 if (extra_bits == 0) {
445 /* It is aligned already */
446 memmove(buffer, src + hdr_bytes, rdbi->data_len);
447 return rdbi->data_len;
448 }
449
450 dst = buffer;
451 src = src + hdr_bytes;
452 last_c = *(src++);
453
454 for (i = 0; i < rdbi->data_len; i++) {
455 c = src[i];
456 *(dst++) = (last_c >> extra_bits) | (c << (8 - extra_bits));
457 last_c = c;
458 }
459
460 return rdbi->data_len;
461}
462
463/**
464 * \brief Get a pointer to byte aligned RLC data.
465 *
466 * Since the RLC data may not be byte aligned to the RLC block data such that a
467 * single RLC data byte is spread over two RLC block bytes, this function
468 * eventually uses the provided buffer as data storage.
469 *
470 * \param src A pointer to the start of the RLC block (incl. the header)
471 * \param buffer A data area of a least the size of the RLC block
472 * \returns A pointer to the RLC data start within src if it is aligned, and
473 * buffer otherwise.
474 */
475const uint8_t *Decoding::rlc_get_data_aligned(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100476 const struct gprs_rlc_data_info *rlc,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100477 unsigned int data_block_idx,
478 const uint8_t *src, uint8_t *buffer)
479{
480 unsigned int hdr_bytes;
481 unsigned int extra_bits;
482
483 OSMO_ASSERT(data_block_idx < ARRAY_SIZE(rlc->data_offs_bits));
484
485 hdr_bytes = rlc->data_offs_bits[data_block_idx] >> 3;
486 extra_bits = (rlc->data_offs_bits[data_block_idx] & 7);
487
488 if (extra_bits == 0)
489 /* It is aligned already, return a pointer that refers to the
490 * original data. */
491 return src + hdr_bytes;
492
493 Decoding::rlc_copy_to_aligned_buffer(rlc, data_block_idx, src, buffer);
494 return buffer;
495}
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100496
497static int handle_final_ack(bitvec *bits, int *bsn_begin, int *bsn_end,
498 gprs_rlc_dl_window *window)
499{
500 int num_blocks, i;
501
502 num_blocks = window->mod_sns(window->v_s() - window->v_a());
503 for (i = 0; i < num_blocks; i++)
504 bitvec_set_bit(bits, ONE);
505
506 *bsn_begin = window->v_a();
507 *bsn_end = window->mod_sns(*bsn_begin + num_blocks);
508 return num_blocks;
509}
510
511int Decoding::decode_egprs_acknack_bits(const EGPRS_AckNack_Desc_t *desc,
512 bitvec *bits, int *bsn_begin, int *bsn_end, gprs_rlc_dl_window *window)
513{
514 int urbb_len = desc->URBB_LENGTH;
515 int crbb_len = 0;
516 int num_blocks = 0;
517 struct bitvec urbb;
518 int i;
519 bool have_bitmap;
520 int implicitly_acked_blocks;
521 int ssn = desc->STARTING_SEQUENCE_NUMBER;
522
523 if (desc->FINAL_ACK_INDICATION)
524 return handle_final_ack(bits, bsn_begin, bsn_end, window);
525
526 if (desc->Exist_CRBB)
527 crbb_len = desc->CRBB_LENGTH;
528
529 have_bitmap = (urbb_len + crbb_len) > 0;
530
531 /*
532 * bow & bitmap present:
533 * V(A)-> [ 11111...11111 0 SSN-> BBBBB...BBBBB ] (SSN+Nbits) .... V(S)
534 * bow & not bitmap present:
535 * V(A)-> [ 11111...11111 ] . SSN .... V(S)
536 * not bow & bitmap present:
537 * V(A)-> ... [ 0 SSN-> BBBBB...BBBBB ](SSN+N) .... V(S)
538 * not bow & not bitmap present:
539 * V(A)-> ... [] . SSN .... V(S)
540 */
541
542 if (desc->BEGINNING_OF_WINDOW) {
543 implicitly_acked_blocks = window->mod_sns(ssn - 1 - window->v_a());
544
545 for (i = 0; i < implicitly_acked_blocks; i++)
546 bitvec_set_bit(bits, ONE);
547
548 num_blocks += implicitly_acked_blocks;
549 }
550
551 if (have_bitmap) {
552 /* next bit refers to V(Q) and thus is always zero (and not
553 * transmitted) */
554 bitvec_set_bit(bits, ZERO);
555 num_blocks += 1;
556
557 if (crbb_len > 0) {
558 int old_len = bits->cur_bit;
559 /*
560 decode_t4_rle(bits, desc->CRBB, desc->CRBB_LENGTH,
561 desc->CRBB_STARTING_COLOR_CODE);
562 */
563
564 num_blocks += (bits->cur_bit - old_len);
565 }
566
567 urbb.cur_bit = 0;
568 urbb.data = (uint8_t *)desc->URBB;
569 urbb.data_len = sizeof(desc->URBB);
570
571 for (i = urbb_len; i > 0; i--) {
572 /*
573 * Set bit at the appropriate position (see 3GPP TS
574 * 44.060 12.3.1)
575 */
576 int is_ack = bitvec_get_bit_pos(&urbb, i-1);
577 bitvec_set_bit(bits, is_ack == 1 ? ONE : ZERO);
578 }
579 num_blocks += urbb_len;
580 }
581
582 *bsn_begin = window->v_a();
583 *bsn_end = window->mod_sns(*bsn_begin + num_blocks);
584
585 return num_blocks;
586}