xref: /aosp_15_r20/external/ethtool/netlink/channels.c (revision 1b481fc3bb1b45d4cf28d1ec12969dc1055f555d)
1 /*
2  * channels.c - netlink implementation of channel commands
3  *
4  * Implementation of "ethtool -l <dev>" and "ethtool -L <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 /* CHANNELS_GET */
17 
channels_reply_cb(const struct nlmsghdr * nlhdr,void * data)18 int channels_reply_cb(const struct nlmsghdr *nlhdr, void *data)
19 {
20 	const struct nlattr *tb[ETHTOOL_A_CHANNELS_MAX + 1] = {};
21 	DECLARE_ATTR_TB_INFO(tb);
22 	struct nl_context *nlctx = data;
23 	bool silent;
24 	int err_ret;
25 	int ret;
26 
27 	silent = nlctx->is_dump || nlctx->is_monitor;
28 	err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR;
29 	ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
30 	if (ret < 0)
31 		return err_ret;
32 	nlctx->devname = get_dev_name(tb[ETHTOOL_A_CHANNELS_HEADER]);
33 	if (!dev_ok(nlctx))
34 		return err_ret;
35 
36 	if (silent)
37 		putchar('\n');
38 	printf("Channel parameters for %s:\n", nlctx->devname);
39 	printf("Pre-set maximums:\n");
40 	show_u32("rx-max", "RX:\t\t", tb[ETHTOOL_A_CHANNELS_RX_MAX]);
41 	show_u32("tx-max", "TX:\t\t", tb[ETHTOOL_A_CHANNELS_TX_MAX]);
42 	show_u32("other-max", "Other:\t\t", tb[ETHTOOL_A_CHANNELS_OTHER_MAX]);
43 	show_u32("combined-max", "Combined:\t",
44 		 tb[ETHTOOL_A_CHANNELS_COMBINED_MAX]);
45 	printf("Current hardware settings:\n");
46 	show_u32("rx", "RX:\t\t", tb[ETHTOOL_A_CHANNELS_RX_COUNT]);
47 	show_u32("tx", "TX:\t\t", tb[ETHTOOL_A_CHANNELS_TX_COUNT]);
48 	show_u32("other", "Other:\t\t", tb[ETHTOOL_A_CHANNELS_OTHER_COUNT]);
49 	show_u32("combined", "Combined:\t",
50 		 tb[ETHTOOL_A_CHANNELS_COMBINED_COUNT]);
51 
52 	return MNL_CB_OK;
53 }
54 
nl_gchannels(struct cmd_context * ctx)55 int nl_gchannels(struct cmd_context *ctx)
56 {
57 	struct nl_context *nlctx = ctx->nlctx;
58 	struct nl_socket *nlsk = nlctx->ethnl_socket;
59 	int ret;
60 
61 	if (netlink_cmd_check(ctx, ETHTOOL_MSG_CHANNELS_GET, true))
62 		return -EOPNOTSUPP;
63 	if (ctx->argc > 0) {
64 		fprintf(stderr, "ethtool: unexpected parameter '%s'\n",
65 			*ctx->argp);
66 		return 1;
67 	}
68 
69 	ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_CHANNELS_GET,
70 				      ETHTOOL_A_CHANNELS_HEADER, 0);
71 	if (ret < 0)
72 		return ret;
73 	return nlsock_send_get_request(nlsk, channels_reply_cb);
74 }
75 
76 /* CHANNELS_SET */
77 
78 static const struct param_parser schannels_params[] = {
79 	{
80 		.arg		= "rx",
81 		.type		= ETHTOOL_A_CHANNELS_RX_COUNT,
82 		.handler	= nl_parse_direct_u32,
83 		.min_argc	= 1,
84 	},
85 	{
86 		.arg		= "tx",
87 		.type		= ETHTOOL_A_CHANNELS_TX_COUNT,
88 		.handler	= nl_parse_direct_u32,
89 		.min_argc	= 1,
90 	},
91 	{
92 		.arg		= "other",
93 		.type		= ETHTOOL_A_CHANNELS_OTHER_COUNT,
94 		.handler	= nl_parse_direct_u32,
95 		.min_argc	= 1,
96 	},
97 	{
98 		.arg		= "combined",
99 		.type		= ETHTOOL_A_CHANNELS_COMBINED_COUNT,
100 		.handler	= nl_parse_direct_u32,
101 		.min_argc	= 1,
102 	},
103 	{}
104 };
105 
nl_schannels(struct cmd_context * ctx)106 int nl_schannels(struct cmd_context *ctx)
107 {
108 	struct nl_context *nlctx = ctx->nlctx;
109 	struct nl_msg_buff *msgbuff;
110 	struct nl_socket *nlsk;
111 	int ret;
112 
113 	if (netlink_cmd_check(ctx, ETHTOOL_MSG_CHANNELS_SET, false))
114 		return -EOPNOTSUPP;
115 
116 	nlctx->cmd = "-L";
117 	nlctx->argp = ctx->argp;
118 	nlctx->argc = ctx->argc;
119 	nlctx->devname = ctx->devname;
120 	nlsk = nlctx->ethnl_socket;
121 	msgbuff = &nlsk->msgbuff;
122 
123 	ret = msg_init(nlctx, msgbuff, ETHTOOL_MSG_CHANNELS_SET,
124 		       NLM_F_REQUEST | NLM_F_ACK);
125 	if (ret < 0)
126 		return 2;
127 	if (ethnla_fill_header(msgbuff, ETHTOOL_A_CHANNELS_HEADER,
128 			       ctx->devname, 0))
129 		return -EMSGSIZE;
130 
131 	ret = nl_parser(nlctx, schannels_params, NULL, PARSER_GROUP_NONE, NULL);
132 	if (ret < 0)
133 		return 1;
134 
135 	ret = nlsock_sendmsg(nlsk, NULL);
136 	if (ret < 0)
137 		return 1;
138 	ret = nlsock_process_reply(nlsk, nomsg_reply_cb, nlctx);
139 	if (ret == 0)
140 		return 0;
141 	else
142 		return nlctx->exit_code ?: 1;
143 }
144