summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/vnet/session/session.c8
-rw-r--r--src/vnet/tcp/tcp_input.c1
-rw-r--r--src/vnet/tcp/tcp_output.c22
3 files changed, 26 insertions, 5 deletions
diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c
index ee22ccbe0ad..dcd141f1b5b 100644
--- a/src/vnet/session/session.c
+++ b/src/vnet/session/session.c
@@ -330,7 +330,13 @@ stream_session_enqueue_notify (stream_session_t * s, u8 block)
static u32 serial_number;
if (PREDICT_FALSE (s->session_state == SESSION_STATE_CLOSED))
- return 0;
+ {
+ /* Session is closed so app will never clean up. Flush rx fifo */
+ u32 to_dequeue = svm_fifo_max_dequeue (s->server_rx_fifo);
+ if (to_dequeue)
+ svm_fifo_dequeue_drop (s->server_rx_fifo, to_dequeue);
+ return 0;
+ }
/* Get session's server */
app = application_get_if_valid (s->app_index);
diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c
index 66e2b88fc5f..1d90345347d 100644
--- a/src/vnet/tcp/tcp_input.c
+++ b/src/vnet/tcp/tcp_input.c
@@ -3073,6 +3073,7 @@ do { \
_(TIME_WAIT, TCP_FLAG_FIN | TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS,
TCP_ERROR_NONE);
_(TIME_WAIT, TCP_FLAG_RST, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
+ _(TIME_WAIT, TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE);
_(CLOSED, TCP_FLAG_ACK, TCP_INPUT_NEXT_RESET, TCP_ERROR_CONNECTION_CLOSED);
_(CLOSED, TCP_FLAG_RST, TCP_INPUT_NEXT_DROP, TCP_ERROR_CONNECTION_CLOSED);
_(CLOSED, TCP_FLAG_FIN | TCP_FLAG_ACK, TCP_INPUT_NEXT_RESET,
diff --git a/src/vnet/tcp/tcp_output.c b/src/vnet/tcp/tcp_output.c
index c56eadf8fdd..0255551318a 100644
--- a/src/vnet/tcp/tcp_output.c
+++ b/src/vnet/tcp/tcp_output.c
@@ -1452,15 +1452,29 @@ tcp_timer_persist_handler (u32 index)
/* Make sure timer handle is set to invalid */
tc->timers[TCP_TIMER_PERSIST] = TCP_TIMER_HANDLE_INVALID;
- offset = tc->snd_una_max - tc->snd_una;
/* Problem already solved or worse */
- available_bytes = stream_session_tx_fifo_max_dequeue (&tc->connection);
if (tc->state == TCP_STATE_CLOSED || tc->state > TCP_STATE_ESTABLISHED
- || tc->snd_wnd > tc->snd_mss || tcp_in_recovery (tc)
- || !available_bytes || available_bytes <= offset)
+ || tc->snd_wnd > tc->snd_mss || tcp_in_recovery (tc))
return;
+ available_bytes = stream_session_tx_fifo_max_dequeue (&tc->connection);
+ offset = tc->snd_una_max - tc->snd_una;
+
+ /* Reprogram persist if no new bytes available to send. We may have data
+ * next time */
+ if (!available_bytes)
+ {
+ tcp_persist_timer_set (tc);
+ return;
+ }
+
+ if (available_bytes <= offset)
+ {
+ ASSERT (tcp_timer_is_active (tc, TCP_TIMER_RETRANSMIT));
+ return;
+ }
+
/* Increment RTO backoff */
tc->rto_boff += 1;
tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);