Commit fe230832 authored by Magnus Karlsson's avatar Magnus Karlsson Committed by Alexei Starovoitov

xsk: add umem completion queue support and mmap

Here, we add another setsockopt for registered user memory (umem)
called XDP_UMEM_COMPLETION_QUEUE. Using this socket option, the
process can ask the kernel to allocate a queue (ring buffer) and also
mmap it (XDP_UMEM_PGOFF_COMPLETION_QUEUE) into the process.

The queue is used to explicitly pass ownership of umem frames from the
kernel to user process. This will be used by the TX path to tell user
space that a certain frame has been transmitted and user space can use
it for something else, if it wishes.
Signed-off-by: default avatarMagnus Karlsson <magnus.karlsson@intel.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 02671e23
...@@ -36,6 +36,7 @@ struct sockaddr_xdp { ...@@ -36,6 +36,7 @@ struct sockaddr_xdp {
#define XDP_RX_RING 1 #define XDP_RX_RING 1
#define XDP_UMEM_REG 3 #define XDP_UMEM_REG 3
#define XDP_UMEM_FILL_RING 4 #define XDP_UMEM_FILL_RING 4
#define XDP_UMEM_COMPLETION_RING 5
struct xdp_umem_reg { struct xdp_umem_reg {
__u64 addr; /* Start of packet data area */ __u64 addr; /* Start of packet data area */
...@@ -47,6 +48,7 @@ struct xdp_umem_reg { ...@@ -47,6 +48,7 @@ struct xdp_umem_reg {
/* Pgoff for mmaping the rings */ /* Pgoff for mmaping the rings */
#define XDP_PGOFF_RX_RING 0 #define XDP_PGOFF_RX_RING 0
#define XDP_UMEM_PGOFF_FILL_RING 0x100000000 #define XDP_UMEM_PGOFF_FILL_RING 0x100000000
#define XDP_UMEM_PGOFF_COMPLETION_RING 0x180000000
struct xdp_desc { struct xdp_desc {
__u32 idx; __u32 idx;
......
...@@ -70,6 +70,11 @@ static void xdp_umem_release(struct xdp_umem *umem) ...@@ -70,6 +70,11 @@ static void xdp_umem_release(struct xdp_umem *umem)
umem->fq = NULL; umem->fq = NULL;
} }
if (umem->cq) {
xskq_destroy(umem->cq);
umem->cq = NULL;
}
if (umem->pgs) { if (umem->pgs) {
xdp_umem_unpin_pages(umem); xdp_umem_unpin_pages(umem);
...@@ -251,5 +256,5 @@ int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) ...@@ -251,5 +256,5 @@ int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
bool xdp_umem_validate_queues(struct xdp_umem *umem) bool xdp_umem_validate_queues(struct xdp_umem *umem)
{ {
return umem->fq; return (umem->fq && umem->cq);
} }
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
struct xdp_umem { struct xdp_umem {
struct xsk_queue *fq; struct xsk_queue *fq;
struct xsk_queue *cq;
struct page **pgs; struct page **pgs;
struct xdp_umem_props props; struct xdp_umem_props props;
u32 npgs; u32 npgs;
......
...@@ -255,6 +255,7 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len) ...@@ -255,6 +255,7 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
} else { } else {
/* This xsk has its own umem. */ /* This xsk has its own umem. */
xskq_set_umem(xs->umem->fq, &xs->umem->props); xskq_set_umem(xs->umem->fq, &xs->umem->props);
xskq_set_umem(xs->umem->cq, &xs->umem->props);
} }
/* Rebind? */ /* Rebind? */
...@@ -334,6 +335,7 @@ static int xsk_setsockopt(struct socket *sock, int level, int optname, ...@@ -334,6 +335,7 @@ static int xsk_setsockopt(struct socket *sock, int level, int optname,
return 0; return 0;
} }
case XDP_UMEM_FILL_RING: case XDP_UMEM_FILL_RING:
case XDP_UMEM_COMPLETION_RING:
{ {
struct xsk_queue **q; struct xsk_queue **q;
int entries; int entries;
...@@ -345,7 +347,8 @@ static int xsk_setsockopt(struct socket *sock, int level, int optname, ...@@ -345,7 +347,8 @@ static int xsk_setsockopt(struct socket *sock, int level, int optname,
return -EFAULT; return -EFAULT;
mutex_lock(&xs->mutex); mutex_lock(&xs->mutex);
q = &xs->umem->fq; q = (optname == XDP_UMEM_FILL_RING) ? &xs->umem->fq :
&xs->umem->cq;
err = xsk_init_queue(entries, q, true); err = xsk_init_queue(entries, q, true);
mutex_unlock(&xs->mutex); mutex_unlock(&xs->mutex);
return err; return err;
...@@ -375,6 +378,8 @@ static int xsk_mmap(struct file *file, struct socket *sock, ...@@ -375,6 +378,8 @@ static int xsk_mmap(struct file *file, struct socket *sock,
if (offset == XDP_UMEM_PGOFF_FILL_RING) if (offset == XDP_UMEM_PGOFF_FILL_RING)
q = xs->umem->fq; q = xs->umem->fq;
else if (offset == XDP_UMEM_PGOFF_COMPLETION_RING)
q = xs->umem->cq;
else else
return -EINVAL; return -EINVAL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment