xref: /aosp_15_r20/external/ethtool/netlink/eee.c (revision 1b481fc3bb1b45d4cf28d1ec12969dc1055f555d)
1*1b481fc3SMaciej Żenczykowski /*
2*1b481fc3SMaciej Żenczykowski  * eee.c - netlink implementation of eee commands
3*1b481fc3SMaciej Żenczykowski  *
4*1b481fc3SMaciej Żenczykowski  * Implementation of "ethtool --show-eee <dev>" and
5*1b481fc3SMaciej Żenczykowski  * "ethtool --set-eee <dev> ..."
6*1b481fc3SMaciej Żenczykowski  */
7*1b481fc3SMaciej Żenczykowski 
8*1b481fc3SMaciej Żenczykowski #include <errno.h>
9*1b481fc3SMaciej Żenczykowski #include <string.h>
10*1b481fc3SMaciej Żenczykowski #include <stdio.h>
11*1b481fc3SMaciej Żenczykowski 
12*1b481fc3SMaciej Żenczykowski #include "../internal.h"
13*1b481fc3SMaciej Żenczykowski #include "../common.h"
14*1b481fc3SMaciej Żenczykowski #include "netlink.h"
15*1b481fc3SMaciej Żenczykowski #include "bitset.h"
16*1b481fc3SMaciej Żenczykowski #include "parser.h"
17*1b481fc3SMaciej Żenczykowski 
18*1b481fc3SMaciej Żenczykowski /* EEE_GET */
19*1b481fc3SMaciej Żenczykowski 
eee_reply_cb(const struct nlmsghdr * nlhdr,void * data)20*1b481fc3SMaciej Żenczykowski int eee_reply_cb(const struct nlmsghdr *nlhdr, void *data)
21*1b481fc3SMaciej Żenczykowski {
22*1b481fc3SMaciej Żenczykowski 	const struct nlattr *tb[ETHTOOL_A_EEE_MAX + 1] = {};
23*1b481fc3SMaciej Żenczykowski 	DECLARE_ATTR_TB_INFO(tb);
24*1b481fc3SMaciej Żenczykowski 	bool enabled, active, tx_lpi_enabled;
25*1b481fc3SMaciej Żenczykowski 	struct nl_context *nlctx = data;
26*1b481fc3SMaciej Żenczykowski 	bool silent;
27*1b481fc3SMaciej Żenczykowski 	int err_ret;
28*1b481fc3SMaciej Żenczykowski 	int ret;
29*1b481fc3SMaciej Żenczykowski 
30*1b481fc3SMaciej Żenczykowski 	silent = nlctx->is_dump || nlctx->is_monitor;
31*1b481fc3SMaciej Żenczykowski 	err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR;
32*1b481fc3SMaciej Żenczykowski 	ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
33*1b481fc3SMaciej Żenczykowski 	if (ret < 0)
34*1b481fc3SMaciej Żenczykowski 		return err_ret;
35*1b481fc3SMaciej Żenczykowski 	nlctx->devname = get_dev_name(tb[ETHTOOL_A_EEE_HEADER]);
36*1b481fc3SMaciej Żenczykowski 	if (!dev_ok(nlctx))
37*1b481fc3SMaciej Żenczykowski 		return err_ret;
38*1b481fc3SMaciej Żenczykowski 
39*1b481fc3SMaciej Żenczykowski 	if (!tb[ETHTOOL_A_EEE_MODES_OURS] ||
40*1b481fc3SMaciej Żenczykowski 	    !tb[ETHTOOL_A_EEE_ACTIVE] || !tb[ETHTOOL_A_EEE_ENABLED] ||
41*1b481fc3SMaciej Żenczykowski 	    !tb[ETHTOOL_A_EEE_TX_LPI_ENABLED] ||
42*1b481fc3SMaciej Żenczykowski 	    !tb[ETHTOOL_A_EEE_TX_LPI_TIMER]) {
43*1b481fc3SMaciej Żenczykowski 		fprintf(stderr, "Malformed response from kernel\n");
44*1b481fc3SMaciej Żenczykowski 		return err_ret;
45*1b481fc3SMaciej Żenczykowski 	}
46*1b481fc3SMaciej Żenczykowski 	active = mnl_attr_get_u8(tb[ETHTOOL_A_EEE_ACTIVE]);
47*1b481fc3SMaciej Żenczykowski 	enabled = mnl_attr_get_u8(tb[ETHTOOL_A_EEE_ENABLED]);
48*1b481fc3SMaciej Żenczykowski 	tx_lpi_enabled = mnl_attr_get_u8(tb[ETHTOOL_A_EEE_TX_LPI_ENABLED]);
49*1b481fc3SMaciej Żenczykowski 
50*1b481fc3SMaciej Żenczykowski 	if (silent)
51*1b481fc3SMaciej Żenczykowski 		putchar('\n');
52*1b481fc3SMaciej Żenczykowski 	printf("EEE settings for %s:\n", nlctx->devname);
53*1b481fc3SMaciej Żenczykowski 	printf("\tEEE status: ");
54*1b481fc3SMaciej Żenczykowski 	if (bitset_is_empty(tb[ETHTOOL_A_EEE_MODES_OURS], true, &ret)) {
55*1b481fc3SMaciej Żenczykowski 		printf("not supported\n");
56*1b481fc3SMaciej Żenczykowski 		return MNL_CB_OK;
57*1b481fc3SMaciej Żenczykowski 	}
58*1b481fc3SMaciej Żenczykowski 	if (!enabled)
59*1b481fc3SMaciej Żenczykowski 		printf("disabled\n");
60*1b481fc3SMaciej Żenczykowski 	else
61*1b481fc3SMaciej Żenczykowski 		printf("enabled - %s\n", active ? "active" : "inactive");
62*1b481fc3SMaciej Żenczykowski 	printf("\tTx LPI: ");
63*1b481fc3SMaciej Żenczykowski 	if (tx_lpi_enabled)
64*1b481fc3SMaciej Żenczykowski 		printf("%u (us)\n",
65*1b481fc3SMaciej Żenczykowski 		       mnl_attr_get_u32(tb[ETHTOOL_A_EEE_TX_LPI_TIMER]));
66*1b481fc3SMaciej Żenczykowski 	else
67*1b481fc3SMaciej Żenczykowski 		printf("disabled\n");
68*1b481fc3SMaciej Żenczykowski 
69*1b481fc3SMaciej Żenczykowski 	ret = dump_link_modes(nlctx, tb[ETHTOOL_A_EEE_MODES_OURS], true,
70*1b481fc3SMaciej Żenczykowski 			      LM_CLASS_REAL,
71*1b481fc3SMaciej Żenczykowski 			      "Supported EEE link modes:  ", NULL, "\n",
72*1b481fc3SMaciej Żenczykowski 			      "Not reported");
73*1b481fc3SMaciej Żenczykowski 	if (ret < 0)
74*1b481fc3SMaciej Żenczykowski 		return err_ret;
75*1b481fc3SMaciej Żenczykowski 	ret = dump_link_modes(nlctx, tb[ETHTOOL_A_EEE_MODES_OURS], false,
76*1b481fc3SMaciej Żenczykowski 			      LM_CLASS_REAL,
77*1b481fc3SMaciej Żenczykowski 			      "Advertised EEE link modes:  ", NULL, "\n",
78*1b481fc3SMaciej Żenczykowski 			      "Not reported");
79*1b481fc3SMaciej Żenczykowski 	if (ret < 0)
80*1b481fc3SMaciej Żenczykowski 		return err_ret;
81*1b481fc3SMaciej Żenczykowski 	ret = dump_link_modes(nlctx, tb[ETHTOOL_A_EEE_MODES_PEER], false,
82*1b481fc3SMaciej Żenczykowski 			      LM_CLASS_REAL,
83*1b481fc3SMaciej Żenczykowski 			      "Link partner advertised EEE link modes:  ", NULL,
84*1b481fc3SMaciej Żenczykowski 			      "\n", "Not reported");
85*1b481fc3SMaciej Żenczykowski 	if (ret < 0)
86*1b481fc3SMaciej Żenczykowski 		return err_ret;
87*1b481fc3SMaciej Żenczykowski 
88*1b481fc3SMaciej Żenczykowski 	return MNL_CB_OK;
89*1b481fc3SMaciej Żenczykowski }
90*1b481fc3SMaciej Żenczykowski 
nl_geee(struct cmd_context * ctx)91*1b481fc3SMaciej Żenczykowski int nl_geee(struct cmd_context *ctx)
92*1b481fc3SMaciej Żenczykowski {
93*1b481fc3SMaciej Żenczykowski 	struct nl_context *nlctx = ctx->nlctx;
94*1b481fc3SMaciej Żenczykowski 	struct nl_socket *nlsk = nlctx->ethnl_socket;
95*1b481fc3SMaciej Żenczykowski 	int ret;
96*1b481fc3SMaciej Żenczykowski 
97*1b481fc3SMaciej Żenczykowski 	if (netlink_cmd_check(ctx, ETHTOOL_MSG_EEE_GET, true))
98*1b481fc3SMaciej Żenczykowski 		return -EOPNOTSUPP;
99*1b481fc3SMaciej Żenczykowski 	if (ctx->argc > 0) {
100*1b481fc3SMaciej Żenczykowski 		fprintf(stderr, "ethtool: unexpected parameter '%s'\n",
101*1b481fc3SMaciej Żenczykowski 			*ctx->argp);
102*1b481fc3SMaciej Żenczykowski 		return 1;
103*1b481fc3SMaciej Żenczykowski 	}
104*1b481fc3SMaciej Żenczykowski 
105*1b481fc3SMaciej Żenczykowski 	ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_EEE_GET,
106*1b481fc3SMaciej Żenczykowski 				      ETHTOOL_A_EEE_HEADER, 0);
107*1b481fc3SMaciej Żenczykowski 	if (ret < 0)
108*1b481fc3SMaciej Żenczykowski 		return ret;
109*1b481fc3SMaciej Żenczykowski 	return nlsock_send_get_request(nlsk, eee_reply_cb);
110*1b481fc3SMaciej Żenczykowski }
111*1b481fc3SMaciej Żenczykowski 
112*1b481fc3SMaciej Żenczykowski /* EEE_SET */
113*1b481fc3SMaciej Żenczykowski 
114*1b481fc3SMaciej Żenczykowski static const struct bitset_parser_data advertise_parser_data = {
115*1b481fc3SMaciej Żenczykowski 	.no_mask	= false,
116*1b481fc3SMaciej Żenczykowski 	.force_hex	= true,
117*1b481fc3SMaciej Żenczykowski };
118*1b481fc3SMaciej Żenczykowski 
119*1b481fc3SMaciej Żenczykowski static const struct param_parser seee_params[] = {
120*1b481fc3SMaciej Żenczykowski 	{
121*1b481fc3SMaciej Żenczykowski 		.arg		= "advertise",
122*1b481fc3SMaciej Żenczykowski 		.type		= ETHTOOL_A_EEE_MODES_OURS,
123*1b481fc3SMaciej Żenczykowski 		.handler	= nl_parse_bitset,
124*1b481fc3SMaciej Żenczykowski 		.handler_data	= &advertise_parser_data,
125*1b481fc3SMaciej Żenczykowski 		.min_argc	= 1,
126*1b481fc3SMaciej Żenczykowski 	},
127*1b481fc3SMaciej Żenczykowski 	{
128*1b481fc3SMaciej Żenczykowski 		.arg		= "tx-lpi",
129*1b481fc3SMaciej Żenczykowski 		.type		= ETHTOOL_A_EEE_TX_LPI_ENABLED,
130*1b481fc3SMaciej Żenczykowski 		.handler	= nl_parse_u8bool,
131*1b481fc3SMaciej Żenczykowski 		.min_argc	= 1,
132*1b481fc3SMaciej Żenczykowski 	},
133*1b481fc3SMaciej Żenczykowski 	{
134*1b481fc3SMaciej Żenczykowski 		.arg		= "tx-timer",
135*1b481fc3SMaciej Żenczykowski 		.type		= ETHTOOL_A_EEE_TX_LPI_TIMER,
136*1b481fc3SMaciej Żenczykowski 		.handler	= nl_parse_direct_u32,
137*1b481fc3SMaciej Żenczykowski 		.min_argc	= 1,
138*1b481fc3SMaciej Żenczykowski 	},
139*1b481fc3SMaciej Żenczykowski 	{
140*1b481fc3SMaciej Żenczykowski 		.arg		= "eee",
141*1b481fc3SMaciej Żenczykowski 		.type		= ETHTOOL_A_EEE_ENABLED,
142*1b481fc3SMaciej Żenczykowski 		.handler	= nl_parse_u8bool,
143*1b481fc3SMaciej Żenczykowski 		.min_argc	= 1,
144*1b481fc3SMaciej Żenczykowski 	},
145*1b481fc3SMaciej Żenczykowski 	{}
146*1b481fc3SMaciej Żenczykowski };
147*1b481fc3SMaciej Żenczykowski 
nl_seee(struct cmd_context * ctx)148*1b481fc3SMaciej Żenczykowski int nl_seee(struct cmd_context *ctx)
149*1b481fc3SMaciej Żenczykowski {
150*1b481fc3SMaciej Żenczykowski 	struct nl_context *nlctx = ctx->nlctx;
151*1b481fc3SMaciej Żenczykowski 	struct nl_msg_buff *msgbuff;
152*1b481fc3SMaciej Żenczykowski 	struct nl_socket *nlsk;
153*1b481fc3SMaciej Żenczykowski 	int ret;
154*1b481fc3SMaciej Żenczykowski 
155*1b481fc3SMaciej Żenczykowski 	if (netlink_cmd_check(ctx, ETHTOOL_MSG_EEE_SET, false))
156*1b481fc3SMaciej Żenczykowski 		return -EOPNOTSUPP;
157*1b481fc3SMaciej Żenczykowski 	if (!ctx->argc) {
158*1b481fc3SMaciej Żenczykowski 		fprintf(stderr, "ethtool (--set-eee): parameters missing\n");
159*1b481fc3SMaciej Żenczykowski 		return 1;
160*1b481fc3SMaciej Żenczykowski 	}
161*1b481fc3SMaciej Żenczykowski 
162*1b481fc3SMaciej Żenczykowski 	nlctx->cmd = "--set-eee";
163*1b481fc3SMaciej Żenczykowski 	nlctx->argp = ctx->argp;
164*1b481fc3SMaciej Żenczykowski 	nlctx->argc = ctx->argc;
165*1b481fc3SMaciej Żenczykowski 	nlctx->devname = ctx->devname;
166*1b481fc3SMaciej Żenczykowski 	nlsk = nlctx->ethnl_socket;
167*1b481fc3SMaciej Żenczykowski 	msgbuff = &nlsk->msgbuff;
168*1b481fc3SMaciej Żenczykowski 
169*1b481fc3SMaciej Żenczykowski 	ret = msg_init(nlctx, msgbuff, ETHTOOL_MSG_EEE_SET,
170*1b481fc3SMaciej Żenczykowski 		       NLM_F_REQUEST | NLM_F_ACK);
171*1b481fc3SMaciej Żenczykowski 	if (ret < 0)
172*1b481fc3SMaciej Żenczykowski 		return 2;
173*1b481fc3SMaciej Żenczykowski 	if (ethnla_fill_header(msgbuff, ETHTOOL_A_EEE_HEADER,
174*1b481fc3SMaciej Żenczykowski 			       ctx->devname, 0))
175*1b481fc3SMaciej Żenczykowski 		return -EMSGSIZE;
176*1b481fc3SMaciej Żenczykowski 
177*1b481fc3SMaciej Żenczykowski 	ret = nl_parser(nlctx, seee_params, NULL, PARSER_GROUP_NONE, NULL);
178*1b481fc3SMaciej Żenczykowski 	if (ret < 0)
179*1b481fc3SMaciej Żenczykowski 		return 1;
180*1b481fc3SMaciej Żenczykowski 
181*1b481fc3SMaciej Żenczykowski 	ret = nlsock_sendmsg(nlsk, NULL);
182*1b481fc3SMaciej Żenczykowski 	if (ret < 0)
183*1b481fc3SMaciej Żenczykowski 		return 76;
184*1b481fc3SMaciej Żenczykowski 	ret = nlsock_process_reply(nlsk, nomsg_reply_cb, nlctx);
185*1b481fc3SMaciej Żenczykowski 	if (ret == 0)
186*1b481fc3SMaciej Żenczykowski 		return 0;
187*1b481fc3SMaciej Żenczykowski 	else
188*1b481fc3SMaciej Żenczykowski 		return nlctx->exit_code ?: 76;
189*1b481fc3SMaciej Żenczykowski }
190