blob: a380f6ac83112e0def86a751f2407b54d90fbadb (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
|
# Copyright (c) 2007-2008 Roy Marples <roy@marples.name>
# Released under the 2-clause BSD license.
# shellcheck shell=sh disable=SC1008
bridge_depend()
{
before interface macnet
program brctl ip
}
_config_vars="$_config_vars bridge bridge_add brctl"
_is_bridge()
{
_netns [ -d /sys/class/net/"${1:-${IFACE}}"/bridge ]
return $?
}
_is_bridge_port()
{
_netns [ -d /sys/class/net/"${1:-${IFACE}}"/brport ]
return $?
}
_bridge_ports()
{
for x in $(_netns glob /sys/class/net/"${1:-${IFACE}}"/brif/\*); do
n=${x##*/}
echo $n
done
}
bridge_pre_start()
{
local brif= oiface="${IFACE}" e= x=
# ports is for static add
local ports="$(_get_array "bridge_${IFVAR}")"
# old config options
local brctl_opts="$(_get_array "brctl_${IFVAR}")"
# brif is used for dynamic add
eval brif=\$bridge_add_${IFVAR}
local do_iproute2=false do_brctl=false
if [ -n "${brctl_opts}" ] && type brctl >/dev/null 2>&1; then
do_brctl=true
elif type ip >/dev/null 2>&1; then
do_iproute2=true
elif type brctl >/dev/null 2>&1; then
do_brctl=true
fi
# we need a way to if the bridge exists in a variable name, not just the
# contents of a variable. Eg if somebody has only bridge_add_eth0='br0',
# with no other lines mentioning br0.
eval bridge_unset=\${bridge_${IFVAR}-y\}
eval brctl_unset=\${brctl_${IFVAR}-y\}
eval bridge_force_unset=\${bridge_force_${IFVAR}-y\}
if [ -z "${brif}" -a "${brctl_unset}${bridge_force_unset}" = 'yy' ]; then
if [ -z "${ports}" -a "${bridge_unset}" = "y" ]; then
#eerror "Misconfigured static bridge detected (see net.example)"
return 0
fi
fi
# If the bridge was already up, we should clear it
[ "${bridge_unset}" != "y" ] && bridge_post_stop
(
# Normalize order of variables
if [ -z "${ports}" -a -n "${brif}" ]; then
# Dynamic mode detected
ports="${IFACE}"
IFACE="${brif}"
IFVAR=$(shell_var "${IFACE}")
else
# Static mode detected
ports="${ports}"
metric=1000
fi
if ! _is_bridge ; then
ebegin "Creating bridge ${IFACE}"
if ${do_iproute2}; then
_netns ip link add "${IFACE}" type bridge
rc=$?
elif ${do_brctl}; then
brctl addbr "${IFACE}"
rc=$?
else
eerror "Neither iproute2 nor brctl has been found, please install"
eerror "either \"iproute2\" or \"brctl\"."
rc=1
fi
if [ ${rc} != 0 ]; then
eend 1
return 1
fi
fi
# TODO: does this reset the bridge every time we add a interface to the
# bridge? We should probably NOT do that.
# Old configuration set mechanism
# Only a very limited subset of the options are available in the old
# configuration method. The sysfs interface is in the next block instead.
if ${do_brctl}; then
if [ -n "${brctl_opts}" ]; then
ewarn "brctl options are deprecated please migrate to sysfs options"
ewarn "map of important options is available at https://wiki.gentoo.org/wiki/Netifrc/Brctl_Migration"
local IFS="$__IFS"
for x in ${brctl_opts}; do
unset IFS
set -- ${x}
x=$1
shift
set -- "${x}" "${IFACE}" "$@"
brctl "$@"
done
unset IFS
fi
fi
# New configuration set mechanism, matches bonding
for x in $(_netns glob /sys/class/net/"${IFACE}"/bridge/\*); do
[ -f "${x}" ] || continue
n=${x##*/}
# keep no prefix for backward compatibility
for prefix in "" bridge_; do
eval s=\$${prefix}${n}_${IFVAR}
if [ -n "${s}" ]; then
[ -z "${prefix}" ] && ewarn "sysfs key '${n}_${IFVAR}' should be prefixed, please add bridge_ prefix."
einfo "Setting ${n}: ${s}"
_netns echo "${s}" \>"${x}" || \
eerror "Failed to configure $n (${n}_${IFVAR})"
fi
done
done
if [ -n "${ports}" ]; then
einfo "Adding ports to ${IFACE}"
eindent
local BR_IFACE="${IFACE}"
for x in ${ports}; do
ebegin "${x}"
local IFACE="${x}"
local IFVAR=$(shell_var "${IFACE}")
if ! _exists "${IFACE}" ; then
eerror "Cannot add non-existent interface ${IFACE} to ${BR_IFACE}"
return 1
fi
# The interface is known to exist now
_up
if ${do_iproute2}; then
_netns ip link set "${x}" master "${BR_IFACE}"
elif ${do_brctl}; then
brctl addif "${BR_IFACE}" "${x}"
fi
if [ $? != 0 ]; then
eend 1
return 1
fi
# Per-interface bridge settings
for x in $(_netns glob /sys/class/net/"${IFACE}"/brport/\*); do
[ -f "${x}" ] || continue
n=${x##*/}
for prefix in "" brport_; do
eval s=\$${prefix}${n}_${IFVAR}
if [ -n "${s}" ]; then
[ -z "${prefix}" ] && ewarn "sysfs key '${n}_${IFVAR}' should be prefixed, please add brport_ prefix."
einfo "Setting ${n}@${IFACE}: ${s}"
_netns echo "${s}" \>"${x}" || \
eerror "Failed to configure $n (${n}_${IFVAR})"
fi
done
done
eend 0
done
eoutdent
fi
) || return 1
# Bring up the bridge
_set_flag promisc
_up
}
bridge_post_stop()
{
local port= ports= delete=false extra=
if _is_bridge "${IFACE}"; then
ebegin "Destroying bridge ${IFACE}"
_down
for x in $(_netns glob /sys/class/net/"${IFACE}"/brif/\*); do
[ -s $x ] || continue
n=${x##*/}
ports="${ports} ${n}"
done
delete=true
iface=${IFACE}
eindent
else
# We are taking down an interface that is part of a bridge maybe
ports="${IFACE}"
local brport_dir="/sys/class/net/${IFACE}/brport"
_netns [ -d ${brport_dir} ] || return 0
iface=$(_netns readlink ${brport_dir}/bridge)
iface=${iface##*/}
[ -z "${iface}" ] && return 0
extra=" from ${iface}"
fi
for port in ${ports}; do
ebegin "Removing port ${port}${extra}"
local IFACE="${port}"
_set_flag -promisc
if type ip > /dev/null 2>&1; then
_netns ip link set "${port}" nomaster
else
brctl delif "${iface}" "${port}"
fi
eend $?
done
if ${delete}; then
eoutdent
if type ip > /dev/null 2>&1; then
_netns ip link del "${iface}"
else
brctl delbr "${iface}"
fi
eend $?
fi
return 0
}
|