netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next v2] xdp: Add helpers for head length, headroom, and metadata length
@ 2025-04-30 20:11 Jon Kohler
  2025-04-30 21:05 ` Jacob Keller
  2025-04-30 21:09 ` Stanislav Fomichev
  0 siblings, 2 replies; 7+ messages in thread
From: Jon Kohler @ 2025-04-30 20:11 UTC (permalink / raw)
  To: Willem de Bruijn, Jason Wang, Andrew Lunn, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Alexei Starovoitov,
	Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend,
	Simon Horman, netdev, linux-kernel, bpf
  Cc: Jon Kohler

Introduce new XDP helpers:
- xdp_headlen: Similar to skb_headlen
- xdp_headroom: Similar to skb_headroom
- xdp_metadata_len: Similar to skb_metadata_len

Integrate these helpers into tap, tun, and XDP implementation to start.

No functional changes introduced.

Signed-off-by: Jon Kohler <jon@nutanix.com>
---
v1->v2: Integrate feedback from Willem
https://patchwork.kernel.org/project/netdevbpf/patch/20250430182921.1704021-1-jon@nutanix.com/

 drivers/net/tap.c |  6 +++---
 drivers/net/tun.c | 12 +++++------
 include/net/xdp.h | 54 +++++++++++++++++++++++++++++++++++++++++++----
 net/core/xdp.c    | 12 +++++------
 4 files changed, 65 insertions(+), 19 deletions(-)

diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index d4ece538f1b2..a62fbca4b08f 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -1048,7 +1048,7 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp)
 	struct sk_buff *skb;
 	int err, depth;
 
-	if (unlikely(xdp->data_end - xdp->data < ETH_HLEN)) {
+	if (unlikely(xdp_headlen(xdp) < ETH_HLEN)) {
 		err = -EINVAL;
 		goto err;
 	}
@@ -1062,8 +1062,8 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp)
 		goto err;
 	}
 
-	skb_reserve(skb, xdp->data - xdp->data_hard_start);
-	skb_put(skb, xdp->data_end - xdp->data);
+	skb_reserve(skb, xdp_headroom(xdp));
+	skb_put(skb, xdp_headlen(xdp));
 
 	skb_set_network_header(skb, ETH_HLEN);
 	skb_reset_mac_header(skb);
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 7babd1e9a378..4c47eed71986 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1567,7 +1567,7 @@ static int tun_xdp_act(struct tun_struct *tun, struct bpf_prog *xdp_prog,
 			dev_core_stats_rx_dropped_inc(tun->dev);
 			return err;
 		}
-		dev_sw_netstats_rx_add(tun->dev, xdp->data_end - xdp->data);
+		dev_sw_netstats_rx_add(tun->dev, xdp_headlen(xdp));
 		break;
 	case XDP_TX:
 		err = tun_xdp_tx(tun->dev, xdp);
@@ -1575,7 +1575,7 @@ static int tun_xdp_act(struct tun_struct *tun, struct bpf_prog *xdp_prog,
 			dev_core_stats_rx_dropped_inc(tun->dev);
 			return err;
 		}
-		dev_sw_netstats_rx_add(tun->dev, xdp->data_end - xdp->data);
+		dev_sw_netstats_rx_add(tun->dev, xdp_headlen(xdp));
 		break;
 	case XDP_PASS:
 		break;
@@ -2355,7 +2355,7 @@ static int tun_xdp_one(struct tun_struct *tun,
 		       struct xdp_buff *xdp, int *flush,
 		       struct tun_page *tpage)
 {
-	unsigned int datasize = xdp->data_end - xdp->data;
+	unsigned int datasize = xdp_headlen(xdp);
 	struct tun_xdp_hdr *hdr = xdp->data_hard_start;
 	struct virtio_net_hdr *gso = &hdr->gso;
 	struct bpf_prog *xdp_prog;
@@ -2415,14 +2415,14 @@ static int tun_xdp_one(struct tun_struct *tun,
 		goto out;
 	}
 
-	skb_reserve(skb, xdp->data - xdp->data_hard_start);
-	skb_put(skb, xdp->data_end - xdp->data);
+	skb_reserve(skb, xdp_headroom(xdp));
+	skb_put(skb, xdp_headlen(xdp));
 
 	/* The externally provided xdp_buff may have no metadata support, which
 	 * is marked by xdp->data_meta being xdp->data + 1. This will lead to a
 	 * metasize of -1 and is the reason why the condition checks for > 0.
 	 */
-	metasize = xdp->data - xdp->data_meta;
+	metasize = xdp_metadata_len(xdp);
 	if (metasize > 0)
 		skb_metadata_set(skb, metasize);
 
diff --git a/include/net/xdp.h b/include/net/xdp.h
index 48efacbaa35d..044345b18305 100644
--- a/include/net/xdp.h
+++ b/include/net/xdp.h
@@ -151,10 +151,56 @@ xdp_get_shared_info_from_buff(const struct xdp_buff *xdp)
 	return (struct skb_shared_info *)xdp_data_hard_end(xdp);
 }
 
+/**
+ * xdp_headlen - Calculate the length of the data in an XDP buffer
+ * @xdp: Pointer to the XDP buffer structure
+ *
+ * Compute the length of the data contained in the XDP buffer. Does not
+ * include frags, use xdp_get_buff_len() for that instead.
+ *
+ * Analogous to skb_headlen().
+ *
+ * Return: The length of the data in the XDP buffer in bytes.
+ */
+static inline unsigned int xdp_headlen(const struct xdp_buff *xdp)
+{
+	return xdp->data_end - xdp->data;
+}
+
+/**
+ * xdp_headroom - Calculate the headroom available in an XDP buffer
+ * @xdp: Pointer to the XDP buffer structure
+ *
+ * Compute the headroom in an XDP buffer.
+ *
+ * Analogous to the skb_headroom().
+ *
+ * Return: The size of the headroom in bytes.
+ */
+static inline unsigned int xdp_headroom(const struct xdp_buff *xdp)
+{
+	return xdp->data - xdp->data_hard_start;
+}
+
+/**
+ * xdp_metadata_len - Calculate the length of metadata in an XDP buffer
+ * @xdp: Pointer to the XDP buffer structure
+ *
+ * Compute the length of the metadata region in an XDP buffer.
+ *
+ * Analogous to skb_metadata_len().
+ *
+ * Return: The length of the metadata in bytes.
+ */
+static inline unsigned int xdp_metadata_len(const struct xdp_buff *xdp)
+{
+	return xdp->data - xdp->data_meta;
+}
+
 static __always_inline unsigned int
 xdp_get_buff_len(const struct xdp_buff *xdp)
 {
-	unsigned int len = xdp->data_end - xdp->data;
+	unsigned int len = xdp_headlen(xdp);
 	const struct skb_shared_info *sinfo;
 
 	if (likely(!xdp_buff_has_frags(xdp)))
@@ -364,8 +410,8 @@ int xdp_update_frame_from_buff(const struct xdp_buff *xdp,
 	int metasize, headroom;
 
 	/* Assure headroom is available for storing info */
-	headroom = xdp->data - xdp->data_hard_start;
-	metasize = xdp->data - xdp->data_meta;
+	headroom = xdp_headroom(xdp);
+	metasize = xdp_metadata_len(xdp);
 	metasize = metasize > 0 ? metasize : 0;
 	if (unlikely((headroom - metasize) < sizeof(*xdp_frame)))
 		return -ENOSPC;
@@ -377,7 +423,7 @@ int xdp_update_frame_from_buff(const struct xdp_buff *xdp,
 	}
 
 	xdp_frame->data = xdp->data;
-	xdp_frame->len  = xdp->data_end - xdp->data;
+	xdp_frame->len  = xdp_headlen(xdp);
 	xdp_frame->headroom = headroom - sizeof(*xdp_frame);
 	xdp_frame->metasize = metasize;
 	xdp_frame->frame_sz = xdp->frame_sz;
diff --git a/net/core/xdp.c b/net/core/xdp.c
index f86eedad586a..0d56320a7ff9 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c
@@ -581,8 +581,8 @@ struct xdp_frame *xdp_convert_zc_to_xdp_frame(struct xdp_buff *xdp)
 
 	/* Clone into a MEM_TYPE_PAGE_ORDER0 xdp_frame. */
 	metasize = xdp_data_meta_unsupported(xdp) ? 0 :
-		   xdp->data - xdp->data_meta;
-	totsize = xdp->data_end - xdp->data + metasize;
+		   xdp_metadata_len(xdp);
+	totsize = xdp_headlen(xdp) + metasize;
 
 	if (sizeof(*xdpf) + totsize > PAGE_SIZE)
 		return NULL;
@@ -646,10 +646,10 @@ struct sk_buff *xdp_build_skb_from_buff(const struct xdp_buff *xdp)
 	if (unlikely(!skb))
 		return NULL;
 
-	skb_reserve(skb, xdp->data - xdp->data_hard_start);
-	__skb_put(skb, xdp->data_end - xdp->data);
+	skb_reserve(skb, xdp_headroom(xdp));
+	__skb_put(skb, xdp_headlen(xdp));
 
-	metalen = xdp->data - xdp->data_meta;
+	metalen = xdp_metadata_len(xdp);
 	if (metalen > 0)
 		skb_metadata_set(skb, metalen);
 
@@ -763,7 +763,7 @@ struct sk_buff *xdp_build_skb_from_zc(struct xdp_buff *xdp)
 
 	memcpy(__skb_put(skb, len), xdp->data_meta, LARGEST_ALIGN(len));
 
-	metalen = xdp->data - xdp->data_meta;
+	metalen = xdp_metadata_len(xdp);
 	if (metalen > 0) {
 		skb_metadata_set(skb, metalen);
 		__skb_pull(skb, metalen);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2025-05-01  2:26 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-30 20:11 [PATCH net-next v2] xdp: Add helpers for head length, headroom, and metadata length Jon Kohler
2025-04-30 21:05 ` Jacob Keller
2025-04-30 21:09 ` Stanislav Fomichev
2025-05-01  1:00   ` Jon Kohler
2025-05-01  1:34     ` Stanislav Fomichev
2025-05-01  1:42       ` Jon Kohler
2025-05-01  2:26         ` Stanislav Fomichev

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).