summaryrefslogtreecommitdiffstats
path: root/zebra/zebra_vrf.c
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2016-04-14 15:20:47 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2016-04-15 02:57:04 +0200
commit7c5519562ec585e9f75fd4dfd88710f4c9df5567 (patch)
treecff935dc5927ebe4ef322e0f21c763ba0d5363da /zebra/zebra_vrf.c
parentlib, zebra: Rework zebra_ns to be a bit more modular (diff)
downloadfrr-7c5519562ec585e9f75fd4dfd88710f4c9df5567.tar.xz
frr-7c5519562ec585e9f75fd4dfd88710f4c9df5567.zip
zebra: Refactor zebra_vrf
Move zebra_vrf_XXX functionality into it's own file so that we can isolate a bit the api edges Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com> Reviewed-by: Don Slice <dslice@cumulusnetworks.com> Reviewed-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
Diffstat (limited to 'zebra/zebra_vrf.c')
-rw-r--r--zebra/zebra_vrf.c306
1 files changed, 306 insertions, 0 deletions
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
new file mode 100644
index 000000000..c268fcbcb
--- /dev/null
+++ b/zebra/zebra_vrf.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2016 CumulusNetworks
+ * Donald Sharp
+ *
+ * This file is part of Quagga
+ *
+ * Quagga is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * Quagga is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#include <zebra.h>
+
+#include "log.h"
+#include "linklist.h"
+
+#include "zebra/debug.h"
+#include "zebra/zserv.h"
+#include "zebra/rib.h"
+#include "zebra/zebra_vrf.h"
+#include "zebra/router-id.h"
+
+extern struct zebra_t zebrad;
+
+/* VRF information update. */
+static void
+zebra_vrf_add_update (struct zebra_vrf *zvrf)
+{
+ struct listnode *node, *nnode;
+ struct zserv *client;
+
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug ("MESSAGE: ZEBRA_VRF_ADD %s", zvrf->name);
+
+ for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
+ zsend_vrf_add (client, zvrf);
+}
+
+static void
+zebra_vrf_delete_update (struct zebra_vrf *zvrf)
+{
+ struct listnode *node, *nnode;
+ struct zserv *client;
+
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug ("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf->name);
+
+ for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
+ zsend_vrf_delete (client, zvrf);
+}
+
+void
+zebra_vrf_update_all (struct zserv *client)
+{
+ struct vrf *vrf;
+ vrf_iter_t iter;
+
+ for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
+ {
+ if ((vrf = vrf_iter2vrf (iter)) && vrf->vrf_id)
+ zsend_vrf_add (client, vrf_info_lookup (vrf->vrf_id));
+ }
+}
+
+/* Callback upon creating a new VRF. */
+static int
+zebra_vrf_new (vrf_id_t vrf_id, const char *name, void **info)
+{
+ struct zebra_vrf *zvrf = *info;
+
+ zlog_info ("ZVRF %s with id %u", name, vrf_id);
+
+ 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);
+ }
+
+ return 0;
+}
+
+/* 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);
+
+ assert (zvrf);
+
+ zebra_vrf_add_update (zvrf);
+
+ return 0;
+}
+
+/* Callback upon disabling a VRF. */
+static int
+zebra_vrf_disable (vrf_id_t vrf_id, const char *name, void **info)
+{
+ struct zebra_vrf *zvrf = (struct zebra_vrf *)(*info);
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug ("VRF %s id %u is now disabled.",
+ zvrf->name, zvrf->vrf_id);
+
+ return 0;
+}
+
+static int
+zebra_vrf_delete (vrf_id_t vrf_id, const char *name, void **info)
+{
+ struct zebra_vrf *zvrf = (struct zebra_vrf *) (*info);
+
+ 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]);
+
+ list_delete_all_node (zvrf->rid_all_sorted_list);
+ list_delete_all_node (zvrf->rid_lo_sorted_list);
+
+ XFREE (MTYPE_ZEBRA_VRF, zvrf);
+
+ return 0;
+}
+
+/* Lookup the routing table in a VRF based on both VRF-Id and table-id.
+ * NOTE: Table-id is relevant only in the Default VRF.
+ */
+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)
+{
+ struct route_table *table = NULL;
+
+ if (afi >= AFI_MAX || safi >= SAFI_MAX)
+ return NULL;
+
+ if (vrf_id == VRF_DEFAULT)
+ {
+ if (table_id == RT_TABLE_MAIN ||
+ table_id == zebrad.rtm_table_default)
+ table = zebra_vrf_table (afi, safi, vrf_id);
+ else
+ table = zebra_vrf_other_route_table (afi, table_id, vrf_id);
+ }
+ else
+ table = zebra_vrf_table (afi, safi, vrf_id);
+
+ return table;
+}
+
+/*
+ * Create a routing table for the specific AFI/SAFI in the given VRF.
+ */
+static void
+zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi)
+{
+ rib_table_info_t *info;
+ struct route_table *table;
+
+ assert (!zvrf->table[afi][safi]);
+
+ table = route_table_init ();
+ zvrf->table[afi][safi] = table;
+
+ info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
+ info->zvrf = zvrf;
+ info->afi = afi;
+ info->safi = safi;
+ table->info = info;
+}
+
+/* Allocate new zebra VRF. */
+struct zebra_vrf *
+zebra_vrf_alloc (vrf_id_t vrf_id, const char *name)
+{
+ struct zebra_vrf *zvrf;
+
+ 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();
+
+ /* Set VRF ID */
+ zvrf->vrf_id = vrf_id;
+
+ if (name)
+ {
+ strncpy (zvrf->name, name, strlen(name));
+ zvrf->name[strlen(name)] = '\0';
+ }
+
+ return zvrf;
+}
+
+/* Lookup VRF by identifier. */
+struct zebra_vrf *
+zebra_vrf_lookup (vrf_id_t vrf_id)
+{
+ return vrf_info_lookup (vrf_id);
+}
+
+/* Lookup the routing table in an enabled VRF. */
+struct route_table *
+zebra_vrf_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
+{
+ struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
+
+ if (!zvrf)
+ return NULL;
+
+ if (afi >= AFI_MAX || safi >= SAFI_MAX)
+ return NULL;
+
+ return zvrf->table[afi][safi];
+}
+
+/* Lookup the static routing table in a VRF. */
+struct route_table *
+zebra_vrf_static_table (afi_t afi, safi_t safi, vrf_id_t vrf_id)
+{
+ struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id);
+
+ if (!zvrf)
+ return NULL;
+
+ if (afi >= AFI_MAX || safi >= SAFI_MAX)
+ return NULL;
+
+ return zvrf->stable[afi][safi];
+}
+
+struct route_table *
+zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id, vrf_id_t vrf_id)
+{
+ struct zebra_vrf *zvrf;
+ rib_table_info_t *info;
+ struct route_table *table;
+
+ zvrf = vrf_info_lookup (vrf_id);
+ if (! zvrf)
+ return NULL;
+
+ if(afi >= AFI_MAX)
+ return NULL;
+
+ if (table_id >= ZEBRA_KERNEL_TABLE_MAX)
+ return NULL;
+
+ if ((vrf_id == VRF_DEFAULT) && (table_id != RT_TABLE_MAIN) && (table_id != zebrad.rtm_table_default))
+ {
+ if (zvrf->other_table[afi][table_id] == NULL)
+ {
+ table = route_table_init();
+ info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
+ info->zvrf = zvrf;
+ info->afi = afi;
+ info->safi = SAFI_UNICAST;
+ table->info = info;
+ zvrf->other_table[afi][table_id] = table;
+ }
+
+ return (zvrf->other_table[afi][table_id]);
+ }
+
+ return zvrf->table[afi][SAFI_UNICAST];
+}
+
+/* Zebra VRF initialization. */
+void
+zebra_vrf_init (void)
+{
+ vrf_add_hook (VRF_NEW_HOOK, zebra_vrf_new);
+ vrf_add_hook (VRF_ENABLE_HOOK, zebra_vrf_enable);
+ vrf_add_hook (VRF_DISABLE_HOOK, zebra_vrf_disable);
+ vrf_add_hook (VRF_DELETE_HOOK, zebra_vrf_delete);
+
+ vrf_init ();
+}