]> git.proxmox.com Git - mirror_iproute2.git/blob - tipc/link.c
tipc: add link monitor list
[mirror_iproute2.git] / tipc / link.c
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"
25 #include "bearer.h"
26
27 static int link_list_cb(const struct nlmsghdr *nlh, void *data)
28 {
29 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
30 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
31 struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1] = {};
32
33 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
34 if (!info[TIPC_NLA_LINK])
35 return MNL_CB_ERROR;
36
37 mnl_attr_parse_nested(info[TIPC_NLA_LINK], parse_attrs, attrs);
38 if (!attrs[TIPC_NLA_LINK_NAME])
39 return MNL_CB_ERROR;
40
41 printf("%s: ", mnl_attr_get_str(attrs[TIPC_NLA_LINK_NAME]));
42
43 if (attrs[TIPC_NLA_LINK_UP])
44 printf("up\n");
45 else
46 printf("down\n");
47
48 return MNL_CB_OK;
49 }
50
51 static int cmd_link_list(struct nlmsghdr *nlh, const struct cmd *cmd,
52 struct cmdl *cmdl, void *data)
53 {
54 char buf[MNL_SOCKET_BUFFER_SIZE];
55
56 if (help_flag) {
57 fprintf(stderr, "Usage: %s link list\n", cmdl->argv[0]);
58 return -EINVAL;
59 }
60
61 if (!(nlh = msg_init(buf, TIPC_NL_LINK_GET))) {
62 fprintf(stderr, "error, message initialisation failed\n");
63 return -1;
64 }
65
66 return msg_dumpit(nlh, link_list_cb, NULL);
67 }
68
69 static int link_get_cb(const struct nlmsghdr *nlh, void *data)
70 {
71 int *prop = data;
72 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
73 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
74 struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1] = {};
75 struct nlattr *props[TIPC_NLA_PROP_MAX + 1] = {};
76
77 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
78 if (!info[TIPC_NLA_LINK])
79 return MNL_CB_ERROR;
80
81 mnl_attr_parse_nested(info[TIPC_NLA_LINK], parse_attrs, attrs);
82 if (!attrs[TIPC_NLA_LINK_PROP])
83 return MNL_CB_ERROR;
84
85 mnl_attr_parse_nested(attrs[TIPC_NLA_LINK_PROP], parse_attrs, props);
86 if (!props[*prop])
87 return MNL_CB_ERROR;
88
89 printf("%u\n", mnl_attr_get_u32(props[*prop]));
90
91 return MNL_CB_OK;
92 }
93
94 static int cmd_link_get_prop(struct nlmsghdr *nlh, const struct cmd *cmd,
95 struct cmdl *cmdl, void *data)
96 {
97 int prop;
98 char buf[MNL_SOCKET_BUFFER_SIZE];
99 struct opt *opt;
100 struct opt opts[] = {
101 { "link", OPT_KEYVAL, NULL },
102 { NULL }
103 };
104
105 if (strcmp(cmd->cmd, "priority") == 0)
106 prop = TIPC_NLA_PROP_PRIO;
107 else if ((strcmp(cmd->cmd, "tolerance") == 0))
108 prop = TIPC_NLA_PROP_TOL;
109 else if ((strcmp(cmd->cmd, "window") == 0))
110 prop = TIPC_NLA_PROP_WIN;
111 else
112 return -EINVAL;
113
114 if (help_flag) {
115 (cmd->help)(cmdl);
116 return -EINVAL;
117 }
118
119 if (parse_opts(opts, cmdl) < 0)
120 return -EINVAL;
121
122 if (!(nlh = msg_init(buf, TIPC_NL_LINK_GET))) {
123 fprintf(stderr, "error, message initialisation failed\n");
124 return -1;
125 }
126
127 if (!(opt = get_opt(opts, "link"))) {
128 fprintf(stderr, "error, missing link\n");
129 return -EINVAL;
130 }
131 mnl_attr_put_strz(nlh, TIPC_NLA_LINK_NAME, opt->val);
132
133 return msg_doit(nlh, link_get_cb, &prop);
134 }
135
136 static void cmd_link_get_help(struct cmdl *cmdl)
137 {
138 fprintf(stderr, "Usage: %s link get PPROPERTY link LINK\n\n"
139 "PROPERTIES\n"
140 " tolerance - Get link tolerance\n"
141 " priority - Get link priority\n"
142 " window - Get link window\n",
143 cmdl->argv[0]);
144 }
145
146 static int cmd_link_get(struct nlmsghdr *nlh, const struct cmd *cmd,
147 struct cmdl *cmdl, void *data)
148 {
149 const struct cmd cmds[] = {
150 { "priority", cmd_link_get_prop, cmd_link_get_help },
151 { "tolerance", cmd_link_get_prop, cmd_link_get_help },
152 { "window", cmd_link_get_prop, cmd_link_get_help },
153 { NULL }
154 };
155
156 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
157 }
158
159 static void cmd_link_stat_reset_help(struct cmdl *cmdl)
160 {
161 fprintf(stderr, "Usage: %s link stat reset link LINK\n\n", cmdl->argv[0]);
162 }
163
164 static int cmd_link_stat_reset(struct nlmsghdr *nlh, const struct cmd *cmd,
165 struct cmdl *cmdl, void *data)
166 {
167 char *link;
168 char buf[MNL_SOCKET_BUFFER_SIZE];
169 struct opt *opt;
170 struct nlattr *nest;
171 struct opt opts[] = {
172 { "link", OPT_KEYVAL, NULL },
173 { NULL }
174 };
175
176 if (help_flag) {
177 (cmd->help)(cmdl);
178 return -EINVAL;
179 }
180
181 if (parse_opts(opts, cmdl) != 1) {
182 (cmd->help)(cmdl);
183 return -EINVAL;
184 }
185
186 if (!(nlh = msg_init(buf, TIPC_NL_LINK_RESET_STATS))) {
187 fprintf(stderr, "error, message initialisation failed\n");
188 return -1;
189 }
190
191 if (!(opt = get_opt(opts, "link"))) {
192 fprintf(stderr, "error, missing link\n");
193 return -EINVAL;
194 }
195 link = opt->val;
196
197 nest = mnl_attr_nest_start(nlh, TIPC_NLA_LINK);
198 mnl_attr_put_strz(nlh, TIPC_NLA_LINK_NAME, link);
199 mnl_attr_nest_end(nlh, nest);
200
201 return msg_doit(nlh, NULL, NULL);
202 }
203
204 static uint32_t perc(uint32_t count, uint32_t total)
205 {
206 return (count * 100 + (total / 2)) / total;
207 }
208
209 static int _show_link_stat(struct nlattr *attrs[], struct nlattr *prop[],
210 struct nlattr *stats[])
211 {
212 uint32_t proft;
213
214 if (attrs[TIPC_NLA_LINK_ACTIVE])
215 printf(" ACTIVE");
216 else if (attrs[TIPC_NLA_LINK_UP])
217 printf(" STANDBY");
218 else
219 printf(" DEFUNCT");
220
221 printf(" MTU:%u Priority:%u Tolerance:%u ms Window:%u packets\n",
222 mnl_attr_get_u32(attrs[TIPC_NLA_LINK_MTU]),
223 mnl_attr_get_u32(prop[TIPC_NLA_PROP_PRIO]),
224 mnl_attr_get_u32(prop[TIPC_NLA_PROP_TOL]),
225 mnl_attr_get_u32(prop[TIPC_NLA_PROP_WIN]));
226
227 printf(" RX packets:%u fragments:%u/%u bundles:%u/%u\n",
228 mnl_attr_get_u32(attrs[TIPC_NLA_LINK_RX]) -
229 mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_INFO]),
230 mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTS]),
231 mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTED]),
232 mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLES]),
233 mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLED]));
234
235 printf(" TX packets:%u fragments:%u/%u bundles:%u/%u\n",
236 mnl_attr_get_u32(attrs[TIPC_NLA_LINK_TX]) -
237 mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_INFO]),
238 mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTS]),
239 mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTED]),
240 mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLES]),
241 mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLED]));
242
243 proft = mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT]);
244 printf(" TX profile sample:%u packets average:%u octets\n",
245 mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_CNT]),
246 mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_TOT]) / proft);
247
248 printf(" 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% "
249 "-16384:%u%% -32768:%u%% -66000:%u%%\n",
250 perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P0]), proft),
251 perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P1]), proft),
252 perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P2]), proft),
253 perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P3]), proft),
254 perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P4]), proft),
255 perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P5]), proft),
256 perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P6]), proft));
257
258 printf(" RX states:%u probes:%u naks:%u defs:%u dups:%u\n",
259 mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_STATES]),
260 mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_PROBES]),
261 mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_NACKS]),
262 mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_DEFERRED]),
263 mnl_attr_get_u32(stats[TIPC_NLA_STATS_DUPLICATES]));
264
265 printf(" TX states:%u probes:%u naks:%u acks:%u dups:%u\n",
266 mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_STATES]),
267 mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_PROBES]),
268 mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_NACKS]),
269 mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_ACKS]),
270 mnl_attr_get_u32(stats[TIPC_NLA_STATS_RETRANSMITTED]));
271
272 printf(" Congestion link:%u Send queue max:%u avg:%u\n",
273 mnl_attr_get_u32(stats[TIPC_NLA_STATS_LINK_CONGS]),
274 mnl_attr_get_u32(stats[TIPC_NLA_STATS_MAX_QUEUE]),
275 mnl_attr_get_u32(stats[TIPC_NLA_STATS_AVG_QUEUE]));
276
277 return MNL_CB_OK;
278 }
279
280 static int _show_bc_link_stat(struct nlattr *prop[], struct nlattr *stats[])
281 {
282 printf(" Window:%u packets\n",
283 mnl_attr_get_u32(prop[TIPC_NLA_PROP_WIN]));
284
285 printf(" RX packets:%u fragments:%u/%u bundles:%u/%u\n",
286 mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_INFO]),
287 mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTS]),
288 mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTED]),
289 mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLES]),
290 mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLED]));
291
292 printf(" TX packets:%u fragments:%u/%u bundles:%u/%u\n",
293 mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_INFO]),
294 mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTS]),
295 mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTED]),
296 mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLES]),
297 mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLED]));
298
299 printf(" RX naks:%u defs:%u dups:%u\n",
300 mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_NACKS]),
301 mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_DEFERRED]),
302 mnl_attr_get_u32(stats[TIPC_NLA_STATS_DUPLICATES]));
303
304 printf(" TX naks:%u acks:%u dups:%u\n",
305 mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_NACKS]),
306 mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_ACKS]),
307 mnl_attr_get_u32(stats[TIPC_NLA_STATS_RETRANSMITTED]));
308
309 printf(" Congestion link:%u Send queue max:%u avg:%u\n",
310 mnl_attr_get_u32(stats[TIPC_NLA_STATS_LINK_CONGS]),
311 mnl_attr_get_u32(stats[TIPC_NLA_STATS_MAX_QUEUE]),
312 mnl_attr_get_u32(stats[TIPC_NLA_STATS_AVG_QUEUE]));
313
314 return MNL_CB_OK;
315 }
316
317 static int link_stat_show_cb(const struct nlmsghdr *nlh, void *data)
318 {
319 const char *name;
320 const char *link = data;
321 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
322 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
323 struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1] = {};
324 struct nlattr *prop[TIPC_NLA_PROP_MAX + 1] = {};
325 struct nlattr *stats[TIPC_NLA_STATS_MAX + 1] = {};
326
327 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
328 if (!info[TIPC_NLA_LINK])
329 return MNL_CB_ERROR;
330
331 mnl_attr_parse_nested(info[TIPC_NLA_LINK], parse_attrs, attrs);
332 if (!attrs[TIPC_NLA_LINK_NAME] || !attrs[TIPC_NLA_LINK_PROP] ||
333 !attrs[TIPC_NLA_LINK_STATS])
334 return MNL_CB_ERROR;
335
336 mnl_attr_parse_nested(attrs[TIPC_NLA_LINK_PROP], parse_attrs, prop);
337 mnl_attr_parse_nested(attrs[TIPC_NLA_LINK_STATS], parse_attrs, stats);
338
339 name = mnl_attr_get_str(attrs[TIPC_NLA_LINK_NAME]);
340
341 /* If a link is passed, skip all but that link */
342 if (link && (strcmp(name, link) != 0))
343 return MNL_CB_OK;
344
345 if (attrs[TIPC_NLA_LINK_BROADCAST]) {
346 printf("Link <%s>\n", name);
347 return _show_bc_link_stat(prop, stats);
348 }
349
350 printf("\nLink <%s>\n", name);
351
352 return _show_link_stat(attrs, prop, stats);
353 }
354
355 static void cmd_link_stat_show_help(struct cmdl *cmdl)
356 {
357 fprintf(stderr, "Usage: %s link stat show [ link LINK ]\n",
358 cmdl->argv[0]);
359 }
360
361 static int cmd_link_stat_show(struct nlmsghdr *nlh, const struct cmd *cmd,
362 struct cmdl *cmdl, void *data)
363 {
364 char *link = NULL;
365 char buf[MNL_SOCKET_BUFFER_SIZE];
366 struct opt *opt;
367 struct opt opts[] = {
368 { "link", OPT_KEYVAL, NULL },
369 { NULL }
370 };
371
372 if (help_flag) {
373 (cmd->help)(cmdl);
374 return -EINVAL;
375 }
376
377 if (!(nlh = msg_init(buf, TIPC_NL_LINK_GET))) {
378 fprintf(stderr, "error, message initialisation failed\n");
379 return -1;
380 }
381
382 if (parse_opts(opts, cmdl) < 0)
383 return -EINVAL;
384
385 if ((opt = get_opt(opts, "link")))
386 link = opt->val;
387
388 return msg_dumpit(nlh, link_stat_show_cb, link);
389 }
390
391 static void cmd_link_stat_help(struct cmdl *cmdl)
392 {
393 fprintf(stderr, "Usage: %s link stat COMMAND [ARGS]\n\n"
394 "COMMANDS:\n"
395 " reset - Reset link statistics for link\n"
396 " show - Get link priority\n",
397 cmdl->argv[0]);
398 }
399
400 static int cmd_link_stat(struct nlmsghdr *nlh, const struct cmd *cmd,
401 struct cmdl *cmdl, void *data)
402 {
403 const struct cmd cmds[] = {
404 { "reset", cmd_link_stat_reset, cmd_link_stat_reset_help },
405 { "show", cmd_link_stat_show, cmd_link_stat_show_help },
406 { NULL }
407 };
408
409 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
410 }
411
412 static void cmd_link_set_help(struct cmdl *cmdl)
413 {
414 fprintf(stderr, "Usage: %s link set PPROPERTY link LINK\n\n"
415 "PROPERTIES\n"
416 " tolerance TOLERANCE - Set link tolerance\n"
417 " priority PRIORITY - Set link priority\n"
418 " window WINDOW - Set link window\n",
419 cmdl->argv[0]);
420 }
421
422 static int cmd_link_set_prop(struct nlmsghdr *nlh, const struct cmd *cmd,
423 struct cmdl *cmdl, void *data)
424 {
425 int val;
426 int prop;
427 char buf[MNL_SOCKET_BUFFER_SIZE];
428 struct nlattr *props;
429 struct nlattr *attrs;
430 struct opt *opt;
431 struct opt opts[] = {
432 { "link", OPT_KEYVAL, NULL },
433 { NULL }
434 };
435
436 if (strcmp(cmd->cmd, "priority") == 0)
437 prop = TIPC_NLA_PROP_PRIO;
438 else if ((strcmp(cmd->cmd, "tolerance") == 0))
439 prop = TIPC_NLA_PROP_TOL;
440 else if ((strcmp(cmd->cmd, "window") == 0))
441 prop = TIPC_NLA_PROP_WIN;
442 else
443 return -EINVAL;
444
445 if (help_flag) {
446 (cmd->help)(cmdl);
447 return -EINVAL;
448 }
449
450 if (cmdl->optind >= cmdl->argc) {
451 fprintf(stderr, "error, missing value\n");
452 return -EINVAL;
453 }
454 val = atoi(shift_cmdl(cmdl));
455
456 if (parse_opts(opts, cmdl) < 0)
457 return -EINVAL;
458
459 if (!(nlh = msg_init(buf, TIPC_NL_LINK_SET))) {
460 fprintf(stderr, "error, message initialisation failed\n");
461 return -1;
462 }
463 attrs = mnl_attr_nest_start(nlh, TIPC_NLA_LINK);
464
465 if (!(opt = get_opt(opts, "link"))) {
466 fprintf(stderr, "error, missing link\n");
467 return -EINVAL;
468 }
469 mnl_attr_put_strz(nlh, TIPC_NLA_LINK_NAME, opt->val);
470
471 props = mnl_attr_nest_start(nlh, TIPC_NLA_LINK_PROP);
472 mnl_attr_put_u32(nlh, prop, val);
473 mnl_attr_nest_end(nlh, props);
474
475 mnl_attr_nest_end(nlh, attrs);
476
477 return msg_doit(nlh, link_get_cb, &prop);
478 }
479
480 static int cmd_link_set(struct nlmsghdr *nlh, const struct cmd *cmd,
481 struct cmdl *cmdl, void *data)
482 {
483 const struct cmd cmds[] = {
484 { "priority", cmd_link_set_prop, cmd_link_set_help },
485 { "tolerance", cmd_link_set_prop, cmd_link_set_help },
486 { "window", cmd_link_set_prop, cmd_link_set_help },
487 { NULL }
488 };
489
490 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
491 }
492
493 static int cmd_link_mon_set_prop(struct nlmsghdr *nlh, const struct cmd *cmd,
494 struct cmdl *cmdl, void *data)
495 {
496 int size;
497 char buf[MNL_SOCKET_BUFFER_SIZE];
498 struct nlattr *attrs;
499
500 if (cmdl->argc != cmdl->optind + 1) {
501 fprintf(stderr, "error, missing value\n");
502 return -EINVAL;
503 }
504 size = atoi(shift_cmdl(cmdl));
505
506 if (!(nlh = msg_init(buf, TIPC_NL_MON_SET))) {
507 fprintf(stderr, "error, message initialisation failed\n");
508 return -1;
509 }
510 attrs = mnl_attr_nest_start(nlh, TIPC_NLA_MON);
511
512 mnl_attr_put_u32(nlh, TIPC_NLA_MON_ACTIVATION_THRESHOLD, size);
513
514 mnl_attr_nest_end(nlh, attrs);
515
516 return msg_doit(nlh, NULL, NULL);
517 }
518
519 static int link_mon_summary_cb(const struct nlmsghdr *nlh, void *data)
520 {
521 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
522 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
523 struct nlattr *attrs[TIPC_NLA_MON_MAX + 1] = {};
524
525 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
526 if (!info[TIPC_NLA_MON])
527 return MNL_CB_ERROR;
528
529 mnl_attr_parse_nested(info[TIPC_NLA_MON], parse_attrs, attrs);
530
531 printf("\nbearer %s\n",
532 mnl_attr_get_str(attrs[TIPC_NLA_MON_BEARER_NAME]));
533
534 printf(" table_generation %u\n",
535 mnl_attr_get_u32(attrs[TIPC_NLA_MON_LISTGEN]));
536 printf(" cluster_size %u\n",
537 mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEERCNT]));
538 printf(" algorithm %s\n",
539 attrs[TIPC_NLA_MON_ACTIVE] ? "overlapping-ring" : "full-mesh");
540
541 return MNL_CB_OK;
542 }
543
544 static int cmd_link_mon_summary(struct nlmsghdr *nlh, const struct cmd *cmd,
545 struct cmdl *cmdl, void *data)
546 {
547 char buf[MNL_SOCKET_BUFFER_SIZE];
548
549 if (help_flag) {
550 fprintf(stderr, "Usage: %s monitor summary\n", cmdl->argv[0]);
551 return -EINVAL;
552 }
553
554 if (!(nlh = msg_init(buf, TIPC_NL_MON_GET))) {
555 fprintf(stderr, "error, message initialisation failed\n");
556 return -1;
557 }
558
559 return msg_dumpit(nlh, link_mon_summary_cb, NULL);
560 }
561
562 #define STATUS_WIDTH 7
563 #define MAX_NODE_WIDTH 14 /* 255.4095.4095 */
564 #define MAX_DOM_GEN_WIDTH 11 /* 65535 */
565 #define DIRECTLY_MON_WIDTH 10
566
567 #define APPL_NODE_STATUS_WIDTH 5
568
569 static int map_get(uint64_t up_map, int i)
570 {
571 return (up_map & (1 << i)) >> i;
572 }
573
574 /* print the applied members, since we know the the members
575 * are listed in ascending order, we print only the state */
576 static void link_mon_print_applied(uint16_t applied, uint64_t up_map)
577 {
578 int i;
579 char state;
580
581 for (i = 0; i < applied; i++) {
582 /* print the delimiter for every -n- entry */
583 if (i && !(i % APPL_NODE_STATUS_WIDTH))
584 printf(",");
585
586 state = map_get(up_map, i) ? 'U' : 'D';
587 printf("%c", state);
588 }
589 }
590
591 /* print the non applied members, since we dont know
592 * the members, we print them along with the state */
593 static void link_mon_print_non_applied(uint16_t applied, uint16_t member_cnt,
594 uint64_t up_map, uint32_t *members)
595 {
596 int i;
597 char state;
598
599 printf(" [");
600 for (i = applied; i < member_cnt; i++) {
601 char addr_str[16];
602
603 /* print the delimiter for every entry */
604 if (i != applied)
605 printf(",");
606
607 sprintf(addr_str, "%u.%u.%u:", tipc_zone(members[i]),
608 tipc_cluster(members[i]), tipc_node(members[i]));
609 state = map_get(up_map, i) ? 'U' : 'D';
610 printf("%s%c", addr_str, state);
611 }
612 printf("]");
613 }
614
615 static void link_mon_print_peer_state(const uint32_t addr, const char *status,
616 const char *monitored,
617 const uint32_t dom_gen)
618 {
619 char addr_str[16];
620
621 sprintf(addr_str, "%u.%u.%u", tipc_zone(addr), tipc_cluster(addr),
622 tipc_node(addr));
623
624 printf("%-*s", MAX_NODE_WIDTH, addr_str);
625 printf("%-*s", STATUS_WIDTH, status);
626 printf("%-*s", DIRECTLY_MON_WIDTH, monitored);
627 printf("%-*u", MAX_DOM_GEN_WIDTH, dom_gen);
628 }
629
630 static int link_mon_peer_list_cb(const struct nlmsghdr *nlh, void *data)
631 {
632 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
633 struct nlattr *attrs[TIPC_NLA_MON_PEER_MAX + 1] = {};
634 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
635 uint16_t member_cnt;
636 uint32_t applied;
637 uint32_t dom_gen;
638 uint64_t up_map;
639 char status[16];
640 char monitored[16];
641
642 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
643 if (!info[TIPC_NLA_MON_PEER])
644 return MNL_CB_ERROR;
645
646 mnl_attr_parse_nested(info[TIPC_NLA_MON_PEER], parse_attrs, attrs);
647
648 (attrs[TIPC_NLA_MON_PEER_LOCAL] || attrs[TIPC_NLA_MON_PEER_HEAD]) ?
649 strcpy(monitored, "direct") :
650 strcpy(monitored, "indirect");
651
652 attrs[TIPC_NLA_MON_PEER_UP] ?
653 strcpy(status, "up") :
654 strcpy(status, "down");
655
656 dom_gen = attrs[TIPC_NLA_MON_PEER_DOMGEN] ?
657 mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEER_DOMGEN]) : 0;
658
659 link_mon_print_peer_state(mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEER_ADDR]),
660 status, monitored, dom_gen);
661
662 applied = mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEER_APPLIED]);
663
664 if (!applied)
665 goto exit;
666
667 up_map = mnl_attr_get_u64(attrs[TIPC_NLA_MON_PEER_UPMAP]);
668
669 member_cnt = mnl_attr_get_payload_len(attrs[TIPC_NLA_MON_PEER_MEMBERS]);
670
671 /* each tipc address occupies 4 bytes of payload, hence compensate it */
672 member_cnt /= sizeof(uint32_t);
673
674 link_mon_print_applied(applied, up_map);
675
676 link_mon_print_non_applied(applied, member_cnt, up_map,
677 mnl_attr_get_payload(attrs[TIPC_NLA_MON_PEER_MEMBERS]));
678
679 exit:
680 printf("\n");
681
682 return MNL_CB_OK;
683 }
684
685 static int link_mon_peer_list(uint32_t mon_ref)
686 {
687 struct nlmsghdr *nlh;
688 char buf[MNL_SOCKET_BUFFER_SIZE];
689 struct nlattr *nest;
690
691 if (!(nlh = msg_init(buf, TIPC_NL_MON_PEER_GET))) {
692 fprintf(stderr, "error, message initialisation failed\n");
693 return -1;
694 }
695
696 nest = mnl_attr_nest_start(nlh, TIPC_NLA_MON);
697 mnl_attr_put_u32(nlh, TIPC_NLA_MON_REF, mon_ref);
698 mnl_attr_nest_end(nlh, nest);
699
700 return msg_dumpit(nlh, link_mon_peer_list_cb, NULL);
701 }
702
703 static int link_mon_list_cb(const struct nlmsghdr *nlh, void *data)
704 {
705 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
706 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
707 struct nlattr *attrs[TIPC_NLA_MON_MAX + 1] = {};
708 char *req_bearer = data;
709 const char *bname;
710 const char *title = "node status monitored generation "
711 "applied_node_status [non_applied_node:status]";
712
713 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
714 if (!info[TIPC_NLA_MON])
715 return MNL_CB_ERROR;
716
717 mnl_attr_parse_nested(info[TIPC_NLA_MON], parse_attrs, attrs);
718
719 bname = mnl_attr_get_str(attrs[TIPC_NLA_MON_BEARER_NAME]);
720
721 if (*req_bearer && (strcmp(req_bearer, bname) != 0))
722 return MNL_CB_OK;
723
724 printf("\nbearer %s\n", bname);
725 printf("%s\n", title);
726
727 if (mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEERCNT]))
728 link_mon_peer_list(mnl_attr_get_u32(attrs[TIPC_NLA_MON_REF]));
729
730 return MNL_CB_OK;
731 }
732
733 static void cmd_link_mon_list_help(struct cmdl *cmdl)
734 {
735 fprintf(stderr, "Usage: %s monitor list [ media MEDIA ARGS...] \n\n",
736 cmdl->argv[0]);
737 print_bearer_media();
738 }
739
740 static void cmd_link_mon_list_l2_help(struct cmdl *cmdl, char *media)
741 {
742 fprintf(stderr,
743 "Usage: %s monitor list media %s device DEVICE [OPTIONS]\n",
744 cmdl->argv[0], media);
745 }
746
747 static void cmd_link_mon_list_udp_help(struct cmdl *cmdl, char *media)
748 {
749 fprintf(stderr,
750 "Usage: %s monitor list media udp name NAME \n\n",
751 cmdl->argv[0]);
752 }
753
754 static int cmd_link_mon_list(struct nlmsghdr *nlh, const struct cmd *cmd,
755 struct cmdl *cmdl, void *data)
756 {
757 char buf[MNL_SOCKET_BUFFER_SIZE];
758 char bname[TIPC_MAX_BEARER_NAME] = {0};
759 struct opt opts[] = {
760 { "media", OPT_KEYVAL, NULL },
761 { "device", OPT_KEYVAL, NULL },
762 { "name", OPT_KEYVAL, NULL },
763 { NULL }
764 };
765 struct tipc_sup_media sup_media[] = {
766 { "udp", "name", cmd_link_mon_list_udp_help},
767 { "eth", "device", cmd_link_mon_list_l2_help },
768 { "ib", "device", cmd_link_mon_list_l2_help },
769 { NULL, },
770 };
771
772 int err;
773
774 if (parse_opts(opts, cmdl) < 0)
775 return -EINVAL;
776
777 if (get_opt(opts, "media")) {
778 if ((err = cmd_get_unique_bearer_name(cmd, cmdl, opts, bname,
779 sup_media)))
780 return err;
781 }
782
783 if (help_flag) {
784 cmd->help(cmdl);
785 return -EINVAL;
786 }
787
788 if (!(nlh = msg_init(buf, TIPC_NL_MON_GET))) {
789 fprintf(stderr, "error, message initialisation failed\n");
790 return -1;
791 }
792
793 return msg_dumpit(nlh, link_mon_list_cb, bname);
794 }
795
796 static void cmd_link_mon_set_help(struct cmdl *cmdl)
797 {
798 fprintf(stderr, "Usage: %s monitor set PPROPERTY\n\n"
799 "PROPERTIES\n"
800 " threshold SIZE - Set monitor activation threshold\n",
801 cmdl->argv[0]);
802 }
803
804 static int cmd_link_mon_set(struct nlmsghdr *nlh, const struct cmd *cmd,
805 struct cmdl *cmdl, void *data)
806 {
807 const struct cmd cmds[] = {
808 { "threshold", cmd_link_mon_set_prop, NULL },
809 { NULL }
810 };
811
812 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
813 }
814
815 static void cmd_link_mon_get_help(struct cmdl *cmdl)
816 {
817 fprintf(stderr, "Usage: %s monitor get PPROPERTY \n\n"
818 "PROPERTIES\n"
819 " threshold - Get monitor activation threshold\n",
820 cmdl->argv[0]);
821 }
822
823 static int link_mon_get_cb(const struct nlmsghdr *nlh, void *data)
824 {
825 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
826 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
827 struct nlattr *attrs[TIPC_NLA_MON_MAX + 1] = {};
828
829 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
830 if (!info[TIPC_NLA_MON])
831 return MNL_CB_ERROR;
832
833 mnl_attr_parse_nested(info[TIPC_NLA_MON], parse_attrs, attrs);
834 if (!attrs[TIPC_NLA_MON_ACTIVATION_THRESHOLD])
835 return MNL_CB_ERROR;
836
837 printf("%u\n",
838 mnl_attr_get_u32(attrs[TIPC_NLA_MON_ACTIVATION_THRESHOLD]));
839
840 return MNL_CB_OK;
841 }
842
843 static int cmd_link_mon_get_prop(struct nlmsghdr *nlh, const struct cmd *cmd,
844 struct cmdl *cmdl, void *data)
845 {
846 char buf[MNL_SOCKET_BUFFER_SIZE];
847
848 if (!(nlh = msg_init(buf, TIPC_NL_MON_GET))) {
849 fprintf(stderr, "error, message initialisation failed\n");
850 return -1;
851 }
852
853 return msg_doit(nlh, link_mon_get_cb, NULL);
854 }
855
856 static int cmd_link_mon_get(struct nlmsghdr *nlh, const struct cmd *cmd,
857 struct cmdl *cmdl, void *data)
858 {
859 const struct cmd cmds[] = {
860 { "threshold", cmd_link_mon_get_prop, NULL},
861 { NULL }
862 };
863
864 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
865 }
866
867 static void cmd_link_mon_help(struct cmdl *cmdl)
868 {
869 fprintf(stderr,
870 "Usage: %s montior COMMAND [ARGS] ...\n\n"
871 "COMMANDS\n"
872 " set - Set monitor properties\n"
873 " get - Get monitor properties\n"
874 " list - List all cluster members\n"
875 " summary - Show local node monitor summary\n",
876 cmdl->argv[0]);
877 }
878
879 static int cmd_link_mon(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl,
880 void *data)
881 {
882 const struct cmd cmds[] = {
883 { "set", cmd_link_mon_set, cmd_link_mon_set_help },
884 { "get", cmd_link_mon_get, cmd_link_mon_get_help },
885 { "list", cmd_link_mon_list, cmd_link_mon_list_help },
886 { "summary", cmd_link_mon_summary, NULL },
887 { NULL }
888 };
889
890 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
891 }
892
893 void cmd_link_help(struct cmdl *cmdl)
894 {
895 fprintf(stderr,
896 "Usage: %s link COMMAND [ARGS] ...\n"
897 "\n"
898 "COMMANDS\n"
899 " list - List links\n"
900 " get - Get various link properties\n"
901 " set - Set various link properties\n"
902 " statistics - Show or reset statistics\n"
903 " monitor - Show or set link supervision\n",
904 cmdl->argv[0]);
905 }
906
907 int cmd_link(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl,
908 void *data)
909 {
910 const struct cmd cmds[] = {
911 { "get", cmd_link_get, cmd_link_get_help },
912 { "list", cmd_link_list, NULL },
913 { "set", cmd_link_set, cmd_link_set_help },
914 { "statistics", cmd_link_stat, cmd_link_stat_help },
915 { "monitor", cmd_link_mon, cmd_link_mon_help },
916 { NULL }
917 };
918
919 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
920 }