Files
xen/tools/examples/network-bridge
T
emellor@leeni.uk.xensource.com 1033d025c4 Moved SuSE-specific getcfg call into a preiftransfer call. The semantics of
this aren't beautiful, but this gets the distro-specific code out of the body
of the network-bridge script and into a common place, while still preserving
the existing code behaviour.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
2005-10-25 11:22:47 +01:00

310 lines
7.9 KiB
Bash
Executable File

#!/bin/sh
#============================================================================
# Default Xen network start/stop script.
# Xend calls a network script when it starts.
# The script name to use is defined in /etc/xen/xend-config.sxp
# in the network-script field.
#
# This script creates a bridge (default xenbr${vifnum}), adds a device
# (default eth${vifnum}) to it, copies the IP addresses from the device
# to the bridge and adjusts the routes accordingly.
#
# If all goes well, this should ensure that networking stays up.
# However, some configurations are upset by this, especially
# NFS roots. If the bridged setup does not meet your needs,
# configure a different script, for example using routing instead.
#
# Usage:
#
# network (start|stop|status) {VAR=VAL}*
#
# Vars:
#
# vifnum Virtual device number to use (default 0). Numbers >=1
# require the netback driver to have nloopbacks set to a
# higher value than its default of 1.
# bridge The bridge to use (default xenbr${vifnum}).
# netdev The interface to add to the bridge (default eth${vifnum}).
# antispoof Whether to use iptables to prevent spoofing (default no).
#
# start:
# Creates the bridge and enslaves netdev to it.
# Copies the IP addresses from netdev to the bridge.
# Deletes the routes to netdev and adds them on bridge.
#
# stop:
# Removes netdev from the bridge.
# Deletes the routes to bridge and adds them to netdev.
#
# status:
# Print ifconfig for netdev and bridge.
# Print routes.
#
#============================================================================
dir=$(dirname "$0")
. "$dir/xen-network-common.sh"
# Exit if anything goes wrong.
set -e
# First arg is the operation.
OP=$1
shift
# Pull variables in args in to environment.
for arg ; do export "${arg}" ; done
vifnum=${vifnum:-0}
bridge=${bridge:-xenbr${vifnum}}
netdev=${netdev:-eth${vifnum}}
antispoof=${antispoof:-no}
pdev="p${netdev}"
vdev="veth${vifnum}"
vif0="vif0.${vifnum}"
legacy_mask_to_prefix() {
mask=$1
first=${mask%%.*}
second=${mask#*.}
third=${second#*.}
fourth=${third#*.}
second=${second%%.*}
third=${third%%.*}
declare -i INT FULLMASK BIT
INT=$((((($first*256)+$second)*256+$third)*256+$fourth))
FULLMASK=4294967295
BIT=1
for bit in `seq 32 -1 0`; do
if test $FULLMASK -eq $INT; then PREFIX=$bit; return; fi
FULLMASK=$(($FULLMASK-$BIT))
BIT=$((BIT*2))
done
echo "ERROR converting netmask $mask to prefix"
exit 1
}
# Usage: transfer_addrs src dst
# Copy all IP addresses (including aliases) from device $src to device $dst.
transfer_addrs () {
local src=$1
local dst=$2
# Don't bother if $dst already has IP addresses.
if ip addr show dev ${dst} | egrep -q '^ *inet ' ; then
return
fi
# Address lines start with 'inet' and have the device in them.
# Replace 'inet' with 'ip addr add' and change the device name $src
# to 'dev $src'.
ip addr show dev ${src} | egrep '^ *inet ' | sed -e "
s/inet/ip addr add/
s@\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+/[0-9]\+\)@\1@
s/${src}/dev ${dst}/
" | sh -e
# Remove automatic routes on destionation device
ip route list | sed -ne "
/dev ${dst}\( \|$\)/ {
s/^/ip route del /
p
}" | sh -e
}
# Usage: del_addrs src
del_addrs () {
local src=$1
ip addr show dev ${src} | egrep '^ *inet ' | sed -e "
s/inet/ip addr del/
s@\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\)/[0-9]\+@\1@
s/${src}/dev ${src}/
" | sh -e
ip link set dev ${dst} up
}
# Usage: transfer_routes src dst
# Get all IP routes to device $src, delete them, and
# add the same routes to device $dst.
# The original routes have to be deleted, otherwise adding them
# for $dst fails (duplicate routes).
transfer_routes () {
local src=$1
local dst=$2
# List all routes and grep the ones with $src in.
# Stick 'ip route del' on the front to delete.
# Change $src to $dst and use 'ip route add' to add.
ip route list | sed -ne "
/dev ${src}\( \|$\)/ {
h
s/^/ip route del /
P
g
s/${src}/${dst}/
s/^/ip route add /
P
d
}" | sh -e
}
# Usage: create_bridge bridge
create_bridge () {
local bridge=$1
# Don't create the bridge if it already exists.
if ! brctl show | grep -q ${bridge} ; then
brctl addbr ${bridge}
brctl stp ${bridge} off
brctl setfd ${bridge} 0
fi
ip link set ${bridge} up
}
# Usage: add_to_bridge bridge dev
add_to_bridge () {
local bridge=$1
local dev=$2
# Don't add $dev to $bridge if it's already on a bridge.
if ! brctl show | grep -q ${dev} ; then
brctl addif ${bridge} ${dev}
fi
}
# Set the default forwarding policy for $dev to drop.
# Allow forwarding to the bridge.
antispoofing () {
iptables -P FORWARD DROP
iptables -F FORWARD
iptables -A FORWARD -m physdev --physdev-in ${pdev} -j ACCEPT
iptables -A FORWARD -m physdev --physdev-in ${vif0} -j ACCEPT
}
# Usage: show_status dev bridge
# Print ifconfig and routes.
show_status () {
local dev=$1
local bridge=$2
echo '============================================================'
ip addr show ${dev}
ip addr show ${bridge}
echo ' '
brctl show ${bridge}
echo ' '
ip route list
echo ' '
route -n
echo '============================================================'
}
op_start () {
if [ "${bridge}" == "null" ] ; then
return
fi
create_bridge ${bridge}
if ! ip link show 2>/dev/null | grep -q "^[0-9]*: ${vdev}"; then
return
fi
if ip link show ${vdev} 2>/dev/null >/dev/null; then
mac=`ip link show ${netdev} | grep 'link\/ether' | sed -e 's/.*ether \(..:..:..:..:..:..\).*/\1/'`
preiftransfer ${netdev}
transfer_addrs ${netdev} ${vdev}
if ! ifdown ${netdev}; then
# if ifup didn't work, see if we have an ip= on cmd line
if egrep 'ip=[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:' /proc/cmdline; then
kip=`sed -e 's!.*ip=\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\):.*!\1!' /proc/cmdline`
kmask=`sed -e 's!.*ip=[^:]*:[^:]*:[^:]*:\([^:]*\):.*!\1!' /proc/cmdline`
kgate=`sed -e 's!.*ip=[^:]*:[^:]*:\([^:]*\):.*!\1!' /proc/cmdline`
ip link set ${netdev} down
ip addr flush ${netdev}
fi
fi
ip link set ${netdev} name ${pdev}
ip link set ${vdev} name ${netdev}
ip link set ${pdev} down arp off
ip link set ${pdev} addr fe:ff:ff:ff:ff:ff
ip addr flush ${pdev}
ip link set ${netdev} addr ${mac} arp on
add_to_bridge ${bridge} ${vif0}
add_to_bridge ${bridge} ${pdev}
ip link set ${bridge} up
ip link set ${vif0} up
ip link set ${pdev} up
if ! ifup ${netdev} ; then
if [ ${kip} ] ; then
# use the addresses we grocked from /proc/cmdline
if [ -z "${kmask}" ]; then
PREFIX=32;
else
legacy_to_prefix ${kmask};
fi
ip addr add ${kip}/${PREFIX} dev ${netdev}
ip link set dev ${netdev} up
[ ${kgate} ] && ip route add default via ${kgate}
fi
fi
else
# old style without ${vdev}
transfer_addrs ${netdev} ${bridge}
transfer_routes ${netdev} ${bridge}
fi
if [ ${antispoof} == 'yes' ] ; then
antispoofing
fi
}
op_stop () {
if [ "${bridge}" == "null" ]; then
return
fi
if ! ip link show ${bridge} >/dev/null 2>&1; then
return
fi
if ip link show ${pdev} 2>/dev/null >/dev/null; then
ip link set dev ${vif0} down
mac=`ip link show ${netdev} | grep 'link\/ether' | sed -e 's/.*ether \(..:..:..:..:..:..\).*/\1/'`
transfer_addrs ${netdev} ${pdev}
ifdown ${netdev}
ip link set ${netdev} down arp off
ip link set ${netdev} addr fe:ff:ff:ff:ff:ff
ip link set ${pdev} down
ip addr flush ${netdev}
ip link set ${pdev} addr ${mac} arp on
brctl delif ${bridge} ${pdev}
brctl delif ${bridge} ${vif0}
ip link set ${bridge} down
ip link set ${netdev} name ${vdev}
ip link set ${pdev} name ${netdev}
ifup ${netdev}
else
transfer_routes ${bridge} ${netdev}
ip link set ${bridge} down
fi
brctl delbr ${bridge}
}
case ${OP} in
start)
op_start
;;
stop)
op_stop
;;
status)
show_status ${netdev} ${bridge}
;;
*)
echo 'Unknown command: ' ${OP} >&2
echo 'Valid commands are: start, stop, status' >&2
exit 1
esac