aboutgitcodebugslistschat
path: root/tcp.c
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2023-03-23 16:07:57 +0100
committerStefano Brivio <sbrivio@redhat.com>2023-03-29 13:47:17 +0200
commit33d88f79d920699be5162e1f5d6901da0c02b005 (patch)
tree7ffffbab76b25ae4a563a30a5db9ab039b8934ad /tcp.c
parent4e73e9bd655c8ebb3e253284f51d4349eea1cc5c (diff)
downloadpasst-33d88f79d920699be5162e1f5d6901da0c02b005.tar
passt-33d88f79d920699be5162e1f5d6901da0c02b005.tar.gz
passt-33d88f79d920699be5162e1f5d6901da0c02b005.tar.bz2
passt-33d88f79d920699be5162e1f5d6901da0c02b005.tar.lz
passt-33d88f79d920699be5162e1f5d6901da0c02b005.tar.xz
passt-33d88f79d920699be5162e1f5d6901da0c02b005.tar.zst
passt-33d88f79d920699be5162e1f5d6901da0c02b005.zip
tcp: Clear ACK_FROM_TAP_DUE also on unchanged ACK sequence from peer
Since commit cc6d8286d104 ("tcp: Reset ACK_FROM_TAP_DUE flag only as needed, update timer"), we don't clear ACK_FROM_TAP_DUE whenever we process an ACK segment, but, more correctly, only if we're really not waiting for a further ACK segment, that is, only if the acknowledged sequence matches what we sent. In the new function implementing this, tcp_update_seqack_from_tap(), we also reset the retransmission counter and store the updated ACK sequence. Both should be done iff forward progress is acknowledged, implied by the fact that the new ACK sequence is greater than the one we previously stored. At that point, it looked natural to also include the statements that clear and set the ACK_FROM_TAP_DUE flag inside the same conditional block: if we're not making forward progress, the need for an ACK, or lack thereof, should remain unchanged. There might be cases where this isn't true, though: without the previous commit 4e73e9bd655c ("tcp: Don't special case the handling of the ack of a syn"), this would happen if a tap-side client initiated a connection, and the server didn't send any data. At that point we would never, in the established state of the connection, call tcp_update_seqack_from_tap() with reported forward progress. That issue itself is fixed by the previous commit, now, but clearing ACK_FROM_TAP_DUE only on ACK sequence progress doesn't really follow any logic. Clear the ACK_FROM_TAP_DUE flag regardless of reported forward progress. If we clear it when it's already unset, conn_flag() will do nothing with it. This doesn't fix any known functional issue, rather a conceptual one. Fixes: cc6d8286d104 ("tcp: Reset ACK_FROM_TAP_DUE flag only as needed, update timer") Reported-by: David Gibson <david@gibson.dropbear.id.au> Analysed-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.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/tcp.c b/tcp.c
index bbdee60..056e917 100644
--- a/tcp.c
+++ b/tcp.c
@@ -1610,10 +1610,12 @@ out:
static void tcp_update_seqack_from_tap(const struct ctx *c,
struct tcp_tap_conn *conn, uint32_t seq)
{
+ if (seq == conn->seq_to_tap)
+ conn_flag(c, conn, ~ACK_FROM_TAP_DUE);
+
if (SEQ_GT(seq, conn->seq_ack_from_tap)) {
- if (seq == conn->seq_to_tap)
- conn_flag(c, conn, ~ACK_FROM_TAP_DUE);
- else
+ /* Forward progress, but more data to acknowledge: reschedule */
+ if (SEQ_LT(seq, conn->seq_to_tap))
conn_flag(c, conn, ACK_FROM_TAP_DUE);
conn->retrans = 0;