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
This commit is contained in:
parent
be9cb745bc
commit
90cc51a1ab
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=304435
@ -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
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -637,8 +637,10 @@ int getsourcefilter(int, uint32_t, struct sockaddr *, socklen_t,
|
||||
#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);
|
||||
|
@ -350,7 +350,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
|
||||
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 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user