From: Chia-Yu Chang <chia-yu.ch...@nokia-bell-labs.com>

In simultaneous connect scenario, the connection will be established
when SYN/ACK is received after patch 23e89e8ee7be7. However, the
third ACK is still anticipated to complete the negotiation for either
RFC3168 ECN and Accurate ECN. In this sense, an additional flag
wait_third_ack is introduced to identify that the 3rd ACK is still
anticipated to ensure ECN or AccECN negotiation will be done in the
ESTABLISHED state.

Signed-off-by: Chia-Yu Chang <chia-yu.ch...@nokia-bell-labs.com>
Co-developed-by: Ilpo Järvinen <i...@kernel.org>
Signed-off-by: Ilpo Järvinen <i...@kernel.org>
---
 .../networking/net_cachelines/tcp_sock.rst    |  1 +
 include/linux/tcp.h                           |  3 ++-
 net/ipv4/tcp.c                                |  1 +
 net/ipv4/tcp_input.c                          | 23 +++++++++++++++----
 4 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/Documentation/networking/net_cachelines/tcp_sock.rst 
b/Documentation/networking/net_cachelines/tcp_sock.rst
index 4f71ece7c655..22ac668fe6c7 100644
--- a/Documentation/networking/net_cachelines/tcp_sock.rst
+++ b/Documentation/networking/net_cachelines/tcp_sock.rst
@@ -105,6 +105,7 @@ u32                           received_ce             
read_mostly         read_w
 u8:4                          received_ce_pending     read_mostly         
read_write
 u8:2                          syn_ect_snt             write_mostly        
read_write
 u8:2                          syn_ect_rcv             read_mostly         
read_write
+u8:1                          wait_third_ack                              
read_write
 u8:4                          accecn_fail_mode
 u32                           lost                                        
read_mostly         tcp_ack
 u32                           app_limited             read_write          
read_mostly         
tcp_rate_check_app_limited,tcp_rate_skb_sent(tx);tcp_rate_gen(rx)
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 994a6e7256e1..1d8301f2883c 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -380,7 +380,8 @@ struct tcp_sock {
        u8      dup_ack_counter:2,
                tlp_retrans:1,  /* TLP is a retransmission */
                syn_ect_snt:2,  /* AccECN ECT memory, only */
-               syn_ect_rcv:2;  /* ... needed durign 3WHS + first seqno */
+               syn_ect_rcv:2,  /* ... needed durign 3WHS + first seqno */
+               wait_third_ack:1; /* Wait 3rd ACK in simultaneous open */
        u8      thin_lto    : 1,/* Use linear timeouts for thin streams */
                fastopen_connect:1, /* FASTOPEN_CONNECT sockopt */
                fastopen_no_cookie:1, /* Allow send/recv SYN+data without a 
cookie */
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 45c85c788def..0548c74458c6 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -3391,6 +3391,7 @@ int tcp_disconnect(struct sock *sk, int flags)
        tp->window_clamp = 0;
        tp->delivered = 0;
        tp->delivered_ce = 0;
+       tp->wait_third_ack = 0;
        tp->accecn_fail_mode = 0;
        tcp_accecn_init_counters(tp);
        if (icsk->icsk_ca_initialized && icsk->icsk_ca_ops->release)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index ea5d47354978..7ccfde9bcfda 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -6001,8 +6001,13 @@ static bool tcp_validate_incoming(struct sock *sk, 
struct sk_buff *skb,
                if (sk->sk_state == TCP_SYN_RECV && sk->sk_socket && th->ack &&
                    TCP_SKB_CB(skb)->seq + 1 == TCP_SKB_CB(skb)->end_seq &&
                    TCP_SKB_CB(skb)->seq + 1 == tp->rcv_nxt &&
-                   TCP_SKB_CB(skb)->ack_seq == tp->snd_nxt)
+                   TCP_SKB_CB(skb)->ack_seq == tp->snd_nxt) {
+                       if (!tcp_ecn_disabled(tp)) {
+                               tp->wait_third_ack = true;
+                               tcp_send_ack_reflect_ect(sk, accecn_reflector);
+                       }
                        goto pass;
+               }
 syn_challenge:
                if (syn_inerr)
                        TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);
@@ -6220,6 +6225,12 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff 
*skb)
                return;
 
 step5:
+       if (unlikely(tp->wait_third_ack)) {
+               tp->wait_third_ack = 0;
+               if (tcp_ecn_mode_accecn(tp))
+                       tcp_accecn_third_ack(sk, skb, tp->syn_ect_snt);
+               tcp_fast_path_on(tp);
+       }
        tcp_ecn_received_counters(sk, skb);
 
        reason = tcp_ack(sk, skb, FLAG_SLOWPATH | FLAG_UPDATE_TS_RECENT);
@@ -6833,12 +6844,16 @@ tcp_rcv_state_process(struct sock *sk, struct sk_buff 
*skb)
                tp->lsndtime = tcp_jiffies32;
 
                tcp_initialize_rcv_mss(sk);
-               if (tcp_ecn_mode_accecn(tp))
-                       tcp_accecn_third_ack(sk, skb, tp->syn_ect_snt);
-               tcp_fast_path_on(tp);
+               if (likely(!tp->wait_third_ack)) {
+                       if (tcp_ecn_mode_accecn(tp))
+                               tcp_accecn_third_ack(sk, skb, tp->syn_ect_snt);
+                       tcp_fast_path_on(tp);
+               }
                if (sk->sk_shutdown & SEND_SHUTDOWN)
                        tcp_shutdown(sk, SEND_SHUTDOWN);
 
+               if (sk->sk_socket && tp->wait_third_ack)
+                       goto consume;
                break;
 
        case TCP_FIN_WAIT1: {
-- 
2.34.1


Reply via email to