blob: 4688c750df1d3ff97b55a4ba0036a0c7760dc66e [file] [log] [blame]
Björn Töpelc0c77d82018-05-02 13:01:23 +02001// SPDX-License-Identifier: GPL-2.0
2/* XDP sockets
3 *
4 * AF_XDP sockets allows a channel between XDP programs and userspace
5 * applications.
6 * Copyright(c) 2018 Intel Corporation.
7 *
Björn Töpelc0c77d82018-05-02 13:01:23 +02008 * Author(s): Björn Töpel <bjorn.topel@intel.com>
9 * Magnus Karlsson <magnus.karlsson@intel.com>
10 */
11
12#define pr_fmt(fmt) "AF_XDP: %s: " fmt, __func__
13
14#include <linux/if_xdp.h>
15#include <linux/init.h>
16#include <linux/sched/mm.h>
17#include <linux/sched/signal.h>
18#include <linux/sched/task.h>
19#include <linux/socket.h>
20#include <linux/file.h>
21#include <linux/uaccess.h>
22#include <linux/net.h>
23#include <linux/netdevice.h>
24#include <net/xdp_sock.h>
Björn Töpelb9b6b682018-05-02 13:01:25 +020025#include <net/xdp.h>
Björn Töpelc0c77d82018-05-02 13:01:23 +020026
Magnus Karlsson423f3832018-05-02 13:01:24 +020027#include "xsk_queue.h"
Björn Töpelc0c77d82018-05-02 13:01:23 +020028#include "xdp_umem.h"
29
Magnus Karlsson35fcde72018-05-02 13:01:34 +020030#define TX_BATCH_SIZE 16
31
Björn Töpelc0c77d82018-05-02 13:01:23 +020032static struct xdp_sock *xdp_sk(struct sock *sk)
33{
34 return (struct xdp_sock *)sk;
35}
36
Björn Töpelfbfc504a2018-05-02 13:01:28 +020037bool xsk_is_setup_for_bpf_map(struct xdp_sock *xs)
38{
39 return !!xs->rx;
40}
41
Björn Töpelc4971762018-05-02 13:01:27 +020042static int __xsk_rcv(struct xdp_sock *xs, struct xdp_buff *xdp)
43{
Björn Töpelbbff2f32018-06-04 13:57:13 +020044 u32 len = xdp->data_end - xdp->data;
Björn Töpelc4971762018-05-02 13:01:27 +020045 void *buffer;
Björn Töpelbbff2f32018-06-04 13:57:13 +020046 u64 addr;
Björn Töpel4e64c832018-06-04 13:57:11 +020047 int err;
Björn Töpelc4971762018-05-02 13:01:27 +020048
49 if (xs->dev != xdp->rxq->dev || xs->queue_id != xdp->rxq->queue_index)
50 return -EINVAL;
51
Björn Töpelbbff2f32018-06-04 13:57:13 +020052 if (!xskq_peek_addr(xs->umem->fq, &addr) ||
53 len > xs->umem->chunk_size_nohr) {
Björn Töpela509a952018-06-04 13:57:12 +020054 xs->rx_dropped++;
Björn Töpelc4971762018-05-02 13:01:27 +020055 return -ENOSPC;
Björn Töpela509a952018-06-04 13:57:12 +020056 }
Björn Töpelc4971762018-05-02 13:01:27 +020057
Björn Töpelbbff2f32018-06-04 13:57:13 +020058 addr += xs->umem->headroom;
59
60 buffer = xdp_umem_get_data(xs->umem, addr);
Björn Töpelc4971762018-05-02 13:01:27 +020061 memcpy(buffer, xdp->data, len);
Björn Töpelbbff2f32018-06-04 13:57:13 +020062 err = xskq_produce_batch_desc(xs->rx, addr, len);
Björn Töpelc4971762018-05-02 13:01:27 +020063 if (!err)
Björn Töpelbbff2f32018-06-04 13:57:13 +020064 xskq_discard_addr(xs->umem->fq);
Björn Töpela509a952018-06-04 13:57:12 +020065 else
66 xs->rx_dropped++;
Björn Töpelc4971762018-05-02 13:01:27 +020067
68 return err;
69}
70
71int xsk_rcv(struct xdp_sock *xs, struct xdp_buff *xdp)
72{
73 int err;
74
75 err = __xsk_rcv(xs, xdp);
76 if (likely(!err))
77 xdp_return_buff(xdp);
Björn Töpelc4971762018-05-02 13:01:27 +020078
79 return err;
80}
81
82void xsk_flush(struct xdp_sock *xs)
83{
84 xskq_produce_flush_desc(xs->rx);
85 xs->sk.sk_data_ready(&xs->sk);
86}
87
88int xsk_generic_rcv(struct xdp_sock *xs, struct xdp_buff *xdp)
89{
90 int err;
91
92 err = __xsk_rcv(xs, xdp);
93 if (!err)
94 xsk_flush(xs);
Björn Töpelc4971762018-05-02 13:01:27 +020095
96 return err;
97}
98
Magnus Karlsson35fcde72018-05-02 13:01:34 +020099static void xsk_destruct_skb(struct sk_buff *skb)
100{
Björn Töpelbbff2f32018-06-04 13:57:13 +0200101 u64 addr = (u64)(long)skb_shinfo(skb)->destructor_arg;
Magnus Karlsson35fcde72018-05-02 13:01:34 +0200102 struct xdp_sock *xs = xdp_sk(skb->sk);
103
Björn Töpelbbff2f32018-06-04 13:57:13 +0200104 WARN_ON_ONCE(xskq_produce_addr(xs->umem->cq, addr));
Magnus Karlsson35fcde72018-05-02 13:01:34 +0200105
106 sock_wfree(skb);
107}
108
109static int xsk_generic_xmit(struct sock *sk, struct msghdr *m,
110 size_t total_len)
111{
112 bool need_wait = !(m->msg_flags & MSG_DONTWAIT);
113 u32 max_batch = TX_BATCH_SIZE;
114 struct xdp_sock *xs = xdp_sk(sk);
115 bool sent_frame = false;
116 struct xdp_desc desc;
117 struct sk_buff *skb;
118 int err = 0;
119
120 if (unlikely(!xs->tx))
121 return -ENOBUFS;
122 if (need_wait)
123 return -EOPNOTSUPP;
124
125 mutex_lock(&xs->mutex);
126
127 while (xskq_peek_desc(xs->tx, &desc)) {
128 char *buffer;
Björn Töpelbbff2f32018-06-04 13:57:13 +0200129 u64 addr;
130 u32 len;
Magnus Karlsson35fcde72018-05-02 13:01:34 +0200131
132 if (max_batch-- == 0) {
133 err = -EAGAIN;
134 goto out;
135 }
136
Björn Töpelbbff2f32018-06-04 13:57:13 +0200137 if (xskq_reserve_addr(xs->umem->cq)) {
Magnus Karlsson35fcde72018-05-02 13:01:34 +0200138 err = -EAGAIN;
139 goto out;
140 }
141
142 len = desc.len;
143 if (unlikely(len > xs->dev->mtu)) {
144 err = -EMSGSIZE;
145 goto out;
146 }
147
Magnus Karlsson2e59dd52018-05-22 09:34:58 +0200148 if (xs->queue_id >= xs->dev->real_num_tx_queues) {
149 err = -ENXIO;
150 goto out;
151 }
152
Magnus Karlsson35fcde72018-05-02 13:01:34 +0200153 skb = sock_alloc_send_skb(sk, len, !need_wait, &err);
154 if (unlikely(!skb)) {
155 err = -EAGAIN;
156 goto out;
157 }
158
159 skb_put(skb, len);
Björn Töpelbbff2f32018-06-04 13:57:13 +0200160 addr = desc.addr;
161 buffer = xdp_umem_get_data(xs->umem, addr);
Magnus Karlsson35fcde72018-05-02 13:01:34 +0200162 err = skb_store_bits(skb, 0, buffer, len);
163 if (unlikely(err)) {
164 kfree_skb(skb);
165 goto out;
166 }
167
168 skb->dev = xs->dev;
169 skb->priority = sk->sk_priority;
170 skb->mark = sk->sk_mark;
Björn Töpelbbff2f32018-06-04 13:57:13 +0200171 skb_shinfo(skb)->destructor_arg = (void *)(long)addr;
Magnus Karlsson35fcde72018-05-02 13:01:34 +0200172 skb->destructor = xsk_destruct_skb;
173
174 err = dev_direct_xmit(skb, xs->queue_id);
175 /* Ignore NET_XMIT_CN as packet might have been sent */
176 if (err == NET_XMIT_DROP || err == NETDEV_TX_BUSY) {
177 err = -EAGAIN;
178 /* SKB consumed by dev_direct_xmit() */
179 goto out;
180 }
181
182 sent_frame = true;
183 xskq_discard_desc(xs->tx);
184 }
185
186out:
187 if (sent_frame)
188 sk->sk_write_space(sk);
189
190 mutex_unlock(&xs->mutex);
191 return err;
192}
193
194static int xsk_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len)
195{
196 struct sock *sk = sock->sk;
197 struct xdp_sock *xs = xdp_sk(sk);
198
199 if (unlikely(!xs->dev))
200 return -ENXIO;
201 if (unlikely(!(xs->dev->flags & IFF_UP)))
202 return -ENETDOWN;
203
204 return xsk_generic_xmit(sk, m, total_len);
205}
206
Björn Töpelc4971762018-05-02 13:01:27 +0200207static unsigned int xsk_poll(struct file *file, struct socket *sock,
208 struct poll_table_struct *wait)
209{
210 unsigned int mask = datagram_poll(file, sock, wait);
211 struct sock *sk = sock->sk;
212 struct xdp_sock *xs = xdp_sk(sk);
213
214 if (xs->rx && !xskq_empty_desc(xs->rx))
215 mask |= POLLIN | POLLRDNORM;
Magnus Karlsson35fcde72018-05-02 13:01:34 +0200216 if (xs->tx && !xskq_full_desc(xs->tx))
217 mask |= POLLOUT | POLLWRNORM;
Björn Töpelc4971762018-05-02 13:01:27 +0200218
219 return mask;
220}
221
Björn Töpelb9b6b682018-05-02 13:01:25 +0200222static int xsk_init_queue(u32 entries, struct xsk_queue **queue,
223 bool umem_queue)
Magnus Karlsson423f3832018-05-02 13:01:24 +0200224{
225 struct xsk_queue *q;
226
227 if (entries == 0 || *queue || !is_power_of_2(entries))
228 return -EINVAL;
229
Björn Töpelb9b6b682018-05-02 13:01:25 +0200230 q = xskq_create(entries, umem_queue);
Magnus Karlsson423f3832018-05-02 13:01:24 +0200231 if (!q)
232 return -ENOMEM;
233
Björn Töpel37b07692018-05-22 09:35:01 +0200234 /* Make sure queue is ready before it can be seen by others */
235 smp_wmb();
Magnus Karlsson423f3832018-05-02 13:01:24 +0200236 *queue = q;
237 return 0;
238}
239
Björn Töpelc0c77d82018-05-02 13:01:23 +0200240static int xsk_release(struct socket *sock)
241{
242 struct sock *sk = sock->sk;
Magnus Karlsson965a9902018-05-02 13:01:26 +0200243 struct xdp_sock *xs = xdp_sk(sk);
Björn Töpelc0c77d82018-05-02 13:01:23 +0200244 struct net *net;
245
246 if (!sk)
247 return 0;
248
249 net = sock_net(sk);
250
251 local_bh_disable();
252 sock_prot_inuse_add(net, sk->sk_prot, -1);
253 local_bh_enable();
254
Magnus Karlsson965a9902018-05-02 13:01:26 +0200255 if (xs->dev) {
Björn Töpel959b71d2018-05-22 09:34:56 +0200256 /* Wait for driver to stop using the xdp socket. */
257 synchronize_net();
258 dev_put(xs->dev);
Magnus Karlsson965a9902018-05-02 13:01:26 +0200259 xs->dev = NULL;
260 }
261
Björn Töpelc0c77d82018-05-02 13:01:23 +0200262 sock_orphan(sk);
263 sock->sk = NULL;
264
265 sk_refcnt_debug_release(sk);
266 sock_put(sk);
267
268 return 0;
269}
270
Magnus Karlsson965a9902018-05-02 13:01:26 +0200271static struct socket *xsk_lookup_xsk_from_fd(int fd)
272{
273 struct socket *sock;
274 int err;
275
276 sock = sockfd_lookup(fd, &err);
277 if (!sock)
278 return ERR_PTR(-ENOTSOCK);
279
280 if (sock->sk->sk_family != PF_XDP) {
281 sockfd_put(sock);
282 return ERR_PTR(-ENOPROTOOPT);
283 }
284
285 return sock;
286}
287
288static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
289{
290 struct sockaddr_xdp *sxdp = (struct sockaddr_xdp *)addr;
291 struct sock *sk = sock->sk;
Magnus Karlsson965a9902018-05-02 13:01:26 +0200292 struct xdp_sock *xs = xdp_sk(sk);
Björn Töpel959b71d2018-05-22 09:34:56 +0200293 struct net_device *dev;
Magnus Karlsson965a9902018-05-02 13:01:26 +0200294 int err = 0;
295
296 if (addr_len < sizeof(struct sockaddr_xdp))
297 return -EINVAL;
298 if (sxdp->sxdp_family != AF_XDP)
299 return -EINVAL;
300
301 mutex_lock(&xs->mutex);
Björn Töpel959b71d2018-05-22 09:34:56 +0200302 if (xs->dev) {
303 err = -EBUSY;
304 goto out_release;
305 }
306
Magnus Karlsson965a9902018-05-02 13:01:26 +0200307 dev = dev_get_by_index(sock_net(sk), sxdp->sxdp_ifindex);
308 if (!dev) {
309 err = -ENODEV;
310 goto out_release;
311 }
312
Magnus Karlssonf6145902018-05-02 13:01:32 +0200313 if (!xs->rx && !xs->tx) {
Magnus Karlsson965a9902018-05-02 13:01:26 +0200314 err = -EINVAL;
315 goto out_unlock;
316 }
317
Magnus Karlsson2e59dd52018-05-22 09:34:58 +0200318 if ((xs->rx && sxdp->sxdp_queue_id >= dev->real_num_rx_queues) ||
319 (xs->tx && sxdp->sxdp_queue_id >= dev->real_num_tx_queues)) {
Magnus Karlsson965a9902018-05-02 13:01:26 +0200320 err = -EINVAL;
321 goto out_unlock;
322 }
323
324 if (sxdp->sxdp_flags & XDP_SHARED_UMEM) {
325 struct xdp_sock *umem_xs;
326 struct socket *sock;
327
328 if (xs->umem) {
329 /* We have already our own. */
330 err = -EINVAL;
331 goto out_unlock;
332 }
333
334 sock = xsk_lookup_xsk_from_fd(sxdp->sxdp_shared_umem_fd);
335 if (IS_ERR(sock)) {
336 err = PTR_ERR(sock);
337 goto out_unlock;
338 }
339
340 umem_xs = xdp_sk(sock->sk);
341 if (!umem_xs->umem) {
342 /* No umem to inherit. */
343 err = -EBADF;
344 sockfd_put(sock);
345 goto out_unlock;
346 } else if (umem_xs->dev != dev ||
347 umem_xs->queue_id != sxdp->sxdp_queue_id) {
348 err = -EINVAL;
349 sockfd_put(sock);
350 goto out_unlock;
351 }
352
353 xdp_get_umem(umem_xs->umem);
Magnus Karlsson965a9902018-05-02 13:01:26 +0200354 xs->umem = umem_xs->umem;
355 sockfd_put(sock);
356 } else if (!xs->umem || !xdp_umem_validate_queues(xs->umem)) {
357 err = -EINVAL;
358 goto out_unlock;
Björn Töpelc4971762018-05-02 13:01:27 +0200359 } else {
360 /* This xsk has its own umem. */
361 xskq_set_umem(xs->umem->fq, &xs->umem->props);
Magnus Karlssonfe230832018-05-02 13:01:31 +0200362 xskq_set_umem(xs->umem->cq, &xs->umem->props);
Magnus Karlsson965a9902018-05-02 13:01:26 +0200363 }
364
Magnus Karlsson965a9902018-05-02 13:01:26 +0200365 xs->dev = dev;
366 xs->queue_id = sxdp->sxdp_queue_id;
367
368 xskq_set_umem(xs->rx, &xs->umem->props);
Magnus Karlsson35fcde72018-05-02 13:01:34 +0200369 xskq_set_umem(xs->tx, &xs->umem->props);
Magnus Karlsson965a9902018-05-02 13:01:26 +0200370
371out_unlock:
372 if (err)
373 dev_put(dev);
374out_release:
375 mutex_unlock(&xs->mutex);
376 return err;
377}
378
Björn Töpelc0c77d82018-05-02 13:01:23 +0200379static int xsk_setsockopt(struct socket *sock, int level, int optname,
380 char __user *optval, unsigned int optlen)
381{
382 struct sock *sk = sock->sk;
383 struct xdp_sock *xs = xdp_sk(sk);
384 int err;
385
386 if (level != SOL_XDP)
387 return -ENOPROTOOPT;
388
389 switch (optname) {
Björn Töpelb9b6b682018-05-02 13:01:25 +0200390 case XDP_RX_RING:
Magnus Karlssonf6145902018-05-02 13:01:32 +0200391 case XDP_TX_RING:
Björn Töpelb9b6b682018-05-02 13:01:25 +0200392 {
393 struct xsk_queue **q;
394 int entries;
395
396 if (optlen < sizeof(entries))
397 return -EINVAL;
398 if (copy_from_user(&entries, optval, sizeof(entries)))
399 return -EFAULT;
400
401 mutex_lock(&xs->mutex);
Magnus Karlssonf6145902018-05-02 13:01:32 +0200402 q = (optname == XDP_TX_RING) ? &xs->tx : &xs->rx;
Björn Töpelb9b6b682018-05-02 13:01:25 +0200403 err = xsk_init_queue(entries, q, false);
404 mutex_unlock(&xs->mutex);
405 return err;
406 }
Björn Töpelc0c77d82018-05-02 13:01:23 +0200407 case XDP_UMEM_REG:
408 {
409 struct xdp_umem_reg mr;
410 struct xdp_umem *umem;
411
Björn Töpelc0c77d82018-05-02 13:01:23 +0200412 if (copy_from_user(&mr, optval, sizeof(mr)))
413 return -EFAULT;
414
415 mutex_lock(&xs->mutex);
Björn Töpela49049e2018-05-22 09:35:02 +0200416 if (xs->umem) {
Björn Töpelc0c77d82018-05-02 13:01:23 +0200417 mutex_unlock(&xs->mutex);
Björn Töpela49049e2018-05-22 09:35:02 +0200418 return -EBUSY;
419 }
420
421 umem = xdp_umem_create(&mr);
422 if (IS_ERR(umem)) {
423 mutex_unlock(&xs->mutex);
424 return PTR_ERR(umem);
Björn Töpelc0c77d82018-05-02 13:01:23 +0200425 }
426
427 /* Make sure umem is ready before it can be seen by others */
428 smp_wmb();
Björn Töpelc0c77d82018-05-02 13:01:23 +0200429 xs->umem = umem;
430 mutex_unlock(&xs->mutex);
431 return 0;
432 }
Magnus Karlsson423f3832018-05-02 13:01:24 +0200433 case XDP_UMEM_FILL_RING:
Magnus Karlssonfe230832018-05-02 13:01:31 +0200434 case XDP_UMEM_COMPLETION_RING:
Magnus Karlsson423f3832018-05-02 13:01:24 +0200435 {
436 struct xsk_queue **q;
437 int entries;
438
Magnus Karlsson423f3832018-05-02 13:01:24 +0200439 if (copy_from_user(&entries, optval, sizeof(entries)))
440 return -EFAULT;
441
442 mutex_lock(&xs->mutex);
Björn Töpela49049e2018-05-22 09:35:02 +0200443 if (!xs->umem) {
444 mutex_unlock(&xs->mutex);
445 return -EINVAL;
446 }
447
Magnus Karlssonfe230832018-05-02 13:01:31 +0200448 q = (optname == XDP_UMEM_FILL_RING) ? &xs->umem->fq :
449 &xs->umem->cq;
Björn Töpelb9b6b682018-05-02 13:01:25 +0200450 err = xsk_init_queue(entries, q, true);
Magnus Karlsson423f3832018-05-02 13:01:24 +0200451 mutex_unlock(&xs->mutex);
452 return err;
453 }
Björn Töpelc0c77d82018-05-02 13:01:23 +0200454 default:
455 break;
456 }
457
458 return -ENOPROTOOPT;
459}
460
Magnus Karlssonaf75d9e2018-05-02 13:01:35 +0200461static int xsk_getsockopt(struct socket *sock, int level, int optname,
462 char __user *optval, int __user *optlen)
463{
464 struct sock *sk = sock->sk;
465 struct xdp_sock *xs = xdp_sk(sk);
466 int len;
467
468 if (level != SOL_XDP)
469 return -ENOPROTOOPT;
470
471 if (get_user(len, optlen))
472 return -EFAULT;
473 if (len < 0)
474 return -EINVAL;
475
476 switch (optname) {
477 case XDP_STATISTICS:
478 {
479 struct xdp_statistics stats;
480
481 if (len < sizeof(stats))
482 return -EINVAL;
483
484 mutex_lock(&xs->mutex);
485 stats.rx_dropped = xs->rx_dropped;
486 stats.rx_invalid_descs = xskq_nb_invalid_descs(xs->rx);
487 stats.tx_invalid_descs = xskq_nb_invalid_descs(xs->tx);
488 mutex_unlock(&xs->mutex);
489
490 if (copy_to_user(optval, &stats, sizeof(stats)))
491 return -EFAULT;
492 if (put_user(sizeof(stats), optlen))
493 return -EFAULT;
494
495 return 0;
496 }
Björn Töpelb3a9e0b2018-05-22 09:34:59 +0200497 case XDP_MMAP_OFFSETS:
498 {
499 struct xdp_mmap_offsets off;
500
501 if (len < sizeof(off))
502 return -EINVAL;
503
504 off.rx.producer = offsetof(struct xdp_rxtx_ring, ptrs.producer);
505 off.rx.consumer = offsetof(struct xdp_rxtx_ring, ptrs.consumer);
506 off.rx.desc = offsetof(struct xdp_rxtx_ring, desc);
507 off.tx.producer = offsetof(struct xdp_rxtx_ring, ptrs.producer);
508 off.tx.consumer = offsetof(struct xdp_rxtx_ring, ptrs.consumer);
509 off.tx.desc = offsetof(struct xdp_rxtx_ring, desc);
510
511 off.fr.producer = offsetof(struct xdp_umem_ring, ptrs.producer);
512 off.fr.consumer = offsetof(struct xdp_umem_ring, ptrs.consumer);
513 off.fr.desc = offsetof(struct xdp_umem_ring, desc);
514 off.cr.producer = offsetof(struct xdp_umem_ring, ptrs.producer);
515 off.cr.consumer = offsetof(struct xdp_umem_ring, ptrs.consumer);
516 off.cr.desc = offsetof(struct xdp_umem_ring, desc);
517
518 len = sizeof(off);
519 if (copy_to_user(optval, &off, len))
520 return -EFAULT;
521 if (put_user(len, optlen))
522 return -EFAULT;
523
524 return 0;
525 }
Magnus Karlssonaf75d9e2018-05-02 13:01:35 +0200526 default:
527 break;
528 }
529
530 return -EOPNOTSUPP;
531}
532
Magnus Karlsson423f3832018-05-02 13:01:24 +0200533static int xsk_mmap(struct file *file, struct socket *sock,
534 struct vm_area_struct *vma)
535{
536 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
537 unsigned long size = vma->vm_end - vma->vm_start;
538 struct xdp_sock *xs = xdp_sk(sock->sk);
539 struct xsk_queue *q = NULL;
Björn Töpel37b07692018-05-22 09:35:01 +0200540 struct xdp_umem *umem;
Magnus Karlsson423f3832018-05-02 13:01:24 +0200541 unsigned long pfn;
542 struct page *qpg;
543
Björn Töpelb9b6b682018-05-02 13:01:25 +0200544 if (offset == XDP_PGOFF_RX_RING) {
Björn Töpel37b07692018-05-22 09:35:01 +0200545 q = READ_ONCE(xs->rx);
Magnus Karlssonf6145902018-05-02 13:01:32 +0200546 } else if (offset == XDP_PGOFF_TX_RING) {
Björn Töpel37b07692018-05-22 09:35:01 +0200547 q = READ_ONCE(xs->tx);
Björn Töpelb9b6b682018-05-02 13:01:25 +0200548 } else {
Björn Töpel37b07692018-05-22 09:35:01 +0200549 umem = READ_ONCE(xs->umem);
550 if (!umem)
Björn Töpelb9b6b682018-05-02 13:01:25 +0200551 return -EINVAL;
Magnus Karlsson423f3832018-05-02 13:01:24 +0200552
Björn Töpelb9b6b682018-05-02 13:01:25 +0200553 if (offset == XDP_UMEM_PGOFF_FILL_RING)
Björn Töpel37b07692018-05-22 09:35:01 +0200554 q = READ_ONCE(umem->fq);
Magnus Karlssonfe230832018-05-02 13:01:31 +0200555 else if (offset == XDP_UMEM_PGOFF_COMPLETION_RING)
Björn Töpel37b07692018-05-22 09:35:01 +0200556 q = READ_ONCE(umem->cq);
Björn Töpelb9b6b682018-05-02 13:01:25 +0200557 }
Magnus Karlsson423f3832018-05-02 13:01:24 +0200558
559 if (!q)
560 return -EINVAL;
561
562 qpg = virt_to_head_page(q->ring);
563 if (size > (PAGE_SIZE << compound_order(qpg)))
564 return -EINVAL;
565
566 pfn = virt_to_phys(q->ring) >> PAGE_SHIFT;
567 return remap_pfn_range(vma, vma->vm_start, pfn,
568 size, vma->vm_page_prot);
569}
570
Björn Töpelc0c77d82018-05-02 13:01:23 +0200571static struct proto xsk_proto = {
572 .name = "XDP",
573 .owner = THIS_MODULE,
574 .obj_size = sizeof(struct xdp_sock),
575};
576
577static const struct proto_ops xsk_proto_ops = {
Björn Töpelc2f43742018-05-18 14:00:24 +0200578 .family = PF_XDP,
579 .owner = THIS_MODULE,
580 .release = xsk_release,
581 .bind = xsk_bind,
582 .connect = sock_no_connect,
583 .socketpair = sock_no_socketpair,
584 .accept = sock_no_accept,
585 .getname = sock_no_getname,
586 .poll = xsk_poll,
587 .ioctl = sock_no_ioctl,
588 .listen = sock_no_listen,
589 .shutdown = sock_no_shutdown,
590 .setsockopt = xsk_setsockopt,
591 .getsockopt = xsk_getsockopt,
592 .sendmsg = xsk_sendmsg,
593 .recvmsg = sock_no_recvmsg,
594 .mmap = xsk_mmap,
595 .sendpage = sock_no_sendpage,
Björn Töpelc0c77d82018-05-02 13:01:23 +0200596};
597
598static void xsk_destruct(struct sock *sk)
599{
600 struct xdp_sock *xs = xdp_sk(sk);
601
602 if (!sock_flag(sk, SOCK_DEAD))
603 return;
604
Björn Töpelb9b6b682018-05-02 13:01:25 +0200605 xskq_destroy(xs->rx);
Magnus Karlssonf6145902018-05-02 13:01:32 +0200606 xskq_destroy(xs->tx);
Björn Töpelc0c77d82018-05-02 13:01:23 +0200607 xdp_put_umem(xs->umem);
608
609 sk_refcnt_debug_dec(sk);
610}
611
612static int xsk_create(struct net *net, struct socket *sock, int protocol,
613 int kern)
614{
615 struct sock *sk;
616 struct xdp_sock *xs;
617
618 if (!ns_capable(net->user_ns, CAP_NET_RAW))
619 return -EPERM;
620 if (sock->type != SOCK_RAW)
621 return -ESOCKTNOSUPPORT;
622
623 if (protocol)
624 return -EPROTONOSUPPORT;
625
626 sock->state = SS_UNCONNECTED;
627
628 sk = sk_alloc(net, PF_XDP, GFP_KERNEL, &xsk_proto, kern);
629 if (!sk)
630 return -ENOBUFS;
631
632 sock->ops = &xsk_proto_ops;
633
634 sock_init_data(sock, sk);
635
636 sk->sk_family = PF_XDP;
637
638 sk->sk_destruct = xsk_destruct;
639 sk_refcnt_debug_inc(sk);
640
641 xs = xdp_sk(sk);
642 mutex_init(&xs->mutex);
643
644 local_bh_disable();
645 sock_prot_inuse_add(net, &xsk_proto, 1);
646 local_bh_enable();
647
648 return 0;
649}
650
651static const struct net_proto_family xsk_family_ops = {
652 .family = PF_XDP,
653 .create = xsk_create,
654 .owner = THIS_MODULE,
655};
656
657static int __init xsk_init(void)
658{
659 int err;
660
661 err = proto_register(&xsk_proto, 0 /* no slab */);
662 if (err)
663 goto out;
664
665 err = sock_register(&xsk_family_ops);
666 if (err)
667 goto out_proto;
668
669 return 0;
670
671out_proto:
672 proto_unregister(&xsk_proto);
673out:
674 return err;
675}
676
677fs_initcall(xsk_init);