@@ -162,6 +162,7 @@ enum Timer {
162162 }
163163}
164164
165+ const ACK_DELAY_DEFAULT : Duration = Duration { millis : 10 } ;
165166const CLOSE_DELAY : Duration = Duration { millis : 10_000 } ;
166167
167168impl Default for Timer {
@@ -341,6 +342,12 @@ pub struct TcpSocket<'a> {
341342 /// each other which have the same ACK number.
342343 local_rx_dup_acks : u8 ,
343344
345+ /// Duration for Delayed ACK. If None no ACKs will be delayed.
346+ ack_delay : Option < Duration > ,
347+ /// Delayed ack timer. If set, packets containing exclusively
348+ /// ACK or window updates (ie, no data) won't be sent until expiry.
349+ ack_delay_until : Option < Instant > ,
350+
344351 #[ cfg( feature = "async" ) ]
345352 rx_waker : WakerRegistration ,
346353 #[ cfg( feature = "async" ) ]
@@ -397,6 +404,8 @@ impl<'a> TcpSocket<'a> {
397404 local_rx_last_ack : None ,
398405 local_rx_last_seq : None ,
399406 local_rx_dup_acks : 0 ,
407+ ack_delay : Some ( ACK_DELAY_DEFAULT ) ,
408+ ack_delay_until : None ,
400409
401410 #[ cfg( feature = "async" ) ]
402411 rx_waker : WakerRegistration :: new ( ) ,
@@ -453,6 +462,13 @@ impl<'a> TcpSocket<'a> {
453462 self . timeout
454463 }
455464
465+ /// Return the ACK delay duration.
466+ ///
467+ /// See also the [set_ack_delay](#method.set_ack_delay) method.
468+ pub fn ack_delay ( & self ) -> Option < Duration > {
469+ self . ack_delay
470+ }
471+
456472 /// Return the current window field value, including scaling according to RFC 1323.
457473 ///
458474 /// Used in internal calculations as well as packet generation.
@@ -478,6 +494,13 @@ impl<'a> TcpSocket<'a> {
478494 self . timeout = duration
479495 }
480496
497+ /// Set the ACK delay duration.
498+ ///
499+ /// By default, the ACK delay is set to 10ms.
500+ pub fn set_ack_delay ( & mut self , duration : Option < Duration > ) {
501+ self . ack_delay = duration
502+ }
503+
481504 /// Return the keep-alive interval.
482505 ///
483506 /// See also the [set_keep_alive](#method.set_keep_alive) method.
@@ -578,6 +601,8 @@ impl<'a> TcpSocket<'a> {
578601 self . remote_win_shift = rx_cap_log2. saturating_sub ( 16 ) as u8 ;
579602 self . remote_mss = DEFAULT_MSS ;
580603 self . remote_last_ts = None ;
604+ self . ack_delay = Some ( ACK_DELAY_DEFAULT ) ;
605+ self . ack_delay_until = None ;
581606
582607 #[ cfg( feature = "async" ) ]
583608 {
@@ -1541,6 +1566,30 @@ impl<'a> TcpSocket<'a> {
15411566 self . assembler) ;
15421567 }
15431568
1569+ // Handle delayed acks
1570+ if let Some ( ack_delay) = self . ack_delay {
1571+ if self . ack_to_transmit ( ) || self . window_to_update ( ) {
1572+ self . ack_delay_until = match self . ack_delay_until {
1573+ None => {
1574+ net_trace ! ( "{}:{}:{}: starting delayed ack timer" ,
1575+ self . meta. handle, self . local_endpoint, self . remote_endpoint
1576+ ) ;
1577+
1578+ Some ( timestamp + ack_delay)
1579+ }
1580+ // RFC1122 says "in a stream of full-sized segments there SHOULD be an ACK
1581+ // for at least every second segment".
1582+ // For now, we send an ACK every second received packet, full-sized or not.
1583+ Some ( _) => {
1584+ net_trace ! ( "{}:{}:{}: delayed ack timer already started, forcing expiry" ,
1585+ self . meta. handle, self . local_endpoint, self . remote_endpoint
1586+ ) ;
1587+ None
1588+ }
1589+ } ;
1590+ }
1591+ }
1592+
15441593 // Per RFC 5681, we should send an immediate ACK when either:
15451594 // 1) an out-of-order segment is received, or
15461595 // 2) a segment arrives that fills in all or part of a gap in sequence space.
@@ -1590,6 +1639,13 @@ impl<'a> TcpSocket<'a> {
15901639 can_data || can_fin
15911640 }
15921641
1642+ fn delayed_ack_expired ( & self , timestamp : Instant ) -> bool {
1643+ match self . ack_delay_until {
1644+ None => true ,
1645+ Some ( t) => t <= timestamp,
1646+ }
1647+ }
1648+
15931649 fn ack_to_transmit ( & self ) -> bool {
15941650 if let Some ( remote_last_ack) = self . remote_last_ack {
15951651 remote_last_ack < self . remote_seq_no + self . rx_buffer . len ( )
@@ -1644,11 +1700,11 @@ impl<'a> TcpSocket<'a> {
16441700 // If we have data to transmit and it fits into partner's window, do it.
16451701 net_trace ! ( "{}:{}:{}: outgoing segment will send data or flags" ,
16461702 self . meta. handle, self . local_endpoint, self . remote_endpoint) ;
1647- } else if self . ack_to_transmit ( ) {
1703+ } else if self . ack_to_transmit ( ) && self . delayed_ack_expired ( timestamp ) {
16481704 // If we have data to acknowledge, do it.
16491705 net_trace ! ( "{}:{}:{}: outgoing segment will acknowledge" ,
16501706 self . meta. handle, self . local_endpoint, self . remote_endpoint) ;
1651- } else if self . window_to_update ( ) {
1707+ } else if self . window_to_update ( ) && self . delayed_ack_expired ( timestamp ) {
16521708 // If we have window length increase to advertise, do it.
16531709 net_trace ! ( "{}:{}:{}: outgoing segment will update window" ,
16541710 self . meta. handle, self . local_endpoint, self . remote_endpoint) ;
@@ -1812,6 +1868,15 @@ impl<'a> TcpSocket<'a> {
18121868 // the keep-alive timer.
18131869 self . timer . rewind_keep_alive ( timestamp, self . keep_alive ) ;
18141870
1871+ // Reset delayed-ack timer
1872+ if self . ack_delay_until . is_some ( ) {
1873+ net_trace ! ( "{}:{}:{}: stop delayed ack timer" ,
1874+ self . meta. handle, self . local_endpoint, self . remote_endpoint
1875+ ) ;
1876+
1877+ self . ack_delay_until = None ;
1878+ }
1879+
18151880 // Leave the rest of the state intact if sending a keep-alive packet, since those
18161881 // carry a fake segment.
18171882 if is_keep_alive { return Ok ( ( ) ) }
@@ -1851,10 +1916,17 @@ impl<'a> TcpSocket<'a> {
18511916 } else if self . state == State :: Closed {
18521917 // Socket was aborted, we have an RST packet to transmit.
18531918 PollAt :: Now
1854- } else if self . seq_to_transmit ( ) || self . ack_to_transmit ( ) || self . window_to_update ( ) {
1919+ } else if self . seq_to_transmit ( ) {
18551920 // We have a data or flag packet to transmit.
18561921 PollAt :: Now
18571922 } else {
1923+ let want_ack = self . ack_to_transmit ( ) || self . window_to_update ( ) ;
1924+ let delayed_ack_poll_at = match ( want_ack, self . ack_delay_until ) {
1925+ ( false , _) => PollAt :: Ingress ,
1926+ ( true , None ) => PollAt :: Now ,
1927+ ( true , Some ( t) ) => PollAt :: Time ( t) ,
1928+ } ;
1929+
18581930 let timeout_poll_at = match ( self . remote_last_ts , self . timeout ) {
18591931 // If we're transmitting or retransmitting data, we need to poll at the moment
18601932 // when the timeout would expire.
@@ -1864,9 +1936,8 @@ impl<'a> TcpSocket<'a> {
18641936 } ;
18651937
18661938 // We wait for the earliest of our timers to fire.
1867- * [ self . timer . poll_at ( ) , timeout_poll_at]
1939+ * [ self . timer . poll_at ( ) , timeout_poll_at, delayed_ack_poll_at ]
18681940 . iter ( )
1869- . filter ( |x| !x. is_ingress ( ) )
18701941 . min ( ) . unwrap_or ( & PollAt :: Ingress )
18711942 }
18721943 }
@@ -2076,7 +2147,9 @@ mod test {
20762147
20772148 let rx_buffer = SocketBuffer :: new ( vec ! [ 0 ; rx_len] ) ;
20782149 let tx_buffer = SocketBuffer :: new ( vec ! [ 0 ; tx_len] ) ;
2079- TcpSocket :: new ( rx_buffer, tx_buffer)
2150+ let mut socket = TcpSocket :: new ( rx_buffer, tx_buffer) ;
2151+ socket. set_ack_delay ( None ) ;
2152+ socket
20802153 }
20812154
20822155 fn socket_syn_received_with_buffer_sizes (
@@ -5084,6 +5157,119 @@ mod test {
50845157 assert_eq ! ( s. recv( |_| ( 0 , ( ) ) ) , Err ( Error :: Illegal ) ) ;
50855158 }
50865159
5160+ // =========================================================================================//
5161+ // Tests for delayed ACK
5162+ // =========================================================================================//
5163+
5164+ #[ test]
5165+ fn test_delayed_ack ( ) {
5166+ let mut s = socket_established ( ) ;
5167+ s. set_ack_delay ( Some ( ACK_DELAY_DEFAULT ) ) ;
5168+ send ! ( s, TcpRepr {
5169+ seq_number: REMOTE_SEQ + 1 ,
5170+ ack_number: Some ( LOCAL_SEQ + 1 ) ,
5171+ payload: & b"abc" [ ..] ,
5172+ ..SEND_TEMPL
5173+ } ) ;
5174+
5175+ // No ACK is immediately sent.
5176+ recv ! ( s, Err ( Error :: Exhausted ) ) ;
5177+
5178+ // After 10ms, it is sent.
5179+ recv ! ( s, time 11 , Ok ( TcpRepr {
5180+ seq_number: LOCAL_SEQ + 1 ,
5181+ ack_number: Some ( REMOTE_SEQ + 1 + 3 ) ,
5182+ window_len: 61 ,
5183+ ..RECV_TEMPL
5184+ } ) ) ;
5185+ }
5186+
5187+ #[ test]
5188+ fn test_delayed_ack_win ( ) {
5189+ let mut s = socket_established ( ) ;
5190+ s. set_ack_delay ( Some ( ACK_DELAY_DEFAULT ) ) ;
5191+ send ! ( s, TcpRepr {
5192+ seq_number: REMOTE_SEQ + 1 ,
5193+ ack_number: Some ( LOCAL_SEQ + 1 ) ,
5194+ payload: & b"abc" [ ..] ,
5195+ ..SEND_TEMPL
5196+ } ) ;
5197+
5198+ // Reading the data off the buffer should cause a window update.
5199+ s. recv ( |data| {
5200+ assert_eq ! ( data, b"abc" ) ;
5201+ ( 3 , ( ) )
5202+ } ) . unwrap ( ) ;
5203+
5204+ // However, no ACK or window update is immediately sent.
5205+ recv ! ( s, Err ( Error :: Exhausted ) ) ;
5206+
5207+ // After 10ms, it is sent.
5208+ recv ! ( s, time 11 , Ok ( TcpRepr {
5209+ seq_number: LOCAL_SEQ + 1 ,
5210+ ack_number: Some ( REMOTE_SEQ + 1 + 3 ) ,
5211+ ..RECV_TEMPL
5212+ } ) ) ;
5213+ }
5214+
5215+ #[ test]
5216+ fn test_delayed_ack_reply ( ) {
5217+ let mut s = socket_established ( ) ;
5218+ s. set_ack_delay ( Some ( ACK_DELAY_DEFAULT ) ) ;
5219+ send ! ( s, TcpRepr {
5220+ seq_number: REMOTE_SEQ + 1 ,
5221+ ack_number: Some ( LOCAL_SEQ + 1 ) ,
5222+ payload: & b"abc" [ ..] ,
5223+ ..SEND_TEMPL
5224+ } ) ;
5225+
5226+ s. recv ( |data| {
5227+ assert_eq ! ( data, b"abc" ) ;
5228+ ( 3 , ( ) )
5229+ } ) . unwrap ( ) ;
5230+
5231+ s. send_slice ( & b"xyz" [ ..] ) . unwrap ( ) ;
5232+
5233+ // Writing data to the socket causes ACK to not be delayed,
5234+ // because it is immediately sent with the data.
5235+ recv ! ( s, Ok ( TcpRepr {
5236+ seq_number: LOCAL_SEQ + 1 ,
5237+ ack_number: Some ( REMOTE_SEQ + 1 + 3 ) ,
5238+ payload: & b"xyz" [ ..] ,
5239+ ..RECV_TEMPL
5240+ } ) ) ;
5241+ }
5242+
5243+ #[ test]
5244+ fn test_delayed_ack_every_second_packet ( ) {
5245+ let mut s = socket_established ( ) ;
5246+ s. set_ack_delay ( Some ( ACK_DELAY_DEFAULT ) ) ;
5247+ send ! ( s, TcpRepr {
5248+ seq_number: REMOTE_SEQ + 1 ,
5249+ ack_number: Some ( LOCAL_SEQ + 1 ) ,
5250+ payload: & b"abc" [ ..] ,
5251+ ..SEND_TEMPL
5252+ } ) ;
5253+
5254+ // No ACK is immediately sent.
5255+ recv ! ( s, Err ( Error :: Exhausted ) ) ;
5256+
5257+ send ! ( s, TcpRepr {
5258+ seq_number: REMOTE_SEQ + 1 + 3 ,
5259+ ack_number: Some ( LOCAL_SEQ + 1 ) ,
5260+ payload: & b"def" [ ..] ,
5261+ ..SEND_TEMPL
5262+ } ) ;
5263+
5264+ // Every 2nd packet, ACK is sent without delay.
5265+ recv ! ( s, Ok ( TcpRepr {
5266+ seq_number: LOCAL_SEQ + 1 ,
5267+ ack_number: Some ( REMOTE_SEQ + 1 + 6 ) ,
5268+ window_len: 58 ,
5269+ ..RECV_TEMPL
5270+ } ) ) ;
5271+ }
5272+
50875273 // =========================================================================================//
50885274 // Tests for packet filtering.
50895275 // =========================================================================================//
0 commit comments