Kernel: Implement super simple TCP stack

No SACK support and windows are fixed size
This commit is contained in:
2024-02-12 04:27:50 +02:00
parent ba06269b14
commit 435636a655
6 changed files with 804 additions and 8 deletions

View File

@@ -12,6 +12,7 @@ namespace Kernel
enum NetworkProtocol : uint8_t
{
ICMP = 0x01,
TCP = 0x06,
UDP = 0x11,
};

View File

@@ -0,0 +1,118 @@
#pragma once
#include <BAN/Endianness.h>
#include <kernel/Memory/VirtualRange.h>
#include <kernel/Networking/NetworkInterface.h>
#include <kernel/Networking/NetworkSocket.h>
#include <kernel/Process.h>
#include <kernel/Semaphore.h>
namespace Kernel
{
struct TCPHeader
{
BAN::NetworkEndian<uint16_t> src_port { 0 };
BAN::NetworkEndian<uint16_t> dst_port { 0 };
BAN::NetworkEndian<uint32_t> seq_number { 0 };
BAN::NetworkEndian<uint32_t> ack_number { 0 };
uint8_t reserved : 4 { 0 };
uint8_t data_offset : 4 { 0 };
uint8_t fin : 1 { 0 };
uint8_t syn : 1 { 0 };
uint8_t rst : 1 { 0 };
uint8_t psh : 1 { 0 };
uint8_t ack : 1 { 0 };
uint8_t urg : 1 { 0 };
uint8_t ece : 1 { 0 };
uint8_t cwr : 1 { 0 };
BAN::NetworkEndian<uint16_t> window_size { 0 };
BAN::NetworkEndian<uint16_t> checksum { 0 };
BAN::NetworkEndian<uint16_t> urgent_pointer { 0 };
uint8_t options[0];
};
static_assert(sizeof(TCPHeader) == 20);
class TCPSocket final : public NetworkSocket
{
public:
static constexpr size_t m_tcp_options_bytes = 4;
public:
static BAN::ErrorOr<BAN::RefPtr<TCPSocket>> create(NetworkLayer&, ino_t, const TmpInodeInfo&);
~TCPSocket();
virtual 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;
protected:
virtual void on_close_impl() override;
virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr_storage& sender) override;
virtual BAN::ErrorOr<size_t> sendto_impl(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len) override;
virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan message, sockaddr* address, socklen_t* address_len) override;
private:
enum class State
{
Closed = 0,
Listen,
SynSent,
SynReceived,
Established,
FinWait1,
FinWait2,
CloseWait,
Closing,
LastAck,
TimeWait,
};
struct WindowInfo
{
uint32_t mss { 0 };
uint16_t size { 0 };
uint8_t scale { 0 };
uint32_t start_seq { 0 };
uint32_t current_seq { 0 };
BAN::Atomic<uint32_t> ack_number { 0 };
uint32_t data_size { 0 };
uint64_t send_time_ms { 0 };
BAN::UniqPtr<VirtualRange> window;
};
private:
TCPSocket(NetworkLayer&, ino_t, const TmpInodeInfo&);
void process_task();
void set_connection_as_closed();
private:
State m_state = State::Closed;
Process* m_process { nullptr };
uint64_t m_time_wait_start_ms { 0 };
RecursiveSpinLock m_lock;
Semaphore m_semaphore;
BAN::Atomic<bool> m_should_ack { false };
WindowInfo m_recv_window;
WindowInfo m_send_window;
struct ConnectionInfo
{
sockaddr_storage address;
socklen_t address_len;
};
BAN::Optional<ConnectionInfo> m_connection_info;
};
}