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:
		
							
								
								
									
										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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user