Why can't ndisc6 update the kernel neighbor table?
Aug 4
I've been doing some work with ARP/NDP and discovered that ndisc6 doesn't update the neighbor table (unlike arping).
arping example:
192.168.0.14 is configured on a device connected to a VLAN member so we are able to resolve its address.
root@ubuntu:/# ip neigh show 192.168.0.14
root@ubuntu:/# arping 192.168.0.14 -i Vlan1000
ARPING 192.168.0.14
60 bytes from ca:6c:4c:92:85:1c (192.168.0.14): index=0 time=38.088 msec
60 bytes from ca:6c:4c:92:85:1c (192.168.0.14): index=1 time=84.431 msec
60 bytes from ca:6c:4c:92:85:1c (192.168.0.14): index=2 time=119.154 msec
60 bytes from ca:6c:4c:92:85:1c (192.168.0.14): index=3 time=53.739 msec
^C
--- 192.168.0.14 statistics ---
4 packets transmitted, 4 packets received, 0% unanswered (0 extra)
rtt min/avg/max/std-dev = 38.088/73.853/119.154/31.015 ms
root@ubuntu:/# ip neigh show 192.168.0.14
192.168.0.14 dev Vlan1000 lladdr ca:6c:4c:92:85:1c REACHABLE
As you can see, arping is able to add a new entry into the kernel neighbor table as shown by ip neigh
For the analogous IPv6 example, ndisc6 cannot accomplish this:
root@ubuntu:/# ip neigh show fc02:1000::3
root@ubuntu:/# ndisc6 fc02:1000::3 Vlan1000
Soliciting fc02:1000::3 (fc02:1000::3) on Vlan1000...
Target link-layer address: CA:58:C2:5F:7C:02
from fc02:1000::3
root@ubuntu:/# ip neigh show fc02:1000::3
root@ubuntu:/#
fc02:1000::3 is a similarly valid IP address configured on a device connected to a VLAN member. Despite receiving a valid neighbor advertisement message, the kernel neighbor table is not update as shown by the empty output from ip neigh
I have also found a reference to someone else seeing the same issue in the comments to this answer but without any explanation as to why.
1 answer
Accepted answer · original discussion
Sep 5
This behavior is by design and is not a problem with ndisc6 specifically nor is it an issue with kernel/userspace separation. According to RFC 4861 (NDP)
When a valid Neighbor Advertisement is received (either solicited or unsolicited), the Neighbor Cache is searched for the target's entry. If no entry exists, the advertisement SHOULD be silently discarded. There is no need to create an entry if none exists, since the recipient has apparently not initiated any communication with the target.
In my case, because I had not tried to communicate with the target IPv6 address prior to running ndisc6, the NA message received by the kernel was ignored. Newer versions of the Linux kernel include the accept_untracked_na parameter which allows this behavior to be adjusted:
Define behavior for accepting neighbor advertisements from devices that are absent in the neighbor cache:
0 - (default) Do not accept unsolicited and untracked neighbor advertisements.
1 - Add a new neighbor cache entry in STALE state for routers on receiving a neighbor advertisement (either solicited or unsolicited) with target link-layer address option specified if no neighbor entry is already present for the advertised IPv6 address. Without this knob, NAs received for untracked addresses (absent in neighbor cache) are silently ignored.
This is as per router-side behavior documented in RFC9131.
This has lower precedence than drop_unsolicited_na.
This will optimize the return path for the initial off-link communication that is initiated by a directly connected host, by ensuring that the first-hop router which turns on this setting doesn’t have to buffer the initial return packets to do neighbor-solicitation. The prerequisite is that the host is configured to send unsolicited neighbor advertisements on interface bringup. This setting should be used in conjunction with the ndisc_notify setting on the host to satisfy this prerequisite.
2 - Extend option (1) to add a new neighbor cache entry only if the source IP address is in the same subnet as an address configured on the interface that received the neighbor advertisement.
1 question comment
Use comments to ask for clarification. Post a solution as an answer.
Aug 4