Created
September 3, 2014 14:12
-
-
Save jgrassler/7283f812bf69985f4c84 to your computer and use it in GitHub Desktop.
Alternative to ifenslave-2.6 for setting up ether bonding
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# 2014, j.grassler@syseleven.de | |
# This script is mostly /etc/network/if-pre-up.d/ifenslave with the deadlocks | |
# and some flexibility ripped out. It is meant to be called as pre-up script for a | |
# bonding interface. Make sure not to set any bond-master or bond-slaves | |
# directives in /etc/network/interfaces to prevent the regular ifenslave script | |
# from interfering. Feel free to set other bonding related options. This script | |
# will honour them in the same manner as the regular ifenslave script. In | |
# addition it will honour the following extra options: | |
# | |
# mtu the interface's MTU. | |
# | |
# All command line arguments are treated as slave interfaces to add to the | |
# bonding interfaces. | |
# | |
# interfaces(5) usage example: | |
# | |
# auto eth0 # First bond slave | |
# iface eth0 inet static | |
# address 0.0.0.0 | |
# | |
# iface eth1 inet static # First bond slave | |
# address 0.0.0.0 | |
# | |
# auto bond0 | |
# iface bond0 inet static | |
# mtu 4000 | |
# up /etc/network/local/sys11bonding | |
[ "$VERBOSITY" = 1 ] && set -x | |
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)" | |
for i in $(seq 50); do | |
if [ -r /sys/class/net/bonding_masters ]; then | |
FAILED=0 | |
break | |
fi | |
sleep 0.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 wich 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 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 | |
} | |
setup_master() | |
{ | |
# Warning: the order in wich 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" | |
# 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 | |
if [ -n "$IF_MTU" ]; then | |
ip link set dev $BOND_MASTER mtu $IF_MTU | |
else | |
ip link set dev $BOND_MASTER up | |
fi | |
} | |
BOND_MASTER=${IFACE} | |
SLAVES=$* | |
if [ $MODE = 'start' ]; then | |
add_master # creates bond0 device | |
setup_master # sets device options in sysfs | |
ifenslave ${IFACE} ${SLAVES} # Adds slaves to device | |
touch /run/network/ifenslave.$BOND_MASTER | |
else | |
exit 0 # Make sure we only take action when interfaces are brought up. | |
fi | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment