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