Skip to main content

Layers & Encapsulation

The network stack is built in layers so each one can do its job without knowing the others' internals. HTTP does not care how bits cross a wire; Ethernet does not care what the bits mean. They cooperate through encapsulation: as your data descends the stack, each layer wraps it in its own header (and the link layer adds a trailer). At the receiver the layers peel those wrappers off in reverse.

Step the data down the stack and watch each layer add its header:

headertrailerpayload
ApplicationHTTP · Data
GET /index.html
TransportTCP · Segment
TCP headerGET /index.html
NetworkIP · Packet
IP headerTCP headerGET /index.html
Data LinkEthernet · Frame
Ethernet headerIP headerTCP headerGET /index.htmlEthernet trailer (FCS)
Physicalsignal · Bits
10110100 01000111 01010100 …
Click "Descend a layer" to begin.
encapsulation ↓ (sender)layer 0 / 5

The five layers (TCP/IP model)

LayerProtocol data unitAddsExample
ApplicationData-HTTP, DNS
TransportSegmentTCP/UDP header (ports, sequence)TCP
NetworkPacketIP header (source/dest IP)IP
Data LinkFrameEthernet header + trailer (MAC, FCS)Ethernet
PhysicalBits-copper, fiber, radio

Encapsulation and decapsulation

  • Sender (down the stack): each layer treats everything from the layer above as opaque payload and prepends its own header. The transport segment becomes the payload of the network packet, which becomes the payload of the link frame.
  • Receiver (up the stack): each layer reads and removes its own header, then hands the remaining payload up. By the time HTTP sees it, every lower header is gone.

This is why the innermost GET /index.html in the animation never changes - each layer only ever touches its own wrapper, never the payload inside.

Worked example: header overhead on a small request

Encapsulation is not free - every header eats into the link's capacity before a single byte of your data crosses it. Take a small 20-byte HTTP request body:

  • Application layer: 20 bytes of data, no header of its own here.
  • Transport layer: + 20-byte TCP header = 40 bytes (the segment).
  • Network layer: + 20-byte IP header = 60 bytes (the packet).
  • Data link layer: + 14-byte Ethernet header + 4-byte trailer (FCS) = 78 bytes (the frame), plus a preamble the physical layer adds outside the frame itself.

So a 20-byte payload actually puts 78 bytes on the wire - almost 4x overhead. This ratio flips for large transfers: a 1400-byte payload in the same frame is only about 4% overhead, which is exactly why protocols batch data into large segments when they can, and why overhead-sensitive traffic (VoIP, small polling requests, IoT telemetry) suffers disproportionately from encapsulation compared to bulk downloads.

Path MTU Discovery black holes

Every link has a maximum transmission unit (MTU) - Ethernet's is 1500 bytes. When a packet is too large for the next link, a router should either fragment it or, if the "don't fragment" bit is set, send back an ICMP "fragmentation needed" message so the sender can retry smaller. Many firewalls, in the name of security, block all ICMP - including that message. The result is a classic, hard-to-diagnose production failure: small requests (a DNS lookup, an HTTP GET) work fine, but any response or upload that would need fragmentation on a lower-MTU link (common on VPNs and tunnels, which shrink the usable MTU by adding their own headers) just vanishes with no error, because the "please resend smaller" signal never arrives. This is often described as a PMTUD (Path MTU Discovery) black hole, and the fix is usually to lower the interface MTU explicitly or clamp the TCP MSS rather than rely on ICMP getting through.