[cmaster-next] [PATCH 1/3] zebra: fix FIB route updates on *BSD

Renato Westphal renato at opensourcerouting.org
Fri Dec 16 10:23:37 EST 2016


On *BSD, we update a route in the FIB by removing the old one and then
installing the new version.

With that said, on kernel_route_rib() we need to provide a pointer to
both the old version and the new version of the route.

We were, however, passing a pointer to the new version to both the
'old' and 'new' parameters. This is not a problem on Linux, which uses
NLM_F_REPLACE to update routes, but it breaks route updates on *BSD
because the 'old' parameter points to a route that is not installed in
the kernel. The kernel_route_rib() function then fails to uninstall the
supposedly 'old' route and can fail to install the new version as well if
the kernel doesn't support ECMP (e.g. FreeBSD with default configuration).

Signed-off-by: Renato Westphal <renato at opensourcerouting.org>
---
 zebra/rib.h          |  2 +-
 zebra/zebra_rib.c    | 12 ++++++------
 zebra/zebra_static.c |  2 +-
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/zebra/rib.h b/zebra/rib.h
index 30929f1..a30c093 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -335,7 +335,7 @@ extern int zebra_check_addr (struct prefix *p);
 
 extern void rib_addnode (struct route_node *rn, struct rib *rib, int process);
 extern void rib_delnode (struct route_node *rn, struct rib *rib);
-extern int rib_install_kernel (struct route_node *rn, struct rib *rib, int update);
+extern int rib_install_kernel (struct route_node *rn, struct rib *rib, struct rib *old);
 extern int rib_uninstall_kernel (struct route_node *rn, struct rib *rib);
 
 /* NOTE:
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index c573f6b..a792bcc 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1212,7 +1212,7 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
  * is only used for IPv4.
  */
 int
-rib_install_kernel (struct route_node *rn, struct rib *rib, int update)
+rib_install_kernel (struct route_node *rn, struct rib *rib, struct rib *old)
 {
   int ret = 0;
   struct nexthop *nexthop, *tnexthop;
@@ -1231,7 +1231,7 @@ rib_install_kernel (struct route_node *rn, struct rib *rib, int update)
    * the kernel.
    */
   zfpm_trigger_update (rn, "installing in kernel");
-  ret = kernel_route_rib (&rn->p, update ? rib : NULL, rib);
+  ret = kernel_route_rib (&rn->p, old, rib);
 
   /* If install succeeds, update FIB flag for nexthops. */
   if (!ret)
@@ -1388,7 +1388,7 @@ rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn,
 
   if (!RIB_SYSTEM_ROUTE (new))
     {
-      if (rib_install_kernel (rn, new, 0))
+      if (rib_install_kernel (rn, new, NULL))
         {
           inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
           zlog_warn ("%u:%s/%d: Route install failed",
@@ -1470,7 +1470,7 @@ rib_process_update_fib (struct zebra_vrf *zvrf, struct route_node *rn,
           /* Non-system route should be installed. */
           if (!RIB_SYSTEM_ROUTE (new))
             {
-              if (rib_install_kernel (rn, new, 1))
+              if (rib_install_kernel (rn, new, old))
                 {
                   installed = 0;
                   inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
@@ -1542,7 +1542,7 @@ rib_process_update_fib (struct zebra_vrf *zvrf, struct route_node *rn,
                 break;
               }
           if (!in_fib)
-            rib_install_kernel (rn, new, 0);
+            rib_install_kernel (rn, new, NULL);
         }
     }
 
@@ -2779,7 +2779,7 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
 	    {
 	      /* This means someone else, other than Zebra, has deleted
 	       * a Zebra router from the kernel. We will add it back */
-	      rib_install_kernel(rn, fib, 0);
+	      rib_install_kernel(rn, fib, NULL);
 	    }
         }
       else
diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c
index e6ae9c7..7c37d6b 100644
--- a/zebra/zebra_static.c
+++ b/zebra/zebra_static.c
@@ -323,7 +323,7 @@ static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_
             {
               /* Update route in kernel if it's in fib */
               if (CHECK_FLAG(rib->status, RIB_ENTRY_SELECTED_FIB))
-              rib_install_kernel (rn, rib, 1);
+              rib_install_kernel (rn, rib, rib);
               /* Update redistribution if it's selected */
               if (CHECK_FLAG(rib->flags, ZEBRA_FLAG_SELECTED))
               redistribute_update (&rn->p, rib, NULL);
-- 
1.9.1





More information about the dev mailing list