blob: 0cb123e40fd273844477b6846dbae3875165ee6c [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"
Max1187a772018-01-26 13:31:42 +010030#include <gprs_rlcmac.h>
31
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010032extern "C" {
33#include "pcu_vty.h"
34
35#include <osmocom/core/application.h>
36#include <osmocom/core/msgb.h>
37#include <osmocom/core/talloc.h>
38#include <osmocom/core/utils.h>
39#include <osmocom/vty/vty.h>
Tom Tsoudf698092016-07-11 17:05:19 -070040#include <osmocom/gprs/protocol/gsm_04_60.h>
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010041}
42
43#include <errno.h>
Jacob Erlbeckf0e40392016-01-08 10:07:53 +010044#include <string.h>
Neels Hofmeyrd34646a2017-02-08 17:07:40 +010045#include <limits.h>
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010046
47void *tall_pcu_ctx;
48int16_t spoof_mnc = 0, spoof_mcc = 0;
Neels Hofmeyrbdc55fa2018-02-21 00:39:07 +010049bool spoof_mnc_3_digits = false;
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010050
51static void check_coding_scheme(GprsCodingScheme& cs, GprsCodingScheme::Mode mode)
52{
53 volatile unsigned expected_size;
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010054 bool need_padding;
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010055 GprsCodingScheme new_cs;
56
57 OSMO_ASSERT(cs.isValid());
58 OSMO_ASSERT(cs.isCompatible(mode));
59
60 /* Check static getBySizeUL() */
Jacob Erlbeckfc1b3e62016-01-11 09:58:11 +010061 expected_size = cs.usedSizeUL();
62 if (cs.spareBitsUL() > 0 && cs.isGprs())
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010063 expected_size += 1;
64 OSMO_ASSERT(expected_size == cs.sizeUL());
65 OSMO_ASSERT(cs == GprsCodingScheme::getBySizeUL(expected_size));
66
67 /* Check static sizeUL() */
Jacob Erlbeckfc1b3e62016-01-11 09:58:11 +010068 expected_size = cs.usedSizeDL();
69 if (cs.spareBitsDL() > 0 && cs.isGprs())
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010070 expected_size += 1;
71 OSMO_ASSERT(expected_size == cs.sizeDL());
72
Jacob Erlbeck392a5452015-12-14 10:38:29 +010073 /* Check data block sizes */
74 OSMO_ASSERT(cs.maxDataBlockBytes() * cs.numDataBlocks() < cs.maxBytesDL());
75 OSMO_ASSERT(cs.maxDataBlockBytes() * cs.numDataBlocks() < cs.maxBytesUL());
76
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010077 /* Check inc/dec */
78 new_cs = cs;
79 new_cs.inc(mode);
80 OSMO_ASSERT(new_cs.isCompatible(mode));
81 if (new_cs != cs) {
82 new_cs.dec(mode);
83 OSMO_ASSERT(new_cs.isCompatible(mode));
84 OSMO_ASSERT(new_cs == cs);
85 }
86 new_cs.dec(mode);
87 OSMO_ASSERT(new_cs.isCompatible(mode));
88 if (new_cs != cs) {
89 new_cs.inc(mode);
90 OSMO_ASSERT(new_cs.isCompatible(mode));
91 OSMO_ASSERT(new_cs == cs);
92 }
Jacob Erlbeck2305afd2016-02-03 15:25:04 +010093
94 new_cs = cs;
95 new_cs.decToSingleBlock(&need_padding);
96 OSMO_ASSERT(new_cs.isFamilyCompatible(cs));
97 OSMO_ASSERT(cs.isFamilyCompatible(new_cs));
98 OSMO_ASSERT(cs.isCompatible(new_cs));
99 if (need_padding) {
Jacob Erlbeck215e18c2016-02-03 18:22:34 +0100100 OSMO_ASSERT(new_cs.maxDataBlockBytes() ==
101 new_cs.optionalPaddingBits()/8 + cs.maxDataBlockBytes());
Jacob Erlbeck2305afd2016-02-03 15:25:04 +0100102 } else {
103 OSMO_ASSERT(new_cs.maxDataBlockBytes() == cs.maxDataBlockBytes());
104 }
105
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100106}
107
Max360e0212019-02-26 17:20:41 +0100108static bool check_strong_monotonicity(const GprsCodingScheme *cs, uint8_t last_UL, uint8_t last_DL)
109{
110 if (cs->maxBytesUL() <= last_UL)
111 return false;
112
113 if (cs->maxBytesDL() <= last_DL)
114 return false;
115
116 return true;
117}
118
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100119static void test_coding_scheme()
120{
121 unsigned i;
Max360e0212019-02-26 17:20:41 +0100122 uint8_t last_size_UL;
123 uint8_t last_size_DL;
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100124 GprsCodingScheme::Scheme gprs_schemes[] = {
125 GprsCodingScheme::CS1,
126 GprsCodingScheme::CS2,
127 GprsCodingScheme::CS3,
128 GprsCodingScheme::CS4
129 };
130 struct {
131 GprsCodingScheme::Scheme s;
132 bool is_gmsk;
133 } egprs_schemes[] = {
134 {GprsCodingScheme::MCS1, true},
135 {GprsCodingScheme::MCS2, true},
136 {GprsCodingScheme::MCS3, true},
137 {GprsCodingScheme::MCS4, true},
138 {GprsCodingScheme::MCS5, false},
139 {GprsCodingScheme::MCS6, false},
140 {GprsCodingScheme::MCS7, false},
141 {GprsCodingScheme::MCS8, false},
142 {GprsCodingScheme::MCS9, false},
143 };
144
145 printf("=== start %s ===\n", __func__);
146
147 GprsCodingScheme cs;
148 OSMO_ASSERT(!cs);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100149 OSMO_ASSERT(GprsCodingScheme::Scheme(cs) == GprsCodingScheme::UNKNOWN);
150 OSMO_ASSERT(cs == GprsCodingScheme(GprsCodingScheme::UNKNOWN));
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100151 OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::GPRS));
152 OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::EGPRS_GMSK));
153 OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::EGPRS));
154
155 last_size_UL = 0;
156 last_size_DL = 0;
157
158 for (i = 0; i < ARRAY_SIZE(gprs_schemes); i++) {
159 GprsCodingScheme current_cs(gprs_schemes[i]);
160 OSMO_ASSERT(current_cs.isGprs());
161 OSMO_ASSERT(!current_cs.isEgprs());
162 OSMO_ASSERT(!current_cs.isEgprsGmsk());
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100163 OSMO_ASSERT(GprsCodingScheme::Scheme(current_cs) == gprs_schemes[i]);
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100164 OSMO_ASSERT(current_cs == GprsCodingScheme(gprs_schemes[i]));
165
Max360e0212019-02-26 17:20:41 +0100166 OSMO_ASSERT(check_strong_monotonicity(&current_cs, last_size_UL, last_size_DL));
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100167 last_size_UL = current_cs.maxBytesUL();
168 last_size_DL = current_cs.maxBytesDL();
169
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +0100170 /* Check header types */
171 OSMO_ASSERT(current_cs.headerTypeData() ==
172 GprsCodingScheme::HEADER_GPRS_DATA);
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +0100173
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100174 check_coding_scheme(current_cs, GprsCodingScheme::GPRS);
175 }
176 OSMO_ASSERT(i == 4);
177
178 last_size_UL = 0;
179 last_size_DL = 0;
180
181 for (i = 0; i < ARRAY_SIZE(egprs_schemes); i++) {
182 GprsCodingScheme current_cs(egprs_schemes[i].s);
183 OSMO_ASSERT(!current_cs.isGprs());
184 OSMO_ASSERT(current_cs.isEgprs());
185 OSMO_ASSERT(!!current_cs.isEgprsGmsk() == !!egprs_schemes[i].is_gmsk);
Jacob Erlbeck4c9e5492016-01-04 16:00:05 +0100186 OSMO_ASSERT(GprsCodingScheme::Scheme(current_cs) == egprs_schemes[i].s);
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100187 OSMO_ASSERT(current_cs == GprsCodingScheme(egprs_schemes[i].s));
188
Max360e0212019-02-26 17:20:41 +0100189 OSMO_ASSERT(check_strong_monotonicity(&current_cs, last_size_UL, last_size_DL));
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100190 last_size_UL = current_cs.maxBytesUL();
191 last_size_DL = current_cs.maxBytesDL();
192
193 if (egprs_schemes[i].is_gmsk)
194 check_coding_scheme(current_cs, GprsCodingScheme::EGPRS_GMSK);
195 check_coding_scheme(current_cs, GprsCodingScheme::EGPRS);
196 }
197 OSMO_ASSERT(i == 9);
198
199 printf("=== end %s ===\n", __func__);
200}
201
Jacob Erlbeck38f18692016-02-01 10:08:00 +0100202static void test_rlc_unit_decoder()
Jacob Erlbeck61679252015-12-11 18:25:21 +0100203{
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100204 struct gprs_rlc_data_block_info rdbi = {0};
Jacob Erlbeck61679252015-12-11 18:25:21 +0100205 GprsCodingScheme cs;
206 uint8_t data[74];
207 Decoding::RlcData chunks[16];
208 volatile int num_chunks = 0;
209 uint32_t tlli, tlli2;
210 unsigned int offs;
211
212
213 printf("=== start %s ===\n", __func__);
214
215 /* TS 44.060, B.1 */
216 cs = GprsCodingScheme::CS4;
217 rdbi.data_len = cs.maxDataBlockBytes();
218 rdbi.e = 0;
219 rdbi.ti = 0;
220 rdbi.cv = 15;
221 tlli = 0;
222 offs = 0;
223 data[offs++] = (11 << 2) | (1 << 1) | (0 << 0);
224 data[offs++] = (26 << 2) | (1 << 1) | (1 << 0);
225 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
226 chunks, ARRAY_SIZE(chunks), &tlli);
227 OSMO_ASSERT(num_chunks == 3);
228 OSMO_ASSERT(tlli == 0);
229 OSMO_ASSERT(chunks[0].offset == 2);
230 OSMO_ASSERT(chunks[0].length == 11);
231 OSMO_ASSERT(chunks[0].is_complete);
232 OSMO_ASSERT(chunks[1].offset == 13);
233 OSMO_ASSERT(chunks[1].length == 26);
234 OSMO_ASSERT(chunks[1].is_complete);
235 OSMO_ASSERT(chunks[2].offset == 39);
236 OSMO_ASSERT(chunks[2].length == cs.maxDataBlockBytes() - 39);
237 OSMO_ASSERT(!chunks[2].is_complete);
238
239 /* TS 44.060, B.2 */
240 cs = GprsCodingScheme::CS1;
241 rdbi.data_len = cs.maxDataBlockBytes();
242 rdbi.e = 0;
243 rdbi.ti = 0;
244 rdbi.cv = 15;
245 tlli = 0;
246 offs = 0;
247 data[offs++] = (0 << 2) | (0 << 1) | (1 << 0);
248 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
249 chunks, ARRAY_SIZE(chunks), &tlli);
250 OSMO_ASSERT(num_chunks == 1);
251 OSMO_ASSERT(tlli == 0);
252 OSMO_ASSERT(chunks[0].offset == 1);
253 OSMO_ASSERT(chunks[0].length == 19);
254 OSMO_ASSERT(!chunks[0].is_complete);
255
256 rdbi.e = 0;
257 rdbi.ti = 0;
258 rdbi.cv = 15;
259 tlli = 0;
260 offs = 0;
261 data[offs++] = (1 << 2) | (1 << 1) | (1 << 0);
262 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
263 chunks, ARRAY_SIZE(chunks), &tlli);
264 OSMO_ASSERT(num_chunks == 2);
265 OSMO_ASSERT(tlli == 0);
266 OSMO_ASSERT(chunks[0].offset == 1);
267 OSMO_ASSERT(chunks[0].length == 1);
268 OSMO_ASSERT(chunks[0].is_complete);
269 OSMO_ASSERT(chunks[1].offset == 2);
270 OSMO_ASSERT(chunks[1].length == 18);
271 OSMO_ASSERT(!chunks[1].is_complete);
272
273 /* TS 44.060, B.3 */
274 cs = GprsCodingScheme::CS1;
275 rdbi.data_len = cs.maxDataBlockBytes();
276 rdbi.e = 0;
277 rdbi.ti = 0;
278 rdbi.cv = 15;
279 tlli = 0;
280 offs = 0;
281 data[offs++] = (7 << 2) | (1 << 1) | (0 << 0);
282 data[offs++] = (11 << 2) | (0 << 1) | (1 << 0);
283 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
284 chunks, ARRAY_SIZE(chunks), &tlli);
285 OSMO_ASSERT(num_chunks == 2);
286 OSMO_ASSERT(tlli == 0);
287 OSMO_ASSERT(chunks[0].offset == 2);
288 OSMO_ASSERT(chunks[0].length == 7);
289 OSMO_ASSERT(chunks[0].is_complete);
290 OSMO_ASSERT(chunks[1].offset == 9);
291 OSMO_ASSERT(chunks[1].length == 11);
292 OSMO_ASSERT(chunks[1].is_complete);
293
294 /* TS 44.060, B.4 */
295 cs = GprsCodingScheme::CS1;
296 rdbi.data_len = cs.maxDataBlockBytes();
297 rdbi.e = 1;
298 rdbi.ti = 0;
299 rdbi.cv = 15;
300 tlli = 0;
301 offs = 0;
302 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
303 chunks, ARRAY_SIZE(chunks), &tlli);
304 OSMO_ASSERT(num_chunks == 1);
305 OSMO_ASSERT(tlli == 0);
306 OSMO_ASSERT(chunks[0].offset == 0);
307 OSMO_ASSERT(chunks[0].length == 20);
308 OSMO_ASSERT(!chunks[0].is_complete);
309
310 /* TS 44.060, B.6 */
311 cs = GprsCodingScheme::CS1;
312 rdbi.data_len = cs.maxDataBlockBytes();
313 rdbi.e = 1;
314 rdbi.ti = 0;
315 rdbi.cv = 0;
316 tlli = 0;
317 offs = 0;
318 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
319 chunks, ARRAY_SIZE(chunks), &tlli);
320 OSMO_ASSERT(num_chunks == 1);
321 OSMO_ASSERT(tlli == 0);
322 OSMO_ASSERT(chunks[0].offset == 0);
323 OSMO_ASSERT(chunks[0].length == 20);
324 OSMO_ASSERT(chunks[0].is_complete);
325
326 /* TS 44.060, B.8.1 */
327 cs = GprsCodingScheme::MCS4;
328 rdbi.data_len = cs.maxDataBlockBytes();
329 rdbi.e = 0;
330 rdbi.ti = 0;
331 rdbi.cv = 15;
332 tlli = 0;
333 offs = 0;
334 data[offs++] = (11 << 1) | (0 << 0);
335 data[offs++] = (26 << 1) | (1 << 0);
336 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
337 chunks, ARRAY_SIZE(chunks), &tlli);
338 OSMO_ASSERT(num_chunks == 3);
339 OSMO_ASSERT(tlli == 0);
340 OSMO_ASSERT(chunks[0].offset == 2);
341 OSMO_ASSERT(chunks[0].length == 11);
342 OSMO_ASSERT(chunks[0].is_complete);
343 OSMO_ASSERT(chunks[1].offset == 13);
344 OSMO_ASSERT(chunks[1].length == 26);
345 OSMO_ASSERT(chunks[1].is_complete);
346 OSMO_ASSERT(chunks[2].offset == 39);
347 OSMO_ASSERT(chunks[2].length == 5);
348 OSMO_ASSERT(!chunks[2].is_complete);
349
350 /* TS 44.060, B.8.2 */
351
352 /* Note that the spec confuses the byte numbering here, since it
353 * includes the FBI/E header bits into the N2 octet count which
354 * is not consistent with Section 10.3a.1 & 10.3a.2. */
355
356 cs = GprsCodingScheme::MCS2;
357 rdbi.data_len = cs.maxDataBlockBytes();
358 rdbi.e = 0;
359 rdbi.ti = 0;
360 rdbi.cv = 15;
361 tlli = 0;
362 offs = 0;
363 data[offs++] = (15 << 1) | (1 << 0);
364 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
365 chunks, ARRAY_SIZE(chunks), &tlli);
366 OSMO_ASSERT(num_chunks == 2);
367 OSMO_ASSERT(tlli == 0);
368 OSMO_ASSERT(chunks[0].offset == 1);
369 OSMO_ASSERT(chunks[0].length == 15);
370 OSMO_ASSERT(chunks[0].is_complete);
371 OSMO_ASSERT(chunks[1].offset == 16);
372 OSMO_ASSERT(chunks[1].length == 12);
373 OSMO_ASSERT(!chunks[1].is_complete);
374
375 rdbi.e = 0;
376 rdbi.ti = 0;
377 rdbi.cv = 15;
378 tlli = 0;
379 offs = 0;
380 data[offs++] = ( 0 << 1) | (0 << 0);
381 data[offs++] = ( 7 << 1) | (0 << 0);
382 data[offs++] = (18 << 1) | (1 << 0); /* Differs from spec's N2-11 = 17 */
383 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
384 chunks, ARRAY_SIZE(chunks), &tlli);
385 OSMO_ASSERT(num_chunks == 3);
386 OSMO_ASSERT(tlli == 0);
387 OSMO_ASSERT(chunks[0].offset == 3);
388 OSMO_ASSERT(chunks[0].length == 0);
389 OSMO_ASSERT(chunks[0].is_complete);
390 OSMO_ASSERT(chunks[1].offset == 3);
391 OSMO_ASSERT(chunks[1].length == 7);
392 OSMO_ASSERT(chunks[1].is_complete);
393 OSMO_ASSERT(chunks[2].offset == 10);
394 OSMO_ASSERT(chunks[2].length == 18);
395 OSMO_ASSERT(chunks[2].is_complete);
396
397 rdbi.e = 0;
398 rdbi.ti = 0;
399 rdbi.cv = 0;
400 tlli = 0;
401 offs = 0;
402 data[offs++] = ( 6 << 1) | (0 << 0);
403 data[offs++] = (12 << 1) | (0 << 0);
404 data[offs++] = (127 << 1) | (1 << 0);
405 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
406 chunks, ARRAY_SIZE(chunks), &tlli);
407 OSMO_ASSERT(num_chunks == 2);
408 OSMO_ASSERT(tlli == 0);
409 OSMO_ASSERT(chunks[0].offset == 3);
410 OSMO_ASSERT(chunks[0].length == 6);
411 OSMO_ASSERT(chunks[0].is_complete);
412 OSMO_ASSERT(chunks[1].offset == 9);
413 OSMO_ASSERT(chunks[1].length == 12);
414 OSMO_ASSERT(chunks[1].is_complete);
415
416 /* TS 44.060, B.8.3 */
417
418 /* Note that the spec confuses the byte numbering here, too (see above) */
419
420 cs = GprsCodingScheme::MCS2;
421 rdbi.data_len = cs.maxDataBlockBytes();
422 rdbi.e = 1;
423 rdbi.ti = 0;
424 rdbi.cv = 0;
425 tlli = 0;
426 offs = 0;
427 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
428 chunks, ARRAY_SIZE(chunks), &tlli);
429 OSMO_ASSERT(num_chunks == 1);
430 OSMO_ASSERT(tlli == 0);
431 OSMO_ASSERT(chunks[0].offset == 0);
432 OSMO_ASSERT(chunks[0].length == 28);
433 OSMO_ASSERT(chunks[0].is_complete);
434
435 /* CS-1, TLLI, last block, single chunk until the end of the block */
436 cs = GprsCodingScheme::CS1;
437 rdbi.data_len = cs.maxDataBlockBytes();
438 rdbi.e = 1;
439 rdbi.ti = 1;
440 rdbi.cv = 0;
441 tlli = 0;
442 tlli2 = 0xffeeddcc;
443 offs = 0;
444 data[offs++] = tlli2 >> 24;
445 data[offs++] = tlli2 >> 16;
446 data[offs++] = tlli2 >> 8;
447 data[offs++] = tlli2 >> 0;
448 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
449 chunks, ARRAY_SIZE(chunks), &tlli);
450 OSMO_ASSERT(num_chunks == 1);
451 OSMO_ASSERT(tlli == tlli2);
452 OSMO_ASSERT(chunks[0].offset == 4);
453 OSMO_ASSERT(chunks[0].length == 16);
454 OSMO_ASSERT(chunks[0].is_complete);
455
456 /* Like TS 44.060, B.2, first RLC block but with TLLI */
457 cs = GprsCodingScheme::CS1;
458 rdbi.data_len = cs.maxDataBlockBytes();
459 rdbi.e = 0;
460 rdbi.ti = 1;
461 rdbi.cv = 15;
462 tlli = 0;
463 tlli2 = 0xffeeddbb;
464 offs = 0;
465 data[offs++] = (0 << 2) | (0 << 1) | (1 << 0);
466 data[offs++] = tlli2 >> 24;
467 data[offs++] = tlli2 >> 16;
468 data[offs++] = tlli2 >> 8;
469 data[offs++] = tlli2 >> 0;
470 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
471 chunks, ARRAY_SIZE(chunks), &tlli);
472 OSMO_ASSERT(num_chunks == 1);
473 OSMO_ASSERT(tlli == tlli2);
474 OSMO_ASSERT(chunks[0].offset == 5);
475 OSMO_ASSERT(chunks[0].length == 15);
476 OSMO_ASSERT(!chunks[0].is_complete);
477
478 /* Like TS 44.060, B.8.1 but with TLLI */
479 cs = GprsCodingScheme::MCS4;
480 rdbi.data_len = cs.maxDataBlockBytes();
481 rdbi.e = 0;
482 rdbi.ti = 1;
483 rdbi.cv = 15;
484 tlli = 0;
485 tlli2 = 0xffeeddaa;
486 offs = 0;
487 data[offs++] = (11 << 1) | (0 << 0);
488 data[offs++] = (26 << 1) | (1 << 0);
489 /* Little endian */
490 data[offs++] = tlli2 >> 0;
491 data[offs++] = tlli2 >> 8;
492 data[offs++] = tlli2 >> 16;
493 data[offs++] = tlli2 >> 24;
494 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
495 chunks, ARRAY_SIZE(chunks), &tlli);
496 OSMO_ASSERT(num_chunks == 3);
497 OSMO_ASSERT(tlli == tlli2);
498 OSMO_ASSERT(chunks[0].offset == 6);
499 OSMO_ASSERT(chunks[0].length == 11);
500 OSMO_ASSERT(chunks[0].is_complete);
501 OSMO_ASSERT(chunks[1].offset == 17);
502 OSMO_ASSERT(chunks[1].length == 26);
503 OSMO_ASSERT(chunks[1].is_complete);
504 OSMO_ASSERT(chunks[2].offset == 43);
505 OSMO_ASSERT(chunks[2].length == 1);
506 OSMO_ASSERT(!chunks[2].is_complete);
507
Aravind Sirsikar3463bd42016-09-15 17:19:54 +0530508 rdbi.e = 0;
509 rdbi.ti = 0;
510 rdbi.cv = 1;
511 tlli = 0;
512 offs = 0;
513 data[offs++] = 1;
514 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
515 chunks, ARRAY_SIZE(chunks), &tlli);
516
Aravind Sirsikar22a90192016-09-15 17:24:49 +0530517 OSMO_ASSERT(num_chunks == 2);
Aravind Sirsikar3463bd42016-09-15 17:19:54 +0530518 OSMO_ASSERT(chunks[0].offset == 1);
Aravind Sirsikar22a90192016-09-15 17:24:49 +0530519 OSMO_ASSERT(chunks[0].length == 0);
520 OSMO_ASSERT(chunks[0].is_complete);
521
522 OSMO_ASSERT(chunks[1].offset == 1);
523 OSMO_ASSERT(chunks[1].length == 43);
524 OSMO_ASSERT(!chunks[1].is_complete);
Aravind Sirsikar3463bd42016-09-15 17:19:54 +0530525
Jacob Erlbeck61679252015-12-11 18:25:21 +0100526 printf("=== end %s ===\n", __func__);
527}
528
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100529static void test_rlc_unit_encoder()
530{
531 struct gprs_rlc_data_block_info rdbi = {0};
532 GprsCodingScheme cs;
533 uint8_t data[74];
534 uint8_t llc_data[1500] = {0,};
535 int num_chunks = 0;
536 int write_offset;
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200537 int count_payload;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100538 struct gprs_llc llc;
539 Encoding::AppendResult ar;
540
541 printf("=== start %s ===\n", __func__);
542
543 llc.init();
544
545 /* TS 44.060, B.1 */
546 cs = GprsCodingScheme::CS4;
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530547 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100548 num_chunks = 0;
549 write_offset = 0;
550 memset(data, 0, sizeof(data));
551
552 llc.reset();
553 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200554 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100555
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100556 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200557 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100558
559 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
560 OSMO_ASSERT(rdbi.e == 0);
561 OSMO_ASSERT(write_offset == 1 + 11);
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 == 1);
564
565 llc.reset();
566 llc.put_frame(llc_data, 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200567 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100568
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100569 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200570 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100571
572 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
573 OSMO_ASSERT(rdbi.e == 0);
574 OSMO_ASSERT(write_offset == 2 + 11 + 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200575 OSMO_ASSERT(count_payload == 26);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100576 OSMO_ASSERT(num_chunks == 2);
577
578 llc.reset();
579 llc.put_frame(llc_data, 99);
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(rdbi.cv != 0);
588 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200589 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100590 OSMO_ASSERT(num_chunks == 3);
591
592 OSMO_ASSERT(data[0] == ((11 << 2) | (1 << 1) | (0 << 0)));
593 OSMO_ASSERT(data[1] == ((26 << 2) | (1 << 1) | (1 << 0)));
594 OSMO_ASSERT(data[2] == 0);
595
596 /* TS 44.060, B.2 */
597 cs = GprsCodingScheme::CS1;
598
599 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530600 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100601 num_chunks = 0;
602 write_offset = 0;
603 memset(data, 0, sizeof(data));
604
605 llc.reset();
606 llc.put_frame(llc_data, 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200607 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100608
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100609 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200610 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100611
612 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
613 OSMO_ASSERT(rdbi.e == 0);
614 OSMO_ASSERT(write_offset == 1 + 19);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200615 OSMO_ASSERT(count_payload == 19);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100616 OSMO_ASSERT(num_chunks == 1);
617
618 OSMO_ASSERT(data[0] == ((0 << 2) | (0 << 1) | (1 << 0)));
619 OSMO_ASSERT(data[1] == 0);
620
621 /* Block 2 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530622 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100623 num_chunks = 0;
624 write_offset = 0;
625 memset(data, 0, sizeof(data));
626
627 OSMO_ASSERT(llc.chunk_size() == 1);
628
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200629 count_payload = -1;
630
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100631 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200632 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100633
634 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
635 OSMO_ASSERT(rdbi.e == 0);
636 OSMO_ASSERT(write_offset == 1 + 1);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200637 OSMO_ASSERT(count_payload == 1);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100638 OSMO_ASSERT(num_chunks == 1);
639
640 llc.reset();
641 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200642 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100643
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100644 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200645 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100646
647 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
648 OSMO_ASSERT(rdbi.e == 0);
649 OSMO_ASSERT(write_offset == 1 + 1 + 18);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200650 OSMO_ASSERT(count_payload == 18);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100651 OSMO_ASSERT(num_chunks == 2);
652
653 OSMO_ASSERT(data[0] == ((1 << 2) | (1 << 1) | (1 << 0)));
654 OSMO_ASSERT(data[1] == 0);
655
656 /* TS 44.060, B.3 */
657 cs = GprsCodingScheme::CS1;
658
659 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530660 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100661 num_chunks = 0;
662 write_offset = 0;
663 memset(data, 0, sizeof(data));
664
665 llc.reset();
666 llc.put_frame(llc_data, 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200667 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100668
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100669 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200670 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100671
672 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
673 OSMO_ASSERT(rdbi.e == 0);
674 OSMO_ASSERT(write_offset == 1 + 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200675 OSMO_ASSERT(count_payload == 7);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100676 OSMO_ASSERT(num_chunks == 1);
677
678 llc.reset();
679 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200680 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100681
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100682 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200683 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100684
685 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
686 OSMO_ASSERT(rdbi.e == 0);
687 OSMO_ASSERT(write_offset == 2 + 7 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200688 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100689 OSMO_ASSERT(num_chunks == 2);
690
691 OSMO_ASSERT(data[0] == ((7 << 2) | (1 << 1) | (0 << 0)));
692 OSMO_ASSERT(data[1] == ((11 << 2) | (0 << 1) | (1 << 0)));
693 OSMO_ASSERT(data[2] == 0);
694
695 /* TS 44.060, B.4 */
696 cs = GprsCodingScheme::CS1;
697
698 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530699 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100700 num_chunks = 0;
701 write_offset = 0;
702 memset(data, 0, sizeof(data));
703
704 llc.reset();
705 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200706 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100707
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100708 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200709 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100710
711 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
712 OSMO_ASSERT(rdbi.e == 1);
713 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200714 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100715 OSMO_ASSERT(num_chunks == 1);
716 OSMO_ASSERT(rdbi.cv != 0);
717
718 OSMO_ASSERT(data[0] == 0);
719
720 /* TS 44.060, B.5 */
721 cs = GprsCodingScheme::CS1;
722
723 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530724 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100725 num_chunks = 0;
726 write_offset = 0;
727 memset(data, 0, sizeof(data));
728
729 llc.reset();
730 llc.put_frame(llc_data, 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200731 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100732
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100733 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200734 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100735
736 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
737 OSMO_ASSERT(rdbi.e == 1);
738 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200739 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100740 OSMO_ASSERT(num_chunks == 1);
741 OSMO_ASSERT(rdbi.cv == 0);
742
743 OSMO_ASSERT(data[0] == 0);
744
745 /* TS 44.060, B.7 */
746 cs = GprsCodingScheme::CS1;
747
748 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530749 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100750 num_chunks = 0;
751 write_offset = 0;
752 memset(data, 0, sizeof(data));
753
754 llc.reset();
755 llc.put_frame(llc_data, 30);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200756 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100757
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100758 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200759 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100760
761 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
762 OSMO_ASSERT(rdbi.e == 1);
763 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200764 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100765 OSMO_ASSERT(num_chunks == 1);
766
767 OSMO_ASSERT(data[0] == 0);
768
769 /* Block 2 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530770 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100771 num_chunks = 0;
772 write_offset = 0;
773 memset(data, 0, sizeof(data));
774
775 OSMO_ASSERT(llc.chunk_size() == 10);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200776 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100777
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100778 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200779 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100780
781 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
782 OSMO_ASSERT(rdbi.e == 0);
783 OSMO_ASSERT(write_offset == 1 + 10);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200784 OSMO_ASSERT(count_payload == 10);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100785 OSMO_ASSERT(num_chunks == 1);
786
787 llc.reset();
788 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200789 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100790
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100791 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200792 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100793
794 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
795 OSMO_ASSERT(rdbi.e == 0);
796 OSMO_ASSERT(write_offset == 1 + 10 + 9);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200797 OSMO_ASSERT(count_payload == 9);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100798 OSMO_ASSERT(num_chunks == 2);
799
800 OSMO_ASSERT(data[0] == ((10 << 2) | (1 << 1) | (1 << 0)));
801 OSMO_ASSERT(data[1] == 0);
802
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100803 /* TS 44.060, B.8.1 */
804 cs = GprsCodingScheme::MCS4;
805
806 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530807 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100808 num_chunks = 0;
809 write_offset = 0;
810 memset(data, 0, sizeof(data));
811
812 llc.reset();
813 llc.put_frame(llc_data, 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200814 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100815
816 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200817 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100818
819 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
820 OSMO_ASSERT(rdbi.e == 0);
821 OSMO_ASSERT(write_offset == 1 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200822 OSMO_ASSERT(count_payload == 11);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100823 OSMO_ASSERT(num_chunks == 1);
824
825 llc.reset();
826 llc.put_frame(llc_data, 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200827 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100828
829 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200830 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100831
832 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
833 OSMO_ASSERT(rdbi.e == 0);
834 OSMO_ASSERT(write_offset == 2 + 11 + 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200835 OSMO_ASSERT(count_payload == 26);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100836 OSMO_ASSERT(num_chunks == 2);
837
838 llc.reset();
839 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200840 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100841
842 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200843 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100844
845 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
846 OSMO_ASSERT(rdbi.e == 0);
847 OSMO_ASSERT(rdbi.cv != 0);
848 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200849 OSMO_ASSERT(count_payload == 5);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100850 OSMO_ASSERT(num_chunks == 3);
851
852 OSMO_ASSERT(data[0] == ((11 << 1) | (0 << 0)));
853 OSMO_ASSERT(data[1] == ((26 << 1) | (1 << 0)));
854 OSMO_ASSERT(data[2] == 0);
855
856 /* TS 44.060, B.8.2 */
857
858 /* Note that the spec confuses the byte numbering here, since it
859 * includes the FBI/E header bits into the N2 octet count which
860 * is not consistent with Section 10.3a.1 & 10.3a.2. */
861
862 cs = GprsCodingScheme::MCS2;
863
864 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530865 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100866 num_chunks = 0;
867 write_offset = 0;
868 memset(data, 0, sizeof(data));
869
870 llc.reset();
871 llc.put_frame(llc_data, 15);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200872 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100873
874 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200875 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100876
877 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
878 OSMO_ASSERT(rdbi.e == 0);
879 OSMO_ASSERT(write_offset == 1 + 15);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200880 OSMO_ASSERT(count_payload == 15);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100881 OSMO_ASSERT(num_chunks == 1);
882
883 llc.reset();
884 llc.put_frame(llc_data, 12);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200885 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100886
887 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200888 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100889
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200890 /* no LI here, becaues there are exact 12 bytes left. Put LI into next frame */
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100891 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
892 OSMO_ASSERT(rdbi.e == 0);
893 OSMO_ASSERT(rdbi.cv != 0);
894 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200895 OSMO_ASSERT(count_payload == 12);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100896 OSMO_ASSERT(num_chunks == 2);
897
898 OSMO_ASSERT(data[0] == ((15 << 1) | (1 << 0)));
899 OSMO_ASSERT(data[1] == 0);
900
901 /* Block 2 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530902 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100903 num_chunks = 0;
904 write_offset = 0;
905 memset(data, 0, sizeof(data));
906
907 OSMO_ASSERT(llc.chunk_size() == 0);
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_SPACE_LEFT);
914 OSMO_ASSERT(rdbi.e == 0);
915 OSMO_ASSERT(write_offset == 1 + 0);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200916 OSMO_ASSERT(count_payload == 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100917 OSMO_ASSERT(num_chunks == 1);
918
919 llc.reset();
920 llc.put_frame(llc_data, 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200921 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100922
923 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200924 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100925
926 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
927 OSMO_ASSERT(rdbi.e == 0);
928 OSMO_ASSERT(rdbi.cv != 0);
929 OSMO_ASSERT(write_offset == 2 + 0 + 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200930 OSMO_ASSERT(count_payload == 7);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100931 OSMO_ASSERT(num_chunks == 2);
932
933 llc.reset();
934 llc.put_frame(llc_data, 18);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200935 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100936
937 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200938 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100939
940 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
941 OSMO_ASSERT(rdbi.e == 0);
942 OSMO_ASSERT(rdbi.cv != 0);
943 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200944 OSMO_ASSERT(count_payload == 18);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100945 OSMO_ASSERT(num_chunks == 3);
946
947 OSMO_ASSERT(data[0] == ((0 << 1) | (0 << 0)));
948 OSMO_ASSERT(data[1] == ((7 << 1) | (0 << 0)));
949 OSMO_ASSERT(data[2] == ((18 << 1) | (1 << 0)));
950 OSMO_ASSERT(data[3] == 0);
951
952 /* Block 3 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530953 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100954 num_chunks = 0;
955 write_offset = 0;
956 memset(data, 0, sizeof(data));
957
958 llc.reset();
959 llc.put_frame(llc_data, 6);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200960 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100961
962 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200963 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100964
965 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
966 OSMO_ASSERT(rdbi.e == 0);
967 OSMO_ASSERT(write_offset == 1 + 6);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200968 OSMO_ASSERT(count_payload == 6);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100969 OSMO_ASSERT(num_chunks == 1);
970
971 llc.reset();
972 llc.put_frame(llc_data, 12);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200973 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100974
975 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200976 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100977
978 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
979 OSMO_ASSERT(rdbi.e == 0);
980 OSMO_ASSERT(rdbi.cv == 0);
981 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200982 OSMO_ASSERT(count_payload == 12);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100983 OSMO_ASSERT(num_chunks == 3);
984
985 OSMO_ASSERT(data[0] == ((6 << 1) | (0 << 0)));
986 OSMO_ASSERT(data[1] == ((12 << 1) | (0 << 0)));
987 OSMO_ASSERT(data[2] == ((127 << 1) | (1 << 0)));
988 OSMO_ASSERT(data[3] == 0);
989
990 /* TS 44.060, B.8.3 */
991
992 /* Note that the spec confuses the byte numbering here, too (see above) */
993
994 cs = GprsCodingScheme::MCS2;
995
996 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530997 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100998 num_chunks = 0;
999 write_offset = 0;
1000 memset(data, 0, sizeof(data));
1001
1002 llc.reset();
1003 llc.put_frame(llc_data, rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001004 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001005
1006 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001007 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001008
1009 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
1010 OSMO_ASSERT(rdbi.e == 1);
1011 OSMO_ASSERT(rdbi.cv == 0);
1012 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Neels Hofmeyrd34646a2017-02-08 17:07:40 +01001013 OSMO_ASSERT(rdbi.data_len <= INT_MAX && count_payload == (int)rdbi.data_len);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001014 OSMO_ASSERT(num_chunks == 1);
1015
1016 OSMO_ASSERT(data[0] == 0);
1017
1018 /* Final block with an LLC of size data_len-1 */
1019
1020 cs = GprsCodingScheme::MCS2;
1021
1022 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301023 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
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 - 1);
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);
Neels Hofmeyrd34646a2017-02-08 17:07:40 +01001039 OSMO_ASSERT((rdbi.data_len - 1) <= INT_MAX
1040 && count_payload == (int)(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);
Neels Hofmeyrd34646a2017-02-08 17:07:40 +01001067 OSMO_ASSERT((rdbi.data_len - 2) <= INT_MAX
1068 && count_payload == (int)(rdbi.data_len - 2));
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001069 OSMO_ASSERT(num_chunks == 2);
1070
1071 OSMO_ASSERT(data[0] == (((rdbi.data_len-2) << 1) | (0 << 0)));
1072 OSMO_ASSERT(data[1] == ((127 << 1) | (1 << 0)));
1073 OSMO_ASSERT(data[2] == 0);
1074
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001075 printf("=== end %s ===\n", __func__);
1076}
1077
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001078static void test_rlc_unaligned_copy()
1079{
1080 uint8_t bits[256];
1081 uint8_t saved_block[256];
1082 uint8_t test_block[256];
1083 uint8_t out_block[256];
1084 GprsCodingScheme::Scheme scheme;
1085 int pattern;
1086 volatile unsigned int block_idx, i;
1087
1088 for (scheme = GprsCodingScheme::CS1;
1089 scheme < GprsCodingScheme::NUM_SCHEMES;
1090 scheme = GprsCodingScheme::Scheme(scheme + 1))
1091 {
1092 GprsCodingScheme cs(scheme);
1093
1094 for (pattern = 0; pattern <= 0xff; pattern += 0xff) {
1095 /* prepare test block */
1096 test_block[0] = pattern ^ 0xff;
1097 for (i = 1; i + 1 < cs.maxDataBlockBytes(); i++)
1098 test_block[i] = i;
1099 test_block[cs.maxDataBlockBytes()-1] = pattern ^ 0xff;
1100
1101 for (block_idx = 0;
1102 block_idx < cs.numDataBlocks();
1103 block_idx++)
1104 {
1105 struct gprs_rlc_data_info rlc;
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301106 gprs_rlc_data_info_init_dl(&rlc, cs, false, 0);
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001107
1108 memset(bits, pattern, sizeof(bits));
1109 Decoding::rlc_copy_to_aligned_buffer(
1110 &rlc, block_idx, bits, saved_block);
1111
1112 fprintf(stderr,
1113 "Test data block: %s\n",
1114 osmo_hexdump(test_block, cs.maxDataBlockBytes()));
1115
1116 Encoding::rlc_copy_from_aligned_buffer(
1117 &rlc, block_idx, bits, test_block);
1118
1119 fprintf(stderr,
1120 "Encoded message block, %s, idx %d, "
1121 "pattern %02x: %s\n",
1122 rlc.cs.name(), block_idx, pattern,
1123 osmo_hexdump(bits, cs.sizeDL()));
1124
1125 Decoding::rlc_copy_to_aligned_buffer(
1126 &rlc, block_idx, bits, out_block);
1127
1128 fprintf(stderr,
1129 "Out data block: %s\n",
1130 osmo_hexdump(out_block, cs.maxDataBlockBytes()));
1131 /* restore original bits */
1132 Encoding::rlc_copy_from_aligned_buffer(
1133 &rlc, block_idx, bits, saved_block);
1134
1135 OSMO_ASSERT(memcmp(test_block, out_block,
1136 rlc.cs.maxDataBlockBytes()) == 0);
1137
1138 for (i = 0; i < sizeof(bits); i++)
1139 OSMO_ASSERT(bits[i] == pattern);
1140 }
1141 }
1142 }
1143}
1144
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001145static void test_rlc_info_init()
1146{
1147 struct gprs_rlc_data_info rlc;
1148
1149 printf("=== start %s ===\n", __func__);
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301150 gprs_rlc_data_info_init_dl(&rlc,
1151 GprsCodingScheme(GprsCodingScheme::CS1), false, 0);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001152 OSMO_ASSERT(rlc.num_data_blocks == 1);
1153 OSMO_ASSERT(rlc.data_offs_bits[0] == 24);
1154 OSMO_ASSERT(rlc.block_info[0].data_len == 20);
1155
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301156 gprs_rlc_data_info_init_dl(&rlc,
1157 GprsCodingScheme(GprsCodingScheme::MCS1), false, 0);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001158 OSMO_ASSERT(rlc.num_data_blocks == 1);
1159 OSMO_ASSERT(rlc.data_offs_bits[0] == 33);
1160 OSMO_ASSERT(rlc.block_info[0].data_len == 22);
1161
1162 printf("=== end %s ===\n", __func__);
1163}
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001164
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301165static void setup_bts(BTS *the_bts, uint8_t ts_no, uint8_t cs = 1)
1166{
1167 gprs_rlcmac_bts *bts;
1168 gprs_rlcmac_trx *trx;
1169
1170 bts = the_bts->bts_data();
1171 bts->egprs_enabled = true;
1172 bts->alloc_algorithm = alloc_algorithm_a;
1173 bts->initial_cs_dl = cs;
1174 bts->initial_cs_ul = cs;
1175 trx = &bts->trx[0];
1176 trx->pdch[ts_no].enable();
1177}
1178static void uplink_header_type_2_parsing_test(BTS *the_bts,
1179 uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
1180 uint8_t ms_class)
1181{
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301182 struct pcu_l1_meas meas;
1183 int tfi = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301184 uint8_t data[79] = {0};
1185 struct gprs_rlc_ul_header_egprs_2 *egprs2 = NULL;
1186
1187 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301188
1189 tfi = 1;
1190
1191 struct gprs_rlc_data_info rlc;
1192 GprsCodingScheme cs;
1193 int rc, offs;
1194
1195 /*without padding*/
1196 cs = GprsCodingScheme::MCS5;
1197 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
1198 egprs2->r = 1;
1199 egprs2->si = 1;
1200 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001201 egprs2->tfi_hi = tfi & 0x03;
1202 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1203 egprs2->bsn1_hi = 0;
1204 egprs2->bsn1_lo = 0;
1205 egprs2->cps_hi = 3;
1206 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301207 egprs2->rsb = 0;
1208 egprs2->pi = 0;
1209 data[4] = 0x20; /* Setting E field */
1210 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001211 OSMO_ASSERT(rc == 487);
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301212 offs = rlc.data_offs_bits[0] / 8;
1213 OSMO_ASSERT(offs == 4);
1214 OSMO_ASSERT(rlc.tfi == 1);
1215 OSMO_ASSERT(rlc.num_data_blocks == 1);
1216 OSMO_ASSERT(rlc.block_info[0].e == 1);
1217 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1218 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1219
1220 /* with padding case */
1221 cs = GprsCodingScheme::MCS6;
1222 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
1223 egprs2->r = 1;
1224 egprs2->si = 1;
1225 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001226 egprs2->tfi_hi = tfi & 0x03;
1227 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1228 egprs2->bsn1_hi = 0;
1229 egprs2->bsn1_lo = 0;
1230 egprs2->cps_hi = 3;
1231 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301232 egprs2->rsb = 0;
1233 egprs2->pi = 0;
1234 data[10] = 0x20; /* Setting E field */
1235 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001236 OSMO_ASSERT(rc == 679);
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301237 offs = rlc.data_offs_bits[0] / 8;
1238 OSMO_ASSERT(offs == 10);
1239 OSMO_ASSERT(rlc.num_data_blocks == 1);
1240 OSMO_ASSERT(rlc.tfi == 1);
1241 OSMO_ASSERT(rlc.block_info[0].e == 1);
1242 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1243 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1244
1245 egprs2->r = 1;
1246 egprs2->si = 1;
1247 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001248 egprs2->tfi_hi = tfi & 0x03;
1249 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1250 egprs2->bsn1_hi = 1;
1251 egprs2->bsn1_lo = 0;
1252 egprs2->cps_hi = 2;
1253 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301254 egprs2->rsb = 0;
1255 egprs2->pi = 0;
1256 data[10] = 0x20; /* Setting E field */
1257 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001258 OSMO_ASSERT(rc == 679);
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301259 offs = rlc.data_offs_bits[0] / 8;
1260 OSMO_ASSERT(offs == 10);
1261 OSMO_ASSERT(rlc.tfi == 1);
1262 OSMO_ASSERT(rlc.num_data_blocks == 1);
1263 OSMO_ASSERT(rlc.block_info[0].e == 1);
1264 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1265 OSMO_ASSERT(rlc.block_info[0].bsn == 1);
1266}
1267
1268static void uplink_header_type2_test(void)
1269{
1270 BTS the_bts;
1271 int ts_no = 7;
1272 uint32_t fn = 2654218;
1273 uint16_t qta = 31;
1274 uint32_t tlli = 0xf1223344;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301275 uint8_t ms_class = 1;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301276
1277 printf("=== start %s ===\n", __func__);
1278 setup_bts(&the_bts, ts_no, 10);
1279
1280 uplink_header_type_2_parsing_test(&the_bts, ts_no,
1281 tlli, &fn, qta, ms_class);
1282 printf("=== end %s ===\n", __func__);
1283}
1284
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301285static void uplink_header_type_1_parsing_test(BTS *the_bts,
1286 uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
1287 uint8_t ms_class)
1288{
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301289 int tfi = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301290 uint8_t data[155] = {0};
1291 struct gprs_rlc_ul_header_egprs_1 *egprs1 = NULL;
1292 struct gprs_rlc_data_info rlc;
1293 GprsCodingScheme cs;
Neels Hofmeyrd34646a2017-02-08 17:07:40 +01001294 int rc;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301295
1296 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301297
1298 tfi = 1;
1299
1300 /* MCS 7 */
1301 cs = GprsCodingScheme::MCS7;
1302 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1303 egprs1->si = 1;
1304 egprs1->r = 1;
1305 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001306 egprs1->tfi_hi = tfi & 0x03;
1307 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1308 egprs1->bsn1_hi = 0;
1309 egprs1->bsn1_lo = 0;
1310 egprs1->bsn2_hi = 1;
1311 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301312 egprs1->cps = 15;
1313 egprs1->rsb = 0;
1314 egprs1->pi = 0;
1315 data[5] = 0xc0;
1316 data[5 + 57] = 1;
1317 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001318 OSMO_ASSERT(rc == 946);
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301319 OSMO_ASSERT(rlc.num_data_blocks == 2);
1320 OSMO_ASSERT(rlc.block_info[0].e == 1);
1321 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1322 OSMO_ASSERT(rlc.block_info[1].e == 1);
1323 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1324 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1325 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1326 OSMO_ASSERT(rlc.tfi == 1);
1327
1328 /* MCS 8 */
1329 cs = GprsCodingScheme::MCS8;
1330 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1331 egprs1->si = 1;
1332 egprs1->r = 1;
1333 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001334 egprs1->tfi_hi = tfi & 0x03;
1335 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1336 egprs1->bsn1_hi = 0;
1337 egprs1->bsn1_lo = 0;
1338 egprs1->bsn2_hi = 1;
1339 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301340 egprs1->cps = 15;
1341 egprs1->rsb = 0;
1342 egprs1->pi = 0;
1343 data[5] = 0xc0;
1344 data[5 + 69] = 1;
1345 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001346 OSMO_ASSERT(rc == 1138);
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301347 OSMO_ASSERT(rlc.num_data_blocks == 2);
1348 OSMO_ASSERT(rlc.block_info[0].e == 1);
1349 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1350 OSMO_ASSERT(rlc.block_info[1].e == 1);
1351 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1352 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1353 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1354 OSMO_ASSERT(rlc.tfi == 1);
1355
1356 /* MCS 9 */
1357 cs = GprsCodingScheme::MCS9;
1358 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1359 egprs1->si = 1;
1360 egprs1->r = 1;
1361 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001362 egprs1->tfi_hi = tfi & 0x03;
1363 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1364 egprs1->bsn1_hi = 0;
1365 egprs1->bsn1_lo = 0;
1366 egprs1->bsn2_hi = 1;
1367 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301368 egprs1->cps = 15;
1369 egprs1->rsb = 0;
1370 egprs1->pi = 0;
1371 data[5] = 0xc0;
1372 data[5 + 75] = 1;
1373 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001374 OSMO_ASSERT(rc == 1234);
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301375 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;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301392 uint8_t ms_class = 1;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301393
1394 printf("=== start %s ===\n", __func__);
1395 setup_bts(&the_bts, ts_no, 12);
1396 uplink_header_type_1_parsing_test(&the_bts, ts_no, tlli, &fn,
1397 qta, ms_class);
1398 printf("=== end %s ===\n", __func__);
1399}
1400
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001401int main(int argc, char **argv)
1402{
1403 struct vty_app_info pcu_vty_info = {0};
1404
1405 tall_pcu_ctx = talloc_named_const(NULL, 1, "EdgeTest context");
1406 if (!tall_pcu_ctx)
1407 abort();
1408
Neels Hofmeyr78ce5912017-02-08 17:07:31 +01001409 msgb_talloc_ctx_init(tall_pcu_ctx, 0);
Neels Hofmeyr42f2d612018-04-01 16:54:40 +02001410 osmo_init_logging2(tall_pcu_ctx, &gprs_log_info);
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001411 log_set_use_color(osmo_stderr_target, 0);
1412 log_set_print_filename(osmo_stderr_target, 0);
1413
1414 vty_init(&pcu_vty_info);
Harald Welteac0490a2017-10-29 10:39:32 +01001415 pcu_vty_init(&gprs_log_info);
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001416
1417 test_coding_scheme();
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001418 test_rlc_info_init();
Jacob Erlbeck38f18692016-02-01 10:08:00 +01001419 test_rlc_unit_decoder();
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001420 test_rlc_unaligned_copy();
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001421 test_rlc_unit_encoder();
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001422
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301423 uplink_header_type2_test();
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301424 uplink_header_type1_test();
1425
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001426 if (getenv("TALLOC_REPORT_FULL"))
1427 talloc_report_full(tall_pcu_ctx, stderr);
1428 return EXIT_SUCCESS;
1429}
1430
1431/*
1432 * stubs that should not be reached
1433 */
1434extern "C" {
1435void l1if_pdch_req() { abort(); }
1436void l1if_connect_pdch() { abort(); }
1437void l1if_close_pdch() { abort(); }
1438void l1if_open_pdch() { abort(); }
1439}