aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2019-11-15 17:56:48 -0800
committerFlorin Coras <florin.coras@gmail.com>2019-12-06 03:55:48 +0000
commit3eba7f1575a17b77924bf5be67b03b0227d04b78 (patch)
treee79d16153de8cfe63a6a96fa79cbd152c4cf5a84
parent61e3ade8436e77730150568ad3a48058c4f49d97 (diff)
tcp: fix tail rescue with sacks
Type: fix Change-Id: Iad73f47cef3d29c4b0b7d1f58f2f2b14ba4b1d38 Signed-off-by: Florin Coras <fcoras@cisco.com>
-rw-r--r--src/vnet/tcp/tcp_output.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/src/vnet/tcp/tcp_output.c b/src/vnet/tcp/tcp_output.c
index f63ffa64022..05db72770f5 100644
--- a/src/vnet/tcp/tcp_output.c
+++ b/src/vnet/tcp/tcp_output.c
@@ -1924,8 +1924,10 @@ tcp_retransmit_sack (tcp_worker_ctx_t * wrk, tcp_connection_t * tc,
u32 n_segs_new;
int av_wnd;
+ /* Make sure we don't exceed available window and leave space
+ * for one more packet, to avoid zero window acks */
av_wnd = (int) tc->snd_wnd - (tc->snd_nxt - tc->snd_una);
- av_wnd = clib_max (av_wnd, 0);
+ av_wnd = clib_max (av_wnd - tc->snd_mss, 0);
snd_space = clib_min (snd_space, av_wnd);
snd_space = clib_min (max_deq, snd_space);
burst_size = clib_min (burst_size - n_segs,
@@ -1948,16 +1950,16 @@ tcp_retransmit_sack (tcp_worker_ctx_t * wrk, tcp_connection_t * tc,
* unSACKed sequence number SHOULD be returned, and RescueRxt set to
* RecoveryPoint. HighRxt MUST NOT be updated.
*/
- max_bytes = clib_min (tc->snd_mss,
- tc->snd_congestion - tc->snd_una);
+ hole = scoreboard_last_hole (sb);
+ max_bytes = clib_min (tc->snd_mss, hole->end - hole->start);
max_bytes = clib_min (max_bytes, snd_space);
- offset = tc->snd_congestion - tc->snd_una - max_bytes;
- sb->rescue_rxt = tc->snd_congestion;
+ offset = hole->end - tc->snd_una - max_bytes;
n_written = tcp_prepare_retransmit_segment (wrk, tc, offset,
max_bytes, &b);
if (!n_written)
goto done;
+ sb->rescue_rxt = tc->snd_congestion;
bi = vlib_get_buffer_index (vm, b);
tcp_enqueue_to_output (wrk, b, bi, tc->c_is_ip4);
n_segs += 1;