blob: 6ae4b16c4f584d6eabc6a9f36ac1a396ab714409 [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 */
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) {
Alexander Couzensb82bd922016-05-30 17:30:10 +0200199 /* Block without LI means it only contains data of one LLC PDU */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100200 chunks[num_chunks].offset = offs;
201 chunks[num_chunks].length = LENGTH_TO_END;
202 chunks[num_chunks].is_complete = is_last_block;
203 num_chunks += 1;
204 } else if (chunks) {
205 LOGP(DRLCMACUL, LOGL_NOTICE, "No extension, "
206 "but no more chunks possible\n");
207 return -ENOSPC;
208 }
209 } else if (cs.isEgprs()) {
210 /* if E is not set (LI follows), EGPRS */
211 num_chunks = parse_extensions_egprs(data, data_len, &offs,
212 is_last_block,
213 chunks, chunks_size);
214 } else {
215 /* if E is not set (LI follows), GPRS */
216 num_chunks = parse_extensions_gprs(data, data_len, &offs,
217 is_last_block,
218 chunks, chunks_size);
219 }
220
Jacob Erlbeckead5e472016-01-08 10:14:50 +0100221 if (num_chunks < 0)
222 return num_chunks;
223
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100224 /* TLLI */
225 if (rdbi->ti) {
226 uint32_t tlli_enc;
227 if (offs + 4 > data_len) {
228 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TLLI out of block "
229 "border\n");
230 return -EINVAL;
231 }
232
233 memcpy(&tlli_enc, data + offs, sizeof(tlli_enc));
234 if (cs.isGprs())
235 /* The TLLI is encoded in big endian for GPRS (see
236 * TS 44.060, figure 10.2.2.1, note) */
237 *tlli = be32toh(tlli_enc);
238 else
239 /* The TLLI is encoded in little endian for EGPRS (see
240 * TS 44.060, figure 10.3a.2.1, note 2) */
241 *tlli = le32toh(tlli_enc);
242
243 offs += sizeof(tlli_enc);
244 } else {
245 *tlli = 0;
246 }
247
248 /* PFI */
249 if (rdbi->pi) {
250 LOGP(DRLCMACUL, LOGL_ERROR, "ERROR: PFI not supported, "
251 "please disable in SYSTEM INFORMATION\n");
252 return -ENOTSUP;
253
254 /* TODO: Skip all extensions with E=0 (see TS 44.060, 10.4.11 */
255 }
256
Jacob Erlbeckead5e472016-01-08 10:14:50 +0100257 if (chunks_size == 0)
258 return num_chunks;
259
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100260 /* LLC */
261 for (i = 0; i < num_chunks; i++) {
262 chunks[i].offset = offs;
263 if (chunks[i].length == LENGTH_TO_END) {
264 if (offs == data_len) {
265 /* There is no place for an additional chunk,
266 * so drop it (this may happen with EGPRS since
267 * there is no M flag. */
268 num_chunks -= 1;
Alexander Couzensd302e4f2016-05-30 17:31:09 +0200269 break;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100270 }
271 chunks[i].length = data_len - offs;
272 }
273 offs += chunks[i].length;
274 if (offs > data_len) {
275 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA out of block "
276 "border, chunk idx: %d, size: %d\n",
277 i, chunks[i].length);
278 return -EINVAL;
279 }
280 }
281
282 return num_chunks;
283}
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +0200284
Holger Hans Peter Freytherfcbc7022013-10-26 17:38:37 +0200285uint8_t Decoding::get_ms_class_by_capability(MS_Radio_Access_capability_t *cap)
286{
287 int i;
288
289 for (i = 0; i < cap->Count_MS_RA_capability_value; i++) {
290 if (!cap->MS_RA_capability_value[i].u.Content.Exist_Multislot_capability)
291 continue;
292 if (!cap->MS_RA_capability_value[i].u.Content.Multislot_capability.Exist_GPRS_multislot_class)
293 continue;
294 return cap->MS_RA_capability_value[i].u.Content.Multislot_capability.GPRS_multislot_class;
295 }
296
297 return 0;
298}
299
Jacob Erlbeckc3c58042015-09-28 17:55:32 +0200300uint8_t Decoding::get_egprs_ms_class_by_capability(MS_Radio_Access_capability_t *cap)
301{
302 int i;
303
304 for (i = 0; i < cap->Count_MS_RA_capability_value; i++) {
305 if (!cap->MS_RA_capability_value[i].u.Content.Exist_Multislot_capability)
306 continue;
307 if (!cap->MS_RA_capability_value[i].u.Content.Multislot_capability.Exist_EGPRS_multislot_class)
308 continue;
309 return cap->MS_RA_capability_value[i].u.Content.Multislot_capability.EGPRS_multislot_class;
310 }
311
312 return 0;
313}
314
Holger Hans Peter Freytherdf6b4f52013-11-24 17:05:48 +0100315/**
316 * show_rbb needs to be an array with 65 elements
Daniel Willmann5e94cd42013-12-11 20:11:16 +0100317 * The index of the array is the bit position in the rbb
318 * (show_rbb[63] relates to BSN ssn-1)
Holger Hans Peter Freytherdf6b4f52013-11-24 17:05:48 +0100319 */
320void Decoding::extract_rbb(const uint8_t *rbb, char *show_rbb)
321{
Daniel Willmann5e94cd42013-12-11 20:11:16 +0100322 for (int i = 0; i < 64; i++) {
Holger Hans Peter Freytherdf6b4f52013-11-24 17:05:48 +0100323 uint8_t bit;
324
Daniel Willmann5e94cd42013-12-11 20:11:16 +0100325 bit = !!(rbb[i/8] & (1<<(7-i%8)));
Daniel Willmann6f7cb2c2013-12-11 14:25:20 +0100326 show_rbb[i] = bit ? 'R' : 'I';
Holger Hans Peter Freytherdf6b4f52013-11-24 17:05:48 +0100327 }
328
329 show_rbb[64] = '\0';
330}
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100331
Jacob Erlbeckf2f24b02016-02-05 13:16:24 +0100332void Decoding::extract_rbb(const struct bitvec *rbb, char *show_rbb)
333{
334 unsigned int i;
335 for (i = 0; i < rbb->cur_bit; i++) {
336 uint8_t bit;
337 bit = bitvec_get_bit_pos(rbb, i);
338 show_rbb[i] = bit == 1 ? 'R' : 'I';
339 }
340
341 show_rbb[i] = '\0';
342}
343
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100344int Decoding::rlc_parse_ul_data_header(struct gprs_rlc_data_info *rlc,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100345 const uint8_t *data, GprsCodingScheme cs)
346{
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100347 unsigned int cur_bit = 0;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100348 switch(cs.headerTypeData()) {
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530349 case GprsCodingScheme::HEADER_GPRS_DATA :
350 cur_bit = rlc_parse_ul_data_header_gprs(rlc, data, cs);
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100351 break;
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530352 case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3 :
353 cur_bit = rlc_parse_ul_data_header_egprs_type_3(rlc, data, cs);
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100354 break;
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530355 case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2 :
356 cur_bit = rlc_parse_ul_data_header_egprs_type_2(rlc, data, cs);
357 break;
358 case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1 :
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530359 cur_bit = rlc_parse_ul_data_header_egprs_type_1(rlc, data, cs);
360 break;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100361 default:
362 LOGP(DRLCMACDL, LOGL_ERROR,
363 "Decoding of uplink %s data blocks not yet supported.\n",
364 cs.name());
365 return -ENOTSUP;
366 };
367
368 return cur_bit;
369}
370
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530371int Decoding::rlc_parse_ul_data_header_egprs_type_3(
372 struct gprs_rlc_data_info *rlc,
373 const uint8_t *data,
374 const GprsCodingScheme &cs)
375{
376 int punct, punct2, with_padding, cps;
377 unsigned int e_ti_header, offs, cur_bit = 0;
378 const struct gprs_rlc_ul_header_egprs_3 *egprs3;
379
380 egprs3 = static_cast < struct gprs_rlc_ul_header_egprs_3 * >
381 ((void *)data);
382
Tom Tsoudf698092016-07-11 17:05:19 -0700383 cps = (egprs3->cps_hi << 0) | (egprs3->cps_lo << 2);
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530384 gprs_rlc_mcs_cps_decode(cps, cs, &punct, &punct2, &with_padding);
385 gprs_rlc_data_info_init_ul(rlc, cs, with_padding);
386
387 rlc->r = egprs3->r;
388 rlc->si = egprs3->si;
Tom Tsoudf698092016-07-11 17:05:19 -0700389 rlc->tfi = (egprs3->tfi_hi << 0) | (egprs3->tfi_lo << 2);
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530390 rlc->cps = cps;
391 rlc->rsb = egprs3->rsb;
392
393 rlc->num_data_blocks = 1;
394 rlc->block_info[0].cv = egprs3->cv;
395 rlc->block_info[0].pi = egprs3->pi;
396 rlc->block_info[0].spb = egprs3->spb;
397 rlc->block_info[0].bsn =
Tom Tsoudf698092016-07-11 17:05:19 -0700398 (egprs3->bsn1_hi << 0) | (egprs3->bsn1_lo << 5);
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530399
400 cur_bit += rlc->data_offs_bits[0] - 2;
401 offs = rlc->data_offs_bits[0] / 8;
402 OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 1);
403 e_ti_header = (data[offs-1] + (data[offs] << 8)) >> 7;
404 rlc->block_info[0].e = !!(e_ti_header & 0x01);
405 rlc->block_info[0].ti = !!(e_ti_header & 0x02);
406 cur_bit += 2;
407 /* skip data area */
408 cur_bit += cs.maxDataBlockBytes() * 8;
409
410 return cur_bit;
411}
412
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530413int Decoding::rlc_parse_ul_data_header_egprs_type_2(
414 struct gprs_rlc_data_info *rlc,
415 const uint8_t *data,
416 const GprsCodingScheme &cs)
417{
418 const struct gprs_rlc_ul_header_egprs_2 *egprs2;
419 unsigned int e_ti_header, offs, cur_bit = 0;
420 int punct, punct2, with_padding, cps;
421
422 egprs2 = static_cast < struct gprs_rlc_ul_header_egprs_2 * >
423 ((void *)data);
424
Tom Tsoudf698092016-07-11 17:05:19 -0700425 cps = (egprs2->cps_hi << 0) | (egprs2->cps_lo << 2);
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530426 gprs_rlc_mcs_cps_decode(cps, cs, &punct, &punct2, &with_padding);
427 gprs_rlc_data_info_init_ul(rlc, cs, with_padding);
428
429 rlc->r = egprs2->r;
430 rlc->si = egprs2->si;
Tom Tsoudf698092016-07-11 17:05:19 -0700431 rlc->tfi = (egprs2->tfi_hi << 0) | (egprs2->tfi_lo << 2);
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530432 rlc->cps = cps;
433 rlc->rsb = egprs2->rsb;
434
435 rlc->num_data_blocks = 1;
436 rlc->block_info[0].cv = egprs2->cv;
437 rlc->block_info[0].pi = egprs2->pi;
438 rlc->block_info[0].bsn =
Tom Tsoudf698092016-07-11 17:05:19 -0700439 (egprs2->bsn1_hi << 0) | (egprs2->bsn1_lo << 5);
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530440
441 cur_bit += rlc->data_offs_bits[0] - 2;
442
443 offs = rlc->data_offs_bits[0] / 8;
444 OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 7);
445
446 e_ti_header = (data[offs] & 0x60) >> 5;
447 rlc->block_info[0].e = !!(e_ti_header & 0x01);
448 rlc->block_info[0].ti = !!(e_ti_header & 0x02);
449 cur_bit += 2;
450
451 /* skip data area */
452 cur_bit += cs.maxDataBlockBytes() * 8;
453
454 return cur_bit;
455}
456
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530457int Decoding::rlc_parse_ul_data_header_egprs_type_1(
458 struct gprs_rlc_data_info *rlc,
459 const uint8_t *data, const GprsCodingScheme &cs)
460{
461 struct gprs_rlc_ul_header_egprs_1 *egprs1;
462 unsigned int e_ti_header, cur_bit = 0, offs;
463 int punct, punct2, with_padding;
464
465 egprs1 = static_cast < struct gprs_rlc_ul_header_egprs_1 * >
466 ((void *)data);
467 gprs_rlc_mcs_cps_decode(egprs1->cps, cs, &punct, &punct2,
468 &with_padding);
469 gprs_rlc_data_info_init_ul(rlc, cs, with_padding);
470
471 rlc->r = egprs1->r;
472 rlc->si = egprs1->si;
Tom Tsoudf698092016-07-11 17:05:19 -0700473 rlc->tfi = (egprs1->tfi_hi << 0) | (egprs1->tfi_lo << 2);
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530474 rlc->cps = egprs1->cps;
475 rlc->rsb = egprs1->rsb;
476 rlc->num_data_blocks = 2;
477 rlc->block_info[0].cv = egprs1->cv;
478 rlc->block_info[0].pi = egprs1->pi;
479 rlc->block_info[0].bsn =
Tom Tsoudf698092016-07-11 17:05:19 -0700480 (egprs1->bsn1_hi << 0) | (egprs1->bsn1_lo << 5);
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530481
482 cur_bit += rlc->data_offs_bits[0] - 2;
483 offs = rlc->data_offs_bits[0] / 8;
484 OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 0);
485
486 e_ti_header = data[offs - 1] >> 6;
487 rlc->block_info[0].e = (e_ti_header & 0x01);
488 rlc->block_info[0].ti = !!(e_ti_header & 0x02);
489 cur_bit += 2;
490
491 rlc->block_info[1].cv = egprs1->cv;
492 rlc->block_info[1].pi = egprs1->pi;
493 rlc->block_info[1].bsn = rlc->block_info[0].bsn +
Tom Tsoudf698092016-07-11 17:05:19 -0700494 ((egprs1->bsn2_hi << 0) | (egprs1->bsn2_lo << 2));
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530495 rlc->block_info[1].bsn = rlc->block_info[1].bsn & (RLC_EGPRS_SNS - 1);
496
497 if ((rlc->block_info[1].bsn != rlc->block_info[0].bsn) &&
498 (rlc->block_info[0].cv == 0))
499 rlc->block_info[0].cv = 1;
500
501 cur_bit = rlc->data_offs_bits[1] - 2;
502
503 offs = rlc->data_offs_bits[1] / 8;
504 OSMO_ASSERT(rlc->data_offs_bits[1] % 8 == 2);
505
506 e_ti_header = (data[offs] & (0x03));
507 rlc->block_info[1].e = (e_ti_header & 0x01);
508 rlc->block_info[1].ti = !!(e_ti_header & 0x02);
509 cur_bit += 2;
510 /* skip data area */
511 cur_bit += cs.maxDataBlockBytes() * 8;
512
513 return cur_bit;
514}
515
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530516int Decoding::rlc_parse_ul_data_header_gprs(struct gprs_rlc_data_info *rlc,
517 const uint8_t *data, const GprsCodingScheme &cs)
518{
519 const struct rlc_ul_header *gprs;
520 unsigned int cur_bit = 0;
521
522 gprs = static_cast < struct rlc_ul_header * >
523 ((void *)data);
524
525 gprs_rlc_data_info_init_ul(rlc, cs, false);
526
527 rlc->r = gprs->r;
528 rlc->si = gprs->si;
529 rlc->tfi = gprs->tfi;
530 rlc->cps = 0;
531 rlc->rsb = 0;
532 rlc->num_data_blocks = 1;
533 rlc->block_info[0].cv = gprs->cv;
534 rlc->block_info[0].pi = gprs->pi;
535 rlc->block_info[0].bsn = gprs->bsn;
536 rlc->block_info[0].e = gprs->e;
537 rlc->block_info[0].ti = gprs->ti;
538 rlc->block_info[0].spb = 0;
539 cur_bit += rlc->data_offs_bits[0];
540 /* skip data area */
541 cur_bit += cs.maxDataBlockBytes() * 8;
542
543 return cur_bit;
544}
545
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100546/**
547 * \brief Copy LSB bitstream RLC data block to byte aligned buffer.
548 *
549 * Note that the bitstream is encoded in LSB first order, so the two octets
550 * 654321xx xxxxxx87 contain the octet 87654321 starting at bit position 3
551 * (LSB has bit position 1). This is a different order than the one used by
552 * CSN.1.
553 *
554 * \param data_block_idx The block index, 0..1 for header type 1, 0 otherwise
555 * \param src A pointer to the start of the RLC block (incl. the header)
556 * \param buffer A data area of a least the size of the RLC block
557 * \returns the number of bytes copied
558 */
559unsigned int Decoding::rlc_copy_to_aligned_buffer(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100560 const struct gprs_rlc_data_info *rlc,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100561 unsigned int data_block_idx,
562 const uint8_t *src, uint8_t *buffer)
563{
564 unsigned int hdr_bytes;
565 unsigned int extra_bits;
566 unsigned int i;
567
568 uint8_t c, last_c;
569 uint8_t *dst;
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100570 const struct gprs_rlc_data_block_info *rdbi;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100571
572 OSMO_ASSERT(data_block_idx < rlc->num_data_blocks);
573 rdbi = &rlc->block_info[data_block_idx];
574
575 hdr_bytes = rlc->data_offs_bits[data_block_idx] >> 3;
576 extra_bits = (rlc->data_offs_bits[data_block_idx] & 7);
577
578 if (extra_bits == 0) {
579 /* It is aligned already */
580 memmove(buffer, src + hdr_bytes, rdbi->data_len);
581 return rdbi->data_len;
582 }
583
584 dst = buffer;
585 src = src + hdr_bytes;
586 last_c = *(src++);
587
588 for (i = 0; i < rdbi->data_len; i++) {
589 c = src[i];
590 *(dst++) = (last_c >> extra_bits) | (c << (8 - extra_bits));
591 last_c = c;
592 }
593
594 return rdbi->data_len;
595}
596
597/**
598 * \brief Get a pointer to byte aligned RLC data.
599 *
600 * Since the RLC data may not be byte aligned to the RLC block data such that a
601 * single RLC data byte is spread over two RLC block bytes, this function
602 * eventually uses the provided buffer as data storage.
603 *
604 * \param src A pointer to the start of the RLC block (incl. the header)
605 * \param buffer A data area of a least the size of the RLC block
606 * \returns A pointer to the RLC data start within src if it is aligned, and
607 * buffer otherwise.
608 */
609const uint8_t *Decoding::rlc_get_data_aligned(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100610 const struct gprs_rlc_data_info *rlc,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100611 unsigned int data_block_idx,
612 const uint8_t *src, uint8_t *buffer)
613{
614 unsigned int hdr_bytes;
615 unsigned int extra_bits;
616
617 OSMO_ASSERT(data_block_idx < ARRAY_SIZE(rlc->data_offs_bits));
618
619 hdr_bytes = rlc->data_offs_bits[data_block_idx] >> 3;
620 extra_bits = (rlc->data_offs_bits[data_block_idx] & 7);
621
622 if (extra_bits == 0)
623 /* It is aligned already, return a pointer that refers to the
624 * original data. */
625 return src + hdr_bytes;
626
627 Decoding::rlc_copy_to_aligned_buffer(rlc, data_block_idx, src, buffer);
628 return buffer;
629}
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100630
631static int handle_final_ack(bitvec *bits, int *bsn_begin, int *bsn_end,
632 gprs_rlc_dl_window *window)
633{
634 int num_blocks, i;
635
636 num_blocks = window->mod_sns(window->v_s() - window->v_a());
637 for (i = 0; i < num_blocks; i++)
638 bitvec_set_bit(bits, ONE);
639
640 *bsn_begin = window->v_a();
641 *bsn_end = window->mod_sns(*bsn_begin + num_blocks);
642 return num_blocks;
643}
644
645int Decoding::decode_egprs_acknack_bits(const EGPRS_AckNack_Desc_t *desc,
646 bitvec *bits, int *bsn_begin, int *bsn_end, gprs_rlc_dl_window *window)
647{
648 int urbb_len = desc->URBB_LENGTH;
649 int crbb_len = 0;
650 int num_blocks = 0;
651 struct bitvec urbb;
652 int i;
653 bool have_bitmap;
654 int implicitly_acked_blocks;
655 int ssn = desc->STARTING_SEQUENCE_NUMBER;
Jacob Erlbeck2bef4db2016-01-20 14:33:11 +0100656 int rc;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100657
658 if (desc->FINAL_ACK_INDICATION)
659 return handle_final_ack(bits, bsn_begin, bsn_end, window);
660
661 if (desc->Exist_CRBB)
662 crbb_len = desc->CRBB_LENGTH;
663
664 have_bitmap = (urbb_len + crbb_len) > 0;
665
666 /*
667 * bow & bitmap present:
668 * V(A)-> [ 11111...11111 0 SSN-> BBBBB...BBBBB ] (SSN+Nbits) .... V(S)
669 * bow & not bitmap present:
670 * V(A)-> [ 11111...11111 ] . SSN .... V(S)
671 * not bow & bitmap present:
672 * V(A)-> ... [ 0 SSN-> BBBBB...BBBBB ](SSN+N) .... V(S)
673 * not bow & not bitmap present:
674 * V(A)-> ... [] . SSN .... V(S)
675 */
676
677 if (desc->BEGINNING_OF_WINDOW) {
678 implicitly_acked_blocks = window->mod_sns(ssn - 1 - window->v_a());
679
680 for (i = 0; i < implicitly_acked_blocks; i++)
681 bitvec_set_bit(bits, ONE);
682
683 num_blocks += implicitly_acked_blocks;
684 }
685
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100686 if (!have_bitmap)
687 goto aborted;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100688
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100689 /* next bit refers to V(Q) and thus is always zero (and not
690 * transmitted) */
691 bitvec_set_bit(bits, ZERO);
692 num_blocks += 1;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100693
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100694 if (crbb_len > 0) {
695 int old_len = bits->cur_bit;
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100696
Pravin Kumarvel0a4a6c12016-10-17 11:00:57 +0530697 LOGP(DRLCMACDL, LOGL_DEBUG, "Compress bitmap exists, "
698 "CRBB LEN = %d and Starting color code = %d",
699 desc->CRBB_LENGTH, desc->CRBB_STARTING_COLOR_CODE);
700 rc = egprs_compress::decompress_crbb(desc->CRBB_LENGTH,
701 desc->CRBB_STARTING_COLOR_CODE, desc->CRBB, bits);
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100702 if (rc < 0) {
703 LOGP(DRLCMACUL, LOGL_NOTICE,
Pravin Kumarvel0a4a6c12016-10-17 11:00:57 +0530704 "Failed to decode CRBB: length %d, data '%s'\n",
705 desc->CRBB_LENGTH, osmo_hexdump(
706 desc->CRBB, (desc->CRBB_LENGTH + 7)/8));
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100707 /* We don't know the SSN offset for the URBB,
708 * return what we have so far and assume the
709 * bitmap has stopped here */
710 goto aborted;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100711 }
712
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100713 LOGP(DRLCMACDL, LOGL_DEBUG,
714 "CRBB len: %d, decoded len: %d, cc: %d, crbb: '%s'\n",
715 desc->CRBB_LENGTH, bits->cur_bit - old_len,
716 desc->CRBB_STARTING_COLOR_CODE,
717 osmo_hexdump(
718 desc->CRBB, (desc->CRBB_LENGTH + 7)/8)
719 );
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100720
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100721 num_blocks += (bits->cur_bit - old_len);
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100722 }
723
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100724 urbb.cur_bit = 0;
725 urbb.data = (uint8_t *)desc->URBB;
726 urbb.data_len = sizeof(desc->URBB);
727
728 for (i = urbb_len; i > 0; i--) {
729 /*
730 * Set bit at the appropriate position (see 3GPP TS
731 * 44.060 12.3.1)
732 */
733 int is_ack = bitvec_get_bit_pos(&urbb, i-1);
734 bitvec_set_bit(bits, is_ack == 1 ? ONE : ZERO);
735 }
736 num_blocks += urbb_len;
737
738aborted:
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100739 *bsn_begin = window->v_a();
740 *bsn_end = window->mod_sns(*bsn_begin + num_blocks);
741
742 return num_blocks;
743}
Jacob Erlbeck192bf332016-02-05 13:10:29 +0100744
745int Decoding::decode_gprs_acknack_bits(const Ack_Nack_Description_t *desc,
746 bitvec *bits, int *bsn_begin, int *bsn_end, gprs_rlc_dl_window *window)
747{
748 int urbb_len = RLC_GPRS_WS;
749 int num_blocks;
750 struct bitvec urbb;
751
752 if (desc->FINAL_ACK_INDICATION)
753 return handle_final_ack(bits, bsn_begin, bsn_end, window);
754
755 *bsn_begin = window->v_a();
756 *bsn_end = desc->STARTING_SEQUENCE_NUMBER;
757
758 num_blocks = window->mod_sns(*bsn_end - *bsn_begin);
759
760 if (num_blocks < 0 || num_blocks > urbb_len) {
761 *bsn_end = *bsn_begin;
762 LOGP(DRLCMACUL, LOGL_NOTICE,
763 "Invalid GPRS Ack/Nack window %d:%d (length %d)\n",
764 *bsn_begin, *bsn_end, num_blocks);
765 return -EINVAL;
766 }
767
768 urbb.cur_bit = 0;
769 urbb.data = (uint8_t *)desc->RECEIVED_BLOCK_BITMAP;
770 urbb.data_len = sizeof(desc->RECEIVED_BLOCK_BITMAP);
771
772 /*
773 * TS 44.060, 12.3:
774 * BSN = (SSN - bit_number) modulo 128, for bit_number = 1 to 64.
775 * The BSN values represented range from (SSN - 1) mod 128 to (SSN - 64) mod 128.
776 *
777 * We are only interested in the range from V(A) to SSN-1 which is
778 * num_blocks large. The RBB is laid out as
779 * [SSN-1] [SSN-2] ... [V(A)] ... [SSN-64]
780 * so we want to start with [V(A)] and go backwards until we reach
781 * [SSN-1] to get the needed BSNs in an increasing order. Note that
782 * the bit numbers are counted from the end of the buffer.
783 */
784 for (int i = num_blocks; i > 0; i--) {
785 int is_ack = bitvec_get_bit_pos(&urbb, urbb_len - i);
786 bitvec_set_bit(bits, is_ack == 1 ? ONE : ZERO);
787 }
788
789 return num_blocks;
790}