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 ===