]>
Commit | Line | Data |
---|---|---|
f043759d RA |
1 | /* |
2 | * link.c TIPC link functionality. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or | |
5 | * modify it under the terms of the GNU General Public License | |
6 | * as published by the Free Software Foundation; either version | |
7 | * 2 of the License, or (at your option) any later version. | |
8 | * | |
9 | * Authors: Richard Alpe <richard.alpe@ericsson.com> | |
10 | */ | |
11 | ||
12 | #include <stdio.h> | |
13 | #include <stdlib.h> | |
14 | #include <string.h> | |
15 | #include <errno.h> | |
16 | ||
17 | #include <linux/tipc_netlink.h> | |
18 | #include <linux/tipc.h> | |
19 | #include <linux/genetlink.h> | |
20 | #include <libmnl/libmnl.h> | |
21 | ||
22 | #include "cmdl.h" | |
23 | #include "msg.h" | |
24 | #include "link.h" | |
5b748f09 | 25 | #include "bearer.h" |
a56e0db7 HL |
26 | #include "utils.h" |
27 | ||
28 | #define PRIORITY_STR "priority" | |
29 | #define TOLERANCE_STR "tolerance" | |
30 | #define WINDOW_STR "window" | |
0ea46945 HL |
31 | #define BROADCAST_STR "broadcast" |
32 | ||
33 | static const char tipc_bclink_name[] = "broadcast-link"; | |
f043759d RA |
34 | |
35 | static int link_list_cb(const struct nlmsghdr *nlh, void *data) | |
36 | { | |
37 | struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); | |
38 | struct nlattr *info[TIPC_NLA_MAX + 1] = {}; | |
39 | struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1] = {}; | |
40 | ||
41 | mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); | |
42 | if (!info[TIPC_NLA_LINK]) | |
43 | return MNL_CB_ERROR; | |
44 | ||
45 | mnl_attr_parse_nested(info[TIPC_NLA_LINK], parse_attrs, attrs); | |
46 | if (!attrs[TIPC_NLA_LINK_NAME]) | |
47 | return MNL_CB_ERROR; | |
48 | ||
a56e0db7 HL |
49 | print_string(PRINT_FP, NULL, "%s: ", |
50 | mnl_attr_get_str(attrs[TIPC_NLA_LINK_NAME])); | |
f043759d | 51 | if (attrs[TIPC_NLA_LINK_UP]) |
a56e0db7 HL |
52 | print_string(PRINT_ANY, |
53 | mnl_attr_get_str(attrs[TIPC_NLA_LINK_NAME]),"%s\n", "up"); | |
f043759d | 54 | else |
a56e0db7 HL |
55 | print_string(PRINT_ANY, |
56 | mnl_attr_get_str(attrs[TIPC_NLA_LINK_NAME]), "%s\n", "down"); | |
f043759d RA |
57 | return MNL_CB_OK; |
58 | } | |
59 | ||
60 | static int cmd_link_list(struct nlmsghdr *nlh, const struct cmd *cmd, | |
61 | struct cmdl *cmdl, void *data) | |
62 | { | |
63 | char buf[MNL_SOCKET_BUFFER_SIZE]; | |
a56e0db7 | 64 | int err = 0; |
f043759d RA |
65 | |
66 | if (help_flag) { | |
67 | fprintf(stderr, "Usage: %s link list\n", cmdl->argv[0]); | |
68 | return -EINVAL; | |
69 | } | |
70 | ||
f3af3074 SH |
71 | nlh = msg_init(buf, TIPC_NL_LINK_GET); |
72 | if (!nlh) { | |
f043759d RA |
73 | fprintf(stderr, "error, message initialisation failed\n"); |
74 | return -1; | |
75 | } | |
76 | ||
a56e0db7 HL |
77 | new_json_obj(json); |
78 | open_json_object(NULL); | |
79 | err = msg_dumpit(nlh, link_list_cb, NULL); | |
80 | close_json_object(); | |
81 | delete_json_obj(); | |
82 | return err; | |
f043759d RA |
83 | } |
84 | ||
85 | static int link_get_cb(const struct nlmsghdr *nlh, void *data) | |
86 | { | |
87 | int *prop = data; | |
88 | struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); | |
89 | struct nlattr *info[TIPC_NLA_MAX + 1] = {}; | |
90 | struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1] = {}; | |
91 | struct nlattr *props[TIPC_NLA_PROP_MAX + 1] = {}; | |
92 | ||
93 | mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); | |
94 | if (!info[TIPC_NLA_LINK]) | |
95 | return MNL_CB_ERROR; | |
96 | ||
97 | mnl_attr_parse_nested(info[TIPC_NLA_LINK], parse_attrs, attrs); | |
98 | if (!attrs[TIPC_NLA_LINK_PROP]) | |
99 | return MNL_CB_ERROR; | |
100 | ||
101 | mnl_attr_parse_nested(attrs[TIPC_NLA_LINK_PROP], parse_attrs, props); | |
102 | if (!props[*prop]) | |
103 | return MNL_CB_ERROR; | |
104 | ||
a56e0db7 HL |
105 | new_json_obj(json); |
106 | open_json_object(NULL); | |
107 | switch (*prop) { | |
108 | case TIPC_NLA_PROP_PRIO: | |
109 | print_uint(PRINT_ANY, PRIORITY_STR, "%u\n", mnl_attr_get_u32(props[*prop])); | |
110 | break; | |
111 | case TIPC_NLA_PROP_TOL: | |
112 | print_uint(PRINT_ANY, TOLERANCE_STR, "%u\n", mnl_attr_get_u32(props[*prop])); | |
113 | break; | |
114 | case TIPC_NLA_PROP_WIN: | |
115 | print_uint(PRINT_ANY, WINDOW_STR, "%u\n", mnl_attr_get_u32(props[*prop])); | |
116 | break; | |
117 | default: | |
118 | break; | |
119 | } | |
120 | close_json_object(); | |
121 | delete_json_obj(); | |
f043759d RA |
122 | return MNL_CB_OK; |
123 | } | |
124 | ||
f043759d RA |
125 | static int cmd_link_get_prop(struct nlmsghdr *nlh, const struct cmd *cmd, |
126 | struct cmdl *cmdl, void *data) | |
127 | { | |
128 | int prop; | |
129 | char buf[MNL_SOCKET_BUFFER_SIZE]; | |
313ce694 | 130 | struct nlattr *attrs; |
f043759d RA |
131 | struct opt *opt; |
132 | struct opt opts[] = { | |
ed81deab | 133 | { "link", OPT_KEYVAL, NULL }, |
f043759d RA |
134 | { NULL } |
135 | }; | |
136 | ||
a56e0db7 | 137 | if (strcmp(cmd->cmd, PRIORITY_STR) == 0) |
f043759d | 138 | prop = TIPC_NLA_PROP_PRIO; |
a56e0db7 | 139 | else if ((strcmp(cmd->cmd, TOLERANCE_STR) == 0)) |
f043759d | 140 | prop = TIPC_NLA_PROP_TOL; |
a56e0db7 | 141 | else if ((strcmp(cmd->cmd, WINDOW_STR) == 0)) |
f043759d RA |
142 | prop = TIPC_NLA_PROP_WIN; |
143 | else | |
144 | return -EINVAL; | |
145 | ||
146 | if (help_flag) { | |
147 | (cmd->help)(cmdl); | |
148 | return -EINVAL; | |
149 | } | |
150 | ||
151 | if (parse_opts(opts, cmdl) < 0) | |
152 | return -EINVAL; | |
153 | ||
f3af3074 SH |
154 | nlh = msg_init(buf, TIPC_NL_LINK_GET); |
155 | if (!nlh) { | |
f043759d RA |
156 | fprintf(stderr, "error, message initialisation failed\n"); |
157 | return -1; | |
158 | } | |
159 | ||
f3af3074 SH |
160 | opt = get_opt(opts, "link"); |
161 | if (!opt) { | |
f043759d RA |
162 | fprintf(stderr, "error, missing link\n"); |
163 | return -EINVAL; | |
164 | } | |
313ce694 | 165 | attrs = mnl_attr_nest_start(nlh, TIPC_NLA_LINK); |
f043759d | 166 | mnl_attr_put_strz(nlh, TIPC_NLA_LINK_NAME, opt->val); |
313ce694 | 167 | mnl_attr_nest_end(nlh, attrs); |
f043759d RA |
168 | |
169 | return msg_doit(nlh, link_get_cb, &prop); | |
170 | } | |
171 | ||
172 | static void cmd_link_get_help(struct cmdl *cmdl) | |
173 | { | |
174 | fprintf(stderr, "Usage: %s link get PPROPERTY link LINK\n\n" | |
175 | "PROPERTIES\n" | |
176 | " tolerance - Get link tolerance\n" | |
177 | " priority - Get link priority\n" | |
178 | " window - Get link window\n", | |
179 | cmdl->argv[0]); | |
180 | } | |
181 | ||
182 | static int cmd_link_get(struct nlmsghdr *nlh, const struct cmd *cmd, | |
183 | struct cmdl *cmdl, void *data) | |
184 | { | |
185 | const struct cmd cmds[] = { | |
a56e0db7 HL |
186 | { PRIORITY_STR, cmd_link_get_prop, cmd_link_get_help }, |
187 | { TOLERANCE_STR, cmd_link_get_prop, cmd_link_get_help }, | |
188 | { WINDOW_STR, cmd_link_get_prop, cmd_link_get_help }, | |
f043759d RA |
189 | { NULL } |
190 | }; | |
191 | ||
192 | return run_cmd(nlh, cmd, cmds, cmdl, NULL); | |
193 | } | |
194 | ||
195 | static void cmd_link_stat_reset_help(struct cmdl *cmdl) | |
196 | { | |
197 | fprintf(stderr, "Usage: %s link stat reset link LINK\n\n", cmdl->argv[0]); | |
198 | } | |
199 | ||
200 | static int cmd_link_stat_reset(struct nlmsghdr *nlh, const struct cmd *cmd, | |
201 | struct cmdl *cmdl, void *data) | |
202 | { | |
203 | char *link; | |
204 | char buf[MNL_SOCKET_BUFFER_SIZE]; | |
205 | struct opt *opt; | |
206 | struct nlattr *nest; | |
207 | struct opt opts[] = { | |
ed81deab | 208 | { "link", OPT_KEYVAL, NULL }, |
f043759d RA |
209 | { NULL } |
210 | }; | |
211 | ||
212 | if (help_flag) { | |
213 | (cmd->help)(cmdl); | |
214 | return -EINVAL; | |
215 | } | |
216 | ||
217 | if (parse_opts(opts, cmdl) != 1) { | |
218 | (cmd->help)(cmdl); | |
219 | return -EINVAL; | |
220 | } | |
221 | ||
f3af3074 SH |
222 | nlh = msg_init(buf, TIPC_NL_LINK_RESET_STATS); |
223 | if (!nlh) { | |
f043759d RA |
224 | fprintf(stderr, "error, message initialisation failed\n"); |
225 | return -1; | |
226 | } | |
227 | ||
f3af3074 SH |
228 | opt = get_opt(opts, "link"); |
229 | if (!opt) { | |
f043759d RA |
230 | fprintf(stderr, "error, missing link\n"); |
231 | return -EINVAL; | |
232 | } | |
233 | link = opt->val; | |
234 | ||
235 | nest = mnl_attr_nest_start(nlh, TIPC_NLA_LINK); | |
236 | mnl_attr_put_strz(nlh, TIPC_NLA_LINK_NAME, link); | |
237 | mnl_attr_nest_end(nlh, nest); | |
238 | ||
239 | return msg_doit(nlh, NULL, NULL); | |
240 | } | |
241 | ||
242 | static uint32_t perc(uint32_t count, uint32_t total) | |
243 | { | |
244 | return (count * 100 + (total / 2)) / total; | |
245 | } | |
246 | ||
a56e0db7 HL |
247 | static int _show_link_stat(const char *name, struct nlattr *attrs[], |
248 | struct nlattr *prop[], struct nlattr *stats[]) | |
f043759d RA |
249 | { |
250 | uint32_t proft; | |
251 | ||
a56e0db7 HL |
252 | open_json_object(NULL); |
253 | ||
254 | print_string(PRINT_ANY, "link", "\nLink <%s>\n", name); | |
255 | print_string(PRINT_JSON, "state", "", NULL); | |
256 | open_json_array(PRINT_JSON, NULL); | |
f043759d | 257 | if (attrs[TIPC_NLA_LINK_ACTIVE]) |
a56e0db7 | 258 | print_string(PRINT_ANY, NULL, " %s", "ACTIVE"); |
f043759d | 259 | else if (attrs[TIPC_NLA_LINK_UP]) |
a56e0db7 | 260 | print_string(PRINT_ANY, NULL, " %s", "STANDBY"); |
f043759d | 261 | else |
a56e0db7 HL |
262 | print_string(PRINT_ANY, NULL, " %s", "DEFUNCT"); |
263 | close_json_array(PRINT_JSON, NULL); | |
264 | ||
265 | print_uint(PRINT_ANY, "mtu", " MTU:%u", | |
266 | mnl_attr_get_u32(attrs[TIPC_NLA_LINK_MTU])); | |
267 | print_uint(PRINT_ANY, PRIORITY_STR, " Priority:%u", | |
268 | mnl_attr_get_u32(prop[TIPC_NLA_PROP_PRIO])); | |
269 | print_uint(PRINT_ANY, TOLERANCE_STR, " Tolerance:%u ms", | |
270 | mnl_attr_get_u32(prop[TIPC_NLA_PROP_TOL])); | |
271 | print_uint(PRINT_ANY, WINDOW_STR, " Window:%u packets\n", | |
272 | mnl_attr_get_u32(prop[TIPC_NLA_PROP_WIN])); | |
273 | ||
274 | open_json_object("rx packets"); | |
275 | print_uint(PRINT_ANY, "rx packets", " RX packets:%u", | |
276 | mnl_attr_get_u32(attrs[TIPC_NLA_LINK_RX]) - | |
277 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_INFO])); | |
278 | print_uint(PRINT_ANY, "fragments", " fragments:%u", | |
279 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTS])); | |
280 | print_uint(PRINT_ANY, "fragmented", "/%u", | |
281 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTED])); | |
282 | print_uint(PRINT_ANY, "bundles", " bundles:%u", | |
283 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLES])); | |
284 | print_uint(PRINT_ANY, "bundled", "/%u\n", | |
285 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLED])); | |
286 | close_json_object(); | |
287 | ||
288 | open_json_object("tx packets"); | |
289 | print_uint(PRINT_ANY, "tx packets", " TX packets:%u", | |
290 | mnl_attr_get_u32(attrs[TIPC_NLA_LINK_TX]) - | |
291 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_INFO])); | |
292 | print_uint(PRINT_ANY, "fragments", " fragments:%u", | |
293 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTS])); | |
294 | print_uint(PRINT_ANY, "fragmented", "/%u", | |
295 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTED])); | |
296 | print_uint(PRINT_ANY, "bundles", " bundles:%u", | |
297 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLES])); | |
298 | print_uint(PRINT_ANY, "bundled", "/%u\n", | |
299 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLED])); | |
300 | close_json_object(); | |
f043759d RA |
301 | |
302 | proft = mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT]); | |
a56e0db7 HL |
303 | print_uint(PRINT_ANY, "tx profile sample", " TX profile sample:%u", |
304 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_CNT])); | |
305 | print_uint(PRINT_ANY, "packets average", " packets average:%u octets\n", | |
306 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_TOT]) / proft); | |
307 | ||
308 | print_uint(PRINT_ANY, "0-64", " 0-64:%u%%", | |
309 | perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P0]), proft)); | |
310 | print_uint(PRINT_ANY, "-256", " -256:%u%%", | |
311 | perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P1]), proft)); | |
312 | print_uint(PRINT_ANY, "-1024", " -1024:%u%%", | |
313 | perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P2]), proft)); | |
314 | print_uint(PRINT_ANY, "-4096", " -4096:%u%%", | |
315 | perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P3]), proft)); | |
316 | print_uint(PRINT_ANY, "-16384", " -16384:%u%%", | |
317 | perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P4]), proft)); | |
318 | print_uint(PRINT_ANY, "-32768", " -32768:%u%%", | |
319 | perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P5]), proft)); | |
320 | print_uint(PRINT_ANY, "-66000", " -66000:%u%%\n", | |
321 | perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P6]), proft)); | |
322 | ||
323 | open_json_object("rx states"); | |
324 | print_uint(PRINT_ANY, "rx states", " RX states:%u", | |
325 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_STATES])); | |
326 | print_uint(PRINT_ANY, "probes", " probes:%u", | |
327 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_PROBES])); | |
328 | print_uint(PRINT_ANY, "naks", " naks:%u", | |
329 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_NACKS])); | |
330 | print_uint(PRINT_ANY, "defs", " defs:%u", | |
331 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_DEFERRED])); | |
332 | print_uint(PRINT_ANY, "dups", " dups:%u\n", | |
333 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_DUPLICATES])); | |
334 | close_json_object(); | |
335 | ||
336 | open_json_object("tx states"); | |
337 | print_uint(PRINT_ANY, "tx states", " TX states:%u", | |
338 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_STATES])); | |
339 | print_uint(PRINT_ANY, "probes", " probes:%u", | |
340 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_PROBES])); | |
341 | print_uint(PRINT_ANY, "naks", " naks:%u", | |
342 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_NACKS])); | |
343 | print_uint(PRINT_ANY, "acks", " acks:%u", | |
344 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_ACKS])); | |
345 | print_uint(PRINT_ANY, "retrans", " retrans:%u\n", | |
346 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_RETRANSMITTED])); | |
347 | close_json_object(); | |
348 | ||
349 | print_uint(PRINT_ANY, "congestion link", " Congestion link:%u", | |
350 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_LINK_CONGS])); | |
351 | print_uint(PRINT_ANY, "send queue max", " Send queue max:%u", | |
352 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_MAX_QUEUE])); | |
353 | print_uint(PRINT_ANY, "avg", " avg:%u\n", | |
354 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_AVG_QUEUE])); | |
355 | ||
356 | close_json_object(); | |
f043759d RA |
357 | return MNL_CB_OK; |
358 | } | |
359 | ||
a56e0db7 HL |
360 | static int _show_bc_link_stat(const char *name, struct nlattr *prop[], |
361 | struct nlattr *stats[]) | |
f043759d | 362 | { |
a56e0db7 HL |
363 | open_json_object(NULL); |
364 | print_string(PRINT_ANY, "link", "Link <%s>\n", name); | |
365 | print_uint(PRINT_ANY, WINDOW_STR, " Window:%u packets\n", | |
366 | mnl_attr_get_u32(prop[TIPC_NLA_PROP_WIN])); | |
367 | ||
368 | open_json_object("rx packets"); | |
369 | print_uint(PRINT_ANY, "rx packets", " RX packets:%u", | |
370 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_INFO])); | |
371 | print_uint(PRINT_ANY, "fragments", " fragments:%u", | |
372 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTS])); | |
373 | print_uint(PRINT_ANY, "fragmented", "/%u", | |
374 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTED])); | |
375 | print_uint(PRINT_ANY, "bundles", " bundles:%u", | |
376 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLES])); | |
377 | print_uint(PRINT_ANY, "bundled", "/%u\n", | |
378 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLED])); | |
379 | close_json_object(); | |
380 | ||
381 | open_json_object("tx packets"); | |
382 | print_uint(PRINT_ANY, "tx packets", " TX packets:%u", | |
383 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_INFO])); | |
384 | print_uint(PRINT_ANY, "fragments", " fragments:%u", | |
385 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTS])); | |
386 | print_uint(PRINT_ANY, "fragmented", "/%u", | |
387 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTED])); | |
388 | print_uint(PRINT_ANY, "bundles", " bundles:%u", | |
389 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLES])); | |
390 | print_uint(PRINT_ANY, "bundled", "/%u\n", | |
391 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLED])); | |
392 | close_json_object(); | |
393 | ||
394 | open_json_object("rx naks"); | |
395 | print_uint(PRINT_ANY, "rx naks", " RX naks:%u", | |
396 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_NACKS])); | |
397 | print_uint(PRINT_ANY, "defs", " defs:%u", | |
398 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_DEFERRED])); | |
399 | print_uint(PRINT_ANY, "dups", " dups:%u\n", | |
400 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_DUPLICATES])); | |
401 | close_json_object(); | |
402 | ||
403 | open_json_object("tx naks"); | |
404 | print_uint(PRINT_ANY, "tx naks", " TX naks:%u", | |
405 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_NACKS])); | |
406 | print_uint(PRINT_ANY, "acks", " acks:%u", | |
407 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_ACKS])); | |
408 | print_uint(PRINT_ANY, "retrans", " retrans:%u\n", | |
409 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_RETRANSMITTED])); | |
410 | close_json_object(); | |
411 | ||
412 | print_uint(PRINT_ANY, "congestion link", " Congestion link:%u", | |
413 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_LINK_CONGS])); | |
414 | print_uint(PRINT_ANY, "send queue max", " Send queue max:%u", | |
415 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_MAX_QUEUE])); | |
416 | print_uint(PRINT_ANY, "avg", " avg:%u\n", | |
417 | mnl_attr_get_u32(stats[TIPC_NLA_STATS_AVG_QUEUE])); | |
418 | close_json_object(); | |
f043759d RA |
419 | |
420 | return MNL_CB_OK; | |
421 | } | |
422 | ||
423 | static int link_stat_show_cb(const struct nlmsghdr *nlh, void *data) | |
424 | { | |
425 | const char *name; | |
426 | const char *link = data; | |
427 | struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); | |
428 | struct nlattr *info[TIPC_NLA_MAX + 1] = {}; | |
429 | struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1] = {}; | |
430 | struct nlattr *prop[TIPC_NLA_PROP_MAX + 1] = {}; | |
431 | struct nlattr *stats[TIPC_NLA_STATS_MAX + 1] = {}; | |
432 | ||
433 | mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); | |
434 | if (!info[TIPC_NLA_LINK]) | |
435 | return MNL_CB_ERROR; | |
436 | ||
437 | mnl_attr_parse_nested(info[TIPC_NLA_LINK], parse_attrs, attrs); | |
438 | if (!attrs[TIPC_NLA_LINK_NAME] || !attrs[TIPC_NLA_LINK_PROP] || | |
439 | !attrs[TIPC_NLA_LINK_STATS]) | |
440 | return MNL_CB_ERROR; | |
441 | ||
442 | mnl_attr_parse_nested(attrs[TIPC_NLA_LINK_PROP], parse_attrs, prop); | |
443 | mnl_attr_parse_nested(attrs[TIPC_NLA_LINK_STATS], parse_attrs, stats); | |
444 | ||
445 | name = mnl_attr_get_str(attrs[TIPC_NLA_LINK_NAME]); | |
446 | ||
447 | /* If a link is passed, skip all but that link */ | |
448 | if (link && (strcmp(name, link) != 0)) | |
449 | return MNL_CB_OK; | |
450 | ||
451 | if (attrs[TIPC_NLA_LINK_BROADCAST]) { | |
a56e0db7 | 452 | return _show_bc_link_stat(name, prop, stats); |
f043759d RA |
453 | } |
454 | ||
a56e0db7 | 455 | return _show_link_stat(name, attrs, prop, stats); |
f043759d RA |
456 | } |
457 | ||
458 | static void cmd_link_stat_show_help(struct cmdl *cmdl) | |
459 | { | |
460 | fprintf(stderr, "Usage: %s link stat show [ link LINK ]\n", | |
461 | cmdl->argv[0]); | |
462 | } | |
463 | ||
464 | static int cmd_link_stat_show(struct nlmsghdr *nlh, const struct cmd *cmd, | |
465 | struct cmdl *cmdl, void *data) | |
466 | { | |
467 | char *link = NULL; | |
468 | char buf[MNL_SOCKET_BUFFER_SIZE]; | |
469 | struct opt *opt; | |
470 | struct opt opts[] = { | |
ed81deab | 471 | { "link", OPT_KEYVAL, NULL }, |
f043759d RA |
472 | { NULL } |
473 | }; | |
a56e0db7 | 474 | int err = 0; |
f043759d RA |
475 | |
476 | if (help_flag) { | |
477 | (cmd->help)(cmdl); | |
478 | return -EINVAL; | |
479 | } | |
480 | ||
f3af3074 SH |
481 | nlh = msg_init(buf, TIPC_NL_LINK_GET); |
482 | if (!nlh) { | |
f043759d RA |
483 | fprintf(stderr, "error, message initialisation failed\n"); |
484 | return -1; | |
485 | } | |
486 | ||
487 | if (parse_opts(opts, cmdl) < 0) | |
488 | return -EINVAL; | |
489 | ||
f3af3074 SH |
490 | opt = get_opt(opts, "link"); |
491 | if (opt) | |
f043759d RA |
492 | link = opt->val; |
493 | ||
a56e0db7 HL |
494 | new_json_obj(json); |
495 | err = msg_dumpit(nlh, link_stat_show_cb, link); | |
496 | delete_json_obj(); | |
497 | return err; | |
f043759d RA |
498 | } |
499 | ||
500 | static void cmd_link_stat_help(struct cmdl *cmdl) | |
501 | { | |
502 | fprintf(stderr, "Usage: %s link stat COMMAND [ARGS]\n\n" | |
503 | "COMMANDS:\n" | |
504 | " reset - Reset link statistics for link\n" | |
505 | " show - Get link priority\n", | |
506 | cmdl->argv[0]); | |
507 | } | |
508 | ||
509 | static int cmd_link_stat(struct nlmsghdr *nlh, const struct cmd *cmd, | |
510 | struct cmdl *cmdl, void *data) | |
511 | { | |
512 | const struct cmd cmds[] = { | |
513 | { "reset", cmd_link_stat_reset, cmd_link_stat_reset_help }, | |
514 | { "show", cmd_link_stat_show, cmd_link_stat_show_help }, | |
515 | { NULL } | |
516 | }; | |
517 | ||
518 | return run_cmd(nlh, cmd, cmds, cmdl, NULL); | |
519 | } | |
520 | ||
521 | static void cmd_link_set_help(struct cmdl *cmdl) | |
522 | { | |
523 | fprintf(stderr, "Usage: %s link set PPROPERTY link LINK\n\n" | |
524 | "PROPERTIES\n" | |
525 | " tolerance TOLERANCE - Set link tolerance\n" | |
526 | " priority PRIORITY - Set link priority\n" | |
0ea46945 HL |
527 | " window WINDOW - Set link window\n" |
528 | " broadcast BROADCAST - Set link broadcast\n", | |
f043759d RA |
529 | cmdl->argv[0]); |
530 | } | |
531 | ||
532 | static int cmd_link_set_prop(struct nlmsghdr *nlh, const struct cmd *cmd, | |
533 | struct cmdl *cmdl, void *data) | |
534 | { | |
535 | int val; | |
536 | int prop; | |
537 | char buf[MNL_SOCKET_BUFFER_SIZE]; | |
538 | struct nlattr *props; | |
539 | struct nlattr *attrs; | |
540 | struct opt *opt; | |
541 | struct opt opts[] = { | |
ed81deab | 542 | { "link", OPT_KEYVAL, NULL }, |
f043759d RA |
543 | { NULL } |
544 | }; | |
545 | ||
a56e0db7 | 546 | if (strcmp(cmd->cmd, PRIORITY_STR) == 0) |
f043759d | 547 | prop = TIPC_NLA_PROP_PRIO; |
a56e0db7 | 548 | else if ((strcmp(cmd->cmd, TOLERANCE_STR) == 0)) |
f043759d | 549 | prop = TIPC_NLA_PROP_TOL; |
a56e0db7 | 550 | else if ((strcmp(cmd->cmd, WINDOW_STR) == 0)) |
f043759d RA |
551 | prop = TIPC_NLA_PROP_WIN; |
552 | else | |
553 | return -EINVAL; | |
554 | ||
555 | if (help_flag) { | |
556 | (cmd->help)(cmdl); | |
557 | return -EINVAL; | |
558 | } | |
559 | ||
560 | if (cmdl->optind >= cmdl->argc) { | |
561 | fprintf(stderr, "error, missing value\n"); | |
562 | return -EINVAL; | |
563 | } | |
564 | val = atoi(shift_cmdl(cmdl)); | |
565 | ||
566 | if (parse_opts(opts, cmdl) < 0) | |
567 | return -EINVAL; | |
568 | ||
f3af3074 SH |
569 | nlh = msg_init(buf, TIPC_NL_LINK_SET); |
570 | if (!nlh) { | |
f043759d RA |
571 | fprintf(stderr, "error, message initialisation failed\n"); |
572 | return -1; | |
573 | } | |
574 | attrs = mnl_attr_nest_start(nlh, TIPC_NLA_LINK); | |
575 | ||
f3af3074 SH |
576 | opt = get_opt(opts, "link"); |
577 | if (!opt) { | |
f043759d RA |
578 | fprintf(stderr, "error, missing link\n"); |
579 | return -EINVAL; | |
580 | } | |
581 | mnl_attr_put_strz(nlh, TIPC_NLA_LINK_NAME, opt->val); | |
582 | ||
583 | props = mnl_attr_nest_start(nlh, TIPC_NLA_LINK_PROP); | |
584 | mnl_attr_put_u32(nlh, prop, val); | |
585 | mnl_attr_nest_end(nlh, props); | |
586 | ||
587 | mnl_attr_nest_end(nlh, attrs); | |
588 | ||
589 | return msg_doit(nlh, link_get_cb, &prop); | |
f043759d RA |
590 | } |
591 | ||
0ea46945 HL |
592 | static void cmd_link_set_bcast_help(struct cmdl *cmdl) |
593 | { | |
594 | fprintf(stderr, "Usage: %s link set broadcast PROPERTY\n\n" | |
595 | "PROPERTIES\n" | |
596 | " BROADCAST - Forces all multicast traffic to be\n" | |
597 | " transmitted via broadcast only,\n" | |
598 | " irrespective of cluster size and number\n" | |
599 | " of destinations\n\n" | |
600 | " REPLICAST - Forces all multicast traffic to be\n" | |
601 | " transmitted via replicast only,\n" | |
602 | " irrespective of cluster size and number\n" | |
603 | " of destinations\n\n" | |
604 | " AUTOSELECT - Auto switching to broadcast or replicast\n" | |
605 | " depending on cluster size and destination\n" | |
606 | " node number\n\n" | |
607 | " ratio SIZE - Set the AUTOSELECT criteria, percentage of\n" | |
608 | " destination nodes vs cluster size\n\n", | |
609 | cmdl->argv[0]); | |
610 | } | |
611 | ||
612 | static int cmd_link_set_bcast(struct nlmsghdr *nlh, const struct cmd *cmd, | |
613 | struct cmdl *cmdl, void *data) | |
614 | { | |
615 | char buf[MNL_SOCKET_BUFFER_SIZE]; | |
616 | struct nlattr *props; | |
617 | struct nlattr *attrs; | |
618 | struct opt *opt; | |
619 | struct opt opts[] = { | |
620 | { "BROADCAST", OPT_KEY, NULL }, | |
621 | { "REPLICAST", OPT_KEY, NULL }, | |
622 | { "AUTOSELECT", OPT_KEY, NULL }, | |
623 | { "ratio", OPT_KEYVAL, NULL }, | |
624 | { NULL } | |
625 | }; | |
626 | int method = 0; | |
627 | ||
628 | if (help_flag) { | |
629 | (cmd->help)(cmdl); | |
630 | return -EINVAL; | |
631 | } | |
632 | ||
633 | if (parse_opts(opts, cmdl) < 0) | |
634 | return -EINVAL; | |
635 | ||
636 | for (opt = opts; opt->key; opt++) | |
637 | if (opt->val) | |
638 | break; | |
639 | ||
640 | if (!opt || !opt->key) { | |
641 | (cmd->help)(cmdl); | |
642 | return -EINVAL; | |
643 | } | |
644 | ||
645 | nlh = msg_init(buf, TIPC_NL_LINK_SET); | |
646 | if (!nlh) { | |
647 | fprintf(stderr, "error, message initialisation failed\n"); | |
648 | return -1; | |
649 | } | |
650 | ||
651 | attrs = mnl_attr_nest_start(nlh, TIPC_NLA_LINK); | |
652 | /* Direct to broadcast-link setting */ | |
653 | mnl_attr_put_strz(nlh, TIPC_NLA_LINK_NAME, tipc_bclink_name); | |
654 | props = mnl_attr_nest_start(nlh, TIPC_NLA_LINK_PROP); | |
655 | ||
656 | if (get_opt(opts, "BROADCAST")) | |
657 | method = 0x1; | |
658 | else if (get_opt(opts, "REPLICAST")) | |
659 | method = 0x2; | |
660 | else if (get_opt(opts, "AUTOSELECT")) | |
661 | method = 0x4; | |
662 | ||
663 | opt = get_opt(opts, "ratio"); | |
664 | if (!method && !opt) { | |
665 | (cmd->help)(cmdl); | |
666 | return -EINVAL; | |
667 | } | |
668 | ||
669 | if (method) | |
670 | mnl_attr_put_u32(nlh, TIPC_NLA_PROP_BROADCAST, method); | |
671 | ||
672 | if (opt) | |
673 | mnl_attr_put_u32(nlh, TIPC_NLA_PROP_BROADCAST_RATIO, | |
674 | atoi(opt->val)); | |
675 | ||
676 | mnl_attr_nest_end(nlh, props); | |
677 | mnl_attr_nest_end(nlh, attrs); | |
678 | return msg_doit(nlh, NULL, NULL); | |
679 | } | |
680 | ||
f043759d RA |
681 | static int cmd_link_set(struct nlmsghdr *nlh, const struct cmd *cmd, |
682 | struct cmdl *cmdl, void *data) | |
683 | { | |
684 | const struct cmd cmds[] = { | |
a56e0db7 HL |
685 | { PRIORITY_STR, cmd_link_set_prop, cmd_link_set_help }, |
686 | { TOLERANCE_STR, cmd_link_set_prop, cmd_link_set_help }, | |
687 | { WINDOW_STR, cmd_link_set_prop, cmd_link_set_help }, | |
0ea46945 | 688 | { BROADCAST_STR, cmd_link_set_bcast, cmd_link_set_bcast_help }, |
f043759d RA |
689 | { NULL } |
690 | }; | |
691 | ||
692 | return run_cmd(nlh, cmd, cmds, cmdl, NULL); | |
693 | } | |
694 | ||
b33a6900 PB |
695 | static int cmd_link_mon_set_prop(struct nlmsghdr *nlh, const struct cmd *cmd, |
696 | struct cmdl *cmdl, void *data) | |
697 | { | |
698 | int size; | |
699 | char buf[MNL_SOCKET_BUFFER_SIZE]; | |
700 | struct nlattr *attrs; | |
701 | ||
702 | if (cmdl->argc != cmdl->optind + 1) { | |
703 | fprintf(stderr, "error, missing value\n"); | |
704 | return -EINVAL; | |
705 | } | |
706 | size = atoi(shift_cmdl(cmdl)); | |
707 | ||
f3af3074 SH |
708 | nlh = msg_init(buf, TIPC_NL_MON_SET); |
709 | if (!nlh) { | |
b33a6900 PB |
710 | fprintf(stderr, "error, message initialisation failed\n"); |
711 | return -1; | |
712 | } | |
713 | attrs = mnl_attr_nest_start(nlh, TIPC_NLA_MON); | |
714 | ||
715 | mnl_attr_put_u32(nlh, TIPC_NLA_MON_ACTIVATION_THRESHOLD, size); | |
716 | ||
717 | mnl_attr_nest_end(nlh, attrs); | |
718 | ||
719 | return msg_doit(nlh, NULL, NULL); | |
720 | } | |
721 | ||
80e9807d PB |
722 | static int link_mon_summary_cb(const struct nlmsghdr *nlh, void *data) |
723 | { | |
724 | struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); | |
725 | struct nlattr *info[TIPC_NLA_MAX + 1] = {}; | |
726 | struct nlattr *attrs[TIPC_NLA_MON_MAX + 1] = {}; | |
727 | ||
728 | mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); | |
729 | if (!info[TIPC_NLA_MON]) | |
730 | return MNL_CB_ERROR; | |
731 | ||
732 | mnl_attr_parse_nested(info[TIPC_NLA_MON], parse_attrs, attrs); | |
733 | ||
a56e0db7 HL |
734 | open_json_object(NULL); |
735 | print_string(PRINT_ANY, "bearer", "\nbearer %s\n", | |
80e9807d PB |
736 | mnl_attr_get_str(attrs[TIPC_NLA_MON_BEARER_NAME])); |
737 | ||
a56e0db7 | 738 | print_uint(PRINT_ANY, "table_generation", " table_generation %u\n", |
80e9807d | 739 | mnl_attr_get_u32(attrs[TIPC_NLA_MON_LISTGEN])); |
a56e0db7 | 740 | print_uint(PRINT_ANY, "cluster_size", " cluster_size %u\n", |
80e9807d | 741 | mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEERCNT])); |
a56e0db7 | 742 | print_string(PRINT_ANY, "algorithm", " algorithm %s\n", |
80e9807d | 743 | attrs[TIPC_NLA_MON_ACTIVE] ? "overlapping-ring" : "full-mesh"); |
a56e0db7 | 744 | close_json_object(); |
80e9807d PB |
745 | |
746 | return MNL_CB_OK; | |
747 | } | |
748 | ||
749 | static int cmd_link_mon_summary(struct nlmsghdr *nlh, const struct cmd *cmd, | |
750 | struct cmdl *cmdl, void *data) | |
751 | { | |
752 | char buf[MNL_SOCKET_BUFFER_SIZE]; | |
a56e0db7 | 753 | int err = 0; |
80e9807d PB |
754 | |
755 | if (help_flag) { | |
756 | fprintf(stderr, "Usage: %s monitor summary\n", cmdl->argv[0]); | |
757 | return -EINVAL; | |
758 | } | |
759 | ||
f3af3074 SH |
760 | nlh = msg_init(buf, TIPC_NL_MON_GET); |
761 | if (!nlh) { | |
80e9807d PB |
762 | fprintf(stderr, "error, message initialisation failed\n"); |
763 | return -1; | |
764 | } | |
765 | ||
a56e0db7 HL |
766 | new_json_obj(json); |
767 | err = msg_dumpit(nlh, link_mon_summary_cb, NULL); | |
768 | delete_json_obj(); | |
769 | ||
770 | return err; | |
80e9807d PB |
771 | } |
772 | ||
5b748f09 PB |
773 | #define STATUS_WIDTH 7 |
774 | #define MAX_NODE_WIDTH 14 /* 255.4095.4095 */ | |
775 | #define MAX_DOM_GEN_WIDTH 11 /* 65535 */ | |
776 | #define DIRECTLY_MON_WIDTH 10 | |
777 | ||
778 | #define APPL_NODE_STATUS_WIDTH 5 | |
779 | ||
780 | static int map_get(uint64_t up_map, int i) | |
781 | { | |
782 | return (up_map & (1 << i)) >> i; | |
783 | } | |
784 | ||
785 | /* print the applied members, since we know the the members | |
f3af3074 SH |
786 | * are listed in ascending order, we print only the state |
787 | */ | |
5b748f09 PB |
788 | static void link_mon_print_applied(uint16_t applied, uint64_t up_map) |
789 | { | |
790 | int i; | |
5b748f09 | 791 | |
a56e0db7 | 792 | open_json_array(PRINT_JSON, "applied_node_status"); |
5b748f09 | 793 | for (i = 0; i < applied; i++) { |
a56e0db7 HL |
794 | char state_str[2] = {0}; |
795 | ||
5b748f09 PB |
796 | /* print the delimiter for every -n- entry */ |
797 | if (i && !(i % APPL_NODE_STATUS_WIDTH)) | |
a56e0db7 | 798 | print_string(PRINT_FP, NULL, "%s", ","); |
5b748f09 | 799 | |
a56e0db7 HL |
800 | sprintf(state_str, "%c", map_get(up_map, i) ? 'U' : 'D'); |
801 | print_string(PRINT_ANY, NULL, "%s", state_str); | |
5b748f09 | 802 | } |
a56e0db7 | 803 | close_json_array(PRINT_JSON, "applied_node_status"); |
5b748f09 PB |
804 | } |
805 | ||
c60683e2 | 806 | /* print the non applied members, since we don't know |
f3af3074 SH |
807 | * the members, we print them along with the state |
808 | */ | |
5b748f09 PB |
809 | static void link_mon_print_non_applied(uint16_t applied, uint16_t member_cnt, |
810 | uint64_t up_map, uint32_t *members) | |
811 | { | |
812 | int i; | |
813 | char state; | |
814 | ||
a56e0db7 HL |
815 | open_json_array(PRINT_JSON, "[non_applied_node:status]"); |
816 | print_string(PRINT_FP, NULL, " %s", "["); | |
5b748f09 PB |
817 | for (i = applied; i < member_cnt; i++) { |
818 | char addr_str[16]; | |
a56e0db7 | 819 | char full_state[17] = {0}; |
5b748f09 PB |
820 | |
821 | /* print the delimiter for every entry */ | |
822 | if (i != applied) | |
a56e0db7 | 823 | print_string(PRINT_FP, NULL, "%s", ","); |
5b748f09 | 824 | |
5aad0baa | 825 | sprintf(addr_str, "%x:", members[i]); |
5b748f09 | 826 | state = map_get(up_map, i) ? 'U' : 'D'; |
a56e0db7 HL |
827 | sprintf(full_state, "%s%c", addr_str, state); |
828 | print_string(PRINT_ANY, NULL, "%s", full_state); | |
5b748f09 | 829 | } |
a56e0db7 HL |
830 | print_string(PRINT_FP, NULL, "%s", "]"); |
831 | close_json_array(PRINT_JSON, "[non_applied_node:status]"); | |
5b748f09 PB |
832 | } |
833 | ||
834 | static void link_mon_print_peer_state(const uint32_t addr, const char *status, | |
835 | const char *monitored, | |
836 | const uint32_t dom_gen) | |
837 | { | |
838 | char addr_str[16]; | |
839 | ||
840 | sprintf(addr_str, "%u.%u.%u", tipc_zone(addr), tipc_cluster(addr), | |
841 | tipc_node(addr)); | |
a56e0db7 HL |
842 | if (is_json_context()) { |
843 | print_string(PRINT_JSON, "node", NULL, addr_str); | |
844 | print_string(PRINT_JSON, "status", NULL, status); | |
845 | print_string(PRINT_JSON, "monitored", NULL, monitored); | |
846 | print_uint(PRINT_JSON, "generation", NULL, dom_gen); | |
847 | } else { | |
848 | printf("%-*s", MAX_NODE_WIDTH, addr_str); | |
849 | printf("%-*s", STATUS_WIDTH, status); | |
850 | printf("%-*s", DIRECTLY_MON_WIDTH, monitored); | |
851 | printf("%-*u", MAX_DOM_GEN_WIDTH, dom_gen); | |
852 | } | |
5b748f09 PB |
853 | } |
854 | ||
855 | static int link_mon_peer_list_cb(const struct nlmsghdr *nlh, void *data) | |
856 | { | |
857 | struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); | |
858 | struct nlattr *attrs[TIPC_NLA_MON_PEER_MAX + 1] = {}; | |
859 | struct nlattr *info[TIPC_NLA_MAX + 1] = {}; | |
860 | uint16_t member_cnt; | |
861 | uint32_t applied; | |
862 | uint32_t dom_gen; | |
863 | uint64_t up_map; | |
864 | char status[16]; | |
865 | char monitored[16]; | |
866 | ||
867 | mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); | |
868 | if (!info[TIPC_NLA_MON_PEER]) | |
869 | return MNL_CB_ERROR; | |
870 | ||
a56e0db7 | 871 | open_json_object(NULL); |
5b748f09 PB |
872 | mnl_attr_parse_nested(info[TIPC_NLA_MON_PEER], parse_attrs, attrs); |
873 | ||
874 | (attrs[TIPC_NLA_MON_PEER_LOCAL] || attrs[TIPC_NLA_MON_PEER_HEAD]) ? | |
875 | strcpy(monitored, "direct") : | |
876 | strcpy(monitored, "indirect"); | |
877 | ||
878 | attrs[TIPC_NLA_MON_PEER_UP] ? | |
879 | strcpy(status, "up") : | |
880 | strcpy(status, "down"); | |
881 | ||
882 | dom_gen = attrs[TIPC_NLA_MON_PEER_DOMGEN] ? | |
883 | mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEER_DOMGEN]) : 0; | |
884 | ||
885 | link_mon_print_peer_state(mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEER_ADDR]), | |
886 | status, monitored, dom_gen); | |
887 | ||
888 | applied = mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEER_APPLIED]); | |
889 | ||
890 | if (!applied) | |
891 | goto exit; | |
892 | ||
893 | up_map = mnl_attr_get_u64(attrs[TIPC_NLA_MON_PEER_UPMAP]); | |
894 | ||
895 | member_cnt = mnl_attr_get_payload_len(attrs[TIPC_NLA_MON_PEER_MEMBERS]); | |
896 | ||
897 | /* each tipc address occupies 4 bytes of payload, hence compensate it */ | |
898 | member_cnt /= sizeof(uint32_t); | |
899 | ||
900 | link_mon_print_applied(applied, up_map); | |
901 | ||
902 | link_mon_print_non_applied(applied, member_cnt, up_map, | |
903 | mnl_attr_get_payload(attrs[TIPC_NLA_MON_PEER_MEMBERS])); | |
904 | ||
905 | exit: | |
a56e0db7 | 906 | print_string(PRINT_FP, NULL, "\n", ""); |
5b748f09 | 907 | |
a56e0db7 | 908 | close_json_object(); |
5b748f09 PB |
909 | return MNL_CB_OK; |
910 | } | |
911 | ||
912 | static int link_mon_peer_list(uint32_t mon_ref) | |
913 | { | |
914 | struct nlmsghdr *nlh; | |
915 | char buf[MNL_SOCKET_BUFFER_SIZE]; | |
916 | struct nlattr *nest; | |
a56e0db7 | 917 | int err = 0; |
5b748f09 | 918 | |
f3af3074 SH |
919 | nlh = msg_init(buf, TIPC_NL_MON_PEER_GET); |
920 | if (!nlh) { | |
5b748f09 PB |
921 | fprintf(stderr, "error, message initialisation failed\n"); |
922 | return -1; | |
923 | } | |
924 | ||
925 | nest = mnl_attr_nest_start(nlh, TIPC_NLA_MON); | |
926 | mnl_attr_put_u32(nlh, TIPC_NLA_MON_REF, mon_ref); | |
927 | mnl_attr_nest_end(nlh, nest); | |
928 | ||
a56e0db7 HL |
929 | err = msg_dumpit(nlh, link_mon_peer_list_cb, NULL); |
930 | return err; | |
5b748f09 PB |
931 | } |
932 | ||
933 | static int link_mon_list_cb(const struct nlmsghdr *nlh, void *data) | |
934 | { | |
935 | struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); | |
936 | struct nlattr *info[TIPC_NLA_MAX + 1] = {}; | |
937 | struct nlattr *attrs[TIPC_NLA_MON_MAX + 1] = {}; | |
938 | char *req_bearer = data; | |
939 | const char *bname; | |
f3af3074 SH |
940 | const char title[] = |
941 | "node status monitored generation applied_node_status [non_applied_node:status]"; | |
5b748f09 PB |
942 | |
943 | mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); | |
944 | if (!info[TIPC_NLA_MON]) | |
945 | return MNL_CB_ERROR; | |
946 | ||
947 | mnl_attr_parse_nested(info[TIPC_NLA_MON], parse_attrs, attrs); | |
948 | ||
949 | bname = mnl_attr_get_str(attrs[TIPC_NLA_MON_BEARER_NAME]); | |
950 | ||
951 | if (*req_bearer && (strcmp(req_bearer, bname) != 0)) | |
952 | return MNL_CB_OK; | |
953 | ||
a56e0db7 HL |
954 | open_json_object(NULL); |
955 | print_string(PRINT_ANY, "bearer", "\nbearer %s\n", bname); | |
956 | print_string(PRINT_FP, NULL, "%s\n", title); | |
5b748f09 | 957 | |
a56e0db7 | 958 | open_json_array(PRINT_JSON, bname); |
5b748f09 PB |
959 | if (mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEERCNT])) |
960 | link_mon_peer_list(mnl_attr_get_u32(attrs[TIPC_NLA_MON_REF])); | |
a56e0db7 | 961 | close_json_array(PRINT_JSON, bname); |
5b748f09 | 962 | |
a56e0db7 | 963 | close_json_object(); |
5b748f09 PB |
964 | return MNL_CB_OK; |
965 | } | |
966 | ||
967 | static void cmd_link_mon_list_help(struct cmdl *cmdl) | |
968 | { | |
f3af3074 | 969 | fprintf(stderr, "Usage: %s monitor list [ media MEDIA ARGS...]\n\n", |
5b748f09 PB |
970 | cmdl->argv[0]); |
971 | print_bearer_media(); | |
972 | } | |
973 | ||
974 | static void cmd_link_mon_list_l2_help(struct cmdl *cmdl, char *media) | |
975 | { | |
976 | fprintf(stderr, | |
977 | "Usage: %s monitor list media %s device DEVICE [OPTIONS]\n", | |
978 | cmdl->argv[0], media); | |
979 | } | |
980 | ||
981 | static void cmd_link_mon_list_udp_help(struct cmdl *cmdl, char *media) | |
982 | { | |
983 | fprintf(stderr, | |
f3af3074 | 984 | "Usage: %s monitor list media udp name NAME\n\n", |
5b748f09 PB |
985 | cmdl->argv[0]); |
986 | } | |
987 | ||
988 | static int cmd_link_mon_list(struct nlmsghdr *nlh, const struct cmd *cmd, | |
989 | struct cmdl *cmdl, void *data) | |
990 | { | |
991 | char buf[MNL_SOCKET_BUFFER_SIZE]; | |
992 | char bname[TIPC_MAX_BEARER_NAME] = {0}; | |
993 | struct opt opts[] = { | |
994 | { "media", OPT_KEYVAL, NULL }, | |
995 | { "device", OPT_KEYVAL, NULL }, | |
996 | { "name", OPT_KEYVAL, NULL }, | |
997 | { NULL } | |
998 | }; | |
999 | struct tipc_sup_media sup_media[] = { | |
1000 | { "udp", "name", cmd_link_mon_list_udp_help}, | |
1001 | { "eth", "device", cmd_link_mon_list_l2_help }, | |
1002 | { "ib", "device", cmd_link_mon_list_l2_help }, | |
1003 | { NULL, }, | |
1004 | }; | |
1005 | ||
1006 | int err; | |
1007 | ||
1008 | if (parse_opts(opts, cmdl) < 0) | |
1009 | return -EINVAL; | |
1010 | ||
1011 | if (get_opt(opts, "media")) { | |
f3af3074 SH |
1012 | err = cmd_get_unique_bearer_name(cmd, cmdl, opts, bname, |
1013 | sup_media); | |
1014 | if (err) | |
5b748f09 PB |
1015 | return err; |
1016 | } | |
1017 | ||
1018 | if (help_flag) { | |
1019 | cmd->help(cmdl); | |
1020 | return -EINVAL; | |
1021 | } | |
1022 | ||
f3af3074 SH |
1023 | nlh = msg_init(buf, TIPC_NL_MON_GET); |
1024 | if (!nlh) { | |
5b748f09 PB |
1025 | fprintf(stderr, "error, message initialisation failed\n"); |
1026 | return -1; | |
1027 | } | |
1028 | ||
a56e0db7 HL |
1029 | new_json_obj(json); |
1030 | err = msg_dumpit(nlh, link_mon_list_cb, bname); | |
1031 | delete_json_obj(); | |
1032 | return err; | |
5b748f09 PB |
1033 | } |
1034 | ||
b33a6900 PB |
1035 | static void cmd_link_mon_set_help(struct cmdl *cmdl) |
1036 | { | |
1037 | fprintf(stderr, "Usage: %s monitor set PPROPERTY\n\n" | |
1038 | "PROPERTIES\n" | |
1039 | " threshold SIZE - Set monitor activation threshold\n", | |
1040 | cmdl->argv[0]); | |
1041 | } | |
1042 | ||
1043 | static int cmd_link_mon_set(struct nlmsghdr *nlh, const struct cmd *cmd, | |
1044 | struct cmdl *cmdl, void *data) | |
1045 | { | |
1046 | const struct cmd cmds[] = { | |
1047 | { "threshold", cmd_link_mon_set_prop, NULL }, | |
1048 | { NULL } | |
1049 | }; | |
1050 | ||
1051 | return run_cmd(nlh, cmd, cmds, cmdl, NULL); | |
1052 | } | |
1053 | ||
7da7ef9b PB |
1054 | static void cmd_link_mon_get_help(struct cmdl *cmdl) |
1055 | { | |
f3af3074 | 1056 | fprintf(stderr, "Usage: %s monitor get PPROPERTY\n\n" |
7da7ef9b | 1057 | "PROPERTIES\n" |
f3af3074 | 1058 | " threshold - Get monitor activation threshold\n", |
7da7ef9b PB |
1059 | cmdl->argv[0]); |
1060 | } | |
1061 | ||
1062 | static int link_mon_get_cb(const struct nlmsghdr *nlh, void *data) | |
1063 | { | |
1064 | struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); | |
1065 | struct nlattr *info[TIPC_NLA_MAX + 1] = {}; | |
1066 | struct nlattr *attrs[TIPC_NLA_MON_MAX + 1] = {}; | |
1067 | ||
1068 | mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); | |
1069 | if (!info[TIPC_NLA_MON]) | |
1070 | return MNL_CB_ERROR; | |
1071 | ||
1072 | mnl_attr_parse_nested(info[TIPC_NLA_MON], parse_attrs, attrs); | |
1073 | if (!attrs[TIPC_NLA_MON_ACTIVATION_THRESHOLD]) | |
1074 | return MNL_CB_ERROR; | |
1075 | ||
a56e0db7 HL |
1076 | new_json_obj(json); |
1077 | print_uint(PRINT_ANY, "threshold", "%u\n", | |
1078 | mnl_attr_get_u32(attrs[TIPC_NLA_MON_ACTIVATION_THRESHOLD])); | |
1079 | delete_json_obj(); | |
7da7ef9b PB |
1080 | |
1081 | return MNL_CB_OK; | |
1082 | } | |
1083 | ||
1084 | static int cmd_link_mon_get_prop(struct nlmsghdr *nlh, const struct cmd *cmd, | |
1085 | struct cmdl *cmdl, void *data) | |
1086 | { | |
1087 | char buf[MNL_SOCKET_BUFFER_SIZE]; | |
1088 | ||
f3af3074 SH |
1089 | nlh = msg_init(buf, TIPC_NL_MON_GET); |
1090 | if (!nlh) { | |
7da7ef9b PB |
1091 | fprintf(stderr, "error, message initialisation failed\n"); |
1092 | return -1; | |
1093 | } | |
1094 | ||
1095 | return msg_doit(nlh, link_mon_get_cb, NULL); | |
1096 | } | |
1097 | ||
1098 | static int cmd_link_mon_get(struct nlmsghdr *nlh, const struct cmd *cmd, | |
1099 | struct cmdl *cmdl, void *data) | |
1100 | { | |
1101 | const struct cmd cmds[] = { | |
1102 | { "threshold", cmd_link_mon_get_prop, NULL}, | |
1103 | { NULL } | |
1104 | }; | |
1105 | ||
1106 | return run_cmd(nlh, cmd, cmds, cmdl, NULL); | |
1107 | } | |
1108 | ||
b33a6900 PB |
1109 | static void cmd_link_mon_help(struct cmdl *cmdl) |
1110 | { | |
1111 | fprintf(stderr, | |
1112 | "Usage: %s montior COMMAND [ARGS] ...\n\n" | |
1113 | "COMMANDS\n" | |
7da7ef9b | 1114 | " set - Set monitor properties\n" |
80e9807d | 1115 | " get - Get monitor properties\n" |
5b748f09 | 1116 | " list - List all cluster members\n" |
80e9807d | 1117 | " summary - Show local node monitor summary\n", |
b33a6900 PB |
1118 | cmdl->argv[0]); |
1119 | } | |
1120 | ||
1121 | static int cmd_link_mon(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl, | |
1122 | void *data) | |
1123 | { | |
1124 | const struct cmd cmds[] = { | |
1125 | { "set", cmd_link_mon_set, cmd_link_mon_set_help }, | |
7da7ef9b | 1126 | { "get", cmd_link_mon_get, cmd_link_mon_get_help }, |
5b748f09 | 1127 | { "list", cmd_link_mon_list, cmd_link_mon_list_help }, |
80e9807d | 1128 | { "summary", cmd_link_mon_summary, NULL }, |
b33a6900 PB |
1129 | { NULL } |
1130 | }; | |
1131 | ||
1132 | return run_cmd(nlh, cmd, cmds, cmdl, NULL); | |
1133 | } | |
1134 | ||
f043759d RA |
1135 | void cmd_link_help(struct cmdl *cmdl) |
1136 | { | |
1137 | fprintf(stderr, | |
1138 | "Usage: %s link COMMAND [ARGS] ...\n" | |
1139 | "\n" | |
1140 | "COMMANDS\n" | |
1141 | " list - List links\n" | |
1142 | " get - Get various link properties\n" | |
1143 | " set - Set various link properties\n" | |
b33a6900 PB |
1144 | " statistics - Show or reset statistics\n" |
1145 | " monitor - Show or set link supervision\n", | |
f043759d RA |
1146 | cmdl->argv[0]); |
1147 | } | |
1148 | ||
1149 | int cmd_link(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl, | |
1150 | void *data) | |
1151 | { | |
1152 | const struct cmd cmds[] = { | |
1153 | { "get", cmd_link_get, cmd_link_get_help }, | |
1154 | { "list", cmd_link_list, NULL }, | |
1155 | { "set", cmd_link_set, cmd_link_set_help }, | |
1156 | { "statistics", cmd_link_stat, cmd_link_stat_help }, | |
b33a6900 | 1157 | { "monitor", cmd_link_mon, cmd_link_mon_help }, |
f043759d RA |
1158 | { NULL } |
1159 | }; | |
1160 | ||
1161 | return run_cmd(nlh, cmd, cmds, cmdl, NULL); | |
1162 | } |