mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-23 18:02:05 -05:00
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.
This commit is contained in:
parent
609495882f
commit
72798519cb
7 changed files with 18 additions and 19 deletions
|
@ -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<KBuffer>&& 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;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <AK/HashMap.h>
|
||||
#include <AK/SinglyLinkedList.h>
|
||||
#include <Kernel/KBuffer.h>
|
||||
#include <Kernel/DoubleBuffer.h>
|
||||
#include <Kernel/Lock.h>
|
||||
#include <Kernel/Net/IPv4.h>
|
||||
|
@ -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<KBuffer>&&);
|
||||
|
||||
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<KBuffer> data;
|
||||
};
|
||||
|
||||
SinglyLinkedList<ReceivedPacket> m_receive_queue;
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
|
|
|
@ -46,11 +46,10 @@ NonnullRefPtr<TCPSocket> 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<const TCPPacket*>(ipv4_packet.payload());
|
||||
size_t payload_size = packet_buffer.size() - sizeof(IPv4Packet) - tcp_packet.header_size();
|
||||
#ifdef TCP_SOCKET_DEBUG
|
||||
|
|
|
@ -33,7 +33,7 @@ private:
|
|||
|
||||
static NetworkOrdered<u16> 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;
|
||||
|
|
|
@ -43,11 +43,10 @@ NonnullRefPtr<UDPSocket> 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<const UDPPacket*>(ipv4_packet.payload());
|
||||
ASSERT(udp_packet.length() >= sizeof(UDPPacket)); // FIXME: This should be rejected earlier.
|
||||
ASSERT(buffer_size >= (udp_packet.length() - sizeof(UDPPacket)));
|
||||
|
|
|
@ -16,7 +16,7 @@ private:
|
|||
virtual const char* class_name() const override { return "UDPSocket"; }
|
||||
static Lockable<HashMap<u16, UDPSocket*>>& 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;
|
||||
|
|
Loading…
Add table
Reference in a new issue