[PATCH RFC net-next 26/34] xdp: add generic XSk xdp_buff -> skb conversion

From: Alexander Lobakin
Date: Fri Dec 22 2023 - 22:07:22 EST


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.
Note that this time skb_record_rx_queue() is called unconditionally, as
it's not intended to call this function with a non-registered RxQ info.

Signed-off-by: Alexander Lobakin <aleksander.lobakin@xxxxxxxxx>
---
include/net/xdp.h | 11 ++++++++++-
net/core/xdp.c | 41 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/include/net/xdp.h b/include/net/xdp.h
index 66854b755b58..23ada4bb0e69 100644
--- a/include/net/xdp.h
+++ b/include/net/xdp.h
@@ -273,7 +273,16 @@ void xdp_warn(const char *msg, const char *func, const int line);

struct sk_buff *__xdp_build_skb_from_buff(struct sk_buff *skb,
const struct xdp_buff *xdp);
-#define xdp_build_skb_from_buff(xdp) __xdp_build_skb_from_buff(NULL, xdp)
+struct sk_buff *xdp_build_skb_from_zc(struct napi_struct *napi,
+ struct xdp_buff *xdp);
+
+static inline struct sk_buff *xdp_build_skb_from_buff(struct xdp_buff *xdp)
+{
+ if (xdp->rxq->mem.type == MEM_TYPE_XSK_BUFF_POOL)
+ return xdp_build_skb_from_zc(NULL, xdp);
+
+ return __xdp_build_skb_from_buff(NULL, 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,
diff --git a/net/core/xdp.c b/net/core/xdp.c
index 8ef1d735a7eb..2bdb1fb8a9b8 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c
@@ -21,6 +21,8 @@
#include <trace/events/xdp.h>
#include <net/xdp_sock_drv.h>

+#include "dev.h"
+
#define REG_STATE_NEW 0x0
#define REG_STATE_REGISTERED 0x1
#define REG_STATE_UNREGISTERED 0x2
@@ -647,6 +649,45 @@ struct sk_buff *__xdp_build_skb_from_buff(struct sk_buff *skb,
}
EXPORT_SYMBOL_GPL(__xdp_build_skb_from_buff);

+struct sk_buff *xdp_build_skb_from_zc(struct napi_struct *napi,
+ struct xdp_buff *xdp)
+{
+ const struct xdp_rxq_info *rxq = xdp->rxq;
+ u32 totalsize, metasize;
+ struct sk_buff *skb;
+
+ if (!napi) {
+ napi = napi_by_id(rxq->napi_id);
+ if (unlikely(!napi))
+ return NULL;
+ }
+
+ totalsize = xdp->data_end - xdp->data_meta;
+
+ skb = __napi_alloc_skb(napi, totalsize, GFP_ATOMIC | __GFP_NOWARN);
+ if (unlikely(!skb))
+ return NULL;
+
+ net_prefetch(xdp->data_meta);
+
+ memcpy(__skb_put(skb, totalsize), xdp->data_meta,
+ ALIGN(totalsize, sizeof(long)));
+
+ metasize = xdp->data - xdp->data_meta;
+ if (metasize) {
+ skb_metadata_set(skb, metasize);
+ __skb_pull(skb, metasize);
+ }
+
+ skb_record_rx_queue(skb, rxq->queue_index);
+ skb->protocol = eth_type_trans(skb, rxq->dev);
+
+ xsk_buff_free(xdp);
+
+ 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.43.0