Technical Tip: How 'diagnose firewall packet distribution' measures packet length (L2 vs L3, and whether the IP header is counted)
Description
This article describes which packet length the FortiGate command ‘diagnose firewall packet distribution’ uses when bucketing forwarded packets, and clarifies whether each bucket boundary refers to the Layer 2 frame size (including the Ethernet header) or the Layer 3 packet size, and, if Layer 3, whether the IP header itself is counted. The conclusion can be verified directly from the command output, without an additional packet capture.
Scope
FortiGate and FortiGate-VM, all current FortiOS branches.
Solution
The byte ranges count Layer 3 length, the value of the IPv4 Total Length field: that is, the IP header + L4 header + payload. The Ethernet header (14 bytes) and the FCS (4 bytes) are not included.
The command produces output similar to the following:
diagnose firewall packet distribution
0 bytes - 63 bytes: 393753482247 packets
64 bytes - 127 bytes: 643078208709 packets
128 bytes - 255 bytes: 354343585853 packets
256 bytes - 383 bytes: 71414869744 packets
384 bytes - 511 bytes: 38138078612 packets
512 bytes - 767 bytes: 31681483152 packets
768 bytes - 1023 bytes: 29021533963 packets
1024 bytes - 1279 bytes: 72746008151 packets
1280 bytes - 1500 bytes: 1041107664589 packets
> 1500 bytes: 76670169586 packets
Why the buckets are Layer 3 and not Layer 2.
Two boundaries in the output confirm this, with no additional capture required:
The upper boundary lands on 1500, not 1514/1518. The highest ‘normal’ bucket ends at 1500, the IP MTU, and it holds the bulk of the traffic. If counting occurred at Layer 2, a full-MTU packet would be 1514 bytes (1500 + 14-byte Ethernet header), or 1518 with FCS, and that traffic would fall into the > 1500 bucket, but it does not. A clean 1500 ceiling is only possible when the boundary is the Layer 3 MTU.
A populated 0–63-byte bucket is impossible at Layer 2. Ethernet pads any frame shorter than the 64-byte minimum up to that floor before transmission, so at Layer 2, there could never be a sub-64-byte entry because everything would begin at 64 - 127. The populated 0 - 63 bucket (bare ~40-byte TCP ACKs and small control packets) can only exist if counting happens at Layer 3, before padding.
Worked example:
A full-MTU TCP segment decomposes as follows:
IPv4 header (no options) 20 B counted
TCP header (no options) 20 B counted
Payload (one MSS) 1460 B counted
------------------------------------------------
IPv4 Total Length 1500 B = top of 1280-1500 bucket
Ethernet header 14 B NOT counted
FCS (CRC) 4 B NOT counted
If the IP header were excluded, the same packet would measure 1480 bytes, and the dominant bucket would top out below 1500. The boundary falling exactly on the MTU confirms the IP header is counted.
IPv6 behavior.
For IPv6 traffic, the on-wire Payload Length field excludes the 40-byte fixed header by definition. FortiOS normalizes to the full Layer 3 length, so an IPv6 packet is counted as 40 + extension headers + payload. There is no IPv4-versus-IPv6 accounting skew in this histogram.
Note on the ‘> 1500’ bucket.
A non-trivial count above 1500 is expected and is not in itself a sign of fragmentation problems. It reflects legitimate oversized-IP accounting: LSO/GRO-coalesced segments counted as a single large IP packet before segmentation, jumbo frames on interfaces configured above 1500, and tunnel/pre-fragmentation sizing.
Summary:
Counting point: Layer 3, maps to the IPv4 Total Length field.
Included: IP header + L4 header + payload.
Excluded: Ethernet header (14 bytes) and FCS (4 bytes).
Self-check in the output: a clean 1500 ceiling (not 1514/1518) and a populated 0–63 bucket.
