diff options
author | Donald Sharp <sharpd@cumulusnetworks.com> | 2016-04-14 15:20:47 +0200 |
---|---|---|
committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2016-04-15 02:57:04 +0200 |
commit | 7c5519562ec585e9f75fd4dfd88710f4c9df5567 (patch) | |
tree | cff935dc5927ebe4ef322e0f21c763ba0d5363da /zebra/zebra_vrf.c | |
parent | lib, zebra: Rework zebra_ns to be a bit more modular (diff) | |
download | frr-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.c | 306 |
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 (); +} |