[quagga-dev 6417] Re: [PATCH] [zebra] Fix multipath route handling capability

Tsachi tsachi.kimel at gmail.com
Tue Feb 10 21:51:09 GMT 2009


Thank you very much,
When running "show ip route" Will Zebra show a list of all nexthop
related with the route ?
Do you think it should be "easy" to migrate the fix to 0.98.6 ? (or
there is a big difference between 0.98.6 and 0.99.11)
Regards,
Tsachi


On Mon, Feb 9, 2009 at 5:25 PM, Suresh Bhogavilli
<sbhogavilli at verisign.com> wrote:
> [zebra] Fix multipath route handling capability
>
> * Add the ability to read multipath routes from the kernel and correctly
>  handle the multipath route update messages.
> * rib.h: Add the function prototype nexthop_ipv4_ifindex_add() as it is
>  now called from functions in rt_netlink.c
> * zebra_rib.c: Make the function nexthop_ipv4_ifindex_add() non-static
> * rt_netlink.c:
>  * netlink_routing_table(): When reading the routes from the kernel,
>    use rib_add_ipv4() only when the route is a unipath route.  If the
>    netlink message has RTA_MULTIPATH attribute, parse all the nexthops
>    and call rib_add_ipv4_multipath() to add the route to the RIB.
>  * netlink_route_change(): Changes similar to above.  Also parse the
>    metric/RTA_PRIORITY attribute if any, so zebra has consistent view
>    of the route whether read at start up or learned dynamically.
>
> Signed-off-by: Suresh Bhogavilli <sbhogavilli at verisign.com>
> ---
> diff -upwb quagga-0.99.11/zebra/rib.h new/zebra/rib.h
> --- quagga-0.99.11/zebra/rib.h  2008-09-05 10:27:26.000000000 -0400
> +++ new/zebra/rib.h     2009-02-09 10:22:15.428217000 -0500
> @@ -225,6 +225,10 @@ extern struct nexthop *nexthop_ifname_ad
>  extern struct nexthop *nexthop_blackhole_add (struct rib *);
>  extern struct nexthop *nexthop_ipv4_add (struct rib *, struct in_addr *,
>                                         struct in_addr *);
> +extern struct nexthop *nexthop_ipv4_ifindex_add (struct rib *,
> +                                                struct in_addr *,
> +                                                struct in_addr *,
> +                                                unsigned int);
>  extern void rib_lookup_and_dump (struct prefix_ipv4 *);
>  extern void rib_lookup_and_pushup (struct prefix_ipv4 *);
>  extern void rib_dump (const char *, const struct prefix_ipv4 *, const struct rib *);
> diff -upwb quagga-0.99.11/zebra/rt_netlink.c new/zebra/rt_netlink.c
> --- quagga-0.99.11/zebra/rt_netlink.c   2008-09-05 10:27:26.000000000 -0400
> +++ new/zebra/rt_netlink.c      2009-02-09 10:20:11.396374000 -0500
> @@ -32,6 +32,7 @@
>  #include "prefix.h"
>  #include "connected.h"
>  #include "table.h"
> +#include "memory.h"
>  #include "rib.h"
>  #include "thread.h"
>  #include "privs.h"
> @@ -709,7 +710,6 @@ netlink_routing_table (struct sockaddr_n
>   if (tb[RTA_PREFSRC])
>     src = RTA_DATA (tb[RTA_PREFSRC]);
>
> -  /* Multipath treatment is needed. */
>   if (tb[RTA_GATEWAY])
>     gate = RTA_DATA (tb[RTA_GATEWAY]);
>
> @@ -723,7 +723,64 @@ netlink_routing_table (struct sockaddr_n
>       memcpy (&p.prefix, dest, 4);
>       p.prefixlen = rtm->rtm_dst_len;
>
> -      rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index, table, metric, 0);
> +      if (!tb[RTA_MULTIPATH])
> +          rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index,
> +                        table, metric, 0);
> +      else
> +        {
> +          /* This is a multipath route */
> +
> +          struct rib *rib;
> +          struct rtnexthop *rtnh =
> +            (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
> +
> +          len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
> +
> +          rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
> +          rib->type = ZEBRA_ROUTE_KERNEL;
> +          rib->distance = 0;
> +          rib->flags = flags;
> +          rib->metric = metric;
> +          rib->table = table;
> +          rib->nexthop_num = 0;
> +          rib->uptime = time (NULL);
> +
> +          for (;;)
> +            {
> +              if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
> +                break;
> +
> +              rib->nexthop_num++;
> +              index = rtnh->rtnh_ifindex;
> +              gate = 0;
> +              if (rtnh->rtnh_len > sizeof (*rtnh))
> +                {
> +                  memset (tb, 0, sizeof (tb));
> +                  netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
> +                                        rtnh->rtnh_len - sizeof (*rtnh));
> +                  if (tb[RTA_GATEWAY])
> +                    gate = RTA_DATA (tb[RTA_GATEWAY]);
> +                }
> +
> +              if (gate)
> +                {
> +                  if (index)
> +                    nexthop_ipv4_ifindex_add (rib, gate, src, index);
> +                  else
> +                    nexthop_ipv4_add (rib, gate, src);
> +                }
> +              else
> +                nexthop_ifindex_add (rib, index);
> +
> +              len -= NLMSG_ALIGN(rtnh->rtnh_len);
> +              rtnh = RTNH_NEXT(rtnh);
> +            }
> +
> +          if (rib->nexthop_num == 0)
> +            XFREE (MTYPE_RIB, rib);
> +          else
> +            rib_add_ipv4_multipath (&p, rib);
> +        }
>     }
>  #ifdef HAVE_IPV6
>   if (rtm->rtm_family == AF_INET6)
> @@ -768,6 +825,7 @@ netlink_route_change (struct sockaddr_nl
>
>   int index;
>   int table;
> +  int metric;
>   void *dest;
>   void *gate;
>   void *src;
> @@ -825,6 +883,7 @@ netlink_route_change (struct sockaddr_nl
>     }
>
>   index = 0;
> +  metric = 0;
>   dest = NULL;
>   gate = NULL;
>   src = NULL;
> @@ -843,6 +902,9 @@ netlink_route_change (struct sockaddr_nl
>   if (tb[RTA_PREFSRC])
>     src = RTA_DATA (tb[RTA_PREFSRC]);
>
> +  if (tb[RTA_PRIORITY])
> +    metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
> +
>   if (rtm->rtm_family == AF_INET)
>     {
>       struct prefix_ipv4 p;
> @@ -861,7 +923,66 @@ netlink_route_change (struct sockaddr_nl
>         }
>
>       if (h->nlmsg_type == RTM_NEWROUTE)
> -        rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table, 0, 0);
> +        {
> +          if (!tb[RTA_MULTIPATH])
> +            rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table,
> +                          metric, 0);
> +          else
> +            {
> +              /* This is a multipath route */
> +
> +              struct rib *rib;
> +              struct rtnexthop *rtnh =
> +                (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
> +
> +              len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
> +
> +              rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
> +              rib->type = ZEBRA_ROUTE_KERNEL;
> +              rib->distance = 0;
> +              rib->flags = 0;
> +              rib->metric = metric;
> +              rib->table = table;
> +              rib->nexthop_num = 0;
> +              rib->uptime = time (NULL);
> +
> +              for (;;)
> +                {
> +                  if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
> +                    break;
> +
> +                  rib->nexthop_num++;
> +                  index = rtnh->rtnh_ifindex;
> +                  gate = 0;
> +                  if (rtnh->rtnh_len > sizeof (*rtnh))
> +                    {
> +                      memset (tb, 0, sizeof (tb));
> +                      netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
> +                                            rtnh->rtnh_len - sizeof (*rtnh));
> +                      if (tb[RTA_GATEWAY])
> +                        gate = RTA_DATA (tb[RTA_GATEWAY]);
> +                    }
> +
> +                  if (gate)
> +                    {
> +                      if (index)
> +                        nexthop_ipv4_ifindex_add (rib, gate, src, index);
> +                      else
> +                        nexthop_ipv4_add (rib, gate, src);
> +                    }
> +                  else
> +                    nexthop_ifindex_add (rib, index);
> +
> +                  len -= NLMSG_ALIGN(rtnh->rtnh_len);
> +                  rtnh = RTNH_NEXT(rtnh);
> +                }
> +
> +              if (rib->nexthop_num == 0)
> +                XFREE (MTYPE_RIB, rib);
> +              else
> +                rib_add_ipv4_multipath (&p, rib);
> +            }
> +        }
>       else
>         rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table);
>     }
> diff -upwb quagga-0.99.11/zebra/zebra_rib.c new/zebra/zebra_rib.c
> --- quagga-0.99.11/zebra/zebra_rib.c    2008-09-05 10:27:26.000000000 -0400
> +++ new/zebra/zebra_rib.c       2009-02-07 22:25:10.780331000 -0500
> @@ -251,7 +251,7 @@ nexthop_ipv4_add (struct rib *rib, struc
>   return nexthop;
>  }
>
> -static struct nexthop *
> +struct nexthop *
>  nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
>                           struct in_addr *src, unsigned int ifindex)
>  {
>
>
>



More information about the Quagga-dev mailing list