Avoid doing multiple route lookups for the same destination IP during forwarding
ip_forward() does a route lookup for testing this packet can be sent to a known destination, it also can do another route lookup if it detects that an ICMP redirect is needed, it forgets all of this and handovers to ip_output() to do the same lookup yet again. This optimisation just does one route lookup during the forwarding path and handovers that to be considered by ip_output(). Differential Revision: https://reviews.freebsd.org/D2964 Approved by: ae, gnn(mentor) MFC after: 1 week
This commit is contained in:
parent
d32a66b2a2
commit
d14122b078
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=285051
@ -897,6 +897,7 @@ ip_forward(struct mbuf *m, int srcrt)
|
||||
struct ip *ip = mtod(m, struct ip *);
|
||||
struct in_ifaddr *ia;
|
||||
struct mbuf *mcopy;
|
||||
struct sockaddr_in *sin;
|
||||
struct in_addr dest;
|
||||
struct route ro;
|
||||
int error, type = 0, code = 0, mtu = 0;
|
||||
@ -925,7 +926,22 @@ ip_forward(struct mbuf *m, int srcrt)
|
||||
}
|
||||
#endif
|
||||
|
||||
ia = ip_rtaddr(ip->ip_dst, M_GETFIB(m));
|
||||
bzero(&ro, sizeof(ro));
|
||||
sin = (struct sockaddr_in *)&ro.ro_dst;
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_len = sizeof(*sin);
|
||||
sin->sin_addr = ip->ip_dst;
|
||||
#ifdef RADIX_MPATH
|
||||
rtalloc_mpath_fib(&ro,
|
||||
ntohl(ip->ip_src.s_addr ^ ip->ip_dst.s_addr),
|
||||
M_GETFIB(m));
|
||||
#else
|
||||
in_rtalloc_ign(&ro, 0, M_GETFIB(m));
|
||||
#endif
|
||||
if (ro.ro_rt != NULL) {
|
||||
ia = ifatoia(ro.ro_rt->rt_ifa);
|
||||
ifa_ref(&ia->ia_ifa);
|
||||
}
|
||||
#ifndef IPSEC
|
||||
/*
|
||||
* 'ia' may be NULL if there is no route for this destination.
|
||||
@ -934,6 +950,7 @@ ip_forward(struct mbuf *m, int srcrt)
|
||||
*/
|
||||
if (!srcrt && ia == NULL) {
|
||||
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0);
|
||||
RO_RTFREE(&ro);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@ -990,16 +1007,8 @@ ip_forward(struct mbuf *m, int srcrt)
|
||||
dest.s_addr = 0;
|
||||
if (!srcrt && V_ipsendredirects &&
|
||||
ia != NULL && ia->ia_ifp == m->m_pkthdr.rcvif) {
|
||||
struct sockaddr_in *sin;
|
||||
struct rtentry *rt;
|
||||
|
||||
bzero(&ro, sizeof(ro));
|
||||
sin = (struct sockaddr_in *)&ro.ro_dst;
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_len = sizeof(*sin);
|
||||
sin->sin_addr = ip->ip_dst;
|
||||
in_rtalloc_ign(&ro, 0, M_GETFIB(m));
|
||||
|
||||
rt = ro.ro_rt;
|
||||
|
||||
if (rt && (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&
|
||||
@ -1018,16 +1027,8 @@ ip_forward(struct mbuf *m, int srcrt)
|
||||
code = ICMP_REDIRECT_HOST;
|
||||
}
|
||||
}
|
||||
if (rt)
|
||||
RTFREE(rt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to cache the route MTU from ip_output so we can consider it for
|
||||
* the ICMP_UNREACH_NEEDFRAG "Next-Hop MTU" field described in RFC1191.
|
||||
*/
|
||||
bzero(&ro, sizeof(ro));
|
||||
|
||||
error = ip_output(m, NULL, &ro, IP_FORWARDING, NULL, NULL);
|
||||
|
||||
if (error == EMSGSIZE && ro.ro_rt)
|
||||
|
Loading…
Reference in New Issue
Block a user