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