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: Vadim Kochan <vadim4j@gmail.com>
This commit is contained in:
parent
e998e118dd
commit
b13ba03f54
|
|
@ -24,6 +24,7 @@ extern int timestamp_short;
|
||||||
extern char * _SL_;
|
extern char * _SL_;
|
||||||
extern int max_flush_loops;
|
extern int max_flush_loops;
|
||||||
extern int batch_mode;
|
extern int batch_mode;
|
||||||
|
extern bool do_all;
|
||||||
|
|
||||||
#ifndef IPPROTO_ESP
|
#ifndef IPPROTO_ESP
|
||||||
#define IPPROTO_ESP 50
|
#define IPPROTO_ESP 50
|
||||||
|
|
|
||||||
5
ip/ip.c
5
ip/ip.c
|
|
@ -36,6 +36,7 @@ char * _SL_ = NULL;
|
||||||
int force = 0;
|
int force = 0;
|
||||||
int max_flush_loops = 10;
|
int max_flush_loops = 10;
|
||||||
int batch_mode = 0;
|
int batch_mode = 0;
|
||||||
|
bool do_all = false;
|
||||||
|
|
||||||
struct rtnl_handle rth = { .fd = -1 };
|
struct rtnl_handle rth = { .fd = -1 };
|
||||||
|
|
||||||
|
|
@ -55,7 +56,7 @@ static void usage(void)
|
||||||
" -4 | -6 | -I | -D | -B | -0 |\n"
|
" -4 | -6 | -I | -D | -B | -0 |\n"
|
||||||
" -l[oops] { maximum-addr-flush-attempts } |\n"
|
" -l[oops] { maximum-addr-flush-attempts } |\n"
|
||||||
" -o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |\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);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -270,6 +271,8 @@ int main(int argc, char **argv)
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if (netns_switch(argv[1]))
|
if (netns_switch(argv[1]))
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
} else if (matches(opt, "-all") == 0) {
|
||||||
|
do_all = true;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Option \"%s\" is unknown, try \"ip -help\".\n", opt);
|
fprintf(stderr, "Option \"%s\" is unknown, try \"ip -help\".\n", opt);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
|
|
||||||
72
ip/ipnetns.c
72
ip/ipnetns.c
|
|
@ -26,7 +26,7 @@ static int usage(void)
|
||||||
fprintf(stderr, " ip netns delete NAME\n");
|
fprintf(stderr, " ip netns delete NAME\n");
|
||||||
fprintf(stderr, " ip netns identify [PID]\n");
|
fprintf(stderr, " ip netns identify [PID]\n");
|
||||||
fprintf(stderr, " ip netns pids NAME\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");
|
fprintf(stderr, " ip netns monitor\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
@ -51,29 +51,10 @@ static int netns_list(int argc, char **argv)
|
||||||
return 0;
|
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);
|
fflush(stdout);
|
||||||
|
if (do_fork) {
|
||||||
if (batch_mode) {
|
|
||||||
int status;
|
int status;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
|
|
@ -91,23 +72,56 @@ static int netns_exec(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WIFEXITED(status)) {
|
if (WIFEXITED(status)) {
|
||||||
/* ip must return the status of the child,
|
return WEXITSTATUS(status);
|
||||||
* but do_cmd() will add a minus to this,
|
|
||||||
* so let's add another one here to cancel it.
|
|
||||||
*/
|
|
||||||
return -WEXITSTATUS(status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (execvp(cmd, argv + 1) < 0)
|
if (execvp(cmd, argv) < 0)
|
||||||
fprintf(stderr, "exec of \"%s\" failed: %s\n",
|
fprintf(stderr, "exec of \"%s\" failed: %s\n",
|
||||||
cmd, strerror(errno));
|
cmd, strerror(errno));
|
||||||
_exit(1);
|
_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)
|
static int is_pid(const char *str)
|
||||||
{
|
{
|
||||||
int ch;
|
int ch;
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@ ip-netns \- process network namespace management
|
||||||
.I NETNSNAME
|
.I NETNSNAME
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "ip netns exec "
|
.BR "ip [-all] netns exec "
|
||||||
.I NETNSNAME command ...
|
.RI "[ " NETNSNAME " ] " command ...
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "ip netns monitor"
|
.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.
|
the named network namespace as their primary network namespace.
|
||||||
|
|
||||||
.TP
|
.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
|
.sp
|
||||||
This command allows applications that are network namespace unaware
|
This command allows applications that are network namespace unaware
|
||||||
to be run in something other than the default network namespace with
|
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
|
are used to move files from their network namespace specific location
|
||||||
to their default locations without affecting other processes.
|
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
|
.TP
|
||||||
.B ip netns monitor - Report as network namespace names are added and deleted
|
.B ip netns monitor - Report as network namespace names are added and deleted
|
||||||
.sp
|
.sp
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,8 @@ ip \- show / manipulate routing, devices, policy routing and tunnels
|
||||||
\fB\-f\fR[\fIamily\fR] {
|
\fB\-f\fR[\fIamily\fR] {
|
||||||
.BR inet " | " inet6 " | " ipx " | " dnet " | " link " } | "
|
.BR inet " | " inet6 " | " ipx " | " dnet " | " link " } | "
|
||||||
\fB\-o\fR[\fIneline\fR] |
|
\fB\-o\fR[\fIneline\fR] |
|
||||||
\fB\-n\fR[\fIetns\fR] name }
|
\fB\-n\fR[\fIetns\fR] name |
|
||||||
|
\fB\-a\fR[\fIll\fR] }
|
||||||
|
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
|
|
@ -155,6 +156,10 @@ to
|
||||||
.RI "-n[etns] " NETNS " [ " OPTIONS " ] " OBJECT " { " COMMAND " | "
|
.RI "-n[etns] " NETNS " [ " OPTIONS " ] " OBJECT " { " COMMAND " | "
|
||||||
.BR help " }"
|
.BR help " }"
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR "\-a" , " \-all"
|
||||||
|
executes specified command over all objects, it depends if command supports this option.
|
||||||
|
|
||||||
.SH IP - COMMAND SYNTAX
|
.SH IP - COMMAND SYNTAX
|
||||||
|
|
||||||
.SS
|
.SS
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue