From: Magnus Karlsson <magnus.karls...@intel.com>

Another setsockopt (XDP_TX_QUEUE) is added to let the process allocate
a queue, where the user process can pass frames to be transmitted by
the kernel.

The mmapping of the queue is done using the XDP_PGOFF_TX_QUEUE offset.

Signed-off-by: Magnus Karlsson <magnus.karls...@intel.com>
---
 include/uapi/linux/if_xdp.h | 2 ++
 net/xdp/xsk.c               | 9 +++++++--
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/if_xdp.h b/include/uapi/linux/if_xdp.h
index aec2eee4e751..6cab56fb8be6 100644
--- a/include/uapi/linux/if_xdp.h
+++ b/include/uapi/linux/if_xdp.h
@@ -33,6 +33,7 @@ struct sockaddr_xdp {
 
 /* XDP socket options */
 #define XDP_RX_QUEUE             1
+#define XDP_TX_QUEUE             2
 #define XDP_UMEM_REG             3
 #define XDP_UMEM_FILL_QUEUE      4
 #define XDP_UMEM_COMPLETION_QUEUE 5
@@ -46,6 +47,7 @@ struct xdp_umem_reg {
 
 /* Pgoff for mmaping the rings */
 #define XDP_PGOFF_RX_QUEUE                       0
+#define XDP_PGOFF_TX_QUEUE              0x80000000
 #define XDP_UMEM_PGOFF_FILL_QUEUE      0x100000000
 #define XDP_UMEM_PGOFF_COMPLETION_QUEUE 0x180000000
 
diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
index 2071365c39b1..a9bceb0958d8 100644
--- a/net/xdp/xsk.c
+++ b/net/xdp/xsk.c
@@ -43,6 +43,7 @@ struct xdp_sock {
        struct xsk_queue *rx;
        struct xskq_iter rx_it;
        u64 rx_dropped;
+       struct xsk_queue *tx;
        struct net_device *dev;
        /* Protects multiple processes in the control path */
        struct mutex mutex;
@@ -218,7 +219,7 @@ static int xsk_bind(struct socket *sock, struct sockaddr 
*addr, int addr_len)
                goto out_release;
        }
 
-       if (!xs->rx) {
+       if (!xs->rx && !xs->tx) {
                err = -EINVAL;
                goto out_unlock;
        }
@@ -303,6 +304,7 @@ static int xsk_setsockopt(struct socket *sock, int level, 
int optname,
 
        switch (optname) {
        case XDP_RX_QUEUE:
+       case XDP_TX_QUEUE:
        {
                struct xsk_queue **q;
                int entries;
@@ -313,7 +315,7 @@ static int xsk_setsockopt(struct socket *sock, int level, 
int optname,
                        return -EFAULT;
 
                mutex_lock(&xs->mutex);
-               q = &xs->rx;
+               q = (optname == XDP_TX_QUEUE) ? &xs->tx : &xs->rx;
                err = xsk_init_queue(entries, q, false);
                mutex_unlock(&xs->mutex);
                return err;
@@ -385,6 +387,8 @@ static int xsk_mmap(struct file *file, struct socket *sock,
 
        if (offset == XDP_PGOFF_RX_QUEUE) {
                q = xs->rx;
+       } else if (offset == XDP_PGOFF_TX_QUEUE) {
+               q = xs->tx;
        } else {
                if (!xs->umem)
                        return -EINVAL;
@@ -443,6 +447,7 @@ static void xsk_destruct(struct sock *sk)
                return;
 
        xskq_destroy(xs->rx);
+       xskq_destroy(xs->tx);
        xdp_put_umem(xs->umem);
 
        sk_refcnt_debug_dec(sk);
-- 
2.14.1

Reply via email to