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