TCP Out-Of-Order Receving handling

It's a little tricky about already_rcvd (uint32_t).

if tcp→rcv_ack == seq : Normal case

if tcp→rcv_ack > seq : Segment contains previous data

if tcp→rcv_ack < seq : Out-Of-Order future data

 if ( already_rcvd >= len ) { 

Acctually have two meanings:

/**
 * 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;
}