Sophie

Sophie

distrib > CentOS > 5 > x86_64 > by-pkgid > 8763144197db7dd837c794bb2da1fedf > files > 20

xen-3.0.3-142.el5_9.3.x86_64.rpm

#!/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-bridge (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}).
# netdev     The interface to add to the bridge (default eth${vifnum}).
# antispoof  Whether to use iptables to prevent spoofing (default no).
#
# Internal Vars:
# pdev="p${netdev}"
# vdev="veth${vifnum}"
# vif0="vif0.${vifnum}"
#
# start:
# Creates the bridge
# Copies the IP and MAC addresses from netdev to vdev
# Renames netdev to be pdev 
# Renames vdev to be netdev 
# Enslaves pdev, vdev to bridge
#
# stop:
# Removes netdev from the bridge
# Transfers addresses, routes from netdev to pdev
# Renames netdev to vdev
# Renames pdev to netdev 
# Deletes 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 / { split($0, x, "dev "); split(x[2], x, " "); print x[1] }' | sed 's/^[^0-9]*//')}
vifnum=${vifnum:-0}
bridge=${bridge:-xenbr${vifnum}}
netdev=${netdev:-eth${vifnum}}
antispoof=${antispoof:-no}

pdev="p${netdev}"
vdev="veth${vifnum}"
vif0="vif0.${vifnum}"
addr_pfx=

get_ip_info() {
    addr_pfx=`ip addr show dev $1 | sed -n 's/^ *inet \(.*\) [^ ]*$/\1/p'`
    gateway=`ip route show dev $1 | fgrep default | sed 's/default via //'`
}
    
is_bonding() {
    [ -f "/sys/class/net/$1/bonding/slaves" ]
}

is_vlan() {
    [ -f "/proc/net/vlan/$1" ]
}

is_ifup() {
    ip link show dev $1 | awk '{ exit $3 !~ /[<,]UP[,>]/ }'
}

do_ifup() {
    if ! ifup $1 || ! is_ifup $1 ; then
        if [ -n "${addr_pfx}" ] ; then
            # use the info from get_ip_info()
            ip addr flush $1
            ip addr add ${addr_pfx} dev $1
            ip link set dev $1 up
            [ ${gateway} ] && ip route add default via ${gateway}
        fi
    fi
}

# 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} label ${dst}/
s/secondary//
" | sh -e
    # Remove automatic routes on destination device
    ip route list | sed -ne "
/dev ${dst}\( \|$\)/ {
  s/^/ip route del /
  p
}" | sh -e
}

# 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
}


##
# 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 ${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 '============================================================'
}

is_network_root () {
    local rootfs=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $3; }}' /etc/mtab)
    local rootopts=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $4; }}' /etc/mtab)

    [[ "$rootfs" =~ "^nfs" ]] || [[ "$rootopts" =~ "_netdev" ]] && return 0 || return 1
}

op_start () {
    if [ "${bridge}" = "null" ] ; then
	return
    fi

    if is_network_root ; then
        [ -x /usr/bin/logger ] && /usr/bin/logger "network-bridge: bridging not supported on network root; not starting"
        return
    fi

    if ! link_exists "$vdev"; then
        if link_exists "$pdev"; then
            # The device is already up.
            return
        else
            echo "
Link $vdev is missing.
This may be because you have reached the limit of the number of interfaces
that the loopback driver supports.  If the loopback driver is a module, you
may raise this limit by passing it as a parameter (nloopbacks=<N>); if the
driver is compiled statically into the kernel, then you may set the parameter
using loopback.nloopbacks=<N> on the domain 0 kernel command line.
" >&2
            exit 1
        fi
    fi

    if link_exists "$vdev"; then
	mac=`ip link show ${netdev} | grep 'link\/ether' | sed -e 's/.*ether \(..:..:..:..:..:..\).*/\1/'`
	preiftransfer ${netdev}
	transfer_addrs ${netdev} ${vdev}
	if is_bonding ${netdev} || is_vlan ${netdev} || ! ifdown ${netdev}; then
	    # Remember the IP details if necessary.
	    get_ip_info ${netdev}
	    ip link set ${netdev} down
	    ip addr flush ${netdev}
	fi
	ip link set ${netdev} name ${pdev}
	ip link set ${vdev} name ${netdev}

	setup_bridge_port ${pdev}
	setup_bridge_port ${vif0}
	ip link set ${netdev} addr ${mac} arp on

	# Set the MTU of the netdev to match the pdev
	if [ -e "/sys/class/net/${pdev}/mtu" ]; then
	    ip link set ${netdev} mtu `cat /sys/class/net/${pdev}/mtu`
	fi

	ifup_and_wait ${pdev}
	create_bridge ${bridge} ${pdev}
	add_to_bridge ${bridge} ${vif0}
	do_ifup ${netdev}
    else
	# old style without ${vdev}
	create_bridge   ${bridge}
	transfer_addrs  ${netdev} ${bridge}
	transfer_routes ${netdev} ${bridge}
    fi

    if [ ${antispoof} = 'yes' ] ; then
	antispoofing
    fi
}

op_stop () {
    if [ "${bridge}" = "null" ]; then
	return
    fi
    if ! link_exists "$bridge"; then
	return
    fi

    if link_exists "$pdev"; then
	ip link set dev ${vif0} down
	mac=`ip link show ${netdev} | grep 'link\/ether' | sed -e 's/.*ether \(..:..:..:..:..:..\).*/\1/'`
	transfer_addrs ${netdev} ${pdev}
	if ! ifdown ${netdev}; then
	    get_ip_info ${netdev}
	fi
	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}
	do_ifup ${netdev}
    else
	transfer_routes ${bridge} ${netdev}
	ip link set ${bridge} down
    fi
    brctl delbr ${bridge}
}

# bring up $1 and wait for $dev to be in running state
ifup_and_wait() {
    local dev=$1
    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
}

case "$command" in
    start)
	op_start
	;;
    
    stop)
	op_stop
	;;

    status)
	show_status ${netdev} ${bridge}
	;;

    *)
	echo "Unknown command: $command" >&2
	echo 'Valid commands are: start, stop, status' >&2
	exit 1
esac