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
|
class TCPSocket final : public NetworkSocket
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr size_t m_tcp_options_bytes = 4;
|
static constexpr size_t m_tcp_options_bytes = 8;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::RefPtr<TCPSocket>> create(NetworkLayer&, const Info&);
|
static BAN::ErrorOr<BAN::RefPtr<TCPSocket>> create(NetworkLayer&, const Info&);
|
||||||
|
@ -91,6 +91,7 @@ namespace Kernel
|
||||||
bool has_ghost_byte { false };
|
bool has_ghost_byte { false };
|
||||||
|
|
||||||
uint32_t data_size { 0 }; // number of bytes in this buffer
|
uint32_t data_size { 0 }; // number of bytes in this buffer
|
||||||
|
uint8_t scale { 1 }; // window scale
|
||||||
BAN::UniqPtr<VirtualRange> buffer;
|
BAN::UniqPtr<VirtualRange> buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@ namespace Kernel
|
||||||
WindowScale = 0x03,
|
WindowScale = 0x03,
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr size_t s_window_buffer_size = 15 * PAGE_SIZE;
|
static constexpr size_t s_recv_window_buffer_size = 16 * PAGE_SIZE;
|
||||||
static_assert(s_window_buffer_size <= UINT16_MAX);
|
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)
|
BAN::ErrorOr<BAN::RefPtr<TCPSocket>> TCPSocket::create(NetworkLayer& network_layer, const Info& info)
|
||||||
{
|
{
|
||||||
|
@ -28,15 +28,16 @@ namespace Kernel
|
||||||
PageTable::kernel(),
|
PageTable::kernel(),
|
||||||
KERNEL_OFFSET,
|
KERNEL_OFFSET,
|
||||||
~(vaddr_t)0,
|
~(vaddr_t)0,
|
||||||
s_window_buffer_size,
|
s_recv_window_buffer_size,
|
||||||
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
|
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
|
||||||
true
|
true
|
||||||
));
|
));
|
||||||
|
socket->m_recv_window.scale = 12; // use PAGE_SIZE windows
|
||||||
socket->m_send_window.buffer = TRY(VirtualRange::create_to_vaddr_range(
|
socket->m_send_window.buffer = TRY(VirtualRange::create_to_vaddr_range(
|
||||||
PageTable::kernel(),
|
PageTable::kernel(),
|
||||||
KERNEL_OFFSET,
|
KERNEL_OFFSET,
|
||||||
~(vaddr_t)0,
|
~(vaddr_t)0,
|
||||||
s_window_buffer_size,
|
s_send_window_buffer_size,
|
||||||
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
|
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
|
||||||
true
|
true
|
||||||
));
|
));
|
||||||
|
@ -73,7 +74,7 @@ namespace Kernel
|
||||||
while (m_pending_connections.empty())
|
while (m_pending_connections.empty())
|
||||||
{
|
{
|
||||||
LockFreeGuard _(m_mutex);
|
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();
|
auto connection = m_pending_connections.front();
|
||||||
|
@ -205,7 +206,7 @@ namespace Kernel
|
||||||
if (m_state != State::Established)
|
if (m_state != State::Established)
|
||||||
return return_with_maybe_zero();
|
return return_with_maybe_zero();
|
||||||
LockFreeGuard free(m_mutex);
|
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);
|
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())
|
if (m_send_window.data_size + message.size() <= m_send_window.buffer->size())
|
||||||
break;
|
break;
|
||||||
LockFreeGuard free(m_mutex);
|
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)
|
if (m_state != State::Established)
|
||||||
return return_with_maybe_zero();
|
return return_with_maybe_zero();
|
||||||
LockFreeGuard free(m_mutex);
|
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();
|
return message.size();
|
||||||
|
@ -376,18 +377,18 @@ namespace Kernel
|
||||||
header.seq_number = m_send_window.current_seq + m_send_window.has_ghost_byte;
|
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.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.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;
|
header.flags = m_next_flags;
|
||||||
if (header.flags & FIN)
|
if (header.flags & FIN)
|
||||||
m_send_window.has_ghost_byte = true;
|
m_send_window.has_ghost_byte = true;
|
||||||
m_next_flags = 0;
|
m_next_flags = 0;
|
||||||
|
|
||||||
ASSERT(m_recv_window.buffer->size() < (1 << (8 * sizeof(header.window_size))));
|
|
||||||
|
|
||||||
if (m_state == State::Closed)
|
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<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.mss = 1440;
|
||||||
m_send_window.start_seq++;
|
m_send_window.start_seq++;
|
||||||
m_send_window.current_seq = 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;
|
m_send_window.mss = *options.maximum_seqment_size;
|
||||||
if (options.window_scale.has_value())
|
if (options.window_scale.has_value())
|
||||||
m_send_window.scale = *options.window_scale;
|
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.start_seq = m_send_window.current_seq;
|
||||||
m_send_window.current_ack = m_send_window.current_seq;
|
m_send_window.current_ack = m_send_window.current_seq;
|
||||||
|
|
Loading…
Reference in New Issue