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