During link-layer address change event, don't send unsolicited
NA for multicast and linklocal addresses.
Details
Run:
kyua test -k /usr/tests/Kyuafile sys/netinet6
or simply change mac address of your interface:
ifconfig vtnet0 ether 11:22:33:44:55:66
Diff Detail
- Repository
- rG FreeBSD src repository
- Lint
Lint Not Applicable - Unit
Tests Not Applicable
Event Timeline
This change also fixes a panic produced in main from kyua tests.
[root@ftsr1] [~] # kyua --config /usr/local/etc/kyua.conf test -k /usr/tests/Kyuafile sys/net Results file id is usr_tests.20260316-214508-051017 Results saved to /root/.kyua/store/results.usr_tests.20260316-214508-051017.db 139/147 passed (0 broken, 2 failed, 6 skipped)
[root@ftsr1] [~] # kyua --config /usr/local/etc/kyua.conf test -k /usr/tests/Kyuafile sys/netinet6 Results file id is usr_tests.20260316-222610-373655 Results saved to /root/.kyua/store/results.usr_tests.20260316-222610-373655.db 83/84 passed (0 broken, 0 failed, 1 skipped)
| sys/netinet6/nd6.c | ||
|---|---|---|
| 243 | I think it is right to not send unsolicited NA for multicast address, but I expect the opposite for linklocal address. My local test show no unsolicited NA sent for linklocal address, hence the peer get stale ndp entry and can not reach after the ether address changed. That appears wrong to me. | |
In addition to comments:
If you check the pcap during grand, you'll see the grand itself will send its NA using link-local addresses.
Therefore, without GRAND, it should hint our NUD to update its NCE.
That is another reason for why our NUD is the problem not the GRAND.
Until I fix our NUD, I'll remove the link-local check for now.
| sys/netinet6/nd6.c | ||
|---|---|---|
| 243 |
Thank you for your test.
Ensuring whether the ndp cache is still valid or not is the job of NUD and as it's outlined in rfc9898, section 3.9: So, the primarily issue is forwarding delay from receive path. However, as you have already found out through your tests, our NUD implementation is not robust enough to detect such changes and may remain stuck in STALE for a long time. | |
The link-local check here is also redundant. You have already checked the scope of the address in nd6_grand_start(). So if the address is global one, it must not be a link-local one.
nd6_grand_start(struct ifaddr *ifa, uint32_t flags) { ... /* Check if new address is global */ if ((flags & ND6_QUEUE_FLAG_NEWGUA) != 0 && in6_addrscope(IFA_IN6(ifa)) != IPV6_ADDR_SCOPE_GLOBAL) return; ... }
Oh no, I reacted too fast, this shows I don't trust my own memory :)
This check only applies for new address event, not link-layer address change.