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