From 2a2f213fde24ac9ae1debc2c1c5beb30e8736bb0 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Mon, 29 Jul 2024 21:33:40 -0400 Subject: [PATCH] network/protocols: Set and check L3/L4_CHECKSUM_VALID flags. iperf3 TCP on loopback, 1 core (in VMware) goes from ~7.2 Gbits/sec to ~9.4 Gbits/sec. Change-Id: I0c93254fab9ee1b5040ef5f71000982bac1a5d15 Reviewed-on: https://review.haiku-os.org/c/haiku/+/7917 Haiku-Format: Haiku-format Bot Reviewed-by: waddlesplash --- src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp | 8 +++++--- src/add-ons/kernel/network/protocols/tcp/tcp.cpp | 8 +++++--- src/add-ons/kernel/network/protocols/udp/udp.cpp | 3 ++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp b/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp index 6b60886b29..94e54f6c06 100644 --- a/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp +++ b/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp @@ -1559,6 +1559,7 @@ ipv4_send_routed_data(net_protocol* _protocol, struct net_route* route, if (checksumNeeded) { *IPChecksumField(buffer) = gBufferModule->checksum(buffer, 0, sizeof(ipv4_header), true); + buffer->buffer_flags |= NET_BUFFER_L3_CHECKSUM_VALID; } if ((buffer->msg_flags & MSG_MCAST) != 0 @@ -1741,9 +1742,10 @@ ipv4_receive_data(net_buffer* buffer) || headerLength < sizeof(ipv4_header)) return B_BAD_DATA; - // TODO: would be nice to have a direct checksum function somewhere - if (gBufferModule->checksum(buffer, 0, headerLength, true) != 0) - return B_BAD_DATA; + if ((buffer->buffer_flags & NET_BUFFER_L3_CHECKSUM_VALID) == 0) { + if (gBufferModule->checksum(buffer, 0, headerLength, true) != 0) + return B_BAD_DATA; + } // lower layers notion of broadcast or multicast have no relevance to us // other than deciding whether to send an ICMP error diff --git a/src/add-ons/kernel/network/protocols/tcp/tcp.cpp b/src/add-ons/kernel/network/protocols/tcp/tcp.cpp index fd5dc38886..aa9604ca0f 100644 --- a/src/add-ons/kernel/network/protocols/tcp/tcp.cpp +++ b/src/add-ons/kernel/network/protocols/tcp/tcp.cpp @@ -435,6 +435,7 @@ add_tcp_header(net_address_module_info* addressModule, *TCPChecksumField(buffer) = Checksum::PseudoHeader(addressModule, gBufferModule, buffer, IPPROTO_TCP); + buffer->buffer_flags |= NET_BUFFER_L4_CHECKSUM_VALID; return B_OK; } @@ -698,9 +699,10 @@ tcp_receive_data(net_buffer* buffer) if (headerLength < sizeof(tcp_header)) return B_BAD_DATA; - if (Checksum::PseudoHeader(addressModule, gBufferModule, buffer, - IPPROTO_TCP) != 0) - return B_BAD_DATA; + if ((buffer->buffer_flags & NET_BUFFER_L4_CHECKSUM_VALID) == 0) { + if (Checksum::PseudoHeader(addressModule, gBufferModule, buffer, IPPROTO_TCP) != 0) + return B_BAD_DATA; + } addressModule->set_port(buffer->source, header.source_port); addressModule->set_port(buffer->destination, header.destination_port); diff --git a/src/add-ons/kernel/network/protocols/udp/udp.cpp b/src/add-ons/kernel/network/protocols/udp/udp.cpp index 53e64929e5..7ada42419b 100644 --- a/src/add-ons/kernel/network/protocols/udp/udp.cpp +++ b/src/add-ons/kernel/network/protocols/udp/udp.cpp @@ -828,7 +828,7 @@ UdpEndpointManager::Deframe(net_buffer* buffer) if (buffer->size > udpLength) gBufferModule->trim(buffer, udpLength); - if (header.udp_checksum != 0) { + if (header.udp_checksum != 0 && (buffer->buffer_flags & NET_BUFFER_L4_CHECKSUM_VALID) == 0) { // check UDP-checksum (simulating a so-called "pseudo-header"): uint16 sum = Checksum::PseudoHeader(addressModule, gBufferModule, buffer, IPPROTO_UDP); @@ -1042,6 +1042,7 @@ UdpEndpoint::SendRoutedData(net_buffer *buffer, net_route *route) calculatedChecksum = 0xffff; *UDPChecksumField(buffer) = calculatedChecksum; + buffer->buffer_flags |= NET_BUFFER_L4_CHECKSUM_VALID; return next->module->send_routed_data(next, route, buffer); }