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 <fcoras@cisco.com>
This commit is contained in:
Florin Coras
committed by
Dave Barach
parent
65eb77231c
commit
a9d5bea69f
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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")
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user