ia64/xen-unstable

annotate tools/examples/network-bridge @ 16684:7b7700a30e52

Handle netdev secondary addresses and labels

Fix the network-bridge logic to correctly transfer secondary IP
address from $netdev to $bridge.

e.g. if you add an secondary address/label/alias with:

$> ip addr add 172.31.0.200/24 dev eth0 label eth0:00

then, "ip addr show dev eth0" gives e.g.:

inet 172.31.0.10/24 brd 172.31.0.255 scope global eth0
inet 172.31.0.200/24 scope global secondary eth0:00

and transfer_addrs() tries to execute:

ip addr add 172.31.0.10/24 brd 172.31.0.255 scope global dev tmpbridge
ip addr add 172.31.0.200/24 scope global secondary dev tmpbridge:00

which causes the sript to fail because:

1) The device tmpbridge:00 doesn't exist
2) The "secondary" flag isn't valid

This patch fixes the sed commands to instead give:

ip addr add 172.31.0.10/24 brd 172.31.0.255 scope global dev tmpbridge label tmpbridge
ip addr add 172.31.0.200/24 scope global dev tmpbridge label tmpbridge:00

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jan 08 09:43:44 2008 +0000 (2008-01-08)
parents d4c5a1cdcf2e
children 850ec55df0dc
rev   line source
atse@13255 1 #!/bin/bash
mjw@1723 2 #============================================================================
mjw@2289 3 # Default Xen network start/stop script.
mjw@1723 4 # Xend calls a network script when it starts.
mjw@2289 5 # The script name to use is defined in /etc/xen/xend-config.sxp
mjw@2289 6 # in the network-script field.
mjw@1723 7 #
kfraser@15258 8 # This script creates a bridge (default ${netdev}), adds a device
kfraser@15258 9 # (defaults to the device on the default gateway route) to it, copies
kfraser@15258 10 # the IP addresses from the device to the bridge and adjusts the routes
kfraser@15258 11 # accordingly.
mjw@2289 12 #
mjw@2289 13 # If all goes well, this should ensure that networking stays up.
mjw@2289 14 # However, some configurations are upset by this, especially
mjw@2289 15 # NFS roots. If the bridged setup does not meet your needs,
mjw@2289 16 # configure a different script, for example using routing instead.
mjw@2289 17 #
mjw@2289 18 # Usage:
mjw@2289 19 #
kaf24@7748 20 # network-bridge (start|stop|status) {VAR=VAL}*
mjw@1723 21 #
mjw@1723 22 # Vars:
mjw@1723 23 #
kfraser@15258 24 # bridge The bridge to use (default ${netdev}).
kfraser@15258 25 # netdev The interface to add to the bridge (default gateway device).
emellor@7468 26 # antispoof Whether to use iptables to prevent spoofing (default no).
mjw@1723 27 #
kaf24@7748 28 # Internal Vars:
kaf24@7748 29 # pdev="p${netdev}"
kfraser@15258 30 # tdev=tmpbridge
kaf24@7748 31 #
mjw@1723 32 # start:
kfraser@15258 33 # Creates the bridge as tdev
kfraser@15258 34 # Copies the IP and MAC addresses from pdev to bridge
kaf24@7748 35 # Renames netdev to be pdev
kfraser@15258 36 # Renames tdev to bridge
kfraser@15258 37 # Enslaves pdev to bridge
mjw@1723 38 #
mjw@1723 39 # stop:
kfraser@15258 40 # Removes pdev from the bridge
kfraser@15258 41 # Transfers addresses, routes from bridge to pdev
kfraser@15258 42 # Renames bridge to tdev
kaf24@7748 43 # Renames pdev to netdev
kfraser@15258 44 # Deletes tdev
mjw@1723 45 #
mjw@1723 46 # status:
kaf24@7748 47 # Print addresses, interfaces, routes
mjw@1723 48 #
mjw@1723 49 #============================================================================
mjw@1723 50
emellor@7557 51
emellor@7468 52 dir=$(dirname "$0")
emellor@7557 53 . "$dir/xen-script-common.sh"
emellor@7468 54 . "$dir/xen-network-common.sh"
kaf24@7233 55
emellor@7557 56 findCommand "$@"
emellor@7557 57 evalVariables "$@"
mjw@1723 58
keir@16072 59 is_network_root () {
keir@16072 60 local rootfs=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $3; }}' /etc/mtab)
keir@16072 61 local rootopts=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $4; }}' /etc/mtab)
keir@16072 62
keir@16072 63 [[ "$rootfs" =~ "^nfs" ]] || [[ "$rootopts" =~ "_netdev" ]] && return 0 || return 1
keir@16072 64 }
keir@16072 65
keir@16072 66 find_alt_device () {
keir@16072 67 local interf=$1
keir@16072 68 local prefix=${interf%[[:digit:]]}
keir@16072 69 local ifs=$(ip link show | grep " $prefix" |\
keir@16072 70 gawk '{ printf ("%s",substr($2,1,length($2)-1)) }' |\
keir@16072 71 sed s/$interf//)
keir@16072 72 echo "$ifs"
keir@16072 73 }
keir@16072 74
keir@16350 75 netdev=${netdev:-$(ip route list 0.0.0.0/0 | \
keir@16350 76 sed 's/.*dev \([a-z]\+[0-9]\+\).*$/\1/')}
keir@16072 77 if is_network_root ; then
keir@16072 78 altdevs=$(find_alt_device $netdev)
keir@16072 79 for netdev in $altdevs; do break; done
keir@16072 80 if [ -z "$netdev" ]; then
keir@16072 81 [ -x /usr/bin/logger ] && /usr/bin/logger "network-bridge: bridging not supported on network root; not starting"
keir@16072 82 exit
keir@16072 83 fi
keir@16072 84 fi
keir@15958 85 netdev=${netdev:-eth0}
kfraser@15258 86 bridge=${bridge:-${netdev}}
emellor@7468 87 antispoof=${antispoof:-no}
mjw@1723 88
emellor@7446 89 pdev="p${netdev}"
kfraser@15258 90 tdev=tmpbridge
emellor@7446 91
emellor@8540 92 get_ip_info() {
emellor@8540 93 addr_pfx=`ip addr show dev $1 | egrep '^ *inet' | sed -e 's/ *inet //' -e 's/ .*//'`
emellor@8540 94 gateway=`ip route show dev $1 | fgrep default | sed 's/default via //'`
emellor@7446 95 }
emellor@8540 96
emellor@8303 97 do_ifup() {
emellor@8303 98 if ! ifup $1 ; then
emellor@8540 99 if [ ${addr_pfx} ] ; then
emellor@8540 100 # use the info from get_ip_info()
emellor@8303 101 ip addr flush $1
emellor@8540 102 ip addr add ${addr_pfx} dev $1
emellor@8303 103 ip link set dev $1 up
emellor@8540 104 [ ${gateway} ] && ip route add default via ${gateway}
emellor@8303 105 fi
emellor@8303 106 fi
emellor@8303 107 }
emellor@8303 108
mjw@1723 109 # Usage: transfer_addrs src dst
mjw@1723 110 # Copy all IP addresses (including aliases) from device $src to device $dst.
mjw@1723 111 transfer_addrs () {
mjw@1723 112 local src=$1
mjw@1723 113 local dst=$2
mjw@1723 114 # Don't bother if $dst already has IP addresses.
iap10@3513 115 if ip addr show dev ${dst} | egrep -q '^ *inet ' ; then
mjw@1723 116 return
mjw@1723 117 fi
mjw@1723 118 # Address lines start with 'inet' and have the device in them.
mjw@1723 119 # Replace 'inet' with 'ip addr add' and change the device name $src
cl349@5270 120 # to 'dev $src'.
iap10@3513 121 ip addr show dev ${src} | egrep '^ *inet ' | sed -e "
mjw@1723 122 s/inet/ip addr add/
cl349@5270 123 s@\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+/[0-9]\+\)@\1@
keir@16684 124 s/${src}/dev ${dst} label ${dst}/
keir@16684 125 s/secondary//
mjw@1723 126 " | sh -e
kaf24@7748 127 # Remove automatic routes on destination device
cl349@5271 128 ip route list | sed -ne "
cl349@5271 129 /dev ${dst}\( \|$\)/ {
cl349@5271 130 s/^/ip route del /
cl349@5271 131 p
cl349@5271 132 }" | sh -e
mjw@1723 133 }
mjw@1723 134
mjw@1723 135 # Usage: transfer_routes src dst
mjw@1723 136 # Get all IP routes to device $src, delete them, and
mjw@1723 137 # add the same routes to device $dst.
mjw@1723 138 # The original routes have to be deleted, otherwise adding them
mjw@1723 139 # for $dst fails (duplicate routes).
mjw@1723 140 transfer_routes () {
mjw@1723 141 local src=$1
mjw@1723 142 local dst=$2
mjw@1723 143 # List all routes and grep the ones with $src in.
mjw@1723 144 # Stick 'ip route del' on the front to delete.
mjw@1723 145 # Change $src to $dst and use 'ip route add' to add.
cl349@5271 146 ip route list | sed -ne "
cl349@5271 147 /dev ${src}\( \|$\)/ {
cl349@5271 148 h
cl349@5271 149 s/^/ip route del /
cl349@5271 150 P
cl349@5271 151 g
cl349@5271 152 s/${src}/${dst}/
cl349@5271 153 s/^/ip route add /
cl349@5271 154 P
cl349@5271 155 d
cl349@5271 156 }" | sh -e
mjw@1723 157 }
mjw@1723 158
emellor@7826 159
emellor@7826 160 ##
emellor@7826 161 # link_exists interface
emellor@7826 162 #
emellor@7826 163 # Returns 0 if the interface named exists (whether up or down), 1 otherwise.
emellor@7826 164 #
emellor@7826 165 link_exists()
emellor@7826 166 {
emellor@8540 167 if ip link show "$1" >/dev/null 2>/dev/null
emellor@7826 168 then
emellor@7826 169 return 0
emellor@7826 170 else
emellor@7826 171 return 1
emellor@7826 172 fi
emellor@7826 173 }
emellor@7826 174
mjw@1723 175 # Set the default forwarding policy for $dev to drop.
mjw@1723 176 # Allow forwarding to the bridge.
mjw@1723 177 antispoofing () {
mjw@1723 178 iptables -P FORWARD DROP
emellor@7468 179 iptables -F FORWARD
emellor@7468 180 iptables -A FORWARD -m physdev --physdev-in ${pdev} -j ACCEPT
mjw@1723 181 }
mjw@1723 182
mjw@1723 183 # Usage: show_status dev bridge
mjw@1723 184 # Print ifconfig and routes.
mjw@1723 185 show_status () {
mjw@1723 186 local dev=$1
mjw@1723 187 local bridge=$2
mjw@1723 188
mjw@1723 189 echo '============================================================'
emellor@7446 190 ip addr show ${dev}
emellor@7446 191 ip addr show ${bridge}
emellor@7446 192 echo ' '
emellor@7446 193 brctl show ${bridge}
mjw@1723 194 echo ' '
mjw@1723 195 ip route list
mjw@1723 196 echo ' '
mjw@1723 197 route -n
mjw@1723 198 echo '============================================================'
mjw@1723 199 }
mjw@1723 200
mjw@2507 201 op_start () {
emellor@8540 202 if [ "${bridge}" = "null" ] ; then
emellor@7446 203 return
mjw@2507 204 fi
kaf24@4938 205
Christian@14817 206 if link_exists "$pdev"; then
kfraser@15258 207 # The device is already up.
kfraser@15258 208 return
emellor@7648 209 fi
kaf24@4938 210
kfraser@15258 211 create_bridge ${tdev}
kaf24@10462 212
kfraser@15258 213 preiftransfer ${netdev}
kfraser@15258 214 transfer_addrs ${netdev} ${tdev}
kfraser@15258 215 if ! ifdown ${netdev}; then
kfraser@15258 216 # If ifdown fails, remember the IP details.
kfraser@15258 217 get_ip_info ${netdev}
kfraser@15258 218 ip link set ${netdev} down
kfraser@15258 219 ip addr flush ${netdev}
kfraser@15258 220 fi
kfraser@15258 221 ip link set ${netdev} name ${pdev}
kfraser@15258 222 ip link set ${tdev} name ${bridge}
kaf24@10462 223
kfraser@15258 224 setup_bridge_port ${pdev}
kfraser@15258 225
kfraser@15258 226 add_to_bridge2 ${bridge} ${pdev}
kfraser@15258 227 do_ifup ${bridge}
emellor@7446 228
emellor@8540 229 if [ ${antispoof} = 'yes' ] ; then
emellor@7468 230 antispoofing
mjw@2507 231 fi
mjw@2507 232 }
mjw@2507 233
mjw@2507 234 op_stop () {
emellor@8540 235 if [ "${bridge}" = "null" ]; then
emellor@7446 236 return
emellor@7446 237 fi
emellor@7826 238 if ! link_exists "$bridge"; then
emellor@7446 239 return
mjw@2507 240 fi
kaf24@4938 241
kfraser@15258 242 transfer_addrs ${bridge} ${pdev}
kfraser@15258 243 if ! ifdown ${bridge}; then
kfraser@15258 244 get_ip_info ${bridge}
kfraser@15258 245 fi
kfraser@15258 246 ip link set ${pdev} down
kfraser@15258 247 ip addr flush ${bridge}
kaf24@6839 248
kfraser@15258 249 brctl delif ${bridge} ${pdev}
kfraser@15258 250 ip link set ${bridge} down
kaf24@6839 251
kfraser@15258 252 ip link set ${bridge} name ${tdev}
kfraser@15258 253 ip link set ${pdev} name ${netdev}
kfraser@15258 254 do_ifup ${netdev}
kfraser@15258 255
kfraser@15258 256 brctl delbr ${tdev}
mjw@2507 257 }
mjw@2507 258
emellor@8646 259 # adds $dev to $bridge but waits for $dev to be in running state first
emellor@8646 260 add_to_bridge2() {
emellor@8646 261 local bridge=$1
emellor@8646 262 local dev=$2
emellor@8646 263 local maxtries=10
emellor@8646 264
emellor@8646 265 echo -n "Waiting for ${dev} to negotiate link."
kaf24@10462 266 ip link set ${dev} up
emellor@8646 267 for i in `seq ${maxtries}` ; do
emellor@8646 268 if ifconfig ${dev} | grep -q RUNNING ; then
emellor@8646 269 break
emellor@8646 270 else
emellor@8646 271 echo -n '.'
emellor@8646 272 sleep 1
emellor@8646 273 fi
emellor@8646 274 done
emellor@8646 275
kfraser@15821 276 if [ ${i} -eq ${maxtries} ] ; then echo -n '(link isnt in running state)' ; fi
kfraser@15821 277 echo
emellor@8646 278
emellor@8646 279 add_to_bridge ${bridge} ${dev}
emellor@8646 280 }
emellor@8646 281
emellor@7557 282 case "$command" in
kaf24@6839 283 start)
emellor@7446 284 op_start
emellor@7446 285 ;;
mjw@1723 286
mjw@1723 287 stop)
emellor@7446 288 op_stop
emellor@7446 289 ;;
mjw@1723 290
mjw@1723 291 status)
emellor@7446 292 show_status ${netdev} ${bridge}
emellor@7446 293 ;;
mjw@1723 294
mjw@1723 295 *)
emellor@7557 296 echo "Unknown command: $command" >&2
emellor@7446 297 echo 'Valid commands are: start, stop, status' >&2
emellor@7446 298 exit 1
mjw@1723 299 esac