* Re: [PATCH v5 2/2] net: phy: adin: implement Energy Detect Powerdown mode via phy-tunable
From: Andrew Lunn @ 2019-09-16 11:57 UTC (permalink / raw)
To: Alexandru Ardelean
Cc: netdev, devicetree, linux-kernel, davem, robh+dt, mark.rutland,
f.fainelli, hkallweit1, mkubecek
In-Reply-To: <20190916073526.24711-3-alexandru.ardelean@analog.com>
On Mon, Sep 16, 2019 at 10:35:26AM +0300, Alexandru Ardelean wrote:
> This driver becomes the first user of the kernel's `ETHTOOL_PHY_EDPD`
> phy-tunable feature.
> EDPD is also enabled by default on PHY config_init, but can be disabled via
> the phy-tunable control.
>
> When enabling EDPD, it's also a good idea (for the ADIN PHYs) to enable TX
> periodic pulses, so that in case the other PHY is also on EDPD mode, there
> is no lock-up situation where both sides are waiting for the other to
> transmit.
>
> Via the phy-tunable control, TX pulses can be disabled if specifying 0
> `tx-interval` via ethtool.
>
> The ADIN PHY supports only fixed 1 second intervals; they cannot be
> configured. That is why the acceptable values are 1,
> ETHTOOL_PHY_EDPD_DFLT_TX_MSECS and ETHTOOL_PHY_EDPD_NO_TX (which disables
> TX pulses).
>
> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply
* [PATCH] selftests: Add test cases for `ip nexthop flush proto XX`
From: Donald Sharp @ 2019-09-16 12:26 UTC (permalink / raw)
To: netdev, dsahern
Add some test cases to allow the fib_nexthops.sh test code
to test the flushing of nexthops based upon the proto passed
in upon creation of the nexthop group.
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
---
tools/testing/selftests/net/fib_nexthops.sh | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/tools/testing/selftests/net/fib_nexthops.sh b/tools/testing/selftests/net/fib_nexthops.sh
index f9ebeac1e6f2..796670ebc65b 100755
--- a/tools/testing/selftests/net/fib_nexthops.sh
+++ b/tools/testing/selftests/net/fib_nexthops.sh
@@ -940,6 +940,20 @@ basic()
run_cmd "$IP nexthop add id 104 group 1 dev veth1"
log_test $? 2 "Nexthop group and device"
+ # Tests to ensure that flushing works as expected.
+ run_cmd "$IP nexthop add id 105 blackhole proto 99"
+ run_cmd "$IP nexthop add id 106 blackhole proto 100"
+ run_cmd "$IP nexthop add id 107 blackhole proto 99"
+ run_cmd "$IP nexthop flush proto 99"
+ check_nexthop "id 105" ""
+ check_nexthop "id 106" "id 106 blackhole proto 100"
+ check_nexthop "id 107" ""
+ run_cmd "$IP nexthop flush proto 100"
+ check_nexthop "id 106" ""
+
+ run_cmd "$IP nexthop flush proto 100"
+ log_test $? 0 "Test proto flush"
+
run_cmd "$IP nexthop add id 104 group 1 blackhole"
log_test $? 2 "Nexthop group and blackhole"
--
2.21.0
^ permalink raw reply related
* [PATCH iproute2-next v2] bpf: replace snprintf with asprintf when dealing with long buffers
From: Andrea Claudi @ 2019-09-16 13:00 UTC (permalink / raw)
To: netdev; +Cc: stephen, dsahern
This reduces stack usage, as asprintf allocates memory on the heap.
This indirectly fixes a snprintf truncation warning (from gcc v9.2.1):
bpf.c: In function ‘bpf_get_work_dir’:
bpf.c:784:49: warning: ‘snprintf’ output may be truncated before the last format character [-Wformat-truncation=]
784 | snprintf(bpf_wrk_dir, sizeof(bpf_wrk_dir), "%s/", mnt);
| ^
bpf.c:784:2: note: ‘snprintf’ output between 2 and 4097 bytes into a destination of size 4096
784 | snprintf(bpf_wrk_dir, sizeof(bpf_wrk_dir), "%s/", mnt);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Fixes: e42256699cac ("bpf: make tc's bpf loader generic and move into lib")
Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
---
lib/bpf.c | 155 ++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 116 insertions(+), 39 deletions(-)
diff --git a/lib/bpf.c b/lib/bpf.c
index 7d2a322ffbaec..0fe2e9eb2cbf8 100644
--- a/lib/bpf.c
+++ b/lib/bpf.c
@@ -406,13 +406,21 @@ static int bpf_derive_elf_map_from_fdinfo(int fd, struct bpf_elf_map *map,
struct bpf_map_ext *ext)
{
unsigned int val, owner_type = 0, owner_jited = 0;
- char file[PATH_MAX], buff[4096];
+ char *file = NULL;
+ char buff[4096];
FILE *fp;
+ int ret;
- snprintf(file, sizeof(file), "/proc/%d/fdinfo/%d", getpid(), fd);
+ ret = asprintf(&file, "/proc/%d/fdinfo/%d", getpid(), fd);
+ if (ret < 0) {
+ fprintf(stderr, "asprintf failed: %s\n", strerror(errno));
+ free(file);
+ return ret;
+ }
memset(map, 0, sizeof(*map));
fp = fopen(file, "r");
+ free(file);
if (!fp) {
fprintf(stderr, "No procfs support?!\n");
return -EIO;
@@ -600,8 +608,9 @@ int bpf_trace_pipe(void)
0,
};
int fd_in, fd_out = STDERR_FILENO;
- char tpipe[PATH_MAX];
+ char *tpipe = NULL;
const char *mnt;
+ int ret;
mnt = bpf_find_mntpt("tracefs", TRACEFS_MAGIC, tracefs_mnt,
sizeof(tracefs_mnt), tracefs_known_mnts);
@@ -610,9 +619,15 @@ int bpf_trace_pipe(void)
return -1;
}
- snprintf(tpipe, sizeof(tpipe), "%s/trace_pipe", mnt);
+ ret = asprintf(&tpipe, "%s/trace_pipe", mnt);
+ if (ret < 0) {
+ fprintf(stderr, "asprintf failed: %s\n", strerror(errno));
+ free(tpipe);
+ return ret;
+ }
fd_in = open(tpipe, O_RDONLY);
+ free(tpipe);
if (fd_in < 0)
return -1;
@@ -633,37 +648,50 @@ int bpf_trace_pipe(void)
static int bpf_gen_global(const char *bpf_sub_dir)
{
- char bpf_glo_dir[PATH_MAX];
+ char *bpf_glo_dir = NULL;
int ret;
- snprintf(bpf_glo_dir, sizeof(bpf_glo_dir), "%s/%s/",
- bpf_sub_dir, BPF_DIR_GLOBALS);
+ ret = asprintf(&bpf_glo_dir, "%s/%s/", bpf_sub_dir, BPF_DIR_GLOBALS);
+ if (ret < 0) {
+ fprintf(stderr, "asprintf failed: %s\n", strerror(errno));
+ goto out;
+ }
ret = mkdir(bpf_glo_dir, S_IRWXU);
if (ret && errno != EEXIST) {
fprintf(stderr, "mkdir %s failed: %s\n", bpf_glo_dir,
strerror(errno));
- return ret;
+ goto out;
}
- return 0;
+ ret = 0;
+out:
+ free(bpf_glo_dir);
+ return ret;
}
static int bpf_gen_master(const char *base, const char *name)
{
- char bpf_sub_dir[PATH_MAX + NAME_MAX + 1];
+ char *bpf_sub_dir = NULL;
int ret;
- snprintf(bpf_sub_dir, sizeof(bpf_sub_dir), "%s%s/", base, name);
+ ret = asprintf(&bpf_sub_dir, "%s%s/", base, name);
+ if (ret < 0) {
+ fprintf(stderr, "asprintf failed: %s\n", strerror(errno));
+ goto out;
+ }
ret = mkdir(bpf_sub_dir, S_IRWXU);
if (ret && errno != EEXIST) {
fprintf(stderr, "mkdir %s failed: %s\n", bpf_sub_dir,
strerror(errno));
- return ret;
+ goto out;
}
- return bpf_gen_global(bpf_sub_dir);
+ ret = bpf_gen_global(bpf_sub_dir);
+out:
+ free(bpf_sub_dir);
+ return ret;
}
static int bpf_slave_via_bind_mnt(const char *full_name,
@@ -692,13 +720,22 @@ static int bpf_slave_via_bind_mnt(const char *full_name,
static int bpf_gen_slave(const char *base, const char *name,
const char *link)
{
- char bpf_lnk_dir[PATH_MAX + NAME_MAX + 1];
- char bpf_sub_dir[PATH_MAX + NAME_MAX];
+ char *bpf_lnk_dir = NULL;
+ char *bpf_sub_dir = NULL;
struct stat sb = {};
int ret;
- snprintf(bpf_lnk_dir, sizeof(bpf_lnk_dir), "%s%s/", base, link);
- snprintf(bpf_sub_dir, sizeof(bpf_sub_dir), "%s%s", base, name);
+ ret = asprintf(&bpf_lnk_dir, "%s%s/", base, link);
+ if (ret < 0) {
+ fprintf(stderr, "asprintf failed: %s\n", strerror(errno));
+ goto out;
+ }
+
+ ret = asprintf(&bpf_sub_dir, "%s%s", base, name);
+ if (ret < 0) {
+ fprintf(stderr, "asprintf failed: %s\n", strerror(errno));
+ goto out;
+ }
ret = symlink(bpf_lnk_dir, bpf_sub_dir);
if (ret) {
@@ -706,25 +743,30 @@ static int bpf_gen_slave(const char *base, const char *name,
if (errno != EPERM) {
fprintf(stderr, "symlink %s failed: %s\n",
bpf_sub_dir, strerror(errno));
- return ret;
+ goto out;
}
- return bpf_slave_via_bind_mnt(bpf_sub_dir,
- bpf_lnk_dir);
+ ret = bpf_slave_via_bind_mnt(bpf_sub_dir, bpf_lnk_dir);
+ goto out;
}
ret = lstat(bpf_sub_dir, &sb);
if (ret) {
fprintf(stderr, "lstat %s failed: %s\n",
bpf_sub_dir, strerror(errno));
- return ret;
+ goto out;
}
- if ((sb.st_mode & S_IFMT) != S_IFLNK)
- return bpf_gen_global(bpf_sub_dir);
+ if ((sb.st_mode & S_IFMT) != S_IFLNK) {
+ ret = bpf_gen_global(bpf_sub_dir);
+ goto out;
+ }
}
- return 0;
+out:
+ free(bpf_lnk_dir);
+ free(bpf_sub_dir);
+ return ret;
}
static int bpf_gen_hierarchy(const char *base)
@@ -742,7 +784,7 @@ static int bpf_gen_hierarchy(const char *base)
static const char *bpf_get_work_dir(enum bpf_prog_type type)
{
static char bpf_tmp[PATH_MAX] = BPF_DIR_MNT;
- static char bpf_wrk_dir[PATH_MAX];
+ static char *bpf_wrk_dir;
static const char *mnt;
static bool bpf_mnt_cached;
const char *mnt_env = getenv(BPF_ENV_MNT);
@@ -781,7 +823,12 @@ static const char *bpf_get_work_dir(enum bpf_prog_type type)
}
}
- snprintf(bpf_wrk_dir, sizeof(bpf_wrk_dir), "%s/", mnt);
+ ret = asprintf(&bpf_wrk_dir, "%s/", mnt);
+ if (ret < 0) {
+ fprintf(stderr, "asprintf failed: %s\n", strerror(errno));
+ free(bpf_wrk_dir);
+ goto out;
+ }
ret = bpf_gen_hierarchy(bpf_wrk_dir);
if (ret) {
@@ -1438,31 +1485,48 @@ static int bpf_probe_pinned(const char *name, const struct bpf_elf_ctx *ctx,
static int bpf_make_obj_path(const struct bpf_elf_ctx *ctx)
{
- char tmp[PATH_MAX];
+ char *tmp = NULL;
int ret;
- snprintf(tmp, sizeof(tmp), "%s/%s", bpf_get_work_dir(ctx->type),
- ctx->obj_uid);
+ ret = asprintf(&tmp, "%s/%s", bpf_get_work_dir(ctx->type), ctx->obj_uid);
+ if (ret < 0) {
+ fprintf(stderr, "asprintf failed: %s\n", strerror(errno));
+ goto out;
+ }
ret = mkdir(tmp, S_IRWXU);
if (ret && errno != EEXIST) {
fprintf(stderr, "mkdir %s failed: %s\n", tmp, strerror(errno));
- return ret;
+ goto out;
}
- return 0;
+ ret = 0;
+out:
+ free(tmp);
+ return ret;
}
static int bpf_make_custom_path(const struct bpf_elf_ctx *ctx,
const char *todo)
{
- char tmp[PATH_MAX], rem[PATH_MAX], *sub;
+ char *tmp = NULL;
+ char *rem = NULL;
+ char *sub;
int ret;
- snprintf(tmp, sizeof(tmp), "%s/../", bpf_get_work_dir(ctx->type));
- snprintf(rem, sizeof(rem), "%s/", todo);
- sub = strtok(rem, "/");
+ ret = asprintf(&tmp, "%s/../", bpf_get_work_dir(ctx->type));
+ if (ret < 0) {
+ fprintf(stderr, "asprintf failed: %s\n", strerror(errno));
+ goto out;
+ }
+ ret = asprintf(&rem, "%s/", todo);
+ if (ret < 0) {
+ fprintf(stderr, "asprintf failed: %s\n", strerror(errno));
+ goto out;
+ }
+
+ sub = strtok(rem, "/");
while (sub) {
if (strlen(tmp) + strlen(sub) + 2 > PATH_MAX)
return -EINVAL;
@@ -1474,13 +1538,17 @@ static int bpf_make_custom_path(const struct bpf_elf_ctx *ctx,
if (ret && errno != EEXIST) {
fprintf(stderr, "mkdir %s failed: %s\n", tmp,
strerror(errno));
- return ret;
+ goto out;
}
sub = strtok(NULL, "/");
}
- return 0;
+ ret = 0;
+out:
+ free(rem);
+ free(tmp);
+ return ret;
}
static int bpf_place_pinned(int fd, const char *name,
@@ -2581,14 +2649,23 @@ struct bpf_jited_aux {
static int bpf_derive_prog_from_fdinfo(int fd, struct bpf_prog_data *prog)
{
- char file[PATH_MAX], buff[4096];
+ char *file = NULL;
+ char buff[4096];
unsigned int val;
FILE *fp;
+ int ret;
+
+ ret = asprintf(&file, "/proc/%d/fdinfo/%d", getpid(), fd);
+ if (ret < 0) {
+ fprintf(stderr, "asprintf failed: %s\n", strerror(errno));
+ free(file);
+ return ret;
+ }
- snprintf(file, sizeof(file), "/proc/%d/fdinfo/%d", getpid(), fd);
memset(prog, 0, sizeof(*prog));
fp = fopen(file, "r");
+ free(file);
if (!fp) {
fprintf(stderr, "No procfs support?!\n");
return -EIO;
--
2.21.0
^ permalink raw reply related
* [PATCH bpf v2] libbpf: Remove getsockopt() check for XDP_OPTIONS
From: Toke Høiland-Jørgensen @ 2019-09-16 12:33 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, netdev, bpf
Cc: Björn Töpel, Toke Høiland-Jørgensen,
Yonghong Song
The xsk_socket__create() function fails and returns an error if it cannot
get the XDP_OPTIONS through getsockopt(). However, support for XDP_OPTIONS
was not added until kernel 5.3, so this means that creating XSK sockets
always fails on older kernels.
Since the option is just used to set the zero-copy flag in the xsk struct,
and that flag is not really used for anything yet, just remove the
getsockopt() call until a proper use for it is introduced.
Suggested-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
---
v2:
- Remove the call entirely.
tools/lib/bpf/xsk.c | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/tools/lib/bpf/xsk.c b/tools/lib/bpf/xsk.c
index 680e63066cf3..14aea315c914 100644
--- a/tools/lib/bpf/xsk.c
+++ b/tools/lib/bpf/xsk.c
@@ -65,7 +65,6 @@ struct xsk_socket {
int xsks_map_fd;
__u32 queue_id;
char ifname[IFNAMSIZ];
- bool zc;
};
struct xsk_nl_info {
@@ -481,7 +480,6 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
void *rx_map = NULL, *tx_map = NULL;
struct sockaddr_xdp sxdp = {};
struct xdp_mmap_offsets off;
- struct xdp_options opts;
struct xsk_socket *xsk;
socklen_t optlen;
int err;
@@ -601,15 +599,6 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
xsk->prog_fd = -1;
- optlen = sizeof(opts);
- err = getsockopt(xsk->fd, SOL_XDP, XDP_OPTIONS, &opts, &optlen);
- if (err) {
- err = -errno;
- goto out_mmap_tx;
- }
-
- xsk->zc = opts.flags & XDP_OPTIONS_ZEROCOPY;
-
if (!(xsk->config.libbpf_flags & XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD)) {
err = xsk_setup_xdp_prog(xsk);
if (err)
--
2.23.0
^ permalink raw reply related
* Re: [v3 2/3] samples: pktgen: add helper functions for IP(v4/v6) CIDR parsing
From: Toke Høiland-Jørgensen @ 2019-09-16 12:52 UTC (permalink / raw)
To: Jesper Dangaard Brouer, Daniel T. Lee; +Cc: David S . Miller, netdev, brouer
In-Reply-To: <20190916085317.02e4d985@carbon>
Jesper Dangaard Brouer <brouer@redhat.com> writes:
> On Sun, 15 Sep 2019 00:13:52 +0900
> "Daniel T. Lee" <danieltimlee@gmail.com> wrote:
>
>> This commit adds CIDR parsing and IP validate helper function to parse
>> single IP or range of IP with CIDR. (e.g. 198.18.0.0/15)
>>
>> Helpers will be used in prior to set target address in samples/pktgen.
>>
>> Signed-off-by: Daniel T. Lee <danieltimlee@gmail.com>
>> ---
>> Changes since v3:
>> * Set errexit option to stop script execution on error
>>
>> samples/pktgen/functions.sh | 124 ++++++++++++++++++++++++++++++++++++
>> 1 file changed, 124 insertions(+)
>>
>> diff --git a/samples/pktgen/functions.sh b/samples/pktgen/functions.sh
>> index 4af4046d71be..87ae61701904 100644
>> --- a/samples/pktgen/functions.sh
>> +++ b/samples/pktgen/functions.sh
>> @@ -5,6 +5,8 @@
>> # Author: Jesper Dangaaard Brouer
>> # License: GPL
>>
>> +set -o errexit
>
> Unfortunately, this breaks the scripts.
>
> The function proc_cmd are designed to grep after "Result: OK:" which
> might fail, and your patch/change makes the script stop immediately.
> We actually want to continue, and output what command that failed (and
> also grep again after "Result:" to provide the kernel reason).
>
> Even if you somehow "fix" function proc_cmd, then we in general want to
> catch different error situations by looking at status $?, and output
> meaning full errors via calling err() function.
Yeah, I can see that some functions do this, but I don't think that
would be too hard to fix. See sample diff below (will need some more
work to deal with grep failing, but you get the idea).
I'd argue that fixing this is the right thing to do... Maybe add set -o
nounset as well while we're at it? :)
> IHMO as minimum with errexit you need a 'trap' function that can
> help/inform the user of what went wrong.
Yeah, trap ERR (which would also need set -o errtrace to work inside the
functions) might be useful in any case.
-Toke
diff --git a/samples/pktgen/functions.sh b/samples/pktgen/functions.sh
index 4af4046d71be..d61a348f85f5 100644
--- a/samples/pktgen/functions.sh
+++ b/samples/pktgen/functions.sh
@@ -58,6 +58,7 @@ function pg_set() {
function proc_cmd() {
local result
local proc_file=$1
+ local status=0
# after shift, the remaining args are contained in $@
shift
local proc_ctrl=${PROC_DIR}/$proc_file
@@ -73,8 +74,7 @@ function proc_cmd() {
echo "cmd: $@ > $proc_ctrl"
fi
# Quoting of "$@" is important for space expansion
- echo "$@" > "$proc_ctrl"
- local status=$?
+ echo "$@" > "$proc_ctrl" || status=$?
result=$(grep "Result: OK:" $proc_ctrl)
# Due to pgctrl, cannot use exit code $? from grep
^ permalink raw reply related
* Re: [PATCH] netfilter: bridge: drop a broken include
From: Jeremy Sowden @ 2019-09-16 13:08 UTC (permalink / raw)
To: Adam Borowski
Cc: Pablo Neira Ayuso, Jozsef Kadlecsik, Florian Westphal,
Roopa Prabhu, Nikolay Aleksandrov, netfilter-devel, coreteam,
netdev
In-Reply-To: <20190916000517.45028-1-kilobyte@angband.pl>
[-- Attachment #1: Type: text/plain, Size: 4755 bytes --]
On 2019-09-16, at 02:05:16 +0200, Adam Borowski wrote:
> This caused a build failure if CONFIG_NF_CONNTRACK_BRIDGE is set but
> CONFIG_NF_TABLES=n -- and appears to be unused anyway.
>
> Signed-off-by: Adam Borowski <kilobyte@angband.pl>
> ---
> net/bridge/netfilter/nf_conntrack_bridge.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/net/bridge/netfilter/nf_conntrack_bridge.c
> b/net/bridge/netfilter/nf_conntrack_bridge.c
> index 4f5444d2a526..844ef5a53f87 100644
> --- a/net/bridge/netfilter/nf_conntrack_bridge.c
> +++ b/net/bridge/netfilter/nf_conntrack_bridge.c
> @@ -18,7 +18,6 @@
>
> #include <linux/netfilter/nf_tables.h>
> #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
> -#include <net/netfilter/nf_tables.h>
>
> #include "../br_private.h"
>
> --
> 2.23.0
This is the build-failure (reproduced with v5.3):
In file included from net/bridge/netfilter/nf_conntrack_bridge.c:21:
./include/net/netfilter/nf_tables.h: In function ‘nft_gencursor_next’:
./include/net/netfilter/nf_tables.h:1223:14: error: ‘const struct net’ has no member named ‘nft’; did you mean ‘nf’?
1223 | return net->nft.gencursor + 1 == 1 ? 1 : 0;
| ^~~
| nf
In file included from ./include/linux/export.h:45,
from ./include/linux/linkage.h:7,
from ./include/linux/kernel.h:8,
from ./include/linux/skbuff.h:13,
from ./include/linux/ip.h:16,
from net/bridge/netfilter/nf_conntrack_bridge.c:3:
./include/net/netfilter/nf_tables.h: In function ‘nft_genmask_cur’:
./include/net/netfilter/nf_tables.h:1234:29: error: ‘const struct net’ has no member named ‘nft’; did you mean ‘nf’?
1234 | return 1 << READ_ONCE(net->nft.gencursor);
| ^~~
./include/linux/compiler.h:261:17: note: in definition of macro ‘__READ_ONCE’
261 | union { typeof(x) __val; char __c[1]; } __u; \
| ^
./include/net/netfilter/nf_tables.h:1234:14: note: in expansion of macro ‘READ_ONCE’
1234 | return 1 << READ_ONCE(net->nft.gencursor);
| ^~~~~~~~~
./include/net/netfilter/nf_tables.h:1234:29: error: ‘const struct net’ has no member named ‘nft’; did you mean ‘nf’?
1234 | return 1 << READ_ONCE(net->nft.gencursor);
| ^~~
./include/linux/compiler.h:263:22: note: in definition of macro ‘__READ_ONCE’
263 | __read_once_size(&(x), __u.__c, sizeof(x)); \
| ^
./include/net/netfilter/nf_tables.h:1234:14: note: in expansion of macro ‘READ_ONCE’
1234 | return 1 << READ_ONCE(net->nft.gencursor);
| ^~~~~~~~~
./include/net/netfilter/nf_tables.h:1234:29: error: ‘const struct net’ has no member named ‘nft’; did you mean ‘nf’?
1234 | return 1 << READ_ONCE(net->nft.gencursor);
| ^~~
./include/linux/compiler.h:263:42: note: in definition of macro ‘__READ_ONCE’
263 | __read_once_size(&(x), __u.__c, sizeof(x)); \
| ^
./include/net/netfilter/nf_tables.h:1234:14: note: in expansion of macro ‘READ_ONCE’
1234 | return 1 << READ_ONCE(net->nft.gencursor);
| ^~~~~~~~~
./include/net/netfilter/nf_tables.h:1234:29: error: ‘const struct net’ has no member named ‘nft’; did you mean ‘nf’?
1234 | return 1 << READ_ONCE(net->nft.gencursor);
| ^~~
./include/linux/compiler.h:265:30: note: in definition of macro ‘__READ_ONCE’
265 | __read_once_size_nocheck(&(x), __u.__c, sizeof(x)); \
| ^
./include/net/netfilter/nf_tables.h:1234:14: note: in expansion of macro ‘READ_ONCE’
1234 | return 1 << READ_ONCE(net->nft.gencursor);
| ^~~~~~~~~
./include/net/netfilter/nf_tables.h:1234:29: error: ‘const struct net’ has no member named ‘nft’; did you mean ‘nf’?
1234 | return 1 << READ_ONCE(net->nft.gencursor);
| ^~~
./include/linux/compiler.h:265:50: note: in definition of macro ‘__READ_ONCE’
265 | __read_once_size_nocheck(&(x), __u.__c, sizeof(x)); \
| ^
./include/net/netfilter/nf_tables.h:1234:14: note: in expansion of macro ‘READ_ONCE’
1234 | return 1 << READ_ONCE(net->nft.gencursor);
| ^~~~~~~~~
There are already changes in the net-next tree that will fix it.
J.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH] libbpf: Don't error out if getsockopt() fails for XDP_OPTIONS
From: Toke Høiland-Jørgensen @ 2019-09-16 12:31 UTC (permalink / raw)
To: Daniel Borkmann, Yonghong Song, Alexei Starovoitov,
netdev@vger.kernel.org, bpf@vger.kernel.org, maximmi@mellanox.com
In-Reply-To: <9271a44f-1bbf-1305-bff9-8cbb8bae9098@iogearbox.net>
Daniel Borkmann <daniel@iogearbox.net> writes:
> On 9/13/19 8:53 PM, Yonghong Song wrote:
>> On 9/10/19 12:06 AM, Toke Høiland-Jørgensen wrote:
>>> Yonghong Song <yhs@fb.com> writes:
>>>> On 9/9/19 10:46 AM, Toke Høiland-Jørgensen wrote:
>>>>> The xsk_socket__create() function fails and returns an error if it cannot
>>>>> get the XDP_OPTIONS through getsockopt(). However, support for XDP_OPTIONS
>>>>> was not added until kernel 5.3, so this means that creating XSK sockets
>>>>> always fails on older kernels.
>>>>>
>>>>> Since the option is just used to set the zero-copy flag in the xsk struct,
>>>>> there really is no need to error out if the getsockopt() call fails.
>>>>>
>>>>> Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
>>>>> ---
>>>>> tools/lib/bpf/xsk.c | 8 ++------
>>>>> 1 file changed, 2 insertions(+), 6 deletions(-)
>>>>>
>>>>> diff --git a/tools/lib/bpf/xsk.c b/tools/lib/bpf/xsk.c
>>>>> index 680e63066cf3..598e487d9ce8 100644
>>>>> --- a/tools/lib/bpf/xsk.c
>>>>> +++ b/tools/lib/bpf/xsk.c
>>>>> @@ -603,12 +603,8 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
>>>>>
>>>>> optlen = sizeof(opts);
>>>>> err = getsockopt(xsk->fd, SOL_XDP, XDP_OPTIONS, &opts, &optlen);
>>>>> - if (err) {
>>>>> - err = -errno;
>>>>> - goto out_mmap_tx;
>>>>> - }
>>>>> -
>>>>> - xsk->zc = opts.flags & XDP_OPTIONS_ZEROCOPY;
>>>>> + if (!err)
>>>>> + xsk->zc = opts.flags & XDP_OPTIONS_ZEROCOPY;
>>>>>
>>>>> if (!(xsk->config.libbpf_flags & XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD)) {
>>>>> err = xsk_setup_xdp_prog(xsk);
>>>>
>>>> Since 'zc' is not used by anybody, maybe all codes 'zc' related can be
>>>> removed? It can be added back back once there is an interface to use
>>>> 'zc'?
>>>
>>> Fine with me; up to the maintainers what they prefer, I guess? :)
>
> Given this is not exposed to applications at this point and we don't do anything
> useful with it, lets just remove the zc cruft until there is a proper interface
> added to libbpf. Toke, please respin with the suggested removal, thanks!
Sure, can do :)
-Toke
^ permalink raw reply
* Re: [PATCH net] net/sched: cls_api: Fix nooffloaddevcnt counter in indr block call success
From: wenxu @ 2019-09-16 13:28 UTC (permalink / raw)
To: Jiri Pirko; +Cc: davem, netdev
In-Reply-To: <20190916102810.GN2286@nanopsycho.orion>
在 2019/9/16 18:28, Jiri Pirko 写道:
> Please use get_maintainers script to get list of ccs.
>
> Mon, Sep 16, 2019 at 12:15:34PM CEST, wenxu@ucloud.cn wrote:
>> From: wenxu <wenxu@ucloud.cn>
>>
>> When a block bind with a dev which support indr block call(vxlan/gretap
>> device). It can bind success but with nooffloaddevcnt++. It will fail
>> when replace the hw filter in tc_setup_cb_call with skip_sw mode for
>> checkout the nooffloaddevcnt and skip_sw.
> I read this paragraph 5 times, I still don't understand :( Could you
> please re-phrase?
will do.
>> if (block->nooffloaddevcnt && err_stop)
>> return -EOPNOTSUPP;
>>
>> So with this patch, if the indr block call success, it will not modify
>> the nooffloaddevcnt counter.
>>
>> Fixes: 7f76fa36754b ("net: sched: register callbacks for indirect tc block binds")
>> Signed-off-by: wenxu <wenxu@ucloud.cn>
>> ---
>> net/sched/cls_api.c | 27 +++++++++++++++------------
>> 1 file changed, 15 insertions(+), 12 deletions(-)
>>
>> diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
>> index efd3cfb..8a1e3a5 100644
>> --- a/net/sched/cls_api.c
>> +++ b/net/sched/cls_api.c
>> @@ -766,10 +766,10 @@ void tc_indr_block_cb_unregister(struct net_device *dev,
>> }
>> EXPORT_SYMBOL_GPL(tc_indr_block_cb_unregister);
>>
>> -static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
>> - struct tcf_block_ext_info *ei,
>> - enum flow_block_command command,
>> - struct netlink_ext_ack *extack)
>> +static int tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
>> + struct tcf_block_ext_info *ei,
>> + enum flow_block_command command,
>> + struct netlink_ext_ack *extack)
>> {
>> struct tc_indr_block_cb *indr_block_cb;
>> struct tc_indr_block_dev *indr_dev;
>> @@ -785,7 +785,7 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
>>
>> indr_dev = tc_indr_block_dev_lookup(dev);
>> if (!indr_dev)
>> - return;
>> + return -ENOENT;
>>
>> indr_dev->block = command == FLOW_BLOCK_BIND ? block : NULL;
>>
>> @@ -793,7 +793,10 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
>> indr_block_cb->cb(dev, indr_block_cb->cb_priv, TC_SETUP_BLOCK,
>> &bo);
>>
>> - tcf_block_setup(block, &bo);
>> + if (list_empty(&bo.cb_list))
>> + return -EOPNOTSUPP;
> How is this part related to the rest of the patch?
This check the list is to make sure there is real hw-offload for the indr device( There maybe
get some wrong with indr_block_cb->cb in the driver). It should a return err to indicate the
caller add the nooffloaddevcnt counter.
.
^ permalink raw reply
* divide error in usbnet_update_max_qlen
From: syzbot @ 2019-09-16 13:29 UTC (permalink / raw)
To: andreyknvl, davem, linux-kernel, linux-usb, netdev, oneukum,
syzkaller-bugs
Hello,
syzbot found the following crash on:
HEAD commit: f0df5c1b usb-fuzzer: main usb gadget fuzzer driver
git tree: https://github.com/google/kasan.git usb-fuzzer
console output: https://syzkaller.appspot.com/x/log.txt?x=117659fa600000
kernel config: https://syzkaller.appspot.com/x/.config?x=5c6633fa4ed00be5
dashboard link: https://syzkaller.appspot.com/bug?extid=6102c120be558c885f04
compiler: gcc (GCC) 9.0.0 20181231 (experimental)
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=12107ba9600000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=146014e6600000
IMPORTANT: if you fix the bug, please add the following tag to the commit:
Reported-by: syzbot+6102c120be558c885f04@syzkaller.appspotmail.com
usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
cdc_ncm 1-1:1.0: MAC-Address: 42:42:42:42:42:42
cdc_ncm 1-1:1.0: dwNtbInMaxSize=0 is too small. Using 2048
cdc_ncm 1-1:1.0: setting rx_max = 2048
divide error: 0000 [#1] SMP KASAN
CPU: 0 PID: 12 Comm: kworker/0:1 Not tainted 5.3.0-rc7+ #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: usb_hub_wq hub_event
RIP: 0010:usbnet_update_max_qlen drivers/net/usb/usbnet.c:344 [inline]
RIP: 0010:usbnet_update_max_qlen+0x231/0x370 drivers/net/usb/usbnet.c:338
Code: 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 80 3c 02 00 0f 85 46 01
00 00 48 8d bb f4 00 00 00 31 d2 b8 c8 63 01 00 48 89 f9 <48> f7 b3 a8 01
00 00 48 ba 00 00 00 00 00 fc ff df 48 c1 e9 03 0f
RSP: 0018:ffff8881da20f010 EFLAGS: 00010246
RAX: 00000000000163c8 RBX: ffff8881d5ad8ac0 RCX: ffff8881d5ad8bb4
RDX: 0000000000000000 RSI: ffffffff8344ecde RDI: ffff8881d5ad8bb4
RBP: 0000000000000003 R08: ffff8881da1f9800 R09: ffffed103ab5b00a
R10: ffffed103ab5b009 R11: ffff8881d5ad804f R12: 0000000000000000
R13: ffff8881d5ad8c38 R14: ffff8881d5ad8ac0 R15: ffff8881d2820c80
FS: 0000000000000000(0000) GS:ffff8881db200000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f26d0180000 CR3: 00000001d38dd000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
cdc_ncm_update_rxtx_max+0x8e9/0xef0 drivers/net/usb/cdc_ncm.c:440
cdc_ncm_setup drivers/net/usb/cdc_ncm.c:667 [inline]
cdc_ncm_bind_common+0x1005/0x2570 drivers/net/usb/cdc_ncm.c:924
cdc_ncm_bind+0x7c/0x1c0 drivers/net/usb/cdc_ncm.c:1038
usbnet_probe+0xb43/0x23cf drivers/net/usb/usbnet.c:1722
usb_probe_interface+0x305/0x7a0 drivers/usb/core/driver.c:361
really_probe+0x281/0x6d0 drivers/base/dd.c:548
driver_probe_device+0x101/0x1b0 drivers/base/dd.c:721
__device_attach_driver+0x1c2/0x220 drivers/base/dd.c:828
bus_for_each_drv+0x162/0x1e0 drivers/base/bus.c:454
__device_attach+0x217/0x360 drivers/base/dd.c:894
bus_probe_device+0x1e4/0x290 drivers/base/bus.c:514
device_add+0xae6/0x16f0 drivers/base/core.c:2165
usb_set_configuration+0xdf6/0x1670 drivers/usb/core/message.c:2023
generic_probe+0x9d/0xd5 drivers/usb/core/generic.c:210
usb_probe_device+0x99/0x100 drivers/usb/core/driver.c:266
really_probe+0x281/0x6d0 drivers/base/dd.c:548
driver_probe_device+0x101/0x1b0 drivers/base/dd.c:721
__device_attach_driver+0x1c2/0x220 drivers/base/dd.c:828
bus_for_each_drv+0x162/0x1e0 drivers/base/bus.c:454
__device_attach+0x217/0x360 drivers/base/dd.c:894
bus_probe_device+0x1e4/0x290 drivers/base/bus.c:514
device_add+0xae6/0x16f0 drivers/base/core.c:2165
usb_new_device.cold+0x6a4/0xe79 drivers/usb/core/hub.c:2536
hub_port_connect drivers/usb/core/hub.c:5098 [inline]
hub_port_connect_change drivers/usb/core/hub.c:5213 [inline]
port_event drivers/usb/core/hub.c:5359 [inline]
hub_event+0x1b5c/0x3640 drivers/usb/core/hub.c:5441
---
This bug is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this bug report. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
syzbot can test patches for this bug, for details see:
https://goo.gl/tpsmEJ#testing-patches
^ permalink raw reply
* divide error in cdc_ncm_update_rxtx_max
From: syzbot @ 2019-09-16 13:29 UTC (permalink / raw)
To: andreyknvl, davem, linux-kernel, linux-usb, netdev, oliver,
syzkaller-bugs
Hello,
syzbot found the following crash on:
HEAD commit: f0df5c1b usb-fuzzer: main usb gadget fuzzer driver
git tree: https://github.com/google/kasan.git usb-fuzzer
console output: https://syzkaller.appspot.com/x/log.txt?x=14cd1459600000
kernel config: https://syzkaller.appspot.com/x/.config?x=5c6633fa4ed00be5
dashboard link: https://syzkaller.appspot.com/bug?extid=ce366e2b8296e25d84f5
compiler: gcc (GCC) 9.0.0 20181231 (experimental)
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=12b4dd85600000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=179b7fc1600000
IMPORTANT: if you fix the bug, please add the following tag to the commit:
Reported-by: syzbot+ce366e2b8296e25d84f5@syzkaller.appspotmail.com
cdc_ncm 1-1:1.0: dwNtbInMaxSize=0 is too small. Using 2048
cdc_ncm 1-1:1.0: setting rx_max = 2048
cdc_ncm 1-1:1.0: setting tx_max = 16384
divide error: 0000 [#1] SMP KASAN
CPU: 0 PID: 12 Comm: kworker/0:1 Not tainted 5.3.0-rc7+ #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: usb_hub_wq hub_event
RIP: 0010:cdc_ncm_update_rxtx_max+0xc6e/0xef0 drivers/net/usb/cdc_ncm.c:419
Code: e0 07 38 c2 0f 9e c1 84 d2 0f 95 c0 84 c1 0f 85 35 02 00 00 0f b7 5b
04 81 e3 ff 07 00 00 e8 29 47 f7 fd 31 d2 44 89 e0 31 ff <f7> f3 41 89 d5
89 d6 e8 86 48 f7 fd 45 85 ed 0f 85 17 f7 ff ff e8
RSP: 0018:ffff8881da20f030 EFLAGS: 00010246
RAX: 0000000000004000 RBX: 0000000000000000 RCX: 0000000000000001
RDX: 0000000000000000 RSI: ffffffff83469377 RDI: 0000000000000000
RBP: ffff8881c7ba0000 R08: ffff8881da1f9800 R09: ffffed103b645d58
R10: ffffed103b645d57 R11: ffff8881db22eabf R12: 0000000000004000
R13: 0000000000000000 R14: ffff8881d35f3dc0 R15: ffff8881d2a70f00
FS: 0000000000000000(0000) GS:ffff8881db200000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f1059879000 CR3: 00000001d49db000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
cdc_ncm_setup drivers/net/usb/cdc_ncm.c:667 [inline]
cdc_ncm_bind_common+0x1005/0x2570 drivers/net/usb/cdc_ncm.c:924
cdc_ncm_bind+0x7c/0x1c0 drivers/net/usb/cdc_ncm.c:1038
usbnet_probe+0xb43/0x23cf drivers/net/usb/usbnet.c:1722
usb_probe_interface+0x305/0x7a0 drivers/usb/core/driver.c:361
really_probe+0x281/0x6d0 drivers/base/dd.c:548
driver_probe_device+0x101/0x1b0 drivers/base/dd.c:721
__device_attach_driver+0x1c2/0x220 drivers/base/dd.c:828
bus_for_each_drv+0x162/0x1e0 drivers/base/bus.c:454
__device_attach+0x217/0x360 drivers/base/dd.c:894
bus_probe_device+0x1e4/0x290 drivers/base/bus.c:514
device_add+0xae6/0x16f0 drivers/base/core.c:2165
usb_set_configuration+0xdf6/0x1670 drivers/usb/core/message.c:2023
generic_probe+0x9d/0xd5 drivers/usb/core/generic.c:210
usb_probe_device+0x99/0x100 drivers/usb/core/driver.c:266
really_probe+0x281/0x6d0 drivers/base/dd.c:548
driver_probe_device+0x101/0x1b0 drivers/base/dd.c:721
__device_attach_driver+0x1c2/0x220 drivers/base/dd.c:828
bus_for_each_drv+0x162/0x1e0 drivers/base/bus.c:454
__device_attach+0x217/0x360 drivers/base/dd.c:894
bus_probe_device+0x1e4/0x290 drivers/base/bus.c:514
device_add+0xae6/0x16f0 drivers/base/core.c:2165
usb_new_device.cold+0x6a4/0xe79 drivers/usb/core/hub.c:2536
hub_port_connect drivers/usb/core/hub.c:5098 [inline]
hub_port_connect_change drivers/usb/core/hub.c:5213 [inline]
port_event drivers/usb/core/hub.c:5359 [inline]
hub_event+0x1b5c/0x3640 drivers/usb/core/hub.c:5441
process_one_work+0x92b/0x1530 kernel/workqueue.c:2269
worker_thread+0x96/0xe20 kernel/workqueue.c:2415
kthread+0x318/0x420 kernel/kthread.c:255
ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352
Modules linked in:
---[ end trace ab75cc10e099d8e9 ]---
RIP:
---
This bug is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this bug report. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
syzbot can test patches for this bug, for details see:
https://goo.gl/tpsmEJ#testing-patches
^ permalink raw reply
* BUG: unable to handle kernel NULL pointer dereference in rds_bind
From: syzbot @ 2019-09-16 13:29 UTC (permalink / raw)
To: arvid.brodin, davem, linux-kernel, linux-rdma, netdev, rds-devel,
santosh.shilimkar, syzkaller-bugs, xiyou.wangcong
Hello,
syzbot found the following crash on:
HEAD commit: f4b752a6 mlx4: fix spelling mistake "veify" -> "verify"
git tree: net
console output: https://syzkaller.appspot.com/x/log.txt?x=16cbebe6600000
kernel config: https://syzkaller.appspot.com/x/.config?x=b89bb446a3faaba4
dashboard link: https://syzkaller.appspot.com/bug?extid=fae39afd2101a17ec624
compiler: gcc (GCC) 9.0.0 20181231 (experimental)
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=10753bc1600000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=111dfc11600000
The bug was bisected to:
commit b9a1e627405d68d475a3c1f35e685ccfb5bbe668
Author: Cong Wang <xiyou.wangcong@gmail.com>
Date: Thu Jul 4 00:21:13 2019 +0000
hsr: implement dellink to clean up resources
bisection log: https://syzkaller.appspot.com/x/bisect.txt?x=11005fc1600000
final crash: https://syzkaller.appspot.com/x/report.txt?x=13005fc1600000
console output: https://syzkaller.appspot.com/x/log.txt?x=15005fc1600000
IMPORTANT: if you fix the bug, please add the following tag to the commit:
Reported-by: syzbot+fae39afd2101a17ec624@syzkaller.appspotmail.com
Fixes: b9a1e627405d ("hsr: implement dellink to clean up resources")
BUG: kernel NULL pointer dereference, address: 0000000000000000
#PF: supervisor instruction fetch in kernel mode
#PF: error_code(0x0010) - not-present page
PGD 9fef0067 P4D 9fef0067 PUD 9060d067 PMD 0
Oops: 0010 [#1] PREEMPT SMP KASAN
CPU: 1 PID: 9884 Comm: syz-executor453 Not tainted 5.3.0-rc7+ #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
RIP: 0010:0x0
Code: Bad RIP value.
RSP: 0018:ffff8880a7c6fcd8 EFLAGS: 00010246
RAX: dffffc0000000000 RBX: ffffffff8992bfe0 RCX: ffffffff86b9b636
RDX: 0000000000000000 RSI: ffff8880a7c6fd40 RDI: ffffffff897830c0
RBP: ffff8880a7c6fda8 R08: ffff888093150558 R09: 0000000000000000
R10: fffffbfff134af9f R11: ffff88809a008040 R12: ffff888093150080
R13: ffffffff897830c0 R14: 0000000000000000 R15: ffff8880a7c6fd40
FS: 000055555738a880(0000) GS:ffff8880ae900000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ffffffffffffffd6 CR3: 000000008f04a000 CR4: 00000000001406e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
rds_bind+0x420/0x800 net/rds/bind.c:247
__sys_bind+0x239/0x290 net/socket.c:1647
__do_sys_bind net/socket.c:1658 [inline]
__se_sys_bind net/socket.c:1656 [inline]
__x64_sys_bind+0x73/0xb0 net/socket.c:1656
do_syscall_64+0xfd/0x6a0 arch/x86/entry/common.c:296
entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x4412b9
Code: e8 ac e8 ff ff 48 83 c4 18 c3 0f 1f 80 00 00 00 00 48 89 f8 48 89 f7
48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff
ff 0f 83 eb 08 fc ff c3 66 2e 0f 1f 84 00 00 00 00
RSP: 002b:00007ffc7c28b228 EFLAGS: 00000246 ORIG_RAX: 0000000000000031
RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00000000004412b9
RDX: 0000000000000010 RSI: 0000000020000200 RDI: 0000000000000003
RBP: 00000000006cb018 R08: 00000000004002c8 R09: 00000000004002c8
R10: 00000000004002c8 R11: 0000000000000246 R12: 0000000000402030
R13: 00000000004020c0 R14: 0000000000000000 R15: 0000000000000000
Modules linked in:
CR2: 0000000000000000
---[ end trace b47a1983319ea52a ]---
RIP: 0010:0x0
Code: Bad RIP value.
RSP: 0018:ffff8880a7c6fcd8 EFLAGS: 00010246
RAX: dffffc0000000000 RBX: ffffffff8992bfe0 RCX: ffffffff86b9b636
RDX: 0000000000000000 RSI: ffff8880a7c6fd40 RDI: ffffffff897830c0
RBP: ffff8880a7c6fda8 R08: ffff888093150558 R09: 0000000000000000
R10: fffffbfff134af9f R11: ffff88809a008040 R12: ffff888093150080
R13: ffffffff897830c0 R14: 0000000000000000 R15: ffff8880a7c6fd40
FS: 000055555738a880(0000) GS:ffff8880ae900000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00000000004bf788 CR3: 000000008f04a000 CR4: 00000000001406e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
---
This bug is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this bug report. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
For information about bisection process see: https://goo.gl/tpsmEJ#bisection
syzbot can test patches for this bug, for details see:
https://goo.gl/tpsmEJ#testing-patches
^ permalink raw reply
* [PATCH net v3 00/11] net: fix nested device bugs
From: Taehee Yoo @ 2019-09-16 13:47 UTC (permalink / raw)
To: davem, netdev, j.vosburgh, vfalico, andy, jiri, sd, roopa, saeedm,
manishc, rahulv, kys, haiyangz, stephen, sashal, hare, varun,
ubraun, kgraul, jay.vosburgh
Cc: ap420073
This patchset fixes several bugs that are related to nesting
device infrastructure.
Current nesting infrastructure code doesn't limit the depth level of
devices. nested devices could be handled recursively. at that moment,
it needs huge memory and stack overflow could occur.
Below devices type have same bug.
VLAN, BONDING, TEAM, MACSEC, MACVLAN and VXLAN.
Test commands:
ip link add dummy0 type dummy
ip link add vlan1 link dummy0 type vlan id 1
for i in {2..100}
do
let A=$i-1
ip link add vlan$i link vlan$A type vlan id $i
done
ip link del dummy0
1st patch actually fixes the root cause.
It adds new common variables {upper/lower}_level that represent
depth level. upper_level variable is depth of upper devices.
lower_level variable is depth of lower devices.
[U][L] [U][L]
vlan1 1 5 vlan4 1 4
vlan2 2 4 vlan5 2 3
vlan3 3 3 |
| |
+------------+
|
vlan6 4 2
dummy0 5 1
After this patch, the nesting infrastructure code uses this variable to
check the depth level.
2, 4, 5, 6, 7 patches fix lockdep related problem.
Before this patch, devices use static lockdep map.
So, if devices that are same type is nested, lockdep will warn about
recursive situation.
These patches make these devices use dynamic lockdep key instead of
static lock or subclass.
3rd patch fixes unexpected IFF_BONDING bit unset.
8th patch fixes a refcnt leak in the macsec module.
9th patch adds ignore flag to an adjacent structure.
In order to exchange an adjacent node safely, ignore flag is needed.
10th patch makes vxlan add an adjacent link to limit depth level.
11th patch removes unnecessary variables and callback.
v2 -> v3 :
- Modify nesting infrastructure code to use iterator instead of recursive.
v1 -> v2 :
- Make the 3rd patch do not add a new priv_flag.
Taehee Yoo (11):
net: core: limit nested device depth
vlan: use dynamic lockdep key instead of subclass
bonding: fix unexpected IFF_BONDING bit unset
bonding: use dynamic lockdep key instead of subclass
team: use dynamic lockdep key instead of static key
macsec: use dynamic lockdep key instead of subclass
macvlan: use dynamic lockdep key instead of subclass
macsec: fix refcnt leak in module exit routine
net: core: add ignore flag to netdev_adjacent structure
vxlan: add adjacent link to limit depth level
net: remove unnecessary variables and callback
drivers/net/bonding/bond_alb.c | 2 +-
drivers/net/bonding/bond_main.c | 81 +++-
.../net/ethernet/mellanox/mlx5/core/en_tc.c | 2 +-
drivers/net/macsec.c | 50 +-
drivers/net/macvlan.c | 36 +-
drivers/net/team/team.c | 61 ++-
drivers/net/vxlan.c | 71 ++-
include/linux/if_macvlan.h | 3 +-
include/linux/if_team.h | 5 +
include/linux/if_vlan.h | 13 +-
include/linux/netdevice.h | 20 +-
include/net/bonding.h | 4 +-
include/net/vxlan.h | 1 +
net/8021q/vlan.c | 1 -
net/8021q/vlan_dev.c | 32 +-
net/core/dev.c | 456 +++++++++++++++---
net/core/dev_addr_lists.c | 12 +-
net/smc/smc_core.c | 2 +-
net/smc/smc_pnet.c | 2 +-
19 files changed, 667 insertions(+), 187 deletions(-)
--
2.17.1
^ permalink raw reply
* [PATCH net v3 01/11] net: core: limit nested device depth
From: Taehee Yoo @ 2019-09-16 13:47 UTC (permalink / raw)
To: davem, netdev, j.vosburgh, vfalico, andy, jiri, sd, roopa, saeedm,
manishc, rahulv, kys, haiyangz, stephen, sashal, hare, varun,
ubraun, kgraul, jay.vosburgh
Cc: ap420073
In-Reply-To: <20190916134802.8252-1-ap420073@gmail.com>
Current code doesn't limit the number of nested devices.
Nested devices would be handled recursively and this needs huge stack
memory. So, unlimited nested devices could make stack overflow.
This patch adds upper_level and lower_level, they are common variables
and represent maximum lower/upper depth.
When upper/lower device is attached or dettached,
{lower/upper}_level are updated. and if maximum depth is bigger than 8,
attach routine fails and returns -EMLINK.
In addition, this patch converts recursive routine of
netdev_walk_all_{lower/upper} to iterator routine.
Test commands:
ip link add dummy0 type dummy
ip link add link dummy0 name vlan1 type vlan id 1
ip link set vlan1 up
for i in {2..200}
do
let A=$i-1
ip link add vlan$i link vlan$A type vlan id $i
done
ip link del vlan1
Splat looks like:
[ 132.396918] Thread overran stack, or stack corrupted
[ 132.397763] Oops: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN PTI
[ 132.398557] CPU: 1 PID: 1299 Comm: ip Not tainted 5.3.0-rc8+ #179
[ 132.399241] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[ 132.400136] RIP: 0010:stack_depot_fetch+0x10/0x30
[ 132.400683] Code: 00 75 10 48 8b 73 18 48 89 ef 5b 5d e9 79 8f 87 ff 0f 0b e8 c2 6d 9b ff eb e9 89 f8 c1 ef 110
[ 132.402711] RSP: 0000:ffff8880b002eb78 EFLAGS: 00010006
[ 132.404578] RAX: 00000000001fffff RBX: ffff8880b002eec0 RCX: 0000000000000000
[ 132.405305] RDX: 000000000000001d RSI: ffff8880b002eb80 RDI: 0000000000003ff0
[ 132.406022] RBP: ffffea0002c00a00 R08: ffffed101b53df23 R09: ffffed101b53df23
[ 132.406776] R10: 0000000000000001 R11: ffffed101b53df22 R12: ffff8880d38dd900
[ 132.407598] R13: ffff8880b002e600 R14: ffff8880b002eec0 R15: ffff8880b002ed20
[ 132.408365] FS: 00007f5fca3c90c0(0000) GS:ffff8880da800000(0000) knlGS:0000000000000000
[ 132.409213] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 132.409788] CR2: ffffffffa598b098 CR3: 00000000ccb86004 CR4: 00000000000606e0
[ 132.410659] Call Trace:
[ 132.410962] Modules linked in: 8021q garp stp mrp llc dummy veth openvswitch nsh nf_conncount nf_nat nf_conntrs
[ 132.412410] CR2: ffffffffa598b098
[ 132.412754] ---[ end trace 7f335fb982ddb2da ]---
[ 132.413293] RIP: 0010:stack_depot_fetch+0x10/0x30
[ 132.413851] Code: 00 75 10 48 8b 73 18 48 89 ef 5b 5d e9 79 8f 87 ff 0f 0b e8 c2 6d 9b ff eb e9 89 f8 c1 ef 110
[ 132.415973] RSP: 0000:ffff8880b002eb78 EFLAGS: 00010006
[ 132.416581] RAX: 00000000001fffff RBX: ffff8880b002eec0 RCX: 0000000000000000
[ 132.417380] RDX: 000000000000001d RSI: ffff8880b002eb80 RDI: 0000000000003ff0
[ 132.418211] RBP: ffffea0002c00a00 R08: ffffed101b53df23 R09: ffffed101b53df23
[ 132.419036] R10: 0000000000000001 R11: ffffed101b53df22 R12: ffff8880d38dd900
[ 132.419815] R13: ffff8880b002e600 R14: ffff8880b002eec0 R15: ffff8880b002ed20
[ 132.420616] FS: 00007f5fca3c90c0(0000) GS:ffff8880da800000(0000) knlGS:0000000000000000
[ 132.421489] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 132.422134] CR2: ffffffffa598b098 CR3: 00000000ccb86004 CR4: 00000000000606e0
[ 132.422912] Kernel panic - not syncing: Fatal exception
[ 132.423441] Kernel Offset: 0x1f000000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffff)
[ 132.425455] Rebooting in 5 seconds..
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
---
v2 -> v3 :
- Modify nesting infra code to use iterator instead of recursive
v1 -> v2 :
- This patch is not changed
include/linux/netdevice.h | 4 +
net/core/dev.c | 286 ++++++++++++++++++++++++++++++++------
2 files changed, 245 insertions(+), 45 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 88292953aa6f..5bb5756129af 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1624,6 +1624,8 @@ enum netdev_priv_flags {
* @type: Interface hardware type
* @hard_header_len: Maximum hardware header length.
* @min_header_len: Minimum hardware header length
+ * @upper_level: Maximum depth level of upper devices.
+ * @lower_level: Maximum depth level of lower devices.
*
* @needed_headroom: Extra headroom the hardware may need, but not in all
* cases can this be guaranteed
@@ -1854,6 +1856,8 @@ struct net_device {
unsigned short type;
unsigned short hard_header_len;
unsigned char min_header_len;
+ unsigned char upper_level;
+ unsigned char lower_level;
unsigned short needed_headroom;
unsigned short needed_tailroom;
diff --git a/net/core/dev.c b/net/core/dev.c
index 5156c0edebe8..fa847ea957ee 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -146,6 +146,7 @@
#include "net-sysfs.h"
#define MAX_GRO_SKBS 8
+#define MAX_NEST_DEV 8
/* This should be increased if a protocol with a bigger head is added. */
#define GRO_MAX_HEAD (MAX_HEADER + 128)
@@ -6602,6 +6603,21 @@ struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
}
EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu);
+static struct net_device *netdev_next_upper_dev(struct net_device *dev,
+ struct list_head **iter)
+{
+ struct netdev_adjacent *upper;
+
+ upper = list_entry((*iter)->next, struct netdev_adjacent, list);
+
+ if (&upper->list == &dev->adj_list.upper)
+ return NULL;
+
+ *iter = &upper->list;
+
+ return upper->dev;
+}
+
static struct net_device *netdev_next_upper_dev_rcu(struct net_device *dev,
struct list_head **iter)
{
@@ -6619,31 +6635,103 @@ static struct net_device *netdev_next_upper_dev_rcu(struct net_device *dev,
return upper->dev;
}
+int netdev_walk_all_upper_dev(struct net_device *dev,
+ int (*fn)(struct net_device *dev,
+ void *data),
+ void *data)
+{
+ struct net_device *udev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
+ struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
+ int ret, cur = 0;
+
+ now = dev;
+ iter = &dev->adj_list.upper;
+
+ while (1) {
+ if (now != dev) {
+ ret = fn(now, data);
+ if (ret)
+ return ret;
+ }
+
+ next = NULL;
+ while (1) {
+ udev = netdev_next_upper_dev(now, &iter);
+ if (!udev)
+ break;
+
+ if (!next) {
+ next = udev;
+ niter = &udev->adj_list.upper;
+ } else {
+ dev_stack[cur] = udev;
+ iter_stack[cur++] = &udev->adj_list.upper;
+ break;
+ }
+ }
+
+ if (!next) {
+ if (!cur)
+ return 0;
+ next = dev_stack[--cur];
+ niter = iter_stack[cur];
+ }
+
+ now = next;
+ iter = niter;
+ }
+
+ return 0;
+}
+
int netdev_walk_all_upper_dev_rcu(struct net_device *dev,
int (*fn)(struct net_device *dev,
void *data),
void *data)
{
- struct net_device *udev;
- struct list_head *iter;
- int ret;
+ struct net_device *udev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
+ struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
+ int ret, cur = 0;
- for (iter = &dev->adj_list.upper,
- udev = netdev_next_upper_dev_rcu(dev, &iter);
- udev;
- udev = netdev_next_upper_dev_rcu(dev, &iter)) {
- /* first is the upper device itself */
- ret = fn(udev, data);
- if (ret)
- return ret;
+ now = dev;
+ iter = &dev->adj_list.upper;
- /* then look at all of its upper devices */
- ret = netdev_walk_all_upper_dev_rcu(udev, fn, data);
- if (ret)
- return ret;
+ while (1) {
+ if (now != dev) {
+ ret = fn(now, data);
+ if (ret)
+ return ret;
+ }
+
+ next = NULL;
+ while (1) {
+ udev = netdev_next_upper_dev_rcu(now, &iter);
+ if (!udev)
+ break;
+
+ if (!next) {
+ next = udev;
+ niter = &udev->adj_list.upper;
+ } else {
+ dev_stack[cur] = udev;
+ iter_stack[cur++] = &udev->adj_list.upper;
+ break;
+ }
+ }
+
+ if (!next) {
+ if (!cur)
+ return 0;
+ next = dev_stack[--cur];
+ niter = iter_stack[cur];
+ }
+
+ now = next;
+ iter = niter;
}
return 0;
+
}
EXPORT_SYMBOL_GPL(netdev_walk_all_upper_dev_rcu);
@@ -6748,23 +6836,45 @@ int netdev_walk_all_lower_dev(struct net_device *dev,
void *data),
void *data)
{
- struct net_device *ldev;
- struct list_head *iter;
- int ret;
+ struct net_device *ldev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
+ struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
+ int ret, cur = 0;
- for (iter = &dev->adj_list.lower,
- ldev = netdev_next_lower_dev(dev, &iter);
- ldev;
- ldev = netdev_next_lower_dev(dev, &iter)) {
- /* first is the lower device itself */
- ret = fn(ldev, data);
- if (ret)
- return ret;
+ now = dev;
+ iter = &dev->adj_list.lower;
- /* then look at all of its lower devices */
- ret = netdev_walk_all_lower_dev(ldev, fn, data);
- if (ret)
- return ret;
+ while (1) {
+ if (now != dev) {
+ ret = fn(now, data);
+ if (ret)
+ return ret;
+ }
+
+ next = NULL;
+ while (1) {
+ ldev = netdev_next_lower_dev(now, &iter);
+ if (!ldev)
+ break;
+
+ if (!next) {
+ next = ldev;
+ niter = &ldev->adj_list.lower;
+ } else {
+ dev_stack[cur] = ldev;
+ iter_stack[cur++] = &ldev->adj_list.lower;
+ break;
+ }
+ }
+
+ if (!next) {
+ if (!cur)
+ return 0;
+ next = dev_stack[--cur];
+ niter = iter_stack[cur];
+ }
+
+ now = next;
+ iter = niter;
}
return 0;
@@ -6785,31 +6895,100 @@ static struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
return lower->dev;
}
-int netdev_walk_all_lower_dev_rcu(struct net_device *dev,
- int (*fn)(struct net_device *dev,
- void *data),
- void *data)
+static u8 __netdev_upper_depth(struct net_device *dev)
+{
+ struct net_device *udev;
+ struct list_head *iter;
+ u8 max_depth = 0;
+
+ for (iter = &dev->adj_list.upper,
+ udev = netdev_next_upper_dev(dev, &iter);
+ udev;
+ udev = netdev_next_upper_dev(dev, &iter)) {
+ if (max_depth < udev->upper_level)
+ max_depth = udev->upper_level;
+ }
+
+ return max_depth;
+}
+
+static u8 __netdev_lower_depth(struct net_device *dev)
{
struct net_device *ldev;
struct list_head *iter;
- int ret;
+ u8 max_depth = 0;
for (iter = &dev->adj_list.lower,
- ldev = netdev_next_lower_dev_rcu(dev, &iter);
+ ldev = netdev_next_lower_dev(dev, &iter);
ldev;
- ldev = netdev_next_lower_dev_rcu(dev, &iter)) {
- /* first is the lower device itself */
- ret = fn(ldev, data);
- if (ret)
- return ret;
+ ldev = netdev_next_lower_dev(dev, &iter)) {
+ if (max_depth < ldev->lower_level)
+ max_depth = ldev->lower_level;
+ }
- /* then look at all of its lower devices */
- ret = netdev_walk_all_lower_dev_rcu(ldev, fn, data);
- if (ret)
- return ret;
+ return max_depth;
+}
+
+static int __netdev_update_upper_level(struct net_device *dev, void *data)
+{
+ dev->upper_level = __netdev_upper_depth(dev) + 1;
+ return 0;
+}
+
+static int __netdev_update_lower_level(struct net_device *dev, void *data)
+{
+ dev->lower_level = __netdev_lower_depth(dev) + 1;
+ return 0;
+}
+
+int netdev_walk_all_lower_dev_rcu(struct net_device *dev,
+ int (*fn)(struct net_device *dev,
+ void *data),
+ void *data)
+{
+ struct net_device *ldev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
+ struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
+ int ret, cur = 0;
+
+ now = dev;
+ iter = &dev->adj_list.lower;
+
+ while (1) {
+ if (now != dev) {
+ ret = fn(now, data);
+ if (ret)
+ return ret;
+ }
+
+ next = NULL;
+ while (1) {
+ ldev = netdev_next_lower_dev_rcu(now, &iter);
+ if (!ldev)
+ break;
+
+ if (!next) {
+ next = ldev;
+ niter = &ldev->adj_list.lower;
+ } else {
+ dev_stack[cur] = ldev;
+ iter_stack[cur++] = &ldev->adj_list.lower;
+ break;
+ }
+ }
+
+ if (!next) {
+ if (!cur)
+ return 0;
+ next = dev_stack[--cur];
+ niter = iter_stack[cur];
+ }
+
+ now = next;
+ iter = niter;
}
return 0;
+
}
EXPORT_SYMBOL_GPL(netdev_walk_all_lower_dev_rcu);
@@ -7063,6 +7242,9 @@ static int __netdev_upper_dev_link(struct net_device *dev,
if (netdev_has_upper_dev(upper_dev, dev))
return -EBUSY;
+ if ((dev->lower_level + upper_dev->upper_level) > MAX_NEST_DEV)
+ return -EMLINK;
+
if (!master) {
if (netdev_has_upper_dev(dev, upper_dev))
return -EEXIST;
@@ -7089,6 +7271,12 @@ static int __netdev_upper_dev_link(struct net_device *dev,
if (ret)
goto rollback;
+ __netdev_update_upper_level(dev, NULL);
+ netdev_walk_all_lower_dev(dev, __netdev_update_upper_level, NULL);
+
+ __netdev_update_lower_level(upper_dev, NULL);
+ netdev_walk_all_upper_dev(upper_dev, __netdev_update_lower_level, NULL);
+
return 0;
rollback:
@@ -7171,6 +7359,12 @@ void netdev_upper_dev_unlink(struct net_device *dev,
call_netdevice_notifiers_info(NETDEV_CHANGEUPPER,
&changeupper_info.info);
+
+ __netdev_update_upper_level(dev, NULL);
+ netdev_walk_all_lower_dev(dev, __netdev_update_upper_level, NULL);
+
+ __netdev_update_lower_level(upper_dev, NULL);
+ netdev_walk_all_upper_dev(upper_dev, __netdev_update_lower_level, NULL);
}
EXPORT_SYMBOL(netdev_upper_dev_unlink);
@@ -9159,6 +9353,8 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
dev->gso_max_size = GSO_MAX_SIZE;
dev->gso_max_segs = GSO_MAX_SEGS;
+ dev->upper_level = 1;
+ dev->lower_level = 1;
INIT_LIST_HEAD(&dev->napi_list);
INIT_LIST_HEAD(&dev->unreg_list);
--
2.17.1
^ permalink raw reply related
* [PATCH net v3 02/11] vlan: use dynamic lockdep key instead of subclass
From: Taehee Yoo @ 2019-09-16 13:47 UTC (permalink / raw)
To: davem, netdev, j.vosburgh, vfalico, andy, jiri, sd, roopa, saeedm,
manishc, rahulv, kys, haiyangz, stephen, sashal, hare, varun,
ubraun, kgraul, jay.vosburgh
Cc: ap420073
In-Reply-To: <20190916134802.8252-1-ap420073@gmail.com>
All VLAN device has same lockdep key and subclass is initialized with
nest_level.
But actual nest_level value can be changed when a lower device is attached.
And at this moment, the subclass should be updated but it seems to be
unsafe.
So this patch makes VLAN use dynamic lockdep key instead of the subclass.
Test commands:
ip link add dummy0 type dummy
ip link set dummy0 up
ip link add bond0 type bond
ip link add vlan_dummy1 link dummy0 type vlan id 1
ip link add vlan_bond1 link bond0 type vlan id 2
ip link set vlan_dummy1 master bond0
ip link set bond0 up
ip link set vlan_dummy1 up
ip link set vlan_bond1 up
Both vlan_dummy1 and vlan_bond1 have the same subclass and it makes
unnecessary deadlock warning message.
Splat looks like:
[ 66.163164] WARNING: possible recursive locking detected
[ 66.163858] 5.3.0-rc8+ #179 Not tainted
[ 66.165520] --------------------------------------------
[ 66.166110] ip/983 is trying to acquire lock:
[ 66.166603] 000000009b85ba3e (&vlan_netdev_addr_lock_key/1){+...}, at: dev_uc_sync_multiple+0xfa/0x1a0
[ 66.194006]
[ 66.194006] but task is already holding lock:
[ 66.194636] 00000000cc752363 (&vlan_netdev_addr_lock_key/1){+...}, at: dev_set_rx_mode+0x19/0x30
[ 66.205191]
[ 66.205191] other info that might help us debug this:
[ 66.205903] Possible unsafe locking scenario:
[ 66.205903]
[ 66.206504] CPU0
[ 66.206781] ----
[ 66.208737] lock(&vlan_netdev_addr_lock_key/1);
[ 66.257676] lock(&vlan_netdev_addr_lock_key/1);
[ 66.282069]
[ 66.282069] *** DEADLOCK ***
[ 66.282069]
[ 66.283708] May be due to missing lock nesting notation
[ 66.283708]
[ 66.284588] 4 locks held by ip/983:
[ 66.285035] #0: 000000002989e16e (rtnl_mutex){+.+.}, at: rtnetlink_rcv_msg+0x466/0x8a0
[ 66.286051] #1: 00000000cc752363 (&vlan_netdev_addr_lock_key/1){+...}, at: dev_set_rx_mode+0x19/0x30
[ 66.287217] #2: 00000000eddac627 (&dev_addr_list_lock_key/3){+...}, at: dev_mc_sync+0xfa/0x1a0
[ 66.288327] #3: 000000001a459ff7 (rcu_read_lock){....}, at: bond_set_rx_mode+0x5/0x3c0 [bonding]
[ 66.289453]
[ 66.289453] stack backtrace:
[ 66.290019] CPU: 1 PID: 983 Comm: ip Not tainted 5.3.0-rc8+ #179
[ 66.290802] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[ 66.297639] Call Trace:
[ 66.298009] dump_stack+0x7c/0xbb
[ 66.298447] __lock_acquire+0x26a9/0x3de0
[ 66.298965] ? register_lock_class+0x14d0/0x14d0
[ 66.299547] ? register_lock_class+0x14d0/0x14d0
[ 66.300151] lock_acquire+0x164/0x3b0
[ 66.300621] ? dev_uc_sync_multiple+0xfa/0x1a0
[ 66.301198] _raw_spin_lock_nested+0x2e/0x60
[ 66.301743] ? dev_uc_sync_multiple+0xfa/0x1a0
[ 66.302311] dev_uc_sync_multiple+0xfa/0x1a0
[ 66.307650] bond_set_rx_mode+0x269/0x3c0 [bonding]
[ 66.308175] ? bond_init+0x6f0/0x6f0 [bonding]
[ 66.308585] dev_mc_sync+0x15a/0x1a0
[ 66.308927] vlan_dev_set_rx_mode+0x37/0x80 [8021q]
[ 66.309375] dev_set_rx_mode+0x21/0x30
[ 66.309727] __dev_open+0x202/0x310
[ 66.310100] ? dev_set_rx_mode+0x30/0x30
[ 66.310513] ? mark_held_locks+0xa5/0xe0
[ 66.310934] ? __local_bh_enable_ip+0xe9/0x1b0
[ 66.311387] __dev_change_flags+0x3c3/0x500
[ 66.311839] ? dev_set_allmulti+0x10/0x10
[ 66.312248] ? kmem_cache_alloc_trace+0x12c/0x320
[ 66.312746] dev_change_flags+0x7a/0x160
[ 66.313161] vlan_device_event+0x846/0x20d0 [8021q]
[ ... ]
Fixes: 0fe1e567d0b4 ("[VLAN]: nested VLAN: fix lockdep's recursive locking warning")
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
---
v2 -> v3 :
- This patch is not changed
v1 -> v2 :
- This patch is not changed
include/linux/if_vlan.h | 3 +++
net/8021q/vlan_dev.c | 28 +++++++++++++++-------------
2 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 244278d5c222..1aed9f613e90 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -183,6 +183,9 @@ struct vlan_dev_priv {
struct netpoll *netpoll;
#endif
unsigned int nest_level;
+
+ struct lock_class_key xmit_lock_key;
+ struct lock_class_key addr_lock_key;
};
static inline struct vlan_dev_priv *vlan_dev_priv(const struct net_device *dev)
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 93eadf179123..12bc80650087 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -494,24 +494,24 @@ static void vlan_dev_set_rx_mode(struct net_device *vlan_dev)
* "super class" of normal network devices; split their locks off into a
* separate class since they always nest.
*/
-static struct lock_class_key vlan_netdev_xmit_lock_key;
-static struct lock_class_key vlan_netdev_addr_lock_key;
-
static void vlan_dev_set_lockdep_one(struct net_device *dev,
struct netdev_queue *txq,
- void *_subclass)
+ void *_unused)
{
- lockdep_set_class_and_subclass(&txq->_xmit_lock,
- &vlan_netdev_xmit_lock_key,
- *(int *)_subclass);
+ struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
+
+ lockdep_set_class(&txq->_xmit_lock, &vlan->xmit_lock_key);
}
-static void vlan_dev_set_lockdep_class(struct net_device *dev, int subclass)
+static void vlan_dev_set_lockdep_class(struct net_device *dev)
{
- lockdep_set_class_and_subclass(&dev->addr_list_lock,
- &vlan_netdev_addr_lock_key,
- subclass);
- netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, &subclass);
+ struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
+
+ lockdep_register_key(&vlan->addr_lock_key);
+ lockdep_set_class(&dev->addr_list_lock, &vlan->addr_lock_key);
+
+ lockdep_register_key(&vlan->xmit_lock_key);
+ netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, NULL);
}
static int vlan_dev_get_lock_subclass(struct net_device *dev)
@@ -609,7 +609,7 @@ static int vlan_dev_init(struct net_device *dev)
SET_NETDEV_DEVTYPE(dev, &vlan_type);
- vlan_dev_set_lockdep_class(dev, vlan_dev_get_lock_subclass(dev));
+ vlan_dev_set_lockdep_class(dev);
vlan->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats);
if (!vlan->vlan_pcpu_stats)
@@ -630,6 +630,8 @@ static void vlan_dev_uninit(struct net_device *dev)
kfree(pm);
}
}
+ lockdep_unregister_key(&vlan->addr_lock_key);
+ lockdep_unregister_key(&vlan->xmit_lock_key);
}
static netdev_features_t vlan_dev_fix_features(struct net_device *dev,
--
2.17.1
^ permalink raw reply related
* [PATCH net v3 03/11] bonding: fix unexpected IFF_BONDING bit unset
From: Taehee Yoo @ 2019-09-16 13:47 UTC (permalink / raw)
To: davem, netdev, j.vosburgh, vfalico, andy, jiri, sd, roopa, saeedm,
manishc, rahulv, kys, haiyangz, stephen, sashal, hare, varun,
ubraun, kgraul, jay.vosburgh
Cc: ap420073
In-Reply-To: <20190916134802.8252-1-ap420073@gmail.com>
The IFF_BONDING means bonding master or bonding slave device.
->ndo_add_slave() sets IFF_BONDING flag and ->ndo_del_slave() unsets
IFF_BONDING flag.
bond0<--bond1
Both bond0 and bond1 are bonding device and these should keep having
IFF_BONDING flag until they are removed.
But bond1 would lose IFF_BONDING at ->ndo_del_slave() because that routine
do not check whether the slave device is the bonding type or not.
This patch adds the interface type check routine before removing
IFF_BONDING flag.
Test commands:
ip link add bond0 type bond
ip link add bond1 type bond
ip link set bond1 master bond0
ip link set bond1 nomaster
ip link del bond1 type bond
ip link add bond1 type bond
Splat looks like:
[ 58.210981] proc_dir_entry 'bonding/bond1' already registered
[ 58.463875] WARNING: CPU: 0 PID: 955 at fs/proc/generic.c:361 proc_register+0x2a9/0x3e0
[ 58.466423] Modules linked in: bonding veth openvswitch nsh nf_conncount nf_nat nf_conntrack nf_defrag_ipv6 nfs
[ 58.483855] CPU: 0 PID: 955 Comm: ip Not tainted 5.3.0-rc8+ #179
[ 58.484657] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[ 58.485779] RIP: 0010:proc_register+0x2a9/0x3e0
[ 58.486377] Code: 89 fa 48 c1 ea 03 80 3c 02 00 0f 85 39 01 00 00 48 8b 04 24 48 89 ea 48 c7 c7 60 0f 14 bd 480
[ 58.489003] RSP: 0018:ffff8880cc007078 EFLAGS: 00010282
[ 58.553743] RAX: dffffc0000000008 RBX: ffff8880ce23c0d0 RCX: ffffffffbbd021e2
[ 58.584076] RDX: 0000000000000001 RSI: 0000000000000008 RDI: ffff8880da5f6b8c
[ 58.584901] RBP: ffff8880ce23c353 R08: ffffed101b4bff91 R09: ffffed101b4bff91
[ 58.585724] R10: 0000000000000001 R11: ffffed101b4bff90 R12: ffff8880ce23c268
[ 58.586508] R13: ffff8880ce23c352 R14: dffffc0000000000 R15: ffffed1019c4786a
[ 58.587296] FS: 00007f52d53b60c0(0000) GS:ffff8880da400000(0000) knlGS:0000000000000000
[ 58.588247] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 58.653694] CR2: 00007f31a9df9320 CR3: 00000000cd4ea006 CR4: 00000000000606f0
[ 58.654591] Call Trace:
[ 58.654895] proc_create_seq_private+0xb3/0xf0
[ 58.655400] bond_create_proc_entry+0x1b3/0x3f0 [bonding]
[ 58.655985] bond_netdev_event+0x433/0x970 [bonding]
[ 58.656545] ? __module_text_address+0x13/0x140
[ 58.657038] notifier_call_chain+0x90/0x160
[ 58.657541] register_netdevice+0x9b3/0xd80
[ 58.657999] ? alloc_netdev_mqs+0x854/0xc10
[ 58.658476] ? netdev_change_features+0xa0/0xa0
[ 58.663592] ? rtnl_create_link+0x2ed/0xad0
[ 58.664049] bond_newlink+0x2a/0x60 [bonding]
[ 58.664529] __rtnl_newlink+0xb9f/0x11b0
[ 58.665014] ? rtnl_link_unregister+0x230/0x230
[ ... ]
Fixes: 0b680e753724 ("[PATCH] bonding: Add priv_flag to avoid event mishandling")
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
---
v2 -> v3 :
- This patch is not changed
v1 -> v2 :
- Do not add a new priv_flag.
drivers/net/bonding/bond_main.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 931d9d935686..0db12fcfc953 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1816,7 +1816,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
slave_disable_netpoll(new_slave);
err_close:
- slave_dev->priv_flags &= ~IFF_BONDING;
+ if (!netif_is_bond_master(slave_dev))
+ slave_dev->priv_flags &= ~IFF_BONDING;
dev_close(slave_dev);
err_restore_mac:
@@ -2017,7 +2018,8 @@ static int __bond_release_one(struct net_device *bond_dev,
else
dev_set_mtu(slave_dev, slave->original_mtu);
- slave_dev->priv_flags &= ~IFF_BONDING;
+ if (!netif_is_bond_master(slave_dev))
+ slave_dev->priv_flags &= ~IFF_BONDING;
bond_free_slave(slave);
--
2.17.1
^ permalink raw reply related
* [PATCH net v3 04/11] bonding: use dynamic lockdep key instead of subclass
From: Taehee Yoo @ 2019-09-16 13:47 UTC (permalink / raw)
To: davem, netdev, j.vosburgh, vfalico, andy, jiri, sd, roopa, saeedm,
manishc, rahulv, kys, haiyangz, stephen, sashal, hare, varun,
ubraun, kgraul, jay.vosburgh
Cc: ap420073
In-Reply-To: <20190916134802.8252-1-ap420073@gmail.com>
All bonding device has same lockdep key and subclass is initialized with
nest_level.
But actual nest_level value can be changed when a lower device is attached.
And at this moment, the subclass should be updated but it seems to be
unsafe.
So this patch makes bonding use dynamic lockdep key instead of the
subclass.
Test commands:
ip link add bond0 type bond
for i in {1..5}
do
let A=$i-1
ip link add bond$i type bond
ip link set bond$i master bond$A
done
ip link set bond5 master bond0
Splat looks like:
[ 53.930344] WARNING: possible recursive locking detected
[ 53.931041] 5.3.0-rc8+ #179 Not tainted
[ 53.931554] --------------------------------------------
[ 53.932285] ip/984 is trying to acquire lock:
[ 53.932854] 00000000e313b280 (&(&bond->stats_lock)->rlock#2/2){+.+.}, at: bond_get_stats+0xb8/0x500 [bonding]
[ 53.934144]
[ 53.934144] but task is already holding lock:
[ 53.934907] 00000000f5a0c2e3 (&(&bond->stats_lock)->rlock#2/2){+.+.}, at: bond_get_stats+0xb8/0x500 [bonding]
[ 53.936268]
[ 53.936268] other info that might help us debug this:
[ 53.937135] Possible unsafe locking scenario:
[ 53.937135]
[ 53.937910] CPU0
[ 53.938247] ----
[ 53.938577] lock(&(&bond->stats_lock)->rlock#2/2);
[ 53.939234] lock(&(&bond->stats_lock)->rlock#2/2);
[ 53.939903]
[ 53.939903] *** DEADLOCK ***
[ 53.939903]
[ 53.940745] May be due to missing lock nesting notation
[ 53.940745]
[ 53.941626] 3 locks held by ip/984:
[ 53.942005] #0: 000000009e3df2a0 (rtnl_mutex){+.+.}, at: rtnetlink_rcv_msg+0x466/0x8a0
[ 53.942942] #1: 00000000f5a0c2e3 (&(&bond->stats_lock)->rlock#2/2){+.+.}, at: bond_get_stats+0xb8/0x500 [bond]
[ 53.944194] #2: 000000005b301abc (rcu_read_lock){....}, at: bond_get_stats+0x9f/0x500 [bonding]
[ 53.945168]
[ 53.945168] stack backtrace:
[ 53.945672] CPU: 0 PID: 984 Comm: ip Not tainted 5.3.0-rc8+ #179
[ 53.946606] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[ 53.947529] Call Trace:
[ 53.947795] dump_stack+0x7c/0xbb
[ 53.948213] __lock_acquire+0x26a9/0x3de0
[ 53.948666] ? register_lock_class+0x14d0/0x14d0
[ 53.949206] lock_acquire+0x164/0x3b0
[ 53.949647] ? bond_get_stats+0xb8/0x500 [bonding]
[ 53.950169] _raw_spin_lock_nested+0x2e/0x60
[ 53.950630] ? bond_get_stats+0xb8/0x500 [bonding]
[ 53.951132] bond_get_stats+0xb8/0x500 [bonding]
[ 53.951655] ? bond_arp_rcv+0xf10/0xf10 [bonding]
[ 53.952220] ? register_lock_class+0x14d0/0x14d0
[ 53.952751] ? bond_get_stats+0xb8/0x500 [bonding]
[ 53.953277] dev_get_stats+0x1ec/0x270
[ 53.984289] bond_get_stats+0x1d1/0x500 [bonding]
[ 53.984803] ? bond_arp_rcv+0xf10/0xf10 [bonding]
[ 53.985323] ? dev_get_alias+0xe2/0x190
[ 53.985748] ? nla_put_ifalias+0x71/0x100
[ 53.986213] ? rtnl_phys_switch_id_fill+0x91/0x100
[ 53.986720] dev_get_stats+0x1ec/0x270
[ 53.987100] rtnl_fill_stats+0x44/0xbe0
[ 53.987494] ? nla_put+0xc2/0x140
[ 53.987828] rtnl_fill_ifinfo+0xec7/0x35b0
[ ... ]
Fixes: d3fff6c443fe ("net: add netdev_lockdep_set_classes() helper")
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
---
v2 -> v3 :
- This patch is not changed
v1 -> v2 :
- This patch is not changed
drivers/net/bonding/bond_main.c | 61 ++++++++++++++++++++++++++++++---
include/net/bonding.h | 3 ++
2 files changed, 59 insertions(+), 5 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 0db12fcfc953..7f574e74ed78 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1857,6 +1857,32 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
return res;
}
+static void bond_dev_set_lockdep_one(struct net_device *dev,
+ struct netdev_queue *txq,
+ void *_unused)
+{
+ struct bonding *bond = netdev_priv(dev);
+
+ lockdep_set_class(&txq->_xmit_lock, &bond->xmit_lock_key);
+}
+
+static void bond_update_lock_key(struct net_device *dev)
+{
+ struct bonding *bond = netdev_priv(dev);
+
+ lockdep_unregister_key(&bond->stats_lock_key);
+ lockdep_unregister_key(&bond->addr_lock_key);
+ lockdep_unregister_key(&bond->xmit_lock_key);
+
+ lockdep_register_key(&bond->stats_lock_key);
+ lockdep_register_key(&bond->addr_lock_key);
+ lockdep_register_key(&bond->xmit_lock_key);
+
+ lockdep_set_class(&bond->stats_lock, &bond->stats_lock_key);
+ lockdep_set_class(&dev->addr_list_lock, &bond->addr_lock_key);
+ netdev_for_each_tx_queue(dev, bond_dev_set_lockdep_one, NULL);
+}
+
/* Try to release the slave device <slave> from the bond device <master>
* It is legal to access curr_active_slave without a lock because all the function
* is RTNL-locked. If "all" is true it means that the function is being called
@@ -2022,6 +2048,8 @@ static int __bond_release_one(struct net_device *bond_dev,
slave_dev->priv_flags &= ~IFF_BONDING;
bond_free_slave(slave);
+ if (netif_is_bond_master(slave_dev))
+ bond_update_lock_key(slave_dev);
return 0;
}
@@ -3459,7 +3487,7 @@ static void bond_get_stats(struct net_device *bond_dev,
struct list_head *iter;
struct slave *slave;
- spin_lock_nested(&bond->stats_lock, bond_get_nest_level(bond_dev));
+ spin_lock(&bond->stats_lock);
memcpy(stats, &bond->bond_stats, sizeof(*stats));
rcu_read_lock();
@@ -4297,8 +4325,6 @@ void bond_setup(struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
- spin_lock_init(&bond->mode_lock);
- spin_lock_init(&bond->stats_lock);
bond->params = bonding_defaults;
/* Initialize pointers */
@@ -4367,6 +4393,9 @@ static void bond_uninit(struct net_device *bond_dev)
list_del(&bond->bond_list);
+ lockdep_unregister_key(&bond->stats_lock_key);
+ lockdep_unregister_key(&bond->addr_lock_key);
+ lockdep_unregister_key(&bond->xmit_lock_key);
bond_debug_unregister(bond);
}
@@ -4758,6 +4787,29 @@ static int bond_check_params(struct bond_params *params)
return 0;
}
+static struct lock_class_key qdisc_tx_busylock_key;
+static struct lock_class_key qdisc_running_key;
+
+static void bond_dev_set_lockdep_class(struct net_device *dev)
+{
+ struct bonding *bond = netdev_priv(dev);
+
+ dev->qdisc_tx_busylock = &qdisc_tx_busylock_key;
+ dev->qdisc_running_key = &qdisc_running_key;
+
+ spin_lock_init(&bond->mode_lock);
+
+ spin_lock_init(&bond->stats_lock);
+ lockdep_register_key(&bond->stats_lock_key);
+ lockdep_set_class(&bond->stats_lock, &bond->stats_lock_key);
+
+ lockdep_register_key(&bond->addr_lock_key);
+ lockdep_set_class(&dev->addr_list_lock, &bond->addr_lock_key);
+
+ lockdep_register_key(&bond->xmit_lock_key);
+ netdev_for_each_tx_queue(dev, bond_dev_set_lockdep_one, NULL);
+}
+
/* Called from registration process */
static int bond_init(struct net_device *bond_dev)
{
@@ -4771,8 +4823,7 @@ static int bond_init(struct net_device *bond_dev)
return -ENOMEM;
bond->nest_level = SINGLE_DEPTH_NESTING;
- netdev_lockdep_set_classes(bond_dev);
-
+ bond_dev_set_lockdep_class(bond_dev);
list_add_tail(&bond->bond_list, &bn->dev_list);
bond_prepare_sysfs_group(bond);
diff --git a/include/net/bonding.h b/include/net/bonding.h
index f7fe45689142..c39ac7061e41 100644
--- a/include/net/bonding.h
+++ b/include/net/bonding.h
@@ -239,6 +239,9 @@ struct bonding {
struct dentry *debug_dir;
#endif /* CONFIG_DEBUG_FS */
struct rtnl_link_stats64 bond_stats;
+ struct lock_class_key stats_lock_key;
+ struct lock_class_key xmit_lock_key;
+ struct lock_class_key addr_lock_key;
};
#define bond_slave_get_rcu(dev) \
--
2.17.1
^ permalink raw reply related
* [PATCH net v3 05/11] team: use dynamic lockdep key instead of static key
From: Taehee Yoo @ 2019-09-16 13:47 UTC (permalink / raw)
To: davem, netdev, j.vosburgh, vfalico, andy, jiri, sd, roopa, saeedm,
manishc, rahulv, kys, haiyangz, stephen, sashal, hare, varun,
ubraun, kgraul, jay.vosburgh
Cc: ap420073
In-Reply-To: <20190916134802.8252-1-ap420073@gmail.com>
In the current code, all team devices have same static lockdep key
and team devices could be nested so that it makes unnecessary
lockdep warning.
Test commands:
ip link add team0 type team
for i in {1..7}
do
let A=$i-1
ip link add team$i type team
ip link set team$i master team$A
done
ip link del team0
Splat looks like:
[ 52.518420] WARNING: possible recursive locking detected
[ 52.518955] 5.3.0-rc8+ #179 Not tainted
[ 52.519373] --------------------------------------------
[ 52.519925] ip/1005 is trying to acquire lock:
[ 52.520893] 00000000c84e69ac (&dev_addr_list_lock_key/1){+...}, at: dev_uc_sync_multiple+0xfa/0x1a0
[ 52.522194]
[ 52.522194] but task is already holding lock:
[ 52.523038] 0000000025864f52 (&dev_addr_list_lock_key/1){+...}, at: dev_uc_unsync+0x10c/0x1b0
[ 52.524609]
[ 52.524609] other info that might help us debug this:
[ 52.525435] Possible unsafe locking scenario:
[ 52.525435]
[ 52.526154] CPU0
[ 52.526460] ----
[ 52.526766] lock(&dev_addr_list_lock_key/1);
[ 52.527311] lock(&dev_addr_list_lock_key/1);
[ 52.527854]
[ 52.527854] *** DEADLOCK ***
[ 52.527854]
[ 52.528573] May be due to missing lock nesting notation
[ 52.528573]
[ 52.529527] 5 locks held by ip/1005:
[ 52.529968] #0: 0000000080a68bb2 (rtnl_mutex){+.+.}, at: rtnetlink_rcv_msg+0x466/0x8a0
[ 52.530940] #1: 0000000035d90450 (&team->lock){+.+.}, at: team_uninit+0x3a/0x1a0 [team]
[ 52.531933] #2: 00000000c75d8f70 (&dev_addr_list_lock_key){+...}, at: dev_uc_unsync+0x98/0x1b0
[ 52.532991] #3: 0000000025864f52 (&dev_addr_list_lock_key/1){+...}, at: dev_uc_unsync+0x10c/0x1b0
[ 52.534142] #4: 00000000efa4d642 (rcu_read_lock){....}, at: team_set_rx_mode+0x5/0x1d0 [team]
[ 52.535195]
[ 52.535195] stack backtrace:
[ 52.535727] CPU: 0 PID: 1005 Comm: ip Not tainted 5.3.0-rc8+ #179
[ 52.536376] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[ 52.537254] Call Trace:
[ 52.537549] dump_stack+0x7c/0xbb
[ 52.537917] __lock_acquire+0x26a9/0x3de0
[ 52.538340] ? register_lock_class+0x14d0/0x14d0
[ 52.538872] ? register_lock_class+0x14d0/0x14d0
[ 52.539559] lock_acquire+0x164/0x3b0
[ 52.540043] ? dev_uc_sync_multiple+0xfa/0x1a0
[ 52.540663] _raw_spin_lock_nested+0x2e/0x60
[ 52.541241] ? dev_uc_sync_multiple+0xfa/0x1a0
[ 52.541867] dev_uc_sync_multiple+0xfa/0x1a0
[ 52.542435] team_set_rx_mode+0xa9/0x1d0 [team]
[ 52.543033] dev_uc_unsync+0x151/0x1b0
[ 52.543534] team_port_del+0x304/0x790 [team]
[ 52.544110] team_uninit+0xb0/0x1a0 [team]
[ 52.544653] rollback_registered_many+0x728/0xda0
[ 52.545271] ? generic_xdp_install+0x310/0x310
[ 52.545865] ? check_chain_key+0x236/0x5d0
[ 52.546425] ? __nla_validate_parse+0x98/0x1ad0
[ 52.547023] unregister_netdevice_many.part.124+0x13/0x1b0
[ 52.547741] rtnl_delete_link+0xbc/0x100
[ 52.548262] ? rtnl_af_register+0xc0/0xc0
[ 52.548793] rtnl_dellink+0x30e/0x8a0
[ ... ]
Fixes: 3d249d4ca7d0 ("net: introduce ethernet teaming device")
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
---
v2 -> v3 :
- This patch is not changed
v1 -> v2 :
- This patch is not changed
drivers/net/team/team.c | 61 ++++++++++++++++++++++++++++++++++++++---
include/linux/if_team.h | 5 ++++
2 files changed, 62 insertions(+), 4 deletions(-)
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index e8089def5a46..bfcd6ed57493 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1607,6 +1607,34 @@ static const struct team_option team_options[] = {
},
};
+static void team_dev_set_lockdep_one(struct net_device *dev,
+ struct netdev_queue *txq,
+ void *_unused)
+{
+ struct team *team = netdev_priv(dev);
+
+ lockdep_set_class(&txq->_xmit_lock, &team->xmit_lock_key);
+}
+
+static struct lock_class_key qdisc_tx_busylock_key;
+static struct lock_class_key qdisc_running_key;
+
+static void team_dev_set_lockdep_class(struct net_device *dev)
+{
+ struct team *team = netdev_priv(dev);
+
+ dev->qdisc_tx_busylock = &qdisc_tx_busylock_key;
+ dev->qdisc_running_key = &qdisc_running_key;
+
+ lockdep_register_key(&team->team_lock_key);
+ __mutex_init(&team->lock, "team->team_lock_key", &team->team_lock_key);
+
+ lockdep_register_key(&team->addr_lock_key);
+ lockdep_set_class(&dev->addr_list_lock, &team->addr_lock_key);
+
+ lockdep_register_key(&team->xmit_lock_key);
+ netdev_for_each_tx_queue(dev, team_dev_set_lockdep_one, NULL);
+}
static int team_init(struct net_device *dev)
{
@@ -1615,7 +1643,6 @@ static int team_init(struct net_device *dev)
int err;
team->dev = dev;
- mutex_init(&team->lock);
team_set_no_mode(team);
team->pcpu_stats = netdev_alloc_pcpu_stats(struct team_pcpu_stats);
@@ -1642,7 +1669,7 @@ static int team_init(struct net_device *dev)
goto err_options_register;
netif_carrier_off(dev);
- netdev_lockdep_set_classes(dev);
+ team_dev_set_lockdep_class(dev);
return 0;
@@ -1673,6 +1700,11 @@ static void team_uninit(struct net_device *dev)
team_queue_override_fini(team);
mutex_unlock(&team->lock);
netdev_change_features(dev);
+
+ lockdep_unregister_key(&team->team_lock_key);
+ lockdep_unregister_key(&team->addr_lock_key);
+ lockdep_unregister_key(&team->xmit_lock_key);
+
}
static void team_destructor(struct net_device *dev)
@@ -1967,6 +1999,23 @@ static int team_add_slave(struct net_device *dev, struct net_device *port_dev,
return err;
}
+static void team_update_lock_key(struct net_device *dev)
+{
+ struct team *team = netdev_priv(dev);
+
+ lockdep_unregister_key(&team->team_lock_key);
+ lockdep_unregister_key(&team->addr_lock_key);
+ lockdep_unregister_key(&team->xmit_lock_key);
+
+ lockdep_register_key(&team->team_lock_key);
+ lockdep_register_key(&team->addr_lock_key);
+ lockdep_register_key(&team->xmit_lock_key);
+
+ lockdep_set_class(&team->lock, &team->team_lock_key);
+ lockdep_set_class(&dev->addr_list_lock, &team->addr_lock_key);
+ netdev_for_each_tx_queue(dev, team_dev_set_lockdep_one, NULL);
+}
+
static int team_del_slave(struct net_device *dev, struct net_device *port_dev)
{
struct team *team = netdev_priv(dev);
@@ -1976,8 +2025,12 @@ static int team_del_slave(struct net_device *dev, struct net_device *port_dev)
err = team_port_del(team, port_dev);
mutex_unlock(&team->lock);
- if (!err)
- netdev_change_features(dev);
+ if (err)
+ return err;
+
+ if (netif_is_team_master(port_dev))
+ team_update_lock_key(port_dev);
+ netdev_change_features(dev);
return err;
}
diff --git a/include/linux/if_team.h b/include/linux/if_team.h
index 06faa066496f..9c97bb19ed34 100644
--- a/include/linux/if_team.h
+++ b/include/linux/if_team.h
@@ -223,6 +223,11 @@ struct team {
atomic_t count_pending;
struct delayed_work dw;
} mcast_rejoin;
+
+ struct lock_class_key team_lock_key;
+ struct lock_class_key xmit_lock_key;
+ struct lock_class_key addr_lock_key;
+
long mode_priv[TEAM_MODE_PRIV_LONGS];
};
--
2.17.1
^ permalink raw reply related
* [PATCH net v3 06/11] macsec: use dynamic lockdep key instead of subclass
From: Taehee Yoo @ 2019-09-16 13:47 UTC (permalink / raw)
To: davem, netdev, j.vosburgh, vfalico, andy, jiri, sd, roopa, saeedm,
manishc, rahulv, kys, haiyangz, stephen, sashal, hare, varun,
ubraun, kgraul, jay.vosburgh
Cc: ap420073
In-Reply-To: <20190916134802.8252-1-ap420073@gmail.com>
All macsec device has same lockdep key and subclass is initialized with
nest_level.
But actual nest_level value can be changed when a lower device is attached.
And at this moment, the subclass should be updated but it seems to be
unsafe.
So this patch makes macsec use dynamic lockdep key instead of the subclass.
Test commands:
ip link add bond0 type bond
ip link add dummy0 type dummy
ip link add macsec0 link bond0 type macsec
ip link add macsec1 link dummy0 type macsec
ip link set bond0 mtu 1000
ip link set macsec1 master bond0
ip link set bond0 up
ip link set macsec0 up
ip link set dummy0 up
ip link set macsec1 up
Splat looks like:
[ 57.903193] WARNING: possible recursive locking detected
[ 57.913011] 5.3.0-rc8+ #179 Not tainted
[ 57.915008] --------------------------------------------
[ 57.916707] ip/964 is trying to acquire lock:
[ 57.917102] 000000007f1963bf (&macsec_netdev_addr_lock_key/1){+...}, at: dev_uc_sync_multiple+0xfa/0x1a0
[ 57.918476]
[ 57.918476] but task is already holding lock:
[ 57.918996] 000000006f6fbc66 (&macsec_netdev_addr_lock_key/1){+...}, at: dev_set_rx_mode+0x19/0x30
[ 57.919790]
[ 57.919790] other info that might help us debug this:
[ 57.920367] Possible unsafe locking scenario:
[ 57.920367]
[ 57.920894] CPU0
[ 57.921119] ----
[ 57.921366] lock(&macsec_netdev_addr_lock_key/1);
[ 57.921813] lock(&macsec_netdev_addr_lock_key/1);
[ 57.922250]
[ 57.922250] *** DEADLOCK ***
[ 57.922250]
[ 57.924742] May be due to missing lock nesting notation
[ 57.924742]
[ 57.925620] 4 locks held by ip/964:
[ 57.926067] #0: 00000000bf0ca196 (rtnl_mutex){+.+.}, at: rtnetlink_rcv_msg+0x466/0x8a0
[ 57.927070] #1: 000000006f6fbc66 (&macsec_netdev_addr_lock_key/1){+...}, at: dev_set_rx_mode+0x19/0x30
[ 57.928241] #2: 00000000e5b874a1 (&dev_addr_list_lock_key/3){+...}, at: dev_mc_sync+0xfa/0x1a0
[ 57.929851] #3: 000000002c43dd91 (rcu_read_lock){....}, at: bond_set_rx_mode+0x5/0x3c0 [bonding]
[ 57.930983]
[ 57.930983] stack backtrace:
[ 57.931582] CPU: 1 PID: 964 Comm: ip Not tainted 5.3.0-rc8+ #179
[ 57.932439] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[ 57.935333] Call Trace:
[ 57.935659] dump_stack+0x7c/0xbb
[ 57.936088] __lock_acquire+0x26a9/0x3de0
[ 57.936590] ? register_lock_class+0x14d0/0x14d0
[ 57.937694] ? register_lock_class+0x14d0/0x14d0
[ 57.938269] lock_acquire+0x164/0x3b0
[ 57.938734] ? dev_uc_sync_multiple+0xfa/0x1a0
[ 57.939291] _raw_spin_lock_nested+0x2e/0x60
[ 57.940112] ? dev_uc_sync_multiple+0xfa/0x1a0
[ 57.940672] dev_uc_sync_multiple+0xfa/0x1a0
[ 57.941730] bond_set_rx_mode+0x269/0x3c0 [bonding]
[ 57.942340] ? bond_init+0x6f0/0x6f0 [bonding]
[ 57.942895] ? do_raw_spin_trylock+0xa9/0x170
[ 57.943435] dev_mc_sync+0x15a/0x1a0
[ 57.943891] macsec_dev_set_rx_mode+0x3a/0x50 [macsec]
[ 57.944560] dev_set_rx_mode+0x21/0x30
[ 57.945051] __dev_open+0x202/0x310
[ ... ]
Fixes: e20038724552 ("macsec: fix lockdep splats when nesting devices")
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
---
v2 -> v3 :
- This patch is not changed
v1 -> v2 :
- This patch is not changed
drivers/net/macsec.c | 37 ++++++++++++++++++++++++++++++++-----
1 file changed, 32 insertions(+), 5 deletions(-)
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index 8f46aa1ddec0..25a4fc88145d 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -267,6 +267,8 @@ struct macsec_dev {
struct pcpu_secy_stats __percpu *stats;
struct list_head secys;
struct gro_cells gro_cells;
+ struct lock_class_key xmit_lock_key;
+ struct lock_class_key addr_lock_key;
unsigned int nest_level;
};
@@ -2749,7 +2751,32 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
#define MACSEC_FEATURES \
(NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST)
-static struct lock_class_key macsec_netdev_addr_lock_key;
+
+static void macsec_dev_set_lockdep_one(struct net_device *dev,
+ struct netdev_queue *txq,
+ void *_unused)
+{
+ struct macsec_dev *macsec = macsec_priv(dev);
+
+ lockdep_set_class(&txq->_xmit_lock, &macsec->xmit_lock_key);
+}
+
+static struct lock_class_key qdisc_tx_busylock_key;
+static struct lock_class_key qdisc_running_key;
+
+static void macsec_dev_set_lockdep_class(struct net_device *dev)
+{
+ struct macsec_dev *macsec = macsec_priv(dev);
+
+ dev->qdisc_tx_busylock = &qdisc_tx_busylock_key;
+ dev->qdisc_running_key = &qdisc_running_key;
+
+ lockdep_register_key(&macsec->addr_lock_key);
+ lockdep_set_class(&dev->addr_list_lock, &macsec->addr_lock_key);
+
+ lockdep_register_key(&macsec->xmit_lock_key);
+ netdev_for_each_tx_queue(dev, macsec_dev_set_lockdep_one, NULL);
+}
static int macsec_dev_init(struct net_device *dev)
{
@@ -2780,6 +2807,7 @@ static int macsec_dev_init(struct net_device *dev)
if (is_zero_ether_addr(dev->broadcast))
memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len);
+ macsec_dev_set_lockdep_class(dev);
return 0;
}
@@ -2789,6 +2817,9 @@ static void macsec_dev_uninit(struct net_device *dev)
gro_cells_destroy(&macsec->gro_cells);
free_percpu(dev->tstats);
+
+ lockdep_unregister_key(&macsec->addr_lock_key);
+ lockdep_unregister_key(&macsec->xmit_lock_key);
}
static netdev_features_t macsec_fix_features(struct net_device *dev,
@@ -3263,10 +3294,6 @@ static int macsec_newlink(struct net *net, struct net_device *dev,
dev_hold(real_dev);
macsec->nest_level = dev_get_nest_level(real_dev) + 1;
- netdev_lockdep_set_classes(dev);
- lockdep_set_class_and_subclass(&dev->addr_list_lock,
- &macsec_netdev_addr_lock_key,
- macsec_get_nest_level(dev));
err = netdev_upper_dev_link(real_dev, dev, extack);
if (err < 0)
--
2.17.1
^ permalink raw reply related
* [PATCH net v3 07/11] macvlan: use dynamic lockdep key instead of subclass
From: Taehee Yoo @ 2019-09-16 13:47 UTC (permalink / raw)
To: davem, netdev, j.vosburgh, vfalico, andy, jiri, sd, roopa, saeedm,
manishc, rahulv, kys, haiyangz, stephen, sashal, hare, varun,
ubraun, kgraul, jay.vosburgh
Cc: ap420073
In-Reply-To: <20190916134802.8252-1-ap420073@gmail.com>
All macvlan device has same lockdep key and subclass is initialized with
nest_level.
But actual nest_level value can be changed when a lower device is attached.
And at this moment, the subclass should be updated but it seems to be
unsafe.
So this patch makes macvlan use dynamic lockdep key instead of the
subclass.
Test commands:
ip link add bond0 type bond
ip link add dummy0 type dummy
ip link add macvlan0 link bond0 type macvlan mode bridge
ip link add macvlan1 link dummy0 type macvlan mode bridge
ip link set bond0 mtu 1000
ip link set macvlan1 master bond0
ip link set bond0 up
ip link set macvlan0 up
ip link set dummy0 up
ip link set macvlan1 up
Splat looks like:
[ 55.694677] WARNING: possible recursive locking detected
[ 55.695420] 5.3.0-rc8+ #179 Not tainted
[ 55.709918] --------------------------------------------
[ 55.711814] ip/982 is trying to acquire lock:
[ 55.712387] 0000000023ca93f4 (&macvlan_netdev_addr_lock_key/1){+...}, at: dev_uc_sync_multiple+0xfa/0x1a0
[ 55.713621]
[ 55.713621] but task is already holding lock:
[ 55.714364] 0000000070c93e9d (&macvlan_netdev_addr_lock_key/1){+...}, at: dev_set_rx_mode+0x19/0x30
[ 55.715548]
[ 55.715548] other info that might help us debug this:
[ 55.716428] Possible unsafe locking scenario:
[ 55.716428]
[ 55.717231] CPU0
[ 55.717563] ----
[ 55.717907] lock(&macvlan_netdev_addr_lock_key/1);
[ 55.718574] lock(&macvlan_netdev_addr_lock_key/1);
[ 55.719149]
[ 55.719149] *** DEADLOCK ***
[ 55.719149]
[ 55.719865] May be due to missing lock nesting notation
[ 55.719865]
[ 55.720607] 4 locks held by ip/982:
[ 55.721056] #0: 0000000096ab2afb (rtnl_mutex){+.+.}, at: rtnetlink_rcv_msg+0x466/0x8a0
[ 55.722031] #1: 0000000070c93e9d (&macvlan_netdev_addr_lock_key/1){+...}, at: dev_set_rx_mode+0x19/0x30
[ 55.791914] #2: 000000005409683b (&dev_addr_list_lock_key/3){+...}, at: dev_uc_sync+0xfa/0x1a0
[ 55.792718] #3: 0000000085f78eaf (rcu_read_lock){....}, at: bond_set_rx_mode+0x5/0x3c0 [bonding]
[ 55.793533]
[ 55.793533] stack backtrace:
[ 55.793939] CPU: 0 PID: 982 Comm: ip Not tainted 5.3.0-rc8+ #179
[ 55.794489] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[ 55.795227] Call Trace:
[ 55.795493] dump_stack+0x7c/0xbb
[ 55.795809] __lock_acquire+0x26a9/0x3de0
[ 55.796184] ? register_lock_class+0x14d0/0x14d0
[ 55.797496] ? register_lock_class+0x14d0/0x14d0
[ 55.797971] lock_acquire+0x164/0x3b0
[ 55.838601] ? dev_uc_sync_multiple+0xfa/0x1a0
[ 55.839281] _raw_spin_lock_nested+0x2e/0x60
[ 55.840289] ? dev_uc_sync_multiple+0xfa/0x1a0
[ 55.841308] dev_uc_sync_multiple+0xfa/0x1a0
[ 55.841868] bond_set_rx_mode+0x269/0x3c0 [bonding]
[ 55.842500] ? bond_init+0x6f0/0x6f0 [bonding]
[ 55.843076] dev_uc_sync+0x15a/0x1a0
[ 55.843567] macvlan_set_mac_lists+0x55/0x110 [macvlan]
[ 55.844247] dev_set_rx_mode+0x21/0x30
[ 55.844733] __dev_open+0x202/0x310
[ 55.845186] ? dev_set_rx_mode+0x30/0x30
[ 55.845707] ? mark_held_locks+0xa5/0xe0
[ 55.846219] ? __local_bh_enable_ip+0xe9/0x1b0
[ 55.846805] __dev_change_flags+0x3c3/0x500
[ 55.847376] ? dev_set_allmulti+0x10/0x10
[ 55.847906] ? check_chain_key+0x236/0x5d0
[ 55.848881] dev_change_flags+0x7a/0x160
[ 55.850015] do_setlink+0xa49/0x2f40
[ ... ]
Fixes: c674ac30c549 ("macvlan: Fix lockdep warnings with stacked macvlan devices")
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
---
v2 -> v3 :
- This patch is not changed
v1 -> v2 :
- This patch is not changed
drivers/net/macvlan.c | 35 +++++++++++++++++++++++++++--------
include/linux/if_macvlan.h | 2 ++
2 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 940192c057b6..dae368a2e8d1 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -852,8 +852,6 @@ static int macvlan_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
* "super class" of normal network devices; split their locks off into a
* separate class since they always nest.
*/
-static struct lock_class_key macvlan_netdev_addr_lock_key;
-
#define ALWAYS_ON_OFFLOADS \
(NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE | \
NETIF_F_GSO_ROBUST | NETIF_F_GSO_ENCAP_ALL)
@@ -874,12 +872,30 @@ static int macvlan_get_nest_level(struct net_device *dev)
return ((struct macvlan_dev *)netdev_priv(dev))->nest_level;
}
-static void macvlan_set_lockdep_class(struct net_device *dev)
+static void macvlan_dev_set_lockdep_one(struct net_device *dev,
+ struct netdev_queue *txq,
+ void *_unused)
+{
+ struct macvlan_dev *macvlan = netdev_priv(dev);
+
+ lockdep_set_class(&txq->_xmit_lock, &macvlan->xmit_lock_key);
+}
+
+static struct lock_class_key qdisc_tx_busylock_key;
+static struct lock_class_key qdisc_running_key;
+
+static void macvlan_dev_set_lockdep_class(struct net_device *dev)
{
- netdev_lockdep_set_classes(dev);
- lockdep_set_class_and_subclass(&dev->addr_list_lock,
- &macvlan_netdev_addr_lock_key,
- macvlan_get_nest_level(dev));
+ struct macvlan_dev *macvlan = netdev_priv(dev);
+
+ dev->qdisc_tx_busylock = &qdisc_tx_busylock_key;
+ dev->qdisc_running_key = &qdisc_running_key;
+
+ lockdep_register_key(&macvlan->addr_lock_key);
+ lockdep_set_class(&dev->addr_list_lock, &macvlan->addr_lock_key);
+
+ lockdep_register_key(&macvlan->xmit_lock_key);
+ netdev_for_each_tx_queue(dev, macvlan_dev_set_lockdep_one, NULL);
}
static int macvlan_init(struct net_device *dev)
@@ -900,7 +916,7 @@ static int macvlan_init(struct net_device *dev)
dev->gso_max_segs = lowerdev->gso_max_segs;
dev->hard_header_len = lowerdev->hard_header_len;
- macvlan_set_lockdep_class(dev);
+ macvlan_dev_set_lockdep_class(dev);
vlan->pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats);
if (!vlan->pcpu_stats)
@@ -922,6 +938,9 @@ static void macvlan_uninit(struct net_device *dev)
port->count -= 1;
if (!port->count)
macvlan_port_destroy(port->dev);
+
+ lockdep_unregister_key(&vlan->addr_lock_key);
+ lockdep_unregister_key(&vlan->xmit_lock_key);
}
static void macvlan_dev_get_stats64(struct net_device *dev,
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index 2e55e4cdbd8a..ea5b41823287 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -31,6 +31,8 @@ struct macvlan_dev {
u16 flags;
int nest_level;
unsigned int macaddr_count;
+ struct lock_class_key xmit_lock_key;
+ struct lock_class_key addr_lock_key;
#ifdef CONFIG_NET_POLL_CONTROLLER
struct netpoll *netpoll;
#endif
--
2.17.1
^ permalink raw reply related
* [PATCH net v3 08/11] macsec: fix refcnt leak in module exit routine
From: Taehee Yoo @ 2019-09-16 13:47 UTC (permalink / raw)
To: davem, netdev, j.vosburgh, vfalico, andy, jiri, sd, roopa, saeedm,
manishc, rahulv, kys, haiyangz, stephen, sashal, hare, varun,
ubraun, kgraul, jay.vosburgh
Cc: ap420073
In-Reply-To: <20190916134802.8252-1-ap420073@gmail.com>
When a macsec interface is created, it increases a refcnt to a lower
device(real device). when macsec interface is deleted, the refcnt is
decreased in macsec_free_netdev(), which is ->priv_destructor() of
macsec interface.
The problem scenario is this.
When nested macsec interfaces are exiting, the exit routine of the
macsec module makes refcnt leaks.
Test commands:
ip link add dummy0 type dummy
ip link add macsec0 link dummy0 type macsec
ip link add macsec1 link macsec0 type macsec
modprobe -rv macsec
[ 208.629433] unregister_netdevice: waiting for macsec0 to become free. Usage count = 1
Steps of exit routine of macsec module are below.
1. Calls ->dellink() in __rtnl_link_unregister().
2. Checks refcnt and wait refcnt to be 0 if refcnt is not 0 in
netdev_run_todo().
3. Calls ->priv_destruvtor() in netdev_run_todo().
Step2 checks refcnt, but step3 decreases refcnt.
So, step2 waits forever.
This patch makes the macsec module do not hold a refcnt of the lower
device because it already holds a refcnt of the lower device with
netdev_upper_dev_link().
Fixes: c09440f7dcb3 ("macsec: introduce IEEE 802.1AE driver")
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
---
v2 -> v3 :
- This patch is not changed
v1 -> v2 :
- This patch is not changed
drivers/net/macsec.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index 25a4fc88145d..41ec1ed0d545 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -3031,12 +3031,10 @@ static const struct nla_policy macsec_rtnl_policy[IFLA_MACSEC_MAX + 1] = {
static void macsec_free_netdev(struct net_device *dev)
{
struct macsec_dev *macsec = macsec_priv(dev);
- struct net_device *real_dev = macsec->real_dev;
free_percpu(macsec->stats);
free_percpu(macsec->secy.tx_sc.stats);
- dev_put(real_dev);
}
static void macsec_setup(struct net_device *dev)
@@ -3291,8 +3289,6 @@ static int macsec_newlink(struct net *net, struct net_device *dev,
if (err < 0)
return err;
- dev_hold(real_dev);
-
macsec->nest_level = dev_get_nest_level(real_dev) + 1;
err = netdev_upper_dev_link(real_dev, dev, extack);
--
2.17.1
^ permalink raw reply related
* [PATCH net v3 09/11] net: core: add ignore flag to netdev_adjacent structure
From: Taehee Yoo @ 2019-09-16 13:48 UTC (permalink / raw)
To: davem, netdev, j.vosburgh, vfalico, andy, jiri, sd, roopa, saeedm,
manishc, rahulv, kys, haiyangz, stephen, sashal, hare, varun,
ubraun, kgraul, jay.vosburgh
Cc: ap420073
In-Reply-To: <20190916134802.8252-1-ap420073@gmail.com>
In order to link an adjacent node, netdev_upper_dev_link() is used
and in order to unlink an adjacent node, netdev_upper_dev_unlink() is used.
unlink operation does not fail, but link operation can fail.
In order to exchange adjacent nodes, we should unlink an old adjacent
node first. then, link a new adjacent node.
If link operation is failed, we should link an old adjacent node again.
But this link operation can fail too.
It eventually breaks the adjacent link relationship.
This patch adds an ignore flag into the netdev_adjacent structure.
If this flag is set, netdev_upper_dev_link() ignores an old adjacent
node for a moment.
So we can skip unlink operation before link operation.
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
---
v2 -> v3 :
- Modify nesting infra code to use iterator instead of recursive
v1 -> v2 :
- This patch is not changed
include/linux/netdevice.h | 4 +
net/core/dev.c | 180 ++++++++++++++++++++++++++++++++++----
2 files changed, 166 insertions(+), 18 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 5bb5756129af..4506810c301b 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4319,6 +4319,10 @@ int netdev_master_upper_dev_link(struct net_device *dev,
struct netlink_ext_ack *extack);
void netdev_upper_dev_unlink(struct net_device *dev,
struct net_device *upper_dev);
+void netdev_adjacent_dev_disable(struct net_device *upper_dev,
+ struct net_device *lower_dev);
+void netdev_adjacent_dev_enable(struct net_device *upper_dev,
+ struct net_device *lower_dev);
void netdev_adjacent_rename_links(struct net_device *dev, char *oldname);
void *netdev_lower_dev_get_private(struct net_device *dev,
struct net_device *lower_dev);
diff --git a/net/core/dev.c b/net/core/dev.c
index fa847ea957ee..12d76b983064 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6448,6 +6448,9 @@ struct netdev_adjacent {
/* upper master flag, there can only be one master device per list */
bool master;
+ /* lookup ignore flag */
+ bool ignore;
+
/* counter for the number of times this device was added to us */
u16 ref_nr;
@@ -6553,6 +6556,22 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
}
EXPORT_SYMBOL(netdev_master_upper_dev_get);
+struct net_device *netdev_master_upper_dev_get_ignore(struct net_device *dev)
+{
+ struct netdev_adjacent *upper;
+
+ ASSERT_RTNL();
+
+ if (list_empty(&dev->adj_list.upper))
+ return NULL;
+
+ upper = list_first_entry(&dev->adj_list.upper,
+ struct netdev_adjacent, list);
+ if (likely(upper->master) && !upper->ignore)
+ return upper->dev;
+ return NULL;
+}
+
/**
* netdev_has_any_lower_dev - Check if device is linked to some device
* @dev: device
@@ -6603,8 +6622,9 @@ struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
}
EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu);
-static struct net_device *netdev_next_upper_dev(struct net_device *dev,
- struct list_head **iter)
+static struct net_device *netdev_next_upper_dev_ignore(struct net_device *dev,
+ struct list_head **iter,
+ bool *ignore)
{
struct netdev_adjacent *upper;
@@ -6614,6 +6634,7 @@ static struct net_device *netdev_next_upper_dev(struct net_device *dev,
return NULL;
*iter = &upper->list;
+ *ignore = upper->ignore;
return upper->dev;
}
@@ -6635,14 +6656,15 @@ static struct net_device *netdev_next_upper_dev_rcu(struct net_device *dev,
return upper->dev;
}
-int netdev_walk_all_upper_dev(struct net_device *dev,
- int (*fn)(struct net_device *dev,
- void *data),
- void *data)
+int netdev_walk_all_upper_dev_ignore(struct net_device *dev,
+ int (*fn)(struct net_device *dev,
+ void *data),
+ void *data)
{
struct net_device *udev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
int ret, cur = 0;
+ bool ignore;
now = dev;
iter = &dev->adj_list.upper;
@@ -6656,9 +6678,12 @@ int netdev_walk_all_upper_dev(struct net_device *dev,
next = NULL;
while (1) {
- udev = netdev_next_upper_dev(now, &iter);
+ udev = netdev_next_upper_dev_ignore(now, &iter,
+ &ignore);
if (!udev)
break;
+ if (ignore)
+ continue;
if (!next) {
next = udev;
@@ -6735,6 +6760,15 @@ int netdev_walk_all_upper_dev_rcu(struct net_device *dev,
}
EXPORT_SYMBOL_GPL(netdev_walk_all_upper_dev_rcu);
+bool netdev_has_upper_dev_ignore(struct net_device *dev,
+ struct net_device *upper_dev)
+{
+ ASSERT_RTNL();
+
+ return netdev_walk_all_upper_dev_ignore(dev, __netdev_has_upper_dev,
+ upper_dev);
+}
+
/**
* netdev_lower_get_next_private - Get the next ->private from the
* lower neighbour list
@@ -6831,6 +6865,23 @@ static struct net_device *netdev_next_lower_dev(struct net_device *dev,
return lower->dev;
}
+static struct net_device *netdev_next_lower_dev_ignore(struct net_device *dev,
+ struct list_head **iter,
+ bool *ignore)
+{
+ struct netdev_adjacent *lower;
+
+ lower = list_entry((*iter)->next, struct netdev_adjacent, list);
+
+ if (&lower->list == &dev->adj_list.lower)
+ return NULL;
+
+ *iter = &lower->list;
+ *ignore = lower->ignore;
+
+ return lower->dev;
+}
+
int netdev_walk_all_lower_dev(struct net_device *dev,
int (*fn)(struct net_device *dev,
void *data),
@@ -6881,6 +6932,59 @@ int netdev_walk_all_lower_dev(struct net_device *dev,
}
EXPORT_SYMBOL_GPL(netdev_walk_all_lower_dev);
+int netdev_walk_all_lower_dev_ignore(struct net_device *dev,
+ int (*fn)(struct net_device *dev,
+ void *data),
+ void *data)
+{
+ struct net_device *ldev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
+ struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
+ int ret, cur = 0;
+ bool ignore;
+
+ now = dev;
+ iter = &dev->adj_list.lower;
+
+ while (1) {
+ if (now != dev) {
+ ret = fn(now, data);
+ if (ret)
+ return ret;
+ }
+
+ next = NULL;
+ while (1) {
+ ldev = netdev_next_lower_dev_ignore(now, &iter,
+ &ignore);
+ if (!ldev)
+ break;
+ if (ignore)
+ continue;
+
+ if (!next) {
+ next = ldev;
+ niter = &ldev->adj_list.lower;
+ } else {
+ dev_stack[cur] = ldev;
+ iter_stack[cur++] = &ldev->adj_list.lower;
+ break;
+ }
+ }
+
+ if (!next) {
+ if (!cur)
+ return 0;
+ next = dev_stack[--cur];
+ niter = iter_stack[cur];
+ }
+
+ now = next;
+ iter = niter;
+ }
+
+ return 0;
+}
+
static struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
struct list_head **iter)
{
@@ -6900,11 +7004,14 @@ static u8 __netdev_upper_depth(struct net_device *dev)
struct net_device *udev;
struct list_head *iter;
u8 max_depth = 0;
+ bool ignore;
for (iter = &dev->adj_list.upper,
- udev = netdev_next_upper_dev(dev, &iter);
+ udev = netdev_next_upper_dev_ignore(dev, &iter, &ignore);
udev;
- udev = netdev_next_upper_dev(dev, &iter)) {
+ udev = netdev_next_upper_dev_ignore(dev, &iter, &ignore)) {
+ if (ignore)
+ continue;
if (max_depth < udev->upper_level)
max_depth = udev->upper_level;
}
@@ -6917,11 +7024,14 @@ static u8 __netdev_lower_depth(struct net_device *dev)
struct net_device *ldev;
struct list_head *iter;
u8 max_depth = 0;
+ bool ignore;
for (iter = &dev->adj_list.lower,
- ldev = netdev_next_lower_dev(dev, &iter);
+ ldev = netdev_next_lower_dev_ignore(dev, &iter, &ignore);
ldev;
- ldev = netdev_next_lower_dev(dev, &iter)) {
+ ldev = netdev_next_lower_dev_ignore(dev, &iter, &ignore)) {
+ if (ignore)
+ continue;
if (max_depth < ldev->lower_level)
max_depth = ldev->lower_level;
}
@@ -7089,6 +7199,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
adj->master = master;
adj->ref_nr = 1;
adj->private = private;
+ adj->ignore = false;
dev_hold(adj_dev);
pr_debug("Insert adjacency: dev %s adj_dev %s adj->ref_nr %d; dev_hold on %s\n",
@@ -7239,17 +7350,17 @@ static int __netdev_upper_dev_link(struct net_device *dev,
return -EBUSY;
/* To prevent loops, check if dev is not upper device to upper_dev. */
- if (netdev_has_upper_dev(upper_dev, dev))
+ if (netdev_has_upper_dev_ignore(upper_dev, dev))
return -EBUSY;
if ((dev->lower_level + upper_dev->upper_level) > MAX_NEST_DEV)
return -EMLINK;
if (!master) {
- if (netdev_has_upper_dev(dev, upper_dev))
+ if (netdev_has_upper_dev_ignore(dev, upper_dev))
return -EEXIST;
} else {
- master_dev = netdev_master_upper_dev_get(dev);
+ master_dev = netdev_master_upper_dev_get_ignore(dev);
if (master_dev)
return master_dev == upper_dev ? -EEXIST : -EBUSY;
}
@@ -7272,10 +7383,12 @@ static int __netdev_upper_dev_link(struct net_device *dev,
goto rollback;
__netdev_update_upper_level(dev, NULL);
- netdev_walk_all_lower_dev(dev, __netdev_update_upper_level, NULL);
+ netdev_walk_all_lower_dev_ignore(dev,
+ __netdev_update_upper_level, NULL);
__netdev_update_lower_level(upper_dev, NULL);
- netdev_walk_all_upper_dev(upper_dev, __netdev_update_lower_level, NULL);
+ netdev_walk_all_upper_dev_ignore(upper_dev,
+ __netdev_update_lower_level, NULL);
return 0;
@@ -7361,13 +7474,44 @@ void netdev_upper_dev_unlink(struct net_device *dev,
&changeupper_info.info);
__netdev_update_upper_level(dev, NULL);
- netdev_walk_all_lower_dev(dev, __netdev_update_upper_level, NULL);
+ netdev_walk_all_lower_dev_ignore(dev,
+ __netdev_update_upper_level, NULL);
__netdev_update_lower_level(upper_dev, NULL);
- netdev_walk_all_upper_dev(upper_dev, __netdev_update_lower_level, NULL);
+ netdev_walk_all_upper_dev_ignore(upper_dev,
+ __netdev_update_lower_level, NULL);
}
EXPORT_SYMBOL(netdev_upper_dev_unlink);
+void __netdev_adjacent_dev_set(struct net_device *upper_dev,
+ struct net_device *lower_dev,
+ bool val)
+{
+ struct netdev_adjacent *adj;
+
+ adj = __netdev_find_adj(lower_dev, &upper_dev->adj_list.lower);
+ if (adj)
+ adj->ignore = val;
+
+ adj = __netdev_find_adj(upper_dev, &lower_dev->adj_list.upper);
+ if (adj)
+ adj->ignore = val;
+}
+
+void netdev_adjacent_dev_disable(struct net_device *upper_dev,
+ struct net_device *lower_dev)
+{
+ __netdev_adjacent_dev_set(upper_dev, lower_dev, true);
+}
+EXPORT_SYMBOL(netdev_adjacent_dev_disable);
+
+void netdev_adjacent_dev_enable(struct net_device *upper_dev,
+ struct net_device *lower_dev)
+{
+ __netdev_adjacent_dev_set(upper_dev, lower_dev, false);
+}
+EXPORT_SYMBOL(netdev_adjacent_dev_enable);
+
/**
* netdev_bonding_info_change - Dispatch event about slave change
* @dev: device
--
2.17.1
^ permalink raw reply related
* [PATCH net v3 10/11] vxlan: add adjacent link to limit depth level
From: Taehee Yoo @ 2019-09-16 13:48 UTC (permalink / raw)
To: davem, netdev, j.vosburgh, vfalico, andy, jiri, sd, roopa, saeedm,
manishc, rahulv, kys, haiyangz, stephen, sashal, hare, varun,
ubraun, kgraul, jay.vosburgh
Cc: ap420073
In-Reply-To: <20190916134802.8252-1-ap420073@gmail.com>
Current vxlan code doesn't limit the number of nested devices.
Nested devices would be handled recursively and this routine needs
huge stack memory. So, unlimited nested devices could make
stack overflow.
In order to fix this issue, this patch adds adjacent links.
The adjacent link APIs internally check the depth level.
Test commands:
ip link add dummy0 type dummy
ip link add vxlan0 type vxlan id 0 group 239.1.1.1 dev dummy0 \
dstport 4789
for i in {1..100}
do
let A=$i-1
ip link add vxlan$i type vxlan id $i group 239.1.1.1 \
dev vxlan$A dstport 4789
done
ip link del dummy0
The top upper link is vxlan100 and the lowest link is vxlan0.
When vxlan0 is deleting, the upper devices will be deleted recursively.
It needs huge stack memory so it makes stack overflow.
Splat looks like:
[ 229.628477] =============================================================================
[ 229.629785] BUG page->ptl (Not tainted): Padding overwritten. 0x0000000026abf214-0x0000000091f6abb2
[ 229.629785] -----------------------------------------------------------------------------
[ 229.629785]
[ 229.655439] ==================================================================
[ 229.629785] INFO: Slab 0x00000000ff7cfda8 objects=19 used=19 fp=0x00000000fe33776c flags=0x200000000010200
[ 229.655688] BUG: KASAN: stack-out-of-bounds in unmap_single_vma+0x25a/0x2e0
[ 229.655688] Read of size 8 at addr ffff888113076928 by task vlan-network-in/2334
[ 229.655688]
[ 229.629785] Padding 0000000026abf214: 00 80 14 0d 81 88 ff ff 68 91 81 14 81 88 ff ff ........h.......
[ 229.629785] Padding 0000000001e24790: 38 91 81 14 81 88 ff ff 68 91 81 14 81 88 ff ff 8.......h.......
[ 229.629785] Padding 00000000b39397c8: 33 30 62 a7 ff ff ff ff ff eb 60 22 10 f1 ff 1f 30b.......`"....
[ 229.629785] Padding 00000000bc98f53a: 80 60 07 13 81 88 ff ff 00 80 14 0d 81 88 ff ff .`..............
[ 229.629785] Padding 000000002aa8123d: 68 91 81 14 81 88 ff ff f7 21 17 a7 ff ff ff ff h........!......
[ 229.629785] Padding 000000001c8c2369: 08 81 14 0d 81 88 ff ff 03 02 00 00 00 00 00 00 ................
[ 229.629785] Padding 000000004e290c5d: 21 90 a2 21 10 ed ff ff 00 00 00 00 00 fc ff df !..!............
[ 229.629785] Padding 000000000e25d731: 18 60 07 13 81 88 ff ff c0 8b 13 05 81 88 ff ff .`..............
[ 229.629785] Padding 000000007adc7ab3: b3 8a b5 41 00 00 00 00 ...A....
[ 229.629785] FIX page->ptl: Restoring 0x0000000026abf214-0x0000000091f6abb2=0x5a
[ ... ]
Fixes: acaf4e70997f ("net: vxlan: when lower dev unregisters remove vxlan dev as well")
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
---
v2 -> v3 :
- This patch is not changed
v1 -> v2 :
- This patch is not changed
drivers/net/vxlan.c | 71 ++++++++++++++++++++++++++++++++++++++-------
include/net/vxlan.h | 1 +
2 files changed, 62 insertions(+), 10 deletions(-)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 3d9bcc957f7d..0d5c8d22d8a4 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -3567,6 +3567,8 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
struct vxlan_net *vn = net_generic(net, vxlan_net_id);
struct vxlan_dev *vxlan = netdev_priv(dev);
struct vxlan_fdb *f = NULL;
+ struct net_device *remote_dev = NULL;
+ struct vxlan_rdst *dst = &vxlan->default_dst;
bool unregister = false;
int err;
@@ -3577,14 +3579,14 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
dev->ethtool_ops = &vxlan_ethtool_ops;
/* create an fdb entry for a valid default destination */
- if (!vxlan_addr_any(&vxlan->default_dst.remote_ip)) {
+ if (!vxlan_addr_any(&dst->remote_ip)) {
err = vxlan_fdb_create(vxlan, all_zeros_mac,
- &vxlan->default_dst.remote_ip,
+ &dst->remote_ip,
NUD_REACHABLE | NUD_PERMANENT,
vxlan->cfg.dst_port,
- vxlan->default_dst.remote_vni,
- vxlan->default_dst.remote_vni,
- vxlan->default_dst.remote_ifindex,
+ dst->remote_vni,
+ dst->remote_vni,
+ dst->remote_ifindex,
NTF_SELF, &f);
if (err)
return err;
@@ -3595,26 +3597,43 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
goto errout;
unregister = true;
+ if (dst->remote_ifindex) {
+ remote_dev = __dev_get_by_index(net, dst->remote_ifindex);
+ if (!remote_dev)
+ goto errout;
+
+ err = netdev_upper_dev_link(remote_dev, dev, extack);
+ if (err)
+ goto errout;
+ }
+
err = rtnl_configure_link(dev, NULL);
if (err)
- goto errout;
+ goto unlink;
if (f) {
- vxlan_fdb_insert(vxlan, all_zeros_mac,
- vxlan->default_dst.remote_vni, f);
+ vxlan_fdb_insert(vxlan, all_zeros_mac, dst->remote_vni, f);
/* notify default fdb entry */
err = vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f),
RTM_NEWNEIGH, true, extack);
if (err) {
vxlan_fdb_destroy(vxlan, f, false, false);
+ if (remote_dev)
+ netdev_upper_dev_unlink(remote_dev, dev);
goto unregister;
}
}
list_add(&vxlan->next, &vn->vxlan_list);
+ if (remote_dev) {
+ dst->remote_dev = remote_dev;
+ dev_hold(remote_dev);
+ }
return 0;
-
+unlink:
+ if (remote_dev)
+ netdev_upper_dev_unlink(remote_dev, dev);
errout:
/* unregister_netdevice() destroys the default FDB entry with deletion
* notification. But the addition notification was not sent yet, so
@@ -3936,6 +3955,8 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
struct net_device *lowerdev;
struct vxlan_config conf;
int err;
+ bool linked = false;
+ bool disabled = false;
err = vxlan_nl2conf(tb, data, dev, &conf, true, extack);
if (err)
@@ -3946,6 +3967,16 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
if (err)
return err;
+ if (lowerdev) {
+ if (dst->remote_dev && lowerdev != dst->remote_dev) {
+ netdev_adjacent_dev_disable(dst->remote_dev, dev);
+ disabled = true;
+ }
+ err = netdev_upper_dev_link(lowerdev, dev, extack);
+ if (err)
+ goto err;
+ linked = true;
+ }
/* handle default dst entry */
if (!vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip)) {
u32 hash_index = fdb_head_index(vxlan, all_zeros_mac, conf.vni);
@@ -3962,7 +3993,7 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
NTF_SELF, true, extack);
if (err) {
spin_unlock_bh(&vxlan->hash_lock[hash_index]);
- return err;
+ goto err;
}
}
if (!vxlan_addr_any(&dst->remote_ip))
@@ -3979,8 +4010,24 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
if (conf.age_interval != vxlan->cfg.age_interval)
mod_timer(&vxlan->age_timer, jiffies);
+ if (disabled) {
+ netdev_adjacent_dev_enable(dst->remote_dev, dev);
+ netdev_upper_dev_unlink(dst->remote_dev, dev);
+ dev_put(dst->remote_dev);
+ }
+ if (linked) {
+ dst->remote_dev = lowerdev;
+ dev_hold(dst->remote_dev);
+ }
+
vxlan_config_apply(dev, &conf, lowerdev, vxlan->net, true);
return 0;
+err:
+ if (linked)
+ netdev_upper_dev_unlink(lowerdev, dev);
+ if (disabled)
+ netdev_adjacent_dev_enable(dst->remote_dev, dev);
+ return err;
}
static void vxlan_dellink(struct net_device *dev, struct list_head *head)
@@ -3991,6 +4038,10 @@ static void vxlan_dellink(struct net_device *dev, struct list_head *head)
list_del(&vxlan->next);
unregister_netdevice_queue(dev, head);
+ if (vxlan->default_dst.remote_dev) {
+ netdev_upper_dev_unlink(vxlan->default_dst.remote_dev, dev);
+ dev_put(vxlan->default_dst.remote_dev);
+ }
}
static size_t vxlan_get_size(const struct net_device *dev)
diff --git a/include/net/vxlan.h b/include/net/vxlan.h
index dc1583a1fb8a..08e237d7aa73 100644
--- a/include/net/vxlan.h
+++ b/include/net/vxlan.h
@@ -197,6 +197,7 @@ struct vxlan_rdst {
u8 offloaded:1;
__be32 remote_vni;
u32 remote_ifindex;
+ struct net_device *remote_dev;
struct list_head list;
struct rcu_head rcu;
struct dst_cache dst_cache;
--
2.17.1
^ permalink raw reply related
* [PATCH net v3 11/11] net: remove unnecessary variables and callback
From: Taehee Yoo @ 2019-09-16 13:48 UTC (permalink / raw)
To: davem, netdev, j.vosburgh, vfalico, andy, jiri, sd, roopa, saeedm,
manishc, rahulv, kys, haiyangz, stephen, sashal, hare, varun,
ubraun, kgraul, jay.vosburgh
Cc: ap420073
In-Reply-To: <20190916134802.8252-1-ap420073@gmail.com>
This patch removes variables and callback these are related to the nested
device structure.
devices that can be nested have their own nest_level variable that
represents the depth of nested devices.
In the previous patch, new {lower/upper}_level variables are added and
they replace old private nest_level variable.
So, this patch removes all 'nest_level' variables.
In order to avoid lockdep warning, ->ndo_get_lock_subclass() was added
to get lockdep subclass value, which is actually lower nested depth value.
But now, they use the dynamic lockdep key to avoid lockdep warning instead
of the subclass.
So, this patch removes ->ndo_get_lock_subclass() callback.
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
---
v2 -> v3 :
- This patch is not changed
v1 -> v2 :
- This patch is not changed
drivers/net/bonding/bond_alb.c | 2 +-
drivers/net/bonding/bond_main.c | 14 -------------
.../net/ethernet/mellanox/mlx5/core/en_tc.c | 2 +-
drivers/net/macsec.c | 9 ---------
drivers/net/macvlan.c | 7 -------
include/linux/if_macvlan.h | 1 -
include/linux/if_vlan.h | 12 -----------
include/linux/netdevice.h | 12 -----------
include/net/bonding.h | 1 -
net/8021q/vlan.c | 1 -
net/8021q/vlan_dev.c | 6 ------
net/core/dev.c | 20 -------------------
net/core/dev_addr_lists.c | 12 +++++------
net/smc/smc_core.c | 2 +-
net/smc/smc_pnet.c | 2 +-
15 files changed, 10 insertions(+), 93 deletions(-)
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 8c79bad2a9a5..4f2e6910c623 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -952,7 +952,7 @@ static int alb_upper_dev_walk(struct net_device *upper, void *_data)
struct bond_vlan_tag *tags;
if (is_vlan_dev(upper) &&
- bond->nest_level == vlan_get_encap_level(upper) - 1) {
+ bond->dev->lower_level == upper->lower_level - 1) {
if (upper->addr_assign_type == NET_ADDR_STOLEN) {
alb_send_lp_vid(slave, mac_addr,
vlan_dev_vlan_proto(upper),
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 7f574e74ed78..69eb61466fbe 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1733,8 +1733,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
goto err_upper_unlink;
}
- bond->nest_level = dev_get_nest_level(bond_dev) + 1;
-
/* If the mode uses primary, then the following is handled by
* bond_change_active_slave().
*/
@@ -1983,9 +1981,6 @@ static int __bond_release_one(struct net_device *bond_dev,
if (!bond_has_slaves(bond)) {
bond_set_carrier(bond);
eth_hw_addr_random(bond_dev);
- bond->nest_level = SINGLE_DEPTH_NESTING;
- } else {
- bond->nest_level = dev_get_nest_level(bond_dev) + 1;
}
unblock_netpoll_tx();
@@ -3472,13 +3467,6 @@ static void bond_fold_stats(struct rtnl_link_stats64 *_res,
}
}
-static int bond_get_nest_level(struct net_device *bond_dev)
-{
- struct bonding *bond = netdev_priv(bond_dev);
-
- return bond->nest_level;
-}
-
static void bond_get_stats(struct net_device *bond_dev,
struct rtnl_link_stats64 *stats)
{
@@ -4298,7 +4286,6 @@ static const struct net_device_ops bond_netdev_ops = {
.ndo_neigh_setup = bond_neigh_setup,
.ndo_vlan_rx_add_vid = bond_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = bond_vlan_rx_kill_vid,
- .ndo_get_lock_subclass = bond_get_nest_level,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_netpoll_setup = bond_netpoll_setup,
.ndo_netpoll_cleanup = bond_netpoll_cleanup,
@@ -4822,7 +4809,6 @@ static int bond_init(struct net_device *bond_dev)
if (!bond->wq)
return -ENOMEM;
- bond->nest_level = SINGLE_DEPTH_NESTING;
bond_dev_set_lockdep_class(bond_dev);
list_add_tail(&bond->bond_list, &bn->dev_list);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index 00b2d4a86159..e056f9aad8df 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -2797,7 +2797,7 @@ static int add_vlan_pop_action(struct mlx5e_priv *priv,
struct mlx5_esw_flow_attr *attr,
u32 *action)
{
- int nest_level = vlan_get_encap_level(attr->parse_attr->filter_dev);
+ int nest_level = attr->parse_attr->filter_dev->lower_level;
struct flow_action_entry vlan_act = {
.id = FLOW_ACTION_VLAN_POP,
};
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index 41ec1ed0d545..c0cb595f2bba 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -269,7 +269,6 @@ struct macsec_dev {
struct gro_cells gro_cells;
struct lock_class_key xmit_lock_key;
struct lock_class_key addr_lock_key;
- unsigned int nest_level;
};
/**
@@ -2988,11 +2987,6 @@ static int macsec_get_iflink(const struct net_device *dev)
return macsec_priv(dev)->real_dev->ifindex;
}
-static int macsec_get_nest_level(struct net_device *dev)
-{
- return macsec_priv(dev)->nest_level;
-}
-
static const struct net_device_ops macsec_netdev_ops = {
.ndo_init = macsec_dev_init,
.ndo_uninit = macsec_dev_uninit,
@@ -3006,7 +3000,6 @@ static const struct net_device_ops macsec_netdev_ops = {
.ndo_start_xmit = macsec_start_xmit,
.ndo_get_stats64 = macsec_get_stats64,
.ndo_get_iflink = macsec_get_iflink,
- .ndo_get_lock_subclass = macsec_get_nest_level,
};
static const struct device_type macsec_type = {
@@ -3289,8 +3282,6 @@ static int macsec_newlink(struct net *net, struct net_device *dev,
if (err < 0)
return err;
- macsec->nest_level = dev_get_nest_level(real_dev) + 1;
-
err = netdev_upper_dev_link(real_dev, dev, extack);
if (err < 0)
goto unregister;
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index dae368a2e8d1..2c14bc606514 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -867,11 +867,6 @@ static int macvlan_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
#define MACVLAN_STATE_MASK \
((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT))
-static int macvlan_get_nest_level(struct net_device *dev)
-{
- return ((struct macvlan_dev *)netdev_priv(dev))->nest_level;
-}
-
static void macvlan_dev_set_lockdep_one(struct net_device *dev,
struct netdev_queue *txq,
void *_unused)
@@ -1180,7 +1175,6 @@ static const struct net_device_ops macvlan_netdev_ops = {
.ndo_fdb_add = macvlan_fdb_add,
.ndo_fdb_del = macvlan_fdb_del,
.ndo_fdb_dump = ndo_dflt_fdb_dump,
- .ndo_get_lock_subclass = macvlan_get_nest_level,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = macvlan_dev_poll_controller,
.ndo_netpoll_setup = macvlan_dev_netpoll_setup,
@@ -1464,7 +1458,6 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
vlan->dev = dev;
vlan->port = port;
vlan->set_features = MACVLAN_FEATURES;
- vlan->nest_level = dev_get_nest_level(lowerdev) + 1;
vlan->mode = MACVLAN_MODE_VEPA;
if (data && data[IFLA_MACVLAN_MODE])
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index ea5b41823287..e9202edcf101 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -29,7 +29,6 @@ struct macvlan_dev {
netdev_features_t set_features;
enum macvlan_mode mode;
u16 flags;
- int nest_level;
unsigned int macaddr_count;
struct lock_class_key xmit_lock_key;
struct lock_class_key addr_lock_key;
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 1aed9f613e90..6f30284a58e5 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -182,8 +182,6 @@ struct vlan_dev_priv {
#ifdef CONFIG_NET_POLL_CONTROLLER
struct netpoll *netpoll;
#endif
- unsigned int nest_level;
-
struct lock_class_key xmit_lock_key;
struct lock_class_key addr_lock_key;
};
@@ -224,11 +222,6 @@ extern void vlan_vids_del_by_dev(struct net_device *dev,
extern bool vlan_uses_dev(const struct net_device *dev);
-static inline int vlan_get_encap_level(struct net_device *dev)
-{
- BUG_ON(!is_vlan_dev(dev));
- return vlan_dev_priv(dev)->nest_level;
-}
#else
static inline struct net_device *
__vlan_find_dev_deep_rcu(struct net_device *real_dev,
@@ -298,11 +291,6 @@ static inline bool vlan_uses_dev(const struct net_device *dev)
{
return false;
}
-static inline int vlan_get_encap_level(struct net_device *dev)
-{
- BUG();
- return 0;
-}
#endif
/**
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 4506810c301b..31283b86a1e2 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1408,7 +1408,6 @@ struct net_device_ops {
void (*ndo_dfwd_del_station)(struct net_device *pdev,
void *priv);
- int (*ndo_get_lock_subclass)(struct net_device *dev);
int (*ndo_set_tx_maxrate)(struct net_device *dev,
int queue_index,
u32 maxrate);
@@ -4047,16 +4046,6 @@ static inline void netif_addr_lock(struct net_device *dev)
spin_lock(&dev->addr_list_lock);
}
-static inline void netif_addr_lock_nested(struct net_device *dev)
-{
- int subclass = SINGLE_DEPTH_NESTING;
-
- if (dev->netdev_ops->ndo_get_lock_subclass)
- subclass = dev->netdev_ops->ndo_get_lock_subclass(dev);
-
- spin_lock_nested(&dev->addr_list_lock, subclass);
-}
-
static inline void netif_addr_lock_bh(struct net_device *dev)
{
spin_lock_bh(&dev->addr_list_lock);
@@ -4334,7 +4323,6 @@ void netdev_lower_state_changed(struct net_device *lower_dev,
extern u8 netdev_rss_key[NETDEV_RSS_KEY_LEN] __read_mostly;
void netdev_rss_key_fill(void *buffer, size_t len);
-int dev_get_nest_level(struct net_device *dev);
int skb_checksum_help(struct sk_buff *skb);
int skb_crc32c_csum_help(struct sk_buff *skb);
int skb_csum_hwoffload_help(struct sk_buff *skb,
diff --git a/include/net/bonding.h b/include/net/bonding.h
index c39ac7061e41..74f41dd73866 100644
--- a/include/net/bonding.h
+++ b/include/net/bonding.h
@@ -203,7 +203,6 @@ struct bonding {
struct slave __rcu *primary_slave;
struct bond_up_slave __rcu *slave_arr; /* Array of usable slaves */
bool force_primary;
- u32 nest_level;
s32 slave_cnt; /* never change this value outside the attach/detach wrappers */
int (*recv_probe)(const struct sk_buff *, struct bonding *,
struct slave *);
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 54728d2eda18..d4bcfd8f95bf 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -172,7 +172,6 @@ int register_vlan_dev(struct net_device *dev, struct netlink_ext_ack *extack)
if (err < 0)
goto out_uninit_mvrp;
- vlan->nest_level = dev_get_nest_level(real_dev) + 1;
err = register_netdevice(dev);
if (err < 0)
goto out_uninit_mvrp;
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 12bc80650087..e8707827540c 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -514,11 +514,6 @@ static void vlan_dev_set_lockdep_class(struct net_device *dev)
netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, NULL);
}
-static int vlan_dev_get_lock_subclass(struct net_device *dev)
-{
- return vlan_dev_priv(dev)->nest_level;
-}
-
static const struct header_ops vlan_header_ops = {
.create = vlan_dev_hard_header,
.parse = eth_header_parse,
@@ -814,7 +809,6 @@ static const struct net_device_ops vlan_netdev_ops = {
.ndo_netpoll_cleanup = vlan_dev_netpoll_cleanup,
#endif
.ndo_fix_features = vlan_dev_fix_features,
- .ndo_get_lock_subclass = vlan_dev_get_lock_subclass,
.ndo_get_iflink = vlan_dev_get_iflink,
};
diff --git a/net/core/dev.c b/net/core/dev.c
index 12d76b983064..5b14a70bea49 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -7624,26 +7624,6 @@ void *netdev_lower_dev_get_private(struct net_device *dev,
}
EXPORT_SYMBOL(netdev_lower_dev_get_private);
-
-int dev_get_nest_level(struct net_device *dev)
-{
- struct net_device *lower = NULL;
- struct list_head *iter;
- int max_nest = -1;
- int nest;
-
- ASSERT_RTNL();
-
- netdev_for_each_lower_dev(dev, lower, iter) {
- nest = dev_get_nest_level(lower);
- if (max_nest < nest)
- max_nest = nest;
- }
-
- return max_nest + 1;
-}
-EXPORT_SYMBOL(dev_get_nest_level);
-
/**
* netdev_lower_change - Dispatch event about lower device state change
* @lower_dev: device
diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c
index 6393ba930097..2f949b5a1eb9 100644
--- a/net/core/dev_addr_lists.c
+++ b/net/core/dev_addr_lists.c
@@ -637,7 +637,7 @@ int dev_uc_sync(struct net_device *to, struct net_device *from)
if (to->addr_len != from->addr_len)
return -EINVAL;
- netif_addr_lock_nested(to);
+ netif_addr_lock(to);
err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len);
if (!err)
__dev_set_rx_mode(to);
@@ -667,7 +667,7 @@ int dev_uc_sync_multiple(struct net_device *to, struct net_device *from)
if (to->addr_len != from->addr_len)
return -EINVAL;
- netif_addr_lock_nested(to);
+ netif_addr_lock(to);
err = __hw_addr_sync_multiple(&to->uc, &from->uc, to->addr_len);
if (!err)
__dev_set_rx_mode(to);
@@ -691,7 +691,7 @@ void dev_uc_unsync(struct net_device *to, struct net_device *from)
return;
netif_addr_lock_bh(from);
- netif_addr_lock_nested(to);
+ netif_addr_lock(to);
__hw_addr_unsync(&to->uc, &from->uc, to->addr_len);
__dev_set_rx_mode(to);
netif_addr_unlock(to);
@@ -858,7 +858,7 @@ int dev_mc_sync(struct net_device *to, struct net_device *from)
if (to->addr_len != from->addr_len)
return -EINVAL;
- netif_addr_lock_nested(to);
+ netif_addr_lock(to);
err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len);
if (!err)
__dev_set_rx_mode(to);
@@ -888,7 +888,7 @@ int dev_mc_sync_multiple(struct net_device *to, struct net_device *from)
if (to->addr_len != from->addr_len)
return -EINVAL;
- netif_addr_lock_nested(to);
+ netif_addr_lock(to);
err = __hw_addr_sync_multiple(&to->mc, &from->mc, to->addr_len);
if (!err)
__dev_set_rx_mode(to);
@@ -912,7 +912,7 @@ void dev_mc_unsync(struct net_device *to, struct net_device *from)
return;
netif_addr_lock_bh(from);
- netif_addr_lock_nested(to);
+ netif_addr_lock(to);
__hw_addr_unsync(&to->mc, &from->mc, to->addr_len);
__dev_set_rx_mode(to);
netif_addr_unlock(to);
diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c
index 4ca50ddf8d16..a2e91b8d04b3 100644
--- a/net/smc/smc_core.c
+++ b/net/smc/smc_core.c
@@ -558,7 +558,7 @@ int smc_vlan_by_tcpsk(struct socket *clcsock, struct smc_init_info *ini)
}
rtnl_lock();
- nest_lvl = dev_get_nest_level(ndev);
+ nest_lvl = ndev->lower_level;
for (i = 0; i < nest_lvl; i++) {
struct list_head *lower = &ndev->adj_list.lower;
diff --git a/net/smc/smc_pnet.c b/net/smc/smc_pnet.c
index bab2da8cf17a..2920b006f65c 100644
--- a/net/smc/smc_pnet.c
+++ b/net/smc/smc_pnet.c
@@ -718,7 +718,7 @@ static struct net_device *pnet_find_base_ndev(struct net_device *ndev)
int i, nest_lvl;
rtnl_lock();
- nest_lvl = dev_get_nest_level(ndev);
+ nest_lvl = ndev->lower_level;
for (i = 0; i < nest_lvl; i++) {
struct list_head *lower = &ndev->adj_list.lower;
--
2.17.1
^ permalink raw reply related
* [PATCH net v2] net/sched: cls_api: Fix nooffloaddevcnt counter when indr block call success
From: wenxu @ 2019-09-16 13:53 UTC (permalink / raw)
To: jiri; +Cc: davem, netdev
From: wenxu <wenxu@ucloud.cn>
A vxlan or gretap device offload through indr block methord. If the device
successfully bind with a real hw through indr block call, It also add
nooffloadcnt counter. This counter will lead the rule add failed in
fl_hw_replace_filter-->tc_setup_cb_call with skip_sw flags.
In the tc_setup_cb_call will check the nooffloaddevcnt and skip_sw flags
as following:
if (block->nooffloaddevcnt && err_stop)
return -EOPNOTSUPP;
So with this patch, if the indr block call success, it will not modify
the nooffloaddevcnt counter.
Fixes: 7f76fa36754b ("net: sched: register callbacks for indirect tc block binds")
Signed-off-by: wenxu <wenxu@ucloud.cn>
---
net/sched/cls_api.c | 27 +++++++++++++++------------
1 file changed, 15 insertions(+), 12 deletions(-)
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index efd3cfb..8a1e3a5 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -766,10 +766,10 @@ void tc_indr_block_cb_unregister(struct net_device *dev,
}
EXPORT_SYMBOL_GPL(tc_indr_block_cb_unregister);
-static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
- struct tcf_block_ext_info *ei,
- enum flow_block_command command,
- struct netlink_ext_ack *extack)
+static int tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
+ struct tcf_block_ext_info *ei,
+ enum flow_block_command command,
+ struct netlink_ext_ack *extack)
{
struct tc_indr_block_cb *indr_block_cb;
struct tc_indr_block_dev *indr_dev;
@@ -785,7 +785,7 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
indr_dev = tc_indr_block_dev_lookup(dev);
if (!indr_dev)
- return;
+ return -ENOENT;
indr_dev->block = command == FLOW_BLOCK_BIND ? block : NULL;
@@ -793,7 +793,10 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
indr_block_cb->cb(dev, indr_block_cb->cb_priv, TC_SETUP_BLOCK,
&bo);
- tcf_block_setup(block, &bo);
+ if (list_empty(&bo.cb_list))
+ return -EOPNOTSUPP;
+
+ return tcf_block_setup(block, &bo);
}
static bool tcf_block_offload_in_use(struct tcf_block *block)
@@ -849,14 +852,14 @@ static int tcf_block_offload_bind(struct tcf_block *block, struct Qdisc *q,
if (err)
return err;
- tc_indr_block_call(block, dev, ei, FLOW_BLOCK_BIND, extack);
return 0;
no_offload_dev_inc:
if (tcf_block_offload_in_use(block))
return -EOPNOTSUPP;
- block->nooffloaddevcnt++;
- tc_indr_block_call(block, dev, ei, FLOW_BLOCK_BIND, extack);
+ err = tc_indr_block_call(block, dev, ei, FLOW_BLOCK_BIND, extack);
+ if (err)
+ block->nooffloaddevcnt++;
return 0;
}
@@ -866,8 +869,6 @@ static void tcf_block_offload_unbind(struct tcf_block *block, struct Qdisc *q,
struct net_device *dev = q->dev_queue->dev;
int err;
- tc_indr_block_call(block, dev, ei, FLOW_BLOCK_UNBIND, NULL);
-
if (!dev->netdev_ops->ndo_setup_tc)
goto no_offload_dev_dec;
err = tcf_block_offload_cmd(block, dev, ei, FLOW_BLOCK_UNBIND, NULL);
@@ -876,7 +877,9 @@ static void tcf_block_offload_unbind(struct tcf_block *block, struct Qdisc *q,
return;
no_offload_dev_dec:
- WARN_ON(block->nooffloaddevcnt-- == 0);
+ err = tc_indr_block_call(block, dev, ei, FLOW_BLOCK_UNBIND, NULL);
+ if (err)
+ WARN_ON(block->nooffloaddevcnt-- == 0);
}
static int
--
1.8.3.1
^ permalink raw reply related
* Re: net: phy: micrel KSZ9031 ifdown ifup issue
From: Paul Thomas @ 2019-09-16 13:54 UTC (permalink / raw)
To: Andrew Lunn; +Cc: Florian Fainelli, Heiner Kallweit, David S. Miller, netdev
In-Reply-To: <20190914145443.GE27922@lunn.ch>
Hi Andrew,
I did some more investigation, and what seems to be happening is the
device get's stuck in auto-negotiation. I looked at this using
phytool:
https://github.com/wkz/phytool
When it is in the good state I see that reg 0x01 is 0x796d where bit
1.2 reports 'Link is up' and bit 1.5 reports 'Auto-negotiation process
complete'. However, once I get to the bad state (it may take several
tries of ifdown, ifup to get there) then reg 0x01 is 0x7649 reporting
'Link is down' and 'Auto-negotiation process not completed'. This can
be fixed by resetting the phy './phytool write eth0/3/0 0x9140'
So, I guess that means the driver is doing what it is supposed to?
Could we add quirk or something to reset the phy again from the driver
if auto-negotiation doesn't complete with x seconds?
> Are you using interrupts, or polling? If interrupts, try polling?
> Seems unlikely, but you could be missing an interrupt.
It must be polling, the interrupt from the PHY is run in the
schematic, but it is not used in the hw or device-tree configuration.
>
> There is a fix from Antoine Tenart which suggests asym pause can be an
> issue? What pause setup are you using? But this is a known issue,
> which 5.2 should have the fix for.
Yes, this kernel includes this asym pause workaround. Reg 4.11:10 is 0
# ./phytool read eth0/3/4
0x01e1
This is the last little Ethernet issue that we are having, it would be
nice if we could find a solution.
thanks,
Paul
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox