Skip to content

Commit

Permalink
Kernel: ARP and routing tables
Browse files Browse the repository at this point in the history
  • Loading branch information
byteduck committed Mar 15, 2024
1 parent f836138 commit 5333de5
Show file tree
Hide file tree
Showing 11 changed files with 325 additions and 44 deletions.
3 changes: 2 additions & 1 deletion kernel/CMakeLists.txt
Expand Up @@ -178,7 +178,8 @@ SET(KERNEL_SRCS
net/NetworkManager.cpp
net/Socket.cpp
net/IPSocket.cpp
net/UDPSocket.cpp)
net/UDPSocket.cpp
net/Router.cpp)

add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/generated/duckos_version.h"
Expand Down
38 changes: 25 additions & 13 deletions kernel/api/ipv4.h
Expand Up @@ -11,26 +11,38 @@ class __attribute__((packed)) IPv4Address {
public:
constexpr IPv4Address() = default;

constexpr IPv4Address(uint32_t addr) {
m_data[0] = addr >> 24;
m_data[1] = addr >> 16;
m_data[2] = addr >> 8;
m_data[3] = addr;
constexpr IPv4Address(uint32_t addr): m_data(addr) {}

constexpr IPv4Address(uint32_t a, uint32_t b, uint32_t c, uint32_t d):
m_data(a | (b << 8) | (c << 16) | (d << 24)) {}

inline constexpr uint8_t operator[](int idx) const {
return m_data >> (idx * 8);
}

constexpr IPv4Address(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
m_data[0] = a;
m_data[1] = b;
m_data[2] = c;
m_data[3] = d;
inline constexpr IPv4Address operator& (const IPv4Address& mask) const {
return mask.m_data & m_data;
}

inline constexpr uint8_t operator[](int idx) const {
return m_data[idx];
inline constexpr IPv4Address& operator&= (const IPv4Address& mask) {
m_data &= mask.m_data;
return *this;
}

inline constexpr bool operator== (const IPv4Address& other) const {
return m_data == other.m_data;
}

inline constexpr uint32_t val() const {
return m_data;
}

inline constexpr bool operator<(const IPv4Address& other) const {
return m_data < other.m_data;
}

private:
uint8_t m_data[4];
uint32_t m_data;
};


Expand Down
13 changes: 12 additions & 1 deletion kernel/api/net.h
Expand Up @@ -21,9 +21,20 @@ class __attribute__((packed)) MACAddress {
m_data[5] = f;
}

uint8_t operator[](size_t index) const {
inline constexpr uint8_t operator[](size_t index) const {
return m_data[index];
}

inline constexpr bool operator<(const MACAddress& other) const {
for (int i = 0; i < 6; i++) {
if (m_data[i] < other.m_data[i])
return true;
else if (m_data[i] > other.m_data[i])
return false;
}
return false;
}

private:
uint8_t m_data[6] = {0};
};
Expand Down
2 changes: 1 addition & 1 deletion kernel/kstd/Arc.h
Expand Up @@ -241,7 +241,7 @@ namespace kstd {
reset();
}

Arc<T> lock() {
Arc<T> lock() const {
if(m_count && m_count->make_strong()) {
auto ret = Arc<T>(m_ptr, m_count);
m_count->release_strong();
Expand Down
2 changes: 1 addition & 1 deletion kernel/net/E1000Adapter.cpp
Expand Up @@ -117,7 +117,7 @@
void E1000Adapter::probe() {
PCI::enumerate_devices([](PCI::Address address, PCI::ID id, uint16_t type, void* dataPtr) {
if(id.vendor == INTEL_VEND && id.device == E1000_DEV) {
new E1000Adapter(address);
NetworkAdapter::register_interface(kstd::Arc(new E1000Adapter(address)));
}
}, nullptr);

Expand Down
22 changes: 14 additions & 8 deletions kernel/net/NetworkAdapter.cpp
Expand Up @@ -6,15 +6,12 @@
#include "../kstd/KLog.h"
#include "E1000Adapter.h"
#include "NetworkManager.h"
#include "Router.h"

kstd::vector<NetworkAdapter*> NetworkAdapter::s_interfaces;
kstd::vector<kstd::Arc<NetworkAdapter>> NetworkAdapter::s_interfaces;

NetworkAdapter::NetworkAdapter(kstd::string name):
m_name(kstd::move(name))
{
KLog::dbg("NetworkAdapter", "Registered network adapter {}", m_name);
s_interfaces.push_back(this);
}
m_name(kstd::move(name)) {}

const kstd::string& NetworkAdapter::name() const {
return m_name;
Expand All @@ -28,19 +25,28 @@ void NetworkAdapter::set_ipv4(IPv4Address addr) {
m_ipv4_addr = addr;
}

void NetworkAdapter::set_netmask(IPv4Address mask) {
m_ipv4_netmask = mask;
}

void NetworkAdapter::setup() {
E1000Adapter::probe();
}

ResultRet<NetworkAdapter*> NetworkAdapter::get_interface(const kstd::string& name) {
ResultRet<kstd::Arc<NetworkAdapter>> NetworkAdapter::get_interface(const kstd::string& name) {
for(auto interface : s_interfaces) {
if (interface->name() == name)
return interface;
}
return Result(ENOENT);
}

const kstd::vector<NetworkAdapter*>& NetworkAdapter::interfaces() {
void NetworkAdapter::register_interface(kstd::Arc<NetworkAdapter> adapter) {
KLog::dbg("NetworkAdapter", "Registered network adapter {}", adapter->name());
s_interfaces.push_back(kstd::move(adapter));
}

const kstd::vector<kstd::Arc<NetworkAdapter>>& NetworkAdapter::interfaces() {
return s_interfaces;
}

Expand Down
15 changes: 9 additions & 6 deletions kernel/net/NetworkAdapter.h
Expand Up @@ -9,7 +9,7 @@
#include "../Result.hpp"
#include "../memory/SafePointer.h"
#include "ARP.h"
class NetworkAdapter {
class NetworkAdapter: public kstd::ArcSelf<NetworkAdapter> {
public:
virtual ~NetworkAdapter() = default;
static void setup();
Expand All @@ -36,26 +36,29 @@ class NetworkAdapter {

[[nodiscard]] IPv4Address ipv4_address() const { return m_ipv4_addr; }
[[nodiscard]] MACAddress mac_address() const { return m_mac_addr; }
[[nodiscard]] IPv4Address netmask() const { return m_ipv4_netmask; }
const kstd::string& name() const;

static ResultRet<NetworkAdapter*> get_interface(const kstd::string& name);
static const kstd::vector<NetworkAdapter*>& interfaces();
static ResultRet<kstd::Arc<NetworkAdapter>> get_interface(const kstd::string& name);
static const kstd::vector<kstd::Arc<NetworkAdapter>>& interfaces();

protected:
explicit NetworkAdapter(kstd::string name);

const kstd::string& name() const;
static void register_interface(kstd::Arc<NetworkAdapter> adapter);

void set_mac(MACAddress addr);
void set_ipv4(IPv4Address addr);
void set_netmask(IPv4Address mask);

virtual void send_bytes(SafePointer<uint8_t> bytes, size_t count) = 0;
void receive_bytes(SafePointer<uint8_t> bytes, size_t count);

private:
static kstd::vector<NetworkAdapter*> s_interfaces;
static kstd::vector<kstd::Arc<NetworkAdapter>> s_interfaces;

kstd::string m_name;
IPv4Address m_ipv4_addr {10, 0, 2, 15};
IPv4Address m_ipv4_netmask = {0, 0, 0, 0};
MACAddress m_mac_addr;
Packet* m_packet_queue = nullptr;
Packet m_packets[32];
Expand Down
18 changes: 10 additions & 8 deletions kernel/net/NetworkManager.cpp
Expand Up @@ -6,8 +6,7 @@
#include "ICMP.h"
#include "UDPSocket.h"
#include "../api/udp.h"

#define ARP_DEBUG 1
#include "Router.h"

NetworkManager* NetworkManager::s_inst = nullptr;

Expand All @@ -22,6 +21,7 @@ void NetworkManager::task_entry() {
}

void NetworkManager::do_task() {
m_thread = TaskManager::current_thread();
while (true) {
/* Block until we get a packet */
TaskManager::current_thread()->block(m_blocker);
Expand All @@ -41,7 +41,7 @@ void NetworkManager::wakeup() {
m_blocker.set_ready(true);
}

void NetworkManager::handle_packet(NetworkAdapter* adapter, NetworkAdapter::Packet* packet) {
void NetworkManager::handle_packet(const kstd::Arc<NetworkAdapter>& adapter, NetworkAdapter::Packet* packet) {
ASSERT(packet->size >= sizeof(NetworkAdapter::FrameHeader));
auto* hdr = (NetworkAdapter::FrameHeader*) packet->buffer;
switch (hdr->type) {
Expand All @@ -60,7 +60,7 @@ void NetworkManager::handle_packet(NetworkAdapter* adapter, NetworkAdapter::Pack
}
}

void NetworkManager::handle_arp(NetworkAdapter* adapter, const NetworkAdapter::Packet* raw_packet) {
void NetworkManager::handle_arp(const kstd::Arc<NetworkAdapter>& adapter, const NetworkAdapter::Packet* raw_packet) {
if (raw_packet->size < (sizeof(NetworkAdapter::FrameHeader) + sizeof(ARPPacket))) {
KLog::warn("NetworkManager", "Got IPv4 packet with invalid frame size!");
}
Expand All @@ -69,7 +69,7 @@ void NetworkManager::handle_arp(NetworkAdapter* adapter, const NetworkAdapter::P

switch (packet.operation) {
case ARPOp::Req: {
KLog::dbg_if<ARP_DEBUG>("NetworkManager", "Got ARP request from {} ({})", packet.sender_protoaddr, packet.sender_hwaddr);
KLog::dbg_if<ARP_DEBUG>("NetworkManager", "Got ARP request from {} ({}), responding", packet.sender_protoaddr, packet.sender_hwaddr);

ARPPacket resp;
resp.operation = ARPOp::Resp;
Expand All @@ -82,13 +82,15 @@ void NetworkManager::handle_arp(NetworkAdapter* adapter, const NetworkAdapter::P
break;
}
case ARPOp::Resp:
KLog::dbg_if<ARP_DEBUG>("NetworkManager", "Received ARP response from {} ({})", packet.sender_protoaddr, packet.sender_hwaddr);
Router::arp_put(packet.sender_protoaddr, packet.sender_hwaddr);
break;
default:
KLog::warn("NetworkManager", "Got ARP packet with unknown operation {}!", packet.operation.val());
}
}

void NetworkManager::handle_ipv4(NetworkAdapter* adapter, const NetworkAdapter::Packet* raw_packet) {
void NetworkManager::handle_ipv4(const kstd::Arc<NetworkAdapter>& adapter, const NetworkAdapter::Packet* raw_packet) {
if (raw_packet->size < (sizeof(NetworkAdapter::FrameHeader) + sizeof(IPv4Packet))) {
KLog::warn("NetworkManager", "Got IPv4 packet with invalid frame size!");
}
Expand All @@ -115,15 +117,15 @@ void NetworkManager::handle_ipv4(NetworkAdapter* adapter, const NetworkAdapter::
}
}

void NetworkManager::handle_icmp(NetworkAdapter* adapter, const IPv4Packet& packet) {
void NetworkManager::handle_icmp(const kstd::Arc<NetworkAdapter>& adapter, const IPv4Packet& packet) {
if (packet.length < (sizeof(IPv4Packet) + sizeof(ICMPHeader))) {
KLog::warn("NetworkManager", "Received ICMP packet of invalid size!");
return;
}
const auto& header= *((ICMPHeader*) packet.payload);
}

void NetworkManager::handle_udp(NetworkAdapter* adapter, const IPv4Packet& packet) {
void NetworkManager::handle_udp(const kstd::Arc<NetworkAdapter>& adapter, const IPv4Packet& packet) {
if (packet.length < (sizeof(IPv4Packet) + sizeof(UDPPacket))) {
KLog::warn("NetworkManager", "Received UDP packet of invalid size!");
return;
Expand Down
13 changes: 8 additions & 5 deletions kernel/net/NetworkManager.h
Expand Up @@ -10,6 +10,8 @@ class NetworkManager {
static NetworkManager& inst();
static void task_entry();

[[nodiscard]] kstd::Arc<Thread> thread() const { return m_thread.lock(); };

protected:
friend class NetworkAdapter;
void wakeup();
Expand All @@ -18,13 +20,14 @@ class NetworkManager {
NetworkManager() = default;

[[noreturn]] void do_task();
void handle_packet(NetworkAdapter* adapter, NetworkAdapter::Packet* packet);
void handle_arp(NetworkAdapter* adapter, const NetworkAdapter::Packet* packet);
void handle_ipv4(NetworkAdapter* adapter, const NetworkAdapter::Packet* packet);
void handle_icmp(NetworkAdapter* adapter, const IPv4Packet& packet);
void handle_udp(NetworkAdapter* adapter, const IPv4Packet& packet);
void handle_packet(const kstd::Arc<NetworkAdapter>& adapter, NetworkAdapter::Packet* packet);
void handle_arp(const kstd::Arc<NetworkAdapter>& adapter, const NetworkAdapter::Packet* packet);
void handle_ipv4(const kstd::Arc<NetworkAdapter>& adapter, const NetworkAdapter::Packet* packet);
void handle_icmp(const kstd::Arc<NetworkAdapter>& adapter, const IPv4Packet& packet);
void handle_udp(const kstd::Arc<NetworkAdapter>& adapter, const IPv4Packet& packet);

static NetworkManager* s_inst;

BooleanBlocker m_blocker;
kstd::Weak<Thread> m_thread;
};

0 comments on commit 5333de5

Please sign in to comment.