From 81cb8e4092991d3fd1e24f0862c12548a2d4c714 Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Tue, 22 Oct 2019 19:44:45 -0700 Subject: [PATCH] tcp: fix sack retransmit beyond snd_nxt Type: fix Ensure that sack retransmit logic does not try to inadvertently send new data. Change-Id: Idfda19643577d9c1b58e2af8d8283cabfbaf98e6 Signed-off-by: Florin Coras --- src/vnet/tcp/tcp_input.c | 6 ++++++ src/vnet/tcp/tcp_output.c | 9 +++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c index 10f96fa7b59..744c5bc01c2 100755 --- a/src/vnet/tcp/tcp_input.c +++ b/src/vnet/tcp/tcp_input.c @@ -890,6 +890,12 @@ scoreboard_next_rxt_hole (sack_scoreboard_t * sb, /* Rule (3): if hole not lost */ else if (seq_lt (hole->start, sb->high_sacked)) { + /* And we didn't already retransmit it */ + if (seq_leq (hole->end, sb->high_rxt)) + { + sb->cur_rxt_hole = TCP_INVALID_SACK_HOLE_INDEX; + return 0; + } *snd_limited = 0; sb->cur_rxt_hole = scoreboard_hole_index (sb, hole); } diff --git a/src/vnet/tcp/tcp_output.c b/src/vnet/tcp/tcp_output.c index e3228c07fa1..0047f3c22e3 100644 --- a/src/vnet/tcp/tcp_output.c +++ b/src/vnet/tcp/tcp_output.c @@ -1392,6 +1392,8 @@ tcp_prepare_retransmit_segment (tcp_worker_ctx_t * wrk, max_deq_bytes = clib_min (available_bytes, max_deq_bytes); start = tc->snd_una + offset; + ASSERT (seq_leq (start + max_deq_bytes, tc->snd_nxt)); + n_bytes = tcp_prepare_segment (wrk, tc, offset, max_deq_bytes, b); if (!n_bytes) return 0; @@ -1521,7 +1523,8 @@ tcp_timer_retransmit_handler (u32 tc_index) /* Send the first unacked segment. If we're short on buffers, return * as soon as possible */ - n_bytes = tcp_prepare_retransmit_segment (wrk, tc, 0, tc->snd_mss, &b); + n_bytes = clib_min (tc->snd_mss, tc->snd_nxt - tc->snd_una); + n_bytes = tcp_prepare_retransmit_segment (wrk, tc, 0, n_bytes, &b); if (!n_bytes) { tcp_timer_update (tc, TCP_TIMER_RETRANSMIT, 1); @@ -1922,7 +1925,7 @@ tcp_retransmit_sack (tcp_worker_ctx_t * wrk, tcp_connection_t * tc, while (snd_space > 0 && n_segs < burst_size) { - hole = scoreboard_next_rxt_hole (sb, hole, max_deq, &can_rescue, + hole = scoreboard_next_rxt_hole (sb, hole, max_deq != 0, &can_rescue, &snd_limited); if (!hole) { @@ -1990,6 +1993,8 @@ tcp_retransmit_sack (tcp_worker_ctx_t * wrk, tcp_connection_t * tc, tcp_enqueue_to_output (wrk, b, bi, tc->c_is_ip4); sb->high_rxt += n_written; + ASSERT (seq_leq (sb->high_rxt, tc->snd_nxt)); + snd_space -= n_written; n_segs += 1; } -- 2.16.6