aboutsummaryrefslogtreecommitdiffstats
path: root/src/pcu_vty.c
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2015-07-17 16:39:09 +0200
committerJacob Erlbeck <jerlbeck@sysmocom.de>2015-07-21 19:22:36 +0200
commitd4ad731baecb1993481941b0cbb6b6d512708572 (patch)
tree1f2b8ecc13a1dd0462fb4a60187a396b009b377b /src/pcu_vty.c
parent4f666bc1136eb581d11dc47741928725c76b09c6 (diff)
llc: Use CoDel to drop packages from the LLC queue
Currently packets are only dropped if they have reached their maximum life time. This leads to LLC queues being constantly filled under load, increasing the latency up to the maximum life time. This kind of bufferbloat hinders TCP's congestion avoidance algorithms. To keep the queues short, the CoDel active queue management algorithm can be used. This commit changes to llc_dequeue method to apply the CoDel algorithm to selectively drop LLC frames before they passed to the TBF layer to be encoded in BSNs. This feature is currently disabled by default. The CoDel state is managed per MS since the LLC queues are also kept in the MS objects. Note that there is still some buffering in the TBF objects, in the worst case (CS4) 3.5kByte + LLC-MTU octets are stored there. The resulting additional packet delay is not (yet) taken into account for CoDel. Also note that configuration changes are applied to new MS objects only. The following VTY commands are added to the 'pcu' node: - queue codel activates CoDel, the interval is selected by the implementation - queue codel interval <1-1000> activates CoDel with a fixed interval given in centiseconds (10ms-10s) - no queue codel deactivates CoDel Which interval value to use is still an open issue. For high speed links (e.g. Ethernet), CoDel suggests 100ms. For slower links, the expected RTT is recommended. The current implementation uses a default value of 2000ms. Measurements: Note that the following measurements depend on several other factors, most notably the interaction with the SGSN's flow control. They are just examples to give an idea how CoDel might influence some parameters. The measurements have been done with a single E71, first with a running ping only (Idle), then with an additional TCP download of a 360k file (Busy). The CoDel interval was set to 1s. - Idle : ping ~400ms, avg queue delay 0ms, dropped 0 - Busy, No CoDel: ping ~6s, avg queue delay 4-6s, dropped 0, scheduled 948, duration 54s - Busy, CoDel: ping 500-1500ms, avg queue delay ~600ms, dropped 77, scheduled 1040, duration 60s More measurements with two MS downloading in parallel (two independant measurements per case). - Busy, No CoDel: dropped 0, scheduled 1883, duration 121s dropped 19, scheduled 2003, duration 133s - Busy, CoDel: dropped 22, scheduled 1926, duration 116s dropped 22, scheduled 1955, duration 108s Sponsored-by: On-Waves ehf
Diffstat (limited to 'src/pcu_vty.c')
-rw-r--r--src/pcu_vty.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/pcu_vty.c b/src/pcu_vty.c
index ed708f8d..94f89b56 100644
--- a/src/pcu_vty.c
+++ b/src/pcu_vty.c
@@ -116,6 +116,14 @@ static int config_write_pcu(struct vty *vty)
if (bts->llc_idle_ack_csec)
vty_out(vty, " queue idle-ack-delay %d%s", bts->llc_idle_ack_csec,
VTY_NEWLINE);
+ if (bts->llc_codel_interval_msec == LLC_CODEL_USE_DEFAULT)
+ vty_out(vty, " queue codel%s", VTY_NEWLINE);
+ else if (bts->llc_codel_interval_msec == LLC_CODEL_DISABLE)
+ vty_out(vty, " no queue codel%s", VTY_NEWLINE);
+ else
+ vty_out(vty, " queue codel interval %d%s",
+ bts->llc_codel_interval_msec/10, VTY_NEWLINE);
+
if (bts->alloc_algorithm == alloc_algorithm_a)
vty_out(vty, " alloc-algorithm a%s", VTY_NEWLINE);
if (bts->alloc_algorithm == alloc_algorithm_b)
@@ -419,6 +427,46 @@ DEFUN(cfg_pcu_no_queue_hysteresis,
return CMD_SUCCESS;
}
+#define QUEUE_CODEL_STR "Set CoDel queue management\n"
+
+DEFUN(cfg_pcu_queue_codel,
+ cfg_pcu_queue_codel_cmd,
+ "queue codel",
+ QUEUE_STR QUEUE_CODEL_STR)
+{
+ struct gprs_rlcmac_bts *bts = bts_main_data();
+
+ bts->llc_codel_interval_msec = LLC_CODEL_USE_DEFAULT;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_pcu_queue_codel_interval,
+ cfg_pcu_queue_codel_interval_cmd,
+ "queue codel interval <1-1000>",
+ QUEUE_STR QUEUE_CODEL_STR "Specify interval\n" "Interval in centi-seconds")
+{
+ struct gprs_rlcmac_bts *bts = bts_main_data();
+ uint16_t csec = atoi(argv[0]);
+
+ bts->llc_codel_interval_msec = 10*csec;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_pcu_no_queue_codel,
+ cfg_pcu_no_queue_codel_cmd,
+ "no queue codel",
+ NO_STR QUEUE_STR QUEUE_CODEL_STR)
+{
+ struct gprs_rlcmac_bts *bts = bts_main_data();
+
+ bts->llc_codel_interval_msec = LLC_CODEL_DISABLE;
+
+ return CMD_SUCCESS;
+}
+
+
#define QUEUE_IDLE_ACK_STR "Request an ACK after the last DL LLC frame in centi-seconds\n"
DEFUN(cfg_pcu_queue_idle_ack_delay,
@@ -776,6 +824,9 @@ int pcu_vty_init(const struct log_info *cat)
install_element(PCU_NODE, &cfg_pcu_no_queue_lifetime_cmd);
install_element(PCU_NODE, &cfg_pcu_queue_hysteresis_cmd);
install_element(PCU_NODE, &cfg_pcu_no_queue_hysteresis_cmd);
+ install_element(PCU_NODE, &cfg_pcu_queue_codel_cmd);
+ install_element(PCU_NODE, &cfg_pcu_queue_codel_interval_cmd);
+ install_element(PCU_NODE, &cfg_pcu_no_queue_codel_cmd);
install_element(PCU_NODE, &cfg_pcu_queue_idle_ack_delay_cmd);
install_element(PCU_NODE, &cfg_pcu_no_queue_idle_ack_delay_cmd);
install_element(PCU_NODE, &cfg_pcu_alloc_cmd);