From a6ce3e3dc0def6ca7ea46b07cf28b1cf292b108b Mon Sep 17 00:00:00 2001 From: John Klug Date: Mon, 13 Feb 2017 14:25:26 -0600 Subject: Add bonding ifup ifdown --- recipes-core/init-ifupdown/files/bonding.post-down | 67 ++++++++++ recipes-core/init-ifupdown/files/bonding.pre-up | 144 +++++++++++++++++++++ recipes-core/init-ifupdown/files/bonding.up | 45 +++++++ .../init-ifupdown/init-ifupdown_1.0.bbappend | 12 ++ 4 files changed, 268 insertions(+) create mode 100644 recipes-core/init-ifupdown/files/bonding.post-down create mode 100644 recipes-core/init-ifupdown/files/bonding.pre-up create mode 100644 recipes-core/init-ifupdown/files/bonding.up create mode 100644 recipes-core/init-ifupdown/init-ifupdown_1.0.bbappend diff --git a/recipes-core/init-ifupdown/files/bonding.post-down b/recipes-core/init-ifupdown/files/bonding.post-down new file mode 100644 index 0000000..13ed4fd --- /dev/null +++ b/recipes-core/init-ifupdown/files/bonding.post-down @@ -0,0 +1,67 @@ +#!/bin/sh + +[ "$IF_VERBOSITY" = 1 ] && set -x + +sysfs() +{ + # Called with : + # $1 = value to write. Won't write if $1 is empty. + # $2 = basename of the file in bonding/ to write to. + if [ "$1" ] ; then + echo "$1" > "/sys/class/net/$IFACE/master/bonding/$2" + return $? + fi + return 0 +} + +sysfs_remove_all() +{ + # Called with: + # $1 = target filename + read values < "/sys/class/net/$IFACE/bonding/$1" + for value in $values ; do + echo "-$value" > "/sys/class/net/$IFACE/bonding/$1" + done +} + +BOND_PARAMS="/sys/class/net/$IFACE/bonding" +IFSTATE=/var/run/ifstate + +# free $IFACE if it is currently enslaved to a bonding device. +if [ -f "/sys/class/net/$IFACE/master/bonding/slaves" ] ; then + echo "-$IFACE" > "/sys/class/net/$IFACE/master/bonding/slaves" + + # 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 and might be undefined if just removed. + for slave in $IF_BOND_PRIMARY ; do + if grep -sq "\\<$slave\\>" "/sys/class/net/$IFACE/master/bonding/slaves" ; then + sysfs "$slave" primary + break + fi + done +fi + +# If $IFACE is not a master, exit. +[ ! -f "$BOND_PARAMS/slaves" ] && exit + +# Unset multivalue sysfs entries, so that re-enabling the interface later won't cause error. + +sysfs_remove_all arp_ip_target + +# Remove any slaves of $IFACE. + +[ "$IF_VERBOSITY" = 1 ] && v=-v +read slaves < "$BOND_PARAMS/slaves" +for slave in $slaves ; do + # If $slave is currently up in $IFSTATE, then bring it down, to keep $IFSTATE consistent. + # This is supposed to have the side effect of freeing the interface. + grep -q "^$slave=" $IFSTATE && ifdown $v $slave + + # Anyway, ensure $slave is free. + if [ -f "/sys/class/net/$slave/master/bonding/slaves" ] ; then + echo "-$slave" > "$BOND_PARAMS/slaves" 2> /dev/null + fi +done + +# make sure that the link is set to down +ip link set dev $IFACE down diff --git a/recipes-core/init-ifupdown/files/bonding.pre-up b/recipes-core/init-ifupdown/files/bonding.pre-up new file mode 100644 index 0000000..39011b6 --- /dev/null +++ b/recipes-core/init-ifupdown/files/bonding.pre-up @@ -0,0 +1,144 @@ +#!/bin/sh + +[ "$IF_VERBOSITY" = 1 ] && set -x + +IFSTATE=/var/run/ifstate + +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 + 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() +{ + # Called with : + # $1 = value to write. Won't write if $1 is empty. + # $2 = basename of the file in bonding/ to write to. + if [ "$1" ] ; then + echo "$1" > "/sys/class/net/$BOND_MASTER/bonding/$2" + return $? + fi + return 0 +} + +sysfs_add() +{ + # Called with : + # $1 = values to write. + # $2 = target filename. + for value in $1; do + # Do not add $1 to $2 if already present. + if ! grep -sq "\\<$value\\>" /sys/class/net/$BOND_MASTER/bonding/$2 + then + sysfs "+$value" "$2" + fi + done +} + +ifup_once() +{ + local v= + [ "$IF_VERBOSITY" = 1 ] && v=-v + if [ "$1" != "$IFACE" ] && ! grep -q "^$1=" $IFSTATE && ifup -n "$1" >/dev/null 2>&1; then + ifup $v $1 + fi +} + +enslave_slaves() +{ + case "$BOND_SLAVES" in + none) + BOND_SLAVES="" + ;; + all) + BOND_SLAVES=`sed -ne 's/ *\(eth[^:]*\):.*/\1/p' /proc/net/dev` + AUTOIF="yes" + ;; + esac + + for slave in $BOND_SLAVES ; do + if ( [ "$AUTOIF" ] && grep -q "^$slave=" $IFSTATE ) ; 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 "$slave" slaves 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 defined in interfaces + # This is usefull to bring up slaves that need extra setup. + ifup_once $slave + fi + fi + done +} + +setup_master() +{ + sysfs "$IF_BOND_MODE" mode + sysfs "$IF_BOND_MIIMON" miimon + sysfs "$IF_BOND_USE_CARRIER" use_carrier + sysfs "$IF_BOND_UPDELAY" updelay + sysfs "$IF_BOND_DOWNDELAY" downdelay + sysfs "$IF_BOND_ARP_INTERVAL" arp_interval + sysfs "$IF_BOND_ARP_VALIDATE" arp_validate + sysfs "$IF_BOND_FAIL_OVER_MAC" fail_over_mac + sysfs "$IF_BOND_XMIT_HASH_POLICY" xmit_hash_policy + sysfs "$IF_BOND_LACP_RATE" lacp_rate + sysfs_add "$IF_BOND_ARP_IP_TARGET" arp_ip_target +} + +setup_slaves() +{ + # 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 "$slave" primary + break + fi + done + + 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 "$IF_BOND_ACTIVE_SLAVE" active_slave + fi +} + +# Are there anything to do ? + +# 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" + if ! [ -e /sys/class/net/$IFACE/master ]; then + ifup_once $BOND_MASTER + fi +else + if [ "$IF_BOND_SLAVES$IF_BOND_MODE" ]; then + BOND_MASTER="$IFACE" + BOND_SLAVES="$IF_BOND_SLAVES" + fi +fi + +# Exit if nothing to do... +[ -z "$BOND_MASTER$BOND_SLAVES" ] && exit + +add_master +setup_master +enslave_slaves +setup_slaves diff --git a/recipes-core/init-ifupdown/files/bonding.up b/recipes-core/init-ifupdown/files/bonding.up new file mode 100644 index 0000000..f10152c --- /dev/null +++ b/recipes-core/init-ifupdown/files/bonding.up @@ -0,0 +1,45 @@ +#!/bin/sh + +[ "$IF_VERBOSITY" = 1 ] && set -x + +sysfs() +{ + # Called with : + # $1 = value to write. Won't write if $1 is empty. + # $2 = basename of the file in bonding/ to write to. + if [ "$1" ] ; then + echo "$1" > "/sys/class/net/$IFACE/master/bonding/$2" + return $? + fi + return 0 +} + +# If the stanza bond-give-a-chance is set for a slave interface, +# then force $IFACE to be the primary for some time, then restore primary to it previous value. + +# This stanza is designed to workaround a bug in wpa_supplicant, when used with bonding : + +# wpa_supplicant expect wifi authentication packets on the bond interface, but also send wifi authentication packets on the bond interface. +# If the active interface is not the wifi interface at the time wpa_supplicant try to authenticate, the wifi AP won't receive anything, causing the authentication to fail. + +# In order for the wifi authentication to succeed, one need to give a chance to the wifi interface to send authentication packets. +# "bond-give-a-chance 10" will set the wifi interface as the primary interface for 10 seconds, then restore the previous primary interface. +# This is supposed to be enought to give a chance to wifi to authenticate properly. + +if [ "$IF_BOND_GIVE_A_CHANCE" ] ; then + read primary < "/sys/class/net/$IFACE/master/bonding/primary" + # Set the temporary primary. + sysfs "$IFACE" primary + + # Wait for the link to be setup, but not longer that $IF_BOND_GIVE_A_CHANGE seconds. + while [ "$IF_BOND_GIVE_A_CHANCE" -gt 0 ] ; do + if ip link show $IFACE | grep -sq 'state UP'; then + break + fi + sleep 1 + IF_BOND_GIVE_A_CHANCE=`expr $IF_BOND_GIVE_A_CHANCE - 1` + done + + # Restore the previous primary. + sysfs "$primary" primary +fi diff --git a/recipes-core/init-ifupdown/init-ifupdown_1.0.bbappend b/recipes-core/init-ifupdown/init-ifupdown_1.0.bbappend new file mode 100644 index 0000000..b0c569e --- /dev/null +++ b/recipes-core/init-ifupdown/init-ifupdown_1.0.bbappend @@ -0,0 +1,12 @@ + +SRC_URI += "file://bonding.pre-up \ + file://bonding.up \ + file://bonding.post-down" + +FILESEXTRAPATHS_prepend := "${THISDIR}/files" + +do_install_${PN}_append () { + install -m 0755 ${WORKDIR}/bonding.pre-up ${D}${sysconfdir}/network/if-pre-up.d/bonding + install -m 0755 ${WORKDIR}/bonding.up ${D}${sysconfdir}/network/if-up.d/bonding + install -m 0755 ${WORKDIR}/bonding.post-down ${D}${sysconfdir}/network/if-post-down.d/bonding +} -- cgit v1.2.3