How Ethernet Frame Length is Determined: Analyzing Type/Length Field and Packet Parsing Logic


2 views

The Ethernet frame format contains a critical 2-byte field that can serve dual purposes:

+-------------------+-------------------+-------------------+
| Destination MAC   | Source MAC        | Type/Length       |
| (6 bytes)         | (6 bytes)         | (2 bytes)         |
+-------------------+-------------------+-------------------+

This field operates differently based on its value:

  • If value ≤ 1500 (0x05DC): Indicates payload length (IEEE 802.3 standard)
  • If value ≥ 1536 (0x0600): Indicates EtherType (Ethernet II frame)

Here's how network interfaces determine frame length:

// Pseudo-code for frame length determination
if (type_length_field <= 1500) {
    // IEEE 802.3 frame with explicit length
    frame_length = 14 + type_length_field + 4; // Header + data + FCS
} else {
    // Ethernet II frame - must parse payload
    switch(type_length_field) {
        case 0x0800: // IPv4
            frame_length = 14 + parse_ipv4_length(payload) + 4;
            break;
        case 0x86DD: // IPv6
            frame_length = 14 + parse_ipv6_length(payload) + 4;
            break;
        // Other EtherType cases...
    }
}

When dealing with IPv4 payloads (EtherType 0x0800), the length is determined from the IP header:

// C code example for parsing IPv4 length
struct ip_header {
    uint8_t version_ihl;
    uint8_t dscp_ecn;
    uint16_t total_length;
    // ... other IP header fields
};

uint16_t get_ethernet_frame_length(const uint8_t *frame) {
    uint16_t type_length = ntohs(*(uint16_t*)(frame + 12));
    
    if (type_length <= 1500) {
        return 14 + type_length + 4;
    } else if (type_length == 0x0800) {
        struct ip_header *ip = (struct ip_header*)(frame + 14);
        return 14 + ntohs(ip->total_length) + 4;
    }
    // Additional cases for other protocols
    return 0;
}

Modern networks often include VLAN tags which add complexity:

// Modified length calculation with VLAN support
uint16_t get_ethernet_frame_length_with_vlan(const uint8_t *frame) {
    uint16_t type_length = ntohs(*(uint16_t*)(frame + 12));
    
    if (type_length == 0x8100) { // VLAN tag present
        uint16_t inner_type = ntohs(*(uint16_t*)(frame + 16));
        if (inner_type <= 1500) {
            return 18 + inner_type + 4; // 18 = 14 + 4 (VLAN tag)
        }
        // Handle other inner types...
    }
    // Original logic for non-VLAN frames
    return get_ethernet_frame_length(frame);
}

Modern network interface cards implement this parsing logic in hardware:

  • Early demultiplexing optimizes packet processing
  • DMA engines use frame length to determine transfer size
  • Checksum validation requires accurate length information

The Ethernet frame structure contains a critical 2-byte field at offset 12-13 in the header that serves dual purposes. This field can represent either:

  1. The total length of the payload (when value ≤ 1500 bytes)
  2. The EtherType protocol identifier (when value ≥ 1536)
// Example frame header structure
struct ethernet_header {
    uint8_t dest_mac[6];
    uint8_t src_mac[6];
    uint16_t type_length;
    // Followed by payload and FCS
};

The receiving NIC implements this decision logic:

bool is_length_field(uint16_t type_length) {
    return type_length <= 1500;  // IEEE 802.3 maximum frame size
}

bool is_ethertype(uint16_t type_length) {
    return type_length >= 1536;  // Starts at 0x0600
}

When the field indicates length:

frame_size = 14 (header) + length + 4 (FCS)

When the field indicates EtherType (e.g., IPv4/IPv6):

// For IPv4
struct ip_header {
    uint8_t version_ihl;
    // ... other fields ...
    uint16_t total_length;
};

void parse_ethernet_frame(uint8_t* frame) {
    if (ntohs(*(uint16_t*)(frame+12)) == 0x0800) {
        uint16_t ip_length = ntohs(*(uint16_t*)(frame+16));
        frame_size = 14 + ip_length + 4;
    }
}

Modern network stacks handle this automatically, but understanding the mechanics is crucial for:

  • Network protocol development
  • Packet sniffing tools
  • Custom NIC drivers

Examining a sample capture shows this behavior clearly:

Frame 1: 60 bytes on wire (480 bits)
    Ethernet II, Src: 00:1a:2b:3c:4d:5e, Dst: 00:0d:0e:0f:10:11
    Type: IPv4 (0x0800)
    Internet Protocol Version 4, Src: 192.168.1.100, Dst: 8.8.8.8
        Total Length: 46

Special scenarios to consider:

  • Jumbo frames (length > 1500)
  • VLAN tagged frames (additional 4-byte header)
  • Malformed packets with length/type conflicts