discovery

package
v0.6.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 31, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package discovery reads the system's network configuration — interfaces, addresses, routes and neighbours — and works out the things a user should not have to type: which interface to use, what source address to send from, and which MAC address the next hop has.

Everything it needs from the kernel goes through the Source interface, so the decision logic is ordinary testable code with no root, no netlink and no hardware. NewSource returns the real netlink-backed implementation.

Index

Constants

View Source
const DefaultProbeTimeout = 1500 * time.Millisecond

DefaultProbeTimeout is how long an active ARP probe waits for an answer before giving up. Long enough for a switched LAN, short enough that a mistyped address does not feel like a hang.

Variables

This section is empty.

Functions

func DefaultRouteLink(s Source) (int, bool)

DefaultRouteLink returns the index of the interface that owns the default route, and whether there is one. Used to warn before blasting traffic out of the interface the machine reaches the world through.

func ExplainVLANInterface

func ExplainVLANInterface(s Source, l Link) string

ExplainVLANInterface builds the message shown when a user selects an 802.1Q sub-interface. Rather than a bare rejection it names the interface and flag combination that does what they meant.

func SourceCandidates

func SourceCandidates(l Link, dst netip.Prefix) []netip.Addr

SourceCandidates lists the addresses a user may pick as the source for a run, in the order the wizard should offer them: matching the destination's family and scope, and on the same subnet, first.

func Usable

func Usable(l Link) bool

Usable reports whether an interface can carry an AF_XDP run: administratively up, not loopback, with a real 6-byte hardware address and at least one receive queue.

VLAN sub-interfaces are excluded on purpose. Binding AF_XDP to one only ever gets the slow generic path, and the right answer is always to bind the parent NIC and set --vlan, which Wireblast says explicitly when a user picks one. See ExplainVLANInterface.

Types

type Link struct {
	Name  string
	Index int
	MAC   net.HardwareAddr
	MTU   int

	// Up is the administrative state; Carrier is whether the link is
	// operationally up (a cable is plugged in and negotiated).
	Up      bool
	Carrier bool

	Loopback bool
	Driver   string

	// Addrs holds the interface's addresses, IPv4 and IPv6 alike, so the
	// wizard can show what the user expects to see.
	Addrs []netip.Prefix

	// VLANID and ParentIndex are set for an 802.1Q sub-interface; VLANID is 0
	// on any other kind of device.
	VLANID      int
	ParentIndex int

	// RxQueues is how many receive queues the device exposes. AF_XDP binds one
	// socket per queue, so a device with none cannot be used.
	RxQueues int

	// SpeedMbps is the negotiated link speed, or 0 when the device does not
	// report one (a veth, or a physical port with no carrier). Backends that
	// size themselves against line rate need it; nothing else does.
	SpeedMbps int
}

Link is one network interface.

func FindLink(s Source, name string) (Link, error)

FindLink returns the link with the given name.

func Interfaces

func Interfaces(s Source) ([]Link, error)

Interfaces returns the interfaces a user may choose from, best candidate first.

The ordering matters more than it sounds: a busy host can have twenty veth, dummy and bridge devices that are technically usable but never what someone running a traffic generator wants. Physical NICs — the ones with a real kernel driver — come first, then those with a carrier, then those with an IPv4 address, then by name.

func VLANLink(s Source, parent Link, vlanID int) (Link, bool)

VLANLink finds the 802.1Q sub-interface carrying vlanID on top of parent, if one exists. Wireblast uses it for routing, neighbour lookups and ARP probes, because that is where the kernel keeps the addressing for that VLAN.

func (Link) IPv4

func (l Link) IPv4() []netip.Prefix

IPv4 returns the link's IPv4 prefixes, in the order the kernel reports them.

func (Link) IsPhysical

func (l Link) IsPhysical() bool

IsPhysical reports whether the interface is backed by a real kernel driver rather than being a virtual device. Used to sort and label the wizard's interface list.

func (Link) IsVLAN

func (l Link) IsVLAN() bool

IsVLAN reports whether this is an 802.1Q sub-interface.

type MACSource

type MACSource string

MACSource records how the destination MAC was arrived at, so the review screen can say where the number came from rather than presenting it as magic.

const (
	MACFromFlag     MACSource = "given with --dst-mac"
	MACFromNeighbor MACSource = "from the neighbour table"
	MACFromARP      MACSource = "resolved by ARP"
	MACFromND       MACSource = "resolved by neighbour discovery"
	MACFromGateway  MACSource = "gateway's MAC"
	MACPreserved    MACSource = "not needed (the capture's own MACs are preserved)"
	MACNotNeeded    MACSource = "not needed"
)

type NeedsDstMACError

type NeedsDstMACError struct {
	Reason string
	// Suggestion, when set, is a command the user could run to fix things.
	Suggestion string
}

NeedsDstMACError is returned when the destination cannot be resolved automatically but a user-supplied --dst-mac would work. It carries an explanation of why, so the TUI can show the reason instead of a generic validation failure.

func (*NeedsDstMACError) Error

func (e *NeedsDstMACError) Error() string

type Neighbor

type Neighbor struct {
	IP        netip.Addr
	MAC       net.HardwareAddr
	LinkIndex int
	// Reachable is true for entries the kernel considers usable (REACHABLE,
	// STALE, PERMANENT and friends) rather than incomplete or failed.
	Reachable bool
}

Neighbor is one entry from the IPv4 neighbour (ARP) table.

type Options

type Options struct {
	// ProbeTimeout bounds the active ARP probe. Zero uses DefaultProbeTimeout;
	// negative disables probing so only the existing neighbour table is used.
	ProbeTimeout time.Duration
}

Options tunes resolution, mostly for tests.

type Resolved

type Resolved struct {
	// Link is the interface AF_XDP binds to — always a physical NIC.
	Link Link
	// L3Link is where addressing lives. It is the VLAN sub-interface when
	// --vlan names one, and Link otherwise.
	L3Link Link

	SrcMAC net.HardwareAddr
	SrcIP  netip.Addr
	Dst    netip.Prefix

	DstMAC    net.HardwareAddr
	MACSource MACSource
	// NextHop is the address the MAC belongs to: the destination itself when
	// it is on-link, or the gateway when it is not.
	NextHop netip.Addr
	OnLink  bool

	// Notes are informational lines for the review screen.
	Notes []string
}

Resolved is everything discovery worked out for a run: which interface to transmit from, which addresses to put in the packets, and the next-hop MAC.

func Resolve

func Resolve(s Source, cfg *config.Config, opts Options) (*Resolved, error)

Resolve works out the addressing for a run.

The order of preference is deliberate and never guesses: an explicit --dst-mac always wins; otherwise an on-link destination is resolved through the neighbour table and then an active ARP probe; an off-link destination is resolved through the route the user's own interface would use. If the routing table disagrees with the chosen interface, or a destination CIDR spans more than one next hop, Resolve stops and explains rather than picking something plausible. It never falls back to the broadcast address.

type Route

type Route struct {
	// Dst is the destination prefix. The zero Prefix means the default route.
	Dst netip.Prefix
	// Gateway is the next hop, or the zero Addr for a directly connected
	// ("on-link") route.
	Gateway   netip.Addr
	LinkIndex int
	Priority  int
	Src       netip.Addr
}

Route is one routing-table entry.

func (Route) Bits

func (r Route) Bits() int

Bits is the route's prefix length, treating an invalid prefix as /0.

func (Route) Contains

func (r Route) Contains(a netip.Addr) bool

Contains reports whether this route covers an address.

func (Route) IsDefault

func (r Route) IsDefault() bool

IsDefault reports whether this is the default route.

type Source

type Source interface {
	Links() ([]Link, error)
	Routes() ([]Route, error)
	Neighbors(linkIndex int) ([]Neighbor, error)
	// Probe provokes IPv4 neighbour resolution for dst out of the given link
	// and waits up to timeout for the kernel to answer. Returning an error is
	// not fatal — the caller checks the neighbour table afterwards either way.
	Probe(link Link, dst netip.Addr, timeout time.Duration) error
}

Source supplies the system state discovery reasons about. It exists so the interface-selection and next-hop logic can be unit-tested against fixtures instead of whatever machine the tests happen to run on.

func NewSource

func NewSource() Source

NewSource returns a Source backed by the running kernel.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL