Date: Sat, 4 Oct 2025 16:23:22 +0000 (UTC) From: "Bjoern A. Zeeb" <bz@FreeBSD.org> To: =?UTF-8?Q?Dag-Erling_Sm=C3=B8rgrav?= <des@FreeBSD.org> Cc: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: Re: git: 5ead817c3b7a - main - rc: Teach netwait to wait for DAD Message-ID: <2r6r204q-qs32-70pq-rqn1-5s4p54r1385@mnoonqbm.arg> In-Reply-To: <202510020932.5929WpJi067756@gitrepo.freebsd.org> References: <202510020932.5929WpJi067756@gitrepo.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
This message is in MIME format. The first part should be readable text, while the remaining parts are likely unreadable without MIME-aware tools. --0-768921551-1759595003=:11296 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8BIT On Thu, 2 Oct 2025, Dag-Erling Smørgrav wrote: > The branch main has been updated by des: > > URL: https://cgit.FreeBSD.org/src/commit/?id=5ead817c3b7af6d6b5fea222ab144db2c3167b22 > > commit 5ead817c3b7af6d6b5fea222ab144db2c3167b22 > Author: Dag-Erling Smørgrav <des@FreeBSD.org> > AuthorDate: 2025-10-02 09:28:05 +0000 > Commit: Dag-Erling Smørgrav <des@FreeBSD.org> > CommitDate: 2025-10-02 09:31:16 +0000 > > rc: Teach netwait to wait for DAD > > In some configurations, especially in jails, it is possible for the > system to boot so fast that we end up launching daemons while duplicate > address detection is still ongoing. If that happens, said daemons may > fail to bind to IPv6 addresses, as they are still tentative. Teach the > netwait service to wait (up to 10 seconds, by default) for the tentative > flag to vanish. Why 10s? You should never have to wait longer than net.inet6.ip6.dad_count + 1 seconds. Also the extra variable netwait_dad_timeout really isn't necessary in that case if you use the sysctl. /bz > MFC after: 1 week > Reviewed by: olce > Differential Revision: https://reviews.freebsd.org/D51889 > --- > libexec/rc/rc.conf | 2 ++ > libexec/rc/rc.d/netwait | 84 ++++++++++++++++++++++++++++++++++-------------- > share/man/man5/rc.conf.5 | 24 +++++++++----- > 3 files changed, 78 insertions(+), 32 deletions(-) > > diff --git a/libexec/rc/rc.conf b/libexec/rc/rc.conf > index c354aec44430..2589e2614c35 100644 > --- a/libexec/rc/rc.conf > +++ b/libexec/rc/rc.conf > @@ -500,6 +500,8 @@ netwait_enable="NO" # Enable rc.d/netwait (or NO) > netwait_timeout="60" # Total number of seconds to perform pings. > #netwait_if="" # Wait for active link on each intf in this list. > netwait_if_timeout="30" # Total number of seconds to monitor link state. > +netwait_dad="NO" # Wait for DAD to complete > +netwait_dad_timeout="10" # Total number of seconds to wait for DAD. > > ### Miscellaneous network options: ### > icmp_bmcastecho="NO" # respond to broadcast ping packets > diff --git a/libexec/rc/rc.d/netwait b/libexec/rc/rc.d/netwait > index 3f374806d97c..b609440a2e4e 100755 > --- a/libexec/rc/rc.d/netwait > +++ b/libexec/rc/rc.d/netwait > @@ -2,12 +2,14 @@ > # > # PROVIDE: netwait > # REQUIRE: devd ipfw pf routing > -# KEYWORD: nojail > # > -# The netwait script helps handle two situations: > +# The netwait script helps handle three situations: > # - Systems with USB or other late-attaching network hardware which > # is initialized by devd events. The script waits for all the > # interfaces named in the netwait_if list to appear. > +# - Systems with IPv6 addresses, especially jails, where we need to > +# wait for DAD to complete before starting daemons, as they will > +# otherwise fail to bind to IN6ADDR_ANY. > # - Systems with statically-configured IP addresses in rc.conf(5). > # The IP addresses in the netwait_ip list are pinged. The script > # waits for any single IP in the list to respond to the ping. If your > @@ -29,28 +31,36 @@ netwait_start() > { > local ip rc count output link wait_if got_if any_error > > - if [ -z "${netwait_if}" ] && [ -z "${netwait_ip}" ]; then > - err 1 "No interface or IP addresses listed, nothing to wait for" > + if [ -z "${netwait_if}" ] && [ -z "${netwait_ip}" ] && > + ! checkyesno netwait_dad ; then > + err 1 "Nothing to wait for" > fi > > - if [ ${netwait_timeout} -lt 1 ]; then > + if ! [ "${netwait_if_timeout}" -ge 1 ]; then > + err 1 "netwait_if_timeout must be >= 1" > + fi > + if ! [ "${netwait_dad_timeout}" -ge 1 ]; then > + err 1 "netwait_dad_timeout must be >= 1" > + fi > + if ! [ "${netwait_timeout}" -ge 1 ]; then > err 1 "netwait_timeout must be >= 1" > fi > > + any_error=false > + > if [ -n "${netwait_if}" ]; then > - any_error=0 > for wait_if in ${netwait_if}; do > echo -n "Waiting for ${wait_if}" > link="" > - got_if=0 > + got_if=false > count=1 > - # Handle SIGINT (Ctrl-C); force abort of while() loop > + # Handle SIGINT (Ctrl-C); force abort of while loop > trap break SIGINT > while [ ${count} -le ${netwait_if_timeout} ]; do > if output=`/sbin/ifconfig ${wait_if} 2>/dev/null`; then > - if [ ${got_if} -eq 0 ]; then > + if ! ${got_if}; then > echo -n ", interface present" > - got_if=1 > + got_if=true > fi > link=`expr "${output}" : '.*[[:blank:]]status: \(no carrier\)'` > if [ -z "${link}" ]; then > @@ -63,22 +73,45 @@ netwait_start() > done > # Restore default SIGINT handler > trap - SIGINT > - if [ ${got_if} -eq 0 ]; then > + if ! ${got_if}; then > echo ", wait failed: interface never appeared." > - any_error=1 > + any_error=true > elif [ -n "${link}" ]; then > echo ", wait failed: interface still has no link." > - any_error=1 > + any_error=true > fi > done > - if [ ${any_error} -eq 1 ]; then > - warn "Continuing with startup, but be aware you may not have " > - warn "a fully functional networking layer at this point." > - fi > fi > > + if checkyesno netwait_dad; then > + got_dad=false > + # Handle SIGINT (Ctrl-C); force abort of while loop > + trap break SIGINT > + > + echo -n "Waiting for DAD to complete" > + count=1 > + while [ ${count} -le ${netwait_dad_timeout} ]; do > + if ! ifconfig | grep -q 'inet6.*tentative'; then > + echo ', done.' > + got_dad=true > + break > + fi > + sleep 1 > + count=$((count+1)) > + done > + > + # Restore default SIGINT handler > + trap - SIGINT > + > + if ! ${got_dad}; then > + echo ', timed out.' > + any_error=true > + fi > + fi > + > if [ -n "${netwait_ip}" ]; then > - # Handle SIGINT (Ctrl-C); force abort of for() loop > + got_ip=false > + # Handle SIGINT (Ctrl-C); force abort of for loop > trap break SIGINT > > for ip in ${netwait_ip}; do > @@ -90,11 +123,9 @@ netwait_start() > rc=$? > > if [ $rc -eq 0 ]; then > - # Restore default SIGINT handler > - trap - SIGINT > - > echo ', got response.' > - return > + got_ip=false > + break 2 > fi > count=$((count+1)) > done > @@ -104,10 +135,15 @@ netwait_start() > # Restore default SIGINT handler > trap - SIGINT > > - warn "Exhausted IP list. Continuing with startup, but be aware you may" > - warn "not have a fully functional networking layer at this point." > + if ! ${got_ip}; then > + any_error=true > + fi > fi > > + if ${any_error}; then > + warn "Continuing with startup, but be aware you may not have " > + warn "a fully functional networking layer at this point." > + fi > } > > load_rc_config $name > diff --git a/share/man/man5/rc.conf.5 b/share/man/man5/rc.conf.5 > index b8c72fc07083..c0048f27c740 100644 > --- a/share/man/man5/rc.conf.5 > +++ b/share/man/man5/rc.conf.5 > @@ -22,7 +22,7 @@ > .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > .\" SUCH DAMAGE. > .\" > -.Dd September 25, 2025 > +.Dd October 2, 2025 > .Dt RC.CONF 5 > .Os > .Sh NAME > @@ -4563,20 +4563,16 @@ If set to > .Dq Li YES , > delays the start of network-reliant services until > .Va netwait_if > -is up and ICMP packets to a destination defined in > +is up, duplicate address discovery (DAD) has completed, and ICMP > +packets to a destination defined in > .Va netwait_ip > are flowing. > -Link state is examined first, followed by > +Link state is examined first, followed by DAD, then > .Dq Li pinging > an IP address to verify network usability. > If no destination can be reached or timeouts are exceeded, > network services are started anyway with no guarantee that > the network is usable. > -Use of this variable requires both > -.Va netwait_ip > -and > -.Va netwait_if > -to be set. > .It Va netwait_ip > .Pq Vt str > Empty by default. > @@ -4612,6 +4608,18 @@ interface if desired. > Defines the total number of seconds to wait for link to become usable, > polled at a 1-second interval. > The default is 30. > +.It Va netwait_dad > +.Pq Vt str > +Set to > +.Dq Li NO > +by default. > +Set to > +.Dq Li YES > +to enable waiting for DAD to complete. > +.It Va netwait_dad_timeout > +.Pq Vt int > +Indicates the total number of seconds to wait for DAD to complete. > +The default is 10. > .It Va rctl_enable > .Pq Vt bool > If set to > -- Bjoern A. Zeeb r15:7 --0-768921551-1759595003=:11296--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?2r6r204q-qs32-70pq-rqn1-5s4p54r1385>