forked from cellular-infrastructure/osmo-pcu
2601 lines
77 KiB
C++
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(); }
|
|
}
|