summaryrefslogtreecommitdiffstats
path: root/src/vnet/tcp
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2019-11-15 17:56:48 -0800
committerAndrew Yourtchenko <ayourtch@gmail.com>2020-08-12 07:43:14 +0000
commit9e51b52bb96288fe6003a248ae67165be026a40b (patch)
tree9cd1b3c74e7a69b1d7bdc9f1876c74bd7b5f63fc /src/vnet/tcp
parent25b58c6d21db0d0ffaebff4effb4aa4a9e41745e (diff)
tcp: fix tail rescue with sacks
Type: fix Change-Id: Iad73f47cef3d29c4b0b7d1f58f2f2b14ba4b1d38 Signed-off-by: Florin Coras <fcoras@cisco.com> (cherry picked from commit 3eba7f1575a17b77924bf5be67b03b0227d04b78)
Diffstat (limited to 'src/vnet/tcp')
-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 1dc629d45c6..60e0927af85 100644
--- a/src/vnet/tcp/tcp_output.c
+++ b/src/vnet/tcp/tcp_output.c
@@ -1937,8 +1937,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,
@@ -1961,16 +1963,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;