EDGE: Fix UL link adaptation.

We have seen that UL MCS5- MCS9 link adaptation has not been implemented in current PCU implementation.
If the MS slowly moves far away from the BTS, the UL MCS will always stick at MCS9 no matter UL link quality values leading to poor data service experience.
The UL MCS is expected to adapt from MCS9 -> MCSx due to bad UL quality.

Below PCU traces indicate that UL MCS is quickly increasing to MCS9 (max MCS 9 was used in this test) and it never changes to other UL MCS due zero thresholds.

<0004> gprs_ms.cpp:670 MS (IMSI ): Link quality 23dB (23dB) left window [0, 0], modifying uplink CS level: MCS-6 -> MCS-7
<0004> gprs_ms.cpp:670 MS (IMSI 000): Link quality 23dB (23dB) left window [0, 0], modifying uplink CS level: MCS-7 -> MCS-8
<0004> gprs_ms.cpp:670 MS (IMSI 000): Link quality 23dB (23dB) left window [0, 0], modifying uplink CS level: MCS-8 -> MCS-9

Change-Id: I9272c337ad6399da4a47cc6e2736e25f24e099d8
This commit is contained in:
Minh-Quang Nguyen 2017-08-16 09:50:06 -04:00 committed by Harald Welte
parent b1be6112bb
commit 1f18909335
4 changed files with 100 additions and 5 deletions

View File

@ -221,6 +221,7 @@ struct gprs_rlcmac_bts {
uint8_t cs_adj_upper_limit;
uint8_t cs_adj_lower_limit;
struct {int16_t low; int16_t high; } cs_lqual_ranges[MAX_GPRS_CS];
struct {int16_t low; int16_t high; } mcs_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

@ -624,7 +624,7 @@ void GprsMs::update_cs_ul(const pcu_l1_meas *meas)
bts_data = m_bts->bts_data();
if (!max_cs_ul) {
LOGP(DRLCMACDL, LOGL_ERROR,
LOGP(DRLCMACMEAS, LOGL_ERROR,
"max_cs_ul cannot be derived (current UL CS: %s)\n",
m_current_cs_ul.name());
return;
@ -642,11 +642,10 @@ void GprsMs::update_cs_ul(const pcu_l1_meas *meas)
low = bts_data->cs_lqual_ranges[current_cs_num-1].low;
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 > 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;
low = bts_data->mcs_lqual_ranges[current_cs_num-1].low;
high = bts_data->mcs_lqual_ranges[current_cs_num-1].high;
} else {
return;
}
@ -661,7 +660,7 @@ void GprsMs::update_cs_ul(const pcu_l1_meas *meas)
new_cs_ul.inc(mode());
if (m_current_cs_ul != new_cs_ul) {
LOGP(DRLCMACDL, LOGL_INFO,
LOGP(DRLCMACMEAS, LOGL_INFO,
"MS (IMSI %s): "
"Link quality %ddB (%ddB) left window [%d, %d], "
"modifying uplink CS level: %s -> %s\n",

View File

@ -200,6 +200,28 @@ int main(int argc, char *argv[])
bts->cs_lqual_ranges[2].high = 13;
bts->cs_lqual_ranges[3].low = 12;
bts->cs_lqual_ranges[3].high = 256;
/* MCS-1 to MCS-9 */
/* Default thresholds are referenced from literature */
/* Fig. 2.3, Chapter 2, Optimizing Wireless Communication Systems, Springer (2009) */
bts->mcs_lqual_ranges[0].low = -256;
bts->mcs_lqual_ranges[0].high = 6;
bts->mcs_lqual_ranges[1].low = 5;
bts->mcs_lqual_ranges[1].high = 8;
bts->mcs_lqual_ranges[2].low = 7;
bts->mcs_lqual_ranges[2].high = 13;
bts->mcs_lqual_ranges[3].low = 12;
bts->mcs_lqual_ranges[3].high = 15;
bts->mcs_lqual_ranges[4].low = 14;
bts->mcs_lqual_ranges[4].high = 17;
bts->mcs_lqual_ranges[5].low = 16;
bts->mcs_lqual_ranges[5].high = 18;
bts->mcs_lqual_ranges[6].low = 17;
bts->mcs_lqual_ranges[6].high = 20;
bts->mcs_lqual_ranges[7].low = 19;
bts->mcs_lqual_ranges[7].high = 24;
bts->mcs_lqual_ranges[8].low = 23;
bts->mcs_lqual_ranges[8].high = 256;
bts->cs_downgrade_threshold = 200;
/* TODO: increase them when CRBB decoding is implemented */

View File

@ -178,6 +178,25 @@ static int config_write_pcu(struct vty *vty)
bts->cs_lqual_ranges[3].low,
VTY_NEWLINE);
vty_out(vty, " mcs link-quality-ranges mcs1 %d mcs2 %d %d mcs3 %d %d mcs4 %d %d mcs5 %d %d mcs6 %d %d mcs7 %d %d mcs8 %d %d mcs9 %d%s",
bts->mcs_lqual_ranges[0].high,
bts->mcs_lqual_ranges[1].low,
bts->mcs_lqual_ranges[1].high,
bts->mcs_lqual_ranges[2].low,
bts->mcs_lqual_ranges[2].high,
bts->mcs_lqual_ranges[3].low,
bts->mcs_lqual_ranges[3].high,
bts->mcs_lqual_ranges[4].low,
bts->mcs_lqual_ranges[4].high,
bts->mcs_lqual_ranges[5].low,
bts->mcs_lqual_ranges[5].high,
bts->mcs_lqual_ranges[6].low,
bts->mcs_lqual_ranges[6].high,
bts->mcs_lqual_ranges[7].low,
bts->mcs_lqual_ranges[7].high,
bts->mcs_lqual_ranges[8].low,
VTY_NEWLINE);
if (bts->initial_mcs_dl != 1 && bts->initial_mcs_ul != 1) {
if (bts->initial_mcs_ul == bts->initial_mcs_dl)
vty_out(vty, " mcs %d%s", bts->initial_mcs_dl,
@ -186,6 +205,7 @@ static int config_write_pcu(struct vty *vty)
vty_out(vty, " mcs %d %d%s", bts->initial_mcs_dl,
bts->initial_mcs_ul, VTY_NEWLINE);
}
if (bts->max_mcs_dl && bts->max_mcs_ul) {
if (bts->max_mcs_ul == bts->max_mcs_dl)
vty_out(vty, " mcs max %d%s", bts->max_mcs_dl,
@ -969,6 +989,58 @@ DEFUN(cfg_pcu_cs_lqual_ranges,
return CMD_SUCCESS;
}
DEFUN(cfg_pcu_mcs_lqual_ranges,
cfg_pcu_mcs_lqual_ranges_cmd,
"mcs link-quality-ranges mcs1 <0-35> mcs2 <0-35> <0-35> mcs3 <0-35> <0-35> mcs4 <0-35> <0-35> mcs5 <0-35> <0-35> mcs6 <0-35> <0-35> mcs7 <0-35> <0-35> mcs8 <0-35> <0-35> mcs9 <0-35>",
CS_STR "Set link quality ranges\n"
"Set quality range for MCS-1 (high value only)\n"
"MCS-1 high (dB)\n"
"Set quality range for MCS-2\n"
"MCS-2 high (dB)\n"
"MCS-2 low (dB)\n"
"Set quality range for MCS-3\n"
"MCS-3 high (dB)\n"
"MCS-3 low (dB)\n"
"Set quality range for MCS-4\n"
"MCS-4 high (dB)\n"
"MCS-4 low (dB)\n"
"Set quality range for MCS-5\n"
"MCS-5 high (dB)\n"
"MCS-5 low (dB)\n"
"Set quality range for MCS-6\n"
"MCS-6 low (dB)\n"
"MCS-6 high (dB)\n"
"Set quality range for MCS-7\n"
"MCS-7 low (dB)\n"
"MCS-7 high (dB)\n"
"Set quality range for MCS-8\n"
"MCS-8 low (dB)\n"
"MCS-8 high (dB)\n"
"Set quality range for MCS-9 (low value only)\n"
"MCS-9 low (dB)\n")
{
struct gprs_rlcmac_bts *bts = bts_main_data();
bts->mcs_lqual_ranges[0].high = atoi(argv[0]);
bts->mcs_lqual_ranges[1].low = atoi(argv[1]);
bts->mcs_lqual_ranges[1].high = atoi(argv[2]);
bts->mcs_lqual_ranges[2].low = atoi(argv[3]);
bts->mcs_lqual_ranges[2].high = atoi(argv[4]);
bts->mcs_lqual_ranges[3].low = atoi(argv[5]);
bts->mcs_lqual_ranges[3].high = atoi(argv[6]);
bts->mcs_lqual_ranges[4].low = atoi(argv[7]);
bts->mcs_lqual_ranges[4].high = atoi(argv[8]);
bts->mcs_lqual_ranges[5].low = atoi(argv[9]);
bts->mcs_lqual_ranges[5].high = atoi(argv[10]);
bts->mcs_lqual_ranges[6].low = atoi(argv[11]);
bts->mcs_lqual_ranges[6].high = atoi(argv[12]);
bts->mcs_lqual_ranges[7].low = atoi(argv[13]);
bts->mcs_lqual_ranges[7].high = atoi(argv[14]);
bts->mcs_lqual_ranges[8].low = atoi(argv[15]);
return CMD_SUCCESS;
}
DEFUN(cfg_pcu_sock,
cfg_pcu_sock_cmd,
"pcu-socket PATH",
@ -1079,6 +1151,7 @@ int pcu_vty_init(const struct log_info *cat)
install_element(PCU_NODE, &cfg_pcu_cs_downgrade_thrsh_cmd);
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_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);