Commit 3e41af90 authored by Eric Dumazet's avatar Eric Dumazet Committed by Jakub Kicinski
Browse files

rtnetlink: use xarray iterator to implement rtnl_dump_ifinfo()

Adopt net->dev_by_index as I did in commit 0e0939c0
("net-procfs: use xarray iterator to implement /proc/net/dev")

This makes sure an existing device is always visible in the dump,
regardless of concurrent insertions/deletions.

v2: added suggestions from Jakub Kicinski and Ido Schimmel,
    thanks for the help !

Link: https://lore.kernel.org/all/20240209142441.6c56435b@kernel.org/
Link: https://lore.kernel.org/all/ZckR-XOsULLI9EHc@shredder/


Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarIdo Schimmel <idosch@nvidia.com>
Link: https://lore.kernel.org/r/20240211214404.1882191-3-edumazet@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent f383ced2
Loading
Loading
Loading
Loading
+20 −38
Original line number Diff line number Diff line
@@ -2188,25 +2188,22 @@ static int rtnl_valid_dump_ifinfo_req(const struct nlmsghdr *nlh,

static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
{
	const struct rtnl_link_ops *kind_ops = NULL;
	struct netlink_ext_ack *extack = cb->extack;
	const struct nlmsghdr *nlh = cb->nlh;
	struct net *net = sock_net(skb->sk);
	struct net *tgt_net = net;
	int h, s_h;
	int idx = 0, s_idx;
	struct net_device *dev;
	struct hlist_head *head;
	unsigned int flags = NLM_F_MULTI;
	struct nlattr *tb[IFLA_MAX+1];
	struct {
		unsigned long ifindex;
	} *ctx = (void *)cb->ctx;
	struct net *tgt_net = net;
	u32 ext_filter_mask = 0;
	const struct rtnl_link_ops *kind_ops = NULL;
	unsigned int flags = NLM_F_MULTI;
	struct net_device *dev;
	int master_idx = 0;
	int netnsid = -1;
	int err, i;

	s_h = cb->args[0];
	s_idx = cb->args[1];

	err = rtnl_valid_dump_ifinfo_req(nlh, cb->strict_check, tb, extack);
	if (err < 0) {
		if (cb->strict_check)
@@ -2250,36 +2247,21 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
		flags |= NLM_F_DUMP_FILTERED;

walk_entries:
	for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
		idx = 0;
		head = &tgt_net->dev_index_head[h];
		hlist_for_each_entry(dev, head, index_hlist) {
	err = 0;
	for_each_netdev_dump(tgt_net, dev, ctx->ifindex) {
		if (link_dump_filtered(dev, master_idx, kind_ops))
				goto cont;
			if (idx < s_idx)
				goto cont;
			err = rtnl_fill_ifinfo(skb, dev, net,
					       RTM_NEWLINK,
			continue;
		err = rtnl_fill_ifinfo(skb, dev, net, RTM_NEWLINK,
				       NETLINK_CB(cb->skb).portid,
				       nlh->nlmsg_seq, 0, flags,
				       ext_filter_mask, 0, NULL, 0,
				       netnsid, GFP_KERNEL);

		if (err < 0) {
			if (likely(skb->len))
					goto out;

				goto out_err;
			}
cont:
			idx++;
				err = skb->len;
			break;
		}
	}
out:
	err = skb->len;
out_err:
	cb->args[1] = idx;
	cb->args[0] = h;
	cb->seq = tgt_net->dev_base_seq;
	nl_dump_check_consistent(cb, nlmsg_hdr(skb));
	if (netnsid >= 0)