blob: 3f424d16b705e313f7239680e14345b76f84a836 [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
Maxa4de02d2019-03-13 16:35:09 +010051static void check_coding_scheme(GprsCodingScheme& cs, enum mcs_kind mode)
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +010052{
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();
Max8a8e0fb2019-03-25 16:32:50 +010062 if (cs.spareBitsUL() > 0 && mcs_is_gprs(cs))
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();
Max8a8e0fb2019-03-25 16:32:50 +010069 if (cs.spareBitsDL() > 0 && mcs_is_gprs(cs))
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 */
Max51754b62019-03-13 17:14:13 +010074 OSMO_ASSERT(cs.maxDataBlockBytes() * num_data_blocks(cs.headerTypeData()) < cs.maxBytesDL());
75 OSMO_ASSERT(cs.maxDataBlockBytes() * num_data_blocks(cs.headerTypeData()) < cs.maxBytesUL());
Jacob Erlbeck392a5452015-12-14 10:38:29 +010076
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;
Maxbea2edb2019-03-06 17:04:59 +0100124 CodingScheme gprs_schemes[] = {
125 CS1,
126 CS2,
127 CS3,
128 CS4
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100129 };
130 struct {
Maxbea2edb2019-03-06 17:04:59 +0100131 CodingScheme s;
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100132 bool is_gmsk;
133 } egprs_schemes[] = {
Maxbea2edb2019-03-06 17:04:59 +0100134 { MCS1, true},
135 { MCS2, true},
136 { MCS3, true},
137 { MCS4, true},
138 { MCS5, false},
139 { MCS6, false},
140 { MCS7, false},
141 { MCS8, false},
142 { MCS9, false},
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100143 };
144
145 printf("=== start %s ===\n", __func__);
146
147 GprsCodingScheme cs;
148 OSMO_ASSERT(!cs);
Maxbea2edb2019-03-06 17:04:59 +0100149 OSMO_ASSERT(CodingScheme(cs) == UNKNOWN);
150 OSMO_ASSERT(cs == GprsCodingScheme(UNKNOWN));
Maxa4de02d2019-03-13 16:35:09 +0100151 OSMO_ASSERT(!cs.isCompatible(GPRS));
152 OSMO_ASSERT(!cs.isCompatible(EGPRS_GMSK));
153 OSMO_ASSERT(!cs.isCompatible(EGPRS));
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100154
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]);
Max8a8e0fb2019-03-25 16:32:50 +0100160 OSMO_ASSERT(mcs_is_gprs(current_cs));
161 OSMO_ASSERT(!mcs_is_edge(current_cs));
162 OSMO_ASSERT(!mcs_is_edge_gmsk(current_cs));
Maxbea2edb2019-03-06 17:04:59 +0100163 OSMO_ASSERT(CodingScheme(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 */
Max51754b62019-03-13 17:14:13 +0100171 OSMO_ASSERT(current_cs.headerTypeData() == HEADER_GPRS_DATA);
Jacob Erlbeck6c3dc612015-12-14 10:21:26 +0100172
Maxa4de02d2019-03-13 16:35:09 +0100173 check_coding_scheme(current_cs, GPRS);
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100174 }
175 OSMO_ASSERT(i == 4);
176
177 last_size_UL = 0;
178 last_size_DL = 0;
179
180 for (i = 0; i < ARRAY_SIZE(egprs_schemes); i++) {
181 GprsCodingScheme current_cs(egprs_schemes[i].s);
Max8a8e0fb2019-03-25 16:32:50 +0100182 OSMO_ASSERT(!mcs_is_gprs(current_cs));
183 OSMO_ASSERT(mcs_is_edge(current_cs));
184 OSMO_ASSERT(mcs_is_edge_gmsk(current_cs) == !!egprs_schemes[i].is_gmsk);
Maxbea2edb2019-03-06 17:04:59 +0100185 OSMO_ASSERT(CodingScheme(current_cs) == egprs_schemes[i].s);
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100186 OSMO_ASSERT(current_cs == GprsCodingScheme(egprs_schemes[i].s));
187
Max360e0212019-02-26 17:20:41 +0100188 OSMO_ASSERT(check_strong_monotonicity(&current_cs, last_size_UL, last_size_DL));
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100189 last_size_UL = current_cs.maxBytesUL();
190 last_size_DL = current_cs.maxBytesDL();
191
192 if (egprs_schemes[i].is_gmsk)
Maxa4de02d2019-03-13 16:35:09 +0100193 check_coding_scheme(current_cs, EGPRS_GMSK);
194 check_coding_scheme(current_cs, EGPRS);
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +0100195 }
196 OSMO_ASSERT(i == 9);
197
198 printf("=== end %s ===\n", __func__);
199}
200
Jacob Erlbeck38f18692016-02-01 10:08:00 +0100201static void test_rlc_unit_decoder()
Jacob Erlbeck61679252015-12-11 18:25:21 +0100202{
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100203 struct gprs_rlc_data_block_info rdbi = {0};
Jacob Erlbeck61679252015-12-11 18:25:21 +0100204 GprsCodingScheme cs;
205 uint8_t data[74];
206 Decoding::RlcData chunks[16];
207 volatile int num_chunks = 0;
208 uint32_t tlli, tlli2;
209 unsigned int offs;
210
211
212 printf("=== start %s ===\n", __func__);
213
214 /* TS 44.060, B.1 */
Maxbea2edb2019-03-06 17:04:59 +0100215 cs = CS4;
Jacob Erlbeck61679252015-12-11 18:25:21 +0100216 rdbi.data_len = cs.maxDataBlockBytes();
217 rdbi.e = 0;
218 rdbi.ti = 0;
219 rdbi.cv = 15;
220 tlli = 0;
221 offs = 0;
222 data[offs++] = (11 << 2) | (1 << 1) | (0 << 0);
223 data[offs++] = (26 << 2) | (1 << 1) | (1 << 0);
224 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
225 chunks, ARRAY_SIZE(chunks), &tlli);
226 OSMO_ASSERT(num_chunks == 3);
227 OSMO_ASSERT(tlli == 0);
228 OSMO_ASSERT(chunks[0].offset == 2);
229 OSMO_ASSERT(chunks[0].length == 11);
230 OSMO_ASSERT(chunks[0].is_complete);
231 OSMO_ASSERT(chunks[1].offset == 13);
232 OSMO_ASSERT(chunks[1].length == 26);
233 OSMO_ASSERT(chunks[1].is_complete);
234 OSMO_ASSERT(chunks[2].offset == 39);
235 OSMO_ASSERT(chunks[2].length == cs.maxDataBlockBytes() - 39);
236 OSMO_ASSERT(!chunks[2].is_complete);
237
238 /* TS 44.060, B.2 */
Maxbea2edb2019-03-06 17:04:59 +0100239 cs = CS1;
Jacob Erlbeck61679252015-12-11 18:25:21 +0100240 rdbi.data_len = cs.maxDataBlockBytes();
241 rdbi.e = 0;
242 rdbi.ti = 0;
243 rdbi.cv = 15;
244 tlli = 0;
245 offs = 0;
246 data[offs++] = (0 << 2) | (0 << 1) | (1 << 0);
247 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
248 chunks, ARRAY_SIZE(chunks), &tlli);
249 OSMO_ASSERT(num_chunks == 1);
250 OSMO_ASSERT(tlli == 0);
251 OSMO_ASSERT(chunks[0].offset == 1);
252 OSMO_ASSERT(chunks[0].length == 19);
253 OSMO_ASSERT(!chunks[0].is_complete);
254
255 rdbi.e = 0;
256 rdbi.ti = 0;
257 rdbi.cv = 15;
258 tlli = 0;
259 offs = 0;
260 data[offs++] = (1 << 2) | (1 << 1) | (1 << 0);
261 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
262 chunks, ARRAY_SIZE(chunks), &tlli);
263 OSMO_ASSERT(num_chunks == 2);
264 OSMO_ASSERT(tlli == 0);
265 OSMO_ASSERT(chunks[0].offset == 1);
266 OSMO_ASSERT(chunks[0].length == 1);
267 OSMO_ASSERT(chunks[0].is_complete);
268 OSMO_ASSERT(chunks[1].offset == 2);
269 OSMO_ASSERT(chunks[1].length == 18);
270 OSMO_ASSERT(!chunks[1].is_complete);
271
272 /* TS 44.060, B.3 */
Maxbea2edb2019-03-06 17:04:59 +0100273 cs = CS1;
Jacob Erlbeck61679252015-12-11 18:25:21 +0100274 rdbi.data_len = cs.maxDataBlockBytes();
275 rdbi.e = 0;
276 rdbi.ti = 0;
277 rdbi.cv = 15;
278 tlli = 0;
279 offs = 0;
280 data[offs++] = (7 << 2) | (1 << 1) | (0 << 0);
281 data[offs++] = (11 << 2) | (0 << 1) | (1 << 0);
282 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
283 chunks, ARRAY_SIZE(chunks), &tlli);
284 OSMO_ASSERT(num_chunks == 2);
285 OSMO_ASSERT(tlli == 0);
286 OSMO_ASSERT(chunks[0].offset == 2);
287 OSMO_ASSERT(chunks[0].length == 7);
288 OSMO_ASSERT(chunks[0].is_complete);
289 OSMO_ASSERT(chunks[1].offset == 9);
290 OSMO_ASSERT(chunks[1].length == 11);
291 OSMO_ASSERT(chunks[1].is_complete);
292
293 /* TS 44.060, B.4 */
Maxbea2edb2019-03-06 17:04:59 +0100294 cs = CS1;
Jacob Erlbeck61679252015-12-11 18:25:21 +0100295 rdbi.data_len = cs.maxDataBlockBytes();
296 rdbi.e = 1;
297 rdbi.ti = 0;
298 rdbi.cv = 15;
299 tlli = 0;
300 offs = 0;
301 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
302 chunks, ARRAY_SIZE(chunks), &tlli);
303 OSMO_ASSERT(num_chunks == 1);
304 OSMO_ASSERT(tlli == 0);
305 OSMO_ASSERT(chunks[0].offset == 0);
306 OSMO_ASSERT(chunks[0].length == 20);
307 OSMO_ASSERT(!chunks[0].is_complete);
308
309 /* TS 44.060, B.6 */
Maxbea2edb2019-03-06 17:04:59 +0100310 cs = CS1;
Jacob Erlbeck61679252015-12-11 18:25:21 +0100311 rdbi.data_len = cs.maxDataBlockBytes();
312 rdbi.e = 1;
313 rdbi.ti = 0;
314 rdbi.cv = 0;
315 tlli = 0;
316 offs = 0;
317 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
318 chunks, ARRAY_SIZE(chunks), &tlli);
319 OSMO_ASSERT(num_chunks == 1);
320 OSMO_ASSERT(tlli == 0);
321 OSMO_ASSERT(chunks[0].offset == 0);
322 OSMO_ASSERT(chunks[0].length == 20);
323 OSMO_ASSERT(chunks[0].is_complete);
324
325 /* TS 44.060, B.8.1 */
Maxbea2edb2019-03-06 17:04:59 +0100326 cs = MCS4;
Jacob Erlbeck61679252015-12-11 18:25:21 +0100327 rdbi.data_len = cs.maxDataBlockBytes();
328 rdbi.e = 0;
329 rdbi.ti = 0;
330 rdbi.cv = 15;
331 tlli = 0;
332 offs = 0;
333 data[offs++] = (11 << 1) | (0 << 0);
334 data[offs++] = (26 << 1) | (1 << 0);
335 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
336 chunks, ARRAY_SIZE(chunks), &tlli);
337 OSMO_ASSERT(num_chunks == 3);
338 OSMO_ASSERT(tlli == 0);
339 OSMO_ASSERT(chunks[0].offset == 2);
340 OSMO_ASSERT(chunks[0].length == 11);
341 OSMO_ASSERT(chunks[0].is_complete);
342 OSMO_ASSERT(chunks[1].offset == 13);
343 OSMO_ASSERT(chunks[1].length == 26);
344 OSMO_ASSERT(chunks[1].is_complete);
345 OSMO_ASSERT(chunks[2].offset == 39);
346 OSMO_ASSERT(chunks[2].length == 5);
347 OSMO_ASSERT(!chunks[2].is_complete);
348
349 /* TS 44.060, B.8.2 */
350
351 /* Note that the spec confuses the byte numbering here, since it
352 * includes the FBI/E header bits into the N2 octet count which
353 * is not consistent with Section 10.3a.1 & 10.3a.2. */
354
Maxbea2edb2019-03-06 17:04:59 +0100355 cs = MCS2;
Jacob Erlbeck61679252015-12-11 18:25:21 +0100356 rdbi.data_len = cs.maxDataBlockBytes();
357 rdbi.e = 0;
358 rdbi.ti = 0;
359 rdbi.cv = 15;
360 tlli = 0;
361 offs = 0;
362 data[offs++] = (15 << 1) | (1 << 0);
363 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
364 chunks, ARRAY_SIZE(chunks), &tlli);
365 OSMO_ASSERT(num_chunks == 2);
366 OSMO_ASSERT(tlli == 0);
367 OSMO_ASSERT(chunks[0].offset == 1);
368 OSMO_ASSERT(chunks[0].length == 15);
369 OSMO_ASSERT(chunks[0].is_complete);
370 OSMO_ASSERT(chunks[1].offset == 16);
371 OSMO_ASSERT(chunks[1].length == 12);
372 OSMO_ASSERT(!chunks[1].is_complete);
373
374 rdbi.e = 0;
375 rdbi.ti = 0;
376 rdbi.cv = 15;
377 tlli = 0;
378 offs = 0;
379 data[offs++] = ( 0 << 1) | (0 << 0);
380 data[offs++] = ( 7 << 1) | (0 << 0);
381 data[offs++] = (18 << 1) | (1 << 0); /* Differs from spec's N2-11 = 17 */
382 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
383 chunks, ARRAY_SIZE(chunks), &tlli);
384 OSMO_ASSERT(num_chunks == 3);
385 OSMO_ASSERT(tlli == 0);
386 OSMO_ASSERT(chunks[0].offset == 3);
387 OSMO_ASSERT(chunks[0].length == 0);
388 OSMO_ASSERT(chunks[0].is_complete);
389 OSMO_ASSERT(chunks[1].offset == 3);
390 OSMO_ASSERT(chunks[1].length == 7);
391 OSMO_ASSERT(chunks[1].is_complete);
392 OSMO_ASSERT(chunks[2].offset == 10);
393 OSMO_ASSERT(chunks[2].length == 18);
394 OSMO_ASSERT(chunks[2].is_complete);
395
396 rdbi.e = 0;
397 rdbi.ti = 0;
398 rdbi.cv = 0;
399 tlli = 0;
400 offs = 0;
401 data[offs++] = ( 6 << 1) | (0 << 0);
402 data[offs++] = (12 << 1) | (0 << 0);
403 data[offs++] = (127 << 1) | (1 << 0);
404 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
405 chunks, ARRAY_SIZE(chunks), &tlli);
406 OSMO_ASSERT(num_chunks == 2);
407 OSMO_ASSERT(tlli == 0);
408 OSMO_ASSERT(chunks[0].offset == 3);
409 OSMO_ASSERT(chunks[0].length == 6);
410 OSMO_ASSERT(chunks[0].is_complete);
411 OSMO_ASSERT(chunks[1].offset == 9);
412 OSMO_ASSERT(chunks[1].length == 12);
413 OSMO_ASSERT(chunks[1].is_complete);
414
415 /* TS 44.060, B.8.3 */
416
417 /* Note that the spec confuses the byte numbering here, too (see above) */
418
Maxbea2edb2019-03-06 17:04:59 +0100419 cs = MCS2;
Jacob Erlbeck61679252015-12-11 18:25:21 +0100420 rdbi.data_len = cs.maxDataBlockBytes();
421 rdbi.e = 1;
422 rdbi.ti = 0;
423 rdbi.cv = 0;
424 tlli = 0;
425 offs = 0;
426 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
427 chunks, ARRAY_SIZE(chunks), &tlli);
428 OSMO_ASSERT(num_chunks == 1);
429 OSMO_ASSERT(tlli == 0);
430 OSMO_ASSERT(chunks[0].offset == 0);
431 OSMO_ASSERT(chunks[0].length == 28);
432 OSMO_ASSERT(chunks[0].is_complete);
433
434 /* CS-1, TLLI, last block, single chunk until the end of the block */
Maxbea2edb2019-03-06 17:04:59 +0100435 cs = CS1;
Jacob Erlbeck61679252015-12-11 18:25:21 +0100436 rdbi.data_len = cs.maxDataBlockBytes();
437 rdbi.e = 1;
438 rdbi.ti = 1;
439 rdbi.cv = 0;
440 tlli = 0;
441 tlli2 = 0xffeeddcc;
442 offs = 0;
443 data[offs++] = tlli2 >> 24;
444 data[offs++] = tlli2 >> 16;
445 data[offs++] = tlli2 >> 8;
446 data[offs++] = tlli2 >> 0;
447 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
448 chunks, ARRAY_SIZE(chunks), &tlli);
449 OSMO_ASSERT(num_chunks == 1);
450 OSMO_ASSERT(tlli == tlli2);
451 OSMO_ASSERT(chunks[0].offset == 4);
452 OSMO_ASSERT(chunks[0].length == 16);
453 OSMO_ASSERT(chunks[0].is_complete);
454
455 /* Like TS 44.060, B.2, first RLC block but with TLLI */
Maxbea2edb2019-03-06 17:04:59 +0100456 cs = CS1;
Jacob Erlbeck61679252015-12-11 18:25:21 +0100457 rdbi.data_len = cs.maxDataBlockBytes();
458 rdbi.e = 0;
459 rdbi.ti = 1;
460 rdbi.cv = 15;
461 tlli = 0;
462 tlli2 = 0xffeeddbb;
463 offs = 0;
464 data[offs++] = (0 << 2) | (0 << 1) | (1 << 0);
465 data[offs++] = tlli2 >> 24;
466 data[offs++] = tlli2 >> 16;
467 data[offs++] = tlli2 >> 8;
468 data[offs++] = tlli2 >> 0;
469 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
470 chunks, ARRAY_SIZE(chunks), &tlli);
471 OSMO_ASSERT(num_chunks == 1);
472 OSMO_ASSERT(tlli == tlli2);
473 OSMO_ASSERT(chunks[0].offset == 5);
474 OSMO_ASSERT(chunks[0].length == 15);
475 OSMO_ASSERT(!chunks[0].is_complete);
476
477 /* Like TS 44.060, B.8.1 but with TLLI */
Maxbea2edb2019-03-06 17:04:59 +0100478 cs = MCS4;
Jacob Erlbeck61679252015-12-11 18:25:21 +0100479 rdbi.data_len = cs.maxDataBlockBytes();
480 rdbi.e = 0;
481 rdbi.ti = 1;
482 rdbi.cv = 15;
483 tlli = 0;
484 tlli2 = 0xffeeddaa;
485 offs = 0;
486 data[offs++] = (11 << 1) | (0 << 0);
487 data[offs++] = (26 << 1) | (1 << 0);
488 /* Little endian */
489 data[offs++] = tlli2 >> 0;
490 data[offs++] = tlli2 >> 8;
491 data[offs++] = tlli2 >> 16;
492 data[offs++] = tlli2 >> 24;
493 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
494 chunks, ARRAY_SIZE(chunks), &tlli);
495 OSMO_ASSERT(num_chunks == 3);
496 OSMO_ASSERT(tlli == tlli2);
497 OSMO_ASSERT(chunks[0].offset == 6);
498 OSMO_ASSERT(chunks[0].length == 11);
499 OSMO_ASSERT(chunks[0].is_complete);
500 OSMO_ASSERT(chunks[1].offset == 17);
501 OSMO_ASSERT(chunks[1].length == 26);
502 OSMO_ASSERT(chunks[1].is_complete);
503 OSMO_ASSERT(chunks[2].offset == 43);
504 OSMO_ASSERT(chunks[2].length == 1);
505 OSMO_ASSERT(!chunks[2].is_complete);
506
Aravind Sirsikar3463bd42016-09-15 17:19:54 +0530507 rdbi.e = 0;
508 rdbi.ti = 0;
509 rdbi.cv = 1;
510 tlli = 0;
511 offs = 0;
512 data[offs++] = 1;
513 num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
514 chunks, ARRAY_SIZE(chunks), &tlli);
515
Aravind Sirsikar22a90192016-09-15 17:24:49 +0530516 OSMO_ASSERT(num_chunks == 2);
Aravind Sirsikar3463bd42016-09-15 17:19:54 +0530517 OSMO_ASSERT(chunks[0].offset == 1);
Aravind Sirsikar22a90192016-09-15 17:24:49 +0530518 OSMO_ASSERT(chunks[0].length == 0);
519 OSMO_ASSERT(chunks[0].is_complete);
520
521 OSMO_ASSERT(chunks[1].offset == 1);
522 OSMO_ASSERT(chunks[1].length == 43);
523 OSMO_ASSERT(!chunks[1].is_complete);
Aravind Sirsikar3463bd42016-09-15 17:19:54 +0530524
Jacob Erlbeck61679252015-12-11 18:25:21 +0100525 printf("=== end %s ===\n", __func__);
526}
527
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100528static void test_rlc_unit_encoder()
529{
530 struct gprs_rlc_data_block_info rdbi = {0};
531 GprsCodingScheme cs;
532 uint8_t data[74];
533 uint8_t llc_data[1500] = {0,};
534 int num_chunks = 0;
535 int write_offset;
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200536 int count_payload;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100537 struct gprs_llc llc;
538 Encoding::AppendResult ar;
539
540 printf("=== start %s ===\n", __func__);
541
542 llc.init();
543
544 /* TS 44.060, B.1 */
Maxbea2edb2019-03-06 17:04:59 +0100545 cs = CS4;
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530546 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100547 num_chunks = 0;
548 write_offset = 0;
549 memset(data, 0, sizeof(data));
550
551 llc.reset();
552 llc.put_frame(llc_data, 11);
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_COMPLETED_SPACE_LEFT);
559 OSMO_ASSERT(rdbi.e == 0);
560 OSMO_ASSERT(write_offset == 1 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200561 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100562 OSMO_ASSERT(num_chunks == 1);
563
564 llc.reset();
565 llc.put_frame(llc_data, 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200566 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100567
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100568 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200569 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100570
571 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
572 OSMO_ASSERT(rdbi.e == 0);
573 OSMO_ASSERT(write_offset == 2 + 11 + 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200574 OSMO_ASSERT(count_payload == 26);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100575 OSMO_ASSERT(num_chunks == 2);
576
577 llc.reset();
578 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200579 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100580
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100581 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200582 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100583
584 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
585 OSMO_ASSERT(rdbi.e == 0);
586 OSMO_ASSERT(rdbi.cv != 0);
587 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200588 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100589 OSMO_ASSERT(num_chunks == 3);
590
591 OSMO_ASSERT(data[0] == ((11 << 2) | (1 << 1) | (0 << 0)));
592 OSMO_ASSERT(data[1] == ((26 << 2) | (1 << 1) | (1 << 0)));
593 OSMO_ASSERT(data[2] == 0);
594
595 /* TS 44.060, B.2 */
Maxbea2edb2019-03-06 17:04:59 +0100596 cs = CS1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100597
598 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530599 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100600 num_chunks = 0;
601 write_offset = 0;
602 memset(data, 0, sizeof(data));
603
604 llc.reset();
605 llc.put_frame(llc_data, 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200606 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100607
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100608 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200609 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100610
611 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
612 OSMO_ASSERT(rdbi.e == 0);
613 OSMO_ASSERT(write_offset == 1 + 19);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200614 OSMO_ASSERT(count_payload == 19);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100615 OSMO_ASSERT(num_chunks == 1);
616
617 OSMO_ASSERT(data[0] == ((0 << 2) | (0 << 1) | (1 << 0)));
618 OSMO_ASSERT(data[1] == 0);
619
620 /* Block 2 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530621 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100622 num_chunks = 0;
623 write_offset = 0;
624 memset(data, 0, sizeof(data));
625
626 OSMO_ASSERT(llc.chunk_size() == 1);
627
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200628 count_payload = -1;
629
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100630 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200631 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100632
633 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
634 OSMO_ASSERT(rdbi.e == 0);
635 OSMO_ASSERT(write_offset == 1 + 1);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200636 OSMO_ASSERT(count_payload == 1);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100637 OSMO_ASSERT(num_chunks == 1);
638
639 llc.reset();
640 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200641 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100642
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100643 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200644 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100645
646 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
647 OSMO_ASSERT(rdbi.e == 0);
648 OSMO_ASSERT(write_offset == 1 + 1 + 18);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200649 OSMO_ASSERT(count_payload == 18);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100650 OSMO_ASSERT(num_chunks == 2);
651
652 OSMO_ASSERT(data[0] == ((1 << 2) | (1 << 1) | (1 << 0)));
653 OSMO_ASSERT(data[1] == 0);
654
655 /* TS 44.060, B.3 */
Maxbea2edb2019-03-06 17:04:59 +0100656 cs = CS1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100657
658 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530659 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100660 num_chunks = 0;
661 write_offset = 0;
662 memset(data, 0, sizeof(data));
663
664 llc.reset();
665 llc.put_frame(llc_data, 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200666 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100667
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100668 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200669 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100670
671 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
672 OSMO_ASSERT(rdbi.e == 0);
673 OSMO_ASSERT(write_offset == 1 + 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200674 OSMO_ASSERT(count_payload == 7);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100675 OSMO_ASSERT(num_chunks == 1);
676
677 llc.reset();
678 llc.put_frame(llc_data, 11);
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_COMPLETED_BLOCK_FILLED);
685 OSMO_ASSERT(rdbi.e == 0);
686 OSMO_ASSERT(write_offset == 2 + 7 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200687 OSMO_ASSERT(count_payload == 11);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100688 OSMO_ASSERT(num_chunks == 2);
689
690 OSMO_ASSERT(data[0] == ((7 << 2) | (1 << 1) | (0 << 0)));
691 OSMO_ASSERT(data[1] == ((11 << 2) | (0 << 1) | (1 << 0)));
692 OSMO_ASSERT(data[2] == 0);
693
694 /* TS 44.060, B.4 */
Maxbea2edb2019-03-06 17:04:59 +0100695 cs = CS1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100696
697 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530698 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100699 num_chunks = 0;
700 write_offset = 0;
701 memset(data, 0, sizeof(data));
702
703 llc.reset();
704 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200705 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100706
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100707 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200708 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100709
710 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
711 OSMO_ASSERT(rdbi.e == 1);
712 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200713 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100714 OSMO_ASSERT(num_chunks == 1);
715 OSMO_ASSERT(rdbi.cv != 0);
716
717 OSMO_ASSERT(data[0] == 0);
718
719 /* TS 44.060, B.5 */
Maxbea2edb2019-03-06 17:04:59 +0100720 cs = CS1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100721
722 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530723 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100724 num_chunks = 0;
725 write_offset = 0;
726 memset(data, 0, sizeof(data));
727
728 llc.reset();
729 llc.put_frame(llc_data, 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200730 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100731
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100732 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200733 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100734
735 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
736 OSMO_ASSERT(rdbi.e == 1);
737 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200738 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100739 OSMO_ASSERT(num_chunks == 1);
740 OSMO_ASSERT(rdbi.cv == 0);
741
742 OSMO_ASSERT(data[0] == 0);
743
744 /* TS 44.060, B.7 */
Maxbea2edb2019-03-06 17:04:59 +0100745 cs = CS1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100746
747 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530748 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100749 num_chunks = 0;
750 write_offset = 0;
751 memset(data, 0, sizeof(data));
752
753 llc.reset();
754 llc.put_frame(llc_data, 30);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200755 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100756
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100757 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200758 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100759
760 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
761 OSMO_ASSERT(rdbi.e == 1);
762 OSMO_ASSERT(write_offset == 20);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200763 OSMO_ASSERT(count_payload == 20);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100764 OSMO_ASSERT(num_chunks == 1);
765
766 OSMO_ASSERT(data[0] == 0);
767
768 /* Block 2 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530769 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100770 num_chunks = 0;
771 write_offset = 0;
772 memset(data, 0, sizeof(data));
773
774 OSMO_ASSERT(llc.chunk_size() == 10);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200775 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100776
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100777 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200778 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100779
780 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
781 OSMO_ASSERT(rdbi.e == 0);
782 OSMO_ASSERT(write_offset == 1 + 10);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200783 OSMO_ASSERT(count_payload == 10);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100784 OSMO_ASSERT(num_chunks == 1);
785
786 llc.reset();
787 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200788 count_payload = -1;
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100789
Jacob Erlbeck5058bd62016-01-13 10:51:25 +0100790 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200791 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100792
793 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
794 OSMO_ASSERT(rdbi.e == 0);
795 OSMO_ASSERT(write_offset == 1 + 10 + 9);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200796 OSMO_ASSERT(count_payload == 9);
Jacob Erlbeck14bb0942016-01-12 11:58:13 +0100797 OSMO_ASSERT(num_chunks == 2);
798
799 OSMO_ASSERT(data[0] == ((10 << 2) | (1 << 1) | (1 << 0)));
800 OSMO_ASSERT(data[1] == 0);
801
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100802 /* TS 44.060, B.8.1 */
Maxbea2edb2019-03-06 17:04:59 +0100803 cs = MCS4;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100804
805 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530806 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100807 num_chunks = 0;
808 write_offset = 0;
809 memset(data, 0, sizeof(data));
810
811 llc.reset();
812 llc.put_frame(llc_data, 11);
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_COMPLETED_SPACE_LEFT);
819 OSMO_ASSERT(rdbi.e == 0);
820 OSMO_ASSERT(write_offset == 1 + 11);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200821 OSMO_ASSERT(count_payload == 11);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100822 OSMO_ASSERT(num_chunks == 1);
823
824 llc.reset();
825 llc.put_frame(llc_data, 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200826 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100827
828 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200829 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100830
831 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
832 OSMO_ASSERT(rdbi.e == 0);
833 OSMO_ASSERT(write_offset == 2 + 11 + 26);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200834 OSMO_ASSERT(count_payload == 26);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100835 OSMO_ASSERT(num_chunks == 2);
836
837 llc.reset();
838 llc.put_frame(llc_data, 99);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200839 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100840
841 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200842 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100843
844 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
845 OSMO_ASSERT(rdbi.e == 0);
846 OSMO_ASSERT(rdbi.cv != 0);
847 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200848 OSMO_ASSERT(count_payload == 5);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100849 OSMO_ASSERT(num_chunks == 3);
850
851 OSMO_ASSERT(data[0] == ((11 << 1) | (0 << 0)));
852 OSMO_ASSERT(data[1] == ((26 << 1) | (1 << 0)));
853 OSMO_ASSERT(data[2] == 0);
854
855 /* TS 44.060, B.8.2 */
856
857 /* Note that the spec confuses the byte numbering here, since it
858 * includes the FBI/E header bits into the N2 octet count which
859 * is not consistent with Section 10.3a.1 & 10.3a.2. */
860
Maxbea2edb2019-03-06 17:04:59 +0100861 cs = MCS2;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100862
863 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530864 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100865 num_chunks = 0;
866 write_offset = 0;
867 memset(data, 0, sizeof(data));
868
869 llc.reset();
870 llc.put_frame(llc_data, 15);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200871 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100872
873 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200874 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100875
876 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
877 OSMO_ASSERT(rdbi.e == 0);
878 OSMO_ASSERT(write_offset == 1 + 15);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200879 OSMO_ASSERT(count_payload == 15);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100880 OSMO_ASSERT(num_chunks == 1);
881
882 llc.reset();
883 llc.put_frame(llc_data, 12);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200884 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100885
886 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200887 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100888
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200889 /* no LI here, becaues there are exact 12 bytes left. Put LI into next frame */
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100890 OSMO_ASSERT(ar == Encoding::AR_NEED_MORE_BLOCKS);
891 OSMO_ASSERT(rdbi.e == 0);
892 OSMO_ASSERT(rdbi.cv != 0);
893 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200894 OSMO_ASSERT(count_payload == 12);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100895 OSMO_ASSERT(num_chunks == 2);
896
897 OSMO_ASSERT(data[0] == ((15 << 1) | (1 << 0)));
898 OSMO_ASSERT(data[1] == 0);
899
900 /* Block 2 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530901 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100902 num_chunks = 0;
903 write_offset = 0;
904 memset(data, 0, sizeof(data));
905
906 OSMO_ASSERT(llc.chunk_size() == 0);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200907 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100908
909 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200910 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100911
912 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
913 OSMO_ASSERT(rdbi.e == 0);
914 OSMO_ASSERT(write_offset == 1 + 0);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200915 OSMO_ASSERT(count_payload == 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100916 OSMO_ASSERT(num_chunks == 1);
917
918 llc.reset();
919 llc.put_frame(llc_data, 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200920 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100921
922 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200923 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100924
925 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
926 OSMO_ASSERT(rdbi.e == 0);
927 OSMO_ASSERT(rdbi.cv != 0);
928 OSMO_ASSERT(write_offset == 2 + 0 + 7);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200929 OSMO_ASSERT(count_payload == 7);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100930 OSMO_ASSERT(num_chunks == 2);
931
932 llc.reset();
933 llc.put_frame(llc_data, 18);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200934 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100935
936 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200937 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100938
939 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
940 OSMO_ASSERT(rdbi.e == 0);
941 OSMO_ASSERT(rdbi.cv != 0);
942 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200943 OSMO_ASSERT(count_payload == 18);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100944 OSMO_ASSERT(num_chunks == 3);
945
946 OSMO_ASSERT(data[0] == ((0 << 1) | (0 << 0)));
947 OSMO_ASSERT(data[1] == ((7 << 1) | (0 << 0)));
948 OSMO_ASSERT(data[2] == ((18 << 1) | (1 << 0)));
949 OSMO_ASSERT(data[3] == 0);
950
951 /* Block 3 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530952 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100953 num_chunks = 0;
954 write_offset = 0;
955 memset(data, 0, sizeof(data));
956
957 llc.reset();
958 llc.put_frame(llc_data, 6);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200959 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100960
961 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200962 &llc, &write_offset, &num_chunks, data, false, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100963
964 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_SPACE_LEFT);
965 OSMO_ASSERT(rdbi.e == 0);
966 OSMO_ASSERT(write_offset == 1 + 6);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200967 OSMO_ASSERT(count_payload == 6);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100968 OSMO_ASSERT(num_chunks == 1);
969
970 llc.reset();
971 llc.put_frame(llc_data, 12);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200972 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100973
974 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200975 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100976
977 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
978 OSMO_ASSERT(rdbi.e == 0);
979 OSMO_ASSERT(rdbi.cv == 0);
980 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Alexander Couzens6f0dc962016-05-30 19:30:21 +0200981 OSMO_ASSERT(count_payload == 12);
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100982 OSMO_ASSERT(num_chunks == 3);
983
984 OSMO_ASSERT(data[0] == ((6 << 1) | (0 << 0)));
985 OSMO_ASSERT(data[1] == ((12 << 1) | (0 << 0)));
986 OSMO_ASSERT(data[2] == ((127 << 1) | (1 << 0)));
987 OSMO_ASSERT(data[3] == 0);
988
989 /* TS 44.060, B.8.3 */
990
991 /* Note that the spec confuses the byte numbering here, too (see above) */
992
Maxbea2edb2019-03-06 17:04:59 +0100993 cs = MCS2;
Jacob Erlbecka88d0652016-01-13 11:28:10 +0100994
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);
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 == 1);
1010 OSMO_ASSERT(rdbi.cv == 0);
1011 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Neels Hofmeyrd34646a2017-02-08 17:07:40 +01001012 OSMO_ASSERT(rdbi.data_len <= INT_MAX && count_payload == (int)rdbi.data_len);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001013 OSMO_ASSERT(num_chunks == 1);
1014
1015 OSMO_ASSERT(data[0] == 0);
1016
1017 /* Final block with an LLC of size data_len-1 */
1018
Maxbea2edb2019-03-06 17:04:59 +01001019 cs = MCS2;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001020
1021 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301022 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001023 num_chunks = 0;
1024 write_offset = 0;
1025 memset(data, 0, sizeof(data));
1026
1027 llc.reset();
1028 llc.put_frame(llc_data, rdbi.data_len - 1);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001029 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001030
1031 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001032 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001033
1034 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
1035 OSMO_ASSERT(rdbi.e == 0);
1036 OSMO_ASSERT(rdbi.cv == 0);
1037 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Neels Hofmeyrd34646a2017-02-08 17:07:40 +01001038 OSMO_ASSERT((rdbi.data_len - 1) <= INT_MAX
1039 && count_payload == (int)(rdbi.data_len - 1));
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001040 OSMO_ASSERT(num_chunks == 1);
1041
1042 OSMO_ASSERT(data[0] == (((rdbi.data_len-1) << 1) | (1 << 0)));
1043 OSMO_ASSERT(data[1] == 0);
1044
1045 /* Final block with an LLC of size data_len-2 */
1046
Maxbea2edb2019-03-06 17:04:59 +01001047 cs = MCS2;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001048
1049 /* Block 1 */
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301050 gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001051 num_chunks = 0;
1052 write_offset = 0;
1053 memset(data, 0, sizeof(data));
1054
1055 llc.reset();
1056 llc.put_frame(llc_data, rdbi.data_len - 2);
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001057 count_payload = -1;
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001058
1059 ar = Encoding::rlc_data_to_dl_append(&rdbi, cs,
Alexander Couzens6f0dc962016-05-30 19:30:21 +02001060 &llc, &write_offset, &num_chunks, data, true, &count_payload);
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001061
1062 OSMO_ASSERT(ar == Encoding::AR_COMPLETED_BLOCK_FILLED);
1063 OSMO_ASSERT(rdbi.e == 0);
1064 OSMO_ASSERT(rdbi.cv == 0);
1065 OSMO_ASSERT(write_offset == (int)rdbi.data_len);
Neels Hofmeyrd34646a2017-02-08 17:07:40 +01001066 OSMO_ASSERT((rdbi.data_len - 2) <= INT_MAX
1067 && count_payload == (int)(rdbi.data_len - 2));
Jacob Erlbecka88d0652016-01-13 11:28:10 +01001068 OSMO_ASSERT(num_chunks == 2);
1069
1070 OSMO_ASSERT(data[0] == (((rdbi.data_len-2) << 1) | (0 << 0)));
1071 OSMO_ASSERT(data[1] == ((127 << 1) | (1 << 0)));
1072 OSMO_ASSERT(data[2] == 0);
1073
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001074 printf("=== end %s ===\n", __func__);
1075}
1076
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001077static void test_rlc_unaligned_copy()
1078{
1079 uint8_t bits[256];
1080 uint8_t saved_block[256];
1081 uint8_t test_block[256];
1082 uint8_t out_block[256];
Maxbea2edb2019-03-06 17:04:59 +01001083 CodingScheme scheme;
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001084 int pattern;
1085 volatile unsigned int block_idx, i;
1086
Maxbea2edb2019-03-06 17:04:59 +01001087 for (scheme = CS1;
1088 scheme < NUM_SCHEMES;
1089 scheme = CodingScheme(scheme + 1))
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001090 {
1091 GprsCodingScheme cs(scheme);
1092
1093 for (pattern = 0; pattern <= 0xff; pattern += 0xff) {
1094 /* prepare test block */
1095 test_block[0] = pattern ^ 0xff;
1096 for (i = 1; i + 1 < cs.maxDataBlockBytes(); i++)
1097 test_block[i] = i;
1098 test_block[cs.maxDataBlockBytes()-1] = pattern ^ 0xff;
1099
1100 for (block_idx = 0;
Max51754b62019-03-13 17:14:13 +01001101 block_idx < num_data_blocks(cs.headerTypeData());
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001102 block_idx++)
1103 {
1104 struct gprs_rlc_data_info rlc;
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301105 gprs_rlc_data_info_init_dl(&rlc, cs, false, 0);
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001106
1107 memset(bits, pattern, sizeof(bits));
1108 Decoding::rlc_copy_to_aligned_buffer(
1109 &rlc, block_idx, bits, saved_block);
1110
1111 fprintf(stderr,
1112 "Test data block: %s\n",
1113 osmo_hexdump(test_block, cs.maxDataBlockBytes()));
1114
1115 Encoding::rlc_copy_from_aligned_buffer(
1116 &rlc, block_idx, bits, test_block);
1117
1118 fprintf(stderr,
1119 "Encoded message block, %s, idx %d, "
1120 "pattern %02x: %s\n",
Max136ebcc2019-03-05 14:59:03 +01001121 mcs_name(rlc.cs), block_idx, pattern,
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001122 osmo_hexdump(bits, cs.sizeDL()));
1123
1124 Decoding::rlc_copy_to_aligned_buffer(
1125 &rlc, block_idx, bits, out_block);
1126
1127 fprintf(stderr,
1128 "Out data block: %s\n",
1129 osmo_hexdump(out_block, cs.maxDataBlockBytes()));
1130 /* restore original bits */
1131 Encoding::rlc_copy_from_aligned_buffer(
1132 &rlc, block_idx, bits, saved_block);
1133
1134 OSMO_ASSERT(memcmp(test_block, out_block,
1135 rlc.cs.maxDataBlockBytes()) == 0);
1136
1137 for (i = 0; i < sizeof(bits); i++)
1138 OSMO_ASSERT(bits[i] == pattern);
1139 }
1140 }
1141 }
1142}
1143
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001144static void test_rlc_info_init()
1145{
1146 struct gprs_rlc_data_info rlc;
1147
1148 printf("=== start %s ===\n", __func__);
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301149 gprs_rlc_data_info_init_dl(&rlc,
Maxbea2edb2019-03-06 17:04:59 +01001150 GprsCodingScheme(CS1), false, 0);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001151 OSMO_ASSERT(rlc.num_data_blocks == 1);
1152 OSMO_ASSERT(rlc.data_offs_bits[0] == 24);
1153 OSMO_ASSERT(rlc.block_info[0].data_len == 20);
1154
Aravind Sirsikar50b09702016-08-22 17:21:10 +05301155 gprs_rlc_data_info_init_dl(&rlc,
Maxbea2edb2019-03-06 17:04:59 +01001156 GprsCodingScheme(MCS1), false, 0);
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001157 OSMO_ASSERT(rlc.num_data_blocks == 1);
1158 OSMO_ASSERT(rlc.data_offs_bits[0] == 33);
1159 OSMO_ASSERT(rlc.block_info[0].data_len == 22);
1160
1161 printf("=== end %s ===\n", __func__);
1162}
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001163
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301164static void setup_bts(BTS *the_bts, uint8_t ts_no, uint8_t cs = 1)
1165{
1166 gprs_rlcmac_bts *bts;
1167 gprs_rlcmac_trx *trx;
1168
1169 bts = the_bts->bts_data();
1170 bts->egprs_enabled = true;
1171 bts->alloc_algorithm = alloc_algorithm_a;
1172 bts->initial_cs_dl = cs;
1173 bts->initial_cs_ul = cs;
1174 trx = &bts->trx[0];
1175 trx->pdch[ts_no].enable();
1176}
1177static void uplink_header_type_2_parsing_test(BTS *the_bts,
1178 uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
1179 uint8_t ms_class)
1180{
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301181 struct pcu_l1_meas meas;
1182 int tfi = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301183 uint8_t data[79] = {0};
1184 struct gprs_rlc_ul_header_egprs_2 *egprs2 = NULL;
1185
1186 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301187
1188 tfi = 1;
1189
1190 struct gprs_rlc_data_info rlc;
1191 GprsCodingScheme cs;
1192 int rc, offs;
1193
1194 /*without padding*/
Maxbea2edb2019-03-06 17:04:59 +01001195 cs = MCS5;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301196 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
1197 egprs2->r = 1;
1198 egprs2->si = 1;
1199 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001200 egprs2->tfi_hi = tfi & 0x03;
1201 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1202 egprs2->bsn1_hi = 0;
1203 egprs2->bsn1_lo = 0;
1204 egprs2->cps_hi = 3;
1205 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301206 egprs2->rsb = 0;
1207 egprs2->pi = 0;
1208 data[4] = 0x20; /* Setting E field */
1209 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001210 OSMO_ASSERT(rc == 487);
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301211 offs = rlc.data_offs_bits[0] / 8;
1212 OSMO_ASSERT(offs == 4);
1213 OSMO_ASSERT(rlc.tfi == 1);
1214 OSMO_ASSERT(rlc.num_data_blocks == 1);
1215 OSMO_ASSERT(rlc.block_info[0].e == 1);
1216 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1217 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1218
1219 /* with padding case */
Maxbea2edb2019-03-06 17:04:59 +01001220 cs = MCS6;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301221 egprs2 = (struct gprs_rlc_ul_header_egprs_2 *) data;
1222 egprs2->r = 1;
1223 egprs2->si = 1;
1224 egprs2->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001225 egprs2->tfi_hi = tfi & 0x03;
1226 egprs2->tfi_lo = (tfi & 0x1c) >> 2;
1227 egprs2->bsn1_hi = 0;
1228 egprs2->bsn1_lo = 0;
1229 egprs2->cps_hi = 3;
1230 egprs2->cps_lo = 0;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301231 egprs2->rsb = 0;
1232 egprs2->pi = 0;
1233 data[10] = 0x20; /* Setting E field */
1234 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001235 OSMO_ASSERT(rc == 679);
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301236 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);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001257 OSMO_ASSERT(rc == 679);
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301258 offs = rlc.data_offs_bits[0] / 8;
1259 OSMO_ASSERT(offs == 10);
1260 OSMO_ASSERT(rlc.tfi == 1);
1261 OSMO_ASSERT(rlc.num_data_blocks == 1);
1262 OSMO_ASSERT(rlc.block_info[0].e == 1);
1263 OSMO_ASSERT(rlc.block_info[0].ti == 0);
1264 OSMO_ASSERT(rlc.block_info[0].bsn == 1);
1265}
1266
1267static void uplink_header_type2_test(void)
1268{
1269 BTS the_bts;
1270 int ts_no = 7;
1271 uint32_t fn = 2654218;
1272 uint16_t qta = 31;
1273 uint32_t tlli = 0xf1223344;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301274 uint8_t ms_class = 1;
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301275
1276 printf("=== start %s ===\n", __func__);
1277 setup_bts(&the_bts, ts_no, 10);
1278
1279 uplink_header_type_2_parsing_test(&the_bts, ts_no,
1280 tlli, &fn, qta, ms_class);
1281 printf("=== end %s ===\n", __func__);
1282}
1283
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301284static void uplink_header_type_1_parsing_test(BTS *the_bts,
1285 uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
1286 uint8_t ms_class)
1287{
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301288 int tfi = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301289 uint8_t data[155] = {0};
1290 struct gprs_rlc_ul_header_egprs_1 *egprs1 = NULL;
1291 struct gprs_rlc_data_info rlc;
1292 GprsCodingScheme cs;
Neels Hofmeyrd34646a2017-02-08 17:07:40 +01001293 int rc;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301294
1295 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301296
1297 tfi = 1;
1298
1299 /* MCS 7 */
Maxbea2edb2019-03-06 17:04:59 +01001300 cs = MCS7;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301301 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1302 egprs1->si = 1;
1303 egprs1->r = 1;
1304 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001305 egprs1->tfi_hi = tfi & 0x03;
1306 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1307 egprs1->bsn1_hi = 0;
1308 egprs1->bsn1_lo = 0;
1309 egprs1->bsn2_hi = 1;
1310 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301311 egprs1->cps = 15;
1312 egprs1->rsb = 0;
1313 egprs1->pi = 0;
1314 data[5] = 0xc0;
1315 data[5 + 57] = 1;
1316 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001317 OSMO_ASSERT(rc == 946);
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301318 OSMO_ASSERT(rlc.num_data_blocks == 2);
1319 OSMO_ASSERT(rlc.block_info[0].e == 1);
1320 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1321 OSMO_ASSERT(rlc.block_info[1].e == 1);
1322 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1323 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1324 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1325 OSMO_ASSERT(rlc.tfi == 1);
1326
1327 /* MCS 8 */
Maxbea2edb2019-03-06 17:04:59 +01001328 cs = MCS8;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301329 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1330 egprs1->si = 1;
1331 egprs1->r = 1;
1332 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001333 egprs1->tfi_hi = tfi & 0x03;
1334 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1335 egprs1->bsn1_hi = 0;
1336 egprs1->bsn1_lo = 0;
1337 egprs1->bsn2_hi = 1;
1338 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301339 egprs1->cps = 15;
1340 egprs1->rsb = 0;
1341 egprs1->pi = 0;
1342 data[5] = 0xc0;
1343 data[5 + 69] = 1;
1344 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001345 OSMO_ASSERT(rc == 1138);
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301346 OSMO_ASSERT(rlc.num_data_blocks == 2);
1347 OSMO_ASSERT(rlc.block_info[0].e == 1);
1348 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1349 OSMO_ASSERT(rlc.block_info[1].e == 1);
1350 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1351 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1352 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1353 OSMO_ASSERT(rlc.tfi == 1);
1354
1355 /* MCS 9 */
Maxbea2edb2019-03-06 17:04:59 +01001356 cs = MCS9;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301357 egprs1 = (struct gprs_rlc_ul_header_egprs_1 *) data;
1358 egprs1->si = 1;
1359 egprs1->r = 1;
1360 egprs1->cv = 7;
Tom Tsoudf698092016-07-11 17:05:19 -07001361 egprs1->tfi_hi = tfi & 0x03;
1362 egprs1->tfi_lo = (tfi & 0x1c) >> 2;
1363 egprs1->bsn1_hi = 0;
1364 egprs1->bsn1_lo = 0;
1365 egprs1->bsn2_hi = 1;
1366 egprs1->bsn2_lo = 0;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301367 egprs1->cps = 15;
1368 egprs1->rsb = 0;
1369 egprs1->pi = 0;
1370 data[5] = 0xc0;
1371 data[5 + 75] = 1;
1372 rc = Decoding::rlc_parse_ul_data_header(&rlc, data, cs);
Neels Hofmeyrde9da392017-02-08 17:34:56 +01001373 OSMO_ASSERT(rc == 1234);
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301374 OSMO_ASSERT(rlc.num_data_blocks == 2);
1375 OSMO_ASSERT(rlc.block_info[0].e == 1);
1376 OSMO_ASSERT(rlc.block_info[0].ti == 1);
1377 OSMO_ASSERT(rlc.block_info[1].e == 1);
1378 OSMO_ASSERT(rlc.block_info[1].ti == 0);
1379 OSMO_ASSERT(rlc.block_info[0].bsn == 0);
1380 OSMO_ASSERT(rlc.block_info[1].bsn == 1);
1381 OSMO_ASSERT(rlc.tfi == 1);
1382}
1383
1384void uplink_header_type1_test(void)
1385{
1386 BTS the_bts;
1387 int ts_no = 7;
1388 uint32_t fn = 2654218;
1389 uint16_t qta = 31;
1390 uint32_t tlli = 0xf1223344;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301391 uint8_t ms_class = 1;
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301392
1393 printf("=== start %s ===\n", __func__);
1394 setup_bts(&the_bts, ts_no, 12);
1395 uplink_header_type_1_parsing_test(&the_bts, ts_no, tlli, &fn,
1396 qta, ms_class);
1397 printf("=== end %s ===\n", __func__);
1398}
1399
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001400int main(int argc, char **argv)
1401{
1402 struct vty_app_info pcu_vty_info = {0};
1403
1404 tall_pcu_ctx = talloc_named_const(NULL, 1, "EdgeTest context");
1405 if (!tall_pcu_ctx)
1406 abort();
1407
Neels Hofmeyr78ce5912017-02-08 17:07:31 +01001408 msgb_talloc_ctx_init(tall_pcu_ctx, 0);
Neels Hofmeyr42f2d612018-04-01 16:54:40 +02001409 osmo_init_logging2(tall_pcu_ctx, &gprs_log_info);
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001410 log_set_use_color(osmo_stderr_target, 0);
1411 log_set_print_filename(osmo_stderr_target, 0);
1412
1413 vty_init(&pcu_vty_info);
Pau Espin Pedrolcd2ac562019-08-05 14:30:44 +02001414 pcu_vty_init();
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001415
1416 test_coding_scheme();
Jacob Erlbeck6e9f9c22016-01-11 11:15:45 +01001417 test_rlc_info_init();
Jacob Erlbeck38f18692016-02-01 10:08:00 +01001418 test_rlc_unit_decoder();
Jacob Erlbeckf0e40392016-01-08 10:07:53 +01001419 test_rlc_unaligned_copy();
Jacob Erlbeck14bb0942016-01-12 11:58:13 +01001420 test_rlc_unit_encoder();
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001421
Aravind Sirsikar189742b2016-06-14 19:01:14 +05301422 uplink_header_type2_test();
Aravind Sirsikar2c9f9802016-06-14 19:01:56 +05301423 uplink_header_type1_test();
1424
Jacob Erlbeckd0222cf2015-12-07 12:23:35 +01001425 if (getenv("TALLOC_REPORT_FULL"))
1426 talloc_report_full(tall_pcu_ctx, stderr);
1427 return EXIT_SUCCESS;
1428}
1429
1430/*
1431 * stubs that should not be reached
1432 */
1433extern "C" {
1434void l1if_pdch_req() { abort(); }
1435void l1if_connect_pdch() { abort(); }
1436void l1if_close_pdch() { abort(); }
1437void l1if_open_pdch() { abort(); }
1438}