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

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>

+29 -37
+1
include/linux/if_packet.h
··· 53 53 54 54 #define PACKET_FANOUT_HASH 0 55 55 #define PACKET_FANOUT_LB 1 56 + #define PACKET_FANOUT_CPU 2 56 57 #define PACKET_FANOUT_FLAG_DEFRAG 0x8000 57 58 58 59 struct tpacket_stats {
+28 -37
net/packet/af_packet.c
··· 447 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 457 static struct sk_buff *fanout_check_defrag(struct sk_buff *skb) 451 458 { 452 459 const struct iphdr *iph; ··· 489 482 return skb; 490 483 } 491 484 492 - static int packet_rcv_fanout_hash(struct sk_buff *skb, struct net_device *dev, 493 - struct packet_type *pt, struct net_device *orig_dev) 485 + static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev, 486 + struct packet_type *pt, struct net_device *orig_dev) 494 487 { 495 488 struct packet_fanout *f = pt->af_packet_priv; 496 489 unsigned int num = f->num_members; ··· 503 496 return 0; 504 497 } 505 498 506 - if (f->defrag) { 507 - skb = fanout_check_defrag(skb); 508 - if (!skb) 509 - return 0; 499 + switch (f->type) { 500 + case PACKET_FANOUT_HASH: 501 + default: 502 + if (f->defrag) { 503 + skb = fanout_check_defrag(skb); 504 + if (!skb) 505 + return 0; 506 + } 507 + skb_get_rxhash(skb); 508 + sk = fanout_demux_hash(f, skb, num); 509 + break; 510 + case PACKET_FANOUT_LB: 511 + sk = fanout_demux_lb(f, skb, num); 512 + break; 513 + case PACKET_FANOUT_CPU: 514 + sk = fanout_demux_cpu(f, skb, num); 515 + break; 510 516 } 511 517 512 - skb_get_rxhash(skb); 513 - 514 - sk = fanout_demux_hash(f, skb, num); 515 - po = pkt_sk(sk); 516 - 517 - return po->prot_hook.func(skb, dev, &po->prot_hook, orig_dev); 518 - } 519 - 520 - static int packet_rcv_fanout_lb(struct sk_buff *skb, struct net_device *dev, 521 - struct packet_type *pt, struct net_device *orig_dev) 522 - { 523 - struct packet_fanout *f = pt->af_packet_priv; 524 - unsigned int num = f->num_members; 525 - struct packet_sock *po; 526 - struct sock *sk; 527 - 528 - if (!net_eq(dev_net(dev), read_pnet(&f->net)) || 529 - !num) { 530 - kfree_skb(skb); 531 - return 0; 532 - } 533 - 534 - sk = fanout_demux_lb(f, skb, num); 535 518 po = pkt_sk(sk); 536 519 537 520 return po->prot_hook.func(skb, dev, &po->prot_hook, orig_dev); ··· 568 571 switch (type) { 569 572 case PACKET_FANOUT_HASH: 570 573 case PACKET_FANOUT_LB: 574 + case PACKET_FANOUT_CPU: 571 575 break; 572 576 default: 573 577 return -EINVAL; ··· 604 606 atomic_set(&match->sk_ref, 0); 605 607 match->prot_hook.type = po->prot_hook.type; 606 608 match->prot_hook.dev = po->prot_hook.dev; 607 - switch (type) { 608 - case PACKET_FANOUT_HASH: 609 - match->prot_hook.func = packet_rcv_fanout_hash; 610 - break; 611 - case PACKET_FANOUT_LB: 612 - match->prot_hook.func = packet_rcv_fanout_lb; 613 - break; 614 - } 609 + match->prot_hook.func = packet_rcv_fanout; 615 610 match->prot_hook.af_packet_priv = match; 616 611 dev_add_pack(&match->prot_hook); 617 612 list_add(&match->list, &fanout_list);