Modify EGPRS DL TBF flow to support SPB

Modify the EGPRS DL TBF flow to support Split block during
Retx. This patch will also Upgrade the test suite with test cases
to validate the EGPRS Downlink SPB for Retransmission

Scenarios like MCS6->MCS3, MCS4->MCS1, MCS5->MCS2, MCS9->MCS3
MCS7->MCS2, MCS8->MCS3 have been simulated and Integration tested
in NuRAN 1.0 hardware thoroughly.

Change-Id: I242afdd8ae7622dec8593b26382ad66bad5b9516
This commit is contained in:
Aravind Sirsikar 2016-08-22 17:21:10 +05:30 committed by arvind.sirsikar
parent e6cadb4e3c
commit 50b097003b
11 changed files with 958 additions and 80 deletions

View File

@ -113,7 +113,8 @@ public:
static const char *modeName(Mode mode);
static Scheme get_retx_mcs(const GprsCodingScheme mcs,
const GprsCodingScheme retx_mcs);
const GprsCodingScheme retx_mcs,
const unsigned arq_type);
static enum Scheme egprs_mcs_retx_tbl[MAX_NUM_ARQ]
[MAX_NUM_MCS][MAX_NUM_MCS];
@ -232,8 +233,9 @@ inline bool operator >=(GprsCodingScheme a, GprsCodingScheme b)
}
inline GprsCodingScheme::Scheme GprsCodingScheme::get_retx_mcs(
const GprsCodingScheme mcs,
const GprsCodingScheme demanded_mcs)
const GprsCodingScheme demanded_mcs,
const unsigned arq_type)
{
return egprs_mcs_retx_tbl[EGPRS_ARQ2][mcs.to_num() - 1]
return egprs_mcs_retx_tbl[arq_type][mcs.to_num() - 1]
[demanded_mcs.to_num() - 1];
}

View File

@ -210,6 +210,12 @@ int main(int argc, char *argv[])
bts->dl_tbf_idle_msec = 2000;
bts->llc_idle_ack_csec = 10;
/*
* By default resegmentation is supported in DL
* can also be configured through VTY
*/
bts->dl_arq_type = EGPRS_ARQ1;
msgb_set_talloc_ctx(tall_pcu_ctx);
osmo_init_logging(&gprs_log_info);

View File

@ -129,6 +129,10 @@ static int config_write_pcu(struct vty *vty)
vty_out(vty, " window-size %d %d%s", bts->ws_base, bts->ws_pdch,
VTY_NEWLINE);
if (bts->dl_arq_type)
vty_out(vty, " egprs dl arq-type arq2%s",
VTY_NEWLINE);
if (bts->force_llc_lifetime == 0xffff)
vty_out(vty, " queue lifetime infinite%s", VTY_NEWLINE);
else if (bts->force_llc_lifetime)
@ -474,6 +478,25 @@ DEFUN(cfg_pcu_no_mcs_max,
return CMD_SUCCESS;
}
#define DL_STR "downlink specific configuration\n"
DEFUN(cfg_pcu_dl_arq_type,
cfg_pcu_dl_arq_cmd,
"egprs dl arq-type (spb|arq2)",
EGPRS_STR DL_STR "ARQ options\n"
"enable SPB(ARQ1) support\n"
"enable ARQ2 support")
{
struct gprs_rlcmac_bts *bts = bts_main_data();
if (!strcmp(argv[0], "arq2"))
bts->dl_arq_type = 1;
else
bts->dl_arq_type = 0;
return CMD_SUCCESS;
}
DEFUN(cfg_pcu_window_size,
cfg_pcu_window_size_cmd,
"window-size <0-1024> [<0-256>]",
@ -948,6 +971,7 @@ int pcu_vty_init(const struct log_info *cat)
install_element(PCU_NODE, &cfg_pcu_no_cs_downgrade_thrsh_cmd);
install_element(PCU_NODE, &cfg_pcu_cs_lqual_ranges_cmd);
install_element(PCU_NODE, &cfg_pcu_mcs_cmd);
install_element(PCU_NODE, &cfg_pcu_dl_arq_cmd);
install_element(PCU_NODE, &cfg_pcu_no_mcs_cmd);
install_element(PCU_NODE, &cfg_pcu_mcs_max_cmd);
install_element(PCU_NODE, &cfg_pcu_no_mcs_max_cmd);

View File

@ -285,7 +285,8 @@ bool gprs_rlc_ul_window::invalidate_bsn(const uint16_t bsn)
}
static void gprs_rlc_data_header_init(struct gprs_rlc_data_info *rlc,
GprsCodingScheme cs, bool with_padding, unsigned int header_bits)
GprsCodingScheme cs, bool with_padding, unsigned int header_bits,
const unsigned int spb)
{
unsigned int i;
unsigned int padding_bits = with_padding ? cs.optionalPaddingBits() : 0;
@ -300,7 +301,7 @@ static void gprs_rlc_data_header_init(struct gprs_rlc_data_info *rlc,
for (i = 0; i < rlc->num_data_blocks; i++) {
gprs_rlc_data_block_info_init(&rlc->block_info[i], cs,
with_padding);
with_padding, spb);
rlc->data_offs_bits[i] =
header_bits + padding_bits +
@ -310,21 +311,25 @@ static void gprs_rlc_data_header_init(struct gprs_rlc_data_info *rlc,
}
void gprs_rlc_data_info_init_dl(struct gprs_rlc_data_info *rlc,
GprsCodingScheme cs, bool with_padding)
GprsCodingScheme cs, bool with_padding, const unsigned int spb)
{
return gprs_rlc_data_header_init(rlc, cs, with_padding,
cs.numDataHeaderBitsDL());
cs.numDataHeaderBitsDL(), spb);
}
void gprs_rlc_data_info_init_ul(struct gprs_rlc_data_info *rlc,
GprsCodingScheme cs, bool with_padding)
{
/*
* last parameter is sent as 0 since common function used
* for both DL and UL
*/
return gprs_rlc_data_header_init(rlc, cs, with_padding,
cs.numDataHeaderBitsUL());
cs.numDataHeaderBitsUL(), 0);
}
void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi,
GprsCodingScheme cs, bool with_padding)
GprsCodingScheme cs, bool with_padding, const unsigned int spb)
{
unsigned int data_len = cs.maxDataBlockBytes();
if (with_padding)
@ -336,7 +341,7 @@ void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi,
rdbi->e = 1;
rdbi->cv = 15;
rdbi->pi = 0;
rdbi->spb = 0;
rdbi->spb = spb;
}
unsigned int gprs_rlc_mcs_cps(GprsCodingScheme cs,
@ -411,8 +416,18 @@ void gprs_rlc_mcs_cps_decode(unsigned int cps,
enum egprs_puncturing_values gprs_get_punct_scheme(
enum egprs_puncturing_values punct,
const GprsCodingScheme &cs,
const GprsCodingScheme &cs_current)
const GprsCodingScheme &cs_current,
const enum egprs_rlcmac_dl_spb spb)
{
/*
* 10.4.8b of TS 44.060
* If it is second segment of the block
* dont change the puncturing scheme
*/
if (spb == EGPRS_RLCMAC_DL_SEC_SEG)
return punct;
/* TS 44.060 9.3.2.1.1 */
if ((GprsCodingScheme::Scheme(cs) == GprsCodingScheme::MCS9) &&
(GprsCodingScheme::Scheme(cs_current) == GprsCodingScheme::MCS6)) {

View File

@ -213,18 +213,19 @@ struct gprs_rlc_data {
};
void gprs_rlc_data_info_init_dl(struct gprs_rlc_data_info *rlc,
GprsCodingScheme cs, bool with_padding);
GprsCodingScheme cs, bool with_padding, const unsigned int spb);
void gprs_rlc_data_info_init_ul(struct gprs_rlc_data_info *rlc,
GprsCodingScheme cs, bool with_padding);
void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi,
GprsCodingScheme cs, bool with_padding);
GprsCodingScheme cs, bool with_padding, const unsigned int spb);
unsigned int gprs_rlc_mcs_cps(GprsCodingScheme cs, enum egprs_puncturing_values
punct, enum egprs_puncturing_values punct2, int with_padding);
void gprs_rlc_mcs_cps_decode(unsigned int cps, GprsCodingScheme cs,
int *punct, int *punct2, int *with_padding);
enum egprs_puncturing_values gprs_get_punct_scheme(enum egprs_puncturing_values
punct, const GprsCodingScheme &cs,
const GprsCodingScheme &cs_current_trans);
const GprsCodingScheme &cs_current_trans,
const enum egprs_rlcmac_dl_spb spb);
void gprs_update_punct_scheme(enum egprs_puncturing_values *punct,
const GprsCodingScheme &cs);
/*

View File

@ -421,6 +421,11 @@ protected:
int analyse_errors(char *show_rbb, uint8_t ssn, ana_result *res);
void schedule_next_frame();
enum egprs_rlc_dl_reseg_bsn_state egprs_dl_get_data
(int bsn, uint8_t **block_data);
unsigned int get_egprs_dl_spb_status(int bsn);
enum egprs_rlcmac_dl_spb get_egprs_dl_spb(int bsn);
struct osmo_timer_list m_llc_timer;
};

View File

@ -375,21 +375,28 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn,
return -1;
if (is_egprs_enabled()) {
/* Table 8.1.1.2 and Table 8.1.1.1 of 44.060 */
m_rlc.block(bsn)->cs_current_trans =
GprsCodingScheme::get_retx_mcs(
m_rlc.block(bsn)->cs_last, ms()->current_cs_dl());
GprsCodingScheme::get_retx_mcs(
m_rlc.block(bsn)->cs_init,
ms()->current_cs_dl(),
bts->bts_data()->dl_arq_type);
LOGP(DRLCMACDL, LOGL_DEBUG,
"- current_cs_dl(%d) demanded_mcs(%d) cs_trans(%d)\n",
m_rlc.block(bsn)->cs_last.to_num(),
ms()->current_cs_dl().to_num(),
m_rlc.block(bsn)->cs_current_trans.to_num());
"- initial_cs_dl(%d) last_mcs(%d)"
" demanded_mcs(%d) cs_trans(%d)"
" arq_type(%d) bsn(%d)\n",
m_rlc.block(bsn)->cs_init.to_num(),
m_rlc.block(bsn)->cs_last.to_num(),
ms()->current_cs_dl().to_num(),
m_rlc.block(bsn)->cs_current_trans.to_num(),
bts->bts_data()->dl_arq_type, bsn);
/* TODO: Need to remove this check when MCS-8 -> MCS-6
* transistion is handled.
* Refer commit be881c028fc4da00c4046ecd9296727975c206a3
*/
if (m_rlc.block(bsn)->cs_last == GprsCodingScheme::MCS8)
if (m_rlc.block(bsn)->cs_init == GprsCodingScheme::MCS8)
m_rlc.block(bsn)->cs_current_trans =
GprsCodingScheme::MCS8;
} else
@ -523,6 +530,11 @@ int gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, GprsCodingScheme cs)
data = rlc_data->prepare(block_data_len);
rlc_data->cs_last = cs;
rlc_data->cs_current_trans = cs;
/* Initialise the variable related to DL SPB */
rlc_data->spb_status.block_status_dl = EGPRS_RESEG_DL_DEFAULT;
rlc_data->cs_init = cs;
rlc_data->len = block_data_len;
rdbi = &(rlc_data->block_info);
@ -616,7 +628,8 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
unsigned num_bsns;
enum egprs_puncturing_values punct[ARRAY_SIZE(rlc.block_info)];
bool need_padding = false;
enum egprs_rlcmac_dl_spb spb = EGPRS_RLCMAC_DL_NO_RETX;
unsigned int spb_status = get_egprs_dl_spb_status(index);
/*
* TODO: This is an experimental work-around to put 2 BSN into
* MSC-7 to MCS-9 encoded messages. It just sends the same BSN
@ -626,6 +639,7 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
* the current limit.
*/
cs = m_rlc.block(index)->cs_current_trans;
GprsCodingScheme &cs_init = m_rlc.block(index)->cs_init;
bsns[0] = index;
num_bsns = 1;
@ -634,7 +648,17 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
num_bsns += 1;
}
if (num_bsns == 1) {
/*
* if the intial mcs is 8 and retransmission mcs is either 6 or 3
* we have to include the padding of 6 octets in first segment
*/
if ((GprsCodingScheme::Scheme(cs_init) == GprsCodingScheme::MCS8) &&
(GprsCodingScheme::Scheme(cs) == GprsCodingScheme::MCS6 ||
GprsCodingScheme::Scheme(cs) == GprsCodingScheme::MCS3)) {
if (spb_status == EGPRS_RESEG_DL_DEFAULT ||
spb_status == EGPRS_RESEG_SECOND_SEG_SENT)
need_padding = true;
} else if (num_bsns == 1) {
/* TODO: remove the conditional when MCS-6 padding isn't
* failing to be decoded by MEs anymore */
/* TODO: support of MCS-8 -> MCS-6 transition should be
@ -646,7 +670,14 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
cs.decToSingleBlock(&need_padding);
}
gprs_rlc_data_info_init_dl(&rlc, cs, need_padding);
spb = get_egprs_dl_spb(index);
LOGP(DRLCMACDL, LOGL_DEBUG, "- need_padding %d spb_status %d spb %d"
"(BSN1 %d BSN2 %d)\n",
need_padding,
spb_status, spb, index, index2);
gprs_rlc_data_info_init_dl(&rlc, cs, need_padding, spb);
rlc.usf = 7; /* will be set at scheduler */
rlc.pr = 0; /* FIXME: power reduction */
@ -665,10 +696,9 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
data_block_idx++)
{
int bsn;
GprsCodingScheme cs_enc;
uint8_t *block_data;
gprs_rlc_data_block_info *rdbi, *block_info;
enum egprs_puncturing_values punct_scheme;
enum egprs_rlc_dl_reseg_bsn_state reseg_status;
/* Check if there are more blocks than BSNs */
if (data_block_idx < num_bsns)
@ -676,38 +706,43 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
else
bsn = bsns[0];
cs_enc = m_rlc.block(bsn)->cs_current_trans;
/* get data and header from current block */
block_data = m_rlc.block(bsn)->block;
/* Get current puncturing scheme from block */
punct_scheme = gprs_get_punct_scheme(
m_rlc.block(bsn)->next_ps = gprs_get_punct_scheme(
m_rlc.block(bsn)->next_ps,
m_rlc.block(bsn)->cs_last, cs);
m_rlc.block(bsn)->cs_last, cs, spb);
if (cs.isEgprs()) {
OSMO_ASSERT(punct_scheme >= EGPRS_PS_1);
OSMO_ASSERT(punct_scheme <= EGPRS_PS_3);
OSMO_ASSERT(m_rlc.block(bsn)->next_ps >= EGPRS_PS_1);
OSMO_ASSERT(m_rlc.block(bsn)->next_ps <= EGPRS_PS_3);
}
punct[data_block_idx] = punct_scheme;
punct[data_block_idx] = m_rlc.block(bsn)->next_ps;
rdbi = &rlc.block_info[data_block_idx];
block_info = &m_rlc.block(bsn)->block_info;
if(rdbi->data_len != m_rlc.block(bsn)->len) {
LOGP(DRLCMACDL, LOGL_ERROR,
"ERROR: Expected len = %d for %s instead of "
"%d in data unit %d (BSN %d, %s)\n",
rdbi->data_len, cs.name(), m_rlc.block(bsn)->len,
data_block_idx, bsn, cs_enc.name());
OSMO_ASSERT(rdbi->data_len == m_rlc.block(bsn)->len);
}
/* TODO: Need to handle 2 same bsns
* in header type 1
/*
* get data and header from current block
* function returns the reseg status
*/
gprs_update_punct_scheme(&m_rlc.block(bsn)->next_ps,
cs);
reseg_status = egprs_dl_get_data(bsn, &block_data);
m_rlc.block(bsn)->spb_status.block_status_dl = reseg_status;
/*
* If it is first segment of the split block set the state of
* bsn to nacked. If it is the first segment dont update the
* next ps value of bsn. since next segment also needs same cps
*/
if (spb == EGPRS_RLCMAC_DL_FIRST_SEG)
m_window.m_v_b.mark_nacked(bsn);
else {
/*
* TODO: Need to handle 2 same bsns
* in header type 1
*/
gprs_update_punct_scheme(&m_rlc.block(bsn)->next_ps,
cs);
}
m_rlc.block(bsn)->cs_last = cs;
rdbi->e = block_info->e;
@ -1169,3 +1204,118 @@ bool gprs_rlcmac_dl_tbf::keep_open(unsigned fn) const
keep_time_frames = msecs_to_frames(bts_data()->dl_tbf_idle_msec);
return frames_since_last_drain(fn) <= keep_time_frames;
}
/*
* This function returns the pointer to data which needs
* to be copied. Also updates the status of the block related to
* Split block handling in the RLC/MAC block.
*/
enum egprs_rlc_dl_reseg_bsn_state
gprs_rlcmac_dl_tbf::egprs_dl_get_data(int bsn, uint8_t **block_data)
{
gprs_rlc_data *rlc_data = m_rlc.block(bsn);
egprs_rlc_dl_reseg_bsn_state *block_status_dl =
&rlc_data->spb_status.block_status_dl;
GprsCodingScheme &cs_current_trans = m_rlc.block(bsn)->cs_current_trans;
GprsCodingScheme &cs_init = m_rlc.block(bsn)->cs_init;
*block_data = &rlc_data->block[0];
/*
* Table 10.3a.0.1 of 44.060
* MCS6,9: second segment starts at 74/2 = 37
* MCS5,7: second segment starts at 56/2 = 28
* MCS8: second segment starts at 31
* MCS4: second segment starts at 44/2 = 22
*/
if (cs_current_trans.headerTypeData() ==
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3) {
if (*block_status_dl == EGPRS_RESEG_FIRST_SEG_SENT) {
switch (GprsCodingScheme::Scheme(cs_init)) {
case GprsCodingScheme::MCS6 :
case GprsCodingScheme::MCS9 :
*block_data = &rlc_data->block[37];
break;
case GprsCodingScheme::MCS7 :
case GprsCodingScheme::MCS5 :
*block_data = &rlc_data->block[28];
break;
case GprsCodingScheme::MCS8 :
*block_data = &rlc_data->block[31];
break;
case GprsCodingScheme::MCS4 :
*block_data = &rlc_data->block[22];
break;
default:
LOGP(DRLCMACDL, LOGL_ERROR, "Software error: "
"--%s hit invalid condition. headerType(%d) "
" blockstatus(%d) cs(%s) PLEASE FIX!\n", name(),
cs_current_trans.headerTypeData(),
*block_status_dl, cs_init.name());
break;
}
return EGPRS_RESEG_SECOND_SEG_SENT;
} else if ((cs_init.headerTypeData() ==
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1) ||
(cs_init.headerTypeData() ==
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2)) {
return EGPRS_RESEG_FIRST_SEG_SENT;
} else if ((GprsCodingScheme::Scheme(cs_init) ==
GprsCodingScheme::MCS4) &&
(GprsCodingScheme::Scheme(cs_current_trans) ==
GprsCodingScheme::MCS1)) {
return EGPRS_RESEG_FIRST_SEG_SENT;
}
}
return EGPRS_RESEG_DL_DEFAULT;
}
/*
* This function returns the status of split block
* for RLC/MAC block.
*/
unsigned int gprs_rlcmac_dl_tbf::get_egprs_dl_spb_status(const int bsn)
{
const gprs_rlc_data *rlc_data = m_rlc.block(bsn);
return rlc_data->spb_status.block_status_dl;
}
/*
* This function returns the spb value to be sent OTA
* for RLC/MAC block.
*/
enum egprs_rlcmac_dl_spb gprs_rlcmac_dl_tbf::get_egprs_dl_spb(const int bsn)
{
struct gprs_rlc_data *rlc_data = m_rlc.block(bsn);
egprs_rlc_dl_reseg_bsn_state block_status_dl =
rlc_data->spb_status.block_status_dl;
GprsCodingScheme &cs_current_trans = m_rlc.block(bsn)->cs_current_trans;
GprsCodingScheme &cs_init = m_rlc.block(bsn)->cs_init;
/* Table 10.4.8b.1 of 44.060 */
if (cs_current_trans.headerTypeData() ==
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3) {
/*
* if we are sending the second segment the spb should be 3
* other wise it should be 2
*/
if (block_status_dl == EGPRS_RESEG_FIRST_SEG_SENT) {
return EGPRS_RLCMAC_DL_SEC_SEG;
} else if ((cs_init.headerTypeData() ==
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1) ||
(cs_init.headerTypeData() ==
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2)) {
return EGPRS_RLCMAC_DL_FIRST_SEG;
} else if ((GprsCodingScheme::Scheme(cs_init) ==
GprsCodingScheme::MCS4) &&
(GprsCodingScheme::Scheme(cs_current_trans) ==
GprsCodingScheme::MCS1)) {
return EGPRS_RLCMAC_DL_FIRST_SEG;
}
}
/* Non SPB cases 0 is reurned */
return EGPRS_RLCMAC_DL_NO_RETX;
}

View File

@ -517,7 +517,7 @@ static void test_rlc_unit_encoder()
/* TS 44.060, B.1 */
cs = GprsCodingScheme::CS4;
gprs_rlc_data_block_info_init(&rdbi, cs, false);
gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
num_chunks = 0;
write_offset = 0;
memset(data, 0, sizeof(data));
@ -570,7 +570,7 @@ static void test_rlc_unit_encoder()
cs = GprsCodingScheme::CS1;
/* Block 1 */
gprs_rlc_data_block_info_init(&rdbi, cs, false);
gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
num_chunks = 0;
write_offset = 0;
memset(data, 0, sizeof(data));
@ -592,7 +592,7 @@ static void test_rlc_unit_encoder()
OSMO_ASSERT(data[1] == 0);
/* Block 2 */
gprs_rlc_data_block_info_init(&rdbi, cs, false);
gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
num_chunks = 0;
write_offset = 0;
memset(data, 0, sizeof(data));
@ -630,7 +630,7 @@ static void test_rlc_unit_encoder()
cs = GprsCodingScheme::CS1;
/* Block 1 */
gprs_rlc_data_block_info_init(&rdbi, cs, false);
gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
num_chunks = 0;
write_offset = 0;
memset(data, 0, sizeof(data));
@ -669,7 +669,7 @@ static void test_rlc_unit_encoder()
cs = GprsCodingScheme::CS1;
/* Block 1 */
gprs_rlc_data_block_info_init(&rdbi, cs, false);
gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
num_chunks = 0;
write_offset = 0;
memset(data, 0, sizeof(data));
@ -694,7 +694,7 @@ static void test_rlc_unit_encoder()
cs = GprsCodingScheme::CS1;
/* Block 1 */
gprs_rlc_data_block_info_init(&rdbi, cs, false);
gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
num_chunks = 0;
write_offset = 0;
memset(data, 0, sizeof(data));
@ -719,7 +719,7 @@ static void test_rlc_unit_encoder()
cs = GprsCodingScheme::CS1;
/* Block 1 */
gprs_rlc_data_block_info_init(&rdbi, cs, false);
gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
num_chunks = 0;
write_offset = 0;
memset(data, 0, sizeof(data));
@ -740,7 +740,7 @@ static void test_rlc_unit_encoder()
OSMO_ASSERT(data[0] == 0);
/* Block 2 */
gprs_rlc_data_block_info_init(&rdbi, cs, false);
gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
num_chunks = 0;
write_offset = 0;
memset(data, 0, sizeof(data));
@ -777,7 +777,7 @@ static void test_rlc_unit_encoder()
cs = GprsCodingScheme::MCS4;
/* Block 1 */
gprs_rlc_data_block_info_init(&rdbi, cs, false);
gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
num_chunks = 0;
write_offset = 0;
memset(data, 0, sizeof(data));
@ -835,7 +835,7 @@ static void test_rlc_unit_encoder()
cs = GprsCodingScheme::MCS2;
/* Block 1 */
gprs_rlc_data_block_info_init(&rdbi, cs, false);
gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
num_chunks = 0;
write_offset = 0;
memset(data, 0, sizeof(data));
@ -872,7 +872,7 @@ static void test_rlc_unit_encoder()
OSMO_ASSERT(data[1] == 0);
/* Block 2 */
gprs_rlc_data_block_info_init(&rdbi, cs, false);
gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
num_chunks = 0;
write_offset = 0;
memset(data, 0, sizeof(data));
@ -923,7 +923,7 @@ static void test_rlc_unit_encoder()
OSMO_ASSERT(data[3] == 0);
/* Block 3 */
gprs_rlc_data_block_info_init(&rdbi, cs, false);
gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
num_chunks = 0;
write_offset = 0;
memset(data, 0, sizeof(data));
@ -967,7 +967,7 @@ static void test_rlc_unit_encoder()
cs = GprsCodingScheme::MCS2;
/* Block 1 */
gprs_rlc_data_block_info_init(&rdbi, cs, false);
gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
num_chunks = 0;
write_offset = 0;
memset(data, 0, sizeof(data));
@ -993,7 +993,7 @@ static void test_rlc_unit_encoder()
cs = GprsCodingScheme::MCS2;
/* Block 1 */
gprs_rlc_data_block_info_init(&rdbi, cs, false);
gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
num_chunks = 0;
write_offset = 0;
memset(data, 0, sizeof(data));
@ -1020,7 +1020,7 @@ static void test_rlc_unit_encoder()
cs = GprsCodingScheme::MCS2;
/* Block 1 */
gprs_rlc_data_block_info_init(&rdbi, cs, false);
gprs_rlc_data_block_info_init(&rdbi, cs, false, 0);
num_chunks = 0;
write_offset = 0;
memset(data, 0, sizeof(data));
@ -1074,7 +1074,7 @@ static void test_rlc_unaligned_copy()
block_idx++)
{
struct gprs_rlc_data_info rlc;
gprs_rlc_data_info_init_dl(&rlc, cs, false);
gprs_rlc_data_info_init_dl(&rlc, cs, false, 0);
memset(bits, pattern, sizeof(bits));
Decoding::rlc_copy_to_aligned_buffer(
@ -1118,12 +1118,14 @@ static void test_rlc_info_init()
struct gprs_rlc_data_info rlc;
printf("=== start %s ===\n", __func__);
gprs_rlc_data_info_init_dl(&rlc, GprsCodingScheme(GprsCodingScheme::CS1), false);
gprs_rlc_data_info_init_dl(&rlc,
GprsCodingScheme(GprsCodingScheme::CS1), false, 0);
OSMO_ASSERT(rlc.num_data_blocks == 1);
OSMO_ASSERT(rlc.data_offs_bits[0] == 24);
OSMO_ASSERT(rlc.block_info[0].data_len == 20);
gprs_rlc_data_info_init_dl(&rlc, GprsCodingScheme(GprsCodingScheme::MCS1), false);
gprs_rlc_data_info_init_dl(&rlc,
GprsCodingScheme(GprsCodingScheme::MCS1), false, 0);
OSMO_ASSERT(rlc.num_data_blocks == 1);
OSMO_ASSERT(rlc.data_offs_bits[0] == 33);
OSMO_ASSERT(rlc.block_info[0].data_len == 22);

View File

@ -1814,6 +1814,203 @@ static void tbf_cleanup(gprs_rlcmac_dl_tbf *dl_tbf)
}
static void egprs_spb_to_normal_validation(BTS *the_bts,
int mcs, int demanded_mcs)
{
uint32_t fn = 0;
gprs_rlcmac_dl_tbf *dl_tbf;
uint8_t block_nr = 0;
int index1 = 0;
uint8_t bn;
uint16_t bsn1, bsn2, bsn3;
struct msgb *msg;
struct gprs_rlc_dl_header_egprs_3 *egprs3;
struct gprs_rlc_dl_header_egprs_2 *egprs2;
printf("Testing retx for MCS %d to reseg_mcs %d\n", mcs, demanded_mcs);
dl_tbf = tbf_init(the_bts, mcs);
/*
* Table 10.4.8a.3.1 of 44.060.
* (MCS7, MCS9) to (MCS2, MCS3) is not handled since it is same as
* (MCS5, MCS6) to (MCS2, MCS3) transition
*/
if (!(mcs == 6 && demanded_mcs == 3))
return;
fn = fn_add_blocks(fn, 1);
/* Send first RLC data block BSN 0 */
msg = dl_tbf->create_dl_acked_block(fn, dl_tbf->control_ts);
OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_unacked(0));
OSMO_ASSERT(dl_tbf->m_rlc.block(0)->cs_current_trans.to_num()
== mcs);
egprs2 = (struct gprs_rlc_dl_header_egprs_2 *) msg->data;
bsn1 = (egprs2->bsn1_hi << 9) || (egprs2->bsn1_mid << 1)
|| (egprs2->bsn1_lo);
dl_tbf->m_window.m_v_b.mark_nacked(0);
OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_nacked(0));
OSMO_ASSERT(bsn1 == 0);
dl_tbf->ms()->set_current_cs_dl
(static_cast < GprsCodingScheme::Scheme >
(GprsCodingScheme::CS4 + demanded_mcs));
fn = fn_add_blocks(fn, 1);
/* Send first segment with demanded_mcs */
msg = dl_tbf->create_dl_acked_block(fn, dl_tbf->control_ts);
OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_nacked(0));
OSMO_ASSERT(dl_tbf->m_rlc.block(0)->cs_current_trans.to_num()
== demanded_mcs);
OSMO_ASSERT(dl_tbf->m_rlc.block(0)->spb_status.block_status_dl
== EGPRS_RESEG_FIRST_SEG_SENT);
egprs3 = (struct gprs_rlc_dl_header_egprs_3 *) msg->data;
OSMO_ASSERT(egprs3->spb == 2);
/* Table 10.4.8a.3.1 of 44.060 */
OSMO_ASSERT(egprs3->cps == 3);
/* Send second segment with demanded_mcs */
msg = dl_tbf->create_dl_acked_block(fn, dl_tbf->control_ts);
OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_unacked(0));
OSMO_ASSERT(dl_tbf->m_rlc.block(0)->cs_current_trans.to_num()
== demanded_mcs);
OSMO_ASSERT(dl_tbf->m_rlc.block(0)->spb_status.block_status_dl
== EGPRS_RESEG_SECOND_SEG_SENT);
egprs3 = (struct gprs_rlc_dl_header_egprs_3 *) msg->data;
/* Table 10.4.8a.3.1 of 44.060 */
OSMO_ASSERT(egprs3->spb == 3);
bsn2 = (egprs3->bsn1_hi << 9) || (egprs3->bsn1_mid << 1) ||
(egprs3->bsn1_lo);
OSMO_ASSERT(bsn2 == bsn1);
/* Table 10.4.8a.3.1 of 44.060 */
OSMO_ASSERT(egprs3->cps == 3);
/* Handle (MCS3, MCS3) -> MCS6 case */
dl_tbf->ms()->set_current_cs_dl
(static_cast < GprsCodingScheme::Scheme >
(GprsCodingScheme::CS4 + mcs));
dl_tbf->m_window.m_v_b.mark_nacked(0);
OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_nacked(0));
msg = dl_tbf->create_dl_acked_block(fn, dl_tbf->control_ts);
egprs2 = (struct gprs_rlc_dl_header_egprs_2 *) msg->data;
/* Table 10.4.8a.3.1 of 44.060 */
OSMO_ASSERT(egprs2->cps == 0);
bsn3 = (egprs2->bsn1_hi << 9) || (egprs2->bsn1_mid << 1) ||
(egprs2->bsn1_lo);
OSMO_ASSERT(bsn3 == bsn2);
tbf_cleanup(dl_tbf);
}
static void establish_and_use_egprs_dl_tbf_for_spb(BTS *the_bts,
int mcs, int demanded_mcs)
{
uint32_t fn = 0;
gprs_rlcmac_dl_tbf *dl_tbf;
uint8_t block_nr = 0;
int index1 = 0;
uint8_t bn;
struct msgb *msg;
struct gprs_rlc_dl_header_egprs_3 *egprs3;
printf("Testing retx for MCS %d to reseg_mcs %d\n", mcs, demanded_mcs);
dl_tbf = tbf_init(the_bts, mcs);
/*
* Table 10.4.8a.3.1 of 44.060.
* (MCS7, MCS9) to (MCS2, MCS3) is not handled since it is same as
* (MCS5, MCS6) to (MCS2, MCS3) transition
*/
/* TODO: Need to support of MCS8 -> MCS6 ->MCS3 transistion
* Refer commit be881c028fc4da00c4046ecd9296727975c206a3
* dated 2016-02-07 23:45:40 (UTC)
*/
if (!(((mcs == 5) && (demanded_mcs == 2)) ||
((mcs == 6) && (demanded_mcs == 3)) ||
((mcs == 4) && (demanded_mcs == 1))))
return;
fn = fn_add_blocks(fn, 1);
/* Send first RLC data block BSN 0 */
msg = dl_tbf->create_dl_acked_block(fn, dl_tbf->control_ts);
OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_unacked(0));
OSMO_ASSERT(dl_tbf->m_rlc.block(0)->cs_current_trans.to_num()
== mcs);
dl_tbf->m_window.m_v_b.mark_nacked(0);
OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_nacked(0));
dl_tbf->ms()->set_current_cs_dl
(static_cast < GprsCodingScheme::Scheme >
(GprsCodingScheme::CS4 + demanded_mcs));
fn = fn_add_blocks(fn, 1);
/* Send first segment with demanded_mcs */
msg = dl_tbf->create_dl_acked_block(fn, dl_tbf->control_ts);
OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_nacked(0));
OSMO_ASSERT(dl_tbf->m_rlc.block(0)->cs_current_trans.to_num()
== demanded_mcs);
OSMO_ASSERT(dl_tbf->m_rlc.block(0)->spb_status.block_status_dl
== EGPRS_RESEG_FIRST_SEG_SENT);
egprs3 = (struct gprs_rlc_dl_header_egprs_3 *) msg->data;
OSMO_ASSERT(egprs3->spb == 2);
/* Table 10.4.8a.3.1 of 44.060 */
switch (demanded_mcs) {
case 3:
OSMO_ASSERT(egprs3->cps == 3);
break;
case 2:
OSMO_ASSERT(egprs3->cps == 9);
break;
case 1:
OSMO_ASSERT(egprs3->cps == 11);
break;
default:
OSMO_ASSERT(false);
break;
}
/* Send second segment with demanded_mcs */
msg = dl_tbf->create_dl_acked_block(fn, dl_tbf->control_ts);
OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_unacked(0));
OSMO_ASSERT(dl_tbf->m_rlc.block(0)->cs_current_trans.to_num()
== demanded_mcs);
OSMO_ASSERT(dl_tbf->m_rlc.block(0)->spb_status.block_status_dl
== EGPRS_RESEG_SECOND_SEG_SENT);
egprs3 = (struct gprs_rlc_dl_header_egprs_3 *) msg->data;
/* Table 10.4.8a.3.1 of 44.060 */
OSMO_ASSERT(egprs3->spb == 3);
/* Table 10.4.8a.3.1 of 44.060 */
switch (demanded_mcs) {
case 3:
OSMO_ASSERT(egprs3->cps == 3);
break;
case 2:
OSMO_ASSERT(egprs3->cps == 9);
break;
case 1:
OSMO_ASSERT(egprs3->cps == 11);
break;
default:
OSMO_ASSERT(false);
break;
}
tbf_cleanup(dl_tbf);
}
static void establish_and_use_egprs_dl_tbf_for_retx(BTS *the_bts,
int mcs, int demanded_mcs)
{
@ -1972,6 +2169,9 @@ static void test_tbf_egprs_retx_dl(void)
setup_bts(&the_bts, ts_no);
bts->dl_tbf_idle_msec = 200;
bts->egprs_enabled = 1;
/* ARQ II */
bts->dl_arq_type = EGPRS_ARQ2;
/* First parameter is current MCS, second one is demanded_mcs */
establish_and_use_egprs_dl_tbf_for_retx(&the_bts, 6, 6);
@ -1985,6 +2185,38 @@ static void test_tbf_egprs_retx_dl(void)
printf("=== end %s ===\n", __func__);
}
static void test_tbf_egprs_spb_dl(void)
{
BTS the_bts;
gprs_rlcmac_bts *bts;
uint8_t ts_no = 4;
int i, j;
printf("=== start %s ===\n", __func__);
bts = the_bts.bts_data();
bts->cs_downgrade_threshold = 0;
setup_bts(&the_bts, ts_no);
bts->dl_tbf_idle_msec = 200;
bts->egprs_enabled = 1;
/* ARQ I resegmentation support */
bts->dl_arq_type = EGPRS_ARQ1;
/*
* First parameter is current MCS, second one is demanded_mcs
* currently only MCS5->MCS2, MCS6->3, MCS4->MCS1 is tested in UT
* rest scenarios has been integration tested
*/
establish_and_use_egprs_dl_tbf_for_spb(&the_bts, 6, 3);
establish_and_use_egprs_dl_tbf_for_spb(&the_bts, 5, 2);
establish_and_use_egprs_dl_tbf_for_spb(&the_bts, 4, 1);
/* check MCS6->(MCS3+MCS3)->MCS6 case */
egprs_spb_to_normal_validation(&the_bts, 6, 3);
printf("=== end %s ===\n", __func__);
}
static void test_tbf_egprs_dl()
{
BTS the_bts;
@ -1999,6 +2231,8 @@ static void test_tbf_egprs_dl()
setup_bts(&the_bts, ts_no);
bts->dl_tbf_idle_msec = 200;
bts->egprs_enabled = 1;
/* ARQ II */
bts->dl_arq_type = EGPRS_ARQ2;
for (i = 1; i <= 9; i++)
establish_and_use_egprs_dl_tbf(&the_bts, i);
@ -2071,6 +2305,7 @@ int main(int argc, char **argv)
test_tbf_egprs_two_phase_spb();
test_tbf_egprs_dl();
test_tbf_egprs_retx_dl();
test_tbf_egprs_spb_dl();
if (getenv("TALLOC_REPORT_FULL"))
talloc_report_full(tall_pcu_ctx, stderr);

File diff suppressed because it is too large Load Diff

View File

@ -54,3 +54,9 @@ Testing retx for MCS 6 - 9
Testing retx for MCS 7 - 5
Testing retx for MCS 9 - 6
=== end test_tbf_egprs_retx_dl ===
=== start test_tbf_egprs_spb_dl ===
Testing retx for MCS 6 to reseg_mcs 3
Testing retx for MCS 5 to reseg_mcs 2
Testing retx for MCS 4 to reseg_mcs 1
Testing retx for MCS 6 to reseg_mcs 3
=== end test_tbf_egprs_spb_dl ===