43678fd2c4
X-Gentoo-Bug: 353124 X-Gentoo-Bug-URL: http://bugs.gentoo.org/show_bug.cgi?id=353124
192 lines
4.1 KiB
Bash
192 lines
4.1 KiB
Bash
# Copyright (c) 2007-2008 Roy Marples <roy@marples.name>
|
|
# All rights reserved. Released under the 2-clause BSD license.
|
|
|
|
bridge_depend()
|
|
{
|
|
before interface macnet
|
|
program /sbin/brctl
|
|
}
|
|
|
|
_config_vars="$_config_vars bridge bridge_add brctl"
|
|
|
|
_is_bridge()
|
|
{
|
|
[ -d /sys/class/net/"${1:-${IFACE}}"/bridge ]
|
|
return $?
|
|
}
|
|
|
|
_is_bridge_port()
|
|
{
|
|
[ -d /sys/class/net/"${1:-${IFACE}}"/brport ]
|
|
return $?
|
|
}
|
|
|
|
_bridge_ports()
|
|
{
|
|
for x in /sys/class/net/"${1:-${IFACE}}"/brif/*; do
|
|
n=${x##*/}
|
|
echo $n
|
|
done
|
|
}
|
|
|
|
bridge_pre_start()
|
|
{
|
|
local brif= oiface="${IFACE}" e= x=
|
|
# ports is for static add
|
|
local ports="$(_get_array "bridge_${IFVAR}")"
|
|
# old config options
|
|
local opts="$(_get_array "brctl_${IFVAR}")"
|
|
# brif is used for dynamic add
|
|
eval brif=\$bridge_add_${IFVAR}
|
|
|
|
# we need a way to if the bridge exists in a variable name, not just the
|
|
# contents of a variable. Eg if somebody has only bridge_add_eth0='br0',
|
|
# with no other lines mentioning br0.
|
|
eval bridge_unset=\${bridge_${IFVAR}-y\}
|
|
eval brctl_unset=\${brctl_${IFVAR}-y\}
|
|
|
|
if [ -z "${brif}" -a "${brctl_unset}" = 'y' ]; then
|
|
if [ -z "${ports}" -a "${bridge_unset}" = "y" ]; then
|
|
#eerror "Misconfigured static bridge detected (see net.example)"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
# If the bridge was already up, we should clear it
|
|
[ "${bridge_unset}" != "y" ] && bridge_post_stop
|
|
|
|
(
|
|
# Normalize order of variables
|
|
if [ -z "${ports}" -a -n "${brif}" ]; then
|
|
# Dynamic mode detected
|
|
ports="${IFACE}"
|
|
IFACE="${brif}"
|
|
IFVAR=$(shell_var "${IFACE}")
|
|
else
|
|
# Static mode detected
|
|
ports="${ports}"
|
|
metric=1000
|
|
fi
|
|
|
|
if ! _is_bridge ; then
|
|
ebegin "Creating bridge ${IFACE}"
|
|
if ! brctl addbr "${IFACE}"; then
|
|
eend 1
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
# TODO: does this reset the bridge every time we add a interface to the
|
|
# bridge? We should probably NOT do that.
|
|
|
|
# Old configuration set mechanism
|
|
# Only a very limited subset of the options are available in the old
|
|
# configuration method. The sysfs interface is in the next block instead.
|
|
local IFS="$__IFS"
|
|
for x in ${opts}; do
|
|
unset IFS
|
|
set -- ${x}
|
|
x=$1
|
|
shift
|
|
set -- "${x}" "${IFACE}" "$@"
|
|
brctl "$@"
|
|
done
|
|
unset IFS
|
|
|
|
# New configuration set mechanism, matches bonding
|
|
for x in /sys/class/net/"${IFACE}"/bridge/*; do
|
|
[ -f "${x}" ] || continue
|
|
n=${x##*/}
|
|
eval s=\$${n}_${IFVAR}
|
|
if [ -n "${s}" ]; then
|
|
einfo "Setting ${n}: ${s}"
|
|
echo "${s}" >"${x}" || \
|
|
eerror "Failed to configure $n (${n}_${IFVAR})"
|
|
fi
|
|
done
|
|
|
|
if [ -n "${ports}" ]; then
|
|
einfo "Adding ports to ${IFACE}"
|
|
eindent
|
|
|
|
local BR_IFACE="${IFACE}"
|
|
for x in ${ports}; do
|
|
ebegin "${x}"
|
|
local IFACE="${x}"
|
|
local IFVAR=$(shell_var "${IFACE}")
|
|
if ! _exists "${IFACE}" ; then
|
|
eerror "Cannot add non-existent interface ${IFACE} to ${BR_IFACE}"
|
|
return 1
|
|
fi
|
|
# The interface is known to exist now
|
|
_set_flag promisc
|
|
_up
|
|
if ! brctl addif "${BR_IFACE}" "${x}"; then
|
|
_set_flag -promisc
|
|
eend 1
|
|
return 1
|
|
fi
|
|
# Per-interface bridge settings
|
|
for x in /sys/class/net/"${IFACE}"/brport/*; do
|
|
[ -f "${x}" ] || continue
|
|
n=${x##*/}
|
|
eval s=\$${n}_${IFVAR}
|
|
if [ -n "${s}" ]; then
|
|
einfo "Setting ${n}@${IFACE}: ${s}"
|
|
echo "${s}" >"${x}" || \
|
|
eerror "Failed to configure $n (${n}_${IFVAR})"
|
|
fi
|
|
done
|
|
eend 0
|
|
done
|
|
eoutdent
|
|
fi
|
|
) || return 1
|
|
|
|
# Bring up the bridge
|
|
_up
|
|
}
|
|
|
|
bridge_post_stop()
|
|
{
|
|
local port= ports= delete=false extra=
|
|
|
|
if _is_bridge "${IFACE}"; then
|
|
ebegin "Destroying bridge ${IFACE}"
|
|
_down
|
|
for x in /sys/class/net/"${IFACE}"/brif/*; do
|
|
[ -s $x ] || continue
|
|
n=${x##*/}
|
|
ports="${ports} ${n}"
|
|
done
|
|
delete=true
|
|
iface=${IFACE}
|
|
eindent
|
|
else
|
|
# We are taking down an interface that is part of a bridge maybe
|
|
ports="${IFACE}"
|
|
local brport_dir="/sys/class/net/${IFACE}/brport"
|
|
[ -d ${brport_dir} ] || return 0
|
|
iface=$(readlink ${brport_dir}/bridge)
|
|
iface=${iface##*/}
|
|
[ -z "${iface}" ] && return 0
|
|
extra=" from ${iface}"
|
|
fi
|
|
|
|
for port in ${ports}; do
|
|
ebegin "Removing port ${port}${extra}"
|
|
local IFACE="${port}"
|
|
_set_flag -promisc
|
|
brctl delif "${iface}" "${port}"
|
|
eend $?
|
|
done
|
|
|
|
if ${delete}; then
|
|
eoutdent
|
|
brctl delbr "${iface}"
|
|
eend $?
|
|
fi
|
|
|
|
return 0
|
|
}
|