How to enable ECMP flow based forwarding ?

Ermal Luçi eri at freebsd.org
Tue Feb 14 19:52:26 UTC 2017


On Tue, Feb 14, 2017 at 6:13 AM, Andrey V. Elsukov <bu7cher at yandex.ru>
wrote:

> On 14.02.2017 03:23, Olivier Cochard-Labbé wrote:
> > Hi,
> >
> > I'm testing FreeBSD ECMP behavior by adding "options RADIX_MPATH" to my
> > kernel configuration (11-stable).
> > Now I can configure two identical routes toward 2 different next-hop:
> First
> > step achieved :-)
> > But it uses only the first entry and never uses the second one.
> >
> > I've tried to shutdown the first next-hop router (then no more arp-reply
> > from this next-hop): But the ECMP FreeBSD router sticks to its first
> route
> > entry and never try the second entry :-(
> >
> > Is there something else to enable (like RSS?) for having a real ECMP flow
> > based router ?
>
> I think you need to implement some code first. The fastfwd has not
> supported MPATH and tryforward also doesn't support it. For IPv4 you can
> try to add some IPsec security policy to disable ip_tryforward. In this
> case ip_forward() will be used, and it uses rtalloc_mpath_fib(), so,
> probably, it will work.
>
> This seems to be a bug to file and which can quickly be fixed by
presenting same
behaviour that slow path does when RADIX_MPATH is active.

It does not impact performance or any of the problems ip_tryforward() is
trying to
solve.

Try the attached patch it should fix your issues.


--
> WBR, Andrey V. Elsukov
>
> --
> Ermal
>
-------------- next part --------------
diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c
index ea59c10..0a50f62 100644
--- a/sys/netinet/ip_fastfwd.c
+++ b/sys/netinet/ip_fastfwd.c
@@ -108,7 +108,8 @@ __FBSDID("$FreeBSD$");
 #include <machine/in_cksum.h>
 
 static struct sockaddr_in *
-ip_findroute(struct route *ro, struct in_addr dest, struct mbuf *m)
+ip_findroute(struct route *ro, struct ip *ip, struct in_addr dest,
+               struct mbuf *m)
 {
        struct sockaddr_in *dst;
        struct rtentry *rt;
@@ -121,7 +122,14 @@ ip_findroute(struct route *ro, struct in_addr dest, struct mbuf *m)
        dst->sin_family = AF_INET;
        dst->sin_len = sizeof(*dst);
        dst->sin_addr.s_addr = dest.s_addr;
-       in_rtalloc_ign(ro, 0, M_GETFIB(m));
+#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
+
 
        /*
         * Route there and interface still up?
@@ -305,7 +313,7 @@ passin:
        /*
         * Find route to destination.
         */
-       if ((dst = ip_findroute(&ro, dest, m)) == NULL)
+       if ((dst = ip_findroute(&ro, ip, dest, m)) == NULL)
                return NULL;    /* icmp unreach already sent */
        ifp = ro.ro_rt->rt_ifp;
 
@@ -366,7 +374,7 @@ forwardlocal:
                        m->m_flags &= ~M_IP_NEXTHOP;
                }
                RTFREE(ro.ro_rt);
-               if ((dst = ip_findroute(&ro, dest, m)) == NULL)
+               if ((dst = ip_findroute(&ro, ip, dest, m)) == NULL)
                        return NULL;    /* icmp unreach already sent */
                ifp = ro.ro_rt->rt_ifp;
        }



More information about the freebsd-net mailing list