Browse Source

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.
Gunnar Beutner 4 years ago
parent
commit
ffc6b714b0
2 changed files with 14 additions and 0 deletions
  1. 7 0
      Kernel/Net/NetworkTask.cpp
  2. 7 0
      Kernel/Net/TCPSocket.h

+ 7 - 0
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);

+ 7 - 0
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 };
 };
 
 }