aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bts.h1
-rw-r--r--src/gprs_ms.cpp33
-rw-r--r--src/gprs_ms.h5
-rw-r--r--src/pcu_main.cpp1
-rw-r--r--src/pcu_vty.c34
-rw-r--r--tests/ms/MsTest.cpp38
-rw-r--r--tests/ms/MsTest.err2
-rw-r--r--tests/ms/MsTest.ok2
8 files changed, 111 insertions, 5 deletions
diff --git a/src/bts.h b/src/bts.h
index 0c5b47a0..2ed50307 100644
--- a/src/bts.h
+++ b/src/bts.h
@@ -149,6 +149,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[4];
+ uint16_t cs_downgrade_threshold; /* downgrade if less packets left (DL) */
/* 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 b40e1eac..2cfedc3b 100644
--- a/src/gprs_ms.cpp
+++ b/src/gprs_ms.cpp
@@ -485,3 +485,36 @@ void GprsMs::update_l1_meas(const pcu_l1_meas *meas)
}
}
}
+
+uint8_t GprsMs::current_cs_dl() const
+{
+ uint8_t cs = m_current_cs_dl;
+ size_t unencoded_octets;
+
+ if (!m_bts)
+ return cs;
+
+ unencoded_octets = m_llc_queue.octets();
+
+ /* If the DL TBF is active, add number of unencoded chunk octets */
+ if (m_dl_tbf)
+ unencoded_octets = m_dl_tbf->m_llc.chunk_size();
+
+ /* There are many unencoded octets, don't reduce */
+ if (unencoded_octets >= m_bts->bts_data()->cs_downgrade_threshold)
+ return cs;
+
+ /* RF conditions are good, don't reduce */
+ if (m_nack_rate_dl < m_bts->bts_data()->cs_adj_lower_limit)
+ return cs;
+
+ /* The throughput would probably be better if the CS level was reduced */
+ cs -= 1;
+
+ /* CS-2 doesn't gain throughput with small packets, further reduce to CS-1 */
+ if (cs == 2)
+ cs -= 1;
+
+ return cs;
+}
+
diff --git a/src/gprs_ms.h b/src/gprs_ms.h
index 05387239..3d0195ce 100644
--- a/src/gprs_ms.h
+++ b/src/gprs_ms.h
@@ -170,11 +170,6 @@ inline uint8_t GprsMs::ms_class() const
return m_ms_class;
}
-inline uint8_t GprsMs::current_cs_dl() const
-{
- return m_current_cs_dl;
-}
-
inline uint8_t GprsMs::current_cs_ul() const
{
return m_current_cs_ul;
diff --git a/src/pcu_main.cpp b/src/pcu_main.cpp
index 416e48f3..3efdd843 100644
--- a/src/pcu_main.cpp
+++ b/src/pcu_main.cpp
@@ -187,6 +187,7 @@ 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;
+ bts->cs_downgrade_threshold = 200;
msgb_set_talloc_ctx(tall_pcu_ctx);
diff --git a/src/pcu_vty.c b/src/pcu_vty.c
index 8db025e6..05c4b7a1 100644
--- a/src/pcu_vty.c
+++ b/src/pcu_vty.c
@@ -90,6 +90,12 @@ static int config_write_pcu(struct vty *vty)
else
vty_out(vty, " no cs threshold%s", VTY_NEWLINE);
+ if (bts->cs_downgrade_threshold)
+ vty_out(vty, " cs downgrade-threshold %d%s",
+ bts->cs_downgrade_threshold, VTY_NEWLINE);
+ else
+ vty_out(vty, " no cs downgrade-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,
@@ -609,6 +615,32 @@ DEFUN(cfg_pcu_no_cs_err_limits,
return CMD_SUCCESS;
}
+#define CS_DOWNGRADE_STR "set threshold for data size based CS downgrade\n"
+DEFUN(cfg_pcu_cs_downgrade_thrsh,
+ cfg_pcu_cs_downgrade_thrsh_cmd,
+ "cs downgrade-threshold <1-10000>",
+ CS_STR CS_DOWNGRADE_STR "downgrade if less octets left\n")
+{
+ struct gprs_rlcmac_bts *bts = bts_main_data();
+
+ bts->cs_downgrade_threshold = atoi(argv[0]);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_pcu_no_cs_downgrade_thrsh,
+ cfg_pcu_no_cs_downgrade_thrsh_cmd,
+ "no cs downgrade-threshold",
+ CS_STR CS_DOWNGRADE_STR)
+{
+ struct gprs_rlcmac_bts *bts = bts_main_data();
+
+ bts->cs_downgrade_threshold = 0;
+
+ 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>",
@@ -729,6 +761,8 @@ 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_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_queue_lifetime_cmd);
install_element(PCU_NODE, &cfg_pcu_queue_lifetime_inf_cmd);
diff --git a/tests/ms/MsTest.cpp b/tests/ms/MsTest.cpp
index 403de439..f2faefc3 100644
--- a/tests/ms/MsTest.cpp
+++ b/tests/ms/MsTest.cpp
@@ -24,6 +24,7 @@
#include "gprs_debug.h"
#include "gprs_ms.h"
#include "gprs_ms_storage.h"
+#include "bts.h"
extern "C" {
#include "pcu_vty.h"
@@ -468,6 +469,42 @@ static void test_ms_timeout()
printf("=== end %s ===\n", __func__);
}
+static void test_ms_cs_selection()
+{
+ BTS the_bts;
+ gprs_rlcmac_bts *bts = the_bts.bts_data();
+ uint32_t tlli = 0xffeeddbb;
+
+ gprs_rlcmac_dl_tbf *dl_tbf;
+ GprsMs *ms;
+
+ printf("=== start %s ===\n", __func__);
+
+ bts->initial_cs_dl = 4;
+ bts->initial_cs_ul = 1;
+ bts->cs_downgrade_threshold = 0;
+
+ ms = new GprsMs(&the_bts, tlli);
+
+ OSMO_ASSERT(ms->is_idle());
+
+ dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
+ dl_tbf->direction = GPRS_RLCMAC_DL_TBF;
+
+ dl_tbf->set_ms(ms);
+ OSMO_ASSERT(!ms->is_idle());
+
+ OSMO_ASSERT(ms->current_cs_dl() == 4);
+
+ bts->cs_downgrade_threshold = 200;
+
+ OSMO_ASSERT(ms->current_cs_dl() == 3);
+
+ talloc_free(dl_tbf);
+
+ printf("=== end %s ===\n", __func__);
+}
+
static const struct log_info_cat default_categories[] = {
{"DPCU", "", "GPRS Packet Control Unit (PCU)", LOGL_INFO, 1},
};
@@ -507,6 +544,7 @@ int main(int argc, char **argv)
test_ms_change_tlli();
test_ms_storage();
test_ms_timeout();
+ test_ms_cs_selection();
if (getenv("TALLOC_REPORT_FULL"))
talloc_report_full(tall_pcu_ctx, stderr);
diff --git a/tests/ms/MsTest.err b/tests/ms/MsTest.err
index 9e9df557..ed53f482 100644
--- a/tests/ms/MsTest.err
+++ b/tests/ms/MsTest.err
@@ -54,3 +54,5 @@ Detaching TBF from MS object, TLLI = 0xffeeddbb, TBF = TBF(TFI=0 TLLI=0x00000000
Detaching TBF from MS object, TLLI = 0xffeeddbb, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL)
Timeout for MS object, TLLI = 0xffeeddbb
Destroying MS object, TLLI = 0xffeeddbb
+Creating MS object, TLLI = 0xffeeddbb
+Attaching TBF to MS object, TLLI = 0xffeeddbb, TBF = TBF(TFI=0 TLLI=0xffeeddbb DIR=DL STATE=NULL)
diff --git a/tests/ms/MsTest.ok b/tests/ms/MsTest.ok
index c49e840a..f14cceb6 100644
--- a/tests/ms/MsTest.ok
+++ b/tests/ms/MsTest.ok
@@ -16,3 +16,5 @@
ms_active() was called
ms_idle() was called
=== end test_ms_timeout ===
+=== start test_ms_cs_selection ===
+=== end test_ms_cs_selection ===