lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Message-ID: <d4987b1f-349b-3c9e-f651-37f097009629@intel.com> Date: Fri, 31 Aug 2018 10:34:56 +0200 From: Björn Töpel <bjorn.topel@...el.com> To: Jakub Kicinski <jakub.kicinski@...ronome.com>, Björn Töpel <bjorn.topel@...il.com> Cc: magnus.karlsson@...el.com, magnus.karlsson@...il.com, alexander.h.duyck@...el.com, alexander.duyck@...il.com, ast@...nel.org, brouer@...hat.com, daniel@...earbox.net, netdev@...r.kernel.org, jesse.brandeburg@...el.com, anjali.singhai@...el.com, peter.waskiewicz.jr@...el.com, michael.lundkvist@...csson.com, willemdebruijn.kernel@...il.com, john.fastabend@...il.com, neerav.parikh@...el.com, mykyta.iziumtsev@...aro.org, francois.ozog@...aro.org, ilias.apalodimas@...aro.org, brian.brooks@...aro.org, u9012063@...il.com, pavel@...tnetmon.com, qi.z.zhang@...el.com Subject: Re: [RFC] net: xsk: add a simple buffer reuse queue On 2018-08-29 21:19, Jakub Kicinski wrote: > XSK UMEM is strongly single producer single consumer so reuse of > frames is challenging. Add a simple "stash" of FILL packets to > reuse for drivers to optionally make use of. This is useful > when driver has to free (ndo_stop) or resize a ring with an active > AF_XDP ZC socket. > I'll take a stab using this in i40e. I have a couple of comments/thoughts on this RFC, but let me get back when I have an actual patch in place. :-) Thanks! Björn > Signed-off-by: Jakub Kicinski <jakub.kicinski@...ronome.com> > --- > include/net/xdp_sock.h | 44 +++++++++++++++++++++++++++++++++ > net/xdp/xdp_umem.c | 2 ++ > net/xdp/xsk_queue.c | 56 ++++++++++++++++++++++++++++++++++++++++++ > net/xdp/xsk_queue.h | 3 +++ > 4 files changed, 105 insertions(+) > > diff --git a/include/net/xdp_sock.h b/include/net/xdp_sock.h > index 6871e4755975..108c1c100de4 100644 > --- a/include/net/xdp_sock.h > +++ b/include/net/xdp_sock.h > @@ -14,6 +14,7 @@ > #include <net/sock.h> > > struct net_device; > +struct xdp_umem_fq_reuse; > struct xsk_queue; > > struct xdp_umem_props { > @@ -41,6 +42,7 @@ struct xdp_umem { > struct page **pgs; > u32 npgs; > struct net_device *dev; > + struct xdp_umem_fq_reuse *fq_reuse; > u16 queue_id; > bool zc; > spinlock_t xsk_list_lock; > @@ -110,4 +112,46 @@ static inline dma_addr_t xdp_umem_get_dma(struct xdp_umem *umem, u64 addr) > return umem->pages[addr >> PAGE_SHIFT].dma + (addr & (PAGE_SIZE - 1)); > } > > +struct xdp_umem_fq_reuse { > + u32 nentries; > + u32 length; > + u64 handles[]; > +}; > + > +/* Following functions are not thread-safe in any way */ > +struct xdp_umem_fq_reuse *xsk_reuseq_prepare(u32 nentries); > +struct xdp_umem_fq_reuse *xsk_reuseq_swap(struct xdp_umem *umem, > + struct xdp_umem_fq_reuse *newq); > +void xsk_reuseq_free(struct xdp_umem_fq_reuse *rq); > + > +/* Reuse-queue aware version of FILL queue helpers */ > +static inline u64 *xsk_umem_peek_addr_rq(struct xdp_umem *umem, u64 *addr) > +{ > + struct xdp_umem_fq_reuse *rq = umem->fq_reuse; > + > + if (!rq->length) { > + return xsk_umem_peek_addr(umem, addr); > + } else { > + *addr = rq->handles[rq->length - 1]; > + return addr; > + } > +} > + > +static inline void xsk_umem_discard_addr_rq(struct xdp_umem *umem) > +{ > + struct xdp_umem_fq_reuse *rq = umem->fq_reuse; > + > + if (!rq->length) > + xsk_umem_discard_addr(umem); > + else > + rq->length--; > +} > + > +static inline void xsk_umem_fq_reuse(struct xdp_umem *umem, u64 addr) > +{ > + struct xdp_umem_fq_reuse *rq = umem->fq_reuse; > + > + rq->handles[rq->length++] = addr; > +} > + > #endif /* _LINUX_XDP_SOCK_H */ > diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c > index e762310c9bee..40303e24c954 100644 > --- a/net/xdp/xdp_umem.c > +++ b/net/xdp/xdp_umem.c > @@ -170,6 +170,8 @@ static void xdp_umem_release(struct xdp_umem *umem) > umem->cq = NULL; > } > > + xsk_reuseq_destroy(umem); > + > xdp_umem_unpin_pages(umem); > > task = get_pid_task(umem->pid, PIDTYPE_PID); > diff --git a/net/xdp/xsk_queue.c b/net/xdp/xsk_queue.c > index 6c32e92e98fc..f9ee40a13a9a 100644 > --- a/net/xdp/xsk_queue.c > +++ b/net/xdp/xsk_queue.c > @@ -3,7 +3,9 @@ > * Copyright(c) 2018 Intel Corporation. > */ > > +#include <linux/log2.h> > #include <linux/slab.h> > +#include <linux/overflow.h> > > #include "xsk_queue.h" > > @@ -61,3 +63,57 @@ void xskq_destroy(struct xsk_queue *q) > page_frag_free(q->ring); > kfree(q); > } > + > +struct xdp_umem_fq_reuse *xsk_reuseq_prepare(u32 nentries) > +{ > + struct xdp_umem_fq_reuse *newq; > + > + /* Check for overflow */ > + if (nentries > (u32)roundup_pow_of_two(nentries)) > + return NULL; > + nentries = roundup_pow_of_two(nentries); > + > + newq = kvmalloc(struct_size(newq, handles, nentries), GFP_KERNEL); > + if (!newq) > + return NULL; > + memset(newq, 0, offsetof(typeof(*newq), handles)); > + > + newq->nentries = nentries; > + return newq; > +} > +EXPORT_SYMBOL_GPL(xsk_reuseq_prepare); > + > +struct xdp_umem_fq_reuse *xsk_reuseq_swap(struct xdp_umem *umem, > + struct xdp_umem_fq_reuse *newq) > +{ > + struct xdp_umem_fq_reuse *oldq = umem->fq_reuse; > + > + if (!oldq) { > + umem->fq_reuse = newq; > + return NULL; > + } > + > + if (newq->nentries < oldq->length) > + return newq; > + > + > + memcpy(newq->handles, oldq->handles, > + array_size(oldq->length, sizeof(u64))); > + newq->length = oldq->length; > + > + umem->fq_reuse = newq; > + return oldq; > +} > +EXPORT_SYMBOL_GPL(xsk_reuseq_swap); > + > +void xsk_reuseq_free(struct xdp_umem_fq_reuse *rq) > +{ > + kvfree(rq); > +} > +EXPORT_SYMBOL_GPL(xsk_reuseq_free); > + > +void xsk_reuseq_destroy(struct xdp_umem *umem) > +{ > + xsk_reuseq_free(umem->fq_reuse); > + umem->fq_reuse = NULL; > +} > diff --git a/net/xdp/xsk_queue.h b/net/xdp/xsk_queue.h > index 8a64b150be54..7a480e3eb35d 100644 > --- a/net/xdp/xsk_queue.h > +++ b/net/xdp/xsk_queue.h > @@ -257,4 +257,7 @@ void xskq_set_umem(struct xsk_queue *q, struct xdp_umem_props *umem_props); > struct xsk_queue *xskq_create(u32 nentries, bool umem_queue); > void xskq_destroy(struct xsk_queue *q_ops); > > +/* Executed by the core when the entire UMEM gets freed */ > +void xsk_reuseq_destroy(struct xdp_umem *umem); > + > #endif /* _LINUX_XSK_QUEUE_H */ >
Powered by blists - more mailing lists