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