Kernel: Cleanup TCP and add basic window scaling support
This commit is contained in:
parent
96767f5ca8
commit
36026d4ec6
|
@ -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<BAN::RefPtr<TCPSocket>> 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<VirtualRange> buffer;
|
||||
};
|
||||
|
||||
|
|
|
@ -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<BAN::RefPtr<TCPSocket>> 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<uint32_t>(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<size_t>(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<size_t>(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;
|
||||
|
|
Loading…
Reference in New Issue