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