* [PATCH iproute2 v2 0/3] ip netns: Run over all netns
@ 2015-01-18 14:10 Vadim Kochan
2015-01-18 14:10 ` [PATCH iproute2 v2 1/3] lib: Exec func on each netns Vadim Kochan
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Vadim Kochan @ 2015-01-18 14:10 UTC (permalink / raw)
To: netdev; +Cc: Vadim Kochan
From: Vadim Kochan <vadim4j@gmail.com>
Allow 'ip netns del' and 'ip netns exec' run over each network namespace names.
'ip netns exec' executes command forcely on eacn nsname.
Added new '-all' 'ip' option to run over each netns,
it can be used for other utils as generic option.
v2:
Use '-all' option instead of netns name 'all'.
Vadim Kochan (3):
lib: Exec func on each netns
ip netns: Allow exec on each netns
ip netns: Delete all netns
include/namespace.h | 6 ++++
include/utils.h | 5 +++
ip/ip.c | 5 ++-
ip/ipnetns.c | 98 ++++++++++++++++++++++++++++++++---------------------
lib/namespace.c | 22 ++++++++++++
lib/utils.c | 28 +++++++++++++++
man/man8/ip-netns.8 | 28 ++++++++++++---
man/man8/ip.8 | 7 +++-
8 files changed, 153 insertions(+), 46 deletions(-)
--
2.1.3
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH iproute2 v2 1/3] lib: Exec func on each netns
2015-01-18 14:10 [PATCH iproute2 v2 0/3] ip netns: Run over all netns Vadim Kochan
@ 2015-01-18 14:10 ` Vadim Kochan
2015-01-18 14:10 ` [PATCH iproute2 v2 2/3] ip netns: Allow exec " Vadim Kochan
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Vadim Kochan @ 2015-01-18 14:10 UTC (permalink / raw)
To: netdev; +Cc: Vadim Kochan
From: Vadim Kochan <vadim4j@gmail.com>
Added possibility to run some func on each netns.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
---
include/namespace.h | 6 ++++++
include/utils.h | 4 ++++
lib/namespace.c | 22 ++++++++++++++++++++++
lib/utils.c | 28 ++++++++++++++++++++++++++++
4 files changed, 60 insertions(+)
diff --git a/include/namespace.h b/include/namespace.h
index b8c5cad..26898b0 100644
--- a/include/namespace.h
+++ b/include/namespace.h
@@ -43,5 +43,11 @@ static int setns(int fd, int nstype)
extern int netns_switch(char *netns);
extern int netns_get_fd(const char *netns);
+extern int netns_foreach(int (*func)(char *nsname, void *arg), void *arg);
+
+struct netns_func {
+ int (*func)(char *nsname, void *arg);
+ void *arg;
+};
#endif /* __NAMESPACE_H__ */
diff --git a/include/utils.h b/include/utils.h
index e1fe7cf..a8817d3 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -5,6 +5,7 @@
#include <asm/types.h>
#include <resolv.h>
#include <stdlib.h>
+#include <stdbool.h>
#include "libnetlink.h"
#include "ll_map.h"
@@ -162,4 +163,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
char **name, char **type, char **link, char **dev,
int *group, int *index);
+extern int do_each_netns(int (*func)(char *nsname, void *arg), void *arg,
+ bool show_label);
+
#endif /* __UTILS_H__ */
diff --git a/lib/namespace.c b/lib/namespace.c
index 65c1e3d..c03a103 100644
--- a/lib/namespace.c
+++ b/lib/namespace.c
@@ -99,3 +99,25 @@ int netns_get_fd(const char *name)
}
return open(path, O_RDONLY);
}
+
+int netns_foreach(int (*func)(char *nsname, void *arg), void *arg)
+{
+ DIR *dir;
+ struct dirent *entry;
+
+ dir = opendir(NETNS_RUN_DIR);
+ if (!dir)
+ return -1;
+
+ while ((entry = readdir(dir)) != NULL) {
+ if (strcmp(entry->d_name, ".") == 0)
+ continue;
+ if (strcmp(entry->d_name, "..") == 0)
+ continue;
+ if (func(entry->d_name, arg))
+ break;
+ }
+
+ closedir(dir);
+ return 0;
+}
diff --git a/lib/utils.c b/lib/utils.c
index f65ceaa..efebe18 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -31,6 +31,7 @@
#include "utils.h"
+#include "namespace.h"
int timestamp_short = 0;
@@ -878,3 +879,30 @@ void print_nlmsg_timestamp(FILE *fp, const struct nlmsghdr *n)
tstr[strlen(tstr)-1] = 0;
fprintf(fp, "Timestamp: %s %lu us\n", tstr, usecs);
}
+
+static int on_netns(char *nsname, void *arg)
+{
+ struct netns_func *f = arg;
+
+ if (netns_switch(nsname))
+ return -1;
+
+ return f->func(nsname, f->arg);
+}
+
+static int on_netns_label(char *nsname, void *arg)
+{
+ printf("\nnetns: %s\n", nsname);
+ return on_netns(nsname, arg);
+}
+
+int do_each_netns(int (*func)(char *nsname, void *arg), void *arg,
+ bool show_label)
+{
+ struct netns_func nsf = { .func = func, .arg = arg };
+
+ if (show_label)
+ return netns_foreach(on_netns_label, &nsf);
+
+ return netns_foreach(on_netns, &nsf);
+}
--
2.1.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH iproute2 v2 2/3] ip netns: Allow exec on each netns
2015-01-18 14:10 [PATCH iproute2 v2 0/3] ip netns: Run over all netns Vadim Kochan
2015-01-18 14:10 ` [PATCH iproute2 v2 1/3] lib: Exec func on each netns Vadim Kochan
@ 2015-01-18 14:10 ` Vadim Kochan
2015-01-18 14:10 ` [PATCH iproute2 v2 3/3] ip netns: Delete all netns Vadim Kochan
2015-02-05 18:29 ` [PATCH iproute2 v2 0/3] ip netns: Run over " Stephen Hemminger
3 siblings, 0 replies; 5+ messages in thread
From: Vadim Kochan @ 2015-01-18 14:10 UTC (permalink / raw)
To: netdev; +Cc: Vadim Kochan
From: Vadim Kochan <vadim4j@gmail.com>
This change allows to exec some cmd on each
named netns (except default) by specifying '-all' option:
# ip -all netns exec ip link
Each command executes synchronously.
Exit status is not considered, so there might be a case
that some CMD can fail on some netns but success on the other.
EXAMPLES:
1) Show link info on all netns:
$ ip -all netns exec ip link
netns: test_net
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
4: tap0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 500
link/ether 1a:19:6f:25:eb:85 brd ff:ff:ff:ff:ff:ff
netns: home0
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
4: tap0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 500
link/ether ea:1a:59:40:d3:29 brd ff:ff:ff:ff:ff:ff
netns: lan0
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
4: tap0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 500
link/ether ce:49:d5:46:81:ea brd ff:ff:ff:ff:ff:ff
2) Set UP tap0 device for the all netns:
$ ip -all netns exec ip link set dev tap0 up
netns: test_net
netns: home0
netns: lan0
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
---
include/utils.h | 1 +
ip/ip.c | 5 +++-
ip/ipnetns.c | 72 ++++++++++++++++++++++++++++++++---------------------
man/man8/ip-netns.8 | 16 +++++++++---
man/man8/ip.8 | 7 +++++-
5 files changed, 67 insertions(+), 34 deletions(-)
diff --git a/include/utils.h b/include/utils.h
index a8817d3..3da2283 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -24,6 +24,7 @@ extern int timestamp_short;
extern char * _SL_;
extern int max_flush_loops;
extern int batch_mode;
+extern bool do_all;
#ifndef IPPROTO_ESP
#define IPPROTO_ESP 50
diff --git a/ip/ip.c b/ip/ip.c
index 850a001..da16b15 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -36,6 +36,7 @@ char * _SL_ = NULL;
int force = 0;
int max_flush_loops = 10;
int batch_mode = 0;
+bool do_all = false;
struct rtnl_handle rth = { .fd = -1 };
@@ -55,7 +56,7 @@ static void usage(void)
" -4 | -6 | -I | -D | -B | -0 |\n"
" -l[oops] { maximum-addr-flush-attempts } |\n"
" -o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |\n"
-" -rc[vbuf] [size] | -n[etns] name }\n");
+" -rc[vbuf] [size] | -n[etns] name | -a[ll] }\n");
exit(-1);
}
@@ -270,6 +271,8 @@ int main(int argc, char **argv)
NEXT_ARG();
if (netns_switch(argv[1]))
exit(-1);
+ } else if (matches(opt, "-all") == 0) {
+ do_all = true;
} else {
fprintf(stderr, "Option \"%s\" is unknown, try \"ip -help\".\n", opt);
exit(-1);
diff --git a/ip/ipnetns.c b/ip/ipnetns.c
index 123318e..59a9321 100644
--- a/ip/ipnetns.c
+++ b/ip/ipnetns.c
@@ -26,7 +26,7 @@ static int usage(void)
fprintf(stderr, " ip netns delete NAME\n");
fprintf(stderr, " ip netns identify [PID]\n");
fprintf(stderr, " ip netns pids NAME\n");
- fprintf(stderr, " ip netns exec NAME cmd ...\n");
+ fprintf(stderr, " ip [-all] netns exec [NAME] cmd ...\n");
fprintf(stderr, " ip netns monitor\n");
exit(-1);
}
@@ -51,29 +51,10 @@ static int netns_list(int argc, char **argv)
return 0;
}
-static int netns_exec(int argc, char **argv)
+static int cmd_exec(const char *cmd, char **argv, bool do_fork)
{
- /* Setup the proper environment for apps that are not netns
- * aware, and execute a program in that environment.
- */
- const char *cmd;
-
- if (argc < 1) {
- fprintf(stderr, "No netns name specified\n");
- return -1;
- }
- if (argc < 2) {
- fprintf(stderr, "No command specified\n");
- return -1;
- }
- cmd = argv[1];
-
- if (netns_switch(argv[0]))
- return -1;
-
fflush(stdout);
-
- if (batch_mode) {
+ if (do_fork) {
int status;
pid_t pid;
@@ -91,23 +72,56 @@ static int netns_exec(int argc, char **argv)
}
if (WIFEXITED(status)) {
- /* ip must return the status of the child,
- * but do_cmd() will add a minus to this,
- * so let's add another one here to cancel it.
- */
- return -WEXITSTATUS(status);
+ return WEXITSTATUS(status);
}
exit(1);
}
}
- if (execvp(cmd, argv + 1) < 0)
+ if (execvp(cmd, argv) < 0)
fprintf(stderr, "exec of \"%s\" failed: %s\n",
- cmd, strerror(errno));
+ cmd, strerror(errno));
_exit(1);
}
+static int on_netns_exec(char *nsname, void *arg)
+{
+ char **argv = arg;
+ cmd_exec(argv[1], argv + 1, true);
+ return 0;
+}
+
+static int netns_exec(int argc, char **argv)
+{
+ /* Setup the proper environment for apps that are not netns
+ * aware, and execute a program in that environment.
+ */
+ const char *cmd;
+
+ if (argc < 1 && !do_all) {
+ fprintf(stderr, "No netns name specified\n");
+ return -1;
+ }
+ if ((argc < 2 && !do_all) || (argc < 1 && do_all)) {
+ fprintf(stderr, "No command specified\n");
+ return -1;
+ }
+
+ if (do_all)
+ return do_each_netns(on_netns_exec, --argv, 1);
+
+ if (netns_switch(argv[0]))
+ return -1;
+
+ /* ip must return the status of the child,
+ * but do_cmd() will add a minus to this,
+ * so let's add another one here to cancel it.
+ */
+ cmd = argv[1];
+ return -cmd_exec(cmd, argv + 1, !!batch_mode);
+}
+
static int is_pid(const char *str)
{
int ch;
diff --git a/man/man8/ip-netns.8 b/man/man8/ip-netns.8
index 74343ed..7b9571e 100644
--- a/man/man8/ip-netns.8
+++ b/man/man8/ip-netns.8
@@ -28,8 +28,8 @@ ip-netns \- process network namespace management
.I NETNSNAME
.ti -8
-.BR "ip netns exec "
-.I NETNSNAME command ...
+.BR "ip [-all] netns exec "
+.RI "[ " NETNSNAME " ] " command ...
.ti -8
.BR "ip netns monitor"
@@ -98,7 +98,7 @@ This command walks through proc and finds all of the process who have
the named network namespace as their primary network namespace.
.TP
-.B ip netns exec NAME cmd ... - Run cmd in the named network namespace
+.B ip [-all] netns exec [ NAME ] cmd ... - Run cmd in the named network namespace
.sp
This command allows applications that are network namespace unaware
to be run in something other than the default network namespace with
@@ -107,6 +107,16 @@ in the customary global locations. A network namespace and bind mounts
are used to move files from their network namespace specific location
to their default locations without affecting other processes.
+If
+.B -all
+option was specified then
+.B cmd
+will be executed synchronously on the each named network namespace even if
+.B cmd
+fails on some of them. Network namespace name is printed on each
+.B cmd
+executing.
+
.TP
.B ip netns monitor - Report as network namespace names are added and deleted
.sp
diff --git a/man/man8/ip.8 b/man/man8/ip.8
index 0bae59e..016e8c6 100644
--- a/man/man8/ip.8
+++ b/man/man8/ip.8
@@ -32,7 +32,8 @@ ip \- show / manipulate routing, devices, policy routing and tunnels
\fB\-f\fR[\fIamily\fR] {
.BR inet " | " inet6 " | " ipx " | " dnet " | " link " } | "
\fB\-o\fR[\fIneline\fR] |
-\fB\-n\fR[\fIetns\fR] name }
+\fB\-n\fR[\fIetns\fR] name |
+\fB\-a\fR[\fIll\fR] }
.SH OPTIONS
@@ -155,6 +156,10 @@ to
.RI "-n[etns] " NETNS " [ " OPTIONS " ] " OBJECT " { " COMMAND " | "
.BR help " }"
+.TP
+.BR "\-a" , " \-all"
+executes specified command over all objects, it depends if command supports this option.
+
.SH IP - COMMAND SYNTAX
.SS
--
2.1.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH iproute2 v2 3/3] ip netns: Delete all netns
2015-01-18 14:10 [PATCH iproute2 v2 0/3] ip netns: Run over all netns Vadim Kochan
2015-01-18 14:10 ` [PATCH iproute2 v2 1/3] lib: Exec func on each netns Vadim Kochan
2015-01-18 14:10 ` [PATCH iproute2 v2 2/3] ip netns: Allow exec " Vadim Kochan
@ 2015-01-18 14:10 ` Vadim Kochan
2015-02-05 18:29 ` [PATCH iproute2 v2 0/3] ip netns: Run over " Stephen Hemminger
3 siblings, 0 replies; 5+ messages in thread
From: Vadim Kochan @ 2015-01-18 14:10 UTC (permalink / raw)
To: netdev; +Cc: Vadim Kochan
From: Vadim Kochan <vadim4j@gmail.com>
Allow delete all namespace names by:
$ ip -all netns del
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
---
ip/ipnetns.c | 26 ++++++++++++++++----------
man/man8/ip-netns.8 | 12 ++++++++++--
2 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/ip/ipnetns.c b/ip/ipnetns.c
index 59a9321..e4038ea 100644
--- a/ip/ipnetns.c
+++ b/ip/ipnetns.c
@@ -23,7 +23,7 @@ static int usage(void)
{
fprintf(stderr, "Usage: ip netns list\n");
fprintf(stderr, " ip netns add NAME\n");
- fprintf(stderr, " ip netns delete NAME\n");
+ fprintf(stderr, " ip [-all] netns delete [NAME]\n");
fprintf(stderr, " ip netns identify [PID]\n");
fprintf(stderr, " ip netns pids NAME\n");
fprintf(stderr, " ip [-all] netns exec [NAME] cmd ...\n");
@@ -259,18 +259,11 @@ static int netns_identify(int argc, char **argv)
}
-static int netns_delete(int argc, char **argv)
+static int on_netns_del(char *nsname, void *arg)
{
- const char *name;
char netns_path[MAXPATHLEN];
- if (argc < 1) {
- fprintf(stderr, "No netns name specified\n");
- return -1;
- }
-
- name = argv[0];
- snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name);
+ snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, nsname);
umount2(netns_path, MNT_DETACH);
if (unlink(netns_path) < 0) {
fprintf(stderr, "Cannot remove namespace file \"%s\": %s\n",
@@ -280,6 +273,19 @@ static int netns_delete(int argc, char **argv)
return 0;
}
+static int netns_delete(int argc, char **argv)
+{
+ if (argc < 1 && !do_all) {
+ fprintf(stderr, "No netns name specified\n");
+ return -1;
+ }
+
+ if (do_all)
+ return netns_foreach(on_netns_del, NULL);
+
+ return on_netns_del(argv[0], NULL);
+}
+
static int create_netns_dir(void)
{
/* Create the base netns directory if it doesn't exist */
diff --git a/man/man8/ip-netns.8 b/man/man8/ip-netns.8
index 7b9571e..8e6999c 100644
--- a/man/man8/ip-netns.8
+++ b/man/man8/ip-netns.8
@@ -16,10 +16,14 @@ ip-netns \- process network namespace management
.BR "ip netns" " { " list " } "
.ti -8
-.BR "ip netns" " { " add " | " delete " } "
+.B ip netns add
.I NETNSNAME
.ti -8
+.B ip [-all] netns del
+.RI "[ " NETNSNAME " ]"
+
+.ti -8
.BR "ip netns identify"
.RI "[ " PID " ]"
@@ -76,7 +80,7 @@ If NAME is available in /var/run/netns/ this command creates a new
network namespace and assigns NAME.
.TP
-.B ip netns delete NAME - delete the name of a network namespace
+.B ip [-all] netns delete [ NAME ] - delete the name of a network namespace(s)
.sp
If NAME is present in /var/run/netns it is umounted and the mount
point is removed. If this is the last user of the network namespace the
@@ -84,6 +88,10 @@ network namespace will be freed, otherwise the network namespace
persists until it has no more users. ip netns delete may fail if
the mount point is in use in another mount namespace.
+If
+.B -all
+option was specified then all the network namespace names will be removed.
+
.TP
.B ip netns identify [PID] - Report network namespaces names for process
.sp
--
2.1.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH iproute2 v2 0/3] ip netns: Run over all netns
2015-01-18 14:10 [PATCH iproute2 v2 0/3] ip netns: Run over all netns Vadim Kochan
` (2 preceding siblings ...)
2015-01-18 14:10 ` [PATCH iproute2 v2 3/3] ip netns: Delete all netns Vadim Kochan
@ 2015-02-05 18:29 ` Stephen Hemminger
3 siblings, 0 replies; 5+ messages in thread
From: Stephen Hemminger @ 2015-02-05 18:29 UTC (permalink / raw)
To: Vadim Kochan; +Cc: netdev
On Sun, 18 Jan 2015 16:10:16 +0200
Vadim Kochan <vadim4j@gmail.com> wrote:
> From: Vadim Kochan <vadim4j@gmail.com>
>
> Allow 'ip netns del' and 'ip netns exec' run over each network namespace names.
>
> 'ip netns exec' executes command forcely on eacn nsname.
>
> Added new '-all' 'ip' option to run over each netns,
> it can be used for other utils as generic option.
>
> v2:
> Use '-all' option instead of netns name 'all'.
>
> Vadim Kochan (3):
> lib: Exec func on each netns
> ip netns: Allow exec on each netns
> ip netns: Delete all netns
>
> include/namespace.h | 6 ++++
> include/utils.h | 5 +++
> ip/ip.c | 5 ++-
> ip/ipnetns.c | 98 ++++++++++++++++++++++++++++++++---------------------
> lib/namespace.c | 22 ++++++++++++
> lib/utils.c | 28 +++++++++++++++
> man/man8/ip-netns.8 | 28 ++++++++++++---
> man/man8/ip.8 | 7 +++-
> 8 files changed, 153 insertions(+), 46 deletions(-)
>
Accepted
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2015-02-05 18:29 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-01-18 14:10 [PATCH iproute2 v2 0/3] ip netns: Run over all netns Vadim Kochan
2015-01-18 14:10 ` [PATCH iproute2 v2 1/3] lib: Exec func on each netns Vadim Kochan
2015-01-18 14:10 ` [PATCH iproute2 v2 2/3] ip netns: Allow exec " Vadim Kochan
2015-01-18 14:10 ` [PATCH iproute2 v2 3/3] ip netns: Delete all netns Vadim Kochan
2015-02-05 18:29 ` [PATCH iproute2 v2 0/3] ip netns: Run over " Stephen Hemminger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).