]>
Commit | Line | Data |
---|---|---|
4b3ac7bd | 1 | diff --git a/ctl_main.c b/ctl_main.c |
15a94530 | 2 | index dd041d7..7382d97 100644 |
4b3ac7bd MT |
3 | --- a/ctl_main.c |
4 | +++ b/ctl_main.c | |
15a94530 | 5 | @@ -443,6 +443,240 @@ static int cmd_debuglevel(int argc, char *const *argv) |
4b3ac7bd MT |
6 | return CTL_set_debug_level(getuint(argv[1])); |
7 | } | |
8 | ||
9 | +#define DUMP_FMT(br_name, key) "%-8s %-26s ", br_name, key | |
10 | + | |
11 | +static int do_dumpbridge(const char *br_name) { | |
12 | + STP_BridgeStatus s; | |
13 | + | |
14 | + int br_index = get_index_die(br_name, "bridge", 0); | |
15 | + if (br_index < 0) | |
16 | + return -1; | |
17 | + | |
18 | + int r = CTL_get_bridge_status(br_index, &s); | |
19 | + if (r) | |
20 | + return -1; | |
21 | + | |
22 | + /* bridge forward delay */ | |
23 | + printf(DUMP_FMT(br_name, "bridge_forward_delay")); | |
24 | + printf("%u\n", s.bridge_forward_delay); | |
25 | + | |
26 | + /* bridge hello time */ | |
27 | + printf(DUMP_FMT(br_name, "bridge_hello_time")); | |
28 | + printf("%u\n", s.bridge_hello_time); | |
29 | + | |
30 | + /* bridge max age */ | |
31 | + printf(DUMP_FMT(br_name, "bridge_max_age")); | |
32 | + printf("%u\n", s.bridge_max_age); | |
33 | + | |
34 | + /* designated root */ | |
35 | + printf(DUMP_FMT(br_name, "designated_root")); | |
36 | + printf(BR_ID_FMT "\n", BR_ID_ARGS(s.designated_root)); | |
37 | + | |
38 | + /* enabled */ | |
39 | + printf(DUMP_FMT(br_name, "enabled")); | |
40 | + printf("%s\n", BOOL_STR(s.enabled)); | |
41 | + | |
42 | + /* forward delay */ | |
43 | + printf(DUMP_FMT(br_name, "forward_delay")); | |
44 | + printf("%u\n", s.forward_delay); | |
45 | + | |
46 | + /* hello time */ | |
47 | + printf(DUMP_FMT(br_name, "hello_time")); | |
48 | + printf("%u\n", s.hello_time); | |
49 | + | |
50 | + /* id */ | |
51 | + printf(DUMP_FMT(br_name, "id")); | |
52 | + printf(BR_ID_FMT "\n", BR_ID_ARGS(s.bridge_id)); | |
53 | + | |
54 | + /* max age */ | |
55 | + printf(DUMP_FMT(br_name, "max_age")); | |
56 | + printf("%u\n", s.max_age); | |
57 | + | |
15a94530 MT |
58 | + /* protocol version */ |
59 | + printf(DUMP_FMT(br_name, "protocol_version")); | |
60 | + printf("%d\n", s.protocol_version); | |
61 | + | |
4b3ac7bd MT |
62 | + /* root path cost */ |
63 | + printf(DUMP_FMT(br_name, "root_path_cost")); | |
64 | + printf("%u\n", s.root_path_cost); | |
65 | + | |
66 | + /* root port */ | |
67 | + printf(DUMP_FMT(br_name, "root_port")); | |
68 | + printf("%u\n", s.root_port); | |
69 | + | |
70 | + /* time since topology change */ | |
71 | + printf(DUMP_FMT(br_name, "time_since_topology_change")); | |
72 | + printf("%u\n", s.time_since_topology_change); | |
73 | + | |
74 | + /* topology change */ | |
75 | + printf(DUMP_FMT(br_name, "topology_change")); | |
76 | + printf("%u\n", s.topology_change); | |
77 | + | |
78 | + /* topology change count */ | |
79 | + printf(DUMP_FMT(br_name, "topology_change_count")); | |
80 | + printf("%u\n", s.topology_change_count); | |
81 | + | |
82 | + /* tx hold count */ | |
83 | + printf(DUMP_FMT(br_name, "tx_hold_count")); | |
84 | + printf("%u\n", s.tx_hold_count); | |
85 | + | |
86 | + return 0; | |
87 | +} | |
88 | + | |
89 | +static int do_dumpbridgeport(int br_index, const char *pt_name) { | |
90 | + STP_PortStatus p; | |
91 | + int r = 0; | |
92 | + int port_index = get_index_die(pt_name, "port", 0); | |
93 | + if (port_index < 0) | |
94 | + return -1; | |
95 | + | |
96 | + r = CTL_get_port_status(br_index, port_index, &p); | |
97 | + if (r) { | |
98 | + fprintf(stderr, "Failed to get port state for port %d\n", port_index); | |
99 | + return -1; | |
100 | + } | |
101 | + | |
102 | + /* admin edge port */ | |
103 | + printf(DUMP_FMT(pt_name, "admin_edge_port")); | |
104 | + printf("%s\n", BOOL_STR(p.admin_edge_port)); | |
105 | + | |
106 | + /* admin point to point */ | |
107 | + printf(DUMP_FMT(pt_name, "admin_point_to_point")); | |
108 | + printf("%s\n", BOOL_STR(p.admin_p2p)); | |
109 | + | |
110 | + /* auto edge port */ | |
111 | + printf(DUMP_FMT(pt_name, "auto_edge_port")); | |
112 | + printf("%s\n", BOOL_STR(p.auto_edge_port)); | |
113 | + | |
114 | + /* path cost */ | |
115 | + printf(DUMP_FMT(pt_name, "admin_path_cost")); | |
116 | + printf("%d\n", p.admin_path_cost); | |
117 | + | |
118 | + /* designated bridge */ | |
119 | + printf(DUMP_FMT(pt_name, "designated_bridge")); | |
120 | + printf(BR_ID_FMT "\n", BR_ID_ARGS(p.designated_bridge)); | |
121 | + | |
122 | + /* designated cost */ | |
123 | + printf(DUMP_FMT(pt_name, "designated_cost")); | |
124 | + printf("%d\n", p.designated_cost); | |
125 | + | |
126 | + /* designated port */ | |
127 | + printf(DUMP_FMT(pt_name, "designated_port")); | |
128 | + printf("%0x\n", p.designated_port); | |
129 | + | |
130 | + /* designated root */ | |
131 | + printf(DUMP_FMT(pt_name, "designated_root")); | |
132 | + printf(BR_ID_FMT "\n", BR_ID_ARGS(p.designated_root)); | |
133 | + | |
134 | + /* enabled */ | |
135 | + printf(DUMP_FMT(pt_name, "enabled")); | |
136 | + printf("%s\n", BOOL_STR(p.enabled)); | |
137 | + | |
138 | + /* id */ | |
139 | + printf(DUMP_FMT(pt_name, "id")); | |
140 | + printf("%u\n", p.id & 0xfff); | |
141 | + | |
142 | + /* oper edge port */ | |
143 | + printf(DUMP_FMT(pt_name, "oper_edge_port")); | |
144 | + printf("%s\n", BOOL_STR(p.oper_edge_port)); | |
145 | + | |
146 | + /* path cost */ | |
147 | + printf(DUMP_FMT(pt_name, "path_cost")); | |
148 | + printf("%d\n", p.path_cost); | |
149 | + | |
150 | + /* point to point */ | |
151 | + printf(DUMP_FMT(pt_name, "point_to_point")); | |
152 | + printf("%s\n", BOOL_STR(p.oper_p2p)); | |
153 | + | |
154 | + /* state */ | |
155 | + printf(DUMP_FMT(pt_name, "state")); | |
156 | + printf(STATE_STR(p.state)); | |
157 | + printf("\n"); | |
158 | + | |
159 | + /* topology change ack */ | |
160 | + printf(DUMP_FMT(pt_name, "topology_change_ack")); | |
161 | + printf("%s\n", BOOL_STR(p.tc_ack)); | |
162 | + | |
163 | + return 0; | |
164 | +} | |
165 | + | |
166 | +static int cmd_dumpbridge(int argc, char *const *argv) | |
167 | +{ | |
168 | + int i, count = 0; | |
169 | + int r = 0; | |
170 | + struct dirent **namelist; | |
171 | + | |
172 | + if (argc > 1) { | |
173 | + count = argc - 1; | |
174 | + } else { | |
175 | + count = | |
176 | + scandir(SYSFS_CLASS_NET, &namelist, isbridge, alphasort); | |
177 | + if (count < 0) { | |
178 | + fprintf(stderr, "Error getting list of all bridges\n"); | |
179 | + return -1; | |
180 | + } | |
181 | + } | |
182 | + | |
183 | + for (i = 0; i < count; i++) { | |
184 | + const char *name; | |
185 | + if (argc > 1) | |
186 | + name = argv[i + 1]; | |
187 | + else | |
188 | + name = namelist[i]->d_name; | |
189 | + | |
190 | + int err = do_dumpbridge(name); | |
191 | + if (err) | |
192 | + r = err; | |
193 | + } | |
194 | + | |
195 | + if (argc <= 1) { | |
196 | + for (i = 0; i < count; i++) | |
197 | + free(namelist[i]); | |
198 | + free(namelist); | |
199 | + } | |
200 | + | |
201 | + return r; | |
202 | +} | |
203 | + | |
204 | +static int cmd_dumpbridgeports(int argc, char *const *argv) | |
205 | +{ | |
206 | + int r = 0; | |
207 | + | |
208 | + int br_index = get_index(argv[1], "bridge"); | |
209 | + | |
210 | + int i, count = 0; | |
211 | + struct dirent **namelist; | |
212 | + | |
213 | + if (argc > 2) { | |
214 | + count = argc - 2; | |
215 | + } else { | |
216 | + char buf[SYSFS_PATH_MAX]; | |
217 | + snprintf(buf, sizeof(buf), SYSFS_CLASS_NET "/%s/brif", argv[1]); | |
218 | + count = scandir(buf, &namelist, not_dot_dotdot, alphasort); | |
219 | + if (count < 0) { | |
220 | + fprintf(stderr, | |
221 | + "Error getting list of all ports of bridge %s\n", | |
222 | + argv[1]); | |
223 | + return -1; | |
224 | + } | |
225 | + } | |
226 | + | |
227 | + for (i = 0; i < count; i++) { | |
228 | + const char *name; | |
229 | + name = namelist[i]->d_name; | |
230 | + | |
231 | + int err = do_dumpbridgeport(br_index, name); | |
232 | + if (err) | |
233 | + r = err; | |
234 | + } | |
235 | + | |
236 | + for (i = 0; i < count; i++) | |
237 | + free(namelist[i]); | |
238 | + free(namelist); | |
239 | + | |
240 | + return r; | |
241 | +} | |
242 | + | |
243 | struct command { | |
244 | int nargs; | |
245 | int optargs; | |
15a94530 | 246 | @@ -483,6 +717,10 @@ static const struct command commands[] = { |
4b3ac7bd MT |
247 | {2, 0, "portmcheck", cmd_portmcheck, |
248 | "<bridge> <port>\ttry to get back from STP to RSTP mode"}, | |
249 | {1, 0, "debuglevel", cmd_debuglevel, "<level>\t\tLevel of verbosity"}, | |
250 | + {0, 32, "dumpbridge", cmd_dumpbridge, | |
251 | + "Dump all information about a bridge in machine parseable format"}, | |
252 | + {1, 0, "dumpports", cmd_dumpbridgeports, | |
253 | + "Dump all port information in machine parseable format"}, | |
254 | }; | |
255 | ||
256 | const struct command *command_lookup(const char *cmd) | |
257 | diff --git a/rstpctl.8 b/rstpctl.8 | |
258 | index ca72eaf..f827c85 100644 | |
259 | --- a/rstpctl.8 | |
260 | +++ b/rstpctl.8 | |
261 | @@ -115,6 +115,13 @@ switch back to RSTP mode. | |
262 | .B rstpctl debuglevel <level> | |
263 | sets the level of verbosity of rstpd's logging. | |
264 | ||
265 | +.B rstpctl dumpbridge [<bridge> ...] | |
266 | +dumps all informational parameters to the console. This is needed to | |
267 | +parse the output in shell scripts for example. | |
268 | + | |
269 | +.B rstpctl dumpports <bridge> [<port> ...] | |
270 | +like dumpbridge but prints information about the ports of a bridge. | |
271 | + | |
272 | .SH NOTES | |
273 | TODO: Indicate lack of persistence of configuration across restarts of | |
274 | daemon. |