Add header type 1 support for EGPRS uplink

Function is added to parse the EGPRS header type 1 in uplink tbf path.
along with configuration parameter updation to reflect max mcs in UL

Change-Id: I13c250e2e07377982ac3f29745f3cffd4088552a
Reviewed-on: https://gerrit.osmocom.org/270
Reviewed-by: Harald Welte <laforge@gnumonks.org>
Tested-by: Jenkins Builder
This commit is contained in:
Aravind Sirsikar 2016-06-15 17:46:41 +05:30 committed by Harald Welte
parent 550a54184b
commit 99ab0a8fa0
6 changed files with 75 additions and 9 deletions

View File

@ -41,6 +41,8 @@ extern "C" {
#define LLC_CODEL_DISABLE 0
#define LLC_CODEL_USE_DEFAULT (-1)
#define MAX_GPRS_CS 9
struct BTS;
struct GprsMs;
@ -188,7 +190,7 @@ struct gprs_rlcmac_bts {
uint8_t cs_adj_enabled;
uint8_t cs_adj_upper_limit;
uint8_t cs_adj_lower_limit;
struct {int16_t low; int16_t high;} cs_lqual_ranges[4];
struct {int16_t low; int16_t high; } cs_lqual_ranges[MAX_GPRS_CS];
uint16_t cs_downgrade_threshold; /* downgrade if less packets left (DL) */
uint16_t ws_base;
uint16_t ws_pdch; /* increase WS by this value per PDCH */

View File

@ -357,8 +357,8 @@ int Decoding::rlc_parse_ul_data_header(struct gprs_rlc_data_info *rlc,
cur_bit = rlc_parse_ul_data_header_egprs_type_2(rlc, data, cs);
break;
case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1 :
/* TODO: Support both header type 1 */
/* fall through */
cur_bit = rlc_parse_ul_data_header_egprs_type_1(rlc, data, cs);
break;
default:
LOGP(DRLCMACDL, LOGL_ERROR,
"Decoding of uplink %s data blocks not yet supported.\n",
@ -455,6 +455,65 @@ int Decoding::rlc_parse_ul_data_header_egprs_type_2(
return cur_bit;
}
int Decoding::rlc_parse_ul_data_header_egprs_type_1(
struct gprs_rlc_data_info *rlc,
const uint8_t *data, const GprsCodingScheme &cs)
{
struct gprs_rlc_ul_header_egprs_1 *egprs1;
unsigned int e_ti_header, cur_bit = 0, offs;
int punct, punct2, with_padding;
egprs1 = static_cast < struct gprs_rlc_ul_header_egprs_1 * >
((void *)data);
gprs_rlc_mcs_cps_decode(egprs1->cps, cs, &punct, &punct2,
&with_padding);
gprs_rlc_data_info_init_ul(rlc, cs, with_padding);
rlc->r = egprs1->r;
rlc->si = egprs1->si;
rlc->tfi = (egprs1->tfi_a << 0) | (egprs1->tfi_b << 2);
rlc->cps = egprs1->cps;
rlc->rsb = egprs1->rsb;
rlc->num_data_blocks = 2;
rlc->block_info[0].cv = egprs1->cv;
rlc->block_info[0].pi = egprs1->pi;
rlc->block_info[0].bsn =
(egprs1->bsn1_a << 0) | (egprs1->bsn1_b << 5);
cur_bit += rlc->data_offs_bits[0] - 2;
offs = rlc->data_offs_bits[0] / 8;
OSMO_ASSERT(rlc->data_offs_bits[0] % 8 == 0);
e_ti_header = data[offs - 1] >> 6;
rlc->block_info[0].e = (e_ti_header & 0x01);
rlc->block_info[0].ti = !!(e_ti_header & 0x02);
cur_bit += 2;
rlc->block_info[1].cv = egprs1->cv;
rlc->block_info[1].pi = egprs1->pi;
rlc->block_info[1].bsn = rlc->block_info[0].bsn +
((egprs1->bsn2_a << 0) | (egprs1->bsn2_b << 2));
rlc->block_info[1].bsn = rlc->block_info[1].bsn & (RLC_EGPRS_SNS - 1);
if ((rlc->block_info[1].bsn != rlc->block_info[0].bsn) &&
(rlc->block_info[0].cv == 0))
rlc->block_info[0].cv = 1;
cur_bit = rlc->data_offs_bits[1] - 2;
offs = rlc->data_offs_bits[1] / 8;
OSMO_ASSERT(rlc->data_offs_bits[1] % 8 == 2);
e_ti_header = (data[offs] & (0x03));
rlc->block_info[1].e = (e_ti_header & 0x01);
rlc->block_info[1].ti = !!(e_ti_header & 0x02);
cur_bit += 2;
/* skip data area */
cur_bit += cs.maxDataBlockBytes() * 8;
return cur_bit;
}
int Decoding::rlc_parse_ul_data_header_gprs(struct gprs_rlc_data_info *rlc,
const uint8_t *data, const GprsCodingScheme &cs)
{

View File

@ -52,6 +52,10 @@ public:
struct gprs_rlc_data_info *rlc,
const uint8_t *data,
const GprsCodingScheme &cs);
static int rlc_parse_ul_data_header_egprs_type_1(
struct gprs_rlc_data_info *rlc,
const uint8_t *data,
const GprsCodingScheme &cs);
static int rlc_parse_ul_data_header_gprs(
struct gprs_rlc_data_info *rlc,
const uint8_t *data,

View File

@ -610,8 +610,9 @@ static void write_packet_uplink_ack_egprs(
struct gprs_rlcmac_ul_tbf *tbf, bool is_final)
{
bitvec_write_field(dest, wp, 0, 2); // fixed 00
bitvec_write_field(dest, wp, 2, 4); // CHANNEL_CODING_COMMAND: MCS-3
// bitvec_write_field(dest, wp, tbf->current_cs() - 1, 4); // CHANNEL_CODING_COMMAND
/* CHANNEL_CODING_COMMAND */
bitvec_write_field(dest, wp,
tbf->current_cs().to_num() - 1, 4);
bitvec_write_field(dest, wp, 0, 1); // 0: no RESEGMENT (nyi)
bitvec_write_field(dest, wp, 1, 1); // PRE_EMPTIVE_TRANSMISSION, TODO: This resembles GPRS, change it?
bitvec_write_field(dest, wp, 0, 1); // 0: no PRR_RETRANSMISSION_REQUEST, TODO: clarify

View File

@ -632,8 +632,8 @@ void GprsMs::update_cs_ul(const pcu_l1_meas *meas)
high = bts_data->cs_lqual_ranges[current_cs_num-1].high;
} else if (m_current_cs_ul.isEgprs()) {
/* TODO, use separate table */
if (current_cs_num > 4)
current_cs_num = 4;
if (current_cs_num > MAX_GPRS_CS)
current_cs_num = MAX_GPRS_CS;
low = bts_data->cs_lqual_ranges[current_cs_num-1].low;
high = bts_data->cs_lqual_ranges[current_cs_num-1].high;
} else {

View File

@ -189,8 +189,8 @@ int main(int argc, char *argv[])
bts->cs_adj_lower_limit = 10; /* Increase CS if the error rate is below */
bts->max_cs_ul = 4;
bts->max_cs_dl = 4;
bts->max_mcs_ul = 4;
bts->max_mcs_dl = 4;
bts->max_mcs_ul = MAX_GPRS_CS;
bts->max_mcs_dl = MAX_GPRS_CS;
/* CS-1 to CS-4 */
bts->cs_lqual_ranges[0].low = -256;
bts->cs_lqual_ranges[0].high = 6;