Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 20 Apr 2018 14:21:37 +0000 (UTC)
From:      "Jonathan T. Looney" <jtl@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r332819 - stable/11/sys/netinet6
Message-ID:  <201804201421.w3KELbAl053823@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jtl
Date: Fri Apr 20 14:21:37 2018
New Revision: 332819
URL: https://svnweb.freebsd.org/changeset/base/332819

Log:
  MFC r331488:
    This change adds a flag to the DAD entry to indicate whether it is
    currently on the queue. This prevents accidentally doubly-removing a DAD
    entry from the queue, while also simplifying some of the logic in
    nd6_dad_stop().
  
  Sponsored by:	Netflix, Inc.

Modified:
  stable/11/sys/netinet6/nd6_nbr.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/netinet6/nd6_nbr.c
==============================================================================
--- stable/11/sys/netinet6/nd6_nbr.c	Fri Apr 20 14:01:08 2018	(r332818)
+++ stable/11/sys/netinet6/nd6_nbr.c	Fri Apr 20 14:21:37 2018	(r332819)
@@ -1119,6 +1119,7 @@ struct dadq {
 #define	ND_OPT_NONCE_LEN32 \
 		((ND_OPT_NONCE_LEN + sizeof(uint32_t) - 1)/sizeof(uint32_t))
 	uint32_t dad_nonce[ND_OPT_NONCE_LEN32];
+	bool dad_ondadq;	/* on dadq? Protected by DADQ_WLOCK. */
 };
 
 static VNET_DEFINE(TAILQ_HEAD(, dadq), dadq);
@@ -1137,6 +1138,7 @@ nd6_dad_add(struct dadq *dp)
 
 	DADQ_WLOCK();
 	TAILQ_INSERT_TAIL(&V_dadq, dp, dad_list);
+	dp->dad_ondadq = true;
 	DADQ_WUNLOCK();
 }
 
@@ -1145,9 +1147,17 @@ nd6_dad_del(struct dadq *dp)
 {
 
 	DADQ_WLOCK();
-	TAILQ_REMOVE(&V_dadq, dp, dad_list);
-	DADQ_WUNLOCK();
-	nd6_dad_rele(dp);
+	if (dp->dad_ondadq) {
+		/*
+		 * Remove dp from the dadq and release the dadq's
+		 * reference.
+		 */
+		TAILQ_REMOVE(&V_dadq, dp, dad_list);
+		dp->dad_ondadq = false;
+		DADQ_WUNLOCK();
+		nd6_dad_rele(dp);
+	} else
+		DADQ_WUNLOCK();
 }
 
 static struct dadq *
@@ -1294,6 +1304,8 @@ nd6_dad_start(struct ifaddr *ifa, int delay)
 	dp->dad_ns_icount = dp->dad_na_icount = 0;
 	dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
 	dp->dad_ns_lcount = dp->dad_loopbackprobe = 0;
+
+	/* Add this to the dadq and add a reference for the dadq. */
 	refcount_init(&dp->dad_refcnt, 1);
 	nd6_dad_add(dp);
 	nd6_dad_starttimer(dp, delay, 0);
@@ -1314,16 +1326,9 @@ nd6_dad_stop(struct ifaddr *ifa)
 	}
 
 	nd6_dad_stoptimer(dp);
-
-	/*
-	 * The DAD queue entry may have been removed by nd6_dad_timer() while
-	 * we were waiting for it to stop, so re-do the lookup.
-	 */
-	nd6_dad_rele(dp);
-	if (nd6_dad_find(ifa, NULL) == NULL)
-		return;
-
 	nd6_dad_del(dp);
+
+	/* Release this function's reference, acquired by nd6_dad_find(). */
 	nd6_dad_rele(dp);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201804201421.w3KELbAl053823>