Page MenuHomeFreeBSD

nd6: Add support for Optimistic DAD (RFC 4429)
Needs ReviewPublic

Authored by pouria on Feb 10 2026, 6:55 PM.
Tags
None
Referenced Files
F156295132: D55229.diff
Tue, May 12, 6:57 AM
Unknown Object (File)
Sun, May 10, 4:22 AM
Unknown Object (File)
Sun, May 10, 4:16 AM
Unknown Object (File)
Sun, May 10, 4:12 AM
Unknown Object (File)
Sun, May 10, 4:07 AM
Unknown Object (File)
Sat, May 9, 9:16 PM
Unknown Object (File)
Sat, May 9, 9:11 PM
Unknown Object (File)
Tue, Apr 28, 4:02 AM

Details

Reviewers
zlei
bz
glebius
madpilot
melifaro
markj
Group Reviewers
network
Summary

Implement optimistic address based on
RFC 4429.
This revision is not really depends on D55015.
However, their IPV6CTL numbers could have
conflicts if I didn't use GRAND as parent commit.

Here is my notes to make reviewing easier.

note on ifconfig: since we don't want the user
to manually set the optimistic flag (RFC 4429 section 3.1),
I didn't update the ifconfig manual just like tentative flag.

note on RFC 4429 Sections:
2.1: done (in6_ifawithifp)
2.2.1: done (nd6_ns_input)
2.2.2: done (nd6_ns_output_fib)
2.3 + 3.2.4: partially without violation (nd6_ns_output_fib).
Since we don't directly have the source address of packet
during nd6_resolve.
I can't return lle of default router without reading
inside the mbuf to get our own source address, AND I don't
want to pullup the mbuf receiving in nd6_resolve.
However, this doesn't violate any rules and *rare* to happen.
if such situation happens, It will behave like before (tenative) if
and only if we don't have an ndp cache entry AND there is no
other address available to be source address of NS.
2.4 + 2.2.3: since RS only sends by rtsold(8), I will
fix it on another review.
In summary, rtsold complains when we don't have link-local
which is *rare* and *not default behavior*.
if link-local is not available it MAY send RS with optimistic
source if other addresses are not available. (rtsold/if.c:166).
3.1: done (in6_update_ifa_internal)
3.2: done
3.3: done

Test Plan

increase dad_count to delay removal of
optimistic flag from address, then enable optimistic
and slaac/tempaddr tunable together:

sysctl net.inet6.ip6.dad_count=10
sysctl net.inet6.ip6.use_optimistic=1
sysctl net.inet6.ip6.use_tempaddr=1

monitor packets via tcpdump -vni vtnet0 icmp6 to verify intended behavior.
You can manually set optimistic flag via ifconfig or restart the interface.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 72269
Build 69152: arc lint + arc unit

Event Timeline

Rebase to main. follow parent commit update and resolve conflict with a2eb0894b79b.

markj added inline comments.
sbin/ifconfig/af_inet6.c
736

Do these need to be documented in ifconfig.8?

usr.sbin/rtsold/if.c
166

Is this something that needs to be addressed in this diff?

sbin/ifconfig/af_inet6.c
736

I explained in summary above:
since we don't want the user to manually set the optimistic flag (RFC 4429 section 3.1), I didn't update the ifconfig manual just like tentative flag.

usr.sbin/rtsold/if.c
166

Not in this diff, I just added the comment for future. I explained this one in summary above too.
RFC 4429 2.4 + 2.2.3 said:
Never using an Optimistic Address as the source address of a Router Solicitation with a SLLAO.

Since RS only sends by rtsold(8), I'll fix it on another review.
In summary, rtsold complains when we don't have link-local which is *rare* and *not default behavior*.
if link-local is not available it MAY send RS with optimistic source if other addresses are not available. (rtsold/if.c:166).

I have been testing this patch on a couple of computers for over a week now, and everything seems to work fine (at least I see no regression).

@bz I would really appreciate it if you could review this when you have some free time.

LGTM. I am not overly familiar with DAD though but it got touched during the MLDv2 import due to its wide use of solicited-node multicast addresses.

The scope and intent are pretty clear and it's worth nothing that Sec. 2.2 calls out what's involved in the potential races/collisions:
https://datatracker.ietf.org/doc/html/rfc4429#section-2.2

There are other places where deeper mbuf inspection happens without necessarily having a clean path to do it. that is what m_getptr() is often used for...
Also there are probably still places where pullups are happening when they may not be necessary.

In D55229#1275984, @bms wrote:

LGTM. I am not overly familiar with DAD though but it got touched during the MLDv2 import due to its wide use of solicited-node multicast addresses.

Thank you!

The scope and intent are pretty clear and it's worth nothing that Sec. 2.2 calls out what's involved in the potential races/collisions:
https://datatracker.ietf.org/doc/html/rfc4429#section-2.2

I tried to carefully handle the 2.2 section to avoid any disruptions.

There are other places where deeper mbuf inspection happens without necessarily having a clean path to do it. that is what m_getptr() is often used for...
Also there are probably still places where pullups are happening when they may not be necessary.

I'll wait for another reviewer for at least another week to make sure everything is right.

pouria retitled this revision from ndp: Add support for Optimistic DAD (RFC 4429) to nd6: Add support for Optimistic DAD (RFC 4429).Apr 1 2026, 4:53 PM

Rebase to main and resolve conflicts.

Spent some time reading the RFC. I'm not sure how useful the Optimistic DAD feature will be. Normal DAD can finish within seconds, is not that enough ?

sbin/ifconfig/af_inet6.c
736

since we don't want the user to manually set the optimistic flag (RFC 4429 section 3.1)

Optimistic DAD SHOULD NOT be used for manually entered addresses

SHOULD NOT is strong enough, so setting the optimistic flag to an address via ifconfig(8) is a possible valid usage ?

Probably you want a nd6 option say OPTIMISTIC_DAD to control the Optimistic DAD behavior fine-grainedly ( I mean enable / disable the feature per interface ) ?

So the sysctl net.inet6.ip6.use_optimistic becomes a global / per vnet default . New interfaces inherent the default on attaching.

sys/netinet6/in6.c
1099

And also IN6_IFF_DEPRECATED ?

	ia->ia6_flags |= IN6_IFF_DEPRECATED | IN6_IFF_OPTIMISTIC;
2043

Quoted from https://www.rfc-editor.org/rfc/rfc4429#section-2.1 ,

Implementations should treat an address in state Optimistic as if it
were in state Deprecated. If address states are recorded as
individual flags, this can easily be achieved by also setting
'Deprecated' when 'Optimistic' is set

The above statement drive me to think an Optimistic address implies Deprecated.

Maybe in6_ifawithifp() can be simplified, so no need to check for IN6_IFF_OPTIMISTIC ?

Spent some time reading the RFC. I'm not sure how useful the Optimistic DAD feature will be. Normal DAD can finish within seconds, is not that enough ?

Thank you so much for your review and reading the rfc.

In IPv6, these features matters a lot.
You may remember the PRs for races in DAD vs daemons trying to bind its address during jail starts.
https://dan.langille.org/2023/03/10/is-your-jail-not-getting-an-ipv6-address-soon-enough-blame-dad/

There were a lot of cases that we have to set the dad_count=0 just to make sure that user daemons have their addresses available when they try to listen on it during startup.
This feature will resolve those issues.

Also, In contrast to IPv4, the probability of duplicate address is almost zero.
and as you know, In IPv6, there is no secondary address. (this was one of its biggest changes in IP principles)
It's normal to have more than hundreds of IPv6 addresses in production (per-VNET).
I've seen many production servers with ~6 IPv6 addresses per jail * ~100 jails per server.
Consider the consequences/races just by starting those jails in parallel.

sbin/ifconfig/af_inet6.c
736

SHOULD NOT is strong enough, so setting the optimistic flag to an address via ifconfig(8) is a possible valid usage ?

Probably you want a nd6 option say OPTIMISTIC_DAD to control the Optimistic DAD behavior fine-grainedly ( I mean enable / disable the feature per interface ) ?

Exactly.

So the sysctl net.inet6.ip6.use_optimistic becomes a global / per vnet default . New interfaces inherent the default on attaching.

You're right, I'm fine with removing this option on ifconfig/nd6.
I just thought it maybe useful.
So, you think we should remove that?

sys/netinet6/in6.c
1099

And also IN6_IFF_DEPRECATED ?

	ia->ia6_flags |= IN6_IFF_DEPRECATED | IN6_IFF_OPTIMISTIC;

I think you suggesting it because of section 2.1 as you noted below.
The problem is we treat DEPRECATED flags very differently.
I've tried to use IN6_IFF_DEPRECATED, I thought it may help with code reduction too.
but unfortunately, it needs more hacks/extra conditions on IN6_IFF_DEPRECATED than it saves.
Of course, with exception of in6_ifawithifp() you've noted below.

2043

Quoted from https://www.rfc-editor.org/rfc/rfc4429#section-2.1 ,

Implementations should treat an address in state Optimistic as if it
were in state Deprecated. If address states are recorded as
individual flags, this can easily be achieved by also setting
'Deprecated' when 'Optimistic' is set

The above statement drive me to think an Optimistic address implies Deprecated.

Maybe in6_ifawithifp() can be simplified, so no need to check for IN6_IFF_OPTIMISTIC ?

Yes we actually can!
The reasons for this extra optimistic part in in6_ifawithifp() was a question that I asked myself.
What would you choose between a real deprecated address vs optimistic address?
IMHO, I believe we should prioritize optimistic over real deprecated addresses.
But your point is completely valid and I can do as you said.