1 // SPDX-License-Identifier: GPL-2.0
2 /* XDP sockets monitoring support
4 * Copyright(c) 2019 Intel Corporation.
6 * Author: Björn Töpel <bjorn.topel@intel.com>
9 #include <linux/module.h>
10 #include <net/xdp_sock.h>
11 #include <linux/xdp_diag.h>
12 #include <linux/sock_diag.h>
14 #include "xsk_queue.h"
17 static int xsk_diag_put_info(const struct xdp_sock
*xs
, struct sk_buff
*nlskb
)
19 struct xdp_diag_info di
= {};
21 di
.ifindex
= xs
->dev
? xs
->dev
->ifindex
: 0;
22 di
.queue_id
= xs
->queue_id
;
23 return nla_put(nlskb
, XDP_DIAG_INFO
, sizeof(di
), &di
);
26 static int xsk_diag_put_ring(const struct xsk_queue
*queue
, int nl_type
,
27 struct sk_buff
*nlskb
)
29 struct xdp_diag_ring dr
= {};
31 dr
.entries
= queue
->nentries
;
32 return nla_put(nlskb
, nl_type
, sizeof(dr
), &dr
);
35 static int xsk_diag_put_rings_cfg(const struct xdp_sock
*xs
,
36 struct sk_buff
*nlskb
)
41 err
= xsk_diag_put_ring(xs
->rx
, XDP_DIAG_RX_RING
, nlskb
);
43 err
= xsk_diag_put_ring(xs
->tx
, XDP_DIAG_TX_RING
, nlskb
);
47 static int xsk_diag_put_umem(const struct xdp_sock
*xs
, struct sk_buff
*nlskb
)
49 struct xsk_buff_pool
*pool
= xs
->pool
;
50 struct xdp_umem
*umem
= xs
->umem
;
51 struct xdp_diag_umem du
= {};
59 du
.num_pages
= umem
->npgs
;
60 du
.chunk_size
= umem
->chunk_size
;
61 du
.headroom
= umem
->headroom
;
62 du
.ifindex
= (pool
&& pool
->netdev
) ? pool
->netdev
->ifindex
: 0;
63 du
.queue_id
= pool
? pool
->queue_id
: 0;
66 du
.flags
|= XDP_DU_F_ZEROCOPY
;
67 du
.refs
= refcount_read(&umem
->users
);
69 err
= nla_put(nlskb
, XDP_DIAG_UMEM
, sizeof(du
), &du
);
70 if (!err
&& pool
&& pool
->fq
)
71 err
= xsk_diag_put_ring(pool
->fq
,
72 XDP_DIAG_UMEM_FILL_RING
, nlskb
);
73 if (!err
&& pool
&& pool
->cq
)
74 err
= xsk_diag_put_ring(pool
->cq
,
75 XDP_DIAG_UMEM_COMPLETION_RING
, nlskb
);
79 static int xsk_diag_put_stats(const struct xdp_sock
*xs
, struct sk_buff
*nlskb
)
81 struct xdp_diag_stats du
= {};
83 du
.n_rx_dropped
= xs
->rx_dropped
;
84 du
.n_rx_invalid
= xskq_nb_invalid_descs(xs
->rx
);
85 du
.n_rx_full
= xs
->rx_queue_full
;
86 du
.n_fill_ring_empty
= xs
->pool
? xskq_nb_queue_empty_descs(xs
->pool
->fq
) : 0;
87 du
.n_tx_invalid
= xskq_nb_invalid_descs(xs
->tx
);
88 du
.n_tx_ring_empty
= xskq_nb_queue_empty_descs(xs
->tx
);
89 return nla_put(nlskb
, XDP_DIAG_STATS
, sizeof(du
), &du
);
92 static int xsk_diag_fill(struct sock
*sk
, struct sk_buff
*nlskb
,
93 struct xdp_diag_req
*req
,
94 struct user_namespace
*user_ns
,
95 u32 portid
, u32 seq
, u32 flags
, int sk_ino
)
97 struct xdp_sock
*xs
= xdp_sk(sk
);
98 struct xdp_diag_msg
*msg
;
101 nlh
= nlmsg_put(nlskb
, portid
, seq
, SOCK_DIAG_BY_FAMILY
, sizeof(*msg
),
106 msg
= nlmsg_data(nlh
);
107 memset(msg
, 0, sizeof(*msg
));
108 msg
->xdiag_family
= AF_XDP
;
109 msg
->xdiag_type
= sk
->sk_type
;
110 msg
->xdiag_ino
= sk_ino
;
111 sock_diag_save_cookie(sk
, msg
->xdiag_cookie
);
113 mutex_lock(&xs
->mutex
);
114 if (READ_ONCE(xs
->state
) == XSK_UNBOUND
)
117 if ((req
->xdiag_show
& XDP_SHOW_INFO
) && xsk_diag_put_info(xs
, nlskb
))
120 if ((req
->xdiag_show
& XDP_SHOW_INFO
) &&
121 nla_put_u32(nlskb
, XDP_DIAG_UID
,
122 from_kuid_munged(user_ns
, sock_i_uid(sk
))))
125 if ((req
->xdiag_show
& XDP_SHOW_RING_CFG
) &&
126 xsk_diag_put_rings_cfg(xs
, nlskb
))
129 if ((req
->xdiag_show
& XDP_SHOW_UMEM
) &&
130 xsk_diag_put_umem(xs
, nlskb
))
133 if ((req
->xdiag_show
& XDP_SHOW_MEMINFO
) &&
134 sock_diag_put_meminfo(sk
, nlskb
, XDP_DIAG_MEMINFO
))
137 if ((req
->xdiag_show
& XDP_SHOW_STATS
) &&
138 xsk_diag_put_stats(xs
, nlskb
))
141 mutex_unlock(&xs
->mutex
);
142 nlmsg_end(nlskb
, nlh
);
146 mutex_unlock(&xs
->mutex
);
147 nlmsg_cancel(nlskb
, nlh
);
151 static int xsk_diag_dump(struct sk_buff
*nlskb
, struct netlink_callback
*cb
)
153 struct xdp_diag_req
*req
= nlmsg_data(cb
->nlh
);
154 struct net
*net
= sock_net(nlskb
->sk
);
155 int num
= 0, s_num
= cb
->args
[0];
158 mutex_lock(&net
->xdp
.lock
);
160 sk_for_each(sk
, &net
->xdp
.list
) {
161 if (!net_eq(sock_net(sk
), net
))
166 if (xsk_diag_fill(sk
, nlskb
, req
,
167 sk_user_ns(NETLINK_CB(cb
->skb
).sk
),
168 NETLINK_CB(cb
->skb
).portid
,
169 cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
,
170 sock_i_ino(sk
)) < 0) {
176 mutex_unlock(&net
->xdp
.lock
);
181 static int xsk_diag_handler_dump(struct sk_buff
*nlskb
, struct nlmsghdr
*hdr
)
183 struct netlink_dump_control c
= { .dump
= xsk_diag_dump
};
184 int hdrlen
= sizeof(struct xdp_diag_req
);
185 struct net
*net
= sock_net(nlskb
->sk
);
187 if (nlmsg_len(hdr
) < hdrlen
)
190 if (!(hdr
->nlmsg_flags
& NLM_F_DUMP
))
193 return netlink_dump_start(net
->diag_nlsk
, nlskb
, hdr
, &c
);
196 static const struct sock_diag_handler xsk_diag_handler
= {
197 .owner
= THIS_MODULE
,
199 .dump
= xsk_diag_handler_dump
,
202 static int __init
xsk_diag_init(void)
204 return sock_diag_register(&xsk_diag_handler
);
207 static void __exit
xsk_diag_exit(void)
209 sock_diag_unregister(&xsk_diag_handler
);
212 module_init(xsk_diag_init
);
213 module_exit(xsk_diag_exit
);
214 MODULE_LICENSE("GPL");
215 MODULE_DESCRIPTION("XDP socket monitoring via SOCK_DIAG");
216 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK
, NETLINK_SOCK_DIAG
, AF_XDP
);