From 36026d4ec6bd386158960abaa48ecaafe5b65500 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Tue, 1 Apr 2025 23:04:59 +0300 Subject: [PATCH] Kernel: Cleanup TCP and add basic window scaling support --- kernel/include/kernel/Networking/TCPSocket.h | 3 ++- kernel/kernel/Networking/TCPSocket.cpp | 27 +++++++++++--------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/kernel/include/kernel/Networking/TCPSocket.h b/kernel/include/kernel/Networking/TCPSocket.h index 130e848b..7414cecc 100644 --- a/kernel/include/kernel/Networking/TCPSocket.h +++ b/kernel/include/kernel/Networking/TCPSocket.h @@ -43,7 +43,7 @@ namespace Kernel class TCPSocket final : public NetworkSocket { public: - static constexpr size_t m_tcp_options_bytes = 4; + static constexpr size_t m_tcp_options_bytes = 8; public: static BAN::ErrorOr> create(NetworkLayer&, const Info&); @@ -91,6 +91,7 @@ namespace Kernel bool has_ghost_byte { false }; uint32_t data_size { 0 }; // number of bytes in this buffer + uint8_t scale { 1 }; // window scale BAN::UniqPtr buffer; }; diff --git a/kernel/kernel/Networking/TCPSocket.cpp b/kernel/kernel/Networking/TCPSocket.cpp index 93df156b..87e40fb2 100644 --- a/kernel/kernel/Networking/TCPSocket.cpp +++ b/kernel/kernel/Networking/TCPSocket.cpp @@ -18,8 +18,8 @@ namespace Kernel WindowScale = 0x03, }; - static constexpr size_t s_window_buffer_size = 15 * PAGE_SIZE; - static_assert(s_window_buffer_size <= UINT16_MAX); + static constexpr size_t s_recv_window_buffer_size = 16 * PAGE_SIZE; + static constexpr size_t s_send_window_buffer_size = 16 * PAGE_SIZE; BAN::ErrorOr> TCPSocket::create(NetworkLayer& network_layer, const Info& info) { @@ -28,15 +28,16 @@ namespace Kernel PageTable::kernel(), KERNEL_OFFSET, ~(vaddr_t)0, - s_window_buffer_size, + s_recv_window_buffer_size, PageTable::Flags::ReadWrite | PageTable::Flags::Present, true )); + socket->m_recv_window.scale = 12; // use PAGE_SIZE windows socket->m_send_window.buffer = TRY(VirtualRange::create_to_vaddr_range( PageTable::kernel(), KERNEL_OFFSET, ~(vaddr_t)0, - s_window_buffer_size, + s_send_window_buffer_size, PageTable::Flags::ReadWrite | PageTable::Flags::Present, true )); @@ -73,7 +74,7 @@ namespace Kernel while (m_pending_connections.empty()) { LockFreeGuard _(m_mutex); - TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker)); + TRY(Thread::current().block_or_eintr_or_timeout_ms(m_thread_blocker, 100, false)); } auto connection = m_pending_connections.front(); @@ -205,7 +206,7 @@ namespace Kernel if (m_state != State::Established) return return_with_maybe_zero(); LockFreeGuard free(m_mutex); - TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker)); + TRY(Thread::current().block_or_eintr_or_timeout_ms(m_thread_blocker, 100, false)); } const uint32_t to_recv = BAN::Math::min(buffer.size(), m_recv_window.data_size); @@ -247,7 +248,7 @@ namespace Kernel if (m_send_window.data_size + message.size() <= m_send_window.buffer->size()) break; LockFreeGuard free(m_mutex); - TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker)); + TRY(Thread::current().block_or_eintr_or_timeout_ms(m_thread_blocker, 100, false)); } { @@ -264,7 +265,7 @@ namespace Kernel if (m_state != State::Established) return return_with_maybe_zero(); LockFreeGuard free(m_mutex); - TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker)); + TRY(Thread::current().block_or_eintr_or_timeout_ms(m_thread_blocker, 100, false)); } return message.size(); @@ -376,18 +377,18 @@ namespace Kernel header.seq_number = m_send_window.current_seq + m_send_window.has_ghost_byte; header.ack_number = m_recv_window.start_seq + m_recv_window.data_size + m_recv_window.has_ghost_byte; header.data_offset = (sizeof(TCPHeader) + m_tcp_options_bytes) / sizeof(uint32_t); - header.window_size = m_recv_window.buffer->size(); + header.window_size = BAN::Math::min(0xFFFF, m_recv_window.buffer->size() >> m_recv_window.scale); header.flags = m_next_flags; if (header.flags & FIN) m_send_window.has_ghost_byte = true; m_next_flags = 0; - ASSERT(m_recv_window.buffer->size() < (1 << (8 * sizeof(header.window_size)))); - if (m_state == State::Closed) { add_tcp_header_option<0, TCPOption::MaximumSeqmentSize>(header, m_interface->payload_mtu() - m_network_layer.header_size()); - add_tcp_header_option<4, TCPOption::WindowScale>(header, 0); + add_tcp_header_option<4, TCPOption::WindowScale>(header, m_recv_window.scale); + header.window_size = BAN::Math::min(0xFFFF, m_recv_window.buffer->size()); + m_send_window.mss = 1440; m_send_window.start_seq++; m_send_window.current_seq = m_send_window.start_seq; @@ -463,6 +464,8 @@ namespace Kernel m_send_window.mss = *options.maximum_seqment_size; if (options.window_scale.has_value()) m_send_window.scale = *options.window_scale; + else + m_recv_window.scale = 1; m_send_window.start_seq = m_send_window.current_seq; m_send_window.current_ack = m_send_window.current_seq;