2 ###############################################################################
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2010 Michael Tremer & Christian Schmidt #
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. #
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. #
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/>. #
20 ###############################################################################
23 # We default to RSTP, because it has the better user experience and
24 # faster convergence times. Despite of that, it completely downgradeable
26 STP_DEFAULT_MODE
="rstp"
28 # Allowed modes of the spanning tree protocol.
29 STP_ALLOWED_MODES
="rstp stp"
31 function stp_enable
() {
35 # Tell the kernel to enable STP.
36 print
1 > ${SYS_CLASS_NET}/${bridge}/bridge
/stp_state
39 function stp_disable
() {
43 # Tell the kernel to disable STP.
44 print
0 > ${SYS_CLASS_NET}/${bridge}/bridge
/stp_state
47 function stp_is_enabled
() {
51 local state
=$
(__device_get_file
${bridge} bridge
/stp_state
)
63 function stp_is_userspace
() {
67 local state
=$
(__device_get_file
${bridge} bridge
/stp_state
)
78 function stp_get_name
() {
83 echo "Spanning Tree Protocol"
86 echo "Rapid Spanning Tree Protocol"
89 echo "Multiple Spanning Tree Protocol"
96 function stp_bridge_get_protocol
() {
101 # Let's check what the kernel is telling us about it's STP state.
102 local state
=$
(__device_get_file
${bridge} "bridge/stp_state")
110 # Kernel mode STP is running.
115 # User-space STP is running.
118 log ERROR
"Kernel is running in an unknown STP state."
123 # We get here, when STP is running in user-space mode.
125 # Get the current protocol version.
126 mstpctl showbridge
${bridge} force-protocol-version
2>/dev
/null
131 function stp_bridge_get_id
() {
135 __device_get_file
${bridge} "bridge/bridge_id"
140 function stp_bridge_get_forward_delay
() {
144 if stp_is_userspace
${bridge}; then
145 cmd mstpctl showbridge
${bridge} forward-delay
147 local output
=$
(__device_get_file
${bridge} bridge
/forward_delay
)
148 __stp_div_100
${output}
154 function stp_bridge_set_forward_delay
() {
159 assert isinteger fdelay
161 # Check if the setting we want is already set.
162 local current_fdelay
=$
(stp_bridge_get_forward_delay
${bridge})
163 [ ${fdelay} -eq ${current_fdelay} ] && return ${EXIT_OK}
165 # The smallest value that may be set is 2.
166 if [ ${fdelay} -lt 2 ]; then
171 log INFO
"Changing forward delay for '${bridge}': ${current_fdelay} --> ${fdelay}"
172 print
"$(( ${fdelay} * 100 ))" > ${SYS_CLASS_NET}/${bridge}/bridge/forward_delay
177 function stp_bridge_get_hello_time() {
181 local ht=$(__device_get_file ${bridge} bridge/hello_time)
187 function stp_bridge_set_hello_time() {
192 assert isinteger hello
194 # Check if the setting we want is already set.
195 local current_hello=$(stp_bridge_get_hello_time ${bridge})
196 [ ${hello} -eq ${current_hello} ] && return ${EXIT_OK}
199 log INFO "Changing hello
time for '${bridge}': ${current_hello} --> ${hello}"
200 print "$(( ${hello} * 100 ))" > ${SYS_CLASS_NET}/${bridge}/bridge/hellow_time
205 function stp_bridge_get_max_age() {
209 local maxage=$(__device_get_file ${bridge} "bridge/max_age")
210 __stp_div_100 ${maxage}
215 function stp_bridge_set_max_age() {
220 assert isinteger maxage
222 # Check if the setting we want is already set.
223 local current_maxage=$(stp_bridge_get_max_age ${bridge})
224 [ ${maxage} -eq ${current_maxage} ] && return ${EXIT_OK}
227 log INFO "Changing max age for '${bridge}': ${current_maxage} --> ${maxage}"
228 print "$
(( ${maxage} * 100 ))" > ${SYS_CLASS_NET}/${bridge}/bridge
/max_age
233 function stp_bridge_get_priority
() {
237 __device_get_file
${bridge} "bridge/priority"
241 function stp_bridge_set_priority
() {
246 assert isinteger priority
248 # Check if the setting we want is already set.
249 local current_priority
=$
(stp_bridge_get_priority
${bridge})
250 [ ${priority} -eq ${current_priority} ] && return ${EXIT_OK}
253 log INFO
"Changing priority for '${bridge}': ${current_priority} --> ${priority}"
254 print
"${priority}" > ${SYS_CLASS_NET}/${bridge}/bridge/priority
259 function stp_bridge_get_designated_root() {
265 if stp_is_userspace ${bridge}; then
266 output=$(cmd mstpctl showbridge ${bridge} designated-root)
268 output=$(__device_get_file ${bridge} bridge/root_id)
272 # Print output (lowercase).
275 if isset output; then
282 function stp_bridge_get_root_path_cost() {
286 if stp_is_userspace ${bridge}; then
287 cmd mstpctl showbridge ${bridge} path-cost
289 __device_get_file ${bridge} bridge/root_path_cost
295 function stp_bridge_get_root_port_id() {
299 if stp_is_userspace ${bridge}; then
300 local root_port=$(cmd mstpctl showbridge ${bridge} root-port)
302 # Return error, when there is no root port.
303 if [ "${root_port}" = "none
" ]; then
309 __device_get_file ${bridge} bridge/root_port_id
315 function stp_bridge_get_root_port() {
319 local id=$(stp_bridge_get_root_port_id ${bridge})
321 local member member_id
322 for member in $(bridge_get_members ${bridge}); do
323 member_id=$(stp_port_get_id ${bridge} ${member})
325 if [ "${id}" = "${member_id}" ]; then
334 function stp_bridge_is_root() {
338 local root_path_cost=$(stp_bridge_get_root_path_cost ${bridge})
340 if [ "${root_path_cost}" = "0" ]; then
347 function stp_bridge_get_topology_change_count() {
351 if stp_is_userspace ${bridge}; then
352 cmd mstpctl showbridge ${bridge} topology-change-count
354 __device_get_file ${bridge} bridge/topology_change
360 function stp_bridge_get_topology_change_timer() {
364 if stp_is_userspace ${bridge}; then
365 cmd mstpctl showbridge ${bridge} time-since-topology-change
367 __device_get_file ${bridge} bridge/topology_change_timer
373 function stp_bridge_get_topology_change_detected() {
379 if stp_is_userspace ${bridge}; then
380 change=$(mstpctl showbridge ${bridge} topology-change)
382 change=$(__device_get_file ${bridge} bridge/topology_change_detected)
385 if enabled change; then
394 function stp_port_get_state() {
402 if stp_is_userspace ${bridge}; then
403 state=$(mstpctl showportdetail ${bridge} ${port} state)
406 state=$(__device_get_file ${bridge} brif/${port}/state)
433 function stp_port_get_id() {
440 dec $(__device_get_file ${bridge} "brif
/${port}/port_no
")
444 function stp_port_get_cost() {
451 if stp_is_userspace ${bridge}; then
452 cmd mstpctl showportdetail ${bridge} ${port} external-port-cost
454 __device_get_file ${bridge} brif/${port}/path_cost
460 function stp_port_get_designated_root() {
469 if stp_is_userspace ${bridge}; then
470 output=$(cmd mstpctl showportdetail ${bridge} ${port} designated-root)
473 output=$(__device_get_file ${bridge} brif/${port}/designated_root)
477 if isset output; then
485 function __stp_div_100() {
488 local split=$((${#val} - 2))
489 val="${val:0:${split}}.${val:${split}:2}"
492 print "%.0f
" "${val}"