From: Chia-Yu Chang chia-yu.chang@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.chang@nokia-bell-labs.com Co-developed-by: Ilpo Järvinen ij@kernel.org Signed-off-by: Ilpo Järvinen ij@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 9a90d6e77f6a..31326c462396 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -3393,6 +3393,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: {