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' ] とブリッジ先を明示するようにする。