]> scripts.mit.edu Git - xen.git/blob - scripts/network-bridge
Allow memory to balloon to 8GiB
[xen.git] / scripts / network-bridge
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 #============================================================================
50
51
52 dir=$(dirname "$0")
53 . "$dir/xen-script-common.sh"
54 . "$dir/xen-network-common.sh"
55
56 findCommand "$@"
57 evalVariables "$@"
58
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)
62
63     [[ "$rootfs" =~ "^nfs" ]] || [[ "$rootopts" =~ "_netdev" ]] && has_nfsroot=1 || has_nfsroot=0
64     if [ $has_nfsroot -eq 1 ]; then
65         local bparms=$(cat /proc/cmdline)
66         for p in $bparms; do
67             local ipaddr=$(echo $p | awk /nfsroot=/'{ print substr($1,9,index($1,":")-9) }')
68             if [ "$ipaddr" != "" ]; then
69                 local nfsdev=$(ip route get $ipaddr | awk /$ipaddr/'{ print $3 }')
70                 [[ "$nfsdev" == "$netdev" ]] && return 0 || return 1
71             fi
72         done
73     fi
74     return 1
75 }
76
77 find_alt_device () {
78     local interf=$1
79     local prefix=${interf%[[:digit:]]}
80     local ifs=$(ip link show | grep " $prefix" |\
81                 gawk '{ printf ("%s",substr($2,1,length($2)-1)) }' |\
82                 sed s/$interf//)
83     echo "$ifs"
84 }
85
86 netdev=${netdev:-$(ip route list 0.0.0.0/0  | \
87                    sed 's/.*dev \([a-z]\+[0-9]\+\).*$/\1/')}
88 if is_network_root ; then
89     altdevs=$(find_alt_device $netdev)
90     for netdev in $altdevs; do break; done
91     if [ -z "$netdev" ]; then
92         [ -x /usr/bin/logger ] && /usr/bin/logger "network-bridge: bridging not supported on network root; not starting"
93         exit
94     fi
95 fi
96 netdev=${netdev:-eth0}
97 bridge=${bridge:-${netdev}}
98 antispoof=${antispoof:-no}
99
100 pdev="p${netdev}"
101 tdev=tmpbridge
102
103 get_ip_info() {
104     addr_pfx=`ip addr show dev $1 | egrep '^ *inet' | sed -e 's/ *inet //' -e 's/ .*//'`
105     gateway=`ip route show dev $1 | fgrep default | sed 's/default via //'`
106 }
107     
108 do_ifup() {
109     if ! ifup $1 ; then
110         if [ -n "$addr_pfx" ] ; then
111             # use the info from get_ip_info()
112             ip addr flush $1
113             ip addr add ${addr_pfx} dev $1
114             ip link set dev $1 up
115             [ -n "$gateway" ] && ip route add default via ${gateway}
116         fi
117     fi
118 }
119
120 # Usage: transfer_addrs src dst
121 # Copy all IP addresses (including aliases) from device $src to device $dst.
122 transfer_addrs () {
123     local src=$1
124     local dst=$2
125     # Don't bother if $dst already has IP addresses.
126     if ip addr show dev ${dst} | egrep -q '^ *inet ' ; then
127         return
128     fi
129     # Address lines start with 'inet' and have the device in them.
130     # Replace 'inet' with 'ip addr add' and change the device name $src
131     # to 'dev $src'.
132     ip addr show dev ${src} | egrep '^ *inet ' | sed -e "
133 s/inet/ip addr add/
134 s@\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+/[0-9]\+\)@\1@
135 s/${src}/dev ${dst} label ${dst}/
136 s/secondary//
137 " | sh -e
138     # Remove automatic routes on destination device
139     ip route list | sed -ne "
140 /dev ${dst}\( \|$\)/ {
141   s/^/ip route del /
142   p
143 }" | sh -e
144 }
145
146 # Usage: transfer_routes src dst
147 # Get all IP routes to device $src, delete them, and
148 # add the same routes to device $dst.
149 # The original routes have to be deleted, otherwise adding them
150 # for $dst fails (duplicate routes).
151 transfer_routes () {
152     local src=$1
153     local dst=$2
154     # List all routes and grep the ones with $src in.
155     # Stick 'ip route del' on the front to delete.
156     # Change $src to $dst and use 'ip route add' to add.
157     ip route list | sed -ne "
158 /dev ${src}\( \|$\)/ {
159   h
160   s/^/ip route del /
161   P
162   g
163   s/${src}/${dst}/
164   s/^/ip route add /
165   P
166   d
167 }" | sh -e
168 }
169
170
171 ##
172 # link_exists interface
173 #
174 # Returns 0 if the interface named exists (whether up or down), 1 otherwise.
175 #
176 link_exists()
177 {
178     if ip link show "$1" >/dev/null 2>/dev/null
179     then
180         return 0
181     else
182         return 1
183     fi
184 }
185
186 # Set the default forwarding policy for $dev to drop.
187 # Allow forwarding to the bridge.
188 antispoofing () {
189     iptables -P FORWARD DROP
190     iptables -F FORWARD
191     iptables -A FORWARD -m physdev --physdev-in ${pdev} -j ACCEPT
192 }
193
194 # Usage: show_status dev bridge
195 # Print ifconfig and routes.
196 show_status () {
197     local dev=$1
198     local bridge=$2
199     
200     echo '============================================================'
201     ip addr show ${dev}
202     ip addr show ${bridge}
203     echo ' '
204     brctl show ${bridge}
205     echo ' '
206     ip route list
207     echo ' '
208     route -n
209     echo '============================================================'
210 }
211
212 op_start () {
213     if [ "${bridge}" = "null" ] ; then
214         return
215     fi
216
217     if link_exists "$pdev"; then
218         # The device is already up.
219         return
220     fi
221
222     create_bridge ${tdev}
223
224     preiftransfer ${netdev}
225     transfer_addrs ${netdev} ${tdev}
226     if ! ifdown ${netdev}; then
227         # If ifdown fails, remember the IP details.
228         get_ip_info ${netdev}
229         ip link set ${netdev} down
230         ip addr flush ${netdev}
231     fi
232     ip link set ${netdev} name ${pdev}
233     ip link set ${tdev} name ${bridge}
234
235     setup_bridge_port ${pdev}
236
237     add_to_bridge2 ${bridge} ${pdev}
238     do_ifup ${bridge}
239
240     if [ ${antispoof} = 'yes' ] ; then
241         antispoofing
242     fi
243 }
244
245 op_stop () {
246     if [ "${bridge}" = "null" ]; then
247         return
248     fi
249     if ! link_exists "$bridge"; then
250         return
251     fi
252
253     transfer_addrs ${bridge} ${pdev}
254     if ! ifdown ${bridge}; then
255         get_ip_info ${bridge}
256     fi
257     ip link set ${pdev} down
258     ip addr flush ${bridge}
259
260     brctl delif ${bridge} ${pdev}
261     ip link set ${bridge} down
262
263     ip link set ${bridge} name ${tdev}
264     ip link set ${pdev} name ${netdev}
265     do_ifup ${netdev}
266
267     brctl delbr ${tdev}
268 }
269
270 # adds $dev to $bridge but waits for $dev to be in running state first
271 add_to_bridge2() {
272     local bridge=$1
273     local dev=$2
274     local maxtries=10
275
276     echo -n "Waiting for ${dev} to negotiate link."
277     ip link set ${dev} up
278     for i in `seq ${maxtries}` ; do
279         if ifconfig ${dev} | grep -q RUNNING ; then
280             break
281         else
282             echo -n '.'
283             sleep 1
284         fi
285     done
286
287     if [ ${i} -eq ${maxtries} ] ; then echo -n '(link isnt in running state)' ; fi
288     echo
289
290     add_to_bridge ${bridge} ${dev}
291 }
292
293 case "$command" in
294     start)
295         op_start
296         ;;
297     
298     stop)
299         op_stop
300         ;;
301
302     status)
303         show_status ${netdev} ${bridge}
304         ;;
305
306     *)
307         echo "Unknown command: $command" >&2
308         echo 'Valid commands are: start, stop, status' >&2
309         exit 1
310 esac