ia64/xen-unstable

view tools/examples/network-bridge @ 16350:d4c5a1cdcf2e

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