From a9d5bea69fafbcc2f24d71439433c9b710db665f Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Mon, 17 Dec 2018 08:24:19 -0800 Subject: [PATCH] tcp/session: drop connections if message queue is full Also cleanup session table when transport closes and app didn't reply to the close notification. Change-Id: Ie3d518e3afff73437561561b46dbf695c24632ad Signed-off-by: Florin Coras --- src/vnet/session/session.c | 15 +++++++++------ src/vnet/session/session.h | 2 +- src/vnet/tcp/tcp_error.def | 2 +- src/vnet/tcp/tcp_input.c | 30 +++++++++++++++++------------- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c index 7f9a32f46de..a03b53dd3bd 100644 --- a/src/vnet/session/session.c +++ b/src/vnet/session/session.c @@ -194,7 +194,6 @@ session_alloc_for_connection (transport_connection_t * tc) s = session_alloc (thread_index); s->session_type = session_type_from_proto_and_ip (tc->proto, tc->is_ip4); - s->session_state = SESSION_STATE_CONNECTING; s->enqueue_epoch = (u64) ~ 0; /* Attach transport to session and vice versa */ @@ -629,6 +628,7 @@ session_stream_connect_notify (transport_connection_t * tc, u8 is_fail) } else { + new_s->session_state = SESSION_STATE_CONNECTING; new_s->app_wrk_index = app_wrk->wrk_index; new_si = new_s->session_index; new_ti = new_s->thread_index; @@ -723,7 +723,7 @@ session_dgram_connect_notify (transport_connection_t * tc, return 0; } -void +int stream_session_accept_notify (transport_connection_t * tc) { app_worker_t *app_wrk; @@ -733,9 +733,9 @@ stream_session_accept_notify (transport_connection_t * tc) s = session_get (tc->s_index, tc->thread_index); app_wrk = app_worker_get_if_valid (s->app_wrk_index); if (!app_wrk) - return; + return -1; app = application_get (app_wrk->app_index); - app->cb_fns.session_accept_callback (s); + return app->cb_fns.session_accept_callback (s); } /** @@ -805,7 +805,10 @@ stream_session_delete_notify (transport_connection_t * tc) case SESSION_STATE_TRANSPORT_CLOSING: /* If transport finishes or times out before we get a reply * from the app, do the whole disconnect since we might still - * have lingering events */ + * have lingering events. Cleanup session table in advance + * because transport will soon be closed and closed sessions + * are assumed to have been removed from the lookup table */ + session_lookup_del_session (s); stream_session_disconnect (s); s->session_state = SESSION_STATE_CLOSED; break; @@ -872,7 +875,7 @@ stream_session_accept (transport_connection_t * tc, u32 listener_index, if (notify) { application_t *app = application_get (app_wrk->app_index); - app->cb_fns.session_accept_callback (s); + return app->cb_fns.session_accept_callback (s); } return 0; diff --git a/src/vnet/session/session.h b/src/vnet/session/session.h index be2490fbe95..6c1bdb639df 100644 --- a/src/vnet/session/session.h +++ b/src/vnet/session/session.h @@ -610,7 +610,7 @@ int session_dequeue_notify (stream_session_t * s); void stream_session_init_fifos_pointers (transport_connection_t * tc, u32 rx_pointer, u32 tx_pointer); -void stream_session_accept_notify (transport_connection_t * tc); +int stream_session_accept_notify (transport_connection_t * tc); void stream_session_disconnect_notify (transport_connection_t * tc); void stream_session_delete_notify (transport_connection_t * tc); void stream_session_reset_notify (transport_connection_t * tc); diff --git a/src/vnet/tcp/tcp_error.def b/src/vnet/tcp/tcp_error.def index 44bf0c04168..141ca515995 100644 --- a/src/vnet/tcp/tcp_error.def +++ b/src/vnet/tcp/tcp_error.def @@ -25,7 +25,7 @@ tcp_error (SEGMENT_OLD, "Old segment") tcp_error (SEGMENT_INVALID, "Invalid segments") tcp_error (SYNS_RCVD, "SYNs received") tcp_error (SYN_ACKS_RCVD, "SYN-ACKs received") -tcp_error (EVENT_FIFO_FULL, "Events not sent for lack of event fifo space") +tcp_error (MSG_QUEUE_FULL, "Events not sent for lack of msg queue space") tcp_error (CREATE_SESSION_FAIL, "Sessions couldn't be allocated") tcp_error (ACK_OK, "Pure ACKs received") tcp_error (ACK_INVALID, "Invalid ACK") diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c index 91876feaf42..8b16275359c 100644 --- a/src/vnet/tcp/tcp_input.c +++ b/src/vnet/tcp/tcp_input.c @@ -183,11 +183,7 @@ tcp_options_parse (tcp_header_t * th, tcp_options_t * to, u8 is_syn) to->flags |= TCP_OPTS_FLAG_WSCALE; to->wscale = data[2]; if (to->wscale > TCP_MAX_WND_SCALE) - { - clib_warning ("Illegal window scaling value: %d", - to->wscale); - to->wscale = TCP_MAX_WND_SCALE; - } + to->wscale = TCP_MAX_WND_SCALE; } break; case TCP_OPTION_TIMESTAMP: @@ -1598,7 +1594,10 @@ process_ack: { tcp_cc_handle_event (tc, is_dack); if (!tcp_in_cong_recovery (tc)) - return 0; + { + *error = TCP_ERROR_ACK_OK; + return 0; + } *error = TCP_ERROR_ACK_DUP; if (vnet_buffer (b)->tcp.data_len || tcp_is_fin (th)) return 0; @@ -2169,7 +2168,7 @@ tcp46_established_inline (vlib_main_t * vm, vlib_node_runtime_t * node, errors = session_manager_flush_enqueue_events (TRANSPORT_PROTO_TCP, thread_index); - err_counters[TCP_ERROR_EVENT_FIFO_FULL] = errors; + err_counters[TCP_ERROR_MSG_QUEUE_FULL] = errors; tcp_store_err_counters (established, err_counters); tcp_handle_postponed_dequeues (wrk); tcp_handle_disconnects (wrk); @@ -2569,7 +2568,7 @@ tcp46_syn_sent_inline (vlib_main_t * vm, vlib_node_runtime_t * node, errors = session_manager_flush_enqueue_events (TRANSPORT_PROTO_TCP, my_thread_index); - tcp_inc_counter (syn_sent, TCP_ERROR_EVENT_FIFO_FULL, errors); + tcp_inc_counter (syn_sent, TCP_ERROR_MSG_QUEUE_FULL, errors); vlib_buffer_free (vm, first_buffer, from_frame->n_vectors); return from_frame->n_vectors; @@ -2750,7 +2749,12 @@ tcp46_rcv_process_inline (vlib_main_t * vm, vlib_node_runtime_t * node, /* Reset SYN-ACK retransmit and SYN_RCV establish timers */ tcp_retransmit_timer_reset (tc0); tcp_timer_reset (tc0, TCP_TIMER_ESTABLISH); - stream_session_accept_notify (&tc0->connection); + if (stream_session_accept_notify (&tc0->connection)) + { + error0 = TCP_ERROR_MSG_QUEUE_FULL; + tcp_connection_reset (tc0); + goto drop; + } error0 = TCP_ERROR_ACK_OK; break; case TCP_STATE_ESTABLISHED: @@ -2958,7 +2962,7 @@ tcp46_rcv_process_inline (vlib_main_t * vm, vlib_node_runtime_t * node, errors = session_manager_flush_enqueue_events (TRANSPORT_PROTO_TCP, thread_index); - tcp_inc_counter (rcv_process, TCP_ERROR_EVENT_FIFO_FULL, errors); + tcp_inc_counter (rcv_process, TCP_ERROR_MSG_QUEUE_FULL, errors); tcp_handle_postponed_dequeues (wrk); vlib_buffer_free (vm, first_buffer, from_frame->n_vectors); @@ -3150,7 +3154,6 @@ tcp46_listen_inline (vlib_main_t * vm, vlib_node_runtime_t * node, if (stream_session_accept (&child0->connection, lc0->c_s_index, 0 /* notify */ )) { - clib_warning ("session accept fail"); tcp_connection_cleanup (child0); error0 = TCP_ERROR_CREATE_SESSION_FAIL; goto drop; @@ -3407,8 +3410,9 @@ tcp_input_dispatch_buffer (tcp_main_t * tm, tcp_connection_t * tc, vnet_buffer (b)->tcp.flags = tc->state; if (*error == TCP_ERROR_DISPATCH) - clib_warning ("disp error state %U flags %U", format_tcp_state, - state, format_tcp_flags, (int) flags); + clib_warning ("tcp conn %u disp error state %U flags %U", + tc->c_c_index, format_tcp_state, state, + format_tcp_flags, (int) flags); } } -- 2.16.6