rtnetlink: switch rtnl_fdb_dump() to for_each_netdev_dump()

This is the last netdev iterator still using net->dev_index_head[].

Convert to modern for_each_netdev_dump() for better scalability,
and use common patterns in our stack.

Following patch in this series removes the pad field
in struct ndo_fdb_dump_context.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Link: https://patch.msgid.link/20241209100747.2269613-3-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Eric Dumazet
2024-12-09 10:07:46 +00:00
committed by Jakub Kicinski
parent be325f08c4
commit 53970a05f7
2 changed files with 41 additions and 63 deletions

View File

@@ -4914,13 +4914,10 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
struct ndo_fdb_dump_context *ctx = (void *)cb->ctx;
struct net_device *dev, *br_dev = NULL;
struct net *net = sock_net(skb->sk);
struct hlist_head *head;
int brport_idx = 0;
int br_idx = 0;
int h, s_h;
int idx = 0, s_idx;
int err = 0;
int fidx = 0;
int err;
NL_ASSERT_CTX_FITS(struct ndo_fdb_dump_context);
@@ -4941,69 +4938,50 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
ops = br_dev->netdev_ops;
}
s_h = ctx->s_h;
s_idx = ctx->s_idx;
for_each_netdev_dump(net, dev, ctx->ifindex) {
if (brport_idx && (dev->ifindex != brport_idx))
continue;
for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
idx = 0;
head = &net->dev_index_head[h];
hlist_for_each_entry(dev, head, index_hlist) {
if (brport_idx && (dev->ifindex != brport_idx))
if (!br_idx) { /* user did not specify a specific bridge */
if (netif_is_bridge_port(dev)) {
br_dev = netdev_master_upper_dev_get(dev);
cops = br_dev->netdev_ops;
}
} else {
if (dev != br_dev &&
!netif_is_bridge_port(dev))
continue;
if (!br_idx) { /* user did not specify a specific bridge */
if (netif_is_bridge_port(dev)) {
br_dev = netdev_master_upper_dev_get(dev);
cops = br_dev->netdev_ops;
}
} else {
if (dev != br_dev &&
!netif_is_bridge_port(dev))
continue;
if (br_dev != netdev_master_upper_dev_get(dev) &&
!netif_is_bridge_master(dev))
continue;
cops = ops;
}
if (idx < s_idx)
goto cont;
if (netif_is_bridge_port(dev)) {
if (cops && cops->ndo_fdb_dump) {
err = cops->ndo_fdb_dump(skb, cb,
br_dev, dev,
&fidx);
if (err == -EMSGSIZE)
goto out;
}
}
if (dev->netdev_ops->ndo_fdb_dump)
err = dev->netdev_ops->ndo_fdb_dump(skb, cb,
dev, NULL,
&fidx);
else
err = ndo_dflt_fdb_dump(skb, cb, dev, NULL,
&fidx);
if (err == -EMSGSIZE)
goto out;
cops = NULL;
/* reset fdb offset to 0 for rest of the interfaces */
ctx->fdb_idx = 0;
fidx = 0;
cont:
idx++;
if (br_dev != netdev_master_upper_dev_get(dev) &&
!netif_is_bridge_master(dev))
continue;
cops = ops;
}
if (netif_is_bridge_port(dev)) {
if (cops && cops->ndo_fdb_dump) {
err = cops->ndo_fdb_dump(skb, cb, br_dev, dev,
&fidx);
if (err == -EMSGSIZE)
break;
}
}
if (dev->netdev_ops->ndo_fdb_dump)
err = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, NULL,
&fidx);
else
err = ndo_dflt_fdb_dump(skb, cb, dev, NULL, &fidx);
if (err == -EMSGSIZE)
break;
cops = NULL;
/* reset fdb offset to 0 for rest of the interfaces */
ctx->fdb_idx = 0;
fidx = 0;
}
out:
ctx->s_h = h;
ctx->s_idx = idx;
ctx->fdb_idx = fidx;
return skb->len;