blob: 592ad633b97f22cdb2c874db16d479bdc66da073 [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 /*
500 * TODO: simulate 3GPP TS 44.060 version 7.27.0 Release 7
501 * row 4 of Table 10.4.14a.1
502 * should expect 2 chunks. but currently it fails
503 * due to bug. The assert will be fixed along with actual
504 * fix
505 */
506 rdbi.e = 0;
507 rdbi.ti = 0;
508 rdbi.cv = 1;
509 tlli = 0;
510 offs = 0;
511 data[offs++] = 1;
512 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
513 chunks, ARRAY_SIZE(chunks), &tlli);
514
515 /*
516 * TODO: we expect 2 chunks here
517 * index 0 as complete and index 1 as incomplete
518 * due to current bug we see only 1 chunk
519 * assert for index 1 will be added in subsequent
520 * patch
521 */
522 OSMO_ASSERT(num_chunks == 1);
523 OSMO_ASSERT(chunks[0].offset == 1);
524 OSMO_ASSERT(chunks[0].length == 43);
525 OSMO_ASSERT(!chunks[0].is_complete);
526
Jacob Erlbeck61679252015-12-11 18:25:21 +0100527 printf("=== end %s ===\n", __func__);
528}
529
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100530static void test_rlc_unit_encoder()
531{
532 struct gprs_rlc_data_block_info rdbi = {0};
533 GprsCodingScheme cs;
534 uint8_t data[74];
535 uint8_t llc_data[1500] = {0,};
536 int num_chunks = 0;
537 int write_offset;
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200538 int count_payload;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100539 struct gprs_llc llc;
540 Encoding::AppendResult ar;
541
542 printf("=== start %s ===\n", __func__);
543
544 llc.init();
545
546 /* TS 44.060, B.1 */
547 cs = GprsCodingScheme::CS4;
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530548 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100549 num_chunks = 0;
550 write_offset = 0;
551 memset(data, 0, sizeof(data));
552
553 llc.reset();
554 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200555 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100556
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100557 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200558 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100559
560 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
561 OSMO_ASSERT(rdbi.e == 0);
562 OSMO_ASSERT(write_offset == 1 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200563 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100564 OSMO_ASSERT(num_chunks == 1);
565
566 llc.reset();
567 llc.put_frame(llc_data, 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200568 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100569
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100570 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200571 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100572
573 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
574 OSMO_ASSERT(rdbi.e == 0);
575 OSMO_ASSERT(write_offset == 2 + 11 + 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200576 OSMO_ASSERT(count_payload == 26);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100577 OSMO_ASSERT(num_chunks == 2);
578
579 llc.reset();
580 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200581 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100582
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100583 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200584 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100585
586 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
587 OSMO_ASSERT(rdbi.e == 0);
588 OSMO_ASSERT(rdbi.cv != 0);
589 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200590 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100591 OSMO_ASSERT(num_chunks == 3);
592
593 OSMO_ASSERT(data[0] == ((11 << 2) | (1 << 1) | (0 << 0)));
594 OSMO_ASSERT(data[1] == ((26 << 2) | (1 << 1) | (1 << 0)));
595 OSMO_ASSERT(data[2] == 0);
596
597 /* TS 44.060, B.2 */
598 cs = GprsCodingScheme::CS1;
599
600 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530601 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100602 num_chunks = 0;
603 write_offset = 0;
604 memset(data, 0, sizeof(data));
605
606 llc.reset();
607 llc.put_frame(llc_data, 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200608 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100609
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100610 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200611 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100612
613 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
614 OSMO_ASSERT(rdbi.e == 0);
615 OSMO_ASSERT(write_offset == 1 + 19);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200616 OSMO_ASSERT(count_payload == 19);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100617 OSMO_ASSERT(num_chunks == 1);
618
619 OSMO_ASSERT(data[0] == ((0 << 2) | (0 << 1) | (1 << 0)));
620 OSMO_ASSERT(data[1] == 0);
621
622 /* Block 2 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530623 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100624 num_chunks = 0;
625 write_offset = 0;
626 memset(data, 0, sizeof(data));
627
628 OSMO_ASSERT(llc.chunk_size() == 1);
629
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200630 count_payload = -1;
631
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100632 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200633 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100634
635 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
636 OSMO_ASSERT(rdbi.e == 0);
637 OSMO_ASSERT(write_offset == 1 + 1);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200638 OSMO_ASSERT(count_payload == 1);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100639 OSMO_ASSERT(num_chunks == 1);
640
641 llc.reset();
642 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200643 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100644
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100645 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200646 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100647
648 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
649 OSMO_ASSERT(rdbi.e == 0);
650 OSMO_ASSERT(write_offset == 1 + 1 + 18);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200651 OSMO_ASSERT(count_payload == 18);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100652 OSMO_ASSERT(num_chunks == 2);
653
654 OSMO_ASSERT(data[0] == ((1 << 2) | (1 << 1) | (1 << 0)));
655 OSMO_ASSERT(data[1] == 0);
656
657 /* TS 44.060, B.3 */
658 cs = GprsCodingScheme::CS1;
659
660 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530661 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100662 num_chunks = 0;
663 write_offset = 0;
664 memset(data, 0, sizeof(data));
665
666 llc.reset();
667 llc.put_frame(llc_data, 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200668 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100669
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100670 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200671 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100672
673 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
674 OSMO_ASSERT(rdbi.e == 0);
675 OSMO_ASSERT(write_offset == 1 + 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200676 OSMO_ASSERT(count_payload == 7);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100677 OSMO_ASSERT(num_chunks == 1);
678
679 llc.reset();
680 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200681 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100682
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100683 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200684 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100685
686 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
687 OSMO_ASSERT(rdbi.e == 0);
688 OSMO_ASSERT(write_offset == 2 + 7 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200689 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100690 OSMO_ASSERT(num_chunks == 2);
691
692 OSMO_ASSERT(data[0] == ((7 << 2) | (1 << 1) | (0 << 0)));
693 OSMO_ASSERT(data[1] == ((11 << 2) | (0 << 1) | (1 << 0)));
694 OSMO_ASSERT(data[2] == 0);
695
696 /* TS 44.060, B.4 */
697 cs = GprsCodingScheme::CS1;
698
699 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530700 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100701 num_chunks = 0;
702 write_offset = 0;
703 memset(data, 0, sizeof(data));
704
705 llc.reset();
706 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200707 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100708
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100709 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200710 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100711
712 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
713 OSMO_ASSERT(rdbi.e == 1);
714 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200715 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100716 OSMO_ASSERT(num_chunks == 1);
717 OSMO_ASSERT(rdbi.cv != 0);
718
719 OSMO_ASSERT(data[0] == 0);
720
721 /* TS 44.060, B.5 */
722 cs = GprsCodingScheme::CS1;
723
724 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530725 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100726 num_chunks = 0;
727 write_offset = 0;
728 memset(data, 0, sizeof(data));
729
730 llc.reset();
731 llc.put_frame(llc_data, 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200732 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100733
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100734 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200735 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100736
737 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
738 OSMO_ASSERT(rdbi.e == 1);
739 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200740 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100741 OSMO_ASSERT(num_chunks == 1);
742 OSMO_ASSERT(rdbi.cv == 0);
743
744 OSMO_ASSERT(data[0] == 0);
745
746 /* TS 44.060, B.7 */
747 cs = GprsCodingScheme::CS1;
748
749 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530750 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100751 num_chunks = 0;
752 write_offset = 0;
753 memset(data, 0, sizeof(data));
754
755 llc.reset();
756 llc.put_frame(llc_data, 30);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200757 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100758
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100759 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200760 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100761
762 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
763 OSMO_ASSERT(rdbi.e == 1);
764 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200765 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100766 OSMO_ASSERT(num_chunks == 1);
767
768 OSMO_ASSERT(data[0] == 0);
769
770 /* Block 2 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530771 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100772 num_chunks = 0;
773 write_offset = 0;
774 memset(data, 0, sizeof(data));
775
776 OSMO_ASSERT(llc.chunk_size() == 10);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200777 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100778
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100779 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200780 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100781
782 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
783 OSMO_ASSERT(rdbi.e == 0);
784 OSMO_ASSERT(write_offset == 1 + 10);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200785 OSMO_ASSERT(count_payload == 10);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100786 OSMO_ASSERT(num_chunks == 1);
787
788 llc.reset();
789 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200790 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100791
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100792 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200793 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100794
795 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
796 OSMO_ASSERT(rdbi.e == 0);
797 OSMO_ASSERT(write_offset == 1 + 10 + 9);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200798 OSMO_ASSERT(count_payload == 9);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100799 OSMO_ASSERT(num_chunks == 2);
800
801 OSMO_ASSERT(data[0] == ((10 << 2) | (1 << 1) | (1 << 0)));
802 OSMO_ASSERT(data[1] == 0);
803
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100804 /* TS 44.060, B.8.1 */
805 cs = GprsCodingScheme::MCS4;
806
807 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530808 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100809 num_chunks = 0;
810 write_offset = 0;
811 memset(data, 0, sizeof(data));
812
813 llc.reset();
814 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200815 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100816
817 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200818 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100819
820 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
821 OSMO_ASSERT(rdbi.e == 0);
822 OSMO_ASSERT(write_offset == 1 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200823 OSMO_ASSERT(count_payload == 11);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100824 OSMO_ASSERT(num_chunks == 1);
825
826 llc.reset();
827 llc.put_frame(llc_data, 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200828 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100829
830 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200831 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100832
833 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
834 OSMO_ASSERT(rdbi.e == 0);
835 OSMO_ASSERT(write_offset == 2 + 11 + 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200836 OSMO_ASSERT(count_payload == 26);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100837 OSMO_ASSERT(num_chunks == 2);
838
839 llc.reset();
840 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200841 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100842
843 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200844 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100845
846 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
847 OSMO_ASSERT(rdbi.e == 0);
848 OSMO_ASSERT(rdbi.cv != 0);
849 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200850 OSMO_ASSERT(count_payload == 5);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100851 OSMO_ASSERT(num_chunks == 3);
852
853 OSMO_ASSERT(data[0] == ((11 << 1) | (0 << 0)));
854 OSMO_ASSERT(data[1] == ((26 << 1) | (1 << 0)));
855 OSMO_ASSERT(data[2] == 0);
856
857 /* TS 44.060, B.8.2 */
858
859 /* Note that the spec confuses the byte numbering here, since it
860 * includes the FBI/E header bits into the N2 octet count which
861 * is not consistent with Section 10.3a.1 & 10.3a.2. */
862
863 cs = GprsCodingScheme::MCS2;
864
865 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530866 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100867 num_chunks = 0;
868 write_offset = 0;
869 memset(data, 0, sizeof(data));
870
871 llc.reset();
872 llc.put_frame(llc_data, 15);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200873 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100874
875 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200876 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100877
878 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
879 OSMO_ASSERT(rdbi.e == 0);
880 OSMO_ASSERT(write_offset == 1 + 15);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200881 OSMO_ASSERT(count_payload == 15);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100882 OSMO_ASSERT(num_chunks == 1);
883
884 llc.reset();
885 llc.put_frame(llc_data, 12);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200886 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100887
888 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200889 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100890
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200891 /* no LI here, becaues there are exact 12 bytes left. Put LI into next frame */
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100892 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
893 OSMO_ASSERT(rdbi.e == 0);
894 OSMO_ASSERT(rdbi.cv != 0);
895 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200896 OSMO_ASSERT(count_payload == 12);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100897 OSMO_ASSERT(num_chunks == 2);
898
899 OSMO_ASSERT(data[0] == ((15 << 1) | (1 << 0)));
900 OSMO_ASSERT(data[1] == 0);
901
902 /* Block 2 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530903 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100904 num_chunks = 0;
905 write_offset = 0;
906 memset(data, 0, sizeof(data));
907
908 OSMO_ASSERT(llc.chunk_size() == 0);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200909 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100910
911 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200912 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100913
914 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
915 OSMO_ASSERT(rdbi.e == 0);
916 OSMO_ASSERT(write_offset == 1 + 0);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200917 OSMO_ASSERT(count_payload == 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100918 OSMO_ASSERT(num_chunks == 1);
919
920 llc.reset();
921 llc.put_frame(llc_data, 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200922 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100923
924 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200925 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100926
927 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
928 OSMO_ASSERT(rdbi.e == 0);
929 OSMO_ASSERT(rdbi.cv != 0);
930 OSMO_ASSERT(write_offset == 2 + 0 + 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200931 OSMO_ASSERT(count_payload == 7);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100932 OSMO_ASSERT(num_chunks == 2);
933
934 llc.reset();
935 llc.put_frame(llc_data, 18);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200936 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100937
938 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200939 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100940
941 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
942 OSMO_ASSERT(rdbi.e == 0);
943 OSMO_ASSERT(rdbi.cv != 0);
944 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200945 OSMO_ASSERT(count_payload == 18);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100946 OSMO_ASSERT(num_chunks == 3);
947
948 OSMO_ASSERT(data[0] == ((0 << 1) | (0 << 0)));
949 OSMO_ASSERT(data[1] == ((7 << 1) | (0 << 0)));
950 OSMO_ASSERT(data[2] == ((18 << 1) | (1 << 0)));
951 OSMO_ASSERT(data[3] == 0);
952
953 /* Block 3 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530954 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100955 num_chunks = 0;
956 write_offset = 0;
957 memset(data, 0, sizeof(data));
958
959 llc.reset();
960 llc.put_frame(llc_data, 6);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200961 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100962
963 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200964 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100965
966 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
967 OSMO_ASSERT(rdbi.e == 0);
968 OSMO_ASSERT(write_offset == 1 + 6);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200969 OSMO_ASSERT(count_payload == 6);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100970 OSMO_ASSERT(num_chunks == 1);
971
972 llc.reset();
973 llc.put_frame(llc_data, 12);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200974 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100975
976 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200977 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100978
979 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
980 OSMO_ASSERT(rdbi.e == 0);
981 OSMO_ASSERT(rdbi.cv == 0);
982 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200983 OSMO_ASSERT(count_payload == 12);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100984 OSMO_ASSERT(num_chunks == 3);
985
986 OSMO_ASSERT(data[0] == ((6 << 1) | (0 << 0)));
987 OSMO_ASSERT(data[1] == ((12 << 1) | (0 << 0)));
988 OSMO_ASSERT(data[2] == ((127 << 1) | (1 << 0)));
989 OSMO_ASSERT(data[3] == 0);
990
991 /* TS 44.060, B.8.3 */
992
993 /* Note that the spec confuses the byte numbering here, too (see above) */
994
995 cs = GprsCodingScheme::MCS2;
996
997 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530998 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100999 num_chunks = 0;
1000 write_offset = 0;
1001 memset(data, 0, sizeof(data));
1002
1003 llc.reset();
1004 llc.put_frame(llc_data, rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001005 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001006
1007 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001008 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001009
1010 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
1011 OSMO_ASSERT(rdbi.e == 1);
1012 OSMO_ASSERT(rdbi.cv == 0);
1013 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001014 OSMO_ASSERT(count_payload == rdbi.data_len);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001015 OSMO_ASSERT(num_chunks == 1);
1016
1017 OSMO_ASSERT(data[0] == 0);
1018
1019 /* Final block with an LLC of size data_len-1 */
1020
1021 cs = GprsCodingScheme::MCS2;
1022
1023 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301024 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001025 num_chunks = 0;
1026 write_offset = 0;
1027 memset(data, 0, sizeof(data));
1028
1029 llc.reset();
1030 llc.put_frame(llc_data, rdbi.data_len - 1);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001031 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001032
1033 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001034 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001035
1036 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
1037 OSMO_ASSERT(rdbi.e == 0);
1038 OSMO_ASSERT(rdbi.cv == 0);
1039 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001040 OSMO_ASSERT(count_payload == rdbi.data_len - 1);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001041 OSMO_ASSERT(num_chunks == 1);
1042
1043 OSMO_ASSERT(data[0] == (((rdbi.data_len-1) << 1) | (1 << 0)));
1044 OSMO_ASSERT(data[1] == 0);
1045
1046 /* Final block with an LLC of size data_len-2 */
1047
1048 cs = GprsCodingScheme::MCS2;
1049
1050 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301051 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001052 num_chunks = 0;
1053 write_offset = 0;
1054 memset(data, 0, sizeof(data));
1055
1056 llc.reset();
1057 llc.put_frame(llc_data, rdbi.data_len - 2);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001058 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001059
1060 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001061 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001062
1063 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
1064 OSMO_ASSERT(rdbi.e == 0);
1065 OSMO_ASSERT(rdbi.cv == 0);
1066 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001067 OSMO_ASSERT(count_payload == rdbi.data_len - 2);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001068 OSMO_ASSERT(num_chunks == 2);
1069
1070 OSMO_ASSERT(data[0] == (((rdbi.data_len-2) << 1) | (0 << 0)));
1071 OSMO_ASSERT(data[1] == ((127 << 1) | (1 << 0)));
1072 OSMO_ASSERT(data[2] == 0);
1073
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001074 printf("=== end %s ===\n", __func__);
1075}
1076
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001077static void test_rlc_unaligned_copy()
1078{
1079 uint8_t bits[256];
1080 uint8_t saved_block[256];
1081 uint8_t test_block[256];
1082 uint8_t out_block[256];
1083 GprsCodingScheme::Scheme scheme;
1084 int pattern;
1085 volatile unsigned int block_idx, i;
1086
1087 for (scheme = GprsCodingScheme::CS1;
1088 scheme < GprsCodingScheme::NUM_SCHEMES;
1089 scheme = GprsCodingScheme::Scheme(scheme + 1))
1090 {
1091 GprsCodingScheme cs(scheme);
1092
1093 for (pattern = 0; pattern <= 0xff; pattern += 0xff) {
1094 /* prepare test block */
1095 test_block[0] = pattern ^ 0xff;
1096 for (i = 1; i + 1 < cs.maxDataBlockBytes(); i++)
1097 test_block[i] = i;
1098 test_block[cs.maxDataBlockBytes()-1] = pattern ^ 0xff;
1099
1100 for (block_idx = 0;
1101 block_idx < cs.numDataBlocks();
1102 block_idx++)
1103 {
1104 struct gprs_rlc_data_info rlc;
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301105 gprs_rlc_data_info_init_dl(&rlc, cs, false, 0);
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001106
1107 memset(bits, pattern, sizeof(bits));
1108 Decoding::rlc_copy_to_aligned_buffer(
1109 &rlc, block_idx, bits, saved_block);
1110
1111 fprintf(stderr,
1112 "Test data block: %s\n",
1113 osmo_hexdump(test_block, cs.maxDataBlockBytes()));
1114
1115 Encoding::rlc_copy_from_aligned_buffer(
1116 &rlc, block_idx, bits, test_block);
1117
1118 fprintf(stderr,
1119 "Encoded message block, %s, idx %d, "
1120 "pattern %02x: %s\n",
1121 rlc.cs.name(), block_idx, pattern,
1122 osmo_hexdump(bits, cs.sizeDL()));
1123
1124 Decoding::rlc_copy_to_aligned_buffer(
1125 &rlc, block_idx, bits, out_block);
1126
1127 fprintf(stderr,
1128 "Out data block: %s\n",
1129 osmo_hexdump(out_block, cs.maxDataBlockBytes()));
1130 /* restore original bits */
1131 Encoding::rlc_copy_from_aligned_buffer(
1132 &rlc, block_idx, bits, saved_block);
1133
1134 OSMO_ASSERT(memcmp(test_block, out_block,
1135 rlc.cs.maxDataBlockBytes()) == 0);
1136
1137 for (i = 0; i < sizeof(bits); i++)
1138 OSMO_ASSERT(bits[i] == pattern);
1139 }
1140 }
1141 }
1142}
1143
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001144static void test_rlc_info_init()
1145{
1146 struct gprs_rlc_data_info rlc;
1147
1148 printf("=== start %s ===\n", __func__);
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301149 gprs_rlc_data_info_init_dl(&rlc,
1150 GprsCodingScheme(GprsCodingScheme::CS1), false, 0);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001151 OSMO_ASSERT(rlc.num_data_blocks == 1);
1152 OSMO_ASSERT(rlc.data_offs_bits[0] == 24);
1153 OSMO_ASSERT(rlc.block_info[0].data_len == 20);
1154
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301155 gprs_rlc_data_info_init_dl(&rlc,
1156 GprsCodingScheme(GprsCodingScheme::MCS1), false, 0);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001157 OSMO_ASSERT(rlc.num_data_blocks == 1);
1158 OSMO_ASSERT(rlc.data_offs_bits[0] == 33);
1159 OSMO_ASSERT(rlc.block_info[0].data_len == 22);
1160
1161 printf("=== end %s ===\n", __func__);
1162}
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001163
1164static const struct log_info_cat default_categories[] = {
1165 {"DCSN1", "\033[1;31m", "Concrete Syntax Notation One (CSN1)", LOGL_INFO, 0},
1166 {"DL1IF", "\033[1;32m", "GPRS PCU L1 interface (L1IF)", LOGL_DEBUG, 1},
1167 {"DRLCMAC", "\033[0;33m", "GPRS RLC/MAC layer (RLCMAC)", LOGL_DEBUG, 1},
1168 {"DRLCMACDATA", "\033[0;33m", "GPRS RLC/MAC layer Data (RLCMAC)", LOGL_DEBUG, 1},
1169 {"DRLCMACDL", "\033[1;33m", "GPRS RLC/MAC layer Downlink (RLCMAC)", LOGL_DEBUG, 1},
1170 {"DRLCMACUL", "\033[1;36m", "GPRS RLC/MAC layer Uplink (RLCMAC)", LOGL_DEBUG, 1},
1171 {"DRLCMACSCHED", "\033[0;36m", "GPRS RLC/MAC layer Scheduling (RLCMAC)", LOGL_DEBUG, 1},
1172 {"DRLCMACMEAS", "\033[1;31m", "GPRS RLC/MAC layer Measurements (RLCMAC)", LOGL_INFO, 1},
1173 {"DNS","\033[1;34m", "GPRS Network Service Protocol (NS)", LOGL_INFO , 1},
1174 {"DBSSGP","\033[1;34m", "GPRS BSS Gateway Protocol (BSSGP)", LOGL_INFO , 1},
1175 {"DPCU", "\033[1;35m", "GPRS Packet Control Unit (PCU)", LOGL_NOTICE, 1},
1176};
1177
1178static int filter_fn(const struct log_context *ctx,
1179 struct log_target *tar)
1180{
1181 return 1;
1182}
1183
1184const struct log_info debug_log_info = {
1185 filter_fn,
1186 (struct log_info_cat*)default_categories,
1187 ARRAY_SIZE(default_categories),
1188};
1189
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301190static void setup_bts(BTS *the_bts, uint8_t ts_no, uint8_t cs = 1)
1191{
1192 gprs_rlcmac_bts *bts;
1193 gprs_rlcmac_trx *trx;
1194
1195 bts = the_bts->bts_data();
1196 bts->egprs_enabled = true;
1197 bts->alloc_algorithm = alloc_algorithm_a;
1198 bts->initial_cs_dl = cs;
1199 bts->initial_cs_ul = cs;
1200 trx = &bts->trx[0];
1201 trx->pdch[ts_no].enable();
1202}
1203static void uplink_header_type_2_parsing_test(BTS *the_bts,
1204 uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
1205 uint8_t ms_class)
1206{
1207 GprsMs *ms;
1208 struct pcu_l1_meas meas;
1209 int tfi = 0;
1210 gprs_rlcmac_bts *bts;
1211 RlcMacUplink_t ulreq = {0};
1212 uint8_t data[79] = {0};
1213 struct gprs_rlc_ul_header_egprs_2 *egprs2 = NULL;
1214
1215 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
1216 bts = the_bts->bts_data();
1217
1218 tfi = 1;
1219
1220 struct gprs_rlc_data_info rlc;
1221 GprsCodingScheme cs;
1222 int rc, offs;
1223
1224 /*without padding*/
1225 cs = GprsCodingScheme::MCS5;
1226 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
1227 egprs2->r = 1;
1228 egprs2->si = 1;
1229 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001230 egprs2->tfi_hi = tfi & 0x03;
1231 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1232 egprs2->bsn1_hi = 0;
1233 egprs2->bsn1_lo = 0;
1234 egprs2->cps_hi = 3;
1235 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301236 egprs2->rsb = 0;
1237 egprs2->pi = 0;
1238 data[4] = 0x20; /* Setting E field */
1239 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1240 offs = rlc.data_offs_bits[0] / 8;
1241 OSMO_ASSERT(offs == 4);
1242 OSMO_ASSERT(rlc.tfi == 1);
1243 OSMO_ASSERT(rlc.num_data_blocks == 1);
1244 OSMO_ASSERT(rlc.block_info[0].e == 1);
1245 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1246 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1247
1248 /* with padding case */
1249 cs = GprsCodingScheme::MCS6;
1250 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
1251 egprs2->r = 1;
1252 egprs2->si = 1;
1253 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001254 egprs2->tfi_hi = tfi & 0x03;
1255 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1256 egprs2->bsn1_hi = 0;
1257 egprs2->bsn1_lo = 0;
1258 egprs2->cps_hi = 3;
1259 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301260 egprs2->rsb = 0;
1261 egprs2->pi = 0;
1262 data[10] = 0x20; /* Setting E field */
1263 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1264 offs = rlc.data_offs_bits[0] / 8;
1265 OSMO_ASSERT(offs == 10);
1266 OSMO_ASSERT(rlc.num_data_blocks == 1);
1267 OSMO_ASSERT(rlc.tfi == 1);
1268 OSMO_ASSERT(rlc.block_info[0].e == 1);
1269 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1270 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1271
1272 egprs2->r = 1;
1273 egprs2->si = 1;
1274 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001275 egprs2->tfi_hi = tfi & 0x03;
1276 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1277 egprs2->bsn1_hi = 1;
1278 egprs2->bsn1_lo = 0;
1279 egprs2->cps_hi = 2;
1280 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301281 egprs2->rsb = 0;
1282 egprs2->pi = 0;
1283 data[10] = 0x20; /* Setting E field */
1284 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1285 offs = rlc.data_offs_bits[0] / 8;
1286 OSMO_ASSERT(offs == 10);
1287 OSMO_ASSERT(rlc.tfi == 1);
1288 OSMO_ASSERT(rlc.num_data_blocks == 1);
1289 OSMO_ASSERT(rlc.block_info[0].e == 1);
1290 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1291 OSMO_ASSERT(rlc.block_info[0].bsn == 1);
1292}
1293
1294static void uplink_header_type2_test(void)
1295{
1296 BTS the_bts;
1297 int ts_no = 7;
1298 uint32_t fn = 2654218;
1299 uint16_t qta = 31;
1300 uint32_t tlli = 0xf1223344;
1301 const char *imsi = "0011223344";
1302 uint8_t ms_class = 1;
1303 gprs_rlcmac_ul_tbf *ul_tbf;
1304 GprsMs *ms;
1305
1306 printf("=== start %s ===\n", __func__);
1307 setup_bts(&the_bts, ts_no, 10);
1308
1309 uplink_header_type_2_parsing_test(&the_bts, ts_no,
1310 tlli, &fn, qta, ms_class);
1311 printf("=== end %s ===\n", __func__);
1312}
1313
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301314static void uplink_header_type_1_parsing_test(BTS *the_bts,
1315 uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
1316 uint8_t ms_class)
1317{
1318 uint8_t trx_no = 0;
1319 int tfi = 0;
1320 struct gprs_rlcmac_pdch *pdch;
1321 gprs_rlcmac_bts *bts;
1322 uint8_t data[155] = {0};
1323 struct gprs_rlc_ul_header_egprs_1 *egprs1 = NULL;
1324 struct gprs_rlc_data_info rlc;
1325 GprsCodingScheme cs;
1326 int rc, offs;
1327
1328 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1329 bts = the_bts->bts_data();
1330
1331 tfi = 1;
1332
1333 /* MCS 7 */
1334 cs = GprsCodingScheme::MCS7;
1335 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1336 egprs1->si = 1;
1337 egprs1->r = 1;
1338 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001339 egprs1->tfi_hi = tfi & 0x03;
1340 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1341 egprs1->bsn1_hi = 0;
1342 egprs1->bsn1_lo = 0;
1343 egprs1->bsn2_hi = 1;
1344 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301345 egprs1->cps = 15;
1346 egprs1->rsb = 0;
1347 egprs1->pi = 0;
1348 data[5] = 0xc0;
1349 data[5 + 57] = 1;
1350 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1351 OSMO_ASSERT(rlc.num_data_blocks == 2);
1352 OSMO_ASSERT(rlc.block_info[0].e == 1);
1353 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1354 OSMO_ASSERT(rlc.block_info[1].e == 1);
1355 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1356 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1357 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1358 OSMO_ASSERT(rlc.tfi == 1);
1359
1360 /* MCS 8 */
1361 cs = GprsCodingScheme::MCS8;
1362 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1363 egprs1->si = 1;
1364 egprs1->r = 1;
1365 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001366 egprs1->tfi_hi = tfi & 0x03;
1367 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1368 egprs1->bsn1_hi = 0;
1369 egprs1->bsn1_lo = 0;
1370 egprs1->bsn2_hi = 1;
1371 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301372 egprs1->cps = 15;
1373 egprs1->rsb = 0;
1374 egprs1->pi = 0;
1375 data[5] = 0xc0;
1376 data[5 + 69] = 1;
1377 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1378 OSMO_ASSERT(rlc.num_data_blocks == 2);
1379 OSMO_ASSERT(rlc.block_info[0].e == 1);
1380 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1381 OSMO_ASSERT(rlc.block_info[1].e == 1);
1382 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1383 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1384 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1385 OSMO_ASSERT(rlc.tfi == 1);
1386
1387 /* MCS 9 */
1388 cs = GprsCodingScheme::MCS9;
1389 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1390 egprs1->si = 1;
1391 egprs1->r = 1;
1392 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001393 egprs1->tfi_hi = tfi & 0x03;
1394 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1395 egprs1->bsn1_hi = 0;
1396 egprs1->bsn1_lo = 0;
1397 egprs1->bsn2_hi = 1;
1398 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301399 egprs1->cps = 15;
1400 egprs1->rsb = 0;
1401 egprs1->pi = 0;
1402 data[5] = 0xc0;
1403 data[5 + 75] = 1;
1404 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1405 OSMO_ASSERT(rlc.num_data_blocks == 2);
1406 OSMO_ASSERT(rlc.block_info[0].e == 1);
1407 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1408 OSMO_ASSERT(rlc.block_info[1].e == 1);
1409 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1410 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1411 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1412 OSMO_ASSERT(rlc.tfi == 1);
1413}
1414
1415void uplink_header_type1_test(void)
1416{
1417 BTS the_bts;
1418 int ts_no = 7;
1419 uint32_t fn = 2654218;
1420 uint16_t qta = 31;
1421 uint32_t tlli = 0xf1223344;
1422 const char *imsi = "0011223344";
1423 uint8_t ms_class = 1;
1424 gprs_rlcmac_ul_tbf *ul_tbf;
1425 GprsMs *ms;
1426
1427 printf("=== start %s ===\n", __func__);
1428 setup_bts(&the_bts, ts_no, 12);
1429 uplink_header_type_1_parsing_test(&the_bts, ts_no, tlli, &fn,
1430 qta, ms_class);
1431 printf("=== end %s ===\n", __func__);
1432}
1433
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001434int main(int argc, char **argv)
1435{
1436 struct vty_app_info pcu_vty_info = {0};
1437
1438 tall_pcu_ctx = talloc_named_const(NULL, 1, "EdgeTest context");
1439 if (!tall_pcu_ctx)
1440 abort();
1441
1442 msgb_set_talloc_ctx(tall_pcu_ctx);
1443 osmo_init_logging(&debug_log_info);
1444 log_set_use_color(osmo_stderr_target, 0);
1445 log_set_print_filename(osmo_stderr_target, 0);
1446
1447 vty_init(&pcu_vty_info);
1448 pcu_vty_init(&debug_log_info);
1449
1450 test_coding_scheme();
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001451 test_rlc_info_init();
Jacob Erlbeck38f18692016-02-01 10:08:00 +01001452 test_rlc_unit_decoder();
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001453 test_rlc_unaligned_copy();
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001454 test_rlc_unit_encoder();
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001455
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301456 uplink_header_type2_test();
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301457 uplink_header_type1_test();
1458
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001459 if (getenv("TALLOC_REPORT_FULL"))
1460 talloc_report_full(tall_pcu_ctx, stderr);
1461 return EXIT_SUCCESS;
1462}
1463
1464/*
1465 * stubs that should not be reached
1466 */
1467extern "C" {
1468void l1if_pdch_req() { abort(); }
1469void l1if_connect_pdch() { abort(); }
1470void l1if_close_pdch() { abort(); }
1471void l1if_open_pdch() { abort(); }
1472}