This site is now 100% read-only, and retired.

DHCP management of bonded eths with ifupdown

Posted by nferrier on Tue 14 Jun 2005 at 15:43

Tags: none.

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.

 

 


Re: DHCP management of bonded eths with ifupdown
Posted by kai1074 (157.27.xx.xx) on Mon 26 Mar 2007 at 14:39
Hello,
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 ]