diff options
author | David S. Miller <davem@davemloft.net> | 2011-07-06 04:56:38 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-07-06 04:56:38 -0400 |
commit | 95ec3eb417115fbb2c73b59e2825f6dd5d2f6cf6 (patch) | |
tree | 009ed6c7ee4d693de36990fa30fdaa79939905f0 /net/packet | |
parent | 81b16ba2f1cc93a1ee1dda48be2ea2d91a0cb72e (diff) |
packet: Add 'cpu' fanout policy.
Unfortunately we have to use a real modulus here as
the multiply trick won't work as effectively with cpu
numbers as it does with rxhash values.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/packet')
-rw-r--r-- | net/packet/af_packet.c | 65 |
1 files changed, 28 insertions, 37 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 7ba6871a1942..41f0489ff665 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -447,6 +447,13 @@ static struct sock *fanout_demux_lb(struct packet_fanout *f, struct sk_buff *skb | |||
447 | return f->arr[cur]; | 447 | return f->arr[cur]; |
448 | } | 448 | } |
449 | 449 | ||
450 | static struct sock *fanout_demux_cpu(struct packet_fanout *f, struct sk_buff *skb, unsigned int num) | ||
451 | { | ||
452 | unsigned int cpu = smp_processor_id(); | ||
453 | |||
454 | return f->arr[cpu % num]; | ||
455 | } | ||
456 | |||
450 | static struct sk_buff *fanout_check_defrag(struct sk_buff *skb) | 457 | static struct sk_buff *fanout_check_defrag(struct sk_buff *skb) |
451 | { | 458 | { |
452 | const struct iphdr *iph; | 459 | const struct iphdr *iph; |
@@ -482,8 +489,8 @@ static struct sk_buff *fanout_check_defrag(struct sk_buff *skb) | |||
482 | return skb; | 489 | return skb; |
483 | } | 490 | } |
484 | 491 | ||
485 | static int packet_rcv_fanout_hash(struct sk_buff *skb, struct net_device *dev, | 492 | static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev, |
486 | struct packet_type *pt, struct net_device *orig_dev) | 493 | struct packet_type *pt, struct net_device *orig_dev) |
487 | { | 494 | { |
488 | struct packet_fanout *f = pt->af_packet_priv; | 495 | struct packet_fanout *f = pt->af_packet_priv; |
489 | unsigned int num = f->num_members; | 496 | unsigned int num = f->num_members; |
@@ -496,35 +503,25 @@ static int packet_rcv_fanout_hash(struct sk_buff *skb, struct net_device *dev, | |||
496 | return 0; | 503 | return 0; |
497 | } | 504 | } |
498 | 505 | ||
499 | if (f->defrag) { | 506 | switch (f->type) { |
500 | skb = fanout_check_defrag(skb); | 507 | case PACKET_FANOUT_HASH: |
501 | if (!skb) | 508 | default: |
502 | return 0; | 509 | if (f->defrag) { |
503 | } | 510 | skb = fanout_check_defrag(skb); |
504 | 511 | if (!skb) | |
505 | skb_get_rxhash(skb); | 512 | return 0; |
506 | 513 | } | |
507 | sk = fanout_demux_hash(f, skb, num); | 514 | skb_get_rxhash(skb); |
508 | po = pkt_sk(sk); | 515 | sk = fanout_demux_hash(f, skb, num); |
509 | 516 | break; | |
510 | return po->prot_hook.func(skb, dev, &po->prot_hook, orig_dev); | 517 | case PACKET_FANOUT_LB: |
511 | } | 518 | sk = fanout_demux_lb(f, skb, num); |
512 | 519 | break; | |
513 | static int packet_rcv_fanout_lb(struct sk_buff *skb, struct net_device *dev, | 520 | case PACKET_FANOUT_CPU: |
514 | struct packet_type *pt, struct net_device *orig_dev) | 521 | sk = fanout_demux_cpu(f, skb, num); |
515 | { | 522 | break; |
516 | struct packet_fanout *f = pt->af_packet_priv; | ||
517 | unsigned int num = f->num_members; | ||
518 | struct packet_sock *po; | ||
519 | struct sock *sk; | ||
520 | |||
521 | if (!net_eq(dev_net(dev), read_pnet(&f->net)) || | ||
522 | !num) { | ||
523 | kfree_skb(skb); | ||
524 | return 0; | ||
525 | } | 523 | } |
526 | 524 | ||
527 | sk = fanout_demux_lb(f, skb, num); | ||
528 | po = pkt_sk(sk); | 525 | po = pkt_sk(sk); |
529 | 526 | ||
530 | return po->prot_hook.func(skb, dev, &po->prot_hook, orig_dev); | 527 | return po->prot_hook.func(skb, dev, &po->prot_hook, orig_dev); |
@@ -571,6 +568,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) | |||
571 | switch (type) { | 568 | switch (type) { |
572 | case PACKET_FANOUT_HASH: | 569 | case PACKET_FANOUT_HASH: |
573 | case PACKET_FANOUT_LB: | 570 | case PACKET_FANOUT_LB: |
571 | case PACKET_FANOUT_CPU: | ||
574 | break; | 572 | break; |
575 | default: | 573 | default: |
576 | return -EINVAL; | 574 | return -EINVAL; |
@@ -606,14 +604,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) | |||
606 | atomic_set(&match->sk_ref, 0); | 604 | atomic_set(&match->sk_ref, 0); |
607 | match->prot_hook.type = po->prot_hook.type; | 605 | match->prot_hook.type = po->prot_hook.type; |
608 | match->prot_hook.dev = po->prot_hook.dev; | 606 | match->prot_hook.dev = po->prot_hook.dev; |
609 | switch (type) { | 607 | match->prot_hook.func = packet_rcv_fanout; |
610 | case PACKET_FANOUT_HASH: | ||
611 | match->prot_hook.func = packet_rcv_fanout_hash; | ||
612 | break; | ||
613 | case PACKET_FANOUT_LB: | ||
614 | match->prot_hook.func = packet_rcv_fanout_lb; | ||
615 | break; | ||
616 | } | ||
617 | match->prot_hook.af_packet_priv = match; | 608 | match->prot_hook.af_packet_priv = match; |
618 | dev_add_pack(&match->prot_hook); | 609 | dev_add_pack(&match->prot_hook); |
619 | list_add(&match->list, &fanout_list); | 610 | list_add(&match->list, &fanout_list); |