mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:04:41 +01:00
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>
This commit is contained in:
parent
f326f1f17f
commit
4024081feb
5 changed files with 36 additions and 9 deletions
|
|
@ -20,6 +20,7 @@
|
|||
#include <net/tcp_states.h>
|
||||
#include <net/xfrm.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/tcp_ecn.h>
|
||||
#include <net/sock_reuseport.h>
|
||||
#include <net/addrconf.h>
|
||||
|
||||
|
|
@ -1103,6 +1104,8 @@ static void reqsk_timer_handler(struct timer_list *t)
|
|||
(!resend ||
|
||||
!tcp_rtx_synack(sk_listener, req) ||
|
||||
inet_rsk(req)->acked)) {
|
||||
if (req->num_retrans > 1 && tcp_rsk(req)->accecn_ok)
|
||||
tcp_rsk(req)->accecn_fail_mode |= TCP_ACCECN_ACE_FAIL_SEND;
|
||||
if (req->num_timeout++ == 0)
|
||||
atomic_dec(&queue->young);
|
||||
mod_timer(&req->rsk_timer, jiffies + tcp_reqsk_timeout(req));
|
||||
|
|
|
|||
|
|
@ -6469,6 +6469,8 @@ step1:
|
|||
if (th->syn) {
|
||||
if (tcp_ecn_mode_accecn(tp)) {
|
||||
accecn_reflector = true;
|
||||
tp->syn_ect_rcv = TCP_SKB_CB(skb)->ip_dsfield &
|
||||
INET_ECN_MASK;
|
||||
if (tp->rx_opt.accecn &&
|
||||
tp->saw_accecn_opt < TCP_ACCECN_OPT_COUNTER_SEEN) {
|
||||
u8 saw_opt = tcp_accecn_option_init(skb, tp->rx_opt.accecn);
|
||||
|
|
|
|||
|
|
@ -481,6 +481,10 @@ static void tcp_ecn_openreq_child(struct sock *sk,
|
|||
tp->syn_ect_snt = treq->syn_ect_snt;
|
||||
tcp_accecn_third_ack(sk, skb, treq->syn_ect_snt);
|
||||
tp->saw_accecn_opt = treq->saw_accecn_opt;
|
||||
if (treq->accecn_fail_mode & TCP_ACCECN_ACE_FAIL_SEND)
|
||||
tcp_accecn_fail_mode_set(tp, TCP_ACCECN_ACE_FAIL_SEND);
|
||||
if (treq->accecn_fail_mode & TCP_ACCECN_ACE_FAIL_RECV)
|
||||
tcp_accecn_fail_mode_set(tp, TCP_ACCECN_ACE_FAIL_RECV);
|
||||
tp->prev_ecnfield = treq->syn_ect_rcv;
|
||||
tp->accecn_opt_demand = 1;
|
||||
tcp_ecn_received_counters_payload(sk, skb);
|
||||
|
|
@ -749,16 +753,28 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
|
|||
*/
|
||||
if (!tcp_oow_rate_limited(sock_net(sk), skb,
|
||||
LINUX_MIB_TCPACKSKIPPEDSYNRECV,
|
||||
&tcp_rsk(req)->last_oow_ack_time) &&
|
||||
&tcp_rsk(req)->last_oow_ack_time)) {
|
||||
if (tcp_rsk(req)->accecn_ok) {
|
||||
u8 ect_rcv = TCP_SKB_CB(skb)->ip_dsfield &
|
||||
INET_ECN_MASK;
|
||||
|
||||
!tcp_rtx_synack(sk, req)) {
|
||||
unsigned long expires = jiffies;
|
||||
tcp_rsk(req)->syn_ect_rcv = ect_rcv;
|
||||
if (tcp_accecn_ace(tcp_hdr(skb)) == 0x0)
|
||||
tcp_rsk(req)->accecn_fail_mode |= TCP_ACCECN_ACE_FAIL_RECV;
|
||||
}
|
||||
if (!tcp_rtx_synack(sk, req)) {
|
||||
unsigned long expires = jiffies;
|
||||
|
||||
expires += tcp_reqsk_timeout(req);
|
||||
if (!fastopen)
|
||||
mod_timer_pending(&req->rsk_timer, expires);
|
||||
else
|
||||
req->rsk_timer.expires = expires;
|
||||
if (req->num_retrans > 1 && tcp_rsk(req)->accecn_ok)
|
||||
tcp_rsk(req)->accecn_fail_mode |= TCP_ACCECN_ACE_FAIL_SEND;
|
||||
|
||||
expires += tcp_reqsk_timeout(req);
|
||||
if (!fastopen)
|
||||
mod_timer_pending(&req->rsk_timer,
|
||||
expires);
|
||||
else
|
||||
req->rsk_timer.expires = expires;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -334,8 +334,11 @@ static void tcp_ecn_send(struct sock *sk, struct sk_buff *skb,
|
|||
return;
|
||||
|
||||
if (tcp_ecn_mode_accecn(tp)) {
|
||||
if (!tcp_accecn_ace_fail_recv(tp))
|
||||
if (!tcp_accecn_ace_fail_recv(tp) &&
|
||||
!tcp_accecn_ace_fail_send(tp))
|
||||
INET_ECN_xmit(sk);
|
||||
else
|
||||
INET_ECN_dontxmit(sk);
|
||||
tcp_accecn_set_ace(tp, skb, th);
|
||||
skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ACCECN;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/tcp_ecn.h>
|
||||
#include <net/rstreason.h>
|
||||
|
||||
static u32 tcp_clamp_rto_to_user_timeout(const struct sock *sk)
|
||||
|
|
@ -479,6 +480,8 @@ static void tcp_fastopen_synack_timer(struct sock *sk, struct request_sock *req)
|
|||
* it's not good to give up too easily.
|
||||
*/
|
||||
tcp_rtx_synack(sk, req);
|
||||
if (req->num_retrans > 1 && tcp_rsk(req)->accecn_ok)
|
||||
tcp_rsk(req)->accecn_fail_mode |= TCP_ACCECN_ACE_FAIL_SEND;
|
||||
req->num_timeout++;
|
||||
tcp_update_rto_stats(sk);
|
||||
if (!tp->retrans_stamp)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue