]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[tcp] Update ts_recent whenever window is advanced
authorMichael Brown <mcb30@ipxe.org>
Sat, 2 Apr 2011 23:37:27 +0000 (00:37 +0100)
committerMichael Brown <mcb30@ipxe.org>
Sat, 2 Apr 2011 23:44:22 +0000 (00:44 +0100)
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>
src/net/tcp.c

index d9529882d1aa210bd5ddf38bb5f3b8e369f7a771..fbcf279e160737bb35b940e5068ea8bf2a688f99 100644 (file)
@@ -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 ) );