Skip to content

Commit 950ab53

Browse files
kuba-mooPaolo Abeni
authored andcommitted
net: page_pool: implement GET in the netlink API
Expose the very basic page pool information via netlink. Example using ynl-py for a system with 9 queues: $ ./cli.py --no-schema --spec netlink/specs/netdev.yaml \ --dump page-pool-get [{'id': 19, 'ifindex': 2, 'napi-id': 147}, {'id': 18, 'ifindex': 2, 'napi-id': 146}, {'id': 17, 'ifindex': 2, 'napi-id': 145}, {'id': 16, 'ifindex': 2, 'napi-id': 144}, {'id': 15, 'ifindex': 2, 'napi-id': 143}, {'id': 14, 'ifindex': 2, 'napi-id': 142}, {'id': 13, 'ifindex': 2, 'napi-id': 141}, {'id': 12, 'ifindex': 2, 'napi-id': 140}, {'id': 11, 'ifindex': 2, 'napi-id': 139}, {'id': 10, 'ifindex': 2, 'napi-id': 138}] Reviewed-by: Eric Dumazet <[email protected]> Acked-by: Jesper Dangaard Brouer <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
1 parent 839ff60 commit 950ab53

File tree

4 files changed

+167
-0
lines changed

4 files changed

+167
-0
lines changed

include/uapi/linux/netdev.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,21 @@ enum {
6464
NETDEV_A_DEV_MAX = (__NETDEV_A_DEV_MAX - 1)
6565
};
6666

67+
enum {
68+
NETDEV_A_PAGE_POOL_ID = 1,
69+
NETDEV_A_PAGE_POOL_IFINDEX,
70+
NETDEV_A_PAGE_POOL_NAPI_ID,
71+
72+
__NETDEV_A_PAGE_POOL_MAX,
73+
NETDEV_A_PAGE_POOL_MAX = (__NETDEV_A_PAGE_POOL_MAX - 1)
74+
};
75+
6776
enum {
6877
NETDEV_CMD_DEV_GET = 1,
6978
NETDEV_CMD_DEV_ADD_NTF,
7079
NETDEV_CMD_DEV_DEL_NTF,
7180
NETDEV_CMD_DEV_CHANGE_NTF,
81+
NETDEV_CMD_PAGE_POOL_GET,
7282

7383
__NETDEV_CMD_MAX,
7484
NETDEV_CMD_MAX = (__NETDEV_CMD_MAX - 1)

net/core/netdev-genl-gen.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,24 @@
1010

1111
#include <uapi/linux/netdev.h>
1212

13+
/* Integer value ranges */
14+
static const struct netlink_range_validation netdev_a_page_pool_id_range = {
15+
.min = 1ULL,
16+
.max = 4294967295ULL,
17+
};
18+
1319
/* NETDEV_CMD_DEV_GET - do */
1420
static const struct nla_policy netdev_dev_get_nl_policy[NETDEV_A_DEV_IFINDEX + 1] = {
1521
[NETDEV_A_DEV_IFINDEX] = NLA_POLICY_MIN(NLA_U32, 1),
1622
};
1723

24+
/* NETDEV_CMD_PAGE_POOL_GET - do */
25+
#ifdef CONFIG_PAGE_POOL
26+
static const struct nla_policy netdev_page_pool_get_nl_policy[NETDEV_A_PAGE_POOL_ID + 1] = {
27+
[NETDEV_A_PAGE_POOL_ID] = NLA_POLICY_FULL_RANGE(NLA_UINT, &netdev_a_page_pool_id_range),
28+
};
29+
#endif /* CONFIG_PAGE_POOL */
30+
1831
/* Ops table for netdev */
1932
static const struct genl_split_ops netdev_nl_ops[] = {
2033
{
@@ -29,6 +42,20 @@ static const struct genl_split_ops netdev_nl_ops[] = {
2942
.dumpit = netdev_nl_dev_get_dumpit,
3043
.flags = GENL_CMD_CAP_DUMP,
3144
},
45+
#ifdef CONFIG_PAGE_POOL
46+
{
47+
.cmd = NETDEV_CMD_PAGE_POOL_GET,
48+
.doit = netdev_nl_page_pool_get_doit,
49+
.policy = netdev_page_pool_get_nl_policy,
50+
.maxattr = NETDEV_A_PAGE_POOL_ID,
51+
.flags = GENL_CMD_CAP_DO,
52+
},
53+
{
54+
.cmd = NETDEV_CMD_PAGE_POOL_GET,
55+
.dumpit = netdev_nl_page_pool_get_dumpit,
56+
.flags = GENL_CMD_CAP_DUMP,
57+
},
58+
#endif /* CONFIG_PAGE_POOL */
3259
};
3360

3461
static const struct genl_multicast_group netdev_nl_mcgrps[] = {

net/core/netdev-genl-gen.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
int netdev_nl_dev_get_doit(struct sk_buff *skb, struct genl_info *info);
1515
int netdev_nl_dev_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
16+
int netdev_nl_page_pool_get_doit(struct sk_buff *skb, struct genl_info *info);
17+
int netdev_nl_page_pool_get_dumpit(struct sk_buff *skb,
18+
struct netlink_callback *cb);
1619

1720
enum {
1821
NETDEV_NLGRP_MGMT,

net/core/page_pool_user.c

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
#include <linux/xarray.h>
66
#include <net/net_debug.h>
77
#include <net/page_pool/types.h>
8+
#include <net/sock.h>
89

910
#include "page_pool_priv.h"
11+
#include "netdev-genl-gen.h"
1012

1113
static DEFINE_XARRAY_FLAGS(page_pools, XA_FLAGS_ALLOC1);
1214
/* Protects: page_pools, netdevice->page_pools, pool->slow.netdev, pool->user.
@@ -26,6 +28,131 @@ static DEFINE_MUTEX(page_pools_lock);
2628
* - user.list: unhashed, netdev: unknown
2729
*/
2830

31+
typedef int (*pp_nl_fill_cb)(struct sk_buff *rsp, const struct page_pool *pool,
32+
const struct genl_info *info);
33+
34+
static int
35+
netdev_nl_page_pool_get_do(struct genl_info *info, u32 id, pp_nl_fill_cb fill)
36+
{
37+
struct page_pool *pool;
38+
struct sk_buff *rsp;
39+
int err;
40+
41+
mutex_lock(&page_pools_lock);
42+
pool = xa_load(&page_pools, id);
43+
if (!pool || hlist_unhashed(&pool->user.list) ||
44+
!net_eq(dev_net(pool->slow.netdev), genl_info_net(info))) {
45+
err = -ENOENT;
46+
goto err_unlock;
47+
}
48+
49+
rsp = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
50+
if (!rsp) {
51+
err = -ENOMEM;
52+
goto err_unlock;
53+
}
54+
55+
err = fill(rsp, pool, info);
56+
if (err)
57+
goto err_free_msg;
58+
59+
mutex_unlock(&page_pools_lock);
60+
61+
return genlmsg_reply(rsp, info);
62+
63+
err_free_msg:
64+
nlmsg_free(rsp);
65+
err_unlock:
66+
mutex_unlock(&page_pools_lock);
67+
return err;
68+
}
69+
70+
struct page_pool_dump_cb {
71+
unsigned long ifindex;
72+
u32 pp_id;
73+
};
74+
75+
static int
76+
netdev_nl_page_pool_get_dump(struct sk_buff *skb, struct netlink_callback *cb,
77+
pp_nl_fill_cb fill)
78+
{
79+
struct page_pool_dump_cb *state = (void *)cb->ctx;
80+
const struct genl_info *info = genl_info_dump(cb);
81+
struct net *net = sock_net(skb->sk);
82+
struct net_device *netdev;
83+
struct page_pool *pool;
84+
int err = 0;
85+
86+
rtnl_lock();
87+
mutex_lock(&page_pools_lock);
88+
for_each_netdev_dump(net, netdev, state->ifindex) {
89+
hlist_for_each_entry(pool, &netdev->page_pools, user.list) {
90+
if (state->pp_id && state->pp_id < pool->user.id)
91+
continue;
92+
93+
state->pp_id = pool->user.id;
94+
err = fill(skb, pool, info);
95+
if (err)
96+
break;
97+
}
98+
99+
state->pp_id = 0;
100+
}
101+
mutex_unlock(&page_pools_lock);
102+
rtnl_unlock();
103+
104+
if (skb->len && err == -EMSGSIZE)
105+
return skb->len;
106+
return err;
107+
}
108+
109+
static int
110+
page_pool_nl_fill(struct sk_buff *rsp, const struct page_pool *pool,
111+
const struct genl_info *info)
112+
{
113+
void *hdr;
114+
115+
hdr = genlmsg_iput(rsp, info);
116+
if (!hdr)
117+
return -EMSGSIZE;
118+
119+
if (nla_put_uint(rsp, NETDEV_A_PAGE_POOL_ID, pool->user.id))
120+
goto err_cancel;
121+
122+
if (pool->slow.netdev->ifindex != LOOPBACK_IFINDEX &&
123+
nla_put_u32(rsp, NETDEV_A_PAGE_POOL_IFINDEX,
124+
pool->slow.netdev->ifindex))
125+
goto err_cancel;
126+
if (pool->user.napi_id &&
127+
nla_put_uint(rsp, NETDEV_A_PAGE_POOL_NAPI_ID, pool->user.napi_id))
128+
goto err_cancel;
129+
130+
genlmsg_end(rsp, hdr);
131+
132+
return 0;
133+
err_cancel:
134+
genlmsg_cancel(rsp, hdr);
135+
return -EMSGSIZE;
136+
}
137+
138+
int netdev_nl_page_pool_get_doit(struct sk_buff *skb, struct genl_info *info)
139+
{
140+
u32 id;
141+
142+
if (GENL_REQ_ATTR_CHECK(info, NETDEV_A_PAGE_POOL_ID))
143+
return -EINVAL;
144+
145+
id = nla_get_uint(info->attrs[NETDEV_A_PAGE_POOL_ID]);
146+
147+
return netdev_nl_page_pool_get_do(info, id, page_pool_nl_fill);
148+
}
149+
150+
int netdev_nl_page_pool_get_dumpit(struct sk_buff *skb,
151+
struct netlink_callback *cb)
152+
{
153+
return netdev_nl_page_pool_get_dump(skb, cb, page_pool_nl_fill);
154+
}
155+
29156
int page_pool_list(struct page_pool *pool)
30157
{
31158
static u32 id_alloc_next;

0 commit comments

Comments
 (0)