1f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe/*
2f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe * link.c	TIPC link functionality.
3f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe *
4f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe *		This program is free software; you can redistribute it and/or
5f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe *		modify it under the terms of the GNU General Public License
6f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe *		as published by the Free Software Foundation; either version
7f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe *		2 of the License, or (at your option) any later version.
8f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe *
9f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe * Authors:	Richard Alpe <richard.alpe@ericsson.com>
10f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe */
11f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
12f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe#include <stdio.h>
13f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe#include <stdlib.h>
14f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe#include <string.h>
15f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe#include <errno.h>
16f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
17f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe#include <linux/tipc_netlink.h>
18f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe#include <linux/tipc.h>
19f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe#include <linux/genetlink.h>
20f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe#include <libmnl/libmnl.h>
21f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
22f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe#include "cmdl.h"
23f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe#include "msg.h"
24f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe#include "link.h"
25f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
26f043759dd492897513d5aa057427bcdab8592d4bRichard Alpestatic int link_list_cb(const struct nlmsghdr *nlh, void *data)
27f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
28f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
29f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct nlattr *info[TIPC_NLA_MAX + 1] = {};
30f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1] = {};
31f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
32f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
33f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (!info[TIPC_NLA_LINK])
34f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return MNL_CB_ERROR;
35f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
36f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	mnl_attr_parse_nested(info[TIPC_NLA_LINK], parse_attrs, attrs);
37f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (!attrs[TIPC_NLA_LINK_NAME])
38f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return MNL_CB_ERROR;
39f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
40f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	printf("%s: ", mnl_attr_get_str(attrs[TIPC_NLA_LINK_NAME]));
41f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
42f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (attrs[TIPC_NLA_LINK_UP])
43f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		printf("up\n");
44f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	else
45f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		printf("down\n");
46f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
47f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	return MNL_CB_OK;
48f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
49f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
50f043759dd492897513d5aa057427bcdab8592d4bRichard Alpestatic int cmd_link_list(struct nlmsghdr *nlh, const struct cmd *cmd,
51f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe			 struct cmdl *cmdl, void *data)
52f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
53f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	char buf[MNL_SOCKET_BUFFER_SIZE];
54f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
55f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (help_flag) {
56f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		fprintf(stderr, "Usage: %s link list\n", cmdl->argv[0]);
57f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -EINVAL;
58f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	}
59f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
60f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (!(nlh = msg_init(buf, TIPC_NL_LINK_GET))) {
61f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		fprintf(stderr, "error, message initialisation failed\n");
62f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -1;
63f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	}
64f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
65f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	return msg_dumpit(nlh, link_list_cb, NULL);
66f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
67f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
68f043759dd492897513d5aa057427bcdab8592d4bRichard Alpestatic int link_get_cb(const struct nlmsghdr *nlh, void *data)
69f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
70f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	int *prop = data;
71f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
72f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct nlattr *info[TIPC_NLA_MAX + 1] = {};
73f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1] = {};
74f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct nlattr *props[TIPC_NLA_PROP_MAX + 1] = {};
75f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
76f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
77f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (!info[TIPC_NLA_LINK])
78f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return MNL_CB_ERROR;
79f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
80f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	mnl_attr_parse_nested(info[TIPC_NLA_LINK], parse_attrs, attrs);
81f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (!attrs[TIPC_NLA_LINK_PROP])
82f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return MNL_CB_ERROR;
83f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
84f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	mnl_attr_parse_nested(attrs[TIPC_NLA_LINK_PROP], parse_attrs, props);
85f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (!props[*prop])
86f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return MNL_CB_ERROR;
87f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
88f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	printf("%u\n", mnl_attr_get_u32(props[*prop]));
89f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
90f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	return MNL_CB_OK;
91f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
92f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
93f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
94f043759dd492897513d5aa057427bcdab8592d4bRichard Alpestatic int cmd_link_get_prop(struct nlmsghdr *nlh, const struct cmd *cmd,
95f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe			     struct cmdl *cmdl, void *data)
96f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
97f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	int prop;
98f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	char buf[MNL_SOCKET_BUFFER_SIZE];
99f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct opt *opt;
100f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct opt opts[] = {
101f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ "link",		NULL },
102f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ NULL }
103f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	};
104f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
105f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (strcmp(cmd->cmd, "priority") == 0)
106f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		prop = TIPC_NLA_PROP_PRIO;
107f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	else if ((strcmp(cmd->cmd, "tolerance") == 0))
108f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		prop = TIPC_NLA_PROP_TOL;
109f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	else if ((strcmp(cmd->cmd, "window") == 0))
110f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		prop = TIPC_NLA_PROP_WIN;
111f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	else
112f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -EINVAL;
113f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
114f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (help_flag) {
115f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		(cmd->help)(cmdl);
116f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -EINVAL;
117f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	}
118f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
119f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (parse_opts(opts, cmdl) < 0)
120f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -EINVAL;
121f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
122f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (!(nlh = msg_init(buf, TIPC_NL_LINK_GET))) {
123f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		fprintf(stderr, "error, message initialisation failed\n");
124f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -1;
125f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	}
126f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
127f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (!(opt = get_opt(opts, "link"))) {
128f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		fprintf(stderr, "error, missing link\n");
129f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -EINVAL;
130f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	}
131f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	mnl_attr_put_strz(nlh, TIPC_NLA_LINK_NAME, opt->val);
132f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
133f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	return msg_doit(nlh, link_get_cb, &prop);
134f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
135f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
136f043759dd492897513d5aa057427bcdab8592d4bRichard Alpestatic void cmd_link_get_help(struct cmdl *cmdl)
137f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
138f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	fprintf(stderr, "Usage: %s link get PPROPERTY link LINK\n\n"
139f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		"PROPERTIES\n"
140f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		" tolerance             - Get link tolerance\n"
141f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		" priority              - Get link priority\n"
142f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		" window                - Get link window\n",
143f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		cmdl->argv[0]);
144f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
145f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
146f043759dd492897513d5aa057427bcdab8592d4bRichard Alpestatic int cmd_link_get(struct nlmsghdr *nlh, const struct cmd *cmd,
147f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe			struct cmdl *cmdl, void *data)
148f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
149f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	const struct cmd cmds[] = {
150f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ "priority",	cmd_link_get_prop,	cmd_link_get_help },
151f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ "tolerance",	cmd_link_get_prop,	cmd_link_get_help },
152f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ "window",	cmd_link_get_prop,	cmd_link_get_help },
153f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ NULL }
154f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	};
155f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
156f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	return run_cmd(nlh, cmd, cmds, cmdl, NULL);
157f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
158f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
159f043759dd492897513d5aa057427bcdab8592d4bRichard Alpestatic void cmd_link_stat_reset_help(struct cmdl *cmdl)
160f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
161f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	fprintf(stderr, "Usage: %s link stat reset link LINK\n\n", cmdl->argv[0]);
162f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
163f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
164f043759dd492897513d5aa057427bcdab8592d4bRichard Alpestatic int cmd_link_stat_reset(struct nlmsghdr *nlh, const struct cmd *cmd,
165f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe			       struct cmdl *cmdl, void *data)
166f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
167f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	char *link;
168f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	char buf[MNL_SOCKET_BUFFER_SIZE];
169f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct opt *opt;
170f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct nlattr *nest;
171f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct opt opts[] = {
172f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ "link",		NULL },
173f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ NULL }
174f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	};
175f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
176f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (help_flag) {
177f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		(cmd->help)(cmdl);
178f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -EINVAL;
179f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	}
180f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
181f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (parse_opts(opts, cmdl) != 1) {
182f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		(cmd->help)(cmdl);
183f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -EINVAL;
184f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	}
185f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
186f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (!(nlh = msg_init(buf, TIPC_NL_LINK_RESET_STATS))) {
187f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		fprintf(stderr, "error, message initialisation failed\n");
188f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -1;
189f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	}
190f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
191f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (!(opt = get_opt(opts, "link"))) {
192f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		fprintf(stderr, "error, missing link\n");
193f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -EINVAL;
194f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	}
195f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	link = opt->val;
196f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
197f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	nest = mnl_attr_nest_start(nlh, TIPC_NLA_LINK);
198f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	mnl_attr_put_strz(nlh, TIPC_NLA_LINK_NAME, link);
199f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	mnl_attr_nest_end(nlh, nest);
200f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
201f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	return msg_doit(nlh, NULL, NULL);
202f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
203f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
204f043759dd492897513d5aa057427bcdab8592d4bRichard Alpestatic uint32_t perc(uint32_t count, uint32_t total)
205f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
206f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	return (count * 100 + (total / 2)) / total;
207f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
208f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
209f043759dd492897513d5aa057427bcdab8592d4bRichard Alpestatic int _show_link_stat(struct nlattr *attrs[], struct nlattr *prop[],
210f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe			   struct nlattr *stats[])
211f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
212f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	uint32_t proft;
213f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
214f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (attrs[TIPC_NLA_LINK_ACTIVE])
215f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		printf("  ACTIVE");
216f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	else if (attrs[TIPC_NLA_LINK_UP])
217f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		printf("  STANDBY");
218f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	else
219f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		printf("  DEFUNCT");
220f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
221f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	printf("  MTU:%u  Priority:%u  Tolerance:%u ms  Window:%u packets\n",
222f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(attrs[TIPC_NLA_LINK_MTU]),
223f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(prop[TIPC_NLA_PROP_PRIO]),
224f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(prop[TIPC_NLA_PROP_TOL]),
225f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(prop[TIPC_NLA_PROP_WIN]));
226f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
227f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	printf("  RX packets:%u fragments:%u/%u bundles:%u/%u\n",
228f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(attrs[TIPC_NLA_LINK_RX]) -
229f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_INFO]),
230f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTS]),
231f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTED]),
232f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLES]),
233f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLED]));
234f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
235f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	printf("  TX packets:%u fragments:%u/%u bundles:%u/%u\n",
236f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(attrs[TIPC_NLA_LINK_TX]) -
237f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_INFO]),
238f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTS]),
239f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTED]),
240f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLES]),
241f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLED]));
242f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
243f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	proft = mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_PROF_TOT]);
244f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	printf("  TX profile sample:%u packets  average:%u octets\n",
245f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_CNT]),
246f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_TOT]) / proft);
247f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
248f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	printf("  0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% "
249f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       "-16384:%u%% -32768:%u%% -66000:%u%%\n",
250f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P0]), proft),
251f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P1]), proft),
252f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P2]), proft),
253f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P3]), proft),
254f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P4]), proft),
255f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P5]), proft),
256f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       perc(mnl_attr_get_u32(stats[TIPC_NLA_STATS_MSG_LEN_P6]), proft));
257f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
258f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	printf("  RX states:%u probes:%u naks:%u defs:%u dups:%u\n",
259f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_STATES]),
260f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_PROBES]),
261f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_NACKS]),
262f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_DEFERRED]),
263f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_DUPLICATES]));
264f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
265f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	printf("  TX states:%u probes:%u naks:%u acks:%u dups:%u\n",
266f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_STATES]),
267f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_PROBES]),
268f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_NACKS]),
269f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_ACKS]),
270f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_RETRANSMITTED]));
271f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
272f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	printf("  Congestion link:%u  Send queue max:%u avg:%u\n",
273f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_LINK_CONGS]),
274f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_MAX_QUEUE]),
275f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_AVG_QUEUE]));
276f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
277f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	return MNL_CB_OK;
278f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
279f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
280f043759dd492897513d5aa057427bcdab8592d4bRichard Alpestatic int _show_bc_link_stat(struct nlattr *prop[], struct nlattr *stats[])
281f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
282f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	printf("  Window:%u packets\n",
283f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(prop[TIPC_NLA_PROP_WIN]));
284f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
285f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	printf("  RX packets:%u fragments:%u/%u bundles:%u/%u\n",
286f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_INFO]),
287f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTS]),
288f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_FRAGMENTED]),
289f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLES]),
290f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_BUNDLED]));
291f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
292f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	printf("  TX packets:%u fragments:%u/%u bundles:%u/%u\n",
293f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_INFO]),
294f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTS]),
295f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_FRAGMENTED]),
296f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLES]),
297f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_BUNDLED]));
298f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
299f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	printf("  RX naks:%u defs:%u dups:%u\n",
300f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_NACKS]),
301f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_RX_DEFERRED]),
302f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_DUPLICATES]));
303f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
304f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	printf("  TX naks:%u acks:%u dups:%u\n",
305f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_NACKS]),
306f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_TX_ACKS]),
307f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_RETRANSMITTED]));
308f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
309f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	printf("  Congestion link:%u  Send queue max:%u avg:%u\n",
310f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_LINK_CONGS]),
311f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_MAX_QUEUE]),
312f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	       mnl_attr_get_u32(stats[TIPC_NLA_STATS_AVG_QUEUE]));
313f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
314f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	return MNL_CB_OK;
315f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
316f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
317f043759dd492897513d5aa057427bcdab8592d4bRichard Alpestatic int link_stat_show_cb(const struct nlmsghdr *nlh, void *data)
318f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
319f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	const char *name;
320f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	const char *link = data;
321f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
322f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct nlattr *info[TIPC_NLA_MAX + 1] = {};
323f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1] = {};
324f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct nlattr *prop[TIPC_NLA_PROP_MAX + 1] = {};
325f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct nlattr *stats[TIPC_NLA_STATS_MAX + 1] = {};
326f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
327f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
328f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (!info[TIPC_NLA_LINK])
329f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return MNL_CB_ERROR;
330f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
331f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	mnl_attr_parse_nested(info[TIPC_NLA_LINK], parse_attrs, attrs);
332f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (!attrs[TIPC_NLA_LINK_NAME] || !attrs[TIPC_NLA_LINK_PROP] ||
333f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	    !attrs[TIPC_NLA_LINK_STATS])
334f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return MNL_CB_ERROR;
335f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
336f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	mnl_attr_parse_nested(attrs[TIPC_NLA_LINK_PROP], parse_attrs, prop);
337f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	mnl_attr_parse_nested(attrs[TIPC_NLA_LINK_STATS], parse_attrs, stats);
338f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
339f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	name = mnl_attr_get_str(attrs[TIPC_NLA_LINK_NAME]);
340f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
341f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	/* If a link is passed, skip all but that link */
342f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (link && (strcmp(name, link) != 0))
343f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return MNL_CB_OK;
344f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
345f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (attrs[TIPC_NLA_LINK_BROADCAST]) {
346f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		printf("Link <%s>\n", name);
347f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return _show_bc_link_stat(prop, stats);
348f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	}
349f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
350f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	printf("\nLink <%s>\n", name);
351f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
352f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	return _show_link_stat(attrs, prop, stats);
353f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
354f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
355f043759dd492897513d5aa057427bcdab8592d4bRichard Alpestatic void cmd_link_stat_show_help(struct cmdl *cmdl)
356f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
357f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	fprintf(stderr, "Usage: %s link stat show [ link LINK ]\n",
358f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		cmdl->argv[0]);
359f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
360f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
361f043759dd492897513d5aa057427bcdab8592d4bRichard Alpestatic int cmd_link_stat_show(struct nlmsghdr *nlh, const struct cmd *cmd,
362f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe			      struct cmdl *cmdl, void *data)
363f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
364f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	char *link = NULL;
365f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	char buf[MNL_SOCKET_BUFFER_SIZE];
366f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct opt *opt;
367f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct opt opts[] = {
368f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ "link",		NULL },
369f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ NULL }
370f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	};
371f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
372f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (help_flag) {
373f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		(cmd->help)(cmdl);
374f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -EINVAL;
375f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	}
376f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
377f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (!(nlh = msg_init(buf, TIPC_NL_LINK_GET))) {
378f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		fprintf(stderr, "error, message initialisation failed\n");
379f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -1;
380f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	}
381f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
382f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (parse_opts(opts, cmdl) < 0)
383f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -EINVAL;
384f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
385f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if ((opt = get_opt(opts, "link")))
386f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		link = opt->val;
387f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
388f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	return msg_dumpit(nlh, link_stat_show_cb, link);
389f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
390f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
391f043759dd492897513d5aa057427bcdab8592d4bRichard Alpestatic void cmd_link_stat_help(struct cmdl *cmdl)
392f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
393f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	fprintf(stderr, "Usage: %s link stat COMMAND [ARGS]\n\n"
394f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		"COMMANDS:\n"
395f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		" reset                 - Reset link statistics for link\n"
396f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		" show                  - Get link priority\n",
397f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		cmdl->argv[0]);
398f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
399f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
400f043759dd492897513d5aa057427bcdab8592d4bRichard Alpestatic int cmd_link_stat(struct nlmsghdr *nlh, const struct cmd *cmd,
401f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe			 struct cmdl *cmdl, void *data)
402f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
403f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	const struct cmd cmds[] = {
404f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ "reset",	cmd_link_stat_reset,	cmd_link_stat_reset_help },
405f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ "show",	cmd_link_stat_show,	cmd_link_stat_show_help },
406f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ NULL }
407f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	};
408f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
409f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	return run_cmd(nlh, cmd, cmds, cmdl, NULL);
410f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
411f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
412f043759dd492897513d5aa057427bcdab8592d4bRichard Alpestatic void cmd_link_set_help(struct cmdl *cmdl)
413f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
414f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	fprintf(stderr, "Usage: %s link set PPROPERTY link LINK\n\n"
415f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		"PROPERTIES\n"
416f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		" tolerance TOLERANCE   - Set link tolerance\n"
417f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		" priority PRIORITY     - Set link priority\n"
418f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		" window WINDOW         - Set link window\n",
419f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		cmdl->argv[0]);
420f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
421f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
422f043759dd492897513d5aa057427bcdab8592d4bRichard Alpestatic int cmd_link_set_prop(struct nlmsghdr *nlh, const struct cmd *cmd,
423f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe			     struct cmdl *cmdl, void *data)
424f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
425f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	int val;
426f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	int prop;
427f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	char buf[MNL_SOCKET_BUFFER_SIZE];
428f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct nlattr *props;
429f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct nlattr *attrs;
430f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct opt *opt;
431f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	struct opt opts[] = {
432f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ "link",	NULL },
433f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ NULL }
434f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	};
435f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
436f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (strcmp(cmd->cmd, "priority") == 0)
437f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		prop = TIPC_NLA_PROP_PRIO;
438f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	else if ((strcmp(cmd->cmd, "tolerance") == 0))
439f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		prop = TIPC_NLA_PROP_TOL;
440f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	else if ((strcmp(cmd->cmd, "window") == 0))
441f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		prop = TIPC_NLA_PROP_WIN;
442f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	else
443f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -EINVAL;
444f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
445f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (help_flag) {
446f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		(cmd->help)(cmdl);
447f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -EINVAL;
448f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	}
449f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
450f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (cmdl->optind >= cmdl->argc) {
451f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		fprintf(stderr, "error, missing value\n");
452f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -EINVAL;
453f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	}
454f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	val = atoi(shift_cmdl(cmdl));
455f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
456f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (parse_opts(opts, cmdl) < 0)
457f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -EINVAL;
458f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
459f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (!(nlh = msg_init(buf, TIPC_NL_LINK_SET))) {
460f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		fprintf(stderr, "error, message initialisation failed\n");
461f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -1;
462f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	}
463f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	attrs = mnl_attr_nest_start(nlh, TIPC_NLA_LINK);
464f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
465f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	if (!(opt = get_opt(opts, "link"))) {
466f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		fprintf(stderr, "error, missing link\n");
467f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		return -EINVAL;
468f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	}
469f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	mnl_attr_put_strz(nlh, TIPC_NLA_LINK_NAME, opt->val);
470f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
471f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	props = mnl_attr_nest_start(nlh, TIPC_NLA_LINK_PROP);
472f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	mnl_attr_put_u32(nlh, prop, val);
473f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	mnl_attr_nest_end(nlh, props);
474f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
475f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	mnl_attr_nest_end(nlh, attrs);
476f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
477f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	return msg_doit(nlh, link_get_cb, &prop);
478f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
479f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	return 0;
480f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
481f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
482f043759dd492897513d5aa057427bcdab8592d4bRichard Alpestatic int cmd_link_set(struct nlmsghdr *nlh, const struct cmd *cmd,
483f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe			struct cmdl *cmdl, void *data)
484f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
485f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	const struct cmd cmds[] = {
486f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ "priority",	cmd_link_set_prop,	cmd_link_set_help },
487f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ "tolerance",	cmd_link_set_prop,	cmd_link_set_help },
488f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ "window",	cmd_link_set_prop,	cmd_link_set_help },
489f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ NULL }
490f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	};
491f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
492f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	return run_cmd(nlh, cmd, cmds, cmdl, NULL);
493f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
494f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
495f043759dd492897513d5aa057427bcdab8592d4bRichard Alpevoid cmd_link_help(struct cmdl *cmdl)
496f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
497f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	fprintf(stderr,
498f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		"Usage: %s link COMMAND [ARGS] ...\n"
499f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		"\n"
500f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		"COMMANDS\n"
501f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		" list                  - List links\n"
502f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		" get                   - Get various link properties\n"
503f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		" set                   - Set various link properties\n"
504f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		" statistics            - Show or reset statistics\n",
505f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		cmdl->argv[0]);
506f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
507f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
508f043759dd492897513d5aa057427bcdab8592d4bRichard Alpeint cmd_link(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl,
509f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	     void *data)
510f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe{
511f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	const struct cmd cmds[] = {
512f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ "get",	cmd_link_get,	cmd_link_get_help },
513f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ "list",	cmd_link_list,	NULL },
514f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ "set",	cmd_link_set,	cmd_link_set_help },
515f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ "statistics", cmd_link_stat,	cmd_link_stat_help },
516f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe		{ NULL }
517f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	};
518f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe
519f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe	return run_cmd(nlh, cmd, cmds, cmdl, NULL);
520f043759dd492897513d5aa057427bcdab8592d4bRichard Alpe}
521