blob: 7c00ff71b3cb8c2956acc77ae4d270b4acc57ca4 [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>
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +010026#include <osmocom/core/bitcomp.h>
Tom Tsoudf698092016-07-11 17:05:19 -070027#include <osmocom/gprs/protocol/gsm_04_60.h>
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010028}
29
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +020030#include <arpa/inet.h>
31
32#include <errno.h>
33#include <string.h>
34
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010035#define LENGTH_TO_END 255
Alexander Couzensb82bd922016-05-30 17:30:10 +020036/*!
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010037 * \returns num extensions fields (num frames == offset) on success,
38 * -errno otherwise.
39 */
40static int parse_extensions_egprs(const uint8_t *data, unsigned int data_len,
41 unsigned int *offs,
42 bool is_last_block,
43 Decoding::RlcData *chunks, unsigned int chunks_size)
44{
45 const struct rlc_li_field_egprs *li;
46 uint8_t e;
47 unsigned int num_chunks = 0;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010048
49 e = 0;
50 while (!e) {
51 if (*offs > data_len) {
52 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
53 "but no more data\n");
54 return -EINVAL;
55 }
56
57 /* get new E */
58 li = (struct rlc_li_field_egprs *)&data[*offs];
59 e = li->e;
60 *offs += 1;
61
62 if (!chunks)
63 continue;
64
65 if (num_chunks == chunks_size) {
66 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
67 "but no more chunks possible\n");
68 return -ENOSPC;
69 }
70 if (li->li == 0 && num_chunks == 0 && li->e == 0) {
71 /* TS 44.060, table 10.4.14a.1, row 2a */
72 chunks[num_chunks].length = 0;
73 chunks[num_chunks].is_complete = true;
74 } else if (li->li == 0 && num_chunks == 0 && li->e == 1) {
75 /* TS 44.060, table 10.4.14a.1, row 4 */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010076 chunks[num_chunks].length = LENGTH_TO_END;
77 chunks[num_chunks].is_complete = is_last_block;
78 } else if (li->li == 127 && li->e == 1) {
79 /* TS 44.060, table 10.4.14a.1, row 3 & 5 */
80 /* only filling bytes left */
81 break;
82 } else if (li->li > 0) {
83 /* TS 44.060, table 10.4.14a.1, row 1 & 2b */
84 chunks[num_chunks].length = li->li;
85 chunks[num_chunks].is_complete = true;
86 } else {
87 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI contains "
88 "invalid extension octet: LI=%d, E=%d, count=%d\n",
89 li->li, li->e, num_chunks);
90 return -EINVAL;
91 }
92
93 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
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100166 num_chunks += 1;
167
168 if (e == 1 && m == 1) {
169 if (num_chunks == chunks_size) {
170 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
171 "but no more chunks possible\n");
172 return -ENOSPC;
173 }
174 /* TS 44.060, 10.4.13.1, row 4 */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100175 chunks[num_chunks].length = LENGTH_TO_END;
176 chunks[num_chunks].is_complete = is_last_block;
177 num_chunks += 1;
178 }
179 }
180
181 return num_chunks;
182}
183
184int Decoding::rlc_data_from_ul_data(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100185 const struct gprs_rlc_data_block_info *rdbi, GprsCodingScheme cs,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100186 const uint8_t *data, RlcData *chunks, unsigned int chunks_size,
187 uint32_t *tlli)
188{
189 uint8_t e;
190 unsigned int data_len = rdbi->data_len;
Jacob Erlbeckead5e472016-01-08 10:14:50 +0100191 int num_chunks = 0, i;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100192 unsigned int offs = 0;
193 bool is_last_block = (rdbi->cv == 0);
194
195 if (!chunks)
196 chunks_size = 0;
197
198 e = rdbi->e;
199 if (e) {
200 if (chunks_size > 0) {
Alexander Couzensb82bd922016-05-30 17:30:10 +0200201 /* Block without LI means it only contains data of one LLC PDU */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100202 chunks[num_chunks].offset = offs;
203 chunks[num_chunks].length = LENGTH_TO_END;
204 chunks[num_chunks].is_complete = is_last_block;
205 num_chunks += 1;
206 } else if (chunks) {
207 LOGP(DRLCMACUL, LOGL_NOTICE, "No extension, "
208 "but no more chunks possible\n");
209 return -ENOSPC;
210 }
211 } else if (cs.isEgprs()) {
212 /* if E is not set (LI follows), EGPRS */
213 num_chunks = parse_extensions_egprs(data, data_len, &offs,
214 is_last_block,
215 chunks, chunks_size);
216 } else {
217 /* if E is not set (LI follows), GPRS */
218 num_chunks = parse_extensions_gprs(data, data_len, &offs,
219 is_last_block,
220 chunks, chunks_size);
221 }
222
Jacob Erlbeckead5e472016-01-08 10:14:50 +0100223 if (num_chunks < 0)
224 return num_chunks;
225
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100226 /* TLLI */
227 if (rdbi->ti) {
228 uint32_t tlli_enc;
229 if (offs + 4 > data_len) {
230 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TLLI out of block "
231 "border\n");
232 return -EINVAL;
233 }
234
235 memcpy(&tlli_enc, data + offs, sizeof(tlli_enc));
236 if (cs.isGprs())
237 /* The TLLI is encoded in big endian for GPRS (see
238 * TS 44.060, figure 10.2.2.1, note) */
239 *tlli = be32toh(tlli_enc);
240 else
241 /* The TLLI is encoded in little endian for EGPRS (see
242 * TS 44.060, figure 10.3a.2.1, note 2) */
243 *tlli = le32toh(tlli_enc);
244
245 offs += sizeof(tlli_enc);
246 } else {
247 *tlli = 0;
248 }
249
250 /* PFI */
251 if (rdbi->pi) {
252 LOGP(DRLCMACUL, LOGL_ERROR, "ERROR: PFI not supported, "
253 "please disable in SYSTEM INFORMATION\n");
254 return -ENOTSUP;
255
256 /* TODO: Skip all extensions with E=0 (see TS 44.060, 10.4.11 */
257 }
258
Jacob Erlbeckead5e472016-01-08 10:14:50 +0100259 if (chunks_size == 0)
260 return num_chunks;
261
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100262 /* LLC */
263 for (i = 0; i < num_chunks; i++) {
264 chunks[i].offset = offs;
265 if (chunks[i].length == LENGTH_TO_END) {
266 if (offs == data_len) {
267 /* There is no place for an additional chunk,
268 * so drop it (this may happen with EGPRS since
269 * there is no M flag. */
270 num_chunks -= 1;
Alexander Couzensd302e4f2016-05-30 17:31:09 +0200271 break;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100272 }
273 chunks[i].length = data_len - offs;
274 }
275 offs += chunks[i].length;
276 if (offs > data_len) {
277 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA out of block "
278 "border, chunk idx: %d, size: %d\n",
279 i, chunks[i].length);
280 return -EINVAL;
281 }
282 }
283
284 return num_chunks;
285}
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +0200286
Holger Hans Peter Freytherfcbc7022013-10-26 17:38:37 +0200287uint8_t Decoding::get_ms_class_by_capability(MS_Radio_Access_capability_t *cap)
288{
289 int i;
290
291 for (i = 0; i < cap->Count_MS_RA_capability_value; i++) {
292 if (!cap->MS_RA_capability_value[i].u.Content.Exist_Multislot_capability)
293 continue;
294 if (!cap->MS_RA_capability_value[i].u.Content.Multislot_capability.Exist_GPRS_multislot_class)
295 continue;
296 return cap->MS_RA_capability_value[i].u.Content.Multislot_capability.GPRS_multislot_class;
297 }
298
299 return 0;
300}
301
Jacob Erlbeckc3c58042015-09-28 17:55:32 +0200302uint8_t Decoding::get_egprs_ms_class_by_capability(MS_Radio_Access_capability_t *cap)
303{
304 int i;
305
306 for (i = 0; i < cap->Count_MS_RA_capability_value; i++) {
307 if (!cap->MS_RA_capability_value[i].u.Content.Exist_Multislot_capability)
308 continue;
309 if (!cap->MS_RA_capability_value[i].u.Content.Multislot_capability.Exist_EGPRS_multislot_class)
310 continue;
311 return cap->MS_RA_capability_value[i].u.Content.Multislot_capability.EGPRS_multislot_class;
312 }
313
314 return 0;
315}
316
Holger Hans Peter Freytherdf6b4f52013-11-24 17:05:48 +0100317/**
318 * show_rbb needs to be an array with 65 elements
Daniel Willmann5e94cd42013-12-11 20:11:16 +0100319 * The index of the array is the bit position in the rbb
320 * (show_rbb[63] relates to BSN ssn-1)
Holger Hans Peter Freytherdf6b4f52013-11-24 17:05:48 +0100321 */
322void Decoding::extract_rbb(const uint8_t *rbb, char *show_rbb)
323{
Daniel Willmann5e94cd42013-12-11 20:11:16 +0100324 for (int i = 0; i < 64; i++) {
Holger Hans Peter Freytherdf6b4f52013-11-24 17:05:48 +0100325 uint8_t bit;
326
Daniel Willmann5e94cd42013-12-11 20:11:16 +0100327 bit = !!(rbb[i/8] & (1<<(7-i%8)));
Daniel Willmann6f7cb2c2013-12-11 14:25:20 +0100328 show_rbb[i] = bit ? 'R' : 'I';
Holger Hans Peter Freytherdf6b4f52013-11-24 17:05:48 +0100329 }
330
331 show_rbb[64] = '\0';
332}
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100333
Jacob Erlbeckf2f24b02016-02-05 13:16:24 +0100334void Decoding::extract_rbb(const struct bitvec *rbb, char *show_rbb)
335{
336 unsigned int i;
337 for (i = 0; i < rbb->cur_bit; i++) {
338 uint8_t bit;
339 bit = bitvec_get_bit_pos(rbb, i);
340 show_rbb[i] = bit == 1 ? 'R' : 'I';
341 }
342
343 show_rbb[i] = '\0';
344}
345
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100346int Decoding::rlc_parse_ul_data_header(struct gprs_rlc_data_info *rlc,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100347 const uint8_t *data, GprsCodingScheme cs)
348{
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100349 unsigned int cur_bit = 0;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100350 switch(cs.headerTypeData()) {
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530351 case GprsCodingScheme::HEADER_GPRS_DATA :
352 cur_bit = rlc_parse_ul_data_header_gprs(rlc, data, cs);
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100353 break;
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530354 case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3 :
355 cur_bit = rlc_parse_ul_data_header_egprs_type_3(rlc, data, cs);
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100356 break;
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530357 case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2 :
358 cur_bit = rlc_parse_ul_data_header_egprs_type_2(rlc, data, cs);
359 break;
360 case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1 :
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530361 cur_bit = rlc_parse_ul_data_header_egprs_type_1(rlc, data, cs);
362 break;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100363 default:
364 LOGP(DRLCMACDL, LOGL_ERROR,
365 "Decoding of uplink %s data blocks not yet supported.\n",
366 cs.name());
367 return -ENOTSUP;
368 };
369
370 return cur_bit;
371}
372
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530373int Decoding::rlc_parse_ul_data_header_egprs_type_3(
374 struct gprs_rlc_data_info *rlc,
375 const uint8_t *data,
376 const GprsCodingScheme &cs)
377{
378 int punct, punct2, with_padding, cps;
379 unsigned int e_ti_header, offs, cur_bit = 0;
380 const struct gprs_rlc_ul_header_egprs_3 *egprs3;
381
382 egprs3 = static_cast < struct gprs_rlc_ul_header_egprs_3 * >
383 ((void *)data);
384
Tom Tsoudf698092016-07-11 17:05:19 -0700385 cps = (egprs3->cps_hi << 0) | (egprs3->cps_lo << 2);
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530386 gprs_rlc_mcs_cps_decode(cps, cs, &punct, &punct2, &with_padding);
387 gprs_rlc_data_info_init_ul(rlc, cs, with_padding);
388
389 rlc->r = egprs3->r;
390 rlc->si = egprs3->si;
Tom Tsoudf698092016-07-11 17:05:19 -0700391 rlc->tfi = (egprs3->tfi_hi << 0) | (egprs3->tfi_lo << 2);
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530392 rlc->cps = cps;
393 rlc->rsb = egprs3->rsb;
394
395 rlc->num_data_blocks = 1;
396 rlc->block_info[0].cv = egprs3->cv;
397 rlc->block_info[0].pi = egprs3->pi;
398 rlc->block_info[0].spb = egprs3->spb;
399 rlc->block_info[0].bsn =
Tom Tsoudf698092016-07-11 17:05:19 -0700400 (egprs3->bsn1_hi << 0) | (egprs3->bsn1_lo << 5);
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530401
402 cur_bit += rlc->data_offs_bits[0] - 2;
403 offs = rlc->data_offs_bits[0] / 8;
404 OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 1);
405 e_ti_header = (data[offs-1] + (data[offs] << 8)) >> 7;
406 rlc->block_info[0].e = !!(e_ti_header & 0x01);
407 rlc->block_info[0].ti = !!(e_ti_header & 0x02);
408 cur_bit += 2;
409 /* skip data area */
410 cur_bit += cs.maxDataBlockBytes() * 8;
411
412 return cur_bit;
413}
414
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530415int Decoding::rlc_parse_ul_data_header_egprs_type_2(
416 struct gprs_rlc_data_info *rlc,
417 const uint8_t *data,
418 const GprsCodingScheme &cs)
419{
420 const struct gprs_rlc_ul_header_egprs_2 *egprs2;
421 unsigned int e_ti_header, offs, cur_bit = 0;
422 int punct, punct2, with_padding, cps;
423
424 egprs2 = static_cast < struct gprs_rlc_ul_header_egprs_2 * >
425 ((void *)data);
426
Tom Tsoudf698092016-07-11 17:05:19 -0700427 cps = (egprs2->cps_hi << 0) | (egprs2->cps_lo << 2);
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530428 gprs_rlc_mcs_cps_decode(cps, cs, &punct, &punct2, &with_padding);
429 gprs_rlc_data_info_init_ul(rlc, cs, with_padding);
430
431 rlc->r = egprs2->r;
432 rlc->si = egprs2->si;
Tom Tsoudf698092016-07-11 17:05:19 -0700433 rlc->tfi = (egprs2->tfi_hi << 0) | (egprs2->tfi_lo << 2);
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530434 rlc->cps = cps;
435 rlc->rsb = egprs2->rsb;
436
437 rlc->num_data_blocks = 1;
438 rlc->block_info[0].cv = egprs2->cv;
439 rlc->block_info[0].pi = egprs2->pi;
440 rlc->block_info[0].bsn =
Tom Tsoudf698092016-07-11 17:05:19 -0700441 (egprs2->bsn1_hi << 0) | (egprs2->bsn1_lo << 5);
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530442
443 cur_bit += rlc->data_offs_bits[0] - 2;
444
445 offs = rlc->data_offs_bits[0] / 8;
446 OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 7);
447
448 e_ti_header = (data[offs] & 0x60) >> 5;
449 rlc->block_info[0].e = !!(e_ti_header & 0x01);
450 rlc->block_info[0].ti = !!(e_ti_header & 0x02);
451 cur_bit += 2;
452
453 /* skip data area */
454 cur_bit += cs.maxDataBlockBytes() * 8;
455
456 return cur_bit;
457}
458
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530459int Decoding::rlc_parse_ul_data_header_egprs_type_1(
460 struct gprs_rlc_data_info *rlc,
461 const uint8_t *data, const GprsCodingScheme &cs)
462{
463 struct gprs_rlc_ul_header_egprs_1 *egprs1;
464 unsigned int e_ti_header, cur_bit = 0, offs;
465 int punct, punct2, with_padding;
466
467 egprs1 = static_cast < struct gprs_rlc_ul_header_egprs_1 * >
468 ((void *)data);
469 gprs_rlc_mcs_cps_decode(egprs1->cps, cs, &punct, &punct2,
470 &with_padding);
471 gprs_rlc_data_info_init_ul(rlc, cs, with_padding);
472
473 rlc->r = egprs1->r;
474 rlc->si = egprs1->si;
Tom Tsoudf698092016-07-11 17:05:19 -0700475 rlc->tfi = (egprs1->tfi_hi << 0) | (egprs1->tfi_lo << 2);
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530476 rlc->cps = egprs1->cps;
477 rlc->rsb = egprs1->rsb;
478 rlc->num_data_blocks = 2;
479 rlc->block_info[0].cv = egprs1->cv;
480 rlc->block_info[0].pi = egprs1->pi;
481 rlc->block_info[0].bsn =
Tom Tsoudf698092016-07-11 17:05:19 -0700482 (egprs1->bsn1_hi << 0) | (egprs1->bsn1_lo << 5);
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530483
484 cur_bit += rlc->data_offs_bits[0] - 2;
485 offs = rlc->data_offs_bits[0] / 8;
486 OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 0);
487
488 e_ti_header = data[offs - 1] >> 6;
489 rlc->block_info[0].e = (e_ti_header & 0x01);
490 rlc->block_info[0].ti = !!(e_ti_header & 0x02);
491 cur_bit += 2;
492
493 rlc->block_info[1].cv = egprs1->cv;
494 rlc->block_info[1].pi = egprs1->pi;
495 rlc->block_info[1].bsn = rlc->block_info[0].bsn +
Tom Tsoudf698092016-07-11 17:05:19 -0700496 ((egprs1->bsn2_hi << 0) | (egprs1->bsn2_lo << 2));
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530497 rlc->block_info[1].bsn = rlc->block_info[1].bsn & (RLC_EGPRS_SNS - 1);
498
499 if ((rlc->block_info[1].bsn != rlc->block_info[0].bsn) &&
500 (rlc->block_info[0].cv == 0))
501 rlc->block_info[0].cv = 1;
502
503 cur_bit = rlc->data_offs_bits[1] - 2;
504
505 offs = rlc->data_offs_bits[1] / 8;
506 OSMO_ASSERT(rlc->data_offs_bits[1] % 8 == 2);
507
508 e_ti_header = (data[offs] & (0x03));
509 rlc->block_info[1].e = (e_ti_header & 0x01);
510 rlc->block_info[1].ti = !!(e_ti_header & 0x02);
511 cur_bit += 2;
512 /* skip data area */
513 cur_bit += cs.maxDataBlockBytes() * 8;
514
515 return cur_bit;
516}
517
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530518int Decoding::rlc_parse_ul_data_header_gprs(struct gprs_rlc_data_info *rlc,
519 const uint8_t *data, const GprsCodingScheme &cs)
520{
521 const struct rlc_ul_header *gprs;
522 unsigned int cur_bit = 0;
523
524 gprs = static_cast < struct rlc_ul_header * >
525 ((void *)data);
526
527 gprs_rlc_data_info_init_ul(rlc, cs, false);
528
529 rlc->r = gprs->r;
530 rlc->si = gprs->si;
531 rlc->tfi = gprs->tfi;
532 rlc->cps = 0;
533 rlc->rsb = 0;
534 rlc->num_data_blocks = 1;
535 rlc->block_info[0].cv = gprs->cv;
536 rlc->block_info[0].pi = gprs->pi;
537 rlc->block_info[0].bsn = gprs->bsn;
538 rlc->block_info[0].e = gprs->e;
539 rlc->block_info[0].ti = gprs->ti;
540 rlc->block_info[0].spb = 0;
541 cur_bit += rlc->data_offs_bits[0];
542 /* skip data area */
543 cur_bit += cs.maxDataBlockBytes() * 8;
544
545 return cur_bit;
546}
547
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100548/**
549 * \brief Copy LSB bitstream RLC data block to byte aligned buffer.
550 *
551 * Note that the bitstream is encoded in LSB first order, so the two octets
552 * 654321xx xxxxxx87 contain the octet 87654321 starting at bit position 3
553 * (LSB has bit position 1). This is a different order than the one used by
554 * CSN.1.
555 *
556 * \param data_block_idx The block index, 0..1 for header type 1, 0 otherwise
557 * \param src A pointer to the start of the RLC block (incl. the header)
558 * \param buffer A data area of a least the size of the RLC block
559 * \returns the number of bytes copied
560 */
561unsigned int Decoding::rlc_copy_to_aligned_buffer(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100562 const struct gprs_rlc_data_info *rlc,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100563 unsigned int data_block_idx,
564 const uint8_t *src, uint8_t *buffer)
565{
566 unsigned int hdr_bytes;
567 unsigned int extra_bits;
568 unsigned int i;
569
570 uint8_t c, last_c;
571 uint8_t *dst;
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100572 const struct gprs_rlc_data_block_info *rdbi;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100573
574 OSMO_ASSERT(data_block_idx < rlc->num_data_blocks);
575 rdbi = &rlc->block_info[data_block_idx];
576
577 hdr_bytes = rlc->data_offs_bits[data_block_idx] >> 3;
578 extra_bits = (rlc->data_offs_bits[data_block_idx] & 7);
579
580 if (extra_bits == 0) {
581 /* It is aligned already */
582 memmove(buffer, src + hdr_bytes, rdbi->data_len);
583 return rdbi->data_len;
584 }
585
586 dst = buffer;
587 src = src + hdr_bytes;
588 last_c = *(src++);
589
590 for (i = 0; i < rdbi->data_len; i++) {
591 c = src[i];
592 *(dst++) = (last_c >> extra_bits) | (c << (8 - extra_bits));
593 last_c = c;
594 }
595
596 return rdbi->data_len;
597}
598
599/**
600 * \brief Get a pointer to byte aligned RLC data.
601 *
602 * Since the RLC data may not be byte aligned to the RLC block data such that a
603 * single RLC data byte is spread over two RLC block bytes, this function
604 * eventually uses the provided buffer as data storage.
605 *
606 * \param src A pointer to the start of the RLC block (incl. the header)
607 * \param buffer A data area of a least the size of the RLC block
608 * \returns A pointer to the RLC data start within src if it is aligned, and
609 * buffer otherwise.
610 */
611const uint8_t *Decoding::rlc_get_data_aligned(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100612 const struct gprs_rlc_data_info *rlc,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100613 unsigned int data_block_idx,
614 const uint8_t *src, uint8_t *buffer)
615{
616 unsigned int hdr_bytes;
617 unsigned int extra_bits;
618
619 OSMO_ASSERT(data_block_idx < ARRAY_SIZE(rlc->data_offs_bits));
620
621 hdr_bytes = rlc->data_offs_bits[data_block_idx] >> 3;
622 extra_bits = (rlc->data_offs_bits[data_block_idx] & 7);
623
624 if (extra_bits == 0)
625 /* It is aligned already, return a pointer that refers to the
626 * original data. */
627 return src + hdr_bytes;
628
629 Decoding::rlc_copy_to_aligned_buffer(rlc, data_block_idx, src, buffer);
630 return buffer;
631}
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100632
633static int handle_final_ack(bitvec *bits, int *bsn_begin, int *bsn_end,
634 gprs_rlc_dl_window *window)
635{
636 int num_blocks, i;
637
638 num_blocks = window->mod_sns(window->v_s() - window->v_a());
639 for (i = 0; i < num_blocks; i++)
640 bitvec_set_bit(bits, ONE);
641
642 *bsn_begin = window->v_a();
643 *bsn_end = window->mod_sns(*bsn_begin + num_blocks);
644 return num_blocks;
645}
646
647int Decoding::decode_egprs_acknack_bits(const EGPRS_AckNack_Desc_t *desc,
648 bitvec *bits, int *bsn_begin, int *bsn_end, gprs_rlc_dl_window *window)
649{
650 int urbb_len = desc->URBB_LENGTH;
651 int crbb_len = 0;
652 int num_blocks = 0;
653 struct bitvec urbb;
654 int i;
655 bool have_bitmap;
656 int implicitly_acked_blocks;
657 int ssn = desc->STARTING_SEQUENCE_NUMBER;
Jacob Erlbeck2bef4db2016-01-20 14:33:11 +0100658 int rc;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100659
660 if (desc->FINAL_ACK_INDICATION)
661 return handle_final_ack(bits, bsn_begin, bsn_end, window);
662
663 if (desc->Exist_CRBB)
664 crbb_len = desc->CRBB_LENGTH;
665
666 have_bitmap = (urbb_len + crbb_len) > 0;
667
668 /*
669 * bow & bitmap present:
670 * V(A)-> [ 11111...11111 0 SSN-> BBBBB...BBBBB ] (SSN+Nbits) .... V(S)
671 * bow & not bitmap present:
672 * V(A)-> [ 11111...11111 ] . SSN .... V(S)
673 * not bow & bitmap present:
674 * V(A)-> ... [ 0 SSN-> BBBBB...BBBBB ](SSN+N) .... V(S)
675 * not bow & not bitmap present:
676 * V(A)-> ... [] . SSN .... V(S)
677 */
678
679 if (desc->BEGINNING_OF_WINDOW) {
680 implicitly_acked_blocks = window->mod_sns(ssn - 1 - window->v_a());
681
682 for (i = 0; i < implicitly_acked_blocks; i++)
683 bitvec_set_bit(bits, ONE);
684
685 num_blocks += implicitly_acked_blocks;
686 }
687
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100688 if (!have_bitmap)
689 goto aborted;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100690
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100691 /* next bit refers to V(Q) and thus is always zero (and not
692 * transmitted) */
693 bitvec_set_bit(bits, ZERO);
694 num_blocks += 1;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100695
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100696 if (crbb_len > 0) {
697 int old_len = bits->cur_bit;
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100698 struct bitvec crbb;
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100699
700 crbb.data = (uint8_t *)desc->CRBB;
701 crbb.data_len = sizeof(desc->CRBB);
702 crbb.cur_bit = desc->CRBB_LENGTH;
703
704 rc = osmo_t4_decode(&crbb, desc->CRBB_STARTING_COLOR_CODE,
705 bits);
706
707 if (rc < 0) {
708 LOGP(DRLCMACUL, LOGL_NOTICE,
709 "Failed to decode CRBB: "
710 "length %d, data '%s'\n",
711 desc->CRBB_LENGTH,
712 osmo_hexdump(crbb.data, crbb.data_len));
713 /* We don't know the SSN offset for the URBB,
714 * return what we have so far and assume the
715 * bitmap has stopped here */
716 goto aborted;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100717 }
718
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100719 LOGP(DRLCMACDL, LOGL_DEBUG,
720 "CRBB len: %d, decoded len: %d, cc: %d, crbb: '%s'\n",
721 desc->CRBB_LENGTH, bits->cur_bit - old_len,
722 desc->CRBB_STARTING_COLOR_CODE,
723 osmo_hexdump(
724 desc->CRBB, (desc->CRBB_LENGTH + 7)/8)
725 );
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100726
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100727 num_blocks += (bits->cur_bit - old_len);
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100728 }
729
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100730 urbb.cur_bit = 0;
731 urbb.data = (uint8_t *)desc->URBB;
732 urbb.data_len = sizeof(desc->URBB);
733
734 for (i = urbb_len; i > 0; i--) {
735 /*
736 * Set bit at the appropriate position (see 3GPP TS
737 * 44.060 12.3.1)
738 */
739 int is_ack = bitvec_get_bit_pos(&urbb, i-1);
740 bitvec_set_bit(bits, is_ack == 1 ? ONE : ZERO);
741 }
742 num_blocks += urbb_len;
743
744aborted:
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100745 *bsn_begin = window->v_a();
746 *bsn_end = window->mod_sns(*bsn_begin + num_blocks);
747
748 return num_blocks;
749}
Jacob Erlbeck192bf332016-02-05 13:10:29 +0100750
751int Decoding::decode_gprs_acknack_bits(const Ack_Nack_Description_t *desc,
752 bitvec *bits, int *bsn_begin, int *bsn_end, gprs_rlc_dl_window *window)
753{
754 int urbb_len = RLC_GPRS_WS;
755 int num_blocks;
756 struct bitvec urbb;
757
758 if (desc->FINAL_ACK_INDICATION)
759 return handle_final_ack(bits, bsn_begin, bsn_end, window);
760
761 *bsn_begin = window->v_a();
762 *bsn_end = desc->STARTING_SEQUENCE_NUMBER;
763
764 num_blocks = window->mod_sns(*bsn_end - *bsn_begin);
765
766 if (num_blocks < 0 || num_blocks > urbb_len) {
767 *bsn_end = *bsn_begin;
768 LOGP(DRLCMACUL, LOGL_NOTICE,
769 "Invalid GPRS Ack/Nack window %d:%d (length %d)\n",
770 *bsn_begin, *bsn_end, num_blocks);
771 return -EINVAL;
772 }
773
774 urbb.cur_bit = 0;
775 urbb.data = (uint8_t *)desc->RECEIVED_BLOCK_BITMAP;
776 urbb.data_len = sizeof(desc->RECEIVED_BLOCK_BITMAP);
777
778 /*
779 * TS 44.060, 12.3:
780 * BSN = (SSN - bit_number) modulo 128, for bit_number = 1 to 64.
781 * The BSN values represented range from (SSN - 1) mod 128 to (SSN - 64) mod 128.
782 *
783 * We are only interested in the range from V(A) to SSN-1 which is
784 * num_blocks large. The RBB is laid out as
785 * [SSN-1] [SSN-2] ... [V(A)] ... [SSN-64]
786 * so we want to start with [V(A)] and go backwards until we reach
787 * [SSN-1] to get the needed BSNs in an increasing order. Note that
788 * the bit numbers are counted from the end of the buffer.
789 */
790 for (int i = num_blocks; i > 0; i--) {
791 int is_ack = bitvec_get_bit_pos(&urbb, urbb_len - i);
792 bitvec_set_bit(bits, is_ack == 1 ? ONE : ZERO);
793 }
794
795 return num_blocks;
796}