| .. | .. |
|---|
| 100 | 100 | return 1; |
|---|
| 101 | 101 | } |
|---|
| 102 | 102 | |
|---|
| 103 | +static inline int IP_ECN_set_ect1(struct iphdr *iph) |
|---|
| 104 | +{ |
|---|
| 105 | + u32 check = (__force u32)iph->check; |
|---|
| 106 | + |
|---|
| 107 | + if ((iph->tos & INET_ECN_MASK) != INET_ECN_ECT_0) |
|---|
| 108 | + return 0; |
|---|
| 109 | + |
|---|
| 110 | + check += (__force u16)htons(0x1); |
|---|
| 111 | + |
|---|
| 112 | + iph->check = (__force __sum16)(check + (check>=0xFFFF)); |
|---|
| 113 | + iph->tos ^= INET_ECN_MASK; |
|---|
| 114 | + return 1; |
|---|
| 115 | +} |
|---|
| 116 | + |
|---|
| 103 | 117 | static inline void IP_ECN_clear(struct iphdr *iph) |
|---|
| 104 | 118 | { |
|---|
| 105 | 119 | iph->tos &= ~INET_ECN_MASK; |
|---|
| .. | .. |
|---|
| 135 | 149 | return 1; |
|---|
| 136 | 150 | } |
|---|
| 137 | 151 | |
|---|
| 152 | +static inline int IP6_ECN_set_ect1(struct sk_buff *skb, struct ipv6hdr *iph) |
|---|
| 153 | +{ |
|---|
| 154 | + __be32 from, to; |
|---|
| 155 | + |
|---|
| 156 | + if ((ipv6_get_dsfield(iph) & INET_ECN_MASK) != INET_ECN_ECT_0) |
|---|
| 157 | + return 0; |
|---|
| 158 | + |
|---|
| 159 | + from = *(__be32 *)iph; |
|---|
| 160 | + to = from ^ htonl(INET_ECN_MASK << 20); |
|---|
| 161 | + *(__be32 *)iph = to; |
|---|
| 162 | + if (skb->ip_summed == CHECKSUM_COMPLETE) |
|---|
| 163 | + skb->csum = csum_add(csum_sub(skb->csum, (__force __wsum)from), |
|---|
| 164 | + (__force __wsum)to); |
|---|
| 165 | + return 1; |
|---|
| 166 | +} |
|---|
| 167 | + |
|---|
| 138 | 168 | static inline void ipv6_copy_dscp(unsigned int dscp, struct ipv6hdr *inner) |
|---|
| 139 | 169 | { |
|---|
| 140 | 170 | dscp &= ~INET_ECN_MASK; |
|---|
| .. | .. |
|---|
| 154 | 184 | if (skb_network_header(skb) + sizeof(struct ipv6hdr) <= |
|---|
| 155 | 185 | skb_tail_pointer(skb)) |
|---|
| 156 | 186 | return IP6_ECN_set_ce(skb, ipv6_hdr(skb)); |
|---|
| 187 | + break; |
|---|
| 188 | + } |
|---|
| 189 | + |
|---|
| 190 | + return 0; |
|---|
| 191 | +} |
|---|
| 192 | + |
|---|
| 193 | +static inline int INET_ECN_set_ect1(struct sk_buff *skb) |
|---|
| 194 | +{ |
|---|
| 195 | + switch (skb_protocol(skb, true)) { |
|---|
| 196 | + case cpu_to_be16(ETH_P_IP): |
|---|
| 197 | + if (skb_network_header(skb) + sizeof(struct iphdr) <= |
|---|
| 198 | + skb_tail_pointer(skb)) |
|---|
| 199 | + return IP_ECN_set_ect1(ip_hdr(skb)); |
|---|
| 200 | + break; |
|---|
| 201 | + |
|---|
| 202 | + case cpu_to_be16(ETH_P_IPV6): |
|---|
| 203 | + if (skb_network_header(skb) + sizeof(struct ipv6hdr) <= |
|---|
| 204 | + skb_tail_pointer(skb)) |
|---|
| 205 | + return IP6_ECN_set_ect1(skb, ipv6_hdr(skb)); |
|---|
| 157 | 206 | break; |
|---|
| 158 | 207 | } |
|---|
| 159 | 208 | |
|---|
| .. | .. |
|---|
| 184 | 233 | * 1 if something is broken and should be logged (!!! above) |
|---|
| 185 | 234 | * 2 if packet should be dropped |
|---|
| 186 | 235 | */ |
|---|
| 187 | | -static inline int INET_ECN_decapsulate(struct sk_buff *skb, |
|---|
| 188 | | - __u8 outer, __u8 inner) |
|---|
| 236 | +static inline int __INET_ECN_decapsulate(__u8 outer, __u8 inner, bool *set_ce) |
|---|
| 189 | 237 | { |
|---|
| 190 | 238 | if (INET_ECN_is_not_ect(inner)) { |
|---|
| 191 | 239 | switch (outer & INET_ECN_MASK) { |
|---|
| .. | .. |
|---|
| 199 | 247 | } |
|---|
| 200 | 248 | } |
|---|
| 201 | 249 | |
|---|
| 202 | | - if (INET_ECN_is_ce(outer)) |
|---|
| 203 | | - INET_ECN_set_ce(skb); |
|---|
| 204 | | - |
|---|
| 250 | + *set_ce = INET_ECN_is_ce(outer); |
|---|
| 205 | 251 | return 0; |
|---|
| 206 | 252 | } |
|---|
| 207 | 253 | |
|---|
| 254 | +static inline int INET_ECN_decapsulate(struct sk_buff *skb, |
|---|
| 255 | + __u8 outer, __u8 inner) |
|---|
| 256 | +{ |
|---|
| 257 | + bool set_ce = false; |
|---|
| 258 | + int rc; |
|---|
| 259 | + |
|---|
| 260 | + rc = __INET_ECN_decapsulate(outer, inner, &set_ce); |
|---|
| 261 | + if (!rc) { |
|---|
| 262 | + if (set_ce) |
|---|
| 263 | + INET_ECN_set_ce(skb); |
|---|
| 264 | + else if ((outer & INET_ECN_MASK) == INET_ECN_ECT_1) |
|---|
| 265 | + INET_ECN_set_ect1(skb); |
|---|
| 266 | + } |
|---|
| 267 | + |
|---|
| 268 | + return rc; |
|---|
| 269 | +} |
|---|
| 270 | + |
|---|
| 208 | 271 | static inline int IP_ECN_decapsulate(const struct iphdr *oiph, |
|---|
| 209 | 272 | struct sk_buff *skb) |
|---|
| 210 | 273 | { |
|---|