/* If our window is 0 and the packet is in sequence, let it pass
* through for ack processing. It should be dropped later. */
- if (tc0->rcv_wnd == 0
+ if (tc0->rcv_wnd < tc0->snd_mss
&& tc0->rcv_nxt == vnet_buffer (b0)->tcp.seq_number)
goto check_reset;
for (i = 0; i < vec_len (ongoing_fast_rxt); i++)
{
+ tc = tcp_connection_get (ongoing_fast_rxt[i], thread_index);
+ if (!tcp_in_fastrecovery (tc))
+ {
+ tc->flags &= ~TCP_CONN_FRXT_PENDING;
+ continue;
+ }
+
if (n_segs >= VLIB_FRAME_SIZE)
{
vec_add1 (wrk->postponed_fast_rxt, ongoing_fast_rxt[i]);
continue;
}
- tc = tcp_connection_get (ongoing_fast_rxt[i], thread_index);
tc->flags &= ~TCP_CONN_FRXT_PENDING;
-
- if (!tcp_in_fastrecovery (tc))
- continue;
-
burst_size = clib_min (max_burst_size, VLIB_FRAME_SIZE - n_segs);
burst_bytes = transport_connection_tx_pacer_burst (&tc->connection,
last_cpu_time);
if (tcp_rcv_ack (wrk, tc0, b0, tcp0, &error0))
goto drop;
+ if (!is_fin0)
+ goto drop;
+
tcp_program_ack (wrk, tc0);
tcp_timer_update (tc0, TCP_TIMER_WAITCLOSE, TCP_TIMEWAIT_TIME);
goto drop;
session_tx_fifo_dequeue_drop (&tc0->connection,
transport_max_tx_dequeue
(&tc0->connection));
+ /* Make it look as if we've recovered, if needed */
+ if (tcp_in_cong_recovery (tc0))
+ {
+ scoreboard_clear (&tc0->sack_sb);
+ tcp_fastrecovery_off (tc0);
+ tcp_recovery_off (tc0);
+ tcp_connection_timers_reset (tc0);
+ tc0->snd_nxt = tc0->snd_una_max = tc0->snd_una;
+ }
tcp_send_fin (tc0);
}
else