xref: /aosp_15_r20/external/ethtool/netlink/rings.c (revision 1b481fc3bb1b45d4cf28d1ec12969dc1055f555d)
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 param_parser sring_params[] = {
120 	{
121 		.arg		= "rx",
122 		.type		= ETHTOOL_A_RINGS_RX,
123 		.handler	= nl_parse_direct_u32,
124 		.min_argc	= 1,
125 	},
126 	{
127 		.arg		= "rx-mini",
128 		.type		= ETHTOOL_A_RINGS_RX_MINI,
129 		.handler	= nl_parse_direct_u32,
130 		.min_argc	= 1,
131 	},
132 	{
133 		.arg		= "rx-jumbo",
134 		.type		= ETHTOOL_A_RINGS_RX_JUMBO,
135 		.handler	= nl_parse_direct_u32,
136 		.min_argc	= 1,
137 	},
138 	{
139 		.arg		= "tx",
140 		.type		= ETHTOOL_A_RINGS_TX,
141 		.handler	= nl_parse_direct_u32,
142 		.min_argc	= 1,
143 	},
144 	{
145 		.arg		= "tx-push-buf-len",
146 		.type		= ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN,
147 		.handler	= nl_parse_direct_u32,
148 		.min_argc	= 1,
149 	},
150 	{
151 		.arg            = "rx-buf-len",
152 		.type           = ETHTOOL_A_RINGS_RX_BUF_LEN,
153 		.handler        = nl_parse_direct_u32,
154 		.min_argc       = 1,
155 	},
156 	{
157 		.arg            = "cqe-size",
158 		.type           = ETHTOOL_A_RINGS_CQE_SIZE,
159 		.handler        = nl_parse_direct_u32,
160 		.min_argc       = 1,
161 	},
162 	{
163 		.arg            = "tx-push",
164 		.type           = ETHTOOL_A_RINGS_TX_PUSH,
165 		.handler        = nl_parse_u8bool,
166 		.min_argc       = 1,
167 	},
168 	{
169 		.arg            = "rx-push",
170 		.type           = ETHTOOL_A_RINGS_RX_PUSH,
171 		.handler        = nl_parse_u8bool,
172 		.min_argc       = 1,
173 	},
174 	{}
175 };
176 
nl_sring(struct cmd_context * ctx)177 int nl_sring(struct cmd_context *ctx)
178 {
179 	struct nl_context *nlctx = ctx->nlctx;
180 	struct nl_msg_buff *msgbuff;
181 	struct nl_socket *nlsk;
182 	int ret;
183 
184 	if (netlink_cmd_check(ctx, ETHTOOL_MSG_RINGS_SET, false))
185 		return -EOPNOTSUPP;
186 
187 	nlctx->cmd = "-G";
188 	nlctx->argp = ctx->argp;
189 	nlctx->argc = ctx->argc;
190 	nlctx->devname = ctx->devname;
191 	nlsk = nlctx->ethnl_socket;
192 	msgbuff = &nlsk->msgbuff;
193 
194 	ret = msg_init(nlctx, msgbuff, ETHTOOL_MSG_RINGS_SET,
195 		       NLM_F_REQUEST | NLM_F_ACK);
196 	if (ret < 0)
197 		return 2;
198 	if (ethnla_fill_header(msgbuff, ETHTOOL_A_RINGS_HEADER,
199 			       ctx->devname, 0))
200 		return -EMSGSIZE;
201 
202 	ret = nl_parser(nlctx, sring_params, NULL, PARSER_GROUP_NONE, NULL);
203 	if (ret < 0)
204 		return 1;
205 
206 	ret = nlsock_sendmsg(nlsk, NULL);
207 	if (ret < 0)
208 		return 81;
209 	ret = nlsock_process_reply(nlsk, nomsg_reply_cb, nlctx);
210 	if (ret == 0)
211 		return 0;
212 	else
213 		return nlctx->exit_code ?: 81;
214 }
215