Author: eri
Date: Thu Jul  2 18:10:41 2015
New Revision: 285051
URL: https://svnweb.freebsd.org/changeset/base/285051

Log:
  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

Modified:
  head/sys/netinet/ip_input.c

Modified: head/sys/netinet/ip_input.c
==============================================================================
--- head/sys/netinet/ip_input.c Thu Jul  2 17:30:59 2015        (r285050)
+++ head/sys/netinet/ip_input.c Thu Jul  2 18:10:41 2015        (r285051)
@@ -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)
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to