]>
Commit | Line | Data |
---|---|---|
e84e4e76 MT |
1 | #!/bin/bash |
2 | ############################################################################### | |
3 | # # | |
4 | # IPFire.org - A linux based firewall # | |
5 | # Copyright (C) 2010 Michael Tremer & Christian Schmidt # | |
6 | # # | |
7 | # This program is free software: you can redistribute it and/or modify # | |
8 | # it under the terms of the GNU General Public License as published by # | |
9 | # the Free Software Foundation, either version 3 of the License, or # | |
10 | # (at your option) any later version. # | |
11 | # # | |
12 | # This program is distributed in the hope that it will be useful, # | |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
15 | # GNU General Public License for more details. # | |
16 | # # | |
17 | # You should have received a copy of the GNU General Public License # | |
18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
19 | # # | |
20 | ############################################################################### | |
21 | ||
e266c18e MT |
22 | # The default mode. |
23 | # We default to RSTP, because it has the better user experience and | |
24 | # faster convergence times. Despite of that, it completely downgradeable | |
25 | # to plain STP. | |
26 | STP_DEFAULT_MODE="rstp" | |
6b3f9c85 | 27 | |
e266c18e MT |
28 | # Allowed modes of the spanning tree protocol. |
29 | STP_ALLOWED_MODES="rstp stp" | |
6b3f9c85 | 30 | |
feb76eaf | 31 | function stp_enable() { |
e84e4e76 | 32 | local bridge=${1} |
e266c18e | 33 | local mode=${2} |
e84e4e76 | 34 | |
feb76eaf MT |
35 | assert isset bridge |
36 | assert zone_exists ${bridge} | |
e84e4e76 | 37 | |
e266c18e | 38 | # Tell the kernel to enable STP. |
feb76eaf | 39 | brctl stp ${bridge} on |
e84e4e76 | 40 | |
e266c18e MT |
41 | # Set the correct protocol version. |
42 | if [ -z "${mode}" ]; then | |
43 | mode="${STP_DEFAULT_MODE}" | |
44 | fi | |
45 | stp_bridge_set_protocol ${bridge} ${mode} | |
e84e4e76 MT |
46 | } |
47 | ||
feb76eaf | 48 | function stp_disable() { |
e84e4e76 | 49 | local bridge=${1} |
e84e4e76 | 50 | |
feb76eaf MT |
51 | assert isset bridge |
52 | assert zone_exists ${bridge} | |
53 | ||
54 | brctl stp ${bridge} off | |
e84e4e76 MT |
55 | } |
56 | ||
3cb2fc42 MT |
57 | function stp_is_enabled() { |
58 | local bridge=${1} | |
59 | assert isset bridge | |
60 | ||
61 | local state=$(__device_get_file ${bridge} bridge/stp_state) | |
62 | ||
63 | case "${state}" in | |
64 | 0) | |
65 | return ${EXIT_FALSE} | |
66 | ;; | |
67 | *) | |
68 | return ${EXIT_TRUE} | |
69 | ;; | |
70 | esac | |
71 | } | |
72 | ||
8d4f9311 MT |
73 | function stp_get_name() { |
74 | local proto=${1} | |
75 | ||
76 | case "${proto}" in | |
77 | stp) | |
78 | echo "Spanning Tree Protocol" | |
79 | ;; | |
80 | rstp) | |
81 | echo "Rapid Spanning Tree Protocol" | |
82 | ;; | |
83 | mstp) | |
84 | echo "Multiple Spanning Tree Protocol" | |
85 | ;; | |
86 | esac | |
87 | ||
88 | return ${EXIT_OK} | |
89 | } | |
90 | ||
e266c18e MT |
91 | function stp_bridge_set_protocol() { |
92 | local bridge=${1} | |
93 | local mode=${2} | |
94 | ||
95 | assert isset bridge | |
96 | assert isset mode | |
97 | ||
98 | if ! listmatch ${mode} ${STP_ALLOWED_MODES}; then | |
99 | log WARNING "Unknown protocol version: ${mode}." | |
100 | log WARNING "Using default mode." | |
101 | ||
102 | mode="${STP_DEFAULT_MODE}" | |
103 | fi | |
104 | ||
105 | mstpctl setforcevers ${bridge} ${mode} | |
106 | assert [ $? -eq 0 ] | |
107 | } | |
108 | ||
feb76eaf | 109 | function stp_bridge_get_protocol() { |
e84e4e76 | 110 | local bridge=${1} |
e84e4e76 | 111 | |
feb76eaf MT |
112 | assert isset bridge |
113 | ||
8d4f9311 MT |
114 | # Let's check what the kernel is telling us about it's STP state. |
115 | local state=$(__device_get_file ${bridge} "bridge/stp_state") | |
feb76eaf | 116 | |
8d4f9311 | 117 | case "${state}" in |
feb76eaf | 118 | 0) |
8d4f9311 MT |
119 | # STP is disabled. |
120 | return ${EXIT_OK} | |
121 | ;; | |
122 | 1) | |
123 | # Kernel mode STP is running. | |
feb76eaf | 124 | echo "stp" |
8d4f9311 | 125 | return ${EXIT_OK} |
feb76eaf MT |
126 | ;; |
127 | 2) | |
8d4f9311 | 128 | # User-space STP is running. |
36e3fd2f | 129 | ;; |
8d4f9311 MT |
130 | *) |
131 | log ERROR "Kernel is running in an unknown STP state." | |
132 | return ${EXIT_ERROR} | |
36e3fd2f | 133 | ;; |
feb76eaf | 134 | esac |
e84e4e76 | 135 | |
8d4f9311 | 136 | # We get here, when STP is running in user-space mode. |
e84e4e76 | 137 | |
8d4f9311 | 138 | # Get the current protocol version. |
6cd354eb | 139 | mstpctl showbridge ${bridge} force-protocol-version |
feb76eaf | 140 | |
8d4f9311 | 141 | return ${EXIT_OK} |
e84e4e76 MT |
142 | } |
143 | ||
8d4f9311 | 144 | function stp_bridge_get_id() { |
e84e4e76 | 145 | local bridge=${1} |
feb76eaf | 146 | assert isset bridge |
e84e4e76 | 147 | |
8d4f9311 | 148 | __device_get_file ${bridge} "bridge/bridge_id" |
feb76eaf | 149 | |
8d4f9311 | 150 | return $? |
e84e4e76 MT |
151 | } |
152 | ||
8d4f9311 | 153 | function stp_bridge_get_forward_delay() { |
e84e4e76 MT |
154 | local bridge=${1} |
155 | ||
feb76eaf MT |
156 | assert isset bridge |
157 | ||
6cd354eb | 158 | mstpctl showbridge ${bridge} forward-delay |
8d4f9311 | 159 | } |
feb76eaf | 160 | |
8d4f9311 | 161 | function stp_bridge_set_forward_delay() { |
e2aa12b3 MT |
162 | local bridge=${1} |
163 | assert isset bridge | |
164 | ||
165 | local fdelay=${2} | |
166 | assert isinteger fdelay | |
167 | ||
168 | # Check if the setting we want is already set. | |
169 | local current_fdelay=$(stp_bridge_get_forward_delay ${bridge}) | |
170 | [ ${fdelay} -eq ${current_fdelay} ] && return ${EXIT_OK} | |
171 | ||
172 | # The smallest value that may be set is 2. | |
173 | if [ ${fdelay} -lt 2 ]; then | |
174 | fdelay=2 | |
175 | fi | |
176 | ||
177 | # Set the new value. | |
178 | log INFO "Changing forward delay for '${bridge}': ${current_fdelay} --> ${fdelay}." | |
179 | brctl setfd ${bridge} ${fdelay} | |
180 | ||
181 | return ${EXIT_OK} | |
182 | } | |
183 | ||
184 | function stp_bridge_get_hello_time() { | |
185 | local bridge=${1} | |
186 | assert isset bridge | |
187 | ||
188 | local ht=$(__device_get_file ${bridge} "bridge/hello_time") | |
189 | ||
190 | # ht is now in seconds * 100. | |
191 | local split=$((${#ht} - 2)) | |
192 | ht="${ht:0:${split}}.${ht:${split}:2}" | |
193 | ||
194 | # Round the output. | |
195 | printf "%.0f\n" "${ht}" | |
196 | } | |
197 | ||
198 | function stp_bridge_set_hello_time() { | |
199 | local bridge=${1} | |
200 | assert isset bridge | |
201 | ||
202 | local hello=${2} | |
203 | assert isinteger hello | |
204 | ||
205 | # Check if the setting we want is already set. | |
206 | local current_hello=$(stp_bridge_get_hello_time ${bridge}) | |
207 | [ ${hello} -eq ${current_hello} ] && return ${EXIT_OK} | |
208 | ||
209 | # Set the new value. | |
210 | log INFO "Changing hello time for '${bridge}': ${current_hello} --> ${hello}." | |
211 | brctl sethello ${bridge} ${hello} | |
212 | ||
213 | return ${EXIT_OK} | |
214 | } | |
215 | ||
216 | function stp_bridge_get_max_age() { | |
217 | local bridge=${1} | |
218 | assert isset bridge | |
219 | ||
220 | local maxage=$(__device_get_file ${bridge} "bridge/max_age") | |
221 | ||
222 | # maxage is now in seconds * 100. | |
223 | local split=$((${#maxage} - 2)) | |
224 | maxage="${maxage:0:${split}}.${maxage:${split}:2}" | |
225 | ||
226 | # Round the output. | |
227 | printf "%.0f\n" "${maxage}" | |
228 | } | |
229 | ||
230 | function stp_bridge_set_max_age() { | |
231 | local bridge=${1} | |
232 | assert isset bridge | |
233 | ||
234 | local maxage=${2} | |
235 | assert isinteger maxage | |
236 | ||
237 | # Check if the setting we want is already set. | |
238 | local current_maxage=$(stp_bridge_get_max_age ${bridge}) | |
239 | [ ${maxage} -eq ${current_maxage} ] && return ${EXIT_OK} | |
240 | ||
241 | # Set the new value. | |
242 | log INFO "Changing max age for '${bridge}': ${current_maxage} --> ${maxage}." | |
243 | brctl setmaxage ${bridge} ${maxage} | |
244 | ||
245 | return ${EXIT_OK} | |
246 | } | |
247 | ||
248 | function stp_bridge_get_priority() { | |
249 | local bridge=${1} | |
250 | assert isset bridge | |
251 | ||
252 | __device_get_file ${bridge} "bridge/priority" | |
253 | } | |
254 | ||
255 | function stp_bridge_set_priority() { | |
256 | local bridge=${1} | |
257 | assert isset bridge | |
258 | ||
259 | local priority=${2} | |
260 | assert isinteger priority | |
261 | ||
262 | # Check if the setting we want is already set. | |
263 | local current_priority=$(stp_bridge_get_priority ${bridge}) | |
264 | [ ${priority} -eq ${current_priority} ] && return ${EXIT_OK} | |
265 | ||
266 | # Set the new value. | |
267 | log INFO "Changing priority for '${bridge}': ${current_priority} --> ${priority}." | |
268 | brctl setbridgeprio ${bridge} ${priority} | |
269 | ||
270 | return ${EXIT_OK} | |
e84e4e76 MT |
271 | } |
272 | ||
feb76eaf | 273 | function stp_bridge_get_designated_root() { |
e84e4e76 | 274 | local bridge=${1} |
feb76eaf MT |
275 | local output |
276 | ||
277 | assert isset bridge | |
e84e4e76 | 278 | |
6cd354eb | 279 | local output=$(mstpctl showbridge ${bridge} designated-root) |
feb76eaf MT |
280 | |
281 | if ! isset output; then | |
282 | return ${EXIT_ERROR} | |
283 | fi | |
284 | ||
8d4f9311 | 285 | echo "${output,,}" |
feb76eaf | 286 | return ${EXIT_OK} |
e84e4e76 MT |
287 | } |
288 | ||
feb76eaf | 289 | function stp_bridge_get_root_path_cost() { |
e84e4e76 MT |
290 | local bridge=${1} |
291 | ||
feb76eaf MT |
292 | assert isset bridge |
293 | ||
6cd354eb | 294 | mstpctl showbridge ${bridge} path-cost |
e84e4e76 MT |
295 | } |
296 | ||
feb76eaf | 297 | function stp_bridge_get_root_port_id() { |
e84e4e76 MT |
298 | local bridge=${1} |
299 | ||
feb76eaf MT |
300 | assert isset bridge |
301 | ||
6cd354eb | 302 | local root_port=$(mstpctl showbridge ${bridge} root-port) |
e84e4e76 | 303 | |
8d4f9311 MT |
304 | # Return error, when there is no root port. |
305 | if [ "${root_port}" = "none" ]; then | |
306 | return ${EXIT_ERROR} | |
307 | fi | |
308 | ||
309 | echo "${root_port}" | |
310 | return ${EXIT_OK} | |
e84e4e76 MT |
311 | } |
312 | ||
feb76eaf | 313 | function stp_bridge_get_root_port() { |
e84e4e76 MT |
314 | local bridge=${1} |
315 | ||
feb76eaf | 316 | assert isset bridge |
e84e4e76 | 317 | |
feb76eaf | 318 | local id=$(stp_bridge_get_root_port_id ${bridge}) |
e84e4e76 | 319 | |
feb76eaf MT |
320 | local member |
321 | local member_id | |
322 | for member in $(bridge_get_members ${bridge}); do | |
323 | member_id=$(stp_port_get_id ${bridge} ${member}) | |
e84e4e76 | 324 | |
feb76eaf MT |
325 | if [ "${id}" = "${member_id}" ]; then |
326 | echo "${member}" | |
327 | return ${EXIT_OK} | |
328 | fi | |
329 | done | |
e84e4e76 | 330 | |
feb76eaf | 331 | return ${EXIT_ERROR} |
e84e4e76 MT |
332 | } |
333 | ||
feb76eaf | 334 | function stp_bridge_is_root() { |
8d4f9311 MT |
335 | stp_bridge_get_root_port_id $@ >/dev/null |
336 | local ret=$? | |
e84e4e76 | 337 | |
8d4f9311 MT |
338 | if [ ${ret} -eq ${EXIT_ERROR} ]; then |
339 | return ${EXIT_OK} | |
340 | fi | |
e84e4e76 | 341 | |
8d4f9311 | 342 | return ${EXIT_ERROR} |
e84e4e76 MT |
343 | } |
344 | ||
feb76eaf MT |
345 | function stp_bridge_get_priority() { |
346 | local bridge=${1} | |
e84e4e76 | 347 | |
feb76eaf | 348 | assert isset bridge |
e84e4e76 | 349 | |
8d4f9311 | 350 | local id=$(stp_bridge_get_id ${bridge}) |
e84e4e76 | 351 | |
8d4f9311 | 352 | dec "${id:0:4}" |
e84e4e76 MT |
353 | } |
354 | ||
feb76eaf MT |
355 | function stp_bridge_get_topology_change_count() { |
356 | local bridge=${1} | |
e84e4e76 | 357 | |
feb76eaf | 358 | assert isset bridge |
e84e4e76 | 359 | |
6cd354eb | 360 | mstpctl showbridge ${bridge} topology-change-count |
e84e4e76 MT |
361 | } |
362 | ||
feb76eaf MT |
363 | function stp_bridge_get_topology_change_timer() { |
364 | local bridge=${1} | |
365 | ||
366 | assert isset bridge | |
367 | ||
6cd354eb | 368 | mstpctl showbridge ${bridge} time-since-topology-change |
e84e4e76 MT |
369 | } |
370 | ||
feb76eaf MT |
371 | function stp_bridge_get_topology_change_detected() { |
372 | local bridge=${1} | |
e84e4e76 | 373 | |
feb76eaf | 374 | assert isset bridge |
e84e4e76 | 375 | |
6cd354eb | 376 | local change=$(mstpctl showbridge ${bridge} topology-change) |
8d4f9311 MT |
377 | |
378 | echo "${change}" | |
379 | case "${change}" in | |
380 | yes) | |
feb76eaf MT |
381 | return ${EXIT_OK} |
382 | ;; | |
8d4f9311 MT |
383 | *) |
384 | return ${EXIT_ERROR} | |
feb76eaf MT |
385 | ;; |
386 | esac | |
6b3f9c85 MT |
387 | } |
388 | ||
feb76eaf | 389 | function stp_port_get_state() { |
6b3f9c85 | 390 | local bridge=${1} |
feb76eaf | 391 | local port=${2} |
6b3f9c85 MT |
392 | |
393 | assert isset bridge | |
feb76eaf | 394 | assert isset port |
6b3f9c85 | 395 | |
6cd354eb | 396 | local state=$(mstpctl showportdetail ${bridge} ${port} state) |
feb76eaf | 397 | |
8d4f9311 | 398 | echo "${state^^}" |
feb76eaf MT |
399 | } |
400 | ||
401 | function stp_port_get_id() { | |
402 | local bridge=${1} | |
403 | local port=${2} | |
404 | ||
405 | assert isset bridge | |
406 | assert isset port | |
407 | ||
8d4f9311 | 408 | local id=$(__device_get_file ${bridge} "brif/${port}/port_no") |
feb76eaf | 409 | |
8d4f9311 MT |
410 | dec ${id} |
411 | ||
412 | return ${EXIT_OK} | |
feb76eaf MT |
413 | } |
414 | ||
415 | function stp_port_get_cost() { | |
416 | local bridge=${1} | |
417 | local port=${2} | |
418 | ||
419 | assert isset bridge | |
420 | assert isset port | |
421 | ||
6cd354eb | 422 | mstpctl showportdetail ${bridge} ${port} external-port-cost |
feb76eaf MT |
423 | |
424 | return ${EXIT_ERROR} | |
6b3f9c85 MT |
425 | } |
426 | ||
feb76eaf | 427 | function stp_port_get_designated_root() { |
6b3f9c85 | 428 | local bridge=${1} |
feb76eaf MT |
429 | local port=${2} |
430 | local output | |
6b3f9c85 MT |
431 | |
432 | assert isset bridge | |
feb76eaf | 433 | assert isset port |
6b3f9c85 | 434 | |
6cd354eb | 435 | output=$(mstpctl showportdetail ${bridge} ${port} designated-root) |
feb76eaf | 436 | |
36e3fd2f | 437 | if [ -n "${output}" ]; then |
8d4f9311 | 438 | echo "${output,,}" |
36e3fd2f MT |
439 | return ${EXIT_OK} |
440 | fi | |
feb76eaf MT |
441 | |
442 | return ${EXIT_ERROR} | |
6b3f9c85 | 443 | } |