1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 #ifndef _TCP_ECN_H 3 #define _TCP_ECN_H 4 5 #include <linux/tcp.h> 6 #include <linux/skbuff.h> 7 8 #include <net/inet_connection_sock.h> 9 #include <net/sock.h> 10 #include <net/tcp.h> 11 #include <net/inet_ecn.h> 12 13 static inline void tcp_ecn_queue_cwr(struct tcp_sock *tp) 14 { 15 if (tcp_ecn_mode_rfc3168(tp)) 16 tp->ecn_flags |= TCP_ECN_QUEUE_CWR; 17 } 18 19 static inline void tcp_ecn_accept_cwr(struct sock *sk, 20 const struct sk_buff *skb) 21 { 22 if (tcp_hdr(skb)->cwr) { 23 tcp_sk(sk)->ecn_flags &= ~TCP_ECN_DEMAND_CWR; 24 25 /* If the sender is telling us it has entered CWR, then its 26 * cwnd may be very low (even just 1 packet), so we should ACK 27 * immediately. 28 */ 29 if (TCP_SKB_CB(skb)->seq != TCP_SKB_CB(skb)->end_seq) 30 inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_NOW; 31 } 32 } 33 34 static inline void tcp_ecn_withdraw_cwr(struct tcp_sock *tp) 35 { 36 tp->ecn_flags &= ~TCP_ECN_QUEUE_CWR; 37 } 38 39 static inline void tcp_ecn_rcv_synack(struct tcp_sock *tp, 40 const struct tcphdr *th) 41 { 42 if (tcp_ecn_mode_rfc3168(tp) && (!th->ece || th->cwr)) 43 tcp_ecn_mode_set(tp, TCP_ECN_DISABLED); 44 } 45 46 static inline void tcp_ecn_rcv_syn(struct tcp_sock *tp, 47 const struct tcphdr *th) 48 { 49 if (tcp_ecn_mode_rfc3168(tp) && (!th->ece || !th->cwr)) 50 tcp_ecn_mode_set(tp, TCP_ECN_DISABLED); 51 } 52 53 static inline bool tcp_ecn_rcv_ecn_echo(const struct tcp_sock *tp, 54 const struct tcphdr *th) 55 { 56 if (th->ece && !th->syn && tcp_ecn_mode_rfc3168(tp)) 57 return true; 58 return false; 59 } 60 61 /* Packet ECN state for a SYN-ACK */ 62 static inline void tcp_ecn_send_synack(struct sock *sk, struct sk_buff *skb) 63 { 64 const struct tcp_sock *tp = tcp_sk(sk); 65 66 TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_CWR; 67 if (tcp_ecn_disabled(tp)) 68 TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_ECE; 69 else if (tcp_ca_needs_ecn(sk) || 70 tcp_bpf_ca_needs_ecn(sk)) 71 INET_ECN_xmit(sk); 72 } 73 74 /* Packet ECN state for a SYN. */ 75 static inline void tcp_ecn_send_syn(struct sock *sk, struct sk_buff *skb) 76 { 77 struct tcp_sock *tp = tcp_sk(sk); 78 bool bpf_needs_ecn = tcp_bpf_ca_needs_ecn(sk); 79 bool use_ecn = READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_ecn) == 1 || 80 tcp_ca_needs_ecn(sk) || bpf_needs_ecn; 81 82 if (!use_ecn) { 83 const struct dst_entry *dst = __sk_dst_get(sk); 84 85 if (dst && dst_feature(dst, RTAX_FEATURE_ECN)) 86 use_ecn = true; 87 } 88 89 tp->ecn_flags = 0; 90 91 if (use_ecn) { 92 if (tcp_ca_needs_ecn(sk) || bpf_needs_ecn) 93 INET_ECN_xmit(sk); 94 95 TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_ECE | TCPHDR_CWR; 96 tcp_ecn_mode_set(tp, TCP_ECN_MODE_RFC3168); 97 } 98 } 99 100 static inline void tcp_ecn_clear_syn(struct sock *sk, struct sk_buff *skb) 101 { 102 if (READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_ecn_fallback)) 103 /* tp->ecn_flags are cleared at a later point in time when 104 * SYN ACK is ultimatively being received. 105 */ 106 TCP_SKB_CB(skb)->tcp_flags &= ~(TCPHDR_ECE | TCPHDR_CWR); 107 } 108 109 static inline void 110 tcp_ecn_make_synack(const struct request_sock *req, struct tcphdr *th) 111 { 112 if (inet_rsk(req)->ecn_ok) 113 th->ece = 1; 114 } 115 116 #endif /* _LINUX_TCP_ECN_H */ 117