Shadow bridging and Xen
Xenがデフォルトで使うネットワークブリッジの設定スクリプトは、いったんネットワークを切断してしまう。
これはいろいろとよろしくないので、あらかじめ作っておいたブリッジに、vifを単純に追加するだけの設定スクリプトを作った。
まずはブリッジを作るスクリプト。RedHat系のディストリビューションなら動くと思うけど、試したのはMandriva 2007だけ。
/etc/init.d/bridge-shadow
#!/bin/bash
# chkconfig: 2345 05 89
# description: Shadow Layer 2 Bridge
#
# Source function library.
. /etc/init.d/functions
INTERFACES=""
[ -f /etc/sysconfig/bridge-shadow ] && . /etc/sysconfig/bridge-shadow
PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin
start() {
gprintf "Starting Shadow Layer 2 Bridge: "
msg=""
for i in $INTERFACES; do
# load aliased drivers
ifconfig "$i" 0.0.0.0 up
# link down interface
ip link set "$i" down
ip addr flush dev "$i" 2>/dev/null
# swap name
ip link set "$i" name "s$i"
# add bridge
brctl addbr "$i"
# add interface to bridge
brctl addif "$i" "s$i"
# link up bridge
ip link set "$i" up
# link up interface
ifconfig "s$i" 0.0.0.0 up
done
# wait for bridge to be in running state
for i in $INTERFACES; do
try=0
while [ "$try" -lt 50 ]; do
if ifconfig "$i" | grep -q "RUNNING"; then
break
else
usleep 100000
fi
try=$(expr $try + 1)
done
done
if [ -n "$msg" ];then
failure "$msg"
else
success
fi
echo
}
stop() {
gprintf "Shutting down Shadow Layer 2 Bridge: "
msg=""
for i in $INTERFACES; do
# link down interface
ip link set "s$i" down
ip addr flush dev "s$i" 2>/dev/null
# link down bridge
ip link set "$i" down
ip addr flush dev "$i" 2>/dev/null
# delete interface from bridge
brctl delif "$i" "s$i"
# delete bridge
brctl delbr "$i"
# swap name
ip link set "s$i" name "$i"
done
if [ -n "$msg" ];then
failure "$msg"
else
success
fi
echo
}
status() {
brctl show
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
sleep 1
start
;;
status)
status
;;
*)
gprintf "Usage: %s {star|stop|restart|status}\n" "$0"
exit 1
esac/etc/sysconfig/bridge-shadow
INTERFACES="eth0"
- eth0をリンクダウンし、名前をseth0に変更する。
- eth0という名前のブリッジを作る
- eth0(ブリッジ)にseth0(物理インターフェース)を追加する
というもの。ブリッジ前後で使用するネットワークインターフェースの名前が変わらない。
ちなみにeth0(ブリッジ)のMACアドレスは、seth0(物理インターフェース)と同じになる。
chkconfigなどを使って、bridge-shadowが起動された後にネットワークが立ち上がるようにしておく。
Xenのブリッジ構築スクリプト:
/etc/xen/scripts/network-bridge-additional
#!/bin/sh
#============================================================================
# Custermized 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 just adds the virtual device to the existent bridge,
# doesn't set IP addresses.
# Setting IP addresses or
#
# Usage:
#
# network-bridge-additional (start|stop|status) {VAR=VAL}*
#
# Vars:
#
# vifnum Virtual device number to use (default 0). Numbers >=8
# require the netback driver to have nloopbacks set to a
# higher value than its default of 8.
# bridge The bridge to use (default xenbr${vifnum}).
# antispoof Whether to use iptables to prevent spoofing (default no).
#
# Internal Vars:
# vif0="vif0.${vifnum}"
#
# start:
# Enslaves vif0 to bridge
#
# stop:
# Removes vif0 from the bridge
#
# status:
# Print addresses, interfaces, routes
#
#============================================================================
dir=$(dirname "$0")
. "$dir/xen-script-common.sh"
. "$dir/xen-network-common.sh"
findCommand "$@"
evalVariables "$@"
vifnum=${vifnum:-$(ip route list | awk '/^default / { print $NF }' | sed 's/^[^0-9]*//')}
vifnum=${vifnum:-0}
bridge=${bridge:-xenbr${vifnum}}
antispoof=${antispoof:-no}
vif0="vif0.${vifnum}"
##
# link_exists interface
#
# Returns 0 if the interface named exists (whether up or down), 1 otherwise.
#
link_exists()
{
if ip link show "$1" >/dev/null 2>/dev/null
then
return 0
else
return 1
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 ${vif0} -j ACCEPT
}
# Usage: show_status bridge
# Print ifconfig and routes.
show_status () {
local bridge=$1
echo '============================================================'
ip addr show ${bridge}
echo ' '
brctl show ${bridge}
echo ' '
ip route list
echo ' '
route -n
echo '============================================================'
}
op_start () {
if [ "${bridge}" = "null" ] ; then
return
fi
if ! link_exists "$bridge"; then
return
fi
# FIXME: Check wheter the device is already up.
ip link set ${bridge} up
add_to_bridge2 ${bridge} ${vif0}
if [ ${antispoof} = 'yes' ] ; then
antispoofing
fi
}
op_stop () {
if [ "${bridge}" = "null" ]; then
return
fi
if ! link_exists "$bridge"; then
return
fi
ip link set ${vif0} down
ip addr flush ${vif0}
brctl delif ${bridge} ${vif0}
}
# adds $dev to $bridge but waits for $dev to be in running state first
add_to_bridge2() {
local bridge=$1
local dev=$2
local maxtries=10
echo -n "Waiting for ${dev} to negotiate link."
ip link set ${dev} up
for i in `seq ${maxtries}` ; do
if ifconfig ${dev} | grep -q RUNNING ; then
break
else
echo -n '.'
sleep 1
fi
done
if [ ${i} -eq ${maxtries} ] ; then echo '(link isnt in running state)' ; fi
add_to_bridge ${bridge} ${dev}
}
case "$command" in
start)
op_start
;;
stop)
op_stop
;;
status)
show_status ${bridge}
;;
*)
echo "Unknown command: $command" >&2
echo 'Valid commands are: start, stop, status' >&2
exit 1
esac
xendの設定ファイル:
/etc/xend-config.sxp
(network-script 'network-bridge-additional bridge=eth0') (vif-script 'vif-bridge bridge=eth0')
ゲストドメインの設定ファイルでは、vif = [ 'type=ioemu, bridge=eth0' ] とブリッジ先を明示するようにする。