Skip to content

Commit b38faa5

Browse files
committed
tcp: start retransmit on first data sent, fix FIN retransmit in CLOSING.
- RFC 6298 says we should start the retransmit timer as soon as we send a segment that has data. We were starting it on the *last* segment instead. - Simplified logic with set_for_idle, it's now uniform across all tcp states. - Fix FIN retransmits not being sent in CLOSED state.
1 parent 91661ee commit b38faa5

File tree

1 file changed

+111
-37
lines changed

1 file changed

+111
-37
lines changed

src/socket/tcp.rs

Lines changed: 111 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,7 +1796,6 @@ impl<'a> Socket<'a> {
17961796
// ACK packets in the SYN-RECEIVED state change it to ESTABLISHED.
17971797
(State::SynReceived, TcpControl::None) => {
17981798
self.set_state(State::Established);
1799-
self.timer.set_for_idle(cx.now(), self.keep_alive);
18001799
}
18011800

18021801
// FIN packets in the SYN-RECEIVED state change it to CLOSE-WAIT.
@@ -1806,7 +1805,6 @@ impl<'a> Socket<'a> {
18061805
self.remote_seq_no += 1;
18071806
self.rx_fin_received = true;
18081807
self.set_state(State::CloseWait);
1809-
self.timer.set_for_idle(cx.now(), self.keep_alive);
18101808
}
18111809

18121810
// SYN|ACK packets in the SYN-SENT state change it to ESTABLISHED.
@@ -1847,26 +1845,15 @@ impl<'a> Socket<'a> {
18471845
} else {
18481846
self.set_state(State::SynReceived);
18491847
}
1850-
self.timer.set_for_idle(cx.now(), self.keep_alive);
18511848
}
18521849

1853-
// RFC 6298: (5.2) ACK of all outstanding data turn off the retransmit timer.
1854-
// (5.3) ACK of new data in ESTABLISHED state restart the retransmit timer.
1855-
(State::Established, TcpControl::None) => {
1856-
if ack_all {
1857-
self.timer.set_for_idle(cx.now(), self.keep_alive);
1858-
} else if ack_len > 0 {
1859-
self.timer
1860-
.set_for_retransmit(cx.now(), self.rtte.retransmission_timeout());
1861-
}
1862-
}
1850+
(State::Established, TcpControl::None) => {}
18631851

18641852
// FIN packets in ESTABLISHED state indicate the remote side has closed.
18651853
(State::Established, TcpControl::Fin) => {
18661854
self.remote_seq_no += 1;
18671855
self.rx_fin_received = true;
18681856
self.set_state(State::CloseWait);
1869-
self.timer.set_for_idle(cx.now(), self.keep_alive);
18701857
}
18711858

18721859
// ACK packets in FIN-WAIT-1 state change it to FIN-WAIT-2, if we've already
@@ -1875,9 +1862,6 @@ impl<'a> Socket<'a> {
18751862
if ack_of_fin {
18761863
self.set_state(State::FinWait2);
18771864
}
1878-
if ack_all {
1879-
self.timer.set_for_idle(cx.now(), self.keep_alive);
1880-
}
18811865
}
18821866

18831867
// FIN packets in FIN-WAIT-1 state change it to CLOSING, or to TIME-WAIT
@@ -1890,14 +1874,10 @@ impl<'a> Socket<'a> {
18901874
self.timer.set_for_close(cx.now());
18911875
} else {
18921876
self.set_state(State::Closing);
1893-
self.timer.set_for_idle(cx.now(), self.keep_alive);
18941877
}
18951878
}
18961879

1897-
// Data packets in FIN-WAIT-2 reset the idle timer.
1898-
(State::FinWait2, TcpControl::None) => {
1899-
self.timer.set_for_idle(cx.now(), self.keep_alive);
1900-
}
1880+
(State::FinWait2, TcpControl::None) => {}
19011881

19021882
// FIN packets in FIN-WAIT-2 state change it to TIME-WAIT.
19031883
(State::FinWait2, TcpControl::Fin) => {
@@ -1912,24 +1892,17 @@ impl<'a> Socket<'a> {
19121892
if ack_of_fin {
19131893
self.set_state(State::TimeWait);
19141894
self.timer.set_for_close(cx.now());
1915-
} else {
1916-
self.timer.set_for_idle(cx.now(), self.keep_alive);
19171895
}
19181896
}
19191897

1920-
// ACK packets in CLOSE-WAIT state reset the retransmit timer.
1921-
(State::CloseWait, TcpControl::None) => {
1922-
self.timer.set_for_idle(cx.now(), self.keep_alive);
1923-
}
1898+
(State::CloseWait, TcpControl::None) => {}
19241899

19251900
// ACK packets in LAST-ACK state change it to CLOSED.
19261901
(State::LastAck, TcpControl::None) => {
19271902
if ack_of_fin {
19281903
// Clear the remote endpoint, or we'll send an RST there.
19291904
self.set_state(State::Closed);
19301905
self.tuple = None;
1931-
} else {
1932-
self.timer.set_for_idle(cx.now(), self.keep_alive);
19331906
}
19341907
}
19351908

@@ -2040,6 +2013,25 @@ impl<'a> Socket<'a> {
20402013
self.last_remote_tsval = timestamp.tsval;
20412014
}
20422015

2016+
// update timers.
2017+
match self.timer {
2018+
Timer::Retransmit { .. } | Timer::FastRetransmit => {
2019+
if ack_all {
2020+
// RFC 6298: (5.2) ACK of all outstanding data turn off the retransmit timer.
2021+
self.timer.set_for_idle(cx.now(), self.keep_alive);
2022+
} else if ack_len > 0 {
2023+
// (5.3) ACK of new data in ESTABLISHED state restart the retransmit timer.
2024+
let rto = self.rtte.retransmission_timeout();
2025+
self.timer.set_for_retransmit(cx.now(), rto);
2026+
}
2027+
}
2028+
Timer::Idle { .. } => {
2029+
// any packet on idle refresh the keepalive timer.
2030+
self.timer.set_for_idle(cx.now(), self.keep_alive);
2031+
}
2032+
_ => {}
2033+
}
2034+
20432035
let payload_len = payload.len();
20442036
if payload_len == 0 {
20452037
return None;
@@ -2537,12 +2529,12 @@ impl<'a> Socket<'a> {
25372529
.post_transmit(cx.now(), repr.segment_len());
25382530
}
25392531

2540-
if !self.seq_to_transmit(cx) && repr.segment_len() > 0 && !self.timer.is_retransmit() {
2541-
// RFC 6298: (5.1) If we've transmitted all data we could (and there was
2542-
// something at all, data or flag, to transmit, not just an ACK), start the
2543-
// retransmit timer if it is not already running.
2544-
self.timer
2545-
.set_for_retransmit(cx.now(), self.rtte.retransmission_timeout());
2532+
if repr.segment_len() > 0 && !self.timer.is_retransmit() {
2533+
// RFC 6298 (5.1) Every time a packet containing data is sent (including a
2534+
// retransmission), if the timer is not running, start it running
2535+
// so that it will expire after RTO seconds.
2536+
let rto = self.rtte.retransmission_timeout();
2537+
self.timer.set_for_retransmit(cx.now(), rto);
25462538
}
25472539

25482540
if self.state == State::Closed {
@@ -2812,7 +2804,7 @@ mod test {
28122804
Ok(())
28132805
});
28142806
if fail {
2815-
panic!("Should not send a packet")
2807+
panic!("Should not send a packet")
28162808
}
28172809

28182810
assert_eq!(result, Ok(()))
@@ -2955,6 +2947,9 @@ mod test {
29552947
s.state = State::Closing;
29562948
s.remote_last_seq = LOCAL_SEQ + 1 + 1;
29572949
s.remote_seq_no = REMOTE_SEQ + 1 + 1;
2950+
s.timer = Timer::Retransmit {
2951+
expires_at: Instant::from_millis_const(1000),
2952+
};
29582953
s
29592954
}
29602955

@@ -6529,6 +6524,85 @@ mod test {
65296524
recv_nothing!(s, time 5000);
65306525
}
65316526

6527+
#[test]
6528+
fn test_retransmit_fin() {
6529+
let mut s = socket_established();
6530+
s.close();
6531+
recv!(s, time 0, Ok(TcpRepr {
6532+
control: TcpControl::Fin,
6533+
seq_number: LOCAL_SEQ + 1,
6534+
ack_number: Some(REMOTE_SEQ + 1),
6535+
..RECV_TEMPL
6536+
}));
6537+
6538+
recv_nothing!(s, time 999);
6539+
recv!(s, time 1000, Ok(TcpRepr {
6540+
control: TcpControl::Fin,
6541+
seq_number: LOCAL_SEQ + 1,
6542+
ack_number: Some(REMOTE_SEQ + 1),
6543+
..RECV_TEMPL
6544+
}));
6545+
}
6546+
6547+
#[test]
6548+
fn test_retransmit_fin_wait() {
6549+
let mut s = socket_fin_wait_1();
6550+
// we send FIN
6551+
recv!(
6552+
s,
6553+
[TcpRepr {
6554+
control: TcpControl::Fin,
6555+
seq_number: LOCAL_SEQ + 1,
6556+
ack_number: Some(REMOTE_SEQ + 1),
6557+
..RECV_TEMPL
6558+
}]
6559+
);
6560+
// remote also sends FIN, does NOT ack ours.
6561+
send!(
6562+
s,
6563+
TcpRepr {
6564+
control: TcpControl::Fin,
6565+
seq_number: REMOTE_SEQ + 1,
6566+
ack_number: Some(LOCAL_SEQ + 1),
6567+
..SEND_TEMPL
6568+
}
6569+
);
6570+
// we ack it
6571+
recv!(
6572+
s,
6573+
[TcpRepr {
6574+
control: TcpControl::None,
6575+
seq_number: LOCAL_SEQ + 2,
6576+
ack_number: Some(REMOTE_SEQ + 2),
6577+
..RECV_TEMPL
6578+
}]
6579+
);
6580+
6581+
// we haven't got an ACK for our FIN, we should retransmit.
6582+
recv_nothing!(s, time 999);
6583+
recv!(
6584+
s,
6585+
time 1000,
6586+
[TcpRepr {
6587+
control: TcpControl::Fin,
6588+
seq_number: LOCAL_SEQ + 1,
6589+
ack_number: Some(REMOTE_SEQ + 2),
6590+
..RECV_TEMPL
6591+
}]
6592+
);
6593+
recv_nothing!(s, time 2999);
6594+
recv!(
6595+
s,
6596+
time 3000,
6597+
[TcpRepr {
6598+
control: TcpControl::Fin,
6599+
seq_number: LOCAL_SEQ + 1,
6600+
ack_number: Some(REMOTE_SEQ + 2),
6601+
..RECV_TEMPL
6602+
}]
6603+
);
6604+
}
6605+
65326606
// =========================================================================================//
65336607
// Tests for window management.
65346608
// =========================================================================================//

0 commit comments

Comments
 (0)