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
|
- ensure all forks block, restore and unblock signals. needs review
|
||||||
|
|
||||||
- add support somehow for optional translations
|
- add support somehow for optional translations
|
||||||
|
|
||||||
|
- oldnet[bridging]: Review setting of bridge configuration on dynamic interface add
|
||||||
|
@ -805,6 +805,18 @@
|
|||||||
#sethello 0
|
#sethello 0
|
||||||
#stp off"
|
#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
|
# RFC 2684 Bridge Support
|
||||||
# For RFC 2684 bridge support emerge net-misc/br2684ctl
|
# For RFC 2684 bridge support emerge net-misc/br2684ctl
|
||||||
|
107
net/bridge.sh
107
net/bridge.sh
@ -11,29 +11,56 @@ _config_vars="$_config_vars bridge bridge_add brctl"
|
|||||||
|
|
||||||
_is_bridge()
|
_is_bridge()
|
||||||
{
|
{
|
||||||
# Ignore header line so as to allow for bridges named 'bridge'
|
[ -d /sys/class/net/"${1:-${IFACE}}"/bridge ]
|
||||||
brctl show 2>/dev/null | sed '1,1d' | grep -q "^${IFACE}[[:space:]]"
|
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()
|
bridge_pre_start()
|
||||||
{
|
{
|
||||||
local brif= iface="${IFACE}" e= x=
|
local brif= oiface="${IFACE}" e= x=
|
||||||
local ports="$(_get_array "bridge_${IFVAR}")"
|
local ports="$(_get_array "bridge_${IFVAR}")"
|
||||||
local opts="$(_get_array "brctl_${IFVAR}")"
|
local opts="$(_get_array "brctl_${IFVAR}")"
|
||||||
|
|
||||||
|
# brif is used for dynamic add
|
||||||
eval brif=\$bridge_add_${IFVAR}
|
eval brif=\$bridge_add_${IFVAR}
|
||||||
eval x=\${bridge_${IFVAR}-y\}
|
# ports is for static add
|
||||||
if [ -z "${brif}" -a -z "${opts}" ]; then
|
eval bridge_unset=\${bridge_${IFVAR}-y\}
|
||||||
[ -n "${ports}" -o "${x}" != "y" ] || return 0
|
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
|
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
|
if [ -z "${ports}" -a -n "${brif}" ]; then
|
||||||
|
# Dynamic mode detected
|
||||||
ports="${IFACE}"
|
ports="${IFACE}"
|
||||||
IFACE="${brif}"
|
IFACE="${brif}"
|
||||||
|
IFVAR=$(shell_var "${IFACE}")
|
||||||
else
|
else
|
||||||
|
# Static mode detected
|
||||||
ports="${ports}"
|
ports="${ports}"
|
||||||
metric=1000
|
metric=1000
|
||||||
fi
|
fi
|
||||||
@ -46,6 +73,12 @@ bridge_pre_start()
|
|||||||
fi
|
fi
|
||||||
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"
|
local IFS="$__IFS"
|
||||||
for x in ${opts}; do
|
for x in ${opts}; do
|
||||||
unset IFS
|
unset IFS
|
||||||
@ -57,21 +90,50 @@ bridge_pre_start()
|
|||||||
done
|
done
|
||||||
unset IFS
|
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
|
if [ -n "${ports}" ]; then
|
||||||
einfo "Adding ports to ${IFACE}"
|
einfo "Adding ports to ${IFACE}"
|
||||||
eindent
|
eindent
|
||||||
|
|
||||||
local OIFACE="${IFACE}"
|
local BR_IFACE="${IFACE}"
|
||||||
for x in ${ports}; do
|
for x in ${ports}; do
|
||||||
ebegin "${x}"
|
ebegin "${x}"
|
||||||
local IFACE="${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
|
_set_flag promisc
|
||||||
_up
|
_up
|
||||||
if ! brctl addif "${OIFACE}" "${x}"; then
|
if ! brctl addif "${BR_IFACE}" "${x}"; then
|
||||||
_set_flag -promisc
|
_set_flag -promisc
|
||||||
eend 1
|
eend 1
|
||||||
return 1
|
return 1
|
||||||
fi
|
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
|
eend 0
|
||||||
done
|
done
|
||||||
eoutdent
|
eoutdent
|
||||||
@ -86,27 +148,24 @@ bridge_post_stop()
|
|||||||
{
|
{
|
||||||
local port= ports= delete=false extra=
|
local port= ports= delete=false extra=
|
||||||
|
|
||||||
if _is_bridge; then
|
if _is_bridge "${IFACE}"; then
|
||||||
ebegin "Destroying bridge ${IFACE}"
|
ebegin "Destroying bridge ${IFACE}"
|
||||||
_down
|
_down
|
||||||
# Ignore header line so as to allow for bridges named 'bridge'
|
for x in /sys/class/net/"${IFACE}"/brif/*; do
|
||||||
ports="$(brctl show 2>/dev/null | \
|
[ -s $x ] || continue
|
||||||
sed -n -e '1,1d' -e '/^'"${IFACE}"'[[:space:]]/,/^\S/ { /^\('"${IFACE}"'[[:space:]]\|\t\)/s/^.*\t//p }')"
|
n=${x##*/}
|
||||||
|
ports="${ports} ${n}"
|
||||||
|
done
|
||||||
delete=true
|
delete=true
|
||||||
iface=${IFACE}
|
iface=${IFACE}
|
||||||
eindent
|
eindent
|
||||||
else
|
else
|
||||||
# Work out if we're added to a bridge for removal or not
|
# We are taking down an interface that is part of a bridge maybe
|
||||||
# Ignore header line so as to allow for bridges named 'bridge'
|
ports="${IFACE}"
|
||||||
eval set -- $(brctl show 2>/dev/null | sed -e '1,1d' -e "s/'/'\\\\''/g" -e "s/$/'/g" -e "s/^/'/g")
|
local brport_dir="/sys/class/net/${IFACE}/brport"
|
||||||
local line=
|
[ -d ${brport_dir} ] || return 0
|
||||||
for line; do
|
iface=$(readlink ${brport_dir}/bridge)
|
||||||
set -- ${line}
|
iface=${iface##*/}
|
||||||
if [ "$3" = "${IFACE}" ]; then
|
|
||||||
iface=$1
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
[ -z "${iface}" ] && return 0
|
[ -z "${iface}" ] && return 0
|
||||||
extra=" from ${iface}"
|
extra=" from ${iface}"
|
||||||
fi
|
fi
|
||||||
|
Loading…
Reference in New Issue
Block a user