blob: 807102c97e631a67e197d1e73a823b7d06c32948 [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
499 printf("=== end %s ===\n", __func__);
500}
501
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100502static void test_rlc_unit_encoder()
503{
504 struct gprs_rlc_data_block_info rdbi = {0};
505 GprsCodingScheme cs;
506 uint8_t data[74];
507 uint8_t llc_data[1500] = {0,};
508 int num_chunks = 0;
509 int write_offset;
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200510 int count_payload;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100511 struct gprs_llc llc;
512 Encoding::AppendResult ar;
513
514 printf("=== start %s ===\n", __func__);
515
516 llc.init();
517
518 /* TS 44.060, B.1 */
519 cs = GprsCodingScheme::CS4;
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100520 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100521 num_chunks = 0;
522 write_offset = 0;
523 memset(data, 0, sizeof(data));
524
525 llc.reset();
526 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200527 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100528
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100529 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200530 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100531
532 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
533 OSMO_ASSERT(rdbi.e == 0);
534 OSMO_ASSERT(write_offset == 1 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200535 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100536 OSMO_ASSERT(num_chunks == 1);
537
538 llc.reset();
539 llc.put_frame(llc_data, 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200540 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100541
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100542 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200543 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100544
545 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
546 OSMO_ASSERT(rdbi.e == 0);
547 OSMO_ASSERT(write_offset == 2 + 11 + 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200548 OSMO_ASSERT(count_payload == 26);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100549 OSMO_ASSERT(num_chunks == 2);
550
551 llc.reset();
552 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200553 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100554
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100555 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200556 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100557
558 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
559 OSMO_ASSERT(rdbi.e == 0);
560 OSMO_ASSERT(rdbi.cv != 0);
561 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200562 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100563 OSMO_ASSERT(num_chunks == 3);
564
565 OSMO_ASSERT(data[0] == ((11 << 2) | (1 << 1) | (0 << 0)));
566 OSMO_ASSERT(data[1] == ((26 << 2) | (1 << 1) | (1 << 0)));
567 OSMO_ASSERT(data[2] == 0);
568
569 /* TS 44.060, B.2 */
570 cs = GprsCodingScheme::CS1;
571
572 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100573 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100574 num_chunks = 0;
575 write_offset = 0;
576 memset(data, 0, sizeof(data));
577
578 llc.reset();
579 llc.put_frame(llc_data, 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200580 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100581
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100582 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200583 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100584
585 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
586 OSMO_ASSERT(rdbi.e == 0);
587 OSMO_ASSERT(write_offset == 1 + 19);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200588 OSMO_ASSERT(count_payload == 19);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100589 OSMO_ASSERT(num_chunks == 1);
590
591 OSMO_ASSERT(data[0] == ((0 << 2) | (0 << 1) | (1 << 0)));
592 OSMO_ASSERT(data[1] == 0);
593
594 /* Block 2 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100595 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100596 num_chunks = 0;
597 write_offset = 0;
598 memset(data, 0, sizeof(data));
599
600 OSMO_ASSERT(llc.chunk_size() == 1);
601
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200602 count_payload = -1;
603
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100604 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200605 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100606
607 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
608 OSMO_ASSERT(rdbi.e == 0);
609 OSMO_ASSERT(write_offset == 1 + 1);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200610 OSMO_ASSERT(count_payload == 1);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100611 OSMO_ASSERT(num_chunks == 1);
612
613 llc.reset();
614 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200615 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100616
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100617 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200618 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100619
620 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
621 OSMO_ASSERT(rdbi.e == 0);
622 OSMO_ASSERT(write_offset == 1 + 1 + 18);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200623 OSMO_ASSERT(count_payload == 18);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100624 OSMO_ASSERT(num_chunks == 2);
625
626 OSMO_ASSERT(data[0] == ((1 << 2) | (1 << 1) | (1 << 0)));
627 OSMO_ASSERT(data[1] == 0);
628
629 /* TS 44.060, B.3 */
630 cs = GprsCodingScheme::CS1;
631
632 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100633 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100634 num_chunks = 0;
635 write_offset = 0;
636 memset(data, 0, sizeof(data));
637
638 llc.reset();
639 llc.put_frame(llc_data, 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200640 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100641
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100642 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200643 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100644
645 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
646 OSMO_ASSERT(rdbi.e == 0);
647 OSMO_ASSERT(write_offset == 1 + 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200648 OSMO_ASSERT(count_payload == 7);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100649 OSMO_ASSERT(num_chunks == 1);
650
651 llc.reset();
652 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200653 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100654
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100655 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200656 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100657
658 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
659 OSMO_ASSERT(rdbi.e == 0);
660 OSMO_ASSERT(write_offset == 2 + 7 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200661 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100662 OSMO_ASSERT(num_chunks == 2);
663
664 OSMO_ASSERT(data[0] == ((7 << 2) | (1 << 1) | (0 << 0)));
665 OSMO_ASSERT(data[1] == ((11 << 2) | (0 << 1) | (1 << 0)));
666 OSMO_ASSERT(data[2] == 0);
667
668 /* TS 44.060, B.4 */
669 cs = GprsCodingScheme::CS1;
670
671 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100672 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100673 num_chunks = 0;
674 write_offset = 0;
675 memset(data, 0, sizeof(data));
676
677 llc.reset();
678 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200679 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100680
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100681 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200682 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100683
684 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
685 OSMO_ASSERT(rdbi.e == 1);
686 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200687 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100688 OSMO_ASSERT(num_chunks == 1);
689 OSMO_ASSERT(rdbi.cv != 0);
690
691 OSMO_ASSERT(data[0] == 0);
692
693 /* TS 44.060, B.5 */
694 cs = GprsCodingScheme::CS1;
695
696 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100697 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100698 num_chunks = 0;
699 write_offset = 0;
700 memset(data, 0, sizeof(data));
701
702 llc.reset();
703 llc.put_frame(llc_data, 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200704 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100705
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100706 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200707 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100708
709 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
710 OSMO_ASSERT(rdbi.e == 1);
711 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200712 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100713 OSMO_ASSERT(num_chunks == 1);
714 OSMO_ASSERT(rdbi.cv == 0);
715
716 OSMO_ASSERT(data[0] == 0);
717
718 /* TS 44.060, B.7 */
719 cs = GprsCodingScheme::CS1;
720
721 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100722 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100723 num_chunks = 0;
724 write_offset = 0;
725 memset(data, 0, sizeof(data));
726
727 llc.reset();
728 llc.put_frame(llc_data, 30);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200729 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100730
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100731 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200732 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100733
734 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
735 OSMO_ASSERT(rdbi.e == 1);
736 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200737 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100738 OSMO_ASSERT(num_chunks == 1);
739
740 OSMO_ASSERT(data[0] == 0);
741
742 /* Block 2 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100743 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100744 num_chunks = 0;
745 write_offset = 0;
746 memset(data, 0, sizeof(data));
747
748 OSMO_ASSERT(llc.chunk_size() == 10);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200749 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100750
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100751 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200752 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100753
754 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
755 OSMO_ASSERT(rdbi.e == 0);
756 OSMO_ASSERT(write_offset == 1 + 10);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200757 OSMO_ASSERT(count_payload == 10);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100758 OSMO_ASSERT(num_chunks == 1);
759
760 llc.reset();
761 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200762 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100763
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100764 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200765 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100766
767 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
768 OSMO_ASSERT(rdbi.e == 0);
769 OSMO_ASSERT(write_offset == 1 + 10 + 9);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200770 OSMO_ASSERT(count_payload == 9);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100771 OSMO_ASSERT(num_chunks == 2);
772
773 OSMO_ASSERT(data[0] == ((10 << 2) | (1 << 1) | (1 << 0)));
774 OSMO_ASSERT(data[1] == 0);
775
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100776 /* TS 44.060, B.8.1 */
777 cs = GprsCodingScheme::MCS4;
778
779 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100780 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100781 num_chunks = 0;
782 write_offset = 0;
783 memset(data, 0, sizeof(data));
784
785 llc.reset();
786 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200787 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100788
789 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200790 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100791
792 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
793 OSMO_ASSERT(rdbi.e == 0);
794 OSMO_ASSERT(write_offset == 1 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200795 OSMO_ASSERT(count_payload == 11);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100796 OSMO_ASSERT(num_chunks == 1);
797
798 llc.reset();
799 llc.put_frame(llc_data, 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200800 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100801
802 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200803 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100804
805 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
806 OSMO_ASSERT(rdbi.e == 0);
807 OSMO_ASSERT(write_offset == 2 + 11 + 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200808 OSMO_ASSERT(count_payload == 26);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100809 OSMO_ASSERT(num_chunks == 2);
810
811 llc.reset();
812 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200813 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100814
815 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200816 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100817
818 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
819 OSMO_ASSERT(rdbi.e == 0);
820 OSMO_ASSERT(rdbi.cv != 0);
821 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200822 OSMO_ASSERT(count_payload == 5);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100823 OSMO_ASSERT(num_chunks == 3);
824
825 OSMO_ASSERT(data[0] == ((11 << 1) | (0 << 0)));
826 OSMO_ASSERT(data[1] == ((26 << 1) | (1 << 0)));
827 OSMO_ASSERT(data[2] == 0);
828
829 /* TS 44.060, B.8.2 */
830
831 /* Note that the spec confuses the byte numbering here, since it
832 * includes the FBI/E header bits into the N2 octet count which
833 * is not consistent with Section 10.3a.1 & 10.3a.2. */
834
835 cs = GprsCodingScheme::MCS2;
836
837 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100838 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100839 num_chunks = 0;
840 write_offset = 0;
841 memset(data, 0, sizeof(data));
842
843 llc.reset();
844 llc.put_frame(llc_data, 15);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200845 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100846
847 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200848 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100849
850 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
851 OSMO_ASSERT(rdbi.e == 0);
852 OSMO_ASSERT(write_offset == 1 + 15);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200853 OSMO_ASSERT(count_payload == 15);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100854 OSMO_ASSERT(num_chunks == 1);
855
856 llc.reset();
857 llc.put_frame(llc_data, 12);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200858 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100859
860 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200861 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100862
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200863 /* no LI here, becaues there are exact 12 bytes left. Put LI into next frame */
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100864 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
865 OSMO_ASSERT(rdbi.e == 0);
866 OSMO_ASSERT(rdbi.cv != 0);
867 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200868 OSMO_ASSERT(count_payload == 12);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100869 OSMO_ASSERT(num_chunks == 2);
870
871 OSMO_ASSERT(data[0] == ((15 << 1) | (1 << 0)));
872 OSMO_ASSERT(data[1] == 0);
873
874 /* Block 2 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100875 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100876 num_chunks = 0;
877 write_offset = 0;
878 memset(data, 0, sizeof(data));
879
880 OSMO_ASSERT(llc.chunk_size() == 0);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200881 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100882
883 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200884 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100885
886 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
887 OSMO_ASSERT(rdbi.e == 0);
888 OSMO_ASSERT(write_offset == 1 + 0);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200889 OSMO_ASSERT(count_payload == 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100890 OSMO_ASSERT(num_chunks == 1);
891
892 llc.reset();
893 llc.put_frame(llc_data, 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200894 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100895
896 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200897 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100898
899 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
900 OSMO_ASSERT(rdbi.e == 0);
901 OSMO_ASSERT(rdbi.cv != 0);
902 OSMO_ASSERT(write_offset == 2 + 0 + 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200903 OSMO_ASSERT(count_payload == 7);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100904 OSMO_ASSERT(num_chunks == 2);
905
906 llc.reset();
907 llc.put_frame(llc_data, 18);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200908 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100909
910 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200911 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100912
913 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
914 OSMO_ASSERT(rdbi.e == 0);
915 OSMO_ASSERT(rdbi.cv != 0);
916 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200917 OSMO_ASSERT(count_payload == 18);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100918 OSMO_ASSERT(num_chunks == 3);
919
920 OSMO_ASSERT(data[0] == ((0 << 1) | (0 << 0)));
921 OSMO_ASSERT(data[1] == ((7 << 1) | (0 << 0)));
922 OSMO_ASSERT(data[2] == ((18 << 1) | (1 << 0)));
923 OSMO_ASSERT(data[3] == 0);
924
925 /* Block 3 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100926 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100927 num_chunks = 0;
928 write_offset = 0;
929 memset(data, 0, sizeof(data));
930
931 llc.reset();
932 llc.put_frame(llc_data, 6);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200933 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100934
935 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200936 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100937
938 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
939 OSMO_ASSERT(rdbi.e == 0);
940 OSMO_ASSERT(write_offset == 1 + 6);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200941 OSMO_ASSERT(count_payload == 6);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100942 OSMO_ASSERT(num_chunks == 1);
943
944 llc.reset();
945 llc.put_frame(llc_data, 12);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200946 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100947
948 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200949 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100950
951 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
952 OSMO_ASSERT(rdbi.e == 0);
953 OSMO_ASSERT(rdbi.cv == 0);
954 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200955 OSMO_ASSERT(count_payload == 12);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100956 OSMO_ASSERT(num_chunks == 3);
957
958 OSMO_ASSERT(data[0] == ((6 << 1) | (0 << 0)));
959 OSMO_ASSERT(data[1] == ((12 << 1) | (0 << 0)));
960 OSMO_ASSERT(data[2] == ((127 << 1) | (1 << 0)));
961 OSMO_ASSERT(data[3] == 0);
962
963 /* TS 44.060, B.8.3 */
964
965 /* Note that the spec confuses the byte numbering here, too (see above) */
966
967 cs = GprsCodingScheme::MCS2;
968
969 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100970 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100971 num_chunks = 0;
972 write_offset = 0;
973 memset(data, 0, sizeof(data));
974
975 llc.reset();
976 llc.put_frame(llc_data, rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200977 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100978
979 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200980 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100981
982 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
983 OSMO_ASSERT(rdbi.e == 1);
984 OSMO_ASSERT(rdbi.cv == 0);
985 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200986 OSMO_ASSERT(count_payload == rdbi.data_len);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100987 OSMO_ASSERT(num_chunks == 1);
988
989 OSMO_ASSERT(data[0] == 0);
990
991 /* Final block with an LLC of size data_len-1 */
992
993 cs = GprsCodingScheme::MCS2;
994
995 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +0100996 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100997 num_chunks = 0;
998 write_offset = 0;
999 memset(data, 0, sizeof(data));
1000
1001 llc.reset();
1002 llc.put_frame(llc_data, rdbi.data_len - 1);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001003 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001004
1005 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001006 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001007
1008 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
1009 OSMO_ASSERT(rdbi.e == 0);
1010 OSMO_ASSERT(rdbi.cv == 0);
1011 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001012 OSMO_ASSERT(count_payload == rdbi.data_len - 1);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001013 OSMO_ASSERT(num_chunks == 1);
1014
1015 OSMO_ASSERT(data[0] == (((rdbi.data_len-1) << 1) | (1 << 0)));
1016 OSMO_ASSERT(data[1] == 0);
1017
1018 /* Final block with an LLC of size data_len-2 */
1019
1020 cs = GprsCodingScheme::MCS2;
1021
1022 /* Block 1 */
Jacob Erlbeckb55f3132016-02-03 18:28:04 +01001023 gprs_rlc_data_block_info_init(&rdbi, cs, false);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001024 num_chunks = 0;
1025 write_offset = 0;
1026 memset(data, 0, sizeof(data));
1027
1028 llc.reset();
1029 llc.put_frame(llc_data, rdbi.data_len - 2);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001030 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001031
1032 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001033 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001034
1035 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
1036 OSMO_ASSERT(rdbi.e == 0);
1037 OSMO_ASSERT(rdbi.cv == 0);
1038 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001039 OSMO_ASSERT(count_payload == rdbi.data_len - 2);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001040 OSMO_ASSERT(num_chunks == 2);
1041
1042 OSMO_ASSERT(data[0] == (((rdbi.data_len-2) << 1) | (0 << 0)));
1043 OSMO_ASSERT(data[1] == ((127 << 1) | (1 << 0)));
1044 OSMO_ASSERT(data[2] == 0);
1045
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001046 printf("=== end %s ===\n", __func__);
1047}
1048
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001049static void test_rlc_unaligned_copy()
1050{
1051 uint8_t bits[256];
1052 uint8_t saved_block[256];
1053 uint8_t test_block[256];
1054 uint8_t out_block[256];
1055 GprsCodingScheme::Scheme scheme;
1056 int pattern;
1057 volatile unsigned int block_idx, i;
1058
1059 for (scheme = GprsCodingScheme::CS1;
1060 scheme < GprsCodingScheme::NUM_SCHEMES;
1061 scheme = GprsCodingScheme::Scheme(scheme + 1))
1062 {
1063 GprsCodingScheme cs(scheme);
1064
1065 for (pattern = 0; pattern <= 0xff; pattern += 0xff) {
1066 /* prepare test block */
1067 test_block[0] = pattern ^ 0xff;
1068 for (i = 1; i + 1 < cs.maxDataBlockBytes(); i++)
1069 test_block[i] = i;
1070 test_block[cs.maxDataBlockBytes()-1] = pattern ^ 0xff;
1071
1072 for (block_idx = 0;
1073 block_idx < cs.numDataBlocks();
1074 block_idx++)
1075 {
1076 struct gprs_rlc_data_info rlc;
Jacob Erlbeckb55f3132016-02-03 18:28:04 +01001077 gprs_rlc_data_info_init_dl(&rlc, cs, false);
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001078
1079 memset(bits, pattern, sizeof(bits));
1080 Decoding::rlc_copy_to_aligned_buffer(
1081 &rlc, block_idx, bits, saved_block);
1082
1083 fprintf(stderr,
1084 "Test data block: %s\n",
1085 osmo_hexdump(test_block, cs.maxDataBlockBytes()));
1086
1087 Encoding::rlc_copy_from_aligned_buffer(
1088 &rlc, block_idx, bits, test_block);
1089
1090 fprintf(stderr,
1091 "Encoded message block, %s, idx %d, "
1092 "pattern %02x: %s\n",
1093 rlc.cs.name(), block_idx, pattern,
1094 osmo_hexdump(bits, cs.sizeDL()));
1095
1096 Decoding::rlc_copy_to_aligned_buffer(
1097 &rlc, block_idx, bits, out_block);
1098
1099 fprintf(stderr,
1100 "Out data block: %s\n",
1101 osmo_hexdump(out_block, cs.maxDataBlockBytes()));
1102 /* restore original bits */
1103 Encoding::rlc_copy_from_aligned_buffer(
1104 &rlc, block_idx, bits, saved_block);
1105
1106 OSMO_ASSERT(memcmp(test_block, out_block,
1107 rlc.cs.maxDataBlockBytes()) == 0);
1108
1109 for (i = 0; i < sizeof(bits); i++)
1110 OSMO_ASSERT(bits[i] == pattern);
1111 }
1112 }
1113 }
1114}
1115
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001116static void test_rlc_info_init()
1117{
1118 struct gprs_rlc_data_info rlc;
1119
1120 printf("=== start %s ===\n", __func__);
Jacob Erlbeckb55f3132016-02-03 18:28:04 +01001121 gprs_rlc_data_info_init_dl(&rlc, GprsCodingScheme(GprsCodingScheme::CS1), false);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001122 OSMO_ASSERT(rlc.num_data_blocks == 1);
1123 OSMO_ASSERT(rlc.data_offs_bits[0] == 24);
1124 OSMO_ASSERT(rlc.block_info[0].data_len == 20);
1125
Jacob Erlbeckb55f3132016-02-03 18:28:04 +01001126 gprs_rlc_data_info_init_dl(&rlc, GprsCodingScheme(GprsCodingScheme::MCS1), false);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001127 OSMO_ASSERT(rlc.num_data_blocks == 1);
1128 OSMO_ASSERT(rlc.data_offs_bits[0] == 33);
1129 OSMO_ASSERT(rlc.block_info[0].data_len == 22);
1130
1131 printf("=== end %s ===\n", __func__);
1132}
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001133
1134static const struct log_info_cat default_categories[] = {
1135 {"DCSN1", "\033[1;31m", "Concrete Syntax Notation One (CSN1)", LOGL_INFO, 0},
1136 {"DL1IF", "\033[1;32m", "GPRS PCU L1 interface (L1IF)", LOGL_DEBUG, 1},
1137 {"DRLCMAC", "\033[0;33m", "GPRS RLC/MAC layer (RLCMAC)", LOGL_DEBUG, 1},
1138 {"DRLCMACDATA", "\033[0;33m", "GPRS RLC/MAC layer Data (RLCMAC)", LOGL_DEBUG, 1},
1139 {"DRLCMACDL", "\033[1;33m", "GPRS RLC/MAC layer Downlink (RLCMAC)", LOGL_DEBUG, 1},
1140 {"DRLCMACUL", "\033[1;36m", "GPRS RLC/MAC layer Uplink (RLCMAC)", LOGL_DEBUG, 1},
1141 {"DRLCMACSCHED", "\033[0;36m", "GPRS RLC/MAC layer Scheduling (RLCMAC)", LOGL_DEBUG, 1},
1142 {"DRLCMACMEAS", "\033[1;31m", "GPRS RLC/MAC layer Measurements (RLCMAC)", LOGL_INFO, 1},
1143 {"DNS","\033[1;34m", "GPRS Network Service Protocol (NS)", LOGL_INFO , 1},
1144 {"DBSSGP","\033[1;34m", "GPRS BSS Gateway Protocol (BSSGP)", LOGL_INFO , 1},
1145 {"DPCU", "\033[1;35m", "GPRS Packet Control Unit (PCU)", LOGL_NOTICE, 1},
1146};
1147
1148static int filter_fn(const struct log_context *ctx,
1149 struct log_target *tar)
1150{
1151 return 1;
1152}
1153
1154const struct log_info debug_log_info = {
1155 filter_fn,
1156 (struct log_info_cat*)default_categories,
1157 ARRAY_SIZE(default_categories),
1158};
1159
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301160static void setup_bts(BTS *the_bts, uint8_t ts_no, uint8_t cs = 1)
1161{
1162 gprs_rlcmac_bts *bts;
1163 gprs_rlcmac_trx *trx;
1164
1165 bts = the_bts->bts_data();
1166 bts->egprs_enabled = true;
1167 bts->alloc_algorithm = alloc_algorithm_a;
1168 bts->initial_cs_dl = cs;
1169 bts->initial_cs_ul = cs;
1170 trx = &bts->trx[0];
1171 trx->pdch[ts_no].enable();
1172}
1173static void uplink_header_type_2_parsing_test(BTS *the_bts,
1174 uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
1175 uint8_t ms_class)
1176{
1177 GprsMs *ms;
1178 struct pcu_l1_meas meas;
1179 int tfi = 0;
1180 gprs_rlcmac_bts *bts;
1181 RlcMacUplink_t ulreq = {0};
1182 uint8_t data[79] = {0};
1183 struct gprs_rlc_ul_header_egprs_2 *egprs2 = NULL;
1184
1185 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
1186 bts = the_bts->bts_data();
1187
1188 tfi = 1;
1189
1190 struct gprs_rlc_data_info rlc;
1191 GprsCodingScheme cs;
1192 int rc, offs;
1193
1194 /*without padding*/
1195 cs = GprsCodingScheme::MCS5;
1196 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
1197 egprs2->r = 1;
1198 egprs2->si = 1;
1199 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001200 egprs2->tfi_hi = tfi & 0x03;
1201 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1202 egprs2->bsn1_hi = 0;
1203 egprs2->bsn1_lo = 0;
1204 egprs2->cps_hi = 3;
1205 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301206 egprs2->rsb = 0;
1207 egprs2->pi = 0;
1208 data[4] = 0x20; /* Setting E field */
1209 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1210 offs = rlc.data_offs_bits[0] / 8;
1211 OSMO_ASSERT(offs == 4);
1212 OSMO_ASSERT(rlc.tfi == 1);
1213 OSMO_ASSERT(rlc.num_data_blocks == 1);
1214 OSMO_ASSERT(rlc.block_info[0].e == 1);
1215 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1216 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1217
1218 /* with padding case */
1219 cs = GprsCodingScheme::MCS6;
1220 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
1221 egprs2->r = 1;
1222 egprs2->si = 1;
1223 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001224 egprs2->tfi_hi = tfi & 0x03;
1225 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1226 egprs2->bsn1_hi = 0;
1227 egprs2->bsn1_lo = 0;
1228 egprs2->cps_hi = 3;
1229 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301230 egprs2->rsb = 0;
1231 egprs2->pi = 0;
1232 data[10] = 0x20; /* Setting E field */
1233 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1234 offs = rlc.data_offs_bits[0] / 8;
1235 OSMO_ASSERT(offs == 10);
1236 OSMO_ASSERT(rlc.num_data_blocks == 1);
1237 OSMO_ASSERT(rlc.tfi == 1);
1238 OSMO_ASSERT(rlc.block_info[0].e == 1);
1239 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1240 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1241
1242 egprs2->r = 1;
1243 egprs2->si = 1;
1244 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001245 egprs2->tfi_hi = tfi & 0x03;
1246 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1247 egprs2->bsn1_hi = 1;
1248 egprs2->bsn1_lo = 0;
1249 egprs2->cps_hi = 2;
1250 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301251 egprs2->rsb = 0;
1252 egprs2->pi = 0;
1253 data[10] = 0x20; /* Setting E field */
1254 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1255 offs = rlc.data_offs_bits[0] / 8;
1256 OSMO_ASSERT(offs == 10);
1257 OSMO_ASSERT(rlc.tfi == 1);
1258 OSMO_ASSERT(rlc.num_data_blocks == 1);
1259 OSMO_ASSERT(rlc.block_info[0].e == 1);
1260 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1261 OSMO_ASSERT(rlc.block_info[0].bsn == 1);
1262}
1263
1264static void uplink_header_type2_test(void)
1265{
1266 BTS the_bts;
1267 int ts_no = 7;
1268 uint32_t fn = 2654218;
1269 uint16_t qta = 31;
1270 uint32_t tlli = 0xf1223344;
1271 const char *imsi = "0011223344";
1272 uint8_t ms_class = 1;
1273 gprs_rlcmac_ul_tbf *ul_tbf;
1274 GprsMs *ms;
1275
1276 printf("=== start %s ===\n", __func__);
1277 setup_bts(&the_bts, ts_no, 10);
1278
1279 uplink_header_type_2_parsing_test(&the_bts, ts_no,
1280 tlli, &fn, qta, ms_class);
1281 printf("=== end %s ===\n", __func__);
1282}
1283
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301284static void uplink_header_type_1_parsing_test(BTS *the_bts,
1285 uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
1286 uint8_t ms_class)
1287{
1288 uint8_t trx_no = 0;
1289 int tfi = 0;
1290 struct gprs_rlcmac_pdch *pdch;
1291 gprs_rlcmac_bts *bts;
1292 uint8_t data[155] = {0};
1293 struct gprs_rlc_ul_header_egprs_1 *egprs1 = NULL;
1294 struct gprs_rlc_data_info rlc;
1295 GprsCodingScheme cs;
1296 int rc, offs;
1297
1298 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1299 bts = the_bts->bts_data();
1300
1301 tfi = 1;
1302
1303 /* MCS 7 */
1304 cs = GprsCodingScheme::MCS7;
1305 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1306 egprs1->si = 1;
1307 egprs1->r = 1;
1308 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001309 egprs1->tfi_hi = tfi & 0x03;
1310 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1311 egprs1->bsn1_hi = 0;
1312 egprs1->bsn1_lo = 0;
1313 egprs1->bsn2_hi = 1;
1314 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301315 egprs1->cps = 15;
1316 egprs1->rsb = 0;
1317 egprs1->pi = 0;
1318 data[5] = 0xc0;
1319 data[5 + 57] = 1;
1320 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1321 OSMO_ASSERT(rlc.num_data_blocks == 2);
1322 OSMO_ASSERT(rlc.block_info[0].e == 1);
1323 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1324 OSMO_ASSERT(rlc.block_info[1].e == 1);
1325 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1326 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1327 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1328 OSMO_ASSERT(rlc.tfi == 1);
1329
1330 /* MCS 8 */
1331 cs = GprsCodingScheme::MCS8;
1332 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1333 egprs1->si = 1;
1334 egprs1->r = 1;
1335 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001336 egprs1->tfi_hi = tfi & 0x03;
1337 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1338 egprs1->bsn1_hi = 0;
1339 egprs1->bsn1_lo = 0;
1340 egprs1->bsn2_hi = 1;
1341 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301342 egprs1->cps = 15;
1343 egprs1->rsb = 0;
1344 egprs1->pi = 0;
1345 data[5] = 0xc0;
1346 data[5 + 69] = 1;
1347 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1348 OSMO_ASSERT(rlc.num_data_blocks == 2);
1349 OSMO_ASSERT(rlc.block_info[0].e == 1);
1350 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1351 OSMO_ASSERT(rlc.block_info[1].e == 1);
1352 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1353 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1354 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1355 OSMO_ASSERT(rlc.tfi == 1);
1356
1357 /* MCS 9 */
1358 cs = GprsCodingScheme::MCS9;
1359 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1360 egprs1->si = 1;
1361 egprs1->r = 1;
1362 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001363 egprs1->tfi_hi = tfi & 0x03;
1364 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1365 egprs1->bsn1_hi = 0;
1366 egprs1->bsn1_lo = 0;
1367 egprs1->bsn2_hi = 1;
1368 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301369 egprs1->cps = 15;
1370 egprs1->rsb = 0;
1371 egprs1->pi = 0;
1372 data[5] = 0xc0;
1373 data[5 + 75] = 1;
1374 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1375 OSMO_ASSERT(rlc.num_data_blocks == 2);
1376 OSMO_ASSERT(rlc.block_info[0].e == 1);
1377 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1378 OSMO_ASSERT(rlc.block_info[1].e == 1);
1379 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1380 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1381 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1382 OSMO_ASSERT(rlc.tfi == 1);
1383}
1384
1385void uplink_header_type1_test(void)
1386{
1387 BTS the_bts;
1388 int ts_no = 7;
1389 uint32_t fn = 2654218;
1390 uint16_t qta = 31;
1391 uint32_t tlli = 0xf1223344;
1392 const char *imsi = "0011223344";
1393 uint8_t ms_class = 1;
1394 gprs_rlcmac_ul_tbf *ul_tbf;
1395 GprsMs *ms;
1396
1397 printf("=== start %s ===\n", __func__);
1398 setup_bts(&the_bts, ts_no, 12);
1399 uplink_header_type_1_parsing_test(&the_bts, ts_no, tlli, &fn,
1400 qta, ms_class);
1401 printf("=== end %s ===\n", __func__);
1402}
1403
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001404int main(int argc, char **argv)
1405{
1406 struct vty_app_info pcu_vty_info = {0};
1407
1408 tall_pcu_ctx = talloc_named_const(NULL, 1, "EdgeTest context");
1409 if (!tall_pcu_ctx)
1410 abort();
1411
1412 msgb_set_talloc_ctx(tall_pcu_ctx);
1413 osmo_init_logging(&debug_log_info);
1414 log_set_use_color(osmo_stderr_target, 0);
1415 log_set_print_filename(osmo_stderr_target, 0);
1416
1417 vty_init(&pcu_vty_info);
1418 pcu_vty_init(&debug_log_info);
1419
1420 test_coding_scheme();
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001421 test_rlc_info_init();
Jacob Erlbeck38f18692016-02-01 10:08:00 +01001422 test_rlc_unit_decoder();
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001423 test_rlc_unaligned_copy();
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001424 test_rlc_unit_encoder();
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001425
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301426 uplink_header_type2_test();
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301427 uplink_header_type1_test();
1428
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001429 if (getenv("TALLOC_REPORT_FULL"))
1430 talloc_report_full(tall_pcu_ctx, stderr);
1431 return EXIT_SUCCESS;
1432}
1433
1434/*
1435 * stubs that should not be reached
1436 */
1437extern "C" {
1438void l1if_pdch_req() { abort(); }
1439void l1if_connect_pdch() { abort(); }
1440void l1if_close_pdch() { abort(); }
1441void l1if_open_pdch() { abort(); }
1442}