blob: 3537aa721b1949ae62f54e0b15f2802693ca255d [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>
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010043
44void *tall_pcu_ctx;
45int16_t spoof_mnc = 0, spoof_mcc = 0;
46
47static void check_coding_scheme(GprsCodingScheme& cs, GprsCodingScheme::Mode mode)
48{
49 volatile unsigned expected_size;
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010050 bool need_padding;
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010051 GprsCodingScheme new_cs;
52
53 OSMO_ASSERT(cs.isValid());
54 OSMO_ASSERT(cs.isCompatible(mode));
55
56 /* Check static getBySizeUL() */
Jacob Erlbeckfc1b3e62016-01-11 09:58:11 +010057 expected_size = cs.usedSizeUL();
58 if (cs.spareBitsUL() > 0 && cs.isGprs())
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010059 expected_size += 1;
60 OSMO_ASSERT(expected_size == cs.sizeUL());
61 OSMO_ASSERT(cs == GprsCodingScheme::getBySizeUL(expected_size));
62
63 /* Check static sizeUL() */
Jacob Erlbeckfc1b3e62016-01-11 09:58:11 +010064 expected_size = cs.usedSizeDL();
65 if (cs.spareBitsDL() > 0 && cs.isGprs())
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010066 expected_size += 1;
67 OSMO_ASSERT(expected_size == cs.sizeDL());
68
Jacob Erlbeck392a5452015-12-14 10:38:29 +010069 /* Check data block sizes */
70 OSMO_ASSERT(cs.maxDataBlockBytes() * cs.numDataBlocks() < cs.maxBytesDL());
71 OSMO_ASSERT(cs.maxDataBlockBytes() * cs.numDataBlocks() < cs.maxBytesUL());
72
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010073 /* Check inc/dec */
74 new_cs = cs;
75 new_cs.inc(mode);
76 OSMO_ASSERT(new_cs.isCompatible(mode));
77 if (new_cs != cs) {
78 new_cs.dec(mode);
79 OSMO_ASSERT(new_cs.isCompatible(mode));
80 OSMO_ASSERT(new_cs == cs);
81 }
82 new_cs.dec(mode);
83 OSMO_ASSERT(new_cs.isCompatible(mode));
84 if (new_cs != cs) {
85 new_cs.inc(mode);
86 OSMO_ASSERT(new_cs.isCompatible(mode));
87 OSMO_ASSERT(new_cs == cs);
88 }
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010089
90 new_cs = cs;
91 new_cs.decToSingleBlock(&need_padding);
92 OSMO_ASSERT(new_cs.isFamilyCompatible(cs));
93 OSMO_ASSERT(cs.isFamilyCompatible(new_cs));
94 OSMO_ASSERT(cs.isCompatible(new_cs));
95 if (need_padding) {
Jacob Erlbeck215e18c2016-02-03 18:22:34 +010096 OSMO_ASSERT(new_cs.maxDataBlockBytes() ==
97 new_cs.optionalPaddingBits()/8 + cs.maxDataBlockBytes());
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010098 } else {
99 OSMO_ASSERT(new_cs.maxDataBlockBytes() == cs.maxDataBlockBytes());
100 }
101
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100102}
103
104static void test_coding_scheme()
105{
106 unsigned i;
107 unsigned last_size_UL;
108 unsigned last_size_DL;
109 GprsCodingScheme::Scheme gprs_schemes[] = {
110 GprsCodingScheme::CS1,
111 GprsCodingScheme::CS2,
112 GprsCodingScheme::CS3,
113 GprsCodingScheme::CS4
114 };
115 struct {
116 GprsCodingScheme::Scheme s;
117 bool is_gmsk;
118 } egprs_schemes[] = {
119 {GprsCodingScheme::MCS1, true},
120 {GprsCodingScheme::MCS2, true},
121 {GprsCodingScheme::MCS3, true},
122 {GprsCodingScheme::MCS4, true},
123 {GprsCodingScheme::MCS5, false},
124 {GprsCodingScheme::MCS6, false},
125 {GprsCodingScheme::MCS7, false},
126 {GprsCodingScheme::MCS8, false},
127 {GprsCodingScheme::MCS9, false},
128 };
129
130 printf("=== start %s ===\n", __func__);
131
132 GprsCodingScheme cs;
133 OSMO_ASSERT(!cs);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100134 OSMO_ASSERT(GprsCodingScheme::Scheme(cs) == GprsCodingScheme::UNKNOWN);
135 OSMO_ASSERT(cs == GprsCodingScheme(GprsCodingScheme::UNKNOWN));
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100136 OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::GPRS));
137 OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::EGPRS_GMSK));
138 OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::EGPRS));
139
140 last_size_UL = 0;
141 last_size_DL = 0;
142
143 for (i = 0; i < ARRAY_SIZE(gprs_schemes); i++) {
144 GprsCodingScheme current_cs(gprs_schemes[i]);
145 OSMO_ASSERT(current_cs.isGprs());
146 OSMO_ASSERT(!current_cs.isEgprs());
147 OSMO_ASSERT(!current_cs.isEgprsGmsk());
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100148 OSMO_ASSERT(GprsCodingScheme::Scheme(current_cs) == gprs_schemes[i]);
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100149 OSMO_ASSERT(current_cs == GprsCodingScheme(gprs_schemes[i]));
150
151 /* Check strong monotonicity */
152 OSMO_ASSERT(current_cs.maxBytesUL() > last_size_UL);
153 OSMO_ASSERT(current_cs.maxBytesDL() > last_size_DL);
154 last_size_UL = current_cs.maxBytesUL();
155 last_size_DL = current_cs.maxBytesDL();
156
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +0100157 /* Check header types */
158 OSMO_ASSERT(current_cs.headerTypeData() ==
159 GprsCodingScheme::HEADER_GPRS_DATA);
160 OSMO_ASSERT(current_cs.headerTypeControl() ==
161 GprsCodingScheme::HEADER_GPRS_CONTROL);
162
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100163 check_coding_scheme(current_cs, GprsCodingScheme::GPRS);
164 }
165 OSMO_ASSERT(i == 4);
166
167 last_size_UL = 0;
168 last_size_DL = 0;
169
170 for (i = 0; i < ARRAY_SIZE(egprs_schemes); i++) {
171 GprsCodingScheme current_cs(egprs_schemes[i].s);
172 OSMO_ASSERT(!current_cs.isGprs());
173 OSMO_ASSERT(current_cs.isEgprs());
174 OSMO_ASSERT(!!current_cs.isEgprsGmsk() == !!egprs_schemes[i].is_gmsk);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100175 OSMO_ASSERT(GprsCodingScheme::Scheme(current_cs) == egprs_schemes[i].s);
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100176 OSMO_ASSERT(current_cs == GprsCodingScheme(egprs_schemes[i].s));
177
178 /* Check strong monotonicity */
179 OSMO_ASSERT(current_cs.maxBytesUL() > last_size_UL);
180 OSMO_ASSERT(current_cs.maxBytesDL() > last_size_DL);
181 last_size_UL = current_cs.maxBytesUL();
182 last_size_DL = current_cs.maxBytesDL();
183
184 if (egprs_schemes[i].is_gmsk)
185 check_coding_scheme(current_cs, GprsCodingScheme::EGPRS_GMSK);
186 check_coding_scheme(current_cs, GprsCodingScheme::EGPRS);
187 }
188 OSMO_ASSERT(i == 9);
189
190 printf("=== end %s ===\n", __func__);
191}
192
Jacob Erlbeck38f18692016-02-01 10:08:00 +0100193static void test_rlc_unit_decoder()
Jacob Erlbeck61679252015-12-11 18:25:21 +0100194{
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100195 struct gprs_rlc_data_block_info rdbi = {0};
Jacob Erlbeck61679252015-12-11 18:25:21 +0100196 GprsCodingScheme cs;
197 uint8_t data[74];
198 Decoding::RlcData chunks[16];
199 volatile int num_chunks = 0;
200 uint32_t tlli, tlli2;
201 unsigned int offs;
202
203
204 printf("=== start %s ===\n", __func__);
205
206 /* TS 44.060, B.1 */
207 cs = GprsCodingScheme::CS4;
208 rdbi.data_len = cs.maxDataBlockBytes();
209 rdbi.e = 0;
210 rdbi.ti = 0;
211 rdbi.cv = 15;
212 tlli = 0;
213 offs = 0;
214 data[offs++] = (11 << 2) | (1 << 1) | (0 << 0);
215 data[offs++] = (26 << 2) | (1 << 1) | (1 << 0);
216 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
217 chunks, ARRAY_SIZE(chunks), &tlli);
218 OSMO_ASSERT(num_chunks == 3);
219 OSMO_ASSERT(tlli == 0);
220 OSMO_ASSERT(chunks[0].offset == 2);
221 OSMO_ASSERT(chunks[0].length == 11);
222 OSMO_ASSERT(chunks[0].is_complete);
223 OSMO_ASSERT(chunks[1].offset == 13);
224 OSMO_ASSERT(chunks[1].length == 26);
225 OSMO_ASSERT(chunks[1].is_complete);
226 OSMO_ASSERT(chunks[2].offset == 39);
227 OSMO_ASSERT(chunks[2].length == cs.maxDataBlockBytes() - 39);
228 OSMO_ASSERT(!chunks[2].is_complete);
229
230 /* TS 44.060, B.2 */
231 cs = GprsCodingScheme::CS1;
232 rdbi.data_len = cs.maxDataBlockBytes();
233 rdbi.e = 0;
234 rdbi.ti = 0;
235 rdbi.cv = 15;
236 tlli = 0;
237 offs = 0;
238 data[offs++] = (0 << 2) | (0 << 1) | (1 << 0);
239 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
240 chunks, ARRAY_SIZE(chunks), &tlli);
241 OSMO_ASSERT(num_chunks == 1);
242 OSMO_ASSERT(tlli == 0);
243 OSMO_ASSERT(chunks[0].offset == 1);
244 OSMO_ASSERT(chunks[0].length == 19);
245 OSMO_ASSERT(!chunks[0].is_complete);
246
247 rdbi.e = 0;
248 rdbi.ti = 0;
249 rdbi.cv = 15;
250 tlli = 0;
251 offs = 0;
252 data[offs++] = (1 << 2) | (1 << 1) | (1 << 0);
253 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
254 chunks, ARRAY_SIZE(chunks), &tlli);
255 OSMO_ASSERT(num_chunks == 2);
256 OSMO_ASSERT(tlli == 0);
257 OSMO_ASSERT(chunks[0].offset == 1);
258 OSMO_ASSERT(chunks[0].length == 1);
259 OSMO_ASSERT(chunks[0].is_complete);
260 OSMO_ASSERT(chunks[1].offset == 2);
261 OSMO_ASSERT(chunks[1].length == 18);
262 OSMO_ASSERT(!chunks[1].is_complete);
263
264 /* TS 44.060, B.3 */
265 cs = GprsCodingScheme::CS1;
266 rdbi.data_len = cs.maxDataBlockBytes();
267 rdbi.e = 0;
268 rdbi.ti = 0;
269 rdbi.cv = 15;
270 tlli = 0;
271 offs = 0;
272 data[offs++] = (7 << 2) | (1 << 1) | (0 << 0);
273 data[offs++] = (11 << 2) | (0 << 1) | (1 << 0);
274 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
275 chunks, ARRAY_SIZE(chunks), &tlli);
276 OSMO_ASSERT(num_chunks == 2);
277 OSMO_ASSERT(tlli == 0);
278 OSMO_ASSERT(chunks[0].offset == 2);
279 OSMO_ASSERT(chunks[0].length == 7);
280 OSMO_ASSERT(chunks[0].is_complete);
281 OSMO_ASSERT(chunks[1].offset == 9);
282 OSMO_ASSERT(chunks[1].length == 11);
283 OSMO_ASSERT(chunks[1].is_complete);
284
285 /* TS 44.060, B.4 */
286 cs = GprsCodingScheme::CS1;
287 rdbi.data_len = cs.maxDataBlockBytes();
288 rdbi.e = 1;
289 rdbi.ti = 0;
290 rdbi.cv = 15;
291 tlli = 0;
292 offs = 0;
293 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
294 chunks, ARRAY_SIZE(chunks), &tlli);
295 OSMO_ASSERT(num_chunks == 1);
296 OSMO_ASSERT(tlli == 0);
297 OSMO_ASSERT(chunks[0].offset == 0);
298 OSMO_ASSERT(chunks[0].length == 20);
299 OSMO_ASSERT(!chunks[0].is_complete);
300
301 /* TS 44.060, B.6 */
302 cs = GprsCodingScheme::CS1;
303 rdbi.data_len = cs.maxDataBlockBytes();
304 rdbi.e = 1;
305 rdbi.ti = 0;
306 rdbi.cv = 0;
307 tlli = 0;
308 offs = 0;
309 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
310 chunks, ARRAY_SIZE(chunks), &tlli);
311 OSMO_ASSERT(num_chunks == 1);
312 OSMO_ASSERT(tlli == 0);
313 OSMO_ASSERT(chunks[0].offset == 0);
314 OSMO_ASSERT(chunks[0].length == 20);
315 OSMO_ASSERT(chunks[0].is_complete);
316
317 /* TS 44.060, B.8.1 */
318 cs = GprsCodingScheme::MCS4;
319 rdbi.data_len = cs.maxDataBlockBytes();
320 rdbi.e = 0;
321 rdbi.ti = 0;
322 rdbi.cv = 15;
323 tlli = 0;
324 offs = 0;
325 data[offs++] = (11 << 1) | (0 << 0);
326 data[offs++] = (26 << 1) | (1 << 0);
327 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
328 chunks, ARRAY_SIZE(chunks), &tlli);
329 OSMO_ASSERT(num_chunks == 3);
330 OSMO_ASSERT(tlli == 0);
331 OSMO_ASSERT(chunks[0].offset == 2);
332 OSMO_ASSERT(chunks[0].length == 11);
333 OSMO_ASSERT(chunks[0].is_complete);
334 OSMO_ASSERT(chunks[1].offset == 13);
335 OSMO_ASSERT(chunks[1].length == 26);
336 OSMO_ASSERT(chunks[1].is_complete);
337 OSMO_ASSERT(chunks[2].offset == 39);
338 OSMO_ASSERT(chunks[2].length == 5);
339 OSMO_ASSERT(!chunks[2].is_complete);
340
341 /* TS 44.060, B.8.2 */
342
343 /* Note that the spec confuses the byte numbering here, since it
344 * includes the FBI/E header bits into the N2 octet count which
345 * is not consistent with Section 10.3a.1 & 10.3a.2. */
346
347 cs = GprsCodingScheme::MCS2;
348 rdbi.data_len = cs.maxDataBlockBytes();
349 rdbi.e = 0;
350 rdbi.ti = 0;
351 rdbi.cv = 15;
352 tlli = 0;
353 offs = 0;
354 data[offs++] = (15 << 1) | (1 << 0);
355 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
356 chunks, ARRAY_SIZE(chunks), &tlli);
357 OSMO_ASSERT(num_chunks == 2);
358 OSMO_ASSERT(tlli == 0);
359 OSMO_ASSERT(chunks[0].offset == 1);
360 OSMO_ASSERT(chunks[0].length == 15);
361 OSMO_ASSERT(chunks[0].is_complete);
362 OSMO_ASSERT(chunks[1].offset == 16);
363 OSMO_ASSERT(chunks[1].length == 12);
364 OSMO_ASSERT(!chunks[1].is_complete);
365
366 rdbi.e = 0;
367 rdbi.ti = 0;
368 rdbi.cv = 15;
369 tlli = 0;
370 offs = 0;
371 data[offs++] = ( 0 << 1) | (0 << 0);
372 data[offs++] = ( 7 << 1) | (0 << 0);
373 data[offs++] = (18 << 1) | (1 << 0); /* Differs from spec's N2-11 = 17 */
374 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
375 chunks, ARRAY_SIZE(chunks), &tlli);
376 OSMO_ASSERT(num_chunks == 3);
377 OSMO_ASSERT(tlli == 0);
378 OSMO_ASSERT(chunks[0].offset == 3);
379 OSMO_ASSERT(chunks[0].length == 0);
380 OSMO_ASSERT(chunks[0].is_complete);
381 OSMO_ASSERT(chunks[1].offset == 3);
382 OSMO_ASSERT(chunks[1].length == 7);
383 OSMO_ASSERT(chunks[1].is_complete);
384 OSMO_ASSERT(chunks[2].offset == 10);
385 OSMO_ASSERT(chunks[2].length == 18);
386 OSMO_ASSERT(chunks[2].is_complete);
387
388 rdbi.e = 0;
389 rdbi.ti = 0;
390 rdbi.cv = 0;
391 tlli = 0;
392 offs = 0;
393 data[offs++] = ( 6 << 1) | (0 << 0);
394 data[offs++] = (12 << 1) | (0 << 0);
395 data[offs++] = (127 << 1) | (1 << 0);
396 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
397 chunks, ARRAY_SIZE(chunks), &tlli);
398 OSMO_ASSERT(num_chunks == 2);
399 OSMO_ASSERT(tlli == 0);
400 OSMO_ASSERT(chunks[0].offset == 3);
401 OSMO_ASSERT(chunks[0].length == 6);
402 OSMO_ASSERT(chunks[0].is_complete);
403 OSMO_ASSERT(chunks[1].offset == 9);
404 OSMO_ASSERT(chunks[1].length == 12);
405 OSMO_ASSERT(chunks[1].is_complete);
406
407 /* TS 44.060, B.8.3 */
408
409 /* Note that the spec confuses the byte numbering here, too (see above) */
410
411 cs = GprsCodingScheme::MCS2;
412 rdbi.data_len = cs.maxDataBlockBytes();
413 rdbi.e = 1;
414 rdbi.ti = 0;
415 rdbi.cv = 0;
416 tlli = 0;
417 offs = 0;
418 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
419 chunks, ARRAY_SIZE(chunks), &tlli);
420 OSMO_ASSERT(num_chunks == 1);
421 OSMO_ASSERT(tlli == 0);
422 OSMO_ASSERT(chunks[0].offset == 0);
423 OSMO_ASSERT(chunks[0].length == 28);
424 OSMO_ASSERT(chunks[0].is_complete);
425
426 /* CS-1, TLLI, last block, single chunk until the end of the block */
427 cs = GprsCodingScheme::CS1;
428 rdbi.data_len = cs.maxDataBlockBytes();
429 rdbi.e = 1;
430 rdbi.ti = 1;
431 rdbi.cv = 0;
432 tlli = 0;
433 tlli2 = 0xffeeddcc;
434 offs = 0;
435 data[offs++] = tlli2 >> 24;
436 data[offs++] = tlli2 >> 16;
437 data[offs++] = tlli2 >> 8;
438 data[offs++] = tlli2 >> 0;
439 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
440 chunks, ARRAY_SIZE(chunks), &tlli);
441 OSMO_ASSERT(num_chunks == 1);
442 OSMO_ASSERT(tlli == tlli2);
443 OSMO_ASSERT(chunks[0].offset == 4);
444 OSMO_ASSERT(chunks[0].length == 16);
445 OSMO_ASSERT(chunks[0].is_complete);
446
447 /* Like TS 44.060, B.2, first RLC block but with TLLI */
448 cs = GprsCodingScheme::CS1;
449 rdbi.data_len = cs.maxDataBlockBytes();
450 rdbi.e = 0;
451 rdbi.ti = 1;
452 rdbi.cv = 15;
453 tlli = 0;
454 tlli2 = 0xffeeddbb;
455 offs = 0;
456 data[offs++] = (0 << 2) | (0 << 1) | (1 << 0);
457 data[offs++] = tlli2 >> 24;
458 data[offs++] = tlli2 >> 16;
459 data[offs++] = tlli2 >> 8;
460 data[offs++] = tlli2 >> 0;
461 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
462 chunks, ARRAY_SIZE(chunks), &tlli);
463 OSMO_ASSERT(num_chunks == 1);
464 OSMO_ASSERT(tlli == tlli2);
465 OSMO_ASSERT(chunks[0].offset == 5);
466 OSMO_ASSERT(chunks[0].length == 15);
467 OSMO_ASSERT(!chunks[0].is_complete);
468
469 /* Like TS 44.060, B.8.1 but with TLLI */
470 cs = GprsCodingScheme::MCS4;
471 rdbi.data_len = cs.maxDataBlockBytes();
472 rdbi.e = 0;
473 rdbi.ti = 1;
474 rdbi.cv = 15;
475 tlli = 0;
476 tlli2 = 0xffeeddaa;
477 offs = 0;
478 data[offs++] = (11 << 1) | (0 << 0);
479 data[offs++] = (26 << 1) | (1 << 0);
480 /* Little endian */
481 data[offs++] = tlli2 >> 0;
482 data[offs++] = tlli2 >> 8;
483 data[offs++] = tlli2 >> 16;
484 data[offs++] = tlli2 >> 24;
485 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
486 chunks, ARRAY_SIZE(chunks), &tlli);
487 OSMO_ASSERT(num_chunks == 3);
488 OSMO_ASSERT(tlli == tlli2);
489 OSMO_ASSERT(chunks[0].offset == 6);
490 OSMO_ASSERT(chunks[0].length == 11);
491 OSMO_ASSERT(chunks[0].is_complete);
492 OSMO_ASSERT(chunks[1].offset == 17);
493 OSMO_ASSERT(chunks[1].length == 26);
494 OSMO_ASSERT(chunks[1].is_complete);
495 OSMO_ASSERT(chunks[2].offset == 43);
496 OSMO_ASSERT(chunks[2].length == 1);
497 OSMO_ASSERT(!chunks[2].is_complete);
498
Aravind Sirsikar3463bd42016-09-15 17:19:54 +0530499 rdbi.e = 0;
500 rdbi.ti = 0;
501 rdbi.cv = 1;
502 tlli = 0;
503 offs = 0;
504 data[offs++] = 1;
505 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
506 chunks, ARRAY_SIZE(chunks), &tlli);
507
Aravind Sirsikar22a90192016-09-15 17:24:49 +0530508 OSMO_ASSERT(num_chunks == 2);
Aravind Sirsikar3463bd42016-09-15 17:19:54 +0530509 OSMO_ASSERT(chunks[0].offset == 1);
Aravind Sirsikar22a90192016-09-15 17:24:49 +0530510 OSMO_ASSERT(chunks[0].length == 0);
511 OSMO_ASSERT(chunks[0].is_complete);
512
513 OSMO_ASSERT(chunks[1].offset == 1);
514 OSMO_ASSERT(chunks[1].length == 43);
515 OSMO_ASSERT(!chunks[1].is_complete);
Aravind Sirsikar3463bd42016-09-15 17:19:54 +0530516
Jacob Erlbeck61679252015-12-11 18:25:21 +0100517 printf("=== end %s ===\n", __func__);
518}
519
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100520static void test_rlc_unit_encoder()
521{
522 struct gprs_rlc_data_block_info rdbi = {0};
523 GprsCodingScheme cs;
524 uint8_t data[74];
525 uint8_t llc_data[1500] = {0,};
526 int num_chunks = 0;
527 int write_offset;
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200528 int count_payload;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100529 struct gprs_llc llc;
530 Encoding::AppendResult ar;
531
532 printf("=== start %s ===\n", __func__);
533
534 llc.init();
535
536 /* TS 44.060, B.1 */
537 cs = GprsCodingScheme::CS4;
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530538 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100539 num_chunks = 0;
540 write_offset = 0;
541 memset(data, 0, sizeof(data));
542
543 llc.reset();
544 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200545 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100546
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100547 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200548 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100549
550 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
551 OSMO_ASSERT(rdbi.e == 0);
552 OSMO_ASSERT(write_offset == 1 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200553 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100554 OSMO_ASSERT(num_chunks == 1);
555
556 llc.reset();
557 llc.put_frame(llc_data, 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200558 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100559
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100560 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200561 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100562
563 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
564 OSMO_ASSERT(rdbi.e == 0);
565 OSMO_ASSERT(write_offset == 2 + 11 + 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200566 OSMO_ASSERT(count_payload == 26);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100567 OSMO_ASSERT(num_chunks == 2);
568
569 llc.reset();
570 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200571 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100572
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100573 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200574 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100575
576 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
577 OSMO_ASSERT(rdbi.e == 0);
578 OSMO_ASSERT(rdbi.cv != 0);
579 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200580 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100581 OSMO_ASSERT(num_chunks == 3);
582
583 OSMO_ASSERT(data[0] == ((11 << 2) | (1 << 1) | (0 << 0)));
584 OSMO_ASSERT(data[1] == ((26 << 2) | (1 << 1) | (1 << 0)));
585 OSMO_ASSERT(data[2] == 0);
586
587 /* TS 44.060, B.2 */
588 cs = GprsCodingScheme::CS1;
589
590 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530591 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100592 num_chunks = 0;
593 write_offset = 0;
594 memset(data, 0, sizeof(data));
595
596 llc.reset();
597 llc.put_frame(llc_data, 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200598 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100599
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100600 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200601 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100602
603 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
604 OSMO_ASSERT(rdbi.e == 0);
605 OSMO_ASSERT(write_offset == 1 + 19);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200606 OSMO_ASSERT(count_payload == 19);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100607 OSMO_ASSERT(num_chunks == 1);
608
609 OSMO_ASSERT(data[0] == ((0 << 2) | (0 << 1) | (1 << 0)));
610 OSMO_ASSERT(data[1] == 0);
611
612 /* Block 2 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530613 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100614 num_chunks = 0;
615 write_offset = 0;
616 memset(data, 0, sizeof(data));
617
618 OSMO_ASSERT(llc.chunk_size() == 1);
619
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200620 count_payload = -1;
621
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100622 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200623 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100624
625 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
626 OSMO_ASSERT(rdbi.e == 0);
627 OSMO_ASSERT(write_offset == 1 + 1);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200628 OSMO_ASSERT(count_payload == 1);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100629 OSMO_ASSERT(num_chunks == 1);
630
631 llc.reset();
632 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200633 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100634
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100635 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200636 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100637
638 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
639 OSMO_ASSERT(rdbi.e == 0);
640 OSMO_ASSERT(write_offset == 1 + 1 + 18);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200641 OSMO_ASSERT(count_payload == 18);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100642 OSMO_ASSERT(num_chunks == 2);
643
644 OSMO_ASSERT(data[0] == ((1 << 2) | (1 << 1) | (1 << 0)));
645 OSMO_ASSERT(data[1] == 0);
646
647 /* TS 44.060, B.3 */
648 cs = GprsCodingScheme::CS1;
649
650 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530651 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100652 num_chunks = 0;
653 write_offset = 0;
654 memset(data, 0, sizeof(data));
655
656 llc.reset();
657 llc.put_frame(llc_data, 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200658 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100659
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100660 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200661 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100662
663 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
664 OSMO_ASSERT(rdbi.e == 0);
665 OSMO_ASSERT(write_offset == 1 + 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200666 OSMO_ASSERT(count_payload == 7);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100667 OSMO_ASSERT(num_chunks == 1);
668
669 llc.reset();
670 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200671 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100672
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100673 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200674 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100675
676 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
677 OSMO_ASSERT(rdbi.e == 0);
678 OSMO_ASSERT(write_offset == 2 + 7 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200679 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100680 OSMO_ASSERT(num_chunks == 2);
681
682 OSMO_ASSERT(data[0] == ((7 << 2) | (1 << 1) | (0 << 0)));
683 OSMO_ASSERT(data[1] == ((11 << 2) | (0 << 1) | (1 << 0)));
684 OSMO_ASSERT(data[2] == 0);
685
686 /* TS 44.060, B.4 */
687 cs = GprsCodingScheme::CS1;
688
689 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530690 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100691 num_chunks = 0;
692 write_offset = 0;
693 memset(data, 0, sizeof(data));
694
695 llc.reset();
696 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200697 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100698
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100699 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200700 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100701
702 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
703 OSMO_ASSERT(rdbi.e == 1);
704 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200705 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100706 OSMO_ASSERT(num_chunks == 1);
707 OSMO_ASSERT(rdbi.cv != 0);
708
709 OSMO_ASSERT(data[0] == 0);
710
711 /* TS 44.060, B.5 */
712 cs = GprsCodingScheme::CS1;
713
714 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530715 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100716 num_chunks = 0;
717 write_offset = 0;
718 memset(data, 0, sizeof(data));
719
720 llc.reset();
721 llc.put_frame(llc_data, 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200722 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100723
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100724 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200725 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100726
727 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
728 OSMO_ASSERT(rdbi.e == 1);
729 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200730 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100731 OSMO_ASSERT(num_chunks == 1);
732 OSMO_ASSERT(rdbi.cv == 0);
733
734 OSMO_ASSERT(data[0] == 0);
735
736 /* TS 44.060, B.7 */
737 cs = GprsCodingScheme::CS1;
738
739 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530740 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100741 num_chunks = 0;
742 write_offset = 0;
743 memset(data, 0, sizeof(data));
744
745 llc.reset();
746 llc.put_frame(llc_data, 30);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200747 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100748
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100749 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200750 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100751
752 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
753 OSMO_ASSERT(rdbi.e == 1);
754 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200755 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100756 OSMO_ASSERT(num_chunks == 1);
757
758 OSMO_ASSERT(data[0] == 0);
759
760 /* Block 2 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530761 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100762 num_chunks = 0;
763 write_offset = 0;
764 memset(data, 0, sizeof(data));
765
766 OSMO_ASSERT(llc.chunk_size() == 10);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200767 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100768
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100769 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200770 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100771
772 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
773 OSMO_ASSERT(rdbi.e == 0);
774 OSMO_ASSERT(write_offset == 1 + 10);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200775 OSMO_ASSERT(count_payload == 10);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100776 OSMO_ASSERT(num_chunks == 1);
777
778 llc.reset();
779 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200780 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100781
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100782 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200783 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100784
785 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
786 OSMO_ASSERT(rdbi.e == 0);
787 OSMO_ASSERT(write_offset == 1 + 10 + 9);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200788 OSMO_ASSERT(count_payload == 9);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100789 OSMO_ASSERT(num_chunks == 2);
790
791 OSMO_ASSERT(data[0] == ((10 << 2) | (1 << 1) | (1 << 0)));
792 OSMO_ASSERT(data[1] == 0);
793
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100794 /* TS 44.060, B.8.1 */
795 cs = GprsCodingScheme::MCS4;
796
797 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530798 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100799 num_chunks = 0;
800 write_offset = 0;
801 memset(data, 0, sizeof(data));
802
803 llc.reset();
804 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200805 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100806
807 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200808 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100809
810 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
811 OSMO_ASSERT(rdbi.e == 0);
812 OSMO_ASSERT(write_offset == 1 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200813 OSMO_ASSERT(count_payload == 11);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100814 OSMO_ASSERT(num_chunks == 1);
815
816 llc.reset();
817 llc.put_frame(llc_data, 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200818 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100819
820 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200821 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100822
823 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
824 OSMO_ASSERT(rdbi.e == 0);
825 OSMO_ASSERT(write_offset == 2 + 11 + 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200826 OSMO_ASSERT(count_payload == 26);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100827 OSMO_ASSERT(num_chunks == 2);
828
829 llc.reset();
830 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200831 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100832
833 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200834 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100835
836 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
837 OSMO_ASSERT(rdbi.e == 0);
838 OSMO_ASSERT(rdbi.cv != 0);
839 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200840 OSMO_ASSERT(count_payload == 5);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100841 OSMO_ASSERT(num_chunks == 3);
842
843 OSMO_ASSERT(data[0] == ((11 << 1) | (0 << 0)));
844 OSMO_ASSERT(data[1] == ((26 << 1) | (1 << 0)));
845 OSMO_ASSERT(data[2] == 0);
846
847 /* TS 44.060, B.8.2 */
848
849 /* Note that the spec confuses the byte numbering here, since it
850 * includes the FBI/E header bits into the N2 octet count which
851 * is not consistent with Section 10.3a.1 & 10.3a.2. */
852
853 cs = GprsCodingScheme::MCS2;
854
855 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530856 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100857 num_chunks = 0;
858 write_offset = 0;
859 memset(data, 0, sizeof(data));
860
861 llc.reset();
862 llc.put_frame(llc_data, 15);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200863 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100864
865 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200866 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100867
868 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
869 OSMO_ASSERT(rdbi.e == 0);
870 OSMO_ASSERT(write_offset == 1 + 15);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200871 OSMO_ASSERT(count_payload == 15);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100872 OSMO_ASSERT(num_chunks == 1);
873
874 llc.reset();
875 llc.put_frame(llc_data, 12);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200876 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100877
878 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200879 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100880
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200881 /* no LI here, becaues there are exact 12 bytes left. Put LI into next frame */
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100882 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
883 OSMO_ASSERT(rdbi.e == 0);
884 OSMO_ASSERT(rdbi.cv != 0);
885 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200886 OSMO_ASSERT(count_payload == 12);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100887 OSMO_ASSERT(num_chunks == 2);
888
889 OSMO_ASSERT(data[0] == ((15 << 1) | (1 << 0)));
890 OSMO_ASSERT(data[1] == 0);
891
892 /* Block 2 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530893 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100894 num_chunks = 0;
895 write_offset = 0;
896 memset(data, 0, sizeof(data));
897
898 OSMO_ASSERT(llc.chunk_size() == 0);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200899 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100900
901 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200902 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100903
904 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
905 OSMO_ASSERT(rdbi.e == 0);
906 OSMO_ASSERT(write_offset == 1 + 0);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200907 OSMO_ASSERT(count_payload == 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100908 OSMO_ASSERT(num_chunks == 1);
909
910 llc.reset();
911 llc.put_frame(llc_data, 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200912 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100913
914 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200915 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100916
917 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
918 OSMO_ASSERT(rdbi.e == 0);
919 OSMO_ASSERT(rdbi.cv != 0);
920 OSMO_ASSERT(write_offset == 2 + 0 + 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200921 OSMO_ASSERT(count_payload == 7);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100922 OSMO_ASSERT(num_chunks == 2);
923
924 llc.reset();
925 llc.put_frame(llc_data, 18);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200926 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100927
928 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200929 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100930
931 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
932 OSMO_ASSERT(rdbi.e == 0);
933 OSMO_ASSERT(rdbi.cv != 0);
934 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200935 OSMO_ASSERT(count_payload == 18);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100936 OSMO_ASSERT(num_chunks == 3);
937
938 OSMO_ASSERT(data[0] == ((0 << 1) | (0 << 0)));
939 OSMO_ASSERT(data[1] == ((7 << 1) | (0 << 0)));
940 OSMO_ASSERT(data[2] == ((18 << 1) | (1 << 0)));
941 OSMO_ASSERT(data[3] == 0);
942
943 /* Block 3 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530944 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100945 num_chunks = 0;
946 write_offset = 0;
947 memset(data, 0, sizeof(data));
948
949 llc.reset();
950 llc.put_frame(llc_data, 6);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200951 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100952
953 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200954 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100955
956 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
957 OSMO_ASSERT(rdbi.e == 0);
958 OSMO_ASSERT(write_offset == 1 + 6);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200959 OSMO_ASSERT(count_payload == 6);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100960 OSMO_ASSERT(num_chunks == 1);
961
962 llc.reset();
963 llc.put_frame(llc_data, 12);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200964 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100965
966 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200967 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100968
969 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
970 OSMO_ASSERT(rdbi.e == 0);
971 OSMO_ASSERT(rdbi.cv == 0);
972 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200973 OSMO_ASSERT(count_payload == 12);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100974 OSMO_ASSERT(num_chunks == 3);
975
976 OSMO_ASSERT(data[0] == ((6 << 1) | (0 << 0)));
977 OSMO_ASSERT(data[1] == ((12 << 1) | (0 << 0)));
978 OSMO_ASSERT(data[2] == ((127 << 1) | (1 << 0)));
979 OSMO_ASSERT(data[3] == 0);
980
981 /* TS 44.060, B.8.3 */
982
983 /* Note that the spec confuses the byte numbering here, too (see above) */
984
985 cs = GprsCodingScheme::MCS2;
986
987 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530988 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100989 num_chunks = 0;
990 write_offset = 0;
991 memset(data, 0, sizeof(data));
992
993 llc.reset();
994 llc.put_frame(llc_data, rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200995 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100996
997 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200998 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100999
1000 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
1001 OSMO_ASSERT(rdbi.e == 1);
1002 OSMO_ASSERT(rdbi.cv == 0);
1003 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001004 OSMO_ASSERT(count_payload == rdbi.data_len);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001005 OSMO_ASSERT(num_chunks == 1);
1006
1007 OSMO_ASSERT(data[0] == 0);
1008
1009 /* Final block with an LLC of size data_len-1 */
1010
1011 cs = GprsCodingScheme::MCS2;
1012
1013 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301014 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001015 num_chunks = 0;
1016 write_offset = 0;
1017 memset(data, 0, sizeof(data));
1018
1019 llc.reset();
1020 llc.put_frame(llc_data, rdbi.data_len - 1);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001021 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001022
1023 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001024 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001025
1026 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
1027 OSMO_ASSERT(rdbi.e == 0);
1028 OSMO_ASSERT(rdbi.cv == 0);
1029 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001030 OSMO_ASSERT(count_payload == rdbi.data_len - 1);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001031 OSMO_ASSERT(num_chunks == 1);
1032
1033 OSMO_ASSERT(data[0] == (((rdbi.data_len-1) << 1) | (1 << 0)));
1034 OSMO_ASSERT(data[1] == 0);
1035
1036 /* Final block with an LLC of size data_len-2 */
1037
1038 cs = GprsCodingScheme::MCS2;
1039
1040 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301041 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001042 num_chunks = 0;
1043 write_offset = 0;
1044 memset(data, 0, sizeof(data));
1045
1046 llc.reset();
1047 llc.put_frame(llc_data, rdbi.data_len - 2);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001048 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001049
1050 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001051 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001052
1053 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
1054 OSMO_ASSERT(rdbi.e == 0);
1055 OSMO_ASSERT(rdbi.cv == 0);
1056 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001057 OSMO_ASSERT(count_payload == rdbi.data_len - 2);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001058 OSMO_ASSERT(num_chunks == 2);
1059
1060 OSMO_ASSERT(data[0] == (((rdbi.data_len-2) << 1) | (0 << 0)));
1061 OSMO_ASSERT(data[1] == ((127 << 1) | (1 << 0)));
1062 OSMO_ASSERT(data[2] == 0);
1063
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001064 printf("=== end %s ===\n", __func__);
1065}
1066
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001067static void test_rlc_unaligned_copy()
1068{
1069 uint8_t bits[256];
1070 uint8_t saved_block[256];
1071 uint8_t test_block[256];
1072 uint8_t out_block[256];
1073 GprsCodingScheme::Scheme scheme;
1074 int pattern;
1075 volatile unsigned int block_idx, i;
1076
1077 for (scheme = GprsCodingScheme::CS1;
1078 scheme < GprsCodingScheme::NUM_SCHEMES;
1079 scheme = GprsCodingScheme::Scheme(scheme + 1))
1080 {
1081 GprsCodingScheme cs(scheme);
1082
1083 for (pattern = 0; pattern <= 0xff; pattern += 0xff) {
1084 /* prepare test block */
1085 test_block[0] = pattern ^ 0xff;
1086 for (i = 1; i + 1 < cs.maxDataBlockBytes(); i++)
1087 test_block[i] = i;
1088 test_block[cs.maxDataBlockBytes()-1] = pattern ^ 0xff;
1089
1090 for (block_idx = 0;
1091 block_idx < cs.numDataBlocks();
1092 block_idx++)
1093 {
1094 struct gprs_rlc_data_info rlc;
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301095 gprs_rlc_data_info_init_dl(&rlc, cs, false, 0);
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001096
1097 memset(bits, pattern, sizeof(bits));
1098 Decoding::rlc_copy_to_aligned_buffer(
1099 &rlc, block_idx, bits, saved_block);
1100
1101 fprintf(stderr,
1102 "Test data block: %s\n",
1103 osmo_hexdump(test_block, cs.maxDataBlockBytes()));
1104
1105 Encoding::rlc_copy_from_aligned_buffer(
1106 &rlc, block_idx, bits, test_block);
1107
1108 fprintf(stderr,
1109 "Encoded message block, %s, idx %d, "
1110 "pattern %02x: %s\n",
1111 rlc.cs.name(), block_idx, pattern,
1112 osmo_hexdump(bits, cs.sizeDL()));
1113
1114 Decoding::rlc_copy_to_aligned_buffer(
1115 &rlc, block_idx, bits, out_block);
1116
1117 fprintf(stderr,
1118 "Out data block: %s\n",
1119 osmo_hexdump(out_block, cs.maxDataBlockBytes()));
1120 /* restore original bits */
1121 Encoding::rlc_copy_from_aligned_buffer(
1122 &rlc, block_idx, bits, saved_block);
1123
1124 OSMO_ASSERT(memcmp(test_block, out_block,
1125 rlc.cs.maxDataBlockBytes()) == 0);
1126
1127 for (i = 0; i < sizeof(bits); i++)
1128 OSMO_ASSERT(bits[i] == pattern);
1129 }
1130 }
1131 }
1132}
1133
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001134static void test_rlc_info_init()
1135{
1136 struct gprs_rlc_data_info rlc;
1137
1138 printf("=== start %s ===\n", __func__);
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301139 gprs_rlc_data_info_init_dl(&rlc,
1140 GprsCodingScheme(GprsCodingScheme::CS1), false, 0);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001141 OSMO_ASSERT(rlc.num_data_blocks == 1);
1142 OSMO_ASSERT(rlc.data_offs_bits[0] == 24);
1143 OSMO_ASSERT(rlc.block_info[0].data_len == 20);
1144
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301145 gprs_rlc_data_info_init_dl(&rlc,
1146 GprsCodingScheme(GprsCodingScheme::MCS1), false, 0);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001147 OSMO_ASSERT(rlc.num_data_blocks == 1);
1148 OSMO_ASSERT(rlc.data_offs_bits[0] == 33);
1149 OSMO_ASSERT(rlc.block_info[0].data_len == 22);
1150
1151 printf("=== end %s ===\n", __func__);
1152}
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001153
1154static const struct log_info_cat default_categories[] = {
1155 {"DCSN1", "\033[1;31m", "Concrete Syntax Notation One (CSN1)", LOGL_INFO, 0},
1156 {"DL1IF", "\033[1;32m", "GPRS PCU L1 interface (L1IF)", LOGL_DEBUG, 1},
1157 {"DRLCMAC", "\033[0;33m", "GPRS RLC/MAC layer (RLCMAC)", LOGL_DEBUG, 1},
1158 {"DRLCMACDATA", "\033[0;33m", "GPRS RLC/MAC layer Data (RLCMAC)", LOGL_DEBUG, 1},
1159 {"DRLCMACDL", "\033[1;33m", "GPRS RLC/MAC layer Downlink (RLCMAC)", LOGL_DEBUG, 1},
1160 {"DRLCMACUL", "\033[1;36m", "GPRS RLC/MAC layer Uplink (RLCMAC)", LOGL_DEBUG, 1},
1161 {"DRLCMACSCHED", "\033[0;36m", "GPRS RLC/MAC layer Scheduling (RLCMAC)", LOGL_DEBUG, 1},
1162 {"DRLCMACMEAS", "\033[1;31m", "GPRS RLC/MAC layer Measurements (RLCMAC)", LOGL_INFO, 1},
1163 {"DNS","\033[1;34m", "GPRS Network Service Protocol (NS)", LOGL_INFO , 1},
1164 {"DBSSGP","\033[1;34m", "GPRS BSS Gateway Protocol (BSSGP)", LOGL_INFO , 1},
1165 {"DPCU", "\033[1;35m", "GPRS Packet Control Unit (PCU)", LOGL_NOTICE, 1},
1166};
1167
1168static int filter_fn(const struct log_context *ctx,
1169 struct log_target *tar)
1170{
1171 return 1;
1172}
1173
1174const struct log_info debug_log_info = {
1175 filter_fn,
1176 (struct log_info_cat*)default_categories,
1177 ARRAY_SIZE(default_categories),
1178};
1179
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301180static void setup_bts(BTS *the_bts, uint8_t ts_no, uint8_t cs = 1)
1181{
1182 gprs_rlcmac_bts *bts;
1183 gprs_rlcmac_trx *trx;
1184
1185 bts = the_bts->bts_data();
1186 bts->egprs_enabled = true;
1187 bts->alloc_algorithm = alloc_algorithm_a;
1188 bts->initial_cs_dl = cs;
1189 bts->initial_cs_ul = cs;
1190 trx = &bts->trx[0];
1191 trx->pdch[ts_no].enable();
1192}
1193static void uplink_header_type_2_parsing_test(BTS *the_bts,
1194 uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
1195 uint8_t ms_class)
1196{
1197 GprsMs *ms;
1198 struct pcu_l1_meas meas;
1199 int tfi = 0;
1200 gprs_rlcmac_bts *bts;
1201 RlcMacUplink_t ulreq = {0};
1202 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;
1206 bts = the_bts->bts_data();
1207
1208 tfi = 1;
1209
1210 struct gprs_rlc_data_info rlc;
1211 GprsCodingScheme cs;
1212 int rc, offs;
1213
1214 /*without padding*/
1215 cs = GprsCodingScheme::MCS5;
1216 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
1217 egprs2->r = 1;
1218 egprs2->si = 1;
1219 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001220 egprs2->tfi_hi = tfi & 0x03;
1221 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1222 egprs2->bsn1_hi = 0;
1223 egprs2->bsn1_lo = 0;
1224 egprs2->cps_hi = 3;
1225 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301226 egprs2->rsb = 0;
1227 egprs2->pi = 0;
1228 data[4] = 0x20; /* Setting E field */
1229 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1230 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);
1254 offs = rlc.data_offs_bits[0] / 8;
1255 OSMO_ASSERT(offs == 10);
1256 OSMO_ASSERT(rlc.num_data_blocks == 1);
1257 OSMO_ASSERT(rlc.tfi == 1);
1258 OSMO_ASSERT(rlc.block_info[0].e == 1);
1259 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1260 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1261
1262 egprs2->r = 1;
1263 egprs2->si = 1;
1264 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001265 egprs2->tfi_hi = tfi & 0x03;
1266 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1267 egprs2->bsn1_hi = 1;
1268 egprs2->bsn1_lo = 0;
1269 egprs2->cps_hi = 2;
1270 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301271 egprs2->rsb = 0;
1272 egprs2->pi = 0;
1273 data[10] = 0x20; /* Setting E field */
1274 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1275 offs = rlc.data_offs_bits[0] / 8;
1276 OSMO_ASSERT(offs == 10);
1277 OSMO_ASSERT(rlc.tfi == 1);
1278 OSMO_ASSERT(rlc.num_data_blocks == 1);
1279 OSMO_ASSERT(rlc.block_info[0].e == 1);
1280 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1281 OSMO_ASSERT(rlc.block_info[0].bsn == 1);
1282}
1283
1284static void uplink_header_type2_test(void)
1285{
1286 BTS the_bts;
1287 int ts_no = 7;
1288 uint32_t fn = 2654218;
1289 uint16_t qta = 31;
1290 uint32_t tlli = 0xf1223344;
1291 const char *imsi = "0011223344";
1292 uint8_t ms_class = 1;
1293 gprs_rlcmac_ul_tbf *ul_tbf;
1294 GprsMs *ms;
1295
1296 printf("=== start %s ===\n", __func__);
1297 setup_bts(&the_bts, ts_no, 10);
1298
1299 uplink_header_type_2_parsing_test(&the_bts, ts_no,
1300 tlli, &fn, qta, ms_class);
1301 printf("=== end %s ===\n", __func__);
1302}
1303
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301304static void uplink_header_type_1_parsing_test(BTS *the_bts,
1305 uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
1306 uint8_t ms_class)
1307{
1308 uint8_t trx_no = 0;
1309 int tfi = 0;
1310 struct gprs_rlcmac_pdch *pdch;
1311 gprs_rlcmac_bts *bts;
1312 uint8_t data[155] = {0};
1313 struct gprs_rlc_ul_header_egprs_1 *egprs1 = NULL;
1314 struct gprs_rlc_data_info rlc;
1315 GprsCodingScheme cs;
1316 int rc, offs;
1317
1318 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1319 bts = the_bts->bts_data();
1320
1321 tfi = 1;
1322
1323 /* MCS 7 */
1324 cs = GprsCodingScheme::MCS7;
1325 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1326 egprs1->si = 1;
1327 egprs1->r = 1;
1328 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001329 egprs1->tfi_hi = tfi & 0x03;
1330 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1331 egprs1->bsn1_hi = 0;
1332 egprs1->bsn1_lo = 0;
1333 egprs1->bsn2_hi = 1;
1334 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301335 egprs1->cps = 15;
1336 egprs1->rsb = 0;
1337 egprs1->pi = 0;
1338 data[5] = 0xc0;
1339 data[5 + 57] = 1;
1340 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1341 OSMO_ASSERT(rlc.num_data_blocks == 2);
1342 OSMO_ASSERT(rlc.block_info[0].e == 1);
1343 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1344 OSMO_ASSERT(rlc.block_info[1].e == 1);
1345 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1346 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1347 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1348 OSMO_ASSERT(rlc.tfi == 1);
1349
1350 /* MCS 8 */
1351 cs = GprsCodingScheme::MCS8;
1352 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1353 egprs1->si = 1;
1354 egprs1->r = 1;
1355 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001356 egprs1->tfi_hi = tfi & 0x03;
1357 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1358 egprs1->bsn1_hi = 0;
1359 egprs1->bsn1_lo = 0;
1360 egprs1->bsn2_hi = 1;
1361 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301362 egprs1->cps = 15;
1363 egprs1->rsb = 0;
1364 egprs1->pi = 0;
1365 data[5] = 0xc0;
1366 data[5 + 69] = 1;
1367 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1368 OSMO_ASSERT(rlc.num_data_blocks == 2);
1369 OSMO_ASSERT(rlc.block_info[0].e == 1);
1370 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1371 OSMO_ASSERT(rlc.block_info[1].e == 1);
1372 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1373 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1374 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1375 OSMO_ASSERT(rlc.tfi == 1);
1376
1377 /* MCS 9 */
1378 cs = GprsCodingScheme::MCS9;
1379 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1380 egprs1->si = 1;
1381 egprs1->r = 1;
1382 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001383 egprs1->tfi_hi = tfi & 0x03;
1384 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1385 egprs1->bsn1_hi = 0;
1386 egprs1->bsn1_lo = 0;
1387 egprs1->bsn2_hi = 1;
1388 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301389 egprs1->cps = 15;
1390 egprs1->rsb = 0;
1391 egprs1->pi = 0;
1392 data[5] = 0xc0;
1393 data[5 + 75] = 1;
1394 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1395 OSMO_ASSERT(rlc.num_data_blocks == 2);
1396 OSMO_ASSERT(rlc.block_info[0].e == 1);
1397 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1398 OSMO_ASSERT(rlc.block_info[1].e == 1);
1399 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1400 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1401 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1402 OSMO_ASSERT(rlc.tfi == 1);
1403}
1404
1405void uplink_header_type1_test(void)
1406{
1407 BTS the_bts;
1408 int ts_no = 7;
1409 uint32_t fn = 2654218;
1410 uint16_t qta = 31;
1411 uint32_t tlli = 0xf1223344;
1412 const char *imsi = "0011223344";
1413 uint8_t ms_class = 1;
1414 gprs_rlcmac_ul_tbf *ul_tbf;
1415 GprsMs *ms;
1416
1417 printf("=== start %s ===\n", __func__);
1418 setup_bts(&the_bts, ts_no, 12);
1419 uplink_header_type_1_parsing_test(&the_bts, ts_no, tlli, &fn,
1420 qta, ms_class);
1421 printf("=== end %s ===\n", __func__);
1422}
1423
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001424int main(int argc, char **argv)
1425{
1426 struct vty_app_info pcu_vty_info = {0};
1427
1428 tall_pcu_ctx = talloc_named_const(NULL, 1, "EdgeTest context");
1429 if (!tall_pcu_ctx)
1430 abort();
1431
1432 msgb_set_talloc_ctx(tall_pcu_ctx);
1433 osmo_init_logging(&debug_log_info);
1434 log_set_use_color(osmo_stderr_target, 0);
1435 log_set_print_filename(osmo_stderr_target, 0);
1436
1437 vty_init(&pcu_vty_info);
1438 pcu_vty_init(&debug_log_info);
1439
1440 test_coding_scheme();
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001441 test_rlc_info_init();
Jacob Erlbeck38f18692016-02-01 10:08:00 +01001442 test_rlc_unit_decoder();
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001443 test_rlc_unaligned_copy();
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001444 test_rlc_unit_encoder();
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001445
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301446 uplink_header_type2_test();
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301447 uplink_header_type1_test();
1448
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001449 if (getenv("TALLOC_REPORT_FULL"))
1450 talloc_report_full(tall_pcu_ctx, stderr);
1451 return EXIT_SUCCESS;
1452}
1453
1454/*
1455 * stubs that should not be reached
1456 */
1457extern "C" {
1458void l1if_pdch_req() { abort(); }
1459void l1if_connect_pdch() { abort(); }
1460void l1if_close_pdch() { abort(); }
1461void l1if_open_pdch() { abort(); }
1462}