Posted by nferrier on Tue 14 Jun 2005 at 15:43
When you're using bonded ethernet interfaces (2 or more cards bound to a single IP address) it can be difficult to manage addresses. Multiple sites might have different IP networks and that means different interfaces files for each site.
This is a scheme that allows you to use DHCP to allow ifupdown to automatically work out which interfaces it should add to a bond.
The idea is that you configure 2 interfaces from the same machine into the local DHCP (each interface will have a different IP address as normal) and then use the script included here to setup the bond.
.Here is an example interfaces file. This should go into /etc/network/interfaces
#### Setup and standard stuff.
auto lo bond0
#### Iface specifications
iface lo inet loopback
iface bond0 inet dhcp
pre-up /etc/network/scripts/bond-init bond0 10.1 10.2 10.3 192.168.1
#### End
This interface file is designed to bring up a bonded interface with any interfaces it finds attached to a network beginning:
Here's how bond-init works.
And here's the source
#!/bin/sh
# Initialize bonding for at most 2 eths connected to one of a range of
# networks.
# Copyright (C) 2005 Tapsell-Ferrier Limited
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING. If not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
# Arg1 is the interface name to bond
# Other args are net patterns.
# What's a net pattern?
# A net pattern is a string pattern that identifies the beginning
# fragment of a network address that is to be bonded.
# Example of using bond-init
# You can't really use bond-init from the command line because it will
# trash your existing interfaces (unless they are already bonded).
#
# You can choose to do this:
#
# DEBUG=1 bond-init bond0 192.168.1 10.18
#
# That just outputs the bonding statements to stderr.
#
# The normal way to use bond-init though is in the pre-up of the
# interfaces file:
#
# iface bond0 inet dhcp
# pre-up bond-init bond0 192.168.1 10.18
# up route add -net 172.25.0.0 netmask 255.255.0.0 dev bond0
DEBUG=${DEBUG:-0}
function list_eths
{
ifconfig -a | awk '/^eth[0-9]/ { print $1 }'
}
function make_dhscript
{
# This script is so small we may as well create it ourselves
cat < /tmp/ethselect-dhscript
#!/bin/sh
echo \$new_ip_address
EOF
chmod u+x /tmp/ethselect-dhscript
}
function get_dhcp_address
{
# Uses DHCP to get the address which is written to stdout.
IF=$1
# Record the current "up or down" status of the interface
ifconfig | grep -qs -e "^$IF"
ifstate=$?
# Bring up the interface if it isn't already
[ $ifstate -eq 0 ] || ifconfig $IF up
# Make the DHCP script if it's not available
[ -f /tmp/ethselect-dhscript ] || make_dhscript
# Get the address from DHCP
dhclient3 -n -sf /tmp/ethselect-dhscript \
-lf /var/lib/dhcp3/ethselect.${IF}.leases \
-pf /var/run/ethselect.${IF}.pid ${IF} 2> /dev/null
# Belt and braces
DHCP_PID=$!
if [ $? -eq 0 ]
then
if [ -f /var/run/ethselect.${IF}.pid ]
then
kill -QUIT `cat /var/run/ethselect.${IF}.pid`
rm /var/run/ethselect.${IF}.pid
else
kill -QUIT $DHCP_PID
fi
fi
# Don't want to do this if the card was already up...
[ $ifstate -eq 0 ] || ifconfig $IF down
}
function bond_up
{
# Bring up the bonded interface
# Arg 1 is the bond interface, other args are the eths we need to bond
to_bond=$1
shift
ifconfig $to_bond up
for eth in $*
do
ifconfig $eth up
done
ifenslave $to_bond $*
exit $?
}
### Main program
# First arg is the bonding iface name
iface=$1
shift
# The list of cards that match the netpattern
matching_cards=""
# DHCP for the addresses
for card in `list_eths`
do
addr=`get_dhcp_address $card`
# addr will be something like 10.18.0.22
for netpattern in $*
do
echo $addr | grep -qs $netpattern
if [ $? -eq 0 ]
then
# If the card matches then add it to the list
matching_cards="$matching_cards $card"
break
fi
done
# If we have two matching cards that's enough
echo $matching_cards | grep -qs ' '
[ $? -eq 0 ] && bond_up $iface $matching_cards
done
# We might have just one card in which case bring it up with just one
[ "$matching_cards" == "" ] || bond_up $iface $matching_cards
# End
Important Caveats
If you mix bonded and normal interfaces, eg:
auto lo eth1 eth4 bond0
the bonded interface should always be referenced last otherwise other interface ups might trash the bonding.
This article can be found online at the Debian Administration website at the following bookmarkable URL (along with associated comments):
This article is copyright 2005 nferrier - please ask for permission to republish or translate.