[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250918162133.111922-13-chia-yu.chang@nokia-bell-labs.com>
Date: Thu, 18 Sep 2025 18:21:31 +0200
From: chia-yu.chang@...ia-bell-labs.com
To: pabeni@...hat.com,
edumazet@...gle.com,
linux-doc@...r.kernel.org,
corbet@....net,
horms@...nel.org,
dsahern@...nel.org,
kuniyu@...zon.com,
bpf@...r.kernel.org,
netdev@...r.kernel.org,
dave.taht@...il.com,
jhs@...atatu.com,
kuba@...nel.org,
stephen@...workplumber.org,
xiyou.wangcong@...il.com,
jiri@...nulli.us,
davem@...emloft.net,
andrew+netdev@...n.ch,
donald.hunter@...il.com,
ast@...erby.net,
liuhangbin@...il.com,
shuah@...nel.org,
linux-kselftest@...r.kernel.org,
ij@...nel.org,
ncardwell@...gle.com,
koen.de_schepper@...ia-bell-labs.com,
g.white@...lelabs.com,
ingemar.s.johansson@...csson.com,
mirja.kuehlewind@...csson.com,
cheshire@...le.com,
rs.ietf@....at,
Jason_Livingood@...cast.com,
vidhi_goel@...le.com
Cc: Chia-Yu Chang <chia-yu.chang@...ia-bell-labs.com>
Subject: [PATCH v2 net-next 12/14] tcp: accecn: verify ACE counter in 1st ACK after AccECN negotiation
From: Chia-Yu Chang <chia-yu.chang@...ia-bell-labs.com>
After successfully negotiating AccECN mode in the handshake, check
the ACE field of the first data ACK. If zero (0b000), non-ECT packets
are sent and any response to CE marking feedback is disabled. This
follows Section 3.2.2.4 of AccECN spec (RFC9768).
Signed-off-by: Chia-Yu Chang <chia-yu.chang@...ia-bell-labs.com>
---
net/ipv4/tcp_input.c | 24 +++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 752251268cbe..f250b4912a0b 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -495,7 +495,7 @@ static void tcp_count_delivered(struct tcp_sock *tp, u32 delivered,
/* Returns the ECN CE delta */
static u32 __tcp_accecn_process(struct sock *sk, const struct sk_buff *skb,
u32 delivered_pkts, u32 delivered_bytes,
- int flag)
+ u64 prior_bytes_acked, int flag)
{
u32 old_ceb = tcp_sk(sk)->delivered_ecn_bytes[INET_ECN_CE - 1];
const struct tcphdr *th = tcp_hdr(skb);
@@ -534,6 +534,16 @@ static u32 __tcp_accecn_process(struct sock *sk, const struct sk_buff *skb,
if (flag & FLAG_SYN_ACKED)
return 0;
+ /* Verify ACE!=0 in the 1st data ACK after AccECN negotiation */
+ if ((flag & FLAG_DATA_ACKED) && prior_bytes_acked <= tp->mss_cache) {
+ if (tcp_accecn_ace(tcp_hdr(skb)) == 0x0) {
+ INET_ECN_dontxmit(sk);
+ tcp_accecn_fail_mode_set(tp, TCP_ACCECN_ACE_FAIL_RECV |
+ TCP_ACCECN_OPT_FAIL_RECV);
+ return 0;
+ }
+ }
+
if (tp->received_ce_pending >= TCP_ACCECN_ACE_MAX_DELTA)
inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_NOW;
@@ -580,13 +590,14 @@ static u32 __tcp_accecn_process(struct sock *sk, const struct sk_buff *skb,
static void tcp_accecn_process(struct sock *sk, struct rate_sample *rs,
const struct sk_buff *skb, u32 delivered_pkts,
- u32 delivered_bytes, int *flag)
+ u32 delivered_bytes, u64 prior_bytes_acked,
+ int *flag)
{
struct tcp_sock *tp = tcp_sk(sk);
u32 delta;
delta = __tcp_accecn_process(sk, skb, delivered_pkts,
- delivered_bytes, *flag);
+ delivered_bytes, prior_bytes_acked, *flag);
if (delta > 0) {
tcp_count_delivered_ce(tp, delta);
*flag |= FLAG_ECE;
@@ -3997,6 +4008,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
struct tcp_sock *tp = tcp_sk(sk);
struct tcp_sacktag_state sack_state;
struct rate_sample rs = { .prior_delivered = 0, .ece_delta = 0 };
+ u64 prior_bytes_acked = tp->bytes_acked;
u32 prior_snd_una = tp->snd_una;
bool is_sack_reneg = tp->is_sack_reneg;
u32 ack_seq = TCP_SKB_CB(skb)->seq;
@@ -4116,7 +4128,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
if (tcp_ecn_mode_accecn(tp))
tcp_accecn_process(sk, &rs, skb, tp->delivered - delivered,
- sack_state.delivered_bytes, &flag);
+ sack_state.delivered_bytes,
+ prior_bytes_acked, &flag);
tcp_in_ack_event(sk, flag);
@@ -4154,7 +4167,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
no_queue:
if (tcp_ecn_mode_accecn(tp))
tcp_accecn_process(sk, &rs, skb, tp->delivered - delivered,
- sack_state.delivered_bytes, &flag);
+ sack_state.delivered_bytes,
+ prior_bytes_acked, &flag);
tcp_in_ack_event(sk, flag);
/* If data was DSACKed, see if we can undo a cwnd reduction. */
if (flag & FLAG_DSACKING_ACK) {
--
2.34.1
Powered by blists - more mailing lists