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 "cmdl.h"
23#include "msg.h"
24#include "link.h"
25#include "bearer.h"
26#include "utils.h"
27
28#define PRIORITY_STR "priority"
29#define TOLERANCE_STR "tolerance"
30#define WINDOW_STR "window"
31#define BROADCAST_STR "broadcast"
32
33static const char tipc_bclink_name[] = "broadcast-link";
34
35static 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
49 print_string(PRINT_FP, NULL, "%s: ",
50 mnl_attr_get_str(attrs[TIPC_NLA_LINK_NAME]));
51 if (attrs[TIPC_NLA_LINK_UP])
52 print_string(PRINT_ANY,
53 mnl_attr_get_str(attrs[TIPC_NLA_LINK_NAME]),"%s\n", "up");
54 else
55 print_string(PRINT_ANY,
56 mnl_attr_get_str(attrs[TIPC_NLA_LINK_NAME]), "%s\n", "down");
57 return MNL_CB_OK;
58}
59
60static 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];
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(buf, 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 char buf[MNL_SOCKET_BUFFER_SIZE];
130 struct nlattr *attrs;
131 struct opt *opt;
132 struct opt opts[] = {
133 { "link", OPT_KEYVAL, NULL },
134 { NULL }
135 };
136
137 if (strcmp(cmd->cmd, PRIORITY_STR) == 0)
138 prop = TIPC_NLA_PROP_PRIO;
139 else if ((strcmp(cmd->cmd, TOLERANCE_STR) == 0))
140 prop = TIPC_NLA_PROP_TOL;
141 else if ((strcmp(cmd->cmd, WINDOW_STR) == 0))
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
154 nlh = msg_init(buf, TIPC_NL_LINK_GET);
155 if (!nlh) {
156 fprintf(stderr, "error, message initialisation failed\n");
157 return -1;
158 }
159
160 opt = get_opt(opts, "link");
161 if (!opt) {
162 fprintf(stderr, "error, missing link\n");
163 return -EINVAL;
164 }
165 attrs = mnl_attr_nest_start(nlh, TIPC_NLA_LINK);
166 mnl_attr_put_strz(nlh, TIPC_NLA_LINK_NAME, opt->val);
167 mnl_attr_nest_end(nlh, attrs);
168
169 return msg_doit(nlh, link_get_cb, &prop);
170}
171
172static void cmd_link_get_help(struct cmdl *cmdl)
173{
174 fprintf(stderr, "Usage: %s link get PPROPERTY link LINK\n\n"
175 "PROPERTIES\n"
176 " tolerance - Get link tolerance\n"
177 " priority - Get link priority\n"
178 " window - Get link window\n"
179 " broadcast - Get link broadcast\n",
180 cmdl->argv[0]);
181}
182
183static 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
232static 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
240static 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
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
264static int cmd_link_get(struct nlmsghdr *nlh, const struct cmd *cmd,
265 struct cmdl *cmdl, void *data)
266{
267 const struct cmd cmds[] = {
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 },
271 { BROADCAST_STR, cmd_link_get_bcast, cmd_link_get_bcast_help },
272 { NULL }
273 };
274
275 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
276}
277
278static 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
283static 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[] = {
291 { "link", OPT_KEYVAL, NULL },
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
305 nlh = msg_init(buf, TIPC_NL_LINK_RESET_STATS);
306 if (!nlh) {
307 fprintf(stderr, "error, message initialisation failed\n");
308 return -1;
309 }
310
311 opt = get_opt(opts, "link");
312 if (!opt) {
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
325static uint32_t perc(uint32_t count, uint32_t total)
326{
327 return (count * 100 + (total / 2)) / total;
328}
329
330static int _show_link_stat(const char *name, struct nlattr *attrs[],
331 struct nlattr *prop[], struct nlattr *stats[])
332{
333 uint32_t proft;
334
335 open_json_object(NULL);
336
337 print_string(PRINT_ANY, "link", "Link <%s>\n", name);
338 print_string(PRINT_JSON, "state", "", NULL);
339 open_json_array(PRINT_JSON, NULL);
340 if (attrs[TIPC_NLA_LINK_ACTIVE])
341 print_string(PRINT_ANY, NULL, " %s", "ACTIVE");
342 else if (attrs[TIPC_NLA_LINK_UP])
343 print_string(PRINT_ANY, NULL, " %s", "STANDBY");
344 else
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();
384
385 proft = mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT]);
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\n",
437 mnl_attr_get_u32(stats[TIPC_NLA_STATS_AVG_QUEUE]));
438
439 close_json_object();
440 return MNL_CB_OK;
441}
442
443static int _show_bc_link_stat(const char *name, struct nlattr *prop[],
444 struct nlattr *stats[])
445{
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\n",
500 mnl_attr_get_u32(stats[TIPC_NLA_STATS_AVG_QUEUE]));
501 close_json_object();
502
503 return MNL_CB_OK;
504}
505
506static 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
531
532
533 if (link && !strstr(name, link))
534 return MNL_CB_OK;
535
536 if (attrs[TIPC_NLA_LINK_BROADCAST]) {
537 return _show_bc_link_stat(name, prop, stats);
538 }
539
540 return _show_link_stat(name, attrs, prop, stats);
541}
542
543static void cmd_link_stat_show_help(struct cmdl *cmdl)
544{
545 fprintf(stderr, "Usage: %s link stat show [ link { LINK | SUBSTRING | all } ]\n",
546 cmdl->argv[0]);
547}
548
549static int cmd_link_stat_show(struct nlmsghdr *nlh, const struct cmd *cmd,
550 struct cmdl *cmdl, void *data)
551{
552 char *link = NULL;
553 char buf[MNL_SOCKET_BUFFER_SIZE];
554 struct opt *opt;
555 struct opt opts[] = {
556 { "link", OPT_KEYVAL, NULL },
557 { NULL }
558 };
559 struct nlattr *attrs;
560 int err = 0;
561
562 if (help_flag) {
563 (cmd->help)(cmdl);
564 return -EINVAL;
565 }
566
567 nlh = msg_init(buf, TIPC_NL_LINK_GET);
568 if (!nlh) {
569 fprintf(stderr, "error, message initialisation failed\n");
570 return -1;
571 }
572
573 if (parse_opts(opts, cmdl) < 0)
574 return -EINVAL;
575
576 opt = get_opt(opts, "link");
577 if (opt) {
578 if (strcmp(opt->val, "all"))
579 link = opt->val;
580
581 attrs = mnl_attr_nest_start(nlh, TIPC_NLA_LINK);
582 mnl_attr_put(nlh, TIPC_NLA_LINK_BROADCAST, 0, NULL);
583 mnl_attr_nest_end(nlh, attrs);
584 }
585
586 new_json_obj(json);
587 err = msg_dumpit(nlh, link_stat_show_cb, link);
588 delete_json_obj();
589 return err;
590}
591
592static void cmd_link_stat_help(struct cmdl *cmdl)
593{
594 fprintf(stderr, "Usage: %s link stat COMMAND [ARGS]\n\n"
595 "COMMANDS:\n"
596 " reset - Reset link statistics for link\n"
597 " show - Get link priority\n",
598 cmdl->argv[0]);
599}
600
601static int cmd_link_stat(struct nlmsghdr *nlh, const struct cmd *cmd,
602 struct cmdl *cmdl, void *data)
603{
604 const struct cmd cmds[] = {
605 { "reset", cmd_link_stat_reset, cmd_link_stat_reset_help },
606 { "show", cmd_link_stat_show, cmd_link_stat_show_help },
607 { NULL }
608 };
609
610 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
611}
612
613static void cmd_link_set_help(struct cmdl *cmdl)
614{
615 fprintf(stderr, "Usage: %s link set PPROPERTY link LINK\n\n"
616 "PROPERTIES\n"
617 " tolerance TOLERANCE - Set link tolerance\n"
618 " priority PRIORITY - Set link priority\n"
619 " window WINDOW - Set link window\n"
620 " broadcast BROADCAST - Set link broadcast\n",
621 cmdl->argv[0]);
622}
623
624static int cmd_link_set_prop(struct nlmsghdr *nlh, const struct cmd *cmd,
625 struct cmdl *cmdl, void *data)
626{
627 int val;
628 int prop;
629 char buf[MNL_SOCKET_BUFFER_SIZE];
630 struct nlattr *props;
631 struct nlattr *attrs;
632 struct opt *opt;
633 struct opt opts[] = {
634 { "link", OPT_KEYVAL, NULL },
635 { NULL }
636 };
637
638 if (strcmp(cmd->cmd, PRIORITY_STR) == 0)
639 prop = TIPC_NLA_PROP_PRIO;
640 else if ((strcmp(cmd->cmd, TOLERANCE_STR) == 0))
641 prop = TIPC_NLA_PROP_TOL;
642 else if ((strcmp(cmd->cmd, WINDOW_STR) == 0))
643 prop = TIPC_NLA_PROP_WIN;
644 else
645 return -EINVAL;
646
647 if (help_flag) {
648 (cmd->help)(cmdl);
649 return -EINVAL;
650 }
651
652 if (cmdl->optind >= cmdl->argc) {
653 fprintf(stderr, "error, missing value\n");
654 return -EINVAL;
655 }
656 val = atoi(shift_cmdl(cmdl));
657
658 if (parse_opts(opts, cmdl) < 0)
659 return -EINVAL;
660
661 nlh = msg_init(buf, TIPC_NL_LINK_SET);
662 if (!nlh) {
663 fprintf(stderr, "error, message initialisation failed\n");
664 return -1;
665 }
666 attrs = mnl_attr_nest_start(nlh, TIPC_NLA_LINK);
667
668 opt = get_opt(opts, "link");
669 if (!opt) {
670 fprintf(stderr, "error, missing link\n");
671 return -EINVAL;
672 }
673 mnl_attr_put_strz(nlh, TIPC_NLA_LINK_NAME, opt->val);
674
675 props = mnl_attr_nest_start(nlh, TIPC_NLA_LINK_PROP);
676 mnl_attr_put_u32(nlh, prop, val);
677 mnl_attr_nest_end(nlh, props);
678
679 mnl_attr_nest_end(nlh, attrs);
680
681 return msg_doit(nlh, link_get_cb, &prop);
682}
683
684static void cmd_link_set_bcast_help(struct cmdl *cmdl)
685{
686 fprintf(stderr, "Usage: %s link set broadcast PROPERTY\n\n"
687 "PROPERTIES\n"
688 " BROADCAST - Forces all multicast traffic to be\n"
689 " transmitted via broadcast only,\n"
690 " irrespective of cluster size and number\n"
691 " of destinations\n\n"
692 " REPLICAST - Forces all multicast traffic to be\n"
693 " transmitted via replicast only,\n"
694 " irrespective of cluster size and number\n"
695 " of destinations\n\n"
696 " AUTOSELECT - Auto switching to broadcast or replicast\n"
697 " depending on cluster size and destination\n"
698 " node number\n\n"
699 " ratio SIZE - Set the AUTOSELECT criteria, percentage of\n"
700 " destination nodes vs cluster size\n\n",
701 cmdl->argv[0]);
702}
703
704static int cmd_link_set_bcast(struct nlmsghdr *nlh, const struct cmd *cmd,
705 struct cmdl *cmdl, void *data)
706{
707 char buf[MNL_SOCKET_BUFFER_SIZE];
708 struct nlattr *props;
709 struct nlattr *attrs;
710 struct opt *opt;
711 struct opt opts[] = {
712 { "BROADCAST", OPT_KEY, NULL },
713 { "REPLICAST", OPT_KEY, NULL },
714 { "AUTOSELECT", OPT_KEY, NULL },
715 { "ratio", OPT_KEYVAL, NULL },
716 { NULL }
717 };
718 int method = 0;
719
720 if (help_flag) {
721 (cmd->help)(cmdl);
722 return -EINVAL;
723 }
724
725 if (parse_opts(opts, cmdl) < 0)
726 return -EINVAL;
727
728 for (opt = opts; opt->key; opt++)
729 if (opt->val)
730 break;
731
732 if (!opt || !opt->key) {
733 (cmd->help)(cmdl);
734 return -EINVAL;
735 }
736
737 nlh = msg_init(buf, TIPC_NL_LINK_SET);
738 if (!nlh) {
739 fprintf(stderr, "error, message initialisation failed\n");
740 return -1;
741 }
742
743 attrs = mnl_attr_nest_start(nlh, TIPC_NLA_LINK);
744
745 mnl_attr_put_strz(nlh, TIPC_NLA_LINK_NAME, tipc_bclink_name);
746 props = mnl_attr_nest_start(nlh, TIPC_NLA_LINK_PROP);
747
748 if (get_opt(opts, "BROADCAST"))
749 method = 0x1;
750 else if (get_opt(opts, "REPLICAST"))
751 method = 0x2;
752 else if (get_opt(opts, "AUTOSELECT"))
753 method = 0x4;
754
755 opt = get_opt(opts, "ratio");
756 if (!method && !opt) {
757 (cmd->help)(cmdl);
758 return -EINVAL;
759 }
760
761 if (method)
762 mnl_attr_put_u32(nlh, TIPC_NLA_PROP_BROADCAST, method);
763
764 if (opt)
765 mnl_attr_put_u32(nlh, TIPC_NLA_PROP_BROADCAST_RATIO,
766 atoi(opt->val));
767
768 mnl_attr_nest_end(nlh, props);
769 mnl_attr_nest_end(nlh, attrs);
770 return msg_doit(nlh, NULL, NULL);
771}
772
773static int cmd_link_set(struct nlmsghdr *nlh, const struct cmd *cmd,
774 struct cmdl *cmdl, void *data)
775{
776 const struct cmd cmds[] = {
777 { PRIORITY_STR, cmd_link_set_prop, cmd_link_set_help },
778 { TOLERANCE_STR, cmd_link_set_prop, cmd_link_set_help },
779 { WINDOW_STR, cmd_link_set_prop, cmd_link_set_help },
780 { BROADCAST_STR, cmd_link_set_bcast, cmd_link_set_bcast_help },
781 { NULL }
782 };
783
784 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
785}
786
787static int cmd_link_mon_set_prop(struct nlmsghdr *nlh, const struct cmd *cmd,
788 struct cmdl *cmdl, void *data)
789{
790 int size;
791 char buf[MNL_SOCKET_BUFFER_SIZE];
792 struct nlattr *attrs;
793
794 if (cmdl->argc != cmdl->optind + 1) {
795 fprintf(stderr, "error, missing value\n");
796 return -EINVAL;
797 }
798 size = atoi(shift_cmdl(cmdl));
799
800 nlh = msg_init(buf, TIPC_NL_MON_SET);
801 if (!nlh) {
802 fprintf(stderr, "error, message initialisation failed\n");
803 return -1;
804 }
805 attrs = mnl_attr_nest_start(nlh, TIPC_NLA_MON);
806
807 mnl_attr_put_u32(nlh, TIPC_NLA_MON_ACTIVATION_THRESHOLD, size);
808
809 mnl_attr_nest_end(nlh, attrs);
810
811 return msg_doit(nlh, NULL, NULL);
812}
813
814static int link_mon_summary_cb(const struct nlmsghdr *nlh, void *data)
815{
816 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
817 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
818 struct nlattr *attrs[TIPC_NLA_MON_MAX + 1] = {};
819
820 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
821 if (!info[TIPC_NLA_MON])
822 return MNL_CB_ERROR;
823
824 mnl_attr_parse_nested(info[TIPC_NLA_MON], parse_attrs, attrs);
825
826 open_json_object(NULL);
827 print_string(PRINT_ANY, "bearer", "\nbearer %s\n",
828 mnl_attr_get_str(attrs[TIPC_NLA_MON_BEARER_NAME]));
829
830 print_uint(PRINT_ANY, "table_generation", " table_generation %u\n",
831 mnl_attr_get_u32(attrs[TIPC_NLA_MON_LISTGEN]));
832 print_uint(PRINT_ANY, "cluster_size", " cluster_size %u\n",
833 mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEERCNT]));
834 print_string(PRINT_ANY, "algorithm", " algorithm %s\n",
835 attrs[TIPC_NLA_MON_ACTIVE] ? "overlapping-ring" : "full-mesh");
836 close_json_object();
837
838 return MNL_CB_OK;
839}
840
841static int cmd_link_mon_summary(struct nlmsghdr *nlh, const struct cmd *cmd,
842 struct cmdl *cmdl, void *data)
843{
844 char buf[MNL_SOCKET_BUFFER_SIZE];
845 int err = 0;
846
847 if (help_flag) {
848 fprintf(stderr, "Usage: %s monitor summary\n", cmdl->argv[0]);
849 return -EINVAL;
850 }
851
852 nlh = msg_init(buf, TIPC_NL_MON_GET);
853 if (!nlh) {
854 fprintf(stderr, "error, message initialisation failed\n");
855 return -1;
856 }
857
858 new_json_obj(json);
859 err = msg_dumpit(nlh, link_mon_summary_cb, NULL);
860 delete_json_obj();
861
862 return err;
863}
864
865#define STATUS_WIDTH 7
866#define MAX_NODE_WIDTH 14
867#define MAX_DOM_GEN_WIDTH 11
868#define DIRECTLY_MON_WIDTH 10
869
870#define APPL_NODE_STATUS_WIDTH 5
871
872static int map_get(uint64_t up_map, int i)
873{
874 return (up_map & (1 << i)) >> i;
875}
876
877
878
879
880static void link_mon_print_applied(uint16_t applied, uint64_t up_map)
881{
882 int i;
883
884 open_json_array(PRINT_JSON, "applied_node_status");
885 for (i = 0; i < applied; i++) {
886 char state_str[2] = {0};
887
888
889 if (i && !(i % APPL_NODE_STATUS_WIDTH))
890 print_string(PRINT_FP, NULL, "%s", ",");
891
892 sprintf(state_str, "%c", map_get(up_map, i) ? 'U' : 'D');
893 print_string(PRINT_ANY, NULL, "%s", state_str);
894 }
895 close_json_array(PRINT_JSON, "applied_node_status");
896}
897
898
899
900
901static void link_mon_print_non_applied(uint16_t applied, uint16_t member_cnt,
902 uint64_t up_map, uint32_t *members)
903{
904 int i;
905 char state;
906
907 open_json_array(PRINT_JSON, "[non_applied_node:status]");
908 print_string(PRINT_FP, NULL, " %s", "[");
909 for (i = applied; i < member_cnt; i++) {
910 char addr_str[16];
911 char full_state[17] = {0};
912
913
914 if (i != applied)
915 print_string(PRINT_FP, NULL, "%s", ",");
916
917 sprintf(addr_str, "%x:", members[i]);
918 state = map_get(up_map, i) ? 'U' : 'D';
919 sprintf(full_state, "%s%c", addr_str, state);
920 print_string(PRINT_ANY, NULL, "%s", full_state);
921 }
922 print_string(PRINT_FP, NULL, "%s", "]");
923 close_json_array(PRINT_JSON, "[non_applied_node:status]");
924}
925
926static void link_mon_print_peer_state(const uint32_t addr, const char *status,
927 const char *monitored,
928 const uint32_t dom_gen)
929{
930 char addr_str[16];
931
932 sprintf(addr_str, "%u.%u.%u", tipc_zone(addr), tipc_cluster(addr),
933 tipc_node(addr));
934 if (is_json_context()) {
935 print_string(PRINT_JSON, "node", NULL, addr_str);
936 print_string(PRINT_JSON, "status", NULL, status);
937 print_string(PRINT_JSON, "monitored", NULL, monitored);
938 print_uint(PRINT_JSON, "generation", NULL, dom_gen);
939 } else {
940 printf("%-*s", MAX_NODE_WIDTH, addr_str);
941 printf("%-*s", STATUS_WIDTH, status);
942 printf("%-*s", DIRECTLY_MON_WIDTH, monitored);
943 printf("%-*u", MAX_DOM_GEN_WIDTH, dom_gen);
944 }
945}
946
947static int link_mon_peer_list_cb(const struct nlmsghdr *nlh, void *data)
948{
949 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
950 struct nlattr *attrs[TIPC_NLA_MON_PEER_MAX + 1] = {};
951 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
952 uint16_t member_cnt;
953 uint32_t applied;
954 uint32_t dom_gen;
955 uint64_t up_map;
956 char status[16];
957 char monitored[16];
958
959 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
960 if (!info[TIPC_NLA_MON_PEER])
961 return MNL_CB_ERROR;
962
963 open_json_object(NULL);
964 mnl_attr_parse_nested(info[TIPC_NLA_MON_PEER], parse_attrs, attrs);
965
966 (attrs[TIPC_NLA_MON_PEER_LOCAL] || attrs[TIPC_NLA_MON_PEER_HEAD]) ?
967 strcpy(monitored, "direct") :
968 strcpy(monitored, "indirect");
969
970 attrs[TIPC_NLA_MON_PEER_UP] ?
971 strcpy(status, "up") :
972 strcpy(status, "down");
973
974 dom_gen = attrs[TIPC_NLA_MON_PEER_DOMGEN] ?
975 mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEER_DOMGEN]) : 0;
976
977 link_mon_print_peer_state(mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEER_ADDR]),
978 status, monitored, dom_gen);
979
980 applied = mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEER_APPLIED]);
981
982 if (!applied)
983 goto exit;
984
985 up_map = mnl_attr_get_u64(attrs[TIPC_NLA_MON_PEER_UPMAP]);
986
987 member_cnt = mnl_attr_get_payload_len(attrs[TIPC_NLA_MON_PEER_MEMBERS]);
988
989
990 member_cnt /= sizeof(uint32_t);
991
992 link_mon_print_applied(applied, up_map);
993
994 link_mon_print_non_applied(applied, member_cnt, up_map,
995 mnl_attr_get_payload(attrs[TIPC_NLA_MON_PEER_MEMBERS]));
996
997exit:
998 print_string(PRINT_FP, NULL, "\n", "");
999
1000 close_json_object();
1001 return MNL_CB_OK;
1002}
1003
1004static int link_mon_peer_list(uint32_t mon_ref)
1005{
1006 struct nlmsghdr *nlh;
1007 char buf[MNL_SOCKET_BUFFER_SIZE];
1008 struct nlattr *nest;
1009 int err = 0;
1010
1011 nlh = msg_init(buf, TIPC_NL_MON_PEER_GET);
1012 if (!nlh) {
1013 fprintf(stderr, "error, message initialisation failed\n");
1014 return -1;
1015 }
1016
1017 nest = mnl_attr_nest_start(nlh, TIPC_NLA_MON);
1018 mnl_attr_put_u32(nlh, TIPC_NLA_MON_REF, mon_ref);
1019 mnl_attr_nest_end(nlh, nest);
1020
1021 err = msg_dumpit(nlh, link_mon_peer_list_cb, NULL);
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 buf[MNL_SOCKET_BUFFER_SIZE];
1084 char bname[TIPC_MAX_BEARER_NAME] = {0};
1085 struct opt opts[] = {
1086 { "media", OPT_KEYVAL, NULL },
1087 { "device", OPT_KEYVAL, NULL },
1088 { "name", OPT_KEYVAL, NULL },
1089 { NULL }
1090 };
1091 struct tipc_sup_media sup_media[] = {
1092 { "udp", "name", cmd_link_mon_list_udp_help},
1093 { "eth", "device", cmd_link_mon_list_l2_help },
1094 { "ib", "device", cmd_link_mon_list_l2_help },
1095 { NULL, },
1096 };
1097
1098 int err;
1099
1100 if (parse_opts(opts, cmdl) < 0)
1101 return -EINVAL;
1102
1103 if (get_opt(opts, "media")) {
1104 err = cmd_get_unique_bearer_name(cmd, cmdl, opts, bname,
1105 sup_media);
1106 if (err)
1107 return err;
1108 }
1109
1110 if (help_flag) {
1111 cmd->help(cmdl);
1112 return -EINVAL;
1113 }
1114
1115 nlh = msg_init(buf, TIPC_NL_MON_GET);
1116 if (!nlh) {
1117 fprintf(stderr, "error, message initialisation failed\n");
1118 return -1;
1119 }
1120
1121 new_json_obj(json);
1122 err = msg_dumpit(nlh, link_mon_list_cb, bname);
1123 delete_json_obj();
1124 return err;
1125}
1126
1127static void cmd_link_mon_set_help(struct cmdl *cmdl)
1128{
1129 fprintf(stderr, "Usage: %s monitor set PPROPERTY\n\n"
1130 "PROPERTIES\n"
1131 " threshold SIZE - Set monitor activation threshold\n",
1132 cmdl->argv[0]);
1133}
1134
1135static int cmd_link_mon_set(struct nlmsghdr *nlh, const struct cmd *cmd,
1136 struct cmdl *cmdl, void *data)
1137{
1138 const struct cmd cmds[] = {
1139 { "threshold", cmd_link_mon_set_prop, NULL },
1140 { NULL }
1141 };
1142
1143 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
1144}
1145
1146static void cmd_link_mon_get_help(struct cmdl *cmdl)
1147{
1148 fprintf(stderr, "Usage: %s monitor get PPROPERTY\n\n"
1149 "PROPERTIES\n"
1150 " threshold - Get monitor activation threshold\n",
1151 cmdl->argv[0]);
1152}
1153
1154static int link_mon_get_cb(const struct nlmsghdr *nlh, void *data)
1155{
1156 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
1157 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
1158 struct nlattr *attrs[TIPC_NLA_MON_MAX + 1] = {};
1159
1160 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
1161 if (!info[TIPC_NLA_MON])
1162 return MNL_CB_ERROR;
1163
1164 mnl_attr_parse_nested(info[TIPC_NLA_MON], parse_attrs, attrs);
1165 if (!attrs[TIPC_NLA_MON_ACTIVATION_THRESHOLD])
1166 return MNL_CB_ERROR;
1167
1168 new_json_obj(json);
1169 print_uint(PRINT_ANY, "threshold", "%u\n",
1170 mnl_attr_get_u32(attrs[TIPC_NLA_MON_ACTIVATION_THRESHOLD]));
1171 delete_json_obj();
1172
1173 return MNL_CB_OK;
1174}
1175
1176static int cmd_link_mon_get_prop(struct nlmsghdr *nlh, const struct cmd *cmd,
1177 struct cmdl *cmdl, void *data)
1178{
1179 char buf[MNL_SOCKET_BUFFER_SIZE];
1180
1181 nlh = msg_init(buf, TIPC_NL_MON_GET);
1182 if (!nlh) {
1183 fprintf(stderr, "error, message initialisation failed\n");
1184 return -1;
1185 }
1186
1187 return msg_doit(nlh, link_mon_get_cb, NULL);
1188}
1189
1190static int cmd_link_mon_get(struct nlmsghdr *nlh, const struct cmd *cmd,
1191 struct cmdl *cmdl, void *data)
1192{
1193 const struct cmd cmds[] = {
1194 { "threshold", cmd_link_mon_get_prop, NULL},
1195 { NULL }
1196 };
1197
1198 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
1199}
1200
1201static void cmd_link_mon_help(struct cmdl *cmdl)
1202{
1203 fprintf(stderr,
1204 "Usage: %s montior COMMAND [ARGS] ...\n\n"
1205 "COMMANDS\n"
1206 " set - Set monitor properties\n"
1207 " get - Get monitor properties\n"
1208 " list - List all cluster members\n"
1209 " summary - Show local node monitor summary\n",
1210 cmdl->argv[0]);
1211}
1212
1213static int cmd_link_mon(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl,
1214 void *data)
1215{
1216 const struct cmd cmds[] = {
1217 { "set", cmd_link_mon_set, cmd_link_mon_set_help },
1218 { "get", cmd_link_mon_get, cmd_link_mon_get_help },
1219 { "list", cmd_link_mon_list, cmd_link_mon_list_help },
1220 { "summary", cmd_link_mon_summary, NULL },
1221 { NULL }
1222 };
1223
1224 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
1225}
1226
1227void cmd_link_help(struct cmdl *cmdl)
1228{
1229 fprintf(stderr,
1230 "Usage: %s link COMMAND [ARGS] ...\n"
1231 "\n"
1232 "COMMANDS\n"
1233 " list - List links\n"
1234 " get - Get various link properties\n"
1235 " set - Set various link properties\n"
1236 " statistics - Show or reset statistics\n"
1237 " monitor - Show or set link supervision\n",
1238 cmdl->argv[0]);
1239}
1240
1241int cmd_link(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl,
1242 void *data)
1243{
1244 const struct cmd cmds[] = {
1245 { "get", cmd_link_get, cmd_link_get_help },
1246 { "list", cmd_link_list, NULL },
1247 { "set", cmd_link_set, cmd_link_set_help },
1248 { "statistics", cmd_link_stat, cmd_link_stat_help },
1249 { "monitor", cmd_link_mon, cmd_link_mon_help },
1250 { NULL }
1251 };
1252
1253 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
1254}
1255