tbf: Force ACK after the last DL LCC frame has been received

If the protocol layers above LLC (e.g. TCP) need an acknowledgement
to continue, it can take up to 400ms (single TS) until the MS is
polled for Ack/Nack which it can use to request an uplink TBF
quickly. The 400ms result from requesting an DL Ack/Nack every 20 RLC
blocks until all pending LLC frames have been sent.

Especially TCP's slow start mechanism can lead to a high delay at the
start of the connection, since the sender will eventually stop after
having sent the first packets (up to 4 (RFC2581) or 10 (RFC6928)).

This commit modifies append_data() to (re-)start
a timer every time it handles an LLC packet and to request an
Ack/Nack every time it expires. So if the server ceases to send IP
packets, the MS is polled in the assumption, that the server is
waiting for an ACK.

The following VTY commands are added (pcu node):

 - queue idle-ack-delay <1-65535>  timeout in centiseconds
 - no queue idle-ack-delay         disable this feature (default)

A sensible value is 10 (100ms) that at gave promising results when
testing locally.

Sponsored-by: On-Waves ehf
diff --git a/src/pcu_vty.c b/src/pcu_vty.c
index 3d9c79a..00cd6fc 100644
--- a/src/pcu_vty.c
+++ b/src/pcu_vty.c
@@ -100,6 +100,9 @@
 	if (bts->llc_discard_csec)
 		vty_out(vty, " queue hysteresis %d%s", bts->llc_discard_csec,
 			VTY_NEWLINE);
+	if (bts->llc_idle_ack_csec)
+		vty_out(vty, " queue idle-ack-delay %d%s", bts->llc_idle_ack_csec,
+			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)
@@ -217,7 +220,7 @@
 
 DEFUN(cfg_pcu_queue_hysteresis,
       cfg_pcu_queue_hysteresis_cmd,
-      "queue hysteresis <1-65534>",
+      "queue hysteresis <1-65535>",
       QUEUE_STR QUEUE_HYSTERESIS_STR "Hysteresis in centi-seconds")
 {
 	struct gprs_rlcmac_bts *bts = bts_main_data();
@@ -240,6 +243,33 @@
 	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,
+      cfg_pcu_queue_idle_ack_delay_cmd,
+      "queue idle-ack-delay <1-65535>",
+      QUEUE_STR QUEUE_IDLE_ACK_STR "Idle ACK delay in centi-seconds")
+{
+	struct gprs_rlcmac_bts *bts = bts_main_data();
+	uint8_t csec = atoi(argv[0]);
+
+	bts->llc_idle_ack_csec = csec;
+
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_pcu_no_queue_idle_ack_delay,
+      cfg_pcu_no_queue_idle_ack_delay_cmd,
+      "no queue idle-ack-delay",
+      NO_STR QUEUE_STR QUEUE_IDLE_ACK_STR)
+{
+	struct gprs_rlcmac_bts *bts = bts_main_data();
+
+	bts->llc_idle_ack_csec = 0;
+
+	return CMD_SUCCESS;
+}
+
 
 DEFUN(cfg_pcu_alloc,
       cfg_pcu_alloc_cmd,
@@ -400,6 +430,8 @@
 	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_idle_ack_delay_cmd);
+	install_element(PCU_NODE, &cfg_pcu_no_queue_idle_ack_delay_cmd);
 	install_element(PCU_NODE, &cfg_pcu_alloc_cmd);
 	install_element(PCU_NODE, &cfg_pcu_two_phase_cmd);
 	install_element(PCU_NODE, &cfg_pcu_fc_interval_cmd);