aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Benc <jbenc@redhat.com>2015-03-28 14:13:25 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-31 13:28:33 -0400
commite9997c2938b23d792528da1597b3aea9b0f2a324 (patch)
treec2e767997eb357c7b48e4711c336a89ddcc730ce
parent40891e8ad630558caae26788d37bf50137b6d5d2 (diff)
ipvlan: fix check for IP addresses in control path
When an ipvlan interface is down, its addresses are not on the hash list. Fix checks for existence of addresses not to depend on the hash list, walk through all interface addresses instead. Signed-off-by: Jiri Benc <jbenc@redhat.com> Acked-by: Mahesh Bandewar <maheshb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ipvlan/ipvlan.h4
-rw-r--r--drivers/net/ipvlan/ipvlan_core.c19
-rw-r--r--drivers/net/ipvlan/ipvlan_main.c8
3 files changed, 21 insertions, 10 deletions
diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h
index 924ea98bd531..54549a6223dd 100644
--- a/drivers/net/ipvlan/ipvlan.h
+++ b/drivers/net/ipvlan/ipvlan.h
@@ -114,7 +114,9 @@ unsigned int ipvlan_mac_hash(const unsigned char *addr);
114rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb); 114rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb);
115int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev); 115int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev);
116void ipvlan_ht_addr_add(struct ipvl_dev *ipvlan, struct ipvl_addr *addr); 116void ipvlan_ht_addr_add(struct ipvl_dev *ipvlan, struct ipvl_addr *addr);
117bool ipvlan_addr_busy(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6); 117struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan,
118 const void *iaddr, bool is_v6);
119bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6);
118struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port, 120struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port,
119 const void *iaddr, bool is_v6); 121 const void *iaddr, bool is_v6);
120void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync); 122void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync);
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index 568628f95aa2..b7877a194cfe 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -92,9 +92,9 @@ void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync)
92 synchronize_rcu(); 92 synchronize_rcu();
93} 93}
94 94
95bool ipvlan_addr_busy(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6) 95struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan,
96 const void *iaddr, bool is_v6)
96{ 97{
97 struct ipvl_port *port = ipvlan->port;
98 struct ipvl_addr *addr; 98 struct ipvl_addr *addr;
99 99
100 list_for_each_entry(addr, &ipvlan->addrs, anode) { 100 list_for_each_entry(addr, &ipvlan->addrs, anode) {
@@ -102,12 +102,21 @@ bool ipvlan_addr_busy(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6)
102 ipv6_addr_equal(&addr->ip6addr, iaddr)) || 102 ipv6_addr_equal(&addr->ip6addr, iaddr)) ||
103 (!is_v6 && addr->atype == IPVL_IPV4 && 103 (!is_v6 && addr->atype == IPVL_IPV4 &&
104 addr->ip4addr.s_addr == ((struct in_addr *)iaddr)->s_addr)) 104 addr->ip4addr.s_addr == ((struct in_addr *)iaddr)->s_addr))
105 return true; 105 return addr;
106 } 106 }
107 return NULL;
108}
107 109
108 if (ipvlan_ht_addr_lookup(port, iaddr, is_v6)) 110bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6)
109 return true; 111{
112 struct ipvl_dev *ipvlan;
113
114 ASSERT_RTNL();
110 115
116 list_for_each_entry(ipvlan, &port->ipvlans, pnode) {
117 if (ipvlan_find_addr(ipvlan, iaddr, is_v6))
118 return true;
119 }
111 return false; 120 return false;
112} 121}
113 122
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index aaa005bd21ce..4fa14208d799 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -607,7 +607,7 @@ static int ipvlan_add_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr)
607{ 607{
608 struct ipvl_addr *addr; 608 struct ipvl_addr *addr;
609 609
610 if (ipvlan_addr_busy(ipvlan, ip6_addr, true)) { 610 if (ipvlan_addr_busy(ipvlan->port, ip6_addr, true)) {
611 netif_err(ipvlan, ifup, ipvlan->dev, 611 netif_err(ipvlan, ifup, ipvlan->dev,
612 "Failed to add IPv6=%pI6c addr for %s intf\n", 612 "Failed to add IPv6=%pI6c addr for %s intf\n",
613 ip6_addr, ipvlan->dev->name); 613 ip6_addr, ipvlan->dev->name);
@@ -635,7 +635,7 @@ static void ipvlan_del_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr)
635{ 635{
636 struct ipvl_addr *addr; 636 struct ipvl_addr *addr;
637 637
638 addr = ipvlan_ht_addr_lookup(ipvlan->port, ip6_addr, true); 638 addr = ipvlan_find_addr(ipvlan, ip6_addr, true);
639 if (!addr) 639 if (!addr)
640 return; 640 return;
641 641
@@ -679,7 +679,7 @@ static int ipvlan_add_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr)
679{ 679{
680 struct ipvl_addr *addr; 680 struct ipvl_addr *addr;
681 681
682 if (ipvlan_addr_busy(ipvlan, ip4_addr, false)) { 682 if (ipvlan_addr_busy(ipvlan->port, ip4_addr, false)) {
683 netif_err(ipvlan, ifup, ipvlan->dev, 683 netif_err(ipvlan, ifup, ipvlan->dev,
684 "Failed to add IPv4=%pI4 on %s intf.\n", 684 "Failed to add IPv4=%pI4 on %s intf.\n",
685 ip4_addr, ipvlan->dev->name); 685 ip4_addr, ipvlan->dev->name);
@@ -708,7 +708,7 @@ static void ipvlan_del_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr)
708{ 708{
709 struct ipvl_addr *addr; 709 struct ipvl_addr *addr;
710 710
711 addr = ipvlan_ht_addr_lookup(ipvlan->port, ip4_addr, false); 711 addr = ipvlan_find_addr(ipvlan, ip4_addr, false);
712 if (!addr) 712 if (!addr)
713 return; 713 return;
714 714