提交 e9997c29 编写于 作者: J Jiri Benc 提交者: David S. Miller

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: NJiri Benc <jbenc@redhat.com>
Acked-by: NMahesh Bandewar <maheshb@google.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 40891e8a
...@@ -114,7 +114,9 @@ unsigned int ipvlan_mac_hash(const unsigned char *addr); ...@@ -114,7 +114,9 @@ unsigned int ipvlan_mac_hash(const unsigned char *addr);
rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb); rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb);
int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev); int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev);
void ipvlan_ht_addr_add(struct ipvl_dev *ipvlan, struct ipvl_addr *addr); void ipvlan_ht_addr_add(struct ipvl_dev *ipvlan, struct ipvl_addr *addr);
bool ipvlan_addr_busy(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6); struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan,
const void *iaddr, bool is_v6);
bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6);
struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port, struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port,
const void *iaddr, bool is_v6); const void *iaddr, bool is_v6);
void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync); void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync);
......
...@@ -92,9 +92,9 @@ void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync) ...@@ -92,9 +92,9 @@ void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync)
synchronize_rcu(); synchronize_rcu();
} }
bool ipvlan_addr_busy(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6) struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan,
const void *iaddr, bool is_v6)
{ {
struct ipvl_port *port = ipvlan->port;
struct ipvl_addr *addr; struct ipvl_addr *addr;
list_for_each_entry(addr, &ipvlan->addrs, anode) { 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,12 +102,21 @@ bool ipvlan_addr_busy(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6)
ipv6_addr_equal(&addr->ip6addr, iaddr)) || ipv6_addr_equal(&addr->ip6addr, iaddr)) ||
(!is_v6 && addr->atype == IPVL_IPV4 && (!is_v6 && addr->atype == IPVL_IPV4 &&
addr->ip4addr.s_addr == ((struct in_addr *)iaddr)->s_addr)) addr->ip4addr.s_addr == ((struct in_addr *)iaddr)->s_addr))
return true; return addr;
} }
return NULL;
}
if (ipvlan_ht_addr_lookup(port, iaddr, is_v6)) bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6)
return true; {
struct ipvl_dev *ipvlan;
ASSERT_RTNL();
list_for_each_entry(ipvlan, &port->ipvlans, pnode) {
if (ipvlan_find_addr(ipvlan, iaddr, is_v6))
return true;
}
return false; return false;
} }
......
...@@ -607,7 +607,7 @@ static int ipvlan_add_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr) ...@@ -607,7 +607,7 @@ static int ipvlan_add_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr)
{ {
struct ipvl_addr *addr; struct ipvl_addr *addr;
if (ipvlan_addr_busy(ipvlan, ip6_addr, true)) { if (ipvlan_addr_busy(ipvlan->port, ip6_addr, true)) {
netif_err(ipvlan, ifup, ipvlan->dev, netif_err(ipvlan, ifup, ipvlan->dev,
"Failed to add IPv6=%pI6c addr for %s intf\n", "Failed to add IPv6=%pI6c addr for %s intf\n",
ip6_addr, ipvlan->dev->name); ip6_addr, ipvlan->dev->name);
...@@ -635,7 +635,7 @@ static void ipvlan_del_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr) ...@@ -635,7 +635,7 @@ static void ipvlan_del_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr)
{ {
struct ipvl_addr *addr; struct ipvl_addr *addr;
addr = ipvlan_ht_addr_lookup(ipvlan->port, ip6_addr, true); addr = ipvlan_find_addr(ipvlan, ip6_addr, true);
if (!addr) if (!addr)
return; return;
...@@ -679,7 +679,7 @@ static int ipvlan_add_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr) ...@@ -679,7 +679,7 @@ static int ipvlan_add_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr)
{ {
struct ipvl_addr *addr; struct ipvl_addr *addr;
if (ipvlan_addr_busy(ipvlan, ip4_addr, false)) { if (ipvlan_addr_busy(ipvlan->port, ip4_addr, false)) {
netif_err(ipvlan, ifup, ipvlan->dev, netif_err(ipvlan, ifup, ipvlan->dev,
"Failed to add IPv4=%pI4 on %s intf.\n", "Failed to add IPv4=%pI4 on %s intf.\n",
ip4_addr, ipvlan->dev->name); ip4_addr, ipvlan->dev->name);
...@@ -708,7 +708,7 @@ static void ipvlan_del_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr) ...@@ -708,7 +708,7 @@ static void ipvlan_del_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr)
{ {
struct ipvl_addr *addr; struct ipvl_addr *addr;
addr = ipvlan_ht_addr_lookup(ipvlan->port, ip4_addr, false); addr = ipvlan_find_addr(ipvlan, ip4_addr, false);
if (!addr) if (!addr)
return; return;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册