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