From 6080e0d15e152e38811b01306eef6719a682c007 Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Fri, 13 Mar 2020 20:39:43 +0000 Subject: [PATCH] tcp: force deschedule if no send space available Type: improvement Signed-off-by: Florin Coras Change-Id: Iae9f118f710153b6c0e390265039db7434e67ed8 --- src/vnet/session/session.c | 4 +++- src/vnet/session/session_node.c | 16 ++++++++-------- src/vnet/session/transport.c | 1 + src/vnet/session/transport.h | 4 +--- src/vnet/tcp/tcp.c | 16 ++++++++-------- src/vnet/tcp/tcp.h | 9 +++++++-- src/vnet/tcp/tcp_input.c | 7 +++++++ src/vnet/tcp/tcp_output.c | 4 +++- 8 files changed, 38 insertions(+), 23 deletions(-) diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c index 15d949c76b5..8b268c00b64 100644 --- a/src/vnet/session/session.c +++ b/src/vnet/session/session.c @@ -130,7 +130,8 @@ session_add_self_custom_tx_evt (transport_connection_t * tc, u8 has_prio) if (!(s->flags & SESSION_F_CUSTOM_TX)) { s->flags |= SESSION_F_CUSTOM_TX; - if (svm_fifo_set_event (s->tx_fifo)) + if (svm_fifo_set_event (s->tx_fifo) + || transport_connection_is_descheduled (tc)) { session_worker_t *wrk; session_evt_elt_t *elt; @@ -141,6 +142,7 @@ session_add_self_custom_tx_evt (transport_connection_t * tc, u8 has_prio) elt = session_evt_alloc_old (wrk); elt->evt.session_index = tc->s_index; elt->evt.event_type = SESSION_IO_EVT_TX; + tc->flags &= ~TRANSPORT_CONNECTION_F_DESCHED; } } } diff --git a/src/vnet/session/session_node.c b/src/vnet/session/session_node.c index b1c2428874e..b5f4321c9a8 100644 --- a/src/vnet/session/session_node.c +++ b/src/vnet/session/session_node.c @@ -872,7 +872,7 @@ session_tx_fifo_read_and_snd_i (session_worker_t * wrk, (ctx->s->session_state >= SESSION_STATE_TRANSPORT_CLOSED)) return SESSION_TX_OK; max_burst -= n_custom_tx; - if (!max_burst) + if (!max_burst || (ctx->s->flags & SESSION_F_CUSTOM_TX)) { session_evt_add_old (wrk, elt); return SESSION_TX_OK; @@ -883,18 +883,18 @@ session_tx_fifo_read_and_snd_i (session_worker_t * wrk, if (!ctx->sp.snd_space) { - /* This flow queue is "empty" so it should be re-evaluated before - * the ones that have data to send. */ - if (PREDICT_TRUE (!ctx->sp.flags)) - session_evt_add_head_old (wrk, elt); + /* If the deschedule flag was set, remove session from scheduler. + * Transport is responsible for rescheduling this session. */ + if (ctx->sp.flags & TRANSPORT_SND_F_DESCHED) + transport_connection_deschedule (ctx->tc); /* Request to postpone the session, e.g., zero-wnd and transport * is not currently probing */ else if (ctx->sp.flags & TRANSPORT_SND_F_POSTPONE) session_evt_add_old (wrk, elt); - /* If the deschedule flag was set, remove session from scheduler. - * Transport is responsible for rescheduling this session. */ + /* This flow queue is "empty" so it should be re-evaluated before + * the ones that have data to send. */ else - transport_connection_deschedule (ctx->tc); + session_evt_add_head_old (wrk, elt); return SESSION_TX_NO_DATA; } diff --git a/src/vnet/session/transport.c b/src/vnet/session/transport.c index e27aaf3ff6b..16f4f02cbe3 100644 --- a/src/vnet/session/transport.c +++ b/src/vnet/session/transport.c @@ -725,6 +725,7 @@ void transport_connection_reschedule (transport_connection_t * tc) { tc->flags &= ~TRANSPORT_CONNECTION_F_DESCHED; + transport_connection_tx_pacer_reset_bucket (tc, TRANSPORT_PACER_MIN_BURST); if (transport_max_tx_dequeue (tc)) sesssion_reschedule_tx (tc); else diff --git a/src/vnet/session/transport.h b/src/vnet/session/transport.h index b2be990947c..3c4e15a9a6b 100644 --- a/src/vnet/session/transport.h +++ b/src/vnet/session/transport.h @@ -184,9 +184,7 @@ transport_connection_snd_params (transport_connection_t * tc, static inline u8 transport_connection_is_descheduled (transport_connection_t * tc) { - if (tc->flags & TRANSPORT_CONNECTION_F_DESCHED) - return 1; - return 0; + return ((tc->flags & TRANSPORT_CONNECTION_F_DESCHED) ? 1 : 0); } static inline void diff --git a/src/vnet/tcp/tcp.c b/src/vnet/tcp/tcp.c index 4a0ffc137e5..dfcce771654 100644 --- a/src/vnet/tcp/tcp.c +++ b/src/vnet/tcp/tcp.c @@ -1281,14 +1281,7 @@ tcp_session_send_params (transport_connection_t * trans_conn, /* This still works if fast retransmit is on */ sp->tx_offset = tc->snd_nxt - tc->snd_una; - sp->flags = 0; - if (!tc->snd_wnd) - { - if (tcp_timer_is_active (tc, TCP_TIMER_PERSIST)) - sp->flags = TRANSPORT_SND_F_DESCHED; - else - sp->flags = TRANSPORT_SND_F_POSTPONE; - } + sp->flags = sp->snd_space ? 0 : TRANSPORT_SND_F_DESCHED; return 0; } @@ -1540,6 +1533,13 @@ tcp_connection_tx_pacer_reset (tcp_connection_t * tc, u32 window, srtt * CLIB_US_TIME_FREQ); } +void +tcp_reschedule (tcp_connection_t * tc) +{ + if (tcp_in_cong_recovery (tc) || tcp_snd_space_inline (tc)) + transport_connection_reschedule (&tc->connection); +} + static void tcp_expired_timers_dispatch (u32 * expired_timers) { diff --git a/src/vnet/tcp/tcp.h b/src/vnet/tcp/tcp.h index 8fa9013e31a..4db6040ae64 100644 --- a/src/vnet/tcp/tcp.h +++ b/src/vnet/tcp/tcp.h @@ -1036,6 +1036,12 @@ tcp_available_cc_snd_space (const tcp_connection_t * tc) return available_wnd - flight_size; } +static inline u8 +tcp_is_descheduled (tcp_connection_t * tc) +{ + return (transport_connection_is_descheduled (&tc->connection) ? 1 : 0); +} + always_inline u8 tcp_is_lost_fin (tcp_connection_t * tc) { @@ -1046,6 +1052,7 @@ tcp_is_lost_fin (tcp_connection_t * tc) u32 tcp_snd_space (tcp_connection_t * tc); int tcp_fastrecovery_prr_snd_space (tcp_connection_t * tc); +void tcp_reschedule (tcp_connection_t * tc); fib_node_index_t tcp_lookup_rmt_in_fib (tcp_connection_t * tc); @@ -1244,8 +1251,6 @@ tcp_persist_timer_update (tcp_connection_t * tc) always_inline void tcp_persist_timer_reset (tcp_connection_t * tc) { - if (transport_connection_is_descheduled (&tc->connection)) - transport_connection_reschedule (&tc->connection); tcp_timer_reset (tc, TCP_TIMER_PERSIST); } diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c index 4f31d21c3c1..bac41473cfa 100755 --- a/src/vnet/tcp/tcp_input.c +++ b/src/vnet/tcp/tcp_input.c @@ -700,6 +700,9 @@ tcp_handle_postponed_dequeues (tcp_worker_ctx_t * wrk) tc->flags &= ~TCP_CONN_PSH_PENDING; } + if (tcp_is_descheduled (tc)) + tcp_reschedule (tc); + /* If everything has been acked, stop retransmit timer * otherwise update. */ tcp_retransmit_timer_update (tc); @@ -1315,6 +1318,9 @@ tcp_update_snd_wnd (tcp_connection_t * tc, u32 seq, u32 ack, u32 snd_wnd) if (PREDICT_FALSE (tcp_timer_is_active (tc, TCP_TIMER_PERSIST))) tcp_persist_timer_reset (tc); + if (PREDICT_FALSE (tcp_is_descheduled (tc))) + tcp_reschedule (tc); + if (PREDICT_FALSE (!tcp_in_recovery (tc) && tc->rto_boff > 0)) { tc->rto_boff = 0; @@ -1465,6 +1471,7 @@ tcp_cc_recover (tcp_connection_t * tc) ASSERT (tc->rto_boff == 0); ASSERT (!tcp_in_cong_recovery (tc)); ASSERT (tcp_scoreboard_is_sane_post_recovery (tc)); + return is_spurious; } diff --git a/src/vnet/tcp/tcp_output.c b/src/vnet/tcp/tcp_output.c index b77713e1538..d33cbdd4ad4 100644 --- a/src/vnet/tcp/tcp_output.c +++ b/src/vnet/tcp/tcp_output.c @@ -1695,9 +1695,11 @@ tcp_timer_persist_handler (tcp_connection_t * tc) /* Just sent new data, enable retransmit */ tcp_retransmit_timer_update (tc); + return; + update_scheduler: - if (transport_connection_is_descheduled (&tc->connection)) + if (tcp_is_descheduled (tc)) transport_connection_reschedule (&tc->connection); } -- 2.16.6