From 72798519cb81e36651831da38e2d07d3920c42d3 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 4 Aug 2019 21:07:50 +0200 Subject: [PATCH] IPv4: Use KBuffer instead of ByteBuffer for socket receive queues This drastically reduces the pressure on the kernel heap when receiving data from IPv4 sockets. --- Kernel/Net/IPv4Socket.cpp | 8 ++++---- Kernel/Net/IPv4Socket.h | 7 ++++--- Kernel/Net/NetworkTask.cpp | 8 ++++---- Kernel/Net/TCPSocket.cpp | 5 ++--- Kernel/Net/TCPSocket.h | 2 +- Kernel/Net/UDPSocket.cpp | 5 ++--- Kernel/Net/UDPSocket.h | 2 +- 7 files changed, 18 insertions(+), 19 deletions(-) diff --git a/Kernel/Net/IPv4Socket.cpp b/Kernel/Net/IPv4Socket.cpp index 40e92f88a5c..2b0b90cc39c 100644 --- a/Kernel/Net/IPv4Socket.cpp +++ b/Kernel/Net/IPv4Socket.cpp @@ -228,7 +228,7 @@ ssize_t IPv4Socket::recvfrom(FileDescription& description, void* buffer, size_t #endif } ASSERT(!packet.data.is_null()); - auto& ipv4_packet = *(const IPv4Packet*)(packet.data.pointer()); + auto& ipv4_packet = *(const IPv4Packet*)(packet.data->data()); if (addr) { dbgprintf("Incoming packet is from: %s:%u\n", packet.peer_address.to_string().characters(), packet.peer_port); @@ -246,13 +246,13 @@ ssize_t IPv4Socket::recvfrom(FileDescription& description, void* buffer, size_t return ipv4_packet.payload_size(); } - return protocol_receive(packet.data, buffer, buffer_length, flags); + return protocol_receive(*packet.data, buffer, buffer_length, flags); } -void IPv4Socket::did_receive(const IPv4Address& source_address, u16 source_port, ByteBuffer&& packet) +void IPv4Socket::did_receive(const IPv4Address& source_address, u16 source_port, NonnullRefPtr&& packet) { LOCKER(lock()); - auto packet_size = packet.size(); + auto packet_size = packet->size(); m_receive_queue.append({ source_address, source_port, move(packet) }); m_can_read = true; m_bytes_received += packet_size; diff --git a/Kernel/Net/IPv4Socket.h b/Kernel/Net/IPv4Socket.h index afb73b56c7f..3577cbe7b96 100644 --- a/Kernel/Net/IPv4Socket.h +++ b/Kernel/Net/IPv4Socket.h @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -33,7 +34,7 @@ public: virtual ssize_t sendto(FileDescription&, const void*, size_t, int, const sockaddr*, socklen_t) override; virtual ssize_t recvfrom(FileDescription&, void*, size_t, int flags, sockaddr*, socklen_t*) override; - void did_receive(const IPv4Address& peer_address, u16 peer_port, ByteBuffer&&); + void did_receive(const IPv4Address& peer_address, u16 peer_port, NonnullRefPtr&&); const IPv4Address& local_address() const; u16 local_port() const { return m_local_port; } @@ -50,7 +51,7 @@ protected: int allocate_local_port_if_needed(); virtual KResult protocol_bind() { return KSuccess; } - virtual int protocol_receive(const ByteBuffer&, void*, size_t, int) { return -ENOTIMPL; } + virtual int protocol_receive(const KBuffer&, void*, size_t, int) { return -ENOTIMPL; } virtual int protocol_send(const void*, int) { return -ENOTIMPL; } virtual KResult protocol_connect(FileDescription&, ShouldBlock) { return KSuccess; } virtual int protocol_allocate_local_port() { return 0; } @@ -65,7 +66,7 @@ private: struct ReceivedPacket { IPv4Address peer_address; u16 peer_port; - ByteBuffer data; + RefPtr data; }; SinglyLinkedList m_receive_queue; diff --git a/Kernel/Net/NetworkTask.cpp b/Kernel/Net/NetworkTask.cpp index 9f01fec0b74..cb23144a447 100644 --- a/Kernel/Net/NetworkTask.cpp +++ b/Kernel/Net/NetworkTask.cpp @@ -203,7 +203,7 @@ void handle_icmp(const EthernetFrameHeader& eth, int frame_size) LOCKER(socket->lock()); if (socket->protocol() != (unsigned)IPv4Protocol::ICMP) continue; - socket->did_receive(ipv4_packet.source(), 0, ByteBuffer::copy(&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size())); + socket->did_receive(ipv4_packet.source(), 0, KBuffer::copy(&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size())); } } @@ -260,7 +260,7 @@ void handle_udp(const EthernetFrameHeader& eth, int frame_size) ASSERT(socket->type() == SOCK_DGRAM); ASSERT(socket->local_port() == udp_packet.destination_port()); - socket->did_receive(ipv4_packet.source(), udp_packet.source_port(), ByteBuffer::copy(&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size())); + socket->did_receive(ipv4_packet.source(), udp_packet.source_port(), KBuffer::copy(&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size())); } void handle_tcp(const EthernetFrameHeader& eth, int frame_size) @@ -319,7 +319,7 @@ void handle_tcp(const EthernetFrameHeader& eth, int frame_size) kprintf("handle_tcp: Got FIN, payload_size=%u\n", payload_size); if (payload_size != 0) - socket->did_receive(ipv4_packet.source(), tcp_packet.source_port(), ByteBuffer::copy(&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size())); + socket->did_receive(ipv4_packet.source(), tcp_packet.source_port(), KBuffer::copy(&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size())); socket->set_ack_number(tcp_packet.sequence_number() + payload_size + 1); socket->send_tcp_packet(TCPFlags::FIN | TCPFlags::ACK); @@ -340,5 +340,5 @@ void handle_tcp(const EthernetFrameHeader& eth, int frame_size) socket->send_tcp_packet(TCPFlags::ACK); if (payload_size != 0) - socket->did_receive(ipv4_packet.source(), tcp_packet.source_port(), ByteBuffer::copy(&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size())); + socket->did_receive(ipv4_packet.source(), tcp_packet.source_port(), KBuffer::copy(&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size())); } diff --git a/Kernel/Net/TCPSocket.cpp b/Kernel/Net/TCPSocket.cpp index fe272ade9cb..42528a85ba1 100644 --- a/Kernel/Net/TCPSocket.cpp +++ b/Kernel/Net/TCPSocket.cpp @@ -46,11 +46,10 @@ NonnullRefPtr TCPSocket::create(int protocol) return adopt(*new TCPSocket(protocol)); } -int TCPSocket::protocol_receive(const ByteBuffer& packet_buffer, void* buffer, size_t buffer_size, int flags) +int TCPSocket::protocol_receive(const KBuffer& packet_buffer, void* buffer, size_t buffer_size, int flags) { (void)flags; - ASSERT(!packet_buffer.is_null()); - auto& ipv4_packet = *(const IPv4Packet*)(packet_buffer.pointer()); + auto& ipv4_packet = *(const IPv4Packet*)(packet_buffer.data()); auto& tcp_packet = *static_cast(ipv4_packet.payload()); size_t payload_size = packet_buffer.size() - sizeof(IPv4Packet) - tcp_packet.header_size(); #ifdef TCP_SOCKET_DEBUG diff --git a/Kernel/Net/TCPSocket.h b/Kernel/Net/TCPSocket.h index 8161eca2345..4a5775bbc6c 100644 --- a/Kernel/Net/TCPSocket.h +++ b/Kernel/Net/TCPSocket.h @@ -33,7 +33,7 @@ private: static NetworkOrdered compute_tcp_checksum(const IPv4Address& source, const IPv4Address& destination, const TCPPacket&, u16 payload_size); - virtual int protocol_receive(const ByteBuffer&, void* buffer, size_t buffer_size, int flags) override; + virtual int protocol_receive(const KBuffer&, void* buffer, size_t buffer_size, int flags) override; virtual int protocol_send(const void*, int) override; virtual KResult protocol_connect(FileDescription&, ShouldBlock) override; virtual int protocol_allocate_local_port() override; diff --git a/Kernel/Net/UDPSocket.cpp b/Kernel/Net/UDPSocket.cpp index 9658346642e..2349837ba49 100644 --- a/Kernel/Net/UDPSocket.cpp +++ b/Kernel/Net/UDPSocket.cpp @@ -43,11 +43,10 @@ NonnullRefPtr UDPSocket::create(int protocol) return adopt(*new UDPSocket(protocol)); } -int UDPSocket::protocol_receive(const ByteBuffer& packet_buffer, void* buffer, size_t buffer_size, int flags) +int UDPSocket::protocol_receive(const KBuffer& packet_buffer, void* buffer, size_t buffer_size, int flags) { (void)flags; - ASSERT(!packet_buffer.is_null()); - auto& ipv4_packet = *(const IPv4Packet*)(packet_buffer.pointer()); + auto& ipv4_packet = *(const IPv4Packet*)(packet_buffer.data()); auto& udp_packet = *static_cast(ipv4_packet.payload()); ASSERT(udp_packet.length() >= sizeof(UDPPacket)); // FIXME: This should be rejected earlier. ASSERT(buffer_size >= (udp_packet.length() - sizeof(UDPPacket))); diff --git a/Kernel/Net/UDPSocket.h b/Kernel/Net/UDPSocket.h index 2f60b0452db..aa304f2b5b0 100644 --- a/Kernel/Net/UDPSocket.h +++ b/Kernel/Net/UDPSocket.h @@ -16,7 +16,7 @@ private: virtual const char* class_name() const override { return "UDPSocket"; } static Lockable>& sockets_by_port(); - virtual int protocol_receive(const ByteBuffer&, void* buffer, size_t buffer_size, int flags) override; + virtual int protocol_receive(const KBuffer&, void* buffer, size_t buffer_size, int flags) override; virtual int protocol_send(const void*, int) override; virtual KResult protocol_connect(FileDescription&, ShouldBlock) override { return KSuccess; } virtual int protocol_allocate_local_port() override;