mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
net: page_pool: support dumping pps of a specific ifindex via Netlink
NIPA tries to make sure that HW tests don't modify system state. It saves the state of page pools, too. Now that I write this commit message I realize that this is impractical since page pool IDs and state will get legitimately changed by the tests. But I already spent a couple of hours implementing the filtering, so.. Link: https://patch.msgid.link/20260506034821.1710113-1-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
6a4c4656b0
commit
c93799de1b
|
|
@ -649,6 +649,9 @@ operations:
|
|||
- dmabuf
|
||||
- io-uring
|
||||
dump:
|
||||
request:
|
||||
attributes:
|
||||
- ifindex
|
||||
reply: *pp-reply
|
||||
config-cond: page-pool
|
||||
-
|
||||
|
|
@ -692,6 +695,9 @@ operations:
|
|||
- recycle-ring-full
|
||||
- recycle-released-refcnt
|
||||
dump:
|
||||
request:
|
||||
attributes:
|
||||
- info
|
||||
reply: *pp-stats-reply
|
||||
config-cond: page-pool-stats
|
||||
-
|
||||
|
|
|
|||
|
|
@ -51,14 +51,28 @@ static const struct nla_policy netdev_dev_get_nl_policy[NETDEV_A_DEV_IFINDEX + 1
|
|||
|
||||
/* NETDEV_CMD_PAGE_POOL_GET - do */
|
||||
#ifdef CONFIG_PAGE_POOL
|
||||
static const struct nla_policy netdev_page_pool_get_nl_policy[NETDEV_A_PAGE_POOL_ID + 1] = {
|
||||
static const struct nla_policy netdev_page_pool_get_do_nl_policy[NETDEV_A_PAGE_POOL_ID + 1] = {
|
||||
[NETDEV_A_PAGE_POOL_ID] = NLA_POLICY_FULL_RANGE(NLA_UINT, &netdev_a_page_pool_id_range),
|
||||
};
|
||||
#endif /* CONFIG_PAGE_POOL */
|
||||
|
||||
/* NETDEV_CMD_PAGE_POOL_GET - dump */
|
||||
#ifdef CONFIG_PAGE_POOL
|
||||
static const struct nla_policy netdev_page_pool_get_dump_nl_policy[NETDEV_A_PAGE_POOL_IFINDEX + 1] = {
|
||||
[NETDEV_A_PAGE_POOL_IFINDEX] = NLA_POLICY_FULL_RANGE(NLA_U32, &netdev_a_page_pool_ifindex_range),
|
||||
};
|
||||
#endif /* CONFIG_PAGE_POOL */
|
||||
|
||||
/* NETDEV_CMD_PAGE_POOL_STATS_GET - do */
|
||||
#ifdef CONFIG_PAGE_POOL_STATS
|
||||
static const struct nla_policy netdev_page_pool_stats_get_nl_policy[NETDEV_A_PAGE_POOL_STATS_INFO + 1] = {
|
||||
static const struct nla_policy netdev_page_pool_stats_get_do_nl_policy[NETDEV_A_PAGE_POOL_STATS_INFO + 1] = {
|
||||
[NETDEV_A_PAGE_POOL_STATS_INFO] = NLA_POLICY_NESTED(netdev_page_pool_info_nl_policy),
|
||||
};
|
||||
#endif /* CONFIG_PAGE_POOL_STATS */
|
||||
|
||||
/* NETDEV_CMD_PAGE_POOL_STATS_GET - dump */
|
||||
#ifdef CONFIG_PAGE_POOL_STATS
|
||||
static const struct nla_policy netdev_page_pool_stats_get_dump_nl_policy[NETDEV_A_PAGE_POOL_STATS_INFO + 1] = {
|
||||
[NETDEV_A_PAGE_POOL_STATS_INFO] = NLA_POLICY_NESTED(netdev_page_pool_info_nl_policy),
|
||||
};
|
||||
#endif /* CONFIG_PAGE_POOL_STATS */
|
||||
|
|
@ -138,28 +152,32 @@ static const struct genl_split_ops netdev_nl_ops[] = {
|
|||
{
|
||||
.cmd = NETDEV_CMD_PAGE_POOL_GET,
|
||||
.doit = netdev_nl_page_pool_get_doit,
|
||||
.policy = netdev_page_pool_get_nl_policy,
|
||||
.policy = netdev_page_pool_get_do_nl_policy,
|
||||
.maxattr = NETDEV_A_PAGE_POOL_ID,
|
||||
.flags = GENL_CMD_CAP_DO,
|
||||
},
|
||||
{
|
||||
.cmd = NETDEV_CMD_PAGE_POOL_GET,
|
||||
.dumpit = netdev_nl_page_pool_get_dumpit,
|
||||
.flags = GENL_CMD_CAP_DUMP,
|
||||
.cmd = NETDEV_CMD_PAGE_POOL_GET,
|
||||
.dumpit = netdev_nl_page_pool_get_dumpit,
|
||||
.policy = netdev_page_pool_get_dump_nl_policy,
|
||||
.maxattr = NETDEV_A_PAGE_POOL_IFINDEX,
|
||||
.flags = GENL_CMD_CAP_DUMP,
|
||||
},
|
||||
#endif /* CONFIG_PAGE_POOL */
|
||||
#ifdef CONFIG_PAGE_POOL_STATS
|
||||
{
|
||||
.cmd = NETDEV_CMD_PAGE_POOL_STATS_GET,
|
||||
.doit = netdev_nl_page_pool_stats_get_doit,
|
||||
.policy = netdev_page_pool_stats_get_nl_policy,
|
||||
.policy = netdev_page_pool_stats_get_do_nl_policy,
|
||||
.maxattr = NETDEV_A_PAGE_POOL_STATS_INFO,
|
||||
.flags = GENL_CMD_CAP_DO,
|
||||
},
|
||||
{
|
||||
.cmd = NETDEV_CMD_PAGE_POOL_STATS_GET,
|
||||
.dumpit = netdev_nl_page_pool_stats_get_dumpit,
|
||||
.flags = GENL_CMD_CAP_DUMP,
|
||||
.cmd = NETDEV_CMD_PAGE_POOL_STATS_GET,
|
||||
.dumpit = netdev_nl_page_pool_stats_get_dumpit,
|
||||
.policy = netdev_page_pool_stats_get_dump_nl_policy,
|
||||
.maxattr = NETDEV_A_PAGE_POOL_STATS_INFO,
|
||||
.flags = GENL_CMD_CAP_DUMP,
|
||||
},
|
||||
#endif /* CONFIG_PAGE_POOL_STATS */
|
||||
{
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ struct page_pool_dump_cb {
|
|||
|
||||
static int
|
||||
netdev_nl_page_pool_get_dump(struct sk_buff *skb, struct netlink_callback *cb,
|
||||
pp_nl_fill_cb fill)
|
||||
pp_nl_fill_cb fill, struct nlattr *ifindex_attr)
|
||||
{
|
||||
struct page_pool_dump_cb *state = (void *)cb->ctx;
|
||||
const struct genl_info *info = genl_info_dump(cb);
|
||||
|
|
@ -88,9 +88,17 @@ netdev_nl_page_pool_get_dump(struct sk_buff *skb, struct netlink_callback *cb,
|
|||
struct page_pool *pool;
|
||||
int err = 0;
|
||||
|
||||
if (ifindex_attr)
|
||||
state->ifindex = nla_get_u32(ifindex_attr);
|
||||
|
||||
rtnl_lock();
|
||||
mutex_lock(&page_pools_lock);
|
||||
for_each_netdev_dump(net, netdev, state->ifindex) {
|
||||
/* Either the provided ifindex doesn't exist or done dumping */
|
||||
if (ifindex_attr &&
|
||||
netdev->ifindex != nla_get_u32(ifindex_attr))
|
||||
break;
|
||||
|
||||
hlist_for_each_entry(pool, &netdev->page_pools, user.list) {
|
||||
if (state->pp_id && state->pp_id < pool->user.id)
|
||||
continue;
|
||||
|
|
@ -206,10 +214,40 @@ int netdev_nl_page_pool_stats_get_doit(struct sk_buff *skb,
|
|||
return netdev_nl_page_pool_get_do(info, id, page_pool_nl_stats_fill);
|
||||
}
|
||||
|
||||
static const struct netlink_range_validation page_pool_ifindex_range = {
|
||||
.min = 1ULL,
|
||||
.max = S32_MAX,
|
||||
};
|
||||
|
||||
static const struct nla_policy
|
||||
page_pool_stat_info_policy[NETDEV_A_PAGE_POOL_IFINDEX + 1] = {
|
||||
[NETDEV_A_PAGE_POOL_IFINDEX] =
|
||||
NLA_POLICY_FULL_RANGE(NLA_U32, &page_pool_ifindex_range),
|
||||
};
|
||||
|
||||
int netdev_nl_page_pool_stats_get_dumpit(struct sk_buff *skb,
|
||||
struct netlink_callback *cb)
|
||||
{
|
||||
return netdev_nl_page_pool_get_dump(skb, cb, page_pool_nl_stats_fill);
|
||||
struct nlattr *tb[ARRAY_SIZE(page_pool_stat_info_policy)];
|
||||
const struct genl_info *info = genl_info_dump(cb);
|
||||
struct nlattr *ifindex_attr = NULL;
|
||||
|
||||
if (info->attrs[NETDEV_A_PAGE_POOL_STATS_INFO]) {
|
||||
struct nlattr *nest;
|
||||
int err;
|
||||
|
||||
nest = info->attrs[NETDEV_A_PAGE_POOL_STATS_INFO];
|
||||
err = nla_parse_nested(tb, ARRAY_SIZE(tb) - 1, nest,
|
||||
page_pool_stat_info_policy,
|
||||
info->extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ifindex_attr = tb[NETDEV_A_PAGE_POOL_IFINDEX];
|
||||
}
|
||||
|
||||
return netdev_nl_page_pool_get_dump(skb, cb, page_pool_nl_stats_fill,
|
||||
ifindex_attr);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -305,7 +343,10 @@ int netdev_nl_page_pool_get_doit(struct sk_buff *skb, struct genl_info *info)
|
|||
int netdev_nl_page_pool_get_dumpit(struct sk_buff *skb,
|
||||
struct netlink_callback *cb)
|
||||
{
|
||||
return netdev_nl_page_pool_get_dump(skb, cb, page_pool_nl_fill);
|
||||
const struct genl_info *info = genl_info_dump(cb);
|
||||
|
||||
return netdev_nl_page_pool_get_dump(skb, cb, page_pool_nl_fill,
|
||||
info->attrs[NETDEV_A_PAGE_POOL_IFINDEX]);
|
||||
}
|
||||
|
||||
int page_pool_list(struct page_pool *pool)
|
||||
|
|
|
|||
|
|
@ -327,7 +327,9 @@ static void aggregate_device_stats(struct pp_stats_array *a,
|
|||
|
||||
static int do_stats(int argc, char **argv)
|
||||
{
|
||||
struct netdev_page_pool_stats_get_req_dump pp_stat_req = {};
|
||||
struct netdev_page_pool_stats_get_list *pp_stats;
|
||||
struct netdev_page_pool_get_req_dump pp_req = {};
|
||||
struct netdev_page_pool_get_list *pools;
|
||||
enum {
|
||||
GROUP_BY_DEVICE,
|
||||
|
|
@ -374,14 +376,14 @@ static int do_stats(int argc, char **argv)
|
|||
return -1;
|
||||
}
|
||||
|
||||
pools = netdev_page_pool_get_dump(ys);
|
||||
pools = netdev_page_pool_get_dump(ys, &pp_req);
|
||||
if (!pools) {
|
||||
p_err("failed to get page pools: %s", ys->err.msg);
|
||||
ret = -1;
|
||||
goto exit_close;
|
||||
}
|
||||
|
||||
pp_stats = netdev_page_pool_stats_get_dump(ys);
|
||||
pp_stats = netdev_page_pool_stats_get_dump(ys, &pp_stat_req);
|
||||
if (!pp_stats) {
|
||||
p_err("failed to get page pool stats: %s", ys->err.msg);
|
||||
ret = -1;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user