]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/zebra_vrf.c
Merge pull request #783 from opensourcerouting/pw-manager-2
[mirror_frr.git] / zebra / zebra_vrf.c
index e28f97d763dfcdd5b03cadde1c6d25511dcbd767..1797ef080c87599778881aa3139d2d7eb3355809 100644 (file)
 #include "linklist.h"
 #include "command.h"
 #include "memory.h"
+#include "srcdest_table.h"
 
+#include "vty.h"
 #include "zebra/debug.h"
 #include "zebra/zserv.h"
 #include "zebra/rib.h"
 #include "zebra/zebra_vrf.h"
+#include "zebra/zebra_rnh.h"
 #include "zebra/router-id.h"
 #include "zebra/zebra_memory.h"
 #include "zebra/zebra_static.h"
+#include "zebra/interface.h"
 #include "zebra/zebra_mpls.h"
 
 extern struct zebra_t zebrad;
@@ -45,7 +49,7 @@ zebra_vrf_add_update (struct zebra_vrf *zvrf)
   struct zserv *client;
 
   if (IS_ZEBRA_DEBUG_EVENT)
-    zlog_debug ("MESSAGE: ZEBRA_VRF_ADD %s", zvrf->name);
+    zlog_debug ("MESSAGE: ZEBRA_VRF_ADD %s", zvrf_name (zvrf));
 
   for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
     zsend_vrf_add (client, zvrf);
@@ -58,7 +62,7 @@ zebra_vrf_delete_update (struct zebra_vrf *zvrf)
   struct zserv *client;
 
   if (IS_ZEBRA_DEBUG_EVENT)
-    zlog_debug ("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf->name);
+    zlog_debug ("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf_name (zvrf));
 
   for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
     zsend_vrf_delete (client, zvrf);
@@ -78,32 +82,18 @@ zebra_vrf_update_all (struct zserv *client)
 
 /* Callback upon creating a new VRF. */
 static int
-zebra_vrf_new (vrf_id_t vrf_id, const char *name, void **info)
+zebra_vrf_new (struct vrf *vrf)
 {
-  struct zebra_vrf *zvrf = *info;
+  struct zebra_vrf *zvrf;
 
   if (IS_ZEBRA_DEBUG_EVENT)
-    zlog_info ("ZVRF %s with id %u", name, vrf_id);
-
-  if (! zvrf)
-    {
-      zvrf = zebra_vrf_list_lookup_by_name (name);
-      if (!zvrf)
-       {
-         zvrf = zebra_vrf_alloc (vrf_id, name);
-         zvrf->zns = zebra_ns_lookup (NS_DEFAULT); /* Point to the global (single) NS */
-         *info = (void *)zvrf;
-         router_id_init (zvrf);
-       }
-      else
-        {
-          *info = (void *)zvrf;
-         router_id_init (zvrf);
-        }
-    }
+    zlog_info ("ZVRF %s with id %u", vrf->name, vrf->vrf_id);
 
-  if (zvrf->vrf_id == VRF_UNKNOWN)
-    zvrf->vrf_id = vrf_id;
+  zvrf = zebra_vrf_alloc ();
+  zvrf->zns = zebra_ns_lookup (NS_DEFAULT); /* Point to the global (single) NS */
+  router_id_init (zvrf);
+  vrf->info = zvrf;
+  zvrf->vrf = vrf;
 
   return 0;
 }
@@ -143,7 +133,7 @@ zebra_vrf_static_route_interface_fixup (struct interface *ifp)
                        (si->ifindex != ifp->ifindex))
                      {
                        si->ifindex = ifp->ifindex;
-                       static_install_route (afi, safi, &rn->p, si);
+                       static_install_route (afi, safi, &rn->p, NULL, si);
                      }   
                  }
              }
@@ -154,13 +144,13 @@ zebra_vrf_static_route_interface_fixup (struct interface *ifp)
 
 /* Callback upon enabling a VRF. */
 static int
-zebra_vrf_enable (vrf_id_t vrf_id, const char *name, void **info)
+zebra_vrf_enable (struct vrf *vrf)
 {
-  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;
+  struct zebra_vrf *zvrf = vrf->info;
+  struct route_table *stable;
+  struct route_node *rn;
+  struct static_route *si;
+  struct interface *ifp;
   afi_t afi;
   safi_t safi;
 
@@ -169,85 +159,151 @@ zebra_vrf_enable (vrf_id_t vrf_id, const char *name, void **info)
   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 (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+      {
+       stable = zvrf->stable[afi][safi];
+       if (! stable)
+         continue;
+
+       for (rn = route_top (stable); rn; rn = route_next (rn))
+         for (si = rn->info; si; si = si->next)
            {
-             for (rn = route_top (stable); rn; rn = route_next (rn))
+             si->vrf_id = vrf->vrf_id;
+             if (si->ifindex)
                {
-                 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);
-                   }
+                 ifp = if_lookup_by_name (si->ifname, si->vrf_id);
+                 if (ifp)
+                   si->ifindex = ifp->ifindex;
+                 else
+                   continue;
                }
+             static_install_route (afi, safi, &rn->p, NULL, si);
            }
-       }
-    }
+      }
+
   return 0;
 }
 
 /* Callback upon disabling a VRF. */
 static int
-zebra_vrf_disable (vrf_id_t vrf_id, const char *name, void **info)
+zebra_vrf_disable (struct vrf *vrf)
 {
-  struct zebra_vrf *zvrf = (struct zebra_vrf *)(*info);
-  struct route_table *stable = NULL;
-  struct route_node *rn = NULL;
+  struct zebra_vrf *zvrf = vrf->info;
+  struct route_table *stable;
+  struct route_node *rn;
+  struct static_route *si;
   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);
+                zvrf_name (zvrf), zvrf_id (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)
-                   static_uninstall_route(afi, safi, &rn->p, rn->info);
-               }
-           }
-       }
-    }
+    for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+      {
+       stable = zvrf->stable[afi][safi];
+       if (! stable)
+         continue;
+
+       for (rn = route_top (stable); rn; rn = route_next (rn))
+         for (si = rn->info; si; si = si->next)
+           static_uninstall_route(afi, safi, &rn->p, NULL, si);
+      }
+
   return 0;
 }
 
 static int
-zebra_vrf_delete (vrf_id_t vrf_id, const char *name, void **info)
+zebra_vrf_delete (struct vrf *vrf)
 {
-  struct zebra_vrf *zvrf = (struct zebra_vrf *) (*info);
+  struct zebra_vrf *zvrf = vrf->info;
+  struct route_table *table;
+  u_int32_t table_id;
+  afi_t afi;
+  safi_t safi;
+  unsigned i;
 
   assert (zvrf);
 
   zebra_vrf_delete_update (zvrf);
 
-  rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
-  rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
+  /* uninstall everything */
+  if (! CHECK_FLAG (zvrf->flags, ZEBRA_VRF_RETAIN))
+    {
+      struct listnode *node;
+      struct interface *ifp;
+
+      for (afi = AFI_IP; afi <= AFI_IP6; afi++)
+       {
+         for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
+           rib_close_table (zvrf->table[afi][safi]);
+
+         if (vrf->vrf_id == VRF_DEFAULT)
+           for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; table_id++)
+             if (zvrf->other_table[afi][table_id])
+               rib_close_table (zvrf->other_table[afi][table_id]);
+       }
+
+      zebra_mpls_close_tables (zvrf);
+      zebra_pw_exit (zvrf);
+
+      for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp))
+       if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp);
+    }
+
+  /* clean-up work queues */
+  for (i = 0; i < MQ_SIZE; i++)
+    {
+      struct listnode *lnode, *nnode;
+      struct route_node *rnode;
+      rib_dest_t *dest;
+
+      for (ALL_LIST_ELEMENTS (zebrad.mq->subq[i], lnode, nnode, rnode))
+       {
+         dest = rib_dest_from_rnode (rnode);
+         if (dest && rib_dest_vrf (dest) == zvrf)
+           {
+             route_unlock_node (rnode);
+             list_delete_node (zebrad.mq->subq[i], lnode);
+             zebrad.mq->size--;
+           }
+       }
+    }
+
+  /* release allocated memory */
+  for (afi = AFI_IP; afi <= AFI_IP6; afi++)
+    {
+      void *table_info;
+
+      for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
+       {
+         table = zvrf->table[afi][safi];
+         table_info = table->info;
+         route_table_finish (table);
+         XFREE (MTYPE_RIB_TABLE_INFO, table_info);
 
+         table = zvrf->stable[afi][safi];
+         route_table_finish (table);
+       }
+
+      for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; table_id++)
+       if (zvrf->other_table[afi][table_id])
+         {
+           table = zvrf->other_table[afi][table_id];
+           table_info = table->info;
+           route_table_finish (table);
+           XFREE (MTYPE_RIB_TABLE_INFO, table_info);
+         }
+
+      route_table_finish (zvrf->rnh_table[afi]);
+      route_table_finish (zvrf->import_check_table[afi]);
+    }
   list_delete_all_node (zvrf->rid_all_sorted_list);
   list_delete_all_node (zvrf->rid_lo_sorted_list);
+  XFREE (MTYPE_ZEBRA_VRF, zvrf);
+  vrf->info = NULL;
 
-  zvrf->vrf_id = VRF_UNKNOWN;
-
-  *info = NULL;
   return 0;
 }
 
@@ -277,6 +333,38 @@ zebra_vrf_table_with_table_id (afi_t afi, safi_t safi,
   return table;
 }
 
+static void
+zebra_rtable_node_cleanup (struct route_table *table, struct route_node *node)
+{
+  struct rib *rib, *next;
+
+  RNODE_FOREACH_RIB_SAFE (node, rib, next)
+    rib_unlink (node, rib);
+
+  if (node->info)
+    XFREE (MTYPE_RIB_DEST, node->info);
+}
+
+static void
+zebra_stable_node_cleanup (struct route_table *table, struct route_node *node)
+{
+  struct static_route *si, *next;
+
+  if (node->info)
+    for (si = node->info; si; si = next)
+      {
+       next = si->next;
+       XFREE (MTYPE_STATIC_ROUTE, si);
+      }
+}
+
+static void
+zebra_rnhtable_node_cleanup (struct route_table *table, struct route_node *node)
+{
+  if (node->info)
+    zebra_free_rnh (node->info);
+}
+
 /*
  * Create a routing table for the specific AFI/SAFI in the given VRF.
  */
@@ -288,7 +376,11 @@ zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi)
 
   assert (!zvrf->table[afi][safi]);
 
-  table = route_table_init ();
+  if (afi == AFI_IP6)
+    table = srcdest_table_init();
+  else
+    table = route_table_init();
+  table->cleanup = zebra_rtable_node_cleanup;
   zvrf->table[afi][safi] = table;
 
   info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
@@ -300,38 +392,39 @@ zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi)
 
 /* Allocate new zebra VRF. */
 struct zebra_vrf *
-zebra_vrf_alloc (vrf_id_t vrf_id, const char *name)
+zebra_vrf_alloc (void)
 {
   struct zebra_vrf *zvrf;
+  afi_t afi;
+  safi_t safi;
+  struct route_table *table;
 
   zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf));
 
-  /* Allocate routing table and static table.  */
-  zebra_vrf_table_create (zvrf, AFI_IP, SAFI_UNICAST);
-  zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_UNICAST);
-  zvrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
-  zvrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
-  zebra_vrf_table_create (zvrf, AFI_IP, SAFI_MULTICAST);
-  zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_MULTICAST);
-  zvrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
-  zvrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
-
-  zvrf->rnh_table[AFI_IP] = route_table_init();
-  zvrf->rnh_table[AFI_IP6] = route_table_init();
-
-  zvrf->import_check_table[AFI_IP] = route_table_init();
-  zvrf->import_check_table[AFI_IP6] = route_table_init();
+  for (afi = AFI_IP; afi <= AFI_IP6; afi++)
+    {
+      for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
+        {
+          zebra_vrf_table_create (zvrf, afi, safi);
+          if (afi == AFI_IP6)
+            table = srcdest_table_init();
+          else
+            table = route_table_init();
+          table->cleanup = zebra_stable_node_cleanup;
+          zvrf->stable[afi][safi] = table;
+        }
 
-  /* Set VRF ID */
-  zvrf->vrf_id = vrf_id;
+      table = route_table_init();
+      table->cleanup = zebra_rnhtable_node_cleanup;
+      zvrf->rnh_table[afi] = table;
 
-  if (name)
-    {
-      strncpy (zvrf->name, name, strlen(name));
-      zvrf->name[strlen(name)] = '\0';
+      table = route_table_init();
+      table->cleanup = zebra_rnhtable_node_cleanup;
+      zvrf->import_check_table[afi] = table;
     }
 
   zebra_mpls_init_tables (zvrf);
+  zebra_pw_init (zvrf);
 
   return zvrf;
 }
@@ -345,14 +438,14 @@ zebra_vrf_lookup_by_id (vrf_id_t vrf_id)
 
 /* Lookup VRF by name.  */
 struct zebra_vrf *
-zebra_vrf_list_lookup_by_name (const char *name)
+zebra_vrf_lookup_by_name (const char *name)
 {
   struct vrf *vrf;
 
   if (!name)
     name = VRF_DEFAULT_NAME;
 
-  vrf = vrf_list_lookup_by_name (name);
+  vrf = vrf_lookup_by_name (name);
   if (vrf)
     return ((struct zebra_vrf *) vrf->info);
 
@@ -408,7 +501,7 @@ zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id, vrf_id_t vrf_id)
     {
       if (zvrf->other_table[afi][table_id] == NULL)
         {
-          table = route_table_init();
+          table = (afi == AFI_IP6) ? srcdest_table_init() : route_table_init();
           info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
           info->zvrf = zvrf;
           info->afi = afi;
@@ -423,26 +516,6 @@ zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id, vrf_id_t vrf_id)
   return zvrf->table[afi][SAFI_UNICAST];
 }
 
-/* Wrapper hook point for zebra daemon so that ifindex can be set
- * DEFUN macro not used as extract.pl HAS to ignore this
- * See also interface_cmd in lib/if.c
- */
-DEFUN_NOSH (zebra_vrf,
-           zebra_vrf_cmd,
-           "vrf NAME",
-           "Select a VRF to configure\n"
-           "VRF's name\n")
-{
-  // VTY_DECLVAR_CONTEXT (vrf, vrfp);
-  int ret;
-
-  /* Call lib vrf() */
-  if ((ret = vrf_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS)
-    return ret;
-
-  return ret;
-}
-
 static int
 vrf_config_write (struct vty *vty)
 {
@@ -452,22 +525,15 @@ vrf_config_write (struct vty *vty)
   RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
     {
       zvrf = vrf->info;
-      if (! zvrf || strcmp (zvrf->name, VRF_DEFAULT_NAME))
+      if (! zvrf || strcmp (zvrf_name (zvrf), VRF_DEFAULT_NAME))
         {
-          vty_out (vty, "vrf %s%s", zvrf->name, VTY_NEWLINE);
+          vty_out (vty, "vrf %s%s", zvrf_name (zvrf), VTY_NEWLINE);
           vty_out (vty, "!%s", VTY_NEWLINE);
         }
     }
   return 0;
 }
 
-struct cmd_node vrf_node =
-{
-  VRF_NODE,
-  "%s(config-vrf)# ",
-  1
-};
-
 /* Zebra VRF initialization. */
 void
 zebra_vrf_init (void)
@@ -478,9 +544,5 @@ zebra_vrf_init (void)
   vrf_add_hook (VRF_DELETE_HOOK, zebra_vrf_delete);
 
   vrf_init ();
-
-  install_node (&vrf_node, vrf_config_write);
-  install_default (VRF_NODE);
-  install_element (CONFIG_NODE, &zebra_vrf_cmd);
-  install_element (CONFIG_NODE, &no_vrf_cmd);
+  vrf_cmd_init (vrf_config_write);
 }