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); } /* _______________________________________________ svn-src-head@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"