iPXE
Functions
tcpip.h File Reference

Transport-network layer interface. More...

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
uint16_t tcpip_continue_chksum (uint16_t partial, const void *data, size_t len)
 Calculate continued TCP/IP checkum.

Detailed Description

Transport-network layer interface.

Definition in file tcpip.h.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
uint16_t tcpip_continue_chksum ( uint16_t  partial,
const void *  data,
size_t  len 
)

Calculate continued TCP/IP checkum.

Parameters:
partialChecksum of already-summed data, in network byte order
dataData buffer
lenLength of data buffer
Return values:
cksumUpdated checksum, in network byte order

Definition at line 45 of file x86_tcpip.c.

References __asm__(), ULONG_MAX, and x86_tcpip_loop_end.

Referenced by icmpv6_rx(), ipv4_pshdr_chksum(), ipv6_pshdr_chksum(), tcp_rx(), tcpip_chksum(), tcpip_okx(), tcpip_random_okx(), and udp_rx().

                                              {
        unsigned long sum = ( ( ~partial ) & 0xffff );
        unsigned long initial_word_count;
        unsigned long loop_count;
        unsigned long loop_partial_count;
        unsigned long final_word_count;
        unsigned long final_byte;
        unsigned long discard_S;
        unsigned long discard_c;
        unsigned long discard_a;
        unsigned long discard_r1;
        unsigned long discard_r2;

        /* Calculate number of initial 16-bit words required to bring
         * the main loop into alignment.  (We don't care about the
         * speed for data aligned to less than 16 bits, since this
         * situation won't occur in practice.)
         */
        if ( len >= sizeof ( sum ) ) {
                initial_word_count = ( ( -( ( intptr_t ) data ) &
                                         ( sizeof ( sum ) - 1 ) ) >> 1 );
        } else {
                initial_word_count = 0;
        }
        len -= ( initial_word_count * 2 );

        /* Calculate number of iterations of the main loop.  This loop
         * processes native machine words (32-bit or 64-bit), and is
         * unrolled 16 times.  We calculate an overall iteration
         * count, and a starting point for the first iteration.
         */
        loop_count = ( len / ( sizeof ( sum ) * 16 ) );
        loop_partial_count =
                ( ( len % ( sizeof ( sum ) * 16 ) ) / sizeof ( sum ) );

        /* Calculate number of 16-bit words remaining after the main
         * loop completes.
         */
        final_word_count = ( ( len % sizeof ( sum ) ) / 2 );

        /* Calculate whether or not a final byte remains at the end */
        final_byte = ( len & 1 );

        /* Calculate the checksum */
        __asm__ ( /* Calculate position at which to jump into the
                   * unrolled loop.
                   */
                  "imul $( -x86_tcpip_loop_step_size ), %4\n\t"
                  "add %5, %4\n\t"

                  /* Clear carry flag before starting checksumming */
                  "clc\n\t"

                  /* Checksum initial words */
                  "jmp 2f\n\t"
                  "\n1:\n\t"
                  "lodsw\n\t"
                  "adcw %w2, %w0\n\t"
                  "\n2:\n\t"
                  "loop 1b\n\t"

                  /* Main "lods;adc" loop, unrolled x16 */
                  "mov %12, %3\n\t"
                  "jmp *%4\n\t"
                  "\nx86_tcpip_loop_start:\n\t"
                  "lods%z2\n\tadc %2, %0\n\t"
                  "lods%z2\n\tadc %2, %0\n\t"
                  "lods%z2\n\tadc %2, %0\n\t"
                  "lods%z2\n\tadc %2, %0\n\t"
                  "lods%z2\n\tadc %2, %0\n\t"
                  "lods%z2\n\tadc %2, %0\n\t"
                  "lods%z2\n\tadc %2, %0\n\t"
                  "lods%z2\n\tadc %2, %0\n\t"
                  "lods%z2\n\tadc %2, %0\n\t"
                  "lods%z2\n\tadc %2, %0\n\t"
                  "lods%z2\n\tadc %2, %0\n\t"
                  "lods%z2\n\tadc %2, %0\n\t"
                  "lods%z2\n\tadc %2, %0\n\t"
                  "lods%z2\n\tadc %2, %0\n\t"
                  "lods%z2\n\tadc %2, %0\n\t"
                  "lods%z2\n\tadc %2, %0\n\t"
                  "\nx86_tcpip_loop_end:\n\t"
                  "loop x86_tcpip_loop_start\n\t"
                  ".equ x86_tcpip_loop_step_size, "
                  "  ( ( x86_tcpip_loop_end - x86_tcpip_loop_start ) >> 4 )\n\t"

                  /* Checksum remaining whole words */
                  "mov %13, %3\n\t"
                  "jmp 2f\n\t"
                  "\n1:\n\t"
                  "lodsw\n\t"
                  "adcw %w2, %w0\n\t"
                  "\n2:\n\t"
                  "loop 1b\n\t"

                  /* Checksum final byte if applicable */
                  "mov %14, %3\n\t"
                  "loop 1f\n\t"
                  "adcb (%1), %b0\n\t"
                  "adcb $0, %h0\n\t"
                  "\n1:\n\t"

                  /* Fold down to a uint16_t */
                  "push %0\n\t"
                  "popw %w0\n\t"
                  "popw %w2\n\t"
                  "adcw %w2, %w0\n\t"
#if ULONG_MAX > 0xffffffffUL /* 64-bit only */
                  "popw %w2\n\t"
                  "adcw %w2, %w0\n\t"
                  "popw %w2\n\t"
                  "adcw %w2, %w0\n\t"
#endif /* 64-bit only */

                  /* Consume CF */
                  "adcw $0, %w0\n\t"
                  "adcw $0, %w0\n\t"

                  : "=&Q" ( sum ), "=&S" ( discard_S ), "=&a" ( discard_a ),
                    "=&c" ( discard_c ), "=&r" ( discard_r1 ),
                    "=&r" ( discard_r2 )
                  : "0" ( sum ), "1" ( data ), "2" ( 0 ),
                    "3" ( initial_word_count + 1 ), "4" ( loop_partial_count ),
                    "5" ( x86_tcpip_loop_end ), "g" ( loop_count + 1 ),
                    "g" ( final_word_count + 1 ), "g" ( final_byte ) );

        return ( ~sum & 0xffff );
}