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