#!/bin/sh
#----------------------------------------------------------------------------
# /etc/init.d/bonding - create bonding devices
#
# Creation:       20.10.2004 babel
# Eisfair version 22.05.2005 jv
# Last Update:    $Id$
#
# Copyright (c) 2005 Fli4l/Eisfair Team
# Copyright (c) 2014-2014 Holger Bruenjes, holgerbruenjes(at)gmx(dot)net
#
# 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 of the License, or
# (at your option) any later version.
#----------------------------------------------------------------------------

. /etc/config.d/base
. /etc/config.d/bonding

# read functions
. /etc/init.d/functions

# ---------------------------------------------------------------------------
# usage
# ---------------------------------------------------------------------------
usage ()
{
cat <<EOF

 Usage:
 ${0}
                -q, --quiet      suppress all normal output
                [start]
                [stop]
                [status]
                [restart]
                [forcestart]

EOF
}

# ---------------------------------------------------------------------------
# check status of bonding
# ---------------------------------------------------------------------------
check_bonding_status()
{
    lsmod | grep -q 'bonding'
    return ${?}
}

# ---------------------------------------------------------------------------
# activate  bonding
# ---------------------------------------------------------------------------
bonding_start()
{
    if check_bonding_status
    then
        boot_mesg " * Bonding is already running ..." ${WARNING}
        echo_warning
        exit 0
    fi

    if "${start_force:-false}"
    then
        START_BONDING='yes'
    fi

    if [ "${START_BONDING}" = "yes" ]
    then
        boot_mesg " * Starting Bonding ..."
        # write pid file
        echo "$BONDING_N" > /run/bonding.pid
        # read config
        bond_idx=1
        while [ ${bond_idx} -le $BONDING_N ]
        do
            eval bond_mode='$BONDING_'${bond_idx}'_MODE'
            eval bond_ipaddr='$BONDING_'${bond_idx}'_IPADDR'
            eval bond_netmask='$BONDING_'${bond_idx}'_NETMASK'
            eval bond_gateway='$BONDING_'${bond_idx}'_GATEWAY'
            eval bond_mac='$BONDING_'${bond_idx}'_MAC'
            eval bond_devn='$BONDING_'${bond_idx}'_DEV_N'
            eval bond_arp_targets='$BONDING_'${bond_idx}'_ARP_IP_TARGET_N'
            eval bond_downdelay='$BONDING_'${bond_idx}'_DOWNDELAY'
            eval bond_miimon='$BONDING_'${bond_idx}'_MIIMON'
            eval bond_primary='$BONDING_'${bond_idx}'_PRIMARY'
            eval bond_updelay='$BONDING_'${bond_idx}'_UPDELAY'
            eval bond_use_carrier='$BONDING_'${bond_idx}'_USE_CARRIER'

            # create device name
            ndev=`/usr/bin/expr ${bond_idx} - 1`
            eval bond_dev_name='bond'$ndev

            # set default if empty
            : ${bond_ipaddr:=''}
            : ${bond_netmask:=''}
            : ${bond_gateway:=''}
            : ${bond_mac:=''}
            : ${bond_arp_targets:=0}
            : ${bond_downdelay:=0}
            : ${bond_updelay:=0}
            : ${bond_use_carrier:=yes}
            : ${bond_miimon:=100}

            bond_modparam="mode=$bond_mode"
            if [ $bond_downdelay -ne 0 ]
            then
                bond_downdelay=`/usr/bin/expr $bond_downdelay \* $bond_miimon`
                bond_modparam="$bond_modparam downdelay=$bond_downdelay"
            fi
            if [ $bond_updelay -ne 0 ]
            then
                bond_updelay=`/usr/bin/expr $bond_updelay \* $bond_miimon`
                bond_modparam="$bond_modparam updelay=$bond_updelay"
            fi

            [ $bond_use_carrier = no ] && bond_modparam="$bond_modparam use_carrier=0"
            [ $bond_primary ] && bond_modparam="$bond_modparam primary=$bond_primary"

            if [ $bond_mode = balance-rr -o $bond_mode = 0 -o $bond_mode = balance-xor -o $bond_mode = 2 ]
            then
                if [ $bond_arp_targets -gt 0 ]
                then
                    eval bond_arp_interval='$BONDING_'${bond_idx}'_ARP_INTERVAL'
                    : ${bond_arp_interval:=200}
                    bond_tmp_ip_targets=''
                    bond_ddx=1
                    while [ $bond_ddx -le $bond_arp_targets ]
                    do
                        [ $bond_ddx -gt 1 ] && bond_tmp_ip_targets="$bond_tmp_ip_targets,"
                        eval bond_tmp_ip_target=$\{BONDING_${bond_idx}_ARP_IP_TARGET_${bond_ddx}\}
                        bond_tmp_ip_targets="${bond_tmp_ip_targets}${bond_tmp_ip_target}"
                        bond_ddx=`/usr/bin/expr $bond_ddx + 1`
                    done
                    bond_modparam="$bond_modparam arp_interval=$bond_arp_interval arp_ip_target=$bond_tmp_ip_targets"
                else
                    bond_modparam="$bond_modparam miimon=$bond_miimon"
                fi
            else
                bond_modparam="$bond_modparam miimon=$bond_miimon"
            fi

            if [ $bond_mode = active-backup -o $bond_mode = 1 ]
            then
                [ ${bond_primary} ] && bond_modparam="${bond_modparam} primary=${bond_primary}"
            fi

            if [ $bond_mode = 802.3ad -o $bond_mode = 4 ]
            then
                eval bond_lacp_rate='$BONDING_'${bond_idx}'_LACP_RATE'
                : ${bond_lacp_rate:=slow}
                if [ $bond_lacp_rate = fast -o $bond_lacp_rate = 1 ]
                then
                    bond_modparam="${bond_modparam} lacp_rate=fast"
                fi
            fi

            # load kernelmodul
            modprobe bonding $bond_modparam
            #insmod bonding -o ${bond_dev_name} ${bond_modparam}  >/dev/null

            # set interface parameter
            if [ -n "$bond_mac" ]
            then
                ifconfig ${bond_dev_name} hw ether ${bond_mac}
            fi

            # set ip parameter if missing
            if [ -z "$bond_ipaddr" ]
            then
                bond_ipaddr="$IP_ETH_1_IPADDR"
            fi
            if [ -z "$bond_netmask" ]
            then
                bond_netmask="$IP_ETH_1_NETMASK"
            fi
            if [ -z "$bond_gateway" ]
            then
                bond_gateway="$IP_DEFAULT_GATEWAY"
            fi

            bond_brc=$(/usr/local/bin/netcalc broadcast ${bond_ipaddr} ${bond_netmask})
            #activat bond interface
            ifconfig ${bond_dev_name} ${bond_ipaddr} netmask ${bond_netmask} broadcast ${bond_brc} up

            eval bond_devn='$BONDING_'${bond_idx}'_DEV_N'
            bond_ddx=1
            while [ ${bond_ddx} -le ${bond_devn} ]
            do
                # putting down the network interface
                eval ifconfig $\{BONDING_${bond_idx}_DEV_${bond_ddx}\} down
                # set interface to bonding
                eval ifenslave $bond_dev_name $\{BONDING_${bond_idx}_DEV_${bond_ddx}\}
                bond_ddx=$(/usr/bin/expr ${bond_ddx} + 1)
            done

            # add new default gateway
            route add default gw ${bond_gateway}

            bond_idx=$(/usr/bin/expr ${bond_idx} + 1)
        done

        # for output
      #  check_bonding_status
        cat /proc/net/bonding/bond0 >/dev/null 2>&1
        evaluate_retval
    fi
}

# ---------------------------------------------------------------------------
# remove bonding
# ---------------------------------------------------------------------------
bonding_stop()
{
    if check_bonding_status
    then
        boot_mesg " * Stopping Bonding ... "

        # get count of bond interfaces
        if [ -f /run/bonding.pid ]
        then
            n_idx=`cat /run/bonding.pid`
        else
            n_idx=0
        fi

        bond_idx=1
        while [ ${bond_idx} -le $n_idx ]
        do
            # create device name
            ndev=`expr ${bond_idx} - 1`
            eval bond_dev_name='bond'$ndev
            # stop bond device
            ifconfig $bond_dev_name down
            bond_idx=$(/usr/bin/expr ${bond_idx} + 1)
        done

        # remove kernelmodul
        rmmod bonding
        evaluate_retval

        /etc/init.d/ip-eth start
        /etc/init.d/route start
    else
        if [ "$(tty)" != "/dev/console" ]
        then
            boot_mesg "Bonding is not runing ... " ${INFO}
            ${ECHO} -e "${NORMAL}"
        fi
    fi

    rm -f /run/bonding.pid
}

# ---------------------------------------------------------------------------
# restart
# ---------------------------------------------------------------------------
bonding_restart ()
{
    bonding_stop
    sleep 2
    bonding_start
}

# ---------------------------------------------------------------------------
# status
# ---------------------------------------------------------------------------
bonding_status ()
{
    if check_bonding_status
    then
        boot_mesg "Bonding is running ..." ${INFO}
        ${ECHO} -e -n "${NORMAL}"
        echo "-----------------------------------------------------------------------------"
        ifconfig bond0
        echo "-----------------------------------------------------------------------------"
   else
       boot_mesg "Bonding is not running ..." ${INFO}
       ${ECHO} -e -n "${NORMAL}"
   fi

}
# ---------------------------------------------------------------------------
# main
# ---------------------------------------------------------------------------
while [ "${#}" -gt 0 ]
do
    case "${1}" in
    --quiet)
        _quiet=true
        shift
        ;;
    *)
        _action="${1}"
        shift
        ;;
    esac
done


case "${_action}" in
    start)
        bonding_start
    ;;
    stop)
        bonding_stop
    ;;
    restart)
        bonding_restart
    ;;
    status)
        bonding_status
    ;;
    forcestart)
        start_force=true
        bonding_start
    ;;
    *)
        usage
        exit 1
    ;;
esac

exit 0
# ---------------------------------------------------------------------------
# end
# ---------------------------------------------------------------------------