From c934da8aaacb015e08ac8abbbd0aa696a7ef19fd Mon Sep 17 00:00:00 2001 From: Moshe Shemesh Date: Tue, 11 Jun 2019 19:11:09 +0300 Subject: [PATCH 01/10] devlink: mnlg: Catch returned error value of dumpit commands Devlink commands which implements the dumpit callback may return error. The netlink function netlink_dump() sends the errno value as the payload of the message, while answering user space with NLMSG_DONE. To enable receiving errno value for dumpit commands we have to check for it in the message. If it is a negative value then the dump returned an error so we should set errno accordingly and check for ext_ack in case it was set. Fixes: 049c58539f5d ("devlink: mnlg: Add support for extended ack") Signed-off-by: Moshe Shemesh Acked-by: Jiri Pirko Signed-off-by: Stephen Hemminger --- devlink/mnlg.c | 7 +++++++ include/libnetlink.h | 1 + lib/libnetlink.c | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/devlink/mnlg.c b/devlink/mnlg.c index 37cc25dd..ee125df0 100644 --- a/devlink/mnlg.c +++ b/devlink/mnlg.c @@ -85,6 +85,13 @@ static int mnlg_cb_error(const struct nlmsghdr *nlh, void *data) static int mnlg_cb_stop(const struct nlmsghdr *nlh, void *data) { + int len = *(int *)NLMSG_DATA(nlh); + + if (len < 0) { + errno = -len; + nl_dump_ext_ack_done(nlh, len); + return MNL_CB_ERROR; + } return MNL_CB_STOP; } diff --git a/include/libnetlink.h b/include/libnetlink.h index 503b3ec1..0205af80 100644 --- a/include/libnetlink.h +++ b/include/libnetlink.h @@ -129,6 +129,7 @@ int rtnl_send(struct rtnl_handle *rth, const void *buf, int) int rtnl_send_check(struct rtnl_handle *rth, const void *buf, int) __attribute__((warn_unused_result)); int nl_dump_ext_ack(const struct nlmsghdr *nlh, nl_ext_ack_fn_t errfn); +int nl_dump_ext_ack_done(const struct nlmsghdr *nlh, int error); int addattr(struct nlmsghdr *n, int maxlen, int type); int addattr8(struct nlmsghdr *n, int maxlen, int type, __u8 data); diff --git a/lib/libnetlink.c b/lib/libnetlink.c index 0d48a3d4..028d5502 100644 --- a/lib/libnetlink.c +++ b/lib/libnetlink.c @@ -125,7 +125,7 @@ int nl_dump_ext_ack(const struct nlmsghdr *nlh, nl_ext_ack_fn_t errfn) return 0; } -static int nl_dump_ext_ack_done(const struct nlmsghdr *nlh, int error) +int nl_dump_ext_ack_done(const struct nlmsghdr *nlh, int error) { struct nlattr *tb[NLMSGERR_ATTR_MAX + 1] = {}; unsigned int hlen = sizeof(int); @@ -155,7 +155,7 @@ int nl_dump_ext_ack(const struct nlmsghdr *nlh, nl_ext_ack_fn_t errfn) return 0; } -static int nl_dump_ext_ack_done(const struct nlmsghdr *nlh, int error) +int nl_dump_ext_ack_done(const struct nlmsghdr *nlh, int error) { return 0; } From b0a09ace394c274d8adc90875dc64ef21a17564f Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 12 Jun 2019 08:48:33 -0700 Subject: [PATCH 02/10] testsuite: intent if/else in Makefile Indent both arms of if/else equally. Signed-off-by: Stephen Hemminger --- Makefile | 2 +- testsuite/Makefile | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 48f469b0..6c35e7c2 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ HOSTCC ?= $(CC) DEFINES += -D_GNU_SOURCE # Turn on transparent support for LFS DEFINES += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -CCOPTS = -O2 +CCOPTS = -O2 -pipe WFLAGS := -Wall -Wstrict-prototypes -Wmissing-prototypes WFLAGS += -Wmissing-declarations -Wold-style-definition -Wformat=2 diff --git a/testsuite/Makefile b/testsuite/Makefile index 7f247bbc..d5408646 100644 --- a/testsuite/Makefile +++ b/testsuite/Makefile @@ -18,9 +18,9 @@ KENVFN := $(shell mktemp /tmp/tc_testkenv.XXXXXX) ifneq (,$(wildcard /proc/config.gz)) KCPATH := /proc/config.gz else -KVER := $(shell uname -r) -KCPATHS := /lib/modules/$(KVER)/config /boot/config-$(KVER) -KCPATH := $(firstword $(wildcard $(KCPATHS))) + KVER := $(shell uname -r) + KCPATHS := /lib/modules/$(KVER)/config /boot/config-$(KVER) + KCPATH := $(firstword $(wildcard $(KCPATHS))) endif .PHONY: compile listtests alltests configure $(TESTS) From 578cadcc68035943062d74507c3b7989741b353f Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Sun, 16 Jun 2019 14:46:02 -0700 Subject: [PATCH 03/10] ipmroute: Prevent overlapping storage of `filter` global This variable has the same name as `struct xfrm_filter filter` in ip/ipxfrm.c, but overrides that definition since `struct rtfilter` is larger. This is visible when built with -Wl,--warn-common in LDFLAGS: /usr/bin/ld: ipxfrm.o: warning: common of `filter' overridden by larger common from ipmroute.o Signed-off-by: Michael Forney Signed-off-by: Stephen Hemminger --- ip/ipmroute.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ip/ipmroute.c b/ip/ipmroute.c index 6cf91fe9..3537bdf4 100644 --- a/ip/ipmroute.c +++ b/ip/ipmroute.c @@ -44,7 +44,7 @@ static void usage(void) exit(-1); } -struct rtfilter { +static struct rtfilter { int tb; int af; int iif; From 77a380379f270d28a771487f964bb7928ac34285 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 18 Jun 2019 09:46:33 -0700 Subject: [PATCH 04/10] uapi: update headers and add if_link.h and if_infiniband.h Signed-off-by: Stephen Hemminger --- include/uapi/linux/bpf.h | 6 ++++-- include/uapi/linux/if_infiniband.h | 30 ++++++++++++++++++++++++++++++ include/uapi/linux/snmp.h | 1 + 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 include/uapi/linux/if_infiniband.h diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index d30bab8b..045545de 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -192,6 +192,8 @@ enum bpf_attach_type { BPF_LIRC_MODE2, BPF_FLOW_DISSECTOR, BPF_CGROUP_SYSCTL, + BPF_CGROUP_UDP4_RECVMSG, + BPF_CGROUP_UDP6_RECVMSG, __MAX_BPF_ATTACH_TYPE }; @@ -3376,8 +3378,8 @@ struct bpf_raw_tracepoint_args { /* DIRECT: Skip the FIB rules and go to FIB table associated with device * OUTPUT: Do lookup from egress perspective; default is ingress */ -#define BPF_FIB_LOOKUP_DIRECT BIT(0) -#define BPF_FIB_LOOKUP_OUTPUT BIT(1) +#define BPF_FIB_LOOKUP_DIRECT (1U << 0) +#define BPF_FIB_LOOKUP_OUTPUT (1U << 1) enum { BPF_FIB_LKUP_RET_SUCCESS, /* lookup successful */ diff --git a/include/uapi/linux/if_infiniband.h b/include/uapi/linux/if_infiniband.h new file mode 100644 index 00000000..0fc33bf3 --- /dev/null +++ b/include/uapi/linux/if_infiniband.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-2-Clause) */ +/* + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available at + * , or the OpenIB.org BSD + * license, available in the LICENSE.TXT file accompanying this + * software. These details are also available at + * . + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright (c) 2004 Topspin Communications. All rights reserved. + * + * $Id$ + */ + +#ifndef _LINUX_IF_INFINIBAND_H +#define _LINUX_IF_INFINIBAND_H + +#define INFINIBAND_ALEN 20 /* Octets in IPoIB HW addr */ + +#endif /* _LINUX_IF_INFINIBAND_H */ diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h index 86dc24a9..fd42c131 100644 --- a/include/uapi/linux/snmp.h +++ b/include/uapi/linux/snmp.h @@ -283,6 +283,7 @@ enum LINUX_MIB_TCPACKCOMPRESSED, /* TCPAckCompressed */ LINUX_MIB_TCPZEROWINDOWDROP, /* TCPZeroWindowDrop */ LINUX_MIB_TCPRCVQDROP, /* TCPRcvQDrop */ + LINUX_MIB_TCPWQUEUETOOBIG, /* TCPWqueueTooBig */ __LINUX_MIB_MAX }; From 8063feebbace60d1d6e11a09a589a8799d1125a3 Mon Sep 17 00:00:00 2001 From: Andrea Claudi Date: Thu, 13 Jun 2019 19:47:02 +0200 Subject: [PATCH 05/10] Makefile: use make -C make provides a handy -C option to change directory before reading the makefiles or doing anything else. Use that instead of the "cd dir && make && cd .." pattern, thus simplifying sintax for some makefiles. Changes from v1: - Drop an obviously wrong leftover on testsuite/iproute2/Makefile Signed-off-by: Andrea Claudi Signed-off-by: Stephen Hemminger --- Makefile | 3 ++- testsuite/Makefile | 6 +++--- testsuite/iproute2/Makefile | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 6c35e7c2..a3cc88f1 100644 --- a/Makefile +++ b/Makefile @@ -114,7 +114,8 @@ clobber: distclean: clobber check: all - cd testsuite && $(MAKE) && $(MAKE) alltests + $(MAKE) -C testsuite + $(MAKE) -C testsuite alltests @if command -v man >/dev/null 2>&1; then \ echo "Checking manpages for syntax errors..."; \ $(MAKE) -C man check; \ diff --git a/testsuite/Makefile b/testsuite/Makefile index d5408646..4451f316 100644 --- a/testsuite/Makefile +++ b/testsuite/Makefile @@ -26,10 +26,10 @@ endif .PHONY: compile listtests alltests configure $(TESTS) configure: - echo "Entering iproute2" && cd iproute2 && $(MAKE) configure && cd ..; + $(MAKE) -C iproute2 configure compile: configure generate_nlmsg - echo "Entering iproute2" && cd iproute2 && $(MAKE) && cd ..; + $(MAKE) -C iproute2 listtests: @for t in $(TESTS); do \ @@ -51,7 +51,7 @@ clean: testclean $(MAKE) -C tools clean distclean: clean - echo "Entering iproute2" && cd iproute2 && $(MAKE) distclean && cd ..; + $(MAKE) -C iproute2 distclean $(TESTS): generate_nlmsg testclean ifeq (,$(IPVERS)) diff --git a/testsuite/iproute2/Makefile b/testsuite/iproute2/Makefile index b8a7d515..f8946058 100644 --- a/testsuite/iproute2/Makefile +++ b/testsuite/iproute2/Makefile @@ -4,7 +4,7 @@ SUBDIRS := $(filter-out Makefile,$(wildcard *)) all: configure @for dir in $(SUBDIRS); do \ - echo "Entering $$dir" && cd $$dir && $(MAKE) && cd ..; \ + $(MAKE) -C $$dir; \ done link: @@ -19,12 +19,12 @@ configure: link clean: link @for dir in $(SUBDIRS); do \ - echo "Entering $$dir" && cd $$dir && $(MAKE) clean && cd ..; \ + $(MAKE) -C $$dir clean; \ done distclean: clean @for dir in $(SUBDIRS); do \ - echo "Entering $$dir" && cd $$dir && $(MAKE) distclean && cd ..; \ + $(MAKE) -C $$dir distclean; \ done show: link From b16f52532335771d6b6b7a36fba43afaf394179f Mon Sep 17 00:00:00 2001 From: Pete Morici Date: Fri, 14 Jun 2019 13:24:59 -0400 Subject: [PATCH 06/10] Add support for configuring MACsec gcm-aes-256 cipher type. Signed-off-by: Pete Morici Signed-off-by: Stephen Hemminger --- ip/ipmacsec.c | 28 +++++++++++++++++++--------- man/man8/ip-macsec.8 | 2 +- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/ip/ipmacsec.c b/ip/ipmacsec.c index 54cd2b8c..ad6ad7d6 100644 --- a/ip/ipmacsec.c +++ b/ip/ipmacsec.c @@ -95,7 +95,7 @@ static void ipmacsec_usage(void) " ip macsec show DEV\n" "where OPTS := [ pn ] [ on | off ]\n" " ID := 128-bit hex string\n" - " KEY := 128-bit hex string\n" + " KEY := 128-bit or 256-bit hex string\n" " SCI := { sci | port { 1..2^16-1 } address }\n"); exit(-1); @@ -586,14 +586,20 @@ static void print_key(struct rtattr *key) keyid, sizeof(keyid))); } -#define DEFAULT_CIPHER_NAME "GCM-AES-128" +#define CIPHER_NAME_GCM_AES_128 "GCM-AES-128" +#define CIPHER_NAME_GCM_AES_256 "GCM-AES-256" +#define DEFAULT_CIPHER_NAME CIPHER_NAME_GCM_AES_128 static const char *cs_id_to_name(__u64 cid) { switch (cid) { case MACSEC_DEFAULT_CIPHER_ID: - case MACSEC_DEFAULT_CIPHER_ALT: return DEFAULT_CIPHER_NAME; + case MACSEC_CIPHER_ID_GCM_AES_128: + /* MACSEC_DEFAULT_CIPHER_ALT: */ + return CIPHER_NAME_GCM_AES_128; + case MACSEC_CIPHER_ID_GCM_AES_256: + return CIPHER_NAME_GCM_AES_256; default: return "(unknown)"; } @@ -1172,7 +1178,7 @@ static void usage(FILE *f) { fprintf(f, "Usage: ... macsec [ [ address ] port { 1..2^16-1 } | sci ]\n" - " [ cipher { default | gcm-aes-128 } ]\n" + " [ cipher { default | gcm-aes-128 | gcm-aes-256 } ]\n" " [ icvlen { 8..16 } ]\n" " [ encrypt { on | off } ]\n" " [ send_sci { on | off } ]\n" @@ -1217,13 +1223,17 @@ static int macsec_parse_opt(struct link_util *lu, int argc, char **argv, NEXT_ARG(); if (cipher.id) duparg("cipher", *argv); - if (strcmp(*argv, "default") == 0 || - strcmp(*argv, "gcm-aes-128") == 0 || - strcmp(*argv, "GCM-AES-128") == 0) + if (strcmp(*argv, "default") == 0) cipher.id = MACSEC_DEFAULT_CIPHER_ID; + else if (strcmp(*argv, "gcm-aes-128") == 0 || + strcmp(*argv, "GCM-AES-128") == 0) + cipher.id = MACSEC_CIPHER_ID_GCM_AES_128; + else if (strcmp(*argv, "gcm-aes-256") == 0 || + strcmp(*argv, "GCM-AES-256") == 0) + cipher.id = MACSEC_CIPHER_ID_GCM_AES_256; else - invarg("expected: default or gcm-aes-128", - *argv); + invarg("expected: default, gcm-aes-128 or" + " gcm-aes-256", *argv); } else if (strcmp(*argv, "icvlen") == 0) { NEXT_ARG(); if (cipher.icv_len) diff --git a/man/man8/ip-macsec.8 b/man/man8/ip-macsec.8 index 1aca3bdc..4fd8a5b6 100644 --- a/man/man8/ip-macsec.8 +++ b/man/man8/ip-macsec.8 @@ -10,7 +10,7 @@ ip-macsec \- MACsec device configuration | .BI sci " " ] [ -.BR cipher " { " default " | " gcm-aes-128 " } ] [" +.BR cipher " { " default " | " gcm-aes-128 " | "gcm-aes-256" } ] [" .BI icvlen " ICVLEN" ] [ .BR encrypt " { " on " | " off " } ] [" From 903818fbf9c73dd71793e5829775d2ccc1775af5 Mon Sep 17 00:00:00 2001 From: Matteo Croce Date: Tue, 18 Jun 2019 16:49:33 +0200 Subject: [PATCH 07/10] netns: switch netns in the child when executing commands '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. Some cleanups must be done both in the parent and in the child: the parent must restore the previous netns, while the child must reset any VRF association. Unfortunately, if do_all is set, the VRF are not reset in the child, and the spawned processes are started with the wrong VRF context. This can be triggered with this script: # ip -b - <<-'EOF' link add type vrf table 100 link set vrf0 up link add type dummy link set dummy0 vrf vrf0 up netns add ns1 EOF # ip -all -b - <<-'EOF' vrf exec vrf0 true netns exec setsid -f sleep 1h EOF # ip vrf pids vrf0 314 sleep # ps 314 PID TTY STAT TIME COMMAND 314 ? Ss 0:00 sleep 1h Refactor cmd_exec() and pass to it a function pointer which is called in the child before the final exec. In the netns exec case the function just resets the VRF and switches netns. Doing it in the child is less error prone and safer, because the parent environment is always kept unaltered. After this refactor some utility functions became unused, so remove them. Signed-off-by: Matteo Croce Signed-off-by: Stephen Hemminger --- include/utils.h | 6 ++---- ip/ipnetns.c | 30 ++++++++++++++++-------------- ip/ipvrf.c | 2 +- lib/exec.c | 7 ++++++- lib/utils.c | 27 --------------------------- 5 files changed, 25 insertions(+), 47 deletions(-) diff --git a/include/utils.h b/include/utils.h index 8a9c3020..927fdc17 100644 --- a/include/utils.h +++ b/include/utils.h @@ -294,14 +294,12 @@ 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, + int (*setup)(void *), void *arg); 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/ipnetns.c b/ip/ipnetns.c index e4788e75..e32e44bd 100644 --- a/ip/ipnetns.c +++ b/ip/ipnetns.c @@ -395,11 +395,24 @@ static int netns_list(int argc, char **argv) return 0; } +static int do_switch(void *arg) +{ + char *netns = arg; + + /* we just changed namespaces. clear any vrf association + * with prior namespace before exec'ing command + */ + vrf_reset(); + + return netns_switch(netns); +} + 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, do_switch, nsname); return 0; } @@ -408,8 +421,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; @@ -420,22 +431,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, do_switch, argv[0]); } static int is_pid(const char *str) diff --git a/ip/ipvrf.c b/ip/ipvrf.c index 08a0d45b..aebcb253 100644 --- a/ip/ipvrf.c +++ b/ip/ipvrf.c @@ -455,7 +455,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); + return -cmd_exec(argv[1], argv + 1, !!batch_mode, NULL, NULL); } /* reset VRF association of current process to default VRF; diff --git a/lib/exec.c b/lib/exec.c index eb36b59d..9b1c8f4a 100644 --- a/lib/exec.c +++ b/lib/exec.c @@ -5,8 +5,10 @@ #include #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, + int (*setup)(void *), void *arg) { fflush(stdout); if (do_fork) { @@ -34,6 +36,9 @@ int cmd_exec(const char *cmd, char **argv, bool do_fork) } } + if (setup && setup(arg)) + 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); From d81d4ba15d74a51f23f61a2ddb792689e5db95f0 Mon Sep 17 00:00:00 2001 From: Matteo Croce Date: Tue, 18 Jun 2019 16:49:34 +0200 Subject: [PATCH 08/10] ip vrf: use hook to change VRF in the child On vrf exec, reset the VRF associations in the child process, via the new hook added to cmd_exec(). In this way, the parent doesn't have to reset the VRF associations before spawning other processes. Signed-off-by: Matteo Croce Signed-off-by: Stephen Hemminger --- ip/ipvrf.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ip/ipvrf.c b/ip/ipvrf.c index aebcb253..f589f7f8 100644 --- a/ip/ipvrf.c +++ b/ip/ipvrf.c @@ -441,6 +441,13 @@ out: return rc; } +static int do_switch(void *arg) +{ + char *vrf = arg; + + return vrf_switch(vrf); +} + static int ipvrf_exec(int argc, char **argv) { if (argc < 1) { @@ -452,10 +459,7 @@ static int ipvrf_exec(int argc, char **argv) return -1; } - if (vrf_switch(argv[0])) - return -1; - - return -cmd_exec(argv[1], argv + 1, !!batch_mode, NULL, NULL); + return -cmd_exec(argv[1], argv + 1, !!batch_mode, do_switch, argv[0]); } /* reset VRF association of current process to default VRF; From b2e2922373a6c65ed08b57926e61f3621d89a70a Mon Sep 17 00:00:00 2001 From: Matteo Croce Date: Tue, 18 Jun 2019 16:49:35 +0200 Subject: [PATCH 09/10] netns: make netns_{save,restore} static 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 Signed-off-by: Stephen Hemminger --- 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 d64d43e1..e4131714 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 e32e44bd..7e6cfe82 100644 --- a/ip/ipnetns.c +++ b/ip/ipnetns.c @@ -44,6 +44,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) @@ -634,6 +635,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 @@ -727,9 +755,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)); From 6d77d9c6ae74fe231d9aab2b7538fdded1d1028c Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Fri, 21 Jun 2019 11:21:32 +0200 Subject: [PATCH 10/10] ip monitor: display interfaces from all groups Only interface from group 0 were displayed. ip monitor calls ipaddr_reset_filter() and there is no reason to not reset the filter group in this function. Fixes: c4fdf75d3def ("ip link: fix display of interface groups") Signed-off-by: Nicolas Dichtel Signed-off-by: Stephen Hemminger --- ip/ipaddress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ip/ipaddress.c b/ip/ipaddress.c index b504200b..fd79f978 100644 --- a/ip/ipaddress.c +++ b/ip/ipaddress.c @@ -1850,7 +1850,6 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action) ipaddr_reset_filter(oneline, 0); filter.showqueue = 1; filter.family = preferred_family; - filter.group = -1; if (action == IPADD_FLUSH) { if (argc <= 0) { @@ -2107,6 +2106,7 @@ void ipaddr_reset_filter(int oneline, int ifindex) memset(&filter, 0, sizeof(filter)); filter.oneline = oneline; filter.ifindex = ifindex; + filter.group = -1; } static int default_scope(inet_prefix *lcl)