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