Browse Source

[tcp] Update received sequence number before delivering received data

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>
tags/v1.20.1
Michael Brown 14 years ago
parent
commit
9ff8229693
1 changed files with 10 additions and 8 deletions
  1. 10
    8
      src/net/tcp.c

+ 10
- 8
src/net/tcp.c View File

@@ -702,13 +702,13 @@ static int tcp_rx_syn ( struct tcp_connection *tcp, uint32_t seq,
702 702
 	if ( ( tcp->rcv_ack - seq ) > 0 )
703 703
 		return 0;
704 704
 
705
+	/* Acknowledge SYN */
706
+	tcp_rx_seq ( tcp, 1 );
707
+
705 708
 	/* Mark SYN as received and start sending ACKs with each packet */
706 709
 	tcp->tcp_state |= ( TCP_STATE_SENT ( TCP_ACK ) |
707 710
 			    TCP_STATE_RCVD ( TCP_SYN ) );
708 711
 
709
-	/* Acknowledge SYN */
710
-	tcp_rx_seq ( tcp, 1 );
711
-
712 712
 	return 0;
713 713
 }
714 714
 
@@ -809,6 +809,9 @@ static int tcp_rx_data ( struct tcp_connection *tcp, uint32_t seq,
809 809
 	iob_pull ( iobuf, already_rcvd );
810 810
 	len -= already_rcvd;
811 811
 
812
+	/* Acknowledge new data */
813
+	tcp_rx_seq ( tcp, len );
814
+
812 815
 	/* Deliver data to application */
813 816
 	if ( ( rc = xfer_deliver_iob ( &tcp->xfer, iobuf ) ) != 0 ) {
814 817
 		DBGC ( tcp, "TCP %p could not deliver %08x..%08x: %s\n",
@@ -816,9 +819,6 @@ static int tcp_rx_data ( struct tcp_connection *tcp, uint32_t seq,
816 819
 		return rc;
817 820
 	}
818 821
 
819
-	/* Acknowledge new data */
820
-	tcp_rx_seq ( tcp, len );
821
-
822 822
 	return 0;
823 823
 }
824 824
 
@@ -835,10 +835,12 @@ static int tcp_rx_fin ( struct tcp_connection *tcp, uint32_t seq ) {
835 835
 	if ( ( tcp->rcv_ack - seq ) > 0 )
836 836
 		return 0;
837 837
 
838
-	/* Mark FIN as received and acknowledge it */
839
-	tcp->tcp_state |= TCP_STATE_RCVD ( TCP_FIN );
838
+	/* Acknowledge FIN */
840 839
 	tcp_rx_seq ( tcp, 1 );
841 840
 
841
+	/* Mark FIN as received */
842
+	tcp->tcp_state |= TCP_STATE_RCVD ( TCP_FIN );
843
+
842 844
 	/* Close connection */
843 845
 	tcp_close ( tcp, 0 );
844 846
 

Loading…
Cancel
Save