Révision 10

trunk/dom0/etc/xen/scripts/network-bridge-internal (revision 10)
1
#!/bin/bash
2
#============================================================================
3
# Based on the default Xen network start/stop script.
4
# Xend calls a network script when it starts.
5
# The script name to use is defined in ${XEN_CONFIG_DIR}/xend-config.sxp
6
# in the network-script field.
7
#
8
# Below, this is what the default script does:
9
# This script creates a bridge (default ${netdev}), adds a device
10
# (defaults to the device on the default gateway route) to it, copies
11
# the IP addresses from the device to the bridge and adjusts the routes
12
# accordingly.
13
#
14
# If all goes well, this should ensure that networking stays up.
15
# However, some configurations are upset by this, especially
16
# NFS roots. If the bridged setup does not meet your needs,
17
# configure a different script, for example using routing instead.
18
#
19
# What we add to create an internal bridge called "internal" is:
20
# just add a line in the op_start (to create) and in the op_stop
21
# to (delete) the internal bridge.
22
#
23
# Usage:
24
#
25
# network-bridge (start|stop|status) {VAR=VAL}*
26
#
27
# Vars:
28
#
29
# bridge     The bridge to use (default ${netdev}).
30
# netdev     The interface to add to the bridge (default gateway device).
31
# antispoof  Whether to use iptables to prevent spoofing (default no).
32
#
33
# Internal Vars:
34
# pdev="p${netdev}"
35
# tdev=tmpbridge
36
#
37
# start:
38
# Creates the bridge as tdev
39
# Copies the IP and MAC addresses from pdev to bridge
40
# Renames netdev to be pdev 
41
# Renames tdev to bridge
42
# Enslaves pdev to bridge
43
#
44
# stop:
45
# Removes pdev from the bridge
46
# Transfers addresses, routes from bridge to pdev
47
# Renames bridge to tdev
48
# Renames pdev to netdev 
49
# Deletes tdev
50
#
51
# status:
52
# Print addresses, interfaces, routes
53
#
54
#============================================================================
55

  
56

  
57
dir=$(dirname "$0")
58
. "$dir/logging.sh"
59
. "$dir/xen-script-common.sh"
60
. "$dir/xen-network-common.sh"
61
. "$dir/locking.sh"
62

  
63
findCommand "$@"
64
evalVariables "$@"
65

  
66
is_network_root () {
67
    local rootfs=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $3; }}' /etc/mtab)
68
    local rootopts=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $4; }}' /etc/mtab)
69

  
70
    [[ "$rootfs" =~ "^nfs" ]] || [[ "$rootopts" =~ "_netdev" ]] && has_nfsroot=1 || has_nfsroot=0
71
    if [ $has_nfsroot -eq 1 ]; then
72
        local bparms=$(cat /proc/cmdline)
73
        for p in $bparms; do
74
            local ipaddr=$(echo $p | awk /nfsroot=/'{ print substr($1,9,index($1,":")-9) }')
75
            if [ "$ipaddr" != "" ]; then
76
                local nfsdev=$(ip route get $ipaddr | awk /$ipaddr/'{ print $3 }')
77
                [[ "$nfsdev" == "$netdev" ]] && return 0 || return 1
78
            fi
79
        done
80
    fi
81
    return 1
82
}
83

  
84
find_alt_device () {
85
    local interf=$1
86
    local prefix=${interf%[[:digit:]]}
87
    local ifs=$(ip link show | grep " $prefix" |\
88
                gawk '{ printf ("%s",substr($2,1,length($2)-1)) }' |\
89
                sed s/$interf//)
90
    echo "$ifs"
91
}
92

  
93
netdev=${netdev:-$(ip route list 0.0.0.0/0  | \
94
                   sed 's/.*dev \([a-z]\+[0-9]\+\).*$/\1/')}
95
if is_network_root ; then
96
    altdevs=$(find_alt_device $netdev)
97
    for netdev in $altdevs; do break; done
98
    if [ -z "$netdev" ]; then
99
        [ -x /usr/bin/logger ] && /usr/bin/logger "network-bridge: bridging not supported on network root; not starting"
100
        exit
101
    fi
102
fi
103
netdev=${netdev:-eth0}
104
bridge=${bridge:-${netdev}}
105
antispoof=${antispoof:-no}
106

  
107
pdev="p${netdev}"
108
tdev=tmpbridge
109

  
110
get_ip_info() {
111
    addr_pfx=`ip addr show dev $1 | egrep '^ *inet' | sed -e 's/ *inet //' -e 's/ .*//'`
112
    gateway=`ip route show dev $1 | fgrep default | sed 's/default via //'`
113
}
114
    
115
do_ifup() {
116
    if [ $1 != "${netdev}" ] || ! ifup $1 ; then
117
        if [ -n "$addr_pfx" ] ; then
118
            # use the info from get_ip_info()
119
            ip addr flush $1
120
            ip addr add ${addr_pfx} dev $1
121
        fi
122
        ip link set dev $1 up
123
        [ -n "$gateway" ] && ip route add default via ${gateway}
124
    fi
125
}
126

  
127
# Usage: transfer_addrs src dst
128
# Copy all IP addresses (including aliases) from device $src to device $dst.
129
transfer_addrs () {
130
    local src=$1
131
    local dst=$2
132
    # Don't bother if $dst already has IP addresses.
133
    if ip addr show dev ${dst} | egrep -q '^ *inet ' ; then
134
        return
135
    fi
136
    # Address lines start with 'inet' and have the device in them.
137
    # Replace 'inet' with 'ip addr add' and change the device name $src
138
    # to 'dev $src'.
139
    ip addr show dev ${src} | egrep '^ *inet ' | sed -e "
140
s/inet/ip addr add/
141
s@\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+/[0-9]\+\)@\1@
142
s/${src}/dev ${dst} label ${dst}/
143
s/secondary//
144
" | sh -e
145
    # Remove automatic routes on destination device
146
    ip route list | sed -ne "
147
/dev ${dst}\( \|$\)/ {
148
  s/^/ip route del /
149
  p
150
}" | sh -e
151
}
152

  
153
# Usage: transfer_routes src dst
154
# Get all IP routes to device $src, delete them, and
155
# add the same routes to device $dst.
156
# The original routes have to be deleted, otherwise adding them
157
# for $dst fails (duplicate routes).
158
transfer_routes () {
159
    local src=$1
160
    local dst=$2
161
    # List all routes and grep the ones with $src in.
162
    # Stick 'ip route del' on the front to delete.
163
    # Change $src to $dst and use 'ip route add' to add.
164
    ip route list | sed -ne "
165
/dev ${src}\( \|$\)/ {
166
  h
167
  s/^/ip route del /
168
  P
169
  g
170
  s/${src}/${dst}/
171
  s/^/ip route add /
172
  P
173
  d
174
}" | sh -e
175
}
176

  
177

  
178
##
179
# link_exists interface
180
#
181
# Returns 0 if the interface named exists (whether up or down), 1 otherwise.
182
#
183
link_exists()
184
{
185
    if ip link show "$1" >/dev/null 2>/dev/null
186
    then
187
        return 0
188
    else
189
        return 1
190
    fi
191
}
192

  
193
# Set the default forwarding policy for $dev to drop.
194
# Allow forwarding to the bridge.
195
antispoofing () {
196
    iptables -P FORWARD DROP
197
    iptables -F FORWARD
198
    iptables -A FORWARD -m physdev --physdev-in ${pdev} -j ACCEPT
199
}
200

  
201
# Usage: show_status dev bridge
202
# Print ifconfig and routes.
203
show_status () {
204
    local dev=$1
205
    local bridge=$2
206
    
207
    echo '============================================================'
208
    ip addr show ${dev}
209
    ip addr show ${bridge}
210
    echo ' '
211
    brctl show ${bridge}
212
    echo ' '
213
    ip route list
214
    echo ' '
215
    route -n
216
    echo '============================================================'
217
}
218

  
219
op_start () {
220
    if [ "${bridge}" = "null" ] ; then
221
	return
222
    fi
223

  
224
    if link_exists "$pdev"; then
225
        # The device is already up.
226
        return
227
    fi
228

  
229
    claim_lock "network-bridge"
230

  
231
    create_bridge ${tdev}
232

  
233
    preiftransfer ${netdev}
234
    transfer_addrs ${netdev} ${tdev}
235
    # Remember slaves for bonding interface.
236
    if [ -e /sys/class/net/${netdev}/bonding/slaves ]; then
237
	slaves=`cat /sys/class/net/${netdev}/bonding/slaves`
238
    fi
239
    # Remember the IP details for do_ifup.
240
    get_ip_info ${netdev}
241
    if ! ifdown ${netdev}; then
242
	ip link set ${netdev} down
243
	ip addr flush ${netdev}
244
    fi
245
    ip link set ${netdev} name ${pdev}
246
    ip link set ${tdev} name ${bridge}
247

  
248
    setup_bridge_port ${pdev}
249

  
250
    # Restore slaves
251
    if [ -n "${slaves}" ]; then
252
	ip link set ${pdev} up
253
	ifenslave ${pdev} ${slaves}
254
    fi
255
    add_to_bridge2 ${bridge} ${pdev}
256
    do_ifup ${bridge}
257

  
258
    if [ ${antispoof} = 'yes' ] ; then
259
	antispoofing
260
    fi
261

  
262
    # ST-2011-02-28: for the internal bridge
263
    create_bridge internal
264
    brctl stp internal off
265
    brctl setfd internal 0
266
    ip link set internal up
267
    # End internal bridge
268

  
269
    release_lock "network-bridge"
270
}
271

  
272
op_stop () {
273
    if [ "${bridge}" = "null" ]; then
274
	return
275
    fi
276
    if ! link_exists "$bridge"; then
277
	return
278
    fi
279

  
280
    claim_lock "network-bridge"
281

  
282
    transfer_addrs ${bridge} ${pdev}
283
    if ! ifdown ${bridge}; then
284
	get_ip_info ${bridge}
285
    fi
286
    ip link set ${pdev} down
287
    ip addr flush ${bridge}
288

  
289
    brctl delif ${bridge} ${pdev}
290
    ip link set ${bridge} down
291

  
292
    ip link set ${bridge} name ${tdev}
293
    ip link set ${pdev} name ${netdev}
294
    do_ifup ${netdev}
295

  
296
    brctl delbr ${tdev}
297
    
298
    # ST-2011-02-28: for the internal bridge
299
    brctl delbr internal
300
    # End internal bridge
301
    
302
    release_lock "network-bridge"
303
}
304

  
305
# adds $dev to $bridge but waits for $dev to be in running state first
306
add_to_bridge2() {
307
    local bridge=$1
308
    local dev=$2
309
    local maxtries=10
310

  
311
    echo -n "Waiting for ${dev} to negotiate link."
312
    ip link set ${dev} up
313
    for i in `seq ${maxtries}` ; do
314
	if ifconfig ${dev} | grep -q RUNNING ; then
315
	    break
316
	else
317
	    echo -n '.'
318
	    sleep 1
319
	fi
320
    done
321

  
322
    if [ ${i} -eq ${maxtries} ] ; then echo -n '(link isnt in running state)' ; fi
323
    echo
324

  
325
    add_to_bridge ${bridge} ${dev}
326
}
327

  
328
case "$command" in
329
    start)
330
	op_start
331
	;;
332
    
333
    stop)
334
	op_stop
335
	;;
336

  
337
    status)
338
	show_status ${netdev} ${bridge}
339
	;;
340

  
341
    *)
342
	echo "Unknown command: $command" >&2
343
	echo 'Valid commands are: start, stop, status' >&2
344
	exit 1
345
esac
0 346

  

Formats disponibles : Unified diff