Commit f24e3d65 authored by Mitsuru Chinen's avatar Mitsuru Chinen Committed by David S. Miller

[IPV6]: Defer IPv6 device initialization until a valid qdisc is specified

To judge the timing for DAD, netif_carrier_ok() is used. However,
there is a possibility that dev->qdisc stays noop_qdisc even if
netif_carrier_ok() returns true. In that case, DAD NS is not sent out.
We need to defer the IPv6 device initialization until a valid qdisc
is specified.
Signed-off-by: default avatarMitsuru Chinen <mitch@linux.vnet.ibm.com>
Signed-off-by: default avatarYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9b772652
...@@ -74,6 +74,7 @@ ...@@ -74,6 +74,7 @@
#include <net/tcp.h> #include <net/tcp.h>
#include <net/ip.h> #include <net/ip.h>
#include <net/netlink.h> #include <net/netlink.h>
#include <net/pkt_sched.h>
#include <linux/if_tunnel.h> #include <linux/if_tunnel.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
...@@ -213,6 +214,12 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { ...@@ -213,6 +214,12 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
/* Check if a valid qdisc is available */
static inline int addrconf_qdisc_ok(struct net_device *dev)
{
return (dev->qdisc != &noop_qdisc);
}
static void addrconf_del_timer(struct inet6_ifaddr *ifp) static void addrconf_del_timer(struct inet6_ifaddr *ifp)
{ {
if (del_timer(&ifp->timer)) if (del_timer(&ifp->timer))
...@@ -384,7 +391,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) ...@@ -384,7 +391,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
} }
#endif #endif
if (netif_running(dev) && netif_carrier_ok(dev)) if (netif_running(dev) && addrconf_qdisc_ok(dev))
ndev->if_flags |= IF_READY; ndev->if_flags |= IF_READY;
ipv6_mc_init_dev(ndev); ipv6_mc_init_dev(ndev);
...@@ -2283,7 +2290,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, ...@@ -2283,7 +2290,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
break; break;
if (event == NETDEV_UP) { if (event == NETDEV_UP) {
if (!netif_carrier_ok(dev)) { if (!addrconf_qdisc_ok(dev)) {
/* device is not ready yet. */ /* device is not ready yet. */
printk(KERN_INFO printk(KERN_INFO
"ADDRCONF(NETDEV_UP): %s: " "ADDRCONF(NETDEV_UP): %s: "
...@@ -2295,7 +2302,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, ...@@ -2295,7 +2302,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
if (idev) if (idev)
idev->if_flags |= IF_READY; idev->if_flags |= IF_READY;
} else { } else {
if (!netif_carrier_ok(dev)) { if (!addrconf_qdisc_ok(dev)) {
/* device is still not ready. */ /* device is still not ready. */
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment