]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
rtnetlink: switch rtnl_fdb_dump() to for_each_netdev_dump()
authorEric Dumazet <edumazet@google.com>
Mon, 9 Dec 2024 10:07:46 +0000 (10:07 +0000)
committerJakub Kicinski <kuba@kernel.org>
Wed, 11 Dec 2024 02:32:32 +0000 (18:32 -0800)
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>
include/linux/rtnetlink.h
net/core/rtnetlink.c

index c43cffb014a7ce1b98cb9604c545fc6c9d36eed9..5546571c25537d9a601aaa7a78594147ae7b6421 100644 (file)
@@ -180,8 +180,8 @@ void rtnl_kfree_skbs(struct sk_buff *head, struct sk_buff *tail);
 
 /* Shared by rtnl_fdb_dump() and various ndo_fdb_dump() helpers. */
 struct ndo_fdb_dump_context {
-       unsigned long s_h;
-       unsigned long s_idx;
+       unsigned long ifindex;
+       unsigned long pad;
        unsigned long fdb_idx;
 };
 
index 453cc8bf18fbe0d2ac41fed13576279b4c7a2c07..8fe252c298a2dbcb3a187a117741cd0149fac4cf 100644 (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 (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))
-                               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;
+       for_each_netdev_dump(net, dev, ctx->ifindex) {
+               if (brport_idx && (dev->ifindex != brport_idx))
+                       continue;
 
-                               if (br_dev != netdev_master_upper_dev_get(dev) &&
-                                   !netif_is_bridge_master(dev))
-                                       continue;
-                               cops = ops;
+               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 (idx < s_idx)
-                               goto cont;
+                       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)
-                                               goto out;
-                               }
+               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)
-                               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)
+                       break;
 
-                       cops = NULL;
+               cops = NULL;
 
-                       /* reset fdb offset to 0 for rest of the interfaces */
-                       ctx->fdb_idx = 0;
-                       fidx = 0;
-cont:
-                       idx++;
-               }
+               /* 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;