Configuring IPv6 Address via Linux Kernel Boot Parameters: ip= Equivalent for IPv6 Networking


2 views

While Linux systems have long supported IPv4 address configuration through kernel boot parameters using the ip= syntax, the equivalent functionality for IPv6 remains conspicuously absent from standard kernel documentation. This gap becomes particularly problematic in scenarios like:

# Example of IPv4 boot configuration we're trying to match for IPv6
ip=192.0.2.1::192.0.2.62:255.255.255.192::eth0:none

For systems requiring early IPv6 connectivity (particularly in pre-boot environments), we have several suboptimal alternatives:

# Option 1: Static configuration in initramfs
ip -6 addr add 2001:db8::1/64 dev eth0
ip -6 route add default via 2001:db8::fffe

The fundamental issue is that none of these solutions integrate with the kernel's early boot parameter system as cleanly as the IPv4 ip= parameter does.

After examining kernel source (particularly net/ipv6/addrconf.c and drivers/net/netconsole.c), I found no built-in equivalent to ip= for IPv6. However, we can implement this through:

# Option 2: Custom kernel patch
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 1a2b3c4..5d6e7f9 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4641,6 +4641,33 @@ static int __init addrconf_init(void)
 {
     int err;
 
+    /* Check for ip6= boot parameter */
+    {
+        char *ip6_param, *ifname, *addr, *next;
+        ip6_param = strstr(boot_command_line, "ip6=");
+        if (ip6_param) {
+            ip6_param += 4; // Skip "ip6="
+            ifname = strsep(&ip6_param, ":");
+            addr = strsep(&ip6_param, ":");
+            if (ifname && addr) {
+                struct in6_addr in6;
+                if (in6_pton(addr, -1, (u8 *)&in6, '\0', NULL) > 0) {
+                    struct net_device *dev;
+                    dev = dev_get_by_name(&init_net, ifname);
+                    if (dev) {
+                        struct inet6_ifaddr *ifp;
+                        ifp = ipv6_add_addr(dev, &in6, 0, 
+                                           IFA_F_PERMANENT);
+                        if (!IS_ERR(ifp))
+                            printk(KERN_INFO "IPv6 boot address %pI6 configured on %s\n",
+                                   &ifp->addr, ifname);
+                        dev_put(dev);
+                    }
+                }
+            }
+        }
+    }
+
     err = addrconf_init_net(&init_net);
     if (err < 0)
         goto out;

For users who can't modify their kernel, consider these approaches:

# Option 3: Early userspace script in initramfs
#!/bin/sh
PREREQ="network"
prereqs() {
    echo "$PREREQ"
}

case $1 in
    prereqs)
        prereqs
        exit 0
        ;;
esac

ip link set eth0 up
ip -6 addr add 2001:db8::1/64 dev eth0
ip -6 route add default via 2001:db8::fffe

For systems using dropbear in initramfs, ensure your init script includes:

# Example for Debian/Ubuntu initramfs-tools
local_ip=2001:db8::1
remote_ip=2001:db8::fffe
ip -6 addr add $local_ip/64 dev eth0
ip -6 route add default via $remote_ip

The Linux kernel's ip= boot parameter follows this syntax for IPv4 configuration:

ip=client_ip:server_ip:gw_ip:netmask:hostname:interface:none

Example configuration that sets static IPv4 on eth0:

ip=192.0.2.1::192.0.2.62:255.255.255.192::eth0:none

Unlike IPv4, there's no direct kernel boot parameter equivalent for IPv6. The need arises in scenarios like:

  • Pre-boot environments (e.g., Dropbear SSH for encrypted root unlock)
  • Network segments without DHCPv6 or RA
  • Hosting provider networks where network configuration cannot be modified

Method 1: Using initramfs scripts

Add this to your initramfs scripts (e.g., /etc/initramfs-tools/scripts/init-premount/static_ipv6):

#!/bin/sh
PREREQ=""
prereqs()
{
    echo "$PREREQ"
}
case $1 in
prereqs)
    prereqs
    exit 0
    ;;
esac

ip -6 addr add 2001:db8::1/64 dev eth0
ip -6 route add default via 2001:db8::ffff

Then update initramfs:

chmod +x /etc/initramfs-tools/scripts/init-premount/static_ipv6
update-initramfs -u

Method 2: GRUB network configuration

For systems using GRUB with network boot:

menuentry 'Linux with IPv6' {
    linux /boot/vmlinuz root=/dev/sda1 ipv6.disable=0
    initrd /boot/initrd.img
    # GRUB network commands (limited IPv6 support)
    net_add_addr enp0s3 2001:db8::1/64
    net_add_route default 2001:db8::ffff
}

Method 3: Kernel command-line extension

Create a custom kernel parameter handler by modifying the kernel source (advanced):

// In drivers/net/netconsole.c or similar
static int __init ipv6_setup(char *str)
{
    char *ip_str, *dev_str;
    ip_str = strsep(&str, ":");
    dev_str = str;
    
    if (ip_str && dev_str) {
        printk(KERN_INFO "Configuring IPv6 %s on %s\n", ip_str, dev_str);
        // Actual implementation would call netdevice APIs
    }
    return 1;
}
__setup("ipv6=", ipv6_setup);

When kernel-level configuration isn't possible:

  • Early userspace scripts: Systemd units with Before=network.target
  • Network manager hooks: Use nmcli in startup scripts
  • Cloud-init: For cloud environments with metadata service

The inability to configure IPv6 at boot creates challenges for:

  • Headless servers in remote locations
  • Secure boot environments requiring early network access
  • Network bootstrap systems without DHCP infrastructure

Current Linux distributions typically handle this through userspace networking daemons, but for special cases, the above solutions provide viable alternatives.