blob: 966307ce4b8e67f0d1085cf65b364a1e17b6c11f [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öpel4e64c832018-06-04 13:57:11 +020044 u32 id, len = xdp->data_end - xdp->data;
Björn Töpelc4971762018-05-02 13:01:27 +020045 void *buffer;
Björn Töpel4e64c832018-06-04 13:57:11 +020046 int err;
Björn Töpelc4971762018-05-02 13:01:27 +020047
48 if (xs->dev != xdp->rxq->dev || xs->queue_id != xdp->rxq->queue_index)
49 return -EINVAL;
50
Björn Töpela509a952018-06-04 13:57:12 +020051 if (!xskq_peek_id(xs->umem->fq, &id)) {
52 xs->rx_dropped++;
Björn Töpelc4971762018-05-02 13:01:27 +020053 return -ENOSPC;
Björn Töpela509a952018-06-04 13:57:12 +020054 }
Björn Töpelc4971762018-05-02 13:01:27 +020055
Björn Töpel4e64c832018-06-04 13:57:11 +020056 buffer = xdp_umem_get_data_with_headroom(xs->umem, id);
Björn Töpelc4971762018-05-02 13:01:27 +020057 memcpy(buffer, xdp->data, len);
Björn Töpel4e64c832018-06-04 13:57:11 +020058 err = xskq_produce_batch_desc(xs->rx, id, len,
Björn Töpelc4971762018-05-02 13:01:27 +020059 xs->umem->frame_headroom);
60 if (!err)
61 xskq_discard_id(xs->umem->fq);
Björn Töpela509a952018-06-04 13:57:12 +020062 else
63 xs->rx_dropped++;
Björn Töpelc4971762018-05-02 13:01:27 +020064
65 return err;
66}
67
68int xsk_rcv(struct xdp_sock *xs, struct xdp_buff *xdp)
69{
70 int err;
71
72 err = __xsk_rcv(xs, xdp);
73 if (likely(!err))
74 xdp_return_buff(xdp);
Björn Töpelc4971762018-05-02 13:01:27 +020075
76 return err;
77}
78
79void xsk_flush(struct xdp_sock *xs)
80{
81 xskq_produce_flush_desc(xs->rx);
82 xs->sk.sk_data_ready(&xs->sk);
83}
84
85int xsk_generic_rcv(struct xdp_sock *xs, struct xdp_buff *xdp)
86{
87 int err;
88
89 err = __xsk_rcv(xs, xdp);
90 if (!err)
91 xsk_flush(xs);
Björn Töpelc4971762018-05-02 13:01:27 +020092
93 return err;
94}
95
Magnus Karlsson35fcde72018-05-02 13:01:34 +020096static void xsk_destruct_skb(struct sk_buff *skb)
97{
98 u32 id = (u32)(long)skb_shinfo(skb)->destructor_arg;
99 struct xdp_sock *xs = xdp_sk(skb->sk);
100
101 WARN_ON_ONCE(xskq_produce_id(xs->umem->cq, id));
102
103 sock_wfree(skb);
104}
105
106static int xsk_generic_xmit(struct sock *sk, struct msghdr *m,
107 size_t total_len)
108{
109 bool need_wait = !(m->msg_flags & MSG_DONTWAIT);
110 u32 max_batch = TX_BATCH_SIZE;
111 struct xdp_sock *xs = xdp_sk(sk);
112 bool sent_frame = false;
113 struct xdp_desc desc;
114 struct sk_buff *skb;
115 int err = 0;
116
117 if (unlikely(!xs->tx))
118 return -ENOBUFS;
119 if (need_wait)
120 return -EOPNOTSUPP;
121
122 mutex_lock(&xs->mutex);
123
124 while (xskq_peek_desc(xs->tx, &desc)) {
125 char *buffer;
126 u32 id, len;
127
128 if (max_batch-- == 0) {
129 err = -EAGAIN;
130 goto out;
131 }
132
133 if (xskq_reserve_id(xs->umem->cq)) {
134 err = -EAGAIN;
135 goto out;
136 }
137
138 len = desc.len;
139 if (unlikely(len > xs->dev->mtu)) {
140 err = -EMSGSIZE;
141 goto out;
142 }
143
Magnus Karlsson2e59dd52018-05-22 09:34:58 +0200144 if (xs->queue_id >= xs->dev->real_num_tx_queues) {
145 err = -ENXIO;
146 goto out;
147 }
148
Magnus Karlsson35fcde72018-05-02 13:01:34 +0200149 skb = sock_alloc_send_skb(sk, len, !need_wait, &err);
150 if (unlikely(!skb)) {
151 err = -EAGAIN;
152 goto out;
153 }
154
155 skb_put(skb, len);
156 id = desc.idx;
157 buffer = xdp_umem_get_data(xs->umem, id) + desc.offset;
158 err = skb_store_bits(skb, 0, buffer, len);
159 if (unlikely(err)) {
160 kfree_skb(skb);
161 goto out;
162 }
163
164 skb->dev = xs->dev;
165 skb->priority = sk->sk_priority;
166 skb->mark = sk->sk_mark;
167 skb_shinfo(skb)->destructor_arg = (void *)(long)id;
168 skb->destructor = xsk_destruct_skb;
169
170 err = dev_direct_xmit(skb, xs->queue_id);
171 /* Ignore NET_XMIT_CN as packet might have been sent */
172 if (err == NET_XMIT_DROP || err == NETDEV_TX_BUSY) {
173 err = -EAGAIN;
174 /* SKB consumed by dev_direct_xmit() */
175 goto out;
176 }
177
178 sent_frame = true;
179 xskq_discard_desc(xs->tx);
180 }
181
182out:
183 if (sent_frame)
184 sk->sk_write_space(sk);
185
186 mutex_unlock(&xs->mutex);
187 return err;
188}
189
190static int xsk_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len)
191{
192 struct sock *sk = sock->sk;
193 struct xdp_sock *xs = xdp_sk(sk);
194
195 if (unlikely(!xs->dev))
196 return -ENXIO;
197 if (unlikely(!(xs->dev->flags & IFF_UP)))
198 return -ENETDOWN;
199
200 return xsk_generic_xmit(sk, m, total_len);
201}
202
Björn Töpelc4971762018-05-02 13:01:27 +0200203static unsigned int xsk_poll(struct file *file, struct socket *sock,
204 struct poll_table_struct *wait)
205{
206 unsigned int mask = datagram_poll(file, sock, wait);
207 struct sock *sk = sock->sk;
208 struct xdp_sock *xs = xdp_sk(sk);
209
210 if (xs->rx && !xskq_empty_desc(xs->rx))
211 mask |= POLLIN | POLLRDNORM;
Magnus Karlsson35fcde72018-05-02 13:01:34 +0200212 if (xs->tx && !xskq_full_desc(xs->tx))
213 mask |= POLLOUT | POLLWRNORM;
Björn Töpelc4971762018-05-02 13:01:27 +0200214
215 return mask;
216}
217
Björn Töpelb9b6b682018-05-02 13:01:25 +0200218static int xsk_init_queue(u32 entries, struct xsk_queue **queue,
219 bool umem_queue)
Magnus Karlsson423f3832018-05-02 13:01:24 +0200220{
221 struct xsk_queue *q;
222
223 if (entries == 0 || *queue || !is_power_of_2(entries))
224 return -EINVAL;
225
Björn Töpelb9b6b682018-05-02 13:01:25 +0200226 q = xskq_create(entries, umem_queue);
Magnus Karlsson423f3832018-05-02 13:01:24 +0200227 if (!q)
228 return -ENOMEM;
229
Björn Töpel37b07692018-05-22 09:35:01 +0200230 /* Make sure queue is ready before it can be seen by others */
231 smp_wmb();
Magnus Karlsson423f3832018-05-02 13:01:24 +0200232 *queue = q;
233 return 0;
234}
235
Björn Töpelc0c77d82018-05-02 13:01:23 +0200236static int xsk_release(struct socket *sock)
237{
238 struct sock *sk = sock->sk;
Magnus Karlsson965a9902018-05-02 13:01:26 +0200239 struct xdp_sock *xs = xdp_sk(sk);
Björn Töpelc0c77d82018-05-02 13:01:23 +0200240 struct net *net;
241
242 if (!sk)
243 return 0;
244
245 net = sock_net(sk);
246
247 local_bh_disable();
248 sock_prot_inuse_add(net, sk->sk_prot, -1);
249 local_bh_enable();
250
Magnus Karlsson965a9902018-05-02 13:01:26 +0200251 if (xs->dev) {
Björn Töpel959b71d2018-05-22 09:34:56 +0200252 /* Wait for driver to stop using the xdp socket. */
253 synchronize_net();
254 dev_put(xs->dev);
Magnus Karlsson965a9902018-05-02 13:01:26 +0200255 xs->dev = NULL;
256 }
257
Björn Töpelc0c77d82018-05-02 13:01:23 +0200258 sock_orphan(sk);
259 sock->sk = NULL;
260
261 sk_refcnt_debug_release(sk);
262 sock_put(sk);
263
264 return 0;
265}
266
Magnus Karlsson965a9902018-05-02 13:01:26 +0200267static struct socket *xsk_lookup_xsk_from_fd(int fd)
268{
269 struct socket *sock;
270 int err;
271
272 sock = sockfd_lookup(fd, &err);
273 if (!sock)
274 return ERR_PTR(-ENOTSOCK);
275
276 if (sock->sk->sk_family != PF_XDP) {
277 sockfd_put(sock);
278 return ERR_PTR(-ENOPROTOOPT);
279 }
280
281 return sock;
282}
283
284static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
285{
286 struct sockaddr_xdp *sxdp = (struct sockaddr_xdp *)addr;
287 struct sock *sk = sock->sk;
Magnus Karlsson965a9902018-05-02 13:01:26 +0200288 struct xdp_sock *xs = xdp_sk(sk);
Björn Töpel959b71d2018-05-22 09:34:56 +0200289 struct net_device *dev;
Magnus Karlsson965a9902018-05-02 13:01:26 +0200290 int err = 0;
291
292 if (addr_len < sizeof(struct sockaddr_xdp))
293 return -EINVAL;
294 if (sxdp->sxdp_family != AF_XDP)
295 return -EINVAL;
296
297 mutex_lock(&xs->mutex);
Björn Töpel959b71d2018-05-22 09:34:56 +0200298 if (xs->dev) {
299 err = -EBUSY;
300 goto out_release;
301 }
302
Magnus Karlsson965a9902018-05-02 13:01:26 +0200303 dev = dev_get_by_index(sock_net(sk), sxdp->sxdp_ifindex);
304 if (!dev) {
305 err = -ENODEV;
306 goto out_release;
307 }
308
Magnus Karlssonf6145902018-05-02 13:01:32 +0200309 if (!xs->rx && !xs->tx) {
Magnus Karlsson965a9902018-05-02 13:01:26 +0200310 err = -EINVAL;
311 goto out_unlock;
312 }
313
Magnus Karlsson2e59dd52018-05-22 09:34:58 +0200314 if ((xs->rx && sxdp->sxdp_queue_id >= dev->real_num_rx_queues) ||
315 (xs->tx && sxdp->sxdp_queue_id >= dev->real_num_tx_queues)) {
Magnus Karlsson965a9902018-05-02 13:01:26 +0200316 err = -EINVAL;
317 goto out_unlock;
318 }
319
320 if (sxdp->sxdp_flags & XDP_SHARED_UMEM) {
321 struct xdp_sock *umem_xs;
322 struct socket *sock;
323
324 if (xs->umem) {
325 /* We have already our own. */
326 err = -EINVAL;
327 goto out_unlock;
328 }
329
330 sock = xsk_lookup_xsk_from_fd(sxdp->sxdp_shared_umem_fd);
331 if (IS_ERR(sock)) {
332 err = PTR_ERR(sock);
333 goto out_unlock;
334 }
335
336 umem_xs = xdp_sk(sock->sk);
337 if (!umem_xs->umem) {
338 /* No umem to inherit. */
339 err = -EBADF;
340 sockfd_put(sock);
341 goto out_unlock;
342 } else if (umem_xs->dev != dev ||
343 umem_xs->queue_id != sxdp->sxdp_queue_id) {
344 err = -EINVAL;
345 sockfd_put(sock);
346 goto out_unlock;
347 }
348
349 xdp_get_umem(umem_xs->umem);
Magnus Karlsson965a9902018-05-02 13:01:26 +0200350 xs->umem = umem_xs->umem;
351 sockfd_put(sock);
352 } else if (!xs->umem || !xdp_umem_validate_queues(xs->umem)) {
353 err = -EINVAL;
354 goto out_unlock;
Björn Töpelc4971762018-05-02 13:01:27 +0200355 } else {
356 /* This xsk has its own umem. */
357 xskq_set_umem(xs->umem->fq, &xs->umem->props);
Magnus Karlssonfe230832018-05-02 13:01:31 +0200358 xskq_set_umem(xs->umem->cq, &xs->umem->props);
Magnus Karlsson965a9902018-05-02 13:01:26 +0200359 }
360
Magnus Karlsson965a9902018-05-02 13:01:26 +0200361 xs->dev = dev;
362 xs->queue_id = sxdp->sxdp_queue_id;
363
364 xskq_set_umem(xs->rx, &xs->umem->props);
Magnus Karlsson35fcde72018-05-02 13:01:34 +0200365 xskq_set_umem(xs->tx, &xs->umem->props);
Magnus Karlsson965a9902018-05-02 13:01:26 +0200366
367out_unlock:
368 if (err)
369 dev_put(dev);
370out_release:
371 mutex_unlock(&xs->mutex);
372 return err;
373}
374
Björn Töpelc0c77d82018-05-02 13:01:23 +0200375static int xsk_setsockopt(struct socket *sock, int level, int optname,
376 char __user *optval, unsigned int optlen)
377{
378 struct sock *sk = sock->sk;
379 struct xdp_sock *xs = xdp_sk(sk);
380 int err;
381
382 if (level != SOL_XDP)
383 return -ENOPROTOOPT;
384
385 switch (optname) {
Björn Töpelb9b6b682018-05-02 13:01:25 +0200386 case XDP_RX_RING:
Magnus Karlssonf6145902018-05-02 13:01:32 +0200387 case XDP_TX_RING:
Björn Töpelb9b6b682018-05-02 13:01:25 +0200388 {
389 struct xsk_queue **q;
390 int entries;
391
392 if (optlen < sizeof(entries))
393 return -EINVAL;
394 if (copy_from_user(&entries, optval, sizeof(entries)))
395 return -EFAULT;
396
397 mutex_lock(&xs->mutex);
Magnus Karlssonf6145902018-05-02 13:01:32 +0200398 q = (optname == XDP_TX_RING) ? &xs->tx : &xs->rx;
Björn Töpelb9b6b682018-05-02 13:01:25 +0200399 err = xsk_init_queue(entries, q, false);
400 mutex_unlock(&xs->mutex);
401 return err;
402 }
Björn Töpelc0c77d82018-05-02 13:01:23 +0200403 case XDP_UMEM_REG:
404 {
405 struct xdp_umem_reg mr;
406 struct xdp_umem *umem;
407
Björn Töpelc0c77d82018-05-02 13:01:23 +0200408 if (copy_from_user(&mr, optval, sizeof(mr)))
409 return -EFAULT;
410
411 mutex_lock(&xs->mutex);
Björn Töpela49049e2018-05-22 09:35:02 +0200412 if (xs->umem) {
Björn Töpelc0c77d82018-05-02 13:01:23 +0200413 mutex_unlock(&xs->mutex);
Björn Töpela49049e2018-05-22 09:35:02 +0200414 return -EBUSY;
415 }
416
417 umem = xdp_umem_create(&mr);
418 if (IS_ERR(umem)) {
419 mutex_unlock(&xs->mutex);
420 return PTR_ERR(umem);
Björn Töpelc0c77d82018-05-02 13:01:23 +0200421 }
422
423 /* Make sure umem is ready before it can be seen by others */
424 smp_wmb();
Björn Töpelc0c77d82018-05-02 13:01:23 +0200425 xs->umem = umem;
426 mutex_unlock(&xs->mutex);
427 return 0;
428 }
Magnus Karlsson423f3832018-05-02 13:01:24 +0200429 case XDP_UMEM_FILL_RING:
Magnus Karlssonfe230832018-05-02 13:01:31 +0200430 case XDP_UMEM_COMPLETION_RING:
Magnus Karlsson423f3832018-05-02 13:01:24 +0200431 {
432 struct xsk_queue **q;
433 int entries;
434
Magnus Karlsson423f3832018-05-02 13:01:24 +0200435 if (copy_from_user(&entries, optval, sizeof(entries)))
436 return -EFAULT;
437
438 mutex_lock(&xs->mutex);
Björn Töpela49049e2018-05-22 09:35:02 +0200439 if (!xs->umem) {
440 mutex_unlock(&xs->mutex);
441 return -EINVAL;
442 }
443
Magnus Karlssonfe230832018-05-02 13:01:31 +0200444 q = (optname == XDP_UMEM_FILL_RING) ? &xs->umem->fq :
445 &xs->umem->cq;
Björn Töpelb9b6b682018-05-02 13:01:25 +0200446 err = xsk_init_queue(entries, q, true);
Magnus Karlsson423f3832018-05-02 13:01:24 +0200447 mutex_unlock(&xs->mutex);
448 return err;
449 }
Björn Töpelc0c77d82018-05-02 13:01:23 +0200450 default:
451 break;
452 }
453
454 return -ENOPROTOOPT;
455}
456
Magnus Karlssonaf75d9e2018-05-02 13:01:35 +0200457static int xsk_getsockopt(struct socket *sock, int level, int optname,
458 char __user *optval, int __user *optlen)
459{
460 struct sock *sk = sock->sk;
461 struct xdp_sock *xs = xdp_sk(sk);
462 int len;
463
464 if (level != SOL_XDP)
465 return -ENOPROTOOPT;
466
467 if (get_user(len, optlen))
468 return -EFAULT;
469 if (len < 0)
470 return -EINVAL;
471
472 switch (optname) {
473 case XDP_STATISTICS:
474 {
475 struct xdp_statistics stats;
476
477 if (len < sizeof(stats))
478 return -EINVAL;
479
480 mutex_lock(&xs->mutex);
481 stats.rx_dropped = xs->rx_dropped;
482 stats.rx_invalid_descs = xskq_nb_invalid_descs(xs->rx);
483 stats.tx_invalid_descs = xskq_nb_invalid_descs(xs->tx);
484 mutex_unlock(&xs->mutex);
485
486 if (copy_to_user(optval, &stats, sizeof(stats)))
487 return -EFAULT;
488 if (put_user(sizeof(stats), optlen))
489 return -EFAULT;
490
491 return 0;
492 }
Björn Töpelb3a9e0b2018-05-22 09:34:59 +0200493 case XDP_MMAP_OFFSETS:
494 {
495 struct xdp_mmap_offsets off;
496
497 if (len < sizeof(off))
498 return -EINVAL;
499
500 off.rx.producer = offsetof(struct xdp_rxtx_ring, ptrs.producer);
501 off.rx.consumer = offsetof(struct xdp_rxtx_ring, ptrs.consumer);
502 off.rx.desc = offsetof(struct xdp_rxtx_ring, desc);
503 off.tx.producer = offsetof(struct xdp_rxtx_ring, ptrs.producer);
504 off.tx.consumer = offsetof(struct xdp_rxtx_ring, ptrs.consumer);
505 off.tx.desc = offsetof(struct xdp_rxtx_ring, desc);
506
507 off.fr.producer = offsetof(struct xdp_umem_ring, ptrs.producer);
508 off.fr.consumer = offsetof(struct xdp_umem_ring, ptrs.consumer);
509 off.fr.desc = offsetof(struct xdp_umem_ring, desc);
510 off.cr.producer = offsetof(struct xdp_umem_ring, ptrs.producer);
511 off.cr.consumer = offsetof(struct xdp_umem_ring, ptrs.consumer);
512 off.cr.desc = offsetof(struct xdp_umem_ring, desc);
513
514 len = sizeof(off);
515 if (copy_to_user(optval, &off, len))
516 return -EFAULT;
517 if (put_user(len, optlen))
518 return -EFAULT;
519
520 return 0;
521 }
Magnus Karlssonaf75d9e2018-05-02 13:01:35 +0200522 default:
523 break;
524 }
525
526 return -EOPNOTSUPP;
527}
528
Magnus Karlsson423f3832018-05-02 13:01:24 +0200529static int xsk_mmap(struct file *file, struct socket *sock,
530 struct vm_area_struct *vma)
531{
532 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
533 unsigned long size = vma->vm_end - vma->vm_start;
534 struct xdp_sock *xs = xdp_sk(sock->sk);
535 struct xsk_queue *q = NULL;
Björn Töpel37b07692018-05-22 09:35:01 +0200536 struct xdp_umem *umem;
Magnus Karlsson423f3832018-05-02 13:01:24 +0200537 unsigned long pfn;
538 struct page *qpg;
539
Björn Töpelb9b6b682018-05-02 13:01:25 +0200540 if (offset == XDP_PGOFF_RX_RING) {
Björn Töpel37b07692018-05-22 09:35:01 +0200541 q = READ_ONCE(xs->rx);
Magnus Karlssonf6145902018-05-02 13:01:32 +0200542 } else if (offset == XDP_PGOFF_TX_RING) {
Björn Töpel37b07692018-05-22 09:35:01 +0200543 q = READ_ONCE(xs->tx);
Björn Töpelb9b6b682018-05-02 13:01:25 +0200544 } else {
Björn Töpel37b07692018-05-22 09:35:01 +0200545 umem = READ_ONCE(xs->umem);
546 if (!umem)
Björn Töpelb9b6b682018-05-02 13:01:25 +0200547 return -EINVAL;
Magnus Karlsson423f3832018-05-02 13:01:24 +0200548
Björn Töpelb9b6b682018-05-02 13:01:25 +0200549 if (offset == XDP_UMEM_PGOFF_FILL_RING)
Björn Töpel37b07692018-05-22 09:35:01 +0200550 q = READ_ONCE(umem->fq);
Magnus Karlssonfe230832018-05-02 13:01:31 +0200551 else if (offset == XDP_UMEM_PGOFF_COMPLETION_RING)
Björn Töpel37b07692018-05-22 09:35:01 +0200552 q = READ_ONCE(umem->cq);
Björn Töpelb9b6b682018-05-02 13:01:25 +0200553 }
Magnus Karlsson423f3832018-05-02 13:01:24 +0200554
555 if (!q)
556 return -EINVAL;
557
558 qpg = virt_to_head_page(q->ring);
559 if (size > (PAGE_SIZE << compound_order(qpg)))
560 return -EINVAL;
561
562 pfn = virt_to_phys(q->ring) >> PAGE_SHIFT;
563 return remap_pfn_range(vma, vma->vm_start, pfn,
564 size, vma->vm_page_prot);
565}
566
Björn Töpelc0c77d82018-05-02 13:01:23 +0200567static struct proto xsk_proto = {
568 .name = "XDP",
569 .owner = THIS_MODULE,
570 .obj_size = sizeof(struct xdp_sock),
571};
572
573static const struct proto_ops xsk_proto_ops = {
Björn Töpelc2f43742018-05-18 14:00:24 +0200574 .family = PF_XDP,
575 .owner = THIS_MODULE,
576 .release = xsk_release,
577 .bind = xsk_bind,
578 .connect = sock_no_connect,
579 .socketpair = sock_no_socketpair,
580 .accept = sock_no_accept,
581 .getname = sock_no_getname,
582 .poll = xsk_poll,
583 .ioctl = sock_no_ioctl,
584 .listen = sock_no_listen,
585 .shutdown = sock_no_shutdown,
586 .setsockopt = xsk_setsockopt,
587 .getsockopt = xsk_getsockopt,
588 .sendmsg = xsk_sendmsg,
589 .recvmsg = sock_no_recvmsg,
590 .mmap = xsk_mmap,
591 .sendpage = sock_no_sendpage,
Björn Töpelc0c77d82018-05-02 13:01:23 +0200592};
593
594static void xsk_destruct(struct sock *sk)
595{
596 struct xdp_sock *xs = xdp_sk(sk);
597
598 if (!sock_flag(sk, SOCK_DEAD))
599 return;
600
Björn Töpelb9b6b682018-05-02 13:01:25 +0200601 xskq_destroy(xs->rx);
Magnus Karlssonf6145902018-05-02 13:01:32 +0200602 xskq_destroy(xs->tx);
Björn Töpelc0c77d82018-05-02 13:01:23 +0200603 xdp_put_umem(xs->umem);
604
605 sk_refcnt_debug_dec(sk);
606}
607
608static int xsk_create(struct net *net, struct socket *sock, int protocol,
609 int kern)
610{
611 struct sock *sk;
612 struct xdp_sock *xs;
613
614 if (!ns_capable(net->user_ns, CAP_NET_RAW))
615 return -EPERM;
616 if (sock->type != SOCK_RAW)
617 return -ESOCKTNOSUPPORT;
618
619 if (protocol)
620 return -EPROTONOSUPPORT;
621
622 sock->state = SS_UNCONNECTED;
623
624 sk = sk_alloc(net, PF_XDP, GFP_KERNEL, &xsk_proto, kern);
625 if (!sk)
626 return -ENOBUFS;
627
628 sock->ops = &xsk_proto_ops;
629
630 sock_init_data(sock, sk);
631
632 sk->sk_family = PF_XDP;
633
634 sk->sk_destruct = xsk_destruct;
635 sk_refcnt_debug_inc(sk);
636
637 xs = xdp_sk(sk);
638 mutex_init(&xs->mutex);
639
640 local_bh_disable();
641 sock_prot_inuse_add(net, &xsk_proto, 1);
642 local_bh_enable();
643
644 return 0;
645}
646
647static const struct net_proto_family xsk_family_ops = {
648 .family = PF_XDP,
649 .create = xsk_create,
650 .owner = THIS_MODULE,
651};
652
653static int __init xsk_init(void)
654{
655 int err;
656
657 err = proto_register(&xsk_proto, 0 /* no slab */);
658 if (err)
659 goto out;
660
661 err = sock_register(&xsk_family_ops);
662 if (err)
663 goto out_proto;
664
665 return 0;
666
667out_proto:
668 proto_unregister(&xsk_proto);
669out:
670 return err;
671}
672
673fs_initcall(xsk_init);