11// Heads up! Before working on this file you should read, at least, RFC 793 and
2- // the parts of RFC 1122 that discuss TCP. Consult RFC 7414 when implementing
3- // a new feature.
2+ // the parts of RFC 1122 that discuss TCP, as well as RFC 7323 for some of the TCP options.
3+ // Consult RFC 7414 when implementing a new feature.
44
55use core:: fmt:: Display ;
66#[ cfg( feature = "async" ) ]
@@ -14,7 +14,7 @@ use crate::storage::{Assembler, RingBuffer};
1414use crate :: time:: { Duration , Instant } ;
1515use crate :: wire:: {
1616 IpAddress , IpEndpoint , IpListenEndpoint , IpProtocol , IpRepr , TcpControl , TcpRepr , TcpSeqNumber ,
17- TCP_HEADER_LEN ,
17+ TcpTimestampGenerator , TcpTimestampRepr , TCP_HEADER_LEN ,
1818} ;
1919
2020mod congestion;
@@ -482,6 +482,12 @@ pub struct Socket<'a> {
482482 /// The congestion control algorithm.
483483 congestion_controller : congestion:: AnyController ,
484484
485+ /// tsval generator - if some, tcp timestamp is enabled
486+ tsval_generator : Option < TcpTimestampGenerator > ,
487+
488+ /// 0 if not seen or timestamp not enabled
489+ last_remote_tsval : u32 ,
490+
485491 #[ cfg( feature = "async" ) ]
486492 rx_waker : WakerRegistration ,
487493 #[ cfg( feature = "async" ) ]
@@ -540,6 +546,8 @@ impl<'a> Socket<'a> {
540546 ack_delay_timer : AckDelayTimer :: Idle ,
541547 challenge_ack_timer : Instant :: from_secs ( 0 ) ,
542548 nagle : true ,
549+ tsval_generator : None ,
550+ last_remote_tsval : 0 ,
543551 congestion_controller : congestion:: AnyController :: new ( ) ,
544552
545553 #[ cfg( feature = "async" ) ]
@@ -549,6 +557,16 @@ impl<'a> Socket<'a> {
549557 }
550558 }
551559
560+ /// Enable or disable TCP Timestamp.
561+ pub fn set_tsval_generator ( & mut self , generator : Option < TcpTimestampGenerator > ) {
562+ self . tsval_generator = generator;
563+ }
564+
565+ /// Return whether TCP Timestamp is enabled.
566+ pub fn timestamp_enabled ( & self ) -> bool {
567+ self . tsval_generator . is_some ( )
568+ }
569+
552570 /// Set an algorithm for congestion control.
553571 ///
554572 /// `CongestionControl::None` indicates that no congestion control is applied.
@@ -1300,6 +1318,7 @@ impl<'a> Socket<'a> {
13001318 max_seg_size : None ,
13011319 sack_permitted : false ,
13021320 sack_ranges : [ None , None , None ] ,
1321+ timestamp : None ,
13031322 payload : & [ ] ,
13041323 } ;
13051324 let ip_reply_repr = IpRepr :: new (
@@ -1330,6 +1349,9 @@ impl<'a> Socket<'a> {
13301349
13311350 fn ack_reply ( & mut self , ip_repr : & IpRepr , repr : & TcpRepr ) -> ( IpRepr , TcpRepr < ' static > ) {
13321351 let ( mut ip_reply_repr, mut reply_repr) = Self :: reply ( ip_repr, repr) ;
1352+ reply_repr. timestamp = repr
1353+ . timestamp
1354+ . and_then ( |tcp_ts| tcp_ts. generate_reply ( self . tsval_generator ) ) ;
13331355
13341356 // From RFC 793:
13351357 // [...] an empty acknowledgment segment containing the current send-sequence number
@@ -1725,6 +1747,10 @@ impl<'a> Socket<'a> {
17251747 if self . remote_win_scale . is_none ( ) {
17261748 self . remote_win_shift = 0 ;
17271749 }
1750+ // Remote doesn't support timestamping, don't do it.
1751+ if repr. timestamp . is_none ( ) {
1752+ self . tsval_generator = None ;
1753+ }
17281754 self . set_state ( State :: SynReceived ) ;
17291755 self . timer . set_for_idle ( cx. now ( ) , self . keep_alive ) ;
17301756 }
@@ -1767,6 +1793,10 @@ impl<'a> Socket<'a> {
17671793 if self . remote_win_scale . is_none ( ) {
17681794 self . remote_win_shift = 0 ;
17691795 }
1796+ // Remote doesn't support timestamping, don't do it.
1797+ if repr. timestamp . is_none ( ) {
1798+ self . tsval_generator = None ;
1799+ }
17701800
17711801 self . set_state ( State :: Established ) ;
17721802 self . timer . set_for_idle ( cx. now ( ) , self . keep_alive ) ;
@@ -1954,6 +1984,11 @@ impl<'a> Socket<'a> {
19541984 }
19551985 }
19561986
1987+ // update last remote tsval
1988+ if let Some ( timestamp) = repr. timestamp {
1989+ self . last_remote_tsval = timestamp. tsval ;
1990+ }
1991+
19571992 let payload_len = payload. len ( ) ;
19581993 if payload_len == 0 {
19591994 return None ;
@@ -2246,6 +2281,10 @@ impl<'a> Socket<'a> {
22462281 max_seg_size : None ,
22472282 sack_permitted : false ,
22482283 sack_ranges : [ None , None , None ] ,
2284+ timestamp : TcpTimestampRepr :: generate_reply_with_tsval (
2285+ self . tsval_generator ,
2286+ self . last_remote_tsval ,
2287+ ) ,
22492288 payload : & [ ] ,
22502289 } ;
22512290
@@ -2574,6 +2613,7 @@ mod test {
25742613 max_seg_size : None ,
25752614 sack_permitted : false ,
25762615 sack_ranges : [ None , None , None ] ,
2616+ timestamp : None ,
25772617 payload : & [ ] ,
25782618 } ;
25792619 const _RECV_IP_TEMPL: IpRepr = IpReprIpvX ( IpvXRepr {
@@ -2594,6 +2634,7 @@ mod test {
25942634 max_seg_size : None ,
25952635 sack_permitted : false ,
25962636 sack_ranges : [ None , None , None ] ,
2637+ timestamp : None ,
25972638 payload : & [ ] ,
25982639 } ;
25992640
@@ -7429,4 +7470,239 @@ mod test {
74297470 s. set_congestion_control ( CongestionControl :: None ) ;
74307471 assert_eq ! ( s. congestion_control( ) , CongestionControl :: None ) ;
74317472 }
7473+
7474+ // =========================================================================================//
7475+ // Timestamp tests
7476+ // =========================================================================================//
7477+
7478+ #[ test]
7479+ fn test_tsval_established_connection ( ) {
7480+ let mut s = socket_established ( ) ;
7481+ s. set_tsval_generator ( Some ( || 1 ) ) ;
7482+
7483+ assert ! ( s. timestamp_enabled( ) ) ;
7484+
7485+ // First roundtrip after establishing.
7486+ s. send_slice ( b"abcdef" ) . unwrap ( ) ;
7487+ recv ! (
7488+ s,
7489+ [ TcpRepr {
7490+ seq_number: LOCAL_SEQ + 1 ,
7491+ ack_number: Some ( REMOTE_SEQ + 1 ) ,
7492+ payload: & b"abcdef" [ ..] ,
7493+ timestamp: Some ( TcpTimestampRepr :: new( 1 , 0 ) ) ,
7494+ ..RECV_TEMPL
7495+ } ]
7496+ ) ;
7497+ assert_eq ! ( s. tx_buffer. len( ) , 6 ) ;
7498+ send ! (
7499+ s,
7500+ TcpRepr {
7501+ seq_number: REMOTE_SEQ + 1 ,
7502+ ack_number: Some ( LOCAL_SEQ + 1 + 6 ) ,
7503+ timestamp: Some ( TcpTimestampRepr :: new( 500 , 1 ) ) ,
7504+ ..SEND_TEMPL
7505+ }
7506+ ) ;
7507+ assert_eq ! ( s. tx_buffer. len( ) , 0 ) ;
7508+ // Second roundtrip.
7509+ s. send_slice ( b"foobar" ) . unwrap ( ) ;
7510+ recv ! (
7511+ s,
7512+ [ TcpRepr {
7513+ seq_number: LOCAL_SEQ + 1 + 6 ,
7514+ ack_number: Some ( REMOTE_SEQ + 1 ) ,
7515+ payload: & b"foobar" [ ..] ,
7516+ timestamp: Some ( TcpTimestampRepr :: new( 1 , 500 ) ) ,
7517+ ..RECV_TEMPL
7518+ } ]
7519+ ) ;
7520+ send ! (
7521+ s,
7522+ TcpRepr {
7523+ seq_number: REMOTE_SEQ + 1 ,
7524+ ack_number: Some ( LOCAL_SEQ + 1 + 6 + 6 ) ,
7525+ ..SEND_TEMPL
7526+ }
7527+ ) ;
7528+ assert_eq ! ( s. tx_buffer. len( ) , 0 ) ;
7529+ }
7530+
7531+ #[ test]
7532+ fn test_tsval_disabled_in_remote_client ( ) {
7533+ let mut s = socket_listen ( ) ;
7534+ s. set_tsval_generator ( Some ( || 1 ) ) ;
7535+ assert ! ( s. timestamp_enabled( ) ) ;
7536+ send ! (
7537+ s,
7538+ TcpRepr {
7539+ control: TcpControl :: Syn ,
7540+ seq_number: REMOTE_SEQ ,
7541+ ack_number: None ,
7542+ ..SEND_TEMPL
7543+ }
7544+ ) ;
7545+ assert_eq ! ( s. state( ) , State :: SynReceived ) ;
7546+ assert_eq ! ( s. tuple, Some ( TUPLE ) ) ;
7547+ assert ! ( !s. timestamp_enabled( ) ) ;
7548+ recv ! (
7549+ s,
7550+ [ TcpRepr {
7551+ control: TcpControl :: Syn ,
7552+ seq_number: LOCAL_SEQ ,
7553+ ack_number: Some ( REMOTE_SEQ + 1 ) ,
7554+ max_seg_size: Some ( BASE_MSS ) ,
7555+ ..RECV_TEMPL
7556+ } ]
7557+ ) ;
7558+ send ! (
7559+ s,
7560+ TcpRepr {
7561+ seq_number: REMOTE_SEQ + 1 ,
7562+ ack_number: Some ( LOCAL_SEQ + 1 ) ,
7563+ ..SEND_TEMPL
7564+ }
7565+ ) ;
7566+ assert_eq ! ( s. state( ) , State :: Established ) ;
7567+ assert_eq ! ( s. local_seq_no, LOCAL_SEQ + 1 ) ;
7568+ assert_eq ! ( s. remote_seq_no, REMOTE_SEQ + 1 ) ;
7569+ }
7570+
7571+ #[ test]
7572+ fn test_tsval_disabled_in_local_server ( ) {
7573+ let mut s = socket_listen ( ) ;
7574+ // s.set_timestamp(false); // commented to alert if the default state changes
7575+ assert ! ( !s. timestamp_enabled( ) ) ;
7576+ send ! (
7577+ s,
7578+ TcpRepr {
7579+ control: TcpControl :: Syn ,
7580+ seq_number: REMOTE_SEQ ,
7581+ ack_number: None ,
7582+ timestamp: Some ( TcpTimestampRepr :: new( 500 , 0 ) ) ,
7583+ ..SEND_TEMPL
7584+ }
7585+ ) ;
7586+ assert_eq ! ( s. state( ) , State :: SynReceived ) ;
7587+ assert_eq ! ( s. tuple, Some ( TUPLE ) ) ;
7588+ assert ! ( !s. timestamp_enabled( ) ) ;
7589+ recv ! (
7590+ s,
7591+ [ TcpRepr {
7592+ control: TcpControl :: Syn ,
7593+ seq_number: LOCAL_SEQ ,
7594+ ack_number: Some ( REMOTE_SEQ + 1 ) ,
7595+ max_seg_size: Some ( BASE_MSS ) ,
7596+ ..RECV_TEMPL
7597+ } ]
7598+ ) ;
7599+ send ! (
7600+ s,
7601+ TcpRepr {
7602+ seq_number: REMOTE_SEQ + 1 ,
7603+ ack_number: Some ( LOCAL_SEQ + 1 ) ,
7604+ ..SEND_TEMPL
7605+ }
7606+ ) ;
7607+ assert_eq ! ( s. state( ) , State :: Established ) ;
7608+ assert_eq ! ( s. local_seq_no, LOCAL_SEQ + 1 ) ;
7609+ assert_eq ! ( s. remote_seq_no, REMOTE_SEQ + 1 ) ;
7610+ }
7611+
7612+ #[ test]
7613+ fn test_tsval_disabled_in_remote_server ( ) {
7614+ let mut s = socket ( ) ;
7615+ s. set_tsval_generator ( Some ( || 1 ) ) ;
7616+ assert ! ( s. timestamp_enabled( ) ) ;
7617+ s. local_seq_no = LOCAL_SEQ ;
7618+ s. socket
7619+ . connect ( & mut s. cx , REMOTE_END , LOCAL_END . port )
7620+ . unwrap ( ) ;
7621+ assert_eq ! ( s. tuple, Some ( TUPLE ) ) ;
7622+ recv ! (
7623+ s,
7624+ [ TcpRepr {
7625+ control: TcpControl :: Syn ,
7626+ seq_number: LOCAL_SEQ ,
7627+ ack_number: None ,
7628+ max_seg_size: Some ( BASE_MSS ) ,
7629+ window_scale: Some ( 0 ) ,
7630+ sack_permitted: true ,
7631+ timestamp: Some ( TcpTimestampRepr :: new( 1 , 0 ) ) ,
7632+ ..RECV_TEMPL
7633+ } ]
7634+ ) ;
7635+ send ! (
7636+ s,
7637+ TcpRepr {
7638+ control: TcpControl :: Syn ,
7639+ seq_number: REMOTE_SEQ ,
7640+ ack_number: Some ( LOCAL_SEQ + 1 ) ,
7641+ max_seg_size: Some ( BASE_MSS - 80 ) ,
7642+ window_scale: Some ( 0 ) ,
7643+ timestamp: None ,
7644+ ..SEND_TEMPL
7645+ }
7646+ ) ;
7647+ assert ! ( !s. timestamp_enabled( ) ) ;
7648+ s. send_slice ( b"abcdef" ) . unwrap ( ) ;
7649+ recv ! (
7650+ s,
7651+ [ TcpRepr {
7652+ seq_number: LOCAL_SEQ + 1 ,
7653+ ack_number: Some ( REMOTE_SEQ + 1 ) ,
7654+ payload: & b"abcdef" [ ..] ,
7655+ timestamp: None ,
7656+ ..RECV_TEMPL
7657+ } ]
7658+ ) ;
7659+ }
7660+
7661+ #[ test]
7662+ fn test_tsval_disabled_in_local_client ( ) {
7663+ let mut s = socket ( ) ;
7664+ // s.set_timestamp(false); // commented to alert if the default state changes
7665+ assert ! ( !s. timestamp_enabled( ) ) ;
7666+ s. local_seq_no = LOCAL_SEQ ;
7667+ s. socket
7668+ . connect ( & mut s. cx , REMOTE_END , LOCAL_END . port )
7669+ . unwrap ( ) ;
7670+ assert_eq ! ( s. tuple, Some ( TUPLE ) ) ;
7671+ recv ! (
7672+ s,
7673+ [ TcpRepr {
7674+ control: TcpControl :: Syn ,
7675+ seq_number: LOCAL_SEQ ,
7676+ ack_number: None ,
7677+ max_seg_size: Some ( BASE_MSS ) ,
7678+ window_scale: Some ( 0 ) ,
7679+ sack_permitted: true ,
7680+ ..RECV_TEMPL
7681+ } ]
7682+ ) ;
7683+ send ! (
7684+ s,
7685+ TcpRepr {
7686+ control: TcpControl :: Syn ,
7687+ seq_number: REMOTE_SEQ ,
7688+ ack_number: Some ( LOCAL_SEQ + 1 ) ,
7689+ max_seg_size: Some ( BASE_MSS - 80 ) ,
7690+ window_scale: Some ( 0 ) ,
7691+ timestamp: Some ( TcpTimestampRepr :: new( 500 , 0 ) ) ,
7692+ ..SEND_TEMPL
7693+ }
7694+ ) ;
7695+ assert ! ( !s. timestamp_enabled( ) ) ;
7696+ s. send_slice ( b"abcdef" ) . unwrap ( ) ;
7697+ recv ! (
7698+ s,
7699+ [ TcpRepr {
7700+ seq_number: LOCAL_SEQ + 1 ,
7701+ ack_number: Some ( REMOTE_SEQ + 1 ) ,
7702+ payload: & b"abcdef" [ ..] ,
7703+ timestamp: None ,
7704+ ..RECV_TEMPL
7705+ } ]
7706+ ) ;
7707+ }
74327708}
0 commit comments