osmo-pcu/tests/edge/EdgeTest.cpp

2601 lines
77 KiB
C++

/*
* EdgeTest.cpp
*
* Copyright (C) 2015 by Sysmocom s.f.m.c. GmbH
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "gprs_debug.h"
#include "gprs_coding_scheme.h"
#include "decoding.h"
#include "rlc.h"
#include "bts.h"
extern "C" {
#include "pcu_vty.h"
#include "pcuif_proto.h"
#include <osmocom/core/application.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
#include <osmocom/vty/vty.h>
}
#include <errno.h>
enum test_tbf_final_ack_mode {
TEST_MODE_STANDARD,
TEST_MODE_REVERSE_FREE
};
/*structure to fill uplink data for mcs 8*/
struct gprs_rlc_ul_header_egprs_1_test {
uint8_t r:1,
si:1,
cv:4,
tfi_a:2;
uint8_t tfi_b:3,
bsn1_a:5;
uint8_t bsn1_b:6,
bsn2_a:2;
uint8_t bsn2_b;
uint8_t cps:5,
rsb:1,
pi:1,
spare:1;
uint8_t spare2:6,
dummy:2;
uint8_t e1 :1,
ti1 : 1,
dummy1:6;
uint8_t e2 :1,
length1 : 7;
uint8_t data1[67];
uint8_t e3: 1,
ti2:1,
dummy2:6;
uint8_t e4:1,
length2:7;
uint8_t data2[67];
} __attribute__ ((packed));
/*structure to fill uplink data for mcs9*/
struct gprs_rlc_ul_header_egprs_2_test {
uint8_t r:1,
si:1,
cv:4,
tfi_a:2;
uint8_t tfi_b:3,
bsn1_a:5;
uint8_t bsn1_b:6,
bsn2_a:2;
uint8_t bsn2_b;
uint8_t cps:5,
rsb:1,
pi:1,
spare:1;
uint8_t spare2:6,
dummy:2;
uint8_t e1 :1,
ti1 : 1,
dummy1:6;
uint8_t e2 :1,
length1 : 7;
uint8_t data1[73];
uint8_t e3: 1,
ti2:1,
dummy2:6;
uint8_t e4:1,
length2:7;
uint8_t data2[73];
} __attribute__ ((packed));
static uint8_t llc_data[256];
void *tall_pcu_ctx;
int16_t spoof_mnc = 0, spoof_mcc = 0;
static void check_coding_scheme(GprsCodingScheme& cs, GprsCodingScheme::Mode mode)
{
volatile unsigned expected_size;
GprsCodingScheme new_cs;
OSMO_ASSERT(cs.isValid());
OSMO_ASSERT(cs.isCompatible(mode));
/* Check static getBySizeUL() */
expected_size = cs.maxBytesUL();
OSMO_ASSERT(expected_size == cs.sizeUL());
OSMO_ASSERT(cs == GprsCodingScheme::getBySizeUL(expected_size));
/* Check static sizeUL() */
expected_size = cs.maxBytesDL();
if (cs.spareBitsDL() > 0)
expected_size += 1;
OSMO_ASSERT(expected_size == cs.sizeDL());
/* Check data block sizes */
OSMO_ASSERT(cs.maxDataBlockBytes() * cs.numDataBlocks() < cs.maxBytesDL());
OSMO_ASSERT(cs.maxDataBlockBytes() * cs.numDataBlocks() < cs.maxBytesUL());
}
static void test_coding_scheme()
{
unsigned i;
unsigned last_size_UL;
unsigned last_size_DL;
GprsCodingScheme::Scheme gprs_schemes[] = {
GprsCodingScheme::CS1,
GprsCodingScheme::CS2,
GprsCodingScheme::CS3,
GprsCodingScheme::CS4
};
struct {
GprsCodingScheme::Scheme s;
bool is_gmsk;
} egprs_schemes[] = {
{GprsCodingScheme::MCS1, true},
{GprsCodingScheme::MCS2, true},
{GprsCodingScheme::MCS3, true},
{GprsCodingScheme::MCS4, true},
{GprsCodingScheme::MCS5, false},
{GprsCodingScheme::MCS6, false},
{GprsCodingScheme::MCS7, false},
{GprsCodingScheme::MCS8, false},
{GprsCodingScheme::MCS9, false},
};
printf("=== start %s ===\n", __func__);
GprsCodingScheme cs;
OSMO_ASSERT(!cs);
OSMO_ASSERT(cs == GprsCodingScheme::UNKNOWN);
OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::GPRS));
OSMO_ASSERT(!cs.isCompatible(GprsCodingScheme::EGPRS));
last_size_UL = 0;
last_size_DL = 0;
for (i = 0; i < ARRAY_SIZE(gprs_schemes); i++) {
GprsCodingScheme current_cs(gprs_schemes[i]);
OSMO_ASSERT(current_cs.isGprs());
OSMO_ASSERT(!current_cs.isEgprs());
OSMO_ASSERT(current_cs == gprs_schemes[i]);
OSMO_ASSERT(current_cs == GprsCodingScheme(gprs_schemes[i]));
/* Check strong monotonicity */
OSMO_ASSERT(current_cs.maxBytesUL() > last_size_UL);
OSMO_ASSERT(current_cs.maxBytesDL() > last_size_DL);
last_size_UL = current_cs.maxBytesUL();
last_size_DL = current_cs.maxBytesDL();
/* Check header types */
OSMO_ASSERT(current_cs.headerTypeData() ==
GprsCodingScheme::HEADER_GPRS_DATA);
OSMO_ASSERT(current_cs.headerTypeControl() ==
GprsCodingScheme::HEADER_GPRS_CONTROL);
#if 0
check_coding_scheme(current_cs, GprsCodingScheme::GPRS);
#endif
}
OSMO_ASSERT(i == 4);
last_size_UL = 0;
last_size_DL = 0;
for (i = 0; i < ARRAY_SIZE(egprs_schemes); i++) {
GprsCodingScheme current_cs(egprs_schemes[i].s);
OSMO_ASSERT(!current_cs.isGprs());
OSMO_ASSERT(current_cs.isEgprs());
OSMO_ASSERT(current_cs == egprs_schemes[i].s);
OSMO_ASSERT(current_cs == GprsCodingScheme(egprs_schemes[i].s));
/* Check strong monotonicity */
OSMO_ASSERT(current_cs.maxBytesUL() > last_size_UL);
OSMO_ASSERT(current_cs.maxBytesDL() > last_size_DL);
last_size_UL = current_cs.maxBytesUL();
last_size_DL = current_cs.maxBytesDL();
#if 0
check_coding_scheme(current_cs, GprsCodingScheme::EGPRS);
#endif
}
OSMO_ASSERT(i == 9);
printf("=== end %s ===\n", __func__);
}
static void test_rlc_decoder()
{
struct gprs_rlc_ul_data_block_info rdbi = {0};
GprsCodingScheme cs;
uint8_t data[74];
Decoding::RlcData chunks[16];
volatile int num_chunks = 0;
uint32_t tlli, tlli2;
unsigned int offs;
BTS the_bts;
the_bts.bts_data()->egprs_enabled = true;
the_bts.bts_data()->alloc_algorithm = alloc_algorithm_b;
the_bts.bts_data()->trx[0].pdch[2].enable();
the_bts.bts_data()->trx[0].pdch[3].enable();/*
* Make a uplink and downlink allocation
*/
gprs_rlcmac_tbf *dl_tbf = tbf_alloc_dl_tbf(the_bts.bts_data(),
NULL,
0, 0, 4, 0);
OSMO_ASSERT(dl_tbf != NULL);
gprs_rlcmac_tbf *ul_tbf = tbf_alloc_ul_tbf(the_bts.bts_data(),
dl_tbf->ms(),
0, 0, 4, 0);
/*
bts.cpp:1156 Got RLC block, coding scheme: CS-4, length : 54 (53))
bts.cpp:1200 UL data: 3c 02 02 33 0a ed 5d fe d8 00 8f 18 33 2c 16 45 03 c0 68 75 00 00 16 45 00 03 c5 62 29 40 00 45 06 4e b6 c0 a8 00 02 c0 a8 00 01 86 74 1f 91 17 ac 35 ee 33 5e
bts.cpp:1217 Got CS-4 RLC block: R=0, SI=0, TFI=1, CPS=0, RSB=0, rc=424
tbf_ul.cpp:323 UL DATA TFI=1 received (V(Q)=1 .. V(R)=1)
tbf.cpp:406 TBF(TFI=1 TLLI=0xdf1781e3 DIR=UL STATE=FLOW) restarting timer 3169 while old timer 3169 pending
tbf_ul.cpp:357 TBF(TFI=1 TLLI=0xdf1781e3 DIR=UL STATE=FLOW): Got CS-4 RLC data block: CV=15, BSN=1, SPB=0, PI=0, E=0, TI=0, bitoffs=24
tbf_ul.cpp:390 - BSN 1 storing in window (1..64)
tbf_ul.cpp:415 TBF(TFI=1 TLLI=0xdf1781e3 DIR=UL STATE=FLOW): data_length=50, data=33 0a ed 5d fe d8 00 8f 18 33 2c 16 45 03 c0 68 75 00 00 16 45 00 03 c5 62 29 40 00 45 06 4e b6 c0 a8 00 02 c0 a8 00 01 86 74 1f 91 17 ac 35 ee 33 5e
*/
printf("=== start %s ===\n", __func__);
printf("=== end %s ===\n", __func__);
}
static void test_rlc_unit_decoder()
{
struct gprs_rlc_ul_data_block_info rdbi = {0};
GprsCodingScheme cs;
uint8_t data[74];
Decoding::RlcData chunks[16];
volatile int num_chunks = 0;
uint32_t tlli, tlli2;
unsigned int offs;
printf("=== start %s ===\n", __func__);
/* TS 44.060, B.1 */
cs = GprsCodingScheme::CS4;
rdbi.data_len = cs.maxDataBlockBytes();
rdbi.e = 0;
rdbi.ti = 0;
rdbi.cv = 15;
tlli = 0;
offs = 0;
data[offs++] = (11 << 2) | (1 << 1) | (0 << 0);
data[offs++] = (26 << 2) | (1 << 1) | (1 << 0);
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 3);
OSMO_ASSERT(tlli == 0);
OSMO_ASSERT(chunks[0].offset == 2);
OSMO_ASSERT(chunks[0].length == 11);
OSMO_ASSERT(chunks[0].is_complete);
OSMO_ASSERT(chunks[1].offset == 13);
OSMO_ASSERT(chunks[1].length == 26);
OSMO_ASSERT(chunks[1].is_complete);
OSMO_ASSERT(chunks[2].offset == 39);
OSMO_ASSERT(chunks[2].length == cs.maxDataBlockBytes() - 39);
OSMO_ASSERT(!chunks[2].is_complete);
/* TS 44.060, B.2 */
cs = GprsCodingScheme::CS1;
rdbi.data_len = cs.maxDataBlockBytes();
rdbi.e = 0;
rdbi.ti = 0;
rdbi.cv = 15;
tlli = 0;
offs = 0;
data[offs++] = (0 << 2) | (0 << 1) | (1 << 0);
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 1);
OSMO_ASSERT(tlli == 0);
OSMO_ASSERT(chunks[0].offset == 1);
OSMO_ASSERT(chunks[0].length == 19);
OSMO_ASSERT(!chunks[0].is_complete);
rdbi.e = 0;
rdbi.ti = 0;
rdbi.cv = 15;
tlli = 0;
offs = 0;
data[offs++] = (1 << 2) | (1 << 1) | (1 << 0);
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 2);
OSMO_ASSERT(tlli == 0);
OSMO_ASSERT(chunks[0].offset == 1);
OSMO_ASSERT(chunks[0].length == 1);
OSMO_ASSERT(chunks[0].is_complete);
OSMO_ASSERT(chunks[1].offset == 2);
OSMO_ASSERT(chunks[1].length == 18);
OSMO_ASSERT(!chunks[1].is_complete);
/* TS 44.060, B.3 */
cs = GprsCodingScheme::CS1;
rdbi.data_len = cs.maxDataBlockBytes();
rdbi.e = 0;
rdbi.ti = 0;
rdbi.cv = 15;
tlli = 0;
offs = 0;
data[offs++] = (7 << 2) | (1 << 1) | (0 << 0);
data[offs++] = (11 << 2) | (0 << 1) | (1 << 0);
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 2);
OSMO_ASSERT(tlli == 0);
OSMO_ASSERT(chunks[0].offset == 2);
OSMO_ASSERT(chunks[0].length == 7);
OSMO_ASSERT(chunks[0].is_complete);
OSMO_ASSERT(chunks[1].offset == 9);
OSMO_ASSERT(chunks[1].length == 11);
OSMO_ASSERT(chunks[1].is_complete);
/* TS 44.060, B.4 */
cs = GprsCodingScheme::CS1;
rdbi.data_len = cs.maxDataBlockBytes();
rdbi.e = 1;
rdbi.ti = 0;
rdbi.cv = 15;
tlli = 0;
offs = 0;
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 1);
OSMO_ASSERT(tlli == 0);
OSMO_ASSERT(chunks[0].offset == 0);
OSMO_ASSERT(chunks[0].length == 20);
OSMO_ASSERT(!chunks[0].is_complete);
/* TS 44.060, B.6 */
cs = GprsCodingScheme::CS1;
rdbi.data_len = cs.maxDataBlockBytes();
rdbi.e = 1;
rdbi.ti = 0;
rdbi.cv = 0;
tlli = 0;
offs = 0;
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 1);
OSMO_ASSERT(tlli == 0);
OSMO_ASSERT(chunks[0].offset == 0);
OSMO_ASSERT(chunks[0].length == 20);
OSMO_ASSERT(chunks[0].is_complete);
/* TS 44.060, B.8.1 */
cs = GprsCodingScheme::MCS4;
rdbi.data_len = cs.maxDataBlockBytes();
rdbi.e = 0;
rdbi.ti = 0;
rdbi.cv = 15;
tlli = 0;
offs = 0;
data[offs++] = 6;
data[offs++] = 10;
data[offs++] = 16;
data[offs++] = 255;
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 3);
OSMO_ASSERT(tlli == 0);
OSMO_ASSERT(chunks[0].offset == 4);
OSMO_ASSERT(chunks[0].length == 3);
OSMO_ASSERT(chunks[0].is_complete);
OSMO_ASSERT(chunks[1].offset == 7);
OSMO_ASSERT(chunks[1].length == 5);
OSMO_ASSERT(chunks[1].is_complete);
OSMO_ASSERT(chunks[2].offset == 12);
OSMO_ASSERT(chunks[2].length == 8);
OSMO_ASSERT(chunks[2].is_complete);
/* TS 44.060, B.8.2 */
/* Note that the spec confuses the byte numbering here, since it
* includes the FBI/E header bits into the N2 octet count which
* is not consistent with Section 10.3a.1 & 10.3a.2. */
cs = GprsCodingScheme::MCS2;
rdbi.data_len = cs.maxDataBlockBytes();
rdbi.e = 0;
rdbi.ti = 0;
rdbi.cv = 15;
tlli = 0;
offs = 0;
data[offs++] = (15 << 1) | (1 << 0);
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 2);
OSMO_ASSERT(tlli == 0);
OSMO_ASSERT(chunks[0].offset == 1);
OSMO_ASSERT(chunks[0].length == 15);
OSMO_ASSERT(chunks[0].is_complete);
OSMO_ASSERT(chunks[1].offset == 16);
OSMO_ASSERT(chunks[1].length == 12);
OSMO_ASSERT(!chunks[1].is_complete);
rdbi.e = 0;
rdbi.ti = 0;
rdbi.cv = 15;
tlli = 0;
offs = 0;
data[offs++] = ( 0 << 1) | (0 << 0);
data[offs++] = ( 7 << 1) | (0 << 0);
data[offs++] = (18 << 1) | (1 << 0); /* Differs from spec's N2-11 = 17 */
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 3);
OSMO_ASSERT(tlli == 0);
OSMO_ASSERT(chunks[0].offset == 3);
OSMO_ASSERT(chunks[0].length == 0);
OSMO_ASSERT(chunks[0].is_complete);
OSMO_ASSERT(chunks[1].offset == 3);
OSMO_ASSERT(chunks[1].length == 7);
OSMO_ASSERT(chunks[1].is_complete);
OSMO_ASSERT(chunks[2].offset == 10);
OSMO_ASSERT(chunks[2].length == 18);
OSMO_ASSERT(chunks[2].is_complete);
rdbi.e = 0;
rdbi.ti = 0;
rdbi.cv = 0;
tlli = 0;
offs = 0;
data[offs++] = ( 6 << 1) | (0 << 0);
data[offs++] = (12 << 1) | (0 << 0);
data[offs++] = (127 << 1) | (1 << 0);
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 2);
OSMO_ASSERT(tlli == 0);
OSMO_ASSERT(chunks[0].offset == 3);
OSMO_ASSERT(chunks[0].length == 6);
OSMO_ASSERT(chunks[0].is_complete);
OSMO_ASSERT(chunks[1].offset == 9);
OSMO_ASSERT(chunks[1].length == 12);
OSMO_ASSERT(chunks[1].is_complete);
/* TS 44.060, B.8.3 */
/* Note that the spec confuses the byte numbering here, too (see above) */
cs = GprsCodingScheme::MCS2;
rdbi.data_len = cs.maxDataBlockBytes();
rdbi.e = 1;
rdbi.ti = 0;
rdbi.cv = 0;
tlli = 0;
offs = 0;
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 1);
OSMO_ASSERT(tlli == 0);
OSMO_ASSERT(chunks[0].offset == 0);
OSMO_ASSERT(chunks[0].length == 28);
OSMO_ASSERT(chunks[0].is_complete);
/* CS-1, TLLI, last block, single chunk until the end of the block */
cs = GprsCodingScheme::CS1;
rdbi.data_len = cs.maxDataBlockBytes();
rdbi.e = 1;
rdbi.ti = 1;
rdbi.cv = 0;
tlli = 0;
tlli2 = 0xffeeddcc;
offs = 0;
data[offs++] = tlli2 >> 24;
data[offs++] = tlli2 >> 16;
data[offs++] = tlli2 >> 8;
data[offs++] = tlli2 >> 0;
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 1);
OSMO_ASSERT(tlli == tlli2);
OSMO_ASSERT(chunks[0].offset == 4);
OSMO_ASSERT(chunks[0].length == 16);
OSMO_ASSERT(chunks[0].is_complete);
/* Like TS 44.060, B.2, first RLC block but with TLLI */
cs = GprsCodingScheme::CS1;
rdbi.data_len = cs.maxDataBlockBytes();
rdbi.e = 0;
rdbi.ti = 1;
rdbi.cv = 15;
tlli = 0;
tlli2 = 0xffeeddbb;
offs = 0;
data[offs++] = (0 << 2) | (0 << 1) | (1 << 0);
data[offs++] = tlli2 >> 24;
data[offs++] = tlli2 >> 16;
data[offs++] = tlli2 >> 8;
data[offs++] = tlli2 >> 0;
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 1);
OSMO_ASSERT(tlli == tlli2);
OSMO_ASSERT(chunks[0].offset == 5);
OSMO_ASSERT(chunks[0].length == 15);
OSMO_ASSERT(!chunks[0].is_complete);
/* Like TS 44.060, B.8.1 but with TLLI */
cs = GprsCodingScheme::MCS4;
rdbi.data_len = cs.maxDataBlockBytes();
rdbi.e = 0;
rdbi.ti = 1;
rdbi.cv = 15;
tlli = 0;
tlli2 = 0xffeeddaa;
offs = 0;
data[offs++] = (11 << 1) | (0 << 0);
data[offs++] = (26 << 1) | (1 << 0);
/* Little endian */
data[offs++] = tlli2 >> 0;
data[offs++] = tlli2 >> 8;
data[offs++] = tlli2 >> 16;
data[offs++] = tlli2 >> 24;
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 3);
OSMO_ASSERT(tlli == tlli2);
OSMO_ASSERT(chunks[0].offset == 6);
OSMO_ASSERT(chunks[0].length == 11);
OSMO_ASSERT(chunks[0].is_complete);
OSMO_ASSERT(chunks[1].offset == 17);
OSMO_ASSERT(chunks[1].length == 26);
OSMO_ASSERT(chunks[1].is_complete);
OSMO_ASSERT(chunks[2].offset == 43);
OSMO_ASSERT(chunks[2].length == 1);
OSMO_ASSERT(!chunks[2].is_complete);
cs = GprsCodingScheme::MCS5;
rdbi.data_len = cs.maxDataBlockBytes();
rdbi.e = 0;
rdbi.ti = 0;
rdbi.cv = 15;
tlli = 0;
offs = 0;
data[offs++] = (15 << 1) | (1 << 0);
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 2);
OSMO_ASSERT(tlli == 0);
OSMO_ASSERT(chunks[0].offset == 1);
OSMO_ASSERT(chunks[0].length == 15);
OSMO_ASSERT(chunks[0].is_complete);
OSMO_ASSERT(chunks[1].offset == 16);
OSMO_ASSERT(chunks[1].length == 40);
OSMO_ASSERT(!chunks[1].is_complete);
rdbi.e = 0;
rdbi.ti = 0;
rdbi.cv = 15;
tlli = 1;
offs = 0;
data[offs++] = ( 0 << 1) | (0 << 0);
data[offs++] = ( 7 << 1) | (0 << 0);
data[offs++] = (18 << 1) | (1 << 0); /* Differs from spec's N2-11 = 17 */
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 4);
OSMO_ASSERT(tlli == 0);
OSMO_ASSERT(chunks[0].length == 0);
OSMO_ASSERT(chunks[0].is_complete);
OSMO_ASSERT(chunks[1].offset == 3);
OSMO_ASSERT(chunks[1].length == 7);
OSMO_ASSERT(chunks[1].is_complete);
OSMO_ASSERT(chunks[2].offset == 10);
OSMO_ASSERT(chunks[2].length == 18);
OSMO_ASSERT(chunks[2].is_complete);
//#endif
rdbi.e = 0;
rdbi.ti = 0;
rdbi.cv = 0;
tlli = 0;
offs = 0;
data[offs++] = ( 6 << 1) | (0 << 0);
data[offs++] = (12 << 1) | (0 << 0);
data[offs++] = (127 << 1) | (1 << 0);
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 2);
OSMO_ASSERT(tlli == 0);
OSMO_ASSERT(chunks[0].offset == 3);
OSMO_ASSERT(chunks[0].length == 6);
OSMO_ASSERT(chunks[0].is_complete);
OSMO_ASSERT(chunks[1].offset == 9);
OSMO_ASSERT(chunks[1].length == 12);
OSMO_ASSERT(chunks[1].is_complete);
cs = GprsCodingScheme::MCS5;
rdbi.data_len = cs.maxDataBlockBytes();
rdbi.e = 1;
rdbi.ti = 0;
rdbi.cv = 0;
tlli = 0;
offs = 0;
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 1);
OSMO_ASSERT(tlli == 0);
OSMO_ASSERT(chunks[0].offset == 0);
OSMO_ASSERT(chunks[0].length == 56);
OSMO_ASSERT(chunks[0].is_complete);
cs = GprsCodingScheme::MCS6;
rdbi.data_len = cs.maxDataBlockBytes();
rdbi.e = 0;
rdbi.ti = 0;
rdbi.cv = 15;
tlli = 0;
offs = 0;
data[offs++] = (15 << 1) | (1 << 0);
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 2);
OSMO_ASSERT(tlli == 0);
OSMO_ASSERT(chunks[0].offset == 1);
OSMO_ASSERT(chunks[0].length == 15);
OSMO_ASSERT(chunks[0].is_complete);
OSMO_ASSERT(chunks[1].offset == 16);
OSMO_ASSERT(chunks[1].length == 58);
OSMO_ASSERT(!chunks[1].is_complete);
rdbi.e = 0;
rdbi.ti = 0;
rdbi.cv = 15;
tlli = 1;
offs = 0;
data[offs++] = ( 0 << 1) | (0 << 0);
data[offs++] = ( 7 << 1) | (0 << 0);
data[offs++] = (18 << 1) | (1 << 0); /* Differs from spec's N2-11 = 17 */
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 4);
OSMO_ASSERT(tlli == 0);
OSMO_ASSERT(chunks[0].length == 0);
OSMO_ASSERT(chunks[0].is_complete);
OSMO_ASSERT(chunks[1].offset == 3);
OSMO_ASSERT(chunks[1].length == 7);
OSMO_ASSERT(chunks[1].is_complete);
OSMO_ASSERT(chunks[2].offset == 10);
OSMO_ASSERT(chunks[2].length == 18);
OSMO_ASSERT(chunks[2].is_complete);
rdbi.e = 0;
rdbi.ti = 0;
rdbi.cv = 0;
tlli = 0;
offs = 0;
data[offs++] = ( 6 << 1) | (0 << 0);
data[offs++] = (12 << 1) | (0 << 0);
data[offs++] = (127 << 1) | (1 << 0);
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 2);
OSMO_ASSERT(tlli == 0);
OSMO_ASSERT(chunks[0].offset == 3);
OSMO_ASSERT(chunks[0].length == 6);
OSMO_ASSERT(chunks[0].is_complete);
OSMO_ASSERT(chunks[1].offset == 9);
OSMO_ASSERT(chunks[1].length == 12);
OSMO_ASSERT(chunks[1].is_complete);
cs = GprsCodingScheme::MCS6;
rdbi.data_len = cs.maxDataBlockBytes();
rdbi.e = 1;
rdbi.ti = 0;
rdbi.cv = 0;
tlli = 0;
offs = 0;
num_chunks = Decoding::rlc_data_from_ul_data(&rdbi, cs, data,
chunks, ARRAY_SIZE(chunks), &tlli);
OSMO_ASSERT(num_chunks == 1);
OSMO_ASSERT(tlli == 0);
OSMO_ASSERT(chunks[0].offset == 0);
OSMO_ASSERT(chunks[0].length == 74);
OSMO_ASSERT(chunks[0].is_complete);
printf("=== end %s ===\n", __func__);
}
static const struct log_info_cat default_categories[] = {
{"DCSN1", "\033[1;31m", "Concrete Syntax Notation One (CSN1)", LOGL_INFO, 0},
{"DL1IF", "\033[1;32m", "GPRS PCU L1 interface (L1IF)", LOGL_DEBUG, 1},
{"DRLCMAC", "\033[0;33m", "GPRS RLC/MAC layer (RLCMAC)", LOGL_DEBUG, 1},
{"DRLCMACDATA", "\033[0;33m", "GPRS RLC/MAC layer Data (RLCMAC)", LOGL_DEBUG, 1},
{"DRLCMACDL", "\033[1;33m", "GPRS RLC/MAC layer Downlink (RLCMAC)", LOGL_DEBUG, 1},
{"DRLCMACUL", "\033[1;36m", "GPRS RLC/MAC layer Uplink (RLCMAC)", LOGL_DEBUG, 1},
{"DRLCMACSCHED", "\033[0;36m", "GPRS RLC/MAC layer Scheduling (RLCMAC)", LOGL_DEBUG, 1},
{"DRLCMACMEAS", "\033[1;31m", "GPRS RLC/MAC layer Measurements (RLCMAC)", LOGL_INFO, 1},
{"DNS","\033[1;34m", "GPRS Network Service Protocol (NS)", LOGL_INFO , 1},
{"DBSSGP","\033[1;34m", "GPRS BSS Gateway Protocol (BSSGP)", LOGL_INFO , 1},
{"DPCU", "\033[1;35m", "GPRS Packet Control Unit (PCU)", LOGL_NOTICE, 1},
};
static int filter_fn(const struct log_context *ctx,
struct log_target *tar)
{
return 1;
}
const struct log_info debug_log_info = {
filter_fn,
(struct log_info_cat*)default_categories,
ARRAY_SIZE(default_categories),
};
static unsigned fn2bn(unsigned fn)
{
return (fn % 52) / 4;
}
static unsigned fn_add_blocks(unsigned fn, unsigned blocks)
{
unsigned bn = fn2bn(fn) + blocks;
fn = fn - (fn % 52);
fn += bn * 4 + bn / 3;
return fn % 2715648;
}
static void request_dl_rlc_block(struct gprs_rlcmac_bts *bts,
uint8_t trx_no, uint8_t ts_no, uint16_t arfcn,
uint32_t *fn, uint8_t *block_nr = NULL)
{
uint8_t bn = fn2bn(*fn);
gprs_rlcmac_rcv_rts_block(bts, trx_no, ts_no, arfcn, *fn, bn);
*fn = fn_add_blocks(*fn, 1);
bn += 1;
if (block_nr)
*block_nr = bn;
}
static void send_ul_mac_block_PDAN(BTS *the_bts, unsigned trx_no, unsigned ts_no,
RlcMacUplink_t *ulreq, unsigned fn)
{
bitvec *rlc_block;
uint8_t buf[64];
int num_bytes;
struct gprs_rlcmac_pdch *pdch;
struct pcu_l1_meas meas;
bitvec *dest;
meas.set_rssi(31);
dest = bitvec_alloc(23);
unsigned wp =0;
bitvec_write_field(dest, wp, 0x1, 2); // Payload Type
bitvec_write_field(dest, wp, 0x0, 2); // Uplink block with TDMA framenumber (N+13)
bitvec_write_field(dest, wp, 0x0, 1); // Suppl/Polling Bit
bitvec_write_field(dest, wp, 0x0, 3); // Uplink state flag
bitvec_write_field(dest, wp, 0x8, 6); // MESSAGE TYPE Uplink Ack/Nack
bitvec_write_field(dest, wp, 0x0, 5); // Downlink TFI
bitvec_write_field(dest, wp, 0, 1); //MS_OUT_OF_MEMORY
bitvec_write_field(dest, wp, 0, 1); //Exist_EGPRS_ChannelQualityReport
bitvec_write_field(dest, wp, 0, 1); //Exist_ChannelRequestDescription
bitvec_write_field(dest, wp, 0, 1); //Exist_PFI
bitvec_write_field(dest, wp, 0, 1); // Exist_ExtensionBits
bitvec_write_field(dest, wp, 1, 1); // 1: have length
bitvec_write_field(dest, wp, 39, 8); // length
bitvec_write_field(dest, wp, 0, 1); // FINAL_ACK_INDICATION
bitvec_write_field(dest, wp, 1, 1); // BEGINNING_OF_WINDOW
bitvec_write_field(dest, wp, 1, 1); // END_OF_WINDOW
bitvec_write_field(dest, wp, 0x1, 11); // STARTING_SEQUENCE_NUMBER
bitvec_write_field(dest, wp, 1, 1); // CRBB_Exist
bitvec_write_field(dest, wp, 10, 7); // CRBB_LENGTH
bitvec_write_field(dest, wp, 1, 1);
bitvec_write_field(dest, wp, 0x73, 8);
bitvec_write_field(dest, wp, 0x35, 8);
bitvec_write_field(dest, wp, 0, 8);//URBB_LENGTH
num_bytes = bitvec_pack(dest, &buf[0]);
OSMO_ASSERT(size_t(num_bytes) < sizeof(buf));
bitvec_free(dest);
the_bts->set_current_block_frame_number(fn, 0);
pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no];
pdch->rcv_block(&buf[0], num_bytes, fn, &meas);
}
static void send_ul_mac_block(BTS *the_bts, unsigned trx_no, unsigned ts_no,
RlcMacUplink_t *ulreq, unsigned fn)
{
bitvec *rlc_block;
// uint8_t rlc_block[128];
uint8_t buf[64];
int num_bytes;
struct gprs_rlcmac_pdch *pdch;
struct pcu_l1_meas meas;
meas.set_rssi(31);
rlc_block = bitvec_alloc(23);
encode_gsm_rlcmac_uplink(rlc_block, ulreq);
num_bytes = bitvec_pack(rlc_block, &buf[0]);
OSMO_ASSERT(size_t(num_bytes) < sizeof(buf));
bitvec_free(rlc_block);
the_bts->set_current_block_frame_number(fn, 0);
pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no];
pdch->rcv_block(&buf[0], num_bytes, fn, &meas);
}
static void send_egprs_control_ack(gprs_rlcmac_tbf *tbf)
{
RlcMacUplink_t ulreq = {0};
OSMO_ASSERT(tbf->poll_fn != 0);
ulreq.u.MESSAGE_TYPE = MT_EGPRS_PACKET_DOWNLINK_ACK_NACK ;
EGPRS_PD_AckNack_t *Egprs_ackNack =
&ulreq.u.Egprs_Packet_Downlink_Ack_Nack;
Egprs_ackNack->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
Egprs_ackNack->DOWNLINK_TFI = tbf->tfi();
Egprs_ackNack->Exist_EGPRS_ChannelQualityReport = 0;
Egprs_ackNack->Exist_ChannelRequestDescription = 0;
Egprs_ackNack->Exist_PFI = 0;
Egprs_ackNack->Exist_ExtensionBits = 0;
//Egprs_ackNack->u.EGPRS_AckNack.UnionType = 0;
Egprs_ackNack->u.EGPRS_AckNack.Desc.FINAL_ACK_INDICATION = 0;
Egprs_ackNack->u.EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER = 10;
Egprs_ackNack->u.EGPRS_AckNack.Desc.BEGINNING_OF_WINDOW = 1 ;
Egprs_ackNack->u.EGPRS_AckNack.Desc.END_OF_WINDOW = 1 ;
Egprs_ackNack->u.EGPRS_AckNack.Desc.Exist_CRBB = 0 ;
Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB_LENGTH = 0x1 ;
send_ul_mac_block(tbf->bts, tbf->trx->trx_no, tbf->control_ts,
&ulreq, tbf->poll_fn);
}
static void send_egprs_pack_dl_acknack1(gprs_rlcmac_tbf *tbf)
{
RlcMacUplink_t ulreq = {0};
OSMO_ASSERT(tbf->poll_fn != 0);
ulreq.u.MESSAGE_TYPE = MT_EGPRS_PACKET_DOWNLINK_ACK_NACK ;
EGPRS_PD_AckNack_t *Egprs_ackNack =
&ulreq.u.Egprs_Packet_Downlink_Ack_Nack;
send_ul_mac_block_PDAN(tbf->bts, tbf->trx->trx_no, tbf->control_ts,
&ulreq, tbf->poll_fn);
}
static void send_egprs_pack_dl_acknack2(gprs_rlcmac_tbf *tbf)
{
RlcMacUplink_t ulreq = {0};
OSMO_ASSERT(tbf->poll_fn != 0);
ulreq.u.MESSAGE_TYPE = MT_EGPRS_PACKET_DOWNLINK_ACK_NACK ;
EGPRS_PD_AckNack_t *Egprs_ackNack =
&ulreq.u.Egprs_Packet_Downlink_Ack_Nack;
Egprs_ackNack->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
Egprs_ackNack->DOWNLINK_TFI = tbf->tfi();
Egprs_ackNack->Exist_EGPRS_ChannelQualityReport = 1;
Egprs_ackNack->EGPRS_ChannelQualityReport.EGPRS_BEP_LinkQualityMeasurements.Exist_MEAN_CV_BEP_GMSK = 1;
Egprs_ackNack->EGPRS_ChannelQualityReport.EGPRS_BEP_LinkQualityMeasurements.MEAN_BEP_GMSK = 10;
Egprs_ackNack->EGPRS_ChannelQualityReport.EGPRS_BEP_LinkQualityMeasurements.CV_BEP_GMSK = 5;
Egprs_ackNack->EGPRS_ChannelQualityReport.EGPRS_BEP_LinkQualityMeasurements.Exist_MEAN_CV_BEP_8PSK = 0;
Egprs_ackNack->EGPRS_ChannelQualityReport.C_VALUE = 10;
Egprs_ackNack->EGPRS_ChannelQualityReport.EGPRS_TimeslotLinkQualityMeasurements.Exist_BEP_MEASUREMENTS = 0;
Egprs_ackNack->EGPRS_ChannelQualityReport.EGPRS_TimeslotLinkQualityMeasurements.Exist_INTERFERENCE_MEASUREMENTS = 0;
Egprs_ackNack->Exist_ChannelRequestDescription = 0;
Egprs_ackNack->Exist_PFI = 0;
Egprs_ackNack->Exist_ExtensionBits = 0;
Egprs_ackNack->UnionType = 0;
Egprs_ackNack->u.EGPRS_AckNack.Desc.FINAL_ACK_INDICATION = 0;
Egprs_ackNack->u.EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER = 1;
Egprs_ackNack->u.EGPRS_AckNack.Desc.BEGINNING_OF_WINDOW = 1 ;
Egprs_ackNack->u.EGPRS_AckNack.Desc.END_OF_WINDOW = 1 ;
Egprs_ackNack->u.EGPRS_AckNack.Desc.Exist_CRBB = 1 ;
Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB_LENGTH = 8;
Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB_STARTING_COLOR_CODE = 0;
Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB[0] = 0x2E;
Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB_LENGTH = 10;
memset(Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB,0,42);
send_ul_mac_block(tbf->bts, tbf->trx->trx_no, tbf->control_ts,
&ulreq, tbf->poll_fn);
}
static void send_egprs_pack_dl_acknack3(gprs_rlcmac_tbf *tbf)
{
RlcMacUplink_t ulreq = {0};
OSMO_ASSERT(tbf->poll_fn != 0);
ulreq.u.MESSAGE_TYPE = MT_EGPRS_PACKET_DOWNLINK_ACK_NACK ;
EGPRS_PD_AckNack_t *Egprs_ackNack =
&ulreq.u.Egprs_Packet_Downlink_Ack_Nack;
Egprs_ackNack->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
Egprs_ackNack->DOWNLINK_TFI = tbf->tfi();
Egprs_ackNack->Exist_EGPRS_ChannelQualityReport = 0;
Egprs_ackNack->Exist_ChannelRequestDescription = 0;
Egprs_ackNack->Exist_PFI = 0;
Egprs_ackNack->Exist_ExtensionBits = 0;
Egprs_ackNack->UnionType = 0;
Egprs_ackNack->u.EGPRS_AckNack.Desc.FINAL_ACK_INDICATION = 0;
Egprs_ackNack->u.EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER = 10;
Egprs_ackNack->u.EGPRS_AckNack.Desc.BEGINNING_OF_WINDOW = 1 ;
Egprs_ackNack->u.EGPRS_AckNack.Desc.END_OF_WINDOW = 1 ;
Egprs_ackNack->u.EGPRS_AckNack.Desc.Exist_CRBB = 1 ;
Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB_LENGTH = 10;
Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB_STARTING_COLOR_CODE = 1;
Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB[0] = 0xD9;
Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB[1] = 0xC0;
Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB_LENGTH = 40;
memset(Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB,0,42);
send_ul_mac_block(tbf->bts, tbf->trx->trx_no, tbf->control_ts,
&ulreq, tbf->poll_fn);
}
static void send_egprs_pack_dl_acknack4(gprs_rlcmac_tbf *tbf)
{
RlcMacUplink_t ulreq = {0};
OSMO_ASSERT(tbf->poll_fn != 0);
ulreq.u.MESSAGE_TYPE = MT_EGPRS_PACKET_DOWNLINK_ACK_NACK ;
EGPRS_PD_AckNack_t *Egprs_ackNack =
&ulreq.u.Egprs_Packet_Downlink_Ack_Nack;
Egprs_ackNack->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
Egprs_ackNack->DOWNLINK_TFI = tbf->tfi();
Egprs_ackNack->Exist_EGPRS_ChannelQualityReport = 0;
Egprs_ackNack->Exist_ChannelRequestDescription = 0;
Egprs_ackNack->Exist_PFI = 0;
Egprs_ackNack->Exist_ExtensionBits = 0;
Egprs_ackNack->UnionType = 0;
Egprs_ackNack->u.EGPRS_AckNack.Desc.FINAL_ACK_INDICATION = 0;
Egprs_ackNack->u.EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER = 20;
Egprs_ackNack->u.EGPRS_AckNack.Desc.BEGINNING_OF_WINDOW = 1 ;
Egprs_ackNack->u.EGPRS_AckNack.Desc.END_OF_WINDOW = 1 ;
Egprs_ackNack->u.EGPRS_AckNack.Desc.Exist_CRBB = 1 ;
Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB_LENGTH = 16;
Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB_STARTING_COLOR_CODE = 0;
Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB[0] = 0x03;
Egprs_ackNack->u.EGPRS_AckNack.Desc.CRBB[1] = 0xC4;
Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB_LENGTH = 40;
memset(Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB,0,42);
send_ul_mac_block(tbf->bts, tbf->trx->trx_no, tbf->control_ts,
&ulreq, tbf->poll_fn);
}
static void send_control_ack(gprs_rlcmac_tbf *tbf)
{
RlcMacUplink_t ulreq = {0};
OSMO_ASSERT(tbf->poll_fn != 0);
ulreq.u.MESSAGE_TYPE = MT_PACKET_CONTROL_ACK;
Packet_Control_Acknowledgement_t *ctrl_ack =
&ulreq.u.Packet_Control_Acknowledgement;
ctrl_ack->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
ctrl_ack->TLLI = tbf->tlli();
send_ul_mac_block(tbf->bts, tbf->trx->trx_no, tbf->control_ts,
&ulreq, tbf->poll_fn);
}
static void check_tbf(gprs_rlcmac_tbf *tbf)
{
OSMO_ASSERT(tbf);
if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE))
OSMO_ASSERT(tbf->T == 3191 || tbf->T == 3193);
if (tbf->state_is(GPRS_RLCMAC_RELEASING))
OSMO_ASSERT(tbf->T != 0);
}
static void request_dl_rlc_block(struct gprs_rlcmac_tbf *tbf,
uint32_t *fn, uint8_t *block_nr = NULL)
{
request_dl_rlc_block(tbf->bts->bts_data(), tbf->trx->trx_no,
tbf->control_ts, tbf->trx->arfcn, fn, block_nr);
}
void send_dl_data(BTS *the_bts, uint32_t tlli, const char *imsi,
const uint8_t *data, unsigned data_size)
{
GprsMs *ms, *ms2;
ms = the_bts->ms_store().get_ms(tlli, 0, imsi);
gprs_rlcmac_dl_tbf::handle(the_bts->bts_data(), tlli, 0, imsi, 0, 0,
1000, data, data_size);
ms = the_bts->ms_by_imsi(imsi);
OSMO_ASSERT(ms != NULL);
OSMO_ASSERT(ms->dl_tbf() != NULL);
if (imsi[0] && strcmp(imsi, "000") != 0) {
ms2 = the_bts->ms_by_tlli(tlli);
OSMO_ASSERT(ms == ms2);
}
}
static gprs_rlcmac_dl_tbf *create_dl_tbf(BTS *the_bts, uint8_t ms_class,
uint8_t *trx_no_)
{
gprs_rlcmac_bts *bts;
int tfi;
uint8_t trx_no;
gprs_rlcmac_dl_tbf *dl_tbf;
bts = the_bts->bts_data();
tfi = the_bts->tfi_find_free(GPRS_RLCMAC_DL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0);
dl_tbf = tbf_alloc_dl_tbf(bts, NULL, trx_no, ms_class, ms_class, 1);
check_tbf(dl_tbf);
/* "Establish" the DL TBF */
dl_tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_SEND_ASS;
dl_tbf->set_state(GPRS_RLCMAC_FLOW);
dl_tbf->m_wait_confirm = 0;
check_tbf(dl_tbf);
*trx_no_ = trx_no;
return dl_tbf;
}
static void setup_bts(BTS *the_bts, uint8_t ts_no, uint8_t cs = 1)
{
gprs_rlcmac_bts *bts;
gprs_rlcmac_trx *trx;
bts = the_bts->bts_data();
bts->egprs_enabled = true;
bts->alloc_algorithm = alloc_algorithm_a;
bts->initial_cs_dl = cs;
bts->initial_cs_ul = cs;
trx = &bts->trx[0];
trx->pdch[ts_no].enable();
}
static void test_tbf_final_ack(enum test_tbf_final_ack_mode test_mode)
{
BTS the_bts;
uint8_t ts_no = 4;
unsigned i;
uint8_t ms_class = 4;
uint32_t fn;
uint8_t block_nr;
uint8_t trx_no;
GprsMs *ms;
uint32_t tlli = 0xffeeddcc;
uint8_t rbb[64/8];
gprs_rlcmac_dl_tbf *dl_tbf;
gprs_rlcmac_tbf *new_tbf;
setup_bts(&the_bts, ts_no , 12);
dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no);
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
ms = dl_tbf->ms();
for (i = 0; i < sizeof(llc_data); i++)
llc_data[i] = i%256;
/* Schedule two LLC frames */
dl_tbf->append_data(ms_class, 2000, llc_data, 25);
dl_tbf->append_data(ms_class, 2000, llc_data, 200);
/* Send only a few RLC/MAC blocks */
fn = 0;
int index = 0;
do {
static int xxx = 0;
/* Request to send one block */
request_dl_rlc_block(dl_tbf, &fn, &block_nr);
index ++;
} while (index < 25);
//send_egprs_control_ack(dl_tbf);
}
static void test_tbf_final_ack_EPDAN(enum test_tbf_final_ack_mode test_mode)
{
BTS the_bts;
uint8_t ts_no = 4;
unsigned i;
uint8_t ms_class = 4;
uint32_t fn;
uint8_t block_nr;
uint8_t trx_no;
GprsMs *ms;
uint32_t tlli = 0xffeeddcc;
// uint8_t rbb[64/8];
printf("=== start %s ===\n", __func__);
gprs_rlcmac_dl_tbf *dl_tbf;
gprs_rlcmac_tbf *new_tbf;
setup_bts(&the_bts, ts_no , 12);
dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no);
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
ms = dl_tbf->ms();
for (i = 0; i < sizeof(llc_data); i++)
llc_data[i] = i%256;
/* Schedule two LLC frames */
dl_tbf->append_data(ms_class, 2000, llc_data, 150);
dl_tbf->append_data(ms_class, 2000, llc_data, 100);
dl_tbf->append_data(ms_class, 2000, llc_data, 100);
dl_tbf->append_data(ms_class, 2000, llc_data, 100);
dl_tbf->append_data(ms_class, 2000, llc_data, 100);
dl_tbf->append_data(ms_class, 2000, llc_data, 100);
/* Send only a few RLC/MAC blocks */
fn = 0;
int index = 0;
do {
/* Request to send one block */
request_dl_rlc_block(dl_tbf, &fn, &block_nr);
index ++;
} while (index < 50);
send_egprs_pack_dl_acknack1(dl_tbf);
index = 0;
do {
/* Request to send one block */
request_dl_rlc_block(dl_tbf, &fn, &block_nr);
index ++;
} while (index < 25);
send_egprs_pack_dl_acknack2(dl_tbf);
index = 0;
do {
/* Request to send one block */
request_dl_rlc_block(dl_tbf, &fn, &block_nr);
index ++;
} while (index < 25);
send_egprs_pack_dl_acknack3(dl_tbf);
index = 0;
do {
/* Request to send one block */
request_dl_rlc_block(dl_tbf, &fn, &block_nr);
index ++;
} while (index < 25);
send_egprs_pack_dl_acknack4(dl_tbf);
printf("=== end %s ===\n", __func__);
}
static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase(BTS *the_bts,
uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
uint8_t ms_class)
{
GprsMs *ms;
uint32_t rach_fn = *fn - 51;
uint32_t sba_fn = *fn + 52;
uint8_t trx_no = 0;
int tfi = 0;
gprs_rlcmac_ul_tbf *ul_tbf;
struct gprs_rlcmac_pdch *pdch;
gprs_rlcmac_bts *bts;
RlcMacUplink_t ulreq = {0};
struct pcu_l1_meas meas;
meas.set_rssi(31);
bts = the_bts->bts_data();
/* needed to set last_rts_fn in the PDCH object */
request_dl_rlc_block(bts, trx_no, ts_no, 0, fn);
/* simulate RACH, this sends an Immediate Assignment Uplink on the AGCH */
the_bts->rcv_rach(0x73, rach_fn, qta);
/* get next free TFI */
tfi = the_bts->tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
/* fake a resource request */
ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST;
ulreq.u.Packet_Resource_Request.PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
ulreq.u.Packet_Resource_Request.ID.UnionType = 1; /* != 0 */
ulreq.u.Packet_Resource_Request.ID.u.TLLI = tlli;
ulreq.u.Packet_Resource_Request.Exist_MS_Radio_Access_capability = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
Count_MS_RA_capability_value = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Exist_Multislot_capability = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Multislot_capability.
Exist_GPRS_multislot_class = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Multislot_capability.
GPRS_multislot_class = ms_class;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Multislot_capability.
Exist_EGPRS_multislot_class = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Multislot_capability.
EGPRS_multislot_class = ms_class;
send_ul_mac_block(the_bts, trx_no, ts_no, &ulreq, sba_fn);
/* check the TBF */
ul_tbf = the_bts->ul_tbf_by_tfi(tfi, trx_no, ts_no);
OSMO_ASSERT(ul_tbf != NULL);
OSMO_ASSERT(ul_tbf->ta() == qta / 4);
/* send packet uplink assignment */
*fn = sba_fn;
request_dl_rlc_block(ul_tbf, fn);
/* send real acknowledgement */
send_control_ack(ul_tbf);
check_tbf(ul_tbf);
uint8_t data_msg[27] = {0};
/* send fake data */
data_msg[0] = 0x00 | 0xf << 2;
data_msg[1] = uint8_t(0 | (tfi << 1));
data_msg[2] = uint8_t(0);/* BSN:7, E:1 */
data_msg[3] =uint8_t(0); /* BSN:7, E:1 */
data_msg[4] = uint8_t(1); /* E: 1 */
pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no];
pdch->rcv_block(&data_msg[0], sizeof(data_msg), *fn, &meas);
ms = the_bts->ms_by_tlli(tlli);
OSMO_ASSERT(ms != NULL);
OSMO_ASSERT(ms->ta() == qta/4);
OSMO_ASSERT(ms->ul_tbf() == ul_tbf);
return ul_tbf;
}
static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_cv0(BTS *the_bts,
uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
uint8_t ms_class)
{
GprsMs *ms;
uint32_t rach_fn = *fn - 51;
uint32_t sba_fn = *fn + 52;
uint8_t trx_no = 0;
int tfi = 0;
gprs_rlcmac_ul_tbf *ul_tbf;
struct gprs_rlcmac_pdch *pdch;
gprs_rlcmac_bts *bts;
RlcMacUplink_t ulreq = {0};
struct pcu_l1_meas meas;
meas.set_rssi(31);
bts = the_bts->bts_data();
/* needed to set last_rts_fn in the PDCH object */
request_dl_rlc_block(bts, trx_no, ts_no, 0, fn);
/* simulate RACH, this sends an Immediate Assignment Uplink on the AGCH */
the_bts->rcv_rach(0x73, rach_fn, qta);
/* get next free TFI */
tfi = the_bts->tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
/* fake a resource request */
ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST;
ulreq.u.Packet_Resource_Request.PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
ulreq.u.Packet_Resource_Request.ID.UnionType = 1; /* != 0 */
ulreq.u.Packet_Resource_Request.ID.u.TLLI = tlli;
ulreq.u.Packet_Resource_Request.Exist_MS_Radio_Access_capability = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
Count_MS_RA_capability_value = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Exist_Multislot_capability = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Multislot_capability.
Exist_GPRS_multislot_class = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Multislot_capability.
GPRS_multislot_class = ms_class;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Multislot_capability.
Exist_EGPRS_multislot_class = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Multislot_capability.
EGPRS_multislot_class = ms_class;
send_ul_mac_block(the_bts, trx_no, ts_no, &ulreq, sba_fn);
/* check the TBF */
ul_tbf = the_bts->ul_tbf_by_tfi(tfi, trx_no, ts_no);
OSMO_ASSERT(ul_tbf != NULL);
OSMO_ASSERT(ul_tbf->ta() == qta / 4);
/* send packet uplink assignment */
*fn = sba_fn;
request_dl_rlc_block(ul_tbf, fn);
/* send real acknowledgement */
send_control_ack(ul_tbf);
check_tbf(ul_tbf);
/* send fake data with cv=0*/
struct gprs_rlc_ul_header_egprs_1 *hdr1 = NULL;
uint8_t data[42] = {0};
hdr1 = (struct gprs_rlc_ul_header_egprs_1 *)data;
/*header_construction */
memset(data, 0x2b, sizeof(data));
for (int i =0 ; i< 100; i++) {
hdr1 -> r = 0;
hdr1 -> si = 0;
hdr1 -> cv = 10;
hdr1 -> tfi_a = (tfi >> 3) & 0x3;
hdr1 -> tfi_b = tfi & 0x7;
hdr1 -> bsn1_a = ((i+1)&0x1f)*2;
hdr1 -> bsn1_b = (i+1)/32;
hdr1 -> rsb = 0;
hdr1 -> pi = 0;
hdr1 -> spare = 1;
hdr1 -> dummy = 1;
data[4] = 0x0;
data[5] = 0x2b;
data[6] = 0x2b;
data[7] = 0x2b;
pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no];
pdch->rcv_block(&data[0], sizeof(data), *fn, &meas);
//request_dl_rlc_block(ul_tbf, fn);
}
memset(data, 0x2b, sizeof(data));
hdr1 = (struct gprs_rlc_ul_header_egprs_1 *)data;
hdr1 -> r = 0;
hdr1 -> si = 0;
hdr1 -> cv = 15;
hdr1 -> tfi_a = (tfi >> 3) & 0x3;
hdr1 -> tfi_b = tfi & 0x7;
hdr1 -> bsn1_a = 0;
hdr1 -> bsn1_b = 2;
hdr1 -> rsb = 0;
hdr1 -> pi = 0;
hdr1 -> spare = 1;
hdr1 -> dummy = 1;
data[4] = 0x0;
data[5] = 0x2b;
data[6] = 0x2b;
data[7] = 0x2b;
pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no];
pdch->rcv_block(&data[0], sizeof(data), *fn, &meas);
request_dl_rlc_block(ul_tbf, fn);
ms = the_bts->ms_by_tlli(tlli);
OSMO_ASSERT(ms != NULL);
OSMO_ASSERT(ms->ta() == qta/4);
OSMO_ASSERT(ms->ul_tbf() == ul_tbf);
return ul_tbf;
}
void test_tbf_two_phase()
{
BTS the_bts;
int ts_no = 7;
uint32_t fn = 2654218;
uint16_t qta = 31;
uint32_t tlli = 0xf1223344;
const char *imsi = "0011223344";
uint8_t ms_class = 1;
gprs_rlcmac_ul_tbf *ul_tbf;
GprsMs *ms;
printf("=== start %s ===\n", __func__);
setup_bts(&the_bts, ts_no, 9);
ul_tbf = establish_ul_tbf_two_phase(&the_bts, ts_no, tlli, &fn, qta, ms_class);
ms = ul_tbf->ms();
fprintf(stderr, "Got '%s', TA=%d\n", ul_tbf->name(), ul_tbf->ta());
fprintf(stderr, "Got MS: TLLI = 0x%08x, TA = %d\n", ms->tlli(), ms->ta());
send_dl_data(&the_bts, tlli, imsi, (const uint8_t *)"TEST", 4);
send_dl_data(&the_bts, tlli, imsi, (const uint8_t *)"TEST", 4);
/* Send Packet Downlink Assignment to MS */
request_dl_rlc_block(ul_tbf, &fn);
printf("=== end %s ===\n", __func__);
}
void test_tbf_two_phase_PUAN()
{
BTS the_bts;
int ts_no = 7;
uint32_t fn = 2654218;
uint16_t qta = 31;
uint32_t tlli = 0xf1223344;
const char *imsi = "0011223344";
uint8_t ms_class = 1;
gprs_rlcmac_ul_tbf *ul_tbf;
GprsMs *ms;
printf("=== start %s ===\n", __func__);
setup_bts(&the_bts, ts_no, 7);
ul_tbf = establish_ul_tbf_two_phase_cv0(&the_bts, ts_no, tlli, &fn, qta, ms_class);
ms = ul_tbf->ms();
fprintf(stderr, "Got '%s', TA=%d\n", ul_tbf->name(), ul_tbf->ta());
fprintf(stderr, "Got MS: TLLI = 0x%08x, TA = %d\n", ms->tlli(), ms->ta());
send_dl_data(&the_bts, tlli, imsi, (const uint8_t *)"TEST", 4);
send_dl_data(&the_bts, tlli, imsi, (const uint8_t *)"TEST", 4);
/* Send Packet Downlink Assignment to MS */
// request_dl_rlc_block(ul_tbf, &fn);
printf("=== end %s ===\n", __func__);
}
int pcu_sock_send(struct msgb *msg)
{
struct gsm_pcu_if *pcu_prim;
struct gsm_pcu_if_data *data_req;
pcu_prim = (struct gsm_pcu_if *) msg->data;
data_req = &pcu_prim->u.data_req;
uint32_t bsn_val = 0, bsn_val1 = 0;
struct gprs_rlc_dl_header_egprs_3 *header3 = NULL;
struct gprs_rlc_dl_header_egprs_2 *header2 = NULL;
struct gprs_rlc_dl_header_egprs_1 *header1 = NULL;
if( data_req->len != 23 ) {
if(data_req -> len == 61 || data_req -> len == 79 ) {
header2 = (struct gprs_rlc_dl_header_egprs_2 *) data_req ->data ;
bsn_val = ((header2 ->bsn_a));
bsn_val = (bsn_val | ((header2 -> bsn_b) << 2));
bsn_val = (bsn_val | ((header2-> bsn_c ) << 10));
LOGP(DRLCMACDL, LOGL_DEBUG,"------------------header type 2 decode-------------- \n");
LOGP(DRLCMACDL, LOGL_DEBUG, "length %d \n ",data_req -> len );
LOGP(DRLCMACDL, LOGL_DEBUG, "usf :%d \n es :%d\n rrbp: %d \n tfi1:%d\n tfi2:%d\n bsn1:%d \n bsn2:%d \n bsn3:%d\n",
header2 ->usf, header2 -> es_p, header2 -> rrbp, header2 -> tfi_a, header2 ->tfi_b, header2->bsn_a,
header2->bsn_b, header2->bsn_c);
LOGP(DRLCMACDL, LOGL_DEBUG," pr: %d cps:%d ", header2 -> pr, header2 ->cps);
LOGP(DRLCMACDL, LOGL_DEBUG,"bsn_val: %d \n", bsn_val);
} else if (data_req -> len == 119 || data_req -> len == 143 || data_req -> len == 155 ) {
header1 = (struct gprs_rlc_dl_header_egprs_1 *) data_req -> data ;
bsn_val = (header1 -> bsn1_a);
bsn_val = (bsn_val | ((header1 -> bsn1_b)<< 2));
bsn_val = (bsn_val | ((header1 -> bsn1_c) << 10));
bsn_val1 = (bsn_val1 | (header1 -> bsn2_a));
bsn_val1 = (bsn_val1 | ((header1 -> bsn2_b) << 7));
LOGP(DRLCMACDL, LOGL_DEBUG,"------------------header type 1 decode-------------- \n");
LOGP(DRLCMACDL, LOGL_DEBUG,"length %d \n ",data_req -> len );
LOGP(DRLCMACDL, LOGL_DEBUG,"usf :%d \n es :%d\n rrbp: %d \n tfi1:%d\n tfi2:%d\n bsn1a:%d \n bsn1b:%d \n bsn1c:%d\n"
"bsn2a:%d\n bsn2b:%d\n ",
header1 ->usf, header1 -> es_p, header1 -> rrbp, header1 -> tfi_a, header1 ->tfi_b, header1->bsn1_a,
header1->bsn1_b, header1->bsn1_c, header1->bsn2_a, header1->bsn2_b);
LOGP(DRLCMACDL, LOGL_DEBUG," pr: %d cps:%d ", header1 -> pr, header1 ->cps);
LOGP(DRLCMACDL, LOGL_DEBUG,"bsn_1: %d \n bsn_2:%d \n", bsn_val, bsn_val1);
} else if(data_req -> len == 27 || data_req -> len == 33 || data_req -> len == 42 || data_req ->len == 49 ) {
header3 = (struct gprs_rlc_dl_header_egprs_3 *) data_req -> data;
bsn_val = ((header3 ->bsn_a));
bsn_val = (bsn_val | ((header3 -> bsn_b) << 2));
bsn_val = (bsn_val | ((header3->bsn_c ) << 10));
LOGP(DRLCMACDL, LOGL_DEBUG,"------------------header type 3 decode-------------- \n");
LOGP(DRLCMACDL, LOGL_DEBUG,"length %d \n ",data_req -> len );
LOGP(DRLCMACDL, LOGL_DEBUG,"usf :%d \n es :%d\n rrbp: %d \n tfi1:%d\n tfi2:%d\n bsn1:%d \n bsn2:%d \n"
"bsn3:%d\n spb:%d \n",header3 ->usf, header3 -> es_p, header3 -> rrbp, header3 -> tfi_a, header3 ->tfi_b,
header3->bsn_a,header3->bsn_b, header3->bsn_c, header3 ->spb);
LOGP(DRLCMACDL, LOGL_DEBUG," pr: %d cps:%d ", header3 -> pr, header3 ->cps);
LOGP(DRLCMACDL, LOGL_DEBUG,"bsn_val: %d \n", bsn_val);
} else {
LOGP(DRLCMACDL, LOGL_DEBUG,"block with size received %d \n ", data_req -> len);
}
}
return 0;
}
static gprs_rlcmac_ul_tbf *establish_ul_tbf_two_phase_header(BTS *the_bts,
uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
uint8_t ms_class)
{
GprsMs *ms;
uint32_t rach_fn = *fn - 51;
uint32_t sba_fn = *fn + 52;
uint8_t trx_no = 0;
int tfi = 0;
gprs_rlcmac_ul_tbf *ul_tbf;
struct gprs_rlcmac_pdch *pdch;
gprs_rlcmac_bts *bts;
RlcMacUplink_t ulreq = {0};
struct pcu_l1_meas meas;
meas.set_rssi(31);
uint8_t data_buf[156] = {0};
uint8_t data[144] = {0};
struct gprs_rlc_ul_header_egprs_1_test *egprs1 = NULL;
egprs1 = (struct gprs_rlc_ul_header_egprs_1_test *) data;
struct gprs_rlc_ul_header_egprs_2_test *egprs2 = NULL;
bts = the_bts->bts_data();
/* needed to set last_rts_fn in the PDCH object */
request_dl_rlc_block(bts, trx_no, ts_no, 0, fn);
/* simulate RACH, this sends an Immediate Assignment Uplink on the AGCH */
the_bts->rcv_rach(0x73, rach_fn, qta);
/* get next free TFI */
tfi = the_bts->tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
/* fake a resource request */
ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST;
ulreq.u.Packet_Resource_Request.PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
ulreq.u.Packet_Resource_Request.ID.UnionType = 1; /* != 0 */
ulreq.u.Packet_Resource_Request.ID.u.TLLI = tlli;
ulreq.u.Packet_Resource_Request.Exist_MS_Radio_Access_capability = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
Count_MS_RA_capability_value = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Exist_Multislot_capability = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Multislot_capability.
Exist_GPRS_multislot_class = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Multislot_capability.
GPRS_multislot_class = ms_class;
send_ul_mac_block(the_bts, trx_no, ts_no, &ulreq, sba_fn);
/* check the TBF */
ul_tbf = the_bts->ul_tbf_by_tfi(tfi, trx_no, ts_no);
OSMO_ASSERT(ul_tbf != NULL);
OSMO_ASSERT(ul_tbf->ta() == qta / 4);
egprs1 -> si = 1;
egprs1 -> r = 1;
egprs1 -> cv = 7;
egprs1 -> tfi_a = tfi & (~((~0) << 2 ));
egprs1 -> tfi_b = tfi & (~((~0) << 3 )) << 2; ;
egprs1 -> bsn1_a = 10;
egprs1 -> bsn1_b = 17;
egprs1 -> bsn2_a = 0;
egprs1 -> bsn2_b = 25;
egprs1 -> cps = 15;
egprs1 -> rsb = 1;
egprs1 -> pi = 0;
egprs1 -> spare = 1;
egprs1 -> spare2 = 10;
egprs1 -> dummy = 2;
egprs1 -> e1 = 0;
egprs1 -> ti1 = 1;
egprs1 -> dummy1 = 2;
egprs1 -> e2 = 1;
egprs1 -> length1 = 40;
egprs1 -> e3 = 0;
egprs1 -> ti2 = 1;
egprs1 -> dummy2 = 2;
egprs1 -> e4 = 1;
egprs1 -> length2 = 33;
pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no];
pdch->rcv_block(&data[0], 144, *fn, &meas);
egprs2 = (struct gprs_rlc_ul_header_egprs_2_test *) data_buf;
egprs2 -> si = 1;
egprs2 -> r = 1;
egprs2 -> cv = 7;
egprs2 -> tfi_a = tfi >> 3;
egprs2 -> tfi_b = (tfi & 0x7);
egprs2 -> bsn1_a = 14;
egprs2 -> bsn1_b = 21;
egprs2 -> bsn2_a = 3;
egprs2 -> bsn2_b = 29;
egprs2 -> cps = 8;
egprs2 -> rsb = 1;
egprs2 -> pi = 0;
egprs2 -> spare = 1;
egprs2 -> spare2 = 10;
egprs2 -> dummy = 2;
egprs2 -> e1 = 0;
egprs2 -> ti1 = 0;
egprs2 -> dummy1 = 2;
egprs2 -> e2 = 1;
egprs2 -> length1 = 40;
egprs2 -> e3 = 0;
egprs2 -> ti2 = 1;
egprs2 -> dummy2 = 2;
egprs2 -> e4 = 1;
egprs2 -> length2 = 33;
pdch->rcv_block(&data_buf[0], 156, *fn, &meas);
}
void uplink_header_type1_test()
{
BTS the_bts;
int ts_no = 7;
uint32_t fn = 2654218;
uint16_t qta = 31;
uint32_t tlli = 0xf1223344;
const char *imsi = "0011223344";
uint8_t ms_class = 1;
gprs_rlcmac_ul_tbf *ul_tbf;
GprsMs *ms;
printf("=== start %s ===\n", __func__);
setup_bts(&the_bts, ts_no, 9);
ul_tbf = establish_ul_tbf_two_phase_header(&the_bts, ts_no, tlli, &fn, qta, ms_class);
}
void test_downlink_for_all_mcs(enum test_tbf_final_ack_mode test_mode, uint8_t mcs)
{
BTS the_bts;
uint8_t ts_no = 4;
unsigned i;
uint8_t ms_class = 4;
uint32_t fn;
uint8_t block_nr;
uint8_t trx_no;
GprsMs *ms;
uint32_t tlli = 0xffeeddcc;
uint8_t rbb[64/8];
gprs_rlcmac_dl_tbf *dl_tbf;
gprs_rlcmac_tbf *new_tbf;
printf("=== start %s ===\n", __func__);
setup_bts(&the_bts, ts_no , (mcs + 5));
dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no);
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
ms = dl_tbf->ms();
for (i = 0; i < sizeof(llc_data); i++)
llc_data[i] = i%256;
/* Schedule two LLC frames */
dl_tbf->append_data(ms_class, 4000, llc_data, 200);
/* Send only a few RLC/MAC blocks */
fn = 0;
int index = 0;
do {
/* Request to send one block */
request_dl_rlc_block(dl_tbf, &fn, &block_nr);
index ++;
} while (index < 25);
printf("=== end %s ===\n", __func__);
}
static void send_egprs_control_nack_all(gprs_rlcmac_tbf *tbf)
{
RlcMacUplink_t ulreq = {0};
OSMO_ASSERT(tbf->poll_fn != 0);
ulreq.u.MESSAGE_TYPE = MT_EGPRS_PACKET_DOWNLINK_ACK_NACK ;
EGPRS_PD_AckNack_t *Egprs_ackNack =
&ulreq.u.Egprs_Packet_Downlink_Ack_Nack;
Egprs_ackNack->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
Egprs_ackNack->DOWNLINK_TFI = tbf->tfi();
Egprs_ackNack->Exist_EGPRS_ChannelQualityReport = 0;
Egprs_ackNack->Exist_ChannelRequestDescription = 0;
Egprs_ackNack->Exist_PFI = 0;
Egprs_ackNack->Exist_ExtensionBits = 0;
Egprs_ackNack->UnionType = 0;
Egprs_ackNack->u.EGPRS_AckNack.Desc.FINAL_ACK_INDICATION = 0;
Egprs_ackNack->u.EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER = 2;
Egprs_ackNack->u.EGPRS_AckNack.Desc.BEGINNING_OF_WINDOW = 1 ;
Egprs_ackNack->u.EGPRS_AckNack.Desc.END_OF_WINDOW = 1 ;
Egprs_ackNack->u.EGPRS_AckNack.Desc.Exist_CRBB = 0 ;
Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB_LENGTH = 10 ; /*Nack case*/
Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB[0] = 0;
Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB[1] = 0;
send_ul_mac_block(tbf->bts, tbf->trx->trx_no, tbf->control_ts,
&ulreq, tbf->poll_fn);
}
static void send_egprs_control_nack_and_ack(gprs_rlcmac_tbf *tbf)
{
RlcMacUplink_t ulreq = {0};
OSMO_ASSERT(tbf->poll_fn != 0);
ulreq.u.MESSAGE_TYPE = MT_EGPRS_PACKET_DOWNLINK_ACK_NACK ;
EGPRS_PD_AckNack_t *Egprs_ackNack =
&ulreq.u.Egprs_Packet_Downlink_Ack_Nack;
Egprs_ackNack->PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
Egprs_ackNack->DOWNLINK_TFI = tbf->tfi();
Egprs_ackNack->Exist_EGPRS_ChannelQualityReport = 0;
Egprs_ackNack->Exist_ChannelRequestDescription = 0;
Egprs_ackNack->Exist_PFI = 0;
Egprs_ackNack->Exist_ExtensionBits = 0;
Egprs_ackNack->UnionType = 0;
Egprs_ackNack->u.EGPRS_AckNack.Desc.FINAL_ACK_INDICATION = 0;
Egprs_ackNack->u.EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER = 2;
Egprs_ackNack->u.EGPRS_AckNack.Desc.BEGINNING_OF_WINDOW = 1 ;
Egprs_ackNack->u.EGPRS_AckNack.Desc.END_OF_WINDOW = 1 ;
Egprs_ackNack->u.EGPRS_AckNack.Desc.Exist_CRBB = 0 ;
Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB_LENGTH = 16 ; /*Nack case*/
Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB[0] = 0;
Egprs_ackNack->u.EGPRS_AckNack.Desc.URBB[2] = 0;
send_ul_mac_block(tbf->bts, tbf->trx->trx_no, tbf->control_ts,
&ulreq, tbf->poll_fn);
}
void test_downlink_retransmission_mcs5_mcs2()
{
BTS the_bts;
uint8_t ts_no = 4;
unsigned i;
uint8_t ms_class = 4;
uint32_t fn;
uint8_t block_nr;
uint8_t trx_no;
GprsMs *ms;
uint32_t tlli = 0xffeeddcc;
uint8_t rbb[64/8];
printf("=== start %s ===\n", __func__);
gprs_rlcmac_dl_tbf *dl_tbf;
gprs_rlcmac_tbf *new_tbf;
setup_bts(&the_bts, ts_no , 9);
dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no);
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
ms = dl_tbf->ms();
for (i = 0; i < sizeof(llc_data); i++)
llc_data[i] = i%256;
/* Schedule two LLC frames */
dl_tbf->append_data(ms_class, 1000, llc_data, 25);
/* Send only a few RLC/MAC blocks */
fn = 0;
int index1 = 0;
while(index1 < 4){
/* Request to send one block */
request_dl_rlc_block(dl_tbf, &fn, &block_nr);
index1 ++;
if(dl_tbf->m_window.m_v_b.is_unacked(0))
{
dl_tbf->m_window.m_v_b.mark_nacked(0);
ms->set_current_cs_dl(6);
}
}
printf("=== end %s ===\n", __func__);
}
void test_downlink_retransmission_mcs7_mcs5()
{
BTS the_bts;
uint8_t ts_no = 4;
unsigned i;
uint8_t ms_class = 4;
uint32_t fn;
uint8_t block_nr;
uint8_t trx_no;
GprsMs *ms;
uint32_t tlli = 0xffeeddcc;
uint8_t rbb[64/8];
printf("=== start %s ===\n", __func__);
gprs_rlcmac_dl_tbf *dl_tbf;
gprs_rlcmac_tbf *new_tbf;
setup_bts(&the_bts, ts_no , 11);
dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no);
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
ms = dl_tbf->ms();
for (i = 0; i < sizeof(llc_data); i++)
llc_data[i] = i%256;
/* Schedule two LLC frames */
dl_tbf->append_data(ms_class, 1000, llc_data, 100);
/* Send only a few RLC/MAC blocks */
fn = 0;
int index1 = 0;
while(index1 < 4){
/* Request to send one block */
request_dl_rlc_block(dl_tbf, &fn, &block_nr);
index1 ++;
if(dl_tbf->m_window.m_v_b.is_unacked(0))
{
dl_tbf->m_window.m_v_b.mark_nacked(0);
ms->set_current_cs_dl(9);
}
}
printf("=== end %s ===\n", __func__);
}
void test_downlink_retransmission_mcs8_mcs6_mcs3()
{
BTS the_bts;
uint8_t ts_no = 4;
unsigned i;
uint8_t ms_class = 4;
uint32_t fn;
uint8_t block_nr;
uint8_t trx_no;
GprsMs *ms;
uint32_t tlli = 0xffeeddcc;
printf("=== start %s ===\n", __func__);
uint8_t rbb[64/8];
gprs_rlcmac_dl_tbf *dl_tbf;
gprs_rlcmac_tbf *new_tbf;
setup_bts(&the_bts, ts_no , 12);
dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no);
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
ms = dl_tbf->ms();
for (i = 0; i < sizeof(llc_data); i++)
llc_data[i] = i%256;
/* Schedule two LLC frames */
dl_tbf->append_data(ms_class, 1000, llc_data, 100);
/* Send only a few RLC/MAC blocks */
fn = 0;
int index1 = 0;
bool hit_already = false;
while(index1 < 10){
/* Request to send one block */
request_dl_rlc_block(dl_tbf, &fn, &block_nr);
index1 ++;
if(dl_tbf->m_window.m_v_b.is_unacked(0) && (hit_already == false))
{
hit_already = true;
dl_tbf->m_window.m_v_b.mark_nacked(0);
ms->set_current_cs_dl(10);
}else if( hit_already == true){
ms->set_current_cs_dl(7);
}
}
printf("=== end %s ===\n", __func__);
}
void test_downlink_retransmission_mcs8_mcs6()
{
BTS the_bts;
uint8_t ts_no = 4;
unsigned i;
uint8_t ms_class = 4;
uint32_t fn;
uint8_t block_nr;
uint8_t trx_no;
GprsMs *ms;
uint32_t tlli = 0xffeeddcc;
uint8_t rbb[64/8];
printf("=== start %s ===\n", __func__);
gprs_rlcmac_dl_tbf *dl_tbf;
gprs_rlcmac_tbf *new_tbf;
setup_bts(&the_bts, ts_no , 12);
dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no);
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
ms = dl_tbf->ms();
for (i = 0; i < sizeof(llc_data); i++)
llc_data[i] = i%256;
/* Schedule two LLC frames */
dl_tbf->append_data(ms_class, 1000, llc_data, 100);
/* Send only a few RLC/MAC blocks */
fn = 0;
int index1 = 0;
while(index1 < 4){
/* Request to send one block */
request_dl_rlc_block(dl_tbf, &fn, &block_nr);
index1 ++;
if(dl_tbf->m_window.m_v_b.is_unacked(0))
{
dl_tbf->m_window.m_v_b.mark_nacked(0);
ms->set_current_cs_dl(10);
}
}
printf("=== end %s ===\n", __func__);
}
void test_downlink_retransmission_mcs9_mcs6()
{
BTS the_bts;
uint8_t ts_no = 4;
unsigned i;
uint8_t ms_class = 4;
uint32_t fn;
uint8_t block_nr;
uint8_t trx_no;
GprsMs *ms;
uint32_t tlli = 0xffeeddcc;
printf("=== start %s ===\n", __func__);
uint8_t rbb[64/8];
gprs_rlcmac_dl_tbf *dl_tbf;
gprs_rlcmac_tbf *new_tbf;
setup_bts(&the_bts, ts_no , 13);
dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no);
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
ms = dl_tbf->ms();
for (i = 0; i < sizeof(llc_data); i++)
llc_data[i] = i%256;
/* Schedule two LLC frames */
dl_tbf->append_data(ms_class, 1000, llc_data, 100);
/* Send only a few RLC/MAC blocks */
fn = 0;
int index1 = 0;
while(index1 < 4){
/* Request to send one block */
request_dl_rlc_block(dl_tbf, &fn, &block_nr);
index1 ++;
if(dl_tbf->m_window.m_v_b.is_unacked(0))
{
dl_tbf->m_window.m_v_b.mark_nacked(0);
ms->set_current_cs_dl(10);
}
}
printf("=== end %s ===\n", __func__);
}
void test_downlink_retransmission_mcs4_mcs1()
{
BTS the_bts;
uint8_t ts_no = 4;
unsigned i;
uint8_t ms_class = 4;
uint32_t fn;
uint8_t block_nr;
uint8_t trx_no;
GprsMs *ms;
uint32_t tlli = 0xffeeddcc;
printf("=== start %s ===\n", __func__);
uint8_t rbb[64/8];
gprs_rlcmac_dl_tbf *dl_tbf;
gprs_rlcmac_tbf *new_tbf;
setup_bts(&the_bts, ts_no , 8);
dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no);
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
ms = dl_tbf->ms();
for (i = 0; i < sizeof(llc_data); i++)
llc_data[i] = i%256;
/* Schedule two LLC frames */
dl_tbf->append_data(ms_class, 1000, llc_data, 25);
/* Send only a few RLC/MAC blocks */
fn = 0;
int index1 = 0;
while(index1 < 4){
/* Request to send one block */
request_dl_rlc_block(dl_tbf, &fn, &block_nr);
index1 ++;
if(dl_tbf->m_window.m_v_b.is_unacked(0))
{
dl_tbf->m_window.m_v_b.mark_nacked(0);
ms->set_current_cs_dl(5);
}
}
printf("=== end %s ===\n", __func__);
}
void test_downlink_retransmission_mcs6_mcs3()
{
BTS the_bts;
uint8_t ts_no = 4;
unsigned i;
uint8_t ms_class = 4;
uint32_t fn;
uint8_t block_nr;
uint8_t trx_no;
GprsMs *ms;
uint32_t tlli = 0xffeeddcc;
uint8_t rbb[64/8];
printf("=== start %s ===\n", __func__);
gprs_rlcmac_dl_tbf *dl_tbf;
gprs_rlcmac_tbf *new_tbf;
setup_bts(&the_bts, ts_no , 10);
dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no);
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
ms = dl_tbf->ms();
for (i = 0; i < sizeof(llc_data); i++)
llc_data[i] = i%256;
/* Schedule two LLC frames */
dl_tbf->append_data(ms_class, 1000, llc_data, 25);
/* Send only a few RLC/MAC blocks */
fn = 0;
int index1 = 0;
while(index1 < 4){
/* Request to send one block */
request_dl_rlc_block(dl_tbf, &fn, &block_nr);
index1 ++;
if(dl_tbf->m_window.m_v_b.is_unacked(0))
{
dl_tbf->m_window.m_v_b.mark_nacked(0);
ms->set_current_cs_dl(7);
}
}
printf("=== end %s ===\n", __func__);
}
void test_downlink_retransmission_mcs9_mcs3()
{
BTS the_bts;
uint8_t ts_no = 4;
unsigned i;
uint8_t ms_class = 4;
uint32_t fn;
uint8_t block_nr;
uint8_t trx_no;
GprsMs *ms;
uint32_t tlli = 0xffeeddcc;
uint8_t rbb[64/8];
printf("=== start %s ===\n", __func__);
gprs_rlcmac_dl_tbf *dl_tbf;
gprs_rlcmac_tbf *new_tbf;
setup_bts(&the_bts, ts_no , 13);
dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no);
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
ms = dl_tbf->ms();
for (i = 0; i < sizeof(llc_data); i++)
llc_data[i] = i%256;
/* Schedule two LLC frames */
dl_tbf->append_data(ms_class, 1000, llc_data, 100);
/* Send only a few RLC/MAC blocks */
fn = 0;
int index1 = 0;
while(index1 < 4){
/* Request to send one block */
request_dl_rlc_block(dl_tbf, &fn, &block_nr);
index1 ++;
if(dl_tbf->m_window.m_v_b.is_unacked(0))
{
dl_tbf->m_window.m_v_b.mark_nacked(0);
ms->set_current_cs_dl(7);
}
}
printf("=== end %s ===\n", __func__);
}
void test_downlink_retransmission_mcs8_mcs3()
{
BTS the_bts;
uint8_t ts_no = 4;
unsigned i;
uint8_t ms_class = 4;
uint32_t fn;
uint8_t block_nr;
uint8_t trx_no;
GprsMs *ms;
uint32_t tlli = 0xffeeddcc;
printf("=== start %s ===\n", __func__);
uint8_t rbb[64/8];
gprs_rlcmac_dl_tbf *dl_tbf;
gprs_rlcmac_tbf *new_tbf;
setup_bts(&the_bts, ts_no , 12);
dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no);
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
ms = dl_tbf->ms();
for (i = 0; i < sizeof(llc_data); i++)
llc_data[i] = i%256;
/* Schedule two LLC frames */
dl_tbf->append_data(ms_class, 1000, llc_data, 100);
/* Send only a few RLC/MAC blocks */
fn = 0;
int index1 = 0;
while(index1 < 4){
/* Request to send one block */
request_dl_rlc_block(dl_tbf, &fn, &block_nr);
index1 ++;
if(dl_tbf->m_window.m_v_b.is_unacked(0))
{
dl_tbf->m_window.m_v_b.mark_nacked(0);
ms->set_current_cs_dl(7);
}
}
printf("=== end %s ===\n", __func__);
}
void test_downlink_retransmission_mcs7_mcs2()
{
BTS the_bts;
uint8_t ts_no = 4;
unsigned i;
uint8_t ms_class = 4;
uint32_t fn;
uint8_t block_nr;
uint8_t trx_no;
GprsMs *ms;
uint32_t tlli = 0xffeeddcc;
uint8_t rbb[64/8];
printf("=== start %s ===\n", __func__);
gprs_rlcmac_dl_tbf *dl_tbf;
gprs_rlcmac_tbf *new_tbf;
setup_bts(&the_bts, ts_no , 11);
dl_tbf = create_dl_tbf(&the_bts, ms_class, &trx_no);
dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF);
ms = dl_tbf->ms();
for (i = 0; i < sizeof(llc_data); i++)
llc_data[i] = i%256;
/* Schedule two LLC frames */
dl_tbf->append_data(ms_class, 1000, llc_data, 100);
/* Send only a few RLC/MAC blocks */
fn = 0;
int index1 = 0;
while(index1 < 4){
/* Request to send one block */
request_dl_rlc_block(dl_tbf, &fn, &block_nr);
index1 ++;
if(dl_tbf->m_window.m_v_b.is_unacked(0))
{
dl_tbf->m_window.m_v_b.mark_nacked(0);
ms->set_current_cs_dl(6);
}
}
printf("=== end %s ===\n", __func__);
}
static gprs_rlcmac_ul_tbf *mcs8_mcs6_retx(BTS *the_bts,
uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
uint8_t ms_class)
{
GprsMs *ms;
uint32_t rach_fn = *fn - 51;
uint32_t sba_fn = *fn + 52;
uint8_t trx_no = 0;
int tfi = 0;
gprs_rlcmac_ul_tbf *ul_tbf;
struct gprs_rlcmac_pdch *pdch;
gprs_rlcmac_bts *bts;
RlcMacUplink_t ulreq = {0};
struct pcu_l1_meas meas;
meas.set_rssi(31);
uint8_t data[80] = {0} ;
bts = the_bts->bts_data();
/* needed to set last_rts_fn in the PDCH object */
request_dl_rlc_block(bts, trx_no, ts_no, 0, fn);
/* simulate RACH, this sends an Immediate Assignment Uplink on the AGCH */
the_bts->rcv_rach(0x73, rach_fn, qta);
/* get next free TFI */
tfi = the_bts->tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
/* fake a resource request */
ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST;
ulreq.u.Packet_Resource_Request.PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
ulreq.u.Packet_Resource_Request.ID.UnionType = 1; /* != 0 */
ulreq.u.Packet_Resource_Request.ID.u.TLLI = tlli;
ulreq.u.Packet_Resource_Request.Exist_MS_Radio_Access_capability = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
Count_MS_RA_capability_value = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Exist_Multislot_capability = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Multislot_capability.
Exist_GPRS_multislot_class = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Multislot_capability.
GPRS_multislot_class = ms_class;
send_ul_mac_block(the_bts, trx_no, ts_no, &ulreq, sba_fn);
/* check the TBF */
ul_tbf = the_bts->ul_tbf_by_tfi(tfi, trx_no, ts_no);
OSMO_ASSERT(ul_tbf != NULL);
OSMO_ASSERT(ul_tbf->ta() == qta / 4);
struct gprs_rlc_ul_header_egprs_2 *hdr2 = NULL;
hdr2 = (struct gprs_rlc_ul_header_egprs_2 *)data;
/*header_construction */
hdr2 -> r = 1;
hdr2 -> si = 1;
hdr2 -> cv = 8;
hdr2 -> tfi_a = (tfi >> 3) & 0x3;
hdr2 -> tfi_b = tfi & 0x7;
hdr2 -> bsn1_a = 0;
hdr2 -> bsn1_b = 0;
hdr2 -> cps_a = 2;
hdr2 -> cps_b = 0;
hdr2 -> rsb = 1;
hdr2 -> pi = 0;
data[4] = 0x2b;
data[5] = 0x2b;
data[6] = 0x2b;
data[7] = 0x2b;
data[8] = 0x2b;
data[9] = 0x2b;
data[10] = 1;
data[11] = 81; /*the li =40 and e = 1*/
pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no];
pdch->rcv_block(&data[0], 80, *fn, &meas);
}
static gprs_rlcmac_ul_tbf *spb_handler(BTS *the_bts,
uint8_t ts_no, uint32_t tlli, uint32_t *fn, uint16_t qta,
uint8_t ms_class)
{
GprsMs *ms;
uint32_t rach_fn = *fn - 51;
uint32_t sba_fn = *fn + 52;
uint8_t trx_no = 0;
int tfi = 0;
gprs_rlcmac_ul_tbf *ul_tbf;
struct gprs_rlcmac_pdch *pdch;
gprs_rlcmac_bts *bts;
RlcMacUplink_t ulreq = {0};
struct pcu_l1_meas meas;
meas.set_rssi(31);
bts = the_bts->bts_data();
/* needed to set last_rts_fn in the PDCH object */
request_dl_rlc_block(bts, trx_no, ts_no, 0, fn);
/* simulate RACH, this sends an Immediate Assignment Uplink on the AGCH */
the_bts->rcv_rach(0x73, rach_fn, qta);
/* get next free TFI */
tfi = the_bts->tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
/* fake a resource request */
ulreq.u.MESSAGE_TYPE = MT_PACKET_RESOURCE_REQUEST;
ulreq.u.Packet_Resource_Request.PayloadType = GPRS_RLCMAC_CONTROL_BLOCK;
ulreq.u.Packet_Resource_Request.ID.UnionType = 1; /* != 0 */
ulreq.u.Packet_Resource_Request.ID.u.TLLI = tlli;
ulreq.u.Packet_Resource_Request.Exist_MS_Radio_Access_capability = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
Count_MS_RA_capability_value = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Exist_Multislot_capability = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Multislot_capability.
Exist_GPRS_multislot_class = 1;
ulreq.u.Packet_Resource_Request.MS_Radio_Access_capability.
MS_RA_capability_value[0].u.Content.Multislot_capability.
GPRS_multislot_class = ms_class;
send_ul_mac_block(the_bts, trx_no, ts_no, &ulreq, sba_fn);
/* check the TBF */
ul_tbf = the_bts->ul_tbf_by_tfi(tfi, trx_no, ts_no);
OSMO_ASSERT(ul_tbf != NULL);
OSMO_ASSERT(ul_tbf->ta() == qta / 4);
struct gprs_rlc_ul_header_egprs_3 *hdr3 = NULL;
uint8_t data[42] = {0};
hdr3 = (struct gprs_rlc_ul_header_egprs_3 *)data;
/*header_construction */
hdr3 -> r = 1;
hdr3 -> si = 1;
hdr3 -> cv = 8;
hdr3 -> tfi_a = (tfi >> 3) & 0x3;
hdr3 -> tfi_b = tfi & 0x7;
hdr3 -> bsn1_a = 0;
hdr3 -> bsn1_b = 0;
hdr3 -> cps_a = 2;
hdr3 -> cps_b = 1;
hdr3 -> spb = 2 ;
hdr3 -> rsb = 1;
hdr3 -> pi = 0;
hdr3 -> spare = 1;
hdr3 -> dummy = 1;
data[4] = 0x2b;
data[5] = 0x2b;
data[6] = 0x2b;
data[7] = 0x2b;
data[8] = 0x2b;
data[9] = 0x2b;
data[10] = 1;
data[11] = 81; /*the li =40 and e = 1*/
pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no];
pdch->rcv_block(&data[0], 42, *fn, &meas);
memset(data, 0x2b , sizeof(data));
hdr3 = (struct gprs_rlc_ul_header_egprs_3 * )data;
hdr3 -> r = 1;
hdr3 -> si = 1;
hdr3 -> cv = 8;
hdr3 -> tfi_a = (tfi >> 3) & 0x3;
hdr3 -> tfi_b = tfi & 0x7;
hdr3 -> bsn1_a = 0;
hdr3 -> bsn1_b = 0;
hdr3 -> cps_a = 3;
hdr3 -> cps_b = 0;
hdr3 -> spb =3;
hdr3 -> rsb = 1;
hdr3 -> pi = 0;
hdr3 -> spare = 1;
hdr3 -> dummy = 1;
data[4] = 1;
pdch = &the_bts->bts_data()->trx[trx_no].pdch[ts_no];
pdch->rcv_block(&data[0], 42, *fn, &meas);
}
void test_spb_handling()
{
BTS the_bts;
int ts_no = 7;
uint32_t fn = 2654218;
uint16_t qta = 31;
uint32_t tlli = 0xf1223344;
const char *imsi = "0011223344";
uint8_t ms_class = 1;
gprs_rlcmac_ul_tbf *ul_tbf;
GprsMs *ms;
printf("=== start %s ===\n", __func__);
setup_bts(&the_bts, ts_no, 7);
ul_tbf = spb_handler(&the_bts, ts_no, tlli, &fn, qta, ms_class);
}
void test__mcs8_retx_mcs6()
{
BTS the_bts;
int ts_no = 7;
uint32_t fn = 2654218;
uint16_t qta = 31;
uint32_t tlli = 0xf1223344;
const char *imsi = "0011223344";
uint8_t ms_class = 1;
gprs_rlcmac_ul_tbf *ul_tbf;
GprsMs *ms;
printf("=== start %s ===\n", __func__);
setup_bts(&the_bts, ts_no, 10);
ul_tbf = mcs8_mcs6_retx(&the_bts, ts_no, tlli, &fn, qta, ms_class);
}
int main(int argc, char **argv)
{
uint8_t i = 0, data_len = 0;
struct vty_app_info pcu_vty_info = {0};
tall_pcu_ctx = talloc_named_const(NULL, 1, "EdgeTest context");
if (!tall_pcu_ctx)
abort();
msgb_set_talloc_ctx(tall_pcu_ctx);
osmo_init_logging(&debug_log_info);
log_set_use_color(osmo_stderr_target, 0);
log_set_print_filename(osmo_stderr_target, 0);
vty_init(&pcu_vty_info);
pcu_vty_init(&debug_log_info);
test_coding_scheme();
test_rlc_decoder();
test_spb_handling();
test__mcs8_retx_mcs6();
uplink_header_type1_test();
test_rlc_unit_decoder();
test_tbf_two_phase();
test_tbf_two_phase_PUAN();
for(i = 0; i < 9; i++) {
test_downlink_for_all_mcs(TEST_MODE_STANDARD, i);
}
test_downlink_retransmission_mcs6_mcs3();
test_downlink_retransmission_mcs5_mcs2();
test_downlink_retransmission_mcs4_mcs1();
test_downlink_retransmission_mcs7_mcs5();
test_downlink_retransmission_mcs8_mcs6();
test_downlink_retransmission_mcs9_mcs6();
test_downlink_retransmission_mcs9_mcs3();
test_downlink_retransmission_mcs8_mcs3();
test_downlink_retransmission_mcs7_mcs2();
test_downlink_retransmission_mcs8_mcs6_mcs3();
test_tbf_final_ack_EPDAN(TEST_MODE_STANDARD);
if (getenv("TALLOC_REPORT_FULL"))
talloc_report_full(tall_pcu_ctx, stderr);
return EXIT_SUCCESS;
}
/*
* stubs that should not be reached
*/
extern "C" {
void l1if_pdch_req() { abort(); }
void l1if_connect_pdch() { abort(); }
void l1if_close_pdch() { abort(); }
void l1if_open_pdch() { abort(); }
}