All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 0/3] neighbour: convert neigh_dump_info() to RCU
@ 2024-04-18  9:51 Eric Dumazet
  2024-04-18  9:51 ` [PATCH net-next 1/3] neighbour: add RCU protection to neigh_tables[] Eric Dumazet
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Eric Dumazet @ 2024-04-18  9:51 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: netdev, David Ahern, eric.dumazet, Eric Dumazet

Remove RTNL requirement for "ip neighbour show" command.

Eric Dumazet (3):
  neighbour: add RCU protection to neigh_tables[]
  neighbour: fix neigh_dump_info() return value
  neighbour: no longer hold RTNL in neigh_dump_info()

 net/core/neighbour.c | 68 +++++++++++++++++++++++---------------------
 1 file changed, 36 insertions(+), 32 deletions(-)

-- 
2.44.0.683.g7961c838ac-goog


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH net-next 1/3] neighbour: add RCU protection to neigh_tables[]
  2024-04-18  9:51 [PATCH net-next 0/3] neighbour: convert neigh_dump_info() to RCU Eric Dumazet
@ 2024-04-18  9:51 ` Eric Dumazet
  2024-04-18  9:51 ` [PATCH net-next 2/3] neighbour: fix neigh_dump_info() return value Eric Dumazet
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Eric Dumazet @ 2024-04-18  9:51 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: netdev, David Ahern, eric.dumazet, Eric Dumazet

In order to remove RTNL protection from neightbl_dump_info()
and neigh_dump_info() later, we need to add
RCU protection to neigh_tables[].

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 net/core/neighbour.c | 30 +++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 552719c3bbc3d7869c49028f4c5c9102d1ae9b0a..33913dbf4023bcb1f18107fc3b5c26280dce7341 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1769,7 +1769,7 @@ 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;
+static struct neigh_table __rcu *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
 
 void neigh_table_init(int index, struct neigh_table *tbl)
 {
@@ -1826,13 +1826,19 @@ 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;
+	rcu_assign_pointer(neigh_tables[index], tbl);
 }
 EXPORT_SYMBOL(neigh_table_init);
 
+/*
+ * Only called from ndisc_cleanup(), which means this is dead code
+ * because we no longer can unload IPv6 module.
+ */
 int neigh_table_clear(int index, struct neigh_table *tbl)
 {
-	neigh_tables[index] = NULL;
+	RCU_INIT_POINTER(neigh_tables[index], NULL);
+	synchronize_rcu();
+
 	/* It is not clean... Fix it to unload IPv6 module safely */
 	cancel_delayed_work_sync(&tbl->managed_work);
 	cancel_delayed_work_sync(&tbl->gc_work);
@@ -1864,10 +1870,10 @@ static struct neigh_table *neigh_find_table(int family)
 
 	switch (family) {
 	case AF_INET:
-		tbl = neigh_tables[NEIGH_ARP_TABLE];
+		tbl = rcu_dereference_rtnl(neigh_tables[NEIGH_ARP_TABLE]);
 		break;
 	case AF_INET6:
-		tbl = neigh_tables[NEIGH_ND_TABLE];
+		tbl = rcu_dereference_rtnl(neigh_tables[NEIGH_ND_TABLE]);
 		break;
 	}
 
@@ -2331,7 +2337,7 @@ 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];
+		tbl = rcu_dereference_rtnl(neigh_tables[tidx]);
 		if (!tbl)
 			continue;
 		if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
@@ -2519,7 +2525,7 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
 	for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
 		struct neigh_parms *p;
 
-		tbl = neigh_tables[tidx];
+		tbl = rcu_dereference_rtnl(neigh_tables[tidx]);
 		if (!tbl)
 			continue;
 
@@ -2879,7 +2885,7 @@ 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];
+		tbl = rcu_dereference_rtnl(neigh_tables[t]);
 
 		if (!tbl)
 			continue;
@@ -3143,14 +3149,15 @@ int neigh_xmit(int index, struct net_device *dev,
 	       const void *addr, struct sk_buff *skb)
 {
 	int err = -EAFNOSUPPORT;
+
 	if (likely(index < NEIGH_NR_TABLES)) {
 		struct neigh_table *tbl;
 		struct neighbour *neigh;
 
-		tbl = neigh_tables[index];
-		if (!tbl)
-			goto out;
 		rcu_read_lock();
+		tbl = rcu_dereference(neigh_tables[index]);
+		if (!tbl)
+			goto out_unlock;
 		if (index == NEIGH_ARP_TABLE) {
 			u32 key = *((u32 *)addr);
 
@@ -3166,6 +3173,7 @@ int neigh_xmit(int index, struct net_device *dev,
 			goto out_kfree_skb;
 		}
 		err = READ_ONCE(neigh->output)(neigh, skb);
+out_unlock:
 		rcu_read_unlock();
 	}
 	else if (index == NEIGH_LINK_TABLE) {
-- 
2.44.0.683.g7961c838ac-goog


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH net-next 2/3] neighbour: fix neigh_dump_info() return value
  2024-04-18  9:51 [PATCH net-next 0/3] neighbour: convert neigh_dump_info() to RCU Eric Dumazet
  2024-04-18  9:51 ` [PATCH net-next 1/3] neighbour: add RCU protection to neigh_tables[] Eric Dumazet
@ 2024-04-18  9:51 ` Eric Dumazet
  2024-04-18  9:51 ` [PATCH net-next 3/3] neighbour: no longer hold RTNL in neigh_dump_info() Eric Dumazet
  2024-04-19 11:40 ` [PATCH net-next 0/3] neighbour: convert neigh_dump_info() to RCU patchwork-bot+netdevbpf
  3 siblings, 0 replies; 5+ messages in thread
From: Eric Dumazet @ 2024-04-18  9:51 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: netdev, David Ahern, eric.dumazet, Eric Dumazet

Change neigh_dump_table() and pneigh_dump_table()
to either return 0 or -EMSGSIZE if not enough
space was available in the skb.

Then neigh_dump_info() can do the same.

This allows NLMSG_DONE to be appended to the current
skb at the end of a dump, saving a couple of recvmsg()
system calls.

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 net/core/neighbour.c | 31 +++++++++++++------------------
 1 file changed, 13 insertions(+), 18 deletions(-)

diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 33913dbf4023bcb1f18107fc3b5c26280dce7341..2f9efc89e94e0f6d9e1491019583babb7bae77c7 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2713,7 +2713,7 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
 {
 	struct net *net = sock_net(skb->sk);
 	struct neighbour *n;
-	int rc, h, s_h = cb->args[1];
+	int err = 0, h, s_h = cb->args[1];
 	int idx, s_idx = idx = cb->args[2];
 	struct neigh_hash_table *nht;
 	unsigned int flags = NLM_F_MULTI;
@@ -2735,23 +2735,20 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
 			if (neigh_ifindex_filtered(n->dev, filter->dev_idx) ||
 			    neigh_master_filtered(n->dev, filter->master_idx))
 				goto next;
-			if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
-					    cb->nlh->nlmsg_seq,
-					    RTM_NEWNEIGH,
-					    flags) < 0) {
-				rc = -1;
+			err = neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
+					      cb->nlh->nlmsg_seq,
+					      RTM_NEWNEIGH, flags);
+			if (err < 0)
 				goto out;
-			}
 next:
 			idx++;
 		}
 	}
-	rc = skb->len;
 out:
 	rcu_read_unlock();
 	cb->args[1] = h;
 	cb->args[2] = idx;
-	return rc;
+	return err;
 }
 
 static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
@@ -2760,7 +2757,7 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
 {
 	struct pneigh_entry *n;
 	struct net *net = sock_net(skb->sk);
-	int rc, h, s_h = cb->args[3];
+	int err = 0, h, s_h = cb->args[3];
 	int idx, s_idx = idx = cb->args[4];
 	unsigned int flags = NLM_F_MULTI;
 
@@ -2778,11 +2775,11 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
 			if (neigh_ifindex_filtered(n->dev, filter->dev_idx) ||
 			    neigh_master_filtered(n->dev, filter->master_idx))
 				goto next;
-			if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
-					    cb->nlh->nlmsg_seq,
-					    RTM_NEWNEIGH, flags, tbl) < 0) {
+			err = pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
+					       cb->nlh->nlmsg_seq,
+					       RTM_NEWNEIGH, flags, tbl);
+			if (err < 0) {
 				read_unlock_bh(&tbl->lock);
-				rc = -1;
 				goto out;
 			}
 		next:
@@ -2791,12 +2788,10 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
 	}
 
 	read_unlock_bh(&tbl->lock);
-	rc = skb->len;
 out:
 	cb->args[3] = h;
 	cb->args[4] = idx;
-	return rc;
-
+	return err;
 }
 
 static int neigh_valid_dump_req(const struct nlmsghdr *nlh,
@@ -2903,7 +2898,7 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
 	}
 
 	cb->args[0] = t;
-	return skb->len;
+	return err;
 }
 
 static int neigh_valid_get_req(const struct nlmsghdr *nlh,
-- 
2.44.0.683.g7961c838ac-goog


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH net-next 3/3] neighbour: no longer hold RTNL in neigh_dump_info()
  2024-04-18  9:51 [PATCH net-next 0/3] neighbour: convert neigh_dump_info() to RCU Eric Dumazet
  2024-04-18  9:51 ` [PATCH net-next 1/3] neighbour: add RCU protection to neigh_tables[] Eric Dumazet
  2024-04-18  9:51 ` [PATCH net-next 2/3] neighbour: fix neigh_dump_info() return value Eric Dumazet
@ 2024-04-18  9:51 ` Eric Dumazet
  2024-04-19 11:40 ` [PATCH net-next 0/3] neighbour: convert neigh_dump_info() to RCU patchwork-bot+netdevbpf
  3 siblings, 0 replies; 5+ messages in thread
From: Eric Dumazet @ 2024-04-18  9:51 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: netdev, David Ahern, eric.dumazet, Eric Dumazet

neigh_dump_table() is already relying on RCU protection.

pneigh_dump_table() is using its own protection (tbl->lock)

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 net/core/neighbour.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 2f9efc89e94e0f6d9e1491019583babb7bae77c7..13f2629091ef9ecd70a83f047a146c0990f308d9 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2721,7 +2721,6 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
 	if (filter->dev_idx || filter->master_idx)
 		flags |= NLM_F_DUMP_FILTERED;
 
-	rcu_read_lock();
 	nht = rcu_dereference(tbl->nht);
 
 	for (h = s_h; h < (1 << nht->hash_shift); h++) {
@@ -2745,7 +2744,6 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
 		}
 	}
 out:
-	rcu_read_unlock();
 	cb->args[1] = h;
 	cb->args[2] = idx;
 	return err;
@@ -2879,8 +2877,9 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
 
 	s_t = cb->args[0];
 
+	rcu_read_lock();
 	for (t = 0; t < NEIGH_NR_TABLES; t++) {
-		tbl = rcu_dereference_rtnl(neigh_tables[t]);
+		tbl = rcu_dereference(neigh_tables[t]);
 
 		if (!tbl)
 			continue;
@@ -2896,6 +2895,7 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
 		if (err < 0)
 			break;
 	}
+	rcu_read_unlock();
 
 	cb->args[0] = t;
 	return err;
@@ -3892,7 +3892,8 @@ static int __init neigh_init(void)
 {
 	rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, 0);
 	rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, 0);
-	rtnl_register(PF_UNSPEC, RTM_GETNEIGH, neigh_get, neigh_dump_info, 0);
+	rtnl_register(PF_UNSPEC, RTM_GETNEIGH, neigh_get, neigh_dump_info,
+		      RTNL_FLAG_DUMP_UNLOCKED);
 
 	rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
 		      0);
-- 
2.44.0.683.g7961c838ac-goog


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH net-next 0/3] neighbour: convert neigh_dump_info() to RCU
  2024-04-18  9:51 [PATCH net-next 0/3] neighbour: convert neigh_dump_info() to RCU Eric Dumazet
                   ` (2 preceding siblings ...)
  2024-04-18  9:51 ` [PATCH net-next 3/3] neighbour: no longer hold RTNL in neigh_dump_info() Eric Dumazet
@ 2024-04-19 11:40 ` patchwork-bot+netdevbpf
  3 siblings, 0 replies; 5+ messages in thread
From: patchwork-bot+netdevbpf @ 2024-04-19 11:40 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: davem, kuba, pabeni, netdev, dsahern, eric.dumazet

Hello:

This series was applied to netdev/net-next.git (main)
by David S. Miller <davem@davemloft.net>:

On Thu, 18 Apr 2024 09:51:03 +0000 you wrote:
> Remove RTNL requirement for "ip neighbour show" command.
> 
> Eric Dumazet (3):
>   neighbour: add RCU protection to neigh_tables[]
>   neighbour: fix neigh_dump_info() return value
>   neighbour: no longer hold RTNL in neigh_dump_info()
> 
> [...]

Here is the summary with links:
  - [net-next,1/3] neighbour: add RCU protection to neigh_tables[]
    https://git.kernel.org/netdev/net-next/c/f8f2eb9de69a
  - [net-next,2/3] neighbour: fix neigh_dump_info() return value
    https://git.kernel.org/netdev/net-next/c/7e4975f7e7fb
  - [net-next,3/3] neighbour: no longer hold RTNL in neigh_dump_info()
    https://git.kernel.org/netdev/net-next/c/ba0f78069423

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2024-04-19 11:40 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-04-18  9:51 [PATCH net-next 0/3] neighbour: convert neigh_dump_info() to RCU Eric Dumazet
2024-04-18  9:51 ` [PATCH net-next 1/3] neighbour: add RCU protection to neigh_tables[] Eric Dumazet
2024-04-18  9:51 ` [PATCH net-next 2/3] neighbour: fix neigh_dump_info() return value Eric Dumazet
2024-04-18  9:51 ` [PATCH net-next 3/3] neighbour: no longer hold RTNL in neigh_dump_info() Eric Dumazet
2024-04-19 11:40 ` [PATCH net-next 0/3] neighbour: convert neigh_dump_info() to RCU patchwork-bot+netdevbpf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.