2 * Zebra NS collector and notifier for Network NameSpaces
3 * Copyright (C) 2017 6WIND
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 #include <sys/inotify.h>
37 #include "lib_errors.h"
39 #include "zebra_router.h"
40 #endif /* defined(HAVE_NETLINK) */
42 #include "zebra_netns_notify.h"
43 #include "zebra_netns_id.h"
44 #include "zebra_errors.h"
45 #include "interface.h"
49 /* upon creation of folder under /var/run/netns,
50 * wait that netns context is bound to
51 * that folder 10 seconds
53 #define ZEBRA_NS_POLLING_INTERVAL_MSEC 1000
54 #define ZEBRA_NS_POLLING_MAX_RETRIES 200
56 DEFINE_MTYPE_STATIC(ZEBRA
, NETNS_MISC
, "ZebraNetNSInfo");
57 static struct thread
*zebra_netns_notify_current
;
59 struct zebra_netns_info
{
60 const char *netnspath
;
64 static void zebra_ns_ready_read(struct thread
*t
);
65 static void zebra_ns_notify_create_context_from_entry_name(const char *name
);
66 static int zebra_ns_continue_read(struct zebra_netns_info
*zns_info
,
68 static void zebra_ns_notify_read(struct thread
*t
);
70 static struct vrf
*vrf_handler_create(struct vty
*vty
, const char *vrfname
)
72 if (strlen(vrfname
) > VRF_NAMSIZ
) {
73 flog_warn(EC_LIB_VRF_LENGTH
,
74 "%% VRF name %s invalid: length exceeds %d bytes",
79 return vrf_get(VRF_UNKNOWN
, vrfname
);
82 static void zebra_ns_notify_create_context_from_entry_name(const char *name
)
84 char *netnspath
= ns_netns_pathname(NULL
, name
);
87 ns_id_t ns_id
, ns_id_external
, ns_id_relative
= NS_UNKNOWN
;
88 struct ns
*default_ns
;
90 if (netnspath
== NULL
)
93 frr_with_privs(&zserv_privs
) {
94 ns_id
= zebra_ns_id_get(netnspath
, -1);
96 if (ns_id
== NS_UNKNOWN
)
98 ns_id_external
= ns_map_nsid_with_external(ns_id
, true);
99 /* if VRF with NS ID already present */
100 vrf
= vrf_lookup_by_id((vrf_id_t
)ns_id_external
);
103 "NS notify : same NSID used by VRF %s. Ignore NS %s creation",
104 vrf
->name
, netnspath
);
107 vrf
= vrf_handler_create(NULL
, name
);
109 flog_warn(EC_ZEBRA_NS_VRF_CREATION_FAILED
,
110 "NS notify : failed to create VRF %s", name
);
111 ns_map_nsid_with_external(ns_id
, false);
115 default_ns
= ns_get_default();
117 /* force kernel ns_id creation in that new vrf */
118 frr_with_privs(&zserv_privs
) {
119 ns_switch_to_netns(netnspath
);
120 ns_id_relative
= zebra_ns_id_get(NULL
, default_ns
->fd
);
121 ns_switchback_to_initial();
124 frr_with_privs(&zserv_privs
) {
125 ret
= zebra_vrf_netns_handler_create(NULL
, vrf
, netnspath
,
126 ns_id_external
, ns_id
,
129 if (ret
!= CMD_SUCCESS
) {
130 flog_warn(EC_ZEBRA_NS_VRF_CREATION_FAILED
,
131 "NS notify : failed to create NS %s", netnspath
);
132 ns_map_nsid_with_external(ns_id
, false);
136 zlog_info("NS notify : created VRF %s NS %s", name
, netnspath
);
139 static int zebra_ns_continue_read(struct zebra_netns_info
*zns_info
,
142 void *ns_path_ptr
= (void *)zns_info
->netnspath
;
145 XFREE(MTYPE_NETNS_MISC
, ns_path_ptr
);
146 XFREE(MTYPE_NETNS_MISC
, zns_info
);
149 thread_add_timer_msec(zrouter
.master
, zebra_ns_ready_read
,
150 (void *)zns_info
, ZEBRA_NS_POLLING_INTERVAL_MSEC
,
155 static int zebra_ns_delete(char *name
)
157 struct vrf
*vrf
= vrf_lookup_by_name(name
);
158 struct interface
*ifp
, *tmp
;
162 flog_warn(EC_ZEBRA_NS_DELETION_FAILED_NO_VRF
,
163 "NS notify : no VRF found using NS %s", name
);
168 * We don't receive interface down/delete notifications from kernel
169 * when a netns is deleted. Therefore we have to manually replicate
170 * the necessary actions here.
172 RB_FOREACH_SAFE (ifp
, if_name_head
, &vrf
->ifaces_by_name
, tmp
) {
173 if (!CHECK_FLAG(ifp
->status
, ZEBRA_INTERFACE_ACTIVE
))
176 if (if_is_no_ptm_operative(ifp
)) {
177 UNSET_FLAG(ifp
->flags
, IFF_RUNNING
);
181 UNSET_FLAG(ifp
->flags
, IFF_UP
);
182 if_delete_update(&ifp
);
185 ns
= (struct ns
*)vrf
->ns_ctxt
;
186 /* the deletion order is the same
187 * as the one used when siging signal is received
194 zlog_info("NS notify : deleted VRF %s", name
);
198 static int zebra_ns_notify_self_identify(struct stat
*netst
)
200 char net_path
[PATH_MAX
];
203 snprintf(net_path
, sizeof(net_path
), "/proc/self/ns/net");
204 netns
= open(net_path
, O_RDONLY
);
207 if (fstat(netns
, netst
) < 0) {
215 static bool zebra_ns_notify_is_default_netns(const char *name
)
217 struct stat default_netns_stat
;
219 char netnspath
[PATH_MAX
];
221 if (zebra_ns_notify_self_identify(&default_netns_stat
))
224 memset(&st
, 0, sizeof(struct stat
));
225 snprintf(netnspath
, sizeof(netnspath
), "%s/%s", NS_RUN_DIR
, name
);
226 /* compare with local stat */
227 if (stat(netnspath
, &st
) == 0 &&
228 (st
.st_dev
== default_netns_stat
.st_dev
) &&
229 (st
.st_ino
== default_netns_stat
.st_ino
))
234 static void zebra_ns_ready_read(struct thread
*t
)
236 struct zebra_netns_info
*zns_info
= THREAD_ARG(t
);
237 const char *netnspath
;
238 int err
, stop_retry
= 0;
242 if (!zns_info
->netnspath
) {
243 XFREE(MTYPE_NETNS_MISC
, zns_info
);
246 netnspath
= zns_info
->netnspath
;
247 if (--zns_info
->retries
== 0)
249 frr_with_privs(&zserv_privs
) {
250 err
= ns_switch_to_netns(netnspath
);
253 zebra_ns_continue_read(zns_info
, stop_retry
);
257 /* go back to default ns */
258 frr_with_privs(&zserv_privs
) {
259 err
= ns_switchback_to_initial();
262 zebra_ns_continue_read(zns_info
, stop_retry
);
266 /* check default name is not already set */
267 if (strmatch(VRF_DEFAULT_NAME
, basename(netnspath
))) {
268 zlog_warn("NS notify : NS %s is already default VRF.Cancel VRF Creation", basename(netnspath
));
269 zebra_ns_continue_read(zns_info
, 1);
272 if (zebra_ns_notify_is_default_netns(basename(netnspath
))) {
274 "NS notify : NS %s is default VRF. Ignore VRF creation",
275 basename(netnspath
));
276 zebra_ns_continue_read(zns_info
, 1);
280 /* success : close fd and create zns context */
281 zebra_ns_notify_create_context_from_entry_name(basename(netnspath
));
282 zebra_ns_continue_read(zns_info
, 1);
285 static void zebra_ns_notify_read(struct thread
*t
)
287 int fd_monitor
= THREAD_FD(t
);
288 struct inotify_event
*event
;
292 thread_add_read(zrouter
.master
, zebra_ns_notify_read
, NULL
, fd_monitor
,
293 &zebra_netns_notify_current
);
294 len
= read(fd_monitor
, buf
, sizeof(buf
));
296 flog_err_sys(EC_ZEBRA_NS_NOTIFY_READ
,
297 "NS notify read: failed to read (%s)",
298 safe_strerror(errno
));
301 for (event
= (struct inotify_event
*)buf
; (char *)event
< &buf
[len
];
302 event
= (struct inotify_event
*)((char *)event
+ sizeof(*event
)
305 struct zebra_netns_info
*netnsinfo
;
307 if (!(event
->mask
& (IN_CREATE
| IN_DELETE
)))
310 if (offsetof(struct inotify_event
, name
) + event
->len
312 flog_err(EC_ZEBRA_NS_NOTIFY_READ
,
313 "NS notify read: buffer underflow");
317 if (strnlen(event
->name
, event
->len
) == event
->len
) {
318 flog_err(EC_ZEBRA_NS_NOTIFY_READ
,
319 "NS notify error: bad event name");
323 if (event
->mask
& IN_DELETE
) {
324 zebra_ns_delete(event
->name
);
327 netnspath
= ns_netns_pathname(NULL
, event
->name
);
330 netnspath
= XSTRDUP(MTYPE_NETNS_MISC
, netnspath
);
331 netnsinfo
= XCALLOC(MTYPE_NETNS_MISC
,
332 sizeof(struct zebra_netns_info
));
333 netnsinfo
->retries
= ZEBRA_NS_POLLING_MAX_RETRIES
;
334 netnsinfo
->netnspath
= netnspath
;
335 thread_add_timer_msec(zrouter
.master
, zebra_ns_ready_read
,
336 (void *)netnsinfo
, 0, NULL
);
340 void zebra_ns_notify_parse(void)
343 DIR *srcdir
= opendir(NS_RUN_DIR
);
345 if (srcdir
== NULL
) {
346 flog_err_sys(EC_LIB_SYSTEM_CALL
,
347 "NS parsing init: failed to parse %s", NS_RUN_DIR
);
350 while ((dent
= readdir(srcdir
)) != NULL
) {
353 if (strcmp(dent
->d_name
, ".") == 0
354 || strcmp(dent
->d_name
, "..") == 0)
356 if (fstatat(dirfd(srcdir
), dent
->d_name
, &st
, 0) < 0) {
359 "NS parsing init: failed to parse entry %s",
363 if (S_ISDIR(st
.st_mode
)) {
364 zlog_debug("NS parsing init: %s is not a NS",
368 /* check default name is not already set */
369 if (strmatch(VRF_DEFAULT_NAME
, basename(dent
->d_name
))) {
370 zlog_warn("NS notify : NS %s is already default VRF.Cancel VRF Creation", dent
->d_name
);
373 if (zebra_ns_notify_is_default_netns(dent
->d_name
)) {
375 "NS notify : NS %s is default VRF. Ignore VRF creation",
379 zebra_ns_notify_create_context_from_entry_name(dent
->d_name
);
384 void zebra_ns_notify_init(void)
388 fd_monitor
= inotify_init();
389 if (fd_monitor
< 0) {
392 "NS notify init: failed to initialize inotify (%s)",
393 safe_strerror(errno
));
395 if (inotify_add_watch(fd_monitor
, NS_RUN_DIR
,
396 IN_CREATE
| IN_DELETE
) < 0) {
397 flog_err_sys(EC_LIB_SYSTEM_CALL
,
398 "NS notify watch: failed to add watch (%s)",
399 safe_strerror(errno
));
401 thread_add_read(zrouter
.master
, zebra_ns_notify_read
, NULL
, fd_monitor
,
402 &zebra_netns_notify_current
);
405 void zebra_ns_notify_close(void)
407 if (zebra_netns_notify_current
== NULL
)
412 if (zebra_netns_notify_current
->u
.fd
> 0)
413 fd
= zebra_netns_notify_current
->u
.fd
;
415 if (zebra_netns_notify_current
->master
!= NULL
)
416 thread_cancel(&zebra_netns_notify_current
);
418 /* auto-removal of notify items */
424 void zebra_ns_notify_parse(void)
428 void zebra_ns_notify_init(void)
432 void zebra_ns_notify_close(void)
435 #endif /* !HAVE_NETLINK */