From owner-svn-src-head@freebsd.org Sat Dec 26 18:21:34 2015 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 6C318A53B35; Sat, 26 Dec 2015 18:21:34 +0000 (UTC) (envelope-from ian@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 25F66132A; Sat, 26 Dec 2015 18:21:34 +0000 (UTC) (envelope-from ian@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id tBQILX62021863; Sat, 26 Dec 2015 18:21:33 GMT (envelope-from ian@FreeBSD.org) Received: (from ian@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id tBQILWmg021860; Sat, 26 Dec 2015 18:21:32 GMT (envelope-from ian@FreeBSD.org) Message-Id: <201512261821.tBQILWmg021860@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ian set sender to ian@FreeBSD.org using -f From: Ian Lepore Date: Sat, 26 Dec 2015 18:21:32 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r292752 - in head/etc: defaults rc.d X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 26 Dec 2015 18:21:34 -0000 Author: ian Date: Sat Dec 26 18:21:32 2015 New Revision: 292752 URL: https://svnweb.freebsd.org/changeset/base/292752 Log: Enhance rc.d/netwait script to wait for late-attaching interfaces such as USB NICs. USB network hardware may not be enumerated and available when the rc.d networking scripts run. Eventually the USB attachment completes and devd events cause the network initialization to happen, but by then other rc.d scripts have already failed, because services which depend on NETWORKING (such as mountcritremote) may end up running before the network is actually ready. There is an existing netwait script, but because it is dependent on NETWORKING it runs too late to prevent failure of some other rc scripts. This change flips the order so that NETWORKING depends on netwait, and netwait now depends on devd and routing (the former is needed to make interfaces appear, and the latter is needed to run the ping tests in netwait). The netwait script used to be oriented primarily towards "as soon as any host is reachable the network is fully functional", so you gave it a list of IPs to try and you could optionally name an interface and it would wait for carrier on that interface. That functionality still works the same, but now you can provide a list of interfaces to wait for and it waits until each one of them is available. The ping logic still completes as soon as the first IP on the list responds. These changes were submitted by Brenden Molloy in PR 205186, and lightly modified by me to allow a list of interfaces instead of just one. PR: 205186 Differential Revision: https://reviews.freebsd.org/D4608 (timeout w/o review) Modified: head/etc/defaults/rc.conf head/etc/rc.d/NETWORKING head/etc/rc.d/netwait Modified: head/etc/defaults/rc.conf ============================================================================== --- head/etc/defaults/rc.conf Sat Dec 26 17:27:48 2015 (r292751) +++ head/etc/defaults/rc.conf Sat Dec 26 18:21:32 2015 (r292752) @@ -439,9 +439,9 @@ ubthidhci_enable="NO" # Switch an USB B ### Network link/usability verification options netwait_enable="NO" # Enable rc.d/netwait (or NO) -#netwait_ip="" # IP addresses to be pinged by netwait. +#netwait_ip="" # Wait for ping response from any IP in this list. netwait_timeout="60" # Total number of seconds to perform pings. -#netwait_if="" # Interface name to watch link state on. +#netwait_if="" # Wait for active link on each intf in this list. netwait_if_timeout="30" # Total number of seconds to monitor link state. ### Miscellaneous network options: ### Modified: head/etc/rc.d/NETWORKING ============================================================================== --- head/etc/rc.d/NETWORKING Sat Dec 26 17:27:48 2015 (r292751) +++ head/etc/rc.d/NETWORKING Sat Dec 26 18:21:32 2015 (r292752) @@ -4,7 +4,7 @@ # # PROVIDE: NETWORKING NETWORK -# REQUIRE: netif netoptions routing ppp ipfw stf +# REQUIRE: netif netwait netoptions routing ppp ipfw stf # REQUIRE: defaultroute routed route6d mroute6d resolv bridge # REQUIRE: static_arp static_ndp Modified: head/etc/rc.d/netwait ============================================================================== --- head/etc/rc.d/netwait Sat Dec 26 17:27:48 2015 (r292751) +++ head/etc/rc.d/netwait Sat Dec 26 18:21:32 2015 (r292752) @@ -3,13 +3,20 @@ # $FreeBSD$ # # PROVIDE: netwait -# REQUIRE: NETWORKING +# REQUIRE: devd routing # KEYWORD: nojail # -# The netwait script is intended to be used by systems which have -# statically-configured IP addresses in rc.conf(5). If your system -# uses DHCP, you should use synchronous_dhclient="YES" in your -# /etc/rc.conf instead of using netwait. +# The netwait script helps handle two 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 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 +# system uses DHCP, you should probably use synchronous_dhclient="YES" +# in your /etc/rc.conf instead of netwait_ip. +# Either or both of the wait lists can be used (at least one must be +# non-empty if netwait is enabled). . /etc/rc.subr @@ -21,77 +28,87 @@ stop_cmd=":" netwait_start() { - local ip rc count output link + local ip rc count output link wait_if got_if any_error - if [ -z "${netwait_ip}" ]; then - err 1 "You must define one or more IP addresses in netwait_ip" + if [ -z "${netwait_if}" ] && [ -z "${netwait_ip}" ]; then + err 1 "No interface or IP addresses listed, nothing to wait for" fi if [ ${netwait_timeout} -lt 1 ]; then err 1 "netwait_timeout must be >= 1" fi - # Handle SIGINT (Ctrl-C); force abort of while() loop - trap break SIGINT - if [ -n "${netwait_if}" ]; then - echo -n "Waiting for $netwait_if to have link" - - count=1 - while [ ${count} -le ${netwait_if_timeout} ]; do - if output=`/sbin/ifconfig ${netwait_if} 2>/dev/null`; then - link=`expr "${output}" : '.*[[:blank:]]status: \(no carrier\)'` - if [ -z "${link}" ]; then - echo '.' - break + any_error=0 + for wait_if in ${netwait_if}; do + echo -n "Waiting for ${wait_if}" + link="" + got_if=0 + count=1 + # 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 + echo -n ", interface present" + got_if=1 + fi + link=`expr "${output}" : '.*[[:blank:]]status: \(no carrier\)'` + if [ -z "${link}" ]; then + echo ', got link.' + break + fi fi - else - echo '' - err 1 "ifconfig ${netwait_if} failed" - fi - sleep 1 - count=$((count+1)) - done - if [ -n "${link}" ]; then + sleep 1 + count=$((count+1)) + done # Restore default SIGINT handler trap - SIGINT - - echo '' - warn "Interface still has no link. Continuing with startup, but" - warn "be aware you may not have a fully functional networking" - warn "layer at this point." - return + if [ ${got_if} -eq 0 ]; then + echo ", wait failed: interface never appeared." + any_error=1 + elif [ -n "${link}" ]; then + echo ", wait failed: interface still has no link." + any_error=1 + 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 [ -n "${netwait_ip}" ]; then + # Handle SIGINT (Ctrl-C); force abort of for() loop + trap break SIGINT + + for ip in ${netwait_ip}; do + echo -n "Waiting for ${ip} to respond to ICMP ping" + + count=1 + while [ ${count} -le ${netwait_timeout} ]; do + /sbin/ping -t 1 -c 1 -o ${ip} >/dev/null 2>&1 + rc=$? + + if [ $rc -eq 0 ]; then + # Restore default SIGINT handler + trap - SIGINT - # Handle SIGINT (Ctrl-C); force abort of while() loop - trap break SIGINT - - for ip in ${netwait_ip}; do - echo -n "Waiting for ${ip} to respond to ICMP" - - count=1 - while [ ${count} -le ${netwait_timeout} ]; do - /sbin/ping -t 1 -c 1 -o ${ip} >/dev/null 2>&1 - rc=$? - - if [ $rc -eq 0 ]; then - # Restore default SIGINT handler - trap - SIGINT - - echo '.' - return - fi - count=$((count+1)) + echo ', got response.' + return + fi + count=$((count+1)) + done + echo ', failed: No response from host.' done - echo ': No response from host.' - done - # Restore default SIGINT handler - trap - SIGINT + # 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." + fi - warn "Exhausted IP list. Continuing with startup, but be aware you may" - warn "not have a fully functional networking layer at this point." } load_rc_config $name