Kernel: Optimize networking code
Remove buffering from network layer and rework loopback interface. loopback now has a separate recieve thread to allow concurrent sends and prevent deadlocks
This commit is contained in:
@@ -31,35 +31,18 @@ namespace Kernel
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::UniqPtr<ARPTable>> create();
|
||||
~ARPTable();
|
||||
|
||||
BAN::ErrorOr<BAN::MACAddress> get_mac_from_ipv4(NetworkInterface&, BAN::IPv4Address);
|
||||
|
||||
void add_arp_packet(NetworkInterface&, BAN::ConstByteSpan);
|
||||
BAN::ErrorOr<void> handle_arp_packet(NetworkInterface&, BAN::ConstByteSpan);
|
||||
|
||||
private:
|
||||
ARPTable();
|
||||
|
||||
void packet_handle_task();
|
||||
BAN::ErrorOr<void> handle_arp_packet(NetworkInterface&, const ARPPacket&);
|
||||
ARPTable() = default;
|
||||
|
||||
private:
|
||||
struct PendingArpPacket
|
||||
{
|
||||
NetworkInterface& interface;
|
||||
ARPPacket packet;
|
||||
};
|
||||
|
||||
private:
|
||||
SpinLock m_table_lock;
|
||||
SpinLock m_pending_lock;
|
||||
|
||||
SpinLock m_arp_table_lock;
|
||||
BAN::HashMap<BAN::IPv4Address, BAN::MACAddress> m_arp_table;
|
||||
|
||||
Thread* m_thread { nullptr };
|
||||
BAN::CircularQueue<PendingArpPacket, 128> m_pending_packets;
|
||||
ThreadBlocker m_pending_thread_blocker;
|
||||
|
||||
friend class BAN::UniqPtr<ARPTable>;
|
||||
};
|
||||
|
||||
|
||||
@@ -23,14 +23,14 @@ namespace Kernel
|
||||
static BAN::ErrorOr<BAN::RefPtr<E1000>> create(PCI::Device&);
|
||||
~E1000();
|
||||
|
||||
virtual BAN::MACAddress get_mac_address() const override { return m_mac_address; }
|
||||
BAN::MACAddress get_mac_address() const override { return m_mac_address; }
|
||||
|
||||
virtual bool link_up() override { return m_link_up; }
|
||||
virtual int link_speed() override;
|
||||
bool link_up() override { return m_link_up; }
|
||||
int link_speed() override;
|
||||
|
||||
virtual size_t payload_mtu() const override { return E1000_RX_BUFFER_SIZE - sizeof(EthernetHeader); }
|
||||
size_t payload_mtu() const override { return E1000_RX_BUFFER_SIZE - sizeof(EthernetHeader); }
|
||||
|
||||
virtual void handle_irq() final override;
|
||||
void handle_irq() final override;
|
||||
|
||||
protected:
|
||||
E1000(PCI::Device& pci_device)
|
||||
@@ -45,12 +45,12 @@ namespace Kernel
|
||||
uint32_t read32(uint16_t reg);
|
||||
void write32(uint16_t reg, uint32_t value);
|
||||
|
||||
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan) override;
|
||||
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
bool can_read_impl() const override { return false; }
|
||||
bool can_write_impl() const override { return false; }
|
||||
bool has_error_impl() const override { return false; }
|
||||
bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
BAN::ErrorOr<void> read_mac_address();
|
||||
@@ -61,7 +61,7 @@ namespace Kernel
|
||||
void enable_link();
|
||||
BAN::ErrorOr<void> enable_interrupt();
|
||||
|
||||
void handle_receive();
|
||||
void receive_thread();
|
||||
|
||||
protected:
|
||||
PCI::Device& m_pci_device;
|
||||
@@ -75,6 +75,10 @@ namespace Kernel
|
||||
BAN::UniqPtr<DMARegion> m_tx_descriptor_region;
|
||||
SpinLock m_lock;
|
||||
|
||||
bool m_thread_should_die { false };
|
||||
BAN::Atomic<bool> m_thread_is_dead { true };
|
||||
ThreadBlocker m_thread_blocker;
|
||||
|
||||
BAN::MACAddress m_mac_address {};
|
||||
bool m_link_up { false };
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ namespace Kernel
|
||||
static BAN::ErrorOr<BAN::RefPtr<E1000E>> create(PCI::Device&);
|
||||
|
||||
protected:
|
||||
virtual void detect_eeprom() override;
|
||||
virtual uint32_t eeprom_read(uint8_t addr) override;
|
||||
void detect_eeprom() override;
|
||||
uint32_t eeprom_read(uint8_t addr) override;
|
||||
|
||||
private:
|
||||
E1000E(PCI::Device& pci_device)
|
||||
|
||||
@@ -38,11 +38,10 @@ namespace Kernel
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::UniqPtr<IPv4Layer>> create();
|
||||
~IPv4Layer();
|
||||
|
||||
ARPTable& arp_table() { return *m_arp_table; }
|
||||
|
||||
void add_ipv4_packet(NetworkInterface&, BAN::ConstByteSpan);
|
||||
BAN::ErrorOr<void> handle_ipv4_packet(NetworkInterface&, BAN::ConstByteSpan);
|
||||
|
||||
virtual void unbind_socket(uint16_t port) override;
|
||||
virtual BAN::ErrorOr<void> bind_socket_with_target(BAN::RefPtr<NetworkSocket>, const sockaddr* target_address, socklen_t target_address_len) override;
|
||||
@@ -55,35 +54,15 @@ namespace Kernel
|
||||
virtual size_t header_size() const override { return sizeof(IPv4Header); }
|
||||
|
||||
private:
|
||||
IPv4Layer();
|
||||
|
||||
void add_ipv4_header(BAN::ByteSpan packet, BAN::IPv4Address src_ipv4, BAN::IPv4Address dst_ipv4, uint8_t protocol) const;
|
||||
IPv4Layer() = default;
|
||||
|
||||
BAN::ErrorOr<in_port_t> find_free_port();
|
||||
|
||||
void packet_handle_task();
|
||||
BAN::ErrorOr<void> handle_ipv4_packet(NetworkInterface&, BAN::ByteSpan);
|
||||
|
||||
private:
|
||||
struct PendingIPv4Packet
|
||||
{
|
||||
NetworkInterface& interface;
|
||||
};
|
||||
BAN::UniqPtr<ARPTable> m_arp_table;
|
||||
|
||||
private:
|
||||
RecursiveSpinLock m_bound_socket_lock;
|
||||
|
||||
BAN::UniqPtr<ARPTable> m_arp_table;
|
||||
Thread* m_thread { nullptr };
|
||||
|
||||
static constexpr size_t pending_packet_buffer_size = 128 * PAGE_SIZE;
|
||||
BAN::UniqPtr<VirtualRange> m_pending_packet_buffer;
|
||||
BAN::CircularQueue<PendingIPv4Packet, 128> m_pending_packets;
|
||||
ThreadBlocker m_pending_thread_blocker;
|
||||
SpinLock m_pending_lock;
|
||||
size_t m_pending_total_size { 0 };
|
||||
|
||||
BAN::HashMap<int, BAN::WeakPtr<NetworkSocket>> m_bound_sockets;
|
||||
RecursiveSpinLock m_bound_socket_lock;
|
||||
BAN::HashMap<int, BAN::WeakPtr<NetworkSocket>> m_bound_sockets;
|
||||
|
||||
friend class BAN::UniqPtr<IPv4Layer>;
|
||||
};
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace Kernel
|
||||
{
|
||||
public:
|
||||
static constexpr size_t buffer_size = BAN::numeric_limits<uint16_t>::max() + 1;
|
||||
static constexpr size_t buffer_count = 32;
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<LoopbackInterface>> create();
|
||||
@@ -24,8 +25,9 @@ namespace Kernel
|
||||
LoopbackInterface()
|
||||
: NetworkInterface(Type::Loopback)
|
||||
{}
|
||||
~LoopbackInterface();
|
||||
|
||||
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan) override;
|
||||
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) override;
|
||||
|
||||
bool can_read_impl() const override { return false; }
|
||||
bool can_write_impl() const override { return false; }
|
||||
@@ -33,8 +35,27 @@ namespace Kernel
|
||||
bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
SpinLock m_buffer_lock;
|
||||
void receive_thread();
|
||||
|
||||
private:
|
||||
struct Descriptor
|
||||
{
|
||||
uint8_t* addr;
|
||||
uint32_t size;
|
||||
uint8_t state;
|
||||
};
|
||||
|
||||
private:
|
||||
Mutex m_buffer_lock;
|
||||
BAN::UniqPtr<VirtualRange> m_buffer;
|
||||
|
||||
uint32_t m_buffer_tail { 0 };
|
||||
uint32_t m_buffer_head { 0 };
|
||||
Descriptor m_descriptors[buffer_count] {};
|
||||
|
||||
bool m_thread_should_die { false };
|
||||
BAN::Atomic<bool> m_thread_is_dead { true };
|
||||
ThreadBlocker m_thread_blocker;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -60,7 +60,11 @@ namespace Kernel
|
||||
virtual dev_t rdev() const override { return m_rdev; }
|
||||
virtual BAN::StringView name() const override { return m_name; }
|
||||
|
||||
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan) = 0;
|
||||
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan payload)
|
||||
{
|
||||
return send_bytes(destination, protocol, { &payload, 1 });
|
||||
}
|
||||
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) = 0;
|
||||
|
||||
private:
|
||||
const Type m_type;
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Kernel
|
||||
BAN::IPv4Address src_ipv4 { 0 };
|
||||
BAN::IPv4Address dst_ipv4 { 0 };
|
||||
BAN::NetworkEndian<uint16_t> protocol { 0 };
|
||||
BAN::NetworkEndian<uint16_t> extra { 0 };
|
||||
BAN::NetworkEndian<uint16_t> length { 0 };
|
||||
};
|
||||
static_assert(sizeof(PseudoHeader) == 12);
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace Kernel
|
||||
NetworkLayer() = default;
|
||||
};
|
||||
|
||||
uint16_t calculate_internet_checksum(BAN::ConstByteSpan packet, const PseudoHeader& pseudo_header);
|
||||
uint16_t calculate_internet_checksum(BAN::ConstByteSpan buffer);
|
||||
uint16_t calculate_internet_checksum(BAN::Span<const BAN::ConstByteSpan> buffers);
|
||||
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<BAN::RefPtr<NetworkInterface>> interface(const sockaddr* target, socklen_t target_len);
|
||||
|
||||
virtual size_t protocol_header_size() const = 0;
|
||||
virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) = 0;
|
||||
virtual void get_protocol_header(BAN::ByteSpan header, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader) = 0;
|
||||
virtual NetworkProtocol protocol() const = 0;
|
||||
|
||||
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) = 0;
|
||||
|
||||
@@ -29,9 +29,11 @@ namespace Kernel
|
||||
: NetworkInterface(Type::Ethernet)
|
||||
, m_pci_device(pci_device)
|
||||
{ }
|
||||
~RTL8169();
|
||||
|
||||
BAN::ErrorOr<void> initialize();
|
||||
|
||||
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan) override;
|
||||
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan>) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
@@ -47,7 +49,7 @@ namespace Kernel
|
||||
void enable_link();
|
||||
BAN::ErrorOr<void> enable_interrupt();
|
||||
|
||||
void handle_receive();
|
||||
void receive_thread();
|
||||
|
||||
protected:
|
||||
PCI::Device& m_pci_device;
|
||||
@@ -63,6 +65,9 @@ namespace Kernel
|
||||
BAN::UniqPtr<DMARegion> m_tx_descriptor_region;
|
||||
|
||||
SpinLock m_lock;
|
||||
|
||||
bool m_thread_should_die { false };
|
||||
BAN::Atomic<bool> m_thread_is_dead { true };
|
||||
ThreadBlocker m_thread_blocker;
|
||||
|
||||
uint32_t m_rx_current { 0 };
|
||||
|
||||
@@ -50,30 +50,30 @@ namespace Kernel
|
||||
static BAN::ErrorOr<BAN::RefPtr<TCPSocket>> create(NetworkLayer&, const Info&);
|
||||
~TCPSocket();
|
||||
|
||||
virtual NetworkProtocol protocol() const override { return NetworkProtocol::TCP; }
|
||||
NetworkProtocol protocol() const override { return NetworkProtocol::TCP; }
|
||||
|
||||
virtual size_t protocol_header_size() const override { return sizeof(TCPHeader) + m_tcp_options_bytes; }
|
||||
virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) override;
|
||||
size_t protocol_header_size() const override { return sizeof(TCPHeader) + m_tcp_options_bytes; }
|
||||
void get_protocol_header(BAN::ByteSpan header, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader) override;
|
||||
|
||||
protected:
|
||||
virtual BAN::ErrorOr<long> accept_impl(sockaddr*, socklen_t*, int) override;
|
||||
virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
|
||||
virtual BAN::ErrorOr<void> listen_impl(int) override;
|
||||
virtual BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t) override;
|
||||
virtual BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
|
||||
virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
|
||||
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override;
|
||||
virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
|
||||
virtual BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) override;
|
||||
BAN::ErrorOr<long> accept_impl(sockaddr*, socklen_t*, int) override;
|
||||
BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
|
||||
BAN::ErrorOr<void> listen_impl(int) override;
|
||||
BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t) override;
|
||||
BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
|
||||
BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
|
||||
BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override;
|
||||
BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
|
||||
BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) override;
|
||||
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||
BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||
|
||||
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override;
|
||||
void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override;
|
||||
|
||||
virtual bool can_read_impl() const override;
|
||||
virtual bool can_write_impl() const override;
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override;
|
||||
bool can_read_impl() const override;
|
||||
bool can_write_impl() const override;
|
||||
bool has_error_impl() const override { return false; }
|
||||
bool has_hungup_impl() const override;
|
||||
|
||||
private:
|
||||
enum class State
|
||||
@@ -181,6 +181,7 @@ namespace Kernel
|
||||
bool m_no_delay { false };
|
||||
|
||||
bool m_should_send_ack { false };
|
||||
bool m_should_send_zero_window { false };
|
||||
|
||||
uint64_t m_time_wait_start_ms { 0 };
|
||||
|
||||
|
||||
@@ -25,28 +25,28 @@ namespace Kernel
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<UDPSocket>> create(NetworkLayer&, const Socket::Info&);
|
||||
|
||||
virtual NetworkProtocol protocol() const override { return NetworkProtocol::UDP; }
|
||||
NetworkProtocol protocol() const override { return NetworkProtocol::UDP; }
|
||||
|
||||
virtual size_t protocol_header_size() const override { return sizeof(UDPHeader); }
|
||||
virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) override;
|
||||
size_t protocol_header_size() const override { return sizeof(UDPHeader); }
|
||||
void get_protocol_header(BAN::ByteSpan header, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader) override;
|
||||
|
||||
protected:
|
||||
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override;
|
||||
void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override;
|
||||
|
||||
virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
|
||||
virtual BAN::ErrorOr<void> bind_impl(const sockaddr* address, socklen_t address_len) override;
|
||||
virtual BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
|
||||
virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
|
||||
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override { return BAN::Error::from_errno(ENOTCONN); }
|
||||
virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
|
||||
virtual BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) override;
|
||||
BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
|
||||
BAN::ErrorOr<void> bind_impl(const sockaddr* address, socklen_t address_len) override;
|
||||
BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
|
||||
BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
|
||||
BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override { return BAN::Error::from_errno(ENOTCONN); }
|
||||
BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
|
||||
BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) override;
|
||||
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||
BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return !m_packets.empty(); }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
bool can_read_impl() const override { return !m_packets.empty(); }
|
||||
bool can_write_impl() const override { return true; }
|
||||
bool has_error_impl() const override { return false; }
|
||||
bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
UDPSocket(NetworkLayer&, const Socket::Info&);
|
||||
|
||||
Reference in New Issue
Block a user