xref: /linux/include/net/tcp_ecn.h (revision 30f5ca00624397d81c99515bdd43286ade93d7c8)
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