> ## Documentation Index
> Fetch the complete documentation index at: https://wireblast.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# VLAN-tagged traffic

> Send 802.1Q tagged frames, and why the minimum frame size becomes 68.

<Note>
  Most people don't need this. If you're sending untagged traffic, skip the page. It's here because tagged frames have one surprise (the 68-byte minimum) and one common mistake (binding the wrong interface), both worth having written down.
</Note>

Add `--vlan` and Wireblast builds the 802.1Q tag into every frame itself.

```bash theme={null}
sudo wireblast -i eno2 --vlan 100 --dst-ip 192.168.0.2 \
  --packet-size 512 --pps 100k -d 30s
```

Valid IDs are 1 to 4094. `0` means untagged, which is the default.

## Bind the physical NIC, not the sub-interface

This is the thing everyone gets wrong once.

AF\_XDP attaches to the real device. If your host has a `vlan.100` sub-interface, **don't** point `--interface` at it. Point at the parent NIC and let Wireblast do the tagging:

```bash theme={null}
sudo wireblast -i eno2 --vlan 100 ...     # correct
sudo wireblast -i vlan.100 ...            # not this
```

Wireblast catches it and tells you exactly what you meant:

```text theme={null}
vlan.2043 is a VLAN sub-interface (VLAN 2043 on eno2). AF_XDP attaches to the
physical NIC, so use --interface eno2 --vlan 2043 instead and Wireblast will
emit tagged frames itself.
```

## Addressing comes from the sub-interface

If a matching sub-interface exists, Wireblast uses it for the things that need an IP stack: picking a source address, looking up the route, resolving the next-hop MAC.

```text theme={null}
VLAN 100 addressing taken from vlan.100
```

If there isn't one, that's fine, but it says so, because you'll have to supply what it can't look up:

```text theme={null}
this host has no VLAN 100 interface on eno2, so addresses and the next-hop MAC
cannot be looked up for that VLAN
```

In that case give `--src-ip` and `--dst-mac` explicitly. That's a perfectly normal way to run a test: you're generating traffic, not participating in the network.

## The 68-byte minimum

The 64-byte Ethernet minimum is measured on the **untagged** frame. Add a 4-byte tag and the smallest legal frame becomes **68 bytes**.

Ask for less and the NIC silently pads it, which means the frame on the wire isn't the size you asked for and every rate Wireblast reported would be short by the difference. So it refuses instead:

```text theme={null}
--packet-size 64 is out of range for --mode udp with a VLAN tag; use 68-9018
(total Ethernet frame bytes, including the 4-byte FCS). The 64-byte Ethernet
minimum applies to the untagged frame, so a tagged one starts at 68: the NIC
pads anything smaller, and the reported rates would not match the wire
```

Verified on ixgbe: `--packet-size 64`, `66` and `68` with a tag all left the NIC as 68-byte frames.

IMIX handles this for you. On a tagged link its 64-byte component becomes 68, so the mix reads `68/594/1518B` and the mean rises from 362 to 364 bytes, which is exactly what the receiver counts. Nothing to set; it just reports honestly.

<Note>
  **Comparing tagged and untagged runs?** Use 68 for both. Comparing a 64-byte untagged run against a 68-byte tagged one is a 6% difference in frame size before you've measured anything.
</Note>

## The tag is inside `--packet-size`

`--packet-size 512` with a tag means 512 bytes total on the wire: 14 bytes of Ethernet header, 4 of tag, 490 of IP packet, 4 of FCS. The payload gets 4 bytes smaller; the frame doesn't get bigger.

This also means the tag **doesn't count against the MTU**. A 1500-byte MTU accepts `--packet-size 1522` when tagged, because the MTU governs the IP packet, not the Ethernet framing.

## Watching it on the far end

If you're checking with `bwm-ng` or similar, point it at the **physical NIC**, not the VLAN sub-interface. Pointed at a sub-interface, the kernel has already stripped the Ethernet header and the tag, so the byte counter reads about 18 bytes per packet lower:

| Pointed at | Counts                          | 512-byte frame |
| ---------- | ------------------------------- | -------------- |
| `eno2`     | frame minus FCS                 | 508 B          |
| `vlan.100` | frame minus FCS, header and tag | 490 B          |

Full explanation in [reading the numbers](/concepts/numbers).

## Limitations

* **One tag.** No QinQ, no stacked tags.
* **No tag on PCAP replay.** Captures are replayed byte for byte, so tags come from the capture itself.
* **IPv6 works too.** A tagged IPv6 UDP frame just starts at 70 bytes (the 66-byte v6 minimum plus the 4-byte tag).

There's a runnable version in [example 014](https://github.com/atoonk/wireblast/tree/main/examples/014-vlan-tagged).
