mkinitrd unification across distributions
 help / color / mirror / Atom feed
From: Seewer Philippe <philippe.seewer-omB+W0Dpw2o@public.gmane.org>
To: David Dillow <dave-i1Mk8JYDVaaSihdK6806/g@public.gmane.org>
Cc: initramfs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [RFC ONLY 5/5] PROOF-OF-CONCEPT: wait for spanning tree timeout via arping
Date: Tue, 7 Jul 2009 10:08:55 +0200	[thread overview]
Message-ID: <4A530297.1020906@bfh.ch> (raw)
In-Reply-To: <8cf3d034e4611fbe661d4585fbfd1a03a6fd094b.1246656269.git.dave-i1Mk8JYDVaaSihdK6806/g@public.gmane.org>

David Dillow wrote:
> When operating on a switch running a spanning tree, it can take up to
> 100 seconds for our port to start forwarding traffic after comming up.
> Normally, this can be eaten by DHCP's request for an IP, but if we have
> a static configuration or need to down the interface to change the MTU, we
> will have to eat the timeout again.
> 
> Most of the network root protocols will timeout while waiting for traffic
> to flow again in this case, so we use ARP pings to determine when the
> link is available prior to trying the mount/disk login.

For the record: I've had a (much simpler, but not as generic as this
one) arping solution active in our production environment for a week and
the few cases that actually still use slow STP are solved.

So yes, this works.

(Some comments below)

> ---
>  modules.d/40network/dhclient-script |   11 ++++--
>  modules.d/40network/ifup            |    8 +++-
>  modules.d/40network/install         |    2 +-
>  modules.d/40network/netroot         |   67 +++++++++++++++++++++++++++++------
>  modules.d/95iscsi/iscsiroot         |   28 +++++++++-----
>  modules.d/95nbd/nbdroot             |   12 +++++--
>  modules.d/95nfs/nfsroot             |    9 +++--
>  7 files changed, 104 insertions(+), 33 deletions(-)
> 
> diff --git a/modules.d/40network/dhclient-script b/modules.d/40network/dhclient-script
> index 5b36a40..e440df9 100755
> --- a/modules.d/40network/dhclient-script
> +++ b/modules.d/40network/dhclient-script
> @@ -13,15 +13,20 @@ setup_interface() {
>  
>      [ -f /tmp/net.$netif.override ] && . /tmp/net.$netif.override
>  
> +    echo mynet=$ip/$mask > /tmp/net.$netif.up
> +

Please don't do this. $ip/$mask is in .override so we don't need
more variables.

>      if [ -n "$mtu" ] ; then
>  	echo ip link set $netif down
>  	echo ip link set $netif mtu $mtu
>  	echo ip link set $netif up
> -    fi > /tmp/net.$netif.up
> +    fi >> /tmp/net.$netif.up
>  
> -    echo ip addr add $ip${mask:+/$mask} ${bcast:+broadcast $bcast} dev $netif >> /tmp/net.$netif.up
> +    echo ip addr add $ip/$mask ${bcast:+broadcast $bcast} dev $netif >> /tmp/net.$netif.up
>  
> -    [ -n "$gw" ] && echo ip route add default via $gw dev $netif > /tmp/net.$netif.gw
> +    if [ -n "$gw" ]; then
> +	echo gw=$gw > /tmp/net.$netif.gw
> +	echo ip route add default via $gw dev $netif >> /tmp/net.$netif.gw
> +    fi

Same here, this information is in .dhcpopts There's no need to store 
them twice

>  
>      [ -n "${search}${domain}" ] && echo search $search $domain > /tmp/net.$netif.resolv.conf
>      if  [ -n "$namesrv" ] ; then
> diff --git a/modules.d/40network/ifup b/modules.d/40network/ifup
> index 89017bb..404d6d8 100755
> --- a/modules.d/40network/ifup
> +++ b/modules.d/40network/ifup
> @@ -32,13 +32,17 @@ do_dhcp() {
>  
>  # Handle static ip configuration
>  do_static() {
> -{
> +    {
> +	echo mynet=$ip/$mask

And again...

>  	echo ip link set $netif up 
>  	echo ip addr flush dev $netif
>  	echo ip addr add $ip/$mask dev $netif
>      } > /tmp/net.$netif.up
>  
> -    [ -n "$gw" ] && echo ip route add default via $gw dev $netif > /tmp/net.$netif.gw
> +    if [ -n "$gw" ]; then
> +	 echo gw=$gw > /tmp/net.$netif.gw
> +	 echo ip route add default via $gw dev $netif >> /tmp/net.$netif.gw
> +    fi
>      [ -n "$hostname" ] && echo hostname $hostname > /tmp/net.$netif.hostname
>  
>      echo online > /sys/class/net/$netif/uevent
> diff --git a/modules.d/40network/install b/modules.d/40network/install
> index 0b76cbd..20e8963 100755
> --- a/modules.d/40network/install
> +++ b/modules.d/40network/install
> @@ -1,5 +1,5 @@
>  #!/bin/bash
> -dracut_install ip dhclient hostname
> +dracut_install ip dhclient hostname arping date
>  # Include wired net drivers, excluding wireless
>  for modname in $(find "/lib/modules/$kernel/kernel/drivers" -name '*.ko'); do
>    if nm -uPA $modname | grep -q eth_type_trans; then
> diff --git a/modules.d/40network/netroot b/modules.d/40network/netroot
> index 2cf51fa..58bbd2e 100755
> --- a/modules.d/40network/netroot
> +++ b/modules.d/40network/netroot
> @@ -1,5 +1,29 @@
>  #!/bin/sh
>  
> +apply_mask() {
> +    local ip=$1
> +    local mask=$2
> +    local out i
> +
> +    for i in 1 2 3 4; do
> +	out=$out.$(( ${ip%%.*} & ${mask%%.*} ))
> +	ip=${ip#*.}
> +	mask=${mask#*.}
> +    done
> +    echo ${out#.}
> +}
> +
> +is_local() {
> +    local server=$1
> +    local mynet=$2
> +    local mask net
> +
> +    mask=${mynet#*/}
> +    mynet=$(apply_mask ${mynet%/*} $mask)
> +    net=$(apply_mask $server $mask)
> +    [ "$net" = "$mynet" ]
> +}
> +
>  PATH=$PATH:/sbin:/usr/sbin
>  
>  . /lib/dracut-lib.sh
> @@ -75,8 +99,10 @@ if [ -z "$netroot" ] || [ ! -e "$handler" ] ; then
>      die "No handler for netroot type '$netroot'"
>  fi
>  
> -# Now that we have DHCP information, we can fully validate netroot
> -$handler checkdhcp $netroot "$server_id" "$new_root_path" || exit 1
> +# Now that we have DHCP information, we can get our server
> +$handler server $netroot "$server_id" "$new_root_path" || exit 1
> +[ -s /tmp/server ] || die "Bug in $handler: did not create /tmp/server"
> +read target < /tmp/server
>  
>  # We're here, so we can assume that upping interfaces is now ok
>  [ -z "$IFACES" ] && IFACES="$netif"
> @@ -88,8 +114,21 @@ done
>  [ -e /tmp/net.$netif.hostname ]    && . /tmp/net.$netif.hostname
>  [ -e /tmp/net.$netif.resolv.conf ] && cp -f /tmp/net.$netif.resolv.conf /etc/resolv.conf
>  
> +# Wait for traffic to be passable before we continue
> +is_local $target $mynet || target=$gw
> +
> +# FIXME make 120 configurable
> +TIMEOUT=$(( $(date +%s) + 120 ))

Is 120 seconds really necessary? I've worked with 60 seconds and haven't
had any problems, even when specifically provoking STP with ip down/up 
before issuing arping.

Something else: If we really have to use 120 seconds and/or do this on 
multiple interface we might run into the default udev event timeout of 
180 seconds. Netroot should be moved into the new initqueue in that case.

> +while [ -z "$proceed" -a $(date +%s) -lt $TIMEOUT ]; do
> +    for iface in $IFACES; do
> +	arping -q -f -c 1 -I $iface $target && proceed=1 && break
> +    done
> +done

Just so that I understand you correctly: You're trying to arping on all
interfaces until one says OK? 

If we have multiple interface to up before mount/login, we should take care 
to try and enable all interfaces:

for iface in $IFACES; do
  is_local $gw $mask && local_target=$gw
  is_local $server $mask && local_target=$server

  [ -z "local_target" ] && continue;

  arping -q -f -w $TIMEOUT -I $iface $local_target || die "Unable to ARP ping $local_target via "$iface"
done

> +
>  # Run the handler to mount/login into the root device
> -if $handler mount "$netroot" "$server_id" "$new_root_path" $NEWROOT; then
> +if [ -n "$proceed" ] &&
> +	$handler mount "$netroot" "$server_id" "$new_root_path" $NEWROOT;
> +then
>      # Network rootfs mount successful
>      for iface in $IFACES ; do
>  	[ -f /tmp/dhclient.$iface.lease ] &&    cp /tmp/dhclient.$iface.lease    /tmp/net.$iface.lease
> @@ -98,14 +137,20 @@ if $handler mount "$netroot" "$server_id" "$new_root_path" $NEWROOT; then
>  
>      # Save used netif for later use
>      [ ! -f /tmp/net.ifaces ] && echo $netif > /tmp/net.ifaces
> -else 
> +    exit 0
> +fi
> +
> +if [ -n "$proceed" ]; then
>      warn "Mounting root via '$netif' failed"
> -    # If we're trying with multiple interfaces, put that one down.
> -    # ip down/flush ensures that routeing info goes away as well
> -    if [ -z "$BOOTDEV" ] ; then
> -	ip link set $netif down
> -	ip addr flush dev $netif
> -	echo "#empty" > /etc/resolv.conf
> -    fi
> +else
> +    warn "Unable to ARP ping $target via $netif"
> +fi
> +
> +# If we're trying with multiple interfaces, put that one down.
> +# ip down/flush ensures that routeing info goes away as well
> +if [ -z "$BOOTDEV" ] ; then
> +    ip link set $netif down
> +    ip addr flush dev $netif
> +    echo "#empty" > /etc/resolv.conf
>  fi
>  exit 0

I'd suggest to move [ -n "$proceed" ] to before mount/login and just do 
[ -z "$proceed" ] && die "..."

that way loose the if/else.

> diff --git a/modules.d/95iscsi/iscsiroot b/modules.d/95iscsi/iscsiroot
> index d79b663..7f2efa2 100755
> --- a/modules.d/95iscsi/iscsiroot
> +++ b/modules.d/95iscsi/iscsiroot
> @@ -17,9 +17,10 @@ if getarg rdnetdebug; then
>  fi
>  
>  case "$1" in
> -    check|checkdhcp)	check_only=1 ;;
> -    mount)		;;
> -    *)			die "$0 called with invalid command '$1'" ;;
> +    check)	check_only=1 ;;
> +    server)	server_only=1 ;;
> +    mount)	;;
> +    *)		die "$0 called with invalid command '$1'" ;;
>  esac
>  
>  # root is in the form
> @@ -55,13 +56,6 @@ if [ ! -e /sys/devices/virtual/iscsi_transport ]; then
>      fi
>  fi
>  
> -[ -n "$check_only" ] && exit 0
> -
> -if getarg iscsi_firmware ; then
> -	iscsistart -b
> -	exit 0
> -fi
> -
>  # override conf settings by command line options
>  arg=$(getarg iscsi_initiator)
>  [ -n "$arg" ] && iscsi_initiator=$arg
> @@ -100,6 +94,20 @@ iscsi_lun=$1; shift
>  iscsi_target_name=$*
>  IFS="$OLDIFS"
>  
> +[ -n "$check_only" ] && exit 0
> +
> +# FIXME need support for service discovery if no server given, or
> +# parsing the firmware tables for an IP if iscsi_firmware is in effect
> +if [ -n "$server_only" ]; then
> +    echo $iscsi_target_ip > /tmp/server
> +    exit 0
> +fi
> +
> +if getarg iscsi_firmware ; then
> +	iscsistart -b
> +	exit 0
> +fi
> +
>  # XXX is this needed?
>  getarg ro && iscsirw=ro
>  getarg rw && iscsirw=rw
> diff --git a/modules.d/95nbd/nbdroot b/modules.d/95nbd/nbdroot
> index 55c1b88..9450b84 100755
> --- a/modules.d/95nbd/nbdroot
> +++ b/modules.d/95nbd/nbdroot
> @@ -11,9 +11,10 @@ if getarg rdnetdebug; then
>  fi
>  
>  case "$1" in
> -    check|checkdhcp)	check_only=1 ;;
> -    mount)		;;
> -    *)			die "$0 called with invalid command '$1'" ;;
> +    check)	check_only=1 ;;
> +    server)	server_only=1 ;;
> +    mount)	;;
> +    *)		die "$0 called with invalid command '$1'" ;;
>  esac
>  
>  # root is in the form root=nbd:srv:port[:fstype[:rootflags[:nbdopts]]]
> @@ -52,6 +53,11 @@ incol2 /proc/devices nbd || modprobe nbd ||
>  [ -z "$nbdport" ] && die "NBD root configuration missing port"
>  [ -n "$check_only" ] && exit 0
>  
> +if [ -n "$server_only" ]; then
> +    echo $nbdserver > /tmp/server
> +    exit 0
> +fi
> +
>  # look through the NBD options and pull out the ones that need to
>  # go before the host etc. Append a ',' so we know we terminate the loop
>  nbdopts=${nbdopts},
> diff --git a/modules.d/95nfs/nfsroot b/modules.d/95nfs/nfsroot
> index 8cbfbb8..acfd6b5 100755
> --- a/modules.d/95nfs/nfsroot
> +++ b/modules.d/95nfs/nfsroot
> @@ -12,7 +12,7 @@ fi
>  
>  case "$1" in
>      check)	basic_check=1 ;;
> -    checkdhcp)	full_check=1 ;;
> +    server)	server_only=1 ;;
>      mount)	;;
>      *)		die "$0 called with invalid command '$1'" ;;
>  esac
> @@ -101,8 +101,11 @@ fi
>  [ -z "$server" ] && die "Required parameter 'server' is missing"
>  [ -z "$path" ] && die "NFS root requires a path"
>  
> -# If we're just validating our options, we're done
> -[ -n "$full_check" ] && exit 0
> +# If we're just looking for the server...
> +if [ -n "$server_only" ]; then
> +    echo $server > /tmp/server
> +    exit 0
> +fi
>  
>  # Kernel replaces first %s with host name, and falls back to the ip address
>  # if it isn't set. Only the first %s is substituted.
--
To unsubscribe from this list: send the line "unsubscribe initramfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

  parent reply	other threads:[~2009-07-07  8:08 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-07-03 21:40 [RFC ONLY 0/5] Move argument validation to root handlers David Dillow
     [not found] ` <cover.1246656269.git.dave-i1Mk8JYDVaaSihdK6806/g@public.gmane.org>
2009-07-03 21:40   ` [RFC ONLY 1/5] netroot: remove unused hook David Dillow
     [not found]     ` <bd4d79bc048ad3944156f86eafb62cf4bc29b1f9.1246656269.git.dave-i1Mk8JYDVaaSihdK6806/g@public.gmane.org>
2009-07-06 12:56       ` Seewer Philippe
2009-07-03 21:40   ` [RFC ONLY 2/5] netroot: remove unhelpful argument checks David Dillow
     [not found]     ` <0535c73bd25fdcaa9bf4de0bc4b041b74d11e547.1246656269.git.dave-i1Mk8JYDVaaSihdK6806/g@public.gmane.org>
2009-07-06 13:00       ` Seewer Philippe
2009-07-03 21:40   ` [RFC ONLY 3/5] netroot: remove netif from handler invocation David Dillow
     [not found]     ` <44494af931ad839908cb4542f7c35ae59a4ef65e.1246656269.git.dave-i1Mk8JYDVaaSihdK6806/g@public.gmane.org>
2009-07-06 13:56       ` Seewer Philippe
     [not found]         ` <4A520291.7010203-omB+W0Dpw2o@public.gmane.org>
2009-07-06 14:43           ` David Dillow
     [not found]             ` <1246891382.24010.6.camel-FqX9LgGZnHWDB2HL1qBt2PIbXMQ5te18@public.gmane.org>
2009-07-06 15:02               ` Seewer Philippe
     [not found]                 ` <4A521208.2050605-omB+W0Dpw2o@public.gmane.org>
2009-07-06 16:06                   ` David Dillow
     [not found]                     ` <1246896365.24010.14.camel-FqX9LgGZnHWDB2HL1qBt2PIbXMQ5te18@public.gmane.org>
2009-07-07  8:10                       ` Seewer Philippe
2009-07-03 21:40   ` [RFC ONLY 4/5] netroot: move dracut syntax validation to root handlers David Dillow
     [not found]     ` <d1aed501ae771d769efcd370f47184f12b9800d6.1246656269.git.dave-i1Mk8JYDVaaSihdK6806/g@public.gmane.org>
2009-07-07  7:47       ` Seewer Philippe
     [not found]         ` <4A52FD93.3000406-omB+W0Dpw2o@public.gmane.org>
2009-07-07 14:57           ` David Dillow
2009-07-03 21:40   ` [RFC ONLY 5/5] PROOF-OF-CONCEPT: wait for spanning tree timeout via arping David Dillow
     [not found]     ` <8cf3d034e4611fbe661d4585fbfd1a03a6fd094b.1246656269.git.dave-i1Mk8JYDVaaSihdK6806/g@public.gmane.org>
2009-07-07  8:08       ` Seewer Philippe [this message]
     [not found]         ` <4A530297.1020906-omB+W0Dpw2o@public.gmane.org>
2009-07-07 15:09           ` David Dillow

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4A530297.1020906@bfh.ch \
    --to=philippe.seewer-omb+w0dpw2o@public.gmane.org \
    --cc=dave-i1Mk8JYDVaaSihdK6806/g@public.gmane.org \
    --cc=initramfs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox