From 1caf7f11c0197a912ccc28e67e4e9af75323af80 Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Thu, 16 Jul 2020 10:05:02 -0700 Subject: [PATCH] tcp: track pending timers Also removes delack timer and reuses the u32 for the pending timers list. Type: fix Ticket: VPP-1923 Signed-off-by: Florin Coras Change-Id: I4edbb72d5b2aa5e14f87659f49e675af1e834aca --- src/vnet/tcp/tcp.c | 9 ++++++++- src/vnet/tcp/tcp.h | 1 - src/vnet/tcp/tcp_input.c | 28 ---------------------------- src/vnet/tcp/tcp_output.c | 11 ----------- src/vnet/tcp/tcp_timer.h | 1 + src/vnet/tcp/tcp_types.h | 2 +- 6 files changed, 10 insertions(+), 42 deletions(-) diff --git a/src/vnet/tcp/tcp.c b/src/vnet/tcp/tcp.c index 3703a4aa358..c30a69304bc 100644 --- a/src/vnet/tcp/tcp.c +++ b/src/vnet/tcp/tcp.c @@ -1064,7 +1064,6 @@ tcp_timer_waitclose_handler (tcp_connection_t * tc) static timer_expiration_handler *timer_expiration_handlers[TCP_N_TIMERS] = { tcp_timer_retransmit_handler, - tcp_timer_delack_handler, tcp_timer_persist_handler, tcp_timer_waitclose_handler, tcp_timer_retransmit_syn_handler, @@ -1096,6 +1095,13 @@ tcp_dispatch_pending_timers (tcp_worker_ctx_t * wrk) if (PREDICT_FALSE (!tc)) continue; + /* Skip if the timer is not pending. Probably it was reset while + * wating for dispatch */ + if (PREDICT_FALSE (!(tc->pending_timers & (1 << timer_id)))) + continue; + + tc->pending_timers &= ~(1 << timer_id); + /* Skip timer if it was rearmed while pending dispatch */ if (PREDICT_FALSE (tc->timers[timer_id] != TCP_TIMER_HANDLE_INVALID)) continue; @@ -1241,6 +1247,7 @@ tcp_expired_timers_dispatch (u32 * expired_timers) TCP_EVT (TCP_EVT_TIMER_POP, connection_index, timer_id); tc->timers[timer_id] = TCP_TIMER_HANDLE_INVALID; + tc->pending_timers |= (1 << timer_id); } clib_fifo_add (wrk->pending_timers, expired_timers, n_expired); diff --git a/src/vnet/tcp/tcp.h b/src/vnet/tcp/tcp.h index 5c66412dfea..91783a6e025 100644 --- a/src/vnet/tcp/tcp.h +++ b/src/vnet/tcp/tcp.h @@ -28,7 +28,6 @@ typedef void (timer_expiration_handler) (tcp_connection_t * tc); -extern timer_expiration_handler tcp_timer_delack_handler; extern timer_expiration_handler tcp_timer_retransmit_handler; extern timer_expiration_handler tcp_timer_persist_handler; extern timer_expiration_handler tcp_timer_retransmit_syn_handler; diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c index cc373f5b665..bdaa28ec3d0 100644 --- a/src/vnet/tcp/tcp_input.c +++ b/src/vnet/tcp/tcp_input.c @@ -1263,26 +1263,6 @@ tcp_session_enqueue_ooo (tcp_connection_t * tc, vlib_buffer_t * b, return TCP_ERROR_ENQUEUED_OOO; } -/** - * Check if ACK could be delayed. If ack can be delayed, it should return - * true for a full frame. If we're always acking return 0. - */ -always_inline int -tcp_can_delack (tcp_connection_t * tc) -{ - /* Send ack if ... */ - if (TCP_ALWAYS_ACK - /* just sent a rcv wnd 0 - || (tc->flags & TCP_CONN_SENT_RCV_WND0) != 0 */ - /* constrained to send ack */ - || (tc->flags & TCP_CONN_SNDACK) != 0 - /* we're almost out of tx wnd */ - || tcp_available_cc_snd_space (tc) < 4 * tc->snd_mss) - return 0; - - return 1; -} - static int tcp_buffer_discard_bytes (vlib_buffer_t * b, u32 n_bytes_to_drop) { @@ -1371,14 +1351,6 @@ in_order: /* In order data, enqueue. Fifo figures out by itself if any out-of-order * segments can be enqueued after fifo tail offset changes. */ error = tcp_session_enqueue_data (tc, b, n_data_bytes); - if (tcp_can_delack (tc)) - { - if (!tcp_timer_is_active (tc, TCP_TIMER_DELACK)) - tcp_timer_set (&wrk->timer_wheel, tc, TCP_TIMER_DELACK, - tcp_cfg.delack_time); - goto done; - } - tcp_program_ack (tc); done: diff --git a/src/vnet/tcp/tcp_output.c b/src/vnet/tcp/tcp_output.c index 46c5661f7c1..e9bff5b954a 100644 --- a/src/vnet/tcp/tcp_output.c +++ b/src/vnet/tcp/tcp_output.c @@ -1063,17 +1063,6 @@ tcp_program_retransmit (tcp_connection_t * tc) } } -/** - * Delayed ack timer handler - * - * Sends delayed ACK when timer expires - */ -void -tcp_timer_delack_handler (tcp_connection_t * tc) -{ - tcp_send_ack (tc); -} - /** * Send window update ack * diff --git a/src/vnet/tcp/tcp_timer.h b/src/vnet/tcp/tcp_timer.h index d34fdcb146d..914b5aaeeb7 100644 --- a/src/vnet/tcp/tcp_timer.h +++ b/src/vnet/tcp/tcp_timer.h @@ -31,6 +31,7 @@ always_inline void tcp_timer_reset (tcp_timer_wheel_t * tw, tcp_connection_t * tc, u8 timer_id) { ASSERT (tc->c_thread_index == vlib_get_thread_index ()); + tc->pending_timers &= ~(1 << timer_id); if (tc->timers[timer_id] == TCP_TIMER_HANDLE_INVALID) return; diff --git a/src/vnet/tcp/tcp_types.h b/src/vnet/tcp/tcp_types.h index 8b599400b8c..3cf4e9e33ef 100644 --- a/src/vnet/tcp/tcp_types.h +++ b/src/vnet/tcp/tcp_types.h @@ -62,7 +62,6 @@ typedef enum _tcp_state /** TCP timers */ #define foreach_tcp_timer \ _(RETRANSMIT, "RETRANSMIT") \ - _(DELACK, "DELAYED ACK") \ _(PERSIST, "PERSIST") \ _(WAITCLOSE, "WAIT CLOSE") \ _(RETRANSMIT_SYN, "RETRANSMIT SYN") \ @@ -281,6 +280,7 @@ typedef struct _tcp_connection u8 cfg_flags; /**< Connection configuration flags */ u16 flags; /**< Connection flags (see tcp_conn_flags_e) */ u32 timers[TCP_N_TIMERS]; /**< Timer handles into timer wheel */ + u32 pending_timers; /**< Expired timers not yet handled */ u64 segs_in; /** RFC4022/4898 tcpHCInSegs/tcpEStatsPerfSegsIn */ u64 bytes_in; /** RFC4898 tcpEStatsPerfHCDataOctetsIn */ -- 2.16.6