]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: Add code to add/remove statics from the rib
authorDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 4 May 2016 00:04:43 +0000 (20:04 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Fri, 6 May 2016 14:41:28 +0000 (10:41 -0400)
On enable/disable of static routes add and remove them
from the rib as appropriate.

Ticket: CM-10139
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Reviewed-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
Reviewed-by: Don Slice <dslice@cumulusnetworks.com>
zebra/interface.c
zebra/rib.h
zebra/zebra_rib.c
zebra/zebra_vrf.c
zebra/zebra_vrf.h
zebra/zebra_vty.c

index 91eb5c49ce5a292db384b726004a716adf9a40bc..ff7cf21512d3ef6fca4c14ffa0fbf76554233577 100644 (file)
@@ -706,6 +706,8 @@ if_handle_vrf_change (struct interface *ifp, vrf_id_t vrf_id)
                 ifp->vrf_id, ifp->name);
   rib_update (old_vrf_id, RIB_UPDATE_IF_CHANGE);
   rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
+
+  zebra_vrf_static_route_interface_fixup (ifp);
 }
 
 static void
index f22d7aa4200cdaa5f7a26ea6c30151b02cb4b2ea..d41519042e36aa501039836fa6a813d1d5a1a792 100644 (file)
@@ -29,6 +29,7 @@
 #include "queue.h"
 #include "nexthop.h"
 #include "vrf.h"
+#include "if.h"
 
 #define DISTANCE_INFINITY  255
 #define ZEBRA_KERNEL_TABLE_MAX 252 /* support for no more than this rt tables */
@@ -204,6 +205,8 @@ struct static_route
   union g_addr addr;
   unsigned int ifindex;
 
+  char ifname[INTERFACE_NAMSIZ + 1];
+
   /* bit flags */
   u_char flags;
 /*
@@ -379,6 +382,10 @@ extern void rib_init (void);
 extern unsigned long rib_score_proto (u_char proto, u_short instance);
 extern void rib_queue_add (struct route_node *rn);
 
+extern void
+static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si);
+extern void
+static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si);
 
 extern int
 static_add_ipv4 (struct prefix *p, struct in_addr *gate, unsigned int ifindex,
index 59da68e2459adc0cd7388a0a9b14d54d0d0a9a38..312a90bc5ff913519d0fc20d5d554e61396e2c84 100644 (file)
@@ -2742,7 +2742,7 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
 }
 
 /* Install static route into rib. */
-static void
+void
 static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
 {
   struct rib *rib;
@@ -2914,7 +2914,7 @@ static_nexthop_same (struct nexthop *nexthop, struct static_route *si)
 }
 
 /* Uninstall static route from RIB. */
-static void
+void
 static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
 {
   struct route_node *rn;
@@ -3074,6 +3074,8 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, unsigned int ifindex,
   si->tag = tag;
   si->vrf_id = zvrf->vrf_id;
   si->ifindex = ifindex;
+  if (si->ifindex)
+    strcpy(si->ifname, ifindex2ifname_vrf (si->ifindex, si->vrf_id));
 
   if (gate)
     si->addr.ipv4 = *gate;
index 0eba9021129063cbf7e9bade45329d20da90ecf9..f76bc98190200d0fede4a460126a587c10d04834 100644 (file)
@@ -94,16 +94,93 @@ zebra_vrf_new (vrf_id_t vrf_id, const char *name, void **info)
   return 0;
 }
 
+/*
+ * Moving an interface amongst different vrf's
+ * causes the interface to get a new ifindex
+ * so we need to find static routes with
+ * the old ifindex and replace with new
+ * ifindex to insert back into the table
+ */
+void
+zebra_vrf_static_route_interface_fixup (struct interface *ifp)
+{
+  afi_t afi;
+  safi_t safi;
+  struct zebra_vrf *zvrf = zebra_vrf_lookup (ifp->vrf_id);
+  struct route_table *stable = NULL;
+  struct route_node *rn = NULL;
+  struct static_route *si = NULL;
+
+  if (!zvrf)
+    return;
+
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    {
+      for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+        {
+          stable = zvrf->stable[afi][safi];
+          if (stable)
+           for (rn = route_top (stable); rn; rn = route_next (rn))
+             {
+               if (rn->info)
+                 {
+                   si = rn->info;
+                   if ((strcmp (si->ifname, ifp->name) == 0) &&
+                       (si->ifindex != ifp->ifindex))
+                     {
+                       si->ifindex = ifp->ifindex;
+                       static_install_route (afi, safi, &rn->p, si);
+                     }   
+                 }
+             }
+       }
+    }
+  
+}
+
 /* Callback upon enabling a VRF. */
 static int
 zebra_vrf_enable (vrf_id_t vrf_id, const char *name, void **info)
 {
   struct zebra_vrf *zvrf = (struct zebra_vrf *) (*info);
+  struct route_table *stable = NULL;
+  struct route_node *rn = NULL;
+  struct static_route *si = NULL;
+  struct interface *ifp = NULL;
+  afi_t afi;
+  safi_t safi;
 
   assert (zvrf);
 
   zebra_vrf_add_update (zvrf);
 
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    {
+      for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+       {
+         stable = zvrf->stable[afi][safi];
+         if (stable)
+           {
+             for (rn = route_top (stable); rn; rn = route_next (rn))
+               {
+                 if (rn->info)
+                   {
+                     si = rn->info;
+                     si->vrf_id = vrf_id;
+                     if (si->ifindex)
+                       {
+                          ifp = if_lookup_by_name_vrf (si->ifname, si->vrf_id);
+                         if (ifp)
+                            si->ifindex = ifp->ifindex;
+                          else
+                           continue;
+                        }
+                     static_install_route (afi, safi, &rn->p, si);
+                   }
+               }
+           }
+       }
+    }
   return 0;
 }
 
@@ -112,11 +189,30 @@ static int
 zebra_vrf_disable (vrf_id_t vrf_id, const char *name, void **info)
 {
   struct zebra_vrf *zvrf = (struct zebra_vrf *)(*info);
+  struct route_table *stable = NULL;
+  struct route_node *rn = NULL;
+  afi_t afi;
+  safi_t safi;
 
   if (IS_ZEBRA_DEBUG_KERNEL)
     zlog_debug ("VRF %s id %u is now disabled.",
                 zvrf->name, zvrf->vrf_id);
 
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    {
+      for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+       {
+         stable = zvrf->stable[afi][safi];
+         if (stable)
+           {
+             for (rn = route_top (stable); rn; rn = route_next (rn))
+               {
+                  if (rn->info)
+                   static_uninstall_route(afi, safi, &rn->p, rn->info);
+               }
+           }
+       }
+    }
   return 0;
 }
 
index 36889e089de397a9b3fd1c7cac146cb6d346dc78..54f8bdc744b0fbe95a044b0d2a46822aed0774be 100644 (file)
@@ -80,6 +80,7 @@ struct route_table *
 zebra_vrf_table_with_table_id (afi_t afi, safi_t safi,
                                vrf_id_t vrf_id, u_int32_t table_id);
 
+extern void zebra_vrf_static_route_interface_fixup (struct interface *ifp);
 extern void zebra_vrf_update_all (struct zserv *client);
 extern struct zebra_vrf *zebra_vrf_lookup (vrf_id_t vrf_id);
 extern struct zebra_vrf *zebra_vrf_alloc (vrf_id_t, const char *);
index de86efef3e905c41a83cae0775e013ed007f098c..6b2f65d700204f7a122f9877cd8fad52015a8237 100644 (file)
@@ -3243,7 +3243,7 @@ static_config_ipv4 (struct vty *vty, safi_t safi, const char *cmd)
                 vty_out (vty, " %s", inet_ntoa (si->addr.ipv4));
                 break;
               case STATIC_IFINDEX:
-                vty_out (vty, " %s", ifindex2ifname_vrf(si->ifindex, si->vrf_id));
+                vty_out (vty, " %s", si->ifname);
                 break;
               case STATIC_IPV4_BLACKHOLE:
                 vty_out (vty, " Null0");
@@ -5509,7 +5509,7 @@ static_config_ipv6 (struct vty *vty)
                vty_out (vty, " %s", inet_ntop (AF_INET6, &si->addr.ipv6, buf, BUFSIZ));
                break;
              case STATIC_IFINDEX:
-               vty_out (vty, " %s", ifindex2ifname_vrf (si->ifindex, si->vrf_id));
+               vty_out (vty, " %s", si->ifname);
                break;
              case STATIC_IPV6_GATEWAY_IFINDEX:
                vty_out (vty, " %s %s",