diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2024-02-07 23:57:21 +1100 |
---|---|---|
committer | Stefano Brivio <sbrivio@redhat.com> | 2024-02-11 18:30:01 +0100 |
commit | 78901eeae3b37c0e15f34512e5ea0c1b7acc4642 (patch) | |
tree | 709bc3d7fcb94d675bb633904e2d54274a94029c /tcp.c | |
parent | 6c7623d07bbd44d81beb4aa60b0a1de12b622630 (diff) | |
download | passt-78901eeae3b37c0e15f34512e5ea0c1b7acc4642.tar passt-78901eeae3b37c0e15f34512e5ea0c1b7acc4642.tar.gz passt-78901eeae3b37c0e15f34512e5ea0c1b7acc4642.tar.bz2 passt-78901eeae3b37c0e15f34512e5ea0c1b7acc4642.tar.lz passt-78901eeae3b37c0e15f34512e5ea0c1b7acc4642.tar.xz passt-78901eeae3b37c0e15f34512e5ea0c1b7acc4642.tar.zst passt-78901eeae3b37c0e15f34512e5ea0c1b7acc4642.zip |
tcp: Fix subtle bug in fast re-transmit path
When a duplicate ack from the tap side triggers a fast re-transmit, we set
both conn->seq_ack_from_tap and conn->seq_to_tap to the sequence number of
the duplicate ack. Setting seq_to_tap is correct: this is what triggers
the retransmit from this point onwards. Setting seq_ack_from_tap is
not correct, though.
In most cases setting seq_ack_from_tap will be redundant but harmless:
it will have already been updated to the same value by
tcp_update_seqack_from_tap() a few lines above. However that call can
be skipped if tcp_sock_consume() fails, which is rare but possible. In
that case this update will cause problems.
We use seq_ack_from_tap to track two logically distinct things: how much of
the stream has been acked by the guest, and how much of the stream from the
socket has been read and discarded (as opposed to MSG_PEEKed). We attempt
to keep those values the same, because we discard data exactly when it is
acked by the guest. However tcp_sock_consume() failing means we weren't
able to disard the acked data. To handle that case, we skip the usual
update of seq_ack_from_tap, effectively ignoring the ack assuming we'll get
one which supersedes it soon enough. Setting seq_ack_from_tap in the
fast retransmit path, however, means we now really will have the
read/discard point in the stream out of sync with seq_ack_from_tap.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'tcp.c')
-rw-r--r-- | tcp.c | 1 |
1 files changed, 0 insertions, 1 deletions
@@ -2365,7 +2365,6 @@ static int tcp_data_from_tap(struct ctx *c, struct tcp_tap_conn *conn, flow_trace(conn, "fast re-transmit, ACK: %u, previous sequence: %u", max_ack_seq, conn->seq_to_tap); - conn->seq_ack_from_tap = max_ack_seq; conn->seq_to_tap = max_ack_seq; tcp_data_from_sock(c, conn); } |