blob: 3f5c4d27f2cefe7fd96d4b5789d3db4129650e3f [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 }
Aravind Sirsikar22a90192016-09-15 17:24:49 +053070 if (li->li == 0 && num_chunks == 0) {
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010071 /* TS 44.060, table 10.4.14a.1, row 2a */
Aravind Sirsikar22a90192016-09-15 17:24:49 +053072 /* TS 44.060, table 10.4.14a.1, row 4 */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010073 chunks[num_chunks].length = 0;
74 chunks[num_chunks].is_complete = true;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010075 } else if (li->li == 127 && li->e == 1) {
76 /* TS 44.060, table 10.4.14a.1, row 3 & 5 */
77 /* only filling bytes left */
78 break;
79 } else if (li->li > 0) {
80 /* TS 44.060, table 10.4.14a.1, row 1 & 2b */
81 chunks[num_chunks].length = li->li;
82 chunks[num_chunks].is_complete = true;
83 } else {
84 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI contains "
85 "invalid extension octet: LI=%d, E=%d, count=%d\n",
86 li->li, li->e, num_chunks);
87 return -EINVAL;
88 }
89
90 num_chunks += 1;
91
92 if (e == 1) {
93 /* There is space after the last chunk, add a final one */
94 if (num_chunks == chunks_size) {
95 LOGP(DRLCMACUL, LOGL_NOTICE,
96 "UL DATA LI possibly extended, "
97 "but no more chunks possible\n");
98 return -ENOSPC;
99 }
100
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100101 chunks[num_chunks].length = LENGTH_TO_END;
102 chunks[num_chunks].is_complete = is_last_block;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100103 num_chunks += 1;
104 }
105 }
106
107 return num_chunks;
108}
109
110static int parse_extensions_gprs(const uint8_t *data, unsigned int data_len,
111 unsigned int *offs,
112 bool is_last_block,
113 Decoding::RlcData *chunks, unsigned int chunks_size)
114{
115 const struct rlc_li_field *li;
116 uint8_t m, e;
117 unsigned int num_chunks = 0;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100118
119 e = 0;
120 while (!e) {
121 if (*offs > data_len) {
122 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
123 "but no more data\n");
124 return -EINVAL;
125 }
126
127 /* get new E */
128 li = (const struct rlc_li_field *)&data[*offs];
129 e = li->e;
130 m = li->m;
131 *offs += 1;
132
133 if (li->li == 0) {
134 /* TS 44.060, 10.4.14, par 6 */
135 e = 1;
136 m = 0;
137 }
138
139 /* TS 44.060, table 10.4.13.1 */
140 if (m == 0 && e == 0) {
141 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA "
142 "ignored, because M='0' and E='0'.\n");
143 return 0;
144 }
145
146 if (!chunks)
147 continue;
148
149 if (num_chunks == chunks_size) {
150 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
151 "but no more chunks possible\n");
152 return -ENOSPC;
153 }
154
155 if (li->li == 0)
156 /* e is 1 here */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100157 chunks[num_chunks].length = LENGTH_TO_END;
158 else
159 chunks[num_chunks].length = li->li;
160
161 chunks[num_chunks].is_complete = li->li || is_last_block;
162
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100163 num_chunks += 1;
164
165 if (e == 1 && m == 1) {
166 if (num_chunks == chunks_size) {
167 LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA LI extended, "
168 "but no more chunks possible\n");
169 return -ENOSPC;
170 }
171 /* TS 44.060, 10.4.13.1, row 4 */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100172 chunks[num_chunks].length = LENGTH_TO_END;
173 chunks[num_chunks].is_complete = is_last_block;
174 num_chunks += 1;
175 }
176 }
177
178 return num_chunks;
179}
180
181int Decoding::rlc_data_from_ul_data(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100182 const struct gprs_rlc_data_block_info *rdbi, GprsCodingScheme cs,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100183 const uint8_t *data, RlcData *chunks, unsigned int chunks_size,
184 uint32_t *tlli)
185{
186 uint8_t e;
187 unsigned int data_len = rdbi->data_len;
Jacob Erlbeckead5e472016-01-08 10:14:50 +0100188 int num_chunks = 0, i;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100189 unsigned int offs = 0;
190 bool is_last_block = (rdbi->cv == 0);
191
192 if (!chunks)
193 chunks_size = 0;
194
195 e = rdbi->e;
196 if (e) {
197 if (chunks_size > 0) {
Alexander Couzensb82bd922016-05-30 17:30:10 +0200198 /* Block without LI means it only contains data of one LLC PDU */
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100199 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;
Alexander Couzensd302e4f2016-05-30 17:31:09 +0200268 break;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100269 }
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 Erlbeckf2f24b02016-02-05 13:16:24 +0100331void Decoding::extract_rbb(const struct bitvec *rbb, char *show_rbb)
332{
333 unsigned int i;
334 for (i = 0; i < rbb->cur_bit; i++) {
335 uint8_t bit;
336 bit = bitvec_get_bit_pos(rbb, i);
337 show_rbb[i] = bit == 1 ? 'R' : 'I';
338 }
339
340 show_rbb[i] = '\0';
341}
342
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100343int Decoding::rlc_parse_ul_data_header(struct gprs_rlc_data_info *rlc,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100344 const uint8_t *data, GprsCodingScheme cs)
345{
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100346 unsigned int cur_bit = 0;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100347 switch(cs.headerTypeData()) {
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530348 case GprsCodingScheme::HEADER_GPRS_DATA :
349 cur_bit = rlc_parse_ul_data_header_gprs(rlc, data, cs);
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100350 break;
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530351 case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3 :
352 cur_bit = rlc_parse_ul_data_header_egprs_type_3(rlc, data, cs);
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100353 break;
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530354 case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2 :
355 cur_bit = rlc_parse_ul_data_header_egprs_type_2(rlc, data, cs);
356 break;
357 case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1 :
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530358 cur_bit = rlc_parse_ul_data_header_egprs_type_1(rlc, data, cs);
359 break;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100360 default:
361 LOGP(DRLCMACDL, LOGL_ERROR,
362 "Decoding of uplink %s data blocks not yet supported.\n",
363 cs.name());
364 return -ENOTSUP;
365 };
366
367 return cur_bit;
368}
369
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530370int Decoding::rlc_parse_ul_data_header_egprs_type_3(
371 struct gprs_rlc_data_info *rlc,
372 const uint8_t *data,
373 const GprsCodingScheme &cs)
374{
375 int punct, punct2, with_padding, cps;
376 unsigned int e_ti_header, offs, cur_bit = 0;
377 const struct gprs_rlc_ul_header_egprs_3 *egprs3;
378
379 egprs3 = static_cast < struct gprs_rlc_ul_header_egprs_3 * >
380 ((void *)data);
381
Tom Tsoudf698092016-07-11 17:05:19 -0700382 cps = (egprs3->cps_hi << 0) | (egprs3->cps_lo << 2);
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530383 gprs_rlc_mcs_cps_decode(cps, cs, &punct, &punct2, &with_padding);
384 gprs_rlc_data_info_init_ul(rlc, cs, with_padding);
385
386 rlc->r = egprs3->r;
387 rlc->si = egprs3->si;
Tom Tsoudf698092016-07-11 17:05:19 -0700388 rlc->tfi = (egprs3->tfi_hi << 0) | (egprs3->tfi_lo << 2);
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530389 rlc->cps = cps;
390 rlc->rsb = egprs3->rsb;
391
392 rlc->num_data_blocks = 1;
393 rlc->block_info[0].cv = egprs3->cv;
394 rlc->block_info[0].pi = egprs3->pi;
395 rlc->block_info[0].spb = egprs3->spb;
396 rlc->block_info[0].bsn =
Tom Tsoudf698092016-07-11 17:05:19 -0700397 (egprs3->bsn1_hi << 0) | (egprs3->bsn1_lo << 5);
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530398
399 cur_bit += rlc->data_offs_bits[0] - 2;
400 offs = rlc->data_offs_bits[0] / 8;
401 OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 1);
402 e_ti_header = (data[offs-1] + (data[offs] << 8)) >> 7;
403 rlc->block_info[0].e = !!(e_ti_header & 0x01);
404 rlc->block_info[0].ti = !!(e_ti_header & 0x02);
405 cur_bit += 2;
406 /* skip data area */
407 cur_bit += cs.maxDataBlockBytes() * 8;
408
409 return cur_bit;
410}
411
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530412int Decoding::rlc_parse_ul_data_header_egprs_type_2(
413 struct gprs_rlc_data_info *rlc,
414 const uint8_t *data,
415 const GprsCodingScheme &cs)
416{
417 const struct gprs_rlc_ul_header_egprs_2 *egprs2;
418 unsigned int e_ti_header, offs, cur_bit = 0;
419 int punct, punct2, with_padding, cps;
420
421 egprs2 = static_cast < struct gprs_rlc_ul_header_egprs_2 * >
422 ((void *)data);
423
Tom Tsoudf698092016-07-11 17:05:19 -0700424 cps = (egprs2->cps_hi << 0) | (egprs2->cps_lo << 2);
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530425 gprs_rlc_mcs_cps_decode(cps, cs, &punct, &punct2, &with_padding);
426 gprs_rlc_data_info_init_ul(rlc, cs, with_padding);
427
428 rlc->r = egprs2->r;
429 rlc->si = egprs2->si;
Tom Tsoudf698092016-07-11 17:05:19 -0700430 rlc->tfi = (egprs2->tfi_hi << 0) | (egprs2->tfi_lo << 2);
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530431 rlc->cps = cps;
432 rlc->rsb = egprs2->rsb;
433
434 rlc->num_data_blocks = 1;
435 rlc->block_info[0].cv = egprs2->cv;
436 rlc->block_info[0].pi = egprs2->pi;
437 rlc->block_info[0].bsn =
Tom Tsoudf698092016-07-11 17:05:19 -0700438 (egprs2->bsn1_hi << 0) | (egprs2->bsn1_lo << 5);
Aravind Sirsikar550a5412016-06-14 18:59:18 +0530439
440 cur_bit += rlc->data_offs_bits[0] - 2;
441
442 offs = rlc->data_offs_bits[0] / 8;
443 OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 7);
444
445 e_ti_header = (data[offs] & 0x60) >> 5;
446 rlc->block_info[0].e = !!(e_ti_header & 0x01);
447 rlc->block_info[0].ti = !!(e_ti_header & 0x02);
448 cur_bit += 2;
449
450 /* skip data area */
451 cur_bit += cs.maxDataBlockBytes() * 8;
452
453 return cur_bit;
454}
455
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530456int Decoding::rlc_parse_ul_data_header_egprs_type_1(
457 struct gprs_rlc_data_info *rlc,
458 const uint8_t *data, const GprsCodingScheme &cs)
459{
460 struct gprs_rlc_ul_header_egprs_1 *egprs1;
461 unsigned int e_ti_header, cur_bit = 0, offs;
462 int punct, punct2, with_padding;
463
464 egprs1 = static_cast < struct gprs_rlc_ul_header_egprs_1 * >
465 ((void *)data);
466 gprs_rlc_mcs_cps_decode(egprs1->cps, cs, &punct, &punct2,
467 &with_padding);
468 gprs_rlc_data_info_init_ul(rlc, cs, with_padding);
469
470 rlc->r = egprs1->r;
471 rlc->si = egprs1->si;
Tom Tsoudf698092016-07-11 17:05:19 -0700472 rlc->tfi = (egprs1->tfi_hi << 0) | (egprs1->tfi_lo << 2);
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530473 rlc->cps = egprs1->cps;
474 rlc->rsb = egprs1->rsb;
475 rlc->num_data_blocks = 2;
476 rlc->block_info[0].cv = egprs1->cv;
477 rlc->block_info[0].pi = egprs1->pi;
478 rlc->block_info[0].bsn =
Tom Tsoudf698092016-07-11 17:05:19 -0700479 (egprs1->bsn1_hi << 0) | (egprs1->bsn1_lo << 5);
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530480
481 cur_bit += rlc->data_offs_bits[0] - 2;
482 offs = rlc->data_offs_bits[0] / 8;
483 OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 0);
484
485 e_ti_header = data[offs - 1] >> 6;
486 rlc->block_info[0].e = (e_ti_header & 0x01);
487 rlc->block_info[0].ti = !!(e_ti_header & 0x02);
488 cur_bit += 2;
489
490 rlc->block_info[1].cv = egprs1->cv;
491 rlc->block_info[1].pi = egprs1->pi;
492 rlc->block_info[1].bsn = rlc->block_info[0].bsn +
Tom Tsoudf698092016-07-11 17:05:19 -0700493 ((egprs1->bsn2_hi << 0) | (egprs1->bsn2_lo << 2));
Aravind Sirsikar99ab0a82016-06-15 17:46:41 +0530494 rlc->block_info[1].bsn = rlc->block_info[1].bsn & (RLC_EGPRS_SNS - 1);
495
496 if ((rlc->block_info[1].bsn != rlc->block_info[0].bsn) &&
497 (rlc->block_info[0].cv == 0))
498 rlc->block_info[0].cv = 1;
499
500 cur_bit = rlc->data_offs_bits[1] - 2;
501
502 offs = rlc->data_offs_bits[1] / 8;
503 OSMO_ASSERT(rlc->data_offs_bits[1] % 8 == 2);
504
505 e_ti_header = (data[offs] & (0x03));
506 rlc->block_info[1].e = (e_ti_header & 0x01);
507 rlc->block_info[1].ti = !!(e_ti_header & 0x02);
508 cur_bit += 2;
509 /* skip data area */
510 cur_bit += cs.maxDataBlockBytes() * 8;
511
512 return cur_bit;
513}
514
Bhargava Abhyankare44383b2016-03-22 18:42:30 +0530515int Decoding::rlc_parse_ul_data_header_gprs(struct gprs_rlc_data_info *rlc,
516 const uint8_t *data, const GprsCodingScheme &cs)
517{
518 const struct rlc_ul_header *gprs;
519 unsigned int cur_bit = 0;
520
521 gprs = static_cast < struct rlc_ul_header * >
522 ((void *)data);
523
524 gprs_rlc_data_info_init_ul(rlc, cs, false);
525
526 rlc->r = gprs->r;
527 rlc->si = gprs->si;
528 rlc->tfi = gprs->tfi;
529 rlc->cps = 0;
530 rlc->rsb = 0;
531 rlc->num_data_blocks = 1;
532 rlc->block_info[0].cv = gprs->cv;
533 rlc->block_info[0].pi = gprs->pi;
534 rlc->block_info[0].bsn = gprs->bsn;
535 rlc->block_info[0].e = gprs->e;
536 rlc->block_info[0].ti = gprs->ti;
537 rlc->block_info[0].spb = 0;
538 cur_bit += rlc->data_offs_bits[0];
539 /* skip data area */
540 cur_bit += cs.maxDataBlockBytes() * 8;
541
542 return cur_bit;
543}
544
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100545/**
546 * \brief Copy LSB bitstream RLC data block to byte aligned buffer.
547 *
548 * Note that the bitstream is encoded in LSB first order, so the two octets
549 * 654321xx xxxxxx87 contain the octet 87654321 starting at bit position 3
550 * (LSB has bit position 1). This is a different order than the one used by
551 * CSN.1.
552 *
553 * \param data_block_idx The block index, 0..1 for header type 1, 0 otherwise
554 * \param src A pointer to the start of the RLC block (incl. the header)
555 * \param buffer A data area of a least the size of the RLC block
556 * \returns the number of bytes copied
557 */
558unsigned int Decoding::rlc_copy_to_aligned_buffer(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100559 const struct gprs_rlc_data_info *rlc,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100560 unsigned int data_block_idx,
561 const uint8_t *src, uint8_t *buffer)
562{
563 unsigned int hdr_bytes;
564 unsigned int extra_bits;
565 unsigned int i;
566
567 uint8_t c, last_c;
568 uint8_t *dst;
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100569 const struct gprs_rlc_data_block_info *rdbi;
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100570
571 OSMO_ASSERT(data_block_idx < rlc->num_data_blocks);
572 rdbi = &rlc->block_info[data_block_idx];
573
574 hdr_bytes = rlc->data_offs_bits[data_block_idx] >> 3;
575 extra_bits = (rlc->data_offs_bits[data_block_idx] & 7);
576
577 if (extra_bits == 0) {
578 /* It is aligned already */
579 memmove(buffer, src + hdr_bytes, rdbi->data_len);
580 return rdbi->data_len;
581 }
582
583 dst = buffer;
584 src = src + hdr_bytes;
585 last_c = *(src++);
586
587 for (i = 0; i < rdbi->data_len; i++) {
588 c = src[i];
589 *(dst++) = (last_c >> extra_bits) | (c << (8 - extra_bits));
590 last_c = c;
591 }
592
593 return rdbi->data_len;
594}
595
596/**
597 * \brief Get a pointer to byte aligned RLC data.
598 *
599 * Since the RLC data may not be byte aligned to the RLC block data such that a
600 * single RLC data byte is spread over two RLC block bytes, this function
601 * eventually uses the provided buffer as data storage.
602 *
603 * \param src A pointer to the start of the RLC block (incl. the header)
604 * \param buffer A data area of a least the size of the RLC block
605 * \returns A pointer to the RLC data start within src if it is aligned, and
606 * buffer otherwise.
607 */
608const uint8_t *Decoding::rlc_get_data_aligned(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100609 const struct gprs_rlc_data_info *rlc,
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100610 unsigned int data_block_idx,
611 const uint8_t *src, uint8_t *buffer)
612{
613 unsigned int hdr_bytes;
614 unsigned int extra_bits;
615
616 OSMO_ASSERT(data_block_idx < ARRAY_SIZE(rlc->data_offs_bits));
617
618 hdr_bytes = rlc->data_offs_bits[data_block_idx] >> 3;
619 extra_bits = (rlc->data_offs_bits[data_block_idx] & 7);
620
621 if (extra_bits == 0)
622 /* It is aligned already, return a pointer that refers to the
623 * original data. */
624 return src + hdr_bytes;
625
626 Decoding::rlc_copy_to_aligned_buffer(rlc, data_block_idx, src, buffer);
627 return buffer;
628}
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100629
630static int handle_final_ack(bitvec *bits, int *bsn_begin, int *bsn_end,
631 gprs_rlc_dl_window *window)
632{
633 int num_blocks, i;
634
635 num_blocks = window->mod_sns(window->v_s() - window->v_a());
636 for (i = 0; i < num_blocks; i++)
637 bitvec_set_bit(bits, ONE);
638
639 *bsn_begin = window->v_a();
640 *bsn_end = window->mod_sns(*bsn_begin + num_blocks);
641 return num_blocks;
642}
643
644int Decoding::decode_egprs_acknack_bits(const EGPRS_AckNack_Desc_t *desc,
645 bitvec *bits, int *bsn_begin, int *bsn_end, gprs_rlc_dl_window *window)
646{
647 int urbb_len = desc->URBB_LENGTH;
648 int crbb_len = 0;
649 int num_blocks = 0;
650 struct bitvec urbb;
651 int i;
652 bool have_bitmap;
653 int implicitly_acked_blocks;
654 int ssn = desc->STARTING_SEQUENCE_NUMBER;
Jacob Erlbeck2bef4db2016-01-20 14:33:11 +0100655 int rc;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100656
657 if (desc->FINAL_ACK_INDICATION)
658 return handle_final_ack(bits, bsn_begin, bsn_end, window);
659
660 if (desc->Exist_CRBB)
661 crbb_len = desc->CRBB_LENGTH;
662
663 have_bitmap = (urbb_len + crbb_len) > 0;
664
665 /*
666 * bow & bitmap present:
667 * V(A)-> [ 11111...11111 0 SSN-> BBBBB...BBBBB ] (SSN+Nbits) .... V(S)
668 * bow & not bitmap present:
669 * V(A)-> [ 11111...11111 ] . SSN .... V(S)
670 * not bow & bitmap present:
671 * V(A)-> ... [ 0 SSN-> BBBBB...BBBBB ](SSN+N) .... V(S)
672 * not bow & not bitmap present:
673 * V(A)-> ... [] . SSN .... V(S)
674 */
675
676 if (desc->BEGINNING_OF_WINDOW) {
677 implicitly_acked_blocks = window->mod_sns(ssn - 1 - window->v_a());
678
679 for (i = 0; i < implicitly_acked_blocks; i++)
680 bitvec_set_bit(bits, ONE);
681
682 num_blocks += implicitly_acked_blocks;
683 }
684
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100685 if (!have_bitmap)
686 goto aborted;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100687
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100688 /* next bit refers to V(Q) and thus is always zero (and not
689 * transmitted) */
690 bitvec_set_bit(bits, ZERO);
691 num_blocks += 1;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100692
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100693 if (crbb_len > 0) {
694 int old_len = bits->cur_bit;
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100695 struct bitvec crbb;
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100696
697 crbb.data = (uint8_t *)desc->CRBB;
698 crbb.data_len = sizeof(desc->CRBB);
699 crbb.cur_bit = desc->CRBB_LENGTH;
700
701 rc = osmo_t4_decode(&crbb, desc->CRBB_STARTING_COLOR_CODE,
702 bits);
703
704 if (rc < 0) {
705 LOGP(DRLCMACUL, LOGL_NOTICE,
706 "Failed to decode CRBB: "
707 "length %d, data '%s'\n",
708 desc->CRBB_LENGTH,
709 osmo_hexdump(crbb.data, crbb.data_len));
710 /* We don't know the SSN offset for the URBB,
711 * return what we have so far and assume the
712 * bitmap has stopped here */
713 goto aborted;
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100714 }
715
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100716 LOGP(DRLCMACDL, LOGL_DEBUG,
717 "CRBB len: %d, decoded len: %d, cc: %d, crbb: '%s'\n",
718 desc->CRBB_LENGTH, bits->cur_bit - old_len,
719 desc->CRBB_STARTING_COLOR_CODE,
720 osmo_hexdump(
721 desc->CRBB, (desc->CRBB_LENGTH + 7)/8)
722 );
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100723
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100724 num_blocks += (bits->cur_bit - old_len);
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100725 }
726
Jacob Erlbeck3fdcb2b2016-01-18 16:51:59 +0100727 urbb.cur_bit = 0;
728 urbb.data = (uint8_t *)desc->URBB;
729 urbb.data_len = sizeof(desc->URBB);
730
731 for (i = urbb_len; i > 0; i--) {
732 /*
733 * Set bit at the appropriate position (see 3GPP TS
734 * 44.060 12.3.1)
735 */
736 int is_ack = bitvec_get_bit_pos(&urbb, i-1);
737 bitvec_set_bit(bits, is_ack == 1 ? ONE : ZERO);
738 }
739 num_blocks += urbb_len;
740
741aborted:
Jacob Erlbeckae9c5752016-01-13 13:55:44 +0100742 *bsn_begin = window->v_a();
743 *bsn_end = window->mod_sns(*bsn_begin + num_blocks);
744
745 return num_blocks;
746}
Jacob Erlbeck192bf332016-02-05 13:10:29 +0100747
748int Decoding::decode_gprs_acknack_bits(const Ack_Nack_Description_t *desc,
749 bitvec *bits, int *bsn_begin, int *bsn_end, gprs_rlc_dl_window *window)
750{
751 int urbb_len = RLC_GPRS_WS;
752 int num_blocks;
753 struct bitvec urbb;
754
755 if (desc->FINAL_ACK_INDICATION)
756 return handle_final_ack(bits, bsn_begin, bsn_end, window);
757
758 *bsn_begin = window->v_a();
759 *bsn_end = desc->STARTING_SEQUENCE_NUMBER;
760
761 num_blocks = window->mod_sns(*bsn_end - *bsn_begin);
762
763 if (num_blocks < 0 || num_blocks > urbb_len) {
764 *bsn_end = *bsn_begin;
765 LOGP(DRLCMACUL, LOGL_NOTICE,
766 "Invalid GPRS Ack/Nack window %d:%d (length %d)\n",
767 *bsn_begin, *bsn_end, num_blocks);
768 return -EINVAL;
769 }
770
771 urbb.cur_bit = 0;
772 urbb.data = (uint8_t *)desc->RECEIVED_BLOCK_BITMAP;
773 urbb.data_len = sizeof(desc->RECEIVED_BLOCK_BITMAP);
774
775 /*
776 * TS 44.060, 12.3:
777 * BSN = (SSN - bit_number) modulo 128, for bit_number = 1 to 64.
778 * The BSN values represented range from (SSN - 1) mod 128 to (SSN - 64) mod 128.
779 *
780 * We are only interested in the range from V(A) to SSN-1 which is
781 * num_blocks large. The RBB is laid out as
782 * [SSN-1] [SSN-2] ... [V(A)] ... [SSN-64]
783 * so we want to start with [V(A)] and go backwards until we reach
784 * [SSN-1] to get the needed BSNs in an increasing order. Note that
785 * the bit numbers are counted from the end of the buffer.
786 */
787 for (int i = num_blocks; i > 0; i--) {
788 int is_ack = bitvec_get_bit_pos(&urbb, urbb_len - i);
789 bitvec_set_bit(bits, is_ack == 1 ? ONE : ZERO);
790 }
791
792 return num_blocks;
793}