Kernel: Make better abstractions for networking
This commit is contained in:
@@ -42,7 +42,7 @@ namespace Kernel
|
||||
uint32_t read32(uint16_t reg);
|
||||
void write32(uint16_t reg, uint32_t value);
|
||||
|
||||
virtual BAN::ErrorOr<void> send_raw_bytes(BAN::ConstByteSpan) override;
|
||||
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan) override;
|
||||
|
||||
private:
|
||||
BAN::ErrorOr<void> read_mac_address();
|
||||
|
||||
24
kernel/include/kernel/Networking/ICMP.h
Normal file
24
kernel/include/kernel/Networking/ICMP.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Endianness.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
struct ICMPHeader
|
||||
{
|
||||
uint8_t type;
|
||||
uint8_t code;
|
||||
BAN::NetworkEndian<uint16_t> checksum;
|
||||
BAN::NetworkEndian<uint32_t> rest;
|
||||
};
|
||||
static_assert(sizeof(ICMPHeader) == 8);
|
||||
|
||||
enum ICMPType : uint8_t
|
||||
{
|
||||
EchoReply = 0x00,
|
||||
EchoRequest = 0x08,
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/ByteSpan.h>
|
||||
#include <BAN/Endianness.h>
|
||||
#include <BAN/IPv4.h>
|
||||
#include <BAN/Vector.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
struct IPv4Header
|
||||
{
|
||||
uint8_t version_IHL;
|
||||
uint8_t DSCP_ECN;
|
||||
BAN::NetworkEndian<uint16_t> total_length { 0 };
|
||||
BAN::NetworkEndian<uint16_t> identification { 0 };
|
||||
BAN::NetworkEndian<uint16_t> flags_frament { 0 };
|
||||
uint8_t time_to_live;
|
||||
uint8_t protocol;
|
||||
BAN::NetworkEndian<uint16_t> checksum { 0 };
|
||||
BAN::IPv4Address src_address;
|
||||
BAN::IPv4Address dst_address;
|
||||
|
||||
constexpr uint16_t calculate_checksum() const
|
||||
{
|
||||
uint32_t total_sum = 0;
|
||||
for (size_t i = 0; i < sizeof(IPv4Header) / sizeof(uint16_t); i++)
|
||||
total_sum += reinterpret_cast<const BAN::NetworkEndian<uint16_t>*>(this)[i];
|
||||
total_sum -= checksum;
|
||||
while (total_sum >> 16)
|
||||
total_sum = (total_sum >> 16) + (total_sum & 0xFFFF);
|
||||
return ~(uint16_t)total_sum;
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(IPv4Header) == 20);
|
||||
|
||||
void add_ipv4_header(BAN::ByteSpan packet, BAN::IPv4Address src_ipv4, BAN::IPv4Address dst_ipv4, uint8_t protocol);
|
||||
|
||||
}
|
||||
105
kernel/include/kernel/Networking/IPv4Layer.h
Normal file
105
kernel/include/kernel/Networking/IPv4Layer.h
Normal file
@@ -0,0 +1,105 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Array.h>
|
||||
#include <BAN/ByteSpan.h>
|
||||
#include <BAN/CircularQueue.h>
|
||||
#include <BAN/Endianness.h>
|
||||
#include <BAN/IPv4.h>
|
||||
#include <BAN/NoCopyMove.h>
|
||||
#include <BAN/UniqPtr.h>
|
||||
#include <kernel/Networking/ARPTable.h>
|
||||
#include <kernel/Networking/NetworkInterface.h>
|
||||
#include <kernel/Networking/NetworkLayer.h>
|
||||
#include <kernel/Networking/NetworkSocket.h>
|
||||
#include <kernel/Process.h>
|
||||
#include <kernel/SpinLock.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
struct IPv4Header
|
||||
{
|
||||
uint8_t version_IHL;
|
||||
uint8_t DSCP_ECN;
|
||||
BAN::NetworkEndian<uint16_t> total_length { 0 };
|
||||
BAN::NetworkEndian<uint16_t> identification { 0 };
|
||||
BAN::NetworkEndian<uint16_t> flags_frament { 0 };
|
||||
uint8_t time_to_live;
|
||||
uint8_t protocol;
|
||||
BAN::NetworkEndian<uint16_t> checksum { 0 };
|
||||
BAN::IPv4Address src_address;
|
||||
BAN::IPv4Address dst_address;
|
||||
|
||||
constexpr uint16_t calculate_checksum() const
|
||||
{
|
||||
uint32_t total_sum = 0;
|
||||
for (size_t i = 0; i < sizeof(IPv4Header) / sizeof(uint16_t); i++)
|
||||
total_sum += reinterpret_cast<const BAN::NetworkEndian<uint16_t>*>(this)[i];
|
||||
total_sum -= checksum;
|
||||
while (total_sum >> 16)
|
||||
total_sum = (total_sum >> 16) + (total_sum & 0xFFFF);
|
||||
return ~(uint16_t)total_sum;
|
||||
}
|
||||
|
||||
constexpr bool is_valid_checksum() const
|
||||
{
|
||||
uint32_t total_sum = 0;
|
||||
for (size_t i = 0; i < sizeof(IPv4Header) / sizeof(uint16_t); i++)
|
||||
total_sum += reinterpret_cast<const BAN::NetworkEndian<uint16_t>*>(this)[i];
|
||||
while (total_sum >> 16)
|
||||
total_sum = (total_sum >> 16) + (total_sum & 0xFFFF);
|
||||
return total_sum == 0xFFFF;
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(IPv4Header) == 20);
|
||||
|
||||
class IPv4Layer : public NetworkLayer
|
||||
{
|
||||
BAN_NON_COPYABLE(IPv4Layer);
|
||||
BAN_NON_MOVABLE(IPv4Layer);
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::UniqPtr<IPv4Layer>> create();
|
||||
~IPv4Layer();
|
||||
|
||||
ARPTable& arp_table() { return *m_arp_table; }
|
||||
|
||||
void add_ipv4_packet(NetworkInterface&, BAN::ConstByteSpan);
|
||||
|
||||
virtual void unbind_socket(uint16_t port, BAN::RefPtr<NetworkSocket>) override;
|
||||
virtual BAN::ErrorOr<void> bind_socket(uint16_t port, BAN::RefPtr<NetworkSocket>) override;
|
||||
|
||||
virtual BAN::ErrorOr<size_t> sendto(NetworkSocket&, const sys_sendto_t*) override;
|
||||
|
||||
private:
|
||||
IPv4Layer();
|
||||
|
||||
void add_ipv4_header(BAN::ByteSpan packet, BAN::IPv4Address src_ipv4, BAN::IPv4Address dst_ipv4, uint8_t protocol) const;
|
||||
|
||||
void packet_handle_task();
|
||||
BAN::ErrorOr<void> handle_ipv4_packet(NetworkInterface&, BAN::ByteSpan);
|
||||
|
||||
private:
|
||||
struct PendingIPv4Packet
|
||||
{
|
||||
NetworkInterface& interface;
|
||||
};
|
||||
|
||||
private:
|
||||
SpinLock m_lock;
|
||||
|
||||
BAN::UniqPtr<ARPTable> m_arp_table;
|
||||
Process* m_process { 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;
|
||||
Semaphore m_pending_semaphore;
|
||||
size_t m_pending_total_size { 0 };
|
||||
|
||||
BAN::HashMap<int, BAN::WeakPtr<NetworkSocket>> m_bound_sockets;
|
||||
|
||||
friend class BAN::UniqPtr<IPv4Layer>;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Errors.h>
|
||||
#include <BAN/ByteSpan.h>
|
||||
#include <BAN/Errors.h>
|
||||
#include <BAN/IPv4.h>
|
||||
#include <BAN/MAC.h>
|
||||
#include <kernel/Device/Device.h>
|
||||
#include <kernel/Networking/IPv4.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
@@ -52,13 +52,10 @@ namespace Kernel
|
||||
virtual bool link_up() = 0;
|
||||
virtual int link_speed() = 0;
|
||||
|
||||
size_t interface_header_size() const;
|
||||
void add_interface_header(BAN::ByteSpan packet, BAN::MACAddress destination);
|
||||
|
||||
virtual dev_t rdev() const override { return m_rdev; }
|
||||
virtual BAN::StringView name() const override { return m_name; }
|
||||
|
||||
virtual BAN::ErrorOr<void> send_raw_bytes(BAN::ConstByteSpan) = 0;
|
||||
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan) = 0;
|
||||
|
||||
private:
|
||||
const Type m_type;
|
||||
|
||||
25
kernel/include/kernel/Networking/NetworkLayer.h
Normal file
25
kernel/include/kernel/Networking/NetworkLayer.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/Networking/NetworkInterface.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class NetworkSocket;
|
||||
enum class SocketType;
|
||||
|
||||
class NetworkLayer
|
||||
{
|
||||
public:
|
||||
virtual ~NetworkLayer() {}
|
||||
|
||||
virtual void unbind_socket(uint16_t port, BAN::RefPtr<NetworkSocket>) = 0;
|
||||
virtual BAN::ErrorOr<void> bind_socket(uint16_t port, BAN::RefPtr<NetworkSocket>) = 0;
|
||||
|
||||
virtual BAN::ErrorOr<size_t> sendto(NetworkSocket&, const sys_sendto_t*) = 0;
|
||||
|
||||
protected:
|
||||
NetworkLayer() = default;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <BAN/Vector.h>
|
||||
#include <kernel/FS/TmpFS/FileSystem.h>
|
||||
#include <kernel/Networking/ARPTable.h>
|
||||
#include <kernel/Networking/IPv4Layer.h>
|
||||
#include <kernel/Networking/NetworkInterface.h>
|
||||
#include <kernel/Networking/NetworkSocket.h>
|
||||
#include <kernel/PCI.h>
|
||||
@@ -17,26 +17,15 @@ namespace Kernel
|
||||
BAN_NON_COPYABLE(NetworkManager);
|
||||
BAN_NON_MOVABLE(NetworkManager);
|
||||
|
||||
public:
|
||||
enum class SocketType
|
||||
{
|
||||
STREAM,
|
||||
DGRAM,
|
||||
SEQPACKET,
|
||||
};
|
||||
|
||||
public:
|
||||
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>);
|
||||
BAN::ErrorOr<void> bind_socket(uint16_t port, BAN::RefPtr<NetworkSocket>);
|
||||
BAN::Vector<BAN::RefPtr<NetworkInterface>> interfaces() { return m_interfaces; }
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<NetworkSocket>> create_socket(SocketType, mode_t, uid_t, gid_t);
|
||||
BAN::ErrorOr<BAN::RefPtr<NetworkSocket>> create_socket(SocketDomain, SocketType, mode_t, uid_t, gid_t);
|
||||
|
||||
void on_receive(NetworkInterface&, BAN::ConstByteSpan);
|
||||
|
||||
@@ -44,9 +33,8 @@ 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;
|
||||
BAN::UniqPtr<IPv4Layer> m_ipv4_layer;
|
||||
BAN::Vector<BAN::RefPtr<NetworkInterface>> m_interfaces;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <BAN/WeakPtr.h>
|
||||
#include <kernel/FS/TmpFS/Inode.h>
|
||||
#include <kernel/Networking/NetworkInterface.h>
|
||||
#include <kernel/Networking/NetworkLayer.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
@@ -11,9 +12,24 @@ namespace Kernel
|
||||
|
||||
enum NetworkProtocol : uint8_t
|
||||
{
|
||||
ICMP = 0x01,
|
||||
UDP = 0x11,
|
||||
};
|
||||
|
||||
enum class SocketDomain
|
||||
{
|
||||
INET,
|
||||
INET6,
|
||||
UNIX,
|
||||
};
|
||||
|
||||
enum class SocketType
|
||||
{
|
||||
STREAM,
|
||||
DGRAM,
|
||||
SEQPACKET,
|
||||
};
|
||||
|
||||
class NetworkSocket : public TmpInode, public BAN::Weakable<NetworkSocket>
|
||||
{
|
||||
BAN_NON_COPYABLE(NetworkSocket);
|
||||
@@ -26,14 +42,16 @@ namespace Kernel
|
||||
void bind_interface_and_port(NetworkInterface*, uint16_t port);
|
||||
~NetworkSocket();
|
||||
|
||||
NetworkInterface& interface() { ASSERT(m_interface); return *m_interface; }
|
||||
|
||||
virtual size_t protocol_header_size() const = 0;
|
||||
virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t src_port, uint16_t dst_port) = 0;
|
||||
virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port) = 0;
|
||||
virtual NetworkProtocol protocol() const = 0;
|
||||
|
||||
virtual void add_packet(BAN::ConstByteSpan, BAN::IPv4Address sender_address, uint16_t sender_port) = 0;
|
||||
|
||||
protected:
|
||||
NetworkSocket(mode_t mode, uid_t uid, gid_t gid);
|
||||
NetworkSocket(NetworkLayer&, ino_t, const TmpInodeInfo&);
|
||||
|
||||
virtual BAN::ErrorOr<size_t> read_packet(BAN::ByteSpan, sockaddr_in* sender_address) = 0;
|
||||
|
||||
@@ -46,6 +64,7 @@ namespace Kernel
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(int request, void* arg) override;
|
||||
|
||||
protected:
|
||||
NetworkLayer& m_network_layer;
|
||||
NetworkInterface* m_interface = nullptr;
|
||||
uint16_t m_port = PORT_NONE;
|
||||
};
|
||||
|
||||
@@ -22,10 +22,10 @@ namespace Kernel
|
||||
class UDPSocket final : public NetworkSocket
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<UDPSocket>> create(mode_t, uid_t, gid_t);
|
||||
static BAN::ErrorOr<BAN::RefPtr<UDPSocket>> create(NetworkLayer&, ino_t, const TmpInodeInfo&);
|
||||
|
||||
virtual size_t protocol_header_size() const override { return sizeof(UDPHeader); }
|
||||
virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t src_port, uint16_t dst_port) override;
|
||||
virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port) override;
|
||||
virtual NetworkProtocol protocol() const override { return NetworkProtocol::UDP; }
|
||||
|
||||
protected:
|
||||
@@ -33,7 +33,7 @@ namespace Kernel
|
||||
virtual BAN::ErrorOr<size_t> read_packet(BAN::ByteSpan, sockaddr_in* sender_address) override;
|
||||
|
||||
private:
|
||||
UDPSocket(mode_t, uid_t, gid_t);
|
||||
UDPSocket(NetworkLayer&, ino_t, const TmpInodeInfo&);
|
||||
|
||||
struct PacketInfo
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user