aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet')
-rw-r--r--src/vnet/sctp/sctp.c39
-rw-r--r--src/vnet/session/session.c21
-rw-r--r--src/vnet/session/session_node.c16
-rw-r--r--src/vnet/tcp/tcp.c8
-rw-r--r--src/vnet/tcp/tcp_input.c3
5 files changed, 61 insertions, 26 deletions
diff --git a/src/vnet/sctp/sctp.c b/src/vnet/sctp/sctp.c
index 482f81a1e2a..10ec7700a2c 100644
--- a/src/vnet/sctp/sctp.c
+++ b/src/vnet/sctp/sctp.c
@@ -23,6 +23,7 @@ sctp_connection_bind (u32 session_index, transport_endpoint_t * tep)
sctp_main_t *tm = &sctp_main;
sctp_connection_t *listener;
void *iface_ip;
+ u32 mtu = 1460;
pool_get (tm->listener_pool, listener);
clib_memset (listener, 0, sizeof (*listener));
@@ -43,11 +44,13 @@ sctp_connection_bind (u32 session_index, transport_endpoint_t * tep)
ip_copy (&listener->sub_conn[SCTP_PRIMARY_PATH_IDX].connection.lcl_ip,
&tep->ip, tep->is_ip4);
- u32 mtu = tep->is_ip4 ? vnet_sw_interface_get_mtu (vnet_get_main (),
- tep->sw_if_index,
- VNET_MTU_IP4) :
- vnet_sw_interface_get_mtu (vnet_get_main (), tep->sw_if_index,
- VNET_MTU_IP6);
+ if (tep->sw_if_index != ENDPOINT_INVALID_INDEX)
+ mtu = tep->is_ip4 ? vnet_sw_interface_get_mtu (vnet_get_main (),
+ tep->sw_if_index,
+ VNET_MTU_IP4) :
+ vnet_sw_interface_get_mtu (vnet_get_main (), tep->sw_if_index,
+ VNET_MTU_IP6);
+
listener->sub_conn[SCTP_PRIMARY_PATH_IDX].PMTU = mtu;
listener->sub_conn[SCTP_PRIMARY_PATH_IDX].connection.is_ip4 = tep->is_ip4;
listener->sub_conn[SCTP_PRIMARY_PATH_IDX].connection.proto =
@@ -192,12 +195,13 @@ format_sctp_connection_id (u8 * s, va_list * args)
u8 i;
for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
{
+ if (i > 0 && sctp_conn->sub_conn[i].state == SCTP_SUBCONN_STATE_DOWN)
+ continue;
if (sctp_conn->sub_conn[i].connection.is_ip4)
{
- s = format (s, "%U[#%d][%s] %U:%d->%U:%d",
- s,
+ s = format (s, "[#%d][%s] %U:%d->%U:%d",
sctp_conn->sub_conn[i].connection.thread_index,
- "T",
+ "S",
format_ip4_address,
&sctp_conn->sub_conn[i].connection.lcl_ip.ip4,
clib_net_to_host_u16 (sctp_conn->sub_conn[i].
@@ -209,10 +213,9 @@ format_sctp_connection_id (u8 * s, va_list * args)
}
else
{
- s = format (s, "%U[#%d][%s] %U:%d->%U:%d",
- s,
+ s = format (s, "[#%d][%s] %U:%d->%U:%d",
sctp_conn->sub_conn[i].connection.thread_index,
- "T",
+ "S",
format_ip6_address,
&sctp_conn->sub_conn[i].connection.lcl_ip.ip6,
clib_net_to_host_u16 (sctp_conn->sub_conn[i].
@@ -238,6 +241,8 @@ format_sctp_connection (u8 * s, va_list * args)
if (verbose)
{
s = format (s, "%-15U", format_sctp_state, sctp_conn->state);
+ if (verbose > 1)
+ s = format (s, "\n");
}
return s;
@@ -458,6 +463,7 @@ sctp_connection_open (transport_endpoint_cfg_t * rmt)
ip46_address_t lcl_addr;
u16 lcl_port;
uword thread_id;
+ u32 mtu = 1460;
int rv;
u8 idx = SCTP_PRIMARY_PATH_IDX;
@@ -484,11 +490,12 @@ sctp_connection_open (transport_endpoint_cfg_t * rmt)
clib_spinlock_lock_if_init (&tm->half_open_lock);
sctp_conn = sctp_half_open_connection_new (thread_id);
- u32 mtu = rmt->is_ip4 ? vnet_sw_interface_get_mtu (vnet_get_main (),
- rmt->peer.sw_if_index,
- VNET_MTU_IP4) :
- vnet_sw_interface_get_mtu (vnet_get_main (), rmt->peer.sw_if_index,
- VNET_MTU_IP6);
+ if (rmt->peer.sw_if_index != ENDPOINT_INVALID_INDEX)
+ mtu = rmt->is_ip4 ? vnet_sw_interface_get_mtu (vnet_get_main (),
+ rmt->peer.sw_if_index,
+ VNET_MTU_IP4) :
+ vnet_sw_interface_get_mtu (vnet_get_main (), rmt->peer.sw_if_index,
+ VNET_MTU_IP6);
sctp_conn->sub_conn[idx].PMTU = mtu;
transport_connection_t *trans_conn = &sctp_conn->sub_conn[idx].connection;
diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c
index cbe0dd76430..d30254e5fc0 100644
--- a/src/vnet/session/session.c
+++ b/src/vnet/session/session.c
@@ -234,6 +234,7 @@ 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->enqueue_epoch = (u64) ~ 0;
+ s->session_state = SESSION_STATE_CLOSED;
/* Attach transport to session and vice versa */
s->connection_index = tc->c_index;
@@ -773,6 +774,7 @@ stream_session_accept_notify (transport_connection_t * tc)
app_wrk = app_worker_get_if_valid (s->app_wrk_index);
if (!app_wrk)
return -1;
+ s->session_state = SESSION_STATE_ACCEPTING;
app = application_get (app_wrk->app_index);
return app->cb_fns.session_accept_callback (s);
}
@@ -824,6 +826,7 @@ session_transport_delete_notify (transport_connection_t * tc)
switch (s->session_state)
{
+ case SESSION_STATE_ACCEPTING:
case SESSION_STATE_TRANSPORT_CLOSING:
/* If transport finishes or times out before we get a reply
* from the app, mark transport as closed and wait for reply
@@ -844,11 +847,13 @@ session_transport_delete_notify (transport_connection_t * tc)
s->session_state = SESSION_STATE_TRANSPORT_CLOSED;
session_program_transport_close (s);
break;
+ case SESSION_STATE_TRANSPORT_CLOSED:
+ break;
case SESSION_STATE_CLOSED:
- case SESSION_STATE_ACCEPTING:
session_delete (s);
break;
default:
+ clib_warning ("session state %u", s->session_state);
session_delete (s);
break;
}
@@ -869,7 +874,16 @@ session_transport_closed_notify (transport_connection_t * tc)
if (!(s = session_get_if_valid (tc->s_index, tc->thread_index)))
return;
- s->session_state = SESSION_STATE_CLOSED;
+
+ /* If app close has not been received or has not yet resulted in
+ * a transport close, only mark the session transport as closed */
+ if (s->session_state <= SESSION_STATE_CLOSING)
+ {
+ session_lookup_del_session (s);
+ s->session_state = SESSION_STATE_TRANSPORT_CLOSED;
+ }
+ else
+ s->session_state = SESSION_STATE_CLOSED;
}
/**
@@ -913,7 +927,6 @@ stream_session_accept (transport_connection_t * tc, u32 listener_index,
s->app_wrk_index = app_wrk->wrk_index;
s->listener_index = listener_index;
- s->session_state = SESSION_STATE_ACCEPTING;
/* Shoulder-tap the server */
if (notify)
@@ -1141,7 +1154,7 @@ void
session_transport_close (stream_session_t * s)
{
/* If transport is already closed, just free the session */
- if (s->session_state == SESSION_STATE_TRANSPORT_CLOSED)
+ if (s->session_state >= SESSION_STATE_TRANSPORT_CLOSED)
{
session_free_w_fifos (s);
return;
diff --git a/src/vnet/session/session_node.c b/src/vnet/session/session_node.c
index 4323ed83cf8..45018daf45a 100644
--- a/src/vnet/session/session_node.c
+++ b/src/vnet/session/session_node.c
@@ -29,6 +29,7 @@ session_mq_accepted_reply_handler (void *data)
{
session_accepted_reply_msg_t *mp = (session_accepted_reply_msg_t *) data;
vnet_disconnect_args_t _a = { 0 }, *a = &_a;
+ stream_session_state_t old_state;
app_worker_t *app_wrk;
local_session_t *ls;
stream_session_t *s;
@@ -64,18 +65,29 @@ session_mq_accepted_reply_handler (void *data)
else
{
s = session_get_from_handle_if_valid (mp->handle);
- /* Closed while waiting for app to reply */
- if (!s || s->session_state > SESSION_STATE_READY)
+ if (!s)
return;
+
app_wrk = app_worker_get (s->app_wrk_index);
if (app_wrk->app_index != mp->context)
{
clib_warning ("app doesn't own session");
return;
}
+
+ old_state = s->session_state;
s->session_state = SESSION_STATE_READY;
if (!svm_fifo_is_empty (s->server_rx_fifo))
app_worker_lock_and_send_event (app_wrk, s, FIFO_EVENT_APP_RX);
+
+ /* Closed while waiting for app to reply. Resend disconnect */
+ if (old_state >= SESSION_STATE_TRANSPORT_CLOSING)
+ {
+ application_t *app = application_get (app_wrk->app_index);
+ app->cb_fns.session_disconnect_callback (s);
+ s->session_state = old_state;
+ return;
+ }
}
}
diff --git a/src/vnet/tcp/tcp.c b/src/vnet/tcp/tcp.c
index 564f200bc00..7f6a087b2f3 100644
--- a/src/vnet/tcp/tcp.c
+++ b/src/vnet/tcp/tcp.c
@@ -284,7 +284,8 @@ tcp_connection_reset (tcp_connection_t * tc)
break;
case TCP_STATE_SYN_SENT:
session_stream_connect_notify (&tc->connection, 1 /* fail */ );
- tcp_connection_cleanup (tc);
+ tcp_connection_set_state (tc, TCP_STATE_CLOSED);
+ tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLEANUP_TIME);
break;
case TCP_STATE_ESTABLISHED:
tcp_connection_timers_reset (tc);
@@ -307,6 +308,7 @@ tcp_connection_reset (tcp_connection_t * tc)
tcp_connection_set_state (tc, TCP_STATE_CLOSED);
break;
case TCP_STATE_CLOSED:
+ case TCP_STATE_TIME_WAIT:
break;
default:
TCP_DBG ("reset state: %u", tc->state);
@@ -1293,9 +1295,9 @@ tcp_timer_waitclose_handler (u32 conn_index)
* is closed. We haven't sent everything but we did try. */
tcp_cong_recovery_off (tc);
tcp_send_fin (tc);
- rto = clib_max (tc->rto >> tc->rto_boff, 1);
+ rto = clib_max ((tc->rto >> tc->rto_boff) * TCP_TO_TIMER_TICK, 1);
tcp_timer_set (tc, TCP_TIMER_WAITCLOSE,
- clib_min (rto * TCP_TO_TIMER_TICK, TCP_2MSL_TIME));
+ clib_min (rto, TCP_2MSL_TIME));
session_transport_closed_notify (&tc->connection);
}
else
diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c
index c3ce2eb1ae1..fb80d7f5759 100644
--- a/src/vnet/tcp/tcp_input.c
+++ b/src/vnet/tcp/tcp_input.c
@@ -2671,7 +2671,8 @@ tcp46_rcv_process_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
is_ip4);
if (tmp->state != tc0->state)
{
- clib_warning ("state changed");
+ if (tc0->state != TCP_STATE_CLOSED)
+ clib_warning ("state changed");
goto drop;
}
}