Receive the TCP MSS option and act on it.
This commit is contained in:
parent
bc1d65ea89
commit
d6b7623c37
|
@ -245,6 +245,8 @@ pub struct TcpSocket<'a> {
|
||||||
/// The speculative remote window size.
|
/// The speculative remote window size.
|
||||||
/// I.e. the actual remote window size minus the count of in-flight octets.
|
/// I.e. the actual remote window size minus the count of in-flight octets.
|
||||||
remote_win_len: usize,
|
remote_win_len: usize,
|
||||||
|
/// The maximum number of data octets that the remote side may receive.
|
||||||
|
remote_mss: usize,
|
||||||
retransmit: Retransmit,
|
retransmit: Retransmit,
|
||||||
rx_buffer: SocketBuffer<'a>,
|
rx_buffer: SocketBuffer<'a>,
|
||||||
tx_buffer: SocketBuffer<'a>,
|
tx_buffer: SocketBuffer<'a>,
|
||||||
|
@ -271,6 +273,7 @@ impl<'a> TcpSocket<'a> {
|
||||||
remote_last_seq: TcpSeqNumber(0),
|
remote_last_seq: TcpSeqNumber(0),
|
||||||
remote_last_ack: TcpSeqNumber(0),
|
remote_last_ack: TcpSeqNumber(0),
|
||||||
remote_win_len: 0,
|
remote_win_len: 0,
|
||||||
|
remote_mss: 536,
|
||||||
retransmit: Retransmit::new(),
|
retransmit: Retransmit::new(),
|
||||||
tx_buffer: tx_buffer.into(),
|
tx_buffer: tx_buffer.into(),
|
||||||
rx_buffer: rx_buffer.into(),
|
rx_buffer: rx_buffer.into(),
|
||||||
|
@ -688,7 +691,8 @@ impl<'a> TcpSocket<'a> {
|
||||||
|
|
||||||
// SYN packets in the LISTEN state change it to SYN-RECEIVED.
|
// SYN packets in the LISTEN state change it to SYN-RECEIVED.
|
||||||
(State::Listen, TcpRepr {
|
(State::Listen, TcpRepr {
|
||||||
src_port, dst_port, control: TcpControl::Syn, seq_number, ack_number: None, ..
|
src_port, dst_port, control: TcpControl::Syn, seq_number, ack_number: None,
|
||||||
|
max_seg_size, ..
|
||||||
}) => {
|
}) => {
|
||||||
net_trace!("[{}]{}: received SYN",
|
net_trace!("[{}]{}: received SYN",
|
||||||
self.debug_id, self.local_endpoint);
|
self.debug_id, self.local_endpoint);
|
||||||
|
@ -698,6 +702,9 @@ impl<'a> TcpSocket<'a> {
|
||||||
self.local_seq_no = TcpSeqNumber(-seq_number.0);
|
self.local_seq_no = TcpSeqNumber(-seq_number.0);
|
||||||
self.remote_last_seq = self.local_seq_no + 1;
|
self.remote_last_seq = self.local_seq_no + 1;
|
||||||
self.remote_seq_no = seq_number + 1;
|
self.remote_seq_no = seq_number + 1;
|
||||||
|
if let Some(max_seg_size) = max_seg_size {
|
||||||
|
self.remote_mss = max_seg_size as usize
|
||||||
|
}
|
||||||
self.set_state(State::SynReceived);
|
self.set_state(State::SynReceived);
|
||||||
self.retransmit.reset();
|
self.retransmit.reset();
|
||||||
}
|
}
|
||||||
|
@ -897,8 +904,8 @@ impl<'a> TcpSocket<'a> {
|
||||||
let mut size = self.tx_buffer.len();
|
let mut size = self.tx_buffer.len();
|
||||||
// Clamp to remote window length.
|
// Clamp to remote window length.
|
||||||
if size > self.remote_win_len { size = self.remote_win_len }
|
if size > self.remote_win_len { size = self.remote_win_len }
|
||||||
// Clamp to MSS. Currently we only support the default MSS value.
|
// Clamp to MSS.
|
||||||
if size > 536 { size = 536 }
|
if size > self.remote_mss { size = self.remote_mss }
|
||||||
// Extract data from the buffer. This may return less than what we want,
|
// Extract data from the buffer. This may return less than what we want,
|
||||||
// in case it's not possible to extract a contiguous slice.
|
// in case it's not possible to extract a contiguous slice.
|
||||||
let offset = self.remote_last_seq - self.local_seq_no;
|
let offset = self.remote_last_seq - self.local_seq_no;
|
||||||
|
@ -2248,4 +2255,37 @@ mod test {
|
||||||
..RECV_TEMPL
|
..RECV_TEMPL
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_maximum_segment_size() {
|
||||||
|
let mut s = socket_listen();
|
||||||
|
s.tx_buffer = SocketBuffer::new(vec![0; 32767]);
|
||||||
|
send!(s, TcpRepr {
|
||||||
|
control: TcpControl::Syn,
|
||||||
|
seq_number: REMOTE_SEQ,
|
||||||
|
ack_number: None,
|
||||||
|
max_seg_size: Some(1000),
|
||||||
|
..SEND_TEMPL
|
||||||
|
});
|
||||||
|
recv!(s, [TcpRepr {
|
||||||
|
control: TcpControl::Syn,
|
||||||
|
seq_number: LOCAL_SEQ,
|
||||||
|
ack_number: Some(REMOTE_SEQ + 1),
|
||||||
|
max_seg_size: Some(1480),
|
||||||
|
..RECV_TEMPL
|
||||||
|
}]);
|
||||||
|
send!(s, TcpRepr {
|
||||||
|
seq_number: REMOTE_SEQ + 1,
|
||||||
|
ack_number: Some(LOCAL_SEQ + 1),
|
||||||
|
window_len: 32767,
|
||||||
|
..SEND_TEMPL
|
||||||
|
});
|
||||||
|
s.send_slice(&[0; 1200][..]).unwrap();
|
||||||
|
recv!(s, [TcpRepr {
|
||||||
|
seq_number: LOCAL_SEQ + 1,
|
||||||
|
ack_number: Some(REMOTE_SEQ + 1),
|
||||||
|
payload: &[0; 1000][..],
|
||||||
|
..RECV_TEMPL
|
||||||
|
}])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue