Revamp of bridging code.
- Use sysfs to read bridge information from the system instead of parsing the brctl outputs. - Allow setting of all bridge configuration parameters using new sysfs methods, modelled after bonding configuration. Also works for per-port bridge interface parameters. - Document pre-starting an empty bridge for dynamic add. - Check for interface existence before adding to bridge. - Should fix bug #293046, #309185.
This commit is contained in:
parent
900d54b0fc
commit
dbb5af2023
2
TODO
2
TODO
@ -1,3 +1,5 @@
|
||||
- ensure all forks block, restore and unblock signals. needs review
|
||||
|
||||
- add support somehow for optional translations
|
||||
|
||||
- oldnet[bridging]: Review setting of bridge configuration on dynamic interface add
|
||||
|
@ -805,6 +805,18 @@
|
||||
#sethello 0
|
||||
#stp off"
|
||||
|
||||
# You can also configure the bridge or bridge members via sysfs on 2.6 kernels
|
||||
# or newer. See the kernel bridge documentation for a description of these
|
||||
# options.
|
||||
#stp_state_br0="0"
|
||||
#forward_delay_br0="10"
|
||||
#hairpin_mode_eth0="1"
|
||||
|
||||
# If you want to start an empty bridge, and then dynmically add ports to it you
|
||||
# MUST set the following variables (with the correct interface name).
|
||||
# If you get the error "Misconfigured static bridge detected", this means you.
|
||||
#bridge_br0=''
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# RFC 2684 Bridge Support
|
||||
# For RFC 2684 bridge support emerge net-misc/br2684ctl
|
||||
|
109
net/bridge.sh
109
net/bridge.sh
@ -11,34 +11,61 @@ _config_vars="$_config_vars bridge bridge_add brctl"
|
||||
|
||||
_is_bridge()
|
||||
{
|
||||
# Ignore header line so as to allow for bridges named 'bridge'
|
||||
brctl show 2>/dev/null | sed '1,1d' | grep -q "^${IFACE}[[:space:]]"
|
||||
[ -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= iface="${IFACE}" e= x=
|
||||
local brif= oiface="${IFACE}" e= x=
|
||||
local ports="$(_get_array "bridge_${IFVAR}")"
|
||||
local opts="$(_get_array "brctl_${IFVAR}")"
|
||||
|
||||
# brif is used for dynamic add
|
||||
eval brif=\$bridge_add_${IFVAR}
|
||||
eval x=\${bridge_${IFVAR}-y\}
|
||||
if [ -z "${brif}" -a -z "${opts}" ]; then
|
||||
[ -n "${ports}" -o "${x}" != "y" ] || return 0
|
||||
# ports is for static add
|
||||
eval bridge_unset=\${bridge_${IFVAR}-y\}
|
||||
eval brctl_unset=\${brctl_${IFVAR}-y\}
|
||||
|
||||
# If we are not doing dynamic add on $IFACE, check for static ports.
|
||||
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
|
||||
|
||||
[ -n "${ports}" ] && bridge_post_stop
|
||||
# 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
|
||||
if ! _is_bridge ; then
|
||||
ebegin "Creating bridge ${IFACE}"
|
||||
if ! brctl addbr "${IFACE}"; then
|
||||
eend 1
|
||||
@ -46,6 +73,12 @@ bridge_pre_start()
|
||||
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
|
||||
@ -57,21 +90,50 @@ bridge_pre_start()
|
||||
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 OIFACE="${IFACE}"
|
||||
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 "${OIFACE}" "${x}"; then
|
||||
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
|
||||
@ -86,27 +148,24 @@ bridge_post_stop()
|
||||
{
|
||||
local port= ports= delete=false extra=
|
||||
|
||||
if _is_bridge; then
|
||||
if _is_bridge "${IFACE}"; then
|
||||
ebegin "Destroying bridge ${IFACE}"
|
||||
_down
|
||||
# Ignore header line so as to allow for bridges named 'bridge'
|
||||
ports="$(brctl show 2>/dev/null | \
|
||||
sed -n -e '1,1d' -e '/^'"${IFACE}"'[[:space:]]/,/^\S/ { /^\('"${IFACE}"'[[:space:]]\|\t\)/s/^.*\t//p }')"
|
||||
for x in /sys/class/net/"${IFACE}"/brif/*; do
|
||||
[ -s $x ] || continue
|
||||
n=${x##*/}
|
||||
ports="${ports} ${n}"
|
||||
done
|
||||
delete=true
|
||||
iface=${IFACE}
|
||||
eindent
|
||||
else
|
||||
# Work out if we're added to a bridge for removal or not
|
||||
# Ignore header line so as to allow for bridges named 'bridge'
|
||||
eval set -- $(brctl show 2>/dev/null | sed -e '1,1d' -e "s/'/'\\\\''/g" -e "s/$/'/g" -e "s/^/'/g")
|
||||
local line=
|
||||
for line; do
|
||||
set -- ${line}
|
||||
if [ "$3" = "${IFACE}" ]; then
|
||||
iface=$1
|
||||
break
|
||||
fi
|
||||
done
|
||||
# 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
|
||||
|
Loading…
Reference in New Issue
Block a user