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