Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 23 Nov 2014 15:38:07 +0000 (UTC)
From:      "Alexander V. Chernikov" <melifaro@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r274917 - in projects/routing/sys: net netinet netinet6
Message-ID:  <201411231538.sANFc7HN026690@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: melifaro
Date: Sun Nov 23 15:38:06 2014
New Revision: 274917
URL: https://svnweb.freebsd.org/changeset/base/274917

Log:
  Do more fine-grained lltable locking: use table runtime lock as rare
  as we can.

Modified:
  projects/routing/sys/net/if.c
  projects/routing/sys/net/if_llatbl.c
  projects/routing/sys/net/if_var.h
  projects/routing/sys/net/rt_nhops.c
  projects/routing/sys/netinet/if_ether.c
  projects/routing/sys/netinet/in.c
  projects/routing/sys/netinet/toecore.c
  projects/routing/sys/netinet6/in6.c
  projects/routing/sys/netinet6/nd6.c
  projects/routing/sys/netinet6/scope6.c

Modified: projects/routing/sys/net/if.c
==============================================================================
--- projects/routing/sys/net/if.c	Sun Nov 23 12:15:28 2014	(r274916)
+++ projects/routing/sys/net/if.c	Sun Nov 23 15:38:06 2014	(r274917)
@@ -774,16 +774,16 @@ if_attachdomain1(struct ifnet *ifp)
 	 * Since dp->dom_ifattach calls malloc() with M_WAITOK, we
 	 * cannot lock ifp->if_afdata initialization, entirely.
 	 */
-	if (IF_AFDATA_TRY_WLOCK(ifp) == 0)
+	if (IF_AFDATA_CFG_TRY_WLOCK(ifp) == 0)
 		return;
 	if (ifp->if_afdata_initialized >= domain_init_status) {
-		IF_AFDATA_UNLOCK(ifp);
+		IF_AFDATA_CFG_WUNLOCK(ifp);
 		log(LOG_WARNING, "%s called more than once on %s\n",
 		    __func__, ifp->if_xname);
 		return;
 	}
 	ifp->if_afdata_initialized = domain_init_status;
-	IF_AFDATA_UNLOCK(ifp);
+	IF_AFDATA_CFG_WUNLOCK(ifp);
 
 	/* address family dependent data region */
 	bzero(ifp->if_afdata, sizeof(ifp->if_afdata));
@@ -961,10 +961,10 @@ if_detach_internal(struct ifnet *ifp, in
 	 * sleep, for example trying to drain a callout, thus open up the
 	 * theoretical race with re-attaching.
 	 */
-	IF_AFDATA_LOCK(ifp);
+	IF_AFDATA_CFG_WLOCK(ifp);
 	i = ifp->if_afdata_initialized;
 	ifp->if_afdata_initialized = 0;
-	IF_AFDATA_UNLOCK(ifp);
+	IF_AFDATA_CFG_WUNLOCK(ifp);
 	for (dp = domains; i > 0 && dp; dp = dp->dom_next) {
 		if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family])
 			(*dp->dom_ifdetach)(ifp,
@@ -3967,36 +3967,10 @@ if_afdata_cfg_wunlock(struct ifnet *ifp)
 	rw_wunlock(&ifp->if_afdata_cfg_lock);
 }
 
-void
-if_afdata_cfg_lock_assert(struct ifnet *ifp, int what)
-{
-
-	rw_assert(&ifp->if_afdata_cfg_lock, what);
-}
-
-void
-if_afdata_wlock(struct ifnet *ifp)
-{
-
-	if_afdata_cfg_wlock(ifp);
-	IF_AFDATA_RUN_WLOCK(ifp);
-}
-
-void
-if_afdata_wunlock(struct ifnet *ifp)
-{
-
-	if_afdata_cfg_wunlock(ifp);
-	IF_AFDATA_RUN_WUNLOCK(ifp);
-}
-
 int
-if_afdata_try_wlock(struct ifnet *ifp)
+if_afdata_cfg_try_wlock(struct ifnet *ifp)
 {
-	if (rw_try_wlock(&ifp->if_afdata_cfg_lock) == 0)
-		return (0);
 
-	IF_AFDATA_RUN_WLOCK(ifp);
-	return (1);
+	return (rw_try_wlock(&ifp->if_afdata_cfg_lock));
 }
 

Modified: projects/routing/sys/net/if_llatbl.c
==============================================================================
--- projects/routing/sys/net/if_llatbl.c	Sun Nov 23 12:15:28 2014	(r274916)
+++ projects/routing/sys/net/if_llatbl.c	Sun Nov 23 15:38:06 2014	(r274917)
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/lock.h>
 #include <sys/mutex.h>
 #include <sys/rwlock.h>
+#include <sys/rmlock.h>
 
 #ifdef DDB
 #include <ddb/ddb.h>
@@ -99,6 +100,11 @@ llentry_link(struct lltable *llt, struct
 	struct llentries *lleh;
 	uint32_t hashkey;
 
+	if ((lle->la_flags & LLE_LINKED) != 0)
+		return;
+
+	IF_AFDATA_RUN_WLOCK_ASSERT(llt->llt_ifp);
+
 	hashkey = llt->llt_hash(lle);
 	lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
 
@@ -112,10 +118,13 @@ void
 llentry_unlink(struct llentry *lle)
 {
 
-	LIST_REMOVE(lle, lle_next);
-	lle->la_flags &= ~(LLE_VALID | LLE_LINKED);
-	lle->lle_tbl = NULL;
-	lle->lle_head = NULL;
+	if ((lle->la_flags & LLE_LINKED) != 0) {
+		IF_AFDATA_RUN_WLOCK_ASSERT(lle->lle_tbl->llt_ifp);
+		LIST_REMOVE(lle, lle_next);
+		lle->la_flags &= ~(LLE_VALID | LLE_LINKED);
+		lle->lle_tbl = NULL;
+		lle->lle_head = NULL;
+	}
 }
 
 void
@@ -143,12 +152,7 @@ llentry_free(struct llentry *lle)
 	struct mbuf *next;
 
 	LLE_WLOCK_ASSERT(lle);
-
-	if ((lle->la_flags & LLE_LINKED) != 0) {
-		IF_AFDATA_WLOCK_ASSERT(lle->lle_tbl->llt_ifp);
-		LIST_REMOVE(lle, lle_next);
-		lle->la_flags &= ~(LLE_VALID | LLE_LINKED);
-	}
+	KASSERT((lle->la_flags & LLE_LINKED) == 0, ("Freeing linked lle"));
 
 	pkts_dropped = 0;
 	while ((lle->la_numheld > 0) && (lle->la_hold != NULL)) {
@@ -172,6 +176,8 @@ llentry_free(struct llentry *lle)
  * (al)locate an llentry for address dst (equivalent to rtalloc for new-arp).
  *
  * If found the llentry * is returned referenced and unlocked.
+ *
+ * XXX: Remove after converting flowtable
  */
 struct llentry *
 llentry_alloc(struct ifnet *ifp, struct lltable *lt,
@@ -184,9 +190,14 @@ llentry_alloc(struct ifnet *ifp, struct 
 	IF_AFDATA_RUNLOCK(ifp);
 	if ((la == NULL) &&
 	    (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0) {
-		IF_AFDATA_WLOCK(ifp);
+		IF_AFDATA_CFG_WLOCK(ifp);
 		la = lla_create(lt, 0, (struct sockaddr *)dst);
-		IF_AFDATA_WUNLOCK(ifp);
+		if (la != NULL) {
+			IF_AFDATA_RUN_WLOCK(ifp);
+			llentry_link(lt, la);
+			IF_AFDATA_RUN_WUNLOCK(ifp);
+		}
+		IF_AFDATA_CFG_WUNLOCK(ifp);
 	}
 
 	if (la != NULL) {
@@ -204,6 +215,7 @@ void
 lltable_free(struct lltable *llt)
 {
 	struct llentry *lle, *next;
+	struct llentries dchain;
 	int i;
 
 	KASSERT(llt != NULL, ("%s: llt is NULL", __func__));
@@ -212,7 +224,8 @@ lltable_free(struct lltable *llt)
 	SLIST_REMOVE(&V_lltables, llt, lltable, llt_link);
 	LLTABLE_WUNLOCK();
 
-	IF_AFDATA_WLOCK(llt->llt_ifp);
+	LIST_INIT(&dchain);
+	IF_AFDATA_CFG_WLOCK(llt->llt_ifp);
 	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
 		LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
 			LLE_WLOCK(lle);
@@ -220,10 +233,15 @@ lltable_free(struct lltable *llt)
 				LLE_REMREF(lle);
 				lle->la_flags &= ~LLE_CALLOUTREF;
 			}
-			llentry_free(lle);
+			LIST_INSERT_HEAD(&dchain, lle, lle_chain);
 		}
 	}
-	IF_AFDATA_WUNLOCK(llt->llt_ifp);
+	IF_AFDATA_RUN_WLOCK(llt->llt_ifp);
+	llentries_unlink(&dchain);
+	IF_AFDATA_RUN_WUNLOCK(llt->llt_ifp);
+	LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next)
+		llentry_free(lle);
+	IF_AFDATA_CFG_WUNLOCK(llt->llt_ifp);
 
 	free(llt, M_LLTABLE);
 }
@@ -337,14 +355,15 @@ lla_rt_output(struct rt_msghdr *rtm, str
 	switch (rtm->rtm_type) {
 	case RTM_ADD:
 		/* Add static LLE */
-		IF_AFDATA_WLOCK(ifp);
+		IF_AFDATA_CFG_WLOCK(ifp);
 		lle = lla_create(llt, 0, dst);
 		if (lle == NULL) {
-			IF_AFDATA_WUNLOCK(ifp);
+			IF_AFDATA_CFG_WUNLOCK(ifp);
 			return (ENOMEM);
 		}
 
 
+		IF_AFDATA_RUN_WLOCK(ifp);
 		bcopy(LLADDR(dl), &lle->ll_addr, ifp->if_addrlen);
 		if ((rtm->rtm_flags & RTF_ANNOUNCE))
 			lle->la_flags |= LLE_PUB;
@@ -366,9 +385,11 @@ lla_rt_output(struct rt_msghdr *rtm, str
 			lle->la_expire = 0;
 		} else
 			lle->la_expire = rtm->rtm_rmx.rmx_expire;
+		llentry_link(llt, lle);
+		IF_AFDATA_RUN_WUNLOCK(ifp);
 		laflags = lle->la_flags;
 		LLE_WUNLOCK(lle);
-		IF_AFDATA_WUNLOCK(ifp);
+		IF_AFDATA_CFG_WUNLOCK(ifp);
 #ifdef INET
 		/* gratuitous ARP */
 		if ((laflags & LLE_PUB) && dst->sa_family == AF_INET)
@@ -381,9 +402,9 @@ lla_rt_output(struct rt_msghdr *rtm, str
 		break;
 
 	case RTM_DELETE:
-		IF_AFDATA_WLOCK(ifp);
+		IF_AFDATA_CFG_WLOCK(ifp);
 		error = lla_delete(llt, 0, dst);
-		IF_AFDATA_WUNLOCK(ifp);
+		IF_AFDATA_CFG_WUNLOCK(ifp);
 		return (error == 0 ? 0 : ENOENT);
 
 	default:

Modified: projects/routing/sys/net/if_var.h
==============================================================================
--- projects/routing/sys/net/if_var.h	Sun Nov 23 12:15:28 2014	(r274916)
+++ projects/routing/sys/net/if_var.h	Sun Nov 23 15:38:06 2014	(r274917)
@@ -355,17 +355,26 @@ EVENTHANDLER_DECLARE(group_change_event,
 #define	IF_AFDATA_CFG_RUNLOCK(ifp)	if_afdata_cfg_runlock(ifp)
 #define	IF_AFDATA_CFG_WLOCK(ifp)	if_afdata_cfg_wlock(ifp)
 #define	IF_AFDATA_CFG_WUNLOCK(ifp)	if_afdata_cfg_wunlock(ifp)
+#define	IF_AFDATA_CFG_TRY_WLOCK(ifp)	if_afdata_cfg_try_wlock(ifp)
 
 #define	IF_AFDATA_CFG_LOCK_ASSERT(i)	if_afdata_cfg_lock_assert(i, RA_LOCKED)
 #define	IF_AFDATA_CFG_RLOCK_ASSERT(i)	if_afdata_cfg_lock_assert(i, RA_RLOCKED)
 #define	IF_AFDATA_CFG_WLOCK_ASSERT(i)	if_afdata_cfg_lock_assert(i, RA_WLOCKED)
 #define	IF_AFDATA_CFG_UNLOCK_ASSERT(i)	if_afdata_cfg_lock_assert(i,RA_UNLOCKED)
 
+#define	if_afdata_cfg_lock_assert(ifp, what)	\
+	rw_assert(&(ifp)->if_afdata_cfg_lock, what)
+
 void if_afdata_cfg_rlock(struct ifnet *ifp);
 void if_afdata_cfg_runlock(struct ifnet *ifp);
 void if_afdata_cfg_wlock(struct ifnet *ifp);
 void if_afdata_cfg_wunlock(struct ifnet *ifp);
-void if_afdata_cfg_lock_assert(struct ifnet *ifp, int what);
+int if_afdata_cfg_try_wlock(struct ifnet *ifp);
+
+/* Wrappers */
+#define	IF_AFDATA_RLOCK		IF_AFDATA_CFG_RLOCK
+#define	IF_AFDATA_RUNLOCK	IF_AFDATA_CFG_RUNLOCK
+
 
 /* if_afdata lock: fast path */
 #define	IF_AFDATA_RUN_WLOCK(ifp)	rm_wlock(&(ifp)->if_afdata_run_lock)
@@ -376,23 +385,8 @@ void if_afdata_cfg_lock_assert(struct if
 	rm_runlock(&(ifp)->if_afdata_run_lock, &if_afdata_tracker)
 #define	IF_AFDATA_RUN_TRACKER		struct rm_priotracker if_afdata_tracker
 
-/* Common wrappers */
-#define	IF_AFDATA_RLOCK(ifp)	IF_AFDATA_CFG_RLOCK(ifp)
-#define	IF_AFDATA_RUNLOCK(ifp)	IF_AFDATA_CFG_RUNLOCK(ifp)
-#define	IF_AFDATA_WLOCK(ifp)	if_afdata_wlock(ifp)
-#define	IF_AFDATA_WUNLOCK(ifp)	if_afdata_wunlock(ifp)
-
-#define	IF_AFDATA_TRY_WLOCK(ifp)	if_afdata_try_wlock(ifp)
-#define	IF_AFDATA_LOCK(ifp)	IF_AFDATA_WLOCK(ifp)
-#define	IF_AFDATA_UNLOCK(ifp)	IF_AFDATA_WUNLOCK(ifp)
-void if_afdata_wlock(struct ifnet *ifp);
-void if_afdata_wunlock(struct ifnet *ifp);
-int if_afdata_try_wlock(struct ifnet *ifp); 
-
-#define	IF_AFDATA_LOCK_ASSERT(ifp)	IF_AFDATA_CFG_LOCK_ASSERT(ifp)
-#define	IF_AFDATA_RLOCK_ASSERT(ifp)	IF_AFDATA_CFG_RLOCK_ASSERT(ifp)
-#define	IF_AFDATA_WLOCK_ASSERT(ifp)	IF_AFDATA_CFG_WLOCK_ASSERT(ifp)
-#define	IF_AFDATA_UNLOCK_ASSERT(ifp)	IF_AFDATA_CFG_UNLOCK_ASSERT(ifp)
+#define	IF_AFDATA_RUN_WLOCK_ASSERT(ifp)	\
+	rm_assert(&(ifp)->if_afdata_run_lock, RA_WLOCKED)
 
 /*
  * 72 was chosen below because it is the size of a TCP/IP

Modified: projects/routing/sys/net/rt_nhops.c
==============================================================================
--- projects/routing/sys/net/rt_nhops.c	Sun Nov 23 12:15:28 2014	(r274916)
+++ projects/routing/sys/net/rt_nhops.c	Sun Nov 23 15:38:06 2014	(r274917)
@@ -699,7 +699,7 @@ fib6_storelladdr(struct ifnet *ifp, stru
 	 * the entry should have been created in nd6_store_lladdr
 	 */
 	IF_AFDATA_RUN_RLOCK(ifp);
-	ln = lla_lookup(LLTABLE6(ifp), 0, (struct sockaddr *)&dst_sa);
+	ln = lla_lookup(LLTABLE6(ifp), LLE_UNLOCKED, (struct sockaddr *)&dst_sa);
 
 	/*
 	 * Perform fast path for the following cases:

Modified: projects/routing/sys/netinet/if_ether.c
==============================================================================
--- projects/routing/sys/netinet/if_ether.c	Sun Nov 23 12:15:28 2014	(r274916)
+++ projects/routing/sys/netinet/if_ether.c	Sun Nov 23 15:38:06 2014	(r274917)
@@ -164,9 +164,9 @@ arp_ifscrub(struct ifnet *ifp, uint32_t 
 	addr4.sin_len    = sizeof(addr4);
 	addr4.sin_family = AF_INET;
 	addr4.sin_addr.s_addr = addr;
-	IF_AFDATA_WLOCK(ifp);
+	IF_AFDATA_CFG_WLOCK(ifp);
 	lla_delete(LLTABLE(ifp), LLE_IFADDR, (struct sockaddr *)&addr4);
-	IF_AFDATA_WUNLOCK(ifp);
+	IF_AFDATA_CFG_WUNLOCK(ifp);
 }
 #endif
 
@@ -247,7 +247,7 @@ arptimer(void *arg)
 
 	/* XXX: LOR avoidance. We still have ref on lle. */
 	LLE_WUNLOCK(lle);
-	IF_AFDATA_LOCK(ifp);
+	IF_AFDATA_CFG_WLOCK(ifp);
 	LLE_WLOCK(lle);
 
 	/*
@@ -262,7 +262,7 @@ arptimer(void *arg)
 	pkts_dropped = llentry_free(lle);
 	ARPSTAT_ADD(dropped, pkts_dropped);
 
-	IF_AFDATA_UNLOCK(ifp);
+	IF_AFDATA_CFG_WUNLOCK(ifp);
 
 	ARPSTAT_INC(timeouts);
 
@@ -492,9 +492,14 @@ arpresolve_slow(struct ifnet *ifp, int i
 	IF_AFDATA_RUNLOCK(ifp);
 	if (la == NULL && (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0) {
 		create = 1;
-		IF_AFDATA_WLOCK(ifp);
+		IF_AFDATA_CFG_WLOCK(ifp);
 		la = lla_create(LLTABLE(ifp), 0, dst);
-		IF_AFDATA_WUNLOCK(ifp);
+		if (la != NULL) {
+			IF_AFDATA_RUN_WLOCK(ifp);
+			llentry_link(LLTABLE(ifp), la);
+			IF_AFDATA_RUN_WUNLOCK(ifp);
+		}
+		IF_AFDATA_CFG_WUNLOCK(ifp);
 	}
 	if (la == NULL) {
 		if (create != 0)
@@ -508,6 +513,7 @@ arpresolve_slow(struct ifnet *ifp, int i
 	if ((la->la_flags & LLE_VALID) &&
 	    ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) {
 		bcopy(&la->ll_addr, desten, ifp->if_addrlen);
+#if 0
 		/*
 		 * If entry has an expiry time and it is approaching,
 		 * see if we need to send an ARP request within this
@@ -518,7 +524,7 @@ arpresolve_slow(struct ifnet *ifp, int i
 			arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL);
 			la->la_preempt--;
 		}
-
+#endif
 		*lle = la;
 		error = 0;
 		goto done;
@@ -851,15 +857,15 @@ match:
 	sin.sin_addr = isaddr;
 	create = (itaddr.s_addr == myaddr.s_addr) ? 1 : 0;
 	flags = LLE_EXCLUSIVE;
-	IF_AFDATA_LOCK(ifp);
-	if (create != 0)
+	IF_AFDATA_CFG_WLOCK(ifp);
+	if (create != 0) {
 		la = lla_create(LLTABLE(ifp), 0, (struct sockaddr *)&sin);
-	else
+	} else
 		la = lla_lookup(LLTABLE(ifp), flags, (struct sockaddr *)&sin);
-	IF_AFDATA_UNLOCK(ifp);
+	IF_AFDATA_CFG_WUNLOCK(ifp);
 	if (la != NULL) {
 		/* the following is not an error when doing bridging */
-		if (!bridged && la->lle_tbl->llt_ifp != ifp) {
+		if (!bridged && la->lle_tbl && la->lle_tbl->llt_ifp != ifp) {
 			if (log_arp_wrong_iface)
 				ARP_LOG(LOG_WARNING, "%s is on %s "
 				    "but got reply from %*D on %s\n",
@@ -910,17 +916,20 @@ match:
 			/* use afdata WLOCK to update fields */
 			LLE_ADDREF(la);
 			LLE_WUNLOCK(la);
-			IF_AFDATA_WLOCK(ifp);
+			IF_AFDATA_CFG_WLOCK(ifp);
 			LLE_WLOCK(la);
 
 			/* Update data */
+			IF_AFDATA_RUN_WLOCK(ifp);
 			memcpy(&la->ll_addr, ar_sha(ah), ifp->if_addrlen);
 			la->la_flags |= LLE_VALID;
 			la->r_flags |= RLLE_VALID;
 			if ((la->la_flags & LLE_STATIC) == 0)
 				la->la_expire = time_uptime + V_arpt_keep;
+			llentry_link(LLTABLE(ifp), la);
+			IF_AFDATA_RUN_WUNLOCK(ifp);
 
-			IF_AFDATA_WUNLOCK(ifp);
+			IF_AFDATA_CFG_WUNLOCK(ifp);
 			LLE_REMREF(la);
 		}
 
@@ -1084,12 +1093,18 @@ arp_ifinit(struct ifnet *ifp, struct ifa
 		 * because the output of the arp utility shows
 		 * that L2 entry as permanent
 		 */
-		IF_AFDATA_LOCK(ifp);
+		IF_AFDATA_CFG_WLOCK(ifp);
 		lle = lla_create(LLTABLE(ifp), LLE_IFADDR | LLE_STATIC,
 				 (struct sockaddr *)IA_SIN(ifa));
-		if (lle != NULL)
+		if (lle != NULL) {
+			IF_AFDATA_RUN_WLOCK(ifp);
+			bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen);
+			lle->la_flags |= (LLE_VALID | LLE_STATIC);
 			lle->r_flags |= RLLE_VALID;
-		IF_AFDATA_UNLOCK(ifp);
+			llentry_link(LLTABLE(ifp), lle);
+			IF_AFDATA_RUN_WUNLOCK(ifp);
+		}
+		IF_AFDATA_CFG_WUNLOCK(ifp);
 		if (lle == NULL)
 			log(LOG_INFO, "arp_ifinit: cannot create arp "
 			    "entry for interface address\n");

Modified: projects/routing/sys/netinet/in.c
==============================================================================
--- projects/routing/sys/netinet/in.c	Sun Nov 23 12:15:28 2014	(r274916)
+++ projects/routing/sys/netinet/in.c	Sun Nov 23 15:38:06 2014	(r274917)
@@ -1050,7 +1050,7 @@ in_lltable_prefix_free(struct lltable *l
 	size_t pkts_dropped;
 
 	LIST_INIT(&dchain);
-	IF_AFDATA_WLOCK(llt->llt_ifp);
+	IF_AFDATA_CFG_WLOCK(llt->llt_ifp);
 	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
 		LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
 			/*
@@ -1070,12 +1070,14 @@ in_lltable_prefix_free(struct lltable *l
 		}
 	}
 	/* Unlink chain */
+	IF_AFDATA_RUN_WLOCK(llt->llt_ifp);
 	llentries_unlink(&dchain);
+	IF_AFDATA_RUN_WUNLOCK(llt->llt_ifp);
 	LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next) {
 		pkts_dropped = llentry_free(lle);
 		ARPSTAT_ADD(dropped, pkts_dropped);
 	}
-	IF_AFDATA_WUNLOCK(llt->llt_ifp);
+	IF_AFDATA_CFG_WUNLOCK(llt->llt_ifp);
 }
 
 
@@ -1159,7 +1161,7 @@ in_lltable_delete(struct lltable *llt, u
 	struct ifnet *ifp = llt->llt_ifp;
 	struct llentry *lle;
 
-	IF_AFDATA_WLOCK_ASSERT(ifp);
+	IF_AFDATA_CFG_WLOCK_ASSERT(ifp);
 	KASSERT(l3addr->sa_family == AF_INET,
 	    ("sin_family %d", l3addr->sa_family));
 
@@ -1175,7 +1177,9 @@ in_lltable_delete(struct lltable *llt, u
 		LLE_WLOCK(lle);
 		lle->la_flags |= LLE_DELETED;
 		EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_DELETED);
+		IF_AFDATA_RUN_WLOCK(ifp);
 		llentry_unlink(lle);
+		IF_AFDATA_RUN_WUNLOCK(ifp);
 #ifdef DIAGNOSTIC
 		log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle);
 #endif
@@ -1195,7 +1199,7 @@ in_lltable_create(struct lltable *llt, u
 	struct ifnet *ifp = llt->llt_ifp;
 	struct llentry *lle;
 
-	IF_AFDATA_WLOCK_ASSERT(ifp);
+	IF_AFDATA_CFG_WLOCK_ASSERT(ifp);
 	KASSERT(l3addr->sa_family == AF_INET,
 	    ("sin_family %d", l3addr->sa_family));
 
@@ -1223,12 +1227,6 @@ in_lltable_create(struct lltable *llt, u
 		return (NULL);
 	}
 	lle->la_flags = flags;
-	if ((flags & LLE_IFADDR) == LLE_IFADDR) {
-		bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen);
-		lle->la_flags |= (LLE_VALID | LLE_STATIC);
-	}
-
-	llentry_link(llt, lle);
 	LLE_WLOCK(lle);
 
 	return (lle);

Modified: projects/routing/sys/netinet/toecore.c
==============================================================================
--- projects/routing/sys/netinet/toecore.c	Sun Nov 23 12:15:28 2014	(r274916)
+++ projects/routing/sys/netinet/toecore.c	Sun Nov 23 15:38:06 2014	(r274917)
@@ -462,9 +462,9 @@ restart:
 	lle = lla_lookup(LLTABLE6(ifp), flags, sa);
 	IF_AFDATA_RUNLOCK(ifp);
 	if (lle == NULL) {
-		IF_AFDATA_LOCK(ifp);
+		IF_AFDATA_CFG_WLOCK(ifp);
 		lle = nd6_create(&sin6->sin6_addr, 0, ifp);
-		IF_AFDATA_UNLOCK(ifp);
+		IF_AFDATA_CFG_WUNLOCK(ifp);
 		if (lle == NULL)
 			return (ENOMEM); /* Couldn't create entry in cache. */
 		lle->ln_state = ND6_LLINFO_INCOMPLETE;

Modified: projects/routing/sys/netinet6/in6.c
==============================================================================
--- projects/routing/sys/netinet6/in6.c	Sun Nov 23 12:15:28 2014	(r274916)
+++ projects/routing/sys/netinet6/in6.c	Sun Nov 23 15:38:06 2014	(r274917)
@@ -72,6 +72,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/errno.h>
 #include <sys/jail.h>
 #include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/rmlock.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/sockio.h>
@@ -2100,7 +2102,7 @@ in6_lltable_prefix_free(struct lltable *
 	 * including static ND6 entries.
 	 */
 	LIST_INIT(&dchain);
-	IF_AFDATA_WLOCK(llt->llt_ifp);
+	IF_AFDATA_CFG_WLOCK(llt->llt_ifp);
 	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
 		LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
 			if (IN6_ARE_MASKED_ADDR_EQUAL(
@@ -2117,10 +2119,12 @@ in6_lltable_prefix_free(struct lltable *
 			}
 		}
 	}
+	IF_AFDATA_RUN_WLOCK(llt->llt_ifp);
 	llentries_unlink(&dchain);
+	IF_AFDATA_RUN_WUNLOCK(llt->llt_ifp);
 	LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next)
 		llentry_free(lle);
-	IF_AFDATA_WUNLOCK(llt->llt_ifp);
+	IF_AFDATA_CFG_WUNLOCK(llt->llt_ifp);
 }
 
 static int
@@ -2198,7 +2202,7 @@ in6_lltable_delete(struct lltable *llt, 
 	const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)l3addr;
 	struct llentry *lle;
 
-	IF_AFDATA_LOCK_ASSERT(llt->llt_ifp);
+	IF_AFDATA_CFG_WLOCK_ASSERT(llt->llt_ifp);
 	KASSERT(l3addr->sa_family == AF_INET6,
 	    ("sin_family %d", l3addr->sa_family));
 
@@ -2210,7 +2214,9 @@ in6_lltable_delete(struct lltable *llt, 
 	if (!(lle->la_flags & LLE_IFADDR) || (flags & LLE_IFADDR)) {
 		LLE_WLOCK(lle);
 		lle->la_flags |= LLE_DELETED;
+		IF_AFDATA_RUN_WLOCK(llt->llt_ifp);
 		llentry_unlink(lle);
+		IF_AFDATA_RUN_WUNLOCK(llt->llt_ifp);
 #ifdef DIAGNOSTIC
 		log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle);
 #endif
@@ -2231,7 +2237,7 @@ in6_lltable_create(struct lltable *llt, 
 	struct ifnet *ifp = llt->llt_ifp;
 	struct llentry *lle;
 
-	IF_AFDATA_WLOCK_ASSERT(ifp);
+	IF_AFDATA_CFG_WLOCK_ASSERT(ifp);
 	KASSERT(l3addr->sa_family == AF_INET6,
 	    ("sin_family %d", l3addr->sa_family));
 
@@ -2257,12 +2263,6 @@ in6_lltable_create(struct lltable *llt, 
 		return NULL;
 	}
 	lle->la_flags = flags;
-	if ((flags & LLE_IFADDR) == LLE_IFADDR) {
-		bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen);
-		lle->la_flags |= (LLE_VALID | LLE_STATIC);
-	}
-
-	llentry_link(llt, lle);
 	LLE_WLOCK(lle);
 
 	return (lle);
@@ -2290,7 +2290,7 @@ in6_lltable_lookup(struct lltable *llt, 
 
 	if (flags & LLE_EXCLUSIVE)
 		LLE_WLOCK(lle);
-	else
+	else if ((flags & LLE_UNLOCKED) == 0)
 		LLE_RLOCK(lle);
 	return (lle);
 }

Modified: projects/routing/sys/netinet6/nd6.c
==============================================================================
--- projects/routing/sys/netinet6/nd6.c	Sun Nov 23 12:15:28 2014	(r274916)
+++ projects/routing/sys/netinet6/nd6.c	Sun Nov 23 15:38:06 2014	(r274917)
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/syslog.h>
 #include <sys/lock.h>
 #include <sys/rwlock.h>
+#include <sys/rmlock.h>
 #include <sys/queue.h>
 #include <sys/sdt.h>
 #include <sys/sysctl.h>
@@ -854,7 +855,9 @@ nd6_lookup(struct in6_addr *addr6, int f
 	sin6.sin6_family = AF_INET6;
 	sin6.sin6_addr = *addr6;
 
-	IF_AFDATA_LOCK_ASSERT(ifp);
+	/*
+	 * IF_AFDATA_LOCK_ASSERT(ifp);
+	*/
 
 	llflags = (flags & ND6_EXCLUSIVE) ? LLE_EXCLUSIVE : 0;
 	ln = lla_lookup(LLTABLE6(ifp), llflags, (struct sockaddr *)&sin6);
@@ -877,11 +880,15 @@ nd6_create(struct in6_addr *addr6, int f
 	sin6.sin6_family = AF_INET6;
 	sin6.sin6_addr = *addr6;
 
-	IF_AFDATA_WLOCK_ASSERT(ifp);
+	IF_AFDATA_CFG_WLOCK_ASSERT(ifp);
 
 	ln = lla_create(LLTABLE6(ifp), 0, (struct sockaddr *)&sin6);
-	if (ln != NULL)
+	if (ln != NULL) {
+		IF_AFDATA_RUN_WLOCK(ifp);
 		ln->ln_state = ND6_LLINFO_NOSTATE;
+		llentry_link(LLTABLE6(ifp), ln);
+		IF_AFDATA_RUN_WUNLOCK(ifp);
+	}
 	
 	return (ln);
 }
@@ -998,7 +1005,7 @@ nd6_is_addr_neighbor(struct sockaddr_in6
 	struct llentry *lle;
 	int rc = 0;
 
-	IF_AFDATA_UNLOCK_ASSERT(ifp);
+	IF_AFDATA_CFG_UNLOCK_ASSERT(ifp);
 	if (nd6_is_new_addr_neighbor(addr, ifp))
 		return (1);
 
@@ -1137,7 +1144,7 @@ nd6_free(struct llentry *ln, int gc)
 	 * free(9) in llentry_free() if someone else holds one as well.
 	 */
 	LLE_WUNLOCK(ln);
-	IF_AFDATA_LOCK(ifp);
+	IF_AFDATA_CFG_WLOCK(ifp);
 	LLE_WLOCK(ln);
 
 	/*
@@ -1149,9 +1156,13 @@ nd6_free(struct llentry *ln, int gc)
 		ln->la_flags &= ~LLE_CALLOUTREF;
 	}
 
+	IF_AFDATA_RUN_WLOCK(ifp);
+	llentry_unlink(ln);
+	IF_AFDATA_RUN_WUNLOCK(ifp);
+
 	llentry_free(ln);
 
-	IF_AFDATA_UNLOCK(ifp);
+	IF_AFDATA_CFG_WUNLOCK(ifp);
 
 	return (next);
 }
@@ -1579,7 +1590,7 @@ nd6_cache_lladdr(struct ifnet *ifp, stru
 	struct mbuf *chain = NULL;
 	int static_route = 0;
 
-	IF_AFDATA_UNLOCK_ASSERT(ifp);
+	IF_AFDATA_CFG_UNLOCK_ASSERT(ifp);
 
 	KASSERT(ifp != NULL, ("%s: ifp == NULL", __func__));
 	KASSERT(from != NULL, ("%s: from == NULL", __func__));
@@ -1598,14 +1609,14 @@ nd6_cache_lladdr(struct ifnet *ifp, stru
 	 * description on it in NS section (RFC 2461 7.2.3).
 	 */
 	flags = lladdr ? ND6_EXCLUSIVE : 0;
-	IF_AFDATA_RLOCK(ifp);
+	IF_AFDATA_CFG_RLOCK(ifp);
 	ln = nd6_lookup(from, flags, ifp);
-	IF_AFDATA_RUNLOCK(ifp);
+	IF_AFDATA_CFG_RUNLOCK(ifp);
 	if (ln == NULL) {
 		flags |= ND6_EXCLUSIVE;
-		IF_AFDATA_LOCK(ifp);
+		IF_AFDATA_CFG_WLOCK(ifp);
 		ln = nd6_create(from, 0, ifp);
-		IF_AFDATA_UNLOCK(ifp);
+		IF_AFDATA_CFG_WUNLOCK(ifp);
 		is_newentry = 1;
 	} else {
 		/* do nothing if static ndp is set */
@@ -2004,9 +2015,9 @@ nd6_output_lle(struct ifnet *ifp, struct
 			 * the condition below is not very efficient.  But we believe
 			 * it is tolerable, because this should be a rare case.
 			 */
-			IF_AFDATA_LOCK(ifp);
+			IF_AFDATA_CFG_WLOCK(ifp);
 			lle = nd6_create(&dst->sin6_addr, 0, ifp);
-			IF_AFDATA_UNLOCK(ifp);
+			IF_AFDATA_CFG_WUNLOCK(ifp);
 		}
 	} 
 	if (lle == NULL) {
@@ -2257,14 +2268,23 @@ nd6_add_ifa_lle(struct in6_ifaddr *ia)
 	struct llentry *ln;
 
 	ifp = ia->ia_ifa.ifa_ifp;
-	IF_AFDATA_LOCK(ifp);
-	ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
+	IF_AFDATA_CFG_WLOCK(ifp);
 	ln = lla_create(LLTABLE6(ifp), LLE_IFADDR,
 	    (struct sockaddr *)&ia->ia_addr);
-	IF_AFDATA_UNLOCK(ifp);
 	if (ln != NULL) {
+		IF_AFDATA_RUN_WLOCK(ifp);
+		bcopy(IF_LLADDR(ifp), &ln->ll_addr, ifp->if_addrlen);
+		ln->la_flags |= (LLE_VALID | LLE_STATIC);
+		ln->r_flags |= RLLE_VALID;
 		ln->la_expire = 0;  /* for IPv6 this means permanent */
 		ln->ln_state = ND6_LLINFO_REACHABLE;
+		llentry_link(LLTABLE6(ifp), ln);
+		IF_AFDATA_RUN_WUNLOCK(ifp);
+	}
+
+	ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
+	IF_AFDATA_CFG_WUNLOCK(ifp);
+	if (ln != NULL) {
 		LLE_WUNLOCK(ln);
 		in6_newaddrmsg(ia, RTM_ADD);
 		return (0);
@@ -2306,7 +2326,7 @@ nd6_storelladdr(struct ifnet *ifp, struc
 	struct llentry *ln;
 
 	*lle = NULL;
-	IF_AFDATA_UNLOCK_ASSERT(ifp);
+	IF_AFDATA_CFG_UNLOCK_ASSERT(ifp);
 	if (m != NULL && m->m_flags & M_MCAST) {
 		int i;
 

Modified: projects/routing/sys/netinet6/scope6.c
==============================================================================
--- projects/routing/sys/netinet6/scope6.c	Sun Nov 23 12:15:28 2014	(r274916)
+++ projects/routing/sys/netinet6/scope6.c	Sun Nov 23 15:38:06 2014	(r274917)
@@ -148,11 +148,11 @@ scope6_set(struct ifnet *ifp, struct sco
 	int error = 0;
 	struct scope6_id *sid = NULL;
 
-	IF_AFDATA_WLOCK(ifp);
+	IF_AFDATA_CFG_WLOCK(ifp);
 	sid = SID(ifp);
 
 	if (!sid) {	/* paranoid? */
-		IF_AFDATA_WUNLOCK(ifp);
+		IF_AFDATA_CFG_WUNLOCK(ifp);
 		return (EINVAL);
 	}
 
@@ -175,7 +175,7 @@ scope6_set(struct ifnet *ifp, struct sco
 			 */
 			if (i == IPV6_ADDR_SCOPE_INTFACELOCAL &&
 			    idlist->s6id_list[i] != ifp->if_index) {
-				IF_AFDATA_WUNLOCK(ifp);
+				IF_AFDATA_CFG_WUNLOCK(ifp);
 				return (EINVAL);
 			}
 
@@ -187,7 +187,7 @@ scope6_set(struct ifnet *ifp, struct sco
 				 * IDs, but we check the consistency for
 				 * safety in later use.
 				 */
-				IF_AFDATA_WUNLOCK(ifp);
+				IF_AFDATA_CFG_WUNLOCK(ifp);
 				return (EINVAL);
 			}
 
@@ -196,10 +196,11 @@ scope6_set(struct ifnet *ifp, struct sco
 			 * but we simply set the new value in this initial
 			 * implementation.
 			 */
+			/* XXX: Use runtime lock? */
 			sid->s6id_list[i] = idlist->s6id_list[i];
 		}
 	}
-	IF_AFDATA_WUNLOCK(ifp);
+	IF_AFDATA_CFG_WUNLOCK(ifp);
 
 	return (error);
 }



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