=== 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;
}