svn commit: r274554 - projects/routing/sys/netinet
Alexander V. Chernikov
melifaro at FreeBSD.org
Sat Nov 15 20:02:23 UTC 2014
Author: melifaro
Date: Sat Nov 15 20:02:22 2014
New Revision: 274554
URL: https://svnweb.freebsd.org/changeset/base/274554
Log:
Move "slow path" handling from arpresolve() to newly-created
arpresolve_slow().
Modified:
projects/routing/sys/netinet/if_ether.c
Modified: projects/routing/sys/netinet/if_ether.c
==============================================================================
--- projects/routing/sys/netinet/if_ether.c Sat Nov 15 18:54:07 2014 (r274553)
+++ projects/routing/sys/netinet/if_ether.c Sat Nov 15 20:02:22 2014 (r274554)
@@ -130,6 +130,8 @@ static void arptimer(void *);
#ifdef INET
static void in_arpinput(struct mbuf *);
#endif
+static int arpresolve_slow(struct ifnet *, int is_gw, struct mbuf *,
+ const struct sockaddr *, u_char *, struct llentry **);
static const struct netisr_handler arp_nh = {
.nh_name = "arp",
@@ -368,13 +370,10 @@ int
arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
const struct sockaddr *dst, u_char *desten, struct llentry **lle)
{
- struct llentry *la = 0;
- u_int flags = 0;
- struct mbuf *curr = NULL;
- struct mbuf *next = NULL;
- int create, error, renew;
+ struct llentry *la = NULL;
+ int is_gw;
+ uint16_t la_flags;
- create = 0;
*lle = NULL;
if (m != NULL) {
if (m->m_flags & M_BCAST) {
@@ -389,16 +388,61 @@ arpresolve(struct ifnet *ifp, struct rte
return (0);
}
}
-retry:
+
+ IF_AFDATA_RLOCK(ifp);
+ la = lla_lookup(LLTABLE(ifp), 0, dst);
+ IF_AFDATA_RUNLOCK(ifp);
+ la_flags = la != NULL ? la->la_flags : 0;
+
+ /* Return to slow path if entry is not found or invalid/expired */
+ if (la == NULL || (la_flags & LLE_VALID) == 0 ||
+ ((la_flags & LLE_STATIC) == 0 && la->la_expire <= time_uptime)) {
+ is_gw = (rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY)) ? 1 : 0;
+ if (la != NULL)
+ LLE_RUNLOCK(la);
+ return (arpresolve_slow(ifp, is_gw, m, dst, desten, lle));
+ }
+
+
+ /* Entry found, let's copy lle info */
+ bcopy(&la->ll_addr, desten, ifp->if_addrlen);
+
+ /*
+ * If entry has an expiry time and it is approaching,
+ * see if we need to send an ARP request within this
+ * arpt_down interval.
+ */
+ if (!(la->la_flags & LLE_STATIC) &&
+ time_uptime + la->la_preempt > la->la_expire) {
+ arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL);
+ la->la_preempt--;
+ }
+
+ /* XXX: Possible use-after-free */
+ *lle = la;
+ LLE_RUNLOCK(la);
+ return (0);
+}
+
+static int
+arpresolve_slow(struct ifnet *ifp, int is_gw, struct mbuf *m,
+ const struct sockaddr *dst, u_char *desten, struct llentry **lle)
+{
+ struct llentry *la = 0;
+ struct mbuf *curr = NULL;
+ struct mbuf *next = NULL;
+ int create, error, renew;
+
+ create = 0;
+ *lle = NULL;
+
IF_AFDATA_RLOCK(ifp);
- la = lla_lookup(LLTABLE(ifp), flags, dst);
+ la = lla_lookup(LLTABLE(ifp), LLE_EXCLUSIVE, dst);
IF_AFDATA_RUNLOCK(ifp);
- if ((la == NULL) && ((flags & LLE_EXCLUSIVE) == 0)
- && ((ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0)) {
+ if (la == NULL && (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0) {
create = 1;
- flags |= LLE_EXCLUSIVE;
IF_AFDATA_WLOCK(ifp);
- la = lla_create(LLTABLE(ifp), flags, dst);
+ la = lla_create(LLTABLE(ifp), 0, dst);
IF_AFDATA_WUNLOCK(ifp);
}
if (la == NULL) {
@@ -438,11 +482,6 @@ retry:
}
renew = (la->la_asked == 0 || la->la_expire != time_uptime);
- if ((renew || m != NULL) && (flags & LLE_EXCLUSIVE) == 0) {
- flags |= LLE_EXCLUSIVE;
- LLE_RUNLOCK(la);
- goto retry;
- }
/*
* There is an arptab entry, but no ethernet address
* response yet. Add the mbuf to the list, dropping
@@ -467,11 +506,6 @@ retry:
} else
la->la_hold = m;
la->la_numheld++;
- if (renew == 0 && (flags & LLE_EXCLUSIVE)) {
- flags &= ~LLE_EXCLUSIVE;
- LLE_DOWNGRADE(la);
- }
-
}
/*
* Return EWOULDBLOCK if we have tried less than arp_maxtries. It
@@ -482,8 +516,7 @@ retry:
if (la->la_asked < V_arp_maxtries)
error = EWOULDBLOCK; /* First request. */
else
- error = rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY) ?
- EHOSTUNREACH : EHOSTDOWN;
+ error = (is_gw != 0) ? EHOSTUNREACH : EHOSTDOWN;
if (renew) {
int canceled;
@@ -500,10 +533,7 @@ retry:
return (error);
}
done:
- if (flags & LLE_EXCLUSIVE)
- LLE_WUNLOCK(la);
- else
- LLE_RUNLOCK(la);
+ LLE_WUNLOCK(la);
return (error);
}
More information about the svn-src-projects
mailing list