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:
{
"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#
| Column | What it is |
|---|---|
| Address | the protocol address that was resolved |
| Interface | the interface the answer came in on |
| Link layer | the hardware address that answered, or — when there is none yet |
| State | the 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.
| State | What it means in practice |
|---|---|
REACHABLE | confirmed recently; traffic to this address is going somewhere real |
STALE | it answered once and has not been confirmed since. Normal for a quiet host |
DELAY, PROBE | the kernel is in the middle of re-confirming it |
INCOMPLETE | a request went out and nothing has answered yet |
FAILED | nothing answered. The address is configured somewhere but nothing on that segment holds it |
PERMANENT | a 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 arpWhat 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 arpprints. 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.