blob: 9081d4ddffd50efabccc4188dbc6ba91be7dcc4a [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;
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530520 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
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 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530573 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
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 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530595 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
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 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530633 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
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 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530672 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
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 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530697 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
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 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530722 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
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 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530743 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
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 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530780 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
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 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530838 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
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 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530875 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
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 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530926 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
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 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530970 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
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 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530996 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
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 */
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 - 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;
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301077 gprs_rlc_data_info_init_dl(&rlc, cs, false, 0);
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__);
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301121 gprs_rlc_data_info_init_dl(&rlc,
1122 GprsCodingScheme(GprsCodingScheme::CS1), false, 0);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001123 OSMO_ASSERT(rlc.num_data_blocks == 1);
1124 OSMO_ASSERT(rlc.data_offs_bits[0] == 24);
1125 OSMO_ASSERT(rlc.block_info[0].data_len == 20);
1126
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301127 gprs_rlc_data_info_init_dl(&rlc,
1128 GprsCodingScheme(GprsCodingScheme::MCS1), false, 0);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001129 OSMO_ASSERT(rlc.num_data_blocks == 1);
1130 OSMO_ASSERT(rlc.data_offs_bits[0] == 33);
1131 OSMO_ASSERT(rlc.block_info[0].data_len == 22);
1132
1133 printf("=== end %s ===\n", __func__);
1134}
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001135
1136static const struct log_info_cat default_categories[] = {
1137 {"DCSN1", "\033[1;31m", "Concrete Syntax Notation One (CSN1)", LOGL_INFO, 0},
1138 {"DL1IF", "\033[1;32m", "GPRS PCU L1 interface (L1IF)", LOGL_DEBUG, 1},
1139 {"DRLCMAC", "\033[0;33m", "GPRS RLC/MAC layer (RLCMAC)", LOGL_DEBUG, 1},
1140 {"DRLCMACDATA", "\033[0;33m", "GPRS RLC/MAC layer Data (RLCMAC)", LOGL_DEBUG, 1},
1141 {"DRLCMACDL", "\033[1;33m", "GPRS RLC/MAC layer Downlink (RLCMAC)", LOGL_DEBUG, 1},
1142 {"DRLCMACUL", "\033[1;36m", "GPRS RLC/MAC layer Uplink (RLCMAC)", LOGL_DEBUG, 1},
1143 {"DRLCMACSCHED", "\033[0;36m", "GPRS RLC/MAC layer Scheduling (RLCMAC)", LOGL_DEBUG, 1},
1144 {"DRLCMACMEAS", "\033[1;31m", "GPRS RLC/MAC layer Measurements (RLCMAC)", LOGL_INFO, 1},
1145 {"DNS","\033[1;34m", "GPRS Network Service Protocol (NS)", LOGL_INFO , 1},
1146 {"DBSSGP","\033[1;34m", "GPRS BSS Gateway Protocol (BSSGP)", LOGL_INFO , 1},
1147 {"DPCU", "\033[1;35m", "GPRS Packet Control Unit (PCU)", LOGL_NOTICE, 1},
1148};
1149
1150static int filter_fn(const struct log_context *ctx,
1151 struct log_target *tar)
1152{
1153 return 1;
1154}
1155
1156const struct log_info debug_log_info = {
1157 filter_fn,
1158 (struct log_info_cat*)default_categories,
1159 ARRAY_SIZE(default_categories),
1160};
1161
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301162static void setup_bts(BTS *the_bts, uint8_t ts_no, uint8_t cs = 1)
1163{
1164 gprs_rlcmac_bts *bts;
1165 gprs_rlcmac_trx *trx;
1166
1167 bts = the_bts->bts_data();
1168 bts->egprs_enabled = true;
1169 bts->alloc_algorithm = alloc_algorithm_a;
1170 bts->initial_cs_dl = cs;
1171 bts->initial_cs_ul = cs;
1172 trx = &bts->trx[0];
1173 trx->pdch[ts_no].enable();
1174}
1175static void uplink_header_type_2_parsing_test(BTS *the_bts,
1176 uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
1177 uint8_t ms_class)
1178{
1179 GprsMs *ms;
1180 struct pcu_l1_meas meas;
1181 int tfi = 0;
1182 gprs_rlcmac_bts *bts;
1183 RlcMacUplink_t ulreq = {0};
1184 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;
1188 bts = the_bts->bts_data();
1189
1190 tfi = 1;
1191
1192 struct gprs_rlc_data_info rlc;
1193 GprsCodingScheme cs;
1194 int rc, offs;
1195
1196 /*without padding*/
1197 cs = GprsCodingScheme::MCS5;
1198 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
1199 egprs2->r = 1;
1200 egprs2->si = 1;
1201 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001202 egprs2->tfi_hi = tfi & 0x03;
1203 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1204 egprs2->bsn1_hi = 0;
1205 egprs2->bsn1_lo = 0;
1206 egprs2->cps_hi = 3;
1207 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301208 egprs2->rsb = 0;
1209 egprs2->pi = 0;
1210 data[4] = 0x20; /* Setting E field */
1211 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1212 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);
1236 offs = rlc.data_offs_bits[0] / 8;
1237 OSMO_ASSERT(offs == 10);
1238 OSMO_ASSERT(rlc.num_data_blocks == 1);
1239 OSMO_ASSERT(rlc.tfi == 1);
1240 OSMO_ASSERT(rlc.block_info[0].e == 1);
1241 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1242 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1243
1244 egprs2->r = 1;
1245 egprs2->si = 1;
1246 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001247 egprs2->tfi_hi = tfi & 0x03;
1248 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1249 egprs2->bsn1_hi = 1;
1250 egprs2->bsn1_lo = 0;
1251 egprs2->cps_hi = 2;
1252 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301253 egprs2->rsb = 0;
1254 egprs2->pi = 0;
1255 data[10] = 0x20; /* Setting E field */
1256 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1257 offs = rlc.data_offs_bits[0] / 8;
1258 OSMO_ASSERT(offs == 10);
1259 OSMO_ASSERT(rlc.tfi == 1);
1260 OSMO_ASSERT(rlc.num_data_blocks == 1);
1261 OSMO_ASSERT(rlc.block_info[0].e == 1);
1262 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1263 OSMO_ASSERT(rlc.block_info[0].bsn == 1);
1264}
1265
1266static void uplink_header_type2_test(void)
1267{
1268 BTS the_bts;
1269 int ts_no = 7;
1270 uint32_t fn = 2654218;
1271 uint16_t qta = 31;
1272 uint32_t tlli = 0xf1223344;
1273 const char *imsi = "0011223344";
1274 uint8_t ms_class = 1;
1275 gprs_rlcmac_ul_tbf *ul_tbf;
1276 GprsMs *ms;
1277
1278 printf("=== start %s ===\n", __func__);
1279 setup_bts(&the_bts, ts_no, 10);
1280
1281 uplink_header_type_2_parsing_test(&the_bts, ts_no,
1282 tlli, &fn, qta, ms_class);
1283 printf("=== end %s ===\n", __func__);
1284}
1285
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301286static void uplink_header_type_1_parsing_test(BTS *the_bts,
1287 uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
1288 uint8_t ms_class)
1289{
1290 uint8_t trx_no = 0;
1291 int tfi = 0;
1292 struct gprs_rlcmac_pdch *pdch;
1293 gprs_rlcmac_bts *bts;
1294 uint8_t data[155] = {0};
1295 struct gprs_rlc_ul_header_egprs_1 *egprs1 = NULL;
1296 struct gprs_rlc_data_info rlc;
1297 GprsCodingScheme cs;
1298 int rc, offs;
1299
1300 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1301 bts = the_bts->bts_data();
1302
1303 tfi = 1;
1304
1305 /* MCS 7 */
1306 cs = GprsCodingScheme::MCS7;
1307 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1308 egprs1->si = 1;
1309 egprs1->r = 1;
1310 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001311 egprs1->tfi_hi = tfi & 0x03;
1312 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1313 egprs1->bsn1_hi = 0;
1314 egprs1->bsn1_lo = 0;
1315 egprs1->bsn2_hi = 1;
1316 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301317 egprs1->cps = 15;
1318 egprs1->rsb = 0;
1319 egprs1->pi = 0;
1320 data[5] = 0xc0;
1321 data[5 + 57] = 1;
1322 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1323 OSMO_ASSERT(rlc.num_data_blocks == 2);
1324 OSMO_ASSERT(rlc.block_info[0].e == 1);
1325 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1326 OSMO_ASSERT(rlc.block_info[1].e == 1);
1327 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1328 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1329 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1330 OSMO_ASSERT(rlc.tfi == 1);
1331
1332 /* MCS 8 */
1333 cs = GprsCodingScheme::MCS8;
1334 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1335 egprs1->si = 1;
1336 egprs1->r = 1;
1337 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001338 egprs1->tfi_hi = tfi & 0x03;
1339 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1340 egprs1->bsn1_hi = 0;
1341 egprs1->bsn1_lo = 0;
1342 egprs1->bsn2_hi = 1;
1343 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301344 egprs1->cps = 15;
1345 egprs1->rsb = 0;
1346 egprs1->pi = 0;
1347 data[5] = 0xc0;
1348 data[5 + 69] = 1;
1349 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1350 OSMO_ASSERT(rlc.num_data_blocks == 2);
1351 OSMO_ASSERT(rlc.block_info[0].e == 1);
1352 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1353 OSMO_ASSERT(rlc.block_info[1].e == 1);
1354 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1355 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1356 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1357 OSMO_ASSERT(rlc.tfi == 1);
1358
1359 /* MCS 9 */
1360 cs = GprsCodingScheme::MCS9;
1361 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1362 egprs1->si = 1;
1363 egprs1->r = 1;
1364 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001365 egprs1->tfi_hi = tfi & 0x03;
1366 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1367 egprs1->bsn1_hi = 0;
1368 egprs1->bsn1_lo = 0;
1369 egprs1->bsn2_hi = 1;
1370 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301371 egprs1->cps = 15;
1372 egprs1->rsb = 0;
1373 egprs1->pi = 0;
1374 data[5] = 0xc0;
1375 data[5 + 75] = 1;
1376 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
1377 OSMO_ASSERT(rlc.num_data_blocks == 2);
1378 OSMO_ASSERT(rlc.block_info[0].e == 1);
1379 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1380 OSMO_ASSERT(rlc.block_info[1].e == 1);
1381 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1382 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1383 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1384 OSMO_ASSERT(rlc.tfi == 1);
1385}
1386
1387void uplink_header_type1_test(void)
1388{
1389 BTS the_bts;
1390 int ts_no = 7;
1391 uint32_t fn = 2654218;
1392 uint16_t qta = 31;
1393 uint32_t tlli = 0xf1223344;
1394 const char *imsi = "0011223344";
1395 uint8_t ms_class = 1;
1396 gprs_rlcmac_ul_tbf *ul_tbf;
1397 GprsMs *ms;
1398
1399 printf("=== start %s ===\n", __func__);
1400 setup_bts(&the_bts, ts_no, 12);
1401 uplink_header_type_1_parsing_test(&the_bts, ts_no, tlli, &fn,
1402 qta, ms_class);
1403 printf("=== end %s ===\n", __func__);
1404}
1405
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001406int main(int argc, char **argv)
1407{
1408 struct vty_app_info pcu_vty_info = {0};
1409
1410 tall_pcu_ctx = talloc_named_const(NULL, 1, "EdgeTest context");
1411 if (!tall_pcu_ctx)
1412 abort();
1413
1414 msgb_set_talloc_ctx(tall_pcu_ctx);
1415 osmo_init_logging(&debug_log_info);
1416 log_set_use_color(osmo_stderr_target, 0);
1417 log_set_print_filename(osmo_stderr_target, 0);
1418
1419 vty_init(&pcu_vty_info);
1420 pcu_vty_init(&debug_log_info);
1421
1422 test_coding_scheme();
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001423 test_rlc_info_init();
Jacob Erlbeck38f18692016-02-01 10:08:00 +01001424 test_rlc_unit_decoder();
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001425 test_rlc_unaligned_copy();
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001426 test_rlc_unit_encoder();
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001427
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301428 uplink_header_type2_test();
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301429 uplink_header_type1_test();
1430
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001431 if (getenv("TALLOC_REPORT_FULL"))
1432 talloc_report_full(tall_pcu_ctx, stderr);
1433 return EXIT_SUCCESS;
1434}
1435
1436/*
1437 * stubs that should not be reached
1438 */
1439extern "C" {
1440void l1if_pdch_req() { abort(); }
1441void l1if_connect_pdch() { abort(); }
1442void l1if_close_pdch() { abort(); }
1443void l1if_open_pdch() { abort(); }
1444}