From 17e6e53948246e2a63357375c9269044eb837dd4 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sun, 28 Jun 2026 22:12:12 +0300 Subject: [PATCH] Kernel: Move Ethernet header prepending from NIC to helper --- .../include/kernel/Networking/E1000/E1000.h | 2 +- kernel/include/kernel/Networking/IPv4Layer.h | 2 +- kernel/include/kernel/Networking/Loopback.h | 2 +- .../kernel/Networking/NetworkInterface.h | 25 +++++++++++++-- .../include/kernel/Networking/NetworkLayer.h | 2 +- .../kernel/Networking/RTL8169/RTL8169.h | 4 +-- kernel/kernel/Networking/ARPTable.cpp | 31 ++++++++++--------- kernel/kernel/Networking/E1000/E1000.cpp | 13 +++----- kernel/kernel/Networking/IPv4Layer.cpp | 27 +++++++--------- kernel/kernel/Networking/Loopback.cpp | 11 ++----- kernel/kernel/Networking/RTL8169/RTL8169.cpp | 12 +++---- kernel/kernel/Networking/UDPSocket.cpp | 4 ++- 12 files changed, 70 insertions(+), 65 deletions(-) diff --git a/kernel/include/kernel/Networking/E1000/E1000.h b/kernel/include/kernel/Networking/E1000/E1000.h index c14f6462..79b8ce82 100644 --- a/kernel/include/kernel/Networking/E1000/E1000.h +++ b/kernel/include/kernel/Networking/E1000/E1000.h @@ -45,7 +45,7 @@ namespace Kernel uint32_t read32(uint16_t reg); void write32(uint16_t reg, uint32_t value); - BAN::ErrorOr send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span payload) override; + BAN::ErrorOr send_raw_bytes(BAN::Span buffers) override; bool can_read_impl() const override { return false; } bool can_write_impl() const override { return false; } diff --git a/kernel/include/kernel/Networking/IPv4Layer.h b/kernel/include/kernel/Networking/IPv4Layer.h index a2eb1409..7bafddf3 100644 --- a/kernel/include/kernel/Networking/IPv4Layer.h +++ b/kernel/include/kernel/Networking/IPv4Layer.h @@ -48,7 +48,7 @@ namespace Kernel virtual BAN::ErrorOr bind_socket_to_address(BAN::RefPtr, const sockaddr* address, socklen_t address_len) override; virtual BAN::ErrorOr get_socket_address(BAN::RefPtr, sockaddr* address, socklen_t* address_len) override; - virtual BAN::ErrorOr sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) override; + virtual BAN::ErrorOr sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) override; virtual Socket::Domain domain() const override { return Socket::Domain::INET ;} virtual size_t header_size() const override { return sizeof(IPv4Header); } diff --git a/kernel/include/kernel/Networking/Loopback.h b/kernel/include/kernel/Networking/Loopback.h index 9a28b549..dfdbe41c 100644 --- a/kernel/include/kernel/Networking/Loopback.h +++ b/kernel/include/kernel/Networking/Loopback.h @@ -27,7 +27,7 @@ namespace Kernel {} ~LoopbackInterface(); - BAN::ErrorOr send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span payload) override; + BAN::ErrorOr send_raw_bytes(BAN::Span buffers) override; bool can_read_impl() const override { return false; } bool can_write_impl() const override { return false; } diff --git a/kernel/include/kernel/Networking/NetworkInterface.h b/kernel/include/kernel/Networking/NetworkInterface.h index 1157ad86..2c6c12eb 100644 --- a/kernel/include/kernel/Networking/NetworkInterface.h +++ b/kernel/include/kernel/Networking/NetworkInterface.h @@ -59,11 +59,30 @@ namespace Kernel virtual BAN::StringView name() const override { return m_name; } - BAN::ErrorOr send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan payload) + BAN::ErrorOr send_with_ethernet_header(BAN::MACAddress dst_mac, EtherType ether_type, BAN::ConstByteSpan buffer) { - return send_bytes(destination, protocol, { &payload, 1 }); + BAN::ConstByteSpan buffer_array[1] { buffer }; + return send_with_ethernet_header(dst_mac, ether_type, buffer_array); } - virtual BAN::ErrorOr send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span payload) = 0; + + template + BAN::ErrorOr send_with_ethernet_header(BAN::MACAddress dst_mac, EtherType ether_type, const BAN::ConstByteSpan (&buffer_array)[SIZE]) + { + const auto ethernet_header = EthernetHeader { + .dst_mac = dst_mac, + .src_mac = get_mac_address(), + .ether_type = ether_type, + }; + + BAN::ConstByteSpan new_buffer_array[SIZE + 1]; + new_buffer_array[0] = BAN::ConstByteSpan::from(ethernet_header); + for (size_t i = 0; i < SIZE; i++) + new_buffer_array[i + 1] = buffer_array[i]; + + return send_raw_bytes({ new_buffer_array, SIZE + 1 }); + } + + virtual BAN::ErrorOr send_raw_bytes(BAN::Span buffers) = 0; private: BAN::ErrorOr ioctl_impl(int, void*) override; diff --git a/kernel/include/kernel/Networking/NetworkLayer.h b/kernel/include/kernel/Networking/NetworkLayer.h index 5cc83fc9..88b92f69 100644 --- a/kernel/include/kernel/Networking/NetworkLayer.h +++ b/kernel/include/kernel/Networking/NetworkLayer.h @@ -27,7 +27,7 @@ namespace Kernel virtual BAN::ErrorOr bind_socket_to_address(BAN::RefPtr, const sockaddr* address, socklen_t address_len) = 0; virtual BAN::ErrorOr get_socket_address(BAN::RefPtr, sockaddr* address, socklen_t* address_len) = 0; - virtual BAN::ErrorOr sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) = 0; + virtual BAN::ErrorOr sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) = 0; virtual Socket::Domain domain() const = 0; virtual size_t header_size() const = 0; diff --git a/kernel/include/kernel/Networking/RTL8169/RTL8169.h b/kernel/include/kernel/Networking/RTL8169/RTL8169.h index c41dc494..908c9e73 100644 --- a/kernel/include/kernel/Networking/RTL8169/RTL8169.h +++ b/kernel/include/kernel/Networking/RTL8169/RTL8169.h @@ -20,7 +20,7 @@ namespace Kernel virtual bool link_up() override { return m_link_up; } virtual int link_speed() override; - virtual size_t payload_mtu() const override { return 7436 - sizeof(EthernetHeader); } + virtual size_t payload_mtu() const override { return 0x1FF8 - sizeof(EthernetHeader); } virtual void handle_irq() override; @@ -33,7 +33,7 @@ namespace Kernel BAN::ErrorOr initialize(); - virtual BAN::ErrorOr send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span) override; + virtual BAN::ErrorOr send_raw_bytes(BAN::Span buffers) override; virtual bool can_read_impl() const override { return false; } virtual bool can_write_impl() const override { return false; } diff --git a/kernel/kernel/Networking/ARPTable.cpp b/kernel/kernel/Networking/ARPTable.cpp index 6c2ee529..abdf6552 100644 --- a/kernel/kernel/Networking/ARPTable.cpp +++ b/kernel/kernel/Networking/ARPTable.cpp @@ -12,8 +12,8 @@ namespace Kernel Reply = 2, }; - static constexpr BAN::IPv4Address s_broadcast_ipv4 { 0xFFFFFFFF }; - static constexpr BAN::MACAddress s_broadcast_mac {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }}; + static constexpr BAN::IPv4Address s_broadcast_ipv4 { 0xFFFFFFFF }; + static constexpr BAN::MACAddress s_broadcast_mac {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }}; BAN::ErrorOr> ARPTable::create() { @@ -50,18 +50,19 @@ namespace Kernel return it->value; } - ARPPacket arp_request; - arp_request.htype = 0x0001; - arp_request.ptype = EtherType::IPv4; - arp_request.hlen = 0x06; - arp_request.plen = 0x04; - arp_request.oper = ARPOperation::Request; - arp_request.sha = interface.get_mac_address(); - arp_request.spa = interface.get_ipv4_address(); - arp_request.tha = {{ 0, 0, 0, 0, 0, 0 }}; - arp_request.tpa = ipv4_address; + const auto arp_request = ARPPacket { + .htype = 0x0001, + .ptype = EtherType::IPv4, + .hlen = 0x06, + .plen = 0x04, + .oper = ARPOperation::Request, + .sha = interface.get_mac_address(), + .spa = interface.get_ipv4_address(), + .tha = {{ 0, 0, 0, 0, 0, 0 }}, + .tpa = ipv4_address, + }; - TRY(interface.send_bytes(s_broadcast_mac, EtherType::ARP, BAN::ConstByteSpan::from(arp_request))); + TRY(interface.send_with_ethernet_header(s_broadcast_mac, EtherType::ARP, BAN::ConstByteSpan::from(arp_request))); uint64_t timeout = SystemTimer::get().ms_since_boot() + 1'000; while (SystemTimer::get().ms_since_boot() < timeout) @@ -100,7 +101,7 @@ namespace Kernel { if (packet.tpa == interface.get_ipv4_address()) { - const ARPPacket arp_reply { + const auto arp_reply = ARPPacket { .htype = 0x0001, .ptype = EtherType::IPv4, .hlen = 0x06, @@ -111,7 +112,7 @@ namespace Kernel .tha = packet.sha, .tpa = packet.spa, }; - TRY(interface.send_bytes(packet.sha, EtherType::ARP, BAN::ConstByteSpan::from(arp_reply))); + TRY(interface.send_with_ethernet_header(packet.sha, EtherType::ARP, BAN::ConstByteSpan::from(arp_reply))); } break; } diff --git a/kernel/kernel/Networking/E1000/E1000.cpp b/kernel/kernel/Networking/E1000/E1000.cpp index fac13f61..a3c7d8f8 100644 --- a/kernel/kernel/Networking/E1000/E1000.cpp +++ b/kernel/kernel/Networking/E1000/E1000.cpp @@ -279,7 +279,7 @@ namespace Kernel return {}; } - BAN::ErrorOr E1000::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span payload) + BAN::ErrorOr E1000::send_raw_bytes(BAN::Span buffers) { const auto interrupt_state = Processor::get_interrupt_state(); Processor::set_interrupt_state(InterruptState::Disabled); @@ -293,15 +293,10 @@ namespace Kernel auto* tx_buffer = reinterpret_cast(m_tx_buffer_region->vaddr() + E1000_TX_BUFFER_SIZE * tx_current); - auto& ethernet_header = *reinterpret_cast(tx_buffer); - ethernet_header.dst_mac = destination; - ethernet_header.src_mac = get_mac_address(); - ethernet_header.ether_type = protocol; - - size_t packet_size = sizeof(EthernetHeader); - for (const auto& buffer : payload) + size_t packet_size = 0; + for (const auto& buffer : buffers) { - ASSERT(packet_size + buffer.size() < E1000_TX_BUFFER_SIZE); + ASSERT(packet_size + buffer.size() <= E1000_TX_BUFFER_SIZE); memcpy(tx_buffer + packet_size, buffer.data(), buffer.size()); packet_size += buffer.size(); } diff --git a/kernel/kernel/Networking/IPv4Layer.cpp b/kernel/kernel/Networking/IPv4Layer.cpp index 6b0ea71c..e181aac4 100644 --- a/kernel/kernel/Networking/IPv4Layer.cpp +++ b/kernel/kernel/Networking/IPv4Layer.cpp @@ -180,7 +180,7 @@ namespace Kernel return {}; } - BAN::ErrorOr IPv4Layer::sendto(NetworkSocket& socket, BAN::ConstByteSpan payload, const sockaddr* address, socklen_t address_len) + BAN::ErrorOr IPv4Layer::sendto(NetworkSocket& socket, BAN::ConstByteSpan payload, const sockaddr* address, socklen_t address_len) { if (address->sa_family != AF_INET) return BAN::Error::from_errno(EINVAL); @@ -224,20 +224,18 @@ namespace Kernel }; uint8_t protocol_header_buffer[32]; - ASSERT(socket.protocol_header_size() < sizeof(protocol_header_buffer)); - auto protocol_header = BAN::ByteSpan::from(protocol_header_buffer).slice(0, socket.protocol_header_size()); socket.get_protocol_header(protocol_header, payload, dst_port, pseudo_header); - BAN::ConstByteSpan buffers[] { + const BAN::ConstByteSpan buffers[] { BAN::ConstByteSpan::from(ipv4_header), protocol_header, payload, }; - TRY(interface->send_bytes(dst_mac, EtherType::IPv4, { buffers, sizeof(buffers) / sizeof(*buffers) })); + TRY(interface->send_with_ethernet_header(dst_mac, EtherType::IPv4, buffers)); - return payload.size(); + return {}; } BAN::ErrorOr IPv4Layer::handle_ipv4_packet(NetworkInterface& interface, BAN::ConstByteSpan packet) @@ -284,34 +282,33 @@ namespace Kernel { case ICMPType::EchoRequest: { - auto dst_mac = TRY(m_arp_table->get_mac_from_ipv4(interface, src_ipv4)); + const auto dst_mac = TRY(m_arp_table->get_mac_from_ipv4(interface, src_ipv4)); - auto send_ipv4_header = get_ipv4_header( + const auto send_ipv4_header = get_ipv4_header( ipv4_data.size(), interface.get_ipv4_address(), src_ipv4, NetworkProtocol::ICMP ); - ICMPHeader send_icmp_header { + auto send_icmp_header = ICMPHeader { .type = ICMPType::EchoReply, .code = icmp_header.code, .checksum = 0, .rest = icmp_header.rest, }; - auto send_payload = ipv4_data.slice(sizeof(ICMPHeader)); - const BAN::ConstByteSpan send_buffers[] { BAN::ConstByteSpan::from(send_ipv4_header), BAN::ConstByteSpan::from(send_icmp_header), - send_payload + ipv4_data.slice(sizeof(ICMPHeader)) }; - auto send_buffers_span = BAN::Span { send_buffers, sizeof(send_buffers) / sizeof(*send_buffers) }; - send_icmp_header.checksum = calculate_internet_checksum(send_buffers_span.slice(1)); + send_icmp_header.checksum = calculate_internet_checksum({ + send_buffers + 1, sizeof(send_buffers) / sizeof(*send_buffers) - 1 + }); - TRY(interface.send_bytes(dst_mac, EtherType::IPv4, send_buffers_span)); + TRY(interface.send_with_ethernet_header(dst_mac, EtherType::IPv4, send_buffers)); break; } diff --git a/kernel/kernel/Networking/Loopback.cpp b/kernel/kernel/Networking/Loopback.cpp index 3fc2ee09..4596fb26 100644 --- a/kernel/kernel/Networking/Loopback.cpp +++ b/kernel/kernel/Networking/Loopback.cpp @@ -54,7 +54,7 @@ namespace Kernel Processor::yield(); } - BAN::ErrorOr LoopbackInterface::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span payload) + BAN::ErrorOr LoopbackInterface::send_raw_bytes(BAN::Span buffers) { auto& descriptor = [&]() -> Descriptor& @@ -73,13 +73,8 @@ namespace Kernel } }(); - auto& ethernet_header = *reinterpret_cast(descriptor.addr); - ethernet_header.dst_mac = destination; - ethernet_header.src_mac = get_mac_address(); - ethernet_header.ether_type = protocol; - - size_t packet_size = sizeof(EthernetHeader); - for (const auto& buffer : payload) + size_t packet_size = 0; + for (const auto& buffer : buffers) { ASSERT(packet_size + buffer.size() <= buffer_size); memcpy(descriptor.addr + packet_size, buffer.data(), buffer.size()); diff --git a/kernel/kernel/Networking/RTL8169/RTL8169.cpp b/kernel/kernel/Networking/RTL8169/RTL8169.cpp index 2b922648..f5dc6908 100644 --- a/kernel/kernel/Networking/RTL8169/RTL8169.cpp +++ b/kernel/kernel/Networking/RTL8169/RTL8169.cpp @@ -197,7 +197,7 @@ namespace Kernel return 0; } - BAN::ErrorOr RTL8169::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span payload) + BAN::ErrorOr RTL8169::send_raw_bytes(BAN::Span buffers) { if (!link_up()) return BAN::Error::from_errno(EADDRNOTAVAIL); @@ -222,14 +222,10 @@ namespace Kernel auto* tx_buffer = reinterpret_cast(m_tx_buffer_region->vaddr() + tx_current * s_buffer_size); // write packet - auto& ethernet_header = *reinterpret_cast(tx_buffer); - ethernet_header.dst_mac = destination; - ethernet_header.src_mac = get_mac_address(); - ethernet_header.ether_type = protocol; - - size_t packet_size = sizeof(EthernetHeader); - for (const auto& buffer : payload) + size_t packet_size = 0; + for (const auto& buffer : buffers) { + ASSERT(packet_size + buffer.size() <= s_buffer_size); memcpy(tx_buffer + packet_size, buffer.data(), buffer.size()); packet_size += buffer.size(); } diff --git a/kernel/kernel/Networking/UDPSocket.cpp b/kernel/kernel/Networking/UDPSocket.cpp index 327a8287..25fb402a 100644 --- a/kernel/kernel/Networking/UDPSocket.cpp +++ b/kernel/kernel/Networking/UDPSocket.cpp @@ -224,7 +224,9 @@ namespace Kernel address_len = message.msg_namelen; } - return TRY(m_network_layer.sendto(*this, buffer.span(), address, address_len)); + TRY(m_network_layer.sendto(*this, buffer.span(), address, address_len)); + + return buffer.size(); } BAN::ErrorOr UDPSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len)