/* 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 */
{
.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 */
{
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);
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;
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
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)
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,
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;