tcp: fix tail rescue with sacks 83/23483/7
authorFlorin Coras <fcoras@cisco.com>
Sat, 16 Nov 2019 01:56:48 +0000 (17:56 -0800)
committerFlorin Coras <florin.coras@gmail.com>
Fri, 6 Dec 2019 03:55:48 +0000 (03:55 +0000)
Type: fix

Change-Id: Iad73f47cef3d29c4b0b7d1f58f2f2b14ba4b1d38
Signed-off-by: Florin Coras <fcoras@cisco.com>
src/vnet/tcp/tcp_output.c

index f63ffa6..05db727 100644 (file)
@@ -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;