tbf_dl: make preemptive retransmission optional

Since [1], OsmoPCU already starts to retransmit downlink blocks before
the MS has had a chance to receive them and/or send the related
acknowledgement in uplink. Make this optional with the new VTY option
"no dl-tbf-preemptive-retransmission".

[1] e25b5b91f60f20f61096bc6199a05b58ee6c6328 ("tbf: Only create dummy frames if necessary")
Related: OS#2408
Change-Id: Id08aed513d4033aa0d4324c6ce07cbb2852f2f92
diff --git a/src/pcu_vty.c b/src/pcu_vty.c
index 1e4f50c..a566e73 100644
--- a/src/pcu_vty.c
+++ b/src/pcu_vty.c
@@ -254,6 +254,8 @@
 	if (bts->dl_tbf_idle_msec)
 		vty_out(vty, " dl-tbf-idle-time %d%s", bts->dl_tbf_idle_msec,
 			VTY_NEWLINE);
+	if (!bts->dl_tbf_preemptive_retransmission)
+		vty_out(vty, " no dl-tbf-preemptive-retransmission%s", VTY_NEWLINE);
 	if (strcmp(bts->pcu_sock_path, PCU_SOCK_DEFAULT))
 		vty_out(vty, " pcu-socket %s%s", bts->pcu_sock_path, VTY_NEWLINE);
 
@@ -870,6 +872,32 @@
 	return CMD_SUCCESS;
 }
 
+#define RETRANSMISSION_STR "retransmit blocks even before the MS had a chance to receive them (better throughput," \
+			   " less readable traces)"
+DEFUN(cfg_pcu_dl_tbf_preemptive_retransmission,
+      cfg_pcu_dl_tbf_preemptive_retransmission_cmd,
+      "dl-tbf-preemptive-retransmission",
+      RETRANSMISSION_STR " (enabled by default)")
+{
+	struct gprs_rlcmac_bts *bts = bts_main_data();
+
+	bts->dl_tbf_preemptive_retransmission = true;
+
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_pcu_no_dl_tbf_preemptive_retransmission,
+      cfg_pcu_no_dl_tbf_preemptive_retransmission_cmd,
+      "no dl-tbf-preemptive-retransmission",
+      NO_STR RETRANSMISSION_STR)
+{
+	struct gprs_rlcmac_bts *bts = bts_main_data();
+
+	bts->dl_tbf_preemptive_retransmission = false;
+
+	return CMD_SUCCESS;
+}
+
 #define MS_IDLE_TIME_STR "keep an idle MS object alive for the time given\n"
 DEFUN(cfg_pcu_ms_idle_time,
       cfg_pcu_ms_idle_time_cmd,
@@ -1215,6 +1243,8 @@
 	install_element(PCU_NODE, &cfg_pcu_gamma_cmd);
 	install_element(PCU_NODE, &cfg_pcu_dl_tbf_idle_time_cmd);
 	install_element(PCU_NODE, &cfg_pcu_no_dl_tbf_idle_time_cmd);
+	install_element(PCU_NODE, &cfg_pcu_dl_tbf_preemptive_retransmission_cmd);
+	install_element(PCU_NODE, &cfg_pcu_no_dl_tbf_preemptive_retransmission_cmd);
 	install_element(PCU_NODE, &cfg_pcu_ms_idle_time_cmd);
 	install_element(PCU_NODE, &cfg_pcu_no_ms_idle_time_cmd);
 	install_element(PCU_NODE, &cfg_pcu_gsmtap_categ_cmd);