]> git.ipfire.org Git - people/stevee/network.git/blob - functions.stp
stp: Transition to mstpd.
[people/stevee/network.git] / functions.stp
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
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"
27
28 # Allowed modes of the spanning tree protocol.
29 STP_ALLOWED_MODES="rstp stp"
30
31 function __rstpctl_bridge_get() {
32 local bridge=${1}
33 local param=${2}
34
35 assert isset bridge
36 assert isset param
37
38 local key
39 local val
40 rstpctl dumpbridge ${bridge} | \
41 while read bridge key val; do
42 if [ "${key}" = "${param}" ]; then
43 echo "${val}"
44 return ${EXIT_OK}
45 fi
46 done
47
48 return ${EXIT_ERROR}
49 }
50
51 function __rstpctl_port_get() {
52 local bridge=${1}
53 local port=${2}
54 local param=${3}
55
56 assert isset bridge
57 assert isset port
58 assert isset param
59
60 local key
61 local val
62 rstpctl dumpports ${bridge} | \
63 while read por key val; do
64 if [ "${port}" = "${por}" -a "${key}" = "${param}" ]; then
65 echo "${val}"
66 return ${EXIT_OK}
67 fi
68 done
69
70 return ${EXIT_ERROR}
71 }
72
73 function stp_enable() {
74 local bridge=${1}
75 local mode=${2}
76
77 assert isset bridge
78 assert zone_exists ${bridge}
79
80 # Tell the kernel to enable STP.
81 brctl stp ${bridge} on
82
83 # Set the correct protocol version.
84 if [ -z "${mode}" ]; then
85 mode="${STP_DEFAULT_MODE}"
86 fi
87 stp_bridge_set_protocol ${bridge} ${mode}
88 }
89
90 function stp_disable() {
91 local bridge=${1}
92
93 assert isset bridge
94 assert zone_exists ${bridge}
95
96 brctl stp ${bridge} off
97 }
98
99 function stp_bridge_set_protocol() {
100 local bridge=${1}
101 local mode=${2}
102
103 assert isset bridge
104 assert isset mode
105
106 if ! listmatch ${mode} ${STP_ALLOWED_MODES}; then
107 log WARNING "Unknown protocol version: ${mode}."
108 log WARNING "Using default mode."
109
110 mode="${STP_DEFAULT_MODE}"
111 fi
112
113 mstpctl setforcevers ${bridge} ${mode}
114 assert [ $? -eq 0 ]
115 }
116
117 function stp_bridge_get_protocol() {
118 local bridge=${1}
119
120 assert isset bridge
121
122 local enabled=$(__device_get_file ${bridge} "bridge/stp_state")
123 if ! enabled ${enabled}; then
124 return ${EXIT_OK}
125 fi
126
127 local mode=$(__rstpctl_bridge_get ${bridge} protocol_version)
128
129 case "${mode}" in
130 0)
131 echo "stp"
132 ;;
133 2)
134 echo "rstp"
135 ;;
136 # When rstpctl has an error, we assume that rstpd is not running and
137 # return the slow mode.
138 "")
139 echo "stp"
140 ;;
141 esac
142 }
143
144 function stp_bridge_get_id() {
145 local bridge=${1}
146
147 assert isset bridge
148
149 case "$(stp_bridge_get_protocol ${bridge})" in
150 rstp)
151 __rstpctl_bridge_get ${bridge} "id"
152 return ${EXIT_OK}
153 ;;
154 stp)
155 __device_get_file ${bridge} "bridge/bridge_id"
156 return ${EXIT_OK}
157 ;;
158 esac
159
160 return ${EXIT_ERROR}
161 }
162
163 function stp_bridge_get_forward_delay() {
164 local bridge=${1}
165
166 assert isset bridge
167
168 case "$(stp_bridge_get_protocol ${bridge})" in
169 rstp)
170 __rstpctl_bridge_get ${bridge} "bridge_forward_delay"
171 return ${EXIT_OK}
172 ;;
173 stp)
174 __device_get_file ${bridge} "bridge/forward_delay"
175 return ${EXIT_OK}
176 ;;
177 esac
178
179 return ${EXIT_ERROR}
180 }
181
182 function stp_bridge_get_hello_time() {
183 local bridge=${1}
184
185 assert isset bridge
186
187 case "$(stp_bridge_get_protocol ${bridge})" in
188 rstp)
189 __rstpctl_bridge_get ${bridge} "bridge_hello_time"
190 return ${EXIT_OK}
191 ;;
192 stp)
193 __device_get_file ${bridge} "bridge/hello_time"
194 return ${EXIT_OK}
195 ;;
196 esac
197
198 return ${EXIT_ERROR}
199 }
200
201 function stp_bridge_get_max_age() {
202 local bridge=${1}
203
204 assert isset bridge
205
206 case "$(stp_bridge_get_protocol ${bridge})" in
207 rstp)
208 __rstpctl_bridge_get ${bridge} "bridge_max_age"
209 return ${EXIT_OK}
210 ;;
211 stp)
212 __device_get_file ${bridge} "bridge/max_age"
213 return ${EXIT_OK}
214 ;;
215 esac
216
217 return ${EXIT_ERROR}
218 }
219
220 function stp_bridge_get_designated_root() {
221 local bridge=${1}
222 local output
223
224 assert isset bridge
225
226 case "$(stp_bridge_get_protocol ${bridge})" in
227 rstp)
228 output=$(__rstpctl_bridge_get ${bridge} "designated_root")
229 ;;
230 stp)
231 output=$(__device_get_file ${bridge} "bridge/root_id")
232 ;;
233 esac
234
235 if ! isset output; then
236 return ${EXIT_ERROR}
237 fi
238
239 mac_format "${output:5:12}"
240
241 return ${EXIT_OK}
242 }
243
244 function stp_bridge_get_root_path_cost() {
245 local bridge=${1}
246
247 assert isset bridge
248
249 case "$(stp_bridge_get_protocol ${bridge})" in
250 rstp)
251 __rstpctl_bridge_get ${bridge} "root_path_cost"
252 return ${EXIT_OK}
253 ;;
254 stp)
255 __device_get_file ${bridge} "bridge/root_path_cost"
256 return ${EXIT_OK}
257 ;;
258 esac
259
260 return ${EXIT_ERROR}
261 }
262
263 function stp_bridge_get_root_port_id() {
264 local bridge=${1}
265
266 assert isset bridge
267
268 case "$(stp_bridge_get_protocol ${bridge})" in
269 rstp)
270 __rstpctl_bridge_get ${bridge} "root_port"
271 return ${EXIT_OK}
272 ;;
273 stp)
274 __device_get_file ${bridge} "bridge/root_port"
275 return ${EXIT_OK}
276 ;;
277 esac
278
279 return ${EXIT_ERROR}
280 }
281
282 function stp_bridge_get_root_port() {
283 local bridge=${1}
284
285 assert isset bridge
286
287 local id=$(stp_bridge_get_root_port_id ${bridge})
288
289 local member
290 local member_id
291 for member in $(bridge_get_members ${bridge}); do
292 member_id=$(stp_port_get_id ${bridge} ${member})
293
294 if [ "${id}" = "${member_id}" ]; then
295 echo "${member}"
296 return ${EXIT_OK}
297 fi
298 done
299
300 return ${EXIT_ERROR}
301 }
302
303 function stp_bridge_is_root() {
304 local bridge=${1}
305
306 assert isset bridge
307
308 [ -n "$(stp_bridge_get_root_port ${bridge})" ]
309 }
310
311 function stp_bridge_get_priority() {
312 local bridge=${1}
313
314 assert isset bridge
315
316 case "$(stp_bridge_get_protocol ${bridge})" in
317 rstp)
318 local output=$(__rstpctl_bridge_get ${bridge} "root_path_cost")
319 dec "${output:0:4}"
320 return ${EXIT_OK}
321 ;;
322 stp)
323 __device_get_file ${bridge} "bridge/priority"
324 return ${EXIT_OK}
325 ;;
326 esac
327
328 return ${EXIT_ERROR}
329 }
330
331 function stp_bridge_get_topology_change_count() {
332 local bridge=${1}
333
334 assert isset bridge
335
336 case "$(stp_bridge_get_protocol ${bridge})" in
337 rstp)
338 __rstpctl_bridge_get ${bridge} "topology_change_count"
339 return ${EXIT_OK}
340 ;;
341 stp)
342 __device_get_file ${bridge} "bridge/topology_change"
343 return ${EXIT_OK}
344 ;;
345 esac
346
347 return ${EXIT_ERROR}
348 }
349
350 function stp_bridge_get_topology_change_timer() {
351 local bridge=${1}
352
353 assert isset bridge
354
355 case "$(stp_bridge_get_protocol ${bridge})" in
356 rstp)
357 __rstpctl_bridge_get ${bridge} "time_since_topology_change"
358 return ${EXIT_OK}
359 ;;
360 stp)
361 __device_get_file ${bridge} "bridge/topology_change_timer"
362 return ${EXIT_OK}
363 ;;
364 esac
365
366 return ${EXIT_ERROR}
367 }
368
369 function stp_bridge_get_topology_change_detected() {
370 local bridge=${1}
371
372 assert isset bridge
373
374 case "$(stp_bridge_get_protocol ${bridge})" in
375 rstp)
376 __rstpctl_bridge_get ${bridge} "topology_change"
377 return ${EXIT_OK}
378 ;;
379 stp)
380 __device_get_file ${bridge} "bridge/topology_change_detected"
381 return ${EXIT_OK}
382 ;;
383 esac
384
385 return ${EXIT_ERROR}
386 }
387
388 # STP states
389 STP_STATE[0]="disabled"
390 STP_STATE[1]="listening"
391 STP_STATE[2]="learning"
392 STP_STATE[3]="forwarding"
393 STP_STATE[4]="blocking"
394
395 function stp_port_get_state() {
396 local bridge=${1}
397 local port=${2}
398 local output
399
400 assert isset bridge
401 assert isset port
402
403 case "$(stp_bridge_get_protocol ${bridge})" in
404 rstp)
405 output=$(__rstpctl_port_get ${bridge} ${port} "state")
406 ;;
407 stp)
408 output=$(__device_get_file ${bridge} "brif/${port}/state")
409
410 # Translate int to name
411 output="${STP_STATE[${output}]}"
412 ;;
413 esac
414
415 if ! isset output; then
416 return ${EXIT_ERROR}
417 fi
418
419 echo "${output^^}"
420
421 return ${EXIT_OK}
422 }
423
424 function stp_port_get_id() {
425 local bridge=${1}
426 local port=${2}
427
428 assert isset bridge
429 assert isset port
430
431 case "$(stp_bridge_get_protocol ${bridge})" in
432 rstp)
433 __rstpctl_port_get ${bridge} ${port} "id"
434 return ${EXIT_OK}
435 ;;
436 stp)
437 dec $(__device_get_file ${bridge} "brif/${port}/port_no")
438 return ${EXIT_OK}
439 ;;
440 esac
441
442 return ${EXIT_ERROR}
443 }
444
445 function stp_port_get_cost() {
446 local bridge=${1}
447 local port=${2}
448
449 assert isset bridge
450 assert isset port
451
452 case "$(stp_bridge_get_protocol ${bridge})" in
453 rstp)
454 __rstpctl_port_get ${bridge} ${port} "path_cost"
455 return ${EXIT_OK}
456 ;;
457 stp)
458 __device_get_file ${bridge} "brif/${port}/path_cost"
459 return ${EXIT_OK}
460 ;;
461 esac
462
463 return ${EXIT_ERROR}
464 }
465
466 function stp_port_get_designated_root() {
467 local bridge=${1}
468 local port=${2}
469 local output
470
471 assert isset bridge
472 assert isset port
473
474 case "$(stp_bridge_get_protocol ${bridge})" in
475 rstp)
476 output=$(__rstpctl_port_get ${bridge} ${port} "designated_root")
477 ;;
478 stp)
479 output=$(__device_get_file ${bridge} "brif/${port}/designated_root")
480 ;;
481 esac
482
483 if [ -n "${output}" ]; then
484 mac_format ${output:5:12}
485 return ${EXIT_OK}
486 fi
487
488 return ${EXIT_ERROR}
489 }