• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * rings.c - netlink implementation of ring commands
3  *
4  * Implementation of "ethtool -g <dev>" and "ethtool -G <dev> ..."
5  */
6 
7 #include <errno.h>
8 #include <string.h>
9 #include <stdio.h>
10 
11 #include "../internal.h"
12 #include "../common.h"
13 #include "netlink.h"
14 #include "parser.h"
15 
16 /* RINGS_GET */
17 
rings_reply_cb(const struct nlmsghdr * nlhdr,void * data)18 int rings_reply_cb(const struct nlmsghdr *nlhdr, void *data)
19 {
20 	const struct nlattr *tb[ETHTOOL_A_RINGS_MAX + 1] = {};
21 	DECLARE_ATTR_TB_INFO(tb);
22 	struct nl_context *nlctx = data;
23 	unsigned char tcp_hds;
24 	char *tcp_hds_fmt;
25 	char *tcp_hds_key;
26 	char tcp_hds_buf[256];
27 	bool silent;
28 	int err_ret;
29 	int ret;
30 
31 	silent = nlctx->is_dump || nlctx->is_monitor;
32 	err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR;
33 	ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
34 	if (ret < 0)
35 		return err_ret;
36 	nlctx->devname = get_dev_name(tb[ETHTOOL_A_RINGS_HEADER]);
37 	if (!dev_ok(nlctx))
38 		return err_ret;
39 
40 	open_json_object(NULL);
41 
42 	if (silent)
43 		show_cr();
44 	print_string(PRINT_ANY, "ifname", "Ring parameters for %s:\n",
45 		     nlctx->devname);
46 	print_string(PRINT_FP, NULL, "Pre-set maximums:\n", NULL);
47 	show_u32("rx-max", "RX:\t\t\t", tb[ETHTOOL_A_RINGS_RX_MAX]);
48 	show_u32("rx-mini-max", "RX Mini:\t\t", tb[ETHTOOL_A_RINGS_RX_MINI_MAX]);
49 	show_u32("rx-jumbo-max", "RX Jumbo:\t\t",
50 		 tb[ETHTOOL_A_RINGS_RX_JUMBO_MAX]);
51 	show_u32("tx-max", "TX:\t\t\t", tb[ETHTOOL_A_RINGS_TX_MAX]);
52 	show_u32("tx-push-buff-max-len", "TX push buff len:\t",
53 		 tb[ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX]);
54 	print_string(PRINT_FP, NULL, "Current hardware settings:\n", NULL);
55 	show_u32("rx", "RX:\t\t\t", tb[ETHTOOL_A_RINGS_RX]);
56 	show_u32("rx-mini", "RX Mini:\t\t", tb[ETHTOOL_A_RINGS_RX_MINI]);
57 	show_u32("rx-jumbo", "RX Jumbo:\t\t", tb[ETHTOOL_A_RINGS_RX_JUMBO]);
58 	show_u32("tx", "TX:\t\t\t", tb[ETHTOOL_A_RINGS_TX]);
59 	show_u32("rx-buf-len", "RX Buf Len:\t\t", tb[ETHTOOL_A_RINGS_RX_BUF_LEN]);
60 	show_u32("cqe-size", "CQE Size:\t\t", tb[ETHTOOL_A_RINGS_CQE_SIZE]);
61 	show_bool("tx-push", "TX Push:\t\t%s\n", tb[ETHTOOL_A_RINGS_TX_PUSH]);
62 	show_bool("rx-push", "RX Push:\t\t%s\n", tb[ETHTOOL_A_RINGS_RX_PUSH]);
63 	show_u32("tx-push-buf-len", "TX push buff len:\t",
64 		 tb[ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN]);
65 
66 	tcp_hds_fmt = "TCP data split:\t\t%s\n";
67 	tcp_hds_key = "tcp-data-split";
68 	tcp_hds = tb[ETHTOOL_A_RINGS_TCP_DATA_SPLIT] ?
69 		mnl_attr_get_u8(tb[ETHTOOL_A_RINGS_TCP_DATA_SPLIT]) : 0;
70 	switch (tcp_hds) {
71 	case ETHTOOL_TCP_DATA_SPLIT_UNKNOWN:
72 		print_string(PRINT_FP, tcp_hds_key, tcp_hds_fmt, "n/a");
73 		break;
74 	case ETHTOOL_TCP_DATA_SPLIT_DISABLED:
75 		print_string(PRINT_ANY, tcp_hds_key, tcp_hds_fmt, "off");
76 		break;
77 	case ETHTOOL_TCP_DATA_SPLIT_ENABLED:
78 		print_string(PRINT_ANY, tcp_hds_key, tcp_hds_fmt, "on");
79 		break;
80 	default:
81 		snprintf(tcp_hds_buf, sizeof(tcp_hds_buf),
82 			 "unknown(%d)\n", tcp_hds);
83 		print_string(PRINT_ANY, tcp_hds_key, tcp_hds_fmt, tcp_hds_buf);
84 		break;
85 	}
86 
87 	close_json_object();
88 
89 	return MNL_CB_OK;
90 }
91 
nl_gring(struct cmd_context * ctx)92 int nl_gring(struct cmd_context *ctx)
93 {
94 	struct nl_context *nlctx = ctx->nlctx;
95 	struct nl_socket *nlsk = nlctx->ethnl_socket;
96 	int ret;
97 
98 	if (netlink_cmd_check(ctx, ETHTOOL_MSG_RINGS_GET, true))
99 		return -EOPNOTSUPP;
100 	if (ctx->argc > 0) {
101 		fprintf(stderr, "ethtool: unexpected parameter '%s'\n",
102 			*ctx->argp);
103 		return 1;
104 	}
105 
106 	ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_RINGS_GET,
107 				      ETHTOOL_A_RINGS_HEADER, 0);
108 	if (ret < 0)
109 		return ret;
110 
111 	new_json_obj(ctx->json);
112 	ret = nlsock_send_get_request(nlsk, rings_reply_cb);
113 	delete_json_obj();
114 	return ret;
115 }
116 
117 /* RINGS_SET */
118 
119 static const struct lookup_entry_u8 tcp_data_split_values[] = {
120 	{
121 		.arg		= "auto",
122 		.val		= ETHTOOL_TCP_DATA_SPLIT_UNKNOWN,
123 	},
124 	{
125 		.arg		= "off",
126 		.val		= ETHTOOL_TCP_DATA_SPLIT_DISABLED,
127 	},
128 	{
129 		.arg		= "on",
130 		.val		= ETHTOOL_TCP_DATA_SPLIT_ENABLED,
131 	},
132 	{}
133 };
134 
135 static const struct param_parser sring_params[] = {
136 	{
137 		.arg		= "rx",
138 		.type		= ETHTOOL_A_RINGS_RX,
139 		.handler	= nl_parse_direct_u32,
140 		.min_argc	= 1,
141 	},
142 	{
143 		.arg		= "rx-mini",
144 		.type		= ETHTOOL_A_RINGS_RX_MINI,
145 		.handler	= nl_parse_direct_u32,
146 		.min_argc	= 1,
147 	},
148 	{
149 		.arg		= "rx-jumbo",
150 		.type		= ETHTOOL_A_RINGS_RX_JUMBO,
151 		.handler	= nl_parse_direct_u32,
152 		.min_argc	= 1,
153 	},
154 	{
155 		.arg		= "tx",
156 		.type		= ETHTOOL_A_RINGS_TX,
157 		.handler	= nl_parse_direct_u32,
158 		.min_argc	= 1,
159 	},
160 	{
161 		.arg		= "tx-push-buf-len",
162 		.type		= ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN,
163 		.handler	= nl_parse_direct_u32,
164 		.min_argc	= 1,
165 	},
166 	{
167 		.arg            = "rx-buf-len",
168 		.type           = ETHTOOL_A_RINGS_RX_BUF_LEN,
169 		.handler        = nl_parse_direct_u32,
170 		.min_argc       = 1,
171 	},
172 	{
173 		.arg		= "tcp-data-split",
174 		.type		= ETHTOOL_A_RINGS_TCP_DATA_SPLIT,
175 		.handler	= nl_parse_lookup_u8,
176 		.handler_data	= tcp_data_split_values,
177 		.min_argc	= 1,
178 	},
179 	{
180 		.arg            = "cqe-size",
181 		.type           = ETHTOOL_A_RINGS_CQE_SIZE,
182 		.handler        = nl_parse_direct_u32,
183 		.min_argc       = 1,
184 	},
185 	{
186 		.arg            = "tx-push",
187 		.type           = ETHTOOL_A_RINGS_TX_PUSH,
188 		.handler        = nl_parse_u8bool,
189 		.min_argc       = 1,
190 	},
191 	{
192 		.arg            = "rx-push",
193 		.type           = ETHTOOL_A_RINGS_RX_PUSH,
194 		.handler        = nl_parse_u8bool,
195 		.min_argc       = 1,
196 	},
197 	{}
198 };
199 
nl_sring(struct cmd_context * ctx)200 int nl_sring(struct cmd_context *ctx)
201 {
202 	struct nl_context *nlctx = ctx->nlctx;
203 	struct nl_msg_buff *msgbuff;
204 	struct nl_socket *nlsk;
205 	int ret;
206 
207 	if (netlink_cmd_check(ctx, ETHTOOL_MSG_RINGS_SET, false))
208 		return -EOPNOTSUPP;
209 
210 	nlctx->cmd = "-G";
211 	nlctx->argp = ctx->argp;
212 	nlctx->argc = ctx->argc;
213 	nlctx->devname = ctx->devname;
214 	nlsk = nlctx->ethnl_socket;
215 	msgbuff = &nlsk->msgbuff;
216 
217 	ret = msg_init(nlctx, msgbuff, ETHTOOL_MSG_RINGS_SET,
218 		       NLM_F_REQUEST | NLM_F_ACK);
219 	if (ret < 0)
220 		return 2;
221 	if (ethnla_fill_header(msgbuff, ETHTOOL_A_RINGS_HEADER,
222 			       ctx->devname, 0))
223 		return -EMSGSIZE;
224 
225 	ret = nl_parser(nlctx, sring_params, NULL, PARSER_GROUP_NONE, NULL);
226 	if (ret < 0)
227 		return 1;
228 
229 	ret = nlsock_sendmsg(nlsk, NULL);
230 	if (ret < 0)
231 		return 81;
232 	ret = nlsock_process_reply(nlsk, nomsg_reply_cb, nlctx);
233 	if (ret == 0)
234 		return 0;
235 	else
236 		return nlctx->exit_code ?: 81;
237 }
238