summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authorjulian <julian@FreeBSD.org>2007-12-31 23:48:06 +0000
committerjulian <julian@FreeBSD.org>2007-12-31 23:48:06 +0000
commit3032c5c97143e8c0b92bae65601cbb7f7c746699 (patch)
treecafc9402b17d1ecb4bfcf6e0b22f4480ebac9217 /sys/netinet
parent9cea85864d49868ad2155b6f59d9ebd33a998a3f (diff)
downloadFreeBSD-src-3032c5c97143e8c0b92bae65601cbb7f7c746699.zip
FreeBSD-src-3032c5c97143e8c0b92bae65601cbb7f7c746699.tar.gz
Don't duplicate the whole of arpresolve to arpresolve 2 for the sake
of two compares against 0. The negative effect of cache flushing is probably more than the gain by not doing the two compares (the value is almost certainly in register or at worst, cache). Note that the uses of m_freem() are in error cases and m_freem() handles NULL anyhow. So fast-path really isn't changed much at all.
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/if_ether.c139
-rw-r--r--sys/netinet/if_ether.h2
2 files changed, 19 insertions, 122 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index f6c5c12..b1133c9 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -344,14 +344,15 @@ arprequest(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip,
* Resolve an IP address into an ethernet address.
* On input:
* ifp is the interface we use
- * dst is the next hop,
* rt0 is the route to the final destination (possibly useless)
- * m is the mbuf
+ * m is the mbuf. May be NULL if we don't have a packet.
+ * dst is the next hop,
* desten is where we want the address.
*
* On success, desten is filled in and the function returns 0;
* If the packet must be held pending resolution, we return EWOULDBLOCK
* On other errors, we return the corresponding error code.
+ * Note that m_freem() handles NULL.
*/
int
arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
@@ -362,13 +363,18 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
struct sockaddr_dl *sdl;
int error;
- if (m->m_flags & M_BCAST) { /* broadcast */
- (void)memcpy(desten, ifp->if_broadcastaddr, ifp->if_addrlen);
- return (0);
- }
- if (m->m_flags & M_MCAST && ifp->if_type != IFT_ARCNET) {/* multicast */
- ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten);
- return (0);
+ if (m) {
+ if (m->m_flags & M_BCAST) {
+ /* broadcast */
+ (void)memcpy(desten,
+ ifp->if_broadcastaddr, ifp->if_addrlen);
+ return (0);
+ }
+ if (m->m_flags & M_MCAST && ifp->if_type != IFT_ARCNET) {
+ /* multicast */
+ ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten);
+ return (0);
+ }
}
if (rt0 != NULL) {
@@ -449,117 +455,10 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
* response yet. Replace the held mbuf with this
* latest one.
*/
- if (la->la_hold)
- m_freem(la->la_hold);
- la->la_hold = m;
- KASSERT(rt->rt_expire > 0, ("sending ARP request for static entry"));
-
- /*
- * Return EWOULDBLOCK if we have tried less than arp_maxtries. It
- * will be masked by ether_output(). Return EHOSTDOWN/EHOSTUNREACH
- * if we have already sent arp_maxtries ARP requests. Retransmit the
- * ARP request, but not faster than one request per second.
- */
- if (la->la_asked < arp_maxtries)
- error = EWOULDBLOCK; /* First request. */
- else
- error = (rt == rt0) ? EHOSTDOWN : EHOSTUNREACH;
-
- if (la->la_asked == 0 || rt->rt_expire != time_uptime) {
- struct in_addr sin =
- SIN(rt->rt_ifa->ifa_addr)->sin_addr;
-
- rt->rt_expire = time_uptime;
- callout_reset(&la->la_timer, hz, arptimer, rt);
- la->la_asked++;
- RT_UNLOCK(rt);
-
- arprequest(ifp, &sin, &SIN(dst)->sin_addr,
- IF_LLADDR(ifp));
- } else
- RT_UNLOCK(rt);
-
- return (error);
-}
-
-
-int
-arpresolve2(struct ifnet *ifp, struct rtentry *rt0, struct sockaddr *dst,
- u_char *desten)
-{
- struct llinfo_arp *la = NULL;
- struct rtentry *rt = NULL;
- struct sockaddr_dl *sdl;
- int error;
-
- if (rt0 != NULL) {
- error = rt_check(&rt, &rt0, dst);
- if (error)
- return (error);
-
- la = (struct llinfo_arp *)rt->rt_llinfo;
- if (la == NULL)
- RT_UNLOCK(rt);
- }
- if (la == NULL) {
- /*
- * We enter this block in case if rt0 was NULL,
- * or if rt found by rt_check() didn't have llinfo.
- */
- 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));
- return (EINVAL); /* XXX */
- }
- la = (struct llinfo_arp *)rt->rt_llinfo;
- if (la == NULL) {
- RT_UNLOCK(rt);
- log(LOG_DEBUG,
- "arpresolve: can't allocate llinfo for %s\n",
- inet_ntoa(SIN(dst)->sin_addr));
- return (EINVAL); /* XXX */
- }
- }
- sdl = SDL(rt->rt_gateway);
- /*
- * Check the address family and length is valid, the address
- * is resolved; otherwise, try to resolve.
- */
- if ((rt->rt_expire == 0 || rt->rt_expire > time_uptime) &&
- sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {
-
- bcopy(LLADDR(sdl), desten, sdl->sdl_alen);
-
- /*
- * If entry has an expiry time and it is approaching,
- * send an ARP request.
- */
- if ((rt->rt_expire != 0) &&
- (time_uptime + la->la_preempt > rt->rt_expire)) {
- struct in_addr sin =
- SIN(rt->rt_ifa->ifa_addr)->sin_addr;
-
- la->la_preempt--;
- RT_UNLOCK(rt);
- arprequest(ifp, &sin, &SIN(dst)->sin_addr,
- IF_LLADDR(ifp));
- return (0);
- }
-
- RT_UNLOCK(rt);
- return (0);
- }
- /*
- * If ARP is disabled or static on this interface, stop.
- * XXX
- * Probably should not allocate empty llinfo struct if we are
- * not going to be sending out an arp request.
- */
- if (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) {
- RT_UNLOCK(rt);
- return (EINVAL);
+ if (m) {
+ if (la->la_hold)
+ m_freem(la->la_hold);
+ la->la_hold = m;
}
KASSERT(rt->rt_expire > 0, ("sending ARP request for static entry"));
diff --git a/sys/netinet/if_ether.h b/sys/netinet/if_ether.h
index ae2b0d0..14df15f 100644
--- a/sys/netinet/if_ether.h
+++ b/sys/netinet/if_ether.h
@@ -111,8 +111,6 @@ extern u_char ether_ipmulticast_max[ETHER_ADDR_LEN];
int arpresolve(struct ifnet *ifp, struct rtentry *rt,
struct mbuf *m, struct sockaddr *dst, u_char *desten);
-int arpresolve2(struct ifnet *ifp, struct rtentry *rt,
- struct sockaddr *dst, u_char *desten);
void arp_ifinit(struct ifnet *, struct ifaddr *);
void arp_ifinit2(struct ifnet *, struct ifaddr *, u_char *);
#endif
OpenPOWER on IntegriCloud