From owner-svn-src-all@FreeBSD.ORG Thu May 29 20:53:54 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id E206AFBC; Thu, 29 May 2014 20:53:53 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id D02CB268D; Thu, 29 May 2014 20:53:53 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s4TKrrMo014206; Thu, 29 May 2014 20:53:53 GMT (envelope-from hrs@svn.freebsd.org) Received: (from hrs@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s4TKrrcd014205; Thu, 29 May 2014 20:53:53 GMT (envelope-from hrs@svn.freebsd.org) Message-Id: <201405292053.s4TKrrcd014205@svn.freebsd.org> From: Hiroki Sato Date: Thu, 29 May 2014 20:53:53 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r266857 - head/sys/netinet6 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 29 May 2014 20:53:54 -0000 Author: hrs Date: Thu May 29 20:53:53 2014 New Revision: 266857 URL: http://svnweb.freebsd.org/changeset/base/266857 Log: Add rwlock to struct dadq. A panic could occur when a large number of addresses performed DAD at the same time. Modified: head/sys/netinet6/nd6_nbr.c Modified: head/sys/netinet6/nd6_nbr.c ============================================================================== --- head/sys/netinet6/nd6_nbr.c Thu May 29 20:26:01 2014 (r266856) +++ head/sys/netinet6/nd6_nbr.c Thu May 29 20:53:53 2014 (r266857) @@ -88,8 +88,10 @@ static void nd6_dad_na_input(struct ifad static void nd6_na_output_fib(struct ifnet *, const struct in6_addr *, const struct in6_addr *, u_long, int, struct sockaddr *, u_int); -VNET_DEFINE(int, dad_ignore_ns) = 0; /* ignore NS in DAD - specwise incorrect*/ -VNET_DEFINE(int, dad_maxtry) = 15; /* max # of *tries* to transmit DAD packet */ +static VNET_DEFINE(int, dad_ignore_ns) = 0; /* ignore NS in DAD + - specwise incorrect */ +static VNET_DEFINE(int, dad_maxtry) = 15; /* max # of *tries* to + transmit DAD packet */ #define V_dad_ignore_ns VNET(dad_ignore_ns) #define V_dad_maxtry VNET(dad_maxtry) @@ -1165,20 +1167,30 @@ struct dadq { }; static VNET_DEFINE(TAILQ_HEAD(, dadq), dadq); -VNET_DEFINE(int, dad_init) = 0; -#define V_dadq VNET(dadq) -#define V_dad_init VNET(dad_init) +static VNET_DEFINE(struct rwlock, dad_rwlock); +#define V_dadq VNET(dadq) +#define V_dad_rwlock VNET(dad_rwlock) + +#define DADQ_LOCK_INIT() rw_init(&V_dad_rwlock, "nd6 DAD queue") +#define DADQ_LOCK_DESTROY() rw_destroy(&V_dad_rwlock) +#define DADQ_LOCK_INITIALIZED() rw_initialized(&V_dad_rwlock) +#define DADQ_RLOCK() rw_rlock(&V_dad_rwlock) +#define DADQ_RUNLOCK() rw_runlock(&V_dad_rwlock) +#define DADQ_WLOCK() rw_wlock(&V_dad_rwlock) +#define DADQ_WUNLOCK() rw_wunlock(&V_dad_rwlock) static struct dadq * nd6_dad_find(struct ifaddr *ifa) { struct dadq *dp; + DADQ_RLOCK(); TAILQ_FOREACH(dp, &V_dadq, dad_list) if (dp->dad_ifa == ifa) - return (dp); + break; + DADQ_RUNLOCK(); - return (NULL); + return (dp); } static void @@ -1206,9 +1218,9 @@ nd6_dad_start(struct ifaddr *ifa, int de struct dadq *dp; char ip6buf[INET6_ADDRSTRLEN]; - if (!V_dad_init) { + if (DADQ_LOCK_INITIALIZED() == 0) { + DADQ_LOCK_INIT(); TAILQ_INIT(&V_dadq); - V_dad_init++; } /* @@ -1258,7 +1270,9 @@ nd6_dad_start(struct ifaddr *ifa, int de #ifdef VIMAGE dp->dad_vnet = curvnet; #endif + DADQ_WLOCK(); TAILQ_INSERT_TAIL(&V_dadq, (struct dadq *)dp, dad_list); + DADQ_WUNLOCK(); nd6log((LOG_DEBUG, "%s: starting DAD for %s\n", if_name(ifa->ifa_ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr))); @@ -1291,7 +1305,7 @@ nd6_dad_stop(struct ifaddr *ifa) { struct dadq *dp; - if (!V_dad_init) + if (DADQ_LOCK_INITIALIZED() == 0) return; dp = nd6_dad_find(ifa); if (!dp) { @@ -1301,7 +1315,9 @@ nd6_dad_stop(struct ifaddr *ifa) nd6_dad_stoptimer(dp); + DADQ_WLOCK(); TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list); + DADQ_WUNLOCK(); free(dp, M_IP6NDP); dp = NULL; ifa_free(ifa); @@ -1351,7 +1367,9 @@ nd6_dad_timer(struct dadq *dp) nd6log((LOG_INFO, "%s: could not run DAD, driver problem?\n", if_name(ifa->ifa_ifp))); + DADQ_WLOCK(); TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list); + DADQ_WUNLOCK(); free(dp, M_IP6NDP); dp = NULL; ifa_free(ifa); @@ -1407,7 +1425,9 @@ nd6_dad_timer(struct dadq *dp) if_name(ifa->ifa_ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr))); + DADQ_WLOCK(); TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list); + DADQ_WUNLOCK(); free(dp, M_IP6NDP); dp = NULL; ifa_free(ifa); @@ -1484,7 +1504,9 @@ nd6_dad_duplicated(struct ifaddr *ifa) } } + DADQ_WLOCK(); TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list); + DADQ_WUNLOCK(); free(dp, M_IP6NDP); dp = NULL; ifa_free(ifa);