^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