Kernel: Implement barebones arp table

This commit is contained in:
Bananymous 2024-02-03 01:26:06 +02:00
parent e1ffbb710b
commit a0138955cd
7 changed files with 76 additions and 11 deletions

View File

@ -49,6 +49,7 @@ set(KERNEL_SOURCES
kernel/Memory/MemoryRegion.cpp
kernel/Memory/PhysicalRange.cpp
kernel/Memory/VirtualRange.cpp
kernel/Networking/ARPTable.cpp
kernel/Networking/E1000/E1000.cpp
kernel/Networking/E1000/E1000E.cpp
kernel/Networking/IPv4.cpp

View File

@ -0,0 +1,30 @@
#pragma once
#include <BAN/HashMap.h>
#include <BAN/IPv4.h>
#include <BAN/MAC.h>
#include <BAN/UniqPtr.h>
namespace Kernel
{
class ARPTable
{
BAN_NON_COPYABLE(ARPTable);
BAN_NON_MOVABLE(ARPTable);
public:
static BAN::ErrorOr<BAN::UniqPtr<ARPTable>> create();
BAN::ErrorOr<BAN::MACAddress> get_mac_from_ipv4(BAN::IPv4Address);
private:
ARPTable();
private:
BAN::HashMap<BAN::IPv4Address, BAN::MACAddress> m_arp_table;
friend class BAN::UniqPtr<ARPTable>;
};
}

View File

@ -2,6 +2,7 @@
#include <BAN/Vector.h>
#include <kernel/FS/TmpFS/FileSystem.h>
#include <kernel/Networking/ARPTable.h>
#include <kernel/Networking/NetworkInterface.h>
#include <kernel/Networking/NetworkSocket.h>
#include <kernel/PCI.h>
@ -13,6 +14,9 @@ namespace Kernel
class NetworkManager : public TmpFileSystem
{
BAN_NON_COPYABLE(NetworkManager);
BAN_NON_MOVABLE(NetworkManager);
public:
enum class SocketType
{
@ -25,6 +29,8 @@ namespace Kernel
static BAN::ErrorOr<void> initialize();
static NetworkManager& get();
ARPTable& arp_table() { return *m_arp_table; }
BAN::ErrorOr<void> add_interface(PCI::Device& pci_device);
void unbind_socket(uint16_t port, BAN::RefPtr<NetworkSocket>);
@ -38,6 +44,7 @@ namespace Kernel
NetworkManager();
private:
BAN::UniqPtr<ARPTable> m_arp_table;
BAN::Vector<BAN::RefPtr<NetworkInterface>> m_interfaces;
BAN::HashMap<int, BAN::WeakPtr<NetworkSocket>> m_bound_sockets;
};

View File

@ -11,6 +11,9 @@ namespace Kernel
class NetworkSocket : public TmpInode, public BAN::Weakable<NetworkSocket>
{
BAN_NON_COPYABLE(NetworkSocket);
BAN_NON_MOVABLE(NetworkSocket);
public:
static constexpr uint16_t PORT_NONE = 0;

View File

@ -0,0 +1,27 @@
#include <kernel/Networking/ARPTable.h>
namespace Kernel
{
static constexpr BAN::IPv4Address s_broadcast_ipv4 { 0xFFFFFFFF };
static constexpr BAN::MACAddress s_broadcast_mac {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }};
BAN::ErrorOr<BAN::UniqPtr<ARPTable>> ARPTable::create()
{
return TRY(BAN::UniqPtr<ARPTable>::create());
}
ARPTable::ARPTable()
{
}
BAN::ErrorOr<BAN::MACAddress> ARPTable::get_mac_from_ipv4(BAN::IPv4Address ipv4_address)
{
if (ipv4_address == s_broadcast_ipv4)
return s_broadcast_mac;
dprintln("No MAC for IPv4 {}", ipv4_address);
return BAN::Error::from_errno(ENOTSUP);
}
}

View File

@ -19,6 +19,7 @@ namespace Kernel
if (manager_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
auto manager = BAN::UniqPtr<NetworkManager>::adopt(manager_ptr);
manager->m_arp_table = TRY(ARPTable::create());
TRY(manager->TmpFileSystem::initialize(0777, 0, 0));
s_instance = BAN::move(manager);
return {};

View File

@ -58,16 +58,12 @@ namespace Kernel
auto* destination = reinterpret_cast<const sockaddr_in*>(arguments->dest_addr);
auto message = BAN::ConstByteSpan((const uint8_t*)arguments->message, arguments->length);
if (destination->sin_port == PORT_NONE)
uint16_t dst_port = destination->sin_port;
if (dst_port == PORT_NONE)
return BAN::Error::from_errno(EINVAL);
if (destination->sin_addr.s_addr != 0xFFFFFFFF)
{
dprintln("Only broadcast ip supported");
return BAN::Error::from_errno(EINVAL);
}
static BAN::MACAddress dest_mac {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }};
auto dst_addr = BAN::IPv4Address(destination->sin_addr.s_addr);
auto dst_mac = TRY(NetworkManager::get().arp_table().get_mac_from_ipv4(dst_addr));
const size_t interface_header_offset = 0;
const size_t interface_header_size = m_interface->interface_header_size();
@ -87,9 +83,9 @@ namespace Kernel
BAN::ByteSpan packet_bytespan { full_packet.span() };
memcpy(full_packet.data() + payload_offset, message.data(), payload_size);
add_protocol_header(packet_bytespan.slice(protocol_header_offset), m_port, destination->sin_port);
add_ipv4_header(packet_bytespan.slice(ipv4_header_offset), m_interface->get_ipv4_address(), destination->sin_addr.s_addr, protocol());
m_interface->add_interface_header(packet_bytespan.slice(interface_header_offset), dest_mac);
add_protocol_header(packet_bytespan.slice(protocol_header_offset), m_port, dst_port);
add_ipv4_header(packet_bytespan.slice(ipv4_header_offset), m_interface->get_ipv4_address(), dst_addr, protocol());
m_interface->add_interface_header(packet_bytespan.slice(interface_header_offset), dst_mac);
TRY(m_interface->send_raw_bytes(packet_bytespan));
return arguments->length;