| rev | 
   line source | 
| 
root@51
 | 
     1 #!/bin/bash
 | 
| 
root@51
 | 
     2 #============================================================================
 | 
| 
root@51
 | 
     3 # Default Xen network start/stop script.
 | 
| 
root@51
 | 
     4 # Xend calls a network script when it starts.
 | 
| 
root@51
 | 
     5 # The script name to use is defined in /etc/xen/xend-config.sxp
 | 
| 
root@51
 | 
     6 # in the network-script field.
 | 
| 
root@51
 | 
     7 #
 | 
| 
root@51
 | 
     8 # This script creates a bridge (default xenbr${vifnum}), adds a device
 | 
| 
root@51
 | 
     9 # (default eth${vifnum}) to it, copies the IP addresses from the device
 | 
| 
root@51
 | 
    10 # to the bridge and adjusts the routes accordingly.
 | 
| 
root@51
 | 
    11 #
 | 
| 
root@51
 | 
    12 # If all goes well, this should ensure that networking stays up.
 | 
| 
root@51
 | 
    13 # However, some configurations are upset by this, especially
 | 
| 
root@51
 | 
    14 # NFS roots. If the bridged setup does not meet your needs,
 | 
| 
root@51
 | 
    15 # configure a different script, for example using routing instead.
 | 
| 
root@51
 | 
    16 #
 | 
| 
root@51
 | 
    17 # Usage:
 | 
| 
root@51
 | 
    18 #
 | 
| 
root@51
 | 
    19 # network-bridge (start|stop|status) {VAR=VAL}*
 | 
| 
root@51
 | 
    20 #
 | 
| 
root@51
 | 
    21 # Vars:
 | 
| 
root@51
 | 
    22 #
 | 
| 
root@51
 | 
    23 # vifnum     Virtual device number to use (default 0). Numbers >=8
 | 
| 
root@51
 | 
    24 #            require the netback driver to have nloopbacks set to a
 | 
| 
root@51
 | 
    25 #            higher value than its default of 8.
 | 
| 
root@51
 | 
    26 # bridge     The bridge to use (default xenbr${vifnum}).
 | 
| 
root@51
 | 
    27 # netdev     The interface to add to the bridge (default eth${vifnum}).
 | 
| 
root@51
 | 
    28 # antispoof  Whether to use iptables to prevent spoofing (default no).
 | 
| 
root@51
 | 
    29 #
 | 
| 
root@51
 | 
    30 # Internal Vars:
 | 
| 
root@51
 | 
    31 # pdev="p${netdev}"
 | 
| 
root@51
 | 
    32 # vdev="veth${vifnum}"
 | 
| 
root@51
 | 
    33 # vif0="vif0.${vifnum}"
 | 
| 
root@51
 | 
    34 #
 | 
| 
root@51
 | 
    35 # start:
 | 
| 
root@51
 | 
    36 # Creates the bridge
 | 
| 
root@51
 | 
    37 # Copies the IP and MAC addresses from netdev to vdev
 | 
| 
root@51
 | 
    38 # Renames netdev to be pdev 
 | 
| 
root@51
 | 
    39 # Renames vdev to be netdev 
 | 
| 
root@51
 | 
    40 # Enslaves pdev, vdev to bridge
 | 
| 
root@51
 | 
    41 #
 | 
| 
root@51
 | 
    42 # stop:
 | 
| 
root@51
 | 
    43 # Removes netdev from the bridge
 | 
| 
root@51
 | 
    44 # Transfers addresses, routes from netdev to pdev
 | 
| 
root@51
 | 
    45 # Renames netdev to vdev
 | 
| 
root@51
 | 
    46 # Renames pdev to netdev 
 | 
| 
root@51
 | 
    47 # Deletes bridge
 | 
| 
root@51
 | 
    48 #
 | 
| 
root@51
 | 
    49 # status:
 | 
| 
root@51
 | 
    50 # Print addresses, interfaces, routes
 | 
| 
root@51
 | 
    51 #
 | 
| 
root@51
 | 
    52 #============================================================================
 | 
| 
root@51
 | 
    53 
 | 
| 
root@51
 | 
    54 
 | 
| 
root@51
 | 
    55 dir=$(dirname "$0")
 | 
| 
root@51
 | 
    56 . "$dir/xen-script-common.sh"
 | 
| 
root@51
 | 
    57 . "$dir/xen-network-common.sh"
 | 
| 
root@51
 | 
    58 
 | 
| 
root@51
 | 
    59 findCommand "$@"
 | 
| 
root@51
 | 
    60 evalVariables "$@"
 | 
| 
root@51
 | 
    61 
 | 
| 
root@51
 | 
    62 modprobe netloop > /dev/null 2>&1 || true
 | 
| 
root@51
 | 
    63 
 | 
| 
root@51
 | 
    64 vifnum=${vifnum:-$(ip route list | awk '/^default / { print $NF }' | sed 's/^[^0-9]*//')}
 | 
| 
root@51
 | 
    65 vifnum=${vifnum:-0}
 | 
| 
root@51
 | 
    66 bridge=${bridge:-xenbr${vifnum}}
 | 
| 
root@51
 | 
    67 netdev=${netdev:-eth${vifnum}}
 | 
| 
root@51
 | 
    68 antispoof=${antispoof:-no}
 | 
| 
root@51
 | 
    69 
 | 
| 
root@51
 | 
    70 pdev="p${netdev}"
 | 
| 
root@51
 | 
    71 vdev="veth${vifnum}"
 | 
| 
root@51
 | 
    72 vif0="vif0.${vifnum}"
 | 
| 
root@51
 | 
    73 
 | 
| 
root@51
 | 
    74 get_ip_info() {
 | 
| 
root@51
 | 
    75     addr_pfx=`ip addr show dev $1 | egrep '^ *inet' | sed -e 's/ *inet //' -e 's/ .*//'`
 | 
| 
root@51
 | 
    76     gateway=`ip route show dev $1 | fgrep default | sed 's/default via //'`
 | 
| 
root@51
 | 
    77 }
 | 
| 
root@51
 | 
    78     
 | 
| 
root@51
 | 
    79 do_ifup() {
 | 
| 
root@51
 | 
    80     if ! ifup $1 ; then
 | 
| 
root@51
 | 
    81         if [ ${addr_pfx} ] ; then
 | 
| 
root@51
 | 
    82             # use the info from get_ip_info()
 | 
| 
root@51
 | 
    83             ip addr flush $1
 | 
| 
root@51
 | 
    84             ip addr add ${addr_pfx} dev $1
 | 
| 
root@51
 | 
    85             ip link set dev $1 up
 | 
| 
root@51
 | 
    86             [ ${gateway} ] && ip route add default via ${gateway}
 | 
| 
root@51
 | 
    87         fi
 | 
| 
root@51
 | 
    88     fi
 | 
| 
root@51
 | 
    89 }
 | 
| 
root@51
 | 
    90 
 | 
| 
root@51
 | 
    91 # Usage: transfer_addrs src dst
 | 
| 
root@51
 | 
    92 # Copy all IP addresses (including aliases) from device $src to device $dst.
 | 
| 
root@51
 | 
    93 transfer_addrs () {
 | 
| 
root@51
 | 
    94     local src=$1
 | 
| 
root@51
 | 
    95     local dst=$2
 | 
| 
root@51
 | 
    96     # Don't bother if $dst already has IP addresses.
 | 
| 
root@51
 | 
    97     if ip addr show dev ${dst} | egrep -q '^ *inet ' ; then
 | 
| 
root@51
 | 
    98         return
 | 
| 
root@51
 | 
    99     fi
 | 
| 
root@51
 | 
   100     # Address lines start with 'inet' and have the device in them.
 | 
| 
root@51
 | 
   101     # Replace 'inet' with 'ip addr add' and change the device name $src
 | 
| 
root@51
 | 
   102     # to 'dev $src'.
 | 
| 
root@51
 | 
   103     ip addr show dev ${src} | egrep '^ *inet ' | sed -e "
 | 
| 
root@51
 | 
   104 s/inet/ip addr add/
 | 
| 
root@51
 | 
   105 s@\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+/[0-9]\+\)@\1@
 | 
| 
root@51
 | 
   106 s/${src}/dev ${dst}/
 | 
| 
root@51
 | 
   107 " | sh -e
 | 
| 
root@51
 | 
   108     # Remove automatic routes on destination device
 | 
| 
root@51
 | 
   109     ip route list | sed -ne "
 | 
| 
root@51
 | 
   110 /dev ${dst}\( \|$\)/ {
 | 
| 
root@51
 | 
   111   s/^/ip route del /
 | 
| 
root@51
 | 
   112   p
 | 
| 
root@51
 | 
   113 }" | sh -e
 | 
| 
root@51
 | 
   114 }
 | 
| 
root@51
 | 
   115 
 | 
| 
root@51
 | 
   116 # Usage: transfer_routes src dst
 | 
| 
root@51
 | 
   117 # Get all IP routes to device $src, delete them, and
 | 
| 
root@51
 | 
   118 # add the same routes to device $dst.
 | 
| 
root@51
 | 
   119 # The original routes have to be deleted, otherwise adding them
 | 
| 
root@51
 | 
   120 # for $dst fails (duplicate routes).
 | 
| 
root@51
 | 
   121 transfer_routes () {
 | 
| 
root@51
 | 
   122     local src=$1
 | 
| 
root@51
 | 
   123     local dst=$2
 | 
| 
root@51
 | 
   124     # List all routes and grep the ones with $src in.
 | 
| 
root@51
 | 
   125     # Stick 'ip route del' on the front to delete.
 | 
| 
root@51
 | 
   126     # Change $src to $dst and use 'ip route add' to add.
 | 
| 
root@51
 | 
   127     ip route list | sed -ne "
 | 
| 
root@51
 | 
   128 /dev ${src}\( \|$\)/ {
 | 
| 
root@51
 | 
   129   h
 | 
| 
root@51
 | 
   130   s/^/ip route del /
 | 
| 
root@51
 | 
   131   P
 | 
| 
root@51
 | 
   132   g
 | 
| 
root@51
 | 
   133   s/${src}/${dst}/
 | 
| 
root@51
 | 
   134   s/^/ip route add /
 | 
| 
root@51
 | 
   135   P
 | 
| 
root@51
 | 
   136   d
 | 
| 
root@51
 | 
   137 }" | sh -e
 | 
| 
root@51
 | 
   138 }
 | 
| 
root@51
 | 
   139 
 | 
| 
root@51
 | 
   140 
 | 
| 
root@51
 | 
   141 ##
 | 
| 
root@51
 | 
   142 # link_exists interface
 | 
| 
root@51
 | 
   143 #
 | 
| 
root@51
 | 
   144 # Returns 0 if the interface named exists (whether up or down), 1 otherwise.
 | 
| 
root@51
 | 
   145 #
 | 
| 
root@51
 | 
   146 link_exists()
 | 
| 
root@51
 | 
   147 {
 | 
| 
root@51
 | 
   148     if ip link show "$1" >/dev/null 2>/dev/null
 | 
| 
root@51
 | 
   149     then
 | 
| 
root@51
 | 
   150         return 0
 | 
| 
root@51
 | 
   151     else
 | 
| 
root@51
 | 
   152         return 1
 | 
| 
root@51
 | 
   153     fi
 | 
| 
root@51
 | 
   154 }
 | 
| 
root@51
 | 
   155 
 | 
| 
root@51
 | 
   156 # Set the default forwarding policy for $dev to drop.
 | 
| 
root@51
 | 
   157 # Allow forwarding to the bridge.
 | 
| 
root@51
 | 
   158 antispoofing () {
 | 
| 
root@51
 | 
   159     iptables -P FORWARD DROP
 | 
| 
root@51
 | 
   160     iptables -F FORWARD
 | 
| 
root@51
 | 
   161     iptables -A FORWARD -m physdev --physdev-in ${pdev} -j ACCEPT
 | 
| 
root@51
 | 
   162     iptables -A FORWARD -m physdev --physdev-in ${vif0} -j ACCEPT
 | 
| 
root@51
 | 
   163 }
 | 
| 
root@51
 | 
   164 
 | 
| 
root@51
 | 
   165 # Usage: show_status dev bridge
 | 
| 
root@51
 | 
   166 # Print ifconfig and routes.
 | 
| 
root@51
 | 
   167 show_status () {
 | 
| 
root@51
 | 
   168     local dev=$1
 | 
| 
root@51
 | 
   169     local bridge=$2
 | 
| 
root@51
 | 
   170     
 | 
| 
root@51
 | 
   171     echo '============================================================'
 | 
| 
root@51
 | 
   172     ip addr show ${dev}
 | 
| 
root@51
 | 
   173     ip addr show ${bridge}
 | 
| 
root@51
 | 
   174     echo ' '
 | 
| 
root@51
 | 
   175     brctl show ${bridge}
 | 
| 
root@51
 | 
   176     echo ' '
 | 
| 
root@51
 | 
   177     ip route list
 | 
| 
root@51
 | 
   178     echo ' '
 | 
| 
root@51
 | 
   179     route -n
 | 
| 
root@51
 | 
   180     echo '============================================================'
 | 
| 
root@51
 | 
   181 }
 | 
| 
root@51
 | 
   182 
 | 
| 
root@51
 | 
   183 op_start () {
 | 
| 
root@51
 | 
   184     if [ "${bridge}" = "null" ] ; then
 | 
| 
root@51
 | 
   185 	return
 | 
| 
root@51
 | 
   186     fi
 | 
| 
root@51
 | 
   187 
 | 
| 
root@51
 | 
   188     if ! link_exists "$vdev"; then
 | 
| 
root@51
 | 
   189         if link_exists "$pdev"; then
 | 
| 
root@51
 | 
   190             # The device is already up.
 | 
| 
root@51
 | 
   191             return
 | 
| 
root@51
 | 
   192         else
 | 
| 
root@51
 | 
   193             echo "
 | 
| 
root@51
 | 
   194 Link $vdev is missing.
 | 
| 
root@51
 | 
   195 This may be because you have reached the limit of the number of interfaces
 | 
| 
root@51
 | 
   196 that the loopback driver supports.  If the loopback driver is a module, you
 | 
| 
root@51
 | 
   197 may raise this limit by passing it as a parameter (nloopbacks=<N>); if the
 | 
| 
root@51
 | 
   198 driver is compiled statically into the kernel, then you may set the parameter
 | 
| 
root@51
 | 
   199 using loopback.nloopbacks=<N> on the domain 0 kernel command line.
 | 
| 
root@51
 | 
   200 " >&2
 | 
| 
root@51
 | 
   201             exit 1
 | 
| 
root@51
 | 
   202         fi
 | 
| 
root@51
 | 
   203     fi
 | 
| 
root@51
 | 
   204 
 | 
| 
root@51
 | 
   205     create_bridge ${bridge}
 | 
| 
root@51
 | 
   206 
 | 
| 
root@51
 | 
   207     if link_exists "$vdev"; then
 | 
| 
root@51
 | 
   208 	mac=`ip link show ${netdev} | grep 'link\/ether' | sed -e 's/.*ether \(..:..:..:..:..:..\).*/\1/'`
 | 
| 
root@51
 | 
   209 	preiftransfer ${netdev}
 | 
| 
root@51
 | 
   210 	transfer_addrs ${netdev} ${vdev}
 | 
| 
root@51
 | 
   211 	if ! ifdown ${netdev}; then
 | 
| 
root@51
 | 
   212 	    # If ifdown fails, remember the IP details.
 | 
| 
root@51
 | 
   213 	    get_ip_info ${netdev}
 | 
| 
root@51
 | 
   214 	    ip link set ${netdev} down
 | 
| 
root@51
 | 
   215 	    ip addr flush ${netdev}
 | 
| 
root@51
 | 
   216 	fi
 | 
| 
root@51
 | 
   217 	ip link set ${netdev} name ${pdev}
 | 
| 
root@51
 | 
   218 	ip link set ${vdev} name ${netdev}
 | 
| 
root@51
 | 
   219 
 | 
| 
root@51
 | 
   220 	setup_bridge_port ${pdev}
 | 
| 
root@51
 | 
   221 	setup_bridge_port ${vif0}
 | 
| 
root@51
 | 
   222 	ip link set ${netdev} addr ${mac} arp on
 | 
| 
root@51
 | 
   223 
 | 
| 
root@51
 | 
   224 	ip link set ${bridge} up
 | 
| 
root@51
 | 
   225 	add_to_bridge  ${bridge} ${vif0}
 | 
| 
root@51
 | 
   226 	add_to_bridge2 ${bridge} ${pdev}
 | 
| 
root@51
 | 
   227 	do_ifup ${netdev}
 | 
| 
root@51
 | 
   228     else
 | 
| 
root@51
 | 
   229 	# old style without ${vdev}
 | 
| 
root@51
 | 
   230 	transfer_addrs  ${netdev} ${bridge}
 | 
| 
root@51
 | 
   231 	transfer_routes ${netdev} ${bridge}
 | 
| 
root@51
 | 
   232     fi
 | 
| 
root@51
 | 
   233 
 | 
| 
root@51
 | 
   234     if [ ${antispoof} = 'yes' ] ; then
 | 
| 
root@51
 | 
   235 	antispoofing
 | 
| 
root@51
 | 
   236     fi
 | 
| 
root@51
 | 
   237 }
 | 
| 
root@51
 | 
   238 
 | 
| 
root@51
 | 
   239 op_stop () {
 | 
| 
root@51
 | 
   240     if [ "${bridge}" = "null" ]; then
 | 
| 
root@51
 | 
   241 	return
 | 
| 
root@51
 | 
   242     fi
 | 
| 
root@51
 | 
   243     if ! link_exists "$bridge"; then
 | 
| 
root@51
 | 
   244 	return
 | 
| 
root@51
 | 
   245     fi
 | 
| 
root@51
 | 
   246 
 | 
| 
root@51
 | 
   247     if link_exists "$pdev"; then
 | 
| 
root@51
 | 
   248 	ip link set dev ${vif0} down
 | 
| 
root@51
 | 
   249 	mac=`ip link show ${netdev} | grep 'link\/ether' | sed -e 's/.*ether \(..:..:..:..:..:..\).*/\1/'`
 | 
| 
root@51
 | 
   250 	transfer_addrs ${netdev} ${pdev}
 | 
| 
root@51
 | 
   251 	if ! ifdown ${netdev}; then
 | 
| 
root@51
 | 
   252 	    get_ip_info ${netdev}
 | 
| 
root@51
 | 
   253 	fi
 | 
| 
root@51
 | 
   254 	ip link set ${netdev} down arp off
 | 
| 
root@51
 | 
   255 	ip link set ${netdev} addr fe:ff:ff:ff:ff:ff
 | 
| 
root@51
 | 
   256 	ip link set ${pdev} down
 | 
| 
root@51
 | 
   257 	ip addr flush ${netdev}
 | 
| 
root@51
 | 
   258 	ip link set ${pdev} addr ${mac} arp on
 | 
| 
root@51
 | 
   259 
 | 
| 
root@51
 | 
   260 	brctl delif ${bridge} ${pdev}
 | 
| 
root@51
 | 
   261 	brctl delif ${bridge} ${vif0}
 | 
| 
root@51
 | 
   262 	ip link set ${bridge} down
 | 
| 
root@51
 | 
   263 
 | 
| 
root@51
 | 
   264 	ip link set ${netdev} name ${vdev}
 | 
| 
root@51
 | 
   265 	ip link set ${pdev} name ${netdev}
 | 
| 
root@51
 | 
   266 	do_ifup ${netdev}
 | 
| 
root@51
 | 
   267     else
 | 
| 
root@51
 | 
   268 	transfer_routes ${bridge} ${netdev}
 | 
| 
root@51
 | 
   269 	ip link set ${bridge} down
 | 
| 
root@51
 | 
   270     fi
 | 
| 
root@51
 | 
   271     brctl delbr ${bridge}
 | 
| 
root@51
 | 
   272 }
 | 
| 
root@51
 | 
   273 
 | 
| 
root@51
 | 
   274 # adds $dev to $bridge but waits for $dev to be in running state first
 | 
| 
root@51
 | 
   275 add_to_bridge2() {
 | 
| 
root@51
 | 
   276     local bridge=$1
 | 
| 
root@51
 | 
   277     local dev=$2
 | 
| 
root@51
 | 
   278     local maxtries=10
 | 
| 
root@51
 | 
   279 
 | 
| 
root@51
 | 
   280     echo -n "Waiting for ${dev} to negotiate link."
 | 
| 
root@51
 | 
   281     ip link set ${dev} up
 | 
| 
root@51
 | 
   282     for i in `seq ${maxtries}` ; do
 | 
| 
root@51
 | 
   283 	if ifconfig ${dev} | grep -q RUNNING ; then
 | 
| 
root@51
 | 
   284 	    break
 | 
| 
root@51
 | 
   285 	else
 | 
| 
root@51
 | 
   286 	    echo -n '.'
 | 
| 
root@51
 | 
   287 	    sleep 1
 | 
| 
root@51
 | 
   288 	fi
 | 
| 
root@51
 | 
   289     done
 | 
| 
root@51
 | 
   290 
 | 
| 
root@51
 | 
   291     if [ ${i} -eq ${maxtries} ] ; then echo '(link isnt in running state)' ; fi
 | 
| 
root@51
 | 
   292 
 | 
| 
root@51
 | 
   293     add_to_bridge ${bridge} ${dev}
 | 
| 
root@51
 | 
   294 }
 | 
| 
root@51
 | 
   295 
 | 
| 
root@51
 | 
   296 case "$command" in
 | 
| 
root@51
 | 
   297     start)
 | 
| 
root@51
 | 
   298 	op_start
 | 
| 
root@51
 | 
   299 	;;
 | 
| 
root@51
 | 
   300     
 | 
| 
root@51
 | 
   301     stop)
 | 
| 
root@51
 | 
   302 	op_stop
 | 
| 
root@51
 | 
   303 	;;
 | 
| 
root@51
 | 
   304 
 | 
| 
root@51
 | 
   305     status)
 | 
| 
root@51
 | 
   306 	show_status ${netdev} ${bridge}
 | 
| 
root@51
 | 
   307 	;;
 | 
| 
root@51
 | 
   308 
 | 
| 
root@51
 | 
   309     *)
 | 
| 
root@51
 | 
   310 	echo "Unknown command: $command" >&2
 | 
| 
root@51
 | 
   311 	echo 'Valid commands are: start, stop, status' >&2
 | 
| 
root@51
 | 
   312 	exit 1
 | 
| 
root@51
 | 
   313 esac
 |