DHCP management of bonded eths with ifupdown
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:
- 10.1
- 10.2
- 10.3
- 192.168.1
Here's how bond-init works.
- it identifies all interfaces
- asks each interface to DHCP
- collects any address returned from the interface
- matches the addresses returned from the interfaces with the patterns specified on the command line
- if the pattern prefix matches more than one interface address the associated interfaces are bon enslaved
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.
I had the same problem (get IP address via dhcp on a bond0), and I solved it in this way:
1) create the following script:
!/bin/bash
#
# Activate physical interfaces before bonding
# Usage: $0 <bonding interface> [slave interfaces]
#
# By default, if no slave is specified, uses all ethernet
# interfaces available
#
# Stefano Cailotto [stefano.cailotto@spammersgohome]
#
bond_if="$1"
shift
[ "$*" != "" ] && slave_if="$*" || slave_if=$(ifconfig -a|grep eth|awk '{ print $1 }')
#activate slave interfaces
for iface in $slave_if; do
echo "Activating slave interface $iface"
ifconfig $iface up
#it seems it takes a bit for the interface to be really up...
sleep 1
done
#activate bonding inteface
ifconfig $bond_if up
#attach slave interfaces to bonding
echo "Enslaving interfaces $slave_if"
ifenslave $bond_if $slave_if
2)Edit your /etc/network/interfaces file like this:
auto bond0
iface bond0 inet dhcp
pre-up /etc/network/interfaces/scripts/upslaves.sh bond0 ethX ethY ethZ
down /sbin/ifenslave -d bond0 ethX ethY ethZ
using proper values for the desired eth interfaces.
Note that, as specified in bonding documentation bond0 takes the MAC of the firs t enslaved interface; to get correct dhcp server behaviour (in case of host declaration), create a number of entries equal to that of enslaved ethernet.
Stefano
[ Parent | Reply to this comment ]