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"
32 static int link_list_cb(const struct nlmsghdr
*nlh
, void *data
)
34 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
35 struct nlattr
*info
[TIPC_NLA_MAX
+ 1] = {};
36 struct nlattr
*attrs
[TIPC_NLA_LINK_MAX
+ 1] = {};
38 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
39 if (!info
[TIPC_NLA_LINK
])
42 mnl_attr_parse_nested(info
[TIPC_NLA_LINK
], parse_attrs
, attrs
);
43 if (!attrs
[TIPC_NLA_LINK_NAME
])
46 print_string(PRINT_FP
, NULL
, "%s: ",
47 mnl_attr_get_str(attrs
[TIPC_NLA_LINK_NAME
]));
48 if (attrs
[TIPC_NLA_LINK_UP
])
49 print_string(PRINT_ANY
,
50 mnl_attr_get_str(attrs
[TIPC_NLA_LINK_NAME
]),"%s\n", "up");
52 print_string(PRINT_ANY
,
53 mnl_attr_get_str(attrs
[TIPC_NLA_LINK_NAME
]), "%s\n", "down");
57 static int cmd_link_list(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
58 struct cmdl
*cmdl
, void *data
)
60 char buf
[MNL_SOCKET_BUFFER_SIZE
];
64 fprintf(stderr
, "Usage: %s link list\n", cmdl
->argv
[0]);
68 nlh
= msg_init(buf
, TIPC_NL_LINK_GET
);
70 fprintf(stderr
, "error, message initialisation failed\n");
75 open_json_object(NULL
);
76 err
= msg_dumpit(nlh
, link_list_cb
, NULL
);
82 static int link_get_cb(const struct nlmsghdr
*nlh
, void *data
)
85 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
86 struct nlattr
*info
[TIPC_NLA_MAX
+ 1] = {};
87 struct nlattr
*attrs
[TIPC_NLA_LINK_MAX
+ 1] = {};
88 struct nlattr
*props
[TIPC_NLA_PROP_MAX
+ 1] = {};
90 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
91 if (!info
[TIPC_NLA_LINK
])
94 mnl_attr_parse_nested(info
[TIPC_NLA_LINK
], parse_attrs
, attrs
);
95 if (!attrs
[TIPC_NLA_LINK_PROP
])
98 mnl_attr_parse_nested(attrs
[TIPC_NLA_LINK_PROP
], parse_attrs
, props
);
103 open_json_object(NULL
);
105 case TIPC_NLA_PROP_PRIO
:
106 print_uint(PRINT_ANY
, PRIORITY_STR
, "%u\n", mnl_attr_get_u32(props
[*prop
]));
108 case TIPC_NLA_PROP_TOL
:
109 print_uint(PRINT_ANY
, TOLERANCE_STR
, "%u\n", mnl_attr_get_u32(props
[*prop
]));
111 case TIPC_NLA_PROP_WIN
:
112 print_uint(PRINT_ANY
, WINDOW_STR
, "%u\n", mnl_attr_get_u32(props
[*prop
]));
122 static int cmd_link_get_prop(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
123 struct cmdl
*cmdl
, void *data
)
126 char buf
[MNL_SOCKET_BUFFER_SIZE
];
127 struct nlattr
*attrs
;
129 struct opt opts
[] = {
130 { "link", OPT_KEYVAL
, NULL
},
134 if (strcmp(cmd
->cmd
, PRIORITY_STR
) == 0)
135 prop
= TIPC_NLA_PROP_PRIO
;
136 else if ((strcmp(cmd
->cmd
, TOLERANCE_STR
) == 0))
137 prop
= TIPC_NLA_PROP_TOL
;
138 else if ((strcmp(cmd
->cmd
, WINDOW_STR
) == 0))
139 prop
= TIPC_NLA_PROP_WIN
;
148 if (parse_opts(opts
, cmdl
) < 0)
151 nlh
= msg_init(buf
, TIPC_NL_LINK_GET
);
153 fprintf(stderr
, "error, message initialisation failed\n");
157 opt
= get_opt(opts
, "link");
159 fprintf(stderr
, "error, missing link\n");
162 attrs
= mnl_attr_nest_start(nlh
, TIPC_NLA_LINK
);
163 mnl_attr_put_strz(nlh
, TIPC_NLA_LINK_NAME
, opt
->val
);
164 mnl_attr_nest_end(nlh
, attrs
);
166 return msg_doit(nlh
, link_get_cb
, &prop
);
169 static void cmd_link_get_help(struct cmdl
*cmdl
)
171 fprintf(stderr
, "Usage: %s link get PPROPERTY link LINK\n\n"
173 " tolerance - Get link tolerance\n"
174 " priority - Get link priority\n"
175 " window - Get link window\n",
179 static int cmd_link_get(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
180 struct cmdl
*cmdl
, void *data
)
182 const struct cmd cmds
[] = {
183 { PRIORITY_STR
, cmd_link_get_prop
, cmd_link_get_help
},
184 { TOLERANCE_STR
, cmd_link_get_prop
, cmd_link_get_help
},
185 { WINDOW_STR
, cmd_link_get_prop
, cmd_link_get_help
},
189 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
192 static void cmd_link_stat_reset_help(struct cmdl
*cmdl
)
194 fprintf(stderr
, "Usage: %s link stat reset link LINK\n\n", cmdl
->argv
[0]);
197 static int cmd_link_stat_reset(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
198 struct cmdl
*cmdl
, void *data
)
201 char buf
[MNL_SOCKET_BUFFER_SIZE
];
204 struct opt opts
[] = {
205 { "link", OPT_KEYVAL
, NULL
},
214 if (parse_opts(opts
, cmdl
) != 1) {
219 nlh
= msg_init(buf
, TIPC_NL_LINK_RESET_STATS
);
221 fprintf(stderr
, "error, message initialisation failed\n");
225 opt
= get_opt(opts
, "link");
227 fprintf(stderr
, "error, missing link\n");
232 nest
= mnl_attr_nest_start(nlh
, TIPC_NLA_LINK
);
233 mnl_attr_put_strz(nlh
, TIPC_NLA_LINK_NAME
, link
);
234 mnl_attr_nest_end(nlh
, nest
);
236 return msg_doit(nlh
, NULL
, NULL
);
239 static uint32_t perc(uint32_t count
, uint32_t total
)
241 return (count
* 100 + (total
/ 2)) / total
;
244 static int _show_link_stat(const char *name
, struct nlattr
*attrs
[],
245 struct nlattr
*prop
[], struct nlattr
*stats
[])
249 open_json_object(NULL
);
251 print_string(PRINT_ANY
, "link", "\nLink <%s>\n", name
);
252 print_string(PRINT_JSON
, "state", "", NULL
);
253 open_json_array(PRINT_JSON
, NULL
);
254 if (attrs
[TIPC_NLA_LINK_ACTIVE
])
255 print_string(PRINT_ANY
, NULL
, " %s", "ACTIVE");
256 else if (attrs
[TIPC_NLA_LINK_UP
])
257 print_string(PRINT_ANY
, NULL
, " %s", "STANDBY");
259 print_string(PRINT_ANY
, NULL
, " %s", "DEFUNCT");
260 close_json_array(PRINT_JSON
, NULL
);
262 print_uint(PRINT_ANY
, "mtu", " MTU:%u",
263 mnl_attr_get_u32(attrs
[TIPC_NLA_LINK_MTU
]));
264 print_uint(PRINT_ANY
, PRIORITY_STR
, " Priority:%u",
265 mnl_attr_get_u32(prop
[TIPC_NLA_PROP_PRIO
]));
266 print_uint(PRINT_ANY
, TOLERANCE_STR
, " Tolerance:%u ms",
267 mnl_attr_get_u32(prop
[TIPC_NLA_PROP_TOL
]));
268 print_uint(PRINT_ANY
, WINDOW_STR
, " Window:%u packets\n",
269 mnl_attr_get_u32(prop
[TIPC_NLA_PROP_WIN
]));
271 open_json_object("rx packets");
272 print_uint(PRINT_ANY
, "rx packets", " RX packets:%u",
273 mnl_attr_get_u32(attrs
[TIPC_NLA_LINK_RX
]) -
274 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_RX_INFO
]));
275 print_uint(PRINT_ANY
, "fragments", " fragments:%u",
276 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_RX_FRAGMENTS
]));
277 print_uint(PRINT_ANY
, "fragmented", "/%u",
278 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_RX_FRAGMENTED
]));
279 print_uint(PRINT_ANY
, "bundles", " bundles:%u",
280 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_RX_BUNDLES
]));
281 print_uint(PRINT_ANY
, "bundled", "/%u\n",
282 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_RX_BUNDLED
]));
285 open_json_object("tx packets");
286 print_uint(PRINT_ANY
, "tx packets", " TX packets:%u",
287 mnl_attr_get_u32(attrs
[TIPC_NLA_LINK_TX
]) -
288 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_TX_INFO
]));
289 print_uint(PRINT_ANY
, "fragments", " fragments:%u",
290 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_TX_FRAGMENTS
]));
291 print_uint(PRINT_ANY
, "fragmented", "/%u",
292 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_TX_FRAGMENTED
]));
293 print_uint(PRINT_ANY
, "bundles", " bundles:%u",
294 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_TX_BUNDLES
]));
295 print_uint(PRINT_ANY
, "bundled", "/%u\n",
296 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_TX_BUNDLED
]));
299 proft
= mnl_attr_get_u32(stats
[TIPC_NLA_STATS_MSG_PROF_TOT
]);
300 print_uint(PRINT_ANY
, "tx profile sample", " TX profile sample:%u",
301 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_MSG_LEN_CNT
]));
302 print_uint(PRINT_ANY
, "packets average", " packets average:%u octets\n",
303 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_MSG_LEN_TOT
]) / proft
);
305 print_uint(PRINT_ANY
, "0-64", " 0-64:%u%%",
306 perc(mnl_attr_get_u32(stats
[TIPC_NLA_STATS_MSG_LEN_P0
]), proft
));
307 print_uint(PRINT_ANY
, "-256", " -256:%u%%",
308 perc(mnl_attr_get_u32(stats
[TIPC_NLA_STATS_MSG_LEN_P1
]), proft
));
309 print_uint(PRINT_ANY
, "-1024", " -1024:%u%%",
310 perc(mnl_attr_get_u32(stats
[TIPC_NLA_STATS_MSG_LEN_P2
]), proft
));
311 print_uint(PRINT_ANY
, "-4096", " -4096:%u%%",
312 perc(mnl_attr_get_u32(stats
[TIPC_NLA_STATS_MSG_LEN_P3
]), proft
));
313 print_uint(PRINT_ANY
, "-16384", " -16384:%u%%",
314 perc(mnl_attr_get_u32(stats
[TIPC_NLA_STATS_MSG_LEN_P4
]), proft
));
315 print_uint(PRINT_ANY
, "-32768", " -32768:%u%%",
316 perc(mnl_attr_get_u32(stats
[TIPC_NLA_STATS_MSG_LEN_P5
]), proft
));
317 print_uint(PRINT_ANY
, "-66000", " -66000:%u%%\n",
318 perc(mnl_attr_get_u32(stats
[TIPC_NLA_STATS_MSG_LEN_P6
]), proft
));
320 open_json_object("rx states");
321 print_uint(PRINT_ANY
, "rx states", " RX states:%u",
322 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_RX_STATES
]));
323 print_uint(PRINT_ANY
, "probes", " probes:%u",
324 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_RX_PROBES
]));
325 print_uint(PRINT_ANY
, "naks", " naks:%u",
326 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_RX_NACKS
]));
327 print_uint(PRINT_ANY
, "defs", " defs:%u",
328 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_RX_DEFERRED
]));
329 print_uint(PRINT_ANY
, "dups", " dups:%u\n",
330 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_DUPLICATES
]));
333 open_json_object("tx states");
334 print_uint(PRINT_ANY
, "tx states", " TX states:%u",
335 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_TX_STATES
]));
336 print_uint(PRINT_ANY
, "probes", " probes:%u",
337 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_TX_PROBES
]));
338 print_uint(PRINT_ANY
, "naks", " naks:%u",
339 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_TX_NACKS
]));
340 print_uint(PRINT_ANY
, "acks", " acks:%u",
341 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_TX_ACKS
]));
342 print_uint(PRINT_ANY
, "retrans", " retrans:%u\n",
343 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_RETRANSMITTED
]));
346 print_uint(PRINT_ANY
, "congestion link", " Congestion link:%u",
347 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_LINK_CONGS
]));
348 print_uint(PRINT_ANY
, "send queue max", " Send queue max:%u",
349 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_MAX_QUEUE
]));
350 print_uint(PRINT_ANY
, "avg", " avg:%u\n",
351 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_AVG_QUEUE
]));
357 static int _show_bc_link_stat(const char *name
, struct nlattr
*prop
[],
358 struct nlattr
*stats
[])
360 open_json_object(NULL
);
361 print_string(PRINT_ANY
, "link", "Link <%s>\n", name
);
362 print_uint(PRINT_ANY
, WINDOW_STR
, " Window:%u packets\n",
363 mnl_attr_get_u32(prop
[TIPC_NLA_PROP_WIN
]));
365 open_json_object("rx packets");
366 print_uint(PRINT_ANY
, "rx packets", " RX packets:%u",
367 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_RX_INFO
]));
368 print_uint(PRINT_ANY
, "fragments", " fragments:%u",
369 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_RX_FRAGMENTS
]));
370 print_uint(PRINT_ANY
, "fragmented", "/%u",
371 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_RX_FRAGMENTED
]));
372 print_uint(PRINT_ANY
, "bundles", " bundles:%u",
373 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_RX_BUNDLES
]));
374 print_uint(PRINT_ANY
, "bundled", "/%u\n",
375 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_RX_BUNDLED
]));
378 open_json_object("tx packets");
379 print_uint(PRINT_ANY
, "tx packets", " TX packets:%u",
380 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_TX_INFO
]));
381 print_uint(PRINT_ANY
, "fragments", " fragments:%u",
382 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_TX_FRAGMENTS
]));
383 print_uint(PRINT_ANY
, "fragmented", "/%u",
384 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_TX_FRAGMENTED
]));
385 print_uint(PRINT_ANY
, "bundles", " bundles:%u",
386 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_TX_BUNDLES
]));
387 print_uint(PRINT_ANY
, "bundled", "/%u\n",
388 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_TX_BUNDLED
]));
391 open_json_object("rx naks");
392 print_uint(PRINT_ANY
, "rx naks", " RX naks:%u",
393 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_RX_NACKS
]));
394 print_uint(PRINT_ANY
, "defs", " defs:%u",
395 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_RX_DEFERRED
]));
396 print_uint(PRINT_ANY
, "dups", " dups:%u\n",
397 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_DUPLICATES
]));
400 open_json_object("tx naks");
401 print_uint(PRINT_ANY
, "tx naks", " TX naks:%u",
402 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_TX_NACKS
]));
403 print_uint(PRINT_ANY
, "acks", " acks:%u",
404 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_TX_ACKS
]));
405 print_uint(PRINT_ANY
, "retrans", " retrans:%u\n",
406 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_RETRANSMITTED
]));
409 print_uint(PRINT_ANY
, "congestion link", " Congestion link:%u",
410 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_LINK_CONGS
]));
411 print_uint(PRINT_ANY
, "send queue max", " Send queue max:%u",
412 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_MAX_QUEUE
]));
413 print_uint(PRINT_ANY
, "avg", " avg:%u\n",
414 mnl_attr_get_u32(stats
[TIPC_NLA_STATS_AVG_QUEUE
]));
420 static int link_stat_show_cb(const struct nlmsghdr
*nlh
, void *data
)
423 const char *link
= data
;
424 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
425 struct nlattr
*info
[TIPC_NLA_MAX
+ 1] = {};
426 struct nlattr
*attrs
[TIPC_NLA_LINK_MAX
+ 1] = {};
427 struct nlattr
*prop
[TIPC_NLA_PROP_MAX
+ 1] = {};
428 struct nlattr
*stats
[TIPC_NLA_STATS_MAX
+ 1] = {};
430 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
431 if (!info
[TIPC_NLA_LINK
])
434 mnl_attr_parse_nested(info
[TIPC_NLA_LINK
], parse_attrs
, attrs
);
435 if (!attrs
[TIPC_NLA_LINK_NAME
] || !attrs
[TIPC_NLA_LINK_PROP
] ||
436 !attrs
[TIPC_NLA_LINK_STATS
])
439 mnl_attr_parse_nested(attrs
[TIPC_NLA_LINK_PROP
], parse_attrs
, prop
);
440 mnl_attr_parse_nested(attrs
[TIPC_NLA_LINK_STATS
], parse_attrs
, stats
);
442 name
= mnl_attr_get_str(attrs
[TIPC_NLA_LINK_NAME
]);
444 /* If a link is passed, skip all but that link */
445 if (link
&& (strcmp(name
, link
) != 0))
448 if (attrs
[TIPC_NLA_LINK_BROADCAST
]) {
449 return _show_bc_link_stat(name
, prop
, stats
);
452 return _show_link_stat(name
, attrs
, prop
, stats
);
455 static void cmd_link_stat_show_help(struct cmdl
*cmdl
)
457 fprintf(stderr
, "Usage: %s link stat show [ link LINK ]\n",
461 static int cmd_link_stat_show(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
462 struct cmdl
*cmdl
, void *data
)
465 char buf
[MNL_SOCKET_BUFFER_SIZE
];
467 struct opt opts
[] = {
468 { "link", OPT_KEYVAL
, NULL
},
478 nlh
= msg_init(buf
, TIPC_NL_LINK_GET
);
480 fprintf(stderr
, "error, message initialisation failed\n");
484 if (parse_opts(opts
, cmdl
) < 0)
487 opt
= get_opt(opts
, "link");
492 err
= msg_dumpit(nlh
, link_stat_show_cb
, link
);
497 static void cmd_link_stat_help(struct cmdl
*cmdl
)
499 fprintf(stderr
, "Usage: %s link stat COMMAND [ARGS]\n\n"
501 " reset - Reset link statistics for link\n"
502 " show - Get link priority\n",
506 static int cmd_link_stat(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
507 struct cmdl
*cmdl
, void *data
)
509 const struct cmd cmds
[] = {
510 { "reset", cmd_link_stat_reset
, cmd_link_stat_reset_help
},
511 { "show", cmd_link_stat_show
, cmd_link_stat_show_help
},
515 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
518 static void cmd_link_set_help(struct cmdl
*cmdl
)
520 fprintf(stderr
, "Usage: %s link set PPROPERTY link LINK\n\n"
522 " tolerance TOLERANCE - Set link tolerance\n"
523 " priority PRIORITY - Set link priority\n"
524 " window WINDOW - Set link window\n",
528 static int cmd_link_set_prop(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
529 struct cmdl
*cmdl
, void *data
)
533 char buf
[MNL_SOCKET_BUFFER_SIZE
];
534 struct nlattr
*props
;
535 struct nlattr
*attrs
;
537 struct opt opts
[] = {
538 { "link", OPT_KEYVAL
, NULL
},
542 if (strcmp(cmd
->cmd
, PRIORITY_STR
) == 0)
543 prop
= TIPC_NLA_PROP_PRIO
;
544 else if ((strcmp(cmd
->cmd
, TOLERANCE_STR
) == 0))
545 prop
= TIPC_NLA_PROP_TOL
;
546 else if ((strcmp(cmd
->cmd
, WINDOW_STR
) == 0))
547 prop
= TIPC_NLA_PROP_WIN
;
556 if (cmdl
->optind
>= cmdl
->argc
) {
557 fprintf(stderr
, "error, missing value\n");
560 val
= atoi(shift_cmdl(cmdl
));
562 if (parse_opts(opts
, cmdl
) < 0)
565 nlh
= msg_init(buf
, TIPC_NL_LINK_SET
);
567 fprintf(stderr
, "error, message initialisation failed\n");
570 attrs
= mnl_attr_nest_start(nlh
, TIPC_NLA_LINK
);
572 opt
= get_opt(opts
, "link");
574 fprintf(stderr
, "error, missing link\n");
577 mnl_attr_put_strz(nlh
, TIPC_NLA_LINK_NAME
, opt
->val
);
579 props
= mnl_attr_nest_start(nlh
, TIPC_NLA_LINK_PROP
);
580 mnl_attr_put_u32(nlh
, prop
, val
);
581 mnl_attr_nest_end(nlh
, props
);
583 mnl_attr_nest_end(nlh
, attrs
);
585 return msg_doit(nlh
, link_get_cb
, &prop
);
588 static int cmd_link_set(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
589 struct cmdl
*cmdl
, void *data
)
591 const struct cmd cmds
[] = {
592 { PRIORITY_STR
, cmd_link_set_prop
, cmd_link_set_help
},
593 { TOLERANCE_STR
, cmd_link_set_prop
, cmd_link_set_help
},
594 { WINDOW_STR
, cmd_link_set_prop
, cmd_link_set_help
},
598 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
601 static int cmd_link_mon_set_prop(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
602 struct cmdl
*cmdl
, void *data
)
605 char buf
[MNL_SOCKET_BUFFER_SIZE
];
606 struct nlattr
*attrs
;
608 if (cmdl
->argc
!= cmdl
->optind
+ 1) {
609 fprintf(stderr
, "error, missing value\n");
612 size
= atoi(shift_cmdl(cmdl
));
614 nlh
= msg_init(buf
, TIPC_NL_MON_SET
);
616 fprintf(stderr
, "error, message initialisation failed\n");
619 attrs
= mnl_attr_nest_start(nlh
, TIPC_NLA_MON
);
621 mnl_attr_put_u32(nlh
, TIPC_NLA_MON_ACTIVATION_THRESHOLD
, size
);
623 mnl_attr_nest_end(nlh
, attrs
);
625 return msg_doit(nlh
, NULL
, NULL
);
628 static int link_mon_summary_cb(const struct nlmsghdr
*nlh
, void *data
)
630 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
631 struct nlattr
*info
[TIPC_NLA_MAX
+ 1] = {};
632 struct nlattr
*attrs
[TIPC_NLA_MON_MAX
+ 1] = {};
634 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
635 if (!info
[TIPC_NLA_MON
])
638 mnl_attr_parse_nested(info
[TIPC_NLA_MON
], parse_attrs
, attrs
);
640 open_json_object(NULL
);
641 print_string(PRINT_ANY
, "bearer", "\nbearer %s\n",
642 mnl_attr_get_str(attrs
[TIPC_NLA_MON_BEARER_NAME
]));
644 print_uint(PRINT_ANY
, "table_generation", " table_generation %u\n",
645 mnl_attr_get_u32(attrs
[TIPC_NLA_MON_LISTGEN
]));
646 print_uint(PRINT_ANY
, "cluster_size", " cluster_size %u\n",
647 mnl_attr_get_u32(attrs
[TIPC_NLA_MON_PEERCNT
]));
648 print_string(PRINT_ANY
, "algorithm", " algorithm %s\n",
649 attrs
[TIPC_NLA_MON_ACTIVE
] ? "overlapping-ring" : "full-mesh");
655 static int cmd_link_mon_summary(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
656 struct cmdl
*cmdl
, void *data
)
658 char buf
[MNL_SOCKET_BUFFER_SIZE
];
662 fprintf(stderr
, "Usage: %s monitor summary\n", cmdl
->argv
[0]);
666 nlh
= msg_init(buf
, TIPC_NL_MON_GET
);
668 fprintf(stderr
, "error, message initialisation failed\n");
673 err
= msg_dumpit(nlh
, link_mon_summary_cb
, NULL
);
679 #define STATUS_WIDTH 7
680 #define MAX_NODE_WIDTH 14 /* 255.4095.4095 */
681 #define MAX_DOM_GEN_WIDTH 11 /* 65535 */
682 #define DIRECTLY_MON_WIDTH 10
684 #define APPL_NODE_STATUS_WIDTH 5
686 static int map_get(uint64_t up_map
, int i
)
688 return (up_map
& (1 << i
)) >> i
;
691 /* print the applied members, since we know the the members
692 * are listed in ascending order, we print only the state
694 static void link_mon_print_applied(uint16_t applied
, uint64_t up_map
)
698 open_json_array(PRINT_JSON
, "applied_node_status");
699 for (i
= 0; i
< applied
; i
++) {
700 char state_str
[2] = {0};
702 /* print the delimiter for every -n- entry */
703 if (i
&& !(i
% APPL_NODE_STATUS_WIDTH
))
704 print_string(PRINT_FP
, NULL
, "%s", ",");
706 sprintf(state_str
, "%c", map_get(up_map
, i
) ? 'U' : 'D');
707 print_string(PRINT_ANY
, NULL
, "%s", state_str
);
709 close_json_array(PRINT_JSON
, "applied_node_status");
712 /* print the non applied members, since we don't know
713 * the members, we print them along with the state
715 static void link_mon_print_non_applied(uint16_t applied
, uint16_t member_cnt
,
716 uint64_t up_map
, uint32_t *members
)
721 open_json_array(PRINT_JSON
, "[non_applied_node:status]");
722 print_string(PRINT_FP
, NULL
, " %s", "[");
723 for (i
= applied
; i
< member_cnt
; i
++) {
725 char full_state
[17] = {0};
727 /* print the delimiter for every entry */
729 print_string(PRINT_FP
, NULL
, "%s", ",");
731 sprintf(addr_str
, "%x:", members
[i
]);
732 state
= map_get(up_map
, i
) ? 'U' : 'D';
733 sprintf(full_state
, "%s%c", addr_str
, state
);
734 print_string(PRINT_ANY
, NULL
, "%s", full_state
);
736 print_string(PRINT_FP
, NULL
, "%s", "]");
737 close_json_array(PRINT_JSON
, "[non_applied_node:status]");
740 static void link_mon_print_peer_state(const uint32_t addr
, const char *status
,
741 const char *monitored
,
742 const uint32_t dom_gen
)
746 sprintf(addr_str
, "%u.%u.%u", tipc_zone(addr
), tipc_cluster(addr
),
748 if (is_json_context()) {
749 print_string(PRINT_JSON
, "node", NULL
, addr_str
);
750 print_string(PRINT_JSON
, "status", NULL
, status
);
751 print_string(PRINT_JSON
, "monitored", NULL
, monitored
);
752 print_uint(PRINT_JSON
, "generation", NULL
, dom_gen
);
754 printf("%-*s", MAX_NODE_WIDTH
, addr_str
);
755 printf("%-*s", STATUS_WIDTH
, status
);
756 printf("%-*s", DIRECTLY_MON_WIDTH
, monitored
);
757 printf("%-*u", MAX_DOM_GEN_WIDTH
, dom_gen
);
761 static int link_mon_peer_list_cb(const struct nlmsghdr
*nlh
, void *data
)
763 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
764 struct nlattr
*attrs
[TIPC_NLA_MON_PEER_MAX
+ 1] = {};
765 struct nlattr
*info
[TIPC_NLA_MAX
+ 1] = {};
773 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
774 if (!info
[TIPC_NLA_MON_PEER
])
777 open_json_object(NULL
);
778 mnl_attr_parse_nested(info
[TIPC_NLA_MON_PEER
], parse_attrs
, attrs
);
780 (attrs
[TIPC_NLA_MON_PEER_LOCAL
] || attrs
[TIPC_NLA_MON_PEER_HEAD
]) ?
781 strcpy(monitored
, "direct") :
782 strcpy(monitored
, "indirect");
784 attrs
[TIPC_NLA_MON_PEER_UP
] ?
785 strcpy(status
, "up") :
786 strcpy(status
, "down");
788 dom_gen
= attrs
[TIPC_NLA_MON_PEER_DOMGEN
] ?
789 mnl_attr_get_u32(attrs
[TIPC_NLA_MON_PEER_DOMGEN
]) : 0;
791 link_mon_print_peer_state(mnl_attr_get_u32(attrs
[TIPC_NLA_MON_PEER_ADDR
]),
792 status
, monitored
, dom_gen
);
794 applied
= mnl_attr_get_u32(attrs
[TIPC_NLA_MON_PEER_APPLIED
]);
799 up_map
= mnl_attr_get_u64(attrs
[TIPC_NLA_MON_PEER_UPMAP
]);
801 member_cnt
= mnl_attr_get_payload_len(attrs
[TIPC_NLA_MON_PEER_MEMBERS
]);
803 /* each tipc address occupies 4 bytes of payload, hence compensate it */
804 member_cnt
/= sizeof(uint32_t);
806 link_mon_print_applied(applied
, up_map
);
808 link_mon_print_non_applied(applied
, member_cnt
, up_map
,
809 mnl_attr_get_payload(attrs
[TIPC_NLA_MON_PEER_MEMBERS
]));
812 print_string(PRINT_FP
, NULL
, "\n", "");
818 static int link_mon_peer_list(uint32_t mon_ref
)
820 struct nlmsghdr
*nlh
;
821 char buf
[MNL_SOCKET_BUFFER_SIZE
];
825 nlh
= msg_init(buf
, TIPC_NL_MON_PEER_GET
);
827 fprintf(stderr
, "error, message initialisation failed\n");
831 nest
= mnl_attr_nest_start(nlh
, TIPC_NLA_MON
);
832 mnl_attr_put_u32(nlh
, TIPC_NLA_MON_REF
, mon_ref
);
833 mnl_attr_nest_end(nlh
, nest
);
835 err
= msg_dumpit(nlh
, link_mon_peer_list_cb
, NULL
);
839 static int link_mon_list_cb(const struct nlmsghdr
*nlh
, void *data
)
841 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
842 struct nlattr
*info
[TIPC_NLA_MAX
+ 1] = {};
843 struct nlattr
*attrs
[TIPC_NLA_MON_MAX
+ 1] = {};
844 char *req_bearer
= data
;
847 "node status monitored generation applied_node_status [non_applied_node:status]";
849 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
850 if (!info
[TIPC_NLA_MON
])
853 mnl_attr_parse_nested(info
[TIPC_NLA_MON
], parse_attrs
, attrs
);
855 bname
= mnl_attr_get_str(attrs
[TIPC_NLA_MON_BEARER_NAME
]);
857 if (*req_bearer
&& (strcmp(req_bearer
, bname
) != 0))
860 open_json_object(NULL
);
861 print_string(PRINT_ANY
, "bearer", "\nbearer %s\n", bname
);
862 print_string(PRINT_FP
, NULL
, "%s\n", title
);
864 open_json_array(PRINT_JSON
, bname
);
865 if (mnl_attr_get_u32(attrs
[TIPC_NLA_MON_PEERCNT
]))
866 link_mon_peer_list(mnl_attr_get_u32(attrs
[TIPC_NLA_MON_REF
]));
867 close_json_array(PRINT_JSON
, bname
);
873 static void cmd_link_mon_list_help(struct cmdl
*cmdl
)
875 fprintf(stderr
, "Usage: %s monitor list [ media MEDIA ARGS...]\n\n",
877 print_bearer_media();
880 static void cmd_link_mon_list_l2_help(struct cmdl
*cmdl
, char *media
)
883 "Usage: %s monitor list media %s device DEVICE [OPTIONS]\n",
884 cmdl
->argv
[0], media
);
887 static void cmd_link_mon_list_udp_help(struct cmdl
*cmdl
, char *media
)
890 "Usage: %s monitor list media udp name NAME\n\n",
894 static int cmd_link_mon_list(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
895 struct cmdl
*cmdl
, void *data
)
897 char buf
[MNL_SOCKET_BUFFER_SIZE
];
898 char bname
[TIPC_MAX_BEARER_NAME
] = {0};
899 struct opt opts
[] = {
900 { "media", OPT_KEYVAL
, NULL
},
901 { "device", OPT_KEYVAL
, NULL
},
902 { "name", OPT_KEYVAL
, NULL
},
905 struct tipc_sup_media sup_media
[] = {
906 { "udp", "name", cmd_link_mon_list_udp_help
},
907 { "eth", "device", cmd_link_mon_list_l2_help
},
908 { "ib", "device", cmd_link_mon_list_l2_help
},
914 if (parse_opts(opts
, cmdl
) < 0)
917 if (get_opt(opts
, "media")) {
918 err
= cmd_get_unique_bearer_name(cmd
, cmdl
, opts
, bname
,
929 nlh
= msg_init(buf
, TIPC_NL_MON_GET
);
931 fprintf(stderr
, "error, message initialisation failed\n");
936 err
= msg_dumpit(nlh
, link_mon_list_cb
, bname
);
941 static void cmd_link_mon_set_help(struct cmdl
*cmdl
)
943 fprintf(stderr
, "Usage: %s monitor set PPROPERTY\n\n"
945 " threshold SIZE - Set monitor activation threshold\n",
949 static int cmd_link_mon_set(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
950 struct cmdl
*cmdl
, void *data
)
952 const struct cmd cmds
[] = {
953 { "threshold", cmd_link_mon_set_prop
, NULL
},
957 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
960 static void cmd_link_mon_get_help(struct cmdl
*cmdl
)
962 fprintf(stderr
, "Usage: %s monitor get PPROPERTY\n\n"
964 " threshold - Get monitor activation threshold\n",
968 static int link_mon_get_cb(const struct nlmsghdr
*nlh
, void *data
)
970 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
971 struct nlattr
*info
[TIPC_NLA_MAX
+ 1] = {};
972 struct nlattr
*attrs
[TIPC_NLA_MON_MAX
+ 1] = {};
974 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
975 if (!info
[TIPC_NLA_MON
])
978 mnl_attr_parse_nested(info
[TIPC_NLA_MON
], parse_attrs
, attrs
);
979 if (!attrs
[TIPC_NLA_MON_ACTIVATION_THRESHOLD
])
983 print_uint(PRINT_ANY
, "threshold", "%u\n",
984 mnl_attr_get_u32(attrs
[TIPC_NLA_MON_ACTIVATION_THRESHOLD
]));
990 static int cmd_link_mon_get_prop(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
991 struct cmdl
*cmdl
, void *data
)
993 char buf
[MNL_SOCKET_BUFFER_SIZE
];
995 nlh
= msg_init(buf
, TIPC_NL_MON_GET
);
997 fprintf(stderr
, "error, message initialisation failed\n");
1001 return msg_doit(nlh
, link_mon_get_cb
, NULL
);
1004 static int cmd_link_mon_get(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
1005 struct cmdl
*cmdl
, void *data
)
1007 const struct cmd cmds
[] = {
1008 { "threshold", cmd_link_mon_get_prop
, NULL
},
1012 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
1015 static void cmd_link_mon_help(struct cmdl
*cmdl
)
1018 "Usage: %s montior COMMAND [ARGS] ...\n\n"
1020 " set - Set monitor properties\n"
1021 " get - Get monitor properties\n"
1022 " list - List all cluster members\n"
1023 " summary - Show local node monitor summary\n",
1027 static int cmd_link_mon(struct nlmsghdr
*nlh
, const struct cmd
*cmd
, struct cmdl
*cmdl
,
1030 const struct cmd cmds
[] = {
1031 { "set", cmd_link_mon_set
, cmd_link_mon_set_help
},
1032 { "get", cmd_link_mon_get
, cmd_link_mon_get_help
},
1033 { "list", cmd_link_mon_list
, cmd_link_mon_list_help
},
1034 { "summary", cmd_link_mon_summary
, NULL
},
1038 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
1041 void cmd_link_help(struct cmdl
*cmdl
)
1044 "Usage: %s link COMMAND [ARGS] ...\n"
1047 " list - List links\n"
1048 " get - Get various link properties\n"
1049 " set - Set various link properties\n"
1050 " statistics - Show or reset statistics\n"
1051 " monitor - Show or set link supervision\n",
1055 int cmd_link(struct nlmsghdr
*nlh
, const struct cmd
*cmd
, struct cmdl
*cmdl
,
1058 const struct cmd cmds
[] = {
1059 { "get", cmd_link_get
, cmd_link_get_help
},
1060 { "list", cmd_link_list
, NULL
},
1061 { "set", cmd_link_set
, cmd_link_set_help
},
1062 { "statistics", cmd_link_stat
, cmd_link_stat_help
},
1063 { "monitor", cmd_link_mon
, cmd_link_mon_help
},
1067 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);