tech-net archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: ifconfig not waiting for DAD completion
On 2015-12-03 22:04, Anthony Mallet wrote:
If ifconfig -w is to wait for detached as well, maybe it could take an
interface name (like -s), e.g. `ifconfig -w 4 wm0` and a new variable
added in
rc.conf, e.g. waitdad_interfaces="wm0 wm1". Or just waitdad=YES/NO and
using
whatever is in net_interfaces or in the auto_ifconfig computed list.
Another approach could be `ifconfig wm0 ... waitdad 4` so that this can
be
tuned in $ifconfig_xxN. But this looses the parallelism if one has
several
interfaces.
Here's a patch which adds the -W flag to ifconfig(8) which will wait for
N seconds for the detached flag to clear.
This does not extend the -w flag option duration.
The default has been set to -w 10 -W 2.
Please test it, as we may need to increase them - they are currently low
to ensure as fast as a boot as possible.
Roy
? sbin/ifconfig/.gdbinit
? sbin/ifconfig/ifconfig
Index: etc/defaults/rc.conf
===================================================================
RCS file: /cvsroot/src/etc/defaults/rc.conf,v
retrieving revision 1.134
diff -u -r1.134 rc.conf
--- etc/defaults/rc.conf 13 Dec 2015 02:27:06 -0000 1.134
+++ etc/defaults/rc.conf 20 Dec 2015 17:11:29 -0000
@@ -162,6 +162,11 @@
# Networking startup.
#
+ifconfig_wait_dad_flags="-w 10 -W 2" # wait upto 10 secs for
+ # tentative flag to clear
+ # and upto 3 seconds for the
+ # detached flag to clear
+ # from all addresses
mdnsd=NO
npf=NO
ipfilter=NO ipfilter_flags="" # uses /etc/ipf.conf
Index: etc/rc.d/network
===================================================================
RCS file: /cvsroot/src/etc/rc.d/network,v
retrieving revision 1.69
diff -u -r1.69 network
--- etc/rc.d/network 14 Oct 2014 20:49:47 -0000 1.69
+++ etc/rc.d/network 20 Dec 2015 17:11:35 -0000
@@ -51,6 +51,7 @@
network_start_defaultroute6
have_inet6 &&
network_start_ipv6_autoconf
+ network_wait_dad
network_start_local
}
@@ -433,18 +434,6 @@
{
# IPv6 interface autoconfiguration.
- dadcount=$(/sbin/sysctl -n net.inet6.ip6.dad_count 2>/dev/null)
- if [ -n "$dadcount" -a "$dadcount" != 0 ]; then
- # wait till DAD is completed
- echo 'Waiting for DAD to complete for' \
- 'statically configured addresses...'
- # Add 1 for MAX_RTR_SOLICITATION_DELAY and another
- # to give time for the last DAD packet to respond and
- # a few more for luck.
- waitsecs=$((dadcount + 4))
- /sbin/ifconfig -w $waitsecs
- fi
-
# dhcpcd will ensure DAD completes before forking
if checkyesnox rtsol && ! checkyesno dhcpcd; then
if [ "$ip6mode" = "autohost" ]; then
@@ -455,6 +444,16 @@
fi
}
+network_wait_dad()
+{
+ # Wait for the DAD flags to clear form all addresses.
+ if [ -n "$ifconfig_wait_dad_flags" ]; then
+ echo 'Waiting for DAD to complete for' \
+ 'statically configured addresses...'
+ ifconfig $ifconfig_wait_dad_flags
+ fi
+}
+
network_start_local()
{
# XXX this must die
Index: sbin/ifconfig/af_inet.c
===================================================================
RCS file: /cvsroot/src/sbin/ifconfig/af_inet.c,v
retrieving revision 1.17
diff -u -r1.17 af_inet.c
--- sbin/ifconfig/af_inet.c 12 May 2015 14:05:29 -0000 1.17
+++ sbin/ifconfig/af_inet.c 20 Dec 2015 17:11:36 -0000
@@ -62,14 +62,17 @@
static void in_constructor(void) __attribute__((constructor));
static void in_status(prop_dictionary_t, prop_dictionary_t, bool);
static void in_commit_address(prop_dictionary_t, prop_dictionary_t);
-static bool in_addr_tentative(struct ifaddrs *ifa);
+static bool in_addr_flags(struct ifaddrs *, int);
+static bool in_addr_tentative(struct ifaddrs *);
+static bool in_addr_tentative_or_detached(struct ifaddrs *);
static void in_alias(const char *, prop_dictionary_t, prop_dictionary_t,
struct in_aliasreq *);
static struct afswtch af = {
.af_name = "inet", .af_af = AF_INET, .af_status = in_status,
.af_addr_commit = in_commit_address,
- .af_addr_tentative = in_addr_tentative
+ .af_addr_tentative = in_addr_tentative,
+ .af_addr_tentative_or_detached = in_addr_tentative_or_detached
};
static void
@@ -220,10 +223,10 @@
commit_address(env, oenv, &inparam);
}
+#ifdef SIOCGIFAFLAG_IN
static bool
-in_addr_tentative(struct ifaddrs *ifa)
+in_addr_flags(struct ifaddrs *ifa, int flags)
{
-#ifdef IN_IFF_TENTATIVE
int s;
struct ifreq ifr;
@@ -234,7 +237,28 @@
err(EXIT_FAILURE, "%s: getsock", __func__);
if (prog_ioctl(s, SIOCGIFAFLAG_IN, &ifr) == -1)
err(EXIT_FAILURE, "SIOCGIFAFLAG_IN");
- return ifr.ifr_addrflags & IN_IFF_TENTATIVE ? true : false;
+ return ifr.ifr_addrflags & flags ? true : false;
+ return false;
+}
+#endif
+
+static bool
+in_addr_tentative(struct ifaddrs *ifa)
+{
+
+#ifdef IN_IFF_TENTATIVE
+ return in_addr_flags(ifa, IN_IFF_TENTATIVE);
+#else
+ return false;
+#endif
+}
+
+static bool
+in_addr_tentative_or_detached(struct ifaddrs *ifa)
+{
+
+#ifdef IN_IFF_TENTATIVE
+ return in_addr_flags(ifa, IN_IFF_TENTATIVE | IN_IFF_DETACHED);
#else
return false;
#endif
Index: sbin/ifconfig/af_inet6.c
===================================================================
RCS file: /cvsroot/src/sbin/ifconfig/af_inet6.c,v
retrieving revision 1.33
diff -u -r1.33 af_inet6.c
--- sbin/ifconfig/af_inet6.c 12 May 2015 14:05:29 -0000 1.33
+++ sbin/ifconfig/af_inet6.c 20 Dec 2015 17:11:38 -0000
@@ -72,7 +72,9 @@
static int setia6lifetime(prop_dictionary_t, int64_t, time_t *, uint32_t *);
static void in6_status(prop_dictionary_t, prop_dictionary_t, bool);
+static bool in6_addr_flags(struct ifaddrs *ifa, int);
static bool in6_addr_tentative(struct ifaddrs *ifa);
+static bool in6_addr_tentative_or_detached(struct ifaddrs *ifa);
static struct usage_func usage;
static cmdloop_branch_t branch[2];
@@ -103,7 +105,8 @@
static struct afswtch in6af = {
.af_name = "inet6", .af_af = AF_INET6, .af_status = in6_status,
.af_addr_commit = in6_commit_address,
- .af_addr_tentative = in6_addr_tentative
+ .af_addr_tentative = in6_addr_tentative,
+ .af_addr_tentative_or_detached = in6_addr_tentative_or_detached
};
static int
@@ -477,7 +480,7 @@
}
static bool
-in6_addr_tentative(struct ifaddrs *ifa)
+in6_addr_flags(struct ifaddrs *ifa, int flags)
{
int s;
struct in6_ifreq ifr;
@@ -489,7 +492,21 @@
ifr.ifr_addr = *(struct sockaddr_in6 *)ifa->ifa_addr;
if (prog_ioctl(s, SIOCGIFAFLAG_IN6, &ifr) == -1)
err(EXIT_FAILURE, "SIOCGIFAFLAG_IN6");
- return ifr.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE ? true : false;
+ return ifr.ifr_ifru.ifru_flags6 & flags ? true : false;
+}
+
+static bool
+in6_addr_tentative(struct ifaddrs *ifa)
+{
+
+ return in6_addr_flags(ifa, IN6_IFF_TENTATIVE);
+}
+
+static bool
+in6_addr_tentative_or_detached(struct ifaddrs *ifa)
+{
+
+ return in6_addr_flags(ifa, IN6_IFF_TENTATIVE | IN6_IFF_DETACHED);
}
static void
Index: sbin/ifconfig/ifconfig.8
===================================================================
RCS file: /cvsroot/src/sbin/ifconfig/ifconfig.8,v
retrieving revision 1.109
diff -u -r1.109 ifconfig.8
--- sbin/ifconfig/ifconfig.8 20 Oct 2014 14:50:09 -0000 1.109
+++ sbin/ifconfig/ifconfig.8 20 Dec 2015 17:11:43 -0000
@@ -29,7 +29,7 @@
.\"
.\" @(#)ifconfig.8 8.4 (Berkeley) 6/1/94
.\"
-.Dd October 12, 2014
+.Dd December 20, 2015
.Dt IFCONFIG 8
.Os
.Sh NAME
@@ -61,6 +61,7 @@
.Nm
.Fl w
.Ar secs
+.Op Fl W Ar secs
.Nm
.Fl C
.Sh DESCRIPTION
@@ -872,6 +873,13 @@
0 seconds means to wait indefinitely until all addresses no longer have the
.Cm tentative
flag.
+The optional
+.Fl W
+flag may be used to wait
+.Ar seconds
+seconds during the above time for the detached flag to be removed from all
+addresses as well.
+The detached flag is set when the interface does not have a carrier.
.Pp
The
.Fl N
Index: sbin/ifconfig/ifconfig.c
===================================================================
RCS file: /cvsroot/src/sbin/ifconfig/ifconfig.c,v
retrieving revision 1.235
diff -u -r1.235 ifconfig.c
--- sbin/ifconfig/ifconfig.c 29 Jul 2015 07:42:27 -0000 1.235
+++ sbin/ifconfig/ifconfig.c 20 Dec 2015 17:11:56 -0000
@@ -104,11 +104,11 @@
#define WAIT_DAD 10000000 /* nanoseconds between each poll, 10ms */
-static bool bflag, dflag, hflag, sflag, uflag, wflag;
+static bool bflag, dflag, hflag, sflag, uflag, Wflag, wflag;
bool lflag, Nflag, vflag, zflag;
-static long wflag_secs;
+static long wflag_secs, Wflag_secs;
-static char gflags[10 + 26 * 2 + 1] = "AabCdhlNsuvw:z";
+static char gflags[10 + 26 * 2 + 1] = "AabCdhlNsuvW:w:z";
bool gflagset[10 + 26 * 2];
static int carrier(prop_dictionary_t);
@@ -518,14 +518,25 @@
bool waiting;
struct ifaddrs *ifaddrs, *ifa;
const struct timespec ts = { .tv_sec = 0, .tv_nsec = WAIT_DAD };
- const struct timespec add = { .tv_sec = wflag_secs, .tv_nsec = 0};
- struct timespec now, end = { .tv_sec = wflag_secs, .tv_nsec = 0};
+ struct timespec now, end_det, end;
const struct afswtch *afp;
if (wflag_secs) {
+ const struct timespec tent =
+ { .tv_sec = wflag_secs, .tv_nsec = 0};
+ const struct timespec det =
+ { .tv_sec = Wflag_secs, .tv_nsec = 0};
+
if (clock_gettime(CLOCK_MONOTONIC, &now) == -1)
err(EXIT_FAILURE, "clock_gettime");
- timespecadd(&now, &add, &end);
+ timespecadd(&now, &tent, &end);
+ if (Wflag_secs)
+ timespecadd(&now, &det, &end_det);
+ else
+ timespecclear(&end_det);
+ } else {
+ timespecclear(&end_det);
+ timespecclear(&end);
}
if (getifaddrs(&ifaddrs) == -1)
@@ -537,8 +548,13 @@
if (ifa->ifa_addr == NULL)
continue;
afp = lookup_af_bynum(ifa->ifa_addr->sa_family);
- if (afp && afp->af_addr_tentative &&
- afp->af_addr_tentative(ifa))
+ if (afp &&
+ ((afp->af_addr_tentative_or_detached &&
+ timespecisset(&end_det) &&
+ timespeccmp(&now, &end_det, <) &&
+ afp->af_addr_tentative_or_detached(ifa)) ||
+ (afp->af_addr_tentative &&
+ afp->af_addr_tentative(ifa))))
{
waiting = true;
break;
@@ -595,7 +611,7 @@
main(int argc, char **argv)
{
const struct afswtch *afp;
- int af, s;
+ int af, s, e;
bool aflag = false, Cflag = false;
struct match match[32];
size_t nmatch;
@@ -603,7 +619,6 @@
int ch, narg = 0, rc;
prop_dictionary_t env, oenv;
const char *ifname;
- char *end;
memset(match, 0, sizeof(match));
@@ -662,9 +677,15 @@
case 'w':
wflag = true;
- wflag_secs = strtol(optarg, &end, 10);
- if ((end != NULL && *end != '\0') ||
- wflag_secs < 0 || wflag_secs >= INT32_MAX)
+ wflag_secs = strtoi(optarg, NULL, 10, 0, INT32_MAX, &e);
+ if (e)
+ errx(EXIT_FAILURE, "%s: not a number", optarg);
+ break;
+
+ case 'W':
+ Wflag = true;
+ Wflag_secs = strtoi(optarg, NULL, 10, 0, INT32_MAX, &e);
+ if (e)
errx(EXIT_FAILURE, "%s: not a number", optarg);
break;
Index: sbin/ifconfig/util.h
===================================================================
RCS file: /cvsroot/src/sbin/ifconfig/util.h,v
retrieving revision 1.11
diff -u -r1.11 util.h
--- sbin/ifconfig/util.h 22 Apr 2015 17:42:22 -0000 1.11
+++ sbin/ifconfig/util.h 20 Dec 2015 17:11:56 -0000
@@ -14,6 +14,7 @@
void (*af_status)(prop_dictionary_t, prop_dictionary_t, bool);
void (*af_addr_commit)(prop_dictionary_t, prop_dictionary_t);
bool (*af_addr_tentative)(struct ifaddrs *);
+ bool (*af_addr_tentative_or_detached)(struct ifaddrs *);
SIMPLEQ_ENTRY(afswtch) af_next;
};
Home |
Main Index |
Thread Index |
Old Index