From: David Keogh <dkeogh@amazon.com>
To: <netdev@vger.kernel.org>, Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>,
Eric Dumazet <edumazet@kernel.org>
Cc: Dragos Tatulea <dtatulea@nvidia.com>,
Nimrod Oren <noren@nvidia.com>, <nh-open-source@amazon.com>,
<linux-kernel@vger.kernel.org>
Subject: [RFC net-next 1/6] net: add tx_extra_headroom and LL_ALLOC_SPACE()
Date: Thu, 15 Oct 2026 23:53:30 +0000 [thread overview]
Message-ID: <20261015235335.4162993-2-dkeogh@amazon.com> (raw)
In-Reply-To: <20261015235335.4162993-1-dkeogh@amazon.com>
Programs attached at TC egress commonly push additional headers onto a
packet, for example to encapsulate it. When the packet does not carry
enough headroom the BPF helpers reallocate the head, which costs an
allocation and a copy per packet.
Locally generated UDP, raw and AF_PACKET traffic is allocated with
exactly LL_RESERVED_SPACE() of headroom, which only covers the driver's
own requirement in needed_headroom. There is currently no way for an
administrator to ask for more headroom at allocation time without
changing the driver.
Add a tx_extra_headroom field to struct net_device for that purpose,
together with LL_ALLOC_SPACE() and LL_ALLOC_SPACE_EX(). These add the
extra reservation on top of LL_RESERVED_SPACE() while keeping the
link-layer header alignment unchanged.
The new macros are intended only for sites that allocate new packets.
LL_RESERVED_SPACE() keeps its current meaning and remains the threshold
used when checking whether an existing packet must be expanded, so the
extra reservation never forces a reallocation on its own: packets that
already have enough room for the headers being pushed, such as TCP
segments built with MAX_TCP_HEADER, are left alone.
Keep the extra reservation separate from needed_headroom so that driver
updates of their own requirement do not clobber it and so that it can
be cleared independently. Place the field in the padding that follows
needed_headroom, which keeps it in the TX read-mostly cacheline group.
The field is not set anywhere yet. A later patch exposes it through
rtnetlink.
Signed-off-by: David Keogh <dkeogh@amazon.com>
---
.../networking/net_cachelines/net_device.rst | 1 +
include/linux/netdevice.h | 33 +++++++++++++++++++
net/core/dev.c | 2 ++
3 files changed, 36 insertions(+)
diff --git a/Documentation/networking/net_cachelines/net_device.rst b/Documentation/networking/net_cachelines/net_device.rst
index 8eceaa80b..a7e311fb7 100644
--- a/Documentation/networking/net_cachelines/net_device.rst
+++ b/Documentation/networking/net_cachelines/net_device.rst
@@ -35,6 +35,7 @@ unsigned_short gflags
unsigned_short hard_header_len read_mostly read_mostly ip6_xmit(tx);gro_list_prepare(rx)
unsigned_int mtu read_mostly ip_finish_output2
unsigned_short needed_headroom read_mostly LL_RESERVED_SPACE/ip_finish_output2
+unsigned_short tx_extra_headroom read_mostly LL_ALLOC_SPACE/__ip_append_data
unsigned_short needed_tailroom
netdev_features_t features read_mostly read_mostly HARD_TX_LOCK,netif_skb_features,sk_setup_caps(tx);netif_elide_gro(rx)
netdev_features_t hw_features
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 8fbe3a5d8..9a2a12db1 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -309,6 +309,24 @@ struct hh_cache {
((((dev)->hard_header_len + READ_ONCE((dev)->needed_headroom) + (extra)) \
& ~(HH_DATA_MOD - 1)) + HH_DATA_MOD)
+/*
+ * Headroom to reserve when allocating a locally generated packet for
+ * transmission through a device. On top of LL_RESERVED_SPACE() this adds
+ * the administrator-configured tx_extra_headroom, folded in before the
+ * alignment so that the link-layer header placement does not change.
+ *
+ * Only use this for new allocations. Code that checks whether an existing
+ * packet has enough headroom must keep using LL_RESERVED_SPACE(), so that
+ * the extra reservation can never force a reallocation by itself.
+ */
+#define LL_ALLOC_SPACE_EX(dev, hlen) \
+ LL_RESERVED_SPACE_EX(dev, (hlen) + READ_ONCE((dev)->tx_extra_headroom))
+#define LL_ALLOC_SPACE(dev) \
+ LL_ALLOC_SPACE_EX(dev, (dev)->hard_header_len)
+
+/* Upper bound for tx_extra_headroom, in bytes. */
+#define NETDEV_TX_EXTRA_HEADROOM_MAX 512
+
struct header_ops {
int (*create) (struct sk_buff *skb, struct net_device *dev,
unsigned short type, const void *daddr,
@@ -1925,6 +1943,10 @@ enum netdev_reg_state {
*
* @needed_headroom: Extra headroom the hardware may need, but not in all
* cases can this be guaranteed
+ * @tx_extra_headroom: Additional headroom reserved when allocating
+ * locally generated packets for transmission,
+ * configured by the administrator. Not a driver
+ * requirement; see LL_ALLOC_SPACE()
* @needed_tailroom: Extra tailroom the hardware may need, but not in all
* cases can this be guaranteed. Some cases also use
* LL_MAX_HEADER instead to allocate the skb
@@ -2187,6 +2209,7 @@ struct net_device {
*/
unsigned int mtu;
unsigned short needed_headroom;
+ unsigned short tx_extra_headroom;
struct netdev_tc_txq tc_to_txq[TC_MAX_QUEUE];
#ifdef CONFIG_XPS
struct xps_dev_maps __rcu *xps_maps[XPS_MAPS_MAX];
@@ -2758,6 +2781,16 @@ struct netdev_queue *netdev_core_pick_tx(struct net_device *dev,
struct sk_buff *skb,
struct net_device *sb_dev);
+/* Same as LL_ALLOC_SPACE() without link-layer header and alignment, for
+ * callers that size the headroom themselves.
+ */
+static inline unsigned int
+netdev_tx_alloc_headroom(const struct net_device *dev)
+{
+ return READ_ONCE(dev->needed_headroom) +
+ READ_ONCE(dev->tx_extra_headroom);
+}
+
/* returns the headroom that the master device needs to take in account
* when forwarding to this dev
*/
diff --git a/net/core/dev.c b/net/core/dev.c
index 8eb9bf1ff..a79f55b85 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -13501,6 +13501,8 @@ static void __init net_dev_struct_check(void)
CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_tx, num_tc);
CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_tx, mtu);
CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_tx, needed_headroom);
+ CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_tx,
+ tx_extra_headroom);
CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_tx, tc_to_txq);
#ifdef CONFIG_XPS
CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_tx, xps_maps);
--
2.50.1
next prev parent reply other threads:[~2026-10-15 23:54 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-15 23:53 [RFC net-next 0/6] net: configurable extra TX headroom for local egress David Keogh
2026-10-15 23:53 ` David Keogh [this message]
2026-10-15 23:53 ` [RFC net-next 2/6] net: reserve " David Keogh
2026-10-15 23:53 ` [RFC net-next 3/6] rtnetlink: add IFLA_TX_EXTRA_HEADROOM David Keogh
2026-10-15 23:53 ` [RFC net-next 4/6] selftests: net: add tx_extra_headroom test David Keogh
2026-10-15 23:53 ` [RFC net-next 5/6] selftests/bpf: add tx_extra_headroom data-plane programs David Keogh
2026-10-15 23:53 ` [RFC net-next 6/6] selftests/net: add tx_extra_headroom data-plane test David Keogh
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261015235335.4162993-2-dkeogh@amazon.com \
--to=dkeogh@amazon.com \
--cc=dtatulea@nvidia.com \
--cc=edumazet@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=nh-open-source@amazon.com \
--cc=noren@nvidia.com \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox