=== TCP Out-Of-Order Receving handling === It's a little tricky about ''already_rcvd'' (''uint32_t''). if ''tcp->rcv_ack'' ''=='' ''seq'' : Normal case * ''already_rcvd'' = 0 if ''tcp->rcv_ack'' ''>'' ''seq'' : Segment contains previous data * ''already_rcvd'' = small positive number if ''tcp->rcv_ack'' ''<'' ''seq'' : Out-Of-Order future data * ''already_rcvd'' = **VERY LARGE** positive number if ( already_rcvd >= len ) { Acctually have two meanings: * The segment contains previous data, and **ALL** the data already received. * The segment is Out-Of-Order /** * Handle TCP received data * * @v tcp TCP connection * @v seq SEQ value (in host-endian order) * @v iobuf I/O buffer * @ret rc Return status code * * This function takes ownership of the I/O buffer. */ static int tcp_rx_data ( struct tcp_connection *tcp, uint32_t seq, struct io_buffer *iobuf ) { uint32_t already_rcvd; uint32_t len; int rc; /* Ignore duplicate or out-of-order data */ already_rcvd = ( tcp->rcv_ack - seq ); len = iob_len ( iobuf ); if ( already_rcvd >= len ) { free_iob ( iobuf ); return 0; } iob_pull ( iobuf, already_rcvd ); len -= already_rcvd; /* 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; }