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 01/15] drivers/net: add ipxlat netdevice skeleton and build plumbing
Date: Thu, 19 Mar 2026 16:12:10 +0100 [thread overview]
Message-ID: <20260319151230.655687-2-ralf@mandelbit.com> (raw)
In-Reply-To: <20260319151230.655687-1-ralf@mandelbit.com>
ipxlat is a virtual netdevice implementing stateless IPv4/IPv6
translation (SIIT). The translation model follows RFC 7915 behavior and
RFC 6052 address embedding rules.
The netdevice form is intentional: it provides per-instance lifecycle,
MTU/statistics semantics and explicit routing integration, so translated
traffic can be steered through a dedicated device and configured per
namespace.
This series targets ipxlat as a reusable kernel building block for SIIT
deployments and for NAT64-style setups when combined with existing
nftables rules in userspace policy.
This first patch introduces only the driver scaffolding:
- drivers/net/ipxlat/ directory and build integration
- Kconfig/Makefile entries
- basic private structures and defaults
- rtnl_link_ops and netdevice skeleton needed to create/register links
No translation logic is added in this patch yet. Follow-up patches add
packet validation, transport/ICMP translation, error handling,
fragmentation handling, generic netlink control plane, selftests and
documentation.
Signed-off-by: Ralf Lici <ralf@mandelbit.com>
---
drivers/net/Kconfig | 13 ++++
drivers/net/Makefile | 1 +
drivers/net/ipxlat/Makefile | 7 ++
drivers/net/ipxlat/ipxlpriv.h | 53 +++++++++++++
drivers/net/ipxlat/main.c | 137 ++++++++++++++++++++++++++++++++++
drivers/net/ipxlat/main.h | 27 +++++++
6 files changed, 238 insertions(+)
create mode 100644 drivers/net/ipxlat/Makefile
create mode 100644 drivers/net/ipxlat/ipxlpriv.h
create mode 100644 drivers/net/ipxlat/main.c
create mode 100644 drivers/net/ipxlat/main.h
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index b2fd90466bab..a3b28f294d95 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -117,6 +117,19 @@ config OVPN
This module enhances the performance of the OpenVPN userspace software
by offloading the data channel processing to kernelspace.
+config IPXLAT
+ tristate "IPv6<>IPv4 packet translation virtual device (SIIT)"
+ depends on NET && INET && IPV6
+ help
+ Virtual network device driver for Stateless IP/ICMP Packet
+ Translation (RFC 7915). Useful for IPv6 focused networks.
+ Particularly NAT64, SIIT-DC, 464XLAT network architectures.
+
+ See also <file:Documentation/networking/ipxlat.rst>.
+
+ To compile this driver as a module, choose M here: the module will be
+ called ipxlat.
+
config EQUALIZER
tristate "EQL (serial line load balancing) support"
help
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 5b01215f6829..4f982c9e6585 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_NET) += loopback.o
obj-$(CONFIG_NETDEV_LEGACY_INIT) += Space.o
obj-$(CONFIG_NETCONSOLE) += netconsole.o
obj-$(CONFIG_NETKIT) += netkit.o
+obj-$(CONFIG_IPXLAT) += ipxlat/
obj-y += phy/
obj-y += pse-pd/
obj-y += mdio/
diff --git a/drivers/net/ipxlat/Makefile b/drivers/net/ipxlat/Makefile
new file mode 100644
index 000000000000..bd48c2700bf5
--- /dev/null
+++ b/drivers/net/ipxlat/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# IPXLAT - Stateless IP/ICMP Translation (SIIT) virtual device driver
+
+obj-$(CONFIG_IPXLAT) := ipxlat.o
+
+ipxlat-objs += main.o
diff --git a/drivers/net/ipxlat/ipxlpriv.h b/drivers/net/ipxlat/ipxlpriv.h
new file mode 100644
index 000000000000..5027d8377bdd
--- /dev/null
+++ b/drivers/net/ipxlat/ipxlpriv.h
@@ -0,0 +1,53 @@
+/* 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_IPXLPRIV_H_
+#define _NET_IPXLAT_IPXLPRIV_H_
+
+#include <linux/mutex.h>
+#include <linux/netdevice.h>
+#include <net/gro_cells.h>
+
+/**
+ * struct ipv6_prefix - IPv6 prefix definition
+ * @addr: prefix address (host bits may be non-zero)
+ * @len: prefix length in bits
+ */
+struct ipv6_prefix {
+ struct in6_addr addr;
+ u8 len;
+};
+
+/**
+ * struct ipxlat_priv - private state stored in netdev priv area
+ * @dev: owning netdevice
+ * @xlat_prefix6: RFC 6052 prefix used for stateless v4<->v6 mapping
+ * @lowest_ipv6_mtu: LIM threshold used by 4->6 pre-fragment planning
+ * @cfg_lock: serializes control-plane updates
+ * @gro_cells: receive-side reinjection queue used by forward path
+ *
+ * Datapath reads config without taking @cfg_lock to keep per-packet overhead
+ * low. Writers serialize updates under @cfg_lock. During reconfiguration,
+ * readers may transiently observe mixed old/new values; this may cause a small
+ * number of drops and is an accepted tradeoff for a lightweight datapath.
+ */
+struct ipxlat_priv {
+ struct net_device *dev;
+ struct ipv6_prefix xlat_prefix6;
+ u32 lowest_ipv6_mtu;
+ /* serializes control-plane updates */
+ struct mutex cfg_lock;
+ struct gro_cells gro_cells;
+};
+
+#endif /* _NET_IPXLAT_IPXLPRIV_H_ */
diff --git a/drivers/net/ipxlat/main.c b/drivers/net/ipxlat/main.c
new file mode 100644
index 000000000000..26b7f5b6ff20
--- /dev/null
+++ b/drivers/net/ipxlat/main.c
@@ -0,0 +1,137 @@
+// 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 <linux/module.h>
+
+#include <net/ip.h>
+
+#include "ipxlpriv.h"
+#include "main.h"
+
+MODULE_AUTHOR("Alberto Leiva Popper <ydahhrk@gmail.com>");
+MODULE_AUTHOR("Antonio Quartulli <antonio@mandelbit.com>");
+MODULE_AUTHOR("Daniel Gröber <dxld@darkboxed.org>");
+MODULE_AUTHOR("Ralf Lici <ralf@mandelbit.com>");
+MODULE_DESCRIPTION("IPv6<>IPv4 translation virtual netdev support (SIIT)");
+MODULE_LICENSE("GPL");
+
+static int ipxlat_dev_init(struct net_device *dev)
+{
+ struct ipxlat_priv *ipxlat = netdev_priv(dev);
+ int err;
+
+ ipxlat->dev = dev;
+ /* default xlat-prefix6 is 64:ff9b::/96 */
+ ipxlat->xlat_prefix6.addr.s6_addr32[0] = htonl(0x0064ff9b);
+ ipxlat->xlat_prefix6.addr.s6_addr32[1] = 0;
+ ipxlat->xlat_prefix6.addr.s6_addr32[2] = 0;
+ ipxlat->xlat_prefix6.addr.s6_addr32[3] = 0;
+ ipxlat->xlat_prefix6.len = 96;
+ ipxlat->lowest_ipv6_mtu = 1280;
+ mutex_init(&ipxlat->cfg_lock);
+
+ err = gro_cells_init(&ipxlat->gro_cells, dev);
+ if (unlikely(err))
+ return err;
+
+ return 0;
+}
+
+static void ipxlat_dev_uninit(struct net_device *dev)
+{
+ struct ipxlat_priv *ipxlat = netdev_priv(dev);
+
+ gro_cells_destroy(&ipxlat->gro_cells);
+}
+
+static int ipxlat_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ dev_dstats_tx_dropped(dev);
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+}
+
+static const struct net_device_ops ipxlat_netdev_ops = {
+ .ndo_init = ipxlat_dev_init,
+ .ndo_uninit = ipxlat_dev_uninit,
+ .ndo_start_xmit = ipxlat_start_xmit,
+};
+
+static const struct device_type ipxlat_type = {
+ .name = "ipxlat",
+};
+
+static void ipxlat_setup(struct net_device *dev)
+{
+ const netdev_features_t feat = NETIF_F_SG | NETIF_F_FRAGLIST |
+ NETIF_F_HW_CSUM | NETIF_F_HIGHDMA |
+ NETIF_F_GSO_SOFTWARE;
+
+ dev->type = ARPHRD_NONE;
+ dev->flags = IFF_NOARP;
+ dev->priv_flags |= IFF_NO_QUEUE;
+ dev->hard_header_len = 0;
+ dev->addr_len = 0;
+
+ dev->lltx = true;
+ dev->features |= feat;
+ dev->hw_features |= feat;
+ dev->hw_enc_features |= feat;
+
+ dev->netdev_ops = &ipxlat_netdev_ops;
+ dev->needs_free_netdev = true;
+ dev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS;
+ dev->max_mtu = IP_MAX_MTU - sizeof(struct ipv6hdr) -
+ sizeof(struct iphdr);
+ dev->min_mtu = IPV6_MIN_MTU;
+ dev->mtu = ETH_DATA_LEN;
+
+ /* keep skb->dst up to ndo_start_xmit so ICMP error emission can
+ * reuse routing metadata from ingress when available
+ */
+ netif_keep_dst(dev);
+
+ SET_NETDEV_DEVTYPE(dev, &ipxlat_type);
+}
+
+static struct rtnl_link_ops ipxlat_link_ops = {
+ .kind = "ipxlat",
+ .priv_size = sizeof(struct ipxlat_priv),
+ .setup = ipxlat_setup,
+};
+
+bool ipxlat_dev_is_valid(const struct net_device *dev)
+{
+ return dev->rtnl_link_ops == &ipxlat_link_ops;
+}
+
+static int __init ipxlat_init(void)
+{
+ int err;
+
+ err = rtnl_link_register(&ipxlat_link_ops);
+ if (err) {
+ pr_err("ipxlat: failed to register rtnl link ops: %d\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
+static void __exit ipxlat_exit(void)
+{
+ rtnl_link_unregister(&ipxlat_link_ops);
+}
+
+module_init(ipxlat_init);
+module_exit(ipxlat_exit);
diff --git a/drivers/net/ipxlat/main.h b/drivers/net/ipxlat/main.h
new file mode 100644
index 000000000000..fb78f910b2e2
--- /dev/null
+++ b/drivers/net/ipxlat/main.h
@@ -0,0 +1,27 @@
+/* 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_MAIN_H_
+#define _NET_IPXLAT_MAIN_H_
+
+#include <linux/netdevice.h>
+
+/**
+ * ipxlat_dev_is_valid - tell whether a netdev is an ipxlat interface
+ * @dev: netdevice to inspect
+ *
+ * Return: true if @dev was created with ipxlat link ops.
+ */
+bool ipxlat_dev_is_valid(const struct net_device *dev);
+
+#endif /* _NET_IPXLAT_MAIN_H_ */
--
2.53.0
next prev parent reply other threads:[~2026-03-19 15:19 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 ` Ralf Lici [this message]
2026-03-19 15:12 ` [RFC net-next 02/15] ipxlat: add RFC 6052 address conversion helpers Ralf Lici
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-2-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