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>