]> git.ipfire.org Git - network.git/blob - functions.stp
Enhanced modem support.
[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 # 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.
26 STP_DEFAULT_MODE="rstp"
27
28 # Allowed modes of the spanning tree protocol.
29 STP_ALLOWED_MODES="rstp stp"
30
31 function stp_enable() {
32 local bridge=${1}
33 local mode=${2}
34
35 assert isset bridge
36 assert zone_exists ${bridge}
37
38 # Tell the kernel to enable STP.
39 brctl stp ${bridge} on
40
41 # Set the correct protocol version.
42 if [ -z "${mode}" ]; then
43 mode="${STP_DEFAULT_MODE}"
44 fi
45 stp_bridge_set_protocol ${bridge} ${mode}
46 }
47
48 function stp_disable() {
49 local bridge=${1}
50
51 assert isset bridge
52 assert zone_exists ${bridge}
53
54 brctl stp ${bridge} off
55 }
56
57 function stp_is_enabled() {
58 local bridge=${1}
59 assert isset bridge
60
61 local state=$(__device_get_file ${bridge} bridge/stp_state)
62
63 case "${state}" in
64 0)
65 return ${EXIT_FALSE}
66 ;;
67 *)
68 return ${EXIT_TRUE}
69 ;;
70 esac
71 }
72
73 function stp_get_name() {
74 local proto=${1}
75
76 case "${proto}" in
77 stp)
78 echo "Spanning Tree Protocol"
79 ;;
80 rstp)
81 echo "Rapid Spanning Tree Protocol"
82 ;;
83 mstp)
84 echo "Multiple Spanning Tree Protocol"
85 ;;
86 esac
87
88 return ${EXIT_OK}
89 }
90
91 function stp_bridge_set_protocol() {
92 local bridge=${1}
93 local mode=${2}
94
95 assert isset bridge
96 assert isset mode
97
98 if ! listmatch ${mode} ${STP_ALLOWED_MODES}; then
99 log WARNING "Unknown protocol version: ${mode}."
100 log WARNING "Using default mode."
101
102 mode="${STP_DEFAULT_MODE}"
103 fi
104
105 mstpctl setforcevers ${bridge} ${mode}
106 assert [ $? -eq 0 ]
107 }
108
109 function stp_bridge_get_protocol() {
110 local bridge=${1}
111
112 assert isset bridge
113
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")
116
117 case "${state}" in
118 0)
119 # STP is disabled.
120 return ${EXIT_OK}
121 ;;
122 1)
123 # Kernel mode STP is running.
124 echo "stp"
125 return ${EXIT_OK}
126 ;;
127 2)
128 # User-space STP is running.
129 ;;
130 *)
131 log ERROR "Kernel is running in an unknown STP state."
132 return ${EXIT_ERROR}
133 ;;
134 esac
135
136 # We get here, when STP is running in user-space mode.
137
138 # Get the current protocol version.
139 mstpctl showbridge ${bridge} force-protocol-version
140
141 return ${EXIT_OK}
142 }
143
144 function stp_bridge_get_id() {
145 local bridge=${1}
146 assert isset bridge
147
148 __device_get_file ${bridge} "bridge/bridge_id"
149
150 return $?
151 }
152
153 function stp_bridge_get_forward_delay() {
154 local bridge=${1}
155
156 assert isset bridge
157
158 mstpctl showbridge ${bridge} forward-delay
159 }
160
161 function stp_bridge_set_forward_delay() {
162 local bridge=${1}
163 assert isset bridge
164
165 local fdelay=${2}
166 assert isinteger fdelay
167
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}
171
172 # The smallest value that may be set is 2.
173 if [ ${fdelay} -lt 2 ]; then
174 fdelay=2
175 fi
176
177 # Set the new value.
178 log INFO "Changing forward delay for '${bridge}': ${current_fdelay} --> ${fdelay}."
179 brctl setfd ${bridge} ${fdelay}
180
181 return ${EXIT_OK}
182 }
183
184 function stp_bridge_get_hello_time() {
185 local bridge=${1}
186 assert isset bridge
187
188 local ht=$(__device_get_file ${bridge} "bridge/hello_time")
189
190 # ht is now in seconds * 100.
191 local split=$((${#ht} - 2))
192 ht="${ht:0:${split}}.${ht:${split}:2}"
193
194 # Round the output.
195 printf "%.0f\n" "${ht}"
196 }
197
198 function stp_bridge_set_hello_time() {
199 local bridge=${1}
200 assert isset bridge
201
202 local hello=${2}
203 assert isinteger hello
204
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}
208
209 # Set the new value.
210 log INFO "Changing hello time for '${bridge}': ${current_hello} --> ${hello}."
211 brctl sethello ${bridge} ${hello}
212
213 return ${EXIT_OK}
214 }
215
216 function stp_bridge_get_max_age() {
217 local bridge=${1}
218 assert isset bridge
219
220 local maxage=$(__device_get_file ${bridge} "bridge/max_age")
221
222 # maxage is now in seconds * 100.
223 local split=$((${#maxage} - 2))
224 maxage="${maxage:0:${split}}.${maxage:${split}:2}"
225
226 # Round the output.
227 printf "%.0f\n" "${maxage}"
228 }
229
230 function stp_bridge_set_max_age() {
231 local bridge=${1}
232 assert isset bridge
233
234 local maxage=${2}
235 assert isinteger maxage
236
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}
240
241 # Set the new value.
242 log INFO "Changing max age for '${bridge}': ${current_maxage} --> ${maxage}."
243 brctl setmaxage ${bridge} ${maxage}
244
245 return ${EXIT_OK}
246 }
247
248 function stp_bridge_get_priority() {
249 local bridge=${1}
250 assert isset bridge
251
252 __device_get_file ${bridge} "bridge/priority"
253 }
254
255 function stp_bridge_set_priority() {
256 local bridge=${1}
257 assert isset bridge
258
259 local priority=${2}
260 assert isinteger priority
261
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}
265
266 # Set the new value.
267 log INFO "Changing priority for '${bridge}': ${current_priority} --> ${priority}."
268 brctl setbridgeprio ${bridge} ${priority}
269
270 return ${EXIT_OK}
271 }
272
273 function stp_bridge_get_designated_root() {
274 local bridge=${1}
275 local output
276
277 assert isset bridge
278
279 local output=$(mstpctl showbridge ${bridge} designated-root)
280
281 if ! isset output; then
282 return ${EXIT_ERROR}
283 fi
284
285 echo "${output,,}"
286 return ${EXIT_OK}
287 }
288
289 function stp_bridge_get_root_path_cost() {
290 local bridge=${1}
291
292 assert isset bridge
293
294 mstpctl showbridge ${bridge} path-cost
295 }
296
297 function stp_bridge_get_root_port_id() {
298 local bridge=${1}
299
300 assert isset bridge
301
302 local root_port=$(mstpctl showbridge ${bridge} root-port)
303
304 # Return error, when there is no root port.
305 if [ "${root_port}" = "none" ]; then
306 return ${EXIT_ERROR}
307 fi
308
309 echo "${root_port}"
310 return ${EXIT_OK}
311 }
312
313 function stp_bridge_get_root_port() {
314 local bridge=${1}
315
316 assert isset bridge
317
318 local id=$(stp_bridge_get_root_port_id ${bridge})
319
320 local member
321 local member_id
322 for member in $(bridge_get_members ${bridge}); do
323 member_id=$(stp_port_get_id ${bridge} ${member})
324
325 if [ "${id}" = "${member_id}" ]; then
326 echo "${member}"
327 return ${EXIT_OK}
328 fi
329 done
330
331 return ${EXIT_ERROR}
332 }
333
334 function stp_bridge_is_root() {
335 stp_bridge_get_root_port_id $@ >/dev/null
336 local ret=$?
337
338 if [ ${ret} -eq ${EXIT_ERROR} ]; then
339 return ${EXIT_OK}
340 fi
341
342 return ${EXIT_ERROR}
343 }
344
345 function stp_bridge_get_priority() {
346 local bridge=${1}
347
348 assert isset bridge
349
350 local id=$(stp_bridge_get_id ${bridge})
351
352 dec "${id:0:4}"
353 }
354
355 function stp_bridge_get_topology_change_count() {
356 local bridge=${1}
357
358 assert isset bridge
359
360 mstpctl showbridge ${bridge} topology-change-count
361 }
362
363 function stp_bridge_get_topology_change_timer() {
364 local bridge=${1}
365
366 assert isset bridge
367
368 mstpctl showbridge ${bridge} time-since-topology-change
369 }
370
371 function stp_bridge_get_topology_change_detected() {
372 local bridge=${1}
373
374 assert isset bridge
375
376 local change=$(mstpctl showbridge ${bridge} topology-change)
377
378 echo "${change}"
379 case "${change}" in
380 yes)
381 return ${EXIT_OK}
382 ;;
383 *)
384 return ${EXIT_ERROR}
385 ;;
386 esac
387 }
388
389 function stp_port_get_state() {
390 local bridge=${1}
391 local port=${2}
392
393 assert isset bridge
394 assert isset port
395
396 local state=$(mstpctl showportdetail ${bridge} ${port} state)
397
398 echo "${state^^}"
399 }
400
401 function stp_port_get_id() {
402 local bridge=${1}
403 local port=${2}
404
405 assert isset bridge
406 assert isset port
407
408 local id=$(__device_get_file ${bridge} "brif/${port}/port_no")
409
410 dec ${id}
411
412 return ${EXIT_OK}
413 }
414
415 function stp_port_get_cost() {
416 local bridge=${1}
417 local port=${2}
418
419 assert isset bridge
420 assert isset port
421
422 mstpctl showportdetail ${bridge} ${port} external-port-cost
423
424 return ${EXIT_ERROR}
425 }
426
427 function stp_port_get_designated_root() {
428 local bridge=${1}
429 local port=${2}
430 local output
431
432 assert isset bridge
433 assert isset port
434
435 output=$(mstpctl showportdetail ${bridge} ${port} designated-root)
436
437 if [ -n "${output}" ]; then
438 echo "${output,,}"
439 return ${EXIT_OK}
440 fi
441
442 return ${EXIT_ERROR}
443 }