* [PATCH net-next 0/7] xdp: a fistful of generic changes pt. III
@ 2024-12-18 17:44 Alexander Lobakin
2024-12-18 17:44 ` [PATCH net-next 1/7] page_pool: add page_pool_dev_alloc_netmem() Alexander Lobakin
` (7 more replies)
0 siblings, 8 replies; 13+ messages in thread
From: Alexander Lobakin @ 2024-12-18 17:44 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Alexander Lobakin, Alexei Starovoitov, Daniel Borkmann,
John Fastabend, Andrii Nakryiko, Jose E. Marchesi,
Toke Høiland-Jørgensen, Magnus Karlsson,
Maciej Fijalkowski, Przemek Kitszel, Jason Baron, Casey Schaufler,
Nathan Chancellor, bpf, netdev, linux-kernel
XDP for idpf is currently 5.(6) chapters:
* convert Rx to libeth;
* convert Tx and stats to libeth;
* generic XDP and XSk code changes;
* generic XDP and XSk code additions pt. 1;
* generic XDP and XSk code additions pt. 2 (you are here);
* actual XDP for idpf via new libeth_xdp;
* XSk for idpf (via ^).
Part III.3 does the following:
* adds generic functions to build skbs from xdp_buffs (regular and
XSk) and attach frags to xdp_buffs (regular and XSk);
* adds helper to optimize XSk xmit in drivers;
* add generic loop unroll hint macros.
Everything is prereq for libeth_xdp, but will be useful standalone
as well: less code in drivers, faster XSk XDP_PASS, smaller object
code.
Alexander Lobakin (7):
page_pool: add page_pool_dev_alloc_netmem()
xdp: add generic xdp_buff_add_frag()
xdp: add generic xdp_build_skb_from_buff()
xsk: make xsk_buff_add_frag() really add the frag via
__xdp_buff_add_frag()
xsk: add generic XSk &xdp_buff -> skb conversion
xsk: add helper to get &xdp_desc's DMA and meta pointer in one go
unroll: add generic loop unroll helpers
include/linux/skbuff.h | 16 +-
include/linux/unroll.h | 44 +++++
include/net/page_pool/helpers.h | 9 ++
include/net/xdp.h | 98 +++++++++++-
include/net/xdp_sock_drv.h | 41 ++++-
include/net/xsk_buff_pool.h | 8 +
drivers/net/ethernet/intel/i40e/i40e_xsk.c | 30 +---
drivers/net/ethernet/intel/ice/ice_xsk.c | 32 +---
net/core/xdp.c | 178 +++++++++++++++++++++
net/xdp/xsk_buff_pool.c | 40 +++++
10 files changed, 431 insertions(+), 65 deletions(-)
---
Each patch except trivial 0001 was on the lists already.
Since the not applied part of Chapter III.2:
* rebase on top of Mina's netmem fixes;
* 0003: remove redundant double CONFIG_PAGE_POOL check (one inside
and another one outside of skb_mark_for_recycle()) (Jakub);
* 0005: remove !CONFIG_PAGE_POOL code as unreachable (eBPF always
selects it) (also Jakub);
* 0005: actually check the pfmemalloc flag of newly allocated frags;
* drop exporting static_key_{inc,dec}_cpuslocked() -- were used on
slowpath in very unlikely case where saving a few cycles looked
worse and less convienient than the "regular" way.
--
2.47.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH net-next 1/7] page_pool: add page_pool_dev_alloc_netmem()
2024-12-18 17:44 [PATCH net-next 0/7] xdp: a fistful of generic changes pt. III Alexander Lobakin
@ 2024-12-18 17:44 ` Alexander Lobakin
2024-12-18 17:44 ` [PATCH net-next 2/7] xdp: add generic xdp_buff_add_frag() Alexander Lobakin
` (6 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Alexander Lobakin @ 2024-12-18 17:44 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Alexander Lobakin, Alexei Starovoitov, Daniel Borkmann,
John Fastabend, Andrii Nakryiko, Jose E. Marchesi,
Toke Høiland-Jørgensen, Magnus Karlsson,
Maciej Fijalkowski, Przemek Kitszel, Jason Baron, Casey Schaufler,
Nathan Chancellor, bpf, netdev, linux-kernel
Similarly to other _dev shorthands, add one for page_pool_alloc_netmem()
to allocate a netmem using the default Rx GFP flags (ATOMIC | NOWARN) to
make the page -> netmem transition of drivers easier.
Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
---
include/net/page_pool/helpers.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/include/net/page_pool/helpers.h b/include/net/page_pool/helpers.h
index 776a3008ac28..543f54fa3020 100644
--- a/include/net/page_pool/helpers.h
+++ b/include/net/page_pool/helpers.h
@@ -144,6 +144,15 @@ static inline netmem_ref page_pool_alloc_netmem(struct page_pool *pool,
return netmem;
}
+static inline netmem_ref page_pool_dev_alloc_netmem(struct page_pool *pool,
+ unsigned int *offset,
+ unsigned int *size)
+{
+ gfp_t gfp = GFP_ATOMIC | __GFP_NOWARN;
+
+ return page_pool_alloc_netmem(pool, offset, size, gfp);
+}
+
static inline struct page *page_pool_alloc(struct page_pool *pool,
unsigned int *offset,
unsigned int *size, gfp_t gfp)
--
2.47.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next 2/7] xdp: add generic xdp_buff_add_frag()
2024-12-18 17:44 [PATCH net-next 0/7] xdp: a fistful of generic changes pt. III Alexander Lobakin
2024-12-18 17:44 ` [PATCH net-next 1/7] page_pool: add page_pool_dev_alloc_netmem() Alexander Lobakin
@ 2024-12-18 17:44 ` Alexander Lobakin
2024-12-18 17:44 ` [PATCH net-next 3/7] xdp: add generic xdp_build_skb_from_buff() Alexander Lobakin
` (5 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Alexander Lobakin @ 2024-12-18 17:44 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Alexander Lobakin, Alexei Starovoitov, Daniel Borkmann,
John Fastabend, Andrii Nakryiko, Jose E. Marchesi,
Toke Høiland-Jørgensen, Magnus Karlsson,
Maciej Fijalkowski, Przemek Kitszel, Jason Baron, Casey Schaufler,
Nathan Chancellor, bpf, netdev, linux-kernel
The code piece which would attach a frag to &xdp_buff is almost
identical across the drivers supporting XDP multi-buffer on Rx.
Make it a generic elegant "oneliner".
Also, I see lots of drivers calculating frags_truesize as
`xdp->frame_sz * nr_frags`. I can't say this is fully correct, since
frags might be backed by chunks of different sizes, especially with
stuff like the header split. Even page_pool_alloc() can give you two
different truesizes on two subsequent requests to allocate the same
buffer size. Add a field to &skb_shared_info (unionized as there's no
free slot currently on x86_64) to track the "true" truesize. It can
be used later when updating the skb.
Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
---
include/linux/skbuff.h | 16 +++++--
include/net/xdp.h | 96 +++++++++++++++++++++++++++++++++++++++++-
net/core/xdp.c | 11 +++++
3 files changed, 118 insertions(+), 5 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index b2509cd0b930..bb2b751d274a 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -608,11 +608,19 @@ struct skb_shared_info {
* Warning : all fields before dataref are cleared in __alloc_skb()
*/
atomic_t dataref;
- unsigned int xdp_frags_size;
- /* Intermediate layers must ensure that destructor_arg
- * remains valid until skb destructor */
- void * destructor_arg;
+ union {
+ struct {
+ u32 xdp_frags_size;
+ u32 xdp_frags_truesize;
+ };
+
+ /*
+ * Intermediate layers must ensure that destructor_arg
+ * remains valid until skb destructor.
+ */
+ void *destructor_arg;
+ };
/* must be last field, see pskb_expand_head() */
skb_frag_t frags[MAX_SKB_FRAGS];
diff --git a/include/net/xdp.h b/include/net/xdp.h
index d2089cfecefd..11139c210b49 100644
--- a/include/net/xdp.h
+++ b/include/net/xdp.h
@@ -167,6 +167,93 @@ xdp_get_buff_len(const struct xdp_buff *xdp)
return len;
}
+void xdp_return_frag(netmem_ref netmem, const struct xdp_buff *xdp);
+
+/**
+ * __xdp_buff_add_frag - attach frag to &xdp_buff
+ * @xdp: XDP buffer to attach the frag to
+ * @netmem: network memory containing the frag
+ * @offset: offset at which the frag starts
+ * @size: size of the frag
+ * @truesize: total memory size occupied by the frag
+ * @try_coalesce: whether to try coalescing the frags (not valid for XSk)
+ *
+ * Attach frag to the XDP buffer. If it currently has no frags attached,
+ * initialize the related fields, otherwise check that the frag number
+ * didn't reach the limit of ``MAX_SKB_FRAGS``. If possible, try coalescing
+ * the frag with the previous one.
+ * The function doesn't check/update the pfmemalloc bit. Please use the
+ * non-underscored wrapper in drivers.
+ *
+ * Return: true on success, false if there's no space for the frag in
+ * the shared info struct.
+ */
+static inline bool __xdp_buff_add_frag(struct xdp_buff *xdp, netmem_ref netmem,
+ u32 offset, u32 size, u32 truesize,
+ bool try_coalesce)
+{
+ struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp);
+ skb_frag_t *prev;
+ u32 nr_frags;
+
+ if (!xdp_buff_has_frags(xdp)) {
+ xdp_buff_set_frags_flag(xdp);
+
+ nr_frags = 0;
+ sinfo->xdp_frags_size = 0;
+ sinfo->xdp_frags_truesize = 0;
+
+ goto fill;
+ }
+
+ nr_frags = sinfo->nr_frags;
+ prev = &sinfo->frags[nr_frags - 1];
+
+ if (try_coalesce && netmem == skb_frag_netmem(prev) &&
+ offset == skb_frag_off(prev) + skb_frag_size(prev)) {
+ skb_frag_size_add(prev, size);
+ /* Guaranteed to only decrement the refcount */
+ xdp_return_frag(netmem, xdp);
+ } else if (unlikely(nr_frags == MAX_SKB_FRAGS)) {
+ return false;
+ } else {
+fill:
+ __skb_fill_netmem_desc_noacc(sinfo, nr_frags++, netmem,
+ offset, size);
+ }
+
+ sinfo->nr_frags = nr_frags;
+ sinfo->xdp_frags_size += size;
+ sinfo->xdp_frags_truesize += truesize;
+
+ return true;
+}
+
+/**
+ * xdp_buff_add_frag - attach frag to &xdp_buff
+ * @xdp: XDP buffer to attach the frag to
+ * @netmem: network memory containing the frag
+ * @offset: offset at which the frag starts
+ * @size: size of the frag
+ * @truesize: total memory size occupied by the frag
+ *
+ * Version of __xdp_buff_add_frag() which takes care of the pfmemalloc bit.
+ *
+ * Return: true on success, false if there's no space for the frag in
+ * the shared info struct.
+ */
+static inline bool xdp_buff_add_frag(struct xdp_buff *xdp, netmem_ref netmem,
+ u32 offset, u32 size, u32 truesize)
+{
+ if (!__xdp_buff_add_frag(xdp, netmem, offset, size, truesize, true))
+ return false;
+
+ if (unlikely(netmem_is_pfmemalloc(netmem)))
+ xdp_buff_set_frag_pfmemalloc(xdp);
+
+ return true;
+}
+
struct xdp_frame {
void *data;
u32 len;
@@ -230,7 +317,14 @@ xdp_update_skb_shared_info(struct sk_buff *skb, u8 nr_frags,
unsigned int size, unsigned int truesize,
bool pfmemalloc)
{
- skb_shinfo(skb)->nr_frags = nr_frags;
+ struct skb_shared_info *sinfo = skb_shinfo(skb);
+
+ sinfo->nr_frags = nr_frags;
+ /*
+ * ``destructor_arg`` is unionized with ``xdp_frags_{,true}size``,
+ * reset it after that these fields aren't used anymore.
+ */
+ sinfo->destructor_arg = NULL;
skb->len += size;
skb->data_len += size;
diff --git a/net/core/xdp.c b/net/core/xdp.c
index f1165a35411b..a66a4e036f53 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c
@@ -535,6 +535,17 @@ void xdp_return_frame_bulk(struct xdp_frame *xdpf,
}
EXPORT_SYMBOL_GPL(xdp_return_frame_bulk);
+/**
+ * xdp_return_frag -- free one XDP frag or decrement its refcount
+ * @netmem: network memory reference to release
+ * @xdp: &xdp_buff to release the frag for
+ */
+void xdp_return_frag(netmem_ref netmem, const struct xdp_buff *xdp)
+{
+ __xdp_return(netmem, xdp->rxq->mem.type, true, NULL);
+}
+EXPORT_SYMBOL_GPL(xdp_return_frag);
+
void xdp_return_buff(struct xdp_buff *xdp)
{
struct skb_shared_info *sinfo;
--
2.47.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next 3/7] xdp: add generic xdp_build_skb_from_buff()
2024-12-18 17:44 [PATCH net-next 0/7] xdp: a fistful of generic changes pt. III Alexander Lobakin
2024-12-18 17:44 ` [PATCH net-next 1/7] page_pool: add page_pool_dev_alloc_netmem() Alexander Lobakin
2024-12-18 17:44 ` [PATCH net-next 2/7] xdp: add generic xdp_buff_add_frag() Alexander Lobakin
@ 2024-12-18 17:44 ` Alexander Lobakin
2024-12-18 17:44 ` [PATCH net-next 4/7] xsk: make xsk_buff_add_frag() really add the frag via __xdp_buff_add_frag() Alexander Lobakin
` (4 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Alexander Lobakin @ 2024-12-18 17:44 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Alexander Lobakin, Alexei Starovoitov, Daniel Borkmann,
John Fastabend, Andrii Nakryiko, Jose E. Marchesi,
Toke Høiland-Jørgensen, Magnus Karlsson,
Maciej Fijalkowski, Przemek Kitszel, Jason Baron, Casey Schaufler,
Nathan Chancellor, bpf, netdev, linux-kernel
The code which builds an skb from an &xdp_buff keeps multiplying itself
around the drivers with almost no changes. Let's try to stop that by
adding a generic function.
Unlike __xdp_build_skb_from_frame(), always allocate an skbuff head
using napi_build_skb() and make use of the available xdp_rxq pointer to
assign the Rx queue index. In case of PP-backed buffer, mark the skb to
be recycled, as every PP user's been switched to recycle skbs.
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
---
include/net/xdp.h | 1 +
net/core/xdp.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 56 insertions(+)
diff --git a/include/net/xdp.h b/include/net/xdp.h
index 11139c210b49..aa24fa78cbe6 100644
--- a/include/net/xdp.h
+++ b/include/net/xdp.h
@@ -336,6 +336,7 @@ xdp_update_skb_shared_info(struct sk_buff *skb, u8 nr_frags,
void xdp_warn(const char *msg, const char *func, const int line);
#define XDP_WARN(msg) xdp_warn(msg, __func__, __LINE__)
+struct sk_buff *xdp_build_skb_from_buff(const struct xdp_buff *xdp);
struct xdp_frame *xdp_convert_zc_to_xdp_frame(struct xdp_buff *xdp);
struct sk_buff *__xdp_build_skb_from_frame(struct xdp_frame *xdpf,
struct sk_buff *skb,
diff --git a/net/core/xdp.c b/net/core/xdp.c
index a66a4e036f53..704203a15a18 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c
@@ -629,6 +629,61 @@ int xdp_alloc_skb_bulk(void **skbs, int n_skb, gfp_t gfp)
}
EXPORT_SYMBOL_GPL(xdp_alloc_skb_bulk);
+/**
+ * xdp_build_skb_from_buff - create an skb from &xdp_buff
+ * @xdp: &xdp_buff to convert to an skb
+ *
+ * Perform common operations to create a new skb to pass up the stack from
+ * &xdp_buff: allocate an skb head from the NAPI percpu cache, initialize
+ * skb data pointers and offsets, set the recycle bit if the buff is
+ * PP-backed, Rx queue index, protocol and update frags info.
+ *
+ * Return: new &sk_buff on success, %NULL on error.
+ */
+struct sk_buff *xdp_build_skb_from_buff(const struct xdp_buff *xdp)
+{
+ const struct xdp_rxq_info *rxq = xdp->rxq;
+ const struct skb_shared_info *sinfo;
+ struct sk_buff *skb;
+ u32 nr_frags = 0;
+ int metalen;
+
+ if (unlikely(xdp_buff_has_frags(xdp))) {
+ sinfo = xdp_get_shared_info_from_buff(xdp);
+ nr_frags = sinfo->nr_frags;
+ }
+
+ skb = napi_build_skb(xdp->data_hard_start, xdp->frame_sz);
+ if (unlikely(!skb))
+ return NULL;
+
+ skb_reserve(skb, xdp->data - xdp->data_hard_start);
+ __skb_put(skb, xdp->data_end - xdp->data);
+
+ metalen = xdp->data - xdp->data_meta;
+ if (metalen > 0)
+ skb_metadata_set(skb, metalen);
+
+ if (rxq->mem.type == MEM_TYPE_PAGE_POOL)
+ skb_mark_for_recycle(skb);
+
+ skb_record_rx_queue(skb, rxq->queue_index);
+
+ if (unlikely(nr_frags)) {
+ u32 tsize;
+
+ tsize = sinfo->xdp_frags_truesize ? : nr_frags * xdp->frame_sz;
+ xdp_update_skb_shared_info(skb, nr_frags,
+ sinfo->xdp_frags_size, tsize,
+ xdp_buff_is_frag_pfmemalloc(xdp));
+ }
+
+ skb->protocol = eth_type_trans(skb, rxq->dev);
+
+ return skb;
+}
+EXPORT_SYMBOL_GPL(xdp_build_skb_from_buff);
+
struct sk_buff *__xdp_build_skb_from_frame(struct xdp_frame *xdpf,
struct sk_buff *skb,
struct net_device *dev)
--
2.47.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next 4/7] xsk: make xsk_buff_add_frag() really add the frag via __xdp_buff_add_frag()
2024-12-18 17:44 [PATCH net-next 0/7] xdp: a fistful of generic changes pt. III Alexander Lobakin
` (2 preceding siblings ...)
2024-12-18 17:44 ` [PATCH net-next 3/7] xdp: add generic xdp_build_skb_from_buff() Alexander Lobakin
@ 2024-12-18 17:44 ` Alexander Lobakin
2024-12-18 17:44 ` [PATCH net-next 5/7] xsk: add generic XSk &xdp_buff -> skb conversion Alexander Lobakin
` (3 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Alexander Lobakin @ 2024-12-18 17:44 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Alexander Lobakin, Alexei Starovoitov, Daniel Borkmann,
John Fastabend, Andrii Nakryiko, Jose E. Marchesi,
Toke Høiland-Jørgensen, Magnus Karlsson,
Maciej Fijalkowski, Przemek Kitszel, Jason Baron, Casey Schaufler,
Nathan Chancellor, bpf, netdev, linux-kernel
Currently, xsk_buff_add_frag() only adds the frag to pool's linked list,
not doing anything with the &xdp_buff. The drivers do that manually and
the logic is the same.
Make it really add an skb frag, just like xdp_buff_add_frag() does that,
and freeing frags on error if needed. This allows to remove repeating
code from i40e and ice and not add the same code again and again.
Acked-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
---
include/net/xdp_sock_drv.h | 18 ++++++++++--
drivers/net/ethernet/intel/i40e/i40e_xsk.c | 30 ++------------------
drivers/net/ethernet/intel/ice/ice_xsk.c | 32 ++--------------------
3 files changed, 20 insertions(+), 60 deletions(-)
diff --git a/include/net/xdp_sock_drv.h b/include/net/xdp_sock_drv.h
index f3175a5d28f7..86620c818965 100644
--- a/include/net/xdp_sock_drv.h
+++ b/include/net/xdp_sock_drv.h
@@ -136,11 +136,21 @@ static inline void xsk_buff_free(struct xdp_buff *xdp)
xp_free(xskb);
}
-static inline void xsk_buff_add_frag(struct xdp_buff *xdp)
+static inline bool xsk_buff_add_frag(struct xdp_buff *head,
+ struct xdp_buff *xdp)
{
- struct xdp_buff_xsk *frag = container_of(xdp, struct xdp_buff_xsk, xdp);
+ const void *data = xdp->data;
+ struct xdp_buff_xsk *frag;
+
+ if (!__xdp_buff_add_frag(head, virt_to_netmem(data),
+ offset_in_page(data), xdp->data_end - data,
+ xdp->frame_sz, false))
+ return false;
+ frag = container_of(xdp, struct xdp_buff_xsk, xdp);
list_add_tail(&frag->list_node, &frag->pool->xskb_list);
+
+ return true;
}
static inline struct xdp_buff *xsk_buff_get_frag(const struct xdp_buff *first)
@@ -357,8 +367,10 @@ static inline void xsk_buff_free(struct xdp_buff *xdp)
{
}
-static inline void xsk_buff_add_frag(struct xdp_buff *xdp)
+static inline bool xsk_buff_add_frag(struct xdp_buff *head,
+ struct xdp_buff *xdp)
{
+ return false;
}
static inline struct xdp_buff *xsk_buff_get_frag(const struct xdp_buff *first)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
index 4e885df789ef..e28f1905a4a0 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
@@ -395,32 +395,6 @@ static void i40e_handle_xdp_result_zc(struct i40e_ring *rx_ring,
WARN_ON_ONCE(1);
}
-static int
-i40e_add_xsk_frag(struct i40e_ring *rx_ring, struct xdp_buff *first,
- struct xdp_buff *xdp, const unsigned int size)
-{
- struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(first);
-
- if (!xdp_buff_has_frags(first)) {
- sinfo->nr_frags = 0;
- sinfo->xdp_frags_size = 0;
- xdp_buff_set_frags_flag(first);
- }
-
- if (unlikely(sinfo->nr_frags == MAX_SKB_FRAGS)) {
- xsk_buff_free(first);
- return -ENOMEM;
- }
-
- __skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++,
- virt_to_page(xdp->data_hard_start),
- XDP_PACKET_HEADROOM, size);
- sinfo->xdp_frags_size += size;
- xsk_buff_add_frag(xdp);
-
- return 0;
-}
-
/**
* i40e_clean_rx_irq_zc - Consumes Rx packets from the hardware ring
* @rx_ring: Rx ring
@@ -486,8 +460,10 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget)
if (!first)
first = bi;
- else if (i40e_add_xsk_frag(rx_ring, first, bi, size))
+ else if (!xsk_buff_add_frag(first, bi)) {
+ xsk_buff_free(first);
break;
+ }
if (++next_to_process == count)
next_to_process = 0;
diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c
index 334ae945d640..8975d2971bc3 100644
--- a/drivers/net/ethernet/intel/ice/ice_xsk.c
+++ b/drivers/net/ethernet/intel/ice/ice_xsk.c
@@ -801,35 +801,6 @@ ice_run_xdp_zc(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,
return result;
}
-static int
-ice_add_xsk_frag(struct ice_rx_ring *rx_ring, struct xdp_buff *first,
- struct xdp_buff *xdp, const unsigned int size)
-{
- struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(first);
-
- if (!size)
- return 0;
-
- if (!xdp_buff_has_frags(first)) {
- sinfo->nr_frags = 0;
- sinfo->xdp_frags_size = 0;
- xdp_buff_set_frags_flag(first);
- }
-
- if (unlikely(sinfo->nr_frags == MAX_SKB_FRAGS)) {
- xsk_buff_free(first);
- return -ENOMEM;
- }
-
- __skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++,
- virt_to_page(xdp->data_hard_start),
- XDP_PACKET_HEADROOM, size);
- sinfo->xdp_frags_size += size;
- xsk_buff_add_frag(xdp);
-
- return 0;
-}
-
/**
* ice_clean_rx_irq_zc - consumes packets from the hardware ring
* @rx_ring: AF_XDP Rx ring
@@ -895,7 +866,8 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring,
if (!first) {
first = xdp;
- } else if (ice_add_xsk_frag(rx_ring, first, xdp, size)) {
+ } else if (likely(size) && !xsk_buff_add_frag(first, xdp)) {
+ xsk_buff_free(first);
break;
}
--
2.47.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next 5/7] xsk: add generic XSk &xdp_buff -> skb conversion
2024-12-18 17:44 [PATCH net-next 0/7] xdp: a fistful of generic changes pt. III Alexander Lobakin
` (3 preceding siblings ...)
2024-12-18 17:44 ` [PATCH net-next 4/7] xsk: make xsk_buff_add_frag() really add the frag via __xdp_buff_add_frag() Alexander Lobakin
@ 2024-12-18 17:44 ` Alexander Lobakin
2024-12-18 17:44 ` [PATCH net-next 6/7] xsk: add helper to get &xdp_desc's DMA and meta pointer in one go Alexander Lobakin
` (2 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Alexander Lobakin @ 2024-12-18 17:44 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Alexander Lobakin, Alexei Starovoitov, Daniel Borkmann,
John Fastabend, Andrii Nakryiko, Jose E. Marchesi,
Toke Høiland-Jørgensen, Magnus Karlsson,
Maciej Fijalkowski, Przemek Kitszel, Jason Baron, Casey Schaufler,
Nathan Chancellor, bpf, netdev, linux-kernel
Same as with converting &xdp_buff to skb on Rx, the code which allocates
a new skb and copies the XSk frame there is identical across the
drivers, so make it generic. This includes copying all the frags if they
are present in the original buff.
System percpu page_pools greatly improve XDP_PASS performance on XSk:
instead of page_alloc() + page_free(), the net core recycles the same
pages, so the only overhead left is memcpy()s. When the Page Pool is
not compiled in, the whole function is a return-NULL (but it always
gets selected when eBPF is enabled).
Note that the passed buff gets freed if the conversion is done w/o any
error, assuming you don't need this buffer after you convert it to an
skb.
Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
---
include/net/xdp.h | 1 +
net/core/xdp.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 113 insertions(+)
diff --git a/include/net/xdp.h b/include/net/xdp.h
index aa24fa78cbe6..6da0e746cf75 100644
--- a/include/net/xdp.h
+++ b/include/net/xdp.h
@@ -337,6 +337,7 @@ void xdp_warn(const char *msg, const char *func, const int line);
#define XDP_WARN(msg) xdp_warn(msg, __func__, __LINE__)
struct sk_buff *xdp_build_skb_from_buff(const struct xdp_buff *xdp);
+struct sk_buff *xdp_build_skb_from_zc(struct xdp_buff *xdp);
struct xdp_frame *xdp_convert_zc_to_xdp_frame(struct xdp_buff *xdp);
struct sk_buff *__xdp_build_skb_from_frame(struct xdp_frame *xdpf,
struct sk_buff *skb,
diff --git a/net/core/xdp.c b/net/core/xdp.c
index 704203a15a18..67b53fc7191e 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c
@@ -684,6 +684,118 @@ struct sk_buff *xdp_build_skb_from_buff(const struct xdp_buff *xdp)
}
EXPORT_SYMBOL_GPL(xdp_build_skb_from_buff);
+/**
+ * xdp_copy_frags_from_zc - copy frags from XSk buff to skb
+ * @skb: skb to copy frags to
+ * @xdp: XSk &xdp_buff from which the frags will be copied
+ * @pp: &page_pool backing page allocation, if available
+ *
+ * Copy all frags from XSk &xdp_buff to the skb to pass it up the stack.
+ * Allocate a new buffer for each frag, copy it and attach to the skb.
+ *
+ * Return: true on success, false on netmem allocation fail.
+ */
+static noinline bool xdp_copy_frags_from_zc(struct sk_buff *skb,
+ const struct xdp_buff *xdp,
+ struct page_pool *pp)
+{
+ struct skb_shared_info *sinfo = skb_shinfo(skb);
+ const struct skb_shared_info *xinfo;
+ u32 nr_frags, tsize = 0;
+ bool pfmemalloc = false;
+
+ xinfo = xdp_get_shared_info_from_buff(xdp);
+ nr_frags = xinfo->nr_frags;
+
+ for (u32 i = 0; i < nr_frags; i++) {
+ u32 len = skb_frag_size(&xinfo->frags[i]);
+ u32 offset, truesize = len;
+ netmem_ref netmem;
+
+ netmem = page_pool_dev_alloc_netmem(pp, &offset, &truesize);
+ if (unlikely(!netmem)) {
+ sinfo->nr_frags = i;
+ return false;
+ }
+
+ memcpy(__netmem_address(netmem),
+ __netmem_address(xinfo->frags[i].netmem),
+ LARGEST_ALIGN(len));
+ __skb_fill_netmem_desc_noacc(sinfo, i, netmem, offset, len);
+
+ tsize += truesize;
+ pfmemalloc |= netmem_is_pfmemalloc(netmem);
+ }
+
+ xdp_update_skb_shared_info(skb, nr_frags, xinfo->xdp_frags_size,
+ tsize, pfmemalloc);
+
+ return true;
+}
+
+/**
+ * xdp_build_skb_from_zc - create an skb from XSk &xdp_buff
+ * @xdp: source XSk buff
+ *
+ * Similar to xdp_build_skb_from_buff(), but for XSk frames. Allocate an skb
+ * head, new buffer for the head, copy the data and initialize the skb fields.
+ * If there are frags, allocate new buffers for them and copy.
+ * Buffers are allocated from the system percpu pools to try recycling them.
+ * If new skb was built successfully, @xdp is returned to XSk pool's freelist.
+ * On error, it remains untouched and the caller must take care of this.
+ *
+ * Return: new &sk_buff on success, %NULL on error.
+ */
+struct sk_buff *xdp_build_skb_from_zc(struct xdp_buff *xdp)
+{
+ struct page_pool *pp = this_cpu_read(system_page_pool);
+ const struct xdp_rxq_info *rxq = xdp->rxq;
+ u32 len = xdp->data_end - xdp->data_meta;
+ u32 truesize = xdp->frame_sz;
+ struct sk_buff *skb;
+ int metalen;
+ void *data;
+
+ if (!IS_ENABLED(CONFIG_PAGE_POOL))
+ return NULL;
+
+ data = page_pool_dev_alloc_va(pp, &truesize);
+ if (unlikely(!data))
+ return NULL;
+
+ skb = napi_build_skb(data, truesize);
+ if (unlikely(!skb)) {
+ page_pool_free_va(pp, data, true);
+ return NULL;
+ }
+
+ skb_mark_for_recycle(skb);
+ skb_reserve(skb, xdp->data_meta - xdp->data_hard_start);
+
+ memcpy(__skb_put(skb, len), xdp->data_meta, LARGEST_ALIGN(len));
+
+ metalen = xdp->data - xdp->data_meta;
+ if (metalen > 0) {
+ skb_metadata_set(skb, metalen);
+ __skb_pull(skb, metalen);
+ }
+
+ skb_record_rx_queue(skb, rxq->queue_index);
+
+ if (unlikely(xdp_buff_has_frags(xdp)) &&
+ unlikely(!xdp_copy_frags_from_zc(skb, xdp, pp))) {
+ napi_consume_skb(skb, true);
+ return NULL;
+ }
+
+ xsk_buff_free(xdp);
+
+ skb->protocol = eth_type_trans(skb, rxq->dev);
+
+ return skb;
+}
+EXPORT_SYMBOL_GPL(xdp_build_skb_from_zc);
+
struct sk_buff *__xdp_build_skb_from_frame(struct xdp_frame *xdpf,
struct sk_buff *skb,
struct net_device *dev)
--
2.47.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next 6/7] xsk: add helper to get &xdp_desc's DMA and meta pointer in one go
2024-12-18 17:44 [PATCH net-next 0/7] xdp: a fistful of generic changes pt. III Alexander Lobakin
` (4 preceding siblings ...)
2024-12-18 17:44 ` [PATCH net-next 5/7] xsk: add generic XSk &xdp_buff -> skb conversion Alexander Lobakin
@ 2024-12-18 17:44 ` Alexander Lobakin
2024-12-20 3:50 ` Jakub Kicinski
2024-12-18 17:44 ` [PATCH net-next 7/7] unroll: add generic loop unroll helpers Alexander Lobakin
2024-12-20 4:00 ` [PATCH net-next 0/7] xdp: a fistful of generic changes pt. III patchwork-bot+netdevbpf
7 siblings, 1 reply; 13+ messages in thread
From: Alexander Lobakin @ 2024-12-18 17:44 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Alexander Lobakin, Alexei Starovoitov, Daniel Borkmann,
John Fastabend, Andrii Nakryiko, Jose E. Marchesi,
Toke Høiland-Jørgensen, Magnus Karlsson,
Maciej Fijalkowski, Przemek Kitszel, Jason Baron, Casey Schaufler,
Nathan Chancellor, bpf, netdev, linux-kernel
Currently, when you send an XSk frame with metadata, you need to do
the following:
* call external xsk_buff_raw_get_dma();
* call inline xsk_buff_get_metadata(), which calls external
xsk_buff_raw_get_data() and then do some inline checks.
This effectively means that the following piece:
addr = pool->unaligned ? xp_unaligned_add_offset_to_addr(addr) : addr;
is done twice per frame, plus you have 2 external calls per frame, plus
this:
meta = pool->addrs + addr - pool->tx_metadata_len;
if (unlikely(!xsk_buff_valid_tx_metadata(meta)))
is always inlined, even if there's no meta or it's invalid.
Add xsk_buff_raw_get_ctx() (xp_raw_get_ctx() to be precise) to do that
in one go. It returns a small structure with 2 fields: DMA address,
filled unconditionally, and metadata pointer, valid only if it's
present. The address correction is performed only once and you also
have only 1 external call per XSk frame, which does all the calculations
and checks outside of your hotpath. You only need to check
`if (ctx.meta)` for the metadata presence.
Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
---
include/net/xdp_sock_drv.h | 23 +++++++++++++++++++++
include/net/xsk_buff_pool.h | 8 ++++++++
net/xdp/xsk_buff_pool.c | 40 +++++++++++++++++++++++++++++++++++++
3 files changed, 71 insertions(+)
diff --git a/include/net/xdp_sock_drv.h b/include/net/xdp_sock_drv.h
index 86620c818965..7fd1709deef5 100644
--- a/include/net/xdp_sock_drv.h
+++ b/include/net/xdp_sock_drv.h
@@ -205,6 +205,23 @@ static inline void *xsk_buff_raw_get_data(struct xsk_buff_pool *pool, u64 addr)
return xp_raw_get_data(pool, addr);
}
+/**
+ * xsk_buff_raw_get_ctx - get &xdp_desc context
+ * @pool: XSk buff pool desc address belongs to
+ * @addr: desc address (from userspace)
+ *
+ * Wrapper for xp_raw_get_ctx() to be used in drivers, see its kdoc for
+ * details.
+ *
+ * Return: new &xdp_desc_ctx struct containing desc's DMA address and metadata
+ * pointer, if it is present and valid (initialized to %NULL otherwise).
+ */
+static inline struct xdp_desc_ctx
+xsk_buff_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr)
+{
+ return xp_raw_get_ctx(pool, addr);
+}
+
#define XDP_TXMD_FLAGS_VALID ( \
XDP_TXMD_FLAGS_TIMESTAMP | \
XDP_TXMD_FLAGS_CHECKSUM | \
@@ -402,6 +419,12 @@ static inline void *xsk_buff_raw_get_data(struct xsk_buff_pool *pool, u64 addr)
return NULL;
}
+static inline struct xdp_desc_ctx
+xsk_buff_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr)
+{
+ return (struct xdp_desc_ctx){ };
+}
+
static inline bool xsk_buff_valid_tx_metadata(struct xsk_tx_metadata *meta)
{
return false;
diff --git a/include/net/xsk_buff_pool.h b/include/net/xsk_buff_pool.h
index 50779406bc2d..1dcd4d71468a 100644
--- a/include/net/xsk_buff_pool.h
+++ b/include/net/xsk_buff_pool.h
@@ -141,6 +141,14 @@ u32 xp_alloc_batch(struct xsk_buff_pool *pool, struct xdp_buff **xdp, u32 max);
bool xp_can_alloc(struct xsk_buff_pool *pool, u32 count);
void *xp_raw_get_data(struct xsk_buff_pool *pool, u64 addr);
dma_addr_t xp_raw_get_dma(struct xsk_buff_pool *pool, u64 addr);
+
+struct xdp_desc_ctx {
+ dma_addr_t dma;
+ struct xsk_tx_metadata *meta;
+};
+
+struct xdp_desc_ctx xp_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr);
+
static inline dma_addr_t xp_get_dma(struct xdp_buff_xsk *xskb)
{
return xskb->dma;
diff --git a/net/xdp/xsk_buff_pool.c b/net/xdp/xsk_buff_pool.c
index 1f7975b49657..4ea742da304d 100644
--- a/net/xdp/xsk_buff_pool.c
+++ b/net/xdp/xsk_buff_pool.c
@@ -714,3 +714,43 @@ dma_addr_t xp_raw_get_dma(struct xsk_buff_pool *pool, u64 addr)
(addr & ~PAGE_MASK);
}
EXPORT_SYMBOL(xp_raw_get_dma);
+
+/**
+ * xp_raw_get_ctx - get &xdp_desc context
+ * @pool: XSk buff pool desc address belongs to
+ * @addr: desc address (from userspace)
+ *
+ * Helper for getting desc's DMA address and metadata pointer, if present.
+ * Saves one call on hotpath, double calculation of the actual address,
+ * and inline checks for metadata presence and sanity.
+ * Please use xsk_buff_raw_get_ctx() in drivers instead.
+ *
+ * Return: new &xdp_desc_ctx struct containing desc's DMA address and metadata
+ * pointer, if it is present and valid (initialized to %NULL otherwise).
+ */
+struct xdp_desc_ctx xp_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr)
+{
+ struct xsk_tx_metadata *meta;
+ struct xdp_desc_ctx ret;
+
+ addr = pool->unaligned ? xp_unaligned_add_offset_to_addr(addr) : addr;
+ ret = (typeof(ret)){
+ /* Same logic as in xp_raw_get_dma() */
+ .dma = (pool->dma_pages[addr >> PAGE_SHIFT] &
+ ~XSK_NEXT_PG_CONTIG_MASK) + (addr & ~PAGE_MASK),
+ };
+
+ if (!pool->tx_metadata_len)
+ goto out;
+
+ /* Same logic as in xp_raw_get_data() + xsk_buff_get_metadata() */
+ meta = pool->addrs + addr - pool->tx_metadata_len;
+ if (unlikely(!xsk_buff_valid_tx_metadata(meta)))
+ goto out;
+
+ ret.meta = meta;
+
+out:
+ return ret;
+}
+EXPORT_SYMBOL(xp_raw_get_ctx);
--
2.47.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next 7/7] unroll: add generic loop unroll helpers
2024-12-18 17:44 [PATCH net-next 0/7] xdp: a fistful of generic changes pt. III Alexander Lobakin
` (5 preceding siblings ...)
2024-12-18 17:44 ` [PATCH net-next 6/7] xsk: add helper to get &xdp_desc's DMA and meta pointer in one go Alexander Lobakin
@ 2024-12-18 17:44 ` Alexander Lobakin
2024-12-20 4:00 ` [PATCH net-next 0/7] xdp: a fistful of generic changes pt. III patchwork-bot+netdevbpf
7 siblings, 0 replies; 13+ messages in thread
From: Alexander Lobakin @ 2024-12-18 17:44 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Alexander Lobakin, Alexei Starovoitov, Daniel Borkmann,
John Fastabend, Andrii Nakryiko, Jose E. Marchesi,
Toke Høiland-Jørgensen, Magnus Karlsson,
Maciej Fijalkowski, Przemek Kitszel, Jason Baron, Casey Schaufler,
Nathan Chancellor, bpf, netdev, linux-kernel
There are cases when we need to explicitly unroll loops. For example,
cache operations, filling DMA descriptors on very high speeds etc.
Add compiler-specific attribute macros to give the compiler a hint
that we'd like to unroll a loop.
Example usage:
#define UNROLL_BATCH 8
unrolled_count(UNROLL_BATCH)
for (u32 i = 0; i < UNROLL_BATCH; i++)
op(priv, i);
Note that sometimes the compilers won't unroll loops if they think this
would have worse optimization and perf than without unrolling, and that
unroll attributes are available only starting GCC 8. For older compiler
versions, no hints/attributes will be applied.
For better unrolling/parallelization, don't have any variables that
interfere between iterations except for the iterator itself.
Co-developed-by: Jose E. Marchesi <jose.marchesi@oracle.com> # pragmas
Signed-off-by: Jose E. Marchesi <jose.marchesi@oracle.com>
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
---
include/linux/unroll.h | 44 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/include/linux/unroll.h b/include/linux/unroll.h
index d42fd6366373..863fb69f6a7e 100644
--- a/include/linux/unroll.h
+++ b/include/linux/unroll.h
@@ -9,6 +9,50 @@
#include <linux/args.h>
+#ifdef CONFIG_CC_IS_CLANG
+#define __pick_unrolled(x, y) _Pragma(#x)
+#elif CONFIG_GCC_VERSION >= 80000
+#define __pick_unrolled(x, y) _Pragma(#y)
+#else
+#define __pick_unrolled(x, y) /* not supported */
+#endif
+
+/**
+ * unrolled - loop attributes to ask the compiler to unroll it
+ *
+ * Usage:
+ *
+ * #define BATCH 8
+ *
+ * unrolled_count(BATCH)
+ * for (u32 i = 0; i < BATCH; i++)
+ * // loop body without cross-iteration dependencies
+ *
+ * This is only a hint and the compiler is free to disable unrolling if it
+ * thinks the count is suboptimal and may hurt performance and/or hugely
+ * increase object code size.
+ * Not having any cross-iteration dependencies (i.e. when iter x + 1 depends
+ * on what iter x will do with variables) is not a strict requirement, but
+ * provides best performance and object code size.
+ * Available only on Clang and GCC 8.x onwards.
+ */
+
+/* Ask the compiler to pick an optimal unroll count, Clang only */
+#define unrolled \
+ __pick_unrolled(clang loop unroll(enable), /* nothing */)
+
+/* Unroll each @n iterations of the loop */
+#define unrolled_count(n) \
+ __pick_unrolled(clang loop unroll_count(n), GCC unroll n)
+
+/* Unroll the whole loop */
+#define unrolled_full \
+ __pick_unrolled(clang loop unroll(full), GCC unroll 65534)
+
+/* Never unroll the loop */
+#define unrolled_none \
+ __pick_unrolled(clang loop unroll(disable), GCC unroll 1)
+
#define UNROLL(N, MACRO, args...) CONCATENATE(__UNROLL_, N)(MACRO, args)
#define __UNROLL_0(MACRO, args...)
--
2.47.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH net-next 6/7] xsk: add helper to get &xdp_desc's DMA and meta pointer in one go
2024-12-18 17:44 ` [PATCH net-next 6/7] xsk: add helper to get &xdp_desc's DMA and meta pointer in one go Alexander Lobakin
@ 2024-12-20 3:50 ` Jakub Kicinski
2024-12-20 15:58 ` Alexander Lobakin
0 siblings, 1 reply; 13+ messages in thread
From: Jakub Kicinski @ 2024-12-20 3:50 UTC (permalink / raw)
To: Alexander Lobakin
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Paolo Abeni,
Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Jose E. Marchesi,
Toke Høiland-Jørgensen, Magnus Karlsson,
Maciej Fijalkowski, Przemek Kitszel, Jason Baron, Casey Schaufler,
Nathan Chancellor, bpf, netdev, linux-kernel
On Wed, 18 Dec 2024 18:44:34 +0100 Alexander Lobakin wrote:
> + ret = (typeof(ret)){
> + /* Same logic as in xp_raw_get_dma() */
> + .dma = (pool->dma_pages[addr >> PAGE_SHIFT] &
> + ~XSK_NEXT_PG_CONTIG_MASK) + (addr & ~PAGE_MASK),
> + };
This is quite ugly IMHO
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net-next 0/7] xdp: a fistful of generic changes pt. III
2024-12-18 17:44 [PATCH net-next 0/7] xdp: a fistful of generic changes pt. III Alexander Lobakin
` (6 preceding siblings ...)
2024-12-18 17:44 ` [PATCH net-next 7/7] unroll: add generic loop unroll helpers Alexander Lobakin
@ 2024-12-20 4:00 ` patchwork-bot+netdevbpf
7 siblings, 0 replies; 13+ messages in thread
From: patchwork-bot+netdevbpf @ 2024-12-20 4:00 UTC (permalink / raw)
To: Alexander Lobakin
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, ast, daniel,
john.fastabend, andrii, jose.marchesi, toke, magnus.karlsson,
maciej.fijalkowski, przemyslaw.kitszel, jbaron, casey, nathan,
bpf, netdev, linux-kernel
Hello:
This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Wed, 18 Dec 2024 18:44:28 +0100 you wrote:
> XDP for idpf is currently 5.(6) chapters:
> * convert Rx to libeth;
> * convert Tx and stats to libeth;
> * generic XDP and XSk code changes;
> * generic XDP and XSk code additions pt. 1;
> * generic XDP and XSk code additions pt. 2 (you are here);
> * actual XDP for idpf via new libeth_xdp;
> * XSk for idpf (via ^).
>
> [...]
Here is the summary with links:
- [net-next,1/7] page_pool: add page_pool_dev_alloc_netmem()
https://git.kernel.org/netdev/net-next/c/a19d0236f466
- [net-next,2/7] xdp: add generic xdp_buff_add_frag()
https://git.kernel.org/netdev/net-next/c/68ddc8ae1768
- [net-next,3/7] xdp: add generic xdp_build_skb_from_buff()
https://git.kernel.org/netdev/net-next/c/539c1fba1ac7
- [net-next,4/7] xsk: make xsk_buff_add_frag() really add the frag via __xdp_buff_add_frag()
(no matching commit)
- [net-next,5/7] xsk: add generic XSk &xdp_buff -> skb conversion
https://git.kernel.org/netdev/net-next/c/560d958c6c68
- [net-next,6/7] xsk: add helper to get &xdp_desc's DMA and meta pointer in one go
(no matching commit)
- [net-next,7/7] unroll: add generic loop unroll helpers
(no matching commit)
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net-next 6/7] xsk: add helper to get &xdp_desc's DMA and meta pointer in one go
2024-12-20 3:50 ` Jakub Kicinski
@ 2024-12-20 15:58 ` Alexander Lobakin
2024-12-20 17:26 ` Jakub Kicinski
0 siblings, 1 reply; 13+ messages in thread
From: Alexander Lobakin @ 2024-12-20 15:58 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Paolo Abeni,
Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Jose E. Marchesi,
Toke Høiland-Jørgensen, Magnus Karlsson,
Maciej Fijalkowski, Przemek Kitszel, Jason Baron, Casey Schaufler,
Nathan Chancellor, bpf, netdev, linux-kernel
From: Jakub Kicinski <kuba@kernel.org>
Date: Thu, 19 Dec 2024 19:50:58 -0800
> On Wed, 18 Dec 2024 18:44:34 +0100 Alexander Lobakin wrote:
>> + ret = (typeof(ret)){
>> + /* Same logic as in xp_raw_get_dma() */
>> + .dma = (pool->dma_pages[addr >> PAGE_SHIFT] &
>> + ~XSK_NEXT_PG_CONTIG_MASK) + (addr & ~PAGE_MASK),
>> + };
>
> This is quite ugly IMHO
What exactly: that the logic is copied or how that code (>> & ~ + & ~)
looks like?
If the former, I already thought of making a couple internal defs to
avoid copying.
If the latter, I also thought of this, just wanted to be clear that it's
the same as in xp_raw_get_dma(). But it can be refactored to look more
fancy anyway.
Or the compound return looks ugly? Or the struct initialization?
Thanks,
Olek
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net-next 6/7] xsk: add helper to get &xdp_desc's DMA and meta pointer in one go
2024-12-20 15:58 ` Alexander Lobakin
@ 2024-12-20 17:26 ` Jakub Kicinski
2024-12-23 13:50 ` Alexander Lobakin
0 siblings, 1 reply; 13+ messages in thread
From: Jakub Kicinski @ 2024-12-20 17:26 UTC (permalink / raw)
To: Alexander Lobakin
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Paolo Abeni,
Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Jose E. Marchesi,
Toke Høiland-Jørgensen, Magnus Karlsson,
Maciej Fijalkowski, Przemek Kitszel, Jason Baron, Casey Schaufler,
Nathan Chancellor, bpf, netdev, linux-kernel
On Fri, 20 Dec 2024 16:58:57 +0100 Alexander Lobakin wrote:
> > On Wed, 18 Dec 2024 18:44:34 +0100 Alexander Lobakin wrote:
> >> + ret = (typeof(ret)){
> >> + /* Same logic as in xp_raw_get_dma() */
> >> + .dma = (pool->dma_pages[addr >> PAGE_SHIFT] &
> >> + ~XSK_NEXT_PG_CONTIG_MASK) + (addr & ~PAGE_MASK),
> >> + };
> >
> > This is quite ugly IMHO
>
> What exactly: that the logic is copied or how that code (>> & ~ + & ~)
> looks like?
>
> If the former, I already thought of making a couple internal defs to
> avoid copying.
> If the latter, I also thought of this, just wanted to be clear that it's
> the same as in xp_raw_get_dma(). But it can be refactored to look more
> fancy anyway.
>
> Or the compound return looks ugly? Or the struct initialization?
Compound using typeof() and the fact it's multi line.
It's a two member struct, which you return by value,
so unlikely to grow. Why not init the members manually?
And you could save the intermediate computations to a temp variable
(addr >> PAGE_SHIFT, addr & ~PAGE_MASK) to make the line shorter.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net-next 6/7] xsk: add helper to get &xdp_desc's DMA and meta pointer in one go
2024-12-20 17:26 ` Jakub Kicinski
@ 2024-12-23 13:50 ` Alexander Lobakin
0 siblings, 0 replies; 13+ messages in thread
From: Alexander Lobakin @ 2024-12-23 13:50 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Paolo Abeni,
Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Jose E. Marchesi,
Toke Høiland-Jørgensen, Magnus Karlsson,
Maciej Fijalkowski, Przemek Kitszel, Jason Baron, Casey Schaufler,
Nathan Chancellor, bpf, netdev, linux-kernel
From: Jakub Kicinski <kuba@kernel.org>
Date: Fri, 20 Dec 2024 09:26:47 -0800
> On Fri, 20 Dec 2024 16:58:57 +0100 Alexander Lobakin wrote:
>>> On Wed, 18 Dec 2024 18:44:34 +0100 Alexander Lobakin wrote:
>>>> + ret = (typeof(ret)){
>>>> + /* Same logic as in xp_raw_get_dma() */
>>>> + .dma = (pool->dma_pages[addr >> PAGE_SHIFT] &
>>>> + ~XSK_NEXT_PG_CONTIG_MASK) + (addr & ~PAGE_MASK),
>>>> + };
>>>
>>> This is quite ugly IMHO
>>
>> What exactly: that the logic is copied or how that code (>> & ~ + & ~)
>> looks like?
>>
>> If the former, I already thought of making a couple internal defs to
>> avoid copying.
>> If the latter, I also thought of this, just wanted to be clear that it's
>> the same as in xp_raw_get_dma(). But it can be refactored to look more
>> fancy anyway.
>>
>> Or the compound return looks ugly? Or the struct initialization?
>
> Compound using typeof() and the fact it's multi line.
>
> It's a two member struct, which you return by value,
> so unlikely to grow. Why not init the members manually?
BTW sometimes such compound initializations are faster than
member-by-member assignment. *Not* in this case, however, so sure,
done already.
>
> And you could save the intermediate computations to a temp variable
> (addr >> PAGE_SHIFT, addr & ~PAGE_MASK) to make the line shorter.
I'll just derive it into a oneliner to not copy the same stuff again
between functions; also, page helpers like PHYS_PFN() and
offset_in_page() can be used here instead of open-coding.
Merry holidays!
Olek
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2024-12-23 13:52 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-18 17:44 [PATCH net-next 0/7] xdp: a fistful of generic changes pt. III Alexander Lobakin
2024-12-18 17:44 ` [PATCH net-next 1/7] page_pool: add page_pool_dev_alloc_netmem() Alexander Lobakin
2024-12-18 17:44 ` [PATCH net-next 2/7] xdp: add generic xdp_buff_add_frag() Alexander Lobakin
2024-12-18 17:44 ` [PATCH net-next 3/7] xdp: add generic xdp_build_skb_from_buff() Alexander Lobakin
2024-12-18 17:44 ` [PATCH net-next 4/7] xsk: make xsk_buff_add_frag() really add the frag via __xdp_buff_add_frag() Alexander Lobakin
2024-12-18 17:44 ` [PATCH net-next 5/7] xsk: add generic XSk &xdp_buff -> skb conversion Alexander Lobakin
2024-12-18 17:44 ` [PATCH net-next 6/7] xsk: add helper to get &xdp_desc's DMA and meta pointer in one go Alexander Lobakin
2024-12-20 3:50 ` Jakub Kicinski
2024-12-20 15:58 ` Alexander Lobakin
2024-12-20 17:26 ` Jakub Kicinski
2024-12-23 13:50 ` Alexander Lobakin
2024-12-18 17:44 ` [PATCH net-next 7/7] unroll: add generic loop unroll helpers Alexander Lobakin
2024-12-20 4:00 ` [PATCH net-next 0/7] xdp: a fistful of generic changes pt. III patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).