aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/flow_dissector.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/flow_dissector.c')
-rw-r--r--net/core/flow_dissector.c85
1 files changed, 49 insertions, 36 deletions
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 107ed12a5323..5f362c1d0332 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -80,6 +80,8 @@ ip:
80 case htons(ETH_P_IPV6): { 80 case htons(ETH_P_IPV6): {
81 const struct ipv6hdr *iph; 81 const struct ipv6hdr *iph;
82 struct ipv6hdr _iph; 82 struct ipv6hdr _iph;
83 __be32 flow_label;
84
83ipv6: 85ipv6:
84 iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); 86 iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
85 if (!iph) 87 if (!iph)
@@ -89,6 +91,21 @@ ipv6:
89 flow->src = (__force __be32)ipv6_addr_hash(&iph->saddr); 91 flow->src = (__force __be32)ipv6_addr_hash(&iph->saddr);
90 flow->dst = (__force __be32)ipv6_addr_hash(&iph->daddr); 92 flow->dst = (__force __be32)ipv6_addr_hash(&iph->daddr);
91 nhoff += sizeof(struct ipv6hdr); 93 nhoff += sizeof(struct ipv6hdr);
94
95 flow_label = ip6_flowlabel(iph);
96 if (flow_label) {
97 /* Awesome, IPv6 packet has a flow label so we can
98 * use that to represent the ports without any
99 * further dissection.
100 */
101 flow->n_proto = proto;
102 flow->ip_proto = ip_proto;
103 flow->ports = flow_label;
104 flow->thoff = (u16)nhoff;
105
106 return true;
107 }
108
92 break; 109 break;
93 } 110 }
94 case htons(ETH_P_8021AD): 111 case htons(ETH_P_8021AD):
@@ -175,6 +192,7 @@ ipv6:
175 break; 192 break;
176 } 193 }
177 194
195 flow->n_proto = proto;
178 flow->ip_proto = ip_proto; 196 flow->ip_proto = ip_proto;
179 flow->ports = skb_flow_get_ports(skb, nhoff, ip_proto); 197 flow->ports = skb_flow_get_ports(skb, nhoff, ip_proto);
180 flow->thoff = (u16) nhoff; 198 flow->thoff = (u16) nhoff;
@@ -195,12 +213,33 @@ static __always_inline u32 __flow_hash_3words(u32 a, u32 b, u32 c)
195 return jhash_3words(a, b, c, hashrnd); 213 return jhash_3words(a, b, c, hashrnd);
196} 214}
197 215
198static __always_inline u32 __flow_hash_1word(u32 a) 216static inline u32 __flow_hash_from_keys(struct flow_keys *keys)
199{ 217{
200 __flow_hash_secret_init(); 218 u32 hash;
201 return jhash_1word(a, hashrnd); 219
220 /* get a consistent hash (same value on both flow directions) */
221 if (((__force u32)keys->dst < (__force u32)keys->src) ||
222 (((__force u32)keys->dst == (__force u32)keys->src) &&
223 ((__force u16)keys->port16[1] < (__force u16)keys->port16[0]))) {
224 swap(keys->dst, keys->src);
225 swap(keys->port16[0], keys->port16[1]);
226 }
227
228 hash = __flow_hash_3words((__force u32)keys->dst,
229 (__force u32)keys->src,
230 (__force u32)keys->ports);
231 if (!hash)
232 hash = 1;
233
234 return hash;
202} 235}
203 236
237u32 flow_hash_from_keys(struct flow_keys *keys)
238{
239 return __flow_hash_from_keys(keys);
240}
241EXPORT_SYMBOL(flow_hash_from_keys);
242
204/* 243/*
205 * __skb_get_hash: calculate a flow hash based on src/dst addresses 244 * __skb_get_hash: calculate a flow hash based on src/dst addresses
206 * and src/dst port numbers. Sets hash in skb to non-zero hash value 245 * and src/dst port numbers. Sets hash in skb to non-zero hash value
@@ -210,7 +249,6 @@ static __always_inline u32 __flow_hash_1word(u32 a)
210void __skb_get_hash(struct sk_buff *skb) 249void __skb_get_hash(struct sk_buff *skb)
211{ 250{
212 struct flow_keys keys; 251 struct flow_keys keys;
213 u32 hash;
214 252
215 if (!skb_flow_dissect(skb, &keys)) 253 if (!skb_flow_dissect(skb, &keys))
216 return; 254 return;
@@ -218,21 +256,9 @@ void __skb_get_hash(struct sk_buff *skb)
218 if (keys.ports) 256 if (keys.ports)
219 skb->l4_hash = 1; 257 skb->l4_hash = 1;
220 258
221 /* get a consistent hash (same value on both flow directions) */ 259 skb->sw_hash = 1;
222 if (((__force u32)keys.dst < (__force u32)keys.src) ||
223 (((__force u32)keys.dst == (__force u32)keys.src) &&
224 ((__force u16)keys.port16[1] < (__force u16)keys.port16[0]))) {
225 swap(keys.dst, keys.src);
226 swap(keys.port16[0], keys.port16[1]);
227 }
228
229 hash = __flow_hash_3words((__force u32)keys.dst,
230 (__force u32)keys.src,
231 (__force u32)keys.ports);
232 if (!hash)
233 hash = 1;
234 260
235 skb->hash = hash; 261 skb->hash = __flow_hash_from_keys(&keys);
236} 262}
237EXPORT_SYMBOL(__skb_get_hash); 263EXPORT_SYMBOL(__skb_get_hash);
238 264
@@ -240,7 +266,7 @@ EXPORT_SYMBOL(__skb_get_hash);
240 * Returns a Tx hash based on the given packet descriptor a Tx queues' number 266 * Returns a Tx hash based on the given packet descriptor a Tx queues' number
241 * to be used as a distribution range. 267 * to be used as a distribution range.
242 */ 268 */
243u16 __skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb, 269u16 __skb_tx_hash(const struct net_device *dev, struct sk_buff *skb,
244 unsigned int num_tx_queues) 270 unsigned int num_tx_queues)
245{ 271{
246 u32 hash; 272 u32 hash;
@@ -260,13 +286,7 @@ u16 __skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb,
260 qcount = dev->tc_to_txq[tc].count; 286 qcount = dev->tc_to_txq[tc].count;
261 } 287 }
262 288
263 if (skb->sk && skb->sk->sk_hash) 289 return (u16) (((u64)skb_get_hash(skb) * qcount) >> 32) + qoffset;
264 hash = skb->sk->sk_hash;
265 else
266 hash = (__force u16) skb->protocol;
267 hash = __flow_hash_1word(hash);
268
269 return (u16) (((u64) hash * qcount) >> 32) + qoffset;
270} 290}
271EXPORT_SYMBOL(__skb_tx_hash); 291EXPORT_SYMBOL(__skb_tx_hash);
272 292
@@ -338,17 +358,10 @@ static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
338 if (map) { 358 if (map) {
339 if (map->len == 1) 359 if (map->len == 1)
340 queue_index = map->queues[0]; 360 queue_index = map->queues[0];
341 else { 361 else
342 u32 hash;
343 if (skb->sk && skb->sk->sk_hash)
344 hash = skb->sk->sk_hash;
345 else
346 hash = (__force u16) skb->protocol ^
347 skb->hash;
348 hash = __flow_hash_1word(hash);
349 queue_index = map->queues[ 362 queue_index = map->queues[
350 ((u64)hash * map->len) >> 32]; 363 ((u64)skb_get_hash(skb) * map->len) >> 32];
351 } 364
352 if (unlikely(queue_index >= dev->real_num_tx_queues)) 365 if (unlikely(queue_index >= dev->real_num_tx_queues))
353 queue_index = -1; 366 queue_index = -1;
354 } 367 }