When working with VLAN traffic capture using tcpdump, many network engineers encounter a common issue: the inability to simultaneously capture traffic from multiple VLANs using simple logical operators. The pcap filter's behavior with VLAN tags creates unexpected results due to header offset calculations.
The key issue lies in how tcpdump handles multiple vlan
expressions in BPF filters. Each vlan
expression increments the filter offset by 4 bytes (the size of an 802.1Q header). This means when you chain multiple vlan
expressions, subsequent checks examine the wrong packet positions.
// Problematic filter example
tcpdump -i eth0 '(vlan 1000 or vlan 501) and (host 10.1.1.1)'
Here are three reliable approaches to capture multiple VLANs:
Method 1: Using Parentheses and Explicit Offsets
tcpdump -i eth0 '(vlan 1000 and host 10.1.1.1) or (vlan 501 and host 10.1.1.1)'
Method 2: VLAN Trunk Capture with Post-Filtering
tcpdump -i eth0 -w all_vlans.pcap
# Then filter with Wireshark or:
tcpdump -r all_vlans.pcap 'vlan 1000 or vlan 501'
Method 3: Advanced BPF Byte Matching
For complex scenarios, directly match the VLAN ID at the Ethernet frame level:
tcpdump -i eth0 '(ether[14:2] & 0x0fff == 1000) or (ether[14:2] & 0x0fff == 501)'
When capturing high-speed VLAN traffic:
- Method 2 (capture first, filter later) has lowest overhead
- Method 3 provides most flexibility but requires precise offset knowledge
- Avoid complex BPF filters on busy interfaces
Here's how we might monitor VoIP traffic across two VLANs:
tcpdump -i eth0 -n \
'((vlan 1000 and (port 5060 or 5061)) or \
(vlan 501 and (port 5060 or 5061)))' \
-w voip_capture.pcap
When working with VLAN traffic analysis, many network engineers encounter the same limitation with tcpdump's VLAN filtering syntax. The core issue stems from how tcpdump handles stacked VLAN tags in packet capture filters.
tcpdump -i eth0 vlan 100
This simple filter works perfectly for single VLAN capture. But problems arise when you need to capture multiple VLANs simultaneously.
The pcap-filter man page explains this behavior clearly:
Each use of the vlan [vlan_id] expression increments the filter offsets by 4.
This means when you chain multiple VLAN filters with OR conditions, tcpdump looks for VLAN tags at different offsets in the packet, which typically won't match any real traffic.
Here are three practical approaches to capture multiple VLANs:
1. Using Parentheses for Logical Grouping
tcpdump -i eth0 '(vlan 1000 or vlan 501)' and 'host 10.1.1.98'
This syntax properly groups the VLAN conditions before applying the host filter.
2. VLAN Filter with Ethertype Matching
tcpdump -i eth0 '(ether proto 0x8100 and vlan 1000) or (ether proto 0x8100 and vlan 501)'
This explicitly matches the 802.1Q tag (0x8100) before filtering VLAN IDs.
3. Post-Capture Filtering with Wireshark
Sometimes it's easier to capture all VLAN traffic and filter later:
tcpdump -i eth0 -w vlan_capture.pcap
For service provider environments with stacked VLAN tags:
tcpdump -i eth0 '(vlan 1000 and vlan 2000)' and 'port 5060'
This captures traffic with outer VLAN 1000 and inner VLAN 2000 running SIP on port 5060.
When capturing multiple VLANs on high-traffic interfaces:
- Use BPF filters to reduce capture volume
- Consider interface hardware filtering capabilities
- Monitor system resources during extended captures