* [PATCH iproute2 0/2] refactor the 'ip netns exec' command
@ 2019-06-10 22:16 Matteo Croce
2019-06-10 22:16 ` [PATCH iproute2 1/2] netns: switch netns in the child when executing commands Matteo Croce
2019-06-10 22:16 ` [PATCH iproute2 2/2] netns: make netns_{save,restore} static Matteo Croce
0 siblings, 2 replies; 7+ messages in thread
From: Matteo Croce @ 2019-06-10 22:16 UTC (permalink / raw)
To: netdev; +Cc: David Ahern, Stephen Hemminger
Refactor the netns code so less steps are needed to exec commands in a netns.
Also remove some code which became dead. bloat-o-meter output:
$ bloat-o-meter ip.old ip
add/remove: 0/5 grow/shrink: 3/3 up/down: 159/-358 (-199)
Function old new delta
netns_add 971 1058 +87
cmd_exec 207 254 +47
on_netns_exec 32 57 +25
netns_restore 69 67 -2
netns_switch 838 822 -16
on_netns_label 45 - -45
do_netns 1226 1180 -46
vrf_reset 55 - -55
do_each_netns 57 - -57
on_netns 60 - -60
netns_save 77 - -77
Total: Before=667505, After=667306, chg -0.03%
Matteo Croce (2):
netns: switch netns in the child when executing commands
netns: make netns_{save,restore} static
include/namespace.h | 2 --
include/utils.h | 5 +----
ip/ip.c | 1 -
ip/ip_common.h | 1 -
ip/ipnetns.c | 49 ++++++++++++++++++++++++++++++++-------------
ip/ipvrf.c | 16 +--------------
lib/exec.c | 6 +++++-
lib/namespace.c | 31 ----------------------------
lib/utils.c | 27 -------------------------
9 files changed, 42 insertions(+), 96 deletions(-)
--
2.21.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH iproute2 1/2] netns: switch netns in the child when executing commands
2019-06-10 22:16 [PATCH iproute2 0/2] refactor the 'ip netns exec' command Matteo Croce
@ 2019-06-10 22:16 ` Matteo Croce
2019-06-10 22:45 ` Stephen Hemminger
2019-06-10 22:16 ` [PATCH iproute2 2/2] netns: make netns_{save,restore} static Matteo Croce
1 sibling, 1 reply; 7+ messages in thread
From: Matteo Croce @ 2019-06-10 22:16 UTC (permalink / raw)
To: netdev; +Cc: David Ahern, Stephen Hemminger
'ip netns exec' changes the current netns just before executing a child
process, and restores it after forking. This is needed if we're running in batch
or do_all mode, as well as other cleanup things like VRF associations.
Add an argument to cmd_exec() which allows to switch the current netns directly
in the child, so the parent environment is kept unaltered.
By doing so, some utility functions became unused, so remove them.
Signed-off-by: Matteo Croce <mcroce@redhat.com>
---
include/utils.h | 5 +----
ip/ip_common.h | 1 -
ip/ipnetns.c | 18 ++++--------------
ip/ipvrf.c | 16 +---------------
lib/exec.c | 6 +++++-
lib/utils.c | 27 ---------------------------
6 files changed, 11 insertions(+), 62 deletions(-)
diff --git a/include/utils.h b/include/utils.h
index 8a9c3020..c58a3886 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -294,14 +294,11 @@ extern int cmdlineno;
ssize_t getcmdline(char **line, size_t *len, FILE *in);
int makeargs(char *line, char *argv[], int maxargs);
-int do_each_netns(int (*func)(char *nsname, void *arg), void *arg,
- bool show_label);
-
char *int_to_str(int val, char *buf);
int get_guid(__u64 *guid, const char *arg);
int get_real_family(int rtm_type, int rtm_family);
-int cmd_exec(const char *cmd, char **argv, bool do_fork);
+int cmd_exec(const char *cmd, char **argv, bool do_fork, char *netns);
int make_path(const char *path, mode_t mode);
char *find_cgroup2_mount(void);
int get_command_name(const char *pid, char *comm, size_t len);
diff --git a/ip/ip_common.h b/ip/ip_common.h
index b4aa34a7..38203aae 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -77,7 +77,6 @@ int do_tcp_metrics(int argc, char **argv);
int do_ipnetconf(int argc, char **argv);
int do_iptoken(int argc, char **argv);
int do_ipvrf(int argc, char **argv);
-void vrf_reset(void);
int netns_identify_pid(const char *pidstr, char *name, int len);
int do_seg6(int argc, char **argv);
diff --git a/ip/ipnetns.c b/ip/ipnetns.c
index 8ead0c4c..9e414b55 100644
--- a/ip/ipnetns.c
+++ b/ip/ipnetns.c
@@ -400,7 +400,8 @@ static int on_netns_exec(char *nsname, void *arg)
{
char **argv = arg;
- cmd_exec(argv[1], argv + 1, true);
+ printf("\nnetns: %s\n", nsname);
+ cmd_exec(argv[0], argv, true, nsname);
return 0;
}
@@ -409,8 +410,6 @@ 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;
@@ -421,22 +420,13 @@ static int netns_exec(int argc, char **argv)
}
if (do_all)
- return do_each_netns(on_netns_exec, --argv, 1);
-
- if (netns_switch(argv[0]))
- return -1;
-
- /* we just changed namespaces. clear any vrf association
- * with prior namespace before exec'ing command
- */
- vrf_reset();
+ return netns_foreach(on_netns_exec, argv);
/* 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);
+ return -cmd_exec(argv[1], argv + 1, !!batch_mode, argv[0]);
}
static int is_pid(const char *str)
diff --git a/ip/ipvrf.c b/ip/ipvrf.c
index a13cf653..894d85fc 100644
--- a/ip/ipvrf.c
+++ b/ip/ipvrf.c
@@ -456,21 +456,7 @@ static int ipvrf_exec(int argc, char **argv)
if (vrf_switch(argv[0]))
return -1;
- return -cmd_exec(argv[1], argv + 1, !!batch_mode);
-}
-
-/* reset VRF association of current process to default VRF;
- * used by netns_exec
- */
-void vrf_reset(void)
-{
- char vrf[32];
-
- if (vrf_identify(getpid(), vrf, sizeof(vrf)) ||
- (vrf[0] == '\0'))
- return;
-
- vrf_switch("default");
+ return -cmd_exec(argv[1], argv + 1, !!batch_mode, NULL);
}
static int ipvrf_filter_req(struct nlmsghdr *nlh, int reqlen)
diff --git a/lib/exec.c b/lib/exec.c
index eb36b59d..3b07e908 100644
--- a/lib/exec.c
+++ b/lib/exec.c
@@ -5,8 +5,9 @@
#include <unistd.h>
#include "utils.h"
+#include "namespace.h"
-int cmd_exec(const char *cmd, char **argv, bool do_fork)
+int cmd_exec(const char *cmd, char **argv, bool do_fork, char *netns)
{
fflush(stdout);
if (do_fork) {
@@ -34,6 +35,9 @@ int cmd_exec(const char *cmd, char **argv, bool do_fork)
}
}
+ if (netns && netns_switch(netns))
+ return -1;
+
if (execvp(cmd, argv) < 0)
fprintf(stderr, "exec of \"%s\" failed: %s\n",
cmd, strerror(errno));
diff --git a/lib/utils.c b/lib/utils.c
index a81c0700..be0f11b0 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -1418,33 +1418,6 @@ void print_nlmsg_timestamp(FILE *fp, const struct nlmsghdr *n)
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);
-}
-
char *int_to_str(int val, char *buf)
{
sprintf(buf, "%d", val);
--
2.21.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH iproute2 2/2] netns: make netns_{save,restore} static
2019-06-10 22:16 [PATCH iproute2 0/2] refactor the 'ip netns exec' command Matteo Croce
2019-06-10 22:16 ` [PATCH iproute2 1/2] netns: switch netns in the child when executing commands Matteo Croce
@ 2019-06-10 22:16 ` Matteo Croce
1 sibling, 0 replies; 7+ messages in thread
From: Matteo Croce @ 2019-06-10 22:16 UTC (permalink / raw)
To: netdev; +Cc: David Ahern, Stephen Hemminger
The netns_{save,restore} functions are only used in ipnetns.c now, since
the restore is not needed anymore after the netns exec command.
Move them in ipnetns.c, and make them static.
Signed-off-by: Matteo Croce <mcroce@redhat.com>
---
include/namespace.h | 2 --
ip/ip.c | 1 -
ip/ipnetns.c | 31 +++++++++++++++++++++++++++++++
lib/namespace.c | 31 -------------------------------
4 files changed, 31 insertions(+), 34 deletions(-)
diff --git a/include/namespace.h b/include/namespace.h
index 89cdda11..e47f9b5d 100644
--- a/include/namespace.h
+++ b/include/namespace.h
@@ -49,8 +49,6 @@ static inline int setns(int fd, int nstype)
}
#endif /* HAVE_SETNS */
-void netns_save(void);
-void netns_restore(void);
int netns_switch(char *netns);
int netns_get_fd(const char *netns);
int netns_foreach(int (*func)(char *nsname, void *arg), void *arg);
diff --git a/ip/ip.c b/ip/ip.c
index 49b3aa49..b71ae816 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -158,7 +158,6 @@ static int batch(const char *name)
if (!force)
break;
}
- netns_restore();
}
if (line)
free(line);
diff --git a/ip/ipnetns.c b/ip/ipnetns.c
index 9e414b55..beb7fb8f 100644
--- a/ip/ipnetns.c
+++ b/ip/ipnetns.c
@@ -45,6 +45,7 @@ static int usage(void)
static struct rtnl_handle rtnsh = { .fd = -1 };
static int have_rtnl_getnsid = -1;
+static int saved_netns = -1;
static int ipnetns_accept_msg(struct rtnl_ctrl_data *ctrl,
struct nlmsghdr *n, void *arg)
@@ -623,6 +624,33 @@ static int create_netns_dir(void)
return 0;
}
+/* Obtain a FD for the current namespace, so we can reenter it later */
+static void netns_save(void)
+{
+ if (saved_netns != -1)
+ return;
+
+ saved_netns = open("/proc/self/ns/net", O_RDONLY | O_CLOEXEC);
+ if (saved_netns == -1) {
+ perror("Cannot open init namespace");
+ exit(1);
+ }
+}
+
+static void netns_restore(void)
+{
+ if (saved_netns == -1)
+ return;
+
+ if (setns(saved_netns, CLONE_NEWNET)) {
+ perror("setns");
+ exit(1);
+ }
+
+ close(saved_netns);
+ saved_netns = -1;
+}
+
static int netns_add(int argc, char **argv, bool create)
{
/* This function creates a new network namespace and
@@ -716,9 +744,12 @@ static int netns_add(int argc, char **argv, bool create)
proc_path, netns_path, strerror(errno));
goto out_delete;
}
+ netns_restore();
+
return 0;
out_delete:
if (create) {
+ netns_restore();
netns_delete(argc, argv);
} else if (unlink(netns_path) < 0) {
fprintf(stderr, "Cannot remove namespace file \"%s\": %s\n",
diff --git a/lib/namespace.c b/lib/namespace.c
index a2aea57a..06ae0a48 100644
--- a/lib/namespace.c
+++ b/lib/namespace.c
@@ -15,35 +15,6 @@
#include "utils.h"
#include "namespace.h"
-static int saved_netns = -1;
-
-/* Obtain a FD for the current namespace, so we can reenter it later */
-void netns_save(void)
-{
- if (saved_netns != -1)
- return;
-
- saved_netns = open("/proc/self/ns/net", O_RDONLY | O_CLOEXEC);
- if (saved_netns == -1) {
- perror("Cannot open init namespace");
- exit(1);
- }
-}
-
-void netns_restore(void)
-{
- if (saved_netns == -1)
- return;
-
- if (setns(saved_netns, CLONE_NEWNET)) {
- perror("setns");
- exit(1);
- }
-
- close(saved_netns);
- saved_netns = -1;
-}
-
static void bind_etc(const char *name)
{
char etc_netns_path[sizeof(NETNS_ETC_DIR) + NAME_MAX];
@@ -90,8 +61,6 @@ int netns_switch(char *name)
return -1;
}
- netns_save();
-
if (setns(netns, CLONE_NEWNET) < 0) {
fprintf(stderr, "setting the network namespace \"%s\" failed: %s\n",
name, strerror(errno));
--
2.21.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH iproute2 1/2] netns: switch netns in the child when executing commands
2019-06-10 22:16 ` [PATCH iproute2 1/2] netns: switch netns in the child when executing commands Matteo Croce
@ 2019-06-10 22:45 ` Stephen Hemminger
2019-06-10 22:52 ` Matteo Croce
0 siblings, 1 reply; 7+ messages in thread
From: Stephen Hemminger @ 2019-06-10 22:45 UTC (permalink / raw)
To: Matteo Croce; +Cc: netdev, David Ahern
On Tue, 11 Jun 2019 00:16:12 +0200
Matteo Croce <mcroce@redhat.com> wrote:
> + printf("\nnetns: %s\n", nsname);
> + cmd_exec(argv[0], argv, true, nsname);
> return 0;
simple printf breaks JSON output.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH iproute2 1/2] netns: switch netns in the child when executing commands
2019-06-10 22:45 ` Stephen Hemminger
@ 2019-06-10 22:52 ` Matteo Croce
2019-06-10 23:03 ` Matteo Croce
0 siblings, 1 reply; 7+ messages in thread
From: Matteo Croce @ 2019-06-10 22:52 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev, David Ahern
On Tue, Jun 11, 2019 at 12:46 AM Stephen Hemminger
<stephen@networkplumber.org> wrote:
>
> On Tue, 11 Jun 2019 00:16:12 +0200
> Matteo Croce <mcroce@redhat.com> wrote:
>
> > + printf("\nnetns: %s\n", nsname);
> > + cmd_exec(argv[0], argv, true, nsname);
> > return 0;
>
> simple printf breaks JSON output.
It was just moved from on_netns_label(). I will check how the json
output works when running doall and provide a similar behaviour.
Anyway, I noticed that the VRF env should be reset but only in the
child. I'm adding a function pointer to cmd_exec which will
point to an hook which changes the netns when doing 'ip netns exec'
and reset the VRF on vrf exec.
Regards,
--
Matteo Croce
per aspera ad upstream
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH iproute2 1/2] netns: switch netns in the child when executing commands
2019-06-10 22:52 ` Matteo Croce
@ 2019-06-10 23:03 ` Matteo Croce
2019-06-10 23:11 ` Stephen Hemminger
0 siblings, 1 reply; 7+ messages in thread
From: Matteo Croce @ 2019-06-10 23:03 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev, David Ahern
On Tue, Jun 11, 2019 at 12:52 AM Matteo Croce <mcroce@redhat.com> wrote:
>
> On Tue, Jun 11, 2019 at 12:46 AM Stephen Hemminger
> <stephen@networkplumber.org> wrote:
> >
> > On Tue, 11 Jun 2019 00:16:12 +0200
> > Matteo Croce <mcroce@redhat.com> wrote:
> >
> > > + printf("\nnetns: %s\n", nsname);
> > > + cmd_exec(argv[0], argv, true, nsname);
> > > return 0;
> >
> > simple printf breaks JSON output.
>
> It was just moved from on_netns_label(). I will check how the json
> output works when running doall and provide a similar behaviour.
>
> Anyway, I noticed that the VRF env should be reset but only in the
> child. I'm adding a function pointer to cmd_exec which will
> point to an hook which changes the netns when doing 'ip netns exec'
> and reset the VRF on vrf exec.
>
> Regards,
> --
> Matteo Croce
> per aspera ad upstream
Hi Stephen,
just checked, but it seems that netns exec in batch mode produces an
invalid output anyway:
# ip netns add n1
# ip netns add n2
# ip -all -json netns exec date
netns: n2
Tue 11 Jun 2019 12:55:11 AM CEST
netns: n1
Tue 11 Jun 2019 12:55:11 AM CEST
Probably there is very little sense in using -all netns exec and json
together, but worth noting it.
Bye,
--
Matteo Croce
per aspera ad upstream
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH iproute2 1/2] netns: switch netns in the child when executing commands
2019-06-10 23:03 ` Matteo Croce
@ 2019-06-10 23:11 ` Stephen Hemminger
0 siblings, 0 replies; 7+ messages in thread
From: Stephen Hemminger @ 2019-06-10 23:11 UTC (permalink / raw)
To: Matteo Croce; +Cc: netdev, David Ahern
On Tue, 11 Jun 2019 01:03:57 +0200
Matteo Croce <mcroce@redhat.com> wrote:
> On Tue, Jun 11, 2019 at 12:52 AM Matteo Croce <mcroce@redhat.com> wrote:
> >
> > On Tue, Jun 11, 2019 at 12:46 AM Stephen Hemminger
> > <stephen@networkplumber.org> wrote:
> > >
> > > On Tue, 11 Jun 2019 00:16:12 +0200
> > > Matteo Croce <mcroce@redhat.com> wrote:
> > >
> > > > + printf("\nnetns: %s\n", nsname);
> > > > + cmd_exec(argv[0], argv, true, nsname);
> > > > return 0;
> > >
> > > simple printf breaks JSON output.
> >
> > It was just moved from on_netns_label(). I will check how the json
> > output works when running doall and provide a similar behaviour.
> >
> > Anyway, I noticed that the VRF env should be reset but only in the
> > child. I'm adding a function pointer to cmd_exec which will
> > point to an hook which changes the netns when doing 'ip netns exec'
> > and reset the VRF on vrf exec.
> >
> > Regards,
> > --
> > Matteo Croce
> > per aspera ad upstream
>
> Hi Stephen,
>
> just checked, but it seems that netns exec in batch mode produces an
> invalid output anyway:
>
> # ip netns add n1
> # ip netns add n2
> # ip -all -json netns exec date
>
> netns: n2
> Tue 11 Jun 2019 12:55:11 AM CEST
>
> netns: n1
> Tue 11 Jun 2019 12:55:11 AM CEST
>
> Probably there is very little sense in using -all netns exec and json
> together, but worth noting it.
>
> Bye,
Thanks, just being paranoid about json output.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2019-06-10 23:12 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-06-10 22:16 [PATCH iproute2 0/2] refactor the 'ip netns exec' command Matteo Croce
2019-06-10 22:16 ` [PATCH iproute2 1/2] netns: switch netns in the child when executing commands Matteo Croce
2019-06-10 22:45 ` Stephen Hemminger
2019-06-10 22:52 ` Matteo Croce
2019-06-10 23:03 ` Matteo Croce
2019-06-10 23:11 ` Stephen Hemminger
2019-06-10 22:16 ` [PATCH iproute2 2/2] netns: make netns_{save,restore} static Matteo Croce
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).