diff options
Diffstat (limited to 'zebra/zebra_netns_notify.c')
| -rw-r--r-- | zebra/zebra_netns_notify.c | 52 |
1 files changed, 43 insertions, 9 deletions
diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c index 61f97ce6a9..391f28d18f 100644 --- a/zebra/zebra_netns_notify.c +++ b/zebra/zebra_netns_notify.c @@ -42,6 +42,7 @@ #include "zebra_netns_notify.h" #include "zebra_netns_id.h" #include "zebra_errors.h" +#include "interface.h" #ifdef HAVE_NETLINK @@ -66,6 +67,18 @@ static int zebra_ns_continue_read(struct zebra_netns_info *zns_info, int stop_retry); static int zebra_ns_notify_read(struct thread *t); +static struct vrf *vrf_handler_create(struct vty *vty, const char *vrfname) +{ + if (strlen(vrfname) > VRF_NAMSIZ) { + flog_warn(EC_LIB_VRF_LENGTH, + "%% VRF name %s invalid: length exceeds %d bytes", + vrfname, VRF_NAMSIZ); + return NULL; + } + + return vrf_get(VRF_UNKNOWN, vrfname); +} + static void zebra_ns_notify_create_context_from_entry_name(const char *name) { char *netnspath = ns_netns_pathname(NULL, name); @@ -91,7 +104,8 @@ static void zebra_ns_notify_create_context_from_entry_name(const char *name) vrf->name, netnspath); return; } - if (vrf_handler_create(NULL, name, &vrf) != CMD_SUCCESS) { + vrf = vrf_handler_create(NULL, name); + if (!vrf) { flog_warn(EC_ZEBRA_NS_VRF_CREATION_FAILED, "NS notify : failed to create VRF %s", name); ns_map_nsid_with_external(ns_id, false); @@ -108,10 +122,9 @@ static void zebra_ns_notify_create_context_from_entry_name(const char *name) } frr_with_privs(&zserv_privs) { - ret = vrf_netns_handler_create(NULL, vrf, netnspath, - ns_id_external, - ns_id, - ns_id_relative); + ret = zebra_vrf_netns_handler_create(NULL, vrf, netnspath, + ns_id_external, ns_id, + ns_id_relative); } if (ret != CMD_SUCCESS) { flog_warn(EC_ZEBRA_NS_VRF_CREATION_FAILED, @@ -142,6 +155,7 @@ static int zebra_ns_continue_read(struct zebra_netns_info *zns_info, static int zebra_ns_delete(char *name) { struct vrf *vrf = vrf_lookup_by_name(name); + struct interface *ifp, *tmp; struct ns *ns; if (!vrf) { @@ -149,10 +163,30 @@ static int zebra_ns_delete(char *name) "NS notify : no VRF found using NS %s", name); return 0; } + + /* + * We don't receive interface down/delete notifications from kernel + * when a netns is deleted. Therefore we have to manually replicate + * the necessary actions here. + */ + RB_FOREACH_SAFE (ifp, if_name_head, &vrf->ifaces_by_name, tmp) { + if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) + continue; + + if (if_is_no_ptm_operative(ifp)) { + UNSET_FLAG(ifp->flags, IFF_RUNNING); + if_down(ifp); + } + + UNSET_FLAG(ifp->flags, IFF_UP); + if_delete_update(ifp); + } + ns = (struct ns *)vrf->ns_ctxt; /* the deletion order is the same * as the one used when siging signal is received */ + vrf->ns_ctxt = NULL; vrf_delete(vrf); if (ns) ns_delete(ns); @@ -249,8 +283,8 @@ static int zebra_ns_notify_read(struct thread *t) char buf[BUFSIZ]; ssize_t len; - zebra_netns_notify_current = thread_add_read( - zrouter.master, zebra_ns_notify_read, NULL, fd_monitor, NULL); + thread_add_read(zrouter.master, zebra_ns_notify_read, NULL, fd_monitor, + &zebra_netns_notify_current); len = read(fd_monitor, buf, sizeof(buf)); if (len < 0) { flog_err_sys(EC_ZEBRA_NS_NOTIFY_READ, @@ -359,8 +393,8 @@ void zebra_ns_notify_init(void) "NS notify watch: failed to add watch (%s)", safe_strerror(errno)); } - zebra_netns_notify_current = thread_add_read( - zrouter.master, zebra_ns_notify_read, NULL, fd_monitor, NULL); + thread_add_read(zrouter.master, zebra_ns_notify_read, NULL, fd_monitor, + &zebra_netns_notify_current); } void zebra_ns_notify_close(void) |
