blob: 98ca206aa70a404a4ec6c24d001c2703c5e6cbb9 [file] [log] [blame]
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001/*
2 * EdgeTest.cpp
3 *
4 * Copyright (C) 2015 by Sysmocom s.f.m.c. GmbH
5 *
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#include "gprs_debug.h"
24#include "gprs_coding_scheme.h"
Jacob Erlbeck61679252015-12-11 18:25:21 +010025#include "decoding.h"
Jacob Erlbeckf0e40392016-01-08 10:07:53 +010026#include "encoding.h"
Jacob Erlbeck61679252015-12-11 18:25:21 +010027#include "rlc.h"
Jacob Erlbeck14bb0942016-01-12 11:58:13 +010028#include "llc.h"
Aravind Sirsikar189742b2016-06-14 19:01:14 +053029#include "bts.h"
Max1187a772018-01-26 13:31:42 +010030#include <gprs_rlcmac.h>
31
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010032extern "C" {
33#include "pcu_vty.h"
34
35#include <osmocom/core/application.h>
36#include <osmocom/core/msgb.h>
37#include <osmocom/core/talloc.h>
38#include <osmocom/core/utils.h>
39#include <osmocom/vty/vty.h>
Tom Tsoudf698092016-07-11 17:05:19 -070040#include <osmocom/gprs/protocol/gsm_04_60.h>
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010041}
42
43#include <errno.h>
Jacob Erlbeckf0e40392016-01-08 10:07:53 +010044#include <string.h>
Neels Hofmeyrd34646a2017-02-08 17:07:40 +010045#include <limits.h>
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010046
47void *tall_pcu_ctx;
48int16_t spoof_mnc = 0, spoof_mcc = 0;
Neels Hofmeyrbdc55fa2018-02-21 00:39:07 +010049bool spoof_mnc_3_digits = false;
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010050
51static void check_coding_scheme(GprsCodingScheme& cs, GprsCodingScheme::Mode mode)
52{
53 volatile unsigned expected_size;
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010054 bool need_padding;
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010055 GprsCodingScheme new_cs;
56
57 OSMO_ASSERT(cs.isValid());
58 OSMO_ASSERT(cs.isCompatible(mode));
59
60 /* Check static getBySizeUL() */
Jacob Erlbeckfc1b3e62016-01-11 09:58:11 +010061 expected_size = cs.usedSizeUL();
62 if (cs.spareBitsUL() > 0 && cs.isGprs())
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010063 expected_size += 1;
64 OSMO_ASSERT(expected_size == cs.sizeUL());
65 OSMO_ASSERT(cs == GprsCodingScheme::getBySizeUL(expected_size));
66
67 /* Check static sizeUL() */
Jacob Erlbeckfc1b3e62016-01-11 09:58:11 +010068 expected_size = cs.usedSizeDL();
69 if (cs.spareBitsDL() > 0 && cs.isGprs())
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010070 expected_size += 1;
71 OSMO_ASSERT(expected_size == cs.sizeDL());
72
Jacob Erlbeck392a5452015-12-14 10:38:29 +010073 /* Check data block sizes */
74 OSMO_ASSERT(cs.maxDataBlockBytes() * cs.numDataBlocks() < cs.maxBytesDL());
75 OSMO_ASSERT(cs.maxDataBlockBytes() * cs.numDataBlocks() < cs.maxBytesUL());
76
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010077 /* Check inc/dec */
78 new_cs = cs;
79 new_cs.inc(mode);
80 OSMO_ASSERT(new_cs.isCompatible(mode));
81 if (new_cs != cs) {
82 new_cs.dec(mode);
83 OSMO_ASSERT(new_cs.isCompatible(mode));
84 OSMO_ASSERT(new_cs == cs);
85 }
86 new_cs.dec(mode);
87 OSMO_ASSERT(new_cs.isCompatible(mode));
88 if (new_cs != cs) {
89 new_cs.inc(mode);
90 OSMO_ASSERT(new_cs.isCompatible(mode));
91 OSMO_ASSERT(new_cs == cs);
92 }
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010093
94 new_cs = cs;
95 new_cs.decToSingleBlock(&need_padding);
96 OSMO_ASSERT(new_cs.isFamilyCompatible(cs));
97 OSMO_ASSERT(cs.isFamilyCompatible(new_cs));
98 OSMO_ASSERT(cs.isCompatible(new_cs));
99 if (need_padding) {
Jacob Erlbeck215e18c2016-02-03 18:22:34 +0100100 OSMO_ASSERT(new_cs.maxDataBlockBytes() ==
101 new_cs.optionalPaddingBits()/8 + cs.maxDataBlockBytes());
Jacob Erlbeck2305afd2016-02-03 15:25:04 +0100102 } else {
103 OSMO_ASSERT(new_cs.maxDataBlockBytes() == cs.maxDataBlockBytes());
104 }
105
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100106}
107
108static void test_coding_scheme()
109{
110 unsigned i;
111 unsigned last_size_UL;
112 unsigned last_size_DL;
113 GprsCodingScheme::Scheme gprs_schemes[] = {
114 GprsCodingScheme::CS1,
115 GprsCodingScheme::CS2,
116 GprsCodingScheme::CS3,
117 GprsCodingScheme::CS4
118 };
119 struct {
120 GprsCodingScheme::Scheme s;
121 bool is_gmsk;
122 } egprs_schemes[] = {
123 {GprsCodingScheme::MCS1, true},
124 {GprsCodingScheme::MCS2, true},
125 {GprsCodingScheme::MCS3, true},
126 {GprsCodingScheme::MCS4, true},
127 {GprsCodingScheme::MCS5, false},
128 {GprsCodingScheme::MCS6, false},
129 {GprsCodingScheme::MCS7, false},
130 {GprsCodingScheme::MCS8, false},
131 {GprsCodingScheme::MCS9, false},
132 };
133
134 printf("=== start %s ===\n", __func__);
135
136 GprsCodingScheme cs;
137 OSMO_ASSERT(!cs);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100138 OSMO_ASSERT(GprsCodingScheme::Scheme(cs) == GprsCodingScheme::UNKNOWN);
139 OSMO_ASSERT(cs == GprsCodingScheme(GprsCodingScheme::UNKNOWN));
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100140 OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::GPRS));
141 OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::EGPRS_GMSK));
142 OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::EGPRS));
143
144 last_size_UL = 0;
145 last_size_DL = 0;
146
147 for (i = 0; i < ARRAY_SIZE(gprs_schemes); i++) {
148 GprsCodingScheme current_cs(gprs_schemes[i]);
149 OSMO_ASSERT(current_cs.isGprs());
150 OSMO_ASSERT(!current_cs.isEgprs());
151 OSMO_ASSERT(!current_cs.isEgprsGmsk());
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100152 OSMO_ASSERT(GprsCodingScheme::Scheme(current_cs) == gprs_schemes[i]);
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100153 OSMO_ASSERT(current_cs == GprsCodingScheme(gprs_schemes[i]));
154
155 /* Check strong monotonicity */
156 OSMO_ASSERT(current_cs.maxBytesUL() > last_size_UL);
157 OSMO_ASSERT(current_cs.maxBytesDL() > last_size_DL);
158 last_size_UL = current_cs.maxBytesUL();
159 last_size_DL = current_cs.maxBytesDL();
160
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +0100161 /* Check header types */
162 OSMO_ASSERT(current_cs.headerTypeData() ==
163 GprsCodingScheme::HEADER_GPRS_DATA);
164 OSMO_ASSERT(current_cs.headerTypeControl() ==
165 GprsCodingScheme::HEADER_GPRS_CONTROL);
166
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100167 check_coding_scheme(current_cs, GprsCodingScheme::GPRS);
168 }
169 OSMO_ASSERT(i == 4);
170
171 last_size_UL = 0;
172 last_size_DL = 0;
173
174 for (i = 0; i < ARRAY_SIZE(egprs_schemes); i++) {
175 GprsCodingScheme current_cs(egprs_schemes[i].s);
176 OSMO_ASSERT(!current_cs.isGprs());
177 OSMO_ASSERT(current_cs.isEgprs());
178 OSMO_ASSERT(!!current_cs.isEgprsGmsk() == !!egprs_schemes[i].is_gmsk);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100179 OSMO_ASSERT(GprsCodingScheme::Scheme(current_cs) == egprs_schemes[i].s);
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100180 OSMO_ASSERT(current_cs == GprsCodingScheme(egprs_schemes[i].s));
181
182 /* Check strong monotonicity */
183 OSMO_ASSERT(current_cs.maxBytesUL() > last_size_UL);
184 OSMO_ASSERT(current_cs.maxBytesDL() > last_size_DL);
185 last_size_UL = current_cs.maxBytesUL();
186 last_size_DL = current_cs.maxBytesDL();
187
188 if (egprs_schemes[i].is_gmsk)
189 check_coding_scheme(current_cs, GprsCodingScheme::EGPRS_GMSK);
190 check_coding_scheme(current_cs, GprsCodingScheme::EGPRS);
191 }
192 OSMO_ASSERT(i == 9);
193
194 printf("=== end %s ===\n", __func__);
195}
196
Jacob Erlbeck38f18692016-02-01 10:08:00 +0100197static void test_rlc_unit_decoder()
Jacob Erlbeck61679252015-12-11 18:25:21 +0100198{
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100199 struct gprs_rlc_data_block_info rdbi = {0};
Jacob Erlbeck61679252015-12-11 18:25:21 +0100200 GprsCodingScheme cs;
201 uint8_t data[74];
202 Decoding::RlcData chunks[16];
203 volatile int num_chunks = 0;
204 uint32_t tlli, tlli2;
205 unsigned int offs;
206
207
208 printf("=== start %s ===\n", __func__);
209
210 /* TS 44.060, B.1 */
211 cs = GprsCodingScheme::CS4;
212 rdbi.data_len = cs.maxDataBlockBytes();
213 rdbi.e = 0;
214 rdbi.ti = 0;
215 rdbi.cv = 15;
216 tlli = 0;
217 offs = 0;
218 data[offs++] = (11 << 2) | (1 << 1) | (0 << 0);
219 data[offs++] = (26 << 2) | (1 << 1) | (1 << 0);
220 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
221 chunks, ARRAY_SIZE(chunks), &tlli);
222 OSMO_ASSERT(num_chunks == 3);
223 OSMO_ASSERT(tlli == 0);
224 OSMO_ASSERT(chunks[0].offset == 2);
225 OSMO_ASSERT(chunks[0].length == 11);
226 OSMO_ASSERT(chunks[0].is_complete);
227 OSMO_ASSERT(chunks[1].offset == 13);
228 OSMO_ASSERT(chunks[1].length == 26);
229 OSMO_ASSERT(chunks[1].is_complete);
230 OSMO_ASSERT(chunks[2].offset == 39);
231 OSMO_ASSERT(chunks[2].length == cs.maxDataBlockBytes() - 39);
232 OSMO_ASSERT(!chunks[2].is_complete);
233
234 /* TS 44.060, B.2 */
235 cs = GprsCodingScheme::CS1;
236 rdbi.data_len = cs.maxDataBlockBytes();
237 rdbi.e = 0;
238 rdbi.ti = 0;
239 rdbi.cv = 15;
240 tlli = 0;
241 offs = 0;
242 data[offs++] = (0 << 2) | (0 << 1) | (1 << 0);
243 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
244 chunks, ARRAY_SIZE(chunks), &tlli);
245 OSMO_ASSERT(num_chunks == 1);
246 OSMO_ASSERT(tlli == 0);
247 OSMO_ASSERT(chunks[0].offset == 1);
248 OSMO_ASSERT(chunks[0].length == 19);
249 OSMO_ASSERT(!chunks[0].is_complete);
250
251 rdbi.e = 0;
252 rdbi.ti = 0;
253 rdbi.cv = 15;
254 tlli = 0;
255 offs = 0;
256 data[offs++] = (1 << 2) | (1 << 1) | (1 << 0);
257 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
258 chunks, ARRAY_SIZE(chunks), &tlli);
259 OSMO_ASSERT(num_chunks == 2);
260 OSMO_ASSERT(tlli == 0);
261 OSMO_ASSERT(chunks[0].offset == 1);
262 OSMO_ASSERT(chunks[0].length == 1);
263 OSMO_ASSERT(chunks[0].is_complete);
264 OSMO_ASSERT(chunks[1].offset == 2);
265 OSMO_ASSERT(chunks[1].length == 18);
266 OSMO_ASSERT(!chunks[1].is_complete);
267
268 /* TS 44.060, B.3 */
269 cs = GprsCodingScheme::CS1;
270 rdbi.data_len = cs.maxDataBlockBytes();
271 rdbi.e = 0;
272 rdbi.ti = 0;
273 rdbi.cv = 15;
274 tlli = 0;
275 offs = 0;
276 data[offs++] = (7 << 2) | (1 << 1) | (0 << 0);
277 data[offs++] = (11 << 2) | (0 << 1) | (1 << 0);
278 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
279 chunks, ARRAY_SIZE(chunks), &tlli);
280 OSMO_ASSERT(num_chunks == 2);
281 OSMO_ASSERT(tlli == 0);
282 OSMO_ASSERT(chunks[0].offset == 2);
283 OSMO_ASSERT(chunks[0].length == 7);
284 OSMO_ASSERT(chunks[0].is_complete);
285 OSMO_ASSERT(chunks[1].offset == 9);
286 OSMO_ASSERT(chunks[1].length == 11);
287 OSMO_ASSERT(chunks[1].is_complete);
288
289 /* TS 44.060, B.4 */
290 cs = GprsCodingScheme::CS1;
291 rdbi.data_len = cs.maxDataBlockBytes();
292 rdbi.e = 1;
293 rdbi.ti = 0;
294 rdbi.cv = 15;
295 tlli = 0;
296 offs = 0;
297 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
298 chunks, ARRAY_SIZE(chunks), &tlli);
299 OSMO_ASSERT(num_chunks == 1);
300 OSMO_ASSERT(tlli == 0);
301 OSMO_ASSERT(chunks[0].offset == 0);
302 OSMO_ASSERT(chunks[0].length == 20);
303 OSMO_ASSERT(!chunks[0].is_complete);
304
305 /* TS 44.060, B.6 */
306 cs = GprsCodingScheme::CS1;
307 rdbi.data_len = cs.maxDataBlockBytes();
308 rdbi.e = 1;
309 rdbi.ti = 0;
310 rdbi.cv = 0;
311 tlli = 0;
312 offs = 0;
313 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
314 chunks, ARRAY_SIZE(chunks), &tlli);
315 OSMO_ASSERT(num_chunks == 1);
316 OSMO_ASSERT(tlli == 0);
317 OSMO_ASSERT(chunks[0].offset == 0);
318 OSMO_ASSERT(chunks[0].length == 20);
319 OSMO_ASSERT(chunks[0].is_complete);
320
321 /* TS 44.060, B.8.1 */
322 cs = GprsCodingScheme::MCS4;
323 rdbi.data_len = cs.maxDataBlockBytes();
324 rdbi.e = 0;
325 rdbi.ti = 0;
326 rdbi.cv = 15;
327 tlli = 0;
328 offs = 0;
329 data[offs++] = (11 << 1) | (0 << 0);
330 data[offs++] = (26 << 1) | (1 << 0);
331 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
332 chunks, ARRAY_SIZE(chunks), &tlli);
333 OSMO_ASSERT(num_chunks == 3);
334 OSMO_ASSERT(tlli == 0);
335 OSMO_ASSERT(chunks[0].offset == 2);
336 OSMO_ASSERT(chunks[0].length == 11);
337 OSMO_ASSERT(chunks[0].is_complete);
338 OSMO_ASSERT(chunks[1].offset == 13);
339 OSMO_ASSERT(chunks[1].length == 26);
340 OSMO_ASSERT(chunks[1].is_complete);
341 OSMO_ASSERT(chunks[2].offset == 39);
342 OSMO_ASSERT(chunks[2].length == 5);
343 OSMO_ASSERT(!chunks[2].is_complete);
344
345 /* TS 44.060, B.8.2 */
346
347 /* Note that the spec confuses the byte numbering here, since it
348 * includes the FBI/E header bits into the N2 octet count which
349 * is not consistent with Section 10.3a.1 & 10.3a.2. */
350
351 cs = GprsCodingScheme::MCS2;
352 rdbi.data_len = cs.maxDataBlockBytes();
353 rdbi.e = 0;
354 rdbi.ti = 0;
355 rdbi.cv = 15;
356 tlli = 0;
357 offs = 0;
358 data[offs++] = (15 << 1) | (1 << 0);
359 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
360 chunks, ARRAY_SIZE(chunks), &tlli);
361 OSMO_ASSERT(num_chunks == 2);
362 OSMO_ASSERT(tlli == 0);
363 OSMO_ASSERT(chunks[0].offset == 1);
364 OSMO_ASSERT(chunks[0].length == 15);
365 OSMO_ASSERT(chunks[0].is_complete);
366 OSMO_ASSERT(chunks[1].offset == 16);
367 OSMO_ASSERT(chunks[1].length == 12);
368 OSMO_ASSERT(!chunks[1].is_complete);
369
370 rdbi.e = 0;
371 rdbi.ti = 0;
372 rdbi.cv = 15;
373 tlli = 0;
374 offs = 0;
375 data[offs++] = ( 0 << 1) | (0 << 0);
376 data[offs++] = ( 7 << 1) | (0 << 0);
377 data[offs++] = (18 << 1) | (1 << 0); /* Differs from spec's N2-11 = 17 */
378 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
379 chunks, ARRAY_SIZE(chunks), &tlli);
380 OSMO_ASSERT(num_chunks == 3);
381 OSMO_ASSERT(tlli == 0);
382 OSMO_ASSERT(chunks[0].offset == 3);
383 OSMO_ASSERT(chunks[0].length == 0);
384 OSMO_ASSERT(chunks[0].is_complete);
385 OSMO_ASSERT(chunks[1].offset == 3);
386 OSMO_ASSERT(chunks[1].length == 7);
387 OSMO_ASSERT(chunks[1].is_complete);
388 OSMO_ASSERT(chunks[2].offset == 10);
389 OSMO_ASSERT(chunks[2].length == 18);
390 OSMO_ASSERT(chunks[2].is_complete);
391
392 rdbi.e = 0;
393 rdbi.ti = 0;
394 rdbi.cv = 0;
395 tlli = 0;
396 offs = 0;
397 data[offs++] = ( 6 << 1) | (0 << 0);
398 data[offs++] = (12 << 1) | (0 << 0);
399 data[offs++] = (127 << 1) | (1 << 0);
400 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
401 chunks, ARRAY_SIZE(chunks), &tlli);
402 OSMO_ASSERT(num_chunks == 2);
403 OSMO_ASSERT(tlli == 0);
404 OSMO_ASSERT(chunks[0].offset == 3);
405 OSMO_ASSERT(chunks[0].length == 6);
406 OSMO_ASSERT(chunks[0].is_complete);
407 OSMO_ASSERT(chunks[1].offset == 9);
408 OSMO_ASSERT(chunks[1].length == 12);
409 OSMO_ASSERT(chunks[1].is_complete);
410
411 /* TS 44.060, B.8.3 */
412
413 /* Note that the spec confuses the byte numbering here, too (see above) */
414
415 cs = GprsCodingScheme::MCS2;
416 rdbi.data_len = cs.maxDataBlockBytes();
417 rdbi.e = 1;
418 rdbi.ti = 0;
419 rdbi.cv = 0;
420 tlli = 0;
421 offs = 0;
422 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
423 chunks, ARRAY_SIZE(chunks), &tlli);
424 OSMO_ASSERT(num_chunks == 1);
425 OSMO_ASSERT(tlli == 0);
426 OSMO_ASSERT(chunks[0].offset == 0);
427 OSMO_ASSERT(chunks[0].length == 28);
428 OSMO_ASSERT(chunks[0].is_complete);
429
430 /* CS-1, TLLI, last block, single chunk until the end of the block */
431 cs = GprsCodingScheme::CS1;
432 rdbi.data_len = cs.maxDataBlockBytes();
433 rdbi.e = 1;
434 rdbi.ti = 1;
435 rdbi.cv = 0;
436 tlli = 0;
437 tlli2 = 0xffeeddcc;
438 offs = 0;
439 data[offs++] = tlli2 >> 24;
440 data[offs++] = tlli2 >> 16;
441 data[offs++] = tlli2 >> 8;
442 data[offs++] = tlli2 >> 0;
443 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
444 chunks, ARRAY_SIZE(chunks), &tlli);
445 OSMO_ASSERT(num_chunks == 1);
446 OSMO_ASSERT(tlli == tlli2);
447 OSMO_ASSERT(chunks[0].offset == 4);
448 OSMO_ASSERT(chunks[0].length == 16);
449 OSMO_ASSERT(chunks[0].is_complete);
450
451 /* Like TS 44.060, B.2, first RLC block but with TLLI */
452 cs = GprsCodingScheme::CS1;
453 rdbi.data_len = cs.maxDataBlockBytes();
454 rdbi.e = 0;
455 rdbi.ti = 1;
456 rdbi.cv = 15;
457 tlli = 0;
458 tlli2 = 0xffeeddbb;
459 offs = 0;
460 data[offs++] = (0 << 2) | (0 << 1) | (1 << 0);
461 data[offs++] = tlli2 >> 24;
462 data[offs++] = tlli2 >> 16;
463 data[offs++] = tlli2 >> 8;
464 data[offs++] = tlli2 >> 0;
465 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
466 chunks, ARRAY_SIZE(chunks), &tlli);
467 OSMO_ASSERT(num_chunks == 1);
468 OSMO_ASSERT(tlli == tlli2);
469 OSMO_ASSERT(chunks[0].offset == 5);
470 OSMO_ASSERT(chunks[0].length == 15);
471 OSMO_ASSERT(!chunks[0].is_complete);
472
473 /* Like TS 44.060, B.8.1 but with TLLI */
474 cs = GprsCodingScheme::MCS4;
475 rdbi.data_len = cs.maxDataBlockBytes();
476 rdbi.e = 0;
477 rdbi.ti = 1;
478 rdbi.cv = 15;
479 tlli = 0;
480 tlli2 = 0xffeeddaa;
481 offs = 0;
482 data[offs++] = (11 << 1) | (0 << 0);
483 data[offs++] = (26 << 1) | (1 << 0);
484 /* Little endian */
485 data[offs++] = tlli2 >> 0;
486 data[offs++] = tlli2 >> 8;
487 data[offs++] = tlli2 >> 16;
488 data[offs++] = tlli2 >> 24;
489 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
490 chunks, ARRAY_SIZE(chunks), &tlli);
491 OSMO_ASSERT(num_chunks == 3);
492 OSMO_ASSERT(tlli == tlli2);
493 OSMO_ASSERT(chunks[0].offset == 6);
494 OSMO_ASSERT(chunks[0].length == 11);
495 OSMO_ASSERT(chunks[0].is_complete);
496 OSMO_ASSERT(chunks[1].offset == 17);
497 OSMO_ASSERT(chunks[1].length == 26);
498 OSMO_ASSERT(chunks[1].is_complete);
499 OSMO_ASSERT(chunks[2].offset == 43);
500 OSMO_ASSERT(chunks[2].length == 1);
501 OSMO_ASSERT(!chunks[2].is_complete);
502
Aravind Sirsikar3463bd42016-09-15 17:19:54 +0530503 rdbi.e = 0;
504 rdbi.ti = 0;
505 rdbi.cv = 1;
506 tlli = 0;
507 offs = 0;
508 data[offs++] = 1;
509 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
510 chunks, ARRAY_SIZE(chunks), &tlli);
511
Aravind Sirsikar22a90192016-09-15 17:24:49 +0530512 OSMO_ASSERT(num_chunks == 2);
Aravind Sirsikar3463bd42016-09-15 17:19:54 +0530513 OSMO_ASSERT(chunks[0].offset == 1);
Aravind Sirsikar22a90192016-09-15 17:24:49 +0530514 OSMO_ASSERT(chunks[0].length == 0);
515 OSMO_ASSERT(chunks[0].is_complete);
516
517 OSMO_ASSERT(chunks[1].offset == 1);
518 OSMO_ASSERT(chunks[1].length == 43);
519 OSMO_ASSERT(!chunks[1].is_complete);
Aravind Sirsikar3463bd42016-09-15 17:19:54 +0530520
Jacob Erlbeck61679252015-12-11 18:25:21 +0100521 printf("=== end %s ===\n", __func__);
522}
523
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100524static void test_rlc_unit_encoder()
525{
526 struct gprs_rlc_data_block_info rdbi = {0};
527 GprsCodingScheme cs;
528 uint8_t data[74];
529 uint8_t llc_data[1500] = {0,};
530 int num_chunks = 0;
531 int write_offset;
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200532 int count_payload;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100533 struct gprs_llc llc;
534 Encoding::AppendResult ar;
535
536 printf("=== start %s ===\n", __func__);
537
538 llc.init();
539
540 /* TS 44.060, B.1 */
541 cs = GprsCodingScheme::CS4;
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530542 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100543 num_chunks = 0;
544 write_offset = 0;
545 memset(data, 0, sizeof(data));
546
547 llc.reset();
548 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200549 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100550
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100551 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200552 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100553
554 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
555 OSMO_ASSERT(rdbi.e == 0);
556 OSMO_ASSERT(write_offset == 1 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200557 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100558 OSMO_ASSERT(num_chunks == 1);
559
560 llc.reset();
561 llc.put_frame(llc_data, 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200562 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100563
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100564 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200565 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100566
567 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
568 OSMO_ASSERT(rdbi.e == 0);
569 OSMO_ASSERT(write_offset == 2 + 11 + 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200570 OSMO_ASSERT(count_payload == 26);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100571 OSMO_ASSERT(num_chunks == 2);
572
573 llc.reset();
574 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200575 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100576
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100577 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200578 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100579
580 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
581 OSMO_ASSERT(rdbi.e == 0);
582 OSMO_ASSERT(rdbi.cv != 0);
583 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200584 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100585 OSMO_ASSERT(num_chunks == 3);
586
587 OSMO_ASSERT(data[0] == ((11 << 2) | (1 << 1) | (0 << 0)));
588 OSMO_ASSERT(data[1] == ((26 << 2) | (1 << 1) | (1 << 0)));
589 OSMO_ASSERT(data[2] == 0);
590
591 /* TS 44.060, B.2 */
592 cs = GprsCodingScheme::CS1;
593
594 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530595 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100596 num_chunks = 0;
597 write_offset = 0;
598 memset(data, 0, sizeof(data));
599
600 llc.reset();
601 llc.put_frame(llc_data, 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200602 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100603
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100604 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200605 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100606
607 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
608 OSMO_ASSERT(rdbi.e == 0);
609 OSMO_ASSERT(write_offset == 1 + 19);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200610 OSMO_ASSERT(count_payload == 19);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100611 OSMO_ASSERT(num_chunks == 1);
612
613 OSMO_ASSERT(data[0] == ((0 << 2) | (0 << 1) | (1 << 0)));
614 OSMO_ASSERT(data[1] == 0);
615
616 /* Block 2 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530617 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100618 num_chunks = 0;
619 write_offset = 0;
620 memset(data, 0, sizeof(data));
621
622 OSMO_ASSERT(llc.chunk_size() == 1);
623
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200624 count_payload = -1;
625
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100626 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200627 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100628
629 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
630 OSMO_ASSERT(rdbi.e == 0);
631 OSMO_ASSERT(write_offset == 1 + 1);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200632 OSMO_ASSERT(count_payload == 1);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100633 OSMO_ASSERT(num_chunks == 1);
634
635 llc.reset();
636 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200637 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100638
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100639 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200640 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100641
642 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
643 OSMO_ASSERT(rdbi.e == 0);
644 OSMO_ASSERT(write_offset == 1 + 1 + 18);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200645 OSMO_ASSERT(count_payload == 18);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100646 OSMO_ASSERT(num_chunks == 2);
647
648 OSMO_ASSERT(data[0] == ((1 << 2) | (1 << 1) | (1 << 0)));
649 OSMO_ASSERT(data[1] == 0);
650
651 /* TS 44.060, B.3 */
652 cs = GprsCodingScheme::CS1;
653
654 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530655 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100656 num_chunks = 0;
657 write_offset = 0;
658 memset(data, 0, sizeof(data));
659
660 llc.reset();
661 llc.put_frame(llc_data, 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200662 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100663
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100664 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200665 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100666
667 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
668 OSMO_ASSERT(rdbi.e == 0);
669 OSMO_ASSERT(write_offset == 1 + 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200670 OSMO_ASSERT(count_payload == 7);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100671 OSMO_ASSERT(num_chunks == 1);
672
673 llc.reset();
674 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200675 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100676
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100677 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200678 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100679
680 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
681 OSMO_ASSERT(rdbi.e == 0);
682 OSMO_ASSERT(write_offset == 2 + 7 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200683 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100684 OSMO_ASSERT(num_chunks == 2);
685
686 OSMO_ASSERT(data[0] == ((7 << 2) | (1 << 1) | (0 << 0)));
687 OSMO_ASSERT(data[1] == ((11 << 2) | (0 << 1) | (1 << 0)));
688 OSMO_ASSERT(data[2] == 0);
689
690 /* TS 44.060, B.4 */
691 cs = GprsCodingScheme::CS1;
692
693 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530694 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100695 num_chunks = 0;
696 write_offset = 0;
697 memset(data, 0, sizeof(data));
698
699 llc.reset();
700 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200701 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100702
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100703 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200704 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100705
706 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
707 OSMO_ASSERT(rdbi.e == 1);
708 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200709 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100710 OSMO_ASSERT(num_chunks == 1);
711 OSMO_ASSERT(rdbi.cv != 0);
712
713 OSMO_ASSERT(data[0] == 0);
714
715 /* TS 44.060, B.5 */
716 cs = GprsCodingScheme::CS1;
717
718 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530719 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100720 num_chunks = 0;
721 write_offset = 0;
722 memset(data, 0, sizeof(data));
723
724 llc.reset();
725 llc.put_frame(llc_data, 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200726 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100727
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100728 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200729 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100730
731 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
732 OSMO_ASSERT(rdbi.e == 1);
733 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200734 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100735 OSMO_ASSERT(num_chunks == 1);
736 OSMO_ASSERT(rdbi.cv == 0);
737
738 OSMO_ASSERT(data[0] == 0);
739
740 /* TS 44.060, B.7 */
741 cs = GprsCodingScheme::CS1;
742
743 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530744 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100745 num_chunks = 0;
746 write_offset = 0;
747 memset(data, 0, sizeof(data));
748
749 llc.reset();
750 llc.put_frame(llc_data, 30);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200751 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100752
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100753 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200754 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100755
756 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
757 OSMO_ASSERT(rdbi.e == 1);
758 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200759 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100760 OSMO_ASSERT(num_chunks == 1);
761
762 OSMO_ASSERT(data[0] == 0);
763
764 /* Block 2 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530765 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100766 num_chunks = 0;
767 write_offset = 0;
768 memset(data, 0, sizeof(data));
769
770 OSMO_ASSERT(llc.chunk_size() == 10);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200771 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100772
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100773 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200774 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100775
776 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
777 OSMO_ASSERT(rdbi.e == 0);
778 OSMO_ASSERT(write_offset == 1 + 10);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200779 OSMO_ASSERT(count_payload == 10);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100780 OSMO_ASSERT(num_chunks == 1);
781
782 llc.reset();
783 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200784 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100785
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100786 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200787 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100788
789 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
790 OSMO_ASSERT(rdbi.e == 0);
791 OSMO_ASSERT(write_offset == 1 + 10 + 9);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200792 OSMO_ASSERT(count_payload == 9);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100793 OSMO_ASSERT(num_chunks == 2);
794
795 OSMO_ASSERT(data[0] == ((10 << 2) | (1 << 1) | (1 << 0)));
796 OSMO_ASSERT(data[1] == 0);
797
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100798 /* TS 44.060, B.8.1 */
799 cs = GprsCodingScheme::MCS4;
800
801 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530802 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100803 num_chunks = 0;
804 write_offset = 0;
805 memset(data, 0, sizeof(data));
806
807 llc.reset();
808 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200809 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100810
811 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200812 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100813
814 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
815 OSMO_ASSERT(rdbi.e == 0);
816 OSMO_ASSERT(write_offset == 1 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200817 OSMO_ASSERT(count_payload == 11);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100818 OSMO_ASSERT(num_chunks == 1);
819
820 llc.reset();
821 llc.put_frame(llc_data, 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200822 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100823
824 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200825 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100826
827 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
828 OSMO_ASSERT(rdbi.e == 0);
829 OSMO_ASSERT(write_offset == 2 + 11 + 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200830 OSMO_ASSERT(count_payload == 26);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100831 OSMO_ASSERT(num_chunks == 2);
832
833 llc.reset();
834 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200835 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100836
837 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200838 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100839
840 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
841 OSMO_ASSERT(rdbi.e == 0);
842 OSMO_ASSERT(rdbi.cv != 0);
843 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200844 OSMO_ASSERT(count_payload == 5);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100845 OSMO_ASSERT(num_chunks == 3);
846
847 OSMO_ASSERT(data[0] == ((11 << 1) | (0 << 0)));
848 OSMO_ASSERT(data[1] == ((26 << 1) | (1 << 0)));
849 OSMO_ASSERT(data[2] == 0);
850
851 /* TS 44.060, B.8.2 */
852
853 /* Note that the spec confuses the byte numbering here, since it
854 * includes the FBI/E header bits into the N2 octet count which
855 * is not consistent with Section 10.3a.1 & 10.3a.2. */
856
857 cs = GprsCodingScheme::MCS2;
858
859 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530860 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100861 num_chunks = 0;
862 write_offset = 0;
863 memset(data, 0, sizeof(data));
864
865 llc.reset();
866 llc.put_frame(llc_data, 15);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200867 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100868
869 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200870 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100871
872 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
873 OSMO_ASSERT(rdbi.e == 0);
874 OSMO_ASSERT(write_offset == 1 + 15);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200875 OSMO_ASSERT(count_payload == 15);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100876 OSMO_ASSERT(num_chunks == 1);
877
878 llc.reset();
879 llc.put_frame(llc_data, 12);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200880 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100881
882 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200883 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100884
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200885 /* no LI here, becaues there are exact 12 bytes left. Put LI into next frame */
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100886 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
887 OSMO_ASSERT(rdbi.e == 0);
888 OSMO_ASSERT(rdbi.cv != 0);
889 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200890 OSMO_ASSERT(count_payload == 12);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100891 OSMO_ASSERT(num_chunks == 2);
892
893 OSMO_ASSERT(data[0] == ((15 << 1) | (1 << 0)));
894 OSMO_ASSERT(data[1] == 0);
895
896 /* Block 2 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530897 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100898 num_chunks = 0;
899 write_offset = 0;
900 memset(data, 0, sizeof(data));
901
902 OSMO_ASSERT(llc.chunk_size() == 0);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200903 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100904
905 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200906 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100907
908 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
909 OSMO_ASSERT(rdbi.e == 0);
910 OSMO_ASSERT(write_offset == 1 + 0);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200911 OSMO_ASSERT(count_payload == 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100912 OSMO_ASSERT(num_chunks == 1);
913
914 llc.reset();
915 llc.put_frame(llc_data, 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200916 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100917
918 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200919 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100920
921 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
922 OSMO_ASSERT(rdbi.e == 0);
923 OSMO_ASSERT(rdbi.cv != 0);
924 OSMO_ASSERT(write_offset == 2 + 0 + 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200925 OSMO_ASSERT(count_payload == 7);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100926 OSMO_ASSERT(num_chunks == 2);
927
928 llc.reset();
929 llc.put_frame(llc_data, 18);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200930 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100931
932 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200933 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100934
935 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
936 OSMO_ASSERT(rdbi.e == 0);
937 OSMO_ASSERT(rdbi.cv != 0);
938 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200939 OSMO_ASSERT(count_payload == 18);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100940 OSMO_ASSERT(num_chunks == 3);
941
942 OSMO_ASSERT(data[0] == ((0 << 1) | (0 << 0)));
943 OSMO_ASSERT(data[1] == ((7 << 1) | (0 << 0)));
944 OSMO_ASSERT(data[2] == ((18 << 1) | (1 << 0)));
945 OSMO_ASSERT(data[3] == 0);
946
947 /* Block 3 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530948 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100949 num_chunks = 0;
950 write_offset = 0;
951 memset(data, 0, sizeof(data));
952
953 llc.reset();
954 llc.put_frame(llc_data, 6);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200955 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100956
957 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200958 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100959
960 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
961 OSMO_ASSERT(rdbi.e == 0);
962 OSMO_ASSERT(write_offset == 1 + 6);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200963 OSMO_ASSERT(count_payload == 6);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100964 OSMO_ASSERT(num_chunks == 1);
965
966 llc.reset();
967 llc.put_frame(llc_data, 12);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200968 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100969
970 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200971 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100972
973 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
974 OSMO_ASSERT(rdbi.e == 0);
975 OSMO_ASSERT(rdbi.cv == 0);
976 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200977 OSMO_ASSERT(count_payload == 12);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100978 OSMO_ASSERT(num_chunks == 3);
979
980 OSMO_ASSERT(data[0] == ((6 << 1) | (0 << 0)));
981 OSMO_ASSERT(data[1] == ((12 << 1) | (0 << 0)));
982 OSMO_ASSERT(data[2] == ((127 << 1) | (1 << 0)));
983 OSMO_ASSERT(data[3] == 0);
984
985 /* TS 44.060, B.8.3 */
986
987 /* Note that the spec confuses the byte numbering here, too (see above) */
988
989 cs = GprsCodingScheme::MCS2;
990
991 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530992 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100993 num_chunks = 0;
994 write_offset = 0;
995 memset(data, 0, sizeof(data));
996
997 llc.reset();
998 llc.put_frame(llc_data, rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200999 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001000
1001 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001002 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001003
1004 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
1005 OSMO_ASSERT(rdbi.e == 1);
1006 OSMO_ASSERT(rdbi.cv == 0);
1007 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Neels Hofmeyrd34646a2017-02-08 17:07:40 +01001008 OSMO_ASSERT(rdbi.data_len <= INT_MAX && count_payload == (int)rdbi.data_len);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001009 OSMO_ASSERT(num_chunks == 1);
1010
1011 OSMO_ASSERT(data[0] == 0);
1012
1013 /* Final block with an LLC of size data_len-1 */
1014
1015 cs = GprsCodingScheme::MCS2;
1016
1017 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301018 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001019 num_chunks = 0;
1020 write_offset = 0;
1021 memset(data, 0, sizeof(data));
1022
1023 llc.reset();
1024 llc.put_frame(llc_data, rdbi.data_len - 1);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001025 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001026
1027 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001028 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001029
1030 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
1031 OSMO_ASSERT(rdbi.e == 0);
1032 OSMO_ASSERT(rdbi.cv == 0);
1033 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Neels Hofmeyrd34646a2017-02-08 17:07:40 +01001034 OSMO_ASSERT((rdbi.data_len - 1) <= INT_MAX
1035 && count_payload == (int)(rdbi.data_len - 1));
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001036 OSMO_ASSERT(num_chunks == 1);
1037
1038 OSMO_ASSERT(data[0] == (((rdbi.data_len-1) << 1) | (1 << 0)));
1039 OSMO_ASSERT(data[1] == 0);
1040
1041 /* Final block with an LLC of size data_len-2 */
1042
1043 cs = GprsCodingScheme::MCS2;
1044
1045 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301046 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001047 num_chunks = 0;
1048 write_offset = 0;
1049 memset(data, 0, sizeof(data));
1050
1051 llc.reset();
1052 llc.put_frame(llc_data, rdbi.data_len - 2);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001053 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001054
1055 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001056 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001057
1058 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
1059 OSMO_ASSERT(rdbi.e == 0);
1060 OSMO_ASSERT(rdbi.cv == 0);
1061 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Neels Hofmeyrd34646a2017-02-08 17:07:40 +01001062 OSMO_ASSERT((rdbi.data_len - 2) <= INT_MAX
1063 && count_payload == (int)(rdbi.data_len - 2));
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001064 OSMO_ASSERT(num_chunks == 2);
1065
1066 OSMO_ASSERT(data[0] == (((rdbi.data_len-2) << 1) | (0 << 0)));
1067 OSMO_ASSERT(data[1] == ((127 << 1) | (1 << 0)));
1068 OSMO_ASSERT(data[2] == 0);
1069
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001070 printf("=== end %s ===\n", __func__);
1071}
1072
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001073static void test_rlc_unaligned_copy()
1074{
1075 uint8_t bits[256];
1076 uint8_t saved_block[256];
1077 uint8_t test_block[256];
1078 uint8_t out_block[256];
1079 GprsCodingScheme::Scheme scheme;
1080 int pattern;
1081 volatile unsigned int block_idx, i;
1082
1083 for (scheme = GprsCodingScheme::CS1;
1084 scheme < GprsCodingScheme::NUM_SCHEMES;
1085 scheme = GprsCodingScheme::Scheme(scheme + 1))
1086 {
1087 GprsCodingScheme cs(scheme);
1088
1089 for (pattern = 0; pattern <= 0xff; pattern += 0xff) {
1090 /* prepare test block */
1091 test_block[0] = pattern ^ 0xff;
1092 for (i = 1; i + 1 < cs.maxDataBlockBytes(); i++)
1093 test_block[i] = i;
1094 test_block[cs.maxDataBlockBytes()-1] = pattern ^ 0xff;
1095
1096 for (block_idx = 0;
1097 block_idx < cs.numDataBlocks();
1098 block_idx++)
1099 {
1100 struct gprs_rlc_data_info rlc;
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301101 gprs_rlc_data_info_init_dl(&rlc, cs, false, 0);
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001102
1103 memset(bits, pattern, sizeof(bits));
1104 Decoding::rlc_copy_to_aligned_buffer(
1105 &rlc, block_idx, bits, saved_block);
1106
1107 fprintf(stderr,
1108 "Test data block: %s\n",
1109 osmo_hexdump(test_block, cs.maxDataBlockBytes()));
1110
1111 Encoding::rlc_copy_from_aligned_buffer(
1112 &rlc, block_idx, bits, test_block);
1113
1114 fprintf(stderr,
1115 "Encoded message block, %s, idx %d, "
1116 "pattern %02x: %s\n",
1117 rlc.cs.name(), block_idx, pattern,
1118 osmo_hexdump(bits, cs.sizeDL()));
1119
1120 Decoding::rlc_copy_to_aligned_buffer(
1121 &rlc, block_idx, bits, out_block);
1122
1123 fprintf(stderr,
1124 "Out data block: %s\n",
1125 osmo_hexdump(out_block, cs.maxDataBlockBytes()));
1126 /* restore original bits */
1127 Encoding::rlc_copy_from_aligned_buffer(
1128 &rlc, block_idx, bits, saved_block);
1129
1130 OSMO_ASSERT(memcmp(test_block, out_block,
1131 rlc.cs.maxDataBlockBytes()) == 0);
1132
1133 for (i = 0; i < sizeof(bits); i++)
1134 OSMO_ASSERT(bits[i] == pattern);
1135 }
1136 }
1137 }
1138}
1139
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001140static void test_rlc_info_init()
1141{
1142 struct gprs_rlc_data_info rlc;
1143
1144 printf("=== start %s ===\n", __func__);
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301145 gprs_rlc_data_info_init_dl(&rlc,
1146 GprsCodingScheme(GprsCodingScheme::CS1), false, 0);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001147 OSMO_ASSERT(rlc.num_data_blocks == 1);
1148 OSMO_ASSERT(rlc.data_offs_bits[0] == 24);
1149 OSMO_ASSERT(rlc.block_info[0].data_len == 20);
1150
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301151 gprs_rlc_data_info_init_dl(&rlc,
1152 GprsCodingScheme(GprsCodingScheme::MCS1), false, 0);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001153 OSMO_ASSERT(rlc.num_data_blocks == 1);
1154 OSMO_ASSERT(rlc.data_offs_bits[0] == 33);
1155 OSMO_ASSERT(rlc.block_info[0].data_len == 22);
1156
1157 printf("=== end %s ===\n", __func__);
1158}
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001159
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301160static void setup_bts(BTS *the_bts, uint8_t ts_no, uint8_t cs = 1)
1161{
1162 gprs_rlcmac_bts *bts;
1163 gprs_rlcmac_trx *trx;
1164
1165 bts = the_bts->bts_data();
1166 bts->egprs_enabled = true;
1167 bts->alloc_algorithm = alloc_algorithm_a;
1168 bts->initial_cs_dl = cs;
1169 bts->initial_cs_ul = cs;
1170 trx = &bts->trx[0];
1171 trx->pdch[ts_no].enable();
1172}
1173static void uplink_header_type_2_parsing_test(BTS *the_bts,
1174 uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
1175 uint8_t ms_class)
1176{
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301177 struct pcu_l1_meas meas;
1178 int tfi = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301179 uint8_t data[79] = {0};
1180 struct gprs_rlc_ul_header_egprs_2 *egprs2 = NULL;
1181
1182 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301183
1184 tfi = 1;
1185
1186 struct gprs_rlc_data_info rlc;
1187 GprsCodingScheme cs;
1188 int rc, offs;
1189
1190 /*without padding*/
1191 cs = GprsCodingScheme::MCS5;
1192 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
1193 egprs2->r = 1;
1194 egprs2->si = 1;
1195 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001196 egprs2->tfi_hi = tfi & 0x03;
1197 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1198 egprs2->bsn1_hi = 0;
1199 egprs2->bsn1_lo = 0;
1200 egprs2->cps_hi = 3;
1201 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301202 egprs2->rsb = 0;
1203 egprs2->pi = 0;
1204 data[4] = 0x20; /* Setting E field */
1205 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001206 OSMO_ASSERT(rc == 487);
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301207 offs = rlc.data_offs_bits[0] / 8;
1208 OSMO_ASSERT(offs == 4);
1209 OSMO_ASSERT(rlc.tfi == 1);
1210 OSMO_ASSERT(rlc.num_data_blocks == 1);
1211 OSMO_ASSERT(rlc.block_info[0].e == 1);
1212 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1213 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1214
1215 /* with padding case */
1216 cs = GprsCodingScheme::MCS6;
1217 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
1218 egprs2->r = 1;
1219 egprs2->si = 1;
1220 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001221 egprs2->tfi_hi = tfi & 0x03;
1222 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1223 egprs2->bsn1_hi = 0;
1224 egprs2->bsn1_lo = 0;
1225 egprs2->cps_hi = 3;
1226 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301227 egprs2->rsb = 0;
1228 egprs2->pi = 0;
1229 data[10] = 0x20; /* Setting E field */
1230 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001231 OSMO_ASSERT(rc == 679);
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301232 offs = rlc.data_offs_bits[0] / 8;
1233 OSMO_ASSERT(offs == 10);
1234 OSMO_ASSERT(rlc.num_data_blocks == 1);
1235 OSMO_ASSERT(rlc.tfi == 1);
1236 OSMO_ASSERT(rlc.block_info[0].e == 1);
1237 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1238 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1239
1240 egprs2->r = 1;
1241 egprs2->si = 1;
1242 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001243 egprs2->tfi_hi = tfi & 0x03;
1244 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1245 egprs2->bsn1_hi = 1;
1246 egprs2->bsn1_lo = 0;
1247 egprs2->cps_hi = 2;
1248 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301249 egprs2->rsb = 0;
1250 egprs2->pi = 0;
1251 data[10] = 0x20; /* Setting E field */
1252 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001253 OSMO_ASSERT(rc == 679);
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301254 offs = rlc.data_offs_bits[0] / 8;
1255 OSMO_ASSERT(offs == 10);
1256 OSMO_ASSERT(rlc.tfi == 1);
1257 OSMO_ASSERT(rlc.num_data_blocks == 1);
1258 OSMO_ASSERT(rlc.block_info[0].e == 1);
1259 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1260 OSMO_ASSERT(rlc.block_info[0].bsn == 1);
1261}
1262
1263static void uplink_header_type2_test(void)
1264{
1265 BTS the_bts;
1266 int ts_no = 7;
1267 uint32_t fn = 2654218;
1268 uint16_t qta = 31;
1269 uint32_t tlli = 0xf1223344;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301270 uint8_t ms_class = 1;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301271
1272 printf("=== start %s ===\n", __func__);
1273 setup_bts(&the_bts, ts_no, 10);
1274
1275 uplink_header_type_2_parsing_test(&the_bts, ts_no,
1276 tlli, &fn, qta, ms_class);
1277 printf("=== end %s ===\n", __func__);
1278}
1279
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301280static void uplink_header_type_1_parsing_test(BTS *the_bts,
1281 uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
1282 uint8_t ms_class)
1283{
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301284 int tfi = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301285 uint8_t data[155] = {0};
1286 struct gprs_rlc_ul_header_egprs_1 *egprs1 = NULL;
1287 struct gprs_rlc_data_info rlc;
1288 GprsCodingScheme cs;
Neels Hofmeyrd34646a2017-02-08 17:07:40 +01001289 int rc;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301290
1291 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301292
1293 tfi = 1;
1294
1295 /* MCS 7 */
1296 cs = GprsCodingScheme::MCS7;
1297 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1298 egprs1->si = 1;
1299 egprs1->r = 1;
1300 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001301 egprs1->tfi_hi = tfi & 0x03;
1302 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1303 egprs1->bsn1_hi = 0;
1304 egprs1->bsn1_lo = 0;
1305 egprs1->bsn2_hi = 1;
1306 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301307 egprs1->cps = 15;
1308 egprs1->rsb = 0;
1309 egprs1->pi = 0;
1310 data[5] = 0xc0;
1311 data[5 + 57] = 1;
1312 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001313 OSMO_ASSERT(rc == 946);
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301314 OSMO_ASSERT(rlc.num_data_blocks == 2);
1315 OSMO_ASSERT(rlc.block_info[0].e == 1);
1316 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1317 OSMO_ASSERT(rlc.block_info[1].e == 1);
1318 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1319 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1320 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1321 OSMO_ASSERT(rlc.tfi == 1);
1322
1323 /* MCS 8 */
1324 cs = GprsCodingScheme::MCS8;
1325 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1326 egprs1->si = 1;
1327 egprs1->r = 1;
1328 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001329 egprs1->tfi_hi = tfi & 0x03;
1330 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1331 egprs1->bsn1_hi = 0;
1332 egprs1->bsn1_lo = 0;
1333 egprs1->bsn2_hi = 1;
1334 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301335 egprs1->cps = 15;
1336 egprs1->rsb = 0;
1337 egprs1->pi = 0;
1338 data[5] = 0xc0;
1339 data[5 + 69] = 1;
1340 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001341 OSMO_ASSERT(rc == 1138);
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301342 OSMO_ASSERT(rlc.num_data_blocks == 2);
1343 OSMO_ASSERT(rlc.block_info[0].e == 1);
1344 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1345 OSMO_ASSERT(rlc.block_info[1].e == 1);
1346 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1347 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1348 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1349 OSMO_ASSERT(rlc.tfi == 1);
1350
1351 /* MCS 9 */
1352 cs = GprsCodingScheme::MCS9;
1353 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1354 egprs1->si = 1;
1355 egprs1->r = 1;
1356 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001357 egprs1->tfi_hi = tfi & 0x03;
1358 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1359 egprs1->bsn1_hi = 0;
1360 egprs1->bsn1_lo = 0;
1361 egprs1->bsn2_hi = 1;
1362 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301363 egprs1->cps = 15;
1364 egprs1->rsb = 0;
1365 egprs1->pi = 0;
1366 data[5] = 0xc0;
1367 data[5 + 75] = 1;
1368 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001369 OSMO_ASSERT(rc == 1234);
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301370 OSMO_ASSERT(rlc.num_data_blocks == 2);
1371 OSMO_ASSERT(rlc.block_info[0].e == 1);
1372 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1373 OSMO_ASSERT(rlc.block_info[1].e == 1);
1374 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1375 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1376 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1377 OSMO_ASSERT(rlc.tfi == 1);
1378}
1379
1380void uplink_header_type1_test(void)
1381{
1382 BTS the_bts;
1383 int ts_no = 7;
1384 uint32_t fn = 2654218;
1385 uint16_t qta = 31;
1386 uint32_t tlli = 0xf1223344;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301387 uint8_t ms_class = 1;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301388
1389 printf("=== start %s ===\n", __func__);
1390 setup_bts(&the_bts, ts_no, 12);
1391 uplink_header_type_1_parsing_test(&the_bts, ts_no, tlli, &fn,
1392 qta, ms_class);
1393 printf("=== end %s ===\n", __func__);
1394}
1395
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001396int main(int argc, char **argv)
1397{
1398 struct vty_app_info pcu_vty_info = {0};
1399
1400 tall_pcu_ctx = talloc_named_const(NULL, 1, "EdgeTest context");
1401 if (!tall_pcu_ctx)
1402 abort();
1403
Neels Hofmeyr78ce5912017-02-08 17:07:31 +01001404 msgb_talloc_ctx_init(tall_pcu_ctx, 0);
Neels Hofmeyr42f2d612018-04-01 16:54:40 +02001405 osmo_init_logging2(tall_pcu_ctx, &gprs_log_info);
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001406 log_set_use_color(osmo_stderr_target, 0);
1407 log_set_print_filename(osmo_stderr_target, 0);
1408
1409 vty_init(&pcu_vty_info);
Harald Welteac0490a2017-10-29 10:39:32 +01001410 pcu_vty_init(&gprs_log_info);
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001411
1412 test_coding_scheme();
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001413 test_rlc_info_init();
Jacob Erlbeck38f18692016-02-01 10:08:00 +01001414 test_rlc_unit_decoder();
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001415 test_rlc_unaligned_copy();
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001416 test_rlc_unit_encoder();
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001417
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301418 uplink_header_type2_test();
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301419 uplink_header_type1_test();
1420
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001421 if (getenv("TALLOC_REPORT_FULL"))
1422 talloc_report_full(tall_pcu_ctx, stderr);
1423 return EXIT_SUCCESS;
1424}
1425
1426/*
1427 * stubs that should not be reached
1428 */
1429extern "C" {
1430void l1if_pdch_req() { abort(); }
1431void l1if_connect_pdch() { abort(); }
1432void l1if_close_pdch() { abort(); }
1433void l1if_open_pdch() { abort(); }
1434}