blob: 73aed3779de06d279b566b235b241635079b00d2 [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"
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010030extern "C" {
31#include "pcu_vty.h"
32
33#include <osmocom/core/application.h>
34#include <osmocom/core/msgb.h>
35#include <osmocom/core/talloc.h>
36#include <osmocom/core/utils.h>
37#include <osmocom/vty/vty.h>
Tom Tsoudf698092016-07-11 17:05:19 -070038#include <osmocom/gprs/protocol/gsm_04_60.h>
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010039}
40
41#include <errno.h>
Jacob Erlbeckf0e40392016-01-08 10:07:53 +010042#include <string.h>
Neels Hofmeyrd34646a2017-02-08 17:07:40 +010043#include <limits.h>
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010044
45void *tall_pcu_ctx;
46int16_t spoof_mnc = 0, spoof_mcc = 0;
47
48static void check_coding_scheme(GprsCodingScheme& cs, GprsCodingScheme::Mode mode)
49{
50 volatile unsigned expected_size;
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010051 bool need_padding;
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010052 GprsCodingScheme new_cs;
53
54 OSMO_ASSERT(cs.isValid());
55 OSMO_ASSERT(cs.isCompatible(mode));
56
57 /* Check static getBySizeUL() */
Jacob Erlbeckfc1b3e62016-01-11 09:58:11 +010058 expected_size = cs.usedSizeUL();
59 if (cs.spareBitsUL() > 0 && cs.isGprs())
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010060 expected_size += 1;
61 OSMO_ASSERT(expected_size == cs.sizeUL());
62 OSMO_ASSERT(cs == GprsCodingScheme::getBySizeUL(expected_size));
63
64 /* Check static sizeUL() */
Jacob Erlbeckfc1b3e62016-01-11 09:58:11 +010065 expected_size = cs.usedSizeDL();
66 if (cs.spareBitsDL() > 0 && cs.isGprs())
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010067 expected_size += 1;
68 OSMO_ASSERT(expected_size == cs.sizeDL());
69
Jacob Erlbeck392a5452015-12-14 10:38:29 +010070 /* Check data block sizes */
71 OSMO_ASSERT(cs.maxDataBlockBytes() * cs.numDataBlocks() < cs.maxBytesDL());
72 OSMO_ASSERT(cs.maxDataBlockBytes() * cs.numDataBlocks() < cs.maxBytesUL());
73
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010074 /* Check inc/dec */
75 new_cs = cs;
76 new_cs.inc(mode);
77 OSMO_ASSERT(new_cs.isCompatible(mode));
78 if (new_cs != cs) {
79 new_cs.dec(mode);
80 OSMO_ASSERT(new_cs.isCompatible(mode));
81 OSMO_ASSERT(new_cs == cs);
82 }
83 new_cs.dec(mode);
84 OSMO_ASSERT(new_cs.isCompatible(mode));
85 if (new_cs != cs) {
86 new_cs.inc(mode);
87 OSMO_ASSERT(new_cs.isCompatible(mode));
88 OSMO_ASSERT(new_cs == cs);
89 }
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010090
91 new_cs = cs;
92 new_cs.decToSingleBlock(&need_padding);
93 OSMO_ASSERT(new_cs.isFamilyCompatible(cs));
94 OSMO_ASSERT(cs.isFamilyCompatible(new_cs));
95 OSMO_ASSERT(cs.isCompatible(new_cs));
96 if (need_padding) {
Jacob Erlbeck215e18c2016-02-03 18:22:34 +010097 OSMO_ASSERT(new_cs.maxDataBlockBytes() ==
98 new_cs.optionalPaddingBits()/8 + cs.maxDataBlockBytes());
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010099 } else {
100 OSMO_ASSERT(new_cs.maxDataBlockBytes() == cs.maxDataBlockBytes());
101 }
102
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100103}
104
105static void test_coding_scheme()
106{
107 unsigned i;
108 unsigned last_size_UL;
109 unsigned last_size_DL;
110 GprsCodingScheme::Scheme gprs_schemes[] = {
111 GprsCodingScheme::CS1,
112 GprsCodingScheme::CS2,
113 GprsCodingScheme::CS3,
114 GprsCodingScheme::CS4
115 };
116 struct {
117 GprsCodingScheme::Scheme s;
118 bool is_gmsk;
119 } egprs_schemes[] = {
120 {GprsCodingScheme::MCS1, true},
121 {GprsCodingScheme::MCS2, true},
122 {GprsCodingScheme::MCS3, true},
123 {GprsCodingScheme::MCS4, true},
124 {GprsCodingScheme::MCS5, false},
125 {GprsCodingScheme::MCS6, false},
126 {GprsCodingScheme::MCS7, false},
127 {GprsCodingScheme::MCS8, false},
128 {GprsCodingScheme::MCS9, false},
129 };
130
131 printf("=== start %s ===\n", __func__);
132
133 GprsCodingScheme cs;
134 OSMO_ASSERT(!cs);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100135 OSMO_ASSERT(GprsCodingScheme::Scheme(cs) == GprsCodingScheme::UNKNOWN);
136 OSMO_ASSERT(cs == GprsCodingScheme(GprsCodingScheme::UNKNOWN));
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100137 OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::GPRS));
138 OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::EGPRS_GMSK));
139 OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::EGPRS));
140
141 last_size_UL = 0;
142 last_size_DL = 0;
143
144 for (i = 0; i < ARRAY_SIZE(gprs_schemes); i++) {
145 GprsCodingScheme current_cs(gprs_schemes[i]);
146 OSMO_ASSERT(current_cs.isGprs());
147 OSMO_ASSERT(!current_cs.isEgprs());
148 OSMO_ASSERT(!current_cs.isEgprsGmsk());
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100149 OSMO_ASSERT(GprsCodingScheme::Scheme(current_cs) == gprs_schemes[i]);
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100150 OSMO_ASSERT(current_cs == GprsCodingScheme(gprs_schemes[i]));
151
152 /* Check strong monotonicity */
153 OSMO_ASSERT(current_cs.maxBytesUL() > last_size_UL);
154 OSMO_ASSERT(current_cs.maxBytesDL() > last_size_DL);
155 last_size_UL = current_cs.maxBytesUL();
156 last_size_DL = current_cs.maxBytesDL();
157
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +0100158 /* Check header types */
159 OSMO_ASSERT(current_cs.headerTypeData() ==
160 GprsCodingScheme::HEADER_GPRS_DATA);
161 OSMO_ASSERT(current_cs.headerTypeControl() ==
162 GprsCodingScheme::HEADER_GPRS_CONTROL);
163
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100164 check_coding_scheme(current_cs, GprsCodingScheme::GPRS);
165 }
166 OSMO_ASSERT(i == 4);
167
168 last_size_UL = 0;
169 last_size_DL = 0;
170
171 for (i = 0; i < ARRAY_SIZE(egprs_schemes); i++) {
172 GprsCodingScheme current_cs(egprs_schemes[i].s);
173 OSMO_ASSERT(!current_cs.isGprs());
174 OSMO_ASSERT(current_cs.isEgprs());
175 OSMO_ASSERT(!!current_cs.isEgprsGmsk() == !!egprs_schemes[i].is_gmsk);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100176 OSMO_ASSERT(GprsCodingScheme::Scheme(current_cs) == egprs_schemes[i].s);
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100177 OSMO_ASSERT(current_cs == GprsCodingScheme(egprs_schemes[i].s));
178
179 /* Check strong monotonicity */
180 OSMO_ASSERT(current_cs.maxBytesUL() > last_size_UL);
181 OSMO_ASSERT(current_cs.maxBytesDL() > last_size_DL);
182 last_size_UL = current_cs.maxBytesUL();
183 last_size_DL = current_cs.maxBytesDL();
184
185 if (egprs_schemes[i].is_gmsk)
186 check_coding_scheme(current_cs, GprsCodingScheme::EGPRS_GMSK);
187 check_coding_scheme(current_cs, GprsCodingScheme::EGPRS);
188 }
189 OSMO_ASSERT(i == 9);
190
191 printf("=== end %s ===\n", __func__);
192}
193
Jacob Erlbeck38f18692016-02-01 10:08:00 +0100194static void test_rlc_unit_decoder()
Jacob Erlbeck61679252015-12-11 18:25:21 +0100195{
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100196 struct gprs_rlc_data_block_info rdbi = {0};
Jacob Erlbeck61679252015-12-11 18:25:21 +0100197 GprsCodingScheme cs;
198 uint8_t data[74];
199 Decoding::RlcData chunks[16];
200 volatile int num_chunks = 0;
201 uint32_t tlli, tlli2;
202 unsigned int offs;
203
204
205 printf("=== start %s ===\n", __func__);
206
207 /* TS 44.060, B.1 */
208 cs = GprsCodingScheme::CS4;
209 rdbi.data_len = cs.maxDataBlockBytes();
210 rdbi.e = 0;
211 rdbi.ti = 0;
212 rdbi.cv = 15;
213 tlli = 0;
214 offs = 0;
215 data[offs++] = (11 << 2) | (1 << 1) | (0 << 0);
216 data[offs++] = (26 << 2) | (1 << 1) | (1 << 0);
217 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
218 chunks, ARRAY_SIZE(chunks), &tlli);
219 OSMO_ASSERT(num_chunks == 3);
220 OSMO_ASSERT(tlli == 0);
221 OSMO_ASSERT(chunks[0].offset == 2);
222 OSMO_ASSERT(chunks[0].length == 11);
223 OSMO_ASSERT(chunks[0].is_complete);
224 OSMO_ASSERT(chunks[1].offset == 13);
225 OSMO_ASSERT(chunks[1].length == 26);
226 OSMO_ASSERT(chunks[1].is_complete);
227 OSMO_ASSERT(chunks[2].offset == 39);
228 OSMO_ASSERT(chunks[2].length == cs.maxDataBlockBytes() - 39);
229 OSMO_ASSERT(!chunks[2].is_complete);
230
231 /* TS 44.060, B.2 */
232 cs = GprsCodingScheme::CS1;
233 rdbi.data_len = cs.maxDataBlockBytes();
234 rdbi.e = 0;
235 rdbi.ti = 0;
236 rdbi.cv = 15;
237 tlli = 0;
238 offs = 0;
239 data[offs++] = (0 << 2) | (0 << 1) | (1 << 0);
240 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
241 chunks, ARRAY_SIZE(chunks), &tlli);
242 OSMO_ASSERT(num_chunks == 1);
243 OSMO_ASSERT(tlli == 0);
244 OSMO_ASSERT(chunks[0].offset == 1);
245 OSMO_ASSERT(chunks[0].length == 19);
246 OSMO_ASSERT(!chunks[0].is_complete);
247
248 rdbi.e = 0;
249 rdbi.ti = 0;
250 rdbi.cv = 15;
251 tlli = 0;
252 offs = 0;
253 data[offs++] = (1 << 2) | (1 << 1) | (1 << 0);
254 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
255 chunks, ARRAY_SIZE(chunks), &tlli);
256 OSMO_ASSERT(num_chunks == 2);
257 OSMO_ASSERT(tlli == 0);
258 OSMO_ASSERT(chunks[0].offset == 1);
259 OSMO_ASSERT(chunks[0].length == 1);
260 OSMO_ASSERT(chunks[0].is_complete);
261 OSMO_ASSERT(chunks[1].offset == 2);
262 OSMO_ASSERT(chunks[1].length == 18);
263 OSMO_ASSERT(!chunks[1].is_complete);
264
265 /* TS 44.060, B.3 */
266 cs = GprsCodingScheme::CS1;
267 rdbi.data_len = cs.maxDataBlockBytes();
268 rdbi.e = 0;
269 rdbi.ti = 0;
270 rdbi.cv = 15;
271 tlli = 0;
272 offs = 0;
273 data[offs++] = (7 << 2) | (1 << 1) | (0 << 0);
274 data[offs++] = (11 << 2) | (0 << 1) | (1 << 0);
275 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
276 chunks, ARRAY_SIZE(chunks), &tlli);
277 OSMO_ASSERT(num_chunks == 2);
278 OSMO_ASSERT(tlli == 0);
279 OSMO_ASSERT(chunks[0].offset == 2);
280 OSMO_ASSERT(chunks[0].length == 7);
281 OSMO_ASSERT(chunks[0].is_complete);
282 OSMO_ASSERT(chunks[1].offset == 9);
283 OSMO_ASSERT(chunks[1].length == 11);
284 OSMO_ASSERT(chunks[1].is_complete);
285
286 /* TS 44.060, B.4 */
287 cs = GprsCodingScheme::CS1;
288 rdbi.data_len = cs.maxDataBlockBytes();
289 rdbi.e = 1;
290 rdbi.ti = 0;
291 rdbi.cv = 15;
292 tlli = 0;
293 offs = 0;
294 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
295 chunks, ARRAY_SIZE(chunks), &tlli);
296 OSMO_ASSERT(num_chunks == 1);
297 OSMO_ASSERT(tlli == 0);
298 OSMO_ASSERT(chunks[0].offset == 0);
299 OSMO_ASSERT(chunks[0].length == 20);
300 OSMO_ASSERT(!chunks[0].is_complete);
301
302 /* TS 44.060, B.6 */
303 cs = GprsCodingScheme::CS1;
304 rdbi.data_len = cs.maxDataBlockBytes();
305 rdbi.e = 1;
306 rdbi.ti = 0;
307 rdbi.cv = 0;
308 tlli = 0;
309 offs = 0;
310 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
311 chunks, ARRAY_SIZE(chunks), &tlli);
312 OSMO_ASSERT(num_chunks == 1);
313 OSMO_ASSERT(tlli == 0);
314 OSMO_ASSERT(chunks[0].offset == 0);
315 OSMO_ASSERT(chunks[0].length == 20);
316 OSMO_ASSERT(chunks[0].is_complete);
317
318 /* TS 44.060, B.8.1 */
319 cs = GprsCodingScheme::MCS4;
320 rdbi.data_len = cs.maxDataBlockBytes();
321 rdbi.e = 0;
322 rdbi.ti = 0;
323 rdbi.cv = 15;
324 tlli = 0;
325 offs = 0;
326 data[offs++] = (11 << 1) | (0 << 0);
327 data[offs++] = (26 << 1) | (1 << 0);
328 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
329 chunks, ARRAY_SIZE(chunks), &tlli);
330 OSMO_ASSERT(num_chunks == 3);
331 OSMO_ASSERT(tlli == 0);
332 OSMO_ASSERT(chunks[0].offset == 2);
333 OSMO_ASSERT(chunks[0].length == 11);
334 OSMO_ASSERT(chunks[0].is_complete);
335 OSMO_ASSERT(chunks[1].offset == 13);
336 OSMO_ASSERT(chunks[1].length == 26);
337 OSMO_ASSERT(chunks[1].is_complete);
338 OSMO_ASSERT(chunks[2].offset == 39);
339 OSMO_ASSERT(chunks[2].length == 5);
340 OSMO_ASSERT(!chunks[2].is_complete);
341
342 /* TS 44.060, B.8.2 */
343
344 /* Note that the spec confuses the byte numbering here, since it
345 * includes the FBI/E header bits into the N2 octet count which
346 * is not consistent with Section 10.3a.1 & 10.3a.2. */
347
348 cs = GprsCodingScheme::MCS2;
349 rdbi.data_len = cs.maxDataBlockBytes();
350 rdbi.e = 0;
351 rdbi.ti = 0;
352 rdbi.cv = 15;
353 tlli = 0;
354 offs = 0;
355 data[offs++] = (15 << 1) | (1 << 0);
356 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
357 chunks, ARRAY_SIZE(chunks), &tlli);
358 OSMO_ASSERT(num_chunks == 2);
359 OSMO_ASSERT(tlli == 0);
360 OSMO_ASSERT(chunks[0].offset == 1);
361 OSMO_ASSERT(chunks[0].length == 15);
362 OSMO_ASSERT(chunks[0].is_complete);
363 OSMO_ASSERT(chunks[1].offset == 16);
364 OSMO_ASSERT(chunks[1].length == 12);
365 OSMO_ASSERT(!chunks[1].is_complete);
366
367 rdbi.e = 0;
368 rdbi.ti = 0;
369 rdbi.cv = 15;
370 tlli = 0;
371 offs = 0;
372 data[offs++] = ( 0 << 1) | (0 << 0);
373 data[offs++] = ( 7 << 1) | (0 << 0);
374 data[offs++] = (18 << 1) | (1 << 0); /* Differs from spec's N2-11 = 17 */
375 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
376 chunks, ARRAY_SIZE(chunks), &tlli);
377 OSMO_ASSERT(num_chunks == 3);
378 OSMO_ASSERT(tlli == 0);
379 OSMO_ASSERT(chunks[0].offset == 3);
380 OSMO_ASSERT(chunks[0].length == 0);
381 OSMO_ASSERT(chunks[0].is_complete);
382 OSMO_ASSERT(chunks[1].offset == 3);
383 OSMO_ASSERT(chunks[1].length == 7);
384 OSMO_ASSERT(chunks[1].is_complete);
385 OSMO_ASSERT(chunks[2].offset == 10);
386 OSMO_ASSERT(chunks[2].length == 18);
387 OSMO_ASSERT(chunks[2].is_complete);
388
389 rdbi.e = 0;
390 rdbi.ti = 0;
391 rdbi.cv = 0;
392 tlli = 0;
393 offs = 0;
394 data[offs++] = ( 6 << 1) | (0 << 0);
395 data[offs++] = (12 << 1) | (0 << 0);
396 data[offs++] = (127 << 1) | (1 << 0);
397 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
398 chunks, ARRAY_SIZE(chunks), &tlli);
399 OSMO_ASSERT(num_chunks == 2);
400 OSMO_ASSERT(tlli == 0);
401 OSMO_ASSERT(chunks[0].offset == 3);
402 OSMO_ASSERT(chunks[0].length == 6);
403 OSMO_ASSERT(chunks[0].is_complete);
404 OSMO_ASSERT(chunks[1].offset == 9);
405 OSMO_ASSERT(chunks[1].length == 12);
406 OSMO_ASSERT(chunks[1].is_complete);
407
408 /* TS 44.060, B.8.3 */
409
410 /* Note that the spec confuses the byte numbering here, too (see above) */
411
412 cs = GprsCodingScheme::MCS2;
413 rdbi.data_len = cs.maxDataBlockBytes();
414 rdbi.e = 1;
415 rdbi.ti = 0;
416 rdbi.cv = 0;
417 tlli = 0;
418 offs = 0;
419 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
420 chunks, ARRAY_SIZE(chunks), &tlli);
421 OSMO_ASSERT(num_chunks == 1);
422 OSMO_ASSERT(tlli == 0);
423 OSMO_ASSERT(chunks[0].offset == 0);
424 OSMO_ASSERT(chunks[0].length == 28);
425 OSMO_ASSERT(chunks[0].is_complete);
426
427 /* CS-1, TLLI, last block, single chunk until the end of the block */
428 cs = GprsCodingScheme::CS1;
429 rdbi.data_len = cs.maxDataBlockBytes();
430 rdbi.e = 1;
431 rdbi.ti = 1;
432 rdbi.cv = 0;
433 tlli = 0;
434 tlli2 = 0xffeeddcc;
435 offs = 0;
436 data[offs++] = tlli2 >> 24;
437 data[offs++] = tlli2 >> 16;
438 data[offs++] = tlli2 >> 8;
439 data[offs++] = tlli2 >> 0;
440 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
441 chunks, ARRAY_SIZE(chunks), &tlli);
442 OSMO_ASSERT(num_chunks == 1);
443 OSMO_ASSERT(tlli == tlli2);
444 OSMO_ASSERT(chunks[0].offset == 4);
445 OSMO_ASSERT(chunks[0].length == 16);
446 OSMO_ASSERT(chunks[0].is_complete);
447
448 /* Like TS 44.060, B.2, first RLC block but with TLLI */
449 cs = GprsCodingScheme::CS1;
450 rdbi.data_len = cs.maxDataBlockBytes();
451 rdbi.e = 0;
452 rdbi.ti = 1;
453 rdbi.cv = 15;
454 tlli = 0;
455 tlli2 = 0xffeeddbb;
456 offs = 0;
457 data[offs++] = (0 << 2) | (0 << 1) | (1 << 0);
458 data[offs++] = tlli2 >> 24;
459 data[offs++] = tlli2 >> 16;
460 data[offs++] = tlli2 >> 8;
461 data[offs++] = tlli2 >> 0;
462 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
463 chunks, ARRAY_SIZE(chunks), &tlli);
464 OSMO_ASSERT(num_chunks == 1);
465 OSMO_ASSERT(tlli == tlli2);
466 OSMO_ASSERT(chunks[0].offset == 5);
467 OSMO_ASSERT(chunks[0].length == 15);
468 OSMO_ASSERT(!chunks[0].is_complete);
469
470 /* Like TS 44.060, B.8.1 but with TLLI */
471 cs = GprsCodingScheme::MCS4;
472 rdbi.data_len = cs.maxDataBlockBytes();
473 rdbi.e = 0;
474 rdbi.ti = 1;
475 rdbi.cv = 15;
476 tlli = 0;
477 tlli2 = 0xffeeddaa;
478 offs = 0;
479 data[offs++] = (11 << 1) | (0 << 0);
480 data[offs++] = (26 << 1) | (1 << 0);
481 /* Little endian */
482 data[offs++] = tlli2 >> 0;
483 data[offs++] = tlli2 >> 8;
484 data[offs++] = tlli2 >> 16;
485 data[offs++] = tlli2 >> 24;
486 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
487 chunks, ARRAY_SIZE(chunks), &tlli);
488 OSMO_ASSERT(num_chunks == 3);
489 OSMO_ASSERT(tlli == tlli2);
490 OSMO_ASSERT(chunks[0].offset == 6);
491 OSMO_ASSERT(chunks[0].length == 11);
492 OSMO_ASSERT(chunks[0].is_complete);
493 OSMO_ASSERT(chunks[1].offset == 17);
494 OSMO_ASSERT(chunks[1].length == 26);
495 OSMO_ASSERT(chunks[1].is_complete);
496 OSMO_ASSERT(chunks[2].offset == 43);
497 OSMO_ASSERT(chunks[2].length == 1);
498 OSMO_ASSERT(!chunks[2].is_complete);
499
Aravind Sirsikar3463bd42016-09-15 17:19:54 +0530500 rdbi.e = 0;
501 rdbi.ti = 0;
502 rdbi.cv = 1;
503 tlli = 0;
504 offs = 0;
505 data[offs++] = 1;
506 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
507 chunks, ARRAY_SIZE(chunks), &tlli);
508
Aravind Sirsikar22a90192016-09-15 17:24:49 +0530509 OSMO_ASSERT(num_chunks == 2);
Aravind Sirsikar3463bd42016-09-15 17:19:54 +0530510 OSMO_ASSERT(chunks[0].offset == 1);
Aravind Sirsikar22a90192016-09-15 17:24:49 +0530511 OSMO_ASSERT(chunks[0].length == 0);
512 OSMO_ASSERT(chunks[0].is_complete);
513
514 OSMO_ASSERT(chunks[1].offset == 1);
515 OSMO_ASSERT(chunks[1].length == 43);
516 OSMO_ASSERT(!chunks[1].is_complete);
Aravind Sirsikar3463bd42016-09-15 17:19:54 +0530517
Jacob Erlbeck61679252015-12-11 18:25:21 +0100518 printf("=== end %s ===\n", __func__);
519}
520
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100521static void test_rlc_unit_encoder()
522{
523 struct gprs_rlc_data_block_info rdbi = {0};
524 GprsCodingScheme cs;
525 uint8_t data[74];
526 uint8_t llc_data[1500] = {0,};
527 int num_chunks = 0;
528 int write_offset;
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200529 int count_payload;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100530 struct gprs_llc llc;
531 Encoding::AppendResult ar;
532
533 printf("=== start %s ===\n", __func__);
534
535 llc.init();
536
537 /* TS 44.060, B.1 */
538 cs = GprsCodingScheme::CS4;
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530539 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100540 num_chunks = 0;
541 write_offset = 0;
542 memset(data, 0, sizeof(data));
543
544 llc.reset();
545 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200546 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100547
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100548 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200549 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100550
551 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
552 OSMO_ASSERT(rdbi.e == 0);
553 OSMO_ASSERT(write_offset == 1 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200554 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100555 OSMO_ASSERT(num_chunks == 1);
556
557 llc.reset();
558 llc.put_frame(llc_data, 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200559 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100560
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100561 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200562 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100563
564 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
565 OSMO_ASSERT(rdbi.e == 0);
566 OSMO_ASSERT(write_offset == 2 + 11 + 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200567 OSMO_ASSERT(count_payload == 26);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100568 OSMO_ASSERT(num_chunks == 2);
569
570 llc.reset();
571 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200572 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100573
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100574 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200575 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100576
577 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
578 OSMO_ASSERT(rdbi.e == 0);
579 OSMO_ASSERT(rdbi.cv != 0);
580 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200581 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100582 OSMO_ASSERT(num_chunks == 3);
583
584 OSMO_ASSERT(data[0] == ((11 << 2) | (1 << 1) | (0 << 0)));
585 OSMO_ASSERT(data[1] == ((26 << 2) | (1 << 1) | (1 << 0)));
586 OSMO_ASSERT(data[2] == 0);
587
588 /* TS 44.060, B.2 */
589 cs = GprsCodingScheme::CS1;
590
591 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530592 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100593 num_chunks = 0;
594 write_offset = 0;
595 memset(data, 0, sizeof(data));
596
597 llc.reset();
598 llc.put_frame(llc_data, 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200599 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100600
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100601 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200602 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100603
604 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
605 OSMO_ASSERT(rdbi.e == 0);
606 OSMO_ASSERT(write_offset == 1 + 19);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200607 OSMO_ASSERT(count_payload == 19);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100608 OSMO_ASSERT(num_chunks == 1);
609
610 OSMO_ASSERT(data[0] == ((0 << 2) | (0 << 1) | (1 << 0)));
611 OSMO_ASSERT(data[1] == 0);
612
613 /* Block 2 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530614 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100615 num_chunks = 0;
616 write_offset = 0;
617 memset(data, 0, sizeof(data));
618
619 OSMO_ASSERT(llc.chunk_size() == 1);
620
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200621 count_payload = -1;
622
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100623 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200624 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100625
626 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
627 OSMO_ASSERT(rdbi.e == 0);
628 OSMO_ASSERT(write_offset == 1 + 1);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200629 OSMO_ASSERT(count_payload == 1);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100630 OSMO_ASSERT(num_chunks == 1);
631
632 llc.reset();
633 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200634 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100635
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100636 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200637 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100638
639 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
640 OSMO_ASSERT(rdbi.e == 0);
641 OSMO_ASSERT(write_offset == 1 + 1 + 18);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200642 OSMO_ASSERT(count_payload == 18);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100643 OSMO_ASSERT(num_chunks == 2);
644
645 OSMO_ASSERT(data[0] == ((1 << 2) | (1 << 1) | (1 << 0)));
646 OSMO_ASSERT(data[1] == 0);
647
648 /* TS 44.060, B.3 */
649 cs = GprsCodingScheme::CS1;
650
651 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530652 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100653 num_chunks = 0;
654 write_offset = 0;
655 memset(data, 0, sizeof(data));
656
657 llc.reset();
658 llc.put_frame(llc_data, 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200659 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100660
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100661 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200662 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100663
664 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
665 OSMO_ASSERT(rdbi.e == 0);
666 OSMO_ASSERT(write_offset == 1 + 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200667 OSMO_ASSERT(count_payload == 7);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100668 OSMO_ASSERT(num_chunks == 1);
669
670 llc.reset();
671 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200672 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100673
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100674 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200675 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100676
677 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
678 OSMO_ASSERT(rdbi.e == 0);
679 OSMO_ASSERT(write_offset == 2 + 7 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200680 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100681 OSMO_ASSERT(num_chunks == 2);
682
683 OSMO_ASSERT(data[0] == ((7 << 2) | (1 << 1) | (0 << 0)));
684 OSMO_ASSERT(data[1] == ((11 << 2) | (0 << 1) | (1 << 0)));
685 OSMO_ASSERT(data[2] == 0);
686
687 /* TS 44.060, B.4 */
688 cs = GprsCodingScheme::CS1;
689
690 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530691 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100692 num_chunks = 0;
693 write_offset = 0;
694 memset(data, 0, sizeof(data));
695
696 llc.reset();
697 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200698 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100699
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100700 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200701 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100702
703 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
704 OSMO_ASSERT(rdbi.e == 1);
705 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200706 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100707 OSMO_ASSERT(num_chunks == 1);
708 OSMO_ASSERT(rdbi.cv != 0);
709
710 OSMO_ASSERT(data[0] == 0);
711
712 /* TS 44.060, B.5 */
713 cs = GprsCodingScheme::CS1;
714
715 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530716 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100717 num_chunks = 0;
718 write_offset = 0;
719 memset(data, 0, sizeof(data));
720
721 llc.reset();
722 llc.put_frame(llc_data, 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200723 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100724
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100725 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200726 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100727
728 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
729 OSMO_ASSERT(rdbi.e == 1);
730 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200731 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100732 OSMO_ASSERT(num_chunks == 1);
733 OSMO_ASSERT(rdbi.cv == 0);
734
735 OSMO_ASSERT(data[0] == 0);
736
737 /* TS 44.060, B.7 */
738 cs = GprsCodingScheme::CS1;
739
740 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530741 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100742 num_chunks = 0;
743 write_offset = 0;
744 memset(data, 0, sizeof(data));
745
746 llc.reset();
747 llc.put_frame(llc_data, 30);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200748 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100749
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100750 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200751 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100752
753 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
754 OSMO_ASSERT(rdbi.e == 1);
755 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200756 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100757 OSMO_ASSERT(num_chunks == 1);
758
759 OSMO_ASSERT(data[0] == 0);
760
761 /* Block 2 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530762 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100763 num_chunks = 0;
764 write_offset = 0;
765 memset(data, 0, sizeof(data));
766
767 OSMO_ASSERT(llc.chunk_size() == 10);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200768 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100769
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100770 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200771 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100772
773 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
774 OSMO_ASSERT(rdbi.e == 0);
775 OSMO_ASSERT(write_offset == 1 + 10);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200776 OSMO_ASSERT(count_payload == 10);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100777 OSMO_ASSERT(num_chunks == 1);
778
779 llc.reset();
780 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200781 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100782
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100783 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200784 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100785
786 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
787 OSMO_ASSERT(rdbi.e == 0);
788 OSMO_ASSERT(write_offset == 1 + 10 + 9);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200789 OSMO_ASSERT(count_payload == 9);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100790 OSMO_ASSERT(num_chunks == 2);
791
792 OSMO_ASSERT(data[0] == ((10 << 2) | (1 << 1) | (1 << 0)));
793 OSMO_ASSERT(data[1] == 0);
794
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100795 /* TS 44.060, B.8.1 */
796 cs = GprsCodingScheme::MCS4;
797
798 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530799 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100800 num_chunks = 0;
801 write_offset = 0;
802 memset(data, 0, sizeof(data));
803
804 llc.reset();
805 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200806 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100807
808 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200809 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100810
811 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
812 OSMO_ASSERT(rdbi.e == 0);
813 OSMO_ASSERT(write_offset == 1 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200814 OSMO_ASSERT(count_payload == 11);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100815 OSMO_ASSERT(num_chunks == 1);
816
817 llc.reset();
818 llc.put_frame(llc_data, 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200819 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100820
821 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200822 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100823
824 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
825 OSMO_ASSERT(rdbi.e == 0);
826 OSMO_ASSERT(write_offset == 2 + 11 + 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200827 OSMO_ASSERT(count_payload == 26);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100828 OSMO_ASSERT(num_chunks == 2);
829
830 llc.reset();
831 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200832 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100833
834 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200835 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100836
837 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
838 OSMO_ASSERT(rdbi.e == 0);
839 OSMO_ASSERT(rdbi.cv != 0);
840 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200841 OSMO_ASSERT(count_payload == 5);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100842 OSMO_ASSERT(num_chunks == 3);
843
844 OSMO_ASSERT(data[0] == ((11 << 1) | (0 << 0)));
845 OSMO_ASSERT(data[1] == ((26 << 1) | (1 << 0)));
846 OSMO_ASSERT(data[2] == 0);
847
848 /* TS 44.060, B.8.2 */
849
850 /* Note that the spec confuses the byte numbering here, since it
851 * includes the FBI/E header bits into the N2 octet count which
852 * is not consistent with Section 10.3a.1 & 10.3a.2. */
853
854 cs = GprsCodingScheme::MCS2;
855
856 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530857 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100858 num_chunks = 0;
859 write_offset = 0;
860 memset(data, 0, sizeof(data));
861
862 llc.reset();
863 llc.put_frame(llc_data, 15);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200864 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100865
866 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200867 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100868
869 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
870 OSMO_ASSERT(rdbi.e == 0);
871 OSMO_ASSERT(write_offset == 1 + 15);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200872 OSMO_ASSERT(count_payload == 15);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100873 OSMO_ASSERT(num_chunks == 1);
874
875 llc.reset();
876 llc.put_frame(llc_data, 12);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200877 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100878
879 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200880 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100881
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200882 /* no LI here, becaues there are exact 12 bytes left. Put LI into next frame */
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100883 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
884 OSMO_ASSERT(rdbi.e == 0);
885 OSMO_ASSERT(rdbi.cv != 0);
886 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200887 OSMO_ASSERT(count_payload == 12);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100888 OSMO_ASSERT(num_chunks == 2);
889
890 OSMO_ASSERT(data[0] == ((15 << 1) | (1 << 0)));
891 OSMO_ASSERT(data[1] == 0);
892
893 /* Block 2 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530894 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100895 num_chunks = 0;
896 write_offset = 0;
897 memset(data, 0, sizeof(data));
898
899 OSMO_ASSERT(llc.chunk_size() == 0);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200900 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100901
902 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200903 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100904
905 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
906 OSMO_ASSERT(rdbi.e == 0);
907 OSMO_ASSERT(write_offset == 1 + 0);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200908 OSMO_ASSERT(count_payload == 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100909 OSMO_ASSERT(num_chunks == 1);
910
911 llc.reset();
912 llc.put_frame(llc_data, 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200913 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100914
915 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200916 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100917
918 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
919 OSMO_ASSERT(rdbi.e == 0);
920 OSMO_ASSERT(rdbi.cv != 0);
921 OSMO_ASSERT(write_offset == 2 + 0 + 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200922 OSMO_ASSERT(count_payload == 7);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100923 OSMO_ASSERT(num_chunks == 2);
924
925 llc.reset();
926 llc.put_frame(llc_data, 18);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200927 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100928
929 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200930 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100931
932 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
933 OSMO_ASSERT(rdbi.e == 0);
934 OSMO_ASSERT(rdbi.cv != 0);
935 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200936 OSMO_ASSERT(count_payload == 18);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100937 OSMO_ASSERT(num_chunks == 3);
938
939 OSMO_ASSERT(data[0] == ((0 << 1) | (0 << 0)));
940 OSMO_ASSERT(data[1] == ((7 << 1) | (0 << 0)));
941 OSMO_ASSERT(data[2] == ((18 << 1) | (1 << 0)));
942 OSMO_ASSERT(data[3] == 0);
943
944 /* Block 3 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530945 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100946 num_chunks = 0;
947 write_offset = 0;
948 memset(data, 0, sizeof(data));
949
950 llc.reset();
951 llc.put_frame(llc_data, 6);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200952 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100953
954 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200955 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100956
957 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
958 OSMO_ASSERT(rdbi.e == 0);
959 OSMO_ASSERT(write_offset == 1 + 6);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200960 OSMO_ASSERT(count_payload == 6);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100961 OSMO_ASSERT(num_chunks == 1);
962
963 llc.reset();
964 llc.put_frame(llc_data, 12);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200965 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100966
967 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200968 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100969
970 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
971 OSMO_ASSERT(rdbi.e == 0);
972 OSMO_ASSERT(rdbi.cv == 0);
973 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200974 OSMO_ASSERT(count_payload == 12);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100975 OSMO_ASSERT(num_chunks == 3);
976
977 OSMO_ASSERT(data[0] == ((6 << 1) | (0 << 0)));
978 OSMO_ASSERT(data[1] == ((12 << 1) | (0 << 0)));
979 OSMO_ASSERT(data[2] == ((127 << 1) | (1 << 0)));
980 OSMO_ASSERT(data[3] == 0);
981
982 /* TS 44.060, B.8.3 */
983
984 /* Note that the spec confuses the byte numbering here, too (see above) */
985
986 cs = GprsCodingScheme::MCS2;
987
988 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530989 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100990 num_chunks = 0;
991 write_offset = 0;
992 memset(data, 0, sizeof(data));
993
994 llc.reset();
995 llc.put_frame(llc_data, rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200996 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100997
998 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200999 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001000
1001 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
1002 OSMO_ASSERT(rdbi.e == 1);
1003 OSMO_ASSERT(rdbi.cv == 0);
1004 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Neels Hofmeyrd34646a2017-02-08 17:07:40 +01001005 OSMO_ASSERT(rdbi.data_len <= INT_MAX && count_payload == (int)rdbi.data_len);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001006 OSMO_ASSERT(num_chunks == 1);
1007
1008 OSMO_ASSERT(data[0] == 0);
1009
1010 /* Final block with an LLC of size data_len-1 */
1011
1012 cs = GprsCodingScheme::MCS2;
1013
1014 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301015 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001016 num_chunks = 0;
1017 write_offset = 0;
1018 memset(data, 0, sizeof(data));
1019
1020 llc.reset();
1021 llc.put_frame(llc_data, rdbi.data_len - 1);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001022 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001023
1024 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001025 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001026
1027 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
1028 OSMO_ASSERT(rdbi.e == 0);
1029 OSMO_ASSERT(rdbi.cv == 0);
1030 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Neels Hofmeyrd34646a2017-02-08 17:07:40 +01001031 OSMO_ASSERT((rdbi.data_len - 1) <= INT_MAX
1032 && count_payload == (int)(rdbi.data_len - 1));
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001033 OSMO_ASSERT(num_chunks == 1);
1034
1035 OSMO_ASSERT(data[0] == (((rdbi.data_len-1) << 1) | (1 << 0)));
1036 OSMO_ASSERT(data[1] == 0);
1037
1038 /* Final block with an LLC of size data_len-2 */
1039
1040 cs = GprsCodingScheme::MCS2;
1041
1042 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301043 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001044 num_chunks = 0;
1045 write_offset = 0;
1046 memset(data, 0, sizeof(data));
1047
1048 llc.reset();
1049 llc.put_frame(llc_data, rdbi.data_len - 2);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001050 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001051
1052 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001053 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001054
1055 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
1056 OSMO_ASSERT(rdbi.e == 0);
1057 OSMO_ASSERT(rdbi.cv == 0);
1058 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Neels Hofmeyrd34646a2017-02-08 17:07:40 +01001059 OSMO_ASSERT((rdbi.data_len - 2) <= INT_MAX
1060 && count_payload == (int)(rdbi.data_len - 2));
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001061 OSMO_ASSERT(num_chunks == 2);
1062
1063 OSMO_ASSERT(data[0] == (((rdbi.data_len-2) << 1) | (0 << 0)));
1064 OSMO_ASSERT(data[1] == ((127 << 1) | (1 << 0)));
1065 OSMO_ASSERT(data[2] == 0);
1066
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001067 printf("=== end %s ===\n", __func__);
1068}
1069
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001070static void test_rlc_unaligned_copy()
1071{
1072 uint8_t bits[256];
1073 uint8_t saved_block[256];
1074 uint8_t test_block[256];
1075 uint8_t out_block[256];
1076 GprsCodingScheme::Scheme scheme;
1077 int pattern;
1078 volatile unsigned int block_idx, i;
1079
1080 for (scheme = GprsCodingScheme::CS1;
1081 scheme < GprsCodingScheme::NUM_SCHEMES;
1082 scheme = GprsCodingScheme::Scheme(scheme + 1))
1083 {
1084 GprsCodingScheme cs(scheme);
1085
1086 for (pattern = 0; pattern <= 0xff; pattern += 0xff) {
1087 /* prepare test block */
1088 test_block[0] = pattern ^ 0xff;
1089 for (i = 1; i + 1 < cs.maxDataBlockBytes(); i++)
1090 test_block[i] = i;
1091 test_block[cs.maxDataBlockBytes()-1] = pattern ^ 0xff;
1092
1093 for (block_idx = 0;
1094 block_idx < cs.numDataBlocks();
1095 block_idx++)
1096 {
1097 struct gprs_rlc_data_info rlc;
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301098 gprs_rlc_data_info_init_dl(&rlc, cs, false, 0);
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001099
1100 memset(bits, pattern, sizeof(bits));
1101 Decoding::rlc_copy_to_aligned_buffer(
1102 &rlc, block_idx, bits, saved_block);
1103
1104 fprintf(stderr,
1105 "Test data block: %s\n",
1106 osmo_hexdump(test_block, cs.maxDataBlockBytes()));
1107
1108 Encoding::rlc_copy_from_aligned_buffer(
1109 &rlc, block_idx, bits, test_block);
1110
1111 fprintf(stderr,
1112 "Encoded message block, %s, idx %d, "
1113 "pattern %02x: %s\n",
1114 rlc.cs.name(), block_idx, pattern,
1115 osmo_hexdump(bits, cs.sizeDL()));
1116
1117 Decoding::rlc_copy_to_aligned_buffer(
1118 &rlc, block_idx, bits, out_block);
1119
1120 fprintf(stderr,
1121 "Out data block: %s\n",
1122 osmo_hexdump(out_block, cs.maxDataBlockBytes()));
1123 /* restore original bits */
1124 Encoding::rlc_copy_from_aligned_buffer(
1125 &rlc, block_idx, bits, saved_block);
1126
1127 OSMO_ASSERT(memcmp(test_block, out_block,
1128 rlc.cs.maxDataBlockBytes()) == 0);
1129
1130 for (i = 0; i < sizeof(bits); i++)
1131 OSMO_ASSERT(bits[i] == pattern);
1132 }
1133 }
1134 }
1135}
1136
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001137static void test_rlc_info_init()
1138{
1139 struct gprs_rlc_data_info rlc;
1140
1141 printf("=== start %s ===\n", __func__);
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301142 gprs_rlc_data_info_init_dl(&rlc,
1143 GprsCodingScheme(GprsCodingScheme::CS1), false, 0);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001144 OSMO_ASSERT(rlc.num_data_blocks == 1);
1145 OSMO_ASSERT(rlc.data_offs_bits[0] == 24);
1146 OSMO_ASSERT(rlc.block_info[0].data_len == 20);
1147
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301148 gprs_rlc_data_info_init_dl(&rlc,
1149 GprsCodingScheme(GprsCodingScheme::MCS1), false, 0);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001150 OSMO_ASSERT(rlc.num_data_blocks == 1);
1151 OSMO_ASSERT(rlc.data_offs_bits[0] == 33);
1152 OSMO_ASSERT(rlc.block_info[0].data_len == 22);
1153
1154 printf("=== end %s ===\n", __func__);
1155}
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001156
1157static const struct log_info_cat default_categories[] = {
1158 {"DCSN1", "\033[1;31m", "Concrete Syntax Notation One (CSN1)", LOGL_INFO, 0},
1159 {"DL1IF", "\033[1;32m", "GPRS PCU L1 interface (L1IF)", LOGL_DEBUG, 1},
1160 {"DRLCMAC", "\033[0;33m", "GPRS RLC/MAC layer (RLCMAC)", LOGL_DEBUG, 1},
1161 {"DRLCMACDATA", "\033[0;33m", "GPRS RLC/MAC layer Data (RLCMAC)", LOGL_DEBUG, 1},
1162 {"DRLCMACDL", "\033[1;33m", "GPRS RLC/MAC layer Downlink (RLCMAC)", LOGL_DEBUG, 1},
1163 {"DRLCMACUL", "\033[1;36m", "GPRS RLC/MAC layer Uplink (RLCMAC)", LOGL_DEBUG, 1},
1164 {"DRLCMACSCHED", "\033[0;36m", "GPRS RLC/MAC layer Scheduling (RLCMAC)", LOGL_DEBUG, 1},
1165 {"DRLCMACMEAS", "\033[1;31m", "GPRS RLC/MAC layer Measurements (RLCMAC)", LOGL_INFO, 1},
1166 {"DNS","\033[1;34m", "GPRS Network Service Protocol (NS)", LOGL_INFO , 1},
1167 {"DBSSGP","\033[1;34m", "GPRS BSS Gateway Protocol (BSSGP)", LOGL_INFO , 1},
1168 {"DPCU", "\033[1;35m", "GPRS Packet Control Unit (PCU)", LOGL_NOTICE, 1},
1169};
1170
1171static int filter_fn(const struct log_context *ctx,
1172 struct log_target *tar)
1173{
1174 return 1;
1175}
1176
1177const struct log_info debug_log_info = {
1178 filter_fn,
1179 (struct log_info_cat*)default_categories,
1180 ARRAY_SIZE(default_categories),
1181};
1182
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301183static void setup_bts(BTS *the_bts, uint8_t ts_no, uint8_t cs = 1)
1184{
1185 gprs_rlcmac_bts *bts;
1186 gprs_rlcmac_trx *trx;
1187
1188 bts = the_bts->bts_data();
1189 bts->egprs_enabled = true;
1190 bts->alloc_algorithm = alloc_algorithm_a;
1191 bts->initial_cs_dl = cs;
1192 bts->initial_cs_ul = cs;
1193 trx = &bts->trx[0];
1194 trx->pdch[ts_no].enable();
1195}
1196static void uplink_header_type_2_parsing_test(BTS *the_bts,
1197 uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
1198 uint8_t ms_class)
1199{
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301200 struct pcu_l1_meas meas;
1201 int tfi = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301202 uint8_t data[79] = {0};
1203 struct gprs_rlc_ul_header_egprs_2 *egprs2 = NULL;
1204
1205 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301206
1207 tfi = 1;
1208
1209 struct gprs_rlc_data_info rlc;
1210 GprsCodingScheme cs;
1211 int rc, offs;
1212
1213 /*without padding*/
1214 cs = GprsCodingScheme::MCS5;
1215 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
1216 egprs2->r = 1;
1217 egprs2->si = 1;
1218 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001219 egprs2->tfi_hi = tfi & 0x03;
1220 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1221 egprs2->bsn1_hi = 0;
1222 egprs2->bsn1_lo = 0;
1223 egprs2->cps_hi = 3;
1224 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301225 egprs2->rsb = 0;
1226 egprs2->pi = 0;
1227 data[4] = 0x20; /* Setting E field */
1228 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001229 OSMO_ASSERT(rc == 487);
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301230 offs = rlc.data_offs_bits[0] / 8;
1231 OSMO_ASSERT(offs == 4);
1232 OSMO_ASSERT(rlc.tfi == 1);
1233 OSMO_ASSERT(rlc.num_data_blocks == 1);
1234 OSMO_ASSERT(rlc.block_info[0].e == 1);
1235 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1236 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1237
1238 /* with padding case */
1239 cs = GprsCodingScheme::MCS6;
1240 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
1241 egprs2->r = 1;
1242 egprs2->si = 1;
1243 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001244 egprs2->tfi_hi = tfi & 0x03;
1245 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1246 egprs2->bsn1_hi = 0;
1247 egprs2->bsn1_lo = 0;
1248 egprs2->cps_hi = 3;
1249 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301250 egprs2->rsb = 0;
1251 egprs2->pi = 0;
1252 data[10] = 0x20; /* Setting E field */
1253 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001254 OSMO_ASSERT(rc == 679);
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301255 offs = rlc.data_offs_bits[0] / 8;
1256 OSMO_ASSERT(offs == 10);
1257 OSMO_ASSERT(rlc.num_data_blocks == 1);
1258 OSMO_ASSERT(rlc.tfi == 1);
1259 OSMO_ASSERT(rlc.block_info[0].e == 1);
1260 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1261 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1262
1263 egprs2->r = 1;
1264 egprs2->si = 1;
1265 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001266 egprs2->tfi_hi = tfi & 0x03;
1267 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1268 egprs2->bsn1_hi = 1;
1269 egprs2->bsn1_lo = 0;
1270 egprs2->cps_hi = 2;
1271 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301272 egprs2->rsb = 0;
1273 egprs2->pi = 0;
1274 data[10] = 0x20; /* Setting E field */
1275 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001276 OSMO_ASSERT(rc == 679);
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301277 offs = rlc.data_offs_bits[0] / 8;
1278 OSMO_ASSERT(offs == 10);
1279 OSMO_ASSERT(rlc.tfi == 1);
1280 OSMO_ASSERT(rlc.num_data_blocks == 1);
1281 OSMO_ASSERT(rlc.block_info[0].e == 1);
1282 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1283 OSMO_ASSERT(rlc.block_info[0].bsn == 1);
1284}
1285
1286static void uplink_header_type2_test(void)
1287{
1288 BTS the_bts;
1289 int ts_no = 7;
1290 uint32_t fn = 2654218;
1291 uint16_t qta = 31;
1292 uint32_t tlli = 0xf1223344;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301293 uint8_t ms_class = 1;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301294
1295 printf("=== start %s ===\n", __func__);
1296 setup_bts(&the_bts, ts_no, 10);
1297
1298 uplink_header_type_2_parsing_test(&the_bts, ts_no,
1299 tlli, &fn, qta, ms_class);
1300 printf("=== end %s ===\n", __func__);
1301}
1302
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301303static void uplink_header_type_1_parsing_test(BTS *the_bts,
1304 uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
1305 uint8_t ms_class)
1306{
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301307 int tfi = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301308 uint8_t data[155] = {0};
1309 struct gprs_rlc_ul_header_egprs_1 *egprs1 = NULL;
1310 struct gprs_rlc_data_info rlc;
1311 GprsCodingScheme cs;
Neels Hofmeyrd34646a2017-02-08 17:07:40 +01001312 int rc;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301313
1314 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301315
1316 tfi = 1;
1317
1318 /* MCS 7 */
1319 cs = GprsCodingScheme::MCS7;
1320 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1321 egprs1->si = 1;
1322 egprs1->r = 1;
1323 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001324 egprs1->tfi_hi = tfi & 0x03;
1325 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1326 egprs1->bsn1_hi = 0;
1327 egprs1->bsn1_lo = 0;
1328 egprs1->bsn2_hi = 1;
1329 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301330 egprs1->cps = 15;
1331 egprs1->rsb = 0;
1332 egprs1->pi = 0;
1333 data[5] = 0xc0;
1334 data[5 + 57] = 1;
1335 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001336 OSMO_ASSERT(rc == 946);
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301337 OSMO_ASSERT(rlc.num_data_blocks == 2);
1338 OSMO_ASSERT(rlc.block_info[0].e == 1);
1339 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1340 OSMO_ASSERT(rlc.block_info[1].e == 1);
1341 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1342 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1343 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1344 OSMO_ASSERT(rlc.tfi == 1);
1345
1346 /* MCS 8 */
1347 cs = GprsCodingScheme::MCS8;
1348 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1349 egprs1->si = 1;
1350 egprs1->r = 1;
1351 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001352 egprs1->tfi_hi = tfi & 0x03;
1353 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1354 egprs1->bsn1_hi = 0;
1355 egprs1->bsn1_lo = 0;
1356 egprs1->bsn2_hi = 1;
1357 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301358 egprs1->cps = 15;
1359 egprs1->rsb = 0;
1360 egprs1->pi = 0;
1361 data[5] = 0xc0;
1362 data[5 + 69] = 1;
1363 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001364 OSMO_ASSERT(rc == 1138);
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301365 OSMO_ASSERT(rlc.num_data_blocks == 2);
1366 OSMO_ASSERT(rlc.block_info[0].e == 1);
1367 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1368 OSMO_ASSERT(rlc.block_info[1].e == 1);
1369 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1370 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1371 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1372 OSMO_ASSERT(rlc.tfi == 1);
1373
1374 /* MCS 9 */
1375 cs = GprsCodingScheme::MCS9;
1376 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1377 egprs1->si = 1;
1378 egprs1->r = 1;
1379 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001380 egprs1->tfi_hi = tfi & 0x03;
1381 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1382 egprs1->bsn1_hi = 0;
1383 egprs1->bsn1_lo = 0;
1384 egprs1->bsn2_hi = 1;
1385 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301386 egprs1->cps = 15;
1387 egprs1->rsb = 0;
1388 egprs1->pi = 0;
1389 data[5] = 0xc0;
1390 data[5 + 75] = 1;
1391 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001392 OSMO_ASSERT(rc == 1234);
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301393 OSMO_ASSERT(rlc.num_data_blocks == 2);
1394 OSMO_ASSERT(rlc.block_info[0].e == 1);
1395 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1396 OSMO_ASSERT(rlc.block_info[1].e == 1);
1397 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1398 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1399 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1400 OSMO_ASSERT(rlc.tfi == 1);
1401}
1402
1403void uplink_header_type1_test(void)
1404{
1405 BTS the_bts;
1406 int ts_no = 7;
1407 uint32_t fn = 2654218;
1408 uint16_t qta = 31;
1409 uint32_t tlli = 0xf1223344;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301410 uint8_t ms_class = 1;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301411
1412 printf("=== start %s ===\n", __func__);
1413 setup_bts(&the_bts, ts_no, 12);
1414 uplink_header_type_1_parsing_test(&the_bts, ts_no, tlli, &fn,
1415 qta, ms_class);
1416 printf("=== end %s ===\n", __func__);
1417}
1418
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001419int main(int argc, char **argv)
1420{
1421 struct vty_app_info pcu_vty_info = {0};
1422
1423 tall_pcu_ctx = talloc_named_const(NULL, 1, "EdgeTest context");
1424 if (!tall_pcu_ctx)
1425 abort();
1426
Neels Hofmeyr78ce5912017-02-08 17:07:31 +01001427 msgb_talloc_ctx_init(tall_pcu_ctx, 0);
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001428 osmo_init_logging(&debug_log_info);
1429 log_set_use_color(osmo_stderr_target, 0);
1430 log_set_print_filename(osmo_stderr_target, 0);
1431
1432 vty_init(&pcu_vty_info);
1433 pcu_vty_init(&debug_log_info);
1434
1435 test_coding_scheme();
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001436 test_rlc_info_init();
Jacob Erlbeck38f18692016-02-01 10:08:00 +01001437 test_rlc_unit_decoder();
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001438 test_rlc_unaligned_copy();
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001439 test_rlc_unit_encoder();
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001440
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301441 uplink_header_type2_test();
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301442 uplink_header_type1_test();
1443
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001444 if (getenv("TALLOC_REPORT_FULL"))
1445 talloc_report_full(tall_pcu_ctx, stderr);
1446 return EXIT_SUCCESS;
1447}
1448
1449/*
1450 * stubs that should not be reached
1451 */
1452extern "C" {
1453void l1if_pdch_req() { abort(); }
1454void l1if_connect_pdch() { abort(); }
1455void l1if_close_pdch() { abort(); }
1456void l1if_open_pdch() { abort(); }
1457}