[test] Fix RFC 1071 checksum calculation for big-endian targets

Calculation of the TCP/IP checksum is fundamentally endian-agnostic:
the checksum is designed to be symmetric so that both big-endian and
little-endian systems can use native addition in any word size without
any byte swapping.  The result is then stored into the checksum field
in the packet header as a native-endian value.

The reference algorithm presented in RFC 1071 (and used in our test
suite) is implicitly little-endian: the trailing byte is on a 16-bit
word boundary and is added to the least significant byte of the 16-bit
checksum value.

Fix by shifting the trailing byte by 8 bits on big-endian targets.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2026-06-13 16:15:57 +01:00
parent 85700526ec
commit 730c122c1d
+5 -1
View File
@@ -140,8 +140,12 @@ TCPIP_RANDOM_TEST ( partial, 0xcafebabe, 121, 5 );
* negative zero (0xffff) if the input data is zero length (or all
* zeros) but positive zero (0x0000) for any other data which sums to
* zero.
*
* A shift is applied to the trailing byte to ensure that the correct
* result is calculated on a big-endian system.
*/
static uint16_t rfc_tcpip_chksum ( const void *data, size_t len ) {
unsigned int shift = ( ( __BYTE_ORDER == __BIG_ENDIAN ) ? 8 : 0 );
unsigned long sum = 0xffff;
while ( len > 1 ) {
@@ -151,7 +155,7 @@ static uint16_t rfc_tcpip_chksum ( const void *data, size_t len ) {
}
if ( len > 0 )
sum += *( ( uint8_t * ) data );
sum += ( *( ( uint8_t * ) data ) << shift );
while ( sum >> 16 )
sum = ( ( sum & 0xffff ) + ( sum >> 16 ) );