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
|