0001
0002 #ifndef _INET_ECN_H_
0003 #define _INET_ECN_H_
0004
0005 #include <linux/ip.h>
0006 #include <linux/skbuff.h>
0007 #include <linux/if_vlan.h>
0008
0009 #include <net/inet_sock.h>
0010 #include <net/dsfield.h>
0011 #include <net/checksum.h>
0012
0013 enum {
0014 INET_ECN_NOT_ECT = 0,
0015 INET_ECN_ECT_1 = 1,
0016 INET_ECN_ECT_0 = 2,
0017 INET_ECN_CE = 3,
0018 INET_ECN_MASK = 3,
0019 };
0020
0021 extern int sysctl_tunnel_ecn_log;
0022
0023 static inline int INET_ECN_is_ce(__u8 dsfield)
0024 {
0025 return (dsfield & INET_ECN_MASK) == INET_ECN_CE;
0026 }
0027
0028 static inline int INET_ECN_is_not_ect(__u8 dsfield)
0029 {
0030 return (dsfield & INET_ECN_MASK) == INET_ECN_NOT_ECT;
0031 }
0032
0033 static inline int INET_ECN_is_capable(__u8 dsfield)
0034 {
0035 return dsfield & INET_ECN_ECT_0;
0036 }
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner)
0047 {
0048 outer &= ~INET_ECN_MASK;
0049 outer |= !INET_ECN_is_ce(inner) ? (inner & INET_ECN_MASK) :
0050 INET_ECN_ECT_0;
0051 return outer;
0052 }
0053
0054 static inline void INET_ECN_xmit(struct sock *sk)
0055 {
0056 inet_sk(sk)->tos |= INET_ECN_ECT_0;
0057 if (inet6_sk(sk) != NULL)
0058 inet6_sk(sk)->tclass |= INET_ECN_ECT_0;
0059 }
0060
0061 static inline void INET_ECN_dontxmit(struct sock *sk)
0062 {
0063 inet_sk(sk)->tos &= ~INET_ECN_MASK;
0064 if (inet6_sk(sk) != NULL)
0065 inet6_sk(sk)->tclass &= ~INET_ECN_MASK;
0066 }
0067
0068 #define IP6_ECN_flow_init(label) do { \
0069 (label) &= ~htonl(INET_ECN_MASK << 20); \
0070 } while (0)
0071
0072 #define IP6_ECN_flow_xmit(sk, label) do { \
0073 if (INET_ECN_is_capable(inet6_sk(sk)->tclass)) \
0074 (label) |= htonl(INET_ECN_ECT_0 << 20); \
0075 } while (0)
0076
0077 static inline int IP_ECN_set_ce(struct iphdr *iph)
0078 {
0079 u32 ecn = (iph->tos + 1) & INET_ECN_MASK;
0080 __be16 check_add;
0081
0082
0083
0084
0085
0086
0087
0088
0089 if (!(ecn & 2))
0090 return !ecn;
0091
0092
0093
0094
0095
0096
0097 check_add = (__force __be16)((__force u16)htons(0xFFFB) +
0098 (__force u16)htons(ecn));
0099
0100 iph->check = csum16_add(iph->check, check_add);
0101 iph->tos |= INET_ECN_CE;
0102 return 1;
0103 }
0104
0105 static inline int IP_ECN_set_ect1(struct iphdr *iph)
0106 {
0107 if ((iph->tos & INET_ECN_MASK) != INET_ECN_ECT_0)
0108 return 0;
0109
0110 iph->check = csum16_add(iph->check, htons(0x1));
0111 iph->tos ^= INET_ECN_MASK;
0112 return 1;
0113 }
0114
0115 static inline void IP_ECN_clear(struct iphdr *iph)
0116 {
0117 iph->tos &= ~INET_ECN_MASK;
0118 }
0119
0120 static inline void ipv4_copy_dscp(unsigned int dscp, struct iphdr *inner)
0121 {
0122 dscp &= ~INET_ECN_MASK;
0123 ipv4_change_dsfield(inner, INET_ECN_MASK, dscp);
0124 }
0125
0126 struct ipv6hdr;
0127
0128
0129
0130
0131
0132
0133
0134 static inline int IP6_ECN_set_ce(struct sk_buff *skb, struct ipv6hdr *iph)
0135 {
0136 __be32 from, to;
0137
0138 if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph)))
0139 return 0;
0140
0141 from = *(__be32 *)iph;
0142 to = from | htonl(INET_ECN_CE << 20);
0143 *(__be32 *)iph = to;
0144 if (skb->ip_summed == CHECKSUM_COMPLETE)
0145 skb->csum = csum_add(csum_sub(skb->csum, (__force __wsum)from),
0146 (__force __wsum)to);
0147 return 1;
0148 }
0149
0150 static inline int IP6_ECN_set_ect1(struct sk_buff *skb, struct ipv6hdr *iph)
0151 {
0152 __be32 from, to;
0153
0154 if ((ipv6_get_dsfield(iph) & INET_ECN_MASK) != INET_ECN_ECT_0)
0155 return 0;
0156
0157 from = *(__be32 *)iph;
0158 to = from ^ htonl(INET_ECN_MASK << 20);
0159 *(__be32 *)iph = to;
0160 if (skb->ip_summed == CHECKSUM_COMPLETE)
0161 skb->csum = csum_add(csum_sub(skb->csum, (__force __wsum)from),
0162 (__force __wsum)to);
0163 return 1;
0164 }
0165
0166 static inline void ipv6_copy_dscp(unsigned int dscp, struct ipv6hdr *inner)
0167 {
0168 dscp &= ~INET_ECN_MASK;
0169 ipv6_change_dsfield(inner, INET_ECN_MASK, dscp);
0170 }
0171
0172 static inline int INET_ECN_set_ce(struct sk_buff *skb)
0173 {
0174 switch (skb_protocol(skb, true)) {
0175 case cpu_to_be16(ETH_P_IP):
0176 if (skb_network_header(skb) + sizeof(struct iphdr) <=
0177 skb_tail_pointer(skb))
0178 return IP_ECN_set_ce(ip_hdr(skb));
0179 break;
0180
0181 case cpu_to_be16(ETH_P_IPV6):
0182 if (skb_network_header(skb) + sizeof(struct ipv6hdr) <=
0183 skb_tail_pointer(skb))
0184 return IP6_ECN_set_ce(skb, ipv6_hdr(skb));
0185 break;
0186 }
0187
0188 return 0;
0189 }
0190
0191 static inline int skb_get_dsfield(struct sk_buff *skb)
0192 {
0193 switch (skb_protocol(skb, true)) {
0194 case cpu_to_be16(ETH_P_IP):
0195 if (!pskb_network_may_pull(skb, sizeof(struct iphdr)))
0196 break;
0197 return ipv4_get_dsfield(ip_hdr(skb));
0198
0199 case cpu_to_be16(ETH_P_IPV6):
0200 if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr)))
0201 break;
0202 return ipv6_get_dsfield(ipv6_hdr(skb));
0203 }
0204
0205 return -1;
0206 }
0207
0208 static inline int INET_ECN_set_ect1(struct sk_buff *skb)
0209 {
0210 switch (skb_protocol(skb, true)) {
0211 case cpu_to_be16(ETH_P_IP):
0212 if (skb_network_header(skb) + sizeof(struct iphdr) <=
0213 skb_tail_pointer(skb))
0214 return IP_ECN_set_ect1(ip_hdr(skb));
0215 break;
0216
0217 case cpu_to_be16(ETH_P_IPV6):
0218 if (skb_network_header(skb) + sizeof(struct ipv6hdr) <=
0219 skb_tail_pointer(skb))
0220 return IP6_ECN_set_ect1(skb, ipv6_hdr(skb));
0221 break;
0222 }
0223
0224 return 0;
0225 }
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251 static inline int __INET_ECN_decapsulate(__u8 outer, __u8 inner, bool *set_ce)
0252 {
0253 if (INET_ECN_is_not_ect(inner)) {
0254 switch (outer & INET_ECN_MASK) {
0255 case INET_ECN_NOT_ECT:
0256 return 0;
0257 case INET_ECN_ECT_0:
0258 case INET_ECN_ECT_1:
0259 return 1;
0260 case INET_ECN_CE:
0261 return 2;
0262 }
0263 }
0264
0265 *set_ce = INET_ECN_is_ce(outer);
0266 return 0;
0267 }
0268
0269 static inline int INET_ECN_decapsulate(struct sk_buff *skb,
0270 __u8 outer, __u8 inner)
0271 {
0272 bool set_ce = false;
0273 int rc;
0274
0275 rc = __INET_ECN_decapsulate(outer, inner, &set_ce);
0276 if (!rc) {
0277 if (set_ce)
0278 INET_ECN_set_ce(skb);
0279 else if ((outer & INET_ECN_MASK) == INET_ECN_ECT_1)
0280 INET_ECN_set_ect1(skb);
0281 }
0282
0283 return rc;
0284 }
0285
0286 static inline int IP_ECN_decapsulate(const struct iphdr *oiph,
0287 struct sk_buff *skb)
0288 {
0289 __u8 inner;
0290
0291 switch (skb_protocol(skb, true)) {
0292 case htons(ETH_P_IP):
0293 inner = ip_hdr(skb)->tos;
0294 break;
0295 case htons(ETH_P_IPV6):
0296 inner = ipv6_get_dsfield(ipv6_hdr(skb));
0297 break;
0298 default:
0299 return 0;
0300 }
0301
0302 return INET_ECN_decapsulate(skb, oiph->tos, inner);
0303 }
0304
0305 static inline int IP6_ECN_decapsulate(const struct ipv6hdr *oipv6h,
0306 struct sk_buff *skb)
0307 {
0308 __u8 inner;
0309
0310 switch (skb_protocol(skb, true)) {
0311 case htons(ETH_P_IP):
0312 inner = ip_hdr(skb)->tos;
0313 break;
0314 case htons(ETH_P_IPV6):
0315 inner = ipv6_get_dsfield(ipv6_hdr(skb));
0316 break;
0317 default:
0318 return 0;
0319 }
0320
0321 return INET_ECN_decapsulate(skb, ipv6_get_dsfield(oipv6h), inner);
0322 }
0323 #endif