diff options
author | Jiri Pirko <jpirko@redhat.com> | 2010-06-14 23:27:57 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-15 14:47:12 -0400 |
commit | a35e2c1b6d90544b3c688783869817628e5f9607 (patch) | |
tree | 64fa6bc6b772248acfb92b5743c5f0d475126891 /drivers/net/macvlan.c | |
parent | 93e2c32b5cb2ad92ceb1d7a4684f20a0d25bf530 (diff) |
macvlan: use rx_handler_data pointer to store macvlan_port pointer V2
Register macvlan_port pointer as rx_handler data pointer. As macvlan_port is
removed from struct net_device, another netdev priv_flag is added to indicate
the device serves as a macvlan port.
Signed-off-by: Jiri Pirko <jpirko@redhat.com>
Acked-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/macvlan.c')
-rw-r--r-- | drivers/net/macvlan.c | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 87a3bf69c4a3..e096875aa055 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c | |||
@@ -40,6 +40,11 @@ struct macvlan_port { | |||
40 | struct rcu_head rcu; | 40 | struct rcu_head rcu; |
41 | }; | 41 | }; |
42 | 42 | ||
43 | #define macvlan_port_get_rcu(dev) \ | ||
44 | ((struct macvlan_port *) rcu_dereference(dev->rx_handler_data)) | ||
45 | #define macvlan_port_get(dev) ((struct macvlan_port *) dev->rx_handler_data) | ||
46 | #define macvlan_port_exists(dev) (dev->priv_flags & IFF_MACVLAN_PORT) | ||
47 | |||
43 | static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port, | 48 | static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port, |
44 | const unsigned char *addr) | 49 | const unsigned char *addr) |
45 | { | 50 | { |
@@ -155,7 +160,7 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb) | |||
155 | struct net_device *dev; | 160 | struct net_device *dev; |
156 | unsigned int len; | 161 | unsigned int len; |
157 | 162 | ||
158 | port = rcu_dereference(skb->dev->macvlan_port); | 163 | port = macvlan_port_get_rcu(skb->dev); |
159 | if (is_multicast_ether_addr(eth->h_dest)) { | 164 | if (is_multicast_ether_addr(eth->h_dest)) { |
160 | src = macvlan_hash_lookup(port, eth->h_source); | 165 | src = macvlan_hash_lookup(port, eth->h_source); |
161 | if (!src) | 166 | if (!src) |
@@ -530,14 +535,12 @@ static int macvlan_port_create(struct net_device *dev) | |||
530 | INIT_LIST_HEAD(&port->vlans); | 535 | INIT_LIST_HEAD(&port->vlans); |
531 | for (i = 0; i < MACVLAN_HASH_SIZE; i++) | 536 | for (i = 0; i < MACVLAN_HASH_SIZE; i++) |
532 | INIT_HLIST_HEAD(&port->vlan_hash[i]); | 537 | INIT_HLIST_HEAD(&port->vlan_hash[i]); |
533 | rcu_assign_pointer(dev->macvlan_port, port); | ||
534 | 538 | ||
535 | err = netdev_rx_handler_register(dev, macvlan_handle_frame, NULL); | 539 | err = netdev_rx_handler_register(dev, macvlan_handle_frame, port); |
536 | if (err) { | 540 | if (err) |
537 | rcu_assign_pointer(dev->macvlan_port, NULL); | ||
538 | kfree(port); | 541 | kfree(port); |
539 | } | ||
540 | 542 | ||
543 | dev->priv_flags |= IFF_MACVLAN_PORT; | ||
541 | return err; | 544 | return err; |
542 | } | 545 | } |
543 | 546 | ||
@@ -551,10 +554,10 @@ static void macvlan_port_rcu_free(struct rcu_head *head) | |||
551 | 554 | ||
552 | static void macvlan_port_destroy(struct net_device *dev) | 555 | static void macvlan_port_destroy(struct net_device *dev) |
553 | { | 556 | { |
554 | struct macvlan_port *port = dev->macvlan_port; | 557 | struct macvlan_port *port = macvlan_port_get(dev); |
555 | 558 | ||
559 | dev->priv_flags &= ~IFF_MACVLAN_PORT; | ||
556 | netdev_rx_handler_unregister(dev); | 560 | netdev_rx_handler_unregister(dev); |
557 | rcu_assign_pointer(dev->macvlan_port, NULL); | ||
558 | call_rcu(&port->rcu, macvlan_port_rcu_free); | 561 | call_rcu(&port->rcu, macvlan_port_rcu_free); |
559 | } | 562 | } |
560 | 563 | ||
@@ -633,12 +636,12 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, | |||
633 | if (!tb[IFLA_ADDRESS]) | 636 | if (!tb[IFLA_ADDRESS]) |
634 | random_ether_addr(dev->dev_addr); | 637 | random_ether_addr(dev->dev_addr); |
635 | 638 | ||
636 | if (lowerdev->macvlan_port == NULL) { | 639 | if (!macvlan_port_exists(lowerdev)) { |
637 | err = macvlan_port_create(lowerdev); | 640 | err = macvlan_port_create(lowerdev); |
638 | if (err < 0) | 641 | if (err < 0) |
639 | return err; | 642 | return err; |
640 | } | 643 | } |
641 | port = lowerdev->macvlan_port; | 644 | port = macvlan_port_get(lowerdev); |
642 | 645 | ||
643 | vlan->lowerdev = lowerdev; | 646 | vlan->lowerdev = lowerdev; |
644 | vlan->dev = dev; | 647 | vlan->dev = dev; |
@@ -748,10 +751,11 @@ static int macvlan_device_event(struct notifier_block *unused, | |||
748 | struct macvlan_dev *vlan, *next; | 751 | struct macvlan_dev *vlan, *next; |
749 | struct macvlan_port *port; | 752 | struct macvlan_port *port; |
750 | 753 | ||
751 | port = dev->macvlan_port; | 754 | if (!macvlan_port_exists(dev)) |
752 | if (port == NULL) | ||
753 | return NOTIFY_DONE; | 755 | return NOTIFY_DONE; |
754 | 756 | ||
757 | port = macvlan_port_get(dev); | ||
758 | |||
755 | switch (event) { | 759 | switch (event) { |
756 | case NETDEV_CHANGE: | 760 | case NETDEV_CHANGE: |
757 | list_for_each_entry(vlan, &port->vlans, list) | 761 | list_for_each_entry(vlan, &port->vlans, list) |