Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) #ifndef _INET_ECN_H_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) #define _INET_ECN_H_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #include <linux/ip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/if_vlan.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <net/inet_sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <net/dsfield.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 	INET_ECN_NOT_ECT = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 	INET_ECN_ECT_1 = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 	INET_ECN_ECT_0 = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 	INET_ECN_CE = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 	INET_ECN_MASK = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) extern int sysctl_tunnel_ecn_log;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) static inline int INET_ECN_is_ce(__u8 dsfield)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	return (dsfield & INET_ECN_MASK) == INET_ECN_CE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) static inline int INET_ECN_is_not_ect(__u8 dsfield)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	return (dsfield & INET_ECN_MASK) == INET_ECN_NOT_ECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) static inline int INET_ECN_is_capable(__u8 dsfield)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	return dsfield & INET_ECN_ECT_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)  * RFC 3168 9.1.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)  *  The full-functionality option for ECN encapsulation is to copy the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)  *  ECN codepoint of the inside header to the outside header on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)  *  encapsulation if the inside header is not-ECT or ECT, and to set the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  *  ECN codepoint of the outside header to ECT(0) if the ECN codepoint of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  *  the inside header is CE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	outer &= ~INET_ECN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	outer |= !INET_ECN_is_ce(inner) ? (inner & INET_ECN_MASK) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 					  INET_ECN_ECT_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	return outer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) static inline void INET_ECN_xmit(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	inet_sk(sk)->tos |= INET_ECN_ECT_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	if (inet6_sk(sk) != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		inet6_sk(sk)->tclass |= INET_ECN_ECT_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) static inline void INET_ECN_dontxmit(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	inet_sk(sk)->tos &= ~INET_ECN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	if (inet6_sk(sk) != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		inet6_sk(sk)->tclass &= ~INET_ECN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) #define IP6_ECN_flow_init(label) do {		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)       (label) &= ~htonl(INET_ECN_MASK << 20);	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)     } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) #define	IP6_ECN_flow_xmit(sk, label) do {				\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	if (INET_ECN_is_capable(inet6_sk(sk)->tclass))			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		(label) |= htonl(INET_ECN_ECT_0 << 20);			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)     } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) static inline int IP_ECN_set_ce(struct iphdr *iph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	u32 check = (__force u32)iph->check;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	u32 ecn = (iph->tos + 1) & INET_ECN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	 * After the last operation we have (in binary):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	 * INET_ECN_NOT_ECT => 01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	 * INET_ECN_ECT_1   => 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	 * INET_ECN_ECT_0   => 11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	 * INET_ECN_CE      => 00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	if (!(ecn & 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		return !ecn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	 * The following gives us:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	 * INET_ECN_ECT_1 => check += htons(0xFFFD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	 * INET_ECN_ECT_0 => check += htons(0xFFFE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	check += (__force u16)htons(0xFFFB) + (__force u16)htons(ecn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	iph->check = (__force __sum16)(check + (check>=0xFFFF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	iph->tos |= INET_ECN_CE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static inline int IP_ECN_set_ect1(struct iphdr *iph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	u32 check = (__force u32)iph->check;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	if ((iph->tos & INET_ECN_MASK) != INET_ECN_ECT_0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	check += (__force u16)htons(0x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	iph->check = (__force __sum16)(check + (check>=0xFFFF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	iph->tos ^= INET_ECN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static inline void IP_ECN_clear(struct iphdr *iph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	iph->tos &= ~INET_ECN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static inline void ipv4_copy_dscp(unsigned int dscp, struct iphdr *inner)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	dscp &= ~INET_ECN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	ipv4_change_dsfield(inner, INET_ECN_MASK, dscp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct ipv6hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /* Note:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)  * IP_ECN_set_ce() has to tweak IPV4 checksum when setting CE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)  * meaning both changes have no effect on skb->csum if/when CHECKSUM_COMPLETE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)  * In IPv6 case, no checksum compensates the change in IPv6 header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)  * so we have to update skb->csum.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static inline int IP6_ECN_set_ce(struct sk_buff *skb, struct ipv6hdr *iph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	__be32 from, to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	from = *(__be32 *)iph;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	to = from | htonl(INET_ECN_CE << 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	*(__be32 *)iph = to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	if (skb->ip_summed == CHECKSUM_COMPLETE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		skb->csum = csum_add(csum_sub(skb->csum, (__force __wsum)from),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 				     (__force __wsum)to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static inline int IP6_ECN_set_ect1(struct sk_buff *skb, struct ipv6hdr *iph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	__be32 from, to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	if ((ipv6_get_dsfield(iph) & INET_ECN_MASK) != INET_ECN_ECT_0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	from = *(__be32 *)iph;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	to = from ^ htonl(INET_ECN_MASK << 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	*(__be32 *)iph = to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	if (skb->ip_summed == CHECKSUM_COMPLETE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		skb->csum = csum_add(csum_sub(skb->csum, (__force __wsum)from),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 				     (__force __wsum)to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static inline void ipv6_copy_dscp(unsigned int dscp, struct ipv6hdr *inner)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	dscp &= ~INET_ECN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	ipv6_change_dsfield(inner, INET_ECN_MASK, dscp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static inline int INET_ECN_set_ce(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	switch (skb_protocol(skb, true)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	case cpu_to_be16(ETH_P_IP):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		if (skb_network_header(skb) + sizeof(struct iphdr) <=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		    skb_tail_pointer(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 			return IP_ECN_set_ce(ip_hdr(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	case cpu_to_be16(ETH_P_IPV6):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		if (skb_network_header(skb) + sizeof(struct ipv6hdr) <=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		    skb_tail_pointer(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 			return IP6_ECN_set_ce(skb, ipv6_hdr(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) static inline int INET_ECN_set_ect1(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	switch (skb_protocol(skb, true)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	case cpu_to_be16(ETH_P_IP):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		if (skb_network_header(skb) + sizeof(struct iphdr) <=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		    skb_tail_pointer(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 			return IP_ECN_set_ect1(ip_hdr(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	case cpu_to_be16(ETH_P_IPV6):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		if (skb_network_header(skb) + sizeof(struct ipv6hdr) <=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		    skb_tail_pointer(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 			return IP6_ECN_set_ect1(skb, ipv6_hdr(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)  * RFC 6040 4.2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)  *  To decapsulate the inner header at the tunnel egress, a compliant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)  *  tunnel egress MUST set the outgoing ECN field to the codepoint at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)  *  intersection of the appropriate arriving inner header (row) and outer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)  *  header (column) in Figure 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)  *      +---------+------------------------------------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)  *      |Arriving |            Arriving Outer Header               |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)  *      |   Inner +---------+------------+------------+------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)  *      |  Header | Not-ECT | ECT(0)     | ECT(1)     |     CE     |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)  *      +---------+---------+------------+------------+------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)  *      | Not-ECT | Not-ECT |Not-ECT(!!!)|Not-ECT(!!!)| <drop>(!!!)|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)  *      |  ECT(0) |  ECT(0) | ECT(0)     | ECT(1)     |     CE     |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)  *      |  ECT(1) |  ECT(1) | ECT(1) (!) | ECT(1)     |     CE     |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)  *      |    CE   |      CE |     CE     |     CE(!!!)|     CE     |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)  *      +---------+---------+------------+------------+------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)  *             Figure 4: New IP in IP Decapsulation Behaviour
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)  *  returns 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)  *          1 if something is broken and should be logged (!!! above)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)  *          2 if packet should be dropped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static inline int __INET_ECN_decapsulate(__u8 outer, __u8 inner, bool *set_ce)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	if (INET_ECN_is_not_ect(inner)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		switch (outer & INET_ECN_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		case INET_ECN_NOT_ECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		case INET_ECN_ECT_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 		case INET_ECN_ECT_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 			return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		case INET_ECN_CE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 			return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	*set_ce = INET_ECN_is_ce(outer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static inline int INET_ECN_decapsulate(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 				       __u8 outer, __u8 inner)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	bool set_ce = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	rc = __INET_ECN_decapsulate(outer, inner, &set_ce);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		if (set_ce)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 			INET_ECN_set_ce(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		else if ((outer & INET_ECN_MASK) == INET_ECN_ECT_1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 			INET_ECN_set_ect1(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static inline int IP_ECN_decapsulate(const struct iphdr *oiph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 				     struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	__u8 inner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	switch (skb_protocol(skb, true)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	case htons(ETH_P_IP):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		inner = ip_hdr(skb)->tos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	case htons(ETH_P_IPV6):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		inner = ipv6_get_dsfield(ipv6_hdr(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	return INET_ECN_decapsulate(skb, oiph->tos, inner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static inline int IP6_ECN_decapsulate(const struct ipv6hdr *oipv6h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 				      struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	__u8 inner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	switch (skb_protocol(skb, true)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	case htons(ETH_P_IP):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		inner = ip_hdr(skb)->tos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	case htons(ETH_P_IPV6):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		inner = ipv6_get_dsfield(ipv6_hdr(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	return INET_ECN_decapsulate(skb, ipv6_get_dsfield(oipv6h), inner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) #endif