Messages in this thread Patch in this message | | | From | zhouzhouyi@gmail ... | Subject | [PATCH v2] net:ipv4: send an ack when seg.ack > snd.nxt | Date | Sat, 19 Mar 2022 19:04:22 +0800 |
| |
From: Zhouyi Zhou <zhouzhouyi@gmail.com>
In RFC 793, page 72: "If the ACK acks something not yet sent (SEG.ACK > SND.NXT) then send an ACK, drop the segment, and return."
Fix Linux's behavior according to RFC 793.
Reported-by: Wei Xu <xuweihf@ustc.edu.cn> Signed-off-by: Wei Xu <xuweihf@ustc.edu.cn> Signed-off-by: Zhouyi Zhou <zhouzhouyi@gmail.com> --- Thank Florian Westphal for pointing out the potential duplicated ack bug in patch version 1. -- net/ipv4/tcp_input.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index bfe4112e000c..4bbf85d7ea8c 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3771,11 +3771,13 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) goto old_ack; } - /* If the ack includes data we haven't sent yet, discard - * this segment (RFC793 Section 3.9). + /* If the ack includes data we haven't sent yet, then send + * an ack, drop this segment, and return (RFC793 Section 3.9 page 72). */ - if (after(ack, tp->snd_nxt)) - return -1; + if (after(ack, tp->snd_nxt)) { + tcp_send_ack(sk); + return -2; + } if (after(ack, prior_snd_una)) { flag |= FLAG_SND_UNA_ADVANCED; @@ -6385,6 +6387,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) struct request_sock *req; int queued = 0; bool acceptable; + int ret; switch (sk->sk_state) { case TCP_CLOSE: @@ -6451,14 +6454,16 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) return 0; /* step 5: check the ACK field */ - acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH | - FLAG_UPDATE_TS_RECENT | - FLAG_NO_CHALLENGE_ACK) > 0; + ret = tcp_ack(sk, skb, FLAG_SLOWPATH | + FLAG_UPDATE_TS_RECENT | + FLAG_NO_CHALLENGE_ACK); + acceptable = ret > 0; if (!acceptable) { if (sk->sk_state == TCP_SYN_RECV) return 1; /* send one RST */ - tcp_send_challenge_ack(sk); + if (ret > -2) + tcp_send_challenge_ack(sk); goto discard; } switch (sk->sk_state) { -- 2.25.1
| |