VyOSI · Networking Foundations for Routing EngineersLayer 2 and Layer 3 foundations
ARP vs NDP — neighbour discovery at Layer 2 / Layer 3, IPv4 and IPv6 side by side
What you'll learn
- Describe ARP for IPv4 and NDP for IPv6 message by message
- Explain why NDP runs over ICMPv6 link-local multicast, not broadcast
- Read the Linux neighbour table for both families
- Apply the right VyOS configuration knob for each family — proxy-arp, arp-cache-timeout, IPv6 ND options
- Recognise the IPv4 vs IPv6 neighbour-resolution failure modes
Prerequisites
Verified against VyOS 1.5.x LTS (circinus) · VyOS 1.4.x (sagitta) — legacy · FRRouting 10.x (VyOS 1.5) · Linux kernel 6.6 LTS (VyOS 1.5 base) · strongSwan 5.9.x (IPsec) · WireGuard 1.0.x (kernel module + userspace tooling) · 2026-08-15
ARP and NDP do the same job for two different address families. ARP turns an IPv4 next-hop into a MAC. NDP turns an IPv6 next-hop into a MAC. Both produce an entry in the Linux neighbour table that the kernel reads on every outgoing packet. Both can fail in ways that look like routing failures but are not.
The routing engineer needs both. An estate running IPv4 only needs ARP. An estate running dual-stack needs both. An estate running IPv6 only — increasingly common in operator circles — needs only NDP but still needs to understand why the link-local multicast behaves the way it does.
ARP for IPv4
ARP is a two-message protocol. The host broadcasts an ARP request asking “who has IP X?” The owner of X replies with an ARP reply containing its MAC. The kernel caches the result in the neighbour table.
sequenceDiagram
autonumber
participant H as Host (sender)
participant N as Next-hop host
H->>N: ARP Request (broadcast: who has 192.0.2.1? tell 192.0.2.50)
N->>H: ARP Reply (unicast: 192.0.2.1 is at aa:bb:cc:11:22:33)
Note over H: kernel caches aa:bb:cc:11:22:33 for 192.0.2.1
The ARP packet is encapsulated directly in an Ethernet frame
with ethertype 0x0806. There is no IP header. The ARP message
carries the sender IP and MAC, the target IP and MAC (unknown
in the request, filled in the reply), and the operation code
(request = 1, reply = 2).
ARP is a broadcast protocol. The request goes to the broadcast
MAC ff:ff:ff:ff:ff:ff, which every host on the segment
receives. The reply is unicast. This is the source of one of
ARP’s biggest limitations: ARP requests scale linearly with the
number of hosts on a segment, and the broadcast is unbounded.
NDP for IPv6
NDP replaces ARP for IPv6. NDP uses ICMPv6 messages
(ethertype 0x86DD for IPv6, protocol 58 for ICMPv6) carried
over multicast — not broadcast. The five NDP messages:
| Type | Code | Purpose |
|---|---|---|
| Neighbor Solicitation (NS) | 135 | “Who has this IPv6 address?” |
| Neighbor Advertisement (NA) | 136 | “I have this IPv6 address, here is my MAC” |
| Router Solicitation (RS) | 133 | Host asking the router for Router Advertisements |
| Router Advertisement (RA) | 134 | Router announcing prefixes and parameters |
| Redirect | 137 | Router telling host about a better first hop |
sequenceDiagram
autonumber
participant H as Host (sender)
participant N as Next-hop host
H->>N: NS (multicast to ff02::1 / solicited-node multicast of 2001:db8::1)
N->>H: NA (unicast: 2001:db8::1 is at aa:bb:cc:11:22:33)
Note over H: kernel caches aa:bb:cc:11:22:33 for 2001:db8::1
The NS is sent to the solicited-node multicast address, which
is ff02::1:ffXX:XXXX where the last 24 bits are the last 24
bits of the target IPv6 address. This is more efficient than
broadcast: only hosts whose address ends in those bits actually
process the NS.
The NA is unicast back to the requester. The kernel caches the result in the neighbour table.
Reading the neighbour table for both families
The Linux kernel maintains a single neighbour table that
contains entries for both IPv4 and IPv6. The ip neigh command
shows both:
ip -s neigh show dev eth0
The output looks like:
192.0.2.1 dev eth0 lladdr aa:bb:cc:11:22:33 REACHABLE
fe80::1 dev eth0 lladdr 00:11:22:33:44:55 router STALE
2001:db8::1 dev eth0 lladdr aa:bb:cc:11:22:33 REACHABLE
192.0.2.254 dev eth0 lladdr dd:ee:ff:00:11:22 STALE
The columns are family-agnostic: the state, the device, the link-layer address (MAC), and the state.
The IPv6-specific information is in ip -6 neigh show. The
Linux kernel also exposes ndisc6 for explicit IPv6 neighbour
discovery from the operator’s shell.
ndisc6 fe80::1 eth0
ndisc6 2001:db8::1 eth0
These send an NS for the target and report what came back. The
result is the equivalent of arping for IPv4.
VyOS configuration knobs
VyOS exposes per-interface knobs for both families:
configure
# IPv4
set interfaces ethernet eth0 ip enable-arp
set interfaces ethernet eth0 ip arp-cache-timeout 1800
set interfaces ethernet eth0 ip proxy-arp
set interfaces ethernet eth0 ip alias-address 192.0.2.65
# IPv6
set interfaces ethernet eth0 ipv6 address autoconfig
set interfaces ethernet eth0 ipv6 dup-addr-detect-transmits 1
set interfaces ethernet eth0 ipv6 router-advert cur-hop-limit 64
commit
save
The IPv4 knobs:
enable-arp— whether the interface answers ARP requests (defaults to true)arp-cache-timeout— kernelneigh_unreachable_timefor entries on this interfaceproxy-arp— whether the interface responds to ARP requests for IPs it does not own (a security-sensitive setting)alias-address— secondary IP address on the interface
The IPv6 knobs:
ipv6 address autoconfig— enable SLAACdup-addr-detect-transmits— DAD attempts before claiming an addressrouter-advert— Router Advertisement configuration (prefix, lifetime, DNS server, etc.)
Failure modes
ARP failures
| Symptom | Likely cause |
|---|---|
connect: network is unreachable to an IP on the local segment | The neighbour entry is FAILED or missing. ARP requests have no reply. |
| Intermittent connectivity to a previously-working host | Stale MAC entry. The host changed its NIC or chassis. |
| ARP request storm on the segment | A misconfigured device is broadcasting ARP requests continuously. |
| One-way connectivity | ARP works from one direction but not the other (often a firewall blocking ICMP / ARP replies selectively). |
NDP failures
| Symptom | Likely cause |
|---|---|
connect: network is unreachable to an IPv6 address on the local segment | NS has no reply. Often a misconfigured accept-redirects, forwarding, or accept-ra flag on the host. |
| IPv6 host has link-local but no global address | DAD failed or RA was not received. Check sysctl net.ipv6.conf.eth0.accept_ra. |
| Router advertisement missing | set interfaces ethernet eth0 ipv6 router-advert send-advert is not configured, or RA filtering is blocking on the host. |
| RA accepting but no global address | DAD is failing — duplicate address on the segment. |
What the routing engineer has to remember
| Concern | ARP (IPv4) | NDP (IPv6) |
|---|---|---|
| Protocol | 802.3/Ethernet, ethertype 0x0806 | IPv6, ICMPv6 type 135/136 |
| Encapsulation | Direct on Ethernet | Inside IPv6 |
| Scope | Local segment (broadcast) | Local segment (multicast) |
| Solicit-message | ARP request | Neighbor Solicitation (NS) |
| Solicit target | Broadcast | Solicited-node multicast |
| Reply | ARP reply (unicast) | Neighbor Advertisement (unicast) |
| Router role | Default gateway learned via DHCP / static | Default gateway learned via Router Advertisement |
| Linux command | ip neigh, arping | ip -6 neigh, ndisc6 |
| Capture | tcpdump -ni eth0 arp | tcpdump -ni eth0 'icmp6' |
The routing engineer who knows the IPv4 column but not the IPv6 column will struggle to diagnose IPv6 incidents. The two columns look similar but the failure modes are different — especially the multicast-based NDP, which behaves subtly differently from broadcast-based ARP.
Validation
The diagnostic sequence when IPv4 or IPv6 traffic is not flowing on the local segment:
# Both families
ip -s neigh show dev eth0
tcpdump -nei eth0 -c 20
# IPv4 specifically
arping -c 3 -I eth0 192.0.2.1
# IPv6 specifically
ndisc6 fe80::1 eth0
tcpdump -nei eth0 -c 20 'icmp6'
arping and ndisc6 are the canonical debug tools for sending
a single ARP or NS and reporting the result. The tcpdump
captures the wire-level evidence.
Cross-course references
- The Linux course’s
XIX-Linux-NetFoundationscovers the neighbour subsystem from the host perspective. - The OPNsense course covers the FreeBSD-specific
arpandndptools, with the equivalent FreeBSD behaviour for proxy-ARP and NDP. - The lesson on Ethernet, MAC and ARP (Part I, lesson 01) covers the kernel neighbour subsystem in greater depth.
Quiz
Knowledge check · 4 questions
Q1. An IPv6 host has a link-local address but cannot reach the IPv6 default gateway. IPv4 to the same gateway works. What is the most likely cause?
Host-A on a dual-stack LAN has working IPv4 connectivity but no IPv6 connectivity beyond the link-local. The host received a Router Advertisement (it has a global IPv6 address from SLAAC) but cannot ping the gateway's global IPv6 address.
Q2. Which message type is the NDP equivalent of an ARP request?
Q3. NDP Neighbor Solicitations are sent to a solicited-node multicast address rather than to the broadcast address.
Q4. A VyOS router has proxy-arp enabled on an interface. The router is now answering ARP requests for IPs it does not own. What is the most likely production consequence?
R1 has proxy-arp on eth0. A host on eth0 sends an ARP request for an IP that is actually on the other side of the router (eth1). With proxy-arp on, R1 replies with its own MAC. The host sends the packet to R1's MAC. R1 forwards the packet correctly. Connectivity works. Until R1 loses connectivity to eth1 — at which point R1 blackholes all traffic to that IP.
Passing score: 75%. Answers are checked in this browser.
Production discipline
ARP and NDP are the two protocols that make routing work. Either failing makes routing look broken even when the routing table is correct. The operator who diagnoses routing incidents without first reading the neighbour table is the operator who opens the wrong ticket every time.
Plan the neighbour-table configuration once. Document the proxy-arp decisions. Validate the IPv6 accept_ra settings on hosts. Then routing and neighbour resolution either work or fail predictably.