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