svn commit: r266857 - head/sys/netinet6
Hiroki Sato
hrs at FreeBSD.org
Thu May 29 20:53:54 UTC 2014
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);
More information about the svn-src-all
mailing list