Skip to content

Commit e0bedba

Browse files
authored
Add mtu option for network attachments (#1267)
1 parent ad7f843 commit e0bedba

File tree

9 files changed

+64
-14
lines changed

9 files changed

+64
-14
lines changed

Sources/ContainerResource/Network/Attachment.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,24 @@ public struct Attachment: Codable, Sendable {
3131
public let ipv6Address: CIDRv6?
3232
/// The MAC address associated with the attachment (optional).
3333
public let macAddress: MACAddress?
34+
/// The MTU for the network interface.
35+
public let mtu: UInt32?
3436

3537
public init(
3638
network: String,
3739
hostname: String,
3840
ipv4Address: CIDRv4,
3941
ipv4Gateway: IPv4Address,
4042
ipv6Address: CIDRv6?,
41-
macAddress: MACAddress?
43+
macAddress: MACAddress?,
44+
mtu: UInt32? = nil
4245
) {
4346
self.network = network
4447
self.hostname = hostname
4548
self.ipv4Address = ipv4Address
4649
self.ipv4Gateway = ipv4Gateway
4750
self.ipv6Address = ipv6Address
4851
self.macAddress = macAddress
52+
self.mtu = mtu
4953
}
5054
}

Sources/ContainerResource/Network/AttachmentConfiguration.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,12 @@ public struct AttachmentOptions: Codable, Sendable {
3838
/// The MAC address associated with the attachment (optional).
3939
public let macAddress: MACAddress?
4040

41-
public init(hostname: String, macAddress: MACAddress? = nil) {
41+
/// The MTU for the network interface.
42+
public let mtu: UInt32?
43+
44+
public init(hostname: String, macAddress: MACAddress? = nil, mtu: UInt32? = nil) {
4245
self.hostname = hostname
4346
self.macAddress = macAddress
47+
self.mtu = mtu
4448
}
4549
}

Sources/Helpers/RuntimeLinux/IsolatedInterfaceStrategy.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ struct IsolatedInterfaceStrategy: InterfaceStrategy {
3030
ipv4Gateway: ipv4Gateway,
3131
macAddress: attachment.macAddress,
3232
// https://github.com/apple/containerization/pull/38
33-
mtu: 1280
33+
mtu: attachment.mtu ?? 1280
3434
)
3535
}
3636
}

Sources/Helpers/RuntimeLinux/NonisolatedInterfaceStrategy.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ struct NonisolatedInterfaceStrategy: InterfaceStrategy {
5050
reference: networkRef,
5151
macAddress: attachment.macAddress,
5252
// https://github.com/apple/containerization/pull/38
53-
mtu: 1280
53+
mtu: attachment.mtu ?? 1280
5454
)
5555
}
5656
}

Sources/Services/ContainerAPIService/Client/Flags.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ public struct Flags {
268268
@Option(name: .long, help: "Use the specified name as the container ID")
269269
public var name: String?
270270

271-
@Option(name: [.customLong("network")], help: "Attach the container to a network (format: <name>[,mac=XX:XX:XX:XX:XX:XX])")
271+
@Option(name: [.customLong("network")], help: "Attach the container to a network (format: <name>[,mac=XX:XX:XX:XX:XX:XX][,mtu=VALUE])")
272272
public var networks: [String] = []
273273

274274
@Flag(name: [.customLong("no-dns")], help: "Do not configure DNS in the container")

Sources/Services/ContainerAPIService/Client/Parser.swift

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -795,16 +795,18 @@ public struct Parser {
795795
public struct ParsedNetwork {
796796
public let name: String
797797
public let macAddress: String?
798+
public let mtu: UInt32?
798799

799-
public init(name: String, macAddress: String? = nil) {
800+
public init(name: String, macAddress: String? = nil, mtu: UInt32? = nil) {
800801
self.name = name
801802
self.macAddress = macAddress
803+
self.mtu = mtu
802804
}
803805
}
804806

805807
/// Parse network attachment with optional properties
806-
/// Format: network_name[,mac=XX:XX:XX:XX:XX:XX]
807-
/// Example: "backend,mac=02:42:ac:11:00:02"
808+
/// Format: network_name[,mac=XX:XX:XX:XX:XX:XX][,mtu=VALUE]
809+
/// Example: "backend,mac=02:42:ac:11:00:02,mtu=1500"
808810
public static func network(_ networkSpec: String) throws -> ParsedNetwork {
809811
guard !networkSpec.isEmpty else {
810812
throw ContainerizationError(.invalidArgument, message: "network specification cannot be empty")
@@ -822,6 +824,7 @@ public struct Parser {
822824
}
823825

824826
var macAddress: String?
827+
var mtu: UInt32?
825828

826829
// Parse properties if any
827830
for part in parts.dropFirst() {
@@ -848,15 +851,23 @@ public struct Parser {
848851
)
849852
}
850853
macAddress = value
854+
case "mtu":
855+
guard let mtuValue = UInt32(value), mtuValue >= 1280, mtuValue <= 65535 else {
856+
throw ContainerizationError(
857+
.invalidArgument,
858+
message: "invalid mtu value '\(value)': must be between 1280 and 65535"
859+
)
860+
}
861+
mtu = mtuValue
851862
default:
852863
throw ContainerizationError(
853864
.invalidArgument,
854-
message: "unknown network property '\(key)'. Available properties: mac"
865+
message: "unknown network property '\(key)'. Available properties: mac, mtu"
855866
)
856867
}
857868
}
858869

859-
return ParsedNetwork(name: networkName, macAddress: macAddress)
870+
return ParsedNetwork(name: networkName, macAddress: macAddress, mtu: mtu)
860871
}
861872

862873
// MARK: DNS

Sources/Services/ContainerAPIService/Client/Utility.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,15 +297,16 @@ public struct Utility {
297297
// attach the first network using the fqdn, and the rest using just the container ID
298298
return try networks.enumerated().map { item in
299299
let macAddress = try item.element.macAddress.map { try MACAddress($0) }
300+
let mtu = item.element.mtu ?? 1280
300301
guard item.offset == 0 else {
301302
return AttachmentConfiguration(
302303
network: item.element.name,
303-
options: AttachmentOptions(hostname: containerId, macAddress: macAddress)
304+
options: AttachmentOptions(hostname: containerId, macAddress: macAddress, mtu: mtu)
304305
)
305306
}
306307
return AttachmentConfiguration(
307308
network: item.element.name,
308-
options: AttachmentOptions(hostname: fqdn ?? containerId, macAddress: macAddress)
309+
options: AttachmentOptions(hostname: fqdn ?? containerId, macAddress: macAddress, mtu: mtu)
309310
)
310311
}
311312
}
@@ -314,7 +315,7 @@ public struct Utility {
314315
guard let builtinNetworkId else {
315316
throw ContainerizationError(.invalidState, message: "builtin network is not present")
316317
}
317-
return [AttachmentConfiguration(network: builtinNetworkId, options: AttachmentOptions(hostname: fqdn ?? containerId, macAddress: nil))]
318+
return [AttachmentConfiguration(network: builtinNetworkId, options: AttachmentOptions(hostname: fqdn ?? containerId, macAddress: nil, mtu: 1280))]
318319
}
319320

320321
private static func getKernel(management: Flags.Management) async throws -> Kernel {

Sources/Services/ContainerAPIService/Server/Containers/ContainersService.swift

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,9 +417,26 @@ public actor ContainersService {
417417
hostname: n.options.hostname,
418418
macAddress: n.options.macAddress
419419
)
420-
guard let allocatedAttach = allocatedAttach else {
420+
guard var allocatedAttach = allocatedAttach else {
421421
throw ContainerizationError(.internalError, message: "failed to allocate a network")
422422
}
423+
424+
if let mtu = n.options.mtu {
425+
let a = allocatedAttach.attachment
426+
allocatedAttach = AllocatedAttachment(
427+
attachment: Attachment(
428+
network: a.network,
429+
hostname: a.hostname,
430+
ipv4Address: a.ipv4Address,
431+
ipv4Gateway: a.ipv4Gateway,
432+
ipv6Address: a.ipv6Address,
433+
macAddress: a.macAddress,
434+
mtu: mtu
435+
),
436+
additionalData: allocatedAttach.additionalData,
437+
pluginInfo: allocatedAttach.pluginInfo
438+
)
439+
}
423440
allocatedAttachments.append(allocatedAttach)
424441
}
425442

Tests/CLITests/Subcommands/Networks/TestCLINetwork.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,19 @@ class TestCLINetwork: CLITest {
191191
}
192192
}
193193

194+
@Test func testNetworkMTU() async throws {
195+
let name = getLowercasedTestName()
196+
try? doStop(name: name)
197+
try? doRemove(name: name)
198+
199+
try doLongRun(name: name, args: ["--network", "default,mtu=1500"])
200+
defer { try? doStop(name: name) }
201+
202+
try waitForContainerRunning(name)
203+
let output = try doExec(name: name, cmd: ["ip", "link", "show", "eth0"])
204+
#expect(output.contains("mtu 1500"), "expected mtu 1500 in ip link output: \(output)")
205+
}
206+
194207
@available(macOS 26, *)
195208
@Test func testIsolatedNetwork() async throws {
196209
do {

0 commit comments

Comments
 (0)