svn commit: r185815 - in user/kmacy/head_arpv2/sys: netinet netinet6

Kip Macy kmacy at FreeBSD.org
Tue Dec 9 16:54:22 PST 2008


Author: kmacy
Date: Wed Dec 10 00:54:21 2008
New Revision: 185815
URL: http://svn.freebsd.org/changeset/base/185815

Log:
  - add missed radix node head lock acquisition when calling
  - only acquire llentry lock exclusively when lookup fails
  - fix lle lookup

Modified:
  user/kmacy/head_arpv2/sys/netinet/if_ether.c
  user/kmacy/head_arpv2/sys/netinet/in.c
  user/kmacy/head_arpv2/sys/netinet6/nd6_rtr.c

Modified: user/kmacy/head_arpv2/sys/netinet/if_ether.c
==============================================================================
--- user/kmacy/head_arpv2/sys/netinet/if_ether.c	Wed Dec 10 00:08:25 2008	(r185814)
+++ user/kmacy/head_arpv2/sys/netinet/if_ether.c	Wed Dec 10 00:54:21 2008	(r185815)
@@ -256,7 +256,7 @@ arpresolve(struct ifnet *ifp, struct rte
 	INIT_VNET_INET(ifp->if_vnet);
 	struct llentry *la = 0;
 	u_int flags;
-	int error;
+	int error, renew;
 
 	log(LOG_DEBUG, "arpesolve called\n");
 	*lle = NULL;
@@ -275,12 +275,12 @@ arpresolve(struct ifnet *ifp, struct rte
 	}
 
 	flags = (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) ? 0 : LLE_CREATE;
-	flags |= (m ? LLE_EXCLUSIVE : 0);
 
 	/* XXXXX
 	 * Since this function returns an llentry, the 
 	 * lock is held by the caller.
 	 */
+retry:
 	la = lla_lookup(LLTABLE(ifp), flags, dst);
 	if (la == NULL) {
 		if (flags & LLE_CREATE)
@@ -325,17 +325,27 @@ arpresolve(struct ifnet *ifp, struct rte
 		error = EINVAL;
 		goto done;
 	}
+
+	renew = (la->la_asked == 0 || la->la_expire != time_uptime);
 	/*
 	 * There is an arptab entry, but no ethernet address
 	 * response yet.  Replace the held mbuf with this
 	 * latest one.
 	 */
 	if (m) {
+		if ((flags & LLE_EXCLUSIVE) == 0) {
+			flags |= LLE_EXCLUSIVE;
+			LLE_RUNLOCK(la);
+			goto retry;
+		}
 		if (la->la_hold)
 			m_freem(la->la_hold);
 		la->la_hold = m;
-		if (!(la->la_asked == 0 || la->la_expire != time_uptime))
+		if (renew == 0) {
+			flags &= ~LLE_EXCLUSIVE;
 			LLE_DOWNGRADE(la);
+		}
+		
 	}
 	/*
 	 * Return EWOULDBLOCK if we have tried less than arp_maxtries. It
@@ -349,7 +359,7 @@ arpresolve(struct ifnet *ifp, struct rte
 		error =
 		    (rt0->rt_flags & RTF_GATEWAY) ? EHOSTDOWN : EHOSTUNREACH;
 
-	if (la->la_asked == 0 || la->la_expire != time_uptime) {
+	if (renew) {
 		log(LOG_DEBUG,
 		    "arpresolve: kicking off new resolve expire=%ld\n",
 			la->la_expire);
@@ -364,7 +374,10 @@ arpresolve(struct ifnet *ifp, struct rte
 	}
 
 done:
-	LLE_RUNLOCK(la);
+	if (flags & LLE_EXCLUSIVE)
+		LLE_WUNLOCK(la);
+	else
+		LLE_RUNLOCK(la);
 	return (error);
 }
 

Modified: user/kmacy/head_arpv2/sys/netinet/in.c
==============================================================================
--- user/kmacy/head_arpv2/sys/netinet/in.c	Wed Dec 10 00:08:25 2008	(r185814)
+++ user/kmacy/head_arpv2/sys/netinet/in.c	Wed Dec 10 00:54:21 2008	(r185815)
@@ -1109,16 +1109,7 @@ in_lltable_lookup(struct lltable *llt, u
 		if (bcmp(L3_ADDR(lle), l3addr, sizeof(struct sockaddr_in)) == 0)
 			break;
 	}
-
-	if ((lle != NULL) && (flags & LLE_DELETE)) {
-		LLE_WLOCK(lle);
-		lle->la_flags = LLE_DELETED;
-		LLE_WUNLOCK(lle);
-#ifdef INVARIANTS
-		log(LOG_INFO, "ifaddr cache = %p  is deleted\n", lle);	
-#endif
-		lle = NULL;
-	} else {
+	if (lle == NULL) {
 #ifdef INVARIANTS
 		if (flags & LLE_DELETE)
 			log(LOG_INFO, "interface address is missing from cache = %p  in delete\n", lle);	
@@ -1148,7 +1139,15 @@ in_lltable_lookup(struct lltable *llt, u
 		lle->lle_tbl  = llt;
 		lle->lle_head = lleh;
 		LIST_INSERT_HEAD(lleh, lle, lle_next);
-	} 
+	} else if (flags & LLE_DELETE) {
+		LLE_WLOCK(lle);
+		lle->la_flags = LLE_DELETED;
+		LLE_WUNLOCK(lle);
+#ifdef INVARIANTS
+		log(LOG_INFO, "ifaddr cache = %p  is deleted\n", lle);	
+#endif
+		lle = NULL;
+	}
 	if (lle) {
 		if (flags & LLE_EXCLUSIVE)
 			LLE_WLOCK(lle);

Modified: user/kmacy/head_arpv2/sys/netinet6/nd6_rtr.c
==============================================================================
--- user/kmacy/head_arpv2/sys/netinet6/nd6_rtr.c	Wed Dec 10 00:08:25 2008	(r185814)
+++ user/kmacy/head_arpv2/sys/netinet6/nd6_rtr.c	Wed Dec 10 00:54:21 2008	(r185815)
@@ -476,10 +476,8 @@ defrouter_addreq(struct nd_defrouter *ne
 	    (struct sockaddr *)&gate, (struct sockaddr *)&mask,
 	    RTF_GATEWAY, &newrt);
 	if (newrt) {
-		RT_LOCK(newrt);
 		nd6_rtmsg(RTM_ADD, newrt); /* tell user process */
-		RT_REMREF(newrt);
-		RT_UNLOCK(newrt);
+		RTFREE(newrt);
 	}
 	if (error == 0)
 		new->installed = 1;
@@ -1549,6 +1547,7 @@ nd6_prefix_onlink(struct nd_prefix *pr)
 	struct nd_prefix *opr;
 	u_long rtflags;
 	int error = 0;
+	struct radix_node_head *rnh;
 	struct rtentry *rt = NULL;
 	char ip6buf[INET6_ADDRSTRLEN];
 	struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
@@ -1632,6 +1631,8 @@ nd6_prefix_onlink(struct nd_prefix *pr)
 	    ifa->ifa_addr, (struct sockaddr *)&mask6, rtflags, &rt);
 	if (error == 0) {
 		if (rt != NULL) /* this should be non NULL, though */ {
+			rnh = V_rt_tables[rt->rt_fibnum][AF_INET6];
+			RADIX_NODE_HEAD_LOCK(rnh);
 			RT_LOCK(rt);
 			if (!rt_setgate(rt, rt_key(rt), (struct sockaddr *)&null_sdl)) {
 				((struct sockaddr_dl *)rt->rt_gateway)->sdl_type =
@@ -1639,6 +1640,7 @@ nd6_prefix_onlink(struct nd_prefix *pr)
 				((struct sockaddr_dl *)rt->rt_gateway)->sdl_index =
 					rt->rt_ifp->if_index;
 			}
+			RADIX_NODE_HEAD_UNLOCK(rnh);
 			nd6_rtmsg(RTM_ADD, rt);
 			RT_UNLOCK(rt);
 		}


More information about the svn-src-user mailing list