Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

tcp: accecn: unset ECT if receive or send ACE=0 in AccECN negotiaion

Based on specification:
https://tools.ietf.org/id/draft-ietf-tcpm-accurate-ecn-28.txt

Based on Section 3.1.5 of AccECN spec (RFC9768), a TCP Server in
AccECN mode MUST NOT set ECT on any packet for the rest of the connection,
if it has received or sent at least one valid SYN or Acceptable SYN/ACK
with (AE,CWR,ECE) = (0,0,0) during the handshake.

In addition, a host in AccECN mode that is feeding back the IP-ECN
field on a SYN or SYN/ACK MUST feed back the IP-ECN field on the
latest valid SYN or acceptable SYN/ACK to arrive.

Signed-off-by: Chia-Yu Chang <chia-yu.chang@nokia-bell-labs.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260131222515.8485-11-chia-yu.chang@nokia-bell-labs.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Chia-Yu Chang and committed by
Paolo Abeni
4024081f f326f1f1

+36 -9
+3
net/ipv4/inet_connection_sock.c
··· 20 20 #include <net/tcp_states.h> 21 21 #include <net/xfrm.h> 22 22 #include <net/tcp.h> 23 + #include <net/tcp_ecn.h> 23 24 #include <net/sock_reuseport.h> 24 25 #include <net/addrconf.h> 25 26 ··· 1104 1103 (!resend || 1105 1104 !tcp_rtx_synack(sk_listener, req) || 1106 1105 inet_rsk(req)->acked)) { 1106 + if (req->num_retrans > 1 && tcp_rsk(req)->accecn_ok) 1107 + tcp_rsk(req)->accecn_fail_mode |= TCP_ACCECN_ACE_FAIL_SEND; 1107 1108 if (req->num_timeout++ == 0) 1108 1109 atomic_dec(&queue->young); 1109 1110 mod_timer(&req->rsk_timer, jiffies + tcp_reqsk_timeout(req));
+2
net/ipv4/tcp_input.c
··· 6469 6469 if (th->syn) { 6470 6470 if (tcp_ecn_mode_accecn(tp)) { 6471 6471 accecn_reflector = true; 6472 + tp->syn_ect_rcv = TCP_SKB_CB(skb)->ip_dsfield & 6473 + INET_ECN_MASK; 6472 6474 if (tp->rx_opt.accecn && 6473 6475 tp->saw_accecn_opt < TCP_ACCECN_OPT_COUNTER_SEEN) { 6474 6476 u8 saw_opt = tcp_accecn_option_init(skb, tp->rx_opt.accecn);
+24 -8
net/ipv4/tcp_minisocks.c
··· 481 481 tp->syn_ect_snt = treq->syn_ect_snt; 482 482 tcp_accecn_third_ack(sk, skb, treq->syn_ect_snt); 483 483 tp->saw_accecn_opt = treq->saw_accecn_opt; 484 + if (treq->accecn_fail_mode & TCP_ACCECN_ACE_FAIL_SEND) 485 + tcp_accecn_fail_mode_set(tp, TCP_ACCECN_ACE_FAIL_SEND); 486 + if (treq->accecn_fail_mode & TCP_ACCECN_ACE_FAIL_RECV) 487 + tcp_accecn_fail_mode_set(tp, TCP_ACCECN_ACE_FAIL_RECV); 484 488 tp->prev_ecnfield = treq->syn_ect_rcv; 485 489 tp->accecn_opt_demand = 1; 486 490 tcp_ecn_received_counters_payload(sk, skb); ··· 753 749 */ 754 750 if (!tcp_oow_rate_limited(sock_net(sk), skb, 755 751 LINUX_MIB_TCPACKSKIPPEDSYNRECV, 756 - &tcp_rsk(req)->last_oow_ack_time) && 752 + &tcp_rsk(req)->last_oow_ack_time)) { 753 + if (tcp_rsk(req)->accecn_ok) { 754 + u8 ect_rcv = TCP_SKB_CB(skb)->ip_dsfield & 755 + INET_ECN_MASK; 757 756 758 - !tcp_rtx_synack(sk, req)) { 759 - unsigned long expires = jiffies; 757 + tcp_rsk(req)->syn_ect_rcv = ect_rcv; 758 + if (tcp_accecn_ace(tcp_hdr(skb)) == 0x0) 759 + tcp_rsk(req)->accecn_fail_mode |= TCP_ACCECN_ACE_FAIL_RECV; 760 + } 761 + if (!tcp_rtx_synack(sk, req)) { 762 + unsigned long expires = jiffies; 760 763 761 - expires += tcp_reqsk_timeout(req); 762 - if (!fastopen) 763 - mod_timer_pending(&req->rsk_timer, expires); 764 - else 765 - req->rsk_timer.expires = expires; 764 + if (req->num_retrans > 1 && tcp_rsk(req)->accecn_ok) 765 + tcp_rsk(req)->accecn_fail_mode |= TCP_ACCECN_ACE_FAIL_SEND; 766 + 767 + expires += tcp_reqsk_timeout(req); 768 + if (!fastopen) 769 + mod_timer_pending(&req->rsk_timer, 770 + expires); 771 + else 772 + req->rsk_timer.expires = expires; 773 + } 766 774 } 767 775 return NULL; 768 776 }
+4 -1
net/ipv4/tcp_output.c
··· 334 334 return; 335 335 336 336 if (tcp_ecn_mode_accecn(tp)) { 337 - if (!tcp_accecn_ace_fail_recv(tp)) 337 + if (!tcp_accecn_ace_fail_recv(tp) && 338 + !tcp_accecn_ace_fail_send(tp)) 338 339 INET_ECN_xmit(sk); 340 + else 341 + INET_ECN_dontxmit(sk); 339 342 tcp_accecn_set_ace(tp, skb, th); 340 343 skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ACCECN; 341 344 } else {
+3
net/ipv4/tcp_timer.c
··· 22 22 #include <linux/module.h> 23 23 #include <linux/gfp.h> 24 24 #include <net/tcp.h> 25 + #include <net/tcp_ecn.h> 25 26 #include <net/rstreason.h> 26 27 27 28 static u32 tcp_clamp_rto_to_user_timeout(const struct sock *sk) ··· 480 479 * it's not good to give up too easily. 481 480 */ 482 481 tcp_rtx_synack(sk, req); 482 + if (req->num_retrans > 1 && tcp_rsk(req)->accecn_ok) 483 + tcp_rsk(req)->accecn_fail_mode |= TCP_ACCECN_ACE_FAIL_SEND; 483 484 req->num_timeout++; 484 485 tcp_update_rto_stats(sk); 485 486 if (!tp->retrans_stamp)