diff options
author | Tom Herbert <therbert@google.com> | 2014-07-02 00:32:05 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-07-08 00:14:20 -0400 |
commit | 5ed20a68cd6ca4adc0aa2d240913d604a2eb3e25 (patch) | |
tree | a1640d40c35cc9f081d18d8d75f1e1759cad92ee | |
parent | 081a20ffccd24d2f5fd06debcff57697fa2ff069 (diff) |
flow_dissector: Abstract out hash computation
Move the hash computation located in __skb_get_hash to be a separate
function which takes flow_keys as input. This will allow flow hash
computation in other contexts where we only have addresses and ports.
Signed-off-by: Tom Herbert <therbert@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/flow_keys.h | 1 | ||||
-rw-r--r-- | net/core/flow_dissector.c | 44 |
2 files changed, 29 insertions, 16 deletions
diff --git a/include/net/flow_keys.h b/include/net/flow_keys.h index fbefdca5e283..6667a054763a 100644 --- a/include/net/flow_keys.h +++ b/include/net/flow_keys.h | |||
@@ -29,4 +29,5 @@ struct flow_keys { | |||
29 | 29 | ||
30 | bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow); | 30 | bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow); |
31 | __be32 skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto); | 31 | __be32 skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto); |
32 | u32 flow_hash_from_keys(struct flow_keys *keys); | ||
32 | #endif | 33 | #endif |
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index c2b53c1b21d2..2ff8cd4dfc5f 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c | |||
@@ -202,6 +202,33 @@ static __always_inline u32 __flow_hash_1word(u32 a) | |||
202 | return jhash_1word(a, hashrnd); | 202 | return jhash_1word(a, hashrnd); |
203 | } | 203 | } |
204 | 204 | ||
205 | static inline u32 __flow_hash_from_keys(struct flow_keys *keys) | ||
206 | { | ||
207 | u32 hash; | ||
208 | |||
209 | /* get a consistent hash (same value on both flow directions) */ | ||
210 | if (((__force u32)keys->dst < (__force u32)keys->src) || | ||
211 | (((__force u32)keys->dst == (__force u32)keys->src) && | ||
212 | ((__force u16)keys->port16[1] < (__force u16)keys->port16[0]))) { | ||
213 | swap(keys->dst, keys->src); | ||
214 | swap(keys->port16[0], keys->port16[1]); | ||
215 | } | ||
216 | |||
217 | hash = __flow_hash_3words((__force u32)keys->dst, | ||
218 | (__force u32)keys->src, | ||
219 | (__force u32)keys->ports); | ||
220 | if (!hash) | ||
221 | hash = 1; | ||
222 | |||
223 | return hash; | ||
224 | } | ||
225 | |||
226 | u32 flow_hash_from_keys(struct flow_keys *keys) | ||
227 | { | ||
228 | return __flow_hash_from_keys(keys); | ||
229 | } | ||
230 | EXPORT_SYMBOL(flow_hash_from_keys); | ||
231 | |||
205 | /* | 232 | /* |
206 | * __skb_get_hash: calculate a flow hash based on src/dst addresses | 233 | * __skb_get_hash: calculate a flow hash based on src/dst addresses |
207 | * and src/dst port numbers. Sets hash in skb to non-zero hash value | 234 | * and src/dst port numbers. Sets hash in skb to non-zero hash value |
@@ -211,7 +238,6 @@ static __always_inline u32 __flow_hash_1word(u32 a) | |||
211 | void __skb_get_hash(struct sk_buff *skb) | 238 | void __skb_get_hash(struct sk_buff *skb) |
212 | { | 239 | { |
213 | struct flow_keys keys; | 240 | struct flow_keys keys; |
214 | u32 hash; | ||
215 | 241 | ||
216 | if (!skb_flow_dissect(skb, &keys)) | 242 | if (!skb_flow_dissect(skb, &keys)) |
217 | return; | 243 | return; |
@@ -219,21 +245,7 @@ void __skb_get_hash(struct sk_buff *skb) | |||
219 | if (keys.ports) | 245 | if (keys.ports) |
220 | skb->l4_hash = 1; | 246 | skb->l4_hash = 1; |
221 | 247 | ||
222 | /* get a consistent hash (same value on both flow directions) */ | 248 | skb->hash = __flow_hash_from_keys(&keys); |
223 | if (((__force u32)keys.dst < (__force u32)keys.src) || | ||
224 | (((__force u32)keys.dst == (__force u32)keys.src) && | ||
225 | ((__force u16)keys.port16[1] < (__force u16)keys.port16[0]))) { | ||
226 | swap(keys.dst, keys.src); | ||
227 | swap(keys.port16[0], keys.port16[1]); | ||
228 | } | ||
229 | |||
230 | hash = __flow_hash_3words((__force u32)keys.dst, | ||
231 | (__force u32)keys.src, | ||
232 | (__force u32)keys.ports); | ||
233 | if (!hash) | ||
234 | hash = 1; | ||
235 | |||
236 | skb->hash = hash; | ||
237 | } | 249 | } |
238 | EXPORT_SYMBOL(__skb_get_hash); | 250 | EXPORT_SYMBOL(__skb_get_hash); |
239 | 251 | ||