Understanding Ethernet Frame Sizes: Calculating Maximum Application Payload (MTU, IP/UDP Headers & Fragmentation)


1 views

When dealing with network programming, one of the most persistent misunderstandings revolves around Ethernet frame sizes and how they affect application payload capacity. The standard MTU (Maximum Transmission Unit) of 1500 bytes refers to the payload portion of the Ethernet frame - not the total frame size including headers.

Here's the complete breakdown for an IPv4/UDP packet:

Standard Ethernet Frame:
- Preamble: 7 bytes
- SFD: 1 byte
- Dest MAC: 6 bytes  
- Src MAC: 6 bytes
- EtherType: 2 bytes
- Payload (MTU): 1500 bytes
- FCS: 4 bytes
- Interpacket Gap: 12 bytes

Total "on-the-wire" size: 1538 bytes

For application developers, the key formula is:

Max Application Payload = MTU (1500) - IP Header (20) - UDP Header (8) = 1472 bytes

Here's a Python example to verify this:

import socket

def get_max_udp_payload():
    # Create raw socket to get interface MTU
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    mtu = s.getsockopt(socket.SOL_IP, socket.IP_MTU)
    
    # Subtract IPv4 and UDP headers
    return mtu - 20 - 8

print(f"Maximum UDP payload without fragmentation: {get_max_udp_payload()} bytes")

The 1518 byte figure comes from:

Ethernet header: 14 bytes
Payload: 1500 bytes
FCS: 4 bytes
Total: 1518 bytes

The 1542 byte figure includes additional overhead:

Preamble/SFD: 8 bytes
Interframe gap: 12 bytes
Total: 1518 + 8 + 12 = 1538 bytes

When programming network applications:

  1. For TCP: Maximum segment size is typically 1460 bytes (1500 - 20 IP - 20 TCP)
  2. For UDP: Maximum datagram size is 1472 bytes as shown above
  3. Jumbo frames (9000 byte MTU) change these calculations significantly

Use ping to test your actual MTU:

# Linux/macOS:
ping -c 1 -s 1472 -M do example.com

# Windows:
ping -f -l 1472 example.com

Remember that any ICMP overhead (8 bytes) counts against your payload, so 1472 is the correct test value for our 1500 byte MTU calculation.


When working with network programming, one of the most common points of confusion is determining the actual maximum payload size that can be transmitted without fragmentation. The core question revolves around whether the standard Ethernet frame size is 1518 bytes or 1542 bytes.

A standard Ethernet frame consists of:

  • Preamble: 7 bytes
  • Start Frame Delimiter: 1 byte
  • Destination MAC: 6 bytes
  • Source MAC: 6 bytes
  • EtherType: 2 bytes
  • Payload: 1500 bytes (MTU)
  • CRC: 4 bytes
  • Interframe Gap: 12 bytes

The "in-the-wire" size includes all these components, totaling 1542 bytes (7+1+6+6+2+1500+4+12). However, the commonly cited 1518 bytes refers to the frame size excluding the preamble, SFD, and interframe gap.

When sending UDP datagrams, you need to account for additional headers:

// Example calculation in Python
def calculate_max_udp_payload():
    ethernet_mtu = 1500
    ip_header = 20
    udp_header = 8
    return ethernet_mtu - ip_header - udp_header

max_udp_payload = calculate_max_udp_payload()  # Returns 1472

You can verify this using ping with different packet sizes:

# Works (1472 payload + 8 ICMP header + 20 IP header = 1500)
ping -s 1472 example.com

# Fails (payload exceeds MTU)
ping -s 1473 example.com

While 1500 bytes is the standard MTU, many modern networks support jumbo frames (typically 9000 bytes). However, you should:

  1. Never assume jumbo frame support
  2. Always implement path MTU discovery
  3. Handle fragmentation gracefully in your application

Here's how to check your interface's MTU in Linux:

ip link show | grep mtu
  • Default to 1472 bytes for UDP payloads (1500 - 28)
  • Implement proper error handling for oversized packets
  • Consider using TCP for large data transfers
  • Document your MTU assumptions clearly