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
() {
36 assert zone_exists
${bridge}
38 # Tell the kernel to enable STP.
39 brctl stp
${bridge} on
41 # Set the correct protocol version.
42 if [ -z "${mode}" ]; then
43 mode
="${STP_DEFAULT_MODE}"
45 stp_bridge_set_protocol
${bridge} ${mode}
48 function stp_disable
() {
52 assert zone_exists
${bridge}
54 brctl stp
${bridge} off
57 function stp_is_enabled
() {
61 local state
=$
(__device_get_file
${bridge} bridge
/stp_state
)
73 function stp_get_name
() {
78 echo "Spanning Tree Protocol"
81 echo "Rapid Spanning Tree Protocol"
84 echo "Multiple Spanning Tree Protocol"
91 function stp_bridge_set_protocol
() {
98 if ! listmatch
${mode} ${STP_ALLOWED_MODES}; then
99 log WARNING
"Unknown protocol version: ${mode}."
100 log WARNING
"Using default mode."
102 mode
="${STP_DEFAULT_MODE}"
105 mstpctl setforcevers
${bridge} ${mode}
109 function stp_bridge_get_protocol
() {
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")
123 # Kernel mode STP is running.
128 # User-space STP is running.
131 log ERROR
"Kernel is running in an unknown STP state."
136 # We get here, when STP is running in user-space mode.
138 # Get the current protocol version.
139 mstpctl showbridge
${bridge} force-protocol-version
144 function stp_bridge_get_id
() {
148 __device_get_file
${bridge} "bridge/bridge_id"
153 function stp_bridge_get_forward_delay
() {
158 mstpctl showbridge
${bridge} forward-delay
161 function stp_bridge_set_forward_delay
() {
166 assert isinteger fdelay
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}
172 # The smallest value that may be set is 2.
173 if [ ${fdelay} -lt 2 ]; then
178 log INFO
"Changing forward delay for '${bridge}': ${current_fdelay} --> ${fdelay}."
179 brctl setfd
${bridge} ${fdelay}
184 function stp_bridge_get_hello_time
() {
188 local ht
=$
(__device_get_file
${bridge} "bridge/hello_time")
190 # ht is now in seconds * 100.
191 local split=$
((${#ht} - 2))
192 ht
="${ht:0:${split}}.${ht:${split}:2}"
195 printf "%.0f\n" "${ht}"
198 function stp_bridge_set_hello_time
() {
203 assert isinteger hello
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}
210 log INFO
"Changing hello time for '${bridge}': ${current_hello} --> ${hello}."
211 brctl sethello
${bridge} ${hello}
216 function stp_bridge_get_max_age
() {
220 local maxage
=$
(__device_get_file
${bridge} "bridge/max_age")
222 # maxage is now in seconds * 100.
223 local split=$
((${#maxage} - 2))
224 maxage
="${maxage:0:${split}}.${maxage:${split}:2}"
227 printf "%.0f\n" "${maxage}"
230 function stp_bridge_set_max_age
() {
235 assert isinteger maxage
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}
242 log INFO
"Changing max age for '${bridge}': ${current_maxage} --> ${maxage}."
243 brctl setmaxage
${bridge} ${maxage}
248 function stp_bridge_get_priority
() {
252 __device_get_file
${bridge} "bridge/priority"
255 function stp_bridge_set_priority
() {
260 assert isinteger priority
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}
267 log INFO
"Changing priority for '${bridge}': ${current_priority} --> ${priority}."
268 brctl setbridgeprio
${bridge} ${priority}
273 function stp_bridge_get_designated_root
() {
279 local output
=$
(mstpctl showbridge
${bridge} designated-root
)
281 if ! isset output
; then
289 function stp_bridge_get_root_path_cost
() {
294 mstpctl showbridge
${bridge} path-cost
297 function stp_bridge_get_root_port_id
() {
302 local root_port
=$
(mstpctl showbridge
${bridge} root-port
)
304 # Return error, when there is no root port.
305 if [ "${root_port}" = "none" ]; then
313 function stp_bridge_get_root_port
() {
318 local id
=$
(stp_bridge_get_root_port_id
${bridge})
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
() {
335 stp_bridge_get_root_port_id $@
>/dev
/null
338 if [ ${ret} -eq ${EXIT_ERROR} ]; then
345 function stp_bridge_get_priority
() {
350 local id
=$
(stp_bridge_get_id
${bridge})
355 function stp_bridge_get_topology_change_count
() {
360 mstpctl showbridge
${bridge} topology-change-count
363 function stp_bridge_get_topology_change_timer
() {
368 mstpctl showbridge
${bridge} time-since-topology-change
371 function stp_bridge_get_topology_change_detected
() {
376 local change
=$
(mstpctl showbridge
${bridge} topology-change
)
389 function stp_port_get_state
() {
396 local state
=$
(mstpctl showportdetail
${bridge} ${port} state
)
401 function stp_port_get_id
() {
408 local id
=$
(__device_get_file
${bridge} "brif/${port}/port_no")
415 function stp_port_get_cost
() {
422 mstpctl showportdetail
${bridge} ${port} external-port-cost
427 function stp_port_get_designated_root
() {
435 output
=$
(mstpctl showportdetail
${bridge} ${port} designated-root
)
437 if [ -n "${output}" ]; then