Skip to content

Commit 0c8cb43

Browse files
yordselclaude
andcommitted
Add IPv6 support for LinuxContainer
LinuxContainer was missing IPv6 configuration that LinuxPod already had. This adds the missing calls to configure IPv6 addresses and routes on container network interfaces. Changes: - LinuxContainer.swift: Add IPv6 address and route configuration - Interface/NATInterface/NATNetworkInterface: IPv6 fields - SandboxContext proto/grpc: IPv6 methods for guest agent - VirtualMachineAgent/Vminitd: IPv6 implementation - NetlinkSession: IPv6 netlink support 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent c3fe889 commit 0c8cb43

File tree

12 files changed

+590
-49
lines changed

12 files changed

+590
-49
lines changed

Sources/Containerization/Interface.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ public protocol Interface: Sendable {
2525
/// The IP address for the default route, or nil for no default route.
2626
var ipv4Gateway: IPv4Address? { get }
2727

28+
/// The interface IPv6 address and subnet prefix length, as a CIDR address.
29+
/// Example: `fdef:4eb5:9ccb:341e:fc98:82ff:fe82:4f28/64`
30+
var ipv6Address: CIDRv6? { get }
31+
32+
/// The IPv6 address for the default route, or nil for no default route.
33+
var ipv6Gateway: IPv6Address? { get }
34+
2835
/// The interface MAC address, or nil to auto-configure the address.
2936
var macAddress: MACAddress? { get }
3037

@@ -34,4 +41,6 @@ public protocol Interface: Sendable {
3441

3542
extension Interface {
3643
public var mtu: UInt32 { 1500 }
44+
public var ipv6Address: CIDRv6? { nil }
45+
public var ipv6Gateway: IPv6Address? { nil }
3746
}

Sources/Containerization/LinuxContainer.swift

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -474,9 +474,11 @@ extension LinuxContainer {
474474
}
475475

476476
// For every interface asked for:
477-
// 1. Add the address requested
477+
// 1. Add the IPv4 address requested
478478
// 2. Online the adapter
479-
// 3. If a gateway IP address is present, add the default route.
479+
// 3. If an IPv4 gateway IP address is present, add the default route.
480+
// 4. Add the IPv6 address if present
481+
// 5. If an IPv6 gateway IP address is present, add the IPv6 default route.
480482
for (index, i) in self.interfaces.enumerated() {
481483
let name = "eth\(index)"
482484
self.logger?.debug("setting up interface \(name) with address \(i.ipv4Address)")
@@ -489,6 +491,15 @@ extension LinuxContainer {
489491
}
490492
try await agent.routeAddDefault(name: name, ipv4Gateway: ipv4Gateway)
491493
}
494+
495+
// Configure IPv6 if address is present
496+
if let ipv6Address = i.ipv6Address {
497+
self.logger?.debug("setting up interface \(name) with IPv6 address \(ipv6Address)")
498+
try await agent.addressAdd(name: name, ipv6Address: ipv6Address)
499+
if let ipv6Gateway = i.ipv6Gateway {
500+
try await agent.routeAddDefault(name: name, ipv6Gateway: ipv6Gateway)
501+
}
502+
}
492503
}
493504

494505
// Setup /etc/resolv.conf and /etc/hosts if asked for.

Sources/Containerization/LinuxPod.swift

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,9 +424,11 @@ extension LinuxPod {
424424
}
425425

426426
// For every interface asked for:
427-
// 1. Add the address requested
427+
// 1. Add the IPv4 address requested
428428
// 2. Online the adapter
429-
// 3. If a gateway IP address is present, add the default route.
429+
// 3. If an IPv4 gateway IP address is present, add the default route.
430+
// 4. Add the IPv6 address if present
431+
// 5. If an IPv6 gateway IP address is present, add the IPv6 default route.
430432
for (index, i) in self.interfaces.enumerated() {
431433
let name = "eth\(index)"
432434
self.logger?.debug("setting up interface \(name) with address \(i.ipv4Address)")
@@ -439,6 +441,15 @@ extension LinuxPod {
439441
}
440442
try await agent.routeAddDefault(name: name, ipv4Gateway: ipv4Gateway)
441443
}
444+
445+
// Configure IPv6 if address is present
446+
if let ipv6Address = i.ipv6Address {
447+
self.logger?.debug("setting up interface \(name) with IPv6 address \(ipv6Address)")
448+
try await agent.addressAdd(name: name, ipv6Address: ipv6Address)
449+
if let ipv6Gateway = i.ipv6Gateway {
450+
try await agent.routeAddDefault(name: name, ipv6Gateway: ipv6Gateway)
451+
}
452+
}
442453
}
443454

444455
// Setup /etc/resolv.conf and /etc/hosts for each container.

Sources/Containerization/NATInterface.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,23 @@ import ContainerizationExtras
1919
public struct NATInterface: Interface {
2020
public var ipv4Address: CIDRv4
2121
public var ipv4Gateway: IPv4Address?
22+
public var ipv6Address: CIDRv6?
23+
public var ipv6Gateway: IPv6Address?
2224
public var macAddress: MACAddress?
2325
public var mtu: UInt32
2426

25-
public init(ipv4Address: CIDRv4, ipv4Gateway: IPv4Address?, macAddress: MACAddress? = nil, mtu: UInt32 = 1500) {
27+
public init(
28+
ipv4Address: CIDRv4,
29+
ipv4Gateway: IPv4Address?,
30+
ipv6Address: CIDRv6? = nil,
31+
ipv6Gateway: IPv6Address? = nil,
32+
macAddress: MACAddress? = nil,
33+
mtu: UInt32 = 1500
34+
) {
2635
self.ipv4Address = ipv4Address
2736
self.ipv4Gateway = ipv4Gateway
37+
self.ipv6Address = ipv6Address
38+
self.ipv6Gateway = ipv6Gateway
2839
self.macAddress = macAddress
2940
self.mtu = mtu
3041
}

Sources/Containerization/NATNetworkInterface.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import Synchronization
2929
public final class NATNetworkInterface: Interface, Sendable {
3030
public let ipv4Address: CIDRv4
3131
public let ipv4Gateway: IPv4Address?
32+
public let ipv6Address: CIDRv6?
33+
public let ipv6Gateway: IPv6Address?
3234
public let macAddress: MACAddress?
3335
public let mtu: UInt32
3436

@@ -40,12 +42,16 @@ public final class NATNetworkInterface: Interface, Sendable {
4042
public init(
4143
ipv4Address: CIDRv4,
4244
ipv4Gateway: IPv4Address?,
45+
ipv6Address: CIDRv6? = nil,
46+
ipv6Gateway: IPv6Address? = nil,
4347
reference: sending vmnet_network_ref,
4448
macAddress: MACAddress? = nil,
4549
mtu: UInt32 = 1500
4650
) {
4751
self.ipv4Address = ipv4Address
4852
self.ipv4Gateway = ipv4Gateway
53+
self.ipv6Address = ipv6Address
54+
self.ipv6Gateway = ipv6Gateway
4955
self.macAddress = macAddress
5056
self.mtu = mtu
5157
self.reference = reference
@@ -55,11 +61,15 @@ public final class NATNetworkInterface: Interface, Sendable {
5561
public init(
5662
ipv4Address: CIDRv4,
5763
ipv4Gateway: IPv4Address?,
64+
ipv6Address: CIDRv6? = nil,
65+
ipv6Gateway: IPv6Address? = nil,
5866
macAddress: MACAddress? = nil,
5967
mtu: UInt32 = 1500
6068
) {
6169
self.ipv4Address = ipv4Address
6270
self.ipv4Gateway = ipv4Gateway
71+
self.ipv6Address = ipv6Address
72+
self.ipv6Gateway = ipv6Gateway
6373
self.macAddress = macAddress
6474
self.mtu = mtu
6575
self.reference = nil

0 commit comments

Comments
 (0)