summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ip_input.c
diff options
context:
space:
mode:
authoreri <eri@FreeBSD.org>2015-07-29 17:46:16 +0000
committereri <eri@FreeBSD.org>2015-07-29 17:46:16 +0000
commitb2cc8257fafcac243898243bbe14dd18835fb5c0 (patch)
treea1b38690aa563d104ca6e3502288a679f17d8b65 /sys/netinet/ip_input.c
parentcdb611ddfcb7a547f90bfbcd4a5f56f9e749e1dc (diff)
downloadFreeBSD-src-b2cc8257fafcac243898243bbe14dd18835fb5c0.zip
FreeBSD-src-b2cc8257fafcac243898243bbe14dd18835fb5c0.tar.gz
MFC r285051
Avoid doing multiple route lookups for the same destination IP during forwarding. Differential Revision: https://reviews.freebsd.org/D2964
Diffstat (limited to 'sys/netinet/ip_input.c')
-rw-r--r--sys/netinet/ip_input.c35
1 files changed, 18 insertions, 17 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index dea8bee..372e48d 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -1345,6 +1345,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;
@@ -1366,7 +1367,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.
@@ -1375,6 +1391,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
@@ -1431,16 +1448,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 &&
@@ -1459,16 +1468,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)
OpenPOWER on IntegriCloud