blob: 68a0d0bf55e420a278b50d991ed0e820f53e62a2 [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"
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010029
30extern "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>
38}
39
40#include <errno.h>
Jacob Erlbeckf0e40392016-01-08 10:07:53 +010041#include <string.h>
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010042
43void *tall_pcu_ctx;
44int16_t spoof_mnc = 0, spoof_mcc = 0;
45
46static void check_coding_scheme(GprsCodingScheme& cs, GprsCodingScheme::Mode mode)
47{
48 volatile unsigned expected_size;
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010049 bool need_padding;
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010050 GprsCodingScheme new_cs;
51
52 OSMO_ASSERT(cs.isValid());
53 OSMO_ASSERT(cs.isCompatible(mode));
54
55 /* Check static getBySizeUL() */
Jacob Erlbeckfc1b3e62016-01-11 09:58:11 +010056 expected_size = cs.usedSizeUL();
57 if (cs.spareBitsUL() > 0 && cs.isGprs())
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010058 expected_size += 1;
59 OSMO_ASSERT(expected_size == cs.sizeUL());
60 OSMO_ASSERT(cs == GprsCodingScheme::getBySizeUL(expected_size));
61
62 /* Check static sizeUL() */
Jacob Erlbeckfc1b3e62016-01-11 09:58:11 +010063 expected_size = cs.usedSizeDL();
64 if (cs.spareBitsDL() > 0 && cs.isGprs())
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010065 expected_size += 1;
66 OSMO_ASSERT(expected_size == cs.sizeDL());
67
Jacob Erlbeck392a5452015-12-14 10:38:29 +010068 /* Check data block sizes */
69 OSMO_ASSERT(cs.maxDataBlockBytes() * cs.numDataBlocks() < cs.maxBytesDL());
70 OSMO_ASSERT(cs.maxDataBlockBytes() * cs.numDataBlocks() < cs.maxBytesUL());
71
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010072 /* Check inc/dec */
73 new_cs = cs;
74 new_cs.inc(mode);
75 OSMO_ASSERT(new_cs.isCompatible(mode));
76 if (new_cs != cs) {
77 new_cs.dec(mode);
78 OSMO_ASSERT(new_cs.isCompatible(mode));
79 OSMO_ASSERT(new_cs == cs);
80 }
81 new_cs.dec(mode);
82 OSMO_ASSERT(new_cs.isCompatible(mode));
83 if (new_cs != cs) {
84 new_cs.inc(mode);
85 OSMO_ASSERT(new_cs.isCompatible(mode));
86 OSMO_ASSERT(new_cs == cs);
87 }
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010088
89 new_cs = cs;
90 new_cs.decToSingleBlock(&need_padding);
91 OSMO_ASSERT(new_cs.isFamilyCompatible(cs));
92 OSMO_ASSERT(cs.isFamilyCompatible(new_cs));
93 OSMO_ASSERT(cs.isCompatible(new_cs));
94 if (need_padding) {
Jacob Erlbeck215e18c2016-02-03 18:22:34 +010095 OSMO_ASSERT(new_cs.maxDataBlockBytes() ==
96 new_cs.optionalPaddingBits()/8 + cs.maxDataBlockBytes());
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010097 } else {
98 OSMO_ASSERT(new_cs.maxDataBlockBytes() == cs.maxDataBlockBytes());
99 }
100
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100101}
102
103static void test_coding_scheme()
104{
105 unsigned i;
106 unsigned last_size_UL;
107 unsigned last_size_DL;
108 GprsCodingScheme::Scheme gprs_schemes[] = {
109 GprsCodingScheme::CS1,
110 GprsCodingScheme::CS2,
111 GprsCodingScheme::CS3,
112 GprsCodingScheme::CS4
113 };
114 struct {
115 GprsCodingScheme::Scheme s;
116 bool is_gmsk;
117 } egprs_schemes[] = {
118 {GprsCodingScheme::MCS1, true},
119 {GprsCodingScheme::MCS2, true},
120 {GprsCodingScheme::MCS3, true},
121 {GprsCodingScheme::MCS4, true},
122 {GprsCodingScheme::MCS5, false},
123 {GprsCodingScheme::MCS6, false},
124 {GprsCodingScheme::MCS7, false},
125 {GprsCodingScheme::MCS8, false},
126 {GprsCodingScheme::MCS9, false},
127 };
128
129 printf("=== start %s ===\n", __func__);
130
131 GprsCodingScheme cs;
132 OSMO_ASSERT(!cs);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100133 OSMO_ASSERT(GprsCodingScheme::Scheme(cs) == GprsCodingScheme::UNKNOWN);
134 OSMO_ASSERT(cs == GprsCodingScheme(GprsCodingScheme::UNKNOWN));
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100135 OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::GPRS));
136 OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::EGPRS_GMSK));
137 OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::EGPRS));
138
139 last_size_UL = 0;
140 last_size_DL = 0;
141
142 for (i = 0; i < ARRAY_SIZE(gprs_schemes); i++) {
143 GprsCodingScheme current_cs(gprs_schemes[i]);
144 OSMO_ASSERT(current_cs.isGprs());
145 OSMO_ASSERT(!current_cs.isEgprs());
146 OSMO_ASSERT(!current_cs.isEgprsGmsk());
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100147 OSMO_ASSERT(GprsCodingScheme::Scheme(current_cs) == gprs_schemes[i]);
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100148 OSMO_ASSERT(current_cs == GprsCodingScheme(gprs_schemes[i]));
149
150 /* Check strong monotonicity */
151 OSMO_ASSERT(current_cs.maxBytesUL() > last_size_UL);
152 OSMO_ASSERT(current_cs.maxBytesDL() > last_size_DL);
153 last_size_UL = current_cs.maxBytesUL();
154 last_size_DL = current_cs.maxBytesDL();
155
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +0100156 /* Check header types */
157 OSMO_ASSERT(current_cs.headerTypeData() ==
158 GprsCodingScheme::HEADER_GPRS_DATA);
159 OSMO_ASSERT(current_cs.headerTypeControl() ==
160 GprsCodingScheme::HEADER_GPRS_CONTROL);
161
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100162 check_coding_scheme(current_cs, GprsCodingScheme::GPRS);
163 }
164 OSMO_ASSERT(i == 4);
165
166 last_size_UL = 0;
167 last_size_DL = 0;
168
169 for (i = 0; i < ARRAY_SIZE(egprs_schemes); i++) {
170 GprsCodingScheme current_cs(egprs_schemes[i].s);
171 OSMO_ASSERT(!current_cs.isGprs());
172 OSMO_ASSERT(current_cs.isEgprs());
173 OSMO_ASSERT(!!current_cs.isEgprsGmsk() == !!egprs_schemes[i].is_gmsk);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100174 OSMO_ASSERT(GprsCodingScheme::Scheme(current_cs) == egprs_schemes[i].s);
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100175 OSMO_ASSERT(current_cs == GprsCodingScheme(egprs_schemes[i].s));
176
177 /* Check strong monotonicity */
178 OSMO_ASSERT(current_cs.maxBytesUL() > last_size_UL);
179 OSMO_ASSERT(current_cs.maxBytesDL() > last_size_DL);
180 last_size_UL = current_cs.maxBytesUL();
181 last_size_DL = current_cs.maxBytesDL();
182
183 if (egprs_schemes[i].is_gmsk)
184 check_coding_scheme(current_cs, GprsCodingScheme::EGPRS_GMSK);
185 check_coding_scheme(current_cs, GprsCodingScheme::EGPRS);
186 }
187 OSMO_ASSERT(i == 9);
188
189 printf("=== end %s ===\n", __func__);
190}
191
Jacob Erlbeck38f18692016-02-01 10:08:00 +0100192static void test_rlc_unit_decoder()
Jacob Erlbeck61679252015-12-11 18:25:21 +0100193{
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100194 struct gprs_rlc_data_block_info rdbi = {0};
Jacob Erlbeck61679252015-12-11 18:25:21 +0100195 GprsCodingScheme cs;
196 uint8_t data[74];
197 Decoding::RlcData chunks[16];
198 volatile int num_chunks = 0;
199 uint32_t tlli, tlli2;
200 unsigned int offs;
201
202
203 printf("=== start %s ===\n", __func__);
204
205 /* TS 44.060, B.1 */
206 cs = GprsCodingScheme::CS4;
207 rdbi.data_len = cs.maxDataBlockBytes();
208 rdbi.e = 0;
209 rdbi.ti = 0;
210 rdbi.cv = 15;
211 tlli = 0;
212 offs = 0;
213 data[offs++] = (11 << 2) | (1 << 1) | (0 << 0);
214 data[offs++] = (26 << 2) | (1 << 1) | (1 << 0);
215 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
216 chunks, ARRAY_SIZE(chunks), &tlli);
217 OSMO_ASSERT(num_chunks == 3);
218 OSMO_ASSERT(tlli == 0);
219 OSMO_ASSERT(chunks[0].offset == 2);
220 OSMO_ASSERT(chunks[0].length == 11);
221 OSMO_ASSERT(chunks[0].is_complete);
222 OSMO_ASSERT(chunks[1].offset == 13);
223 OSMO_ASSERT(chunks[1].length == 26);
224 OSMO_ASSERT(chunks[1].is_complete);
225 OSMO_ASSERT(chunks[2].offset == 39);
226 OSMO_ASSERT(chunks[2].length == cs.maxDataBlockBytes() - 39);
227 OSMO_ASSERT(!chunks[2].is_complete);
228
229 /* TS 44.060, B.2 */
230 cs = GprsCodingScheme::CS1;
231 rdbi.data_len = cs.maxDataBlockBytes();
232 rdbi.e = 0;
233 rdbi.ti = 0;
234 rdbi.cv = 15;
235 tlli = 0;
236 offs = 0;
237 data[offs++] = (0 << 2) | (0 << 1) | (1 << 0);
238 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
239 chunks, ARRAY_SIZE(chunks), &tlli);
240 OSMO_ASSERT(num_chunks == 1);
241 OSMO_ASSERT(tlli == 0);
242 OSMO_ASSERT(chunks[0].offset == 1);
243 OSMO_ASSERT(chunks[0].length == 19);
244 OSMO_ASSERT(!chunks[0].is_complete);
245
246 rdbi.e = 0;
247 rdbi.ti = 0;
248 rdbi.cv = 15;
249 tlli = 0;
250 offs = 0;
251 data[offs++] = (1 << 2) | (1 << 1) | (1 << 0);
252 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
253 chunks, ARRAY_SIZE(chunks), &tlli);
254 OSMO_ASSERT(num_chunks == 2);
255 OSMO_ASSERT(tlli == 0);
256 OSMO_ASSERT(chunks[0].offset == 1);
257 OSMO_ASSERT(chunks[0].length == 1);
258 OSMO_ASSERT(chunks[0].is_complete);
259 OSMO_ASSERT(chunks[1].offset == 2);
260 OSMO_ASSERT(chunks[1].length == 18);
261 OSMO_ASSERT(!chunks[1].is_complete);
262
263 /* TS 44.060, B.3 */
264 cs = GprsCodingScheme::CS1;
265 rdbi.data_len = cs.maxDataBlockBytes();
266 rdbi.e = 0;
267 rdbi.ti = 0;
268 rdbi.cv = 15;
269 tlli = 0;
270 offs = 0;
271 data[offs++] = (7 << 2) | (1 << 1) | (0 << 0);
272 data[offs++] = (11 << 2) | (0 << 1) | (1 << 0);
273 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
274 chunks, ARRAY_SIZE(chunks), &tlli);
275 OSMO_ASSERT(num_chunks == 2);
276 OSMO_ASSERT(tlli == 0);
277 OSMO_ASSERT(chunks[0].offset == 2);
278 OSMO_ASSERT(chunks[0].length == 7);
279 OSMO_ASSERT(chunks[0].is_complete);
280 OSMO_ASSERT(chunks[1].offset == 9);
281 OSMO_ASSERT(chunks[1].length == 11);
282 OSMO_ASSERT(chunks[1].is_complete);
283
284 /* TS 44.060, B.4 */
285 cs = GprsCodingScheme::CS1;
286 rdbi.data_len = cs.maxDataBlockBytes();
287 rdbi.e = 1;
288 rdbi.ti = 0;
289 rdbi.cv = 15;
290 tlli = 0;
291 offs = 0;
292 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
293 chunks, ARRAY_SIZE(chunks), &tlli);
294 OSMO_ASSERT(num_chunks == 1);
295 OSMO_ASSERT(tlli == 0);
296 OSMO_ASSERT(chunks[0].offset == 0);
297 OSMO_ASSERT(chunks[0].length == 20);
298 OSMO_ASSERT(!chunks[0].is_complete);
299
300 /* TS 44.060, B.6 */
301 cs = GprsCodingScheme::CS1;
302 rdbi.data_len = cs.maxDataBlockBytes();
303 rdbi.e = 1;
304 rdbi.ti = 0;
305 rdbi.cv = 0;
306 tlli = 0;
307 offs = 0;
308 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
309 chunks, ARRAY_SIZE(chunks), &tlli);
310 OSMO_ASSERT(num_chunks == 1);
311 OSMO_ASSERT(tlli == 0);
312 OSMO_ASSERT(chunks[0].offset == 0);
313 OSMO_ASSERT(chunks[0].length == 20);
314 OSMO_ASSERT(chunks[0].is_complete);
315
316 /* TS 44.060, B.8.1 */
317 cs = GprsCodingScheme::MCS4;
318 rdbi.data_len = cs.maxDataBlockBytes();
319 rdbi.e = 0;
320 rdbi.ti = 0;
321 rdbi.cv = 15;
322 tlli = 0;
323 offs = 0;
324 data[offs++] = (11 << 1) | (0 << 0);
325 data[offs++] = (26 << 1) | (1 << 0);
326 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
327 chunks, ARRAY_SIZE(chunks), &tlli);
328 OSMO_ASSERT(num_chunks == 3);
329 OSMO_ASSERT(tlli == 0);
330 OSMO_ASSERT(chunks[0].offset == 2);
331 OSMO_ASSERT(chunks[0].length == 11);
332 OSMO_ASSERT(chunks[0].is_complete);
333 OSMO_ASSERT(chunks[1].offset == 13);
334 OSMO_ASSERT(chunks[1].length == 26);
335 OSMO_ASSERT(chunks[1].is_complete);
336 OSMO_ASSERT(chunks[2].offset == 39);
337 OSMO_ASSERT(chunks[2].length == 5);
338 OSMO_ASSERT(!chunks[2].is_complete);
339
340 /* TS 44.060, B.8.2 */
341
342 /* Note that the spec confuses the byte numbering here, since it
343 * includes the FBI/E header bits into the N2 octet count which
344 * is not consistent with Section 10.3a.1 & 10.3a.2. */
345
346 cs = GprsCodingScheme::MCS2;
347 rdbi.data_len = cs.maxDataBlockBytes();
348 rdbi.e = 0;
349 rdbi.ti = 0;
350 rdbi.cv = 15;
351 tlli = 0;
352 offs = 0;
353 data[offs++] = (15 << 1) | (1 << 0);
354 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
355 chunks, ARRAY_SIZE(chunks), &tlli);
356 OSMO_ASSERT(num_chunks == 2);
357 OSMO_ASSERT(tlli == 0);
358 OSMO_ASSERT(chunks[0].offset == 1);
359 OSMO_ASSERT(chunks[0].length == 15);
360 OSMO_ASSERT(chunks[0].is_complete);
361 OSMO_ASSERT(chunks[1].offset == 16);
362 OSMO_ASSERT(chunks[1].length == 12);
363 OSMO_ASSERT(!chunks[1].is_complete);
364
365 rdbi.e = 0;
366 rdbi.ti = 0;
367 rdbi.cv = 15;
368 tlli = 0;
369 offs = 0;
370 data[offs++] = ( 0 << 1) | (0 << 0);
371 data[offs++] = ( 7 << 1) | (0 << 0);
372 data[offs++] = (18 << 1) | (1 << 0); /* Differs from spec's N2-11 = 17 */
373 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
374 chunks, ARRAY_SIZE(chunks), &tlli);
375 OSMO_ASSERT(num_chunks == 3);
376 OSMO_ASSERT(tlli == 0);
377 OSMO_ASSERT(chunks[0].offset == 3);
378 OSMO_ASSERT(chunks[0].length == 0);
379 OSMO_ASSERT(chunks[0].is_complete);
380 OSMO_ASSERT(chunks[1].offset == 3);
381 OSMO_ASSERT(chunks[1].length == 7);
382 OSMO_ASSERT(chunks[1].is_complete);
383 OSMO_ASSERT(chunks[2].offset == 10);
384 OSMO_ASSERT(chunks[2].length == 18);
385 OSMO_ASSERT(chunks[2].is_complete);
386
387 rdbi.e = 0;
388 rdbi.ti = 0;
389 rdbi.cv = 0;
390 tlli = 0;
391 offs = 0;
392 data[offs++] = ( 6 << 1) | (0 << 0);
393 data[offs++] = (12 << 1) | (0 << 0);
394 data[offs++] = (127 << 1) | (1 << 0);
395 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
396 chunks, ARRAY_SIZE(chunks), &tlli);
397 OSMO_ASSERT(num_chunks == 2);
398 OSMO_ASSERT(tlli == 0);
399 OSMO_ASSERT(chunks[0].offset == 3);
400 OSMO_ASSERT(chunks[0].length == 6);
401 OSMO_ASSERT(chunks[0].is_complete);
402 OSMO_ASSERT(chunks[1].offset == 9);
403 OSMO_ASSERT(chunks[1].length == 12);
404 OSMO_ASSERT(chunks[1].is_complete);
405
406 /* TS 44.060, B.8.3 */
407
408 /* Note that the spec confuses the byte numbering here, too (see above) */
409
410 cs = GprsCodingScheme::MCS2;
411 rdbi.data_len = cs.maxDataBlockBytes();
412 rdbi.e = 1;
413 rdbi.ti = 0;
414 rdbi.cv = 0;
415 tlli = 0;
416 offs = 0;
417 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
418 chunks, ARRAY_SIZE(chunks), &tlli);
419 OSMO_ASSERT(num_chunks == 1);
420 OSMO_ASSERT(tlli == 0);
421 OSMO_ASSERT(chunks[0].offset == 0);
422 OSMO_ASSERT(chunks[0].length == 28);
423 OSMO_ASSERT(chunks[0].is_complete);
424
425 /* CS-1, TLLI, last block, single chunk until the end of the block */
426 cs = GprsCodingScheme::CS1;
427 rdbi.data_len = cs.maxDataBlockBytes();
428 rdbi.e = 1;
429 rdbi.ti = 1;
430 rdbi.cv = 0;
431 tlli = 0;
432 tlli2 = 0xffeeddcc;
433 offs = 0;
434 data[offs++] = tlli2 >> 24;
435 data[offs++] = tlli2 >> 16;
436 data[offs++] = tlli2 >> 8;
437 data[offs++] = tlli2 >> 0;
438 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
439 chunks, ARRAY_SIZE(chunks), &tlli);
440 OSMO_ASSERT(num_chunks == 1);
441 OSMO_ASSERT(tlli == tlli2);
442 OSMO_ASSERT(chunks[0].offset == 4);
443 OSMO_ASSERT(chunks[0].length == 16);
444 OSMO_ASSERT(chunks[0].is_complete);
445
446 /* Like TS 44.060, B.2, first RLC block but with TLLI */
447 cs = GprsCodingScheme::CS1;
448 rdbi.data_len = cs.maxDataBlockBytes();
449 rdbi.e = 0;
450 rdbi.ti = 1;
451 rdbi.cv = 15;
452 tlli = 0;
453 tlli2 = 0xffeeddbb;
454 offs = 0;
455 data[offs++] = (0 << 2) | (0 << 1) | (1 << 0);
456 data[offs++] = tlli2 >> 24;
457 data[offs++] = tlli2 >> 16;
458 data[offs++] = tlli2 >> 8;
459 data[offs++] = tlli2 >> 0;
460 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
461 chunks, ARRAY_SIZE(chunks), &tlli);
462 OSMO_ASSERT(num_chunks == 1);
463 OSMO_ASSERT(tlli == tlli2);
464 OSMO_ASSERT(chunks[0].offset == 5);
465 OSMO_ASSERT(chunks[0].length == 15);
466 OSMO_ASSERT(!chunks[0].is_complete);
467
468 /* Like TS 44.060, B.8.1 but with TLLI */
469 cs = GprsCodingScheme::MCS4;
470 rdbi.data_len = cs.maxDataBlockBytes();
471 rdbi.e = 0;
472 rdbi.ti = 1;
473 rdbi.cv = 15;
474 tlli = 0;
475 tlli2 = 0xffeeddaa;
476 offs = 0;
477 data[offs++] = (11 << 1) | (0 << 0);
478 data[offs++] = (26 << 1) | (1 << 0);
479 /* Little endian */
480 data[offs++] = tlli2 >> 0;
481 data[offs++] = tlli2 >> 8;
482 data[offs++] = tlli2 >> 16;
483 data[offs++] = tlli2 >> 24;
484 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
485 chunks, ARRAY_SIZE(chunks), &tlli);
486 OSMO_ASSERT(num_chunks == 3);
487 OSMO_ASSERT(tlli == tlli2);
488 OSMO_ASSERT(chunks[0].offset == 6);
489 OSMO_ASSERT(chunks[0].length == 11);
490 OSMO_ASSERT(chunks[0].is_complete);
491 OSMO_ASSERT(chunks[1].offset == 17);
492 OSMO_ASSERT(chunks[1].length == 26);
493 OSMO_ASSERT(chunks[1].is_complete);
494 OSMO_ASSERT(chunks[2].offset == 43);
495 OSMO_ASSERT(chunks[2].length == 1);
496 OSMO_ASSERT(!chunks[2].is_complete);
497
498 printf("=== end %s ===\n", __func__);
499}
500
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100501static void test_rlc_unit_encoder()
502{
503 struct gprs_rlc_data_block_info rdbi = {0};
504 GprsCodingScheme cs;
505 uint8_t data[74];
506 uint8_t llc_data[1500] = {0,};
507 int num_chunks = 0;
508 int write_offset;
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200509 int count_payload;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100510 struct gprs_llc llc;
511 Encoding::AppendResult ar;
512
513 printf("=== start %s ===\n", __func__);
514
515 llc.init();
516
517 /* TS 44.060, B.1 */
518 cs = GprsCodingScheme::CS4;
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100519 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100520 num_chunks = 0;
521 write_offset = 0;
522 memset(data, 0, sizeof(data));
523
524 llc.reset();
525 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200526 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100527
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100528 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200529 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100530
531 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
532 OSMO_ASSERT(rdbi.e == 0);
533 OSMO_ASSERT(write_offset == 1 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200534 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100535 OSMO_ASSERT(num_chunks == 1);
536
537 llc.reset();
538 llc.put_frame(llc_data, 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200539 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100540
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100541 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200542 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100543
544 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
545 OSMO_ASSERT(rdbi.e == 0);
546 OSMO_ASSERT(write_offset == 2 + 11 + 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200547 OSMO_ASSERT(count_payload == 26);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100548 OSMO_ASSERT(num_chunks == 2);
549
550 llc.reset();
551 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200552 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100553
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100554 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200555 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100556
557 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
558 OSMO_ASSERT(rdbi.e == 0);
559 OSMO_ASSERT(rdbi.cv != 0);
560 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200561 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100562 OSMO_ASSERT(num_chunks == 3);
563
564 OSMO_ASSERT(data[0] == ((11 << 2) | (1 << 1) | (0 << 0)));
565 OSMO_ASSERT(data[1] == ((26 << 2) | (1 << 1) | (1 << 0)));
566 OSMO_ASSERT(data[2] == 0);
567
568 /* TS 44.060, B.2 */
569 cs = GprsCodingScheme::CS1;
570
571 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100572 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100573 num_chunks = 0;
574 write_offset = 0;
575 memset(data, 0, sizeof(data));
576
577 llc.reset();
578 llc.put_frame(llc_data, 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200579 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100580
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100581 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200582 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100583
584 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
585 OSMO_ASSERT(rdbi.e == 0);
586 OSMO_ASSERT(write_offset == 1 + 19);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200587 OSMO_ASSERT(count_payload == 19);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100588 OSMO_ASSERT(num_chunks == 1);
589
590 OSMO_ASSERT(data[0] == ((0 << 2) | (0 << 1) | (1 << 0)));
591 OSMO_ASSERT(data[1] == 0);
592
593 /* Block 2 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100594 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100595 num_chunks = 0;
596 write_offset = 0;
597 memset(data, 0, sizeof(data));
598
599 OSMO_ASSERT(llc.chunk_size() == 1);
600
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200601 count_payload = -1;
602
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100603 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200604 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100605
606 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
607 OSMO_ASSERT(rdbi.e == 0);
608 OSMO_ASSERT(write_offset == 1 + 1);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200609 OSMO_ASSERT(count_payload == 1);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100610 OSMO_ASSERT(num_chunks == 1);
611
612 llc.reset();
613 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200614 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100615
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100616 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200617 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100618
619 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
620 OSMO_ASSERT(rdbi.e == 0);
621 OSMO_ASSERT(write_offset == 1 + 1 + 18);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200622 OSMO_ASSERT(count_payload == 18);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100623 OSMO_ASSERT(num_chunks == 2);
624
625 OSMO_ASSERT(data[0] == ((1 << 2) | (1 << 1) | (1 << 0)));
626 OSMO_ASSERT(data[1] == 0);
627
628 /* TS 44.060, B.3 */
629 cs = GprsCodingScheme::CS1;
630
631 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100632 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100633 num_chunks = 0;
634 write_offset = 0;
635 memset(data, 0, sizeof(data));
636
637 llc.reset();
638 llc.put_frame(llc_data, 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200639 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100640
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100641 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200642 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100643
644 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
645 OSMO_ASSERT(rdbi.e == 0);
646 OSMO_ASSERT(write_offset == 1 + 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200647 OSMO_ASSERT(count_payload == 7);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100648 OSMO_ASSERT(num_chunks == 1);
649
650 llc.reset();
651 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200652 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100653
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100654 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200655 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100656
657 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
658 OSMO_ASSERT(rdbi.e == 0);
659 OSMO_ASSERT(write_offset == 2 + 7 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200660 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100661 OSMO_ASSERT(num_chunks == 2);
662
663 OSMO_ASSERT(data[0] == ((7 << 2) | (1 << 1) | (0 << 0)));
664 OSMO_ASSERT(data[1] == ((11 << 2) | (0 << 1) | (1 << 0)));
665 OSMO_ASSERT(data[2] == 0);
666
667 /* TS 44.060, B.4 */
668 cs = GprsCodingScheme::CS1;
669
670 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100671 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100672 num_chunks = 0;
673 write_offset = 0;
674 memset(data, 0, sizeof(data));
675
676 llc.reset();
677 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200678 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100679
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100680 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200681 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100682
683 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
684 OSMO_ASSERT(rdbi.e == 1);
685 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200686 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100687 OSMO_ASSERT(num_chunks == 1);
688 OSMO_ASSERT(rdbi.cv != 0);
689
690 OSMO_ASSERT(data[0] == 0);
691
692 /* TS 44.060, B.5 */
693 cs = GprsCodingScheme::CS1;
694
695 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100696 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100697 num_chunks = 0;
698 write_offset = 0;
699 memset(data, 0, sizeof(data));
700
701 llc.reset();
702 llc.put_frame(llc_data, 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200703 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100704
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100705 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200706 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100707
708 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
709 OSMO_ASSERT(rdbi.e == 1);
710 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200711 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100712 OSMO_ASSERT(num_chunks == 1);
713 OSMO_ASSERT(rdbi.cv == 0);
714
715 OSMO_ASSERT(data[0] == 0);
716
717 /* TS 44.060, B.7 */
718 cs = GprsCodingScheme::CS1;
719
720 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100721 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100722 num_chunks = 0;
723 write_offset = 0;
724 memset(data, 0, sizeof(data));
725
726 llc.reset();
727 llc.put_frame(llc_data, 30);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200728 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100729
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100730 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200731 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100732
733 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
734 OSMO_ASSERT(rdbi.e == 1);
735 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200736 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100737 OSMO_ASSERT(num_chunks == 1);
738
739 OSMO_ASSERT(data[0] == 0);
740
741 /* Block 2 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100742 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100743 num_chunks = 0;
744 write_offset = 0;
745 memset(data, 0, sizeof(data));
746
747 OSMO_ASSERT(llc.chunk_size() == 10);
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_COMPLETED_SPACE_LEFT);
754 OSMO_ASSERT(rdbi.e == 0);
755 OSMO_ASSERT(write_offset == 1 + 10);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200756 OSMO_ASSERT(count_payload == 10);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100757 OSMO_ASSERT(num_chunks == 1);
758
759 llc.reset();
760 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200761 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100762
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100763 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200764 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100765
766 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
767 OSMO_ASSERT(rdbi.e == 0);
768 OSMO_ASSERT(write_offset == 1 + 10 + 9);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200769 OSMO_ASSERT(count_payload == 9);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100770 OSMO_ASSERT(num_chunks == 2);
771
772 OSMO_ASSERT(data[0] == ((10 << 2) | (1 << 1) | (1 << 0)));
773 OSMO_ASSERT(data[1] == 0);
774
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100775 /* TS 44.060, B.8.1 */
776 cs = GprsCodingScheme::MCS4;
777
778 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100779 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100780 num_chunks = 0;
781 write_offset = 0;
782 memset(data, 0, sizeof(data));
783
784 llc.reset();
785 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200786 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100787
788 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200789 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100790
791 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
792 OSMO_ASSERT(rdbi.e == 0);
793 OSMO_ASSERT(write_offset == 1 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200794 OSMO_ASSERT(count_payload == 11);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100795 OSMO_ASSERT(num_chunks == 1);
796
797 llc.reset();
798 llc.put_frame(llc_data, 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200799 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100800
801 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200802 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100803
804 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
805 OSMO_ASSERT(rdbi.e == 0);
806 OSMO_ASSERT(write_offset == 2 + 11 + 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200807 OSMO_ASSERT(count_payload == 26);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100808 OSMO_ASSERT(num_chunks == 2);
809
810 llc.reset();
811 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200812 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100813
814 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200815 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100816
817 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
818 OSMO_ASSERT(rdbi.e == 0);
819 OSMO_ASSERT(rdbi.cv != 0);
820 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200821 OSMO_ASSERT(count_payload == 5);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100822 OSMO_ASSERT(num_chunks == 3);
823
824 OSMO_ASSERT(data[0] == ((11 << 1) | (0 << 0)));
825 OSMO_ASSERT(data[1] == ((26 << 1) | (1 << 0)));
826 OSMO_ASSERT(data[2] == 0);
827
828 /* TS 44.060, B.8.2 */
829
830 /* Note that the spec confuses the byte numbering here, since it
831 * includes the FBI/E header bits into the N2 octet count which
832 * is not consistent with Section 10.3a.1 & 10.3a.2. */
833
834 cs = GprsCodingScheme::MCS2;
835
836 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100837 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100838 num_chunks = 0;
839 write_offset = 0;
840 memset(data, 0, sizeof(data));
841
842 llc.reset();
843 llc.put_frame(llc_data, 15);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200844 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100845
846 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200847 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100848
849 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
850 OSMO_ASSERT(rdbi.e == 0);
851 OSMO_ASSERT(write_offset == 1 + 15);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200852 OSMO_ASSERT(count_payload == 15);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100853 OSMO_ASSERT(num_chunks == 1);
854
855 llc.reset();
856 llc.put_frame(llc_data, 12);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200857 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100858
859 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200860 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100861
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200862 /* no LI here, becaues there are exact 12 bytes left. Put LI into next frame */
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100863 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
864 OSMO_ASSERT(rdbi.e == 0);
865 OSMO_ASSERT(rdbi.cv != 0);
866 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200867 OSMO_ASSERT(count_payload == 12);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100868 OSMO_ASSERT(num_chunks == 2);
869
870 OSMO_ASSERT(data[0] == ((15 << 1) | (1 << 0)));
871 OSMO_ASSERT(data[1] == 0);
872
873 /* Block 2 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100874 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100875 num_chunks = 0;
876 write_offset = 0;
877 memset(data, 0, sizeof(data));
878
879 OSMO_ASSERT(llc.chunk_size() == 0);
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
885 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
886 OSMO_ASSERT(rdbi.e == 0);
887 OSMO_ASSERT(write_offset == 1 + 0);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200888 OSMO_ASSERT(count_payload == 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100889 OSMO_ASSERT(num_chunks == 1);
890
891 llc.reset();
892 llc.put_frame(llc_data, 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200893 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100894
895 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200896 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100897
898 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
899 OSMO_ASSERT(rdbi.e == 0);
900 OSMO_ASSERT(rdbi.cv != 0);
901 OSMO_ASSERT(write_offset == 2 + 0 + 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200902 OSMO_ASSERT(count_payload == 7);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100903 OSMO_ASSERT(num_chunks == 2);
904
905 llc.reset();
906 llc.put_frame(llc_data, 18);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200907 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100908
909 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200910 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100911
912 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
913 OSMO_ASSERT(rdbi.e == 0);
914 OSMO_ASSERT(rdbi.cv != 0);
915 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200916 OSMO_ASSERT(count_payload == 18);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100917 OSMO_ASSERT(num_chunks == 3);
918
919 OSMO_ASSERT(data[0] == ((0 << 1) | (0 << 0)));
920 OSMO_ASSERT(data[1] == ((7 << 1) | (0 << 0)));
921 OSMO_ASSERT(data[2] == ((18 << 1) | (1 << 0)));
922 OSMO_ASSERT(data[3] == 0);
923
924 /* Block 3 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100925 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100926 num_chunks = 0;
927 write_offset = 0;
928 memset(data, 0, sizeof(data));
929
930 llc.reset();
931 llc.put_frame(llc_data, 6);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200932 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100933
934 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200935 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100936
937 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
938 OSMO_ASSERT(rdbi.e == 0);
939 OSMO_ASSERT(write_offset == 1 + 6);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200940 OSMO_ASSERT(count_payload == 6);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100941 OSMO_ASSERT(num_chunks == 1);
942
943 llc.reset();
944 llc.put_frame(llc_data, 12);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200945 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100946
947 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200948 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100949
950 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
951 OSMO_ASSERT(rdbi.e == 0);
952 OSMO_ASSERT(rdbi.cv == 0);
953 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200954 OSMO_ASSERT(count_payload == 12);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100955 OSMO_ASSERT(num_chunks == 3);
956
957 OSMO_ASSERT(data[0] == ((6 << 1) | (0 << 0)));
958 OSMO_ASSERT(data[1] == ((12 << 1) | (0 << 0)));
959 OSMO_ASSERT(data[2] == ((127 << 1) | (1 << 0)));
960 OSMO_ASSERT(data[3] == 0);
961
962 /* TS 44.060, B.8.3 */
963
964 /* Note that the spec confuses the byte numbering here, too (see above) */
965
966 cs = GprsCodingScheme::MCS2;
967
968 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100969 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100970 num_chunks = 0;
971 write_offset = 0;
972 memset(data, 0, sizeof(data));
973
974 llc.reset();
975 llc.put_frame(llc_data, rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200976 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100977
978 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200979 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100980
981 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
982 OSMO_ASSERT(rdbi.e == 1);
983 OSMO_ASSERT(rdbi.cv == 0);
984 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200985 OSMO_ASSERT(count_payload == rdbi.data_len);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100986 OSMO_ASSERT(num_chunks == 1);
987
988 OSMO_ASSERT(data[0] == 0);
989
990 /* Final block with an LLC of size data_len-1 */
991
992 cs = GprsCodingScheme::MCS2;
993
994 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100995 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100996 num_chunks = 0;
997 write_offset = 0;
998 memset(data, 0, sizeof(data));
999
1000 llc.reset();
1001 llc.put_frame(llc_data, rdbi.data_len - 1);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001002 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001003
1004 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001005 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001006
1007 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
1008 OSMO_ASSERT(rdbi.e == 0);
1009 OSMO_ASSERT(rdbi.cv == 0);
1010 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001011 OSMO_ASSERT(count_payload == rdbi.data_len - 1);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001012 OSMO_ASSERT(num_chunks == 1);
1013
1014 OSMO_ASSERT(data[0] == (((rdbi.data_len-1) << 1) | (1 << 0)));
1015 OSMO_ASSERT(data[1] == 0);
1016
1017 /* Final block with an LLC of size data_len-2 */
1018
1019 cs = GprsCodingScheme::MCS2;
1020
1021 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +01001022 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001023 num_chunks = 0;
1024 write_offset = 0;
1025 memset(data, 0, sizeof(data));
1026
1027 llc.reset();
1028 llc.put_frame(llc_data, rdbi.data_len - 2);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001029 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001030
1031 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001032 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001033
1034 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
1035 OSMO_ASSERT(rdbi.e == 0);
1036 OSMO_ASSERT(rdbi.cv == 0);
1037 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001038 OSMO_ASSERT(count_payload == rdbi.data_len - 2);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001039 OSMO_ASSERT(num_chunks == 2);
1040
1041 OSMO_ASSERT(data[0] == (((rdbi.data_len-2) << 1) | (0 << 0)));
1042 OSMO_ASSERT(data[1] == ((127 << 1) | (1 << 0)));
1043 OSMO_ASSERT(data[2] == 0);
1044
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001045 printf("=== end %s ===\n", __func__);
1046}
1047
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001048static void test_rlc_unaligned_copy()
1049{
1050 uint8_t bits[256];
1051 uint8_t saved_block[256];
1052 uint8_t test_block[256];
1053 uint8_t out_block[256];
1054 GprsCodingScheme::Scheme scheme;
1055 int pattern;
1056 volatile unsigned int block_idx, i;
1057
1058 for (scheme = GprsCodingScheme::CS1;
1059 scheme < GprsCodingScheme::NUM_SCHEMES;
1060 scheme = GprsCodingScheme::Scheme(scheme + 1))
1061 {
1062 GprsCodingScheme cs(scheme);
1063
1064 for (pattern = 0; pattern <= 0xff; pattern += 0xff) {
1065 /* prepare test block */
1066 test_block[0] = pattern ^ 0xff;
1067 for (i = 1; i + 1 < cs.maxDataBlockBytes(); i++)
1068 test_block[i] = i;
1069 test_block[cs.maxDataBlockBytes()-1] = pattern ^ 0xff;
1070
1071 for (block_idx = 0;
1072 block_idx < cs.numDataBlocks();
1073 block_idx++)
1074 {
1075 struct gprs_rlc_data_info rlc;
Jacob Erlbeckb55f3132016-02-03 18:28:04 +01001076 gprs_rlc_data_info_init_dl(&rlc, cs, false);
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001077
1078 memset(bits, pattern, sizeof(bits));
1079 Decoding::rlc_copy_to_aligned_buffer(
1080 &rlc, block_idx, bits, saved_block);
1081
1082 fprintf(stderr,
1083 "Test data block: %s\n",
1084 osmo_hexdump(test_block, cs.maxDataBlockBytes()));
1085
1086 Encoding::rlc_copy_from_aligned_buffer(
1087 &rlc, block_idx, bits, test_block);
1088
1089 fprintf(stderr,
1090 "Encoded message block, %s, idx %d, "
1091 "pattern %02x: %s\n",
1092 rlc.cs.name(), block_idx, pattern,
1093 osmo_hexdump(bits, cs.sizeDL()));
1094
1095 Decoding::rlc_copy_to_aligned_buffer(
1096 &rlc, block_idx, bits, out_block);
1097
1098 fprintf(stderr,
1099 "Out data block: %s\n",
1100 osmo_hexdump(out_block, cs.maxDataBlockBytes()));
1101 /* restore original bits */
1102 Encoding::rlc_copy_from_aligned_buffer(
1103 &rlc, block_idx, bits, saved_block);
1104
1105 OSMO_ASSERT(memcmp(test_block, out_block,
1106 rlc.cs.maxDataBlockBytes()) == 0);
1107
1108 for (i = 0; i < sizeof(bits); i++)
1109 OSMO_ASSERT(bits[i] == pattern);
1110 }
1111 }
1112 }
1113}
1114
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001115static void test_rlc_info_init()
1116{
1117 struct gprs_rlc_data_info rlc;
1118
1119 printf("=== start %s ===\n", __func__);
Jacob Erlbeckb55f3132016-02-03 18:28:04 +01001120 gprs_rlc_data_info_init_dl(&rlc, GprsCodingScheme(GprsCodingScheme::CS1), false);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001121 OSMO_ASSERT(rlc.num_data_blocks == 1);
1122 OSMO_ASSERT(rlc.data_offs_bits[0] == 24);
1123 OSMO_ASSERT(rlc.block_info[0].data_len == 20);
1124
Jacob Erlbeckb55f3132016-02-03 18:28:04 +01001125 gprs_rlc_data_info_init_dl(&rlc, GprsCodingScheme(GprsCodingScheme::MCS1), false);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001126 OSMO_ASSERT(rlc.num_data_blocks == 1);
1127 OSMO_ASSERT(rlc.data_offs_bits[0] == 33);
1128 OSMO_ASSERT(rlc.block_info[0].data_len == 22);
1129
1130 printf("=== end %s ===\n", __func__);
1131}
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001132
1133static const struct log_info_cat default_categories[] = {
1134 {"DCSN1", "\033[1;31m", "Concrete Syntax Notation One (CSN1)", LOGL_INFO, 0},
1135 {"DL1IF", "\033[1;32m", "GPRS PCU L1 interface (L1IF)", LOGL_DEBUG, 1},
1136 {"DRLCMAC", "\033[0;33m", "GPRS RLC/MAC layer (RLCMAC)", LOGL_DEBUG, 1},
1137 {"DRLCMACDATA", "\033[0;33m", "GPRS RLC/MAC layer Data (RLCMAC)", LOGL_DEBUG, 1},
1138 {"DRLCMACDL", "\033[1;33m", "GPRS RLC/MAC layer Downlink (RLCMAC)", LOGL_DEBUG, 1},
1139 {"DRLCMACUL", "\033[1;36m", "GPRS RLC/MAC layer Uplink (RLCMAC)", LOGL_DEBUG, 1},
1140 {"DRLCMACSCHED", "\033[0;36m", "GPRS RLC/MAC layer Scheduling (RLCMAC)", LOGL_DEBUG, 1},
1141 {"DRLCMACMEAS", "\033[1;31m", "GPRS RLC/MAC layer Measurements (RLCMAC)", LOGL_INFO, 1},
1142 {"DNS","\033[1;34m", "GPRS Network Service Protocol (NS)", LOGL_INFO , 1},
1143 {"DBSSGP","\033[1;34m", "GPRS BSS Gateway Protocol (BSSGP)", LOGL_INFO , 1},
1144 {"DPCU", "\033[1;35m", "GPRS Packet Control Unit (PCU)", LOGL_NOTICE, 1},
1145};
1146
1147static int filter_fn(const struct log_context *ctx,
1148 struct log_target *tar)
1149{
1150 return 1;
1151}
1152
1153const struct log_info debug_log_info = {
1154 filter_fn,
1155 (struct log_info_cat*)default_categories,
1156 ARRAY_SIZE(default_categories),
1157};
1158
1159int main(int argc, char **argv)
1160{
1161 struct vty_app_info pcu_vty_info = {0};
1162
1163 tall_pcu_ctx = talloc_named_const(NULL, 1, "EdgeTest context");
1164 if (!tall_pcu_ctx)
1165 abort();
1166
1167 msgb_set_talloc_ctx(tall_pcu_ctx);
1168 osmo_init_logging(&debug_log_info);
1169 log_set_use_color(osmo_stderr_target, 0);
1170 log_set_print_filename(osmo_stderr_target, 0);
1171
1172 vty_init(&pcu_vty_info);
1173 pcu_vty_init(&debug_log_info);
1174
1175 test_coding_scheme();
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001176 test_rlc_info_init();
Jacob Erlbeck38f18692016-02-01 10:08:00 +01001177 test_rlc_unit_decoder();
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001178 test_rlc_unaligned_copy();
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001179 test_rlc_unit_encoder();
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001180
1181 if (getenv("TALLOC_REPORT_FULL"))
1182 talloc_report_full(tall_pcu_ctx, stderr);
1183 return EXIT_SUCCESS;
1184}
1185
1186/*
1187 * stubs that should not be reached
1188 */
1189extern "C" {
1190void l1if_pdch_req() { abort(); }
1191void l1if_connect_pdch() { abort(); }
1192void l1if_close_pdch() { abort(); }
1193void l1if_open_pdch() { abort(); }
1194}