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: disable RFC3168 fallback identifier for CC modules

When AccECN is not successfully negociated for a TCP flow, it defaults
fallback to classic ECN (RFC3168). However, L4S service will fallback
to non-ECN.

This patch enables congestion control module to control whether it
should not fallback to classic ECN after unsuccessful AccECN negotiation.
A new CA module flag (TCP_CONG_NO_FALLBACK_RFC3168) identifies this
behavior expected by the CA.

Signed-off-by: Chia-Yu Chang <chia-yu.chang@nokia-bell-labs.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260131222515.8485-6-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
e68c28f2 100f946b

+24 -8
+11 -1
include/net/tcp.h
··· 1219 1219 #define TCP_CONG_NEEDS_ACCECN BIT(2) 1220 1220 /* Use ECT(1) instead of ECT(0) while the CA is uninitialized */ 1221 1221 #define TCP_CONG_ECT_1_NEGOTIATION BIT(3) 1222 + /* Cannot fallback to RFC3168 during AccECN negotiation */ 1223 + #define TCP_CONG_NO_FALLBACK_RFC3168 BIT(4) 1222 1224 #define TCP_CONG_MASK (TCP_CONG_NON_RESTRICTED | TCP_CONG_NEEDS_ECN | \ 1223 - TCP_CONG_NEEDS_ACCECN | TCP_CONG_ECT_1_NEGOTIATION) 1225 + TCP_CONG_NEEDS_ACCECN | TCP_CONG_ECT_1_NEGOTIATION | \ 1226 + TCP_CONG_NO_FALLBACK_RFC3168) 1224 1227 1225 1228 union tcp_cc_info; 1226 1229 ··· 1376 1373 const struct inet_connection_sock *icsk = inet_csk(sk); 1377 1374 1378 1375 return icsk->icsk_ca_ops->flags & TCP_CONG_ECT_1_NEGOTIATION; 1376 + } 1377 + 1378 + static inline bool tcp_ca_no_fallback_rfc3168(const struct sock *sk) 1379 + { 1380 + const struct inet_connection_sock *icsk = inet_csk(sk); 1381 + 1382 + return icsk->icsk_ca_ops->flags & TCP_CONG_NO_FALLBACK_RFC3168; 1379 1383 } 1380 1384 1381 1385 static inline void tcp_ca_event(struct sock *sk, const enum tcp_ca_event event)
+8 -3
include/net/tcp_ecn.h
··· 507 507 * | ECN | AccECN | 0 0 1 | Classic ECN | 508 508 * +========+========+============+=============+ 509 509 */ 510 - if (tcp_ecn_mode_pending(tp)) 510 + if (tcp_ca_no_fallback_rfc3168(sk)) 511 + tcp_ecn_mode_set(tp, TCP_ECN_DISABLED); 512 + else if (tcp_ecn_mode_pending(tp)) 511 513 /* Downgrade from AccECN, or requested initially */ 512 514 tcp_ecn_mode_set(tp, TCP_ECN_MODE_RFC3168); 513 515 break; ··· 533 531 } 534 532 } 535 533 536 - static inline void tcp_ecn_rcv_syn(struct tcp_sock *tp, const struct tcphdr *th, 534 + static inline void tcp_ecn_rcv_syn(struct sock *sk, const struct tcphdr *th, 537 535 const struct sk_buff *skb) 538 536 { 537 + struct tcp_sock *tp = tcp_sk(sk); 538 + 539 539 if (tcp_ecn_mode_pending(tp)) { 540 540 if (!tcp_accecn_syn_requested(th)) { 541 541 /* Downgrade to classic ECN feedback */ ··· 549 545 tcp_ecn_mode_set(tp, TCP_ECN_MODE_ACCECN); 550 546 } 551 547 } 552 - if (tcp_ecn_mode_rfc3168(tp) && (!th->ece || !th->cwr)) 548 + if (tcp_ecn_mode_rfc3168(tp) && 549 + (!th->ece || !th->cwr || tcp_ca_no_fallback_rfc3168(sk))) 553 550 tcp_ecn_mode_set(tp, TCP_ECN_DISABLED); 554 551 } 555 552
+1 -1
net/ipv4/tcp_input.c
··· 7090 7090 tp->snd_wl1 = TCP_SKB_CB(skb)->seq; 7091 7091 tp->max_window = tp->snd_wnd; 7092 7092 7093 - tcp_ecn_rcv_syn(tp, th, skb); 7093 + tcp_ecn_rcv_syn(sk, th, skb); 7094 7094 7095 7095 tcp_mtup_init(sk); 7096 7096 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
+4 -3
net/ipv4/tcp_minisocks.c
··· 485 485 tp->accecn_opt_demand = 1; 486 486 tcp_ecn_received_counters_payload(sk, skb); 487 487 } else { 488 - tcp_ecn_mode_set(tp, inet_rsk(req)->ecn_ok ? 489 - TCP_ECN_MODE_RFC3168 : 490 - TCP_ECN_DISABLED); 488 + if (inet_rsk(req)->ecn_ok && !tcp_ca_no_fallback_rfc3168(sk)) 489 + tcp_ecn_mode_set(tp, TCP_ECN_MODE_RFC3168); 490 + else 491 + tcp_ecn_mode_set(tp, TCP_ECN_DISABLED); 491 492 } 492 493 } 493 494