diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2011-11-28 00:25:02 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-11-28 19:09:28 -0500 |
commit | a00bd469b6604aa5f165dcc4d07dc07499439a6b (patch) | |
tree | 0b77d5fc46189223b18d5519586d6d1294ad8b96 /net/sched/sch_sfb.c | |
parent | 6bd2a9af17cc3b153de45390b54c7d64a773beee (diff) |
sch_sfb: use skb_flow_dissect()
Current SFB double hashing is not fulfilling SFB theory, if two flows
share same rxhash value.
Using skb_flow_dissect() permits to really have better hash dispersion,
and get tunnelling support as well.
Double hashing point was mentioned by Florian Westphal
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/sch_sfb.c')
-rw-r--r-- | net/sched/sch_sfb.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c index e83c272c0325..96e42cae4c7a 100644 --- a/net/sched/sch_sfb.c +++ b/net/sched/sch_sfb.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <net/ip.h> | 26 | #include <net/ip.h> |
27 | #include <net/pkt_sched.h> | 27 | #include <net/pkt_sched.h> |
28 | #include <net/inet_ecn.h> | 28 | #include <net/inet_ecn.h> |
29 | #include <net/flow_keys.h> | ||
29 | 30 | ||
30 | /* | 31 | /* |
31 | * SFB uses two B[l][n] : L x N arrays of bins (L levels, N bins per level) | 32 | * SFB uses two B[l][n] : L x N arrays of bins (L levels, N bins per level) |
@@ -286,6 +287,7 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
286 | u32 minqlen = ~0; | 287 | u32 minqlen = ~0; |
287 | u32 r, slot, salt, sfbhash; | 288 | u32 r, slot, salt, sfbhash; |
288 | int ret = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; | 289 | int ret = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; |
290 | struct flow_keys keys; | ||
289 | 291 | ||
290 | if (unlikely(sch->q.qlen >= q->limit)) { | 292 | if (unlikely(sch->q.qlen >= q->limit)) { |
291 | sch->qstats.overlimits++; | 293 | sch->qstats.overlimits++; |
@@ -309,13 +311,19 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
309 | /* If using external classifiers, get result and record it. */ | 311 | /* If using external classifiers, get result and record it. */ |
310 | if (!sfb_classify(skb, q, &ret, &salt)) | 312 | if (!sfb_classify(skb, q, &ret, &salt)) |
311 | goto other_drop; | 313 | goto other_drop; |
314 | keys.src = salt; | ||
315 | keys.dst = 0; | ||
316 | keys.ports = 0; | ||
312 | } else { | 317 | } else { |
313 | salt = skb_get_rxhash(skb); | 318 | skb_flow_dissect(skb, &keys); |
314 | } | 319 | } |
315 | 320 | ||
316 | slot = q->slot; | 321 | slot = q->slot; |
317 | 322 | ||
318 | sfbhash = jhash_1word(salt, q->bins[slot].perturbation); | 323 | sfbhash = jhash_3words((__force u32)keys.dst, |
324 | (__force u32)keys.src, | ||
325 | (__force u32)keys.ports, | ||
326 | q->bins[slot].perturbation); | ||
319 | if (!sfbhash) | 327 | if (!sfbhash) |
320 | sfbhash = 1; | 328 | sfbhash = 1; |
321 | sfb_skb_cb(skb)->hashes[slot] = sfbhash; | 329 | sfb_skb_cb(skb)->hashes[slot] = sfbhash; |
@@ -347,7 +355,10 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
347 | if (unlikely(p_min >= SFB_MAX_PROB)) { | 355 | if (unlikely(p_min >= SFB_MAX_PROB)) { |
348 | /* Inelastic flow */ | 356 | /* Inelastic flow */ |
349 | if (q->double_buffering) { | 357 | if (q->double_buffering) { |
350 | sfbhash = jhash_1word(salt, q->bins[slot].perturbation); | 358 | sfbhash = jhash_3words((__force u32)keys.dst, |
359 | (__force u32)keys.src, | ||
360 | (__force u32)keys.ports, | ||
361 | q->bins[slot].perturbation); | ||
351 | if (!sfbhash) | 362 | if (!sfbhash) |
352 | sfbhash = 1; | 363 | sfbhash = 1; |
353 | sfb_skb_cb(skb)->hashes[slot] = sfbhash; | 364 | sfb_skb_cb(skb)->hashes[slot] = sfbhash; |