Skip to content

Told the application of a failed IPv6 address only once it is removed - #494

Merged
fdesbiens merged 1 commit into
devfrom
fix/ipv6-dad-failure-notify
Oct 18, 2026
Merged

fdesbiens merged 1 commit into
devfrom
fix/ipv6-dad-failure-notify

Conversation

@fdesbiens

Copy link
Copy Markdown
Contributor

Problem

When duplicate address detection fails, _nx_icmpv6_DAD_failure marks the address invalid
(nx_icmpv6_DAD_failure.c:87), calls the application's address change callback with
NX_IPV6_ADDRESS_DAD_FAILURE (:96), and only then removes the address from its interface's
address list (:105, :116).

The callback runs on the IP thread, and the user guide puts no restriction on what it may do. If it
sends to a multicast group joined on that interface, _nxd_ipv6_interface_find takes the head of the
interface's address list as the source, finds the address just marked invalid, and fails
NX_ASSERT((*ipv6_addr) -> nxd_ipv6_address_valid) (nxd_ipv6_interface_find.c:122).
NX_ASSERT_FAIL sleeps forever, so the IP thread stops and the IP instance is dead.

Reproduced on dev in v6_full_build: the callback's nxd_udp_socket_send never returns and the IP
thread is left in TX_SLEEP (state 4). The same in v6_full_secure_build.

The other address change callbacks were checked: DAD success, stateless address configuration,
prefix expiry, manual set and delete, and the IPv4 ones all call after the change is complete.

Change

The callback is made after the address has been removed from the list, with the same arguments.
The DHCPv6 client and netx_icmpv6_DAD_test, the existing users, record the index and address and
wake a thread, and neither depends on the address still being on the list.

Test

netx_ipv6_dad_failure_notify_send_test: one IP instance sets an address another already owns, so
detection fails; its callback sends to a group joined on that interface. The test checks that the
callback returns and that the IP instance still answers a ping. It fails without the change and
passes with it. It runs where NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY and NX_ENABLE_IPV6_MULTICAST
are both set (v6_full_build, v6_full_secure_build) and reports N/A elsewhere.

Control on dev: without the change the test fails in v6_full_build and
v6_full_secure_build; with it, it passes. netx_icmpv6_DAD_test, which checks the DAD failure
notification itself, passes with the change in v6_full_build, v6_full_secure_build,
v6_address_change_build, v6_build and v6_dhcp_tahi_build.

Sweep: the new test ran five times in all 43 NetX Duo configurations. Result: 10 pass
(v6_full_build, v6_full_secure_build), 205 report N/A, 0 failures — exactly the configurations
with and without both features.

When duplicate address detection fails, _nx_icmpv6_DAD_failure marks the
address invalid, calls the application's address change callback with
NX_IPV6_ADDRESS_DAD_FAILURE, and only then removes the address from its
interface's address list. The callback runs on the IP thread and is
free to send. A send to a multicast group joined on that interface looks
for a source address at the head of the interface's list, finds the
address just marked invalid, and fails the NX_ASSERT in
_nxd_ipv6_interface_find that such an address is never there. The IP
thread then sleeps forever and the IP instance is dead.

Measured on dev in v6_full_build: the callback's nxd_udp_socket_send never
returns and the IP thread is left in TX_SLEEP. No other address change
callback runs with the address half changed; DAD success, stateless
configuration, prefix expiry, manual set and delete, and the IPv4 ones
all call after the change is complete.

The callback is now made after the address is off the list, with the same
arguments. Its existing users -- the DHCPv6 client and
netx_icmpv6_DAD_test -- record the index and address and wake a thread,
and both are unchanged by the move. The product file header is
unchanged.

netx_ipv6_dad_failure_notify_send_test sets on one IP instance an address
another already owns, sends from the callback to a group joined on the
interface, and checks that the callback returns and the IP instance still
answers a ping. Without the change it fails; with it, it passes.

Assisted-by: Claude Code (Opus 5.5) <noreply@anthropic.com>
@fdesbiens
fdesbiens merged commit 9609e85 into dev Oct 18, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant