diff options
author | Gunnar Beutner <gbeutner@serenityos.org> | 2021-05-12 08:13:53 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-05-12 13:47:07 +0200 |
commit | ffc6b714b0876262d80fe7f48ba071ce33ff99fb (patch) | |
tree | 57a9da6c2915d3392f86abc864ed76f56f2988eb | |
parent | 7272127927119fc4eb4a79704d5520f7cb5a0c3b (diff) | |
download | serenity-ffc6b714b0876262d80fe7f48ba071ce33ff99fb.zip |
Kernel: Trigger TCP fast retransmission when we encounter lost packets
When we receive a TCP packet with a sequence number that is not what
we expected we have lost one or more packets. We can signal this to
the sender by sending a TCP ACK with the previous ack number so that
they can resend the missing TCP fragments.
-rw-r--r-- | Kernel/Net/NetworkTask.cpp | 7 | ||||
-rw-r--r-- | Kernel/Net/TCPSocket.h | 7 |
2 files changed, 14 insertions, 0 deletions
diff --git a/Kernel/Net/NetworkTask.cpp b/Kernel/Net/NetworkTask.cpp index 7484f297e3..70457c02c4 100644 --- a/Kernel/Net/NetworkTask.cpp +++ b/Kernel/Net/NetworkTask.cpp @@ -533,9 +533,16 @@ void handle_tcp(const IPv4Packet& ipv4_packet, const Time& packet_timestamp) if (tcp_packet.sequence_number() != socket->ack_number()) { dbgln_if(TCP_DEBUG, "Discarding out of order packet: seq {} vs. ack {}", tcp_packet.sequence_number(), socket->ack_number()); + if (socket->duplicate_acks() < TCPSocket::maximum_duplicate_acks) { + dbgln_if(TCP_DEBUG, "Sending ACK with same ack number to trigger fast retransmission"); + socket->set_duplicate_acks(socket->duplicate_acks() + 1); + unused_rc = socket->send_tcp_packet(TCPFlags::ACK); + } return; } + socket->set_duplicate_acks(0); + if (tcp_packet.has_fin()) { if (payload_size != 0) socket->did_receive(ipv4_packet.source(), tcp_packet.source_port(), { &ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size() }, packet_timestamp); diff --git a/Kernel/Net/TCPSocket.h b/Kernel/Net/TCPSocket.h index 37e03e26fa..cb490effbe 100644 --- a/Kernel/Net/TCPSocket.h +++ b/Kernel/Net/TCPSocket.h @@ -128,6 +128,11 @@ public: u32 packets_out() const { return m_packets_out; } u32 bytes_out() const { return m_bytes_out; } + // FIXME: Make this configurable? + static constexpr u32 maximum_duplicate_acks = 5; + void set_duplicate_acks(u32 acks) { m_duplicate_acks = acks; } + u32 duplicate_acks() const { return m_duplicate_acks; } + KResult send_tcp_packet(u16 flags, const UserOrKernelBuffer* = nullptr, size_t = 0); void send_outgoing_packets(RoutingDecision&); void receive_tcp_packet(const TCPPacket&, u16 size); @@ -187,6 +192,8 @@ private: Lock m_not_acked_lock { "TCPSocket unacked packets" }; SinglyLinkedList<OutgoingPacket> m_not_acked; + + u32 m_duplicate_acks { 0 }; }; } |