1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 21:37:35 +00:00

Kernel: Avoid allocations when sending IP packets

Previously we'd allocate buffers when sending packets. This patch
avoids these allocations by using the NetworkAdapter's packet queue.

At the same time this also avoids copying partially constructed
packets in order to prepend Ethernet and/or IPv4 headers. It also
properly truncates UDP and raw IP packets.
This commit is contained in:
Gunnar Beutner 2021-05-26 05:35:05 +02:00 committed by Andreas Kling
parent f8310b7796
commit b436dd138b
7 changed files with 94 additions and 117 deletions

View file

@ -15,6 +15,7 @@
#include <AK/Weakable.h>
#include <Kernel/KBuffer.h>
#include <Kernel/Net/ARP.h>
#include <Kernel/Net/EthernetFrameHeader.h>
#include <Kernel/Net/ICMP.h>
#include <Kernel/Net/IPv4.h>
#include <Kernel/PCI/Definitions.h>
@ -38,7 +39,8 @@ struct PacketWithTimestamp : public RefCounted<PacketWithTimestamp> {
IntrusiveListNode<PacketWithTimestamp, RefPtr<PacketWithTimestamp>> packet_node;
};
class NetworkAdapter : public RefCounted<NetworkAdapter> {
class NetworkAdapter : public RefCounted<NetworkAdapter>
, public Weakable<NetworkAdapter> {
public:
template<typename Callback>
static inline void for_each(Callback callback)
@ -67,8 +69,7 @@ public:
void set_ipv4_gateway(const IPv4Address&);
void send(const MACAddress&, const ARPPacket&);
KResult send_ipv4(const IPv4Address& source_ipv4, const MACAddress&, const IPv4Address&, IPv4Protocol, const UserOrKernelBuffer& payload, size_t payload_size, u8 ttl);
KResult send_ipv4_fragmented(const IPv4Address& source_ipv4, const MACAddress&, const IPv4Address&, IPv4Protocol, const UserOrKernelBuffer& payload, size_t payload_size, u8 ttl);
void fill_in_ipv4_header(PacketWithTimestamp&, IPv4Address const&, MACAddress const&, IPv4Address const&, IPv4Protocol, size_t, u8);
size_t dequeue_packet(u8* buffer, size_t buffer_size, Time& packet_timestamp);
@ -85,13 +86,17 @@ public:
RefPtr<PacketWithTimestamp> acquire_packet_buffer(size_t);
void release_packet_buffer(PacketWithTimestamp&);
constexpr size_t layer3_payload_offset() const { return sizeof(EthernetFrameHeader); }
constexpr size_t ipv4_payload_offset() const { return layer3_payload_offset() + sizeof(IPv4Packet); }
virtual void send_raw(ReadonlyBytes) = 0;
Function<void()> on_receive;
protected:
NetworkAdapter();
void set_interface_name(const PCI::Address&);
void set_mac_address(const MACAddress& mac_address) { m_mac_address = mac_address; }
virtual void send_raw(ReadonlyBytes) = 0;
void did_receive(ReadonlyBytes);
void set_loopback_name();