diff options
Diffstat (limited to 'drivers/net/ipvlan/ipvlan_main.c')
-rw-r--r-- | drivers/net/ipvlan/ipvlan_main.c | 42 |
1 files changed, 19 insertions, 23 deletions
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index 1acc283160d9..20b58bdecf75 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c | |||
@@ -153,10 +153,9 @@ static int ipvlan_open(struct net_device *dev) | |||
153 | else | 153 | else |
154 | dev->flags &= ~IFF_NOARP; | 154 | dev->flags &= ~IFF_NOARP; |
155 | 155 | ||
156 | if (ipvlan->ipv6cnt > 0 || ipvlan->ipv4cnt > 0) { | 156 | list_for_each_entry(addr, &ipvlan->addrs, anode) |
157 | list_for_each_entry(addr, &ipvlan->addrs, anode) | 157 | ipvlan_ht_addr_add(ipvlan, addr); |
158 | ipvlan_ht_addr_add(ipvlan, addr); | 158 | |
159 | } | ||
160 | return dev_uc_add(phy_dev, phy_dev->dev_addr); | 159 | return dev_uc_add(phy_dev, phy_dev->dev_addr); |
161 | } | 160 | } |
162 | 161 | ||
@@ -171,10 +170,9 @@ static int ipvlan_stop(struct net_device *dev) | |||
171 | 170 | ||
172 | dev_uc_del(phy_dev, phy_dev->dev_addr); | 171 | dev_uc_del(phy_dev, phy_dev->dev_addr); |
173 | 172 | ||
174 | if (ipvlan->ipv6cnt > 0 || ipvlan->ipv4cnt > 0) { | 173 | list_for_each_entry(addr, &ipvlan->addrs, anode) |
175 | list_for_each_entry(addr, &ipvlan->addrs, anode) | 174 | ipvlan_ht_addr_del(addr); |
176 | ipvlan_ht_addr_del(addr, !dev->dismantle); | 175 | |
177 | } | ||
178 | return 0; | 176 | return 0; |
179 | } | 177 | } |
180 | 178 | ||
@@ -471,8 +469,6 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev, | |||
471 | ipvlan->port = port; | 469 | ipvlan->port = port; |
472 | ipvlan->sfeatures = IPVLAN_FEATURES; | 470 | ipvlan->sfeatures = IPVLAN_FEATURES; |
473 | INIT_LIST_HEAD(&ipvlan->addrs); | 471 | INIT_LIST_HEAD(&ipvlan->addrs); |
474 | ipvlan->ipv4cnt = 0; | ||
475 | ipvlan->ipv6cnt = 0; | ||
476 | 472 | ||
477 | /* TODO Probably put random address here to be presented to the | 473 | /* TODO Probably put random address here to be presented to the |
478 | * world but keep using the physical-dev address for the outgoing | 474 | * world but keep using the physical-dev address for the outgoing |
@@ -508,12 +504,12 @@ static void ipvlan_link_delete(struct net_device *dev, struct list_head *head) | |||
508 | struct ipvl_dev *ipvlan = netdev_priv(dev); | 504 | struct ipvl_dev *ipvlan = netdev_priv(dev); |
509 | struct ipvl_addr *addr, *next; | 505 | struct ipvl_addr *addr, *next; |
510 | 506 | ||
511 | if (ipvlan->ipv6cnt > 0 || ipvlan->ipv4cnt > 0) { | 507 | list_for_each_entry_safe(addr, next, &ipvlan->addrs, anode) { |
512 | list_for_each_entry_safe(addr, next, &ipvlan->addrs, anode) { | 508 | ipvlan_ht_addr_del(addr); |
513 | ipvlan_ht_addr_del(addr, !dev->dismantle); | 509 | list_del(&addr->anode); |
514 | list_del(&addr->anode); | 510 | kfree_rcu(addr, rcu); |
515 | } | ||
516 | } | 511 | } |
512 | |||
517 | list_del_rcu(&ipvlan->pnode); | 513 | list_del_rcu(&ipvlan->pnode); |
518 | unregister_netdevice_queue(dev, head); | 514 | unregister_netdevice_queue(dev, head); |
519 | netdev_upper_dev_unlink(ipvlan->phy_dev, dev); | 515 | netdev_upper_dev_unlink(ipvlan->phy_dev, dev); |
@@ -627,7 +623,7 @@ static int ipvlan_add_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr) | |||
627 | memcpy(&addr->ip6addr, ip6_addr, sizeof(struct in6_addr)); | 623 | memcpy(&addr->ip6addr, ip6_addr, sizeof(struct in6_addr)); |
628 | addr->atype = IPVL_IPV6; | 624 | addr->atype = IPVL_IPV6; |
629 | list_add_tail(&addr->anode, &ipvlan->addrs); | 625 | list_add_tail(&addr->anode, &ipvlan->addrs); |
630 | ipvlan->ipv6cnt++; | 626 | |
631 | /* If the interface is not up, the address will be added to the hash | 627 | /* If the interface is not up, the address will be added to the hash |
632 | * list by ipvlan_open. | 628 | * list by ipvlan_open. |
633 | */ | 629 | */ |
@@ -645,10 +641,8 @@ static void ipvlan_del_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr) | |||
645 | if (!addr) | 641 | if (!addr) |
646 | return; | 642 | return; |
647 | 643 | ||
648 | ipvlan_ht_addr_del(addr, true); | 644 | ipvlan_ht_addr_del(addr); |
649 | list_del(&addr->anode); | 645 | list_del(&addr->anode); |
650 | ipvlan->ipv6cnt--; | ||
651 | WARN_ON(ipvlan->ipv6cnt < 0); | ||
652 | kfree_rcu(addr, rcu); | 646 | kfree_rcu(addr, rcu); |
653 | 647 | ||
654 | return; | 648 | return; |
@@ -661,6 +655,10 @@ static int ipvlan_addr6_event(struct notifier_block *unused, | |||
661 | struct net_device *dev = (struct net_device *)if6->idev->dev; | 655 | struct net_device *dev = (struct net_device *)if6->idev->dev; |
662 | struct ipvl_dev *ipvlan = netdev_priv(dev); | 656 | struct ipvl_dev *ipvlan = netdev_priv(dev); |
663 | 657 | ||
658 | /* FIXME IPv6 autoconf calls us from bh without RTNL */ | ||
659 | if (in_softirq()) | ||
660 | return NOTIFY_DONE; | ||
661 | |||
664 | if (!netif_is_ipvlan(dev)) | 662 | if (!netif_is_ipvlan(dev)) |
665 | return NOTIFY_DONE; | 663 | return NOTIFY_DONE; |
666 | 664 | ||
@@ -699,7 +697,7 @@ static int ipvlan_add_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr) | |||
699 | memcpy(&addr->ip4addr, ip4_addr, sizeof(struct in_addr)); | 697 | memcpy(&addr->ip4addr, ip4_addr, sizeof(struct in_addr)); |
700 | addr->atype = IPVL_IPV4; | 698 | addr->atype = IPVL_IPV4; |
701 | list_add_tail(&addr->anode, &ipvlan->addrs); | 699 | list_add_tail(&addr->anode, &ipvlan->addrs); |
702 | ipvlan->ipv4cnt++; | 700 | |
703 | /* If the interface is not up, the address will be added to the hash | 701 | /* If the interface is not up, the address will be added to the hash |
704 | * list by ipvlan_open. | 702 | * list by ipvlan_open. |
705 | */ | 703 | */ |
@@ -717,10 +715,8 @@ static void ipvlan_del_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr) | |||
717 | if (!addr) | 715 | if (!addr) |
718 | return; | 716 | return; |
719 | 717 | ||
720 | ipvlan_ht_addr_del(addr, true); | 718 | ipvlan_ht_addr_del(addr); |
721 | list_del(&addr->anode); | 719 | list_del(&addr->anode); |
722 | ipvlan->ipv4cnt--; | ||
723 | WARN_ON(ipvlan->ipv4cnt < 0); | ||
724 | kfree_rcu(addr, rcu); | 720 | kfree_rcu(addr, rcu); |
725 | 721 | ||
726 | return; | 722 | return; |