Inspect and Safely Change Linux Neighbour Entries with ip neigh
ip neigh shows you exactly what the kernel believes about every device on the wire, and lets you fix a stale entry safely. You will inspect the neighbour table, query one address on a named interface, and make a narrowly scoped static entry when you have a verified reason. Linux calls the IPv4 version of this table the ARP table. The same commands also cover IPv6 neighbour discovery.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes for inspection and a little longer for a change. You need a shell and the iproute2 package. These examples were checked with iproute2 6.1.0, provided here as package version 6.1.0-1ubuntu6.4. Read-only commands normally run as your ordinary user. Adding, changing, deleting or flushing entries usually needs root, and can affect traffic immediately.
Checkpoint
If you only need to diagnose connectivity, stop after the read-only sections. Do not use flush as a general-purpose refresh command.
1. Confirm the installed command and interfaces
Check the executable, package version and the interface name you will use. This does not alter networking:
$ command -v ip
/usr/sbin/ip
$ ip -V
ip utility, iproute2-6.1.0, libbpf 1.3.0
$ dpkg-query -W -f='${Package} ${Version}\n' iproute2
iproute2 6.1.0-1ubuntu6.4
$ ip -brief link show
enp0s31f6 UP ...
docker0 UP ...
Replace INTERFACE below with an interface that actually carries the address you are investigating. Interface names are host-specific. A frequent mistake is to copy eth0 from an old example when this machine uses a predictable name such as enp0s31f6.
2. List the neighbour table
Start with the complete table. The command prints protocol address, device, link-layer address when known, and a neighbour state:
$ ip neigh show
192.0.2.1 dev INTERFACE lladdr 02:00:00:00:00:01 REACHABLE
2001:db8::1 dev INTERFACE lladdr 02:00:00:00:00:01 router STALE
The example addresses are documentation values, so your output will differ. IPv4 entries are commonly described as ARP entries, while IPv6 entries use neighbour discovery. The final word is the NUD state. REACHABLE is currently validated, STALE is usable but should be checked when next used, DELAY or PROBE indicates validation work, and FAILED means that probing ultimately failed. INCOMPLETE means resolution is still in progress.
By default, ip neigh shows entries except for the pseudo-state none and noarp. Filter by device or state when the full output is distracting:
$ ip neigh show dev INTERFACE
$ ip neigh show dev INTERFACE nud failed
$ ip neigh show dev INTERFACE nud all
Checkpoint
Verify that the selected address is attached to the expected device. An entry on the wrong interface is not fixed by changing its MAC address.
3. Query one address with ip neigh get
Use get when you want the kernel's neighbour lookup for one destination on one device:
$ ip neigh get 192.0.2.1 dev INTERFACE
192.0.2.1 dev INTERFACE lladdr 02:00:00:00:00:01 REACHABLE
This command is read-only, but the lookup can cause the kernel to resolve a missing neighbour. On a real network, that may send normal discovery traffic. The result may include router, and it may be INCOMPLETE or fail if the address cannot be resolved. If you do not know which interface owns the route, find that separately before querying:
$ ip route get 192.0.2.1
192.0.2.1 dev INTERFACE src 192.0.2.10
The route output is useful context, but it is not a substitute for the device argument required by ip neigh get.
4. Understand the state before changing it
nud means Neighbour Unreachability Detection. The installed command accepts permanent, noarp, stale, reachable, none, incomplete, delay, probe and failed. Do not force permanent merely to make a warning disappear. It prevents normal expiry and can leave a stale link-layer address in service until somebody removes it.
A normal dynamically learned entry is owned by the kernel's neighbour machinery. Manually changing or deleting a kernel-created noarp entry is specifically unsafe: the kernel may try to resolve an address on a NOARP interface, or an address that is multicast or broadcast. Treat that warning as a boundary, not as an invitation to retry with sudo.
5. Add a verified static entry
Only do this when you have independently verified both the protocol address and the link-layer address, and have a rollback command ready. Adding a neighbour entry changes live kernel state and normally needs elevated privileges:
$ sudo ip neigh replace 192.0.2.1 lladdr 02:00:00:00:00:01 nud permanent dev INTERFACE
$ ip neigh show 192.0.2.1 dev INTERFACE
192.0.2.1 dev INTERFACE lladdr 02:00:00:00:00:01 PERMANENT
replace adds the record when it is absent and updates it when it exists. That makes it suitable for an explicitly managed entry, but it can overwrite a dynamic binding if you select the wrong address or MAC. Use add when an existing entry should be rejected instead:
$ sudo ip neigh add 192.0.2.1 lladdr 02:00:00:00:00:01 nud permanent dev INTERFACE
Do not treat the example MAC address or documentation address as real values. Copying an unverified MAC can divert traffic to the wrong host. On a production system, make this change during a maintenance window if an incorrect neighbour entry could interrupt access.
6. Undo a manual entry
Remove the exact entry you created, again with elevated privileges:
$ sudo ip neigh del 192.0.2.1 dev INTERFACE
$ ip neigh show 192.0.2.1 dev INTERFACE
192.0.2.1 dev INTERFACE FAILED
The follow-up output is host-dependent. The entry may disappear, or a later lookup may recreate a dynamic result. The delete syntax accepts the same address and device context as the add form; lladdr and nud are ignored for deletion. If the address belongs to a kernel-managed noarp entry, do not force the operation. Restore the network's normal configuration instead.
Neighbour entries are normally runtime state. A reboot, interface recreation or network manager may remove a manual entry. If you need persistence, configure the system's network manager or provisioning layer using its documented mechanism, then test the resulting configuration. This guide does not edit those persistent files.
7. Filter or flush with a safety boundary
flush deletes matching entries. It does not run with no arguments, and its default states exclude permanent and noarp, but those defaults are not a safety guarantee. A broad flush can trigger resolution storms or disrupt active connections. Do not paste a flush command until you have inspected the matching set.
First preview the scope with the equivalent read-only show command:
$ ip neigh show dev INTERFACE nud failed
192.0.2.44 dev INTERFACE FAILED
$ sudo ip neigh flush dev INTERFACE nud failed -statistics
1 addresses deleted
1 rounds flushed
The count and wording vary. -statistics makes the flush verbose; supplying it twice also dumps deleted entries. Keep the filter as narrow as possible. Never use a remembered interface name or a whole-table command in an automated repair script without first proving its scope on the target host.
8. Diagnose the usual failures
If ip neigh get reports that the device is missing, check ip -brief link show and use the exact interface name. If the result is INCOMPLETE, the kernel has not resolved the neighbour yet; check link state, VLAN or bridge membership, addressing and the remote host rather than pinning a guessed MAC.
If the state becomes FAILED, compare the table with ip route get ADDRESS. A route through a different interface, a disconnected bridge, or a remote host that is offline can all produce an apparently mysterious neighbour failure. Capture the output before flushing it, because deletion removes useful evidence.
A non-zero status from an add, change or delete is a useful failure signal. Read the diagnostic, confirm the address and device, and check whether the command requires root. Privilege escalation cannot correct a wrong interface, invalid MAC address or unsafe kernel-managed entry.
Done means
- You confirmed the installed iproute2 version and the real interface name.
- You inspected the table and used
ip neigh getfor a specific lookup. - You can distinguish common NUD states from a missing route or interface.
- Any manual entry used independently verified values and a matching rollback command.
- Any flush was previewed with
showand restricted by device and state. - You know that runtime neighbour changes are not automatically persistent.