Message ID | 20231219210357.4029713-11-dw@davidwei.uk (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Zero copy Rx using io_uring | expand |
On 12/19/23 2:03 PM, David Wei wrote: > From: David Wei <davidhwei@meta.com> > > This patch sets up ZC for an Rx queue in a net device when an ifq is > registered with io_uring. The Rx queue is specified in the registration > struct. > > For now since there is only one ifq, its destruction is implicit during > io_uring cleanup. > > Signed-off-by: David Wei <dw@davidwei.uk> > --- > io_uring/zc_rx.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 43 insertions(+), 2 deletions(-) > > diff --git a/io_uring/zc_rx.c b/io_uring/zc_rx.c > index 7e3e6f6d446b..259e08a34ab2 100644 > --- a/io_uring/zc_rx.c > +++ b/io_uring/zc_rx.c > @@ -4,6 +4,7 @@ > #include <linux/errno.h> > #include <linux/mm.h> > #include <linux/io_uring.h> > +#include <linux/netdevice.h> > > #include <uapi/linux/io_uring.h> > > @@ -11,6 +12,34 @@ > #include "kbuf.h" > #include "zc_rx.h" > > +typedef int (*bpf_op_t)(struct net_device *dev, struct netdev_bpf *bpf); Let's get rid of this, since it isn't even typedef'ed on the networking side. Doesn't really buy us anything, and it's only used once anyway.
On 12/20/23 16:06, Jens Axboe wrote: > On 12/19/23 2:03 PM, David Wei wrote: >> From: David Wei <davidhwei@meta.com> >> >> This patch sets up ZC for an Rx queue in a net device when an ifq is >> registered with io_uring. The Rx queue is specified in the registration >> struct. >> >> For now since there is only one ifq, its destruction is implicit during >> io_uring cleanup. >> >> Signed-off-by: David Wei <dw@davidwei.uk> >> --- >> io_uring/zc_rx.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- >> 1 file changed, 43 insertions(+), 2 deletions(-) >> >> diff --git a/io_uring/zc_rx.c b/io_uring/zc_rx.c >> index 7e3e6f6d446b..259e08a34ab2 100644 >> --- a/io_uring/zc_rx.c >> +++ b/io_uring/zc_rx.c >> @@ -4,6 +4,7 @@ >> #include <linux/errno.h> >> #include <linux/mm.h> >> #include <linux/io_uring.h> >> +#include <linux/netdevice.h> >> >> #include <uapi/linux/io_uring.h> >> >> @@ -11,6 +12,34 @@ >> #include "kbuf.h" >> #include "zc_rx.h" >> >> +typedef int (*bpf_op_t)(struct net_device *dev, struct netdev_bpf *bpf); > > Let's get rid of this, since it isn't even typedef'ed on the networking > side. Doesn't really buy us anything, and it's only used once anyway. That should naturally go away once we move from ndo_bpf
diff --git a/io_uring/zc_rx.c b/io_uring/zc_rx.c index 7e3e6f6d446b..259e08a34ab2 100644 --- a/io_uring/zc_rx.c +++ b/io_uring/zc_rx.c @@ -4,6 +4,7 @@ #include <linux/errno.h> #include <linux/mm.h> #include <linux/io_uring.h> +#include <linux/netdevice.h> #include <uapi/linux/io_uring.h> @@ -11,6 +12,34 @@ #include "kbuf.h" #include "zc_rx.h" +typedef int (*bpf_op_t)(struct net_device *dev, struct netdev_bpf *bpf); + +static int __io_queue_mgmt(struct net_device *dev, struct io_zc_rx_ifq *ifq, + u16 queue_id) +{ + struct netdev_bpf cmd; + bpf_op_t ndo_bpf; + + ndo_bpf = dev->netdev_ops->ndo_bpf; + if (!ndo_bpf) + return -EINVAL; + + cmd.command = XDP_SETUP_ZC_RX; + cmd.zc_rx.ifq = ifq; + cmd.zc_rx.queue_id = queue_id; + return ndo_bpf(dev, &cmd); +} + +static int io_open_zc_rxq(struct io_zc_rx_ifq *ifq) +{ + return __io_queue_mgmt(ifq->dev, ifq, ifq->if_rxq_id); +} + +static int io_close_zc_rxq(struct io_zc_rx_ifq *ifq) +{ + return __io_queue_mgmt(ifq->dev, NULL, ifq->if_rxq_id); +} + static int io_allocate_rbuf_ring(struct io_zc_rx_ifq *ifq, struct io_uring_zc_rx_ifq_reg *reg) { @@ -52,6 +81,10 @@ static struct io_zc_rx_ifq *io_zc_rx_ifq_alloc(struct io_ring_ctx *ctx) static void io_zc_rx_ifq_free(struct io_zc_rx_ifq *ifq) { + if (ifq->if_rxq_id != -1) + io_close_zc_rxq(ifq); + if (ifq->dev) + dev_put(ifq->dev); io_free_rbuf_ring(ifq); kfree(ifq); } @@ -77,18 +110,25 @@ int io_register_zc_rx_ifq(struct io_ring_ctx *ctx, if (!ifq) return -ENOMEM; - /* TODO: initialise network interface */ - ret = io_allocate_rbuf_ring(ifq, ®); if (ret) goto err; + ret = -ENODEV; + ifq->dev = dev_get_by_index(current->nsproxy->net_ns, reg.if_idx); + if (!ifq->dev) + goto err; + /* TODO: map zc region and initialise zc pool */ ifq->rq_entries = reg.rq_entries; ifq->cq_entries = reg.cq_entries; ifq->if_rxq_id = reg.if_rxq_id; + ret = io_open_zc_rxq(ifq); + if (ret) + goto err; + ring_sz = sizeof(struct io_rbuf_ring); rqes_sz = sizeof(struct io_uring_rbuf_rqe) * ifq->rq_entries; cqes_sz = sizeof(struct io_uring_rbuf_cqe) * ifq->cq_entries; @@ -101,6 +141,7 @@ int io_register_zc_rx_ifq(struct io_ring_ctx *ctx, reg.cq_off.tail = offsetof(struct io_rbuf_ring, cq.tail); if (copy_to_user(arg, ®, sizeof(reg))) { + io_close_zc_rxq(ifq); ret = -EFAULT; goto err; }