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