Commit b13ba03f authored by Vadim Kochan's avatar Vadim Kochan Committed by Stephen Hemminger

ip netns: Allow exec on each netns

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: default avatarVadim Kochan <vadim4j@gmail.com>
parent e998e118
......@@ -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
......
......@@ -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);
......
......@@ -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;
......
......@@ -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
......
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment