#!/bin/sh [ "$VERBOSITY" = 1 ] && set -x [ "$ADDRFAM" = meta ] && exit 0 add_master() { # Return if $BOND_MASTER is already a bonding interface. [ -f "/sys/class/net/$BOND_MASTER/bonding/slaves" ] && return # If the bonding module is not yet loaded, load it. if [ ! -r /sys/class/net/bonding_masters ]; then modprobe -q bonding FAILED=1 echo "Waiting for bonding kernel module to be ready (will timeout after 5s)" count=0 while [ "$count" -lt "50" ]; do if [ -r /sys/class/net/bonding_masters ]; then FAILED=0 break fi sleep 0.1 count=$(($count+1)) done if [ "$FAILED" = "1" ]; then echo "/sys/class/net/bonding_masters doesn't exist. Unable to create $BOND_MASTER" exit 1 fi fi # Create the master interface. if ! grep -sq "\\<$BOND_MASTER\\>" /sys/class/net/bonding_masters; then echo "+$BOND_MASTER" > /sys/class/net/bonding_masters fi } sysfs_change_down() { # Called with : # $1 = basename of the file in bonding/ to write to. # $2 = value to write. Won't write if $2 is empty. if [ "$2" ] ; then # If the value we plan to write is different from the current one... if ! grep -sq "\\<$2\\>" "/sys/class/net/$BOND_MASTER/bonding/$1" ; then # ...and the master is up... if ip link show "$BOND_MASTER" | grep -sq '[<,]UP[,>]' ; then # ...bring the master down. ip link set dev "$BOND_MASTER" down fi fi sysfs "$1" "$2" fi } sysfs() { # Called with : # $1 = basename of the file in bonding/ to write to. # $2 = value to write. Won't write if $2 is empty. if [ "$2" ] ; then echo "$2" > "/sys/class/net/$BOND_MASTER/bonding/$1" return $? fi return 0 } sysfs_add() { #??Called with : # $1 = target filename. # $2 = values to write. for value in $2; do # Do not add $2 to $1 if already present. if ! grep -sq "\\<$value\\>" /sys/class/net/$BOND_MASTER/bonding/$1 then sysfs "$1" "+$value" fi done } # early_setup_master is the place where we do master setup that need to be done before enslavement. early_setup_master() { # Warning: the order in which we write into the sysfs files is important. # Double check in drivers/net/bonding/bond_sysfs.c in linux kernel source tree # before changing anything here. # fail_over_mac must be set before enslavement of any slaves. sysfs fail_over_mac "$IF_BOND_FAIL_OVER_MAC" } # late_setup_master runs actions that need to happen after enslavement late_setup_master() { # primary must be set after mode (because only supported in some modes) and after enslavement. # The first slave in bond-primary found in current slaves becomes the primary. # If no slave in bond-primary is found, then the primary does not change. for slave in $IF_BOND_PRIMARY ; do if grep -sq "\\<$slave\\>" "/sys/class/net/$BOND_MASTER/bonding/slaves" ; then sysfs primary "$slave" break fi done # primary_reselect should be set after mode (because only supported in some modes), after enslavement # and after primary. This is currently (2.6.35-rc1) not enforced by the bonding driver, but it is # probably safer to do it in that order. sysfs primary_reselect "$IF_BOND_PRIMARY_RESELECT" # queue_id must be set after enslavement. for iface_queue_id in $IF_BOND_QUEUE_ID do sysfs iface_queue_id $iface_queue_id done # active_slave must be set after mode and after enslavement. # The slave must be up and the underlying link must be up too. # FIXME: We should have a way to write an empty string to active_slave, to set the active_slave to none. if [ "$IF_BOND_ACTIVE_SLAVE" ] ; then # Need to force interface up before. Bonding will refuse to activate a down interface. ip link set "$IF_BOND_ACTIVE_SLAVE" up sysfs active_slave "$IF_BOND_ACTIVE_SLAVE" fi } enslave_slaves() { case "$BOND_SLAVES" in none) BOND_SLAVES="" ;; all) BOND_SLAVES="" for device in /sys/class/net/*/device; do name=$(basename ${device%*/device}) [ -n "$BOND_SLAVES" ] && BOND_SLAVES="$BOND_SLAVES $name" || BOND_SLAVES="$name" done AUTOIF="yes" ;; esac [ "$VERBOSITY" = 1 ] && v=-v for slave in $BOND_SLAVES ; do if ( [ "$AUTOIF" ] && ifquery --state $slave ) ; then echo "Not enslaving interface $slave since it is already configured" else # Ensure $slave is down. ip link set "$slave" down 2>/dev/null if ! sysfs_add slaves "$slave" 2>/dev/null ; then echo "Failed to enslave $slave to $BOND_MASTER. Is $BOND_MASTER ready and a bonding interface ?" >&2 else # Bring up slave if it is the target of an allow-bondX stanza. # This is useful to bring up slaves that need extra setup. if [ -z "$(which ifquery)" ] || ifquery --allow \"$BOND_MASTER\" --list | grep -q $slave; then ifup $v --allow "$BOND_MASTER" "$slave" fi fi fi done } setup_master() { # Warning: the order in which we write into the sysfs files is important. # Double check in drivers/net/bonding/bond_sysfs.c in linux kernel source tree # before changing anything here. # use_carrier can be set anytime. sysfs use_carrier "$IF_BOND_USE_CARRIER" # num_grat_arp can be set anytime. sysfs num_grat_arp "$IF_BOND_NUM_GRAT_ARP" # num_unsol_na can be set anytime. sysfs num_unsol_na "$IF_BOND_NUM_UNSOL_NA" # xmit_hash_policy can be set anytime. # Changing xmit_hash_policy requires $BOND_MASTER to be down. sysfs_change_down xmit_hash_policy "$IF_BOND_XMIT_HASH_POLICY" # arp_ip_target must be set before arp_interval. sysfs_add arp_ip_target "$IF_BOND_ARP_IP_TARGET" sysfs arp_interval "$IF_BOND_ARP_INTERVAL" # miimon must be set before updelay and downdelay. sysfs miimon "$IF_BOND_MIIMON" sysfs downdelay "$IF_BOND_DOWNDELAY" sysfs updelay "$IF_BOND_UPDELAY" # Changing ad_select requires $BOND_MASTER to be down. sysfs_change_down ad_select "$IF_BOND_AD_SELECT" # Changing mode requires $BOND_MASTER to be down. # Mode should be set after miimon or arp_interval, to avoid a warning in syslog. sysfs_change_down mode "$IF_BOND_MODE" # packets_per_slave allowed for mode balance-rr only. sysfs packets_per_slave "$IF_BOND_PACKETS_PER_SLAVE" # arp_validate must be after mode (because mode must be active-backup). sysfs arp_validate "$IF_BOND_ARP_VALIDATE" # lacp_rate must be set after mode (because mode must be 802.3ad). # Changing lacp_rate requires $BOND_MASTER to be down. sysfs_change_down lacp_rate "$IF_BOND_LACP_RATE" # Finally bring the bond up, note that without a slave it won't be usable though ip link set dev $BOND_MASTER up } # Option slaves deprecated, replaced by bond-slaves, but still supported for backward compatibility. IF_BOND_SLAVES=${IF_BOND_SLAVES:-$IF_SLAVES} if [ "$IF_BOND_MASTER" ] ; then BOND_MASTER="$IF_BOND_MASTER" BOND_SLAVES="$IFACE" else if [ "$IF_BOND_SLAVES" ] ; then BOND_MASTER="$IFACE" BOND_SLAVES="$IF_BOND_SLAVES" fi fi # Exit if nothing to do... [ -z "$BOND_MASTER$BOND_SLAVES" ] && exit # Always try to create the master, returns if already exists add_master if [ "$BOND_MASTER" = "$IFACE" ]; then # Setup the master interface early_setup_master setup_master # Indicate that we're done setting up the master # this is required as ifstate is modified at the beginning # of the interface setup, not at the end touch /run/network/ifenslave.$IFACE # Wait for a slave to join, continuing without a slave # would make dhclient, vconfig or brctl fail, so better wait # Timeout after a minute FAILED=1 echo "Waiting for a slave to join $BOND_MASTER (will timeout after 60s)" count=0 while [ "$count" -lt "600" ]; do if [ -n "$(cat /sys/class/net/$BOND_MASTER/bonding/slaves)" ]; then FAILED=0 break fi sleep 0.1 count=$(($count+1)) done if [ "$FAILED" = "1" ]; then echo "No slave joined $BOND_MASTER, continuing anyway" else # Trigger the udev bridging hook to bridge the bond if needed if [ -x /lib/udev/bridge-network-interface ]; then INTERFACE=$BOND_MASTER /lib/udev/bridge-network-interface fi # Trigger the udev bridging hook to tag the bond if needed if [ -x /lib/udev/vlan-network-interface ]; then INTERFACE=$BOND_MASTER /lib/udev/vlan-network-interface fi fi else # Wait for the master to be ready [ ! -f /run/network/ifenslave.$BOND_MASTER ] && echo "Waiting for bond master $BOND_MASTER to be ready" while :; do if [ -f /run/network/ifenslave.$BOND_MASTER ]; then break fi sleep 0.1 done # Only setup one slave at once BOND_SLAVES=$IFACE enslave_slaves # Call late_setup_master every time we add a slave as we don't have a way to know # when all the slaves are up BOND_SLAVES=$IFACE late_setup_master fi exit 0