mirror of
https://github.com/apple/container.git
synced 2026-08-24 10:05:43 -05:00
Add mtu option for network attachments (#1267)
This commit is contained in:
@@ -31,6 +31,8 @@ public struct Attachment: Codable, Sendable {
|
||||
public let ipv6Address: CIDRv6?
|
||||
/// The MAC address associated with the attachment (optional).
|
||||
public let macAddress: MACAddress?
|
||||
/// The MTU for the network interface.
|
||||
public let mtu: UInt32?
|
||||
|
||||
public init(
|
||||
network: String,
|
||||
@@ -38,7 +40,8 @@ public struct Attachment: Codable, Sendable {
|
||||
ipv4Address: CIDRv4,
|
||||
ipv4Gateway: IPv4Address,
|
||||
ipv6Address: CIDRv6?,
|
||||
macAddress: MACAddress?
|
||||
macAddress: MACAddress?,
|
||||
mtu: UInt32? = nil
|
||||
) {
|
||||
self.network = network
|
||||
self.hostname = hostname
|
||||
@@ -46,5 +49,6 @@ public struct Attachment: Codable, Sendable {
|
||||
self.ipv4Gateway = ipv4Gateway
|
||||
self.ipv6Address = ipv6Address
|
||||
self.macAddress = macAddress
|
||||
self.mtu = mtu
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,8 +38,12 @@ public struct AttachmentOptions: Codable, Sendable {
|
||||
/// The MAC address associated with the attachment (optional).
|
||||
public let macAddress: MACAddress?
|
||||
|
||||
public init(hostname: String, macAddress: MACAddress? = nil) {
|
||||
/// The MTU for the network interface.
|
||||
public let mtu: UInt32?
|
||||
|
||||
public init(hostname: String, macAddress: MACAddress? = nil, mtu: UInt32? = nil) {
|
||||
self.hostname = hostname
|
||||
self.macAddress = macAddress
|
||||
self.mtu = mtu
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ struct IsolatedInterfaceStrategy: InterfaceStrategy {
|
||||
ipv4Gateway: ipv4Gateway,
|
||||
macAddress: attachment.macAddress,
|
||||
// https://github.com/apple/containerization/pull/38
|
||||
mtu: 1280
|
||||
mtu: attachment.mtu ?? 1280
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ struct NonisolatedInterfaceStrategy: InterfaceStrategy {
|
||||
reference: networkRef,
|
||||
macAddress: attachment.macAddress,
|
||||
// https://github.com/apple/containerization/pull/38
|
||||
mtu: 1280
|
||||
mtu: attachment.mtu ?? 1280
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ public struct Flags {
|
||||
@Option(name: .long, help: "Use the specified name as the container ID")
|
||||
public var name: String?
|
||||
|
||||
@Option(name: [.customLong("network")], help: "Attach the container to a network (format: <name>[,mac=XX:XX:XX:XX:XX:XX])")
|
||||
@Option(name: [.customLong("network")], help: "Attach the container to a network (format: <name>[,mac=XX:XX:XX:XX:XX:XX][,mtu=VALUE])")
|
||||
public var networks: [String] = []
|
||||
|
||||
@Flag(name: [.customLong("no-dns")], help: "Do not configure DNS in the container")
|
||||
|
||||
@@ -795,16 +795,18 @@ public struct Parser {
|
||||
public struct ParsedNetwork {
|
||||
public let name: String
|
||||
public let macAddress: String?
|
||||
public let mtu: UInt32?
|
||||
|
||||
public init(name: String, macAddress: String? = nil) {
|
||||
public init(name: String, macAddress: String? = nil, mtu: UInt32? = nil) {
|
||||
self.name = name
|
||||
self.macAddress = macAddress
|
||||
self.mtu = mtu
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse network attachment with optional properties
|
||||
/// Format: network_name[,mac=XX:XX:XX:XX:XX:XX]
|
||||
/// Example: "backend,mac=02:42:ac:11:00:02"
|
||||
/// Format: network_name[,mac=XX:XX:XX:XX:XX:XX][,mtu=VALUE]
|
||||
/// Example: "backend,mac=02:42:ac:11:00:02,mtu=1500"
|
||||
public static func network(_ networkSpec: String) throws -> ParsedNetwork {
|
||||
guard !networkSpec.isEmpty else {
|
||||
throw ContainerizationError(.invalidArgument, message: "network specification cannot be empty")
|
||||
@@ -822,6 +824,7 @@ public struct Parser {
|
||||
}
|
||||
|
||||
var macAddress: String?
|
||||
var mtu: UInt32?
|
||||
|
||||
// Parse properties if any
|
||||
for part in parts.dropFirst() {
|
||||
@@ -848,15 +851,23 @@ public struct Parser {
|
||||
)
|
||||
}
|
||||
macAddress = value
|
||||
case "mtu":
|
||||
guard let mtuValue = UInt32(value), mtuValue >= 1280, mtuValue <= 65535 else {
|
||||
throw ContainerizationError(
|
||||
.invalidArgument,
|
||||
message: "invalid mtu value '\(value)': must be between 1280 and 65535"
|
||||
)
|
||||
}
|
||||
mtu = mtuValue
|
||||
default:
|
||||
throw ContainerizationError(
|
||||
.invalidArgument,
|
||||
message: "unknown network property '\(key)'. Available properties: mac"
|
||||
message: "unknown network property '\(key)'. Available properties: mac, mtu"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return ParsedNetwork(name: networkName, macAddress: macAddress)
|
||||
return ParsedNetwork(name: networkName, macAddress: macAddress, mtu: mtu)
|
||||
}
|
||||
|
||||
// MARK: DNS
|
||||
|
||||
@@ -297,15 +297,16 @@ public struct Utility {
|
||||
// attach the first network using the fqdn, and the rest using just the container ID
|
||||
return try networks.enumerated().map { item in
|
||||
let macAddress = try item.element.macAddress.map { try MACAddress($0) }
|
||||
let mtu = item.element.mtu ?? 1280
|
||||
guard item.offset == 0 else {
|
||||
return AttachmentConfiguration(
|
||||
network: item.element.name,
|
||||
options: AttachmentOptions(hostname: containerId, macAddress: macAddress)
|
||||
options: AttachmentOptions(hostname: containerId, macAddress: macAddress, mtu: mtu)
|
||||
)
|
||||
}
|
||||
return AttachmentConfiguration(
|
||||
network: item.element.name,
|
||||
options: AttachmentOptions(hostname: fqdn ?? containerId, macAddress: macAddress)
|
||||
options: AttachmentOptions(hostname: fqdn ?? containerId, macAddress: macAddress, mtu: mtu)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -314,7 +315,7 @@ public struct Utility {
|
||||
guard let builtinNetworkId else {
|
||||
throw ContainerizationError(.invalidState, message: "builtin network is not present")
|
||||
}
|
||||
return [AttachmentConfiguration(network: builtinNetworkId, options: AttachmentOptions(hostname: fqdn ?? containerId, macAddress: nil))]
|
||||
return [AttachmentConfiguration(network: builtinNetworkId, options: AttachmentOptions(hostname: fqdn ?? containerId, macAddress: nil, mtu: 1280))]
|
||||
}
|
||||
|
||||
private static func getKernel(management: Flags.Management) async throws -> Kernel {
|
||||
|
||||
@@ -417,9 +417,26 @@ public actor ContainersService {
|
||||
hostname: n.options.hostname,
|
||||
macAddress: n.options.macAddress
|
||||
)
|
||||
guard let allocatedAttach = allocatedAttach else {
|
||||
guard var allocatedAttach = allocatedAttach else {
|
||||
throw ContainerizationError(.internalError, message: "failed to allocate a network")
|
||||
}
|
||||
|
||||
if let mtu = n.options.mtu {
|
||||
let a = allocatedAttach.attachment
|
||||
allocatedAttach = AllocatedAttachment(
|
||||
attachment: Attachment(
|
||||
network: a.network,
|
||||
hostname: a.hostname,
|
||||
ipv4Address: a.ipv4Address,
|
||||
ipv4Gateway: a.ipv4Gateway,
|
||||
ipv6Address: a.ipv6Address,
|
||||
macAddress: a.macAddress,
|
||||
mtu: mtu
|
||||
),
|
||||
additionalData: allocatedAttach.additionalData,
|
||||
pluginInfo: allocatedAttach.pluginInfo
|
||||
)
|
||||
}
|
||||
allocatedAttachments.append(allocatedAttach)
|
||||
}
|
||||
|
||||
|
||||
@@ -191,6 +191,19 @@ class TestCLINetwork: CLITest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test func testNetworkMTU() async throws {
|
||||
let name = getLowercasedTestName()
|
||||
try? doStop(name: name)
|
||||
try? doRemove(name: name)
|
||||
|
||||
try doLongRun(name: name, args: ["--network", "default,mtu=1500"])
|
||||
defer { try? doStop(name: name) }
|
||||
|
||||
try waitForContainerRunning(name)
|
||||
let output = try doExec(name: name, cmd: ["ip", "link", "show", "eth0"])
|
||||
#expect(output.contains("mtu 1500"), "expected mtu 1500 in ip link output: \(output)")
|
||||
}
|
||||
|
||||
@available(macOS 26, *)
|
||||
@Test func testIsolatedNetwork() async throws {
|
||||
do {
|
||||
|
||||
Reference in New Issue
Block a user