Skip to main content

checksum

Function checksum 

Source
pub fn checksum(data: &[u8]) -> u16
Expand description

The CDP checksum: a 16-bit one’s-complement sum (RFC 1071) over the CDP payload with the checksum field zeroed — with Cisco’s non-standard treatment of an odd-length payload.

For an even-length payload this is the plain IP checksum. For an odd-length payload RFC 1071 says to pad with a trailing zero byte, which makes the final word last << 8. Cisco’s implementation instead puts the last octet in the low half of the final big-endian word and then compensates for an off-by-one in its own sign handling:

last byte Lfinal 16-bit word
L < 0x800x00 << 8 | L
L >= 0x800xFF << 8 | (L - 1)

This is not a guess. It is transcribed from Wireshark’s packet-cdp.c, which builds exactly that padded buffer (“Swap bytes in last word” / “Compensate off-by-one error”) before calling in_cksum, and it is corroborated by scapy’s independent _CDPChecksum._check_len. The two disagree on one value: scapy tests last <= 0x80 where Wireshark tests last & 0x80, so for a payload ending in exactly 0x80 scapy produces 0x0080 and Wireshark 0xFF7F. This implementation follows Wireshark, because Wireshark’s is the reading that treats the byte as signed (0x80 is negative, so it takes the compensated branch) and because Wireshark is what an operator will use to check our frames.

Emitting the RFC-1071 form instead is not a cosmetic difference: Wireshark flags the packet [incorrect] and a real Cisco device discards it, which is precisely the failure mode this project’s OSPF checksum bug had (src/server/ospf/CLAUDE.md).