http://www.holm.cc/stress/log/cons141.html

Gleb Smirnoff glebius at FreeBSD.org
Thu Jul 14 11:11:50 GMT 2005


On Thu, Jul 14, 2005 at 03:10:43PM +0400, Gleb Smirnoff wrote:
T> The attached WIP patch

The attached patch was not attached. Here it is.

-- 
Totus tuus, Glebius.
GLEBIUS-RIPN GLEB-RIPE
-------------- next part --------------
Index: net/route.c
===================================================================
RCS file: /home/ncvs/src/sys/net/route.c,v
retrieving revision 1.109
diff -u -r1.109 route.c
--- net/route.c	28 Jun 2005 23:32:22 -0000	1.109
+++ net/route.c	14 Jul 2005 09:42:00 -0000
@@ -1255,7 +1255,8 @@
  * Their values are meaningful ONLY if no error is returned.
  */
 int
-rt_check(struct rtentry **lrt, struct rtentry **lrt0, struct sockaddr *dst)
+rt_check0(struct rtentry **lrt, struct rtentry **lrt0, struct sockaddr *dst,
+   int locked)
 {
 #define senderr(x) { error = x ; goto bad; }
 	struct rtentry *rt;
@@ -1302,11 +1303,14 @@
 		error = (rt->rt_flags & RTF_REJECT) &&
 			(rt->rt_rmx.rmx_expire == 0 ||
 				time_second < rt->rt_rmx.rmx_expire);
-		RT_UNLOCK(rt);
-		if (error)
+		if (error) {
+			RT_UNLOCK(rt);
 			senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
+		}
+		if (locked == 0)
+			RT_UNLOCK(rt);
 	}
-	*lrt = rt;		/* NB: return unlocked */
+	*lrt = rt;		/* NB: return unlocked, if locked is 0 */
 	*lrt0 = rt0;
 	return (0);
 bad:
@@ -1315,5 +1319,11 @@
 #undef senderr
 }
 
+int
+rt_check(struct rtentry **lrt, struct rtentry **lrt0, struct sockaddr *dst)
+{
+	return rt_check0(lrt, lrt0, dst, 0);
+}
+
 /* This must be before ip6_init2(), which is now SI_ORDER_MIDDLE */
 SYSINIT(route, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, route_init, 0);
Index: net/route.h
===================================================================
RCS file: /home/ncvs/src/sys/net/route.h,v
retrieving revision 1.63
diff -u -r1.63 route.h
--- net/route.h	7 Jan 2005 01:45:35 -0000	1.63
+++ net/route.h	14 Jul 2005 09:38:48 -0000
@@ -353,6 +353,8 @@
 	    struct sockaddr *, struct sockaddr *, int, struct rtentry **);
 int	 rtrequest1(int, struct rt_addrinfo *, struct rtentry **);
 int	 rt_check(struct rtentry **, struct rtentry **, struct sockaddr *);
+int	 rt_check0(struct rtentry **, struct rtentry **, struct sockaddr *,
+	    int);
 #endif
 
 #endif
Index: netinet/if_ether.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/if_ether.c,v
retrieving revision 1.137
diff -u -r1.137 if_ether.c
--- netinet/if_ether.c	5 Jun 2005 03:13:12 -0000	1.137
+++ netinet/if_ether.c	14 Jul 2005 10:51:23 -0000
@@ -125,7 +125,7 @@
 static void	arpintr(struct mbuf *);
 static void	arptfree(struct llinfo_arp *);
 static void	arptimer(void *);
-static struct llinfo_arp
+static struct rtentry
 		*arplookup(u_long, int, int);
 #ifdef INET
 static void	in_arpinput(struct mbuf *);
@@ -369,33 +369,41 @@
 	struct llinfo_arp *la = 0;
 	struct sockaddr_dl *sdl;
 	int error;
-	struct rtentry *rt;
+	struct rtentry *rt = NULL;
 
-	error = rt_check(&rt, &rt0, dst);
+	error = rt_check0(&rt, &rt0, dst, 1);
 	if (error) {
 		m_freem(m);
 		return error;
 	}
+	KASSERT(rt != NULL, ("arpresolve: must not happen"));
 
 	if (m->m_flags & M_BCAST) {	/* broadcast */
+		RT_UNLOCK(rt);
 		(void)memcpy(desten, ifp->if_broadcastaddr, ifp->if_addrlen);
 		return (0);
 	}
 	if (m->m_flags & M_MCAST && ifp->if_type != IFT_ARCNET) {/* multicast */
+		RT_UNLOCK(rt);
 		ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten);
 		return (0);
 	}
-	if (rt)
+	if ((la = (struct llinfo_arp *)rt->rt_llinfo) == NULL) {
+		RT_UNLOCK(rt);
+		rt = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0);
+		if (rt == NULL) {
+			log(LOG_DEBUG,
+			    "arpresolve: can't allocate route for %s\n",
+			    inet_ntoa(SIN(dst)->sin_addr));
+			m_freem(m);
+			return (EINVAL); /* XXX */
+		}
 		la = (struct llinfo_arp *)rt->rt_llinfo;
-	if (la == 0) {
-		la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0);
-		if (la)
-			rt = la->la_rt;
-	}
-	if (la == 0 || rt == 0) {
-		log(LOG_DEBUG, "arpresolve: can't allocate llinfo for %s%s%s\n",
-			inet_ntoa(SIN(dst)->sin_addr), la ? "la" : "",
-				rt ? "rt" : "");
+	}
+	if (la == NULL) {
+		RT_UNLOCK(rt);
+		log(LOG_DEBUG, "arpresolve: can't allocate llinfo for %s\n",
+		    inet_ntoa(SIN(dst)->sin_addr));
 		m_freem(m);
 		return (EINVAL); /* XXX */
 	}
@@ -419,7 +427,7 @@
 				   IF_LLADDR(ifp));
 			la->la_preempt--;
 		} 
-
+		RT_UNLOCK(rt);
 		bcopy(LLADDR(sdl), desten, sdl->sdl_alen);
 		return (0);
 	}
@@ -430,6 +438,7 @@
 	 * not going to be sending out an arp request.
 	 */
 	if (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) {
+		RT_UNLOCK(rt);
 		m_freem(m);
 		return (EINVAL);
 	}
@@ -442,7 +451,6 @@
 		m_freem(la->la_hold);
 	la->la_hold = m;
 	if (rt->rt_expire) {
-		RT_LOCK(rt);
 		rt->rt_flags &= ~RTF_REJECT;
 		if (la->la_asked == 0 || rt->rt_expire != time_second) {
 			rt->rt_expire = time_second;
@@ -459,8 +467,8 @@
 			}
 
 		}
-		RT_UNLOCK(rt);
 	}
+	RT_UNLOCK(rt);
 	return (EWOULDBLOCK);
 }
 
@@ -543,7 +551,7 @@
 	struct ifnet *ifp = m->m_pkthdr.rcvif;
 	struct iso88025_header *th = (struct iso88025_header *)0;
 	struct iso88025_sockaddr_dl_data *trld;
-	struct llinfo_arp *la = 0;
+	struct llinfo_arp *la = NULL;
 	struct rtentry *rt;
 	struct ifaddr *ifa;
 	struct in_ifaddr *ia;
@@ -640,8 +648,12 @@
 	}
 	if (ifp->if_flags & IFF_STATICARP)
 		goto reply;
-	la = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0);
-	if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) {
+	rt = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0);
+	if (rt != NULL)
+		la = (struct llinfo_arp *)rt->rt_llinfo;
+	if (la && (sdl = SDL(rt->rt_gateway))) {
+		struct mbuf *hold;
+
 		/* the following is not an error when doing bridging */
 		if (!bridged && rt->rt_ifp != ifp
 #ifdef DEV_CARP
@@ -654,6 +666,7 @@
 				    rt->rt_ifp->if_xname,
 				    ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
 				    ifp->if_xname);
+			RT_UNLOCK(rt);
 			goto reply;
 		}
 		if (sdl->sdl_alen &&
@@ -670,6 +683,7 @@
 				"arp: %*D attempts to modify permanent entry for %s on %s\n",
 				ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
 				inet_ntoa(isaddr), ifp->if_xname);
+			    RT_UNLOCK(rt);
 			    goto reply;
 			}
 		}
@@ -690,6 +704,7 @@
 			    "arp from %*D: addr len: new %d, i/f %d (ignored)",
 			    ifp->if_addrlen, (u_char *) ar_sha(ah), ":",
 			    ah->ar_hln, ifp->if_addrlen);
+			RT_UNLOCK(rt);
 			goto reply;
 		}
 		(void)memcpy(LLADDR(sdl), ar_sha(ah),
@@ -725,17 +740,16 @@
 			m->m_pkthdr.len += 8;
 			th->rcf = trld->trld_rcf;
 		}
-		RT_LOCK(rt);
 		if (rt->rt_expire)
 			rt->rt_expire = time_second + arpt_keep;
 		rt->rt_flags &= ~RTF_REJECT;
-		RT_UNLOCK(rt);
 		la->la_asked = 0;
 		la->la_preempt = arp_maxtries;
-		if (la->la_hold) {
-			(*ifp->if_output)(ifp, la->la_hold, rt_key(rt), rt);
-			la->la_hold = 0;
-		}
+		hold = la->la_hold;
+		la->la_hold = NULL;
+		RT_UNLOCK(rt);
+		if (hold)
+			(*ifp->if_output)(ifp, hold, rt_key(rt), rt);
 	}
 reply:
 	if (op != ARPOP_REQUEST)
@@ -745,8 +759,8 @@
 		(void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
 		(void)memcpy(ar_sha(ah), enaddr, ah->ar_hln);
 	} else {
-		la = arplookup(itaddr.s_addr, 0, SIN_PROXY);
-		if (la == NULL) {
+		rt = arplookup(itaddr.s_addr, 0, SIN_PROXY);
+		if (rt == NULL) {
 			struct sockaddr_in sin;
 
 			if (!arp_proxyall)
@@ -799,9 +813,9 @@
 			       inet_ntoa(itaddr));
 #endif
 		} else {
-			rt = la->la_rt;
-			(void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
 			sdl = SDL(rt->rt_gateway);
+			RT_UNLOCK(rt);
+			(void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
 			(void)memcpy(ar_sha(ah), LLADDR(sdl), ah->ar_hln);
 		}
 	}
@@ -850,7 +864,7 @@
 /*
  * Lookup or enter a new address in arptab.
  */
-static struct llinfo_arp *
+static struct rtentry *
 arplookup(addr, create, proxy)
 	u_long addr;
 	int create, proxy;
@@ -895,8 +909,7 @@
 #undef ISDYNCLONE
 	} else {
 		RT_REMREF(rt);
-		RT_UNLOCK(rt);
-		return ((struct llinfo_arp *)rt->rt_llinfo);
+		return (rt);
 	}
 }
 


More information about the freebsd-current mailing list