]> git.ipfire.org Git - people/stevee/network.git/blame - src/functions/functions.stp
Use autotools.
[people/stevee/network.git] / src / functions / functions.stp
CommitLineData
e84e4e76
MT
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
e266c18e
MT
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.
26STP_DEFAULT_MODE="rstp"
6b3f9c85 27
e266c18e
MT
28# Allowed modes of the spanning tree protocol.
29STP_ALLOWED_MODES="rstp stp"
6b3f9c85 30
feb76eaf 31function stp_enable() {
e84e4e76 32 local bridge=${1}
feb76eaf 33 assert isset bridge
e84e4e76 34
e266c18e 35 # Tell the kernel to enable STP.
7d85603e 36 print 1 > ${SYS_CLASS_NET}/${bridge}/bridge/stp_state
e84e4e76
MT
37}
38
feb76eaf 39function stp_disable() {
e84e4e76 40 local bridge=${1}
feb76eaf 41 assert isset bridge
feb76eaf 42
7d85603e
MT
43 # Tell the kernel to disable STP.
44 print 0 > ${SYS_CLASS_NET}/${bridge}/bridge/stp_state
e84e4e76
MT
45}
46
3cb2fc42
MT
47function stp_is_enabled() {
48 local bridge=${1}
49 assert isset bridge
50
51 local state=$(__device_get_file ${bridge} bridge/stp_state)
52
53 case "${state}" in
54 0)
55 return ${EXIT_FALSE}
56 ;;
57 *)
58 return ${EXIT_TRUE}
59 ;;
60 esac
61}
62
48bc31eb
MT
63function stp_is_userspace() {
64 local bridge=${1}
65 assert isset bridge
66
67 local state=$(__device_get_file ${bridge} bridge/stp_state)
68 case "${state}" in
69 2)
70 return ${EXIT_TRUE}
71 ;;
72 *)
73 return ${EXIT_FALSE}
74 ;;
75 esac
76}
77
8d4f9311
MT
78function stp_get_name() {
79 local proto=${1}
80
81 case "${proto}" in
82 stp)
83 echo "Spanning Tree Protocol"
84 ;;
85 rstp)
86 echo "Rapid Spanning Tree Protocol"
87 ;;
88 mstp)
89 echo "Multiple Spanning Tree Protocol"
90 ;;
91 esac
92
93 return ${EXIT_OK}
94}
95
f7d36d3f
MT
96function stp_bridge_set_protocol() {
97 local bridge=${1}
98 assert isset bridge
99
100 local mode=${2}
101 assert isset mode
102
103 if ! listmatch ${mode} ${STP_ALLOWED_MODES}; then
104 log WARNING "Unknown protocol version: ${mode}."
105 log WARNING "Using default mode."
106
107 mode="${STP_DEFAULT_MODE}"
108 fi
109
064655d5 110 cmd mstpctl setforcevers ${bridge} ${mode}
f7d36d3f
MT
111 assert [ $? -eq 0 ]
112}
113
feb76eaf 114function stp_bridge_get_protocol() {
e84e4e76 115 local bridge=${1}
e84e4e76 116
feb76eaf
MT
117 assert isset bridge
118
8d4f9311
MT
119 # Let's check what the kernel is telling us about it's STP state.
120 local state=$(__device_get_file ${bridge} "bridge/stp_state")
feb76eaf 121
8d4f9311 122 case "${state}" in
feb76eaf 123 0)
8d4f9311
MT
124 # STP is disabled.
125 return ${EXIT_OK}
126 ;;
127 1)
128 # Kernel mode STP is running.
feb76eaf 129 echo "stp"
8d4f9311 130 return ${EXIT_OK}
feb76eaf
MT
131 ;;
132 2)
8d4f9311 133 # User-space STP is running.
36e3fd2f 134 ;;
8d4f9311
MT
135 *)
136 log ERROR "Kernel is running in an unknown STP state."
137 return ${EXIT_ERROR}
36e3fd2f 138 ;;
feb76eaf 139 esac
e84e4e76 140
8d4f9311 141 # We get here, when STP is running in user-space mode.
e84e4e76 142
8d4f9311 143 # Get the current protocol version.
48bc31eb 144 mstpctl showbridge ${bridge} force-protocol-version 2>/dev/null
feb76eaf 145
8d4f9311 146 return ${EXIT_OK}
e84e4e76
MT
147}
148
8d4f9311 149function stp_bridge_get_id() {
e84e4e76 150 local bridge=${1}
feb76eaf 151 assert isset bridge
e84e4e76 152
8d4f9311 153 __device_get_file ${bridge} "bridge/bridge_id"
feb76eaf 154
8d4f9311 155 return $?
e84e4e76
MT
156}
157
8d4f9311 158function stp_bridge_get_forward_delay() {
e84e4e76 159 local bridge=${1}
feb76eaf
MT
160 assert isset bridge
161
48bc31eb
MT
162 if stp_is_userspace ${bridge}; then
163 cmd mstpctl showbridge ${bridge} forward-delay
164 else
165 local output=$(__device_get_file ${bridge} bridge/forward_delay)
166 __stp_div_100 ${output}
167 fi
168
169 return ${EXIT_OK}
8d4f9311 170}
feb76eaf 171
8d4f9311 172function stp_bridge_set_forward_delay() {
e2aa12b3
MT
173 local bridge=${1}
174 assert isset bridge
175
176 local fdelay=${2}
177 assert isinteger fdelay
178
179 # Check if the setting we want is already set.
180 local current_fdelay=$(stp_bridge_get_forward_delay ${bridge})
181 [ ${fdelay} -eq ${current_fdelay} ] && return ${EXIT_OK}
182
183 # The smallest value that may be set is 2.
184 if [ ${fdelay} -lt 2 ]; then
185 fdelay=2
186 fi
187
188 # Set the new value.
48bc31eb
MT
189 log INFO "Changing forward delay for '${bridge}': ${current_fdelay} --> ${fdelay}"
190 print "$(( ${fdelay} * 100 ))" > ${SYS_CLASS_NET}/${bridge}/bridge/forward_delay
e2aa12b3
MT
191
192 return ${EXIT_OK}
193}
194
195function stp_bridge_get_hello_time() {
196 local bridge=${1}
197 assert isset bridge
198
48bc31eb
MT
199 local ht=$(__device_get_file ${bridge} bridge/hello_time)
200 __stp_div_100 ${ht}
e2aa12b3 201
48bc31eb 202 return ${EXIT_OK}
e2aa12b3
MT
203}
204
205function stp_bridge_set_hello_time() {
206 local bridge=${1}
207 assert isset bridge
208
209 local hello=${2}
210 assert isinteger hello
211
212 # Check if the setting we want is already set.
213 local current_hello=$(stp_bridge_get_hello_time ${bridge})
214 [ ${hello} -eq ${current_hello} ] && return ${EXIT_OK}
215
216 # Set the new value.
48bc31eb
MT
217 log INFO "Changing hello time for '${bridge}': ${current_hello} --> ${hello}"
218 print "$(( ${hello} * 100 ))" > ${SYS_CLASS_NET}/${bridge}/bridge/hellow_time
e2aa12b3
MT
219
220 return ${EXIT_OK}
221}
222
223function stp_bridge_get_max_age() {
224 local bridge=${1}
225 assert isset bridge
226
227 local maxage=$(__device_get_file ${bridge} "bridge/max_age")
48bc31eb 228 __stp_div_100 ${maxage}
e2aa12b3 229
48bc31eb 230 return ${EXIT_OK}
e2aa12b3
MT
231}
232
233function stp_bridge_set_max_age() {
234 local bridge=${1}
235 assert isset bridge
236
237 local maxage=${2}
238 assert isinteger maxage
239
240 # Check if the setting we want is already set.
241 local current_maxage=$(stp_bridge_get_max_age ${bridge})
242 [ ${maxage} -eq ${current_maxage} ] && return ${EXIT_OK}
243
244 # Set the new value.
48bc31eb
MT
245 log INFO "Changing max age for '${bridge}': ${current_maxage} --> ${maxage}"
246 print "$(( ${maxage} * 100 ))" > ${SYS_CLASS_NET}/${bridge}/bridge/max_age
e2aa12b3
MT
247
248 return ${EXIT_OK}
249}
250
251function stp_bridge_get_priority() {
252 local bridge=${1}
253 assert isset bridge
254
255 __device_get_file ${bridge} "bridge/priority"
48bc31eb 256 return ${EXIT_OK}
e2aa12b3
MT
257}
258
259function stp_bridge_set_priority() {
260 local bridge=${1}
261 assert isset bridge
262
263 local priority=${2}
264 assert isinteger priority
265
266 # Check if the setting we want is already set.
267 local current_priority=$(stp_bridge_get_priority ${bridge})
268 [ ${priority} -eq ${current_priority} ] && return ${EXIT_OK}
269
270 # Set the new value.
48bc31eb
MT
271 log INFO "Changing priority for '${bridge}': ${current_priority} --> ${priority}"
272 print "${priority}" > ${SYS_CLASS_NET}/${bridge}/bridge/priority
e2aa12b3
MT
273
274 return ${EXIT_OK}
e84e4e76
MT
275}
276
feb76eaf 277function stp_bridge_get_designated_root() {
e84e4e76 278 local bridge=${1}
48bc31eb
MT
279 assert isset bridge
280
feb76eaf
MT
281 local output
282
48bc31eb
MT
283 if stp_is_userspace ${bridge}; then
284 output=$(cmd mstpctl showbridge ${bridge} designated-root)
285 else
286 output=$(__device_get_file ${bridge} bridge/root_id)
287 fi
288 output=${output:6}
e84e4e76 289
48bc31eb
MT
290 # Print output (lowercase).
291 print "${output,,}"
feb76eaf 292
48bc31eb
MT
293 if isset output; then
294 return ${EXIT_OK}
295 else
feb76eaf
MT
296 return ${EXIT_ERROR}
297 fi
e84e4e76
MT
298}
299
feb76eaf 300function stp_bridge_get_root_path_cost() {
e84e4e76 301 local bridge=${1}
feb76eaf
MT
302 assert isset bridge
303
48bc31eb
MT
304 if stp_is_userspace ${bridge}; then
305 cmd mstpctl showbridge ${bridge} path-cost
306 else
307 __device_get_file ${bridge} bridge/root_path_cost
308 fi
309
310 return ${EXIT_OK}
e84e4e76
MT
311}
312
feb76eaf 313function stp_bridge_get_root_port_id() {
e84e4e76 314 local bridge=${1}
feb76eaf
MT
315 assert isset bridge
316
48bc31eb
MT
317 if stp_is_userspace ${bridge}; then
318 local root_port=$(cmd mstpctl showbridge ${bridge} root-port)
e84e4e76 319
48bc31eb
MT
320 # Return error, when there is no root port.
321 if [ "${root_port}" = "none" ]; then
322 return ${EXIT_ERROR}
323 fi
324
325 print "${root_port}"
326 else
327 __device_get_file ${bridge} bridge/root_port_id
8d4f9311
MT
328 fi
329
8d4f9311 330 return ${EXIT_OK}
e84e4e76
MT
331}
332
feb76eaf 333function stp_bridge_get_root_port() {
e84e4e76 334 local bridge=${1}
feb76eaf 335 assert isset bridge
e84e4e76 336
feb76eaf 337 local id=$(stp_bridge_get_root_port_id ${bridge})
e84e4e76 338
48bc31eb 339 local member member_id
feb76eaf
MT
340 for member in $(bridge_get_members ${bridge}); do
341 member_id=$(stp_port_get_id ${bridge} ${member})
e84e4e76 342
feb76eaf 343 if [ "${id}" = "${member_id}" ]; then
48bc31eb 344 print "${member}"
feb76eaf
MT
345 return ${EXIT_OK}
346 fi
347 done
e84e4e76 348
feb76eaf 349 return ${EXIT_ERROR}
e84e4e76
MT
350}
351
feb76eaf 352function stp_bridge_is_root() {
feb76eaf 353 local bridge=${1}
feb76eaf 354 assert isset bridge
e84e4e76 355
48bc31eb 356 local root_path_cost=$(stp_bridge_get_root_path_cost ${bridge})
e84e4e76 357
48bc31eb
MT
358 if [ "${root_path_cost}" = "0" ]; then
359 return ${EXIT_TRUE}
360 fi
361
362 return ${EXIT_FALSE}
e84e4e76
MT
363}
364
feb76eaf
MT
365function stp_bridge_get_topology_change_count() {
366 local bridge=${1}
feb76eaf 367 assert isset bridge
e84e4e76 368
48bc31eb
MT
369 if stp_is_userspace ${bridge}; then
370 cmd mstpctl showbridge ${bridge} topology-change-count
371 else
372 __device_get_file ${bridge} bridge/topology_change
373 fi
374
375 return ${EXIT_OK}
e84e4e76
MT
376}
377
feb76eaf
MT
378function stp_bridge_get_topology_change_timer() {
379 local bridge=${1}
feb76eaf
MT
380 assert isset bridge
381
48bc31eb
MT
382 if stp_is_userspace ${bridge}; then
383 cmd mstpctl showbridge ${bridge} time-since-topology-change
384 else
385 __device_get_file ${bridge} bridge/topology_change_timer
386 fi
387
388 return ${EXIT_OK}
e84e4e76
MT
389}
390
feb76eaf
MT
391function stp_bridge_get_topology_change_detected() {
392 local bridge=${1}
feb76eaf 393 assert isset bridge
e84e4e76 394
48bc31eb 395 local change
8d4f9311 396
48bc31eb
MT
397 if stp_is_userspace ${bridge}; then
398 change=$(mstpctl showbridge ${bridge} topology-change)
399 else
400 change=$(__device_get_file ${bridge} bridge/topology_change_detected)
401 fi
402
403 if enabled change; then
404 print "yes"
405 return ${EXIT_TRUE}
406 else
407 print "no"
408 return ${EXIT_FALSE}
409 fi
6b3f9c85
MT
410}
411
feb76eaf 412function stp_port_get_state() {
6b3f9c85 413 local bridge=${1}
6b3f9c85 414 assert isset bridge
48bc31eb
MT
415
416 local port=${2}
feb76eaf 417 assert isset port
6b3f9c85 418
48bc31eb
MT
419 local space
420 if stp_is_userspace ${bridge}; then
421 state=$(mstpctl showportdetail ${bridge} ${port} state)
422 print "${state^^}"
423 else
424 state=$(__device_get_file ${bridge} brif/${port}/state)
425
426 case "${state}" in
427 0)
428 print "DISABLED"
429 ;;
430 1)
431 print "LISTENING"
432 ;;
433 2)
434 print "LEARNING"
435 ;;
436 3)
437 print "FORWARDING"
438 ;;
439 4)
440 print "BLOCKING"
441 ;;
442 *)
443 return ${EXIT_ERROR}
444 ;;
445 esac
446 fi
feb76eaf 447
48bc31eb 448 return ${EXIT_OK}
feb76eaf
MT
449}
450
451function stp_port_get_id() {
452 local bridge=${1}
feb76eaf 453 assert isset bridge
feb76eaf 454
48bc31eb
MT
455 local port=${2}
456 assert isset port
8d4f9311 457
48bc31eb 458 dec $(__device_get_file ${bridge} "brif/${port}/port_no")
8d4f9311 459 return ${EXIT_OK}
feb76eaf
MT
460}
461
462function stp_port_get_cost() {
463 local bridge=${1}
feb76eaf 464 assert isset bridge
48bc31eb
MT
465
466 local port=${2}
feb76eaf
MT
467 assert isset port
468
48bc31eb
MT
469 if stp_is_userspace ${bridge}; then
470 cmd mstpctl showportdetail ${bridge} ${port} external-port-cost
471 else
472 __device_get_file ${bridge} brif/${port}/path_cost
473 fi
feb76eaf
MT
474
475 return ${EXIT_ERROR}
6b3f9c85
MT
476}
477
feb76eaf 478function stp_port_get_designated_root() {
6b3f9c85 479 local bridge=${1}
6b3f9c85 480 assert isset bridge
48bc31eb
MT
481
482 local port=${2}
feb76eaf 483 assert isset port
6b3f9c85 484
48bc31eb
MT
485 local output
486
487 if stp_is_userspace ${bridge}; then
488 output=$(cmd mstpctl showportdetail ${bridge} ${port} designated-root)
489 output=${output:6}
490 else
491 output=$(__device_get_file ${bridge} brif/${port}/designated_root)
492 output=${output:5}
493 fi
feb76eaf 494
48bc31eb
MT
495 if isset output; then
496 mac_format ${output}
36e3fd2f
MT
497 return ${EXIT_OK}
498 fi
feb76eaf
MT
499
500 return ${EXIT_ERROR}
6b3f9c85 501}
48bc31eb
MT
502
503function __stp_div_100() {
504 local val=${1}
505
506 local split=$((${#val} - 2))
507 val="${val:0:${split}}.${val:${split}:2}"
508
509 # Round the output.
510 print "%.0f" "${val}"
511}