* [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.