287 lines
8.4 KiB
Plaintext
287 lines
8.4 KiB
Plaintext
|
#!/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
|