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