Ethernet Internals

MAC Address

What range of MAC addresses can I safely use for my virtual machines?
MAC Address: Universally or Locally Administered Bit and Individual/Group Bit

Frame Check Sequence (FCS) = Cyclic Redundancy Check (CRC)

Cyclic Redundancy Check (CRC), Frame Check Sequence (FCS)

UDP Checksum

Short UDP Checksum Calculation HowTo

Following is a description by Ed Beroset of the calculation of the UDP checksum for this packet. Many thanks to Ed for figuring out the details and writing it up.

First, the checksum calculation is defined in RFC 768 but hints as to how to calculate it efficiently are in RFC 1071. Both are worth reading and contain a much more in-depth description that I’m going to write here.

The basic idea is that the UDP checksum is a the complement of a 16-bit one’s complement sum calculated over an IP “pseudo-header” and the actual UDP data. The IP pseudo-header is the source address, destination address, protocol (padded with a zero byte) and UDP length. So to take the example of this short packet, the source IP address is 152.1.51.27, and the destination IP address is 152.14.94.75. Divided into 16-bit quantities, these are 0x9801, 0x331b and 0x980e, 0x5e4b. If you add those together using two’s complement (e.g. with Windows calculator), you get 0x1c175. Note that this overflows a 16-bit quantity, but we’ll take care of that later. Next is to add in the protocol and UDP length. For this packet, the protocol is UDP so the protocol type byte is 17or 0x11. We pad that with zero to get 0x0011 and then add the UDP length which is 0x000a (10 bytes). So 0x1c175 + 0x0011 + 0x0! 00a = 0x1c190.

Now we add the entire UDP datagram, treating it all as 16-bit quantities and skipping the checksum (until we finish calculating it!). For this datagram, that’s 0xa08f, 0x2694, 0x000a, 0x6262, so if we add all that to our running sum, we get 0x1c190 + 0xa08f + 0x2694 + 0x000a + 0x6262 = 0x2eb1f.

Now to convert to a ones complement 16-bit sum we just treat our current sum (0x2eb1f) as a 32-bit quantity and add the high half to the low half. 0x0002 + 0xeb1f = 0xeb21. (If that still had an overflow, we’d add the high and low halves again until there was no longer an overflow.) Now we complement that quantity (i.e. flip all the bits, or do a NOT operation) and we get a value of 0x14de which is exactly what the reported checksum shows in the packet.

Short UDP Checksum Calculation HowTo
How to Calculate IP/TCP/UDP Checksum–Part 1 Theory

/*
 * Our algorithm is simple, using a 32 bit accumulator (sum), we add
 * sequential 16 bit words to it, and at the end, fold back all the
 * carry bits from the top 16 bits into the lower 16 bits.
 */
uint16_t
raw_packet_calc_checksum(uint16_t *buffer, uint16_t len)
{
    const uint16_t  words = len / 2;
    uint32_t        sum;
    uint16_t        i;
    
    sum = 0;
    for (i = 0; i < words; i++) {
        sum = sum + *(buffer + i);
    }
    
    /* add carry */
    sum = (sum >> 16) + sum;
    
    /* truncate to 16 bits */
    return ~sum;
}

Leave a Reply

Your email address will not be published. Required fields are marked *