summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGunnar Beutner <gbeutner@serenityos.org>2021-05-12 08:13:53 +0200
committerAndreas Kling <kling@serenityos.org>2021-05-12 13:47:07 +0200
commitffc6b714b0876262d80fe7f48ba071ce33ff99fb (patch)
tree57a9da6c2915d3392f86abc864ed76f56f2988eb
parent7272127927119fc4eb4a79704d5520f7cb5a0c3b (diff)
downloadserenity-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.cpp7
-rw-r--r--Kernel/Net/TCPSocket.h7
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 };
};
}