tcp: add loss signal to cc algo
Type:feature
Change-Id: Ibe1a4c555b55fb929d55b02599aaf099ed522cdf
Signed-off-by: Florin Coras <fcoras@cisco.com>
diff --git a/src/vnet/tcp/tcp.h b/src/vnet/tcp/tcp.h
index 8b943cd..2bc6f22 100644
--- a/src/vnet/tcp/tcp.h
+++ b/src/vnet/tcp/tcp.h
@@ -379,13 +379,14 @@
{
const char *name;
uword (*unformat_cfg) (unformat_input_t * input);
+ void (*init) (tcp_connection_t * tc);
+ void (*cleanup) (tcp_connection_t * tc);
void (*rcv_ack) (tcp_connection_t * tc, tcp_rate_sample_t *rs);
void (*rcv_cong_ack) (tcp_connection_t * tc, tcp_cc_ack_t ack,
tcp_rate_sample_t *rs);
void (*congestion) (tcp_connection_t * tc);
+ void (*loss) (tcp_connection_t * tc);
void (*recovered) (tcp_connection_t * tc);
- void (*init) (tcp_connection_t * tc);
- void (*cleanup) (tcp_connection_t * tc);
};
/* *INDENT-ON* */
@@ -900,7 +901,7 @@
int tcp_fast_retransmit (tcp_worker_ctx_t * wrk, tcp_connection_t * tc,
u32 burst_size);
void tcp_cc_init_congestion (tcp_connection_t * tc);
-void tcp_cc_fastrecovery_exit (tcp_connection_t * tc);
+void tcp_cc_fastrecovery_clear (tcp_connection_t * tc);
fib_node_index_t tcp_lookup_rmt_in_fib (tcp_connection_t * tc);
@@ -958,6 +959,12 @@
tc->cc_algo->rcv_cong_ack (tc, ack_type, rs);
}
+static inline void
+tcp_cc_loss (tcp_connection_t * tc)
+{
+ tc->cc_algo->loss (tc);
+}
+
always_inline void
tcp_timer_set (tcp_connection_t * tc, u8 timer_id, u32 interval)
{
diff --git a/src/vnet/tcp/tcp_cubic.c b/src/vnet/tcp/tcp_cubic.c
index 80d4308..0b4226d 100644
--- a/src/vnet/tcp/tcp_cubic.c
+++ b/src/vnet/tcp/tcp_cubic.c
@@ -106,6 +106,18 @@
}
static void
+cubic_loss (tcp_connection_t * tc)
+{
+ cubic_data_t *cd = (cubic_data_t *) tcp_cc_data (tc);
+
+ tc->ssthresh = clib_max (tc->cwnd * beta_cubic, 2 * tc->snd_mss);
+ tc->cwnd = tcp_loss_wnd (tc);
+ cd->t_start = cubic_time (tc->c_thread_index);
+ cd->K = 0;
+ cd->w_max = 0;
+}
+
+static void
cubic_recovered (tcp_connection_t * tc)
{
cubic_data_t *cd = (cubic_data_t *) tcp_cc_data (tc);
@@ -217,6 +229,7 @@
.name = "cubic",
.unformat_cfg = cubic_unformat_config,
.congestion = cubic_congestion,
+ .loss = cubic_loss,
.recovered = cubic_recovered,
.rcv_ack = cubic_rcv_ack,
.rcv_cong_ack = newreno_rcv_cong_ack,
diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c
index 848028f..5a7ae5e 100644
--- a/src/vnet/tcp/tcp_input.c
+++ b/src/vnet/tcp/tcp_input.c
@@ -1183,14 +1183,11 @@
TCP_EVT_DBG (TCP_EVT_CC_EVT, tc, 3);
}
-#ifndef CLIB_MARCH_VARIANT
-void
-tcp_cc_fastrecovery_exit (tcp_connection_t * tc)
+static inline void
+tcp_cc_fastrecovery_clear_inline (tcp_connection_t * tc)
{
- tc->cc_algo->recovered (tc);
tc->snd_rxt_bytes = 0;
tc->rcv_dupacks = 0;
- tc->snd_rxt_bytes = 0;
tc->rtt_ts = 0;
tcp_fastrecovery_off (tc);
@@ -1198,6 +1195,20 @@
TCP_EVT_DBG (TCP_EVT_CC_EVT, tc, 3);
}
+
+static void
+tcp_cc_fastrecovery_exit (tcp_connection_t * tc)
+{
+ tc->cc_algo->recovered (tc);
+ tcp_cc_fastrecovery_clear_inline (tc);
+}
+
+#ifndef CLIB_MARCH_VARIANT
+void
+tcp_cc_fastrecovery_clear (tcp_connection_t * tc)
+{
+ tcp_cc_fastrecovery_clear_inline (tc);
+}
#endif /* CLIB_MARCH_VARIANT */
static void
diff --git a/src/vnet/tcp/tcp_newreno.c b/src/vnet/tcp/tcp_newreno.c
index 3887b34..7e37efb 100644
--- a/src/vnet/tcp/tcp_newreno.c
+++ b/src/vnet/tcp/tcp_newreno.c
@@ -15,19 +15,26 @@
#include <vnet/tcp/tcp.h>
-void
+static void
newreno_congestion (tcp_connection_t * tc)
{
tc->ssthresh = clib_max (tcp_flight_size (tc) / 2, 2 * tc->snd_mss);
}
-void
+static void
+newreno_loss (tcp_connection_t * tc)
+{
+ tc->ssthresh = clib_max (tcp_flight_size (tc) / 2, 2 * tc->snd_mss);
+ tc->cwnd = tcp_loss_wnd (tc);
+}
+
+static void
newreno_recovered (tcp_connection_t * tc)
{
tc->cwnd = tc->ssthresh;
}
-void
+static void
newreno_rcv_ack (tcp_connection_t * tc, tcp_rate_sample_t * rs)
{
if (tcp_in_slowstart (tc))
@@ -72,7 +79,7 @@
}
}
-void
+static void
newreno_conn_init (tcp_connection_t * tc)
{
tc->ssthresh = tc->snd_wnd;
@@ -82,6 +89,7 @@
const static tcp_cc_algorithm_t tcp_newreno = {
.name = "newreno",
.congestion = newreno_congestion,
+ .loss = newreno_loss,
.recovered = newreno_recovered,
.rcv_ack = newreno_rcv_ack,
.rcv_cong_ack = newreno_rcv_cong_ack,
diff --git a/src/vnet/tcp/tcp_output.c b/src/vnet/tcp/tcp_output.c
index 7cf85c3..8537b1f 100644
--- a/src/vnet/tcp/tcp_output.c
+++ b/src/vnet/tcp/tcp_output.c
@@ -1472,26 +1472,22 @@
* Reset congestion control, switch cwnd to loss window and try again.
*/
static void
-tcp_rxt_timeout_cc (tcp_connection_t * tc)
+tcp_cc_init_rxt_timeout (tcp_connection_t * tc)
{
TCP_EVT_DBG (TCP_EVT_CC_EVT, tc, 6);
tc->prev_ssthresh = tc->ssthresh;
tc->prev_cwnd = tc->cwnd;
- /* Cleanly recover cc (also clears up fast retransmit) */
+ /* Clear fast recovery state if needed */
if (tcp_in_fastrecovery (tc))
- {
- /* TODO be less aggressive about this */
- scoreboard_clear (&tc->sack_sb);
- tcp_cc_fastrecovery_exit (tc);
- }
- else
- tc->rcv_dupacks = 0;
+ tcp_cc_fastrecovery_clear (tc);
+
+ /* Let cc algo decide loss cwnd and ssthresh */
+ tcp_cc_loss (tc);
/* Start again from the beginning */
- tc->cc_algo->congestion (tc);
- tc->cwnd = tcp_loss_wnd (tc);
tc->snd_congestion = tc->snd_nxt;
+ tc->rcv_dupacks = 0;
tc->rtt_ts = 0;
tc->cwnd_acc_bytes = 0;
tcp_connection_tx_pacer_reset (tc, tc->cwnd, 2 * tc->snd_mss);
@@ -1577,11 +1573,12 @@
* to first un-acked byte */
tc->rto_boff += 1;
+ /* TODO be less aggressive about clearing scoreboard */
+ scoreboard_clear (&tc->sack_sb);
+
/* First retransmit timeout */
if (tc->rto_boff == 1)
- tcp_rxt_timeout_cc (tc);
- else
- scoreboard_clear (&tc->sack_sb);
+ tcp_cc_init_rxt_timeout (tc);
if (tc->flags & TCP_CONN_RATE_SAMPLE)
tcp_bt_flush_samples (tc);