summaryrefslogtreecommitdiff
path: root/zebra/zebra_vrf.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_vrf.c')
-rw-r--r--zebra/zebra_vrf.c116
1 files changed, 105 insertions, 11 deletions
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index e162347726..1cc7e8932b 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -20,6 +20,9 @@
*/
#include <zebra.h>
+/* for basename */
+#include <libgen.h>
+
#include "log.h"
#include "linklist.h"
#include "command.h"
@@ -158,7 +161,7 @@ static int zebra_vrf_enable(struct vrf *vrf)
table = route_table_init();
table->cleanup = zebra_rnhtable_node_cleanup;
- zvrf->import_check_table[afi] = table;
+ zvrf->rnh_table_multicast[afi] = table;
}
/* Kick off any VxLAN-EVPN processing. */
@@ -181,8 +184,6 @@ static int zebra_vrf_disable(struct vrf *vrf)
zlog_debug("VRF %s id %u is now inactive", zvrf_name(zvrf),
zvrf_id(zvrf));
- table_manager_disable(zvrf);
-
/* Stop any VxLAN-EVPN processing. */
zebra_vxlan_vrf_disable(zvrf);
@@ -203,8 +204,8 @@ static int zebra_vrf_disable(struct vrf *vrf)
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
route_table_finish(zvrf->rnh_table[afi]);
zvrf->rnh_table[afi] = NULL;
- route_table_finish(zvrf->import_check_table[afi]);
- zvrf->import_check_table[afi] = NULL;
+ route_table_finish(zvrf->rnh_table_multicast[afi]);
+ zvrf->rnh_table_multicast[afi] = NULL;
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
rib_close_table(zvrf->table[afi][safi]);
@@ -271,6 +272,8 @@ static int zebra_vrf_delete(struct vrf *vrf)
zlog_debug("VRF %s id %u deleted", zvrf_name(zvrf),
zvrf_id(zvrf));
+ table_manager_disable(zvrf);
+
/* clean-up work queues */
for (i = 0; i < MQ_SIZE; i++) {
struct listnode *lnode, *nnode;
@@ -305,8 +308,8 @@ static int zebra_vrf_delete(struct vrf *vrf)
if (zvrf->rnh_table[afi])
route_table_finish(zvrf->rnh_table[afi]);
- if (zvrf->import_check_table[afi])
- route_table_finish(zvrf->import_check_table[afi]);
+ if (zvrf->rnh_table_multicast[afi])
+ route_table_finish(zvrf->rnh_table[afi]);
}
otable = otable_pop(&zvrf->other_tables);
@@ -565,10 +568,8 @@ DEFPY (vrf_netns,
return CMD_WARNING_CONFIG_FAILED;
frr_with_privs(&zserv_privs) {
- ret = vrf_netns_handler_create(vty, vrf, pathname,
- NS_UNKNOWN,
- NS_UNKNOWN,
- NS_UNKNOWN);
+ ret = zebra_vrf_netns_handler_create(
+ vty, vrf, pathname, NS_UNKNOWN, NS_UNKNOWN, NS_UNKNOWN);
}
return ret;
@@ -607,12 +608,105 @@ DEFUN (no_vrf_netns,
return CMD_SUCCESS;
}
+/* if ns_id is different and not VRF_UNKNOWN,
+ * then update vrf identifier, and enable VRF
+ */
+static void vrf_update_vrf_id(ns_id_t ns_id, void *opaqueptr)
+{
+ ns_id_t vrf_id = (vrf_id_t)ns_id;
+ vrf_id_t old_vrf_id;
+ struct vrf *vrf = (struct vrf *)opaqueptr;
+
+ if (!vrf)
+ return;
+ old_vrf_id = vrf->vrf_id;
+ if (vrf_id == vrf->vrf_id)
+ return;
+ if (vrf->vrf_id != VRF_UNKNOWN)
+ RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
+ vrf->vrf_id = vrf_id;
+ RB_INSERT(vrf_id_head, &vrfs_by_id, vrf);
+ if (old_vrf_id == VRF_UNKNOWN)
+ vrf_enable(vrf);
+}
+
+int zebra_vrf_netns_handler_create(struct vty *vty, struct vrf *vrf,
+ char *pathname, ns_id_t ns_id,
+ ns_id_t internal_ns_id,
+ ns_id_t rel_def_ns_id)
+{
+ struct ns *ns = NULL;
+
+ if (!vrf)
+ return CMD_WARNING_CONFIG_FAILED;
+ if (vrf->vrf_id != VRF_UNKNOWN && vrf->ns_ctxt == NULL) {
+ if (vty)
+ vty_out(vty,
+ "VRF %u is already configured with VRF %s\n",
+ vrf->vrf_id, vrf->name);
+ else
+ zlog_info("VRF %u is already configured with VRF %s",
+ vrf->vrf_id, vrf->name);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ if (vrf->ns_ctxt != NULL) {
+ ns = (struct ns *)vrf->ns_ctxt;
+ if (!strcmp(ns->name, pathname)) {
+ if (vty)
+ vty_out(vty,
+ "VRF %u already configured with NETNS %s\n",
+ vrf->vrf_id, ns->name);
+ else
+ zlog_info(
+ "VRF %u already configured with NETNS %s",
+ vrf->vrf_id, ns->name);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
+ ns = ns_lookup_name(pathname);
+ if (ns && ns->vrf_ctxt) {
+ struct vrf *vrf2 = (struct vrf *)ns->vrf_ctxt;
+
+ if (vrf2 == vrf)
+ return CMD_SUCCESS;
+ if (vty)
+ vty_out(vty,
+ "NS %s is already configured with VRF %u(%s)\n",
+ ns->name, vrf2->vrf_id, vrf2->name);
+ else
+ zlog_info("NS %s is already configured with VRF %u(%s)",
+ ns->name, vrf2->vrf_id, vrf2->name);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ ns = ns_get_created(ns, pathname, ns_id);
+ ns->internal_ns_id = internal_ns_id;
+ ns->relative_default_ns = rel_def_ns_id;
+ ns->vrf_ctxt = (void *)vrf;
+ vrf->ns_ctxt = (void *)ns;
+ /* update VRF netns NAME */
+ strlcpy(vrf->data.l.netns_name, basename(pathname), NS_NAMSIZ);
+
+ if (!ns_enable(ns, vrf_update_vrf_id)) {
+ if (vty)
+ vty_out(vty, "Can not associate NS %u with NETNS %s\n",
+ ns->ns_id, ns->name);
+ else
+ zlog_info("Can not associate NS %u with NETNS %s",
+ ns->ns_id, ns->name);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return CMD_SUCCESS;
+}
+
/* Zebra VRF initialization. */
void zebra_vrf_init(void)
{
vrf_init(zebra_vrf_new, zebra_vrf_enable, zebra_vrf_disable,
zebra_vrf_delete, zebra_vrf_update);
+ hook_register(zserv_client_close, release_daemon_table_chunks);
+
vrf_cmd_init(vrf_config_write);
if (vrf_is_backend_netns() && ns_have_netns()) {