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