From a3c3265b20c2a382656957b4afd2003bddccd9bb Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Wed, 3 Jul 2019 17:47:22 -0700 Subject: tcp: add loss signal to cc algo Type:feature Change-Id: Ibe1a4c555b55fb929d55b02599aaf099ed522cdf Signed-off-by: Florin Coras --- src/vnet/tcp/tcp.h | 13 ++++++++++--- src/vnet/tcp/tcp_cubic.c | 13 +++++++++++++ src/vnet/tcp/tcp_input.c | 21 ++++++++++++++++----- src/vnet/tcp/tcp_newreno.c | 16 ++++++++++++---- src/vnet/tcp/tcp_output.c | 25 +++++++++++-------------- 5 files changed, 62 insertions(+), 26 deletions(-) diff --git a/src/vnet/tcp/tcp.h b/src/vnet/tcp/tcp.h index 8b943cdd5b5..2bc6f22ba83 100644 --- a/src/vnet/tcp/tcp.h +++ b/src/vnet/tcp/tcp.h @@ -379,13 +379,14 @@ struct _tcp_cc_algorithm { 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_sack (tcp_worker_ctx_t * wrk, tcp_connection_t * tc, 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 @@ tcp_cc_rcv_cong_ack (tcp_connection_t * tc, tcp_cc_ack_t ack_type, 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 80d4308bbb7..0b4226d6f12 100644 --- a/src/vnet/tcp/tcp_cubic.c +++ b/src/vnet/tcp/tcp_cubic.c @@ -105,6 +105,18 @@ cubic_congestion (tcp_connection_t * tc) tc->ssthresh = clib_max (tc->cwnd * beta_cubic, 2 * tc->snd_mss); } +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) { @@ -217,6 +229,7 @@ const static tcp_cc_algorithm_t tcp_cubic = { .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 848028f6940..5a7ae5eb2ab 100644 --- a/src/vnet/tcp/tcp_input.c +++ b/src/vnet/tcp/tcp_input.c @@ -1183,14 +1183,11 @@ tcp_cc_recovery_exit (tcp_connection_t * tc) 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_cc_fastrecovery_exit (tcp_connection_t * tc) 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 3887b34b7ea..7e37efb1052 100644 --- a/src/vnet/tcp/tcp_newreno.c +++ b/src/vnet/tcp/tcp_newreno.c @@ -15,19 +15,26 @@ #include -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 @@ newreno_rcv_cong_ack (tcp_connection_t * tc, tcp_cc_ack_t ack_type, } } -void +static void newreno_conn_init (tcp_connection_t * tc) { tc->ssthresh = tc->snd_wnd; @@ -82,6 +89,7 @@ newreno_conn_init (tcp_connection_t * tc) 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 7cf85c3bdce..8537b1fb772 100644 --- a/src/vnet/tcp/tcp_output.c +++ b/src/vnet/tcp/tcp_output.c @@ -1472,26 +1472,22 @@ done: * 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 @@ tcp_timer_retransmit_handler_i (u32 index, u8 is_syn) * 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); -- cgit 1.2.3-korg