Skip to content

Commit

Permalink
[tcp] Update received sequence number before delivering received data
Browse files Browse the repository at this point in the history
iPXE currently updates the TCP sequence number after delivering the
data to the application via xfer_deliver_iob().  If the application
responds to the received data by transmitting more data, this would
result in a stale ACK number appearing in the transmitted packet,
which potentially causes retransmissions and also gives the
undesirable appearance of violating causality (by sending a response
to a message that we claim not to have yet received).

Reported-by: Guo-Fu Tseng <cooldavid@cooldavid.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed May 21, 2010
1 parent 13dfe2c commit 9ff8229
Showing 1 changed file with 10 additions and 8 deletions.
18 changes: 10 additions & 8 deletions src/net/tcp.c
Expand Up @@ -702,13 +702,13 @@ static int tcp_rx_syn ( struct tcp_connection *tcp, uint32_t seq,
if ( ( tcp->rcv_ack - seq ) > 0 )
return 0;

/* Acknowledge SYN */
tcp_rx_seq ( tcp, 1 );

/* Mark SYN as received and start sending ACKs with each packet */
tcp->tcp_state |= ( TCP_STATE_SENT ( TCP_ACK ) |
TCP_STATE_RCVD ( TCP_SYN ) );

/* Acknowledge SYN */
tcp_rx_seq ( tcp, 1 );

return 0;
}

Expand Down Expand Up @@ -809,16 +809,16 @@ static int tcp_rx_data ( struct tcp_connection *tcp, uint32_t seq,
iob_pull ( iobuf, already_rcvd );
len -= already_rcvd;

/* Acknowledge new data */
tcp_rx_seq ( tcp, len );

/* Deliver data to application */
if ( ( rc = xfer_deliver_iob ( &tcp->xfer, iobuf ) ) != 0 ) {
DBGC ( tcp, "TCP %p could not deliver %08x..%08x: %s\n",
tcp, seq, ( seq + len ), strerror ( rc ) );
return rc;
}

/* Acknowledge new data */
tcp_rx_seq ( tcp, len );

return 0;
}

Expand All @@ -835,10 +835,12 @@ static int tcp_rx_fin ( struct tcp_connection *tcp, uint32_t seq ) {
if ( ( tcp->rcv_ack - seq ) > 0 )
return 0;

/* Mark FIN as received and acknowledge it */
tcp->tcp_state |= TCP_STATE_RCVD ( TCP_FIN );
/* Acknowledge FIN */
tcp_rx_seq ( tcp, 1 );

/* Mark FIN as received */
tcp->tcp_state |= TCP_STATE_RCVD ( TCP_FIN );

/* Close connection */
tcp_close ( tcp, 0 );

Expand Down

0 comments on commit 9ff8229

Please sign in to comment.