summaryrefslogtreecommitdiffstats
path: root/src/net/tcp.c
diff options
context:
space:
mode:
authorMichael Brown2011-04-03 01:37:27 +0200
committerMichael Brown2011-04-03 01:44:22 +0200
commitc4369eb6c2d14e92c7b820be14da25afad456a5e (patch)
treeeff33efa5a8a4edae4fde3aeb89c6b6bada0fb6d /src/net/tcp.c
parent[cmdline] Fix "isset" command (diff)
downloadipxe-c4369eb6c2d14e92c7b820be14da25afad456a5e.tar.gz
ipxe-c4369eb6c2d14e92c7b820be14da25afad456a5e.tar.xz
ipxe-c4369eb6c2d14e92c7b820be14da25afad456a5e.zip
[tcp] Update ts_recent whenever window is advanced
Commit 3f442d3 ("[tcp] Record ts_recent on first received packet") failed to achieve its stated intention. Fix this (and reduce the code size) by moving the ts_recent update to tcp_rx_seq(). This is the code responsible for advancing the window, called by both tcp_rx_syn() and tcp_rx_data(), and so the window check is now redundant. Reported-by: Frank Weed <zorbustheknight@gmail.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/net/tcp.c')
-rw-r--r--src/net/tcp.c31
1 files changed, 22 insertions, 9 deletions
diff --git a/src/net/tcp.c b/src/net/tcp.c
index d9529882..fbcf279e 100644
--- a/src/net/tcp.c
+++ b/src/net/tcp.c
@@ -74,7 +74,13 @@ struct tcp_connection {
* Equivalent to RCV.WND in RFC 793 terminology.
*/
uint32_t rcv_win;
- /** Most recent received timestamp
+ /** Received timestamp value
+ *
+ * Updated when a packet is received; copied to ts_recent when
+ * the window is advanced.
+ */
+ uint32_t ts_val;
+ /** Most recent received timestamp that advanced the window
*
* Equivalent to TS.Recent in RFC 1323 terminology.
*/
@@ -740,12 +746,24 @@ static void tcp_rx_opts ( struct tcp_connection *tcp, const void *data,
* @v seq_len Sequence space length to consume
*/
static void tcp_rx_seq ( struct tcp_connection *tcp, uint32_t seq_len ) {
+
+ /* Sanity check */
+ assert ( seq_len > 0 );
+
+ /* Update acknowledgement number */
tcp->rcv_ack += seq_len;
+
+ /* Update window */
if ( tcp->rcv_win > seq_len ) {
tcp->rcv_win -= seq_len;
} else {
tcp->rcv_win = 0;
}
+
+ /* Update timestamp */
+ tcp->ts_recent = tcp->ts_val;
+
+ /* Mark ACK as pending */
tcp->flags |= TCP_ACK_PENDING;
}
@@ -1060,7 +1078,6 @@ static int tcp_rx ( struct io_buffer *iobuf,
struct tcp_options options;
size_t hlen;
uint16_t csum;
- uint32_t start_seq;
uint32_t seq;
uint32_t ack;
uint32_t win;
@@ -1100,12 +1117,14 @@ static int tcp_rx ( struct io_buffer *iobuf,
/* Parse parameters from header and strip header */
tcp = tcp_demux ( ntohs ( tcphdr->dest ) );
- seq = start_seq = ntohl ( tcphdr->seq );
+ seq = ntohl ( tcphdr->seq );
ack = ntohl ( tcphdr->ack );
win = ntohs ( tcphdr->win );
flags = tcphdr->flags;
tcp_rx_opts ( tcp, ( ( ( void * ) tcphdr ) + sizeof ( *tcphdr ) ),
( hlen - sizeof ( *tcphdr ) ), &options );
+ if ( options.tsopt )
+ tcp->ts_val = ntohl ( options.tsopt->tsval );
iob_pull ( iobuf, hlen );
len = iob_len ( iobuf );
seq_len = ( len + ( ( flags & TCP_SYN ) ? 1 : 0 ) +
@@ -1152,12 +1171,6 @@ static int tcp_rx ( struct io_buffer *iobuf,
goto discard;
}
- /* Update timestamp, if applicable */
- if ( options.tsopt &&
- tcp_in_window ( tcp->rcv_ack, start_seq, seq_len ) ) {
- tcp->ts_recent = ntohl ( options.tsopt->tsval );
- }
-
/* Enqueue received data */
tcp_rx_enqueue ( tcp, seq, flags, iob_disown ( iobuf ) );