distributed bridging [script]

Julian Elischer julian at elischer.org
Fri Oct 28 13:04:21 PDT 2005


Julian Elischer wrote:

> spoggle wrote:
>
>> Greetings,
>>
>> I'm trying to create a configuration that would bridge interfaces on
>> different hosts.  Each host would have at least two interfaces, one
>> would be the inter-host connection, the remaining would be the bridged
>> interfaces, so that a packet appearing on host a's bridged interface
>> would also appear on host b, c, etc. bridged interfaces and vice
>> versa.
>>
>> My equipment to try this is on order, so it's still somewhat of a
>> brain exercise.
>>
>> I would like to use if_bridge (for it's STP) and I was thinking of
>> bridging the local interfaces and then using netgraph (eiface?)
>> connected to some other plumbing like l2tp to connect the remote
>> bridges together.
>>
>> Does this sound feasible? Anyone have any other suggestions on how to
>> pull this off?
>>
>> I've also considered hacking if_bridge to allow the configuration of
>> remote bridges as pseudo ports, but not sure I'll have time.
>>  
>>
>
> on machine A you have:
> NIC A     1.1.1.1
> NIC B    10.0.0.1
> on machine B you have:
>
> NIC A   2.2.2.2
> NIC B  10.0.0.2
>
>
> On each machine use a modification of 
> /usr/share/examples/netgraph/ether.bridge
>
> so that one link of each bridge is set to an ng_ksocket instead of a 
> real interface.
> then send messages to each or the sockets to connect to each other 
> with UDP.
>
> how to do this is in /usr/share/examples/netgraph/udp.tunnel
>
> by combining the two you should create a tunnel between the two 
> bridges which
> should result in a single bridged network.
>
>
> that should be about all you need.


here's a completely untested script.
swap the addresses on each end of the bridge (and probably remove one of 
the
bridged ethernet ports ans you probably only have one internal NIC on
each machine (remove ed0))

>
>
>
>
>
>
>> spoggle
>> _______________________________________________
>> freebsd-net at freebsd.org mailing list
>> http://lists.freebsd.org/mailman/listinfo/freebsd-net
>> To unsubscribe, send any mail to "freebsd-net-unsubscribe at freebsd.org"
>>  
>>
> _______________________________________________
> freebsd-net at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-net
> To unsubscribe, send any mail to "freebsd-net-unsubscribe at freebsd.org"


-------------- next part --------------
#!/bin/sh
# $FreeBSD: src/share/examples/netgraph/ether.bridge,v 1.1.2.2 2001/07/19 05:45:03 dd Exp $

# This script sets up an Ethernet bridging network across multiple
# Ethernet interfaces using the ng_bridge(4) and ng_ether(4) netgraph
# node types.
#
# To use this script:
#
# 0. Make your own copy of this example script
#
# 1. Give your bridging network a name by editing the definition of
#    ${BRIDGE_NAME} below. It must be a valid netgraph node name.
#
# 2. Edit the definitions of ${BRIDGE_IFACES} and ${LOCAL_IFACE}
#    as described below to define your bridging interfaces.
#
# 3. Run this script with "start" as the command line argument.
#
# 4. Examine bridging statistics by running this script with "stats"
#    as the command line argument.
#
# 5. Stop bridging by running this script with "stop" as the
#    command line argument.
#
# To run multiple independent bridging networks, create multiple
# copies of this script with different variable definitions.
# 

# Give each bridging network a unique name here

BRIDGE_NAME="bnet0"

# List the names of the interfaces that you want to bridge across
# here in ${BRIDGE_IFACES}. If you want to include the local host
# machine as well then set ${LOCAL_IFACE} as well (it may also be
# listed in ${BRIDGE_IFACES}). Of course, any ${LOCAL_IFACE} must
# be ifconfig(8)ured separately. If you don't want a ${LOCAL_IFACE}
# then leave it defined as the emtpy string.

# This script sets up a virtual point-to-point WAN link between
# two subnets, using UDP packets as the ``WAN connection.''
# The two subnets might be non-routable addresses behind a
# firewall.
#

# Here define the local and remote inside networks as well
# as the local and remote outside IP addresses and UDP port
# number that will be used for the tunnel.
#
#BRIDGE_IFACES="ed0 fxp0 fxp1 tunnel1"
BRIDGE_IFACES="fxp0 tunnel1"
LOCAL_IFACE="fxp0"
LOC_INTERIOR_IP=192.168.1.1
LOC_EXTERIOR_IP=1.1.1.1
REM_INTERIOR_IP=192.168.2.1
REM_EXTERIOR_IP=2.2.2.2
REM_INSIDE_NET=192.168.2.0
UDP_TUNNEL_PORT=4028

####################################################################
#### Everything below this point should not need to be modified ####
####################################################################

# Routine to verify node's existence
bridge_verify() {
	ngctl info ${BRIDGE_NAME}: >/dev/null 2>&1
	if [ $? -ne 0 ]; then
		echo "${BRIDGE_NAME}: bridge network not found"
		exit 1
	fi
}

# Routine to get and display link stats
bridge_linkstats() {
	STATS=`ngctl msg ${BRIDGE_NAME}: getstats $1`
	if [ $? -ne 0 ]; then
		exit 1
	fi
	echo "${STATS}" | fmt 2 | awk '/=/ { fl=index($0, "="); \
	    printf "%20s = %s\n", substr($0, 0, fl - 1), substr($0, fl + 1); }'
}

# Start/restart routine
bridge_start() {

	# Load netgraph KLD's as necessary
	for KLD in ng_ether ng_bridge ng_ksocket; do
		if kldstat -v | grep -qw ${KLD}; then
		else
			echo -n "Loading ${KLD}.ko... "
			kldload ${KLD} || exit 1
			echo "done"
		fi
	done

	# Reset all interfaces
	bridge_stop

	# Verify all interfaces exist
	for ETHER in ${BRIDGE_IFACES} ${LOCAL_IFACE}; do
		case $ETHER in
		tunnel*)
			# nothing to do (I think)
			;;
		*)
			if ngctl info ${ETHER}: >/dev/null 2>&1; then
				ifconfig ${ETHER} up || exit 1
			else
				echo "Error: interface ${ETHER} does not exist"
				exit 1
			fi
			;;
		esac
	done

	# Create new ng_bridge(4) node, attached to the first interface
	FIRSTIF=`echo ${BRIDGE_IFACES} | awk '{ print $1 }'`
	ngctl mkpeer ${FIRSTIF}: bridge lower link0 || exit 1
	ngctl name ${FIRSTIF}:lower ${BRIDGE_NAME} || exit 1

	# Attach other interfaces as well
	LINKNUM=0
	for ETHER in ${BRIDGE_IFACES}; do
		case $ETHER in
		tunnel*)
			# Attach a UDP socket to the ``inet''
			# hook of the interface node
			# using the ng_ksocket(8) node type.
			#
			ngctl mkpeer ${BRIDGE_NAME}: ksocket \
				link${LINKNUM} inet/dgram/udp

			# Bind the UDP socket to the local external
			# IP address and port
			ngctl msg ng0:inet bind \
				inet/${LOC_EXTERIOR_IP}:${UDP_TUNNEL_PORT}

			# Connect the UDP socket to the peer's
			# external IP address and port
			ngctl msg ng0:inet connect \
				inet/${REM_EXTERIOR_IP}:${UDP_TUNNEL_PORT}

			;;
		*)
			if [ ${LINKNUM} != 0 ]; then
				ngctl connect ${ETHER}: ${BRIDGE_NAME}: \
			    	lower link${LINKNUM} || exit 1
			fi
			;;
		esac
		LINKNUM=`expr ${LINKNUM} + 1`
	done

	# Hook up local interface, if any
	if [ "${LOCAL_IFACE}" != "" ]; then
		ngctl connect ${LOCAL_IFACE}: ${BRIDGE_NAME}: \
		    upper link${LINKNUM} || exit 1
	fi

	# Set all interfaces in promiscuous mode and don't overwrite src addr
	for ETHER in ${BRIDGE_IFACES}; do
		case $ETHER in
		tunnel*)
			# nothing to do (I think)
			;;
		*)
			ngctl msg ${ETHER}: setpromisc 1 || exit 1
			ngctl msg ${ETHER}: setautosrc 0 || exit 1
		;;
		esac
	done
}

# Stop routine
bridge_stop() {
	ngctl kill ${BRIDGE_NAME}: >/dev/null 2>&1
	for ETHER in ${BRIDGE_IFACES} ${LOCAL_IFACE}; do
		ngctl kill ${ETHER}: >/dev/null 2>&1
	done
}

# Stats routine
bridge_stats() {

	# Make sure node exists
	bridge_verify

	echo ""
	echo "Statistics for bridging network ${BRIDGE_NAME}:"
	echo ""
	LINKNUM=0
	for ETHER in ${BRIDGE_IFACES}; do
		echo "Network interface ${ETHER}:"
		bridge_linkstats ${LINKNUM}
		LINKNUM=`expr ${LINKNUM} + 1`
	done
	if [ "${LOCAL_IFACE}" != "" ]; then
		echo "Local host interface ${LOCAL_IFACE}:"
		bridge_linkstats ${LINKNUM}
	fi
}

# Main entry point
case $1 in
	start)
		bridge_start
		;;
	stats)
		bridge_verify
		bridge_stats
		;;
	stop)
		bridge_verify
		bridge_stop
		;;
	*)
		echo "Usage: ether.bridge [ start | stop | stats ]"
		exit 1
esac




More information about the freebsd-net mailing list