Wheelhouse docs

Neighbours#

The second view on Interfaces, reached from the segmented control in the header. It answers one question: is that host actually on the wire? The router keeps a cache of the addresses it has resolved to hardware addresses, and this table is that cache, verbatim.

It is read-only. There is no editor for a static ARP entry here, and no button to flush the cache.

Where the data comes from#

GET /api/neighbors runs show arp on the router and parses its output as a fixed-width table. The response carries both the parsed rows and the original text:

json
{
  "neighbors": [
    {
      "Address": "10.0.0.50",
      "Interface": "eth0",
      "Link layer address": "aa:bb:cc:dd:ee:ff",
      "State": "REACHABLE"
    }
  ],
  "raw": "…"
}

The column names in each row are the column headings the router printed, which is why they are capitalised the way they are. The page polls this every 15 seconds, and the agent caches op-mode reads for 3 seconds, so two open tabs do not double the load on the router — agent/opmode.go (handleNeighbors), agent/cache.go.

The parser slices rows on the column offsets given by the dashed rule under the header rather than splitting on whitespace, because values contain spaces — and it counts offsets in characters rather than bytes, so a multibyte character earlier in a row does not shift every column after it — agent/parse.go (parseTable).

The columns#

ColumnWhat it is
Addressthe protocol address that was resolved
Interfacethe interface the answer came in on
Link layerthe hardware address that answered, or when there is none yet
Statethe kernel's neighbour state for the entry

Reading the State column#

The badge is coloured from the state text: green for REACHABLE and PERMANENT, red for FAILED and INCOMPLETE, grey for everything else.

StateWhat it means in practice
REACHABLEconfirmed recently; traffic to this address is going somewhere real
STALEit answered once and has not been confirmed since. Normal for a quiet host
DELAY, PROBEthe kernel is in the middle of re-confirming it
INCOMPLETEa request went out and nothing has answered yet
FAILEDnothing answered. The address is configured somewhere but nothing on that segment holds it
PERMANENTa static entry, added by hand

A FAILED entry for a gateway address is the fastest confirmation that an uplink is dead at layer 2 rather than upstream. A FAILED entry for a host you expected to be present usually means a VLAN mistake: the address is right, the segment is wrong.

An empty table is not an error. The cache fills as traffic flows, and the empty state says so and gives you the command to run on the router yourself:

show arp

What this table cannot tell you#

  • It is a cache, not an inventory. A host that has not spoken recently is not in it. Absence proves nothing.
  • It has no history. There is no record of which hardware address held an address yesterday, so it will not help you find a duplicate that has already resolved itself.
  • It is what show arp prints. The agent adds no second source and does not merge in the IPv6 neighbour table separately; whether IPv6 neighbours appear depends entirely on what that command outputs on the running base. Nothing on this page is IPv6-aware in its own right.
  • There is no "flush" and no "add static entry". Both are CLI work.

The other neighbour views#

The same GET /api/neighbors data appears on the Diagnostics page, where it sits beside LLDP — what the switches on the other end of each cable announce about themselves. When the question is which switch port is this, that is the better view; when the question is is this host alive on this segment, this one is enough. See Diagnostics → Neighbours.

See also#

  • Interfaces — the page this view belongs to.
  • Diagnostics → Neighbours — the same table beside LLDP.
  • Static routes — when the neighbour is a gateway, this is where its route lives.
  • DHCP — the lease table, which is the other list of who is on the segment, and the one with hostnames in it.

Checked against ui/src/pages/Interfaces.tsx, agent/opmode.go (handleNeighbors), agent/parse.go (parseTable), agent/cache.go, agent/main.go.

Updated 2026-09-02 manual network interfaces arp neighbours