mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 17:52:45 +00:00 
			
		
		
		
	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.
This commit is contained in:
		
							parent
							
								
									7272127927
								
							
						
					
					
						commit
						ffc6b714b0
					
				
					 2 changed files with 14 additions and 0 deletions
				
			
		|  | @ -533,9 +533,16 @@ void handle_tcp(const IPv4Packet& ipv4_packet, const Time& packet_timestamp) | ||||||
| 
 | 
 | ||||||
|         if (tcp_packet.sequence_number() != socket->ack_number()) { |         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()); |             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; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         socket->set_duplicate_acks(0); | ||||||
|  | 
 | ||||||
|         if (tcp_packet.has_fin()) { |         if (tcp_packet.has_fin()) { | ||||||
|             if (payload_size != 0) |             if (payload_size != 0) | ||||||
|                 socket->did_receive(ipv4_packet.source(), tcp_packet.source_port(), { &ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size() }, packet_timestamp); |                 socket->did_receive(ipv4_packet.source(), tcp_packet.source_port(), { &ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size() }, packet_timestamp); | ||||||
|  |  | ||||||
|  | @ -128,6 +128,11 @@ public: | ||||||
|     u32 packets_out() const { return m_packets_out; } |     u32 packets_out() const { return m_packets_out; } | ||||||
|     u32 bytes_out() const { return m_bytes_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); |     KResult send_tcp_packet(u16 flags, const UserOrKernelBuffer* = nullptr, size_t = 0); | ||||||
|     void send_outgoing_packets(RoutingDecision&); |     void send_outgoing_packets(RoutingDecision&); | ||||||
|     void receive_tcp_packet(const TCPPacket&, u16 size); |     void receive_tcp_packet(const TCPPacket&, u16 size); | ||||||
|  | @ -187,6 +192,8 @@ private: | ||||||
| 
 | 
 | ||||||
|     Lock m_not_acked_lock { "TCPSocket unacked packets" }; |     Lock m_not_acked_lock { "TCPSocket unacked packets" }; | ||||||
|     SinglyLinkedList<OutgoingPacket> m_not_acked; |     SinglyLinkedList<OutgoingPacket> m_not_acked; | ||||||
|  | 
 | ||||||
|  |     u32 m_duplicate_acks { 0 }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Gunnar Beutner
						Gunnar Beutner