Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH v2 05/17] asm-generic: Remove empty asm/unistd.h
From: Christoph Hellwig @ 2018-07-17 12:51 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: tglx, y2038, hch, linux-api, linux-arch, libc-alpha,
	albert.aribaud, netdev, viro, peterz, dvhart, ebiederm, linux
In-Reply-To: <20180716161103.16239-6-arnd@arndb.de>

On Mon, Jul 16, 2018 at 06:10:51PM +0200, Arnd Bergmann wrote:
> Nothing is left in asm/unistd.h except for the redirect to
> uapi/asm/unistd.h, so removing the file simply leads to that one being
> used directly.  The linux/export.h inclusion is a leftover from commit
> e1b5bb6d1236 ("consolidate cond_syscall and SYSCALL_ALIAS declarations")
> and should not be used anyway.

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply

* Re: [PATCH v2 04/17] asm-generic: Remove unneeded __ARCH_WANT_SYS_LLSEEK macro
From: Christoph Hellwig @ 2018-07-17 12:51 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: tglx, y2038, hch, linux-api, linux-arch, libc-alpha,
	albert.aribaud, netdev, viro, peterz, dvhart, ebiederm, linux
In-Reply-To: <20180716161103.16239-5-arnd@arndb.de>

On Mon, Jul 16, 2018 at 06:10:50PM +0200, Arnd Bergmann wrote:
> The sys_llseek sytem call is needed on all 32-bit architectures and
> none of the 64-bit ones, so we can remove the __ARCH_WANT_SYS_LLSEEK guard
> and simplify the include/asm-generic/unistd.h header further.
> 
> Since 32-bit tasks can run either natively or in compat mode on 64-bit
> architectures, we have to check for both !CONFIG_64BIT and CONFIG_COMPAT.
> 
> There are a few 64-bit architectures that also reference sys_llseek
> in their 64-bit ABI (e.g. sparc), but I verified that those all
> select CONFIG_COMPAT, so the #if check is still correct here. It's
> a bit odd to include it in the syscall table though, as it's the
> same as sys_lseek() on 64-bit, but with strange calling conventions.

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply

* Re: [PATCH v2 02/17] y2038: Remove newstat family from default syscall set
From: Christoph Hellwig @ 2018-07-17 12:50 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: tglx, y2038, hch, linux-api, linux-arch, libc-alpha,
	albert.aribaud, netdev, viro, peterz, dvhart, ebiederm, linux
In-Reply-To: <20180716161103.16239-3-arnd@arndb.de>

On Mon, Jul 16, 2018 at 06:10:48PM +0200, Arnd Bergmann wrote:
> We have four generations of stat() syscalls:
> - the oldstat syscalls that are only used on the older architectures
> - the newstat family that is used on all 64-bit architectures but
>   lacked support for large files on 32-bit architectures.
> - the stat64 family that is used mostly on 32-bit architectures to
>   replace newstat
> - statx() to replace all of the above, adding 64-bit timestamps among
>   other things.
> 
> We already compile stat64 only on those architectures that need it,
> but newstat is always built, including on those that don't reference
> it. This adds a new __ARCH_WANT_NEW_STAT symbol along the lines of
> __ARCH_WANT_OLD_STAT and __ARCH_WANT_STAT64 to control compilation of
> newstat. All architectures that need it use an explict define, the
> others now get a little bit smaller, and future architecture (including
> 64-bit targets) won't ever see it.
> 
> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Do I read this right that you only want to provide statx by default?
It is a little different from the traditional stat calls, so I'd like
to know this is actually ok from libc folks first.

^ permalink raw reply

* [PATCH iproute2 v2] ip: add support for seg6local End.BPF action
From: Mathieu Xhonneux @ 2018-07-17 14:49 UTC (permalink / raw)
  To: netdev; +Cc: stephen, dlebrun

This patch adds support for the End.BPF action of the seg6local
lightweight tunnel. Functions from the BPF lightweight tunnel are
re-used in this patch. Example:

$ ip -6 route add fc00::18 encap seg6local action End.BPF endpoint
obj my_bpf.o sec my_func dev eth0

$ ip -6 route show fc00::18
fc00::18  encap seg6local action End.BPF endpoint my_bpf.o:[my_func]
dev eth0 metric 1024 pref medium

v2: - re-use of print_encap_bpf_prog instead of fprintf
    - introduction of "endpoint" keyword for more consistency with
      others parameters

Signed-off-by: Mathieu Xhonneux <m.xhonneux@gmail.com>
---
 ip/iproute_lwtunnel.c | 154 +++++++++++++++++++++++++++-----------------------
 lib/bpf.c             |   5 ++
 2 files changed, 88 insertions(+), 71 deletions(-)

diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c
index 46a212c8..e6044811 100644
--- a/ip/iproute_lwtunnel.c
+++ b/ip/iproute_lwtunnel.c
@@ -177,6 +177,7 @@ static const char *seg6_action_names[SEG6_LOCAL_ACTION_MAX + 1] = {
 	[SEG6_LOCAL_ACTION_END_S]		= "End.S",
 	[SEG6_LOCAL_ACTION_END_AS]		= "End.AS",
 	[SEG6_LOCAL_ACTION_END_AM]		= "End.AM",
+	[SEG6_LOCAL_ACTION_END_BPF]		= "End.BPF",
 };
 
 static const char *format_action_type(int action)
@@ -202,6 +203,27 @@ static int read_action_type(const char *name)
 	return SEG6_LOCAL_ACTION_UNSPEC;
 }
 
+static void print_encap_bpf_prog(FILE *fp, struct rtattr *encap,
+				 const char *str)
+{
+	struct rtattr *tb[LWT_BPF_PROG_MAX+1];
+	const char *progname = NULL;
+
+	parse_rtattr_nested(tb, LWT_BPF_PROG_MAX, encap);
+
+	if (tb[LWT_BPF_PROG_NAME])
+		progname = rta_getattr_str(tb[LWT_BPF_PROG_NAME]);
+
+	if (is_json_context())
+		print_string(PRINT_JSON, str, NULL,
+			     progname ? : "<unknown>");
+	else {
+		fprintf(fp, "%s ", str);
+		if (progname)
+			fprintf(fp, "%s ", progname);
+	}
+}
+
 static void print_encap_seg6local(FILE *fp, struct rtattr *encap)
 {
 	struct rtattr *tb[SEG6_LOCAL_MAX + 1];
@@ -250,6 +272,9 @@ static void print_encap_seg6local(FILE *fp, struct rtattr *encap)
 		print_string(PRINT_ANY, "oif",
 			     "oif %s ", ll_index_to_name(oif));
 	}
+
+	if (tb[SEG6_LOCAL_BPF])
+		print_encap_bpf_prog(fp, tb[SEG6_LOCAL_BPF], "endpoint");
 }
 
 static void print_encap_mpls(FILE *fp, struct rtattr *encap)
@@ -356,27 +381,6 @@ static void print_encap_ip6(FILE *fp, struct rtattr *encap)
 			   "tc %u ", rta_getattr_u8(tb[LWTUNNEL_IP6_TC]));
 }
 
-static void print_encap_bpf_prog(FILE *fp, struct rtattr *encap,
-				 const char *str)
-{
-	struct rtattr *tb[LWT_BPF_PROG_MAX+1];
-	const char *progname = NULL;
-
-	parse_rtattr_nested(tb, LWT_BPF_PROG_MAX, encap);
-
-	if (tb[LWT_BPF_PROG_NAME])
-		progname = rta_getattr_str(tb[LWT_BPF_PROG_NAME]);
-
-	if (is_json_context())
-		print_string(PRINT_JSON, str, NULL,
-			     progname ? : "<unknown>");
-	else {
-		fprintf(fp, "%s ", str);
-		if (progname)
-			fprintf(fp, "%s ", progname);
-	}
-}
-
 static void print_encap_bpf(FILE *fp, struct rtattr *encap)
 {
 	struct rtattr *tb[LWT_BPF_MAX+1];
@@ -546,11 +550,60 @@ static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp,
 	return 0;
 }
 
+struct lwt_x {
+	struct rtattr *rta;
+	size_t len;
+};
+
+static void bpf_lwt_cb(void *lwt_ptr, int fd, const char *annotation)
+{
+	struct lwt_x *x = lwt_ptr;
+
+	rta_addattr32(x->rta, x->len, LWT_BPF_PROG_FD, fd);
+	rta_addattr_l(x->rta, x->len, LWT_BPF_PROG_NAME, annotation,
+		      strlen(annotation) + 1);
+}
+
+static const struct bpf_cfg_ops bpf_cb_ops = {
+	.ebpf_cb = bpf_lwt_cb,
+};
+
+static int lwt_parse_bpf(struct rtattr *rta, size_t len,
+			 int *argcp, char ***argvp,
+			 int attr, const enum bpf_prog_type bpf_type)
+{
+	struct bpf_cfg_in cfg = {
+		.type = bpf_type,
+		.argc = *argcp,
+		.argv = *argvp,
+	};
+	struct lwt_x x = {
+		.rta = rta,
+		.len = len,
+	};
+	struct rtattr *nest;
+	int err;
+
+	nest = rta_nest(rta, len, attr);
+	err = bpf_parse_and_load_common(&cfg, &bpf_cb_ops, &x);
+	if (err < 0) {
+		fprintf(stderr, "Failed to parse eBPF program: %s\n",
+			strerror(-err));
+		return -1;
+	}
+	rta_nest_end(rta, nest);
+
+	*argcp = cfg.argc;
+	*argvp = cfg.argv;
+
+	return 0;
+}
+
 static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp,
 				 char ***argvp)
 {
 	int segs_ok = 0, hmac_ok = 0, table_ok = 0, nh4_ok = 0, nh6_ok = 0;
-	int iif_ok = 0, oif_ok = 0, action_ok = 0, srh_ok = 0;
+	int iif_ok = 0, oif_ok = 0, action_ok = 0, srh_ok = 0, bpf_ok = 0;
 	__u32 action = 0, table, iif, oif;
 	struct ipv6_sr_hdr *srh;
 	char **argv = *argvp;
@@ -627,6 +680,14 @@ static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp,
 			} else {
 				continue;
 			}
+		} else if (strcmp(*argv, "endpoint") == 0) {
+			NEXT_ARG();
+			if (bpf_ok++)
+				duparg2("endpoint", *argv);
+
+			if (lwt_parse_bpf(rta, len, &argc, &argv, SEG6_LOCAL_BPF,
+			    BPF_PROG_TYPE_LWT_SEG6LOCAL) < 0)
+				exit(-1);
 		} else {
 			break;
 		}
@@ -896,55 +957,6 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len,
 	return 0;
 }
 
-struct lwt_x {
-	struct rtattr *rta;
-	size_t len;
-};
-
-static void bpf_lwt_cb(void *lwt_ptr, int fd, const char *annotation)
-{
-	struct lwt_x *x = lwt_ptr;
-
-	rta_addattr32(x->rta, x->len, LWT_BPF_PROG_FD, fd);
-	rta_addattr_l(x->rta, x->len, LWT_BPF_PROG_NAME, annotation,
-		      strlen(annotation) + 1);
-}
-
-static const struct bpf_cfg_ops bpf_cb_ops = {
-	.ebpf_cb = bpf_lwt_cb,
-};
-
-static int lwt_parse_bpf(struct rtattr *rta, size_t len,
-			 int *argcp, char ***argvp,
-			 int attr, const enum bpf_prog_type bpf_type)
-{
-	struct bpf_cfg_in cfg = {
-		.type = bpf_type,
-		.argc = *argcp,
-		.argv = *argvp,
-	};
-	struct lwt_x x = {
-		.rta = rta,
-		.len = len,
-	};
-	struct rtattr *nest;
-	int err;
-
-	nest = rta_nest(rta, len, attr);
-	err = bpf_parse_and_load_common(&cfg, &bpf_cb_ops, &x);
-	if (err < 0) {
-		fprintf(stderr, "Failed to parse eBPF program: %s\n",
-			strerror(-err));
-		return -1;
-	}
-	rta_nest_end(rta, nest);
-
-	*argcp = cfg.argc;
-	*argvp = cfg.argv;
-
-	return 0;
-}
-
 static void lwt_bpf_usage(void)
 {
 	fprintf(stderr, "Usage: ip route ... encap bpf [ in BPF ] [ out BPF ] [ xmit BPF ] [...]\n");
diff --git a/lib/bpf.c b/lib/bpf.c
index 4e26c0df..65e26989 100644
--- a/lib/bpf.c
+++ b/lib/bpf.c
@@ -95,6 +95,11 @@ static const struct bpf_prog_meta __bpf_prog_meta[] = {
 		.subdir		= "ip",
 		.section	= ELF_SECTION_PROG,
 	},
+	[BPF_PROG_TYPE_LWT_SEG6LOCAL] = {
+		.type		= "lwt_seg6local",
+		.subdir		= "ip",
+		.section	= ELF_SECTION_PROG,
+	},
 };
 
 static bool bpf_map_offload_neutral(enum bpf_map_type type)
-- 
2.16.1

^ permalink raw reply related

* Re: [PATCH v2 01/17] y2038: compat: Move common compat types to asm-generic/compat.h
From: Christoph Hellwig @ 2018-07-17 12:49 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: tglx, y2038, hch, linux-api, linux-arch, libc-alpha,
	albert.aribaud, netdev, viro, peterz, dvhart, ebiederm, linux
In-Reply-To: <20180716161103.16239-2-arnd@arndb.de>

On Mon, Jul 16, 2018 at 06:10:47PM +0200, Arnd Bergmann wrote:
> While converting compat system call handlers to work on 32-bit
> architectures, I found a number of types used in those handlers
> that are identical between all architectures.
> 
> Let's move all the identical ones into asm-generic/compat.h to avoid
> having to add even more identical definitions of those types.
> 
> For unknown reasons, mips defines __compat_gid32_t, __compat_uid32_t
> and compat_caddr_t as signed, while all others have them unsigned.
> This seems to be a mistake, but I'm leaving it alone here. The other
> types all differ by size or alignment on at least on architecture.
> 
> compat_aio_context_t is currently defined in linux/compat.h but
> also needed for compat_sys_io_getevents(), so let's move it into
> the same place.
> 
> While we still have not decided whether the 32-bit time handling
> will always use the compat syscalls, or in which form, I think this
> is a useful cleanup that we can merge regardless.

Looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply

* Re: [RFC PATCH rdma-next 13/18] RDMA/mlx5: Enable decap and packet reformat on flow tables
From: Or Gerlitz @ 2018-07-17 12:47 UTC (permalink / raw)
  To: Mark Bloch
  Cc: Doug Ledford, Jason Gunthorpe, Leon Romanovsky, RDMA mailing list,
	Saeed Mahameed, linux-netdev
In-Reply-To: <AM0PR05MB44032E09426E5E1DB5AD149ED25D0@AM0PR05MB4403.eurprd05.prod.outlook.com>

On Tue, Jul 17, 2018 at 12:46 AM, Mark Bloch <markb@mellanox.com> wrote:
>> From: Or Gerlitz [mailto:gerlitz.or@gmail.com]

>> > If NIC RX flow tables support decap opertion, enable it on creation.
>> opertion --> operation

saw it?

>> > If NIC TX flow tables support reformat opertion, enable it on creation.

opertion --> operation

>> What is the trigger to use the decap flag on RX table or encap flag on
>> TX table?

> It has no performance penalty to always enable that, so that's what I do if supported.

I was not referring to performance, see below

>> Please note that we have a short blanket w.r.t mutual usage by

> FDB and NIC steering tables have different limitations, so encap/decap on NIC steering
> have nothing to do with the limitations the FDB has with those operations.

no! AFAIK it has to do, the FW maintains three states for encap(decap)
NONE, FDB or NIC
if the state is NIC, an FDB table can't be created with encap set, and
the other way around, if the
state is FDB, NIC TX table can't be created with encap set, etc. This
is the short blanket I was
referring too, you can check me.

>> NIC vs e-Switch  steering, did you consider to do that on demand?
>
> The flow table needs to be created with those flags set if we want to attach
> decap/packet reformat action to it. BTW, there is no modify action for those bits
> so that's why I'm doing it on creation.

The question was if you can let the application tell you that they want to use
rules with encap/decap, as we did in the devlink switchdev API (encap enabled)

^ permalink raw reply

* [PATCH net-next] net: sched: Using NULL instead of plain integer
From: YueHaibing @ 2018-07-17 12:58 UTC (permalink / raw)
  To: davem, jhs, xiyou.wangcong, jiri; +Cc: linux-kernel, netdev, YueHaibing

Fixes the following sparse warnings:

net/sched/cls_api.c:1101:43: warning: Using plain integer as NULL pointer
net/sched/cls_api.c:1492:75: warning: Using plain integer as NULL pointer

Signed-off-by: YueHaibing <yuehaibing@huawei.com>
---
 net/sched/cls_api.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index c51b1b1..623fe2c 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -1098,7 +1098,7 @@ static void tfilter_notify_chain(struct net *net, struct sk_buff *oskb,
 	for (tp = rtnl_dereference(chain->filter_chain);
 	     tp; tp = rtnl_dereference(tp->next))
 		tfilter_notify(net, oskb, n, tp, block,
-			       q, parent, 0, event, false);
+			       q, parent, NULL, event, false);
 }
 
 static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
@@ -1489,7 +1489,7 @@ static bool tcf_chain_dump(struct tcf_chain *chain, struct Qdisc *q, u32 parent,
 			memset(&cb->args[1], 0,
 			       sizeof(cb->args) - sizeof(cb->args[0]));
 		if (cb->args[1] == 0) {
-			if (tcf_fill_node(net, skb, tp, block, q, parent, 0,
+			if (tcf_fill_node(net, skb, tp, block, q, parent, NULL,
 					  NETLINK_CB(cb->skb).portid,
 					  cb->nlh->nlmsg_seq, NLM_F_MULTI,
 					  RTM_NEWTFILTER) <= 0)
-- 
2.7.0

^ permalink raw reply related

* Re: [PATCH v2 net] net/ipv6: Do not allow device only routes via the multipath API
From: David Ahern @ 2018-07-17 12:13 UTC (permalink / raw)
  To: David Miller, dsahern; +Cc: netdev, eric.dumazet
In-Reply-To: <20180716.140901.431992949954567398.davem@davemloft.net>

On 7/16/18 3:09 PM, David Miller wrote:
> 
> Is this a -stable candidate?
> 

I think so. The API is not doing what the user requested, even though
the route add does not fail.

^ permalink raw reply

* [PATCH RFC/RFT net-next 10/17] net: Add key_len to neighbor constructor
From: dsahern @ 2018-07-17 12:06 UTC (permalink / raw)
  To: netdev
  Cc: nikita.leshchenko, roopa, stephen, idosch, jiri, saeedm,
	alex.aring, linux-wpan, netfilter-devel, linux-kernel,
	David Ahern
In-Reply-To: <20180717120651.15748-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Allows arp_constructor to not reference the arp_tbl directly.
ndisc_constructor assumes key length. Could do the same with arp.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 include/net/neighbour.h | 3 ++-
 net/core/neighbour.c    | 3 ++-
 net/decnet/dn_neigh.c   | 4 ++--
 net/ipv4/arp.c          | 6 +++---
 net/ipv6/ndisc.c        | 4 ++--
 5 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 5bc4d79b4b3a..6cf9ce16eac8 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -198,7 +198,8 @@ struct neigh_table {
 					const struct net_device *dev,
 					__u32 *hash_rnd);
 	bool			(*key_eq)(const struct neighbour *, const void *pkey);
-	int			(*constructor)(struct neighbour *);
+	int			(*constructor)(struct neighbour *,
+					       unsigned int key_len);
 	int			(*pconstructor)(struct pneigh_entry *);
 	void			(*pdestructor)(struct pneigh_entry *);
 	void			(*proxy_redo)(struct sk_buff *skb);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index e8630f9de24a..41841d8e4ea4 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -505,7 +505,8 @@ struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
 	dev_hold(dev);
 
 	/* Protocol specific setup. */
-	if (tbl->constructor &&	(error = tbl->constructor(n)) < 0) {
+	if (tbl->constructor &&
+	    (error = tbl->constructor(n, tbl->key_len)) < 0) {
 		rc = ERR_PTR(error);
 		goto out_neigh_release;
 	}
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 94b306f6d551..74112777beb0 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -49,7 +49,7 @@
 #include <net/dn_neigh.h>
 #include <net/dn_route.h>
 
-static int dn_neigh_construct(struct neighbour *);
+static int dn_neigh_construct(struct neighbour *, unsigned int key_len);
 static void dn_neigh_error_report(struct neighbour *, struct sk_buff *);
 static int dn_neigh_output(struct neighbour *neigh, struct sk_buff *skb);
 
@@ -108,7 +108,7 @@ struct neigh_table dn_neigh_table = {
 	.gc_thresh3 =			1024,
 };
 
-static int dn_neigh_construct(struct neighbour *neigh)
+static int dn_neigh_construct(struct neighbour *neigh, unsigned int key_len)
 {
 	struct net_device *dev = neigh->dev;
 	struct dn_neigh *dn = container_of(neigh, struct dn_neigh, n);
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index fd4a380da9bb..7b27faefa01b 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -125,7 +125,7 @@
  */
 static u32 arp_hash(const void *pkey, const struct net_device *dev, __u32 *hash_rnd);
 static bool arp_key_eq(const struct neighbour *n, const void *pkey);
-static int arp_constructor(struct neighbour *neigh);
+static int arp_constructor(struct neighbour *neigh, unsigned int key_len);
 static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb);
 static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb);
 static void parp_redo(struct sk_buff *skb);
@@ -221,7 +221,7 @@ static bool arp_key_eq(const struct neighbour *neigh, const void *pkey)
 	return neigh_key_eq32(neigh, pkey);
 }
 
-static int arp_constructor(struct neighbour *neigh)
+static int arp_constructor(struct neighbour *neigh, unsigned int key_len)
 {
 	__be32 addr;
 	struct net_device *dev = neigh->dev;
@@ -230,7 +230,7 @@ static int arp_constructor(struct neighbour *neigh)
 	u32 inaddr_any = INADDR_ANY;
 
 	if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
-		memcpy(neigh->primary_key, &inaddr_any, arp_tbl.key_len);
+		memcpy(neigh->primary_key, &inaddr_any, key_len);
 
 	addr = *(__be32 *)neigh->primary_key;
 	rcu_read_lock();
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 14b925f36099..5103d8641b04 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -77,7 +77,7 @@ static u32 ndisc_hash(const void *pkey,
 		      const struct net_device *dev,
 		      __u32 *hash_rnd);
 static bool ndisc_key_eq(const struct neighbour *neigh, const void *pkey);
-static int ndisc_constructor(struct neighbour *neigh);
+static int ndisc_constructor(struct neighbour *neigh, unsigned int key_len);
 static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb);
 static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb);
 static int pndisc_constructor(struct pneigh_entry *n);
@@ -319,7 +319,7 @@ static bool ndisc_key_eq(const struct neighbour *n, const void *pkey)
 	return neigh_key_eq128(n, pkey);
 }
 
-static int ndisc_constructor(struct neighbour *neigh)
+static int ndisc_constructor(struct neighbour *neigh, unsigned int key_len)
 {
 	struct in6_addr *addr = (struct in6_addr *)&neigh->primary_key;
 	struct net_device *dev = neigh->dev;
-- 
2.11.0

^ permalink raw reply related

* photos
From: Ruby @ 2018-07-17  9:59 UTC (permalink / raw)
  To: netdev

We have got a team of professional to do image editing service for you.

We have 20 image editors and on daily basis 2000 images can be processed.

If you want to check our quality of work please send us a photo with
instruction and we will work on it.

Our Services:
Photo cut out, masking, clipping path
Color, brightness and contrast correction
Beauty, Model retouching, skin retouching
Image cropping and resizing
Correcting the shape and size

We do unlimited revisions until you are satisfied with the work.

Thanks,
Ruby Young

^ permalink raw reply

* [PATCH] net: usb: asix: replace mii_nway_restart in resume path
From: Alexander Couzens @ 2018-07-17 11:17 UTC (permalink / raw)
  To: linux-usb; +Cc: Robert Foss, netdev, David S. Miller, Alexander Couzens

mii_nway_restart is not pm aware which results in a rtnl deadlock.
Implement mii_nway_restart manual by setting BMCR_ANRESTART if
BMCR_ANENABLE is set.

To reproduce:
* plug an asix based usb network interface
* wait until the device enters PM (~5 sec)
* `ip link set eth1 up` will never return

Fixes: d9fe64e51114 ("net: asix: Add in_pm parameter")
Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
---
 drivers/net/usb/asix_devices.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index 3d4f7959dabb..b1b3d8f7e67d 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -642,10 +642,12 @@ static void ax88772_restore_phy(struct usbnet *dev)
 				     priv->presvd_phy_advertise);
 
 		/* Restore BMCR */
+		if (priv->presvd_phy_bmcr & BMCR_ANENABLE)
+			priv->presvd_phy_bmcr |= BMCR_ANRESTART;
+
 		asix_mdio_write_nopm(dev->net, dev->mii.phy_id, MII_BMCR,
 				     priv->presvd_phy_bmcr);
 
-		mii_nway_restart(&dev->mii);
 		priv->presvd_phy_advertise = 0;
 		priv->presvd_phy_bmcr = 0;
 	}
-- 
2.18.0

^ permalink raw reply related

* Re: [libvirt] opening tap devices that are created in a container
From: Martin Kletzander @ 2018-07-17 11:45 UTC (permalink / raw)
  To: Jason Baron
  Cc: Roman Mohr, fdeutsch, libvir-list, netdev, ebiederm, davem,
	Laine Stump
In-Reply-To: <6f5f40b6-3637-c7a9-44f8-81352ece2bef@akamai.com>

[-- Attachment #1: Type: text/plain, Size: 5144 bytes --]

[Not sure who got this message, but it probably didn't get anywhere due to one
 mailserver, so resending to make sure]

On Mon, Jul 09, 2018 at 05:00:49PM -0400, Jason Baron wrote:
>On 07/08/2018 02:01 AM, Martin Kletzander wrote:
>> On Thu, Jul 05, 2018 at 06:24:20PM +0200, Roman Mohr wrote:
>>> On Thu, Jul 5, 2018 at 4:20 PM Jason Baron <jbaron@akamai.com> wrote:
>>>
>>>> Hi,
>>>>
>>>> Opening tap devices, such as macvtap, that are created in containers is
>>>> problematic because the interface for opening tap devices is via
>>>> /dev/tapNN and devtmpfs is not typically mounted inside a container as
>>>> its not namespace aware. It is possible to do a mknod() in the
>>>> container, once the tap devices are created, however, since the tap
>>>> devices are created dynamically its not possible to apriori allow access
>>>> to certain major/minor numbers, since we don't know what these are going
>>>> to be. In addition, its desirable to not allow the mknod capability in
>>>> containers. This behavior, I think is somewhat inconsistent with the
>>>> tuntap driver where one can create tuntap devices inside a container by
>>>> first opening /dev/net/tun and then using them by supplying the tuntap
>>>> device name via the ioctl(TUNSETIFF). And since TUNSETIFF validates the
>>>> network namespace, one is limited to opening network devices that belong
>>>> to your current network namespace.
>>>>
>>>> Here are some options to this issue, that I wanted to get feedback
>>>> about, and just wondering if anybody else has run into this.
>>>>
>>>> 1)
>>>>
>>>> Don't create the tap device, such as macvtap in the container. Instead,
>>>> create the tap device outside of the container and then move it into the
>>>> desired container network namespace. In addition, do a mknod() for the
>>>> corresponding /dev/tapNN device from outside the container before doing
>>>> chroot().
>>>>
>>>> This solution still doesn't allow tap devices to be created inside the
>>>> container. Thus, in the case of kubevirt, which runs libvirtd inside of
>>>> a container, it would mean changing libvirtd to open existing tap
>>>> devices (as opposed to the current behavior of creating new ones). This
>>>> would not require any kernel changes, but as mentioned seems
>>>> inconsistent with the tuntap interface.
>>>>
>>>
>>> For KubeVirt, apart from how exactly the device ends up in the
>>> container, I
>>> would want to pursue a way where all network preparations which require
>>> privileges happens from a privileged process *outside* of the container.
>>> Like CNI solutions do it. They run outside, have privileges and then
>>> create
>>> devices in the right network/mount namespace or move them there. The
>>> final
>>> goal for KubeVirt is that our pod with the qemu process is completely
>>> unprivileged and privileged setup happens from outside.
>>>
>>> As a consequence, and depending on which route Dan pursues with the
>>> restructured libvirt, I would assume that either a privileged
>>> libvirtd-part
>>> outside of containers creates the devices by entering the right
>>> namespaces,
>>> or that libvirt in the container can consume pre-created tun/tap devices,
>>> like qemu.
>>>
>>
>> That would be nice, but as far as I understand there will always be a
>> need for
>> some privileges if you want to use a tap device.  It's nice that CNI
>> does that
>> and all the containers can run unprivileged, but that's because they do
>> not open
>> the tap device and they do not do any privileged operations on it.  But
>> QEMU
>> needs to.  So the only way would be passing an opened fd to the
>> container or
>> opening the tap device there and making the fd usable for one process in
>> the
>> container.  Is this already supported for some type of containers in
>> some way?
>>
>> Martin
>
>Hi,
>
>So another option here call it #3 is to pass open fds via unix sockets.
>If there are privileged operations that QEMU is trying to do with the fd
>though, how will opening it first and then passing it to an unprivileged
>QEMU address that? Is the opener doing those operations first?
>

Sorry for the confusion, but QEMU is not doing any privileged operations.  I got
confused by the fact that anyone can open and do a R/W on a tap device.  But it
looks like that's on purpose.  No capabilities are needed for opening
/dev/net/tun and calling ioctl(TUNSETIFF) with existing name and then doing R/W
operations on it.  It just works.

Correct me if I'm wrong, but to sum it all up, the only things that we need to
figure out (which might possibly be solved by ideas in the other thread) are:

tap:
- Existence of /dev/net/tun
- Having permissions to open it (0666 by default, shouldn't be a nig deal)
- Knowing the device name

macvtap:
- Existence of /dev/tapXX
- Having permissions to open /dev/tapXX
- One of the following:
  - Knowing the device name (and being able to translate it using a netlink socket)
  - Knowing the the device index

The rest should be an implementation detail.

Am I right?  Did I miss anything?

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [V9fs-developer] BUG: corrupted list in p9_fd_cancelled
From: jiangyiwen @ 2018-07-17 12:09 UTC (permalink / raw)
  To: syzbot, davem, ericvh, linux-kernel, lucho, netdev, rminnich,
	syzkaller-bugs, v9fs-developer
In-Reply-To: <000000000000ca008a05711fc427@google.com>

On 2018/7/16 23:49, syzbot wrote:
> Hello,
> 
> syzbot found the following crash on:
> 
> HEAD commit:    1d4eb636f0ab Add linux-next specific files for 20180716
> git tree:       linux-next
> console output: https://syzkaller.appspot.com/x/log.txt?x=10abe770400000
> kernel config:  https://syzkaller.appspot.com/x/.config?x=ea5926dddb0db97a
> dashboard link: https://syzkaller.appspot.com/bug?extid=f78c15f5aa00e5c16d59
> compiler:       gcc (GCC) 8.0.1 20180413 (experimental)
> 
> Unfortunately, I don't have any reproducer for this crash yet.
> 
> IMPORTANT: if you fix the bug, please add the following tag to the commit:
> Reported-by: syzbot+f78c15f5aa00e5c16d59@syzkaller.appspotmail.com
> 
> list_del corruption, ffff880193723368->next is LIST_POISON1 (dead000000000100)
> ------------[ cut here ]------------
> kernel BUG at lib/list_debug.c:47!
> invalid opcode: 0000 [#1] SMP KASAN
> CPU: 1 PID: 9124 Comm: syz-executor7 Not tainted 4.18.0-rc5-next-20180716+ #8
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
> RIP: 0010:__list_del_entry_valid.cold.1+0x26/0x58 lib/list_debug.c:45
> Code: ff fd 0f 0b 4c 89 e2 48 89 de 48 c7 c7 40 88 1a 88 e8 0a 35 ff fd 0f 0b 4c 89 ea 48 89 de 48 c7 c7 e0 87 1a 88 e8 f6 34 ff fd <0f> 0b 48 89 de 48 c7 c7 00 89 1a 88 e8 e5 34 ff fd 0f 0b 48 89 de
> RSP: 0018:ffff88019b65f1d0 EFLAGS: 00010282
> RAX: 000000000000004e RBX: ffff880193723368 RCX: ffffc90008c3b000
> RDX: 0000000000000000 RSI: ffffffff81633fc1 RDI: 0000000000000001
> RBP: ffff88019b65f1e8 R08: ffff88019918e100 R09: ffffed003b5e4fc0
> R10: ffffed003b5e4fc0 R11: ffff8801daf27e07 R12: dead000000000200
> R13: dead000000000100 R14: ffff8801ab908600 R15: dffffc0000000000
> FS:  00007f238387e700(0000) GS:ffff8801daf00000(0000) knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 0000000000625208 CR3: 00000001b4588000 CR4: 00000000001406e0
> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> Call Trace:
>  __list_del_entry include/linux/list.h:117 [inline]
>  list_del include/linux/list.h:125 [inline]
>  p9_fd_cancelled+0x80/0x2f0 net/9p/trans_fd.c:707
>  p9_client_flush+0x252/0x2a0 net/9p/client.c:693
>  p9_client_rpc+0x122c/0x1400 net/9p/client.c:802
>  p9_client_version net/9p/client.c:977 [inline]
>  p9_client_create+0xdbc/0x177c net/9p/client.c:1070
>  v9fs_session_init+0x21a/0x1a80 fs/9p/v9fs.c:400
>  v9fs_mount+0x7c/0x900 fs/9p/vfs_super.c:135
>  legacy_get_tree+0x118/0x440 fs/fs_context.c:659
>  vfs_get_tree+0x1cb/0x5c0 fs/super.c:1743
>  do_new_mount fs/namespace.c:2567 [inline]
>  do_mount+0x6c1/0x1fb0 fs/namespace.c:2889
>  ksys_mount+0x12d/0x140 fs/namespace.c:3105
>  __do_sys_mount fs/namespace.c:3119 [inline]
>  __se_sys_mount fs/namespace.c:3116 [inline]
>  __x64_sys_mount+0xbe/0x150 fs/namespace.c:3116
>  do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290
>  entry_SYSCALL_64_after_hwframe+0x49/0xbe
> RIP: 0033:0x455ab9
> Code: 1d ba fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 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 b9 fb ff c3 66 2e 0f 1f 84 00 00 00 00
> RSP: 002b:00007f238387dc68 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5
> RAX: ffffffffffffffda RBX: 00007f238387e6d4 RCX: 0000000000455ab9
> RDX: 00000000200002c0 RSI: 00000000200001c0 RDI: 0000000000000000
> RBP: 000000000072bea0 R08: 00000000200003c0 R09: 0000000000000000
> R10: 0000000000000000 R11: 0000000000000246 R12: 00000000ffffffff
> R13: 00000000004c0201 R14: 00000000004cfe50 R15: 0000000000000000
> Modules linked in:
> Dumping ftrace buffer:
>    (ftrace buffer empty)
> ---[ end trace 7de5f20f6f7cde43 ]---
> RIP: 0010:__list_del_entry_valid.cold.1+0x26/0x58 lib/list_debug.c:45
> Code: ff fd 0f 0b 4c 89 e2 48 89 de 48 c7 c7 40 88 1a 88 e8 0a 35 ff fd 0f 0b 4c 89 ea 48 89 de 48 c7 c7 e0 87 1a 88 e8 f6 34 ff fd <0f> 0b 48 89 de 48 c7 c7 00 89 1a 88 e8 e5 34 ff fd 0f 0b 48 89 de
> serio: Serial port pts1
> RSP: 0018:ffff88019b65f1d0 EFLAGS: 00010282
> RAX: 000000000000004e RBX: ffff880193723368 RCX: ffffc90008c3b000
> RDX: 0000000000000000 RSI: ffffffff81633fc1 RDI: 0000000000000001
> RBP: ffff88019b65f1e8 R08: ffff88019918e100 R09: ffffed003b5e4fc0
> R10: ffffed003b5e4fc0 R11: ffff8801daf27e07 R12: dead000000000200
> R13: dead000000000100 R14: ffff8801ab908600 R15: dffffc0000000000
> FS:  00007f238387e700(0000) GS:ffff8801daf00000(0000) knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 0000000000625208 CR3: 00000001b4588000 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#bug-status-tracking for how to communicate with syzbot.
> 
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> V9fs-developer mailing list
> V9fs-developer@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/v9fs-developer
> 
> .
> 

I think the reason of corrupted is list_del(&req->req_list) can be
called by multi-threads, like the race between p9_conn_cancel and
p9_fd_cancelled. There are two problems, first list_del the req_list
don't use spin lock in p9_conn_cancel; second, we should use list_del_init,
it will not report the warning when it is protected in the spinlock.

Thanks,
Yiwen.

^ permalink raw reply

* [PATCH RFC/RFT net-next 17/17] net/neighbor: Remove neigh_tables and NEIGH enum
From: dsahern @ 2018-07-17 12:06 UTC (permalink / raw)
  To: netdev
  Cc: nikita.leshchenko, roopa, stephen, idosch, jiri, saeedm,
	alex.aring, linux-wpan, netfilter-devel, linux-kernel,
	David Ahern
In-Reply-To: <20180717120651.15748-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

No longer used.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 include/net/neighbour.h | 8 --------
 net/core/neighbour.c    | 2 --
 2 files changed, 10 deletions(-)

diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index e968db1b7742..72002a24e72e 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -222,14 +222,6 @@ struct neigh_table {
 	struct pneigh_entry	**phash_buckets;
 };
 
-enum {
-	NEIGH_ARP_TABLE = 0,
-	NEIGH_ND_TABLE = 1,
-	NEIGH_DN_TABLE = 2,
-	NEIGH_NR_TABLES,
-	NEIGH_LINK_TABLE = NEIGH_NR_TABLES /* Pseudo table for neigh_xmit */
-};
-
 struct neigh_table *neigh_find_table(struct net *net, u8 family);
 
 static inline int neigh_parms_family(struct neigh_parms *p)
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 1bb7fa14cb62..7c3d4cb811d3 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1559,8 +1559,6 @@ static void neigh_parms_destroy(struct neigh_parms *parms)
 
 static struct lock_class_key neigh_table_proxy_queue_class;
 
-static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
-
 void neigh_table_init(struct net *net, struct neigh_table *tbl)
 {
 	unsigned long now = jiffies;
-- 
2.11.0

^ permalink raw reply related

* [PATCH RFC/RFT net-next 16/17] net/decnet: Move neighbor table to per-namespace
From: dsahern @ 2018-07-17 12:06 UTC (permalink / raw)
  To: netdev
  Cc: nikita.leshchenko, roopa, stephen, idosch, jiri, saeedm,
	alex.aring, linux-wpan, netfilter-devel, linux-kernel,
	David Ahern
In-Reply-To: <20180717120651.15748-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Convert decnet neighbor table to per-namespace. Since there are no
other per-namespace parameters for decnet just add the reference to
struct net directly.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 include/net/net_namespace.h |  3 +++
 net/core/neighbour.c        | 26 ++++++++++----------------
 2 files changed, 13 insertions(+), 16 deletions(-)

diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index a71264d75d7f..77799ed7212e 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -108,6 +108,9 @@ struct net {
 #if IS_ENABLED(CONFIG_IPV6)
 	struct netns_ipv6	ipv6;
 #endif
+#if IS_ENABLED(CONFIG_DECNET)
+	struct neigh_table	*dn_tbl;
+#endif
 #if IS_ENABLED(CONFIG_IEEE802154_6LOWPAN)
 	struct netns_ieee802154_lowpan	ieee802154_lowpan;
 #endif
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 35c41c4876e5..1bb7fa14cb62 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1485,15 +1485,11 @@ EXPORT_SYMBOL(pneigh_enqueue);
 static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
 						      struct net *net, int ifindex)
 {
-	struct net *def_net = &init_net;
 	struct neigh_parms *p;
 
-	if (tbl->family != AF_DECnet)
-		def_net = neigh_parms_net(p);
-
 	list_for_each_entry(p, &tbl->parms_list, list) {
 		if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
-		    (!p->dev && !ifindex && net_eq(net, def_net)))
+		    (!p->dev && !ifindex))
 			return p;
 	}
 
@@ -1622,9 +1618,11 @@ void neigh_table_init(struct net *net, struct neigh_table *tbl)
 		net->ipv6.nd_tbl = tbl;
 		break;
 #endif
+#if IS_ENABLED(CONFIG_DECNET)
 	case AF_DECnet:
-		neigh_tables[NEIGH_DN_TABLE] = tbl;
+		net->dn_tbl = tbl;
 		break;
+#endif
 	}
 }
 EXPORT_SYMBOL(neigh_table_init);
@@ -1642,9 +1640,11 @@ int neigh_table_clear(struct net *net, struct neigh_table *tbl)
 		net->ipv6.nd_tbl = NULL;
 		break;
 #endif
+#if IS_ENABLED(CONFIG_DECNET)
 	case AF_DECnet:
-		neigh_tables[NEIGH_DN_TABLE] = NULL;
+		net->dn_tbl = NULL;
 		break;
+#endif
 	}
 
 	/* It is not clean... Fix it to unload IPv6 module safely */
@@ -1684,9 +1684,11 @@ struct neigh_table *neigh_find_table(struct net *net, u8 family)
 		tbl = net->ipv6.nd_tbl;
 		break;
 #endif
+#if IS_ENABLED(CONFIG_DECNET)
 	case AF_DECnet:
-		tbl = neigh_tables[NEIGH_DN_TABLE];
+		tbl = net->dn_tbl;
 		break;
+#endif
 	}
 
 	return tbl;
@@ -2182,14 +2184,6 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh,
 		}
 	}
 
-	err = -ENOENT;
-	if (tbl->family == AF_DECnet) {
-		if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
-		     tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
-		    !net_eq(net, &init_net))
-			goto errout_tbl_lock;
-	}
-
 	if (tb[NDTA_THRESH1])
 		tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH RFC/RFT net-next 15/17] net/ipv6: Convert neighbor table to per-namespace
From: dsahern @ 2018-07-17 12:06 UTC (permalink / raw)
  To: netdev
  Cc: nikita.leshchenko, roopa, stephen, idosch, jiri, saeedm,
	alex.aring, linux-wpan, netfilter-devel, linux-kernel,
	David Ahern
In-Reply-To: <20180717120651.15748-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Convert IPv6 neighbor table to per-namespace.

This patch is a transition patch for the core neighbor code, so update
the init_net reference as needed for AF_INET6. With the per-namespace
table allow gc parameters to be changed per namespace.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 include/net/ndisc.h      |   6 ++-
 include/net/netns/ipv6.h |   1 +
 net/core/neighbour.c     |  16 +++++--
 net/ipv6/ndisc.c         | 120 +++++++++++++++++++++++------------------------
 4 files changed, 76 insertions(+), 67 deletions(-)

diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 6fc58a61acdd..ce8ccc45cb4e 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -374,7 +374,11 @@ static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, _
 
 static inline struct neigh_table *ipv6_neigh_table(struct net *net)
 {
-	return neigh_find_table(net, AF_INET6);
+#if IS_ENABLED(CONFIG_IPV6)
+	return net->ipv6.nd_tbl;
+#else
+	return NULL;
+#endif
 }
 
 static inline struct neighbour *ipv6_neigh_create(struct net_device *dev,
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 762ac9931b62..62fd0ce9ab0b 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -66,6 +66,7 @@ struct netns_ipv6 {
 	struct rt6_statistics   *rt6_stats;
 	struct timer_list       ip6_fib_timer;
 	struct hlist_head       *fib_table_hash;
+	struct neigh_table	*nd_tbl;
 	struct fib6_table       *fib6_main_tbl;
 	struct list_head	fib6_walkers;
 	struct dst_ops		ip6_dst_ops;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 95b9269e3f35..35c41c4876e5 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1488,7 +1488,7 @@ static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
 	struct net *def_net = &init_net;
 	struct neigh_parms *p;
 
-	if (tbl->family == AF_INET)
+	if (tbl->family != AF_DECnet)
 		def_net = neigh_parms_net(p);
 
 	list_for_each_entry(p, &tbl->parms_list, list) {
@@ -1617,9 +1617,11 @@ void neigh_table_init(struct net *net, struct neigh_table *tbl)
 	case AF_INET:
 		net->ipv4.arp_tbl = tbl;
 		break;
+#if IS_ENABLED(CONFIG_IPV6)
 	case AF_INET6:
-		neigh_tables[NEIGH_ND_TABLE] = tbl;
+		net->ipv6.nd_tbl = tbl;
 		break;
+#endif
 	case AF_DECnet:
 		neigh_tables[NEIGH_DN_TABLE] = tbl;
 		break;
@@ -1635,9 +1637,11 @@ int neigh_table_clear(struct net *net, struct neigh_table *tbl)
 	case AF_INET:
 		net->ipv4.arp_tbl = NULL;
 		break;
+#if IS_ENABLED(CONFIG_IPV6)
 	case AF_INET6:
-		neigh_tables[NEIGH_ND_TABLE] = NULL;
+		net->ipv6.nd_tbl = NULL;
 		break;
+#endif
 	case AF_DECnet:
 		neigh_tables[NEIGH_DN_TABLE] = NULL;
 		break;
@@ -1675,9 +1679,11 @@ struct neigh_table *neigh_find_table(struct net *net, u8 family)
 	case AF_INET:
 		tbl = net->ipv4.arp_tbl;
 		break;
+#if IS_ENABLED(CONFIG_IPV6)
 	case AF_INET6:
-		tbl = neigh_tables[NEIGH_ND_TABLE];
+		tbl = net->ipv6.nd_tbl;
 		break;
+#endif
 	case AF_DECnet:
 		tbl = neigh_tables[NEIGH_DN_TABLE];
 		break;
@@ -2177,7 +2183,7 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh,
 	}
 
 	err = -ENOENT;
-	if (tbl->family != AF_INET) {
+	if (tbl->family == AF_DECnet) {
 		if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
 		     tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
 		    !net_eq(net, &init_net))
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 6105530fe865..ae78984c4c94 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -107,39 +107,18 @@ static const struct neigh_ops ndisc_direct_ops = {
 	.connected_output =	neigh_direct_output,
 };
 
-struct neigh_table nd_tbl = {
-	.family =	AF_INET6,
-	.key_len =	sizeof(struct in6_addr),
-	.protocol =	cpu_to_be16(ETH_P_IPV6),
-	.hash =		ndisc_hash,
-	.key_eq =	ndisc_key_eq,
-	.constructor =	ndisc_constructor,
-	.pconstructor =	pndisc_constructor,
-	.pdestructor =	pndisc_destructor,
-	.proxy_redo =	pndisc_redo,
-	.id =		"ndisc_cache",
-	.parms = {
-		.tbl			= &nd_tbl,
-		.reachable_time		= ND_REACHABLE_TIME,
-		.data = {
-			[NEIGH_VAR_MCAST_PROBES] = 3,
-			[NEIGH_VAR_UCAST_PROBES] = 3,
-			[NEIGH_VAR_RETRANS_TIME] = ND_RETRANS_TIMER,
-			[NEIGH_VAR_BASE_REACHABLE_TIME] = ND_REACHABLE_TIME,
-			[NEIGH_VAR_DELAY_PROBE_TIME] = 5 * HZ,
-			[NEIGH_VAR_GC_STALETIME] = 60 * HZ,
-			[NEIGH_VAR_QUEUE_LEN_BYTES] = SK_WMEM_MAX,
-			[NEIGH_VAR_PROXY_QLEN] = 64,
-			[NEIGH_VAR_ANYCAST_DELAY] = 1 * HZ,
-			[NEIGH_VAR_PROXY_DELAY] = (8 * HZ) / 10,
-		},
-	},
-	.gc_interval =	  30 * HZ,
-	.gc_thresh1 =	 128,
-	.gc_thresh2 =	 512,
-	.gc_thresh3 =	1024,
+static int parms_data[NEIGH_VAR_DATA_MAX] = {
+	[NEIGH_VAR_MCAST_PROBES] = 3,
+	[NEIGH_VAR_UCAST_PROBES] = 3,
+	[NEIGH_VAR_RETRANS_TIME] = ND_RETRANS_TIMER,
+	[NEIGH_VAR_BASE_REACHABLE_TIME] = ND_REACHABLE_TIME,
+	[NEIGH_VAR_DELAY_PROBE_TIME] = 5 * HZ,
+	[NEIGH_VAR_GC_STALETIME] = 60 * HZ,
+	[NEIGH_VAR_QUEUE_LEN_BYTES] = SK_WMEM_MAX,
+	[NEIGH_VAR_PROXY_QLEN] = 64,
+	[NEIGH_VAR_ANYCAST_DELAY] = 1 * HZ,
+	[NEIGH_VAR_PROXY_DELAY] = (8 * HZ) / 10,
 };
-EXPORT_SYMBOL_GPL(nd_tbl);
 
 void __ndisc_fill_addr_option(struct sk_buff *skb, int type, void *data,
 			      int data_len, int pad)
@@ -1865,16 +1844,22 @@ int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, void __user *bu
 
 static int __net_init ndisc_net_init(struct net *net)
 {
+	struct neigh_table *nd_tbl;
 	struct ipv6_pinfo *np;
 	struct sock *sk;
 	int err;
 
+	nd_tbl = kzalloc(sizeof(*nd_tbl), GFP_KERNEL);
+	if (!nd_tbl)
+		return -ENOMEM;
+
 	err = inet_ctl_sock_create(&sk, PF_INET6,
 				   SOCK_RAW, IPPROTO_ICMPV6, net);
 	if (err < 0) {
 		ND_PRINTK(0, err,
 			  "NDISC: Failed to initialize the control socket (err %d)\n",
 			  err);
+		kfree(nd_tbl);
 		return err;
 	}
 
@@ -1885,12 +1870,52 @@ static int __net_init ndisc_net_init(struct net *net)
 	/* Do not loopback ndisc messages */
 	np->mc_loop = 0;
 
-	return 0;
+	rwlock_init(&nd_tbl->lock);
+	nd_tbl->family		= AF_INET6;
+	nd_tbl->key_len		= sizeof(struct in6_addr);
+	nd_tbl->protocol	= cpu_to_be16(ETH_P_IPV6);
+	nd_tbl->hash		= ndisc_hash;
+	nd_tbl->key_eq		= ndisc_key_eq;
+	nd_tbl->constructor	= ndisc_constructor;
+	nd_tbl->pconstructor	= pndisc_constructor;
+	nd_tbl->pdestructor	= pndisc_destructor;
+	nd_tbl->proxy_redo	= pndisc_redo;
+	nd_tbl->id		= "ndisc_cache";
+	nd_tbl->gc_interval	= 30 * HZ;
+	nd_tbl->gc_thresh1	= 128;
+	nd_tbl->gc_thresh2	= 512;
+	nd_tbl->gc_thresh3	= 1024;
+
+	nd_tbl->parms.tbl	= nd_tbl;
+	nd_tbl->parms.reachable_time = ND_REACHABLE_TIME;
+	memcpy(nd_tbl->parms.data, parms_data, sizeof(parms_data));
+
+	neigh_table_init(net, nd_tbl);
+
+	err = 0;
+#ifdef CONFIG_SYSCTL
+	err = neigh_sysctl_register(NULL, &nd_tbl->parms,
+				    ndisc_ifinfo_sysctl_change);
+	if (err) {
+		inet_ctl_sock_destroy(net->ipv6.ndisc_sk);
+		kfree(nd_tbl);
+	}
+#endif
+	return err;
 }
 
 static void __net_exit ndisc_net_exit(struct net *net)
 {
+	struct neigh_table *nd_tbl = net->ipv6.nd_tbl;
+
 	inet_ctl_sock_destroy(net->ipv6.ndisc_sk);
+
+#ifdef CONFIG_SYSCTL
+	neigh_sysctl_unregister(&nd_tbl->parms);
+#endif
+	net->ipv6.nd_tbl = NULL;
+	neigh_table_clear(net, nd_tbl);
+	kfree(nd_tbl);
 }
 
 static struct pernet_operations ndisc_net_ops = {
@@ -1900,30 +1925,7 @@ static struct pernet_operations ndisc_net_ops = {
 
 int __init ndisc_init(void)
 {
-	int err;
-
-	err = register_pernet_subsys(&ndisc_net_ops);
-	if (err)
-		return err;
-	/*
-	 * Initialize the neighbour table
-	 */
-	neigh_table_init(&init_net, &nd_tbl);
-
-#ifdef CONFIG_SYSCTL
-	err = neigh_sysctl_register(NULL, &nd_tbl.parms,
-				    ndisc_ifinfo_sysctl_change);
-	if (err)
-		goto out_unregister_pernet;
-out:
-#endif
-	return err;
-
-#ifdef CONFIG_SYSCTL
-out_unregister_pernet:
-	unregister_pernet_subsys(&ndisc_net_ops);
-	goto out;
-#endif
+	return register_pernet_subsys(&ndisc_net_ops);
 }
 
 int __init ndisc_late_init(void)
@@ -1938,9 +1940,5 @@ void ndisc_late_cleanup(void)
 
 void ndisc_cleanup(void)
 {
-#ifdef CONFIG_SYSCTL
-	neigh_sysctl_unregister(&nd_tbl.parms);
-#endif
-	neigh_table_clear(&init_net, &nd_tbl);
 	unregister_pernet_subsys(&ndisc_net_ops);
 }
-- 
2.11.0

^ permalink raw reply related

* [PATCH RFC/RFT net-next 14/17] net/ipv4: Convert arp table to per namespace
From: dsahern @ 2018-07-17 12:06 UTC (permalink / raw)
  To: netdev
  Cc: nikita.leshchenko, roopa, stephen, idosch, jiri, saeedm,
	alex.aring, linux-wpan, netfilter-devel, linux-kernel,
	David Ahern
In-Reply-To: <20180717120651.15748-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Convert IPv4 neighbor table to per-namespace.

This patch is a transition patch for the core neighbor code, so update
the init_net reference as needed for AF_INET. With the per-namespace
table allow gc parameters to be changed per namespace.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 include/net/arp.h        |  2 +-
 include/net/netns/ipv4.h |  1 +
 net/core/neighbour.c     | 22 +++++++-----
 net/ipv4/arp.c           | 88 ++++++++++++++++++++++++++++--------------------
 4 files changed, 67 insertions(+), 46 deletions(-)

diff --git a/include/net/arp.h b/include/net/arp.h
index fae3561db10b..ec86b286f779 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -9,7 +9,7 @@
 
 static inline struct neigh_table *ipv4_neigh_table(struct net *net)
 {
-	return neigh_find_table(net, AF_INET);
+	return net->ipv4.arp_tbl;
 }
 
 static inline struct neighbour *ipv4_neigh_create(struct net_device *dev,
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 661348f23ea5..bc1fab231500 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -51,6 +51,7 @@ struct netns_ipv4 {
 	struct ipv4_devconf	*devconf_dflt;
 	struct ip_ra_chain __rcu *ra_chain;
 	struct mutex		ra_mutex;
+	struct neigh_table	*arp_tbl;
 #ifdef CONFIG_IP_MULTIPLE_TABLES
 	struct fib_rules_ops	*rules_ops;
 	bool			fib_has_custom_rules;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index afb2ee985dd1..95b9269e3f35 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1485,11 +1485,15 @@ EXPORT_SYMBOL(pneigh_enqueue);
 static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
 						      struct net *net, int ifindex)
 {
+	struct net *def_net = &init_net;
 	struct neigh_parms *p;
 
+	if (tbl->family == AF_INET)
+		def_net = neigh_parms_net(p);
+
 	list_for_each_entry(p, &tbl->parms_list, list) {
 		if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
-		    (!p->dev && !ifindex && net_eq(net, &init_net)))
+		    (!p->dev && !ifindex && net_eq(net, def_net)))
 			return p;
 	}
 
@@ -1611,7 +1615,7 @@ void neigh_table_init(struct net *net, struct neigh_table *tbl)
 
 	switch (family) {
 	case AF_INET:
-		neigh_tables[NEIGH_ARP_TABLE] = tbl;
+		net->ipv4.arp_tbl = tbl;
 		break;
 	case AF_INET6:
 		neigh_tables[NEIGH_ND_TABLE] = tbl;
@@ -1629,7 +1633,7 @@ int neigh_table_clear(struct net *net, struct neigh_table *tbl)
 
 	switch (family) {
 	case AF_INET:
-		neigh_tables[NEIGH_ARP_TABLE] = NULL;
+		net->ipv4.arp_tbl = NULL;
 		break;
 	case AF_INET6:
 		neigh_tables[NEIGH_ND_TABLE] = NULL;
@@ -1669,7 +1673,7 @@ struct neigh_table *neigh_find_table(struct net *net, u8 family)
 
 	switch (family) {
 	case AF_INET:
-		tbl = neigh_tables[NEIGH_ARP_TABLE];
+		tbl = net->ipv4.arp_tbl;
 		break;
 	case AF_INET6:
 		tbl = neigh_tables[NEIGH_ND_TABLE];
@@ -2173,10 +2177,12 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh,
 	}
 
 	err = -ENOENT;
-	if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
-	     tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
-	    !net_eq(net, &init_net))
-		goto errout_tbl_lock;
+	if (tbl->family != AF_INET) {
+		if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
+		     tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
+		    !net_eq(net, &init_net))
+			goto errout_tbl_lock;
+	}
 
 	if (tb[NDTA_THRESH1])
 		tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 707b40f76852..61c1d02a8fad 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -152,38 +152,19 @@ static const struct neigh_ops arp_direct_ops = {
 	.connected_output =	neigh_direct_output,
 };
 
-struct neigh_table arp_tbl = {
-	.family		= AF_INET,
-	.key_len	= 4,
-	.protocol	= cpu_to_be16(ETH_P_IP),
-	.hash		= arp_hash,
-	.key_eq		= arp_key_eq,
-	.constructor	= arp_constructor,
-	.proxy_redo	= parp_redo,
-	.id		= "arp_cache",
-	.parms		= {
-		.tbl			= &arp_tbl,
-		.reachable_time		= 30 * HZ,
-		.data	= {
-			[NEIGH_VAR_MCAST_PROBES] = 3,
-			[NEIGH_VAR_UCAST_PROBES] = 3,
-			[NEIGH_VAR_RETRANS_TIME] = 1 * HZ,
-			[NEIGH_VAR_BASE_REACHABLE_TIME] = 30 * HZ,
-			[NEIGH_VAR_DELAY_PROBE_TIME] = 5 * HZ,
-			[NEIGH_VAR_GC_STALETIME] = 60 * HZ,
-			[NEIGH_VAR_QUEUE_LEN_BYTES] = SK_WMEM_MAX,
-			[NEIGH_VAR_PROXY_QLEN] = 64,
-			[NEIGH_VAR_ANYCAST_DELAY] = 1 * HZ,
-			[NEIGH_VAR_PROXY_DELAY]	= (8 * HZ) / 10,
-			[NEIGH_VAR_LOCKTIME] = 1 * HZ,
-		},
-	},
-	.gc_interval	= 30 * HZ,
-	.gc_thresh1	= 128,
-	.gc_thresh2	= 512,
-	.gc_thresh3	= 1024,
+static int parms_data[NEIGH_VAR_DATA_MAX] = {
+	[NEIGH_VAR_MCAST_PROBES] = 3,
+	[NEIGH_VAR_UCAST_PROBES] = 3,
+	[NEIGH_VAR_RETRANS_TIME] = 1 * HZ,
+	[NEIGH_VAR_BASE_REACHABLE_TIME] = 30 * HZ,
+	[NEIGH_VAR_DELAY_PROBE_TIME] = 5 * HZ,
+	[NEIGH_VAR_GC_STALETIME] = 60 * HZ,
+	[NEIGH_VAR_QUEUE_LEN_BYTES] = SK_WMEM_MAX,
+	[NEIGH_VAR_PROXY_QLEN] = 64,
+	[NEIGH_VAR_ANYCAST_DELAY] = 1 * HZ,
+	[NEIGH_VAR_PROXY_DELAY]	= (8 * HZ) / 10,
+	[NEIGH_VAR_LOCKTIME] = 1 * HZ,
 };
-EXPORT_SYMBOL(arp_tbl);
 
 int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir)
 {
@@ -1291,13 +1272,8 @@ static int arp_proc_init(void);
 
 void __init arp_init(void)
 {
-	neigh_table_init(&init_net, &arp_tbl);
-
 	dev_add_pack(&arp_packet_type);
 	arp_proc_init();
-#ifdef CONFIG_SYSCTL
-	neigh_sysctl_register(NULL, &arp_tbl.parms, NULL);
-#endif
 	register_netdevice_notifier(&arp_netdev_notifier);
 }
 
@@ -1426,15 +1402,53 @@ static const struct seq_operations arp_seq_ops = {
 
 static int __net_init arp_net_init(struct net *net)
 {
+	struct neigh_table *arp_tbl;
+
+	arp_tbl = kzalloc(sizeof(*arp_tbl), GFP_KERNEL);
+	if (!arp_tbl)
+		return -ENOMEM;
+
 	if (!proc_create_net("arp", 0444, net->proc_net, &arp_seq_ops,
-			sizeof(struct neigh_seq_state)))
+			sizeof(struct neigh_seq_state))) {
+		kfree(arp_tbl);
 		return -ENOMEM;
+	}
+
+	arp_tbl->family		= AF_INET;
+	arp_tbl->key_len	= 4;
+	arp_tbl->protocol	= cpu_to_be16(ETH_P_IP);
+	arp_tbl->hash		= arp_hash;
+	arp_tbl->key_eq		= arp_key_eq;
+	arp_tbl->constructor	= arp_constructor;
+	arp_tbl->proxy_redo	= parp_redo;
+	arp_tbl->id		= "arp_cache";
+	arp_tbl->gc_interval	= 30 * HZ;
+	arp_tbl->gc_thresh1	= 128;
+	arp_tbl->gc_thresh2	= 512;
+	arp_tbl->gc_thresh3	= 1024;
+
+	arp_tbl->parms.tbl	= arp_tbl;
+	arp_tbl->parms.reachable_time = 30 * HZ;
+	memcpy(arp_tbl->parms.data, parms_data, sizeof(parms_data));
+
+	neigh_table_init(net, arp_tbl);
+
+#ifdef CONFIG_SYSCTL
+	neigh_sysctl_register(NULL, &arp_tbl->parms, NULL);
+#endif
 	return 0;
 }
 
 static void __net_exit arp_net_exit(struct net *net)
 {
+	struct neigh_table *arp_tbl = ipv4_neigh_table(net);
+
 	remove_proc_entry("arp", net->proc_net);
+#ifdef CONFIG_SYSCTL
+	neigh_sysctl_unregister(&arp_tbl->parms);
+#endif
+	neigh_table_clear(net, arp_tbl);
+	kfree(arp_tbl);
 }
 
 static struct pernet_operations arp_net_ops = {
-- 
2.11.0

^ permalink raw reply related

* [PATCH RFC/RFT net-next 13/17] net/neighbor: Convert internal functions away from neigh_tables
From: dsahern @ 2018-07-17 12:06 UTC (permalink / raw)
  To: netdev
  Cc: nikita.leshchenko, roopa, stephen, idosch, jiri, saeedm,
	alex.aring, linux-wpan, netfilter-devel, linux-kernel,
	David Ahern
In-Reply-To: <20180717120651.15748-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Convert uses of neigh_tables array to neigh_find_table. Maintain existing
family order using a new table_families array. A later patch removes the
neigh_tables array in favor of per-namespace accesses.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 net/core/neighbour.c | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index b60087d7c0bc..afb2ee985dd1 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -62,6 +62,19 @@ static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
 static const struct seq_operations neigh_stat_seq_ops;
 #endif
 
+/* used for table dumps to maintain the legacy order of
+ * ipv4, ipv6, decnet
+ */
+static int table_families[] = {
+	AF_INET,
+#if IS_ENABLED(CONFIG_IPV6)
+	AF_INET6,
+#endif
+#if IS_ENABLED(CONFIG_DECNET)
+	AF_DECnet,
+#endif
+};
+
 /*
    Neighbour hash table buckets are protected with rwlock tbl->lock.
 
@@ -2046,8 +2059,8 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh,
 
 	ndtmsg = nlmsg_data(nlh);
 
-	for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
-		tbl = neigh_tables[tidx];
+	for (tidx = 0; tidx < ARRAY_SIZE(table_families); tidx++) {
+		tbl = neigh_find_table(net, table_families[tidx]);
 		if (!tbl)
 			continue;
 		if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
@@ -2195,10 +2208,10 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
 
 	family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
 
-	for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
+	for (tidx = 0; tidx < ARRAY_SIZE(table_families); tidx++) {
 		struct neigh_parms *p;
 
-		tbl = neigh_tables[tidx];
+		tbl = neigh_find_table(net, table_families[tidx]);
 		if (!tbl)
 			continue;
 
@@ -2453,6 +2466,7 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
 
 static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
 {
+	struct net *net = sock_net(skb->sk);
 	struct neigh_table *tbl;
 	int t, family, s_t;
 	int proxy = 0;
@@ -2469,9 +2483,8 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
 
 	s_t = cb->args[0];
 
-	for (t = 0; t < NEIGH_NR_TABLES; t++) {
-		tbl = neigh_tables[t];
-
+	for (t = 0; t < ARRAY_SIZE(table_families); t++) {
+		tbl = neigh_find_table(net, table_families[t]);
 		if (!tbl)
 			continue;
 		if (t < s_t || (family && tbl->family != family))
-- 
2.11.0

^ permalink raw reply related

* [PATCH RFC/RFT net-next 12/17] net/neigh: Change neigh_xmit to take an address family
From: dsahern @ 2018-07-17 12:06 UTC (permalink / raw)
  To: netdev
  Cc: nikita.leshchenko, roopa, stephen, idosch, jiri, saeedm,
	alex.aring, linux-wpan, netfilter-devel, linux-kernel,
	David Ahern
In-Reply-To: <20180717120651.15748-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

The NEIGH_*_TABLE enum is really related to *how* the tables are
stored (in an array), a detail that does not need to leave the
neighbor code. Change the neigh_xmit API to take a proper address
family.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 include/net/neighbour.h          |  2 +-
 net/core/neighbour.c             | 10 +++++-----
 net/mpls/af_mpls.c               | 33 ++++++++++++---------------------
 net/mpls/mpls_iptunnel.c         |  6 ++----
 net/netfilter/nf_flow_table_ip.c |  4 ++--
 net/netfilter/nft_fwd_netdev.c   |  6 +++---
 6 files changed, 25 insertions(+), 36 deletions(-)

diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index b70afea05f86..e968db1b7742 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -365,7 +365,7 @@ void neigh_for_each(struct neigh_table *tbl,
 		    void (*cb)(struct neighbour *, void *), void *cookie);
 void __neigh_for_each_release(struct neigh_table *tbl,
 			      int (*cb)(struct neighbour *));
-int neigh_xmit(int fam, struct net_device *, const void *, struct sk_buff *);
+int neigh_xmit(u8 fam, struct net_device *, const void *, struct sk_buff *);
 void pneigh_for_each(struct neigh_table *tbl,
 		     void (*cb)(struct pneigh_entry *));
 
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 8bdaeb080ce4..b60087d7c0bc 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2548,15 +2548,16 @@ void __neigh_for_each_release(struct neigh_table *tbl,
 }
 EXPORT_SYMBOL(__neigh_for_each_release);
 
-int neigh_xmit(int index, struct net_device *dev,
+int neigh_xmit(u8 family, struct net_device *dev,
 	       const void *addr, struct sk_buff *skb)
 {
 	int err = -EAFNOSUPPORT;
-	if (likely(index < NEIGH_NR_TABLES)) {
+
+	if (likely(family != AF_UNSPEC)) {
 		struct neigh_table *tbl;
 		struct neighbour *neigh;
 
-		tbl = neigh_tables[index];
+		tbl = neigh_find_table(dev_net(dev), family);
 		if (!tbl)
 			goto out;
 		rcu_read_lock_bh();
@@ -2570,8 +2571,7 @@ int neigh_xmit(int index, struct net_device *dev,
 		}
 		err = neigh->output(neigh, skb);
 		rcu_read_unlock_bh();
-	}
-	else if (index == NEIGH_LINK_TABLE) {
+	} else {
 		err = dev_hard_header(skb, dev, ntohs(skb->protocol),
 				      addr, NULL, skb->len);
 		if (err < 0)
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index 7a4de6d618b1..a701dc055de2 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -34,7 +34,7 @@
  */
 #define MAX_MP_SELECT_LABELS 4
 
-#define MPLS_NEIGH_TABLE_UNSPEC (NEIGH_LINK_TABLE + 1)
+#define MPLS_NEIGH_TABLE_UNSPEC AF_UNSPEC
 
 static int zero = 0;
 static int one = 1;
@@ -453,7 +453,7 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
 
 	/* If via wasn't specified then send out using device address */
 	if (nh->nh_via_table == MPLS_NEIGH_TABLE_UNSPEC)
-		err = neigh_xmit(NEIGH_LINK_TABLE, out_dev,
+		err = neigh_xmit(AF_UNSPEC, out_dev,
 				 out_dev->dev_addr, skb);
 	else
 		err = neigh_xmit(nh->nh_via_table, out_dev,
@@ -651,14 +651,12 @@ static struct net_device *find_outdev(struct net *net,
 
 	if (!oif) {
 		switch (nh->nh_via_table) {
-		case NEIGH_ARP_TABLE:
+		case AF_INET:
 			dev = inet_fib_lookup_dev(net, mpls_nh_via(rt, nh));
 			break;
-		case NEIGH_ND_TABLE:
+		case AF_INET6:
 			dev = inet6_fib_lookup_dev(net, mpls_nh_via(rt, nh));
 			break;
-		case NEIGH_LINK_TABLE:
-			break;
 		}
 	} else {
 		dev = dev_get_by_index(net, oif);
@@ -694,7 +692,7 @@ static int mpls_nh_assign_dev(struct net *net, struct mpls_route *rt,
 	if (!mpls_dev_get(dev))
 		goto errout;
 
-	if ((nh->nh_via_table == NEIGH_LINK_TABLE) &&
+	if ((nh->nh_via_table == MPLS_NEIGH_TABLE_UNSPEC) &&
 	    (dev->addr_len != nh->nh_via_alen))
 		goto errout;
 
@@ -739,15 +737,15 @@ static int nla_get_via(const struct nlattr *nla, u8 *via_alen, u8 *via_table,
 	/* Validate the address family */
 	switch (via->rtvia_family) {
 	case AF_PACKET:
-		*via_table = NEIGH_LINK_TABLE;
+		*via_table = MPLS_NEIGH_TABLE_UNSPEC;
 		break;
 	case AF_INET:
-		*via_table = NEIGH_ARP_TABLE;
+		*via_table = AF_INET;
 		if (alen != 4)
 			goto errout;
 		break;
 	case AF_INET6:
-		*via_table = NEIGH_ND_TABLE;
+		*via_table = AF_INET6;
 		if (alen != 16)
 			goto errout;
 		break;
@@ -1596,23 +1594,16 @@ static struct notifier_block mpls_dev_notifier = {
 	.notifier_call = mpls_dev_notify,
 };
 
-static int nla_put_via(struct sk_buff *skb,
-		       u8 table, const void *addr, int alen)
+static int nla_put_via(struct sk_buff *skb, u8 family,
+		       const void *addr, int alen)
 {
-	static const int table_to_family[NEIGH_NR_TABLES + 1] = {
-		AF_INET, AF_INET6, AF_DECnet, AF_PACKET,
-	};
 	struct nlattr *nla;
 	struct rtvia *via;
-	int family = AF_UNSPEC;
 
 	nla = nla_reserve(skb, RTA_VIA, alen + 2);
 	if (!nla)
 		return -EMSGSIZE;
 
-	if (table <= NEIGH_NR_TABLES)
-		family = table_to_family[table];
-
 	via = nla_data(nla);
 	via->rtvia_family = family;
 	memcpy(via->rtvia_addr, addr, alen);
@@ -2295,7 +2286,7 @@ static int resize_platform_label_table(struct net *net, size_t limit)
 		rt0->rt_protocol = RTPROT_KERNEL;
 		rt0->rt_payload_type = MPT_IPV4;
 		rt0->rt_ttl_propagate = MPLS_TTL_PROP_DEFAULT;
-		rt0->rt_nh->nh_via_table = NEIGH_LINK_TABLE;
+		rt0->rt_nh->nh_via_table = MPLS_NEIGH_TABLE_UNSPEC;
 		rt0->rt_nh->nh_via_alen = lo->addr_len;
 		memcpy(__mpls_nh_via(rt0, rt0->rt_nh), lo->dev_addr,
 		       lo->addr_len);
@@ -2309,7 +2300,7 @@ static int resize_platform_label_table(struct net *net, size_t limit)
 		rt2->rt_protocol = RTPROT_KERNEL;
 		rt2->rt_payload_type = MPT_IPV6;
 		rt2->rt_ttl_propagate = MPLS_TTL_PROP_DEFAULT;
-		rt2->rt_nh->nh_via_table = NEIGH_LINK_TABLE;
+		rt2->rt_nh->nh_via_table = MPLS_NEIGH_TABLE_UNSPEC;
 		rt2->rt_nh->nh_via_alen = lo->addr_len;
 		memcpy(__mpls_nh_via(rt2, rt2->rt_nh), lo->dev_addr,
 		       lo->addr_len);
diff --git a/net/mpls/mpls_iptunnel.c b/net/mpls/mpls_iptunnel.c
index 6e558a419f60..6dc8370c290d 100644
--- a/net/mpls/mpls_iptunnel.c
+++ b/net/mpls/mpls_iptunnel.c
@@ -138,11 +138,9 @@ static int mpls_xmit(struct sk_buff *skb)
 	mpls_stats_inc_outucastpkts(out_dev, skb);
 
 	if (rt)
-		err = neigh_xmit(NEIGH_ARP_TABLE, out_dev, &rt->rt_gateway,
-				 skb);
+		err = neigh_xmit(AF_INET, out_dev, &rt->rt_gateway, skb);
 	else if (rt6)
-		err = neigh_xmit(NEIGH_ND_TABLE, out_dev, &rt6->rt6i_gateway,
-				 skb);
+		err = neigh_xmit(AF_INET6, out_dev, &rt6->rt6i_gateway, skb);
 	if (err)
 		net_dbg_ratelimited("%s: packet transmission failed: %d\n",
 				    __func__, err);
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index 15ed91309992..e56fcea9c7ba 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -265,7 +265,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
 	skb->dev = outdev;
 	nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr);
 	skb_dst_set_noref(skb, &rt->dst);
-	neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb);
+	neigh_xmit(AF_INET, outdev, &nexthop, skb);
 
 	return NF_STOLEN;
 }
@@ -482,7 +482,7 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
 	skb->dev = outdev;
 	nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6);
 	skb_dst_set_noref(skb, &rt->dst);
-	neigh_xmit(NEIGH_ND_TABLE, outdev, nexthop, skb);
+	neigh_xmit(AF_INET6, outdev, nexthop, skb);
 
 	return NF_STOLEN;
 }
diff --git a/net/netfilter/nft_fwd_netdev.c b/net/netfilter/nft_fwd_netdev.c
index 8abb9891cdf2..c361b0636a8c 100644
--- a/net/netfilter/nft_fwd_netdev.c
+++ b/net/netfilter/nft_fwd_netdev.c
@@ -84,7 +84,7 @@ static void nft_fwd_neigh_eval(const struct nft_expr *expr,
 	unsigned int verdict = NF_STOLEN;
 	struct sk_buff *skb = pkt->skb;
 	struct net_device *dev;
-	int neigh_table;
+	u8 neigh_table;
 
 	switch (priv->nfproto) {
 	case NFPROTO_IPV4: {
@@ -100,7 +100,7 @@ static void nft_fwd_neigh_eval(const struct nft_expr *expr,
 		}
 		iph = ip_hdr(skb);
 		ip_decrease_ttl(iph);
-		neigh_table = NEIGH_ARP_TABLE;
+		neigh_table = AF_INET;
 		break;
 		}
 	case NFPROTO_IPV6: {
@@ -116,7 +116,7 @@ static void nft_fwd_neigh_eval(const struct nft_expr *expr,
 		}
 		ip6h = ipv6_hdr(skb);
 		ip6h->hop_limit--;
-		neigh_table = NEIGH_ND_TABLE;
+		neigh_table = AF_INET6;
 		break;
 		}
 	default:
-- 
2.11.0

^ permalink raw reply related

* [PATCH RFC/RFT net-next 11/17] net: Change neigh_table_init and neigh_table_clear signature
From: dsahern @ 2018-07-17 12:06 UTC (permalink / raw)
  To: netdev
  Cc: nikita.leshchenko, roopa, stephen, idosch, jiri, saeedm,
	alex.aring, linux-wpan, netfilter-devel, linux-kernel,
	David Ahern
In-Reply-To: <20180717120651.15748-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Convert neigh_table_init and neigh_table_clear to use an address family
instead of the NEIGH_*_TABLE macros which are effectively the same thing
only setup as index into neigh_tables. The functions can do that mapping
internally.

Further, add net to the arg list for both and remove the dependence on
init_net.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 include/net/neighbour.h |  4 ++--
 net/core/neighbour.c    | 40 ++++++++++++++++++++++++++++++++--------
 net/decnet/dn_neigh.c   |  4 ++--
 net/ipv4/arp.c          |  2 +-
 net/ipv6/ndisc.c        |  4 ++--
 5 files changed, 39 insertions(+), 15 deletions(-)

diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 6cf9ce16eac8..b70afea05f86 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -304,8 +304,8 @@ static inline struct neighbour *__neigh_lookup_noref(struct neigh_table *tbl,
 	return ___neigh_lookup_noref(tbl, tbl->key_eq, tbl->hash, pkey, dev);
 }
 
-void neigh_table_init(int index, struct neigh_table *tbl);
-int neigh_table_clear(int index, struct neigh_table *tbl);
+void neigh_table_init(struct net *net, struct neigh_table *tbl);
+int neigh_table_clear(struct net *net, struct neigh_table *tbl);
 struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
 			       struct net_device *dev);
 struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 41841d8e4ea4..8bdaeb080ce4 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1548,14 +1548,15 @@ static struct lock_class_key neigh_table_proxy_queue_class;
 
 static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
 
-void neigh_table_init(int index, struct neigh_table *tbl)
+void neigh_table_init(struct net *net, struct neigh_table *tbl)
 {
 	unsigned long now = jiffies;
+	u8 family = tbl->family;
 	unsigned long phsize;
 
 	INIT_LIST_HEAD(&tbl->parms_list);
 	list_add(&tbl->parms.list, &tbl->parms_list);
-	write_pnet(&tbl->parms.net, &init_net);
+	write_pnet(&tbl->parms.net, net);
 	refcount_set(&tbl->parms.refcnt, 1);
 	tbl->parms.reachable_time =
 			  neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
@@ -1565,8 +1566,8 @@ void neigh_table_init(int index, struct neigh_table *tbl)
 		panic("cannot create neighbour cache statistics");
 
 #ifdef CONFIG_PROC_FS
-	if (!proc_create_seq_data(tbl->id, 0, init_net.proc_net_stat,
-			      &neigh_stat_seq_ops, tbl))
+	if (!proc_create_seq_data(tbl->id, 0, net->proc_net_stat,
+				  &neigh_stat_seq_ops, tbl))
 		panic("cannot create neighbour proc dir entry");
 #endif
 
@@ -1595,13 +1596,36 @@ void neigh_table_init(int index, struct neigh_table *tbl)
 	tbl->last_flush = now;
 	tbl->last_rand	= now + tbl->parms.reachable_time * 20;
 
-	neigh_tables[index] = tbl;
+	switch (family) {
+	case AF_INET:
+		neigh_tables[NEIGH_ARP_TABLE] = tbl;
+		break;
+	case AF_INET6:
+		neigh_tables[NEIGH_ND_TABLE] = tbl;
+		break;
+	case AF_DECnet:
+		neigh_tables[NEIGH_DN_TABLE] = tbl;
+		break;
+	}
 }
 EXPORT_SYMBOL(neigh_table_init);
 
-int neigh_table_clear(int index, struct neigh_table *tbl)
+int neigh_table_clear(struct net *net, struct neigh_table *tbl)
 {
-	neigh_tables[index] = NULL;
+	u8 family = tbl->family;
+
+	switch (family) {
+	case AF_INET:
+		neigh_tables[NEIGH_ARP_TABLE] = NULL;
+		break;
+	case AF_INET6:
+		neigh_tables[NEIGH_ND_TABLE] = NULL;
+		break;
+	case AF_DECnet:
+		neigh_tables[NEIGH_DN_TABLE] = NULL;
+		break;
+	}
+
 	/* It is not clean... Fix it to unload IPv6 module safely */
 	cancel_delayed_work_sync(&tbl->gc_work);
 	del_timer_sync(&tbl->proxy_timer);
@@ -1617,7 +1641,7 @@ int neigh_table_clear(int index, struct neigh_table *tbl)
 	kfree(tbl->phash_buckets);
 	tbl->phash_buckets = NULL;
 
-	remove_proc_entry(tbl->id, init_net.proc_net_stat);
+	remove_proc_entry(tbl->id, net->proc_net_stat);
 
 	free_percpu(tbl->stats);
 	tbl->stats = NULL;
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 74112777beb0..6d5078ddffac 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -593,7 +593,7 @@ static const struct seq_operations dn_neigh_seq_ops = {
 
 void __init dn_neigh_init(void)
 {
-	neigh_table_init(NEIGH_DN_TABLE, &dn_neigh_table);
+	neigh_table_init(&init_net, &dn_neigh_table);
 	proc_create_net("decnet_neigh", 0444, init_net.proc_net,
 			&dn_neigh_seq_ops, sizeof(struct neigh_seq_state));
 }
@@ -601,5 +601,5 @@ void __init dn_neigh_init(void)
 void __exit dn_neigh_cleanup(void)
 {
 	remove_proc_entry("decnet_neigh", init_net.proc_net);
-	neigh_table_clear(NEIGH_DN_TABLE, &dn_neigh_table);
+	neigh_table_clear(&init_net, &dn_neigh_table);
 }
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 7b27faefa01b..707b40f76852 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -1291,7 +1291,7 @@ static int arp_proc_init(void);
 
 void __init arp_init(void)
 {
-	neigh_table_init(NEIGH_ARP_TABLE, &arp_tbl);
+	neigh_table_init(&init_net, &arp_tbl);
 
 	dev_add_pack(&arp_packet_type);
 	arp_proc_init();
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 5103d8641b04..6105530fe865 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1908,7 +1908,7 @@ int __init ndisc_init(void)
 	/*
 	 * Initialize the neighbour table
 	 */
-	neigh_table_init(NEIGH_ND_TABLE, &nd_tbl);
+	neigh_table_init(&init_net, &nd_tbl);
 
 #ifdef CONFIG_SYSCTL
 	err = neigh_sysctl_register(NULL, &nd_tbl.parms,
@@ -1941,6 +1941,6 @@ void ndisc_cleanup(void)
 #ifdef CONFIG_SYSCTL
 	neigh_sysctl_unregister(&nd_tbl.parms);
 #endif
-	neigh_table_clear(NEIGH_ND_TABLE, &nd_tbl);
+	neigh_table_clear(&init_net, &nd_tbl);
 	unregister_pernet_subsys(&ndisc_net_ops);
 }
-- 
2.11.0

^ permalink raw reply related

* [PATCH RFC/RFT net-next 09/17] net: Remove arp_tbl and nd_tbl from headers
From: dsahern @ 2018-07-17 12:06 UTC (permalink / raw)
  To: netdev
  Cc: nikita.leshchenko, roopa, stephen, idosch, jiri, saeedm,
	alex.aring, linux-wpan, netfilter-devel, linux-kernel,
	David Ahern
In-Reply-To: <20180717120651.15748-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

No more users at this point.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 include/net/arp.h   | 3 ---
 include/net/ndisc.h | 2 --
 2 files changed, 5 deletions(-)

diff --git a/include/net/arp.h b/include/net/arp.h
index 7b503bedd9fb..fae3561db10b 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -7,9 +7,6 @@
 #include <linux/hash.h>
 #include <net/neighbour.h>
 
-
-extern struct neigh_table arp_tbl;
-
 static inline struct neigh_table *ipv4_neigh_table(struct net *net)
 {
 	return neigh_find_table(net, AF_INET);
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 078951ac54fd..6fc58a61acdd 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -72,8 +72,6 @@ struct net_proto_family;
 struct sk_buff;
 struct prefix_info;
 
-extern struct neigh_table nd_tbl;
-
 struct nd_msg {
         struct icmp6hdr	icmph;
         struct in6_addr	target;
-- 
2.11.0

^ permalink raw reply related

* [PATCH RFC/RFT net-next 08/17] net: Remove nd_tbl from ipv6 stub
From: dsahern @ 2018-07-17 12:06 UTC (permalink / raw)
  To: netdev
  Cc: nikita.leshchenko, roopa, stephen, idosch, jiri, saeedm,
	alex.aring, linux-wpan, netfilter-devel, linux-kernel,
	David Ahern
In-Reply-To: <20180717120651.15748-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Fixup last 2 users to nd_tbl entry of the stub and remove it.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 include/net/addrconf.h       | 1 -
 net/bridge/br_arp_nd_proxy.c | 2 +-
 net/core/filter.c            | 3 +--
 net/ipv6/af_inet6.c          | 1 -
 4 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 5f43f7a70fe6..3108e9d6a066 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -256,7 +256,6 @@ struct ipv6_stub {
 	void (*ndisc_send_na)(struct net_device *dev, const struct in6_addr *daddr,
 			      const struct in6_addr *solicited_addr,
 			      bool router, bool solicited, bool override, bool inc_opt);
-	struct neigh_table *nd_tbl;
 };
 extern const struct ipv6_stub *ipv6_stub __read_mostly;
 
diff --git a/net/bridge/br_arp_nd_proxy.c b/net/bridge/br_arp_nd_proxy.c
index 29a1e25fc169..9dd2a5dd721b 100644
--- a/net/bridge/br_arp_nd_proxy.c
+++ b/net/bridge/br_arp_nd_proxy.c
@@ -433,7 +433,7 @@ void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br,
 		return;
 	}
 
-	n = neigh_lookup(ipv6_stub->nd_tbl, &msg->target, vlandev);
+	n = ipv6_neigh_lookup(vlandev, &msg->target);
 	if (n) {
 		struct net_bridge_fdb_entry *f;
 
diff --git a/net/core/filter.c b/net/core/filter.c
index b9ec916f4e3a..11d4af3886be 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -4290,8 +4290,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
 	 * not needed here. Can not use __ipv6_neigh_lookup_noref here
 	 * because we need to get nd_tbl via the stub
 	 */
-	neigh = ___neigh_lookup_noref(ipv6_stub->nd_tbl, neigh_key_eq128,
-				      ndisc_hashfn, dst, dev);
+	neigh = ___ipv6_neigh_lookup_noref(dev, dst);
 	if (!neigh)
 		return BPF_FIB_LKUP_RET_NO_NEIGH;
 
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index c9535354149f..9e7d0f3d4edb 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -898,7 +898,6 @@ static const struct ipv6_stub ipv6_stub_impl = {
 	.ip6_mtu_from_fib6 = ip6_mtu_from_fib6,
 	.udpv6_encap_enable = udpv6_encap_enable,
 	.ndisc_send_na = ndisc_send_na,
-	.nd_tbl	= &nd_tbl,
 };
 
 static const struct ipv6_bpf_stub ipv6_bpf_stub_impl = {
-- 
2.11.0

^ permalink raw reply related

* [PATCH RFC/RFT net-next 07/17] drivers/net: remove open coding of neighbor tables
From: dsahern @ 2018-07-17 12:06 UTC (permalink / raw)
  To: netdev
  Cc: nikita.leshchenko, roopa, stephen, idosch, jiri, saeedm,
	alex.aring, linux-wpan, netfilter-devel, linux-kernel,
	David Ahern
In-Reply-To: <20180717120651.15748-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Remove open use of arp_tbl and nd_tbl in favor of the new
ipv{4,6}_neigh_table helpers. Since the existence of the IPv6 table
is managed by the core networking, the IS_ENABLED checks for IPv6
can be removed in favor of "is the table non-NULL".

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 drivers/infiniband/ulp/ipoib/ipoib_main.c          | 14 ++++++---
 drivers/net/ethernet/mellanox/mlx5/core/en_rep.c   | 35 +++++++++++-----------
 drivers/net/ethernet/mellanox/mlx5/core/en_tc.c    | 11 ++-----
 .../net/ethernet/mellanox/mlxsw/spectrum_router.c  | 27 ++++++++---------
 .../net/ethernet/mellanox/mlxsw/spectrum_span.c    |  8 +++--
 .../ethernet/netronome/nfp/flower/tunnel_conf.c    |  2 +-
 drivers/net/ethernet/rocker/rocker_main.c          |  4 +--
 drivers/net/ethernet/rocker/rocker_ofdpa.c         |  2 +-
 drivers/net/vrf.c                                  |  4 +--
 drivers/net/vxlan.c                                | 10 +++----
 net/atm/clip.c                                     | 14 +++++----
 net/ieee802154/6lowpan/tx.c                        |  2 +-
 12 files changed, 70 insertions(+), 63 deletions(-)

diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 26cde95bc0f3..4f798a7b9cc0 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1298,6 +1298,8 @@ struct ipoib_neigh *ipoib_neigh_get(struct net_device *dev, u8 *daddr)
 
 static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv)
 {
+	struct net *net = dev_net(priv->dev);
+	struct neigh_table *arp_tbl = ipv4_neigh_table(net);
 	struct ipoib_neigh_table *ntbl = &priv->ntbl;
 	struct ipoib_neigh_hash *htbl;
 	unsigned long neigh_obsolete;
@@ -1318,7 +1320,7 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv)
 		goto out_unlock;
 
 	/* neigh is obsolete if it was idle for two GC periods */
-	dt = 2 * arp_tbl.gc_interval;
+	dt = 2 * arp_tbl->gc_interval;
 	neigh_obsolete = jiffies - dt;
 	/* handle possible race condition */
 	if (test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags))
@@ -1357,12 +1359,14 @@ static void ipoib_reap_neigh(struct work_struct *work)
 {
 	struct ipoib_dev_priv *priv =
 		container_of(work, struct ipoib_dev_priv, neigh_reap_task.work);
+	struct net *net = dev_net(priv->dev);
+	struct neigh_table *arp_tbl = ipv4_neigh_table(net);
 
 	__ipoib_reap_neigh(priv);
 
 	if (!test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags))
 		queue_delayed_work(priv->wq, &priv->neigh_reap_task,
-				   arp_tbl.gc_interval);
+				   arp_tbl->gc_interval);
 }
 
 
@@ -1514,6 +1518,8 @@ void ipoib_neigh_free(struct ipoib_neigh *neigh)
 
 static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv)
 {
+	struct net *net = dev_net(priv->dev);
+	struct neigh_table *arp_tbl = ipv4_neigh_table(net);
 	struct ipoib_neigh_table *ntbl = &priv->ntbl;
 	struct ipoib_neigh_hash *htbl;
 	struct ipoib_neigh __rcu **buckets;
@@ -1525,7 +1531,7 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv)
 	if (!htbl)
 		return -ENOMEM;
 	set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags);
-	size = roundup_pow_of_two(arp_tbl.gc_thresh3);
+	size = roundup_pow_of_two(arp_tbl->gc_thresh3);
 	buckets = kcalloc(size, sizeof(*buckets), GFP_KERNEL);
 	if (!buckets) {
 		kfree(htbl);
@@ -1541,7 +1547,7 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv)
 	/* start garbage collection */
 	clear_bit(IPOIB_STOP_NEIGH_GC, &priv->flags);
 	queue_delayed_work(priv->wq, &priv->neigh_reap_task,
-			   arp_tbl.gc_interval);
+			   arp_tbl->gc_interval);
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 8e3c5b4b90ab..a2283a4b3a17 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -309,17 +309,19 @@ void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv)
 
 static void mlx5e_rep_neigh_update_init_interval(struct mlx5e_rep_priv *rpriv)
 {
-#if IS_ENABLED(CONFIG_IPV6)
-	unsigned long ipv6_interval = NEIGH_VAR(&nd_tbl.parms,
+	struct net_device *netdev = rpriv->netdev;
+	struct net *net = dev_net(netdev);
+	struct neigh_table *arp_table = ipv4_neigh_table(net);
+	struct neigh_table *nd_table = ipv6_neigh_table(net);
+
+	unsigned long ipv4_interval = NEIGH_VAR(&arp_table->parms,
 						DELAY_PROBE_TIME);
-#else
 	unsigned long ipv6_interval = ~0UL;
-#endif
-	unsigned long ipv4_interval = NEIGH_VAR(&arp_tbl.parms,
-						DELAY_PROBE_TIME);
-	struct net_device *netdev = rpriv->netdev;
 	struct mlx5e_priv *priv = netdev_priv(netdev);
 
+	if (nd_table)
+		ipv6_interval = NEIGH_VAR(&nd_table->parms, DELAY_PROBE_TIME);
+
 	rpriv->neigh_update.min_interval = min_t(unsigned long, ipv6_interval, ipv4_interval);
 	mlx5_fc_update_sampling_interval(priv->mdev, rpriv->neigh_update.min_interval);
 }
@@ -437,19 +439,22 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
 	struct net_device *netdev = rpriv->netdev;
 	struct mlx5e_priv *priv = netdev_priv(netdev);
 	struct mlx5e_neigh_hash_entry *nhe = NULL;
+	struct net *net = dev_net(netdev);
 	struct mlx5e_neigh m_neigh = {};
+	struct neigh_table *arp_table;
+	struct neigh_table *nd_table;
 	struct neigh_parms *p;
 	struct neighbour *n;
 	bool found = false;
 
+	arp_table = ipv4_neigh_table(net);
+	nd_table = ipv6_neigh_table(net);
+
 	switch (event) {
 	case NETEVENT_NEIGH_UPDATE:
 		n = ptr;
-#if IS_ENABLED(CONFIG_IPV6)
-		if (n->tbl != &nd_tbl && n->tbl != &arp_tbl)
-#else
-		if (n->tbl != &arp_tbl)
-#endif
+
+		if (n->tbl != nd_table && n->tbl != arp_table)
 			return NOTIFY_DONE;
 
 		m_neigh.dev = n->dev;
@@ -493,11 +498,7 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
 		 * changes in the default table, we only care about changes
 		 * done per device delay prob time parameter.
 		 */
-#if IS_ENABLED(CONFIG_IPV6)
-		if (!p->dev || (p->tbl != &nd_tbl && p->tbl != &arp_tbl))
-#else
-		if (!p->dev || p->tbl != &arp_tbl)
-#endif
+		if (!p->dev || (p->tbl != nd_table && p->tbl != arp_table))
 			return NOTIFY_DONE;
 
 		/* We are in atomic context and can't take RTNL mutex,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index 0edf4751a8ba..f4f2bace496a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -45,7 +45,7 @@
 #include <net/tc_act/tc_pedit.h>
 #include <net/tc_act/tc_csum.h>
 #include <net/vxlan.h>
-#include <net/arp.h>
+#include <net/neighbour.h>
 #include "en.h"
 #include "en_rep.h"
 #include "en_tc.h"
@@ -999,13 +999,8 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe)
 	bool neigh_used = false;
 	struct neighbour *n;
 
-	if (m_neigh->family == AF_INET)
-		tbl = &arp_tbl;
-#if IS_ENABLED(CONFIG_IPV6)
-	else if (m_neigh->family == AF_INET6)
-		tbl = &nd_tbl;
-#endif
-	else
+	tbl = neigh_find_table(dev_net(m_neigh->dev), m_neigh->family);
+	if (!tbl)
 		return;
 
 	list_for_each_entry(e, &nhe->encap_list, encap_list) {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index e51c8dc52f37..c5e6b2972d0f 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -2019,15 +2019,15 @@ mlxsw_sp_neigh_entry_lookup(struct mlxsw_sp *mlxsw_sp, struct neighbour *n)
 static void
 mlxsw_sp_router_neighs_update_interval_init(struct mlxsw_sp *mlxsw_sp)
 {
-	unsigned long interval;
+	/* mlxsw only works with init_net at the moment */
+	struct neigh_table *arp_table = ipv4_neigh_table(&init_net);
+	struct neigh_table *nd_table = ipv6_neigh_table(&init_net);
+	unsigned long interval = NEIGH_VAR(&arp_table->parms, DELAY_PROBE_TIME);
+
+	if (nd_table)
+		interval = min_t(unsigned long, interval,
+				 NEIGH_VAR(&nd_table->parms, DELAY_PROBE_TIME));
 
-#if IS_ENABLED(CONFIG_IPV6)
-	interval = min_t(unsigned long,
-			 NEIGH_VAR(&arp_tbl.parms, DELAY_PROBE_TIME),
-			 NEIGH_VAR(&nd_tbl.parms, DELAY_PROBE_TIME));
-#else
-	interval = NEIGH_VAR(&arp_tbl.parms, DELAY_PROBE_TIME);
-#endif
 	mlxsw_sp->router->neighs_update.interval = jiffies_to_msecs(interval);
 }
 
@@ -2050,7 +2050,7 @@ static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp *mlxsw_sp,
 
 	dipn = htonl(dip);
 	dev = mlxsw_sp->router->rifs[rif]->dev;
-	n = neigh_lookup(&arp_tbl, &dipn, dev);
+	n = ipv4_neigh_lookup(dev, &dipn);
 	if (!n)
 		return;
 
@@ -2064,6 +2064,7 @@ static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp,
 						   char *rauhtd_pl,
 						   int rec_index)
 {
+	struct neigh_table *nd_table = ipv6_neigh_table(&init_net);
 	struct net_device *dev;
 	struct neighbour *n;
 	struct in6_addr dip;
@@ -2078,7 +2079,7 @@ static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp,
 	}
 
 	dev = mlxsw_sp->router->rifs[rif]->dev;
-	n = neigh_lookup(&nd_tbl, &dip, dev);
+	n = neigh_lookup(nd_table, &dip, dev);
 	if (!n)
 		return;
 
@@ -3721,7 +3722,7 @@ mlxsw_sp_nexthop4_group_create(struct mlxsw_sp *mlxsw_sp, struct fib_info *fi)
 		return ERR_PTR(-ENOMEM);
 	nh_grp->priv = fi;
 	INIT_LIST_HEAD(&nh_grp->fib_list);
-	nh_grp->neigh_tbl = &arp_tbl;
+	nh_grp->neigh_tbl = ipv4_neigh_table(&init_net);
 
 	nh_grp->gateway = mlxsw_sp_fi_is_gateway(mlxsw_sp, fi);
 	nh_grp->count = fi->fib_nhs;
@@ -4919,9 +4920,7 @@ mlxsw_sp_nexthop6_group_create(struct mlxsw_sp *mlxsw_sp,
 	if (!nh_grp)
 		return ERR_PTR(-ENOMEM);
 	INIT_LIST_HEAD(&nh_grp->fib_list);
-#if IS_ENABLED(CONFIG_IPV6)
-	nh_grp->neigh_tbl = &nd_tbl;
-#endif
+	nh_grp->neigh_tbl = ipv6_neigh_table(&init_net);
 	mlxsw_sp_rt6 = list_first_entry(&fib6_entry->rt6_list,
 					struct mlxsw_sp_rt6, list);
 	nh_grp->gateway = mlxsw_sp_rt6_is_gateway(mlxsw_sp, mlxsw_sp_rt6->rt);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
index e42d640cddab..8d21a340cf47 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -365,6 +365,7 @@ mlxsw_sp_span_entry_gretap4_parms(const struct net_device *to_dev,
 	bool inherit_ttl = !tparm.iph.ttl;
 	union mlxsw_sp_l3addr gw = daddr;
 	struct net_device *l3edev;
+	struct neigh_table *tbl;
 
 	if (!(to_dev->flags & IFF_UP) ||
 	    /* Reject tunnels with GRE keys, checksums, etc. */
@@ -376,9 +377,10 @@ mlxsw_sp_span_entry_gretap4_parms(const struct net_device *to_dev,
 		return mlxsw_sp_span_entry_unoffloadable(sparmsp);
 
 	l3edev = mlxsw_sp_span_gretap4_route(to_dev, &saddr.addr4, &gw.addr4);
+	tbl = ipv4_neigh_table(dev_net(l3edev));
 	return mlxsw_sp_span_entry_tunnel_parms_common(l3edev, saddr, daddr, gw,
 						       tparm.iph.ttl,
-						       &arp_tbl, sparmsp);
+						       tbl, sparmsp);
 }
 
 static int
@@ -466,6 +468,7 @@ mlxsw_sp_span_entry_gretap6_parms(const struct net_device *to_dev,
 	bool inherit_ttl = !tparm.hop_limit;
 	union mlxsw_sp_l3addr gw = daddr;
 	struct net_device *l3edev;
+	struct neigh_table *tbl;
 
 	if (!(to_dev->flags & IFF_UP) ||
 	    /* Reject tunnels with GRE keys, checksums, etc. */
@@ -477,9 +480,10 @@ mlxsw_sp_span_entry_gretap6_parms(const struct net_device *to_dev,
 		return mlxsw_sp_span_entry_unoffloadable(sparmsp);
 
 	l3edev = mlxsw_sp_span_gretap6_route(to_dev, &saddr.addr6, &gw.addr6);
+	tbl = ipv6_neigh_table(dev_net(l3edev));
 	return mlxsw_sp_span_entry_tunnel_parms_common(l3edev, saddr, daddr, gw,
 						       tparm.hop_limit,
-						       &nd_tbl, sparmsp);
+						       tbl, sparmsp);
 }
 
 static int
diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
index 78afe75129ab..2f52cbd01d31 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
@@ -201,7 +201,7 @@ void nfp_tunnel_keep_alive(struct nfp_app *app, struct sk_buff *skb)
 		if (!netdev)
 			continue;
 
-		n = neigh_lookup(&arp_tbl, &ipv4_addr, netdev);
+		n = ipv4_neigh_lookup(netdev, &ipv4_addr);
 		if (!n)
 			continue;
 
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index aeafdb9ac015..6791941b3472 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -3098,9 +3098,9 @@ static int rocker_netevent_event(struct notifier_block *unused,
 
 	switch (event) {
 	case NETEVENT_NEIGH_UPDATE:
-		if (n->tbl != &arp_tbl)
-			return NOTIFY_DONE;
 		dev = n->dev;
+		if (n->tbl != ipv4_neigh_table(dev_net(dev)))
+			return NOTIFY_DONE;
 		if (!rocker_port_dev_check(dev))
 			return NOTIFY_DONE;
 		rocker_port = netdev_priv(dev);
diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c
index 6473cc68c2d5..5745d675aaeb 100644
--- a/drivers/net/ethernet/rocker/rocker_ofdpa.c
+++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c
@@ -1356,7 +1356,7 @@ static int ofdpa_port_ipv4_resolve(struct ofdpa_port *ofdpa_port,
 	int err = 0;
 
 	if (!n) {
-		n = neigh_create(&arp_tbl, &ip_addr, dev);
+		n = ipv4_neigh_create(dev, &ip_addr);
 		if (IS_ERR(n))
 			return PTR_ERR(n);
 	}
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index f93547f257fb..304f452f619a 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -367,7 +367,7 @@ static int vrf_finish_output6(struct net *net, struct sock *sk,
 	nexthop = rt6_nexthop((struct rt6_info *)dst, &ipv6_hdr(skb)->daddr);
 	neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop);
 	if (unlikely(!neigh))
-		neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false);
+		neigh = ipv6_neigh_create(dst->dev, nexthop, false);
 	if (!IS_ERR(neigh)) {
 		sock_confirm_neigh(skb, neigh);
 		ret = neigh_output(neigh, skb);
@@ -575,7 +575,7 @@ static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *s
 	nexthop = (__force u32)rt_nexthop(rt, ip_hdr(skb)->daddr);
 	neigh = __ipv4_neigh_lookup_noref(dev, nexthop);
 	if (unlikely(!neigh))
-		neigh = __neigh_create(&arp_tbl, &nexthop, dev, false);
+		neigh = ipv4_neigh_create_noref(dev, &nexthop);
 	if (!IS_ERR(neigh)) {
 		sock_confirm_neigh(skb, neigh);
 		ret = neigh_output(neigh, skb);
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index ababba37d735..2ef9df11eaff 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1520,8 +1520,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
 	    ipv4_is_multicast(tip))
 		goto out;
 
-	n = neigh_lookup(&arp_tbl, &tip, dev);
-
+	n = ipv4_neigh_lookup(dev, &tip);
 	if (n) {
 		struct vxlan_fdb *f;
 		struct sk_buff	*reply;
@@ -1675,8 +1674,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
 	    ipv6_addr_is_multicast(&msg->target))
 		goto out;
 
-	n = neigh_lookup(ipv6_stub->nd_tbl, &msg->target, dev);
-
+	n = ipv6_neigh_lookup(dev, &msg->target);
 	if (n) {
 		struct vxlan_fdb *f;
 		struct sk_buff *reply;
@@ -1736,7 +1734,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
 		if (!pskb_may_pull(skb, sizeof(struct iphdr)))
 			return false;
 		pip = ip_hdr(skb);
-		n = neigh_lookup(&arp_tbl, &pip->daddr, dev);
+		n = ipv4_neigh_lookup(dev, &pip->daddr);
 		if (!n && (vxlan->cfg.flags & VXLAN_F_L3MISS)) {
 			union vxlan_addr ipa = {
 				.sin.sin_addr.s_addr = pip->daddr,
@@ -1757,7 +1755,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
 		if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
 			return false;
 		pip6 = ipv6_hdr(skb);
-		n = neigh_lookup(ipv6_stub->nd_tbl, &pip6->daddr, dev);
+		n = ipv6_neigh_lookup(dev, &pip6->daddr);
 		if (!n && (vxlan->cfg.flags & VXLAN_F_L3MISS)) {
 			union vxlan_addr ipa = {
 				.sin6.sin6_addr = pip6->daddr,
diff --git a/net/atm/clip.c b/net/atm/clip.c
index d795b9c5aea4..a85410000abc 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -155,10 +155,12 @@ static int neigh_check_cb(struct neighbour *n)
 
 static void idle_timer_check(struct timer_list *unused)
 {
-	write_lock(&arp_tbl.lock);
-	__neigh_for_each_release(&arp_tbl, neigh_check_cb);
+	struct neigh_table *tbl = ipv4_neigh_table(&init_net);
+
+	write_lock(&tbl->lock);
+	__neigh_for_each_release(tbl, neigh_check_cb);
 	mod_timer(&idle_timer, jiffies + CLIP_CHECK_INTERVAL * HZ);
-	write_unlock(&arp_tbl.lock);
+	write_unlock(&tbl->lock);
 }
 
 static int clip_arp_rcv(struct sk_buff *skb)
@@ -465,7 +467,8 @@ static int clip_setentry(struct atm_vcc *vcc, __be32 ip)
 	rt = ip_route_output(&init_net, ip, 0, 1, 0);
 	if (IS_ERR(rt))
 		return PTR_ERR(rt);
-	neigh = __neigh_lookup(&arp_tbl, &ip, rt->dst.dev, 1);
+	neigh = __neigh_lookup(ipv4_neigh_table(&init_net), &ip,
+			       rt->dst.dev, 1);
 	ip_rt_put(rt);
 	if (!neigh)
 		return -ENOMEM;
@@ -836,7 +839,8 @@ static void *clip_seq_start(struct seq_file *seq, loff_t * pos)
 {
 	struct clip_seq_state *state = seq->private;
 	state->ns.neigh_sub_iter = clip_seq_sub_iter;
-	return neigh_seq_start(seq, pos, &arp_tbl, NEIGH_SEQ_NEIGH_ONLY);
+	return neigh_seq_start(seq, pos, ipv4_neigh_table(&init_net),
+			       NEIGH_SEQ_NEIGH_ONLY);
 }
 
 static int clip_seq_show(struct seq_file *seq, void *v)
diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c
index e6ff5128e61a..d472b08fbf25 100644
--- a/net/ieee802154/6lowpan/tx.c
+++ b/net/ieee802154/6lowpan/tx.c
@@ -64,7 +64,7 @@ int lowpan_header_create(struct sk_buff *skb, struct net_device *ldev,
 	} else {
 		__le16 short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC);
 
-		n = neigh_lookup(&nd_tbl, &hdr->daddr, ldev);
+		n = ipv6_neigh_lookup(ldev, &hdr->daddr);
 		if (n) {
 			llneigh = lowpan_802154_neigh(neighbour_priv(n));
 			read_lock_bh(&n->lock);
-- 
2.11.0

^ permalink raw reply related

* [PATCH RFC/RFT net-next 06/17] net/ipv6: Remove open coded use of neighbor table
From: dsahern @ 2018-07-17 12:06 UTC (permalink / raw)
  To: netdev
  Cc: nikita.leshchenko, roopa, stephen, idosch, jiri, saeedm,
	alex.aring, linux-wpan, netfilter-devel, linux-kernel,
	David Ahern
In-Reply-To: <20180717120651.15748-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Convert existing uses for nd_tbl to the helpers introduced in the previous
patch.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 net/ipv6/addrconf.c   | 16 ++++++++++------
 net/ipv6/ip6_output.c |  4 ++--
 net/ipv6/ndisc.c      | 41 +++++++++++++++++++++++------------------
 net/ipv6/route.c      | 12 +++++++-----
 4 files changed, 42 insertions(+), 31 deletions(-)

diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 1659a6b3cf42..104bf4c6c1f9 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -365,6 +365,8 @@ static int snmp6_alloc_dev(struct inet6_dev *idev)
 
 static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
 {
+	struct net *net = dev_net(dev);
+	struct neigh_table *neigh_tbl = ipv6_neigh_table(net);
 	struct inet6_dev *ndev;
 	int err = -ENOMEM;
 
@@ -381,13 +383,13 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
 	ndev->dev = dev;
 	INIT_LIST_HEAD(&ndev->addr_list);
 	timer_setup(&ndev->rs_timer, addrconf_rs_timer, 0);
-	memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf));
+	memcpy(&ndev->cnf, net->ipv6.devconf_dflt, sizeof(ndev->cnf));
 
 	if (ndev->cnf.stable_secret.initialized)
 		ndev->cnf.addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
 
 	ndev->cnf.mtu6 = dev->mtu;
-	ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl);
+	ndev->nd_parms = neigh_parms_alloc(dev, neigh_tbl);
 	if (!ndev->nd_parms) {
 		kfree(ndev);
 		return ERR_PTR(err);
@@ -400,7 +402,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
 	if (snmp6_alloc_dev(ndev) < 0) {
 		netdev_dbg(dev, "%s: cannot allocate memory for statistics\n",
 			   __func__);
-		neigh_parms_release(&nd_tbl, ndev->nd_parms);
+		neigh_parms_release(neigh_tbl, ndev->nd_parms);
 		dev_put(dev);
 		kfree(ndev);
 		return ERR_PTR(err);
@@ -465,7 +467,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
 	return ndev;
 
 err_release:
-	neigh_parms_release(&nd_tbl, ndev->nd_parms);
+	neigh_parms_release(ipv6_neigh_table(net), ndev->nd_parms);
 	ndev->dead = 1;
 	in6_dev_finish_destroy(ndev);
 	return ERR_PTR(err);
@@ -3787,9 +3789,11 @@ static int addrconf_ifdown(struct net_device *dev, int how)
 
 	/* Last: Shot the device (if unregistered) */
 	if (how) {
+		struct neigh_table *tbl = ipv6_neigh_table(net);
+
 		addrconf_sysctl_unregister(idev);
-		neigh_parms_release(&nd_tbl, idev->nd_parms);
-		neigh_ifdown(&nd_tbl, dev);
+		neigh_parms_release(tbl, idev->nd_parms);
+		neigh_ifdown(tbl, dev);
 		in6_dev_put(idev);
 	}
 	return 0;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 8047fd41ba88..05e11f71da49 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -114,7 +114,7 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
 	nexthop = rt6_nexthop((struct rt6_info *)dst, &ipv6_hdr(skb)->daddr);
 	neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop);
 	if (unlikely(!neigh))
-		neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false);
+		neigh = ipv6_neigh_create(dst->dev, nexthop, false);
 	if (!IS_ERR(neigh)) {
 		sock_confirm_neigh(skb, neigh);
 		ret = neigh_output(neigh, skb);
@@ -462,7 +462,7 @@ int ip6_forward(struct sk_buff *skb)
 
 	/* XXX: idev->cnf.proxy_ndp? */
 	if (net->ipv6.devconf_all->proxy_ndp &&
-	    pneigh_lookup(&nd_tbl, net, &hdr->daddr, skb->dev, 0)) {
+	    ipv6_pneigh_lookup(net, &hdr->daddr, skb->dev, 0)) {
 		int proxied = ip6_forward_proxy_check(skb);
 		if (proxied > 0)
 			return ip6_input(skb);
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index e640d2f3c55c..14b925f36099 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -729,14 +729,16 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
 static int pndisc_is_router(const void *pkey,
 			    struct net_device *dev)
 {
+	struct net *net = dev_net(dev);
+	struct neigh_table *neigh_tbl = ipv6_neigh_table(net);
 	struct pneigh_entry *n;
 	int ret = -1;
 
-	read_lock_bh(&nd_tbl.lock);
-	n = __pneigh_lookup(&nd_tbl, dev_net(dev), pkey, dev);
+	read_lock_bh(&neigh_tbl->lock);
+	n = __pneigh_lookup(ipv6_neigh_table(net), net, pkey, dev);
 	if (n)
 		ret = !!(n->flags & NTF_ROUTER);
-	read_unlock_bh(&nd_tbl.lock);
+	read_unlock_bh(&neigh_tbl->lock);
 
 	return ret;
 }
@@ -764,6 +766,8 @@ static void ndisc_recv_ns(struct sk_buff *skb)
 	struct inet6_dev *idev = NULL;
 	struct neighbour *neigh;
 	int dad = ipv6_addr_any(saddr);
+	struct neigh_table *neigh_tbl;
+	struct net *net;
 	bool inc;
 	int is_router = -1;
 	u64 nonce = 0;
@@ -816,7 +820,10 @@ static void ndisc_recv_ns(struct sk_buff *skb)
 
 	inc = ipv6_addr_is_multicast(daddr);
 
-	ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1);
+	net = dev_net(dev);
+	neigh_tbl = ipv6_neigh_table(net);
+
+	ifp = ipv6_get_ifaddr(net, &msg->target, dev, 1);
 	if (ifp) {
 have_ifp:
 		if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) {
@@ -851,8 +858,6 @@ static void ndisc_recv_ns(struct sk_buff *skb)
 
 		idev = ifp->idev;
 	} else {
-		struct net *net = dev_net(dev);
-
 		/* perhaps an address on the master device */
 		if (netif_is_l3_slave(dev)) {
 			struct net_device *mdev;
@@ -888,7 +893,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
 				 */
 				struct sk_buff *n = skb_clone(skb, GFP_ATOMIC);
 				if (n)
-					pneigh_enqueue(&nd_tbl, idev->nd_parms, n);
+					pneigh_enqueue(neigh_tbl, idev->nd_parms, n);
 				goto out;
 			}
 		} else
@@ -905,15 +910,15 @@ static void ndisc_recv_ns(struct sk_buff *skb)
 	}
 
 	if (inc)
-		NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_mcast);
+		NEIGH_CACHE_STAT_INC(neigh_tbl, rcv_probes_mcast);
 	else
-		NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_ucast);
+		NEIGH_CACHE_STAT_INC(neigh_tbl, rcv_probes_ucast);
 
 	/*
 	 *	update / create cache entry
 	 *	for the source address
 	 */
-	neigh = __neigh_lookup(&nd_tbl, saddr, dev,
+	neigh = __neigh_lookup(neigh_tbl, saddr, dev,
 			       !inc || lladdr || !dev->addr_len);
 	if (neigh)
 		ndisc_update(dev, neigh, lladdr, NUD_STALE,
@@ -1007,7 +1012,7 @@ static void ndisc_recv_na(struct sk_buff *skb)
 		in6_ifa_put(ifp);
 		return;
 	}
-	neigh = neigh_lookup(&nd_tbl, &msg->target, dev);
+	neigh = ipv6_neigh_lookup(dev, &msg->target);
 
 	if (neigh) {
 		u8 old_flags = neigh->flags;
@@ -1023,7 +1028,7 @@ static void ndisc_recv_na(struct sk_buff *skb)
 		 */
 		if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) &&
 		    net->ipv6.devconf_all->forwarding && net->ipv6.devconf_all->proxy_ndp &&
-		    pneigh_lookup(&nd_tbl, net, &msg->target, dev, 0)) {
+		    ipv6_pneigh_lookup(net, &msg->target, dev, 0)) {
 			/* XXX: idev->cnf.proxy_ndp */
 			goto out;
 		}
@@ -1091,7 +1096,7 @@ static void ndisc_recv_rs(struct sk_buff *skb)
 			goto out;
 	}
 
-	neigh = __neigh_lookup(&nd_tbl, saddr, skb->dev, 1);
+	neigh = __ipv6_neigh_lookup(skb->dev, saddr, 1);
 	if (neigh) {
 		ndisc_update(skb->dev, neigh, lladdr, NUD_STALE,
 			     NEIGH_UPDATE_F_WEAK_OVERRIDE|
@@ -1384,8 +1389,8 @@ static void ndisc_router_discovery(struct sk_buff *skb)
 	 */
 
 	if (!neigh)
-		neigh = __neigh_lookup(&nd_tbl, &ipv6_hdr(skb)->saddr,
-				       skb->dev, 1);
+		neigh = __ipv6_neigh_lookup(skb->dev, &ipv6_hdr(skb)->saddr, 1);
+
 	if (neigh) {
 		u8 *lladdr = NULL;
 		if (ndopts.nd_opts_src_lladdr) {
@@ -1768,7 +1773,7 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event,
 
 	switch (event) {
 	case NETDEV_CHANGEADDR:
-		neigh_changeaddr(&nd_tbl, dev);
+		neigh_changeaddr(ipv6_neigh_table(dev_net(dev)), dev);
 		fib6_run_gc(0, net, false);
 		/* fallthrough */
 	case NETDEV_UP:
@@ -1783,10 +1788,10 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event,
 	case NETDEV_CHANGE:
 		change_info = ptr;
 		if (change_info->flags_changed & IFF_NOARP)
-			neigh_changeaddr(&nd_tbl, dev);
+			neigh_changeaddr(ipv6_neigh_table(dev_net(dev)), dev);
 		break;
 	case NETDEV_DOWN:
-		neigh_ifdown(&nd_tbl, dev);
+		neigh_ifdown(ipv6_neigh_table(dev_net(dev)), dev);
 		fib6_run_gc(0, net, false);
 		break;
 	case NETDEV_NOTIFY_PEERS:
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 86a0e4333d42..17f01b8cb05f 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -207,10 +207,10 @@ struct neighbour *ip6_neigh_lookup(const struct in6_addr *gw,
 	struct neighbour *n;
 
 	daddr = choose_neigh_daddr(gw, skb, daddr);
-	n = __ipv6_neigh_lookup(dev, daddr);
+	n = __ipv6_neigh_lookup_noref(dev, daddr);
 	if (n)
 		return n;
-	return neigh_create(&nd_tbl, daddr, dev);
+	return ipv6_neigh_create(dev, daddr, true);
 }
 
 static struct neighbour *ip6_dst_neigh_lookup(const struct dst_entry *dst,
@@ -3392,7 +3392,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
 	 */
 	dst_confirm_neigh(&rt->dst, &ipv6_hdr(skb)->saddr);
 
-	neigh = __neigh_lookup(&nd_tbl, &msg->target, skb->dev, 1);
+	neigh = __ipv6_neigh_lookup(skb->dev, &msg->target, 1);
 	if (!neigh)
 		return;
 
@@ -4064,9 +4064,11 @@ void rt6_sync_down_dev(struct net_device *dev, unsigned long event)
 
 void rt6_disable_ip(struct net_device *dev, unsigned long event)
 {
+	struct net *net = dev_net(dev);
+
 	rt6_sync_down_dev(dev, event);
-	rt6_uncached_list_flush_dev(dev_net(dev), dev);
-	neigh_ifdown(&nd_tbl, dev);
+	rt6_uncached_list_flush_dev(net, dev);
+	neigh_ifdown(ipv6_neigh_table(net), dev);
 }
 
 struct rt6_mtu_change_arg {
-- 
2.11.0

^ permalink raw reply related

* [PATCH RFC/RFT net-next 05/17] net/ipv6: wrappers for neighbor table references
From: dsahern @ 2018-07-17 12:06 UTC (permalink / raw)
  To: netdev
  Cc: nikita.leshchenko, roopa, stephen, idosch, jiri, saeedm,
	alex.aring, linux-wpan, netfilter-devel, linux-kernel,
	David Ahern
In-Reply-To: <20180717120651.15748-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Create a helper, ipv6_neigh_table, for retrieving a reference to the ipv6
neighbor table. Add additional wrappers for commonly used neigh_* functions
to avoid propagating the ipv6_neigh_table lookup all over the code.

For ipv6, the neighbor table may not exist (e.g., IPv6 not enabled at
build time or the module is not loaded) so NULL checks are needed before
use.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 include/net/ndisc.h | 69 +++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 65 insertions(+), 4 deletions(-)

diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index ddfbb591e2c5..078951ac54fd 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -374,17 +374,70 @@ static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, _
 		(p32[3] * hash_rnd[3]));
 }
 
-static inline struct neighbour *__ipv6_neigh_lookup_noref(struct net_device *dev, const void *pkey)
+static inline struct neigh_table *ipv6_neigh_table(struct net *net)
 {
-	return ___neigh_lookup_noref(&nd_tbl, neigh_key_eq128, ndisc_hashfn, pkey, dev);
+	return neigh_find_table(net, AF_INET6);
 }
 
-static inline struct neighbour *__ipv6_neigh_lookup(struct net_device *dev, const void *pkey)
+static inline struct neighbour *ipv6_neigh_create(struct net_device *dev,
+						  const void *pkey,
+						  bool want_ref)
+{
+	struct neigh_table *tbl = ipv6_neigh_table(dev_net(dev));
+	struct neighbour *n = NULL;
+
+	if (tbl)
+		n = __neigh_create(tbl, pkey, dev, want_ref);
+
+	return n;
+}
+
+static inline struct neighbour *ipv6_neigh_lookup(struct net_device *dev,
+						  const void *pkey)
+{
+	struct neigh_table *tbl = ipv6_neigh_table(dev_net(dev));
+	struct neighbour *n = NULL;
+
+	if (tbl)
+		n = neigh_lookup(tbl, pkey, dev);
+
+	return n;
+}
+
+static inline struct neighbour *__ipv6_neigh_lookup(struct net_device *dev,
+						    const void *pkey, int creat)
+{
+	struct neigh_table *tbl = ipv6_neigh_table(dev_net(dev));
+	struct neighbour *n = NULL;
+
+	if (tbl)
+		n = __neigh_lookup(tbl, pkey, dev, creat);
+
+	return n;
+}
+
+static inline
+struct neighbour *___ipv6_neigh_lookup_noref(struct net_device *dev,
+					     const void *pkey)
+{
+	struct neigh_table *tbl = ipv6_neigh_table(dev_net(dev));
+	struct neighbour *n = NULL;
+
+	if (tbl)
+		n = ___neigh_lookup_noref(tbl, neigh_key_eq128, ndisc_hashfn,
+					  pkey, dev);
+
+	return n;
+}
+
+static inline
+struct neighbour *__ipv6_neigh_lookup_noref(struct net_device *dev,
+					    const void *pkey)
 {
 	struct neighbour *n;
 
 	rcu_read_lock_bh();
-	n = __ipv6_neigh_lookup_noref(dev, pkey);
+	n = ___ipv6_neigh_lookup_noref(dev, pkey);
 	if (n && !refcount_inc_not_zero(&n->refcnt))
 		n = NULL;
 	rcu_read_unlock_bh();
@@ -409,6 +462,14 @@ static inline void __ipv6_confirm_neigh(struct net_device *dev,
 	rcu_read_unlock_bh();
 }
 
+static inline struct pneigh_entry *ipv6_pneigh_lookup(struct net *net,
+						      const void *key,
+						      struct net_device *dev,
+						      int creat)
+{
+	return pneigh_lookup(ipv6_neigh_table(net), net, key, dev, creat);
+}
+
 int ndisc_init(void);
 int ndisc_late_init(void);
 
-- 
2.11.0

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox