Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Tom Herbert and committed by
David S. Miller
5ed20a68 081a20ff

+29 -16
+1
include/net/flow_keys.h
··· 29 29 30 30 bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow); 31 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 33 #endif
+28 -16
net/core/flow_dissector.c
··· 202 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 233 * __skb_get_hash: calculate a flow hash based on src/dst addresses 207 234 * and src/dst port numbers. Sets hash in skb to non-zero hash value ··· 238 211 void __skb_get_hash(struct sk_buff *skb) 239 212 { 240 213 struct flow_keys keys; 241 - u32 hash; 242 214 243 215 if (!skb_flow_dissect(skb, &keys)) 244 216 return; ··· 245 219 if (keys.ports) 246 220 skb->l4_hash = 1; 247 221 248 - /* get a consistent hash (same value on both flow directions) */ 249 - if (((__force u32)keys.dst < (__force u32)keys.src) || 250 - (((__force u32)keys.dst == (__force u32)keys.src) && 251 - ((__force u16)keys.port16[1] < (__force u16)keys.port16[0]))) { 252 - swap(keys.dst, keys.src); 253 - swap(keys.port16[0], keys.port16[1]); 254 - } 255 - 256 - hash = __flow_hash_3words((__force u32)keys.dst, 257 - (__force u32)keys.src, 258 - (__force u32)keys.ports); 259 - if (!hash) 260 - hash = 1; 261 - 262 - skb->hash = hash; 222 + skb->hash = __flow_hash_from_keys(&keys); 263 223 } 264 224 EXPORT_SYMBOL(__skb_get_hash); 265 225