Skip to main content
A flow here is what a router or a load balancer would call one: a stable combination of source IP, destination IP, source port and destination port. --flows 64 means 64 distinct tuples, cycled through as packets go out. This matters when you’re testing anything that hashes: ECMP, LAG, RSS, a firewall’s connection table. One flow exercises one path. A thousand flows exercise the spread.

Generating them

By default the source port increments per flow, starting at --src-port, and the destination port stays fixed. That mirrors real client traffic, where many clients hit one service port. Add --vary-dst-port to increment both, which spreads across a wider hash space. Give --dst-ip a CIDR and destinations cycle across flows too:
Network and broadcast addresses are skipped for /30 and shorter. A /31 uses both of its addresses (RFC 3021), and a /32 uses its single address.

Order

--flow-order sequential (the default) walks flows in order. --flow-order random scatters them, so consecutive packets land on different tuples. “Random” is a fixed permutation, not randomness: a coprime stride derived from the golden ratio. The same config always produces the same order. You get scattering without losing reproducibility.

It’s deterministic

The same configuration always produces the same tuples in the same order. Two things follow:
  • A run is reproducible. Same flags today and next week, same packets.
  • Queue count doesn’t change the traffic. Queue q of Q takes flow q and steps by Q, so together they cover every flow exactly once per cycle. Changing --queues changes which queue carries a flow, never which flows exist. If there are fewer flows than queues, the modulo folds them back so every queue stays busy.
That second one is what makes --queues safe to use as an experimental variable. See finding your max rate.

Working out the next-hop MAC

Wireblast needs a destination MAC before it can send anything. It works one out from your routing and neighbour tables, and if it can’t, it stops and tells you why. It never falls back to broadcast, because flooding every port in the broadcast domain is not a reasonable thing to do by accident. The review screen shows which branch it took:

When it stops

Each failure names the fix.
Usually the destination isn’t up, or isn’t on the VLAN you think it is. If you’re deliberately sending at something that won’t answer, like a black hole, a tap, or a device in another rack, just give --dst-mac.
Either transmit from that interface, or keep the one you picked and give the next-hop MAC on it. Wireblast won’t silently switch interfaces on you.
Target a single address, or point the run at a router and give its MAC. This is the common one when you first try a CIDR destination on a local subnet.
Narrow the destination range, or pin the MAC.

IPv6

Everything above works for IPv6. Give --dst-ip and --src-ip IPv6 addresses and Wireblast builds IPv6 frames; give --dst-ip an IPv6 prefix and destinations cycle across it just like a v4 CIDR.
Two differences from IPv4:
  • No addresses are reserved. IPv6 has no network or broadcast address, so every address in the prefix is used, including the first one.
  • Frames start a little larger. The IPv6 header is 40 bytes rather than 20, and the UDP checksum is mandatory, so the smallest frame is 66 bytes for UDP and 78 for TCP (four more with a VLAN tag).
Next-hop resolution is the same decision tree, using neighbour discovery (NDP) where the IPv4 path uses ARP. Source and destination must be the same family: a v4 source with a v6 destination is rejected up front. Runnable IPv6 examples are in the repo.

Source addressing

--src-ip defaults to an address of the chosen interface. If the interface has several, Wireblast picks one and says which:
If it has none, you have to say:
That’s common on a NIC used purely for testing, where the addresses live on a VLAN sub-interface instead. Nothing stops you sending from an address the host doesn’t own, but replies won’t come back unless something upstream routes them to you. --src-mac defaults to the interface’s own hardware address, and you can override it if you’re testing MAC learning or filtering.