diff options
author | Jiri Pirko <jpirko@redhat.com> | 2010-06-01 17:52:08 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-02 10:11:15 -0400 |
commit | ab95bfe01f9872459c8678572ccadbf646badad0 (patch) | |
tree | 8e11f94077c9a80f7af52ce3dd50591a686561d7 /drivers | |
parent | 20c59de2e6b6bc74bbf714dcd4e720afe8d516cf (diff) |
net: replace hooks in __netif_receive_skb V5
What this patch does is it removes two receive frame hooks (for bridge and for
macvlan) from __netif_receive_skb. These are replaced them with a single
hook for both. It only supports one hook per device because it makes no
sense to do bridging and macvlan on the same device.
Then a network driver (of virtual netdev like macvlan or bridge) can register
an rx_handler for needed net device.
Signed-off-by: Jiri Pirko <jpirko@redhat.com>
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/macvlan.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 87e8d4cb4057..53422ce26f7f 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c | |||
@@ -145,15 +145,16 @@ static void macvlan_broadcast(struct sk_buff *skb, | |||
145 | } | 145 | } |
146 | 146 | ||
147 | /* called under rcu_read_lock() from netif_receive_skb */ | 147 | /* called under rcu_read_lock() from netif_receive_skb */ |
148 | static struct sk_buff *macvlan_handle_frame(struct macvlan_port *port, | 148 | static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb) |
149 | struct sk_buff *skb) | ||
150 | { | 149 | { |
150 | struct macvlan_port *port; | ||
151 | const struct ethhdr *eth = eth_hdr(skb); | 151 | const struct ethhdr *eth = eth_hdr(skb); |
152 | const struct macvlan_dev *vlan; | 152 | const struct macvlan_dev *vlan; |
153 | const struct macvlan_dev *src; | 153 | const struct macvlan_dev *src; |
154 | struct net_device *dev; | 154 | struct net_device *dev; |
155 | unsigned int len; | 155 | unsigned int len; |
156 | 156 | ||
157 | port = rcu_dereference(skb->dev->macvlan_port); | ||
157 | if (is_multicast_ether_addr(eth->h_dest)) { | 158 | if (is_multicast_ether_addr(eth->h_dest)) { |
158 | src = macvlan_hash_lookup(port, eth->h_source); | 159 | src = macvlan_hash_lookup(port, eth->h_source); |
159 | if (!src) | 160 | if (!src) |
@@ -515,6 +516,7 @@ static int macvlan_port_create(struct net_device *dev) | |||
515 | { | 516 | { |
516 | struct macvlan_port *port; | 517 | struct macvlan_port *port; |
517 | unsigned int i; | 518 | unsigned int i; |
519 | int err; | ||
518 | 520 | ||
519 | if (dev->type != ARPHRD_ETHER || dev->flags & IFF_LOOPBACK) | 521 | if (dev->type != ARPHRD_ETHER || dev->flags & IFF_LOOPBACK) |
520 | return -EINVAL; | 522 | return -EINVAL; |
@@ -528,13 +530,21 @@ static int macvlan_port_create(struct net_device *dev) | |||
528 | for (i = 0; i < MACVLAN_HASH_SIZE; i++) | 530 | for (i = 0; i < MACVLAN_HASH_SIZE; i++) |
529 | INIT_HLIST_HEAD(&port->vlan_hash[i]); | 531 | INIT_HLIST_HEAD(&port->vlan_hash[i]); |
530 | rcu_assign_pointer(dev->macvlan_port, port); | 532 | rcu_assign_pointer(dev->macvlan_port, port); |
531 | return 0; | 533 | |
534 | err = netdev_rx_handler_register(dev, macvlan_handle_frame); | ||
535 | if (err) { | ||
536 | rcu_assign_pointer(dev->macvlan_port, NULL); | ||
537 | kfree(port); | ||
538 | } | ||
539 | |||
540 | return err; | ||
532 | } | 541 | } |
533 | 542 | ||
534 | static void macvlan_port_destroy(struct net_device *dev) | 543 | static void macvlan_port_destroy(struct net_device *dev) |
535 | { | 544 | { |
536 | struct macvlan_port *port = dev->macvlan_port; | 545 | struct macvlan_port *port = dev->macvlan_port; |
537 | 546 | ||
547 | netdev_rx_handler_unregister(dev); | ||
538 | rcu_assign_pointer(dev->macvlan_port, NULL); | 548 | rcu_assign_pointer(dev->macvlan_port, NULL); |
539 | synchronize_rcu(); | 549 | synchronize_rcu(); |
540 | kfree(port); | 550 | kfree(port); |
@@ -767,14 +777,12 @@ static int __init macvlan_init_module(void) | |||
767 | int err; | 777 | int err; |
768 | 778 | ||
769 | register_netdevice_notifier(&macvlan_notifier_block); | 779 | register_netdevice_notifier(&macvlan_notifier_block); |
770 | macvlan_handle_frame_hook = macvlan_handle_frame; | ||
771 | 780 | ||
772 | err = macvlan_link_register(&macvlan_link_ops); | 781 | err = macvlan_link_register(&macvlan_link_ops); |
773 | if (err < 0) | 782 | if (err < 0) |
774 | goto err1; | 783 | goto err1; |
775 | return 0; | 784 | return 0; |
776 | err1: | 785 | err1: |
777 | macvlan_handle_frame_hook = NULL; | ||
778 | unregister_netdevice_notifier(&macvlan_notifier_block); | 786 | unregister_netdevice_notifier(&macvlan_notifier_block); |
779 | return err; | 787 | return err; |
780 | } | 788 | } |
@@ -782,7 +790,6 @@ err1: | |||
782 | static void __exit macvlan_cleanup_module(void) | 790 | static void __exit macvlan_cleanup_module(void) |
783 | { | 791 | { |
784 | rtnl_link_unregister(&macvlan_link_ops); | 792 | rtnl_link_unregister(&macvlan_link_ops); |
785 | macvlan_handle_frame_hook = NULL; | ||
786 | unregister_netdevice_notifier(&macvlan_notifier_block); | 793 | unregister_netdevice_notifier(&macvlan_notifier_block); |
787 | } | 794 | } |
788 | 795 | ||