diff options
Diffstat (limited to 'include/net/inet_ecn.h')
| -rw-r--r-- | include/net/inet_ecn.h | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h index f87845e2e965..b0c47e2eccf1 100644 --- a/include/net/inet_ecn.h +++ b/include/net/inet_ecn.h | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | #define _INET_ECN_H_ | 2 | #define _INET_ECN_H_ |
| 3 | 3 | ||
| 4 | #include <linux/ip.h> | 4 | #include <linux/ip.h> |
| 5 | #include <linux/skbuff.h> | ||
| 5 | #include <net/dsfield.h> | 6 | #include <net/dsfield.h> |
| 6 | 7 | ||
| 7 | enum { | 8 | enum { |
| @@ -48,7 +49,7 @@ static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner) | |||
| 48 | (label) |= __constant_htons(INET_ECN_ECT_0 << 4); \ | 49 | (label) |= __constant_htons(INET_ECN_ECT_0 << 4); \ |
| 49 | } while (0) | 50 | } while (0) |
| 50 | 51 | ||
| 51 | static inline void IP_ECN_set_ce(struct iphdr *iph) | 52 | static inline int IP_ECN_set_ce(struct iphdr *iph) |
| 52 | { | 53 | { |
| 53 | u32 check = iph->check; | 54 | u32 check = iph->check; |
| 54 | u32 ecn = (iph->tos + 1) & INET_ECN_MASK; | 55 | u32 ecn = (iph->tos + 1) & INET_ECN_MASK; |
| @@ -61,7 +62,7 @@ static inline void IP_ECN_set_ce(struct iphdr *iph) | |||
| 61 | * INET_ECN_CE => 00 | 62 | * INET_ECN_CE => 00 |
| 62 | */ | 63 | */ |
| 63 | if (!(ecn & 2)) | 64 | if (!(ecn & 2)) |
| 64 | return; | 65 | return !ecn; |
| 65 | 66 | ||
| 66 | /* | 67 | /* |
| 67 | * The following gives us: | 68 | * The following gives us: |
| @@ -72,6 +73,7 @@ static inline void IP_ECN_set_ce(struct iphdr *iph) | |||
| 72 | 73 | ||
| 73 | iph->check = check + (check>=0xFFFF); | 74 | iph->check = check + (check>=0xFFFF); |
| 74 | iph->tos |= INET_ECN_CE; | 75 | iph->tos |= INET_ECN_CE; |
| 76 | return 1; | ||
| 75 | } | 77 | } |
| 76 | 78 | ||
| 77 | static inline void IP_ECN_clear(struct iphdr *iph) | 79 | static inline void IP_ECN_clear(struct iphdr *iph) |
| @@ -87,11 +89,12 @@ static inline void ipv4_copy_dscp(struct iphdr *outer, struct iphdr *inner) | |||
| 87 | 89 | ||
| 88 | struct ipv6hdr; | 90 | struct ipv6hdr; |
| 89 | 91 | ||
| 90 | static inline void IP6_ECN_set_ce(struct ipv6hdr *iph) | 92 | static inline int IP6_ECN_set_ce(struct ipv6hdr *iph) |
| 91 | { | 93 | { |
| 92 | if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph))) | 94 | if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph))) |
| 93 | return; | 95 | return 0; |
| 94 | *(u32*)iph |= htonl(INET_ECN_CE << 20); | 96 | *(u32*)iph |= htonl(INET_ECN_CE << 20); |
| 97 | return 1; | ||
| 95 | } | 98 | } |
| 96 | 99 | ||
| 97 | static inline void IP6_ECN_clear(struct ipv6hdr *iph) | 100 | static inline void IP6_ECN_clear(struct ipv6hdr *iph) |
| @@ -105,4 +108,21 @@ static inline void ipv6_copy_dscp(struct ipv6hdr *outer, struct ipv6hdr *inner) | |||
| 105 | ipv6_change_dsfield(inner, INET_ECN_MASK, dscp); | 108 | ipv6_change_dsfield(inner, INET_ECN_MASK, dscp); |
| 106 | } | 109 | } |
| 107 | 110 | ||
| 111 | static inline int INET_ECN_set_ce(struct sk_buff *skb) | ||
| 112 | { | ||
| 113 | switch (skb->protocol) { | ||
| 114 | case __constant_htons(ETH_P_IP): | ||
| 115 | if (skb->nh.raw + sizeof(struct iphdr) <= skb->tail) | ||
| 116 | return IP_ECN_set_ce(skb->nh.iph); | ||
| 117 | break; | ||
| 118 | |||
| 119 | case __constant_htons(ETH_P_IPV6): | ||
| 120 | if (skb->nh.raw + sizeof(struct ipv6hdr) <= skb->tail) | ||
| 121 | return IP6_ECN_set_ce(skb->nh.ipv6h); | ||
| 122 | break; | ||
| 123 | } | ||
| 124 | |||
| 125 | return 0; | ||
| 126 | } | ||
| 127 | |||
| 108 | #endif | 128 | #endif |
