svn commit: r304435 - head/sys/netinet
Ryan Stone
rstone at FreeBSD.org
Thu Aug 18 22:59:01 UTC 2016
Author: rstone
Date: Thu Aug 18 22:59:00 2016
New Revision: 304435
URL: https://svnweb.freebsd.org/changeset/base/304435
Log:
Don't iterate over the ifnet addr list in ip_output()
For almost every packet that is transmitted through ip_output(),
a call to in_broadcast() was made to decide if the destination
IP was a broadcast address. in_broadcast() iterates over the
ifnet's address to find a source IP matching the subnet of the
destination IP, and then checks if the IP is a broadcast in that
subnet.
This is completely redundant as we have already performed the
route lookup, so the source IP is already known. Just use that
address to directly check whether the destination IP is a
broadcast address or not.
MFC after: 2 months
Sponsored By: EMC / Isilon Storage Division
Differential Revision: https://reviews.freebsd.org/D7266
Modified:
head/sys/netinet/in.c
head/sys/netinet/in.h
head/sys/netinet/ip_output.c
Modified: head/sys/netinet/in.c
==============================================================================
--- head/sys/netinet/in.c Thu Aug 18 22:01:52 2016 (r304434)
+++ head/sys/netinet/in.c Thu Aug 18 22:59:00 2016 (r304435)
@@ -928,6 +928,25 @@ in_ifscrub_all(void)
IFNET_RUNLOCK();
}
+int
+in_ifaddr_broadcast(struct in_addr in, struct in_ifaddr *ia)
+{
+
+ return ((in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
+ /*
+ * Check for old-style (host 0) broadcast, but
+ * taking into account that RFC 3021 obsoletes it.
+ */
+ (ia->ia_subnetmask != IN_RFC3021_MASK &&
+ ntohl(in.s_addr) == ia->ia_subnet)) &&
+ /*
+ * Check for an all one subnetmask. These
+ * only exist when an interface gets a secondary
+ * address.
+ */
+ ia->ia_subnetmask != (u_long)0xffffffff);
+}
+
/*
* Return 1 if the address might be a local broadcast address.
*/
@@ -935,37 +954,21 @@ int
in_broadcast(struct in_addr in, struct ifnet *ifp)
{
register struct ifaddr *ifa;
- u_long t;
if (in.s_addr == INADDR_BROADCAST ||
in.s_addr == INADDR_ANY)
return (1);
if ((ifp->if_flags & IFF_BROADCAST) == 0)
return (0);
- t = ntohl(in.s_addr);
/*
* Look through the list of addresses for a match
* with a broadcast address.
*/
-#define ia ((struct in_ifaddr *)ifa)
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
if (ifa->ifa_addr->sa_family == AF_INET &&
- (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
- /*
- * Check for old-style (host 0) broadcast, but
- * taking into account that RFC 3021 obsoletes it.
- */
- (ia->ia_subnetmask != IN_RFC3021_MASK &&
- t == ia->ia_subnet)) &&
- /*
- * Check for an all one subnetmask. These
- * only exist when an interface gets a secondary
- * address.
- */
- ia->ia_subnetmask != (u_long)0xffffffff)
+ in_ifaddr_broadcast(in, (struct in_ifaddr *)ifa))
return (1);
return (0);
-#undef ia
}
/*
Modified: head/sys/netinet/in.h
==============================================================================
--- head/sys/netinet/in.h Thu Aug 18 22:01:52 2016 (r304434)
+++ head/sys/netinet/in.h Thu Aug 18 22:59:00 2016 (r304435)
@@ -637,8 +637,10 @@ int getsourcefilter(int, uint32_t, struc
#ifdef _KERNEL
struct ifnet; struct mbuf; /* forward declarations for Standard C */
+struct in_ifaddr;
int in_broadcast(struct in_addr, struct ifnet *);
+int in_ifaddr_broadcast(struct in_addr, struct in_ifaddr *);
int in_canforward(struct in_addr);
int in_localaddr(struct in_addr);
int in_localip(struct in_addr);
Modified: head/sys/netinet/ip_output.c
==============================================================================
--- head/sys/netinet/ip_output.c Thu Aug 18 22:01:52 2016 (r304434)
+++ head/sys/netinet/ip_output.c Thu Aug 18 22:59:00 2016 (r304435)
@@ -350,7 +350,7 @@ again:
have_ia_ref = 1;
ifp = ia->ia_ifp;
ip->ip_ttl = 1;
- isbroadcast = in_broadcast(dst->sin_addr, ifp);
+ isbroadcast = in_ifaddr_broadcast(dst->sin_addr, ia);
} else if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) &&
imo != NULL && imo->imo_multicast_ifp != NULL) {
/*
@@ -404,7 +404,7 @@ again:
if (rte->rt_flags & RTF_HOST)
isbroadcast = (rte->rt_flags & RTF_BROADCAST);
else
- isbroadcast = in_broadcast(gw->sin_addr, ifp);
+ isbroadcast = in_ifaddr_broadcast(gw->sin_addr, ia);
}
/*
More information about the svn-src-head
mailing list