[RFC net-next 01/15] drivers/net: add ipxlat netdevice skeleton and build plumbing
From: Ralf Lici <hidden>
Date: 2026-03-19 15:19:50
Also in:
lkml
Subsystem:
networking drivers, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
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 <redacted> --- 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