Created
November 22, 2017 00:53
-
-
Save nickpegg/eaaa14f033d3fbd3d92101f9d28c8a7b to your computer and use it in GitHub Desktop.
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 | |
[ "$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 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 | |
} | |
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 usefull 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 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" | |
# 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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment