1#!/bin/sh
2# $FreeBSD: src/share/examples/netgraph/ether.bridge,v 1.1.2.2 2001/07/19 05:45:03 dd Exp $
3# $DragonFly: src/share/examples/netgraph/ether.bridge,v 1.2 2003/06/17 04:36:57 dillon Exp $
4
5# This script sets up an Ethernet bridging network across multiple
6# Ethernet interfaces using the ng_bridge(4) and ng_ether(4) netgraph
7# node types.
8#
9# To use this script:
10#
11# 0. Make your own copy of this example script
12#
13# 1. Give your bridging network a name by editing the definition of
14#    ${BRIDGE_NAME} below. It must be a valid netgraph node name.
15#
16# 2. Edit the definitions of ${BRIDGE_IFACES} and ${LOCAL_IFACE}
17#    as described below to define your bridging interfaces.
18#
19# 3. Run this script with "start" as the command line argument.
20#
21# 4. Examine bridging statistics by running this script with "stats"
22#    as the command line argument.
23#
24# 5. Stop bridging by running this script with "stop" as the
25#    command line argument.
26#
27# To run multiple independent bridging networks, create multiple
28# copies of this script with different variable definitions.
29#
30
31# Give each bridging network a unique name here
32
33BRIDGE_NAME="bnet0"
34
35# List the names of the interfaces that you want to bridge across
36# here in ${BRIDGE_IFACES}. If you want to include the local host
37# machine as well then set ${LOCAL_IFACE} as well (it may also be
38# listed in ${BRIDGE_IFACES}). Of course, any ${LOCAL_IFACE} must
39# be ifconfig(8)ured separately. If you don't want a ${LOCAL_IFACE}
40# then leave it defined as the emtpy string.
41
42BRIDGE_IFACES="ed0 fxp0 fxp1"
43LOCAL_IFACE="fxp0"
44
45####################################################################
46#### Everything below this point should not need to be modified ####
47####################################################################
48
49# Routine to verify node's existence
50bridge_verify() {
51	ngctl info ${BRIDGE_NAME}: >/dev/null 2>&1
52	if [ $? -ne 0 ]; then
53		echo "${BRIDGE_NAME}: bridge network not found"
54		exit 1
55	fi
56}
57
58# Routine to get and display link stats
59bridge_linkstats() {
60	STATS=`ngctl msg ${BRIDGE_NAME}: getstats $1`
61	if [ $? -ne 0 ]; then
62		exit 1
63	fi
64	echo "${STATS}" | fmt 2 | awk '/=/ { fl=index($0, "="); \
65	    printf "%20s = %s\n", substr($0, 0, fl - 1), substr($0, fl + 1); }'
66}
67
68# Start/restart routine
69bridge_start() {
70
71	# Load netgraph KLD's as necessary
72	for KLD in ng_ether ng_bridge; do
73		if kldstat -v | grep -qw ${KLD}; then
74		else
75			echo -n "Loading ${KLD}.ko... "
76			kldload ${KLD} || exit 1
77			echo "done"
78		fi
79	done
80
81	# Reset all interfaces
82	bridge_stop
83
84	# Verify all interfaces exist
85	for ETHER in ${BRIDGE_IFACES} ${LOCAL_IFACE}; do
86		if ngctl info ${ETHER}: >/dev/null 2>&1; then
87		else
88			echo "Error: interface ${ETHER} does not exist"
89			exit 1
90		fi
91		ifconfig ${ETHER} up || exit 1
92	done
93
94	# Create new ng_bridge(4) node, attached to the first interface
95	FIRSTIF=`echo ${BRIDGE_IFACES} | awk '{ print $1 }'`
96	ngctl mkpeer ${FIRSTIF}: bridge lower link0 || exit 1
97	ngctl name ${FIRSTIF}:lower ${BRIDGE_NAME} || exit 1
98
99	# Attach other interfaces as well
100	LINKNUM=0
101	for ETHER in ${BRIDGE_IFACES}; do
102		if [ ${LINKNUM} != 0 ]; then
103			ngctl connect ${ETHER}: ${BRIDGE_NAME}: \
104			    lower link${LINKNUM} || exit 1
105		fi
106		LINKNUM=`expr ${LINKNUM} + 1`
107	done
108
109	# Hook up local interface, if any
110	if [ "${LOCAL_IFACE}" != "" ]; then
111		ngctl connect ${LOCAL_IFACE}: ${BRIDGE_NAME}: \
112		    upper link${LINKNUM} || exit 1
113	fi
114
115	# Set all interfaces in promiscuous mode and don't overwrite src addr
116	for ETHER in ${BRIDGE_IFACES}; do
117		ngctl msg ${ETHER}: setpromisc 1 || exit 1
118		ngctl msg ${ETHER}: setautosrc 0 || exit 1
119	done
120}
121
122# Stop routine
123bridge_stop() {
124	ngctl kill ${BRIDGE_NAME}: >/dev/null 2>&1
125	for ETHER in ${BRIDGE_IFACES} ${LOCAL_IFACE}; do
126		ngctl kill ${ETHER}: >/dev/null 2>&1
127	done
128}
129
130# Stats routine
131bridge_stats() {
132
133	# Make sure node exists
134	bridge_verify
135
136	echo ""
137	echo "Statistics for bridging network ${BRIDGE_NAME}:"
138	echo ""
139	LINKNUM=0
140	for ETHER in ${BRIDGE_IFACES}; do
141		echo "Network interface ${ETHER}:"
142		bridge_linkstats ${LINKNUM}
143		LINKNUM=`expr ${LINKNUM} + 1`
144	done
145	if [ "${LOCAL_IFACE}" != "" ]; then
146		echo "Local host interface ${LOCAL_IFACE}:"
147		bridge_linkstats ${LINKNUM}
148	fi
149}
150
151# Main entry point
152case $1 in
153	start)
154		bridge_start
155		;;
156	stats)
157		bridge_verify
158		bridge_stats
159		;;
160	stop)
161		bridge_verify
162		bridge_stop
163		;;
164	*)
165		echo "Usage: ether.bridge [ start | stop | stats ]"
166		exit 1
167esac
168
169