*/
static int ns_enable(struct ns *ns)
{
+ int vrf_on = 0;
if (!ns_is_enabled(ns)) {
if (have_netns()) {
return 0;
}
+ /* Non default NS. leave */
+ if (ns->ns_id == NS_UNKNOWN) {
+ zlog_err("Can not enable NS %s %u: Invalid NSID",
+ ns->name, ns->ns_id);
+ return 0;
+ }
+ vrf_on = vrf_update_vrf_id((vrf_id_t)ns->ns_id,
+ (struct vrf *)ns->vrf_ctxt);
if (have_netns())
zlog_info("NS %u is associated with NETNS %s.",
ns->ns_id, ns->name);
zlog_info("NS %u is enabled.", ns->ns_id);
+ /* zebra first receives NS enable event,
+ * then VRF enable event
+ */
if (ns_master.ns_enable_hook)
(*ns_master.ns_enable_hook)(ns->ns_id, &ns->info);
+ if (vrf_on == 1)
+ vrf_enable((struct vrf *)ns->vrf_ctxt);
}
return 1;
* NS realization with NETNS
*/
-static char *ns_netns_pathname(struct vty *vty, const char *name)
+char *ns_netns_pathname(struct vty *vty, const char *name)
{
static char pathname[PATH_MAX];
char *result;
}
if (!result) {
- vty_out(vty, "Invalid pathname: %s\n", safe_strerror(errno));
+ if (vty)
+ vty_out(vty, "Invalid pathname: %s\n",
+ safe_strerror(errno));
return NULL;
}
return pathname;
return CMD_SUCCESS;
}
-DEFUN_NOSH (ns_netns,
- ns_netns_cmd,
- "netns NAME",
- "Attach VRF to a Namespace\n"
- "The file name in " NS_RUN_DIR ", or a full pathname\n")
+int ns_handler_create(struct vty *vty, struct vrf *vrf,
+ char *pathname, ns_id_t ns_id)
{
- int idx_name = 1;
struct ns *ns = NULL;
- char *pathname = ns_netns_pathname(vty, argv[idx_name]->arg);
-
- VTY_DECLVAR_CONTEXT(vrf, vrf);
-
- if (!pathname)
- return CMD_WARNING_CONFIG_FAILED;
if (!vrf)
return CMD_WARNING_CONFIG_FAILED;
if (vrf->vrf_id != VRF_UNKNOWN && vrf->ns_ctxt == NULL) {
- vty_out(vty, "VRF %u is already configured with VRF %s\n",
- vrf->vrf_id, vrf->name);
+ if (vty)
+ vty_out(vty,
+ "VRF %u is already configured with VRF %s\n",
+ vrf->vrf_id, vrf->name);
+ else
+ zlog_warn("VRF %u is already configured with VRF %s\n",
+ vrf->vrf_id, vrf->name);
return CMD_WARNING_CONFIG_FAILED;
}
if (vrf->ns_ctxt != NULL) {
ns = (struct ns *) vrf->ns_ctxt;
if (ns && 0 != strcmp(ns->name, pathname)) {
- vty_out(vty, "VRF %u is already configured"
- " with NETNS %s\n",
- vrf->vrf_id, ns->name);
+ if (vty)
+ vty_out(vty,
+ "VRF %u is already configured"
+ " with NETNS %s\n",
+ vrf->vrf_id, ns->name);
+ else
+ zlog_warn("VRF %u is already configured with NETNS %s",
+ vrf->vrf_id, ns->name);
return CMD_WARNING_CONFIG_FAILED;
}
}
if (ns && ns->vrf_ctxt) {
struct vrf *vrf2 = (struct vrf *)ns->vrf_ctxt;
- vty_out(vty, "NS %s is already configured"
- " with VRF %u(%s)\n",
- ns->name, vrf2->vrf_id, vrf2->name);
+ if (vty)
+ vty_out(vty, "NS %s is already configured"
+ " with VRF %u(%s)\n",
+ ns->name, vrf2->vrf_id, vrf2->name);
+ else
+ zlog_warn("NS %s is already configured with VRF %u(%s)",
+ ns->name, vrf2->vrf_id, vrf2->name);
return CMD_WARNING_CONFIG_FAILED;
} else if (!ns)
ns = ns_get_by_name(pathname);
+ if (ns_id != ns->ns_id) {
+ RB_REMOVE(ns_head, &ns_tree, ns);
+ ns->ns_id = ns_id;
+ RB_INSERT(ns_head, &ns_tree, ns);
+ }
+ ns->vrf_ctxt = (void *)vrf;
+ vrf->ns_ctxt = (void *)ns;
if (!ns_enable(ns)) {
- vty_out(vty, "Can not associate NS %u with NETNS %s\n",
- ns->ns_id, ns->name);
+ if (vty)
+ vty_out(vty, "Can not associate NS %u with NETNS %s\n",
+ ns->ns_id, ns->name);
+ else
+ zlog_warn("Can not associate NS %u with NETNS %s",
+ ns->ns_id, ns->name);
return CMD_WARNING_CONFIG_FAILED;
}
- vrf->ns_ctxt = (void *)ns;
- ns->vrf_ctxt = (void *)vrf;
return CMD_SUCCESS;
}
+
static int ns_logicalrouter_config_write(struct vty *vty)
{
struct ns *ns;
return write;
}
+DEFUN_NOSH (ns_netns,
+ ns_netns_cmd,
+ "netns NAME",
+ "Attach VRF to a Namespace\n"
+ "The file name in " NS_RUN_DIR ", or a full pathname\n")
+{
+ int idx_name = 1;
+ char *pathname = ns_netns_pathname(vty, argv[idx_name]->arg);
+
+ VTY_DECLVAR_CONTEXT(vrf, vrf);
+
+ if (!pathname)
+ return CMD_WARNING_CONFIG_FAILED;
+ return ns_handler_create(vty, vrf, pathname, NS_UNKNOWN);
+}
+
DEFUN (no_ns_netns,
no_ns_netns_cmd,
"no netns [NAME]",
ns = (struct ns *)vrf->ns_ctxt;
ns->vrf_ctxt = NULL;
+ vrf_disable(vrf);
+ /* vrf ID from VRF is necessary for Zebra
+ * so that propagate to other clients is done
+ */
+ RB_REMOVE(ns_head, &ns_tree, ns);
+ ns->ns_id = NS_UNKNOWN;
+ RB_INSERT(ns_head, &ns_tree, ns);
ns_delete(ns);
vrf->ns_ctxt = NULL;
return CMD_SUCCESS;
};
static int vrf_is_enabled(struct vrf *vrf);
-static void vrf_disable(struct vrf *vrf);
/* VRF list existance check by name. */
struct vrf *vrf_lookup_by_name(const char *name)
return strcmp(a->name, b->name);
}
+/* return 1 if vrf can be enabled */
+int vrf_update_vrf_id(vrf_id_t vrf_id, struct vrf *vrf)
+{
+ vrf_id_t old_vrf_id;
+
+ if (!vrf)
+ return 0;
+ old_vrf_id = vrf->vrf_id;
+ if (vrf_id == vrf->vrf_id)
+ return 0;
+ 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)
+ return 1;
+ return 0;
+}
+
/* Get a VRF. If not found, create one.
* Arg:
* name - The name of the vrf. May be NULL if unknown.
* The VRF_DELETE_HOOK callback will be called to inform
* that they must release the resources in the VRF.
*/
-static void vrf_disable(struct vrf *vrf)
+void vrf_disable(struct vrf *vrf)
{
if (!vrf_is_enabled(vrf))
return;
vrf_backend = vrf_backend_netns;
}
-/* vrf CLI commands */
-DEFUN_NOSH (vrf,
- vrf_cmd,
- "vrf NAME",
- "Select a VRF to configure\n"
- "VRF's name\n")
+int vrf_handler_create(struct vty *vty, const char *vrfname, struct vrf **vrf)
{
- int idx_name = 1;
- const char *vrfname = argv[idx_name]->arg;
struct vrf *vrfp;
if (strlen(vrfname) > VRF_NAMSIZ) {
- vty_out(vty,
- "%% VRF name %s is invalid: length exceeds "
- "%d characters\n",
- vrfname, VRF_NAMSIZ);
+ if (vty)
+ vty_out(vty,
+ "%% VRF name %s invalid: length exceeds %d bytes\n",
+ vrfname, VRF_NAMSIZ);
+ else
+ zlog_warn(
+ "%% VRF name %s invalid: length exceeds %d bytes\n",
+ vrfname, VRF_NAMSIZ);
return CMD_WARNING_CONFIG_FAILED;
}
vrfp = vrf_get(VRF_UNKNOWN, vrfname);
- VTY_PUSH_CONTEXT(VRF_NODE, vrfp);
+ if (vty)
+ VTY_PUSH_CONTEXT(VRF_NODE, vrfp);
+ if (vrf)
+ *vrf = vrfp;
return CMD_SUCCESS;
}
+/* vrf CLI commands */
+DEFUN_NOSH (vrf,
+ vrf_cmd,
+ "vrf NAME",
+ "Select a VRF to configure\n"
+ "VRF's name\n")
+{
+ int idx_name = 1;
+ const char *vrfname = argv[idx_name]->arg;
+
+ return vrf_handler_create(vty, vrfname, NULL);
+}
+
DEFUN_NOSH (no_vrf,
no_vrf_cmd,
"no vrf NAME",