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 02/15] ipxlat: add RFC 6052 address conversion helpers
Date: Thu, 19 Mar 2026 16:12:11 +0100 [thread overview]
Message-ID: <20260319151230.655687-3-ralf@mandelbit.com> (raw)
In-Reply-To: <20260319151230.655687-1-ralf@mandelbit.com>
Introduce IPv4/IPv6 stateless address mapping helpers used by the
translation pipeline. Add the core 4<->6 conversion routines, including
RFC 6052 prefix embedding/extraction and the RFC 6791 fallback source
selection logic used by ICMP translation paths.
Signed-off-by: Ralf Lici <ralf@mandelbit.com>
---
drivers/net/ipxlat/Makefile | 1 +
drivers/net/ipxlat/address.c | 132 +++++++++++++++++++++++++++++++++++
drivers/net/ipxlat/address.h | 59 ++++++++++++++++
3 files changed, 192 insertions(+)
create mode 100644 drivers/net/ipxlat/address.c
create mode 100644 drivers/net/ipxlat/address.h
diff --git a/drivers/net/ipxlat/Makefile b/drivers/net/ipxlat/Makefile
index bd48c2700bf5..b6367dedd78e 100644
--- a/drivers/net/ipxlat/Makefile
+++ b/drivers/net/ipxlat/Makefile
@@ -5,3 +5,4 @@
obj-$(CONFIG_IPXLAT) := ipxlat.o
ipxlat-objs += main.o
+ipxlat-objs += address.o
diff --git a/drivers/net/ipxlat/address.c b/drivers/net/ipxlat/address.c
new file mode 100644
index 000000000000..d1a2b7d1768f
--- /dev/null
+++ b/drivers/net/ipxlat/address.c
@@ -0,0 +1,132 @@
+// 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 "address.h"
+
+static bool ipxlat_prefix6_contains(const struct ipv6_prefix *prefix,
+ const struct in6_addr *addr)
+{
+ return ipv6_prefix_equal(&prefix->addr, addr, prefix->len);
+}
+
+static __be32 ipxlat_64_extract_addr(const struct in6_addr *src,
+ unsigned int q1, unsigned int q2,
+ unsigned int q3, unsigned int q4)
+{
+ q1 = src->s6_addr[q1];
+ q2 = src->s6_addr[q2];
+ q3 = src->s6_addr[q3];
+ q4 = src->s6_addr[q4];
+ return htonl((q1 << 24) | (q2 << 16) | (q3 << 8) | q4);
+}
+
+static void ipxlat_46_embed_addr(__be32 __src, struct in6_addr *dst,
+ unsigned int q1, unsigned int q2,
+ unsigned int q3, unsigned int q4)
+{
+ u32 src = ntohl(__src);
+
+ dst->s6_addr[q1] = ((src >> 24) & 0xFF);
+ dst->s6_addr[q2] = ((src >> 16) & 0xFF);
+ dst->s6_addr[q3] = ((src >> 8) & 0xFF);
+ dst->s6_addr[q4] = ((src) & 0xFF);
+}
+
+void ipxlat_46_convert_addr(const struct ipv6_prefix *xlat_prefix6,
+ __be32 addr4, struct in6_addr *addr6)
+{
+ *addr6 = xlat_prefix6->addr;
+
+ switch (xlat_prefix6->len) {
+ case 96:
+ addr6->s6_addr32[3] = addr4;
+ return;
+ case 64:
+ ipxlat_46_embed_addr(addr4, addr6, 9, 10, 11, 12);
+ return;
+ case 56:
+ ipxlat_46_embed_addr(addr4, addr6, 7, 9, 10, 11);
+ return;
+ case 48:
+ ipxlat_46_embed_addr(addr4, addr6, 6, 7, 9, 10);
+ return;
+ case 40:
+ ipxlat_46_embed_addr(addr4, addr6, 5, 6, 7, 9);
+ return;
+ case 32:
+ addr6->s6_addr32[1] = addr4;
+ return;
+ }
+
+ DEBUG_NET_WARN_ON_ONCE(1);
+}
+
+int ipxlat_64_convert_addrs(const struct ipv6_prefix *xlat_prefix6,
+ const struct ipv6hdr *hdr6, bool icmp_err,
+ __be32 *src, __be32 *dst)
+{
+ bool src_ok;
+
+ src_ok = ipxlat_prefix6_contains(xlat_prefix6, &hdr6->saddr);
+ if (unlikely(!src_ok && !icmp_err))
+ return -EINVAL;
+ if (unlikely(!ipxlat_prefix6_contains(xlat_prefix6, &hdr6->daddr)))
+ return -EINVAL;
+
+ switch (xlat_prefix6->len) {
+ case 96:
+ if (likely(src_ok))
+ *src = hdr6->saddr.s6_addr32[3];
+ *dst = hdr6->daddr.s6_addr32[3];
+ break;
+ case 64:
+ if (likely(src_ok))
+ *src = ipxlat_64_extract_addr(&hdr6->saddr, 9, 10, 11,
+ 12);
+ *dst = ipxlat_64_extract_addr(&hdr6->daddr, 9, 10, 11, 12);
+ break;
+ case 56:
+ if (likely(src_ok))
+ *src = ipxlat_64_extract_addr(&hdr6->saddr, 7,
+ 9, 10, 11);
+ *dst = ipxlat_64_extract_addr(&hdr6->daddr, 7, 9, 10, 11);
+ break;
+ case 48:
+ if (likely(src_ok))
+ *src = ipxlat_64_extract_addr(&hdr6->saddr, 6,
+ 7, 9, 10);
+ *dst = ipxlat_64_extract_addr(&hdr6->daddr, 6, 7, 9, 10);
+ break;
+ case 40:
+ if (likely(src_ok))
+ *src = ipxlat_64_extract_addr(&hdr6->saddr, 5, 6, 7, 9);
+ *dst = ipxlat_64_extract_addr(&hdr6->daddr, 5, 6, 7, 9);
+ break;
+ case 32:
+ if (likely(src_ok))
+ *src = hdr6->saddr.s6_addr32[1];
+ *dst = hdr6->daddr.s6_addr32[1];
+ break;
+ default:
+ DEBUG_NET_WARN_ON_ONCE(1);
+ return -EINVAL;
+ }
+
+ /* keep 6->4 ICMP error translation functional even when the ICMPv6
+ * source is not xlat_prefix6-mapped (for example, stack-generated PTB)
+ */
+ if (unlikely(!src_ok))
+ *src = htonl(INADDR_DUMMY);
+
+ return 0;
+}
diff --git a/drivers/net/ipxlat/address.h b/drivers/net/ipxlat/address.h
new file mode 100644
index 000000000000..4283fdddac56
--- /dev/null
+++ b/drivers/net/ipxlat/address.h
@@ -0,0 +1,59 @@
+/* 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_ADDRESS_H_
+#define _NET_IPXLAT_ADDRESS_H_
+
+#include <linux/ip.h>
+#include <net/ipv6.h>
+
+#include "ipxlpriv.h"
+
+/**
+ * ipxlat_46_convert_addr - translate one IPv4 address into RFC 6052 IPv6 form
+ * @xlat_prefix6: configured RFC 6052 prefix
+ * @addr4: IPv4 address to convert
+ * @addr6: output IPv6 address
+ */
+void ipxlat_46_convert_addr(const struct ipv6_prefix *xlat_prefix6,
+ __be32 addr4, struct in6_addr *addr6);
+
+/**
+ * ipxlat_64_convert_addrs - translate outer IPv6 endpoints into IPv4 pair
+ * @xlat_prefix6: configured RFC 6052 prefix
+ * @hdr6: source IPv6 header
+ * @icmp_err: source packet is ICMPv6 error
+ * @src: output IPv4 source address
+ * @dst: output IPv4 destination address
+ *
+ * Return: 0 on success, negative errno on non-translatable addresses.
+ */
+int ipxlat_64_convert_addrs(const struct ipv6_prefix *xlat_prefix6,
+ const struct ipv6hdr *hdr6, bool icmp_err,
+ __be32 *src, __be32 *dst);
+
+/**
+ * ipxlat_46_convert_addrs - translate outer IPv4 endpoints into IPv6 pair
+ * @xlat_prefix6: configured RFC 6052 prefix
+ * @iph4: source IPv4 header
+ * @iph6: output IPv6 header (only saddr/daddr are updated)
+ */
+static inline void
+ipxlat_46_convert_addrs(const struct ipv6_prefix *xlat_prefix6,
+ const struct iphdr *iph4, struct ipv6hdr *iph6)
+{
+ ipxlat_46_convert_addr(xlat_prefix6, iph4->saddr, &iph6->saddr);
+ ipxlat_46_convert_addr(xlat_prefix6, iph4->daddr, &iph6->daddr);
+}
+
+#endif /* _NET_IPXLAT_ADDRESS_H_ */
--
2.53.0
next prev parent reply other threads:[~2026-03-19 15:22 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 ` Ralf Lici [this message]
2026-03-19 15:12 ` [RFC net-next 03/15] ipxlat: add packet metadata control block helpers Ralf Lici
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-3-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