> ## 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.

# Runnable examples

> Dozens of examples you can clone and run, from a first packet to an overnight soak test.

The repository ships a numbered set of examples, roughly simplest to most advanced. Each one is a directory with a `README.md` explaining what it demonstrates and a `run.sh` you can execute directly.

Most are transmit-only, which is safe on a live box: nothing is taken away from the kernel network stack. The ones that receive are grouped together under "receiving and two-box tests" and called out there.

## Get them

```bash theme={null}
git clone https://github.com/atoonk/wireblast.git
cd wireblast/examples/001-veth-quickstart
./run.sh
```

## Nothing to edit

Every script takes its settings from environment variables, so you never have to open one to change a value:

```bash theme={null}
IFACE=eth1 DST=192.0.2.10 ./run.sh
```

The common ones are `IFACE`, `DST`, `PPS`, `SIZE` and `DUR`. Anything a script needs and can't guess is required, and it will tell you which one is missing rather than run something surprising. Each example's `README` lists the rest.

The commands below are what the scripts run with their default values filled in. `--start` skips the wizard but keeps the live dashboard, so you still watch the run.

## Start with no hardware

[001-veth-quickstart](https://github.com/atoonk/wireblast/tree/main/examples/001-veth-quickstart) is the one to run first. It builds a `veth` pair inside a throwaway network namespace, sends across it, and tears the whole thing down again. There's no NIC involved, so it can't touch your real network.

```bash theme={null}
cd examples/001-veth-quickstart
./run.sh
```

```text theme={null}
started: wb0: 1 queue(s), copy, native XDP, rx filter none
ran for 0:10
  tx: 1 M packets, 512.03 MB, 99.95 kpps, L1 425.38 Mbit/s, L2 409.39 Mbit/s, avg frame 512B
```

Two things differ from a physical NIC. There's no carrier to renegotiate, so the attach is instant rather than taking several seconds. And you get `copy` on a single queue rather than zero-copy, which is expected on `veth`.

Run it with `KEEP=1` to leave the lab up, and the [namespace lab guide](/guides/namespace-lab) turns it into a full sender and receiver with the numbers to expect.

## The catalog

<AccordionGroup>
  <Accordion title="Start here" icon="play">
    [**001-veth-quickstart**](https://github.com/atoonk/wireblast/tree/main/examples/001-veth-quickstart) builds its own lab and needs no NIC. See above.

    [**002-first-run**](https://github.com/atoonk/wireblast/tree/main/examples/002-first-run) is the simplest useful command on a real interface: one flow of 512-byte UDP frames at a modest rate.

    ```bash theme={null}
    sudo wireblast -i eth1 --dst-ip 192.0.2.10 \
      --packet-size 512 --pps 100k -d 30s --start
    ```

    [**003-fixed-rate**](https://github.com/atoonk/wireblast/tree/main/examples/003-fixed-rate) pins the rate and the duration so runs are comparable with each other.

    ```bash theme={null}
    sudo wireblast -i eth1 --dst-ip 192.0.2.10 \
      --packet-size 512 --pps 1M -d 60s --start
    ```
  </Accordion>

  <Accordion title="Rate and frame size" icon="gauge-high">
    [**004-packet-sizes**](https://github.com/atoonk/wireblast/tree/main/examples/004-packet-sizes) runs three frame sizes back to back at the same packet rate, so you can watch packet rate and bit rate trade off.

    ```bash theme={null}
    for size in 64 512 1518; do
      sudo wireblast --no-tui -i eth1 --dst-ip 192.0.2.10 \
        --packet-size "$size" --pps 500k -d 15s -y
    done
    ```

    [**005-bit-rate-limit**](https://github.com/atoonk/wireblast/tree/main/examples/005-bit-rate-limit) limits by bits instead of packets, for when you want "fill 2.5 gigabit" rather than a packet count. `--bps` is measured in L1.

    ```bash theme={null}
    sudo wireblast -i eth1 --dst-ip 192.0.2.10 \
      --packet-size 1518 --bps 2.5G -d 30s --start
    ```

    [**006-line-rate-64byte**](https://github.com/atoonk/wireblast/tree/main/examples/006-line-rate-64byte) is the small-frame ceiling, the hardest thing you can ask a NIC to do. 10G line rate at this size is 14.88 Mpps.

    ```bash theme={null}
    sudo wireblast -i eth1 --dst-ip 192.0.2.10 \
      --packet-size 64 --pps unlimited -d 30s --start
    ```

    [**011-imix-line-rate**](https://github.com/atoonk/wireblast/tree/main/examples/011-imix-line-rate) finds the same ceiling with realistic traffic instead of one artificial size.

    ```bash theme={null}
    sudo wireblast -i eth1 --dst-ip 192.0.2.10 --mode imix \
      --flows 64 --pps unlimited -d 30s --start
    ```

    [**019-queue-scaling**](https://github.com/atoonk/wireblast/tree/main/examples/019-queue-scaling) runs the same rate at 1, 2, 4 and all queues. It proves the rate limit is aggregate rather than per queue, and shows whether more queues actually help. `--queues 0` means all of them.

    ```bash theme={null}
    for q in 1 2 4 0; do
      sudo wireblast --no-tui -i eth1 --dst-ip 192.0.2.10 \
        --queues "$q" --packet-size 64 --pps 1M -d 15s -y
    done
    ```

    Falling short of the number you expected? [Finding your max rate](/guides/max-rate) walks through whether it was the CPU, the driver or the path.
  </Accordion>

  <Accordion title="Flows and hashing" icon="arrows-split-up-and-left">
    One flow only ever takes one path through a network. To exercise anything that hashes, you need many.

    [**007-many-flows**](https://github.com/atoonk/wireblast/tree/main/examples/007-many-flows) generates a thousand distinct tuples instead of one.

    ```bash theme={null}
    sudo wireblast -i eth1 --dst-ip 192.0.2.10 \
      --flows 1000 --packet-size 512 --pps 1M -d 30s --start
    ```

    [**008-flow-hashing**](https://github.com/atoonk/wireblast/tree/main/examples/008-flow-hashing) widens the hash space as far as it goes: ten thousand flows, both ports varying, and a scattered order so consecutive packets land on different tuples. This is the one for ECMP, LAG and RSS.

    ```bash theme={null}
    sudo wireblast -i eth1 --dst-ip 192.0.2.10 \
      --flows 10000 --vary-dst-port --flow-order random \
      --packet-size 512 --pps 1M -d 60s --start
    ```

    [**009-cidr-destinations**](https://github.com/atoonk/wireblast/tree/main/examples/009-cidr-destinations) takes a CIDR instead of a single address and cycles destinations across the flows.

    ```bash theme={null}
    sudo wireblast -i eth1 --dst-ip 10.0.0.0/24 --flows 254 \
      --packet-size 512 --pps 1M -d 30s --start
    ```

    A directly connected CIDR would need one MAC per destination, which Wireblast won't guess. Set `DSTMAC` to point it at a router instead. [Flows and addressing](/patterns/flows) explains how the tuples are built.
  </Accordion>

  <Accordion title="Traffic patterns" icon="shapes">
    [**010-imix**](https://github.com/atoonk/wireblast/tree/main/examples/010-imix) is the classic 7:4:1 mix of 64, 594 and 1518-byte frames, averaging 362 bytes. `avg frame 362B` in the summary is your confirmation the mix came out right.

    ```bash theme={null}
    sudo wireblast -i eth1 --dst-ip 192.0.2.10 --mode imix \
      --flows 64 --pps 200k -d 30s --start
    ```

    [**012-tcp-syn**](https://github.com/atoonk/wireblast/tree/main/examples/012-tcp-syn) sends stateless SYNs across a hundred thousand flows, with no handshake. It's for stressing a firewall or load balancer's connection table.

    ```bash theme={null}
    sudo wireblast -i eth1 --dst-ip 192.0.2.10 --mode tcp-syn \
      --dst-port 443 --flows 100000 --pps 1M -d 30s --start
    ```

    <Warning>
      That is a SYN flood. Only point it at something you own and have permission to test.
    </Warning>

    [**013-raw-ethernet**](https://github.com/atoonk/wireblast/tree/main/examples/013-raw-ethernet) sends frames with a fixed EtherType and no IP layer at all. `--dst-mac` is required, because raw frames carry no addresses to resolve a next hop from.

    ```bash theme={null}
    sudo wireblast -i eth1 --mode raw \
      --ethertype 0x88b5 --dst-mac 3c:ec:ef:b4:c2:dc \
      --packet-size 128 --pps 1M -d 30s --start
    ```

    [**014-vlan-tagged**](https://github.com/atoonk/wireblast/tree/main/examples/014-vlan-tagged) sends 802.1Q tagged frames. Bind the physical NIC, not a VLAN sub-interface, and note that the smallest tagged frame is 68 bytes rather than 64.

    ```bash theme={null}
    sudo wireblast -i eth1 --vlan 100 --dst-ip 192.0.2.10 \
      --packet-size 68 --pps 1M -d 30s --start
    ```

    Set `SRCIP` or `DSTMAC` and the script adds `--src-ip` or `--dst-mac` for you. [VLAN-tagged traffic](/guides/vlan) covers both surprises.
  </Accordion>

  <Accordion title="IPv6" icon="globe">
    Everything Wireblast does over IPv4 it does over IPv6. Give it a v6 destination and it builds v6 frames, resolving the next hop with neighbour discovery exactly as the v4 path uses ARP.

    [**022-ipv6-udp**](https://github.com/atoonk/wireblast/tree/main/examples/022-ipv6-udp) is a plain v6 UDP blast. 66 bytes is the smallest IPv6 UDP frame on the wire, because the header is 40 bytes and the checksum is mandatory.

    ```bash theme={null}
    sudo wireblast -i eth1 --dst-ip 2001:db8::2 \
      --packet-size 66 --pps 1M -d 30s --start
    ```

    [**023-ipv6-flows**](https://github.com/atoonk/wireblast/tree/main/examples/023-ipv6-flows) cycles ten thousand flows across a prefix. Unlike IPv4 there's no network or broadcast address to skip, so every address in the prefix gets used.

    ```bash theme={null}
    sudo wireblast -i eth1 --dst-ip 2001:db8::/64 --flows 10000 \
      --packet-size 128 --pps 1M -d 30s --start
    ```

    Both take optional `SRCIP` and `DSTMAC`, and 023 also takes `VARY_DST_PORT`.
  </Accordion>

  <Accordion title="Capture replay" icon="file-arrow-up">
    [**015-pcap-replay**](https://github.com/atoonk/wireblast/tree/main/examples/015-pcap-replay) puts a capture back on the wire at a rate you choose. The directory ships a small `sample.pcap`, so it runs out of the box with nothing but an interface.

    ```bash theme={null}
    sudo wireblast -i eth1 --pcap sample.pcap --pps 100k -d 30s --start
    ```

    Frames go out byte for byte as captured. Nothing is rewritten and no checksum is recomputed unless you override the MACs yourself. The capture loops until the duration expires, which is what makes a short one useful as a traffic source. Point `PCAP` at your own.

    [**016-pcap-original-timing**](https://github.com/atoonk/wireblast/tree/main/examples/016-pcap-original-timing) replays the same capture with its recorded gaps between packets, exactly once. That reproduces a scenario rather than generating a load.

    ```bash theme={null}
    sudo wireblast -i eth1 --pcap ../015-pcap-replay/sample.pcap \
      --pcap-timing original --pcap-loop=false --start
    ```

    Make your own with `sudo tcpdump -ni eth1 -c 1000 -w mycapture.pcap`. It has to be an Ethernet capture. More in [PCAP replay](/patterns/pcap).
  </Accordion>

  <Accordion title="Receiving and two-box tests" icon="right-left">
    These are the examples that take packets away from the kernel. Read [transmit and receive](/concepts/receive) first, and unless you're using 021, use an interface you aren't logged in over.

    [**017-receiver**](https://github.com/atoonk/wireblast/tree/main/examples/017-receiver) turns a box into a sink that transmits nothing and counts what lands on it. The filter is deliberately narrow.

    ```bash theme={null}
    sudo wireblast -i eth1 --mode receive \
      --rx-mode udp-port --rx-port 9000 -d 60s --start
    ```

    Set `PROTO=tcp` for `--rx-mode tcp-port` instead.

    [**018-two-box-imix**](https://github.com/atoonk/wireblast/tree/main/examples/018-two-box-imix) is the sender half of an end-to-end test. Start the receiver on the far box first, then run the sender. When both ends report the same packet count, the path carried everything.

    ```bash theme={null}
    # on the receiver
    sudo wireblast -i eth1 --mode receive --rx-mode udp-port --rx-port 9000 -d 90s

    # on the sender
    sudo wireblast -i eth1 --mode imix --dst-ip 192.0.2.20 --dst-port 9000 \
      --flows 64 --pps 200k -d 30s --start
    ```

    `VLAN`, `SRCIP` and `DSTMAC` are all optional additions to the sender. The [two-box test](/guides/two-box) covers reading the two summaries against each other.

    [**021-safe-capture**](https://github.com/atoonk/wireblast/tree/main/examples/021-safe-capture) is the exception: it's safe on the very NIC you're logged in over. `keep-management` takes every packet on the interface except ARP, IPv6 neighbour discovery, SSH and DNS, so it cannot strand you. No `--allow-match-all`, no typed confirmation.

    ```bash theme={null}
    sudo wireblast -i eth1 --mode receive \
      --rx-mode keep-management -d 60s --start
    ```

    Other services on that NIC do stop receiving for the duration of the run, which matters on a box that does more than testing.
  </Accordion>

  <Accordion title="Long runs" icon="clock">
    [**020-soak-test**](https://github.com/atoonk/wireblast/tree/main/examples/020-soak-test) runs for hours, unattended, logging to a file. It's for the failures that only show up after a while: thermal throttling, memory leaks in the device under test, slow counter drift.

    ```bash theme={null}
    sudo nohup wireblast --no-tui -i eth1 --dst-ip 192.0.2.10 \
      --mode imix --pps 500k -d 28800s -y > /var/log/wireblast-soak.log 2>&1 &
    ```

    Set `HOURS` to change the length. Stop it with `sudo pkill -INT wireblast`, which gives you a clean summary rather than a truncated log, because Wireblast drains its rings and detaches before exiting.

    [Scripting and automation](/guides/scripting) covers parsing that log.
  </Accordion>
</AccordionGroup>

## Next

<CardGroup cols={2}>
  <Card title="Common tasks" icon="list-check" href="/recipes">
    The same ground as copy-paste commands, when you don't want to clone anything.
  </Card>

  <Card title="All the flags" icon="list" href="/reference/cli">
    Every flag the scripts use, its default, and what it does.
  </Card>

  <Card title="Transmit and receive" icon="shield-check" href="/concepts/receive">
    Read this before running any of the receive examples on a shared box.
  </Card>

  <Card title="Examples on GitHub" icon="github" href="https://github.com/atoonk/wireblast/tree/main/examples">
    The source for all of the above, with a fuller README in every directory.
  </Card>
</CardGroup>
