ms: Add UL CS selection based on L1 link quality

Currently the UL CS values are set to the corresponding DL CS value,
eventually limited by a maximum value. This approach does not reflect
the general situation of the RF link between ME and BTS, which is
rather asymmetric e.g. due to a lower degree of TX efficiency of the
built-in antenna. This means, that UL and DL CS control should be
decoupled for better results.

This commit adds automatic UL CS selection based on the link quality
measurement parameter. Each coding scheme is mapped to a link quality
range. If the link quality value leaves that range, the current UL CS
value is increased/decreased accordingly. This value will be copied
when the next PACKET_UPLINK_ACK_NACK or PACKET_UPLINK_ASSIGMENT is
sent to the MS.

The following VTY command will be added to the config-pcu node:

-  cs link-quality-ranges cs1 <0-35> cs2 <0-35> <0-35>
          cs3 <0-35> <0-35> cs4 <0-35>

which sets the ranges for the four coding schemes. For instance the
example below reflects the current default values:

  cs link-quality-ranges cs1 6 cs2 5 8 cs3 7 13 cs4 12

set the following ranges, where the overlapping is used to configure
a hysteresis:

  CS1: -inf ..  6
  CS2:    5 ..  8
  CS3:    7 .. 13
  CS4:   12 .. inf

Sponsored-by: On-Waves ehf
This commit is contained in:
Jacob Erlbeck 2015-06-09 09:44:36 +02:00
parent e4bcb62dbf
commit 94cde130ca
4 changed files with 95 additions and 8 deletions

View File

@ -148,6 +148,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];
/* TBF handling, make private or move into TBFController */
/* list of uplink TBFs */

View File

@ -367,7 +367,7 @@ void GprsMs::update_error_rate(gprs_rlcmac_tbf *tbf, int error_rate)
{
struct gprs_rlcmac_bts *bts_data;
int64_t now;
uint8_t max_cs_ul = 4, max_cs_dl = 4;
uint8_t max_cs_dl = 4;
OSMO_ASSERT(m_bts != NULL);
bts_data = m_bts->bts_data();
@ -377,18 +377,15 @@ void GprsMs::update_error_rate(gprs_rlcmac_tbf *tbf, int error_rate)
now = now_msec();
if (bts_data->max_cs_ul)
max_cs_ul = bts_data->max_cs_ul;
if (bts_data->max_cs_dl)
max_cs_dl = bts_data->max_cs_dl;
/* TODO: Check for TBF direction */
/* TODO: Support different CS values for UL and DL */
if (error_rate > bts_data->cs_adj_upper_limit) {
if (m_current_cs_dl > 1) {
m_current_cs_dl -= 1;
m_current_cs_ul = m_current_cs_dl;
LOGP(DRLCMACDL, LOGL_INFO,
"MS (IMSI %s): High error rate %d%%, "
"reducing CS level to %d\n",
@ -399,12 +396,10 @@ void GprsMs::update_error_rate(gprs_rlcmac_tbf *tbf, int error_rate)
if (m_current_cs_dl < max_cs_dl) {
if (now - m_last_cs_not_low > 1000) {
m_current_cs_dl += 1;
if (m_current_cs_dl <= max_cs_ul)
m_current_cs_ul = m_current_cs_dl;
LOGP(DRLCMACDL, LOGL_INFO,
"MS (IMSI %s): Low error rate %d%%, "
"increasing CS level to %d\n",
"increasing DL CS level to %d\n",
imsi(), error_rate, m_current_cs_dl);
m_last_cs_not_low = now;
} else {
@ -424,6 +419,43 @@ void GprsMs::update_error_rate(gprs_rlcmac_tbf *tbf, int error_rate)
void GprsMs::update_l1_meas(const pcu_l1_meas *meas)
{
struct gprs_rlcmac_bts *bts_data;
uint8_t max_cs_ul = 4;
OSMO_ASSERT(m_bts != NULL);
bts_data = m_bts->bts_data();
if (bts_data->max_cs_ul)
max_cs_ul = bts_data->max_cs_ul;
if (meas->have_link_qual) {
int old_link_qual = meas->link_qual;
int low = bts_data->cs_lqual_ranges[current_cs_ul()-1].low;
int high = bts_data->cs_lqual_ranges[current_cs_ul()-1].high;
uint8_t new_cs_ul = m_current_cs_ul;
if (m_l1_meas.have_link_qual)
old_link_qual = m_l1_meas.link_qual;
if (meas->link_qual < low && old_link_qual < low)
new_cs_ul = m_current_cs_ul - 1;
else if (meas->link_qual > high && old_link_qual > high &&
m_current_cs_ul < max_cs_ul)
new_cs_ul = m_current_cs_ul + 1;
if (m_current_cs_ul != new_cs_ul) {
LOGP(DRLCMACDL, LOGL_INFO,
"MS (IMSI %s): "
"Link quality %ddB (%ddB) left window [%d, %d], "
"modifying uplink CS level: %d -> %d\n",
imsi(), meas->link_qual, old_link_qual,
low, high,
m_current_cs_ul, new_cs_ul);
m_current_cs_ul = new_cs_ul;
}
}
if (meas->have_rssi)
m_l1_meas.set_rssi(meas->rssi);
if (meas->have_bto)

View File

@ -178,6 +178,15 @@ 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;
/* CS-1 to CS-4 */
bts->cs_lqual_ranges[0].low = -256;
bts->cs_lqual_ranges[0].high = 6;
bts->cs_lqual_ranges[1].low = 5;
bts->cs_lqual_ranges[1].high = 8;
bts->cs_lqual_ranges[2].low = 7;
bts->cs_lqual_ranges[2].high = 13;
bts->cs_lqual_ranges[3].low = 12;
bts->cs_lqual_ranges[3].high = 256;
msgb_set_talloc_ctx(tall_pcu_ctx);

View File

@ -90,6 +90,15 @@ static int config_write_pcu(struct vty *vty)
else
vty_out(vty, " no cs threshold%s", VTY_NEWLINE);
vty_out(vty, " cs link-quality-ranges cs1 %d cs2 %d %d cs3 %d %d cs4 %d%s",
bts->cs_lqual_ranges[0].high,
bts->cs_lqual_ranges[1].low,
bts->cs_lqual_ranges[1].high,
bts->cs_lqual_ranges[2].low,
bts->cs_lqual_ranges[2].high,
bts->cs_lqual_ranges[3].low,
VTY_NEWLINE);
if (bts->force_llc_lifetime == 0xffff)
vty_out(vty, " queue lifetime infinite%s", VTY_NEWLINE);
else if (bts->force_llc_lifetime)
@ -600,6 +609,41 @@ DEFUN(cfg_pcu_no_cs_err_limits,
return CMD_SUCCESS;
}
DEFUN(cfg_pcu_cs_lqual_ranges,
cfg_pcu_cs_lqual_ranges_cmd,
"cs link-quality-ranges cs1 <0-35> cs2 <0-35> <0-35> cs3 <0-35> <0-35> cs4 <0-35>",
CS_STR "Set link quality ranges\n"
"Set quality range for CS-1 (high value only)\n"
"CS-1 high (dB)\n"
"Set quality range for CS-2\n"
"CS-2 low (dB)\n"
"CS-2 high (dB)\n"
"Set quality range for CS-3\n"
"CS-3 low (dB)\n"
"CS-3 high (dB)\n"
"Set quality range for CS-4 (low value only)\n"
"CS-4 low (dB)\n")
{
struct gprs_rlcmac_bts *bts = bts_main_data();
uint8_t cs1_high = atoi(argv[0]);
uint8_t cs2_low = atoi(argv[1]);
uint8_t cs2_high = atoi(argv[2]);
uint8_t cs3_low = atoi(argv[3]);
uint8_t cs3_high = atoi(argv[4]);
uint8_t cs4_low = atoi(argv[5]);
bts->cs_lqual_ranges[0].high = cs1_high;
bts->cs_lqual_ranges[1].low = cs2_low;
bts->cs_lqual_ranges[1].high = cs2_high;
bts->cs_lqual_ranges[2].low = cs3_low;
bts->cs_lqual_ranges[2].high = cs3_high;
bts->cs_lqual_ranges[3].low = cs4_low;
return CMD_SUCCESS;
}
DEFUN(show_tbf,
show_tbf_cmd,
"show tbf all",
@ -685,6 +729,7 @@ int pcu_vty_init(const struct log_info *cat)
install_element(PCU_NODE, &cfg_pcu_no_cs_max_cmd);
install_element(PCU_NODE, &cfg_pcu_cs_err_limits_cmd);
install_element(PCU_NODE, &cfg_pcu_no_cs_err_limits_cmd);
install_element(PCU_NODE, &cfg_pcu_cs_lqual_ranges_cmd);
install_element(PCU_NODE, &cfg_pcu_queue_lifetime_cmd);
install_element(PCU_NODE, &cfg_pcu_queue_lifetime_inf_cmd);
install_element(PCU_NODE, &cfg_pcu_no_queue_lifetime_cmd);