Commit 0feb396f authored by Eric Dumazet's avatar Eric Dumazet Committed by Jakub Kicinski
Browse files

rtnetlink: use for_each_netdev_dump() in rtnl_stats_dump()



Switch rtnl_stats_dump() to use for_each_netdev_dump()
instead of net->dev_index_head[] hash table.

This makes the code much easier to read, and fixes
scalability issues.

Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarDavid Ahern <dsahern@kernel.org>
Link: https://lore.kernel.org/r/20240502113748.1622637-3-edumazet@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 136c2a9a
Loading
Loading
Loading
Loading
+22 −37
Original line number Diff line number Diff line
@@ -5961,19 +5961,17 @@ static int rtnl_stats_get(struct sk_buff *skb, struct nlmsghdr *nlh,
static int rtnl_stats_dump(struct sk_buff *skb, struct netlink_callback *cb)
{
	struct netlink_ext_ack *extack = cb->extack;
	int h, s_h, err, s_idx, s_idxattr, s_prividx;
	struct rtnl_stats_dump_filters filters;
	struct net *net = sock_net(skb->sk);
	unsigned int flags = NLM_F_MULTI;
	struct if_stats_msg *ifsm;
	struct hlist_head *head;
	struct {
		unsigned long ifindex;
		int idxattr;
		int prividx;
	} *ctx = (void *)cb->ctx;
	struct net_device *dev;
	int idx = 0;

	s_h = cb->args[0];
	s_idx = cb->args[1];
	s_idxattr = cb->args[2];
	s_prividx = cb->args[3];
	int err;

	cb->seq = net->dev_base_seq;

@@ -5992,37 +5990,24 @@ static int rtnl_stats_dump(struct sk_buff *skb, struct netlink_callback *cb)
	if (err)
		return err;

	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 (idx < s_idx)
				goto cont;
	for_each_netdev_dump(net, dev, ctx->ifindex) {
		err = rtnl_fill_statsinfo(skb, dev, RTM_NEWSTATS,
					  NETLINK_CB(cb->skb).portid,
					  cb->nlh->nlmsg_seq, 0,
					  flags, &filters,
						  &s_idxattr, &s_prividx,
					  &ctx->idxattr, &ctx->prividx,
					  extack);
		/* If we ran out of room on the first message,
			 * we're in trouble
		 * we're in trouble.
		 */
		WARN_ON((err == -EMSGSIZE) && (skb->len == 0));

		if (err < 0)
				goto out;
			s_prividx = 0;
			s_idxattr = 0;
			break;
		ctx->prividx = 0;
		ctx->idxattr = 0;
		nl_dump_check_consistent(cb, nlmsg_hdr(skb));
cont:
			idx++;
		}
	}
out:
	cb->args[3] = s_prividx;
	cb->args[2] = s_idxattr;
	cb->args[1] = idx;
	cb->args[0] = h;

	return err;
}