aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bts.h1
-rw-r--r--src/gprs_ms.cpp48
-rw-r--r--src/pcu_main.cpp9
-rw-r--r--src/pcu_vty.c45
4 files changed, 95 insertions, 8 deletions
diff --git a/src/bts.h b/src/bts.h
index 8233b637..0c5b47a0 100644
--- a/src/bts.h
+++ b/src/bts.h
@@ -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 */
diff --git a/src/gprs_ms.cpp b/src/gprs_ms.cpp
index 189e4bd2..cc211713 100644
--- a/src/gprs_ms.cpp
+++ b/src/gprs_ms.cpp
@@ -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)
diff --git a/src/pcu_main.cpp b/src/pcu_main.cpp
index cecf786e..416e48f3 100644
--- a/src/pcu_main.cpp
+++ b/src/pcu_main.cpp
@@ -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);
diff --git a/src/pcu_vty.c b/src/pcu_vty.c
index 355f5440..8db025e6 100644
--- a/src/pcu_vty.c
+++ b/src/pcu_vty.c
@@ -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);