2 * link.c TIPC link functionality.
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.
9 * Authors: Richard Alpe <richard.alpe@ericsson.com>
17 #include <linux/tipc_netlink.h>
18 #include <linux/tipc.h>
19 #include <linux/genetlink.h>
20 #include <libmnl/libmnl.h>
28 #define PRIORITY_STR "priority"
29 #define TOLERANCE_STR "tolerance"
30 #define WINDOW_STR "window"
31 #define BROADCAST_STR "broadcast"
33 static const char tipc_bclink_name
[] = "broadcast-link";
35 static int link_list_cb(const struct nlmsghdr
*nlh
, void *data
)
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] = {};
41 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
42 if (!info
[TIPC_NLA_LINK
])
45 mnl_attr_parse_nested(info
[TIPC_NLA_LINK
], parse_attrs
, attrs
);
46 if (!attrs
[TIPC_NLA_LINK_NAME
])
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");
55 print_string(PRINT_ANY
,
56 mnl_attr_get_str(attrs
[TIPC_NLA_LINK_NAME
]), "%s\n", "down");
60 static int cmd_link_list(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
61 struct cmdl
*cmdl
, void *data
)
63 char buf
[MNL_SOCKET_BUFFER_SIZE
];
67 fprintf(stderr
, "Usage: %s link list\n", cmdl
->argv
[0]);
71 nlh
= msg_init(buf
, TIPC_NL_LINK_GET
);
73 fprintf(stderr
, "error, message initialisation failed\n");
78 open_json_object(NULL
);
79 err
= msg_dumpit(nlh
, link_list_cb
, NULL
);
85 static int link_get_cb(const struct nlmsghdr
*nlh
, void *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] = {};
93 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
94 if (!info
[TIPC_NLA_LINK
])
97 mnl_attr_parse_nested(info
[TIPC_NLA_LINK
], parse_attrs
, attrs
);
98 if (!attrs
[TIPC_NLA_LINK_PROP
])
101 mnl_attr_parse_nested(attrs
[TIPC_NLA_LINK_PROP
], parse_attrs
, props
);
106 open_json_object(NULL
);
108 case TIPC_NLA_PROP_PRIO
:
109 print_uint(PRINT_ANY
, PRIORITY_STR
, "%u\n", mnl_attr_get_u32(props
[*prop
]));
111 case TIPC_NLA_PROP_TOL
:
112 print_uint(PRINT_ANY
, TOLERANCE_STR
, "%u\n", mnl_attr_get_u32(props
[*prop
]));
114 case TIPC_NLA_PROP_WIN
:
115 print_uint(PRINT_ANY
, WINDOW_STR
, "%u\n", mnl_attr_get_u32(props
[*prop
]));
125 static int cmd_link_get_prop(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
126 struct cmdl
*cmdl
, void *data
)
129 char buf
[MNL_SOCKET_BUFFER_SIZE
];
130 struct nlattr
*attrs
;
132 struct opt opts
[] = {
133 { "link", OPT_KEYVAL
, NULL
},
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
;
151 if (parse_opts(opts
, cmdl
) < 0)
154 nlh
= msg_init(buf
, TIPC_NL_LINK_GET
);
156 fprintf(stderr
, "error, message initialisation failed\n");
160 opt
= get_opt(opts
, "link");
162 fprintf(stderr
, "error, missing link\n");
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
);
169 return msg_doit(nlh
, link_get_cb
, &prop
);
172 static void cmd_link_get_help(struct cmdl
*cmdl
)
174 fprintf(stderr
, "Usage: %s link get PPROPERTY link LINK\n\n"
176 " tolerance - Get link tolerance\n"
177 " priority - Get link priority\n"
178 " window - Get link window\n",
182 static int cmd_link_get(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
183 struct cmdl
*cmdl
, void *data
)
185 const struct cmd cmds
[] = {
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
},
192 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
195 static void cmd_link_stat_reset_help(struct cmdl
*cmdl
)
197 fprintf(stderr
, "Usage: %s link stat reset link LINK\n\n", cmdl
->argv
[0]);
200 static int cmd_link_stat_reset(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
201 struct cmdl
*cmdl
, void *data
)
204 char buf
[MNL_SOCKET_BUFFER_SIZE
];
207 struct opt opts
[] = {
208 { "link", OPT_KEYVAL
, NULL
},
217 if (parse_opts(opts
, cmdl
) != 1) {
222 nlh
= msg_init(buf
, TIPC_NL_LINK_RESET_STATS
);
224 fprintf(stderr
, "error, message initialisation failed\n");
228 opt
= get_opt(opts
, "link");
230 fprintf(stderr
, "error, missing link\n");
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
);
239 return msg_doit(nlh
, NULL
, NULL
);
242 static uint32_t perc(uint32_t count
, uint32_t total
)
244 return (count
* 100 + (total
/ 2)) / total
;
247 static int _show_link_stat(const char *name
, struct nlattr
*attrs
[],
248 struct nlattr
*prop
[], struct nlattr
*stats
[])
252 open_json_object(NULL
);
254 print_string(PRINT_ANY
, "link", "\nLink <%s>\n", name
);
255 print_string(PRINT_JSON
, "state", "", NULL
);
256 open_json_array(PRINT_JSON
, NULL
);
257 if (attrs
[TIPC_NLA_LINK_ACTIVE
])
258 print_string(PRINT_ANY
, NULL
, " %s", "ACTIVE");
259 else if (attrs
[TIPC_NLA_LINK_UP
])
260 print_string(PRINT_ANY
, NULL
, " %s", "STANDBY");
262 print_string(PRINT_ANY
, NULL
, " %s", "DEFUNCT");
263 close_json_array(PRINT_JSON
, NULL
);
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
]));
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
]));
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
]));
302 proft
= mnl_attr_get_u32(stats
[TIPC_NLA_STATS_MSG_PROF_TOT
]);
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
);
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
));
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
]));
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
]));
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
]));
360 static int _show_bc_link_stat(const char *name
, struct nlattr
*prop
[],
361 struct nlattr
*stats
[])
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
]));
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
]));
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
]));
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
]));
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
]));
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
]));
423 static int link_stat_show_cb(const struct nlmsghdr
*nlh
, void *data
)
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] = {};
433 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
434 if (!info
[TIPC_NLA_LINK
])
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
])
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
);
445 name
= mnl_attr_get_str(attrs
[TIPC_NLA_LINK_NAME
]);
447 /* If a link is passed, skip all but that link */
448 if (link
&& (strcmp(name
, link
) != 0))
451 if (attrs
[TIPC_NLA_LINK_BROADCAST
]) {
452 return _show_bc_link_stat(name
, prop
, stats
);
455 return _show_link_stat(name
, attrs
, prop
, stats
);
458 static void cmd_link_stat_show_help(struct cmdl
*cmdl
)
460 fprintf(stderr
, "Usage: %s link stat show [ link LINK ]\n",
464 static int cmd_link_stat_show(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
465 struct cmdl
*cmdl
, void *data
)
468 char buf
[MNL_SOCKET_BUFFER_SIZE
];
470 struct opt opts
[] = {
471 { "link", OPT_KEYVAL
, NULL
},
481 nlh
= msg_init(buf
, TIPC_NL_LINK_GET
);
483 fprintf(stderr
, "error, message initialisation failed\n");
487 if (parse_opts(opts
, cmdl
) < 0)
490 opt
= get_opt(opts
, "link");
495 err
= msg_dumpit(nlh
, link_stat_show_cb
, link
);
500 static void cmd_link_stat_help(struct cmdl
*cmdl
)
502 fprintf(stderr
, "Usage: %s link stat COMMAND [ARGS]\n\n"
504 " reset - Reset link statistics for link\n"
505 " show - Get link priority\n",
509 static int cmd_link_stat(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
510 struct cmdl
*cmdl
, void *data
)
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
},
518 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
521 static void cmd_link_set_help(struct cmdl
*cmdl
)
523 fprintf(stderr
, "Usage: %s link set PPROPERTY link LINK\n\n"
525 " tolerance TOLERANCE - Set link tolerance\n"
526 " priority PRIORITY - Set link priority\n"
527 " window WINDOW - Set link window\n"
528 " broadcast BROADCAST - Set link broadcast\n",
532 static int cmd_link_set_prop(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
533 struct cmdl
*cmdl
, void *data
)
537 char buf
[MNL_SOCKET_BUFFER_SIZE
];
538 struct nlattr
*props
;
539 struct nlattr
*attrs
;
541 struct opt opts
[] = {
542 { "link", OPT_KEYVAL
, NULL
},
546 if (strcmp(cmd
->cmd
, PRIORITY_STR
) == 0)
547 prop
= TIPC_NLA_PROP_PRIO
;
548 else if ((strcmp(cmd
->cmd
, TOLERANCE_STR
) == 0))
549 prop
= TIPC_NLA_PROP_TOL
;
550 else if ((strcmp(cmd
->cmd
, WINDOW_STR
) == 0))
551 prop
= TIPC_NLA_PROP_WIN
;
560 if (cmdl
->optind
>= cmdl
->argc
) {
561 fprintf(stderr
, "error, missing value\n");
564 val
= atoi(shift_cmdl(cmdl
));
566 if (parse_opts(opts
, cmdl
) < 0)
569 nlh
= msg_init(buf
, TIPC_NL_LINK_SET
);
571 fprintf(stderr
, "error, message initialisation failed\n");
574 attrs
= mnl_attr_nest_start(nlh
, TIPC_NLA_LINK
);
576 opt
= get_opt(opts
, "link");
578 fprintf(stderr
, "error, missing link\n");
581 mnl_attr_put_strz(nlh
, TIPC_NLA_LINK_NAME
, opt
->val
);
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
);
587 mnl_attr_nest_end(nlh
, attrs
);
589 return msg_doit(nlh
, link_get_cb
, &prop
);
592 static void cmd_link_set_bcast_help(struct cmdl
*cmdl
)
594 fprintf(stderr
, "Usage: %s link set broadcast PROPERTY\n\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"
607 " ratio SIZE - Set the AUTOSELECT criteria, percentage of\n"
608 " destination nodes vs cluster size\n\n",
612 static int cmd_link_set_bcast(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
613 struct cmdl
*cmdl
, void *data
)
615 char buf
[MNL_SOCKET_BUFFER_SIZE
];
616 struct nlattr
*props
;
617 struct nlattr
*attrs
;
619 struct opt opts
[] = {
620 { "BROADCAST", OPT_KEY
, NULL
},
621 { "REPLICAST", OPT_KEY
, NULL
},
622 { "AUTOSELECT", OPT_KEY
, NULL
},
623 { "ratio", OPT_KEYVAL
, NULL
},
633 if (parse_opts(opts
, cmdl
) < 0)
636 for (opt
= opts
; opt
->key
; opt
++)
640 if (!opt
|| !opt
->key
) {
645 nlh
= msg_init(buf
, TIPC_NL_LINK_SET
);
647 fprintf(stderr
, "error, message initialisation failed\n");
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
);
656 if (get_opt(opts
, "BROADCAST"))
658 else if (get_opt(opts
, "REPLICAST"))
660 else if (get_opt(opts
, "AUTOSELECT"))
663 opt
= get_opt(opts
, "ratio");
664 if (!method
&& !opt
) {
670 mnl_attr_put_u32(nlh
, TIPC_NLA_PROP_BROADCAST
, method
);
673 mnl_attr_put_u32(nlh
, TIPC_NLA_PROP_BROADCAST_RATIO
,
676 mnl_attr_nest_end(nlh
, props
);
677 mnl_attr_nest_end(nlh
, attrs
);
678 return msg_doit(nlh
, NULL
, NULL
);
681 static int cmd_link_set(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
682 struct cmdl
*cmdl
, void *data
)
684 const struct cmd cmds
[] = {
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
},
688 { BROADCAST_STR
, cmd_link_set_bcast
, cmd_link_set_bcast_help
},
692 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
695 static int cmd_link_mon_set_prop(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
696 struct cmdl
*cmdl
, void *data
)
699 char buf
[MNL_SOCKET_BUFFER_SIZE
];
700 struct nlattr
*attrs
;
702 if (cmdl
->argc
!= cmdl
->optind
+ 1) {
703 fprintf(stderr
, "error, missing value\n");
706 size
= atoi(shift_cmdl(cmdl
));
708 nlh
= msg_init(buf
, TIPC_NL_MON_SET
);
710 fprintf(stderr
, "error, message initialisation failed\n");
713 attrs
= mnl_attr_nest_start(nlh
, TIPC_NLA_MON
);
715 mnl_attr_put_u32(nlh
, TIPC_NLA_MON_ACTIVATION_THRESHOLD
, size
);
717 mnl_attr_nest_end(nlh
, attrs
);
719 return msg_doit(nlh
, NULL
, NULL
);
722 static int link_mon_summary_cb(const struct nlmsghdr
*nlh
, void *data
)
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] = {};
728 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
729 if (!info
[TIPC_NLA_MON
])
732 mnl_attr_parse_nested(info
[TIPC_NLA_MON
], parse_attrs
, attrs
);
734 open_json_object(NULL
);
735 print_string(PRINT_ANY
, "bearer", "\nbearer %s\n",
736 mnl_attr_get_str(attrs
[TIPC_NLA_MON_BEARER_NAME
]));
738 print_uint(PRINT_ANY
, "table_generation", " table_generation %u\n",
739 mnl_attr_get_u32(attrs
[TIPC_NLA_MON_LISTGEN
]));
740 print_uint(PRINT_ANY
, "cluster_size", " cluster_size %u\n",
741 mnl_attr_get_u32(attrs
[TIPC_NLA_MON_PEERCNT
]));
742 print_string(PRINT_ANY
, "algorithm", " algorithm %s\n",
743 attrs
[TIPC_NLA_MON_ACTIVE
] ? "overlapping-ring" : "full-mesh");
749 static int cmd_link_mon_summary(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
750 struct cmdl
*cmdl
, void *data
)
752 char buf
[MNL_SOCKET_BUFFER_SIZE
];
756 fprintf(stderr
, "Usage: %s monitor summary\n", cmdl
->argv
[0]);
760 nlh
= msg_init(buf
, TIPC_NL_MON_GET
);
762 fprintf(stderr
, "error, message initialisation failed\n");
767 err
= msg_dumpit(nlh
, link_mon_summary_cb
, NULL
);
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
778 #define APPL_NODE_STATUS_WIDTH 5
780 static int map_get(uint64_t up_map
, int i
)
782 return (up_map
& (1 << i
)) >> i
;
785 /* print the applied members, since we know the the members
786 * are listed in ascending order, we print only the state
788 static void link_mon_print_applied(uint16_t applied
, uint64_t up_map
)
792 open_json_array(PRINT_JSON
, "applied_node_status");
793 for (i
= 0; i
< applied
; i
++) {
794 char state_str
[2] = {0};
796 /* print the delimiter for every -n- entry */
797 if (i
&& !(i
% APPL_NODE_STATUS_WIDTH
))
798 print_string(PRINT_FP
, NULL
, "%s", ",");
800 sprintf(state_str
, "%c", map_get(up_map
, i
) ? 'U' : 'D');
801 print_string(PRINT_ANY
, NULL
, "%s", state_str
);
803 close_json_array(PRINT_JSON
, "applied_node_status");
806 /* print the non applied members, since we don't know
807 * the members, we print them along with the state
809 static void link_mon_print_non_applied(uint16_t applied
, uint16_t member_cnt
,
810 uint64_t up_map
, uint32_t *members
)
815 open_json_array(PRINT_JSON
, "[non_applied_node:status]");
816 print_string(PRINT_FP
, NULL
, " %s", "[");
817 for (i
= applied
; i
< member_cnt
; i
++) {
819 char full_state
[17] = {0};
821 /* print the delimiter for every entry */
823 print_string(PRINT_FP
, NULL
, "%s", ",");
825 sprintf(addr_str
, "%x:", members
[i
]);
826 state
= map_get(up_map
, i
) ? 'U' : 'D';
827 sprintf(full_state
, "%s%c", addr_str
, state
);
828 print_string(PRINT_ANY
, NULL
, "%s", full_state
);
830 print_string(PRINT_FP
, NULL
, "%s", "]");
831 close_json_array(PRINT_JSON
, "[non_applied_node:status]");
834 static void link_mon_print_peer_state(const uint32_t addr
, const char *status
,
835 const char *monitored
,
836 const uint32_t dom_gen
)
840 sprintf(addr_str
, "%u.%u.%u", tipc_zone(addr
), tipc_cluster(addr
),
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
);
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
);
855 static int link_mon_peer_list_cb(const struct nlmsghdr
*nlh
, void *data
)
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] = {};
867 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
868 if (!info
[TIPC_NLA_MON_PEER
])
871 open_json_object(NULL
);
872 mnl_attr_parse_nested(info
[TIPC_NLA_MON_PEER
], parse_attrs
, attrs
);
874 (attrs
[TIPC_NLA_MON_PEER_LOCAL
] || attrs
[TIPC_NLA_MON_PEER_HEAD
]) ?
875 strcpy(monitored
, "direct") :
876 strcpy(monitored
, "indirect");
878 attrs
[TIPC_NLA_MON_PEER_UP
] ?
879 strcpy(status
, "up") :
880 strcpy(status
, "down");
882 dom_gen
= attrs
[TIPC_NLA_MON_PEER_DOMGEN
] ?
883 mnl_attr_get_u32(attrs
[TIPC_NLA_MON_PEER_DOMGEN
]) : 0;
885 link_mon_print_peer_state(mnl_attr_get_u32(attrs
[TIPC_NLA_MON_PEER_ADDR
]),
886 status
, monitored
, dom_gen
);
888 applied
= mnl_attr_get_u32(attrs
[TIPC_NLA_MON_PEER_APPLIED
]);
893 up_map
= mnl_attr_get_u64(attrs
[TIPC_NLA_MON_PEER_UPMAP
]);
895 member_cnt
= mnl_attr_get_payload_len(attrs
[TIPC_NLA_MON_PEER_MEMBERS
]);
897 /* each tipc address occupies 4 bytes of payload, hence compensate it */
898 member_cnt
/= sizeof(uint32_t);
900 link_mon_print_applied(applied
, up_map
);
902 link_mon_print_non_applied(applied
, member_cnt
, up_map
,
903 mnl_attr_get_payload(attrs
[TIPC_NLA_MON_PEER_MEMBERS
]));
906 print_string(PRINT_FP
, NULL
, "\n", "");
912 static int link_mon_peer_list(uint32_t mon_ref
)
914 struct nlmsghdr
*nlh
;
915 char buf
[MNL_SOCKET_BUFFER_SIZE
];
919 nlh
= msg_init(buf
, TIPC_NL_MON_PEER_GET
);
921 fprintf(stderr
, "error, message initialisation failed\n");
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
);
929 err
= msg_dumpit(nlh
, link_mon_peer_list_cb
, NULL
);
933 static int link_mon_list_cb(const struct nlmsghdr
*nlh
, void *data
)
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
;
941 "node status monitored generation applied_node_status [non_applied_node:status]";
943 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
944 if (!info
[TIPC_NLA_MON
])
947 mnl_attr_parse_nested(info
[TIPC_NLA_MON
], parse_attrs
, attrs
);
949 bname
= mnl_attr_get_str(attrs
[TIPC_NLA_MON_BEARER_NAME
]);
951 if (*req_bearer
&& (strcmp(req_bearer
, bname
) != 0))
954 open_json_object(NULL
);
955 print_string(PRINT_ANY
, "bearer", "\nbearer %s\n", bname
);
956 print_string(PRINT_FP
, NULL
, "%s\n", title
);
958 open_json_array(PRINT_JSON
, bname
);
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
]));
961 close_json_array(PRINT_JSON
, bname
);
967 static void cmd_link_mon_list_help(struct cmdl
*cmdl
)
969 fprintf(stderr
, "Usage: %s monitor list [ media MEDIA ARGS...]\n\n",
971 print_bearer_media();
974 static void cmd_link_mon_list_l2_help(struct cmdl
*cmdl
, char *media
)
977 "Usage: %s monitor list media %s device DEVICE [OPTIONS]\n",
978 cmdl
->argv
[0], media
);
981 static void cmd_link_mon_list_udp_help(struct cmdl
*cmdl
, char *media
)
984 "Usage: %s monitor list media udp name NAME\n\n",
988 static int cmd_link_mon_list(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
989 struct cmdl
*cmdl
, void *data
)
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
},
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
},
1008 if (parse_opts(opts
, cmdl
) < 0)
1011 if (get_opt(opts
, "media")) {
1012 err
= cmd_get_unique_bearer_name(cmd
, cmdl
, opts
, bname
,
1023 nlh
= msg_init(buf
, TIPC_NL_MON_GET
);
1025 fprintf(stderr
, "error, message initialisation failed\n");
1030 err
= msg_dumpit(nlh
, link_mon_list_cb
, bname
);
1035 static void cmd_link_mon_set_help(struct cmdl
*cmdl
)
1037 fprintf(stderr
, "Usage: %s monitor set PPROPERTY\n\n"
1039 " threshold SIZE - Set monitor activation threshold\n",
1043 static int cmd_link_mon_set(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
1044 struct cmdl
*cmdl
, void *data
)
1046 const struct cmd cmds
[] = {
1047 { "threshold", cmd_link_mon_set_prop
, NULL
},
1051 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
1054 static void cmd_link_mon_get_help(struct cmdl
*cmdl
)
1056 fprintf(stderr
, "Usage: %s monitor get PPROPERTY\n\n"
1058 " threshold - Get monitor activation threshold\n",
1062 static int link_mon_get_cb(const struct nlmsghdr
*nlh
, void *data
)
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] = {};
1068 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
1069 if (!info
[TIPC_NLA_MON
])
1070 return MNL_CB_ERROR
;
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
;
1077 print_uint(PRINT_ANY
, "threshold", "%u\n",
1078 mnl_attr_get_u32(attrs
[TIPC_NLA_MON_ACTIVATION_THRESHOLD
]));
1084 static int cmd_link_mon_get_prop(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
1085 struct cmdl
*cmdl
, void *data
)
1087 char buf
[MNL_SOCKET_BUFFER_SIZE
];
1089 nlh
= msg_init(buf
, TIPC_NL_MON_GET
);
1091 fprintf(stderr
, "error, message initialisation failed\n");
1095 return msg_doit(nlh
, link_mon_get_cb
, NULL
);
1098 static int cmd_link_mon_get(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
1099 struct cmdl
*cmdl
, void *data
)
1101 const struct cmd cmds
[] = {
1102 { "threshold", cmd_link_mon_get_prop
, NULL
},
1106 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
1109 static void cmd_link_mon_help(struct cmdl
*cmdl
)
1112 "Usage: %s montior COMMAND [ARGS] ...\n\n"
1114 " set - Set monitor properties\n"
1115 " get - Get monitor properties\n"
1116 " list - List all cluster members\n"
1117 " summary - Show local node monitor summary\n",
1121 static int cmd_link_mon(struct nlmsghdr
*nlh
, const struct cmd
*cmd
, struct cmdl
*cmdl
,
1124 const struct cmd cmds
[] = {
1125 { "set", cmd_link_mon_set
, cmd_link_mon_set_help
},
1126 { "get", cmd_link_mon_get
, cmd_link_mon_get_help
},
1127 { "list", cmd_link_mon_list
, cmd_link_mon_list_help
},
1128 { "summary", cmd_link_mon_summary
, NULL
},
1132 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
1135 void cmd_link_help(struct cmdl
*cmdl
)
1138 "Usage: %s link COMMAND [ARGS] ...\n"
1141 " list - List links\n"
1142 " get - Get various link properties\n"
1143 " set - Set various link properties\n"
1144 " statistics - Show or reset statistics\n"
1145 " monitor - Show or set link supervision\n",
1149 int cmd_link(struct nlmsghdr
*nlh
, const struct cmd
*cmd
, struct cmdl
*cmdl
,
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
},
1157 { "monitor", cmd_link_mon
, cmd_link_mon_help
},
1161 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);