1
0
mirror of https://github.com/fwbuilder/fwbuilder synced 2026-03-25 04:37:22 +01:00

incremental updates for bonding interfaces. Refs #261 #265 #454

This commit is contained in:
Vadim Kurland 2009-09-24 00:03:52 +00:00
parent e127687142
commit ff97b6bf33
4 changed files with 184 additions and 53 deletions

View File

@ -1 +1 @@
#define BUILD_NUM 1490
#define BUILD_NUM 1492

View File

@ -1,3 +1,27 @@
2009-09-23 vadim <vadim@vk.crocodile.org>
* ../src/res/configlets/linux24/update_bonding: Generated iptables
script incrementally updates bonding interfaces: it adds missing
slaves and removes those that are not configued in fwbuilder. It
also tries to load module "bonding" with protocol parameters
defined in the GUI. Bonding interfaces that exist on the firewall
but are not configured in fwbuilder are cleared of all slaves and
brought down. They can not be removed because that requires
removing module which kills bond interfaces that should be there.
Limitation: currently all bonding interfaces will use the same
protocol parameters. This is because module loading with parameter
"-obond1" that is supposed to be the way to obtain more than one
bonding interface and also the way to specify different parameters
for different interfaces causes kernel panic in my tests. Tested
with bonding module v3.5.0 and kernel 2.6.29.4-167.fc11.i686.PAE
on Fedora Core 11. The only way to get two bonding interfaces that
works is to load the module with parameter max_bonds=2, but this
means all bonding interfaces work with the same protocol
parameters. If bond interfaces are configured with different
parameters in the GUI, compiler uses the first and issues warning
for others.
2009-09-18 vadim <vadim@vk.crocodile.org>
* PolicyCompiler.cpp (ItfNegation::processNext): (change in

View File

@ -304,6 +304,8 @@ string OSConfigurator_linux24::printBondingInterfaceConfigurationCommands()
*/
QStringList gencmd;
QStringList bonding_interfaces;
QString module_parameters;
FWObjectTypedChildIterator i = fw->findByType(Interface::TYPENAME);
for ( ; i!=i.end(); ++i )
@ -313,25 +315,48 @@ string OSConfigurator_linux24::printBondingInterfaceConfigurationCommands()
QStringList out;
if (iface->getOptionsObject()->getStr("type") == "bonding")
{
out.push_back("update_bonding");
out.push_back(iface->getName().c_str());
/*
* current implementation of function load_bonding_module()
* in the configlet loads the module once, which means we can
* only support the same parameters for all bonding interfaces.
* Take parameters from the first bonding interface and use that
* in the call to load_bonding_module()
*
* However, check if parameters for the subsequent bonding
* interfaces are different and issue warning.
*/
QString mode = iface->getOptionsObject()->getStr("bonding_policy").c_str();
QString xmit_hash_policy = iface->getOptionsObject()->getStr("xmit_hash_policy").c_str();
QString driver_opts = iface->getOptionsObject()->getStr("bondng_driver_options").c_str();
QStringList params;
if (!mode.isEmpty())
params.push_back("mode=" + mode);
if (!xmit_hash_policy.isEmpty())
params.push_back("xmit_hash_policy=" + xmit_hash_policy);
if (!driver_opts.isEmpty())
params.push_back(driver_opts);
// Function update_bonding in the configlet expects 3
// arguments. If there are no parameters for the bonding
// module, just put empty string in place of the argument
// 2.
out.push_back("\"" + params.join(" ") + "\"");
if (module_parameters.isEmpty())
{
module_parameters = params.join(" ");
} else
{
if (module_parameters != params.join(" "))
{
warning(
QString("Different protocol parameters for multiple "
"bonding interfaces are not supported at "
"this time. Module 'bonding' "
"will be loaded with the following parameters: '%1'")
.arg(module_parameters).toStdString());
}
}
out.push_back("update_bonding");
out.push_back(iface->getName().c_str());
bonding_interfaces.push_back(iface->getName().c_str());
QStringList bonding_interfaces;
FWObjectTypedChildIterator j = iface->findByType(Interface::TYPENAME);
@ -342,11 +367,24 @@ string OSConfigurator_linux24::printBondingInterfaceConfigurationCommands()
subint->getOptionsObject()->getStr("type") == "ethernet")
bonding_interfaces.push_back(subint->getName().c_str());
}
out.push_back("\"" + bonding_interfaces.join(" ") + "\"");
out.push_back(bonding_interfaces.join(" "));
gencmd.push_back(out.join(" "));
}
}
if (bonding_interfaces.size())
{
gencmd.push_front(
QString("load_bonding_module \"%1\" max_bonds=%2 %3")
.arg(bonding_interfaces.join(" "))
.arg(bonding_interfaces.size())
.arg(module_parameters));
gencmd.push_back(
QString("clear_bonding_except_known %1")
.arg(bonding_interfaces.join(" ")));
} else
gencmd.push_front("unload_bonding_module");
return gencmd.join("\n").toStdString() + "\n";
}

View File

@ -22,6 +22,16 @@
##
##
missing_bond() {
bond_intf=$1
cmd=$2
test "$cmd" = "down" && {
echo "# Bring unconfigured bonding interface $bond_intf down"
$FWBDEBUG $IFCONFIG $bond_intf down
}
}
missing_slave() {
slave=$1
cmd=$2
@ -43,58 +53,117 @@ missing_slave() {
}
}
## update_bonding bond0 "mode=balance-alb miimon=50" "eth2 eth3"
## Quotes are essential
update_bonding() {
bond_interface=$1
module_parameters=$2
shift
## verify that bonding module is loaded with parameters that provide
## support for required number of bonding interfaces (bonding
## interfaces get created when module is loaded and if we need 2 --
## bond0 and bond1 -- then the way to get them is to load the module
## with parameter max_bonds=2).
##
## Current implementation only supports identical bonding parameters
## for all bonding interfaces. This is because in my tests command
## "modprobe bonding -obond1" always causes kernel panic. This means I
## could not find a way to load bonding module two times with
## different parameters. Call for this function is generated in
## OSConfigurator_linux24::printBondingInterfaceConfigurationCommands()
##
## load_bonding_module "bond0 bond1" max_bonds=2 mode=balance-alb miimon=50
##
load_bonding_module() {
bonding_interfaces=$1
shift
module_parameters=$*
FWB_SLAVES=""
CURRENT_SLAVES=""
FWB_SLAVES=$(
for subint in $*; do
echo "${subint}@$bond_interface"
done | sort
)
# we can load the module and configure parameters at the same time as such:
# /sbin/modprobe bonding -obond1 mode=balance-alb miimon=50
# modprobe does not return error and terminates silently if the module is
# already loaded. It DOES NOT update module parameters though.
PROC_DIR="/proc/net/bonding/"
PROD_BOND_IFACE="${PROC_DIR}/$bond_interface"
test -f $PROD_BOND_IFACE || {
echo "# Installing bonding module for $bond_interface with parameters $module_parameters"
cmd="$MODPROBE bonding -o$bond_interface $module_parameters"
test -n "$FWBDEBUG" && echo "# $cmd"
$cmd || {
# we could not create bonding interface. Possible reason is that
# this is second (third) bonding interface which requires special
# configuration in /etc/modprobe.conf
test -d $PROC_DIR || {
## module is not loaded. Load it with appropriate max_bonds argument
cmd="$MODPROBE bonding $module_parameters"
test -n "$FWBDEBUG" && echo "# $cmd" || $cmd || {
# Module load failed.
cat <<EOF
Could not create bonding interface $bond_interface
If this is second bonding interface, then you need to
add module parameters in the file /etc/modprobe.conf or
/etc/modprobe.d/bond.conf
Could not load bonding interface module. Try to add
module parameters to the file /etc/modprobe.conf or
/etc/modprobe.d/bond.conf and reboot
EOF
echo "Installing bonding module failed. Bonding interface $bond_interface is not available."
# do not abort in test mode
test -z "$FWBDEBUG" && exit 1
}
}
CURRENT_SLAVES=$(
cat $PROD_BOND_IFACE | grep 'Slave Interface:' | \
while read a b slave; do
echo "${slave}@$bond_interface"
done | sort
)
diff_intf missing_slave "$FWB_SLAVES" "$CURRENT_SLAVES" " "
diff_intf missing_slave "$CURRENT_SLAVES" "$FWB_SLAVES" "-d"
## test that we now have bonding interfaces that we need
for bondint in $bonding_interfaces; do
PROD_BOND_IFACE="${PROC_DIR}/$bondint"
test -f $PROD_BOND_IFACE || {
echo "Bonding interface $bondint does not exist"
test -z "$FWBDEBUG" && exit 1
}
done
}
## If no bonding interfaces are configured in fwbuilder, unload the module
## to kill any that might be present on the machine.
unload_bonding_module() {
$MODPROBE -r bonding
}
## update_bonding bond0 eth2 eth3
## Quotes are essential
update_bonding() {
bond_interface=$1
shift
PROC_DIR="/proc/net/bonding/"
PROD_BOND_IFACE="${PROC_DIR}/$bond_interface"
test -f $PROD_BOND_IFACE && {
FWB_SLAVES=""
CURRENT_SLAVES=""
FWB_SLAVES=$(
for subint in $*; do
echo "${subint}@$bond_interface"
done | sort
)
CURRENT_SLAVES=$(
cat $PROD_BOND_IFACE | grep 'Slave Interface:' | \
while read a b slave; do
echo "${slave}@$bond_interface"
done | sort
)
diff_intf missing_slave "$FWB_SLAVES" "$CURRENT_SLAVES" " "
diff_intf missing_slave "$CURRENT_SLAVES" "$FWB_SLAVES" "-d"
}
}
## Since we can not remove bonding interface without unloading the
## module (which kills other bonding interfaces), we'll just bridge
## bonding interfaces that exist on the machine but not in fwbuilder
## config down.
##
## clear_bonding_except_known bond0 bond1
##
## If bond2 interface exist, it will be brought down.
##
## Note that ifenslave fails to remove slave if bond interface is down
## with error "Illegal operation; the specified master interface 'bond1' is not up."
## Need to bring bond interface up before removing slaves. This makes
## no sense, but still. This is with bonding module v3.5.0, tested on Fedora C11.
##
clear_bonding_except_known() {
PROC_DIR="/proc/net/bonding/"
ls $PROC_DIR | awk -v IGNORED="$*" \
'BEGIN {
split(IGNORED,ignored_arr);
for (a in ignored_arr) {ignored_dict[ignored_arr[a]]=1;}
}
(!($1 in ignored_dict)) {print $1;}' | \
while read bond_intf; do
echo "Removing slaves and bringing unconfigured bonding interface $bond_intf down"
PROD_BOND_IFACE="${PROC_DIR}/$bond_intf"
slaves=$(cat $PROD_BOND_IFACE | awk '/[sS]lave [iI]nterface:/ { printf "%s ",$NF;}')
$FWBDEBUG $IFCONFIG $bond_intf up
$FWBDEBUG $IFENSLAVE -d $bond_intf $slaves
$FWBDEBUG $IFCONFIG $bond_intf down
done
}