aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/vnet/tcp/tcp.c12
-rw-r--r--src/vnet/tcp/tcp_input.c17
2 files changed, 18 insertions, 11 deletions
diff --git a/src/vnet/tcp/tcp.c b/src/vnet/tcp/tcp.c
index 9a3c90425b2..b1ed99a4dee 100644
--- a/src/vnet/tcp/tcp.c
+++ b/src/vnet/tcp/tcp.c
@@ -290,22 +290,21 @@ tcp_connection_reset (tcp_connection_t * tc)
tcp_connection_timers_reset (tc);
/* Set the cleanup timer, in case the session layer/app don't
* cleanly close the connection */
- tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, TCP_CLOSEWAIT_TIME);
+ tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLOSEWAIT_TIME);
stream_session_reset_notify (&tc->connection);
break;
case TCP_STATE_CLOSE_WAIT:
case TCP_STATE_FIN_WAIT_1:
case TCP_STATE_FIN_WAIT_2:
case TCP_STATE_CLOSING:
- tc->state = TCP_STATE_CLOSED;
- TCP_EVT_DBG (TCP_EVT_STATE_CHANGE, tc);
tcp_connection_timers_reset (tc);
- tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, TCP_CLOSEWAIT_TIME);
+ tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLOSEWAIT_TIME);
break;
case TCP_STATE_CLOSED:
return;
}
tc->state = TCP_STATE_CLOSED;
+ TCP_EVT_DBG (TCP_EVT_STATE_CHANGE, tc);
}
/**
@@ -1252,7 +1251,7 @@ tcp_timer_waitclose_handler (u32 conn_index)
/* Session didn't come back with a close(). Send FIN either way
* and switch to LAST_ACK. */
- if (tc->state == TCP_STATE_CLOSE_WAIT)
+ if (tc->state == TCP_STATE_CLOSE_WAIT && (tc->flags & TCP_CONN_FINPNDG))
{
/* Make sure we don't try to send unsent data */
tcp_connection_timers_reset (tc);
@@ -1269,8 +1268,9 @@ tcp_timer_waitclose_handler (u32 conn_index)
}
else if (tc->state == TCP_STATE_FIN_WAIT_1)
{
- /* Wait for session layer to clean up tx events */
+ tcp_connection_timers_reset (tc);
tc->state = TCP_STATE_CLOSED;
+ /* Wait for session layer to clean up tx events */
tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLEANUP_TIME);
return;
}
diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c
index 8481c76f489..f1d0f0186d5 100644
--- a/src/vnet/tcp/tcp_input.c
+++ b/src/vnet/tcp/tcp_input.c
@@ -2725,7 +2725,8 @@ tcp46_rcv_process_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
}
/* Make sure the ack is exactly right */
- if (tc0->rcv_nxt != vnet_buffer (b0)->tcp.seq_number || is_fin0)
+ if (tc0->rcv_nxt != vnet_buffer (b0)->tcp.seq_number || is_fin0
+ || vnet_buffer (b0)->tcp.data_len)
{
tcp_connection_reset (tc0);
error0 = TCP_ERROR_SEGMENT_INVALID;
@@ -2912,14 +2913,18 @@ tcp46_rcv_process_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
switch (tc0->state)
{
case TCP_STATE_ESTABLISHED:
+ tcp_rcv_fin (wrk, tc0, b0, &error0);
+ break;
case TCP_STATE_SYN_RCVD:
- /* Send FIN-ACK notify app and enter CLOSE-WAIT */
+ /* Send FIN-ACK, enter LAST-ACK and because the app was not
+ * notified yet, set a cleanup timer instead of relying on
+ * disconnect notify and the implicit close call. */
tcp_connection_timers_reset (tc0);
+ tc0->rcv_nxt += 1;
tcp_send_fin (tc0);
- stream_session_disconnect_notify (&tc0->connection);
- tc0->state = TCP_STATE_CLOSE_WAIT;
- tcp_timer_update (tc0, TCP_TIMER_WAITCLOSE, TCP_CLOSEWAIT_TIME);
+ tc0->state = TCP_STATE_LAST_ACK;
TCP_EVT_DBG (TCP_EVT_STATE_CHANGE, tc0);
+ tcp_timer_set (tc0, TCP_TIMER_WAITCLOSE, TCP_2MSL_TIME);
break;
case TCP_STATE_CLOSE_WAIT:
case TCP_STATE_CLOSING:
@@ -3601,6 +3606,7 @@ do { \
} while (0)
/* RFC 793: In LISTEN if RST drop and if ACK return RST */
+ _(LISTEN, 0, TCP_INPUT_NEXT_DROP, TCP_ERROR_SEGMENT_INVALID);
_(LISTEN, TCP_FLAG_ACK, TCP_INPUT_NEXT_RESET, TCP_ERROR_ACK_INVALID);
_(LISTEN, TCP_FLAG_RST, TCP_INPUT_NEXT_DROP, TCP_ERROR_INVALID_CONNECTION);
_(LISTEN, TCP_FLAG_SYN, TCP_INPUT_NEXT_LISTEN, TCP_ERROR_NONE);
@@ -3697,6 +3703,7 @@ do { \
TCP_ERROR_NONE);
/* FIN in reply to our FIN from the other side */
_(FIN_WAIT_1, TCP_FLAG_FIN, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
+ _(FIN_WAIT_1, TCP_FLAG_SYN, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
_(FIN_WAIT_1, TCP_FLAG_RST, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
_(FIN_WAIT_1, TCP_FLAG_RST | TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS,
TCP_ERROR_NONE);