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"
179 " broadcast - Get link broadcast\n",
183 static int cmd_link_get_bcast_cb(const struct nlmsghdr
*nlh
, void *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] = {};
193 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
194 if (!info
[TIPC_NLA_LINK
])
197 mnl_attr_parse_nested(info
[TIPC_NLA_LINK
], parse_attrs
, attrs
);
198 if (!attrs
[TIPC_NLA_LINK_PROP
])
201 mnl_attr_parse_nested(attrs
[TIPC_NLA_LINK_PROP
], parse_attrs
, props
);
205 bc_mode
= mnl_attr_get_u32(props
[*prop
]);
208 open_json_object(NULL
);
211 print_string(PRINT_ANY
, "method", "%s\n", "BROADCAST");
214 print_string(PRINT_ANY
, "method", "%s\n", "REPLICAST");
217 print_string(PRINT_ANY
, "method", "%s", "AUTOSELECT");
219 open_json_object(NULL
);
220 print_uint(PRINT_ANY
, "ratio", " ratio:%u%\n",
221 mnl_attr_get_u32(props
[prop_ratio
]));
224 print_string(PRINT_ANY
, NULL
, "UNKNOWN\n", NULL
);
232 static void cmd_link_get_bcast_help(struct cmdl
*cmdl
)
234 fprintf(stderr
, "Usage: %s link get PPROPERTY\n\n"
236 " broadcast - Get link broadcast\n",
240 static int cmd_link_get_bcast(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
241 struct cmdl
*cmdl
, void *data
)
243 int prop
= TIPC_NLA_PROP_BROADCAST
;
244 char buf
[MNL_SOCKET_BUFFER_SIZE
];
245 struct nlattr
*attrs
;
252 nlh
= msg_init(buf
, TIPC_NL_LINK_GET
);
254 fprintf(stderr
, "error, message initialisation failed\n");
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
);
264 static int cmd_link_get(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
265 struct cmdl
*cmdl
, void *data
)
267 const struct cmd cmds
[] = {
268 { PRIORITY_STR
, cmd_link_get_prop
, cmd_link_get_help
},
269 { TOLERANCE_STR
, cmd_link_get_prop
, cmd_link_get_help
},
270 { WINDOW_STR
, cmd_link_get_prop
, cmd_link_get_help
},
271 { BROADCAST_STR
, cmd_link_get_bcast
, cmd_link_get_bcast_help
},
275 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
278 static void cmd_link_stat_reset_help(struct cmdl
*cmdl
)
280 fprintf(stderr
, "Usage: %s link stat reset link LINK\n\n", cmdl
->argv
[0]);
283 static int cmd_link_stat_reset(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
284 struct cmdl
*cmdl
, void *data
)
287 char buf
[MNL_SOCKET_BUFFER_SIZE
];
290 struct opt opts
[] = {
291 { "link", OPT_KEYVAL
, NULL
},
300 if (parse_opts(opts
, cmdl
) != 1) {
305 nlh
= msg_init(buf
, TIPC_NL_LINK_RESET_STATS
);
307 fprintf(stderr
, "error, message initialisation failed\n");
311 opt
= get_opt(opts
, "link");
313 fprintf(stderr
, "error, missing link\n");
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
);
322 return msg_doit(nlh
, NULL
, NULL
);
325 static uint32_t perc(uint32_t count
, uint32_t total
)
327 return (count
* 100 + (total
/ 2)) / total
;
330 static int _show_link_stat(const char *name
, struct nlattr
*attrs
[],
331 struct nlattr
*prop
[], struct nlattr
*stats
[])
335 open_json_object(NULL
);
337 print_string(PRINT_ANY
, "link", "\nLink <%s>\n", name
);
338 print_string(PRINT_JSON
, "state", "", NULL
);
339 open_json_array(PRINT_JSON
, NULL
);
340 if (attrs
[TIPC_NLA_LINK_ACTIVE
])
341 print_string(PRINT_ANY
, NULL
, " %s", "ACTIVE");
342 else if (attrs
[TIPC_NLA_LINK_UP
])
343 print_string(PRINT_ANY
, NULL
, " %s", "STANDBY");
345 print_string(PRINT_ANY
, NULL
, " %s", "DEFUNCT");
346 close_json_array(PRINT_JSON
, NULL
);
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
]));
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
]));
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
]));
385 proft
= mnl_attr_get_u32(stats
[TIPC_NLA_STATS_MSG_PROF_TOT
]);
386 print_uint(PRINT_ANY
, "tx profile sample", " TX profile sample:%u",
387 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_MSG_LEN_CNT
]));
388 print_uint(PRINT_ANY
, "packets average", " packets average:%u octets\n",
389 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_MSG_LEN_TOT
]) / proft
);
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
));
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
]));
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
]));
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
]));
443 static int _show_bc_link_stat(const char *name
, struct nlattr
*prop
[],
444 struct nlattr
*stats
[])
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
]));
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
]));
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
]));
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
]));
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
]));
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
]));
506 static int link_stat_show_cb(const struct nlmsghdr
*nlh
, void *data
)
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] = {};
516 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
517 if (!info
[TIPC_NLA_LINK
])
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
])
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
);
528 name
= mnl_attr_get_str(attrs
[TIPC_NLA_LINK_NAME
]);
530 /* If a link is passed, skip all but that link */
531 if (link
&& (strcmp(name
, link
) != 0))
534 if (attrs
[TIPC_NLA_LINK_BROADCAST
]) {
535 return _show_bc_link_stat(name
, prop
, stats
);
538 return _show_link_stat(name
, attrs
, prop
, stats
);
541 static void cmd_link_stat_show_help(struct cmdl
*cmdl
)
543 fprintf(stderr
, "Usage: %s link stat show [ link LINK ]\n",
547 static int cmd_link_stat_show(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
548 struct cmdl
*cmdl
, void *data
)
551 char buf
[MNL_SOCKET_BUFFER_SIZE
];
553 struct opt opts
[] = {
554 { "link", OPT_KEYVAL
, NULL
},
564 nlh
= msg_init(buf
, TIPC_NL_LINK_GET
);
566 fprintf(stderr
, "error, message initialisation failed\n");
570 if (parse_opts(opts
, cmdl
) < 0)
573 opt
= get_opt(opts
, "link");
578 err
= msg_dumpit(nlh
, link_stat_show_cb
, link
);
583 static void cmd_link_stat_help(struct cmdl
*cmdl
)
585 fprintf(stderr
, "Usage: %s link stat COMMAND [ARGS]\n\n"
587 " reset - Reset link statistics for link\n"
588 " show - Get link priority\n",
592 static int cmd_link_stat(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
593 struct cmdl
*cmdl
, void *data
)
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
},
601 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
604 static void cmd_link_set_help(struct cmdl
*cmdl
)
606 fprintf(stderr
, "Usage: %s link set PPROPERTY link LINK\n\n"
608 " tolerance TOLERANCE - Set link tolerance\n"
609 " priority PRIORITY - Set link priority\n"
610 " window WINDOW - Set link window\n"
611 " broadcast BROADCAST - Set link broadcast\n",
615 static int cmd_link_set_prop(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
616 struct cmdl
*cmdl
, void *data
)
620 char buf
[MNL_SOCKET_BUFFER_SIZE
];
621 struct nlattr
*props
;
622 struct nlattr
*attrs
;
624 struct opt opts
[] = {
625 { "link", OPT_KEYVAL
, NULL
},
629 if (strcmp(cmd
->cmd
, PRIORITY_STR
) == 0)
630 prop
= TIPC_NLA_PROP_PRIO
;
631 else if ((strcmp(cmd
->cmd
, TOLERANCE_STR
) == 0))
632 prop
= TIPC_NLA_PROP_TOL
;
633 else if ((strcmp(cmd
->cmd
, WINDOW_STR
) == 0))
634 prop
= TIPC_NLA_PROP_WIN
;
643 if (cmdl
->optind
>= cmdl
->argc
) {
644 fprintf(stderr
, "error, missing value\n");
647 val
= atoi(shift_cmdl(cmdl
));
649 if (parse_opts(opts
, cmdl
) < 0)
652 nlh
= msg_init(buf
, TIPC_NL_LINK_SET
);
654 fprintf(stderr
, "error, message initialisation failed\n");
657 attrs
= mnl_attr_nest_start(nlh
, TIPC_NLA_LINK
);
659 opt
= get_opt(opts
, "link");
661 fprintf(stderr
, "error, missing link\n");
664 mnl_attr_put_strz(nlh
, TIPC_NLA_LINK_NAME
, opt
->val
);
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
);
670 mnl_attr_nest_end(nlh
, attrs
);
672 return msg_doit(nlh
, link_get_cb
, &prop
);
675 static void cmd_link_set_bcast_help(struct cmdl
*cmdl
)
677 fprintf(stderr
, "Usage: %s link set broadcast PROPERTY\n\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"
690 " ratio SIZE - Set the AUTOSELECT criteria, percentage of\n"
691 " destination nodes vs cluster size\n\n",
695 static int cmd_link_set_bcast(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
696 struct cmdl
*cmdl
, void *data
)
698 char buf
[MNL_SOCKET_BUFFER_SIZE
];
699 struct nlattr
*props
;
700 struct nlattr
*attrs
;
702 struct opt opts
[] = {
703 { "BROADCAST", OPT_KEY
, NULL
},
704 { "REPLICAST", OPT_KEY
, NULL
},
705 { "AUTOSELECT", OPT_KEY
, NULL
},
706 { "ratio", OPT_KEYVAL
, NULL
},
716 if (parse_opts(opts
, cmdl
) < 0)
719 for (opt
= opts
; opt
->key
; opt
++)
723 if (!opt
|| !opt
->key
) {
728 nlh
= msg_init(buf
, TIPC_NL_LINK_SET
);
730 fprintf(stderr
, "error, message initialisation failed\n");
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
);
739 if (get_opt(opts
, "BROADCAST"))
741 else if (get_opt(opts
, "REPLICAST"))
743 else if (get_opt(opts
, "AUTOSELECT"))
746 opt
= get_opt(opts
, "ratio");
747 if (!method
&& !opt
) {
753 mnl_attr_put_u32(nlh
, TIPC_NLA_PROP_BROADCAST
, method
);
756 mnl_attr_put_u32(nlh
, TIPC_NLA_PROP_BROADCAST_RATIO
,
759 mnl_attr_nest_end(nlh
, props
);
760 mnl_attr_nest_end(nlh
, attrs
);
761 return msg_doit(nlh
, NULL
, NULL
);
764 static int cmd_link_set(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
765 struct cmdl
*cmdl
, void *data
)
767 const struct cmd cmds
[] = {
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
},
771 { BROADCAST_STR
, cmd_link_set_bcast
, cmd_link_set_bcast_help
},
775 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
778 static int cmd_link_mon_set_prop(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
779 struct cmdl
*cmdl
, void *data
)
782 char buf
[MNL_SOCKET_BUFFER_SIZE
];
783 struct nlattr
*attrs
;
785 if (cmdl
->argc
!= cmdl
->optind
+ 1) {
786 fprintf(stderr
, "error, missing value\n");
789 size
= atoi(shift_cmdl(cmdl
));
791 nlh
= msg_init(buf
, TIPC_NL_MON_SET
);
793 fprintf(stderr
, "error, message initialisation failed\n");
796 attrs
= mnl_attr_nest_start(nlh
, TIPC_NLA_MON
);
798 mnl_attr_put_u32(nlh
, TIPC_NLA_MON_ACTIVATION_THRESHOLD
, size
);
800 mnl_attr_nest_end(nlh
, attrs
);
802 return msg_doit(nlh
, NULL
, NULL
);
805 static int link_mon_summary_cb(const struct nlmsghdr
*nlh
, void *data
)
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] = {};
811 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
812 if (!info
[TIPC_NLA_MON
])
815 mnl_attr_parse_nested(info
[TIPC_NLA_MON
], parse_attrs
, attrs
);
817 open_json_object(NULL
);
818 print_string(PRINT_ANY
, "bearer", "\nbearer %s\n",
819 mnl_attr_get_str(attrs
[TIPC_NLA_MON_BEARER_NAME
]));
821 print_uint(PRINT_ANY
, "table_generation", " table_generation %u\n",
822 mnl_attr_get_u32(attrs
[TIPC_NLA_MON_LISTGEN
]));
823 print_uint(PRINT_ANY
, "cluster_size", " cluster_size %u\n",
824 mnl_attr_get_u32(attrs
[TIPC_NLA_MON_PEERCNT
]));
825 print_string(PRINT_ANY
, "algorithm", " algorithm %s\n",
826 attrs
[TIPC_NLA_MON_ACTIVE
] ? "overlapping-ring" : "full-mesh");
832 static int cmd_link_mon_summary(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
833 struct cmdl
*cmdl
, void *data
)
835 char buf
[MNL_SOCKET_BUFFER_SIZE
];
839 fprintf(stderr
, "Usage: %s monitor summary\n", cmdl
->argv
[0]);
843 nlh
= msg_init(buf
, TIPC_NL_MON_GET
);
845 fprintf(stderr
, "error, message initialisation failed\n");
850 err
= msg_dumpit(nlh
, link_mon_summary_cb
, NULL
);
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
861 #define APPL_NODE_STATUS_WIDTH 5
863 static int map_get(uint64_t up_map
, int i
)
865 return (up_map
& (1 << i
)) >> i
;
868 /* print the applied members, since we know the the members
869 * are listed in ascending order, we print only the state
871 static void link_mon_print_applied(uint16_t applied
, uint64_t up_map
)
875 open_json_array(PRINT_JSON
, "applied_node_status");
876 for (i
= 0; i
< applied
; i
++) {
877 char state_str
[2] = {0};
879 /* print the delimiter for every -n- entry */
880 if (i
&& !(i
% APPL_NODE_STATUS_WIDTH
))
881 print_string(PRINT_FP
, NULL
, "%s", ",");
883 sprintf(state_str
, "%c", map_get(up_map
, i
) ? 'U' : 'D');
884 print_string(PRINT_ANY
, NULL
, "%s", state_str
);
886 close_json_array(PRINT_JSON
, "applied_node_status");
889 /* print the non applied members, since we don't know
890 * the members, we print them along with the state
892 static void link_mon_print_non_applied(uint16_t applied
, uint16_t member_cnt
,
893 uint64_t up_map
, uint32_t *members
)
898 open_json_array(PRINT_JSON
, "[non_applied_node:status]");
899 print_string(PRINT_FP
, NULL
, " %s", "[");
900 for (i
= applied
; i
< member_cnt
; i
++) {
902 char full_state
[17] = {0};
904 /* print the delimiter for every entry */
906 print_string(PRINT_FP
, NULL
, "%s", ",");
908 sprintf(addr_str
, "%x:", members
[i
]);
909 state
= map_get(up_map
, i
) ? 'U' : 'D';
910 sprintf(full_state
, "%s%c", addr_str
, state
);
911 print_string(PRINT_ANY
, NULL
, "%s", full_state
);
913 print_string(PRINT_FP
, NULL
, "%s", "]");
914 close_json_array(PRINT_JSON
, "[non_applied_node:status]");
917 static void link_mon_print_peer_state(const uint32_t addr
, const char *status
,
918 const char *monitored
,
919 const uint32_t dom_gen
)
923 sprintf(addr_str
, "%u.%u.%u", tipc_zone(addr
), tipc_cluster(addr
),
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
);
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
);
938 static int link_mon_peer_list_cb(const struct nlmsghdr
*nlh
, void *data
)
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] = {};
950 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
951 if (!info
[TIPC_NLA_MON_PEER
])
954 open_json_object(NULL
);
955 mnl_attr_parse_nested(info
[TIPC_NLA_MON_PEER
], parse_attrs
, attrs
);
957 (attrs
[TIPC_NLA_MON_PEER_LOCAL
] || attrs
[TIPC_NLA_MON_PEER_HEAD
]) ?
958 strcpy(monitored
, "direct") :
959 strcpy(monitored
, "indirect");
961 attrs
[TIPC_NLA_MON_PEER_UP
] ?
962 strcpy(status
, "up") :
963 strcpy(status
, "down");
965 dom_gen
= attrs
[TIPC_NLA_MON_PEER_DOMGEN
] ?
966 mnl_attr_get_u32(attrs
[TIPC_NLA_MON_PEER_DOMGEN
]) : 0;
968 link_mon_print_peer_state(mnl_attr_get_u32(attrs
[TIPC_NLA_MON_PEER_ADDR
]),
969 status
, monitored
, dom_gen
);
971 applied
= mnl_attr_get_u32(attrs
[TIPC_NLA_MON_PEER_APPLIED
]);
976 up_map
= mnl_attr_get_u64(attrs
[TIPC_NLA_MON_PEER_UPMAP
]);
978 member_cnt
= mnl_attr_get_payload_len(attrs
[TIPC_NLA_MON_PEER_MEMBERS
]);
980 /* each tipc address occupies 4 bytes of payload, hence compensate it */
981 member_cnt
/= sizeof(uint32_t);
983 link_mon_print_applied(applied
, up_map
);
985 link_mon_print_non_applied(applied
, member_cnt
, up_map
,
986 mnl_attr_get_payload(attrs
[TIPC_NLA_MON_PEER_MEMBERS
]));
989 print_string(PRINT_FP
, NULL
, "\n", "");
995 static int link_mon_peer_list(uint32_t mon_ref
)
997 struct nlmsghdr
*nlh
;
998 char buf
[MNL_SOCKET_BUFFER_SIZE
];
1002 nlh
= msg_init(buf
, TIPC_NL_MON_PEER_GET
);
1004 fprintf(stderr
, "error, message initialisation failed\n");
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
);
1012 err
= msg_dumpit(nlh
, link_mon_peer_list_cb
, NULL
);
1016 static int link_mon_list_cb(const struct nlmsghdr
*nlh
, void *data
)
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
;
1023 const char title
[] =
1024 "node status monitored generation applied_node_status [non_applied_node:status]";
1026 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
1027 if (!info
[TIPC_NLA_MON
])
1028 return MNL_CB_ERROR
;
1030 mnl_attr_parse_nested(info
[TIPC_NLA_MON
], parse_attrs
, attrs
);
1032 bname
= mnl_attr_get_str(attrs
[TIPC_NLA_MON_BEARER_NAME
]);
1034 if (*req_bearer
&& (strcmp(req_bearer
, bname
) != 0))
1037 open_json_object(NULL
);
1038 print_string(PRINT_ANY
, "bearer", "\nbearer %s\n", bname
);
1039 print_string(PRINT_FP
, NULL
, "%s\n", title
);
1041 open_json_array(PRINT_JSON
, bname
);
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
]));
1044 close_json_array(PRINT_JSON
, bname
);
1046 close_json_object();
1050 static void cmd_link_mon_list_help(struct cmdl
*cmdl
)
1052 fprintf(stderr
, "Usage: %s monitor list [ media MEDIA ARGS...]\n\n",
1054 print_bearer_media();
1057 static void cmd_link_mon_list_l2_help(struct cmdl
*cmdl
, char *media
)
1060 "Usage: %s monitor list media %s device DEVICE [OPTIONS]\n",
1061 cmdl
->argv
[0], media
);
1064 static void cmd_link_mon_list_udp_help(struct cmdl
*cmdl
, char *media
)
1067 "Usage: %s monitor list media udp name NAME\n\n",
1071 static int cmd_link_mon_list(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
1072 struct cmdl
*cmdl
, void *data
)
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
},
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
},
1091 if (parse_opts(opts
, cmdl
) < 0)
1094 if (get_opt(opts
, "media")) {
1095 err
= cmd_get_unique_bearer_name(cmd
, cmdl
, opts
, bname
,
1106 nlh
= msg_init(buf
, TIPC_NL_MON_GET
);
1108 fprintf(stderr
, "error, message initialisation failed\n");
1113 err
= msg_dumpit(nlh
, link_mon_list_cb
, bname
);
1118 static void cmd_link_mon_set_help(struct cmdl
*cmdl
)
1120 fprintf(stderr
, "Usage: %s monitor set PPROPERTY\n\n"
1122 " threshold SIZE - Set monitor activation threshold\n",
1126 static int cmd_link_mon_set(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
1127 struct cmdl
*cmdl
, void *data
)
1129 const struct cmd cmds
[] = {
1130 { "threshold", cmd_link_mon_set_prop
, NULL
},
1134 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
1137 static void cmd_link_mon_get_help(struct cmdl
*cmdl
)
1139 fprintf(stderr
, "Usage: %s monitor get PPROPERTY\n\n"
1141 " threshold - Get monitor activation threshold\n",
1145 static int link_mon_get_cb(const struct nlmsghdr
*nlh
, void *data
)
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] = {};
1151 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
1152 if (!info
[TIPC_NLA_MON
])
1153 return MNL_CB_ERROR
;
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
;
1160 print_uint(PRINT_ANY
, "threshold", "%u\n",
1161 mnl_attr_get_u32(attrs
[TIPC_NLA_MON_ACTIVATION_THRESHOLD
]));
1167 static int cmd_link_mon_get_prop(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
1168 struct cmdl
*cmdl
, void *data
)
1170 char buf
[MNL_SOCKET_BUFFER_SIZE
];
1172 nlh
= msg_init(buf
, TIPC_NL_MON_GET
);
1174 fprintf(stderr
, "error, message initialisation failed\n");
1178 return msg_doit(nlh
, link_mon_get_cb
, NULL
);
1181 static int cmd_link_mon_get(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
1182 struct cmdl
*cmdl
, void *data
)
1184 const struct cmd cmds
[] = {
1185 { "threshold", cmd_link_mon_get_prop
, NULL
},
1189 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
1192 static void cmd_link_mon_help(struct cmdl
*cmdl
)
1195 "Usage: %s montior COMMAND [ARGS] ...\n\n"
1197 " set - Set monitor properties\n"
1198 " get - Get monitor properties\n"
1199 " list - List all cluster members\n"
1200 " summary - Show local node monitor summary\n",
1204 static int cmd_link_mon(struct nlmsghdr
*nlh
, const struct cmd
*cmd
, struct cmdl
*cmdl
,
1207 const struct cmd cmds
[] = {
1208 { "set", cmd_link_mon_set
, cmd_link_mon_set_help
},
1209 { "get", cmd_link_mon_get
, cmd_link_mon_get_help
},
1210 { "list", cmd_link_mon_list
, cmd_link_mon_list_help
},
1211 { "summary", cmd_link_mon_summary
, NULL
},
1215 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
1218 void cmd_link_help(struct cmdl
*cmdl
)
1221 "Usage: %s link COMMAND [ARGS] ...\n"
1224 " list - List links\n"
1225 " get - Get various link properties\n"
1226 " set - Set various link properties\n"
1227 " statistics - Show or reset statistics\n"
1228 " monitor - Show or set link supervision\n",
1232 int cmd_link(struct nlmsghdr
*nlh
, const struct cmd
*cmd
, struct cmdl
*cmdl
,
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
},
1240 { "monitor", cmd_link_mon
, cmd_link_mon_help
},
1244 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);