@@ -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 }
@@ -2074,7 +2145,9 @@ mod test {
20742145
20752146 let rx_buffer = SocketBuffer :: new ( vec ! [ 0 ; rx_len] ) ;
20762147 let tx_buffer = SocketBuffer :: new ( vec ! [ 0 ; tx_len] ) ;
2077- TcpSocket :: new ( rx_buffer, tx_buffer)
2148+ let mut socket = TcpSocket :: new ( rx_buffer, tx_buffer) ;
2149+ socket. set_ack_delay ( None ) ;
2150+ socket
20782151 }
20792152
20802153 fn socket_syn_received_with_buffer_sizes (
@@ -5080,6 +5153,119 @@ mod test {
50805153 assert_eq ! ( s. recv( |_| ( 0 , ( ) ) ) , Err ( Error :: Illegal ) ) ;
50815154 }
50825155
5156+ // =========================================================================================//
5157+ // Tests for delayed ACK
5158+ // =========================================================================================//
5159+
5160+ #[ test]
5161+ fn test_delayed_ack ( ) {
5162+ let mut s = socket_established ( ) ;
5163+ s. set_ack_delay ( Some ( ACK_DELAY_DEFAULT ) ) ;
5164+ send ! ( s, TcpRepr {
5165+ seq_number: REMOTE_SEQ + 1 ,
5166+ ack_number: Some ( LOCAL_SEQ + 1 ) ,
5167+ payload: & b"abc" [ ..] ,
5168+ ..SEND_TEMPL
5169+ } ) ;
5170+
5171+ // No ACK is immediately sent.
5172+ recv ! ( s, Err ( Error :: Exhausted ) ) ;
5173+
5174+ // After 10ms, it is sent.
5175+ recv ! ( s, time 11 , Ok ( TcpRepr {
5176+ seq_number: LOCAL_SEQ + 1 ,
5177+ ack_number: Some ( REMOTE_SEQ + 1 + 3 ) ,
5178+ window_len: 61 ,
5179+ ..RECV_TEMPL
5180+ } ) ) ;
5181+ }
5182+
5183+ #[ test]
5184+ fn test_delayed_ack_win ( ) {
5185+ let mut s = socket_established ( ) ;
5186+ s. set_ack_delay ( Some ( ACK_DELAY_DEFAULT ) ) ;
5187+ send ! ( s, TcpRepr {
5188+ seq_number: REMOTE_SEQ + 1 ,
5189+ ack_number: Some ( LOCAL_SEQ + 1 ) ,
5190+ payload: & b"abc" [ ..] ,
5191+ ..SEND_TEMPL
5192+ } ) ;
5193+
5194+ // Reading the data off the buffer should cause a window update.
5195+ s. recv ( |data| {
5196+ assert_eq ! ( data, b"abc" ) ;
5197+ ( 3 , ( ) )
5198+ } ) . unwrap ( ) ;
5199+
5200+ // However, no ACK or window update is immediately sent.
5201+ recv ! ( s, Err ( Error :: Exhausted ) ) ;
5202+
5203+ // After 10ms, it is sent.
5204+ recv ! ( s, time 11 , Ok ( TcpRepr {
5205+ seq_number: LOCAL_SEQ + 1 ,
5206+ ack_number: Some ( REMOTE_SEQ + 1 + 3 ) ,
5207+ ..RECV_TEMPL
5208+ } ) ) ;
5209+ }
5210+
5211+ #[ test]
5212+ fn test_delayed_ack_reply ( ) {
5213+ let mut s = socket_established ( ) ;
5214+ s. set_ack_delay ( Some ( ACK_DELAY_DEFAULT ) ) ;
5215+ send ! ( s, TcpRepr {
5216+ seq_number: REMOTE_SEQ + 1 ,
5217+ ack_number: Some ( LOCAL_SEQ + 1 ) ,
5218+ payload: & b"abc" [ ..] ,
5219+ ..SEND_TEMPL
5220+ } ) ;
5221+
5222+ s. recv ( |data| {
5223+ assert_eq ! ( data, b"abc" ) ;
5224+ ( 3 , ( ) )
5225+ } ) . unwrap ( ) ;
5226+
5227+ s. send_slice ( & b"xyz" [ ..] ) . unwrap ( ) ;
5228+
5229+ // Writing data to the socket causes ACK to not be delayed,
5230+ // because it is immediately sent with the data.
5231+ recv ! ( s, Ok ( TcpRepr {
5232+ seq_number: LOCAL_SEQ + 1 ,
5233+ ack_number: Some ( REMOTE_SEQ + 1 + 3 ) ,
5234+ payload: & b"xyz" [ ..] ,
5235+ ..RECV_TEMPL
5236+ } ) ) ;
5237+ }
5238+
5239+ #[ test]
5240+ fn test_delayed_ack_every_second_packet ( ) {
5241+ let mut s = socket_established ( ) ;
5242+ s. set_ack_delay ( Some ( ACK_DELAY_DEFAULT ) ) ;
5243+ send ! ( s, TcpRepr {
5244+ seq_number: REMOTE_SEQ + 1 ,
5245+ ack_number: Some ( LOCAL_SEQ + 1 ) ,
5246+ payload: & b"abc" [ ..] ,
5247+ ..SEND_TEMPL
5248+ } ) ;
5249+
5250+ // No ACK is immediately sent.
5251+ recv ! ( s, Err ( Error :: Exhausted ) ) ;
5252+
5253+ send ! ( s, TcpRepr {
5254+ seq_number: REMOTE_SEQ + 1 + 3 ,
5255+ ack_number: Some ( LOCAL_SEQ + 1 ) ,
5256+ payload: & b"def" [ ..] ,
5257+ ..SEND_TEMPL
5258+ } ) ;
5259+
5260+ // Every 2nd packet, ACK is sent without delay.
5261+ recv ! ( s, Ok ( TcpRepr {
5262+ seq_number: LOCAL_SEQ + 1 ,
5263+ ack_number: Some ( REMOTE_SEQ + 1 + 6 ) ,
5264+ window_len: 58 ,
5265+ ..RECV_TEMPL
5266+ } ) ) ;
5267+ }
5268+
50835269 // =========================================================================================//
50845270 // Tests for packet filtering.
50855271 // =========================================================================================//
0 commit comments