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_get_name
() {
62 echo "Spanning Tree Protocol"
65 echo "Rapid Spanning Tree Protocol"
68 echo "Multiple Spanning Tree Protocol"
75 function stp_bridge_set_protocol
() {
82 if ! listmatch
${mode} ${STP_ALLOWED_MODES}; then
83 log WARNING
"Unknown protocol version: ${mode}."
84 log WARNING
"Using default mode."
86 mode
="${STP_DEFAULT_MODE}"
89 mstpctl setforcevers
${bridge} ${mode}
93 function stp_bridge_get_protocol
() {
98 # Let's check what the kernel is telling us about it's STP state.
99 local state
=$
(__device_get_file
${bridge} "bridge/stp_state")
107 # Kernel mode STP is running.
112 # User-space STP is running.
115 log ERROR
"Kernel is running in an unknown STP state."
120 # We get here, when STP is running in user-space mode.
122 # Get the current protocol version.
123 mstpctl showbridge
${bridge} force-protocol-version
128 function stp_bridge_get_id
() {
132 __device_get_file
${bridge} "bridge/bridge_id"
137 function stp_bridge_get_forward_delay
() {
142 mstpctl showbridge
${bridge} forward-delay
145 function stp_bridge_set_forward_delay
() {
150 assert isinteger fdelay
152 # Check if the setting we want is already set.
153 local current_fdelay
=$
(stp_bridge_get_forward_delay
${bridge})
154 [ ${fdelay} -eq ${current_fdelay} ] && return ${EXIT_OK}
156 # The smallest value that may be set is 2.
157 if [ ${fdelay} -lt 2 ]; then
162 log INFO
"Changing forward delay for '${bridge}': ${current_fdelay} --> ${fdelay}."
163 brctl setfd
${bridge} ${fdelay}
168 function stp_bridge_get_hello_time
() {
172 local ht
=$
(__device_get_file
${bridge} "bridge/hello_time")
174 # ht is now in seconds * 100.
175 local split=$
((${#ht} - 2))
176 ht
="${ht:0:${split}}.${ht:${split}:2}"
179 printf "%.0f\n" "${ht}"
182 function stp_bridge_set_hello_time
() {
187 assert isinteger hello
189 # Check if the setting we want is already set.
190 local current_hello
=$
(stp_bridge_get_hello_time
${bridge})
191 [ ${hello} -eq ${current_hello} ] && return ${EXIT_OK}
194 log INFO
"Changing hello time for '${bridge}': ${current_hello} --> ${hello}."
195 brctl sethello
${bridge} ${hello}
200 function stp_bridge_get_max_age
() {
204 local maxage
=$
(__device_get_file
${bridge} "bridge/max_age")
206 # maxage is now in seconds * 100.
207 local split=$
((${#maxage} - 2))
208 maxage
="${maxage:0:${split}}.${maxage:${split}:2}"
211 printf "%.0f\n" "${maxage}"
214 function stp_bridge_set_max_age
() {
219 assert isinteger maxage
221 # Check if the setting we want is already set.
222 local current_maxage
=$
(stp_bridge_get_max_age
${bridge})
223 [ ${maxage} -eq ${current_maxage} ] && return ${EXIT_OK}
226 log INFO
"Changing max age for '${bridge}': ${current_maxage} --> ${maxage}."
227 brctl setmaxage
${bridge} ${maxage}
232 function stp_bridge_get_priority
() {
236 __device_get_file
${bridge} "bridge/priority"
239 function stp_bridge_set_priority
() {
244 assert isinteger priority
246 # Check if the setting we want is already set.
247 local current_priority
=$
(stp_bridge_get_priority
${bridge})
248 [ ${priority} -eq ${current_priority} ] && return ${EXIT_OK}
251 log INFO
"Changing priority for '${bridge}': ${current_priority} --> ${priority}."
252 brctl setbridgeprio
${bridge} ${priority}
257 function stp_bridge_get_designated_root
() {
263 local output
=$
(mstpctl showbridge
${bridge} designated-root
)
265 if ! isset output
; then
273 function stp_bridge_get_root_path_cost
() {
278 mstpctl showbridge
${bridge} path-cost
281 function stp_bridge_get_root_port_id
() {
286 local root_port
=$
(mstpctl showbridge
${bridge} root-port
)
288 # Return error, when there is no root port.
289 if [ "${root_port}" = "none" ]; then
297 function stp_bridge_get_root_port
() {
302 local id
=$
(stp_bridge_get_root_port_id
${bridge})
306 for member
in $
(bridge_get_members
${bridge}); do
307 member_id
=$
(stp_port_get_id
${bridge} ${member})
309 if [ "${id}" = "${member_id}" ]; then
318 function stp_bridge_is_root
() {
319 stp_bridge_get_root_port_id $@
>/dev
/null
322 if [ ${ret} -eq ${EXIT_ERROR} ]; then
329 function stp_bridge_get_priority
() {
334 local id
=$
(stp_bridge_get_id
${bridge})
339 function stp_bridge_get_topology_change_count
() {
344 mstpctl showbridge
${bridge} topology-change-count
347 function stp_bridge_get_topology_change_timer
() {
352 mstpctl showbridge
${bridge} time-since-topology-change
355 function stp_bridge_get_topology_change_detected
() {
360 local change
=$
(mstpctl showbridge
${bridge} topology-change
)
373 function stp_port_get_state
() {
380 local state
=$
(mstpctl showportdetail
${bridge} ${port} state
)
385 function stp_port_get_id
() {
392 local id
=$
(__device_get_file
${bridge} "brif/${port}/port_no")
399 function stp_port_get_cost
() {
406 mstpctl showportdetail
${bridge} ${port} external-port-cost
411 function stp_port_get_designated_root
() {
419 output
=$
(mstpctl showportdetail
${bridge} ${port} designated-root
)
421 if [ -n "${output}" ]; then