public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
From: Ralf Lici <ralf@mandelbit.com>
To: netdev@vger.kernel.org
Cc: "Daniel Gröber" <dxld@darkboxed.org>,
	"Ralf Lici" <ralf@mandelbit.com>,
	"Antonio Quartulli" <antonio@mandelbit.com>,
	"Andrew Lunn" <andrew+netdev@lunn.ch>,
	"David S. Miller" <davem@davemloft.net>,
	"Eric Dumazet" <edumazet@google.com>,
	"Jakub Kicinski" <kuba@kernel.org>,
	"Paolo Abeni" <pabeni@redhat.com>,
	linux-kernel@vger.kernel.org
Subject: [RFC net-next 03/15] ipxlat: add packet metadata control block helpers
Date: Thu, 19 Mar 2026 16:12:12 +0100	[thread overview]
Message-ID: <20260319151230.655687-4-ralf@mandelbit.com> (raw)
In-Reply-To: <20260319151230.655687-1-ralf@mandelbit.com>

Add the per-skb control-block layout and shared packet helper routines
used by translation stages introducing common metadata bookkeeping
(offset rebasing and invariant checks) plus protocol-fragment helper
utilities.

Signed-off-by: Ralf Lici <ralf@mandelbit.com>
---
 drivers/net/ipxlat/Makefile |   1 +
 drivers/net/ipxlat/packet.c |  99 +++++++++++++++++++++
 drivers/net/ipxlat/packet.h | 166 ++++++++++++++++++++++++++++++++++++
 3 files changed, 266 insertions(+)
 create mode 100644 drivers/net/ipxlat/packet.c
 create mode 100644 drivers/net/ipxlat/packet.h

diff --git a/drivers/net/ipxlat/Makefile b/drivers/net/ipxlat/Makefile
index b6367dedd78e..90dbc0489fa2 100644
--- a/drivers/net/ipxlat/Makefile
+++ b/drivers/net/ipxlat/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_IPXLAT) := ipxlat.o
 
 ipxlat-objs += main.o
 ipxlat-objs += address.o
+ipxlat-objs += packet.o
diff --git a/drivers/net/ipxlat/packet.c b/drivers/net/ipxlat/packet.c
new file mode 100644
index 000000000000..f82c375255f3
--- /dev/null
+++ b/drivers/net/ipxlat/packet.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0
+/*  IPXLAT - Stateless IP/ICMP Translation (SIIT) virtual device driver
+ *
+ *  Copyright (C) 2024- Alberto Leiva Popper <ydahhrk@gmail.com>
+ *  Copyright (C) 2026- Mandelbit SRL
+ *  Copyright (C) 2026- Daniel Gröber <dxld@darkboxed.org>
+ *
+ *  Author:	Alberto Leiva Popper <ydahhrk@gmail.com>
+ *		Antonio Quartulli <antonio@mandelbit.com>
+ *		Daniel Gröber <dxld@darkboxed.org>
+ *		Ralf Lici <ralf@mandelbit.com>
+ */
+
+#include "packet.h"
+
+/* Shift cached skb cb offsets by the L3 header delta after in-place rewrite.
+ *
+ * Translation may replace only the outer L3 header size (4->6 or 6->4), while
+ * cached offsets were computed before rewrite. Rebasing applies the same delta
+ * to all cached absolute offsets so they still point to the same logical
+ * fields in the modified skb.
+ *
+ * This helper only guards against underflow (< 0). Relative ordering checks
+ * are done by ipxlat_cb_offsets_valid.
+ */
+int ipxlat_cb_rebase_offsets(struct ipxlat_cb *cb, int delta)
+{
+	int off;
+
+	off = cb->l4_off + delta;
+	if (unlikely(off < 0))
+		return -EINVAL;
+	cb->l4_off = off;
+
+	off = cb->payload_off + delta;
+	if (unlikely(off < 0))
+		return -EINVAL;
+	cb->payload_off = off;
+
+	if (unlikely(cb->is_icmp_err)) {
+		off = cb->inner_l3_offset + delta;
+		if (unlikely(off < 0))
+			return -EINVAL;
+		cb->inner_l3_offset = off;
+
+		off = cb->inner_l4_offset + delta;
+		if (unlikely(off < 0))
+			return -EINVAL;
+		cb->inner_l4_offset = off;
+
+		if (cb->inner_fragh_off) {
+			off = cb->inner_fragh_off + delta;
+			if (unlikely(off < 0))
+				return -EINVAL;
+			cb->inner_fragh_off = off;
+		}
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_DEBUG_NET
+/* Verify ordering/range relations between cached skb cb offsets.
+ *
+ * Unlike ipxlat_cb_rebase_offsets, this checks structural invariants:
+ * l4 <= payload, inner_l3 >= payload, inner_l3 <= inner_l4, and fragment
+ * header (when present) located inside inner L3 area before inner L4.
+ */
+bool ipxlat_cb_offsets_valid(const struct ipxlat_cb *cb)
+{
+	if (unlikely(cb->payload_off < cb->l4_off))
+		return false;
+
+	if (unlikely(cb->is_icmp_err)) {
+		if (unlikely(cb->inner_l3_offset < cb->payload_off))
+			return false;
+		if (unlikely(cb->inner_l4_offset < cb->inner_l3_offset))
+			return false;
+		if (unlikely(cb->inner_fragh_off &&
+			     cb->inner_fragh_off < cb->inner_l3_offset))
+			return false;
+		if (unlikely(cb->inner_fragh_off &&
+			     cb->inner_fragh_off >= cb->inner_l4_offset))
+			return false;
+	}
+
+	return true;
+}
+#endif
+
+int ipxlat_v4_validate_skb(struct ipxlat_priv *ipxl, struct sk_buff *skb)
+{
+	return -EOPNOTSUPP;
+}
+
+int ipxlat_v6_validate_skb(struct sk_buff *skb)
+{
+	return -EOPNOTSUPP;
+}
diff --git a/drivers/net/ipxlat/packet.h b/drivers/net/ipxlat/packet.h
new file mode 100644
index 000000000000..f39c25987940
--- /dev/null
+++ b/drivers/net/ipxlat/packet.h
@@ -0,0 +1,166 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*  IPXLAT - Stateless IP/ICMP Translation (SIIT) virtual device driver
+ *
+ *  Copyright (C) 2024- Alberto Leiva Popper <ydahhrk@gmail.com>
+ *  Copyright (C) 2026- Mandelbit SRL
+ *  Copyright (C) 2026- Daniel Gröber <dxld@darkboxed.org>
+ *
+ *  Author:	Alberto Leiva Popper <ydahhrk@gmail.com>
+ *		Antonio Quartulli <antonio@mandelbit.com>
+ *		Daniel Gröber <dxld@darkboxed.org>
+ *		Ralf Lici <ralf@mandelbit.com>
+ */
+
+#ifndef _NET_IPXLAT_PACKET_H_
+#define _NET_IPXLAT_PACKET_H_
+
+#include <net/ip.h>
+
+#include "ipxlpriv.h"
+
+/**
+ * struct ipxlat_cb - per-skb parser and control metadata stored in skb->cb
+ * @l4_off: outer L4 header offset
+ * @payload_off: outer payload offset
+ * @fragh_off: outer IPv6 Fragment Header offset, or 0 if absent
+ * @inner_l3_offset: quoted inner L3 offset for ICMP errors
+ * @inner_l4_offset: quoted inner L4 offset for ICMP errors
+ * @inner_fragh_off: quoted inner IPv6 Fragment Header offset, or 0
+ * @udp_zero_csum_len: outer UDP length used for 4->6 checksum synthesis
+ * @frag_max_size: pre-fragment payload cap for ip_do_fragment
+ * @l4_proto: outer L4 protocol (or nexthdr for IPv6)
+ * @inner_l4_proto: quoted inner L4 protocol
+ * @l3_hdr_len: outer L3 header length including extension headers
+ * @inner_l3_hdr_len: quoted inner L3 header length
+ * @is_icmp_err: packet is ICMP error and carries quoted inner packet
+ * @emit_icmp_err: datapath must emit translator-generated ICMP on drop
+ * @icmp_err: ICMP type/code/info cached for deferred emission
+ * @icmp_err.type: ICMP type to emit
+ * @icmp_err.code: ICMP code to emit
+ * @icmp_err.info: ICMP auxiliary info (e.g. pointer/MTU)
+ */
+struct ipxlat_cb {
+	u16 l4_off;
+	u16 payload_off;
+	u16 fragh_off;
+	u16 inner_l3_offset;
+	u16 inner_l4_offset;
+	u16 inner_fragh_off;
+	/* L4 span length (UDP header + payload) for outer IPv4 UDP packets
+	 * arriving with checksum 0.
+	 */
+	u16 udp_zero_csum_len;
+	u16 frag_max_size;
+	u8 l4_proto;
+	u8 inner_l4_proto;
+	u8 l3_hdr_len;
+	u8 inner_l3_hdr_len;
+	bool is_icmp_err;
+	bool emit_icmp_err;
+	struct {
+		u8 type;
+		u8 code;
+		u32 info;
+	} icmp_err;
+};
+
+/**
+ * ipxlat_skb_cb - return ipxlat private control block in skb->cb
+ * @skb: skb carrying ipxlat metadata
+ *
+ * Return: pointer to &struct ipxlat_cb stored in the control buffer of @skb.
+ */
+static inline struct ipxlat_cb *ipxlat_skb_cb(const struct sk_buff *skb)
+{
+	BUILD_BUG_ON(sizeof(struct ipxlat_cb) > sizeof(skb->cb));
+	return (struct ipxlat_cb *)(skb->cb);
+}
+
+static inline unsigned int ipxlat_skb_datagram_len(const struct sk_buff *skb)
+{
+	return skb->len - skb_transport_offset(skb);
+}
+
+static inline u8 ipxlat_get_ipv6_tclass(const struct ipv6hdr *hdr)
+{
+	return (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4);
+}
+
+static inline u16 ipxlat_get_frag6_offset(const struct frag_hdr *hdr)
+{
+	return be16_to_cpu(hdr->frag_off) & 0xFFF8U;
+}
+
+static inline u16 ipxlat_get_frag4_offset(const struct iphdr *hdr)
+{
+	return (be16_to_cpu(hdr->frag_off) & IP_OFFSET) << 3;
+}
+
+static inline bool ipxlat_is_first_frag6(const struct frag_hdr *hdr)
+{
+	return hdr ? (ipxlat_get_frag6_offset(hdr) == 0) : true;
+}
+
+static inline bool ipxlat_is_first_frag4(const struct iphdr *hdr)
+{
+	return !(hdr->frag_off & htons(IP_OFFSET));
+}
+
+static inline __be16 ipxlat_build_frag6_offset(u16 frag_offset, bool mf)
+{
+	return cpu_to_be16((frag_offset & 0xFFF8U) | mf);
+}
+
+static inline __be16
+ipxlat_build_frag4_offset(bool df, bool mf, u16 frag_offset)
+{
+	return cpu_to_be16((df ? (1U << 14) : 0) | (mf ? (1U << 13) : 0) |
+			   (frag_offset >> 3));
+}
+
+/**
+ * ipxlat_cb_rebase_offsets - shift cached cb offsets after skb relayout
+ * @cb: parsed packet metadata
+ * @delta: signed byte delta applied to cached offsets
+ *
+ * Return: 0 on success, negative errno if rebased offsets would underflow.
+ */
+int ipxlat_cb_rebase_offsets(struct ipxlat_cb *cb, int delta);
+#ifdef CONFIG_DEBUG_NET
+/**
+ * ipxlat_cb_offsets_valid - validate monotonicity and bounds of cb offsets
+ * @cb: parsed packet metadata
+ *
+ * Return: true if cached offsets are internally consistent.
+ */
+bool ipxlat_cb_offsets_valid(const struct ipxlat_cb *cb);
+#else
+static inline bool ipxlat_cb_offsets_valid(const struct ipxlat_cb *cb)
+{
+	return true;
+}
+#endif
+
+/**
+ * ipxlat_v4_validate_skb - validate and summarize IPv4 packet into skb->cb
+ * @ipxlat: translator private context
+ * @skb: packet to validate
+ *
+ * Populates &struct ipxlat_cb and may mark translator-generated ICMP action on
+ * failure paths.
+ *
+ * Return: 0 on success, negative errno on validation failure.
+ */
+int ipxlat_v4_validate_skb(struct ipxlat_priv *ipxlat, struct sk_buff *skb);
+
+/**
+ * ipxlat_v6_validate_skb - validate and summarize IPv6 packet into skb->cb
+ * @skb: packet to validate
+ *
+ * Populates &struct ipxlat_cb for subsequent 6->4 translation.
+ *
+ * Return: 0 on success, negative errno on validation failure.
+ */
+int ipxlat_v6_validate_skb(struct sk_buff *skb);
+
+#endif /* _NET_IPXLAT_PACKET_H_ */
-- 
2.53.0


  parent reply	other threads:[~2026-03-19 15:13 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-19 15:12 [RFC net-next 00/15] Introducing ipxlat: a stateless IPv4/IPv6 translation device Ralf Lici
2026-03-19 15:12 ` [RFC net-next 01/15] drivers/net: add ipxlat netdevice skeleton and build plumbing Ralf Lici
2026-03-19 15:12 ` [RFC net-next 02/15] ipxlat: add RFC 6052 address conversion helpers Ralf Lici
2026-03-19 15:12 ` Ralf Lici [this message]
2026-03-19 15:12 ` [RFC net-next 04/15] ipxlat: add IPv4 packet validation path Ralf Lici
2026-03-19 15:12 ` [RFC net-next 05/15] ipxlat: add IPv6 " Ralf Lici
2026-03-19 15:12 ` [RFC net-next 06/15] ipxlat: add transport checksum and offload helpers Ralf Lici
2026-03-19 15:12 ` [RFC net-next 07/15] ipxlat: add 4to6 and 6to4 TCP/UDP translation helpers Ralf Lici
2026-03-19 15:12 ` [RFC net-next 08/15] ipxlat: add translation engine and dispatch core Ralf Lici
2026-03-19 15:12 ` [RFC net-next 09/15] ipxlat: emit translator-generated ICMP errors on drop Ralf Lici
2026-03-19 15:12 ` [RFC net-next 10/15] ipxlat: add 4to6 pre-fragmentation path Ralf Lici
2026-03-19 15:12 ` [RFC net-next 11/15] ipxlat: add ICMP informational translation paths Ralf Lici
2026-03-19 15:12 ` [RFC net-next 12/15] ipxlat: add ICMP error translation and quoted-inner handling Ralf Lici
2026-03-19 15:12 ` [RFC net-next 13/15] ipxlat: add netlink control plane and uapi Ralf Lici
2026-03-19 15:12 ` [RFC net-next 14/15] selftests: net: add ipxlat coverage Ralf Lici
2026-03-19 15:12 ` [RFC net-next 15/15] Documentation: networking: add ipxlat translator guide Ralf Lici
2026-03-19 22:11   ` Jonathan Corbet
2026-03-24  9:55     ` Ralf Lici

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=20260319151230.655687-4-ralf@mandelbit.com \
    --to=ralf@mandelbit.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=antonio@mandelbit.com \
    --cc=davem@davemloft.net \
    --cc=dxld@darkboxed.org \
    --cc=edumazet@google.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --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