From 98ffa5f655f7b83e715f13a2330f8bba91526a6a Mon Sep 17 00:00:00 2001 From: agnosticdev Date: Thu, 2 Jul 2026 18:12:22 -0700 Subject: [PATCH 1/5] Updates to Swift UDP --- Sources/SwiftNetwork/Protocols/Checksum.swift | 22 +++ .../Protocols/HarnessProtocols.swift | 4 + .../SwiftNetwork/Protocols/UDPProtocol.swift | 87 +++++++++--- .../SwiftNetworkUDPTests.swift | 130 +++++++++++++++++- 4 files changed, 224 insertions(+), 19 deletions(-) diff --git a/Sources/SwiftNetwork/Protocols/Checksum.swift b/Sources/SwiftNetwork/Protocols/Checksum.swift index 0ef95ac..85cad4a 100644 --- a/Sources/SwiftNetwork/Protocols/Checksum.swift +++ b/Sources/SwiftNetwork/Protocols/Checksum.swift @@ -57,6 +57,23 @@ enum ChecksumError: Error { case invalidBuffer } +struct ChecksumFlags: OptionSet { + let rawValue: UInt8 + static let partial = ChecksumFlags(rawValue: 0x01) + static let zeroInvert = ChecksumFlags(rawValue: 0x02) + static let ip = ChecksumFlags(rawValue: 0x04) + static let tcpv4 = ChecksumFlags(rawValue: 0x08) + static let udpv4 = ChecksumFlags(rawValue: 0x10) + static let tcpv6 = ChecksumFlags(rawValue: 0x20) + static let udpv6 = ChecksumFlags(rawValue: 0x40) +} + +struct InterfaceChecksumFlags: OptionSet { + let rawValue: UInt32 + static let csumUDP = InterfaceChecksumFlags(rawValue: 0x0000_0004) + static let csumUDPIPV6 = InterfaceChecksumFlags(rawValue: 0x0000_0040) +} + @available(Network 0.1.0, *) extension IPv6Address { func checksum() -> UInt32 { @@ -141,6 +158,11 @@ extension Frame { return ((~value) & 0xffff) } + mutating func setInternetChecksum(flags: ChecksumFlags, startOffset: UInt16, checksumOffset: UInt16) -> Bool { + checksumOffloadFlags |= flags.rawValue + return false + } + mutating func finalizeIPChecksum(checksumOffset: Int, zeroInvert: Bool) throws(ChecksumError) { let unclaimedLength = self.unclaimedLength if unclaimedLength == 0 { diff --git a/Sources/SwiftNetwork/Protocols/HarnessProtocols.swift b/Sources/SwiftNetwork/Protocols/HarnessProtocols.swift index 0875dc3..d3c2984 100644 --- a/Sources/SwiftNetwork/Protocols/HarnessProtocols.swift +++ b/Sources/SwiftNetwork/Protocols/HarnessProtocols.swift @@ -237,6 +237,10 @@ public class UpperHarness: UpperHarnessProtocol return invokeGetMetadata() as? ProtocolMetadata

} + final public func getMetrics(requestedNetworkMetric: RequestedNetworkMetrics) -> NetworkMetrics? { + lower.invokeGetMetrics(reference, requestedNetworkMetric: requestedNetworkMetric) + } + public func setApplicationError(_ applicationError: UInt64, applicationErrorReason: String) { if let metadata: ProtocolMetadata = self.getMetadata() { metadata.perProtocolMetadata?.quicConnectionMetadata?.applicationError = applicationError diff --git a/Sources/SwiftNetwork/Protocols/UDPProtocol.swift b/Sources/SwiftNetwork/Protocols/UDPProtocol.swift index 0f6c05e..b3af06a 100644 --- a/Sources/SwiftNetwork/Protocols/UDPProtocol.swift +++ b/Sources/SwiftNetwork/Protocols/UDPProtocol.swift @@ -97,8 +97,12 @@ public struct UDPProtocol: NetworkProtocol { var eventManager = ProtocolEventManager() // Only called by newProtocolInstance() - fileprivate static func registerNewUDP(on context: NetworkContext) -> ProtocolInstanceReference { - let udp = UDPInstance(context: context) + fileprivate static func registerNewUDP( + on context: NetworkContext, + flags: UInt16 = 0 + ) -> ProtocolInstanceReference { + var udp = UDPInstance(context: context) + udp.flags = UDPProtocol.Instance.Flags(rawValue: flags) let registeredIndex = context.registerUDPInstance(udp) context.udpInstances[registeredIndex].udpInstanceIndex = registeredIndex context.udpInstances[registeredIndex].reference = ProtocolInstanceReference( @@ -121,6 +125,9 @@ public struct UDPProtocol: NetworkProtocol { var serviceClass = Parameters.ServiceClass.bestEffort var maximumDatagramSize: Int = 0 + var isIPv4: Bool { + flags.contains(.isIPv4) + } struct Flags: OptionSet { init(rawValue: Self.RawValue) { @@ -153,6 +160,13 @@ public struct UDPProtocol: NetworkProtocol { if self.maximumDatagramSize > UDPProtocol.headerLength { self.maximumDatagramSize -= UDPProtocol.headerLength } + let udpCsumOffload: UInt32 = path.hardwareChecksumFlags + if isIPv4 && ((udpCsumOffload & InterfaceChecksumFlags.csumUDP.rawValue) != 0) + || !isIPv4 && ((udpCsumOffload & InterfaceChecksumFlags.csumUDPIPV6.rawValue) != 0) + { + self.flags.insert(.fullChecksumOffload) + self.flags.remove(.partialChecksumOffload) + } } mutating func setup( @@ -202,6 +216,16 @@ public struct UDPProtocol: NetworkProtocol { if udpOptions.ignoreInboundChecksum { self.flags.insert(.ignoreInboundChecksum) } + if let transport = parameters.defaultStack.transport { + if transport.options == udpOptions, udpOptions.useQUICStats { + self.flags.insert(.upperTransportIsQUIC) + } else if let quicOptions = transport.options, + quicOptions.matches(identifier: QUICStreamProtocol.identifier) + || quicOptions.matches(identifier: QUICConnectionProtocol.identifier) + { + self.flags.insert(.upperTransportIsQUIC) + } + } } } @@ -213,7 +237,7 @@ public struct UDPProtocol: NetworkProtocol { let inbound = (inboundChecksum != nil) let existingChecksum: UInt16 = inboundChecksum ?? 0 var checksumValue: UInt16 = 0 - if self.flags.contains(.isIPv4) { + if isIPv4 { checksumValue = Checksum.ipv4PseudoHeader( source: inbound ? ipv4Remote : ipv4Local, dest: inbound ? ipv4Local : ipv4Remote, @@ -295,7 +319,7 @@ public struct UDPProtocol: NetworkProtocol { return .removeFrameAndContinue } - guard self.flags.contains(.isIPv4) || checksum != 0 else { + guard isIPv4 || checksum != 0 else { log.error("Received an IPv6 packet with zero checksum") frame.finalize(success: false) return .removeFrameAndContinue @@ -391,7 +415,7 @@ public struct UDPProtocol: NetworkProtocol { frame.serviceClass = self.serviceClass } - if !self.flags.contains(.isIPv4) || !self.flags.contains(.noChecksum) { + if !isIPv4 || !self.flags.contains(.noChecksum) { // Always insert pseudo header checksum let checksumValue = pseudoHeaderChecksum(inboundChecksum: nil, length: length) @@ -407,23 +431,41 @@ public struct UDPProtocol: NetworkProtocol { return .removeFrameAndContinue } - let finalizedChecksum = false if self.flags.contains(.fullChecksumOffload) { - // TODO: Checksum offload - } else if self.flags.contains(.partialChecksumOffload) { - // TODO: Checksum offload + let csumFlags: ChecksumFlags = + isIPv4 + ? [.udpv4, .zeroInvert] + : [.udpv6, .zeroInvert] + frame.checksumOffloadFlags |= csumFlags.rawValue } - if !finalizedChecksum { - do throws(ChecksumError) { - try frame.finalizeIPChecksum(checksumOffset: checksumOffset, zeroInvert: true) - } catch { - log.error("Failed to finalize UDP checksum") - frame.finalize(success: false) - return .removeFrameAndContinue + if !self.flags.contains(.fullChecksumOffload) { + var noChecksumOffload = !self.flags.contains(.partialChecksumOffload) + if !noChecksumOffload { + let csumStart = UInt16(isIPv4 ? IPProtocol.ipv4HeaderLength : IPProtocol.ipv6HeaderLength) + let csumWrite = csumStart + UInt16(checksumOffset) + let csumFlags: ChecksumFlags = [.partial, .zeroInvert] + if !frame.setInternetChecksum( + flags: csumFlags, + startOffset: csumStart, + checksumOffset: csumWrite + ) { + noChecksumOffload = true + } + } + + if noChecksumOffload { + do throws(ChecksumError) { + try frame.finalizeIPChecksum(checksumOffset: checksumOffset, zeroInvert: true) + } catch { + log.error("Failed to finalize UDP checksum") + frame.finalize(success: false) + return .removeFrameAndContinue + } } } } + transmitByteCount += length - UDPProtocol.headerLength return .continueIterating } @@ -434,6 +476,11 @@ public struct UDPProtocol: NetworkProtocol { #if !NETWORK_EMBEDDED var metadata: AbstractProtocolMetadata? { nil } #endif + + func updateDataTransferSnapshot(_ snapshot: inout DataTransferSnapshot) { + snapshot.receivedTransportByteCount = UInt64(receiveByteCount) + snapshot.sentTransportByteCount = UInt64(transmitByteCount) + } } public init() {} @@ -448,6 +495,10 @@ public struct UDPProtocol: NetworkProtocol { UDPInstance.registerNewUDP(on: context) } + public func newProtocolInstance(context: NetworkContext, flags: UInt16 = 0) -> ProtocolInstanceReference? { + UDPInstance.registerNewUDP(on: context, flags: flags) + } + static public let identifier = ProtocolIdentifier(name: "udp", level: .transport, mapping: .oneToOne) #if !NETWORK_PRIVATE @@ -456,8 +507,8 @@ public struct UDPProtocol: NetworkProtocol { static public func options() -> ProtocolOptions { UDPProtocol.definition.protocolOptions() } - static public func instance(context: NetworkContext) -> ProtocolInstanceReference { - UDPProtocol().newProtocolInstance(context: context)! + static public func instance(context: NetworkContext, flags: UInt16 = 0) -> ProtocolInstanceReference { + UDPProtocol().newProtocolInstance(context: context, flags: flags)! } } diff --git a/Tests/SwiftNetworkTests/SwiftNetworkUDPTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkUDPTests.swift index 51664ec..0d5f088 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkUDPTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkUDPTests.swift @@ -79,7 +79,8 @@ final class SwiftNetworkUDPTests: NetTestCase { outputPacket: [UInt8], inputPacket: [UInt8], secondaryInputPacket: [UInt8]? = nil, - expectBadInput: Bool = false + expectBadInput: Bool = false, + validateMetrics: Bool = false ) { let parameters = Parameters() @@ -169,6 +170,17 @@ final class SwiftNetworkUDPTests: NetTestCase { XCTAssertEqual(expectedInputData, readApplicationData, "Failed to read expected UDP input data") } + if validateMetrics { + let metrics = upperHarness.getMetrics(requestedNetworkMetric: .dataTransferSnapshot) + XCTAssertNotNil(metrics) + switch metrics { + case .dataTransferSnapshot(let snapshot): + XCTAssertTrue(snapshot.receivedTransportByteCount > 0) + XCTAssertTrue(snapshot.sentTransportByteCount > 0) + default: + XCTFail("Failed to get UDP harness metrics") + } + } upperHarness.stop() upperHarness.teardown() @@ -186,6 +198,16 @@ final class SwiftNetworkUDPTests: NetTestCase { ) } + func testUDPIPv4WithMetrics() { + internalTestUDP( + localEndpoint: Endpoint(address: IPv4Address(SwiftNetworkUDPTests.localIPv4Address)!, port: 1234), + remoteEndpoint: Endpoint(address: IPv4Address(SwiftNetworkUDPTests.remoteIPv4Address)!, port: 2345), + outputPacket: SwiftNetworkUDPTests.outputIPv4Packet, + inputPacket: SwiftNetworkUDPTests.inputIPv4Packet, + validateMetrics: true + ) + } + func testUDPIPv6() { internalTestUDP( localEndpoint: Endpoint(address: IPv6Address(SwiftNetworkUDPTests.localIPv6Address)!, port: 1234), @@ -195,6 +217,112 @@ final class SwiftNetworkUDPTests: NetTestCase { ) } + func internalTestUDPChecksumFlags( + localEndpoint: Endpoint, + remoteEndpoint: Endpoint, + instanceFlags: UInt16, + validateOutbound: @escaping (DatagramLowerHarness) -> Void + ) { + let parameters = Parameters() + let expectation = XCTestExpectation() + let context = parameters.context + context.async { + defer { expectation.fulfill() } + let path = PathProperties(parameters: parameters) + + let reference = UDPProtocol.instance(context: context, flags: instanceFlags) + let udpOptions = UDPProtocol.options() + udpOptions.noMetadata = true + udpOptions.setLogID(prefix: "C", parent: "1", protocolLogIDNumber: 1) + udpOptions.setProtocolInstance(reference) + parameters.defaultStack.transport = .udp(udpOptions) + + let udpLinkage = OutboundDatagramLinkage(reference: reference) + guard + let upperHarness = DatagramUpperHarness( + identifier: "Client", + local: localEndpoint, + remote: remoteEndpoint, + parameters: parameters, + path: path, + context: context, + lowerProtocol: udpLinkage + ) + else { + XCTFail("Failed to attach UDP to upper harness") + return + } + + let lowerHarness = DatagramLowerHarness(identifier: "Client", context: context) + do { + try reference.attachLowerDatagramProtocol( + lowerHarness.reference, + remote: remoteEndpoint, + local: localEndpoint, + parameters: parameters, + path: path + ) + } catch { + XCTFail("Failed to attach UDP to lower harness") + return + } + + upperHarness.start { connected in + XCTAssertTrue(connected, "UDP failed to become connected") + } + + var message = SwiftNetworkUDPTests.outputMessage + XCTAssertTrue(message.withUTF8 { upperHarness.write($0.map { $0 }) }, "Failed to write") + + validateOutbound(lowerHarness) + + upperHarness.stop() + upperHarness.teardown() + } + wait(for: [expectation], timeout: 10.0) + } + + func testUDPIPv4FullChecksumOffload() { + internalTestUDPChecksumFlags( + localEndpoint: Endpoint(address: IPv4Address(SwiftNetworkUDPTests.localIPv4Address)!, port: 1234), + remoteEndpoint: Endpoint(address: IPv4Address(SwiftNetworkUDPTests.remoteIPv4Address)!, port: 2345), + instanceFlags: UDPProtocol.Instance.Flags.fullChecksumOffload.rawValue + ) { lowerHarness in + let flags = lowerHarness.pendingOutboundPackets.peekFirstFrame { $0.checksumOffloadFlags } + // udpv4 = 0x10, zeroInvert = 0x02 → 0x12 + XCTAssertEqual(flags, 0x10 | 0x02, "Expected fullChecksumOffload flags for IPv4 UDP") + } + } + + func testUDPIPv6FullChecksumOffload() { + internalTestUDPChecksumFlags( + localEndpoint: Endpoint(address: IPv6Address(SwiftNetworkUDPTests.localIPv6Address)!, port: 1234), + remoteEndpoint: Endpoint(address: IPv6Address(SwiftNetworkUDPTests.remoteIPv6Address)!, port: 2345), + instanceFlags: UDPProtocol.Instance.Flags.fullChecksumOffload.rawValue + ) { lowerHarness in + let flags = lowerHarness.pendingOutboundPackets.peekFirstFrame { $0.checksumOffloadFlags } + // udpv6 = 0x40, zeroInvert = 0x02 → 0x42 + XCTAssertEqual(flags, 0x40 | 0x02, "Expected fullChecksumOffload flags for IPv6 UDP") + } + } + + func testUDPIPv4NoChecksum() { + internalTestUDPChecksumFlags( + localEndpoint: Endpoint(address: IPv4Address(SwiftNetworkUDPTests.localIPv4Address)!, port: 1234), + remoteEndpoint: Endpoint(address: IPv4Address(SwiftNetworkUDPTests.remoteIPv4Address)!, port: 2345), + instanceFlags: UDPProtocol.Instance.Flags.noChecksum.rawValue + ) { lowerHarness in + guard let packet = lowerHarness.extractLastOutboundPacket() else { + XCTFail("No outbound packet") + return + } + // Everything should be zero here + XCTAssertTrue(packet.count >= 8, "Packet too short") + XCTAssertEqual(packet[6], 0x00, "Checksum high byte should be zero") + XCTAssertEqual(packet[7], 0x00, "Checksum low byte should be zero") + } + } + func testBadChecksumUDPIPv4() { internalTestUDP( localEndpoint: Endpoint(address: IPv4Address(SwiftNetworkUDPTests.localIPv4Address)!, port: 1234), From 1c526ad9a0685a38b4c216a8c7e25d331f3957aa Mon Sep 17 00:00:00 2001 From: agnosticdev Date: Thu, 2 Jul 2026 20:19:37 -0700 Subject: [PATCH 2/5] agnosticdev/UpdateUDP: Added fullChecksumOffload to protocol options --- .../SwiftNetwork/Protocols/UDPProtocol.swift | 27 ++++++++++++------- .../SwiftNetworkUDPTests.swift | 14 ++++++---- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/Sources/SwiftNetwork/Protocols/UDPProtocol.swift b/Sources/SwiftNetwork/Protocols/UDPProtocol.swift index b3af06a..ae14553 100644 --- a/Sources/SwiftNetwork/Protocols/UDPProtocol.swift +++ b/Sources/SwiftNetwork/Protocols/UDPProtocol.swift @@ -48,6 +48,7 @@ public struct UDPProtocol: NetworkProtocol { static public let noMetadata = UDPOptions(rawValue: 1 << 1) static public let ignoreInboundChecksum = UDPOptions(rawValue: 1 << 2) static public let useQUICStats = UDPOptions(rawValue: 1 << 3) + static public let fullChecksumOffload = UDPOptions(rawValue: 1 << 4) #if NETWORK_PRIVATE var privateStorage = UDPProtocolOptionsPrivateStorage() @@ -99,10 +100,8 @@ public struct UDPProtocol: NetworkProtocol { // Only called by newProtocolInstance() fileprivate static func registerNewUDP( on context: NetworkContext, - flags: UInt16 = 0 ) -> ProtocolInstanceReference { - var udp = UDPInstance(context: context) - udp.flags = UDPProtocol.Instance.Flags(rawValue: flags) + let udp = UDPInstance(context: context) let registeredIndex = context.registerUDPInstance(udp) context.udpInstances[registeredIndex].udpInstanceIndex = registeredIndex context.udpInstances[registeredIndex].reference = ProtocolInstanceReference( @@ -216,6 +215,9 @@ public struct UDPProtocol: NetworkProtocol { if udpOptions.ignoreInboundChecksum { self.flags.insert(.ignoreInboundChecksum) } + if udpOptions.fullChecksumOffload { + self.flags.insert(.fullChecksumOffload) + } if let transport = parameters.defaultStack.transport { if transport.options == udpOptions, udpOptions.useQUICStats { self.flags.insert(.upperTransportIsQUIC) @@ -495,10 +497,6 @@ public struct UDPProtocol: NetworkProtocol { UDPInstance.registerNewUDP(on: context) } - public func newProtocolInstance(context: NetworkContext, flags: UInt16 = 0) -> ProtocolInstanceReference? { - UDPInstance.registerNewUDP(on: context, flags: flags) - } - static public let identifier = ProtocolIdentifier(name: "udp", level: .transport, mapping: .oneToOne) #if !NETWORK_PRIVATE @@ -507,8 +505,8 @@ public struct UDPProtocol: NetworkProtocol { static public func options() -> ProtocolOptions { UDPProtocol.definition.protocolOptions() } - static public func instance(context: NetworkContext, flags: UInt16 = 0) -> ProtocolInstanceReference { - UDPProtocol().newProtocolInstance(context: context, flags: flags)! + static public func instance(context: NetworkContext) -> ProtocolInstanceReference { + UDPProtocol().newProtocolInstance(context: context)! } } @@ -557,4 +555,15 @@ extension ProtocolOptions { } } } + + public var fullChecksumOffload: Bool { + get { perProtocolOptions!.contains(.fullChecksumOffload) } + set { + if newValue { + perProtocolOptions!.insert(.fullChecksumOffload) + } else { + perProtocolOptions!.remove(.fullChecksumOffload) + } + } + } } diff --git a/Tests/SwiftNetworkTests/SwiftNetworkUDPTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkUDPTests.swift index 0d5f088..fecbdbf 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkUDPTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkUDPTests.swift @@ -220,7 +220,8 @@ final class SwiftNetworkUDPTests: NetTestCase { func internalTestUDPChecksumFlags( localEndpoint: Endpoint, remoteEndpoint: Endpoint, - instanceFlags: UInt16, + fullChecksumOffload: Bool, + preferNoChecksum: Bool = false, validateOutbound: @escaping (DatagramLowerHarness) -> Void ) { let parameters = Parameters() @@ -230,8 +231,10 @@ final class SwiftNetworkUDPTests: NetTestCase { defer { expectation.fulfill() } let path = PathProperties(parameters: parameters) - let reference = UDPProtocol.instance(context: context, flags: instanceFlags) + let reference = UDPProtocol.instance(context: context) let udpOptions = UDPProtocol.options() + udpOptions.fullChecksumOffload = fullChecksumOffload + udpOptions.preferNoChecksum = preferNoChecksum udpOptions.noMetadata = true udpOptions.setLogID(prefix: "C", parent: "1", protocolLogIDNumber: 1) udpOptions.setProtocolInstance(reference) @@ -286,7 +289,7 @@ final class SwiftNetworkUDPTests: NetTestCase { internalTestUDPChecksumFlags( localEndpoint: Endpoint(address: IPv4Address(SwiftNetworkUDPTests.localIPv4Address)!, port: 1234), remoteEndpoint: Endpoint(address: IPv4Address(SwiftNetworkUDPTests.remoteIPv4Address)!, port: 2345), - instanceFlags: UDPProtocol.Instance.Flags.fullChecksumOffload.rawValue + fullChecksumOffload: true ) { lowerHarness in let flags = lowerHarness.pendingOutboundPackets.peekFirstFrame { $0.checksumOffloadFlags } // udpv4 = 0x10, zeroInvert = 0x02 → 0x12 @@ -298,7 +301,7 @@ final class SwiftNetworkUDPTests: NetTestCase { internalTestUDPChecksumFlags( localEndpoint: Endpoint(address: IPv6Address(SwiftNetworkUDPTests.localIPv6Address)!, port: 1234), remoteEndpoint: Endpoint(address: IPv6Address(SwiftNetworkUDPTests.remoteIPv6Address)!, port: 2345), - instanceFlags: UDPProtocol.Instance.Flags.fullChecksumOffload.rawValue + fullChecksumOffload: true ) { lowerHarness in let flags = lowerHarness.pendingOutboundPackets.peekFirstFrame { $0.checksumOffloadFlags } // udpv6 = 0x40, zeroInvert = 0x02 → 0x42 @@ -310,7 +313,8 @@ final class SwiftNetworkUDPTests: NetTestCase { internalTestUDPChecksumFlags( localEndpoint: Endpoint(address: IPv4Address(SwiftNetworkUDPTests.localIPv4Address)!, port: 1234), remoteEndpoint: Endpoint(address: IPv4Address(SwiftNetworkUDPTests.remoteIPv4Address)!, port: 2345), - instanceFlags: UDPProtocol.Instance.Flags.noChecksum.rawValue + fullChecksumOffload: false, + preferNoChecksum: true ) { lowerHarness in guard let packet = lowerHarness.extractLastOutboundPacket() else { XCTFail("No outbound packet") From 2f4aa406b83ae7933fcc8e27a33ec2b121e92e51 Mon Sep 17 00:00:00 2001 From: agnosticdev Date: Thu, 2 Jul 2026 20:36:31 -0700 Subject: [PATCH 3/5] agnosticdev/UpdateUDP: Added testable import --- .../SwiftNetworkMultiplexingTests.swift | 12 ++++++++---- Tests/SwiftNetworkTests/SwiftNetworkUDPTests.swift | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Tests/SwiftNetworkTests/SwiftNetworkMultiplexingTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkMultiplexingTests.swift index 5515a16..7a215a0 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkMultiplexingTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkMultiplexingTests.swift @@ -25,6 +25,10 @@ import XCTest @available(Network 0.1.0, *) final class SwiftNetworkMultiplexingTests: NetTestCase { + // 10.0.0.20 + static let localIPv4Address: [UInt8] = [0x0a, 0x00, 0x00, 0x14] + // 10.0.0.117 + static let remoteIPv4Address: [UInt8] = [0x0a, 0x00, 0x00, 0x75] static let outputMessage: [UInt8] = [0x0a, 0x0b, 0x0c, 0x0d] static let inputMessage: [UInt8] = [0x0d, 0x0c, 0x0b, 0x0a, 0x01] @@ -33,8 +37,8 @@ final class SwiftNetworkMultiplexingTests: NetTestCase { let context = parameters.context let path = PathProperties(parameters: parameters) - let localEndpoint = Endpoint(address: IPv4Address(SwiftNetworkUDPTests.localIPv4Address)!, port: 1234) - let remoteEndpoint = Endpoint(address: IPv4Address(SwiftNetworkUDPTests.localIPv4Address)!, port: 2345) + let localEndpoint = Endpoint(address: IPv4Address(SwiftNetworkMultiplexingTests.localIPv4Address)!, port: 1234) + let remoteEndpoint = Endpoint(address: IPv4Address(SwiftNetworkMultiplexingTests.localIPv4Address)!, port: 2345) var instance: TestMultiplexingProtocol? = nil var upperHarness1: DatagramUpperHarness? @@ -217,8 +221,8 @@ final class SwiftNetworkMultiplexingTests: NetTestCase { let context = parameters.context let path = PathProperties(parameters: parameters) - let localEndpoint = Endpoint(address: IPv4Address(SwiftNetworkUDPTests.localIPv4Address)!, port: 1234) - let remoteEndpoint = Endpoint(address: IPv4Address(SwiftNetworkUDPTests.localIPv4Address)!, port: 2345) + let localEndpoint = Endpoint(address: IPv4Address(SwiftNetworkMultiplexingTests.localIPv4Address)!, port: 1234) + let remoteEndpoint = Endpoint(address: IPv4Address(SwiftNetworkMultiplexingTests.localIPv4Address)!, port: 2345) // Use a high number of streams to ensure that we don't have poor scaling let upperHarnessCount = 1000 diff --git a/Tests/SwiftNetworkTests/SwiftNetworkUDPTests.swift b/Tests/SwiftNetworkTests/SwiftNetworkUDPTests.swift index fecbdbf..2353e2e 100644 --- a/Tests/SwiftNetworkTests/SwiftNetworkUDPTests.swift +++ b/Tests/SwiftNetworkTests/SwiftNetworkUDPTests.swift @@ -19,7 +19,7 @@ import XCTest #if canImport(SwiftNetwork) @_spi(Essentials) @_spi(ProtocolProvider) @testable import SwiftNetwork #elseif canImport(Network) -@_spi(Essentials) @_spi(ProtocolProvider) import Network +@_spi(Essentials) @_spi(ProtocolProvider) @testable import Network #endif @available(Network 0.1.0, *) From 6946f2fb5213f6ae8cf86e8553810b6b0be4372b Mon Sep 17 00:00:00 2001 From: agnosticdev Date: Mon, 6 Jul 2026 13:09:46 -0700 Subject: [PATCH 4/5] Review feedback --- Sources/SwiftNetwork/Protocols/Checksum.swift | 12 ++++++------ Sources/SwiftNetwork/Protocols/UDPProtocol.swift | 12 +++++++----- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Sources/SwiftNetwork/Protocols/Checksum.swift b/Sources/SwiftNetwork/Protocols/Checksum.swift index 85cad4a..4c8329c 100644 --- a/Sources/SwiftNetwork/Protocols/Checksum.swift +++ b/Sources/SwiftNetwork/Protocols/Checksum.swift @@ -62,16 +62,16 @@ struct ChecksumFlags: OptionSet { static let partial = ChecksumFlags(rawValue: 0x01) static let zeroInvert = ChecksumFlags(rawValue: 0x02) static let ip = ChecksumFlags(rawValue: 0x04) - static let tcpv4 = ChecksumFlags(rawValue: 0x08) - static let udpv4 = ChecksumFlags(rawValue: 0x10) - static let tcpv6 = ChecksumFlags(rawValue: 0x20) - static let udpv6 = ChecksumFlags(rawValue: 0x40) + static let tcpIPv4 = ChecksumFlags(rawValue: 0x08) + static let udpIPv4 = ChecksumFlags(rawValue: 0x10) + static let tcpIPv6 = ChecksumFlags(rawValue: 0x20) + static let udpIPv6 = ChecksumFlags(rawValue: 0x40) } struct InterfaceChecksumFlags: OptionSet { let rawValue: UInt32 - static let csumUDP = InterfaceChecksumFlags(rawValue: 0x0000_0004) - static let csumUDPIPV6 = InterfaceChecksumFlags(rawValue: 0x0000_0040) + static let csumUDPIPv4 = InterfaceChecksumFlags(rawValue: 0x0000_0004) + static let csumUDPIPv6 = InterfaceChecksumFlags(rawValue: 0x0000_0040) } @available(Network 0.1.0, *) diff --git a/Sources/SwiftNetwork/Protocols/UDPProtocol.swift b/Sources/SwiftNetwork/Protocols/UDPProtocol.swift index ae14553..e67d7c2 100644 --- a/Sources/SwiftNetwork/Protocols/UDPProtocol.swift +++ b/Sources/SwiftNetwork/Protocols/UDPProtocol.swift @@ -159,9 +159,9 @@ public struct UDPProtocol: NetworkProtocol { if self.maximumDatagramSize > UDPProtocol.headerLength { self.maximumDatagramSize -= UDPProtocol.headerLength } - let udpCsumOffload: UInt32 = path.hardwareChecksumFlags - if isIPv4 && ((udpCsumOffload & InterfaceChecksumFlags.csumUDP.rawValue) != 0) - || !isIPv4 && ((udpCsumOffload & InterfaceChecksumFlags.csumUDPIPV6.rawValue) != 0) + let udpChecksumOffload: UInt32 = path.hardwareChecksumFlags + if isIPv4 && ((udpChecksumOffload & InterfaceChecksumFlags.csumUDPIPv4.rawValue) != 0) + || !isIPv4 && ((udpChecksumOffload & InterfaceChecksumFlags.csumUDPIPv6.rawValue) != 0) { self.flags.insert(.fullChecksumOffload) self.flags.remove(.partialChecksumOffload) @@ -218,6 +218,7 @@ public struct UDPProtocol: NetworkProtocol { if udpOptions.fullChecksumOffload { self.flags.insert(.fullChecksumOffload) } + #if !NETWORK_EMBEDDED if let transport = parameters.defaultStack.transport { if transport.options == udpOptions, udpOptions.useQUICStats { self.flags.insert(.upperTransportIsQUIC) @@ -228,6 +229,7 @@ public struct UDPProtocol: NetworkProtocol { self.flags.insert(.upperTransportIsQUIC) } } + #endif } } @@ -436,8 +438,8 @@ public struct UDPProtocol: NetworkProtocol { if self.flags.contains(.fullChecksumOffload) { let csumFlags: ChecksumFlags = isIPv4 - ? [.udpv4, .zeroInvert] - : [.udpv6, .zeroInvert] + ? [.udpIPv4, .zeroInvert] + : [.udpIPv6, .zeroInvert] frame.checksumOffloadFlags |= csumFlags.rawValue } From 93ccf9ee00be14a04e2f2c2fe996021097e442ec Mon Sep 17 00:00:00 2001 From: agnosticdev Date: Mon, 6 Jul 2026 13:30:33 -0700 Subject: [PATCH 5/5] Review feedback --- Sources/SwiftNetwork/Protocols/Checksum.swift | 4 ++-- Sources/SwiftNetwork/Protocols/UDPProtocol.swift | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Sources/SwiftNetwork/Protocols/Checksum.swift b/Sources/SwiftNetwork/Protocols/Checksum.swift index 4c8329c..4e6c67f 100644 --- a/Sources/SwiftNetwork/Protocols/Checksum.swift +++ b/Sources/SwiftNetwork/Protocols/Checksum.swift @@ -70,8 +70,8 @@ struct ChecksumFlags: OptionSet { struct InterfaceChecksumFlags: OptionSet { let rawValue: UInt32 - static let csumUDPIPv4 = InterfaceChecksumFlags(rawValue: 0x0000_0004) - static let csumUDPIPv6 = InterfaceChecksumFlags(rawValue: 0x0000_0040) + static let udpIPv4 = InterfaceChecksumFlags(rawValue: 0x0000_0004) + static let udpIPv6 = InterfaceChecksumFlags(rawValue: 0x0000_0040) } @available(Network 0.1.0, *) diff --git a/Sources/SwiftNetwork/Protocols/UDPProtocol.swift b/Sources/SwiftNetwork/Protocols/UDPProtocol.swift index e67d7c2..7e8d7ab 100644 --- a/Sources/SwiftNetwork/Protocols/UDPProtocol.swift +++ b/Sources/SwiftNetwork/Protocols/UDPProtocol.swift @@ -160,8 +160,8 @@ public struct UDPProtocol: NetworkProtocol { self.maximumDatagramSize -= UDPProtocol.headerLength } let udpChecksumOffload: UInt32 = path.hardwareChecksumFlags - if isIPv4 && ((udpChecksumOffload & InterfaceChecksumFlags.csumUDPIPv4.rawValue) != 0) - || !isIPv4 && ((udpChecksumOffload & InterfaceChecksumFlags.csumUDPIPv6.rawValue) != 0) + if isIPv4 && ((udpChecksumOffload & InterfaceChecksumFlags.udpIPv4.rawValue) != 0) + || !isIPv4 && ((udpChecksumOffload & InterfaceChecksumFlags.udpIPv6.rawValue) != 0) { self.flags.insert(.fullChecksumOffload) self.flags.remove(.partialChecksumOffload) @@ -444,8 +444,8 @@ public struct UDPProtocol: NetworkProtocol { } if !self.flags.contains(.fullChecksumOffload) { - var noChecksumOffload = !self.flags.contains(.partialChecksumOffload) - if !noChecksumOffload { + var checksumOffloadDisabled = !self.flags.contains(.partialChecksumOffload) + if !checksumOffloadDisabled { let csumStart = UInt16(isIPv4 ? IPProtocol.ipv4HeaderLength : IPProtocol.ipv6HeaderLength) let csumWrite = csumStart + UInt16(checksumOffset) let csumFlags: ChecksumFlags = [.partial, .zeroInvert] @@ -454,11 +454,11 @@ public struct UDPProtocol: NetworkProtocol { startOffset: csumStart, checksumOffset: csumWrite ) { - noChecksumOffload = true + checksumOffloadDisabled = true } } - if noChecksumOffload { + if checksumOffloadDisabled { do throws(ChecksumError) { try frame.finalizeIPChecksum(checksumOffset: checksumOffset, zeroInvert: true) } catch {