Skip to content

Commit 358cf77

Browse files
tomDev5cavivie
authored andcommitted
TCP Timestamp option support
1 parent 57b1dd4 commit 358cf77

File tree

4 files changed

+353
-4
lines changed

4 files changed

+353
-4
lines changed

src/iface/interface/tests/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ pub fn tcp_not_accepted() {
169169
max_seg_size: None,
170170
sack_permitted: false,
171171
sack_ranges: [None, None, None],
172+
timestamp: None,
172173
payload: &[],
173174
};
174175

@@ -212,6 +213,7 @@ pub fn tcp_not_accepted() {
212213
max_seg_size: None,
213214
sack_permitted: false,
214215
sack_ranges: [None, None, None],
216+
timestamp: None,
215217
payload: &[],
216218
})
217219
))

src/socket/tcp.rs

Lines changed: 279 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
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

55
use core::fmt::Display;
66
#[cfg(feature = "async")]
@@ -14,7 +14,7 @@ use crate::storage::{Assembler, RingBuffer};
1414
use crate::time::{Duration, Instant};
1515
use crate::wire::{
1616
IpAddress, IpEndpoint, IpListenEndpoint, IpProtocol, IpRepr, TcpControl, TcpRepr, TcpSeqNumber,
17-
TCP_HEADER_LEN,
17+
TcpTimestampGenerator, TcpTimestampRepr, TCP_HEADER_LEN,
1818
};
1919

2020
mod 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

Comments
 (0)