1*1b481fc3SMaciej Żenczykowski /*
2*1b481fc3SMaciej Żenczykowski * fec.c - netlink implementation of FEC commands
3*1b481fc3SMaciej Żenczykowski *
4*1b481fc3SMaciej Żenczykowski * Implementation of "ethtool --show-fec <dev>" and
5*1b481fc3SMaciej Żenczykowski * "ethtool --set-fec <dev> ..."
6*1b481fc3SMaciej Żenczykowski */
7*1b481fc3SMaciej Żenczykowski
8*1b481fc3SMaciej Żenczykowski #include <errno.h>
9*1b481fc3SMaciej Żenczykowski #include <ctype.h>
10*1b481fc3SMaciej Żenczykowski #include <inttypes.h>
11*1b481fc3SMaciej Żenczykowski #include <string.h>
12*1b481fc3SMaciej Żenczykowski #include <strings.h>
13*1b481fc3SMaciej Żenczykowski #include <stdio.h>
14*1b481fc3SMaciej Żenczykowski
15*1b481fc3SMaciej Żenczykowski #include "../internal.h"
16*1b481fc3SMaciej Żenczykowski #include "../common.h"
17*1b481fc3SMaciej Żenczykowski #include "netlink.h"
18*1b481fc3SMaciej Żenczykowski #include "bitset.h"
19*1b481fc3SMaciej Żenczykowski #include "parser.h"
20*1b481fc3SMaciej Żenczykowski
21*1b481fc3SMaciej Żenczykowski /* FEC_GET */
22*1b481fc3SMaciej Żenczykowski
23*1b481fc3SMaciej Żenczykowski static void
fec_mode_walk(unsigned int idx,const char * name,bool val,void * data)24*1b481fc3SMaciej Żenczykowski fec_mode_walk(unsigned int idx, const char *name, bool val, void *data)
25*1b481fc3SMaciej Żenczykowski {
26*1b481fc3SMaciej Żenczykowski bool *empty = data;
27*1b481fc3SMaciej Żenczykowski
28*1b481fc3SMaciej Żenczykowski if (!val)
29*1b481fc3SMaciej Żenczykowski return;
30*1b481fc3SMaciej Żenczykowski if (empty)
31*1b481fc3SMaciej Żenczykowski *empty = false;
32*1b481fc3SMaciej Żenczykowski
33*1b481fc3SMaciej Żenczykowski /* Rename None to Off - in legacy ioctl None means "not supported"
34*1b481fc3SMaciej Żenczykowski * rather than supported but disabled.
35*1b481fc3SMaciej Żenczykowski */
36*1b481fc3SMaciej Żenczykowski if (idx == ETHTOOL_LINK_MODE_FEC_NONE_BIT)
37*1b481fc3SMaciej Żenczykowski name = "Off";
38*1b481fc3SMaciej Żenczykowski /* Rename to match the ioctl letter case */
39*1b481fc3SMaciej Żenczykowski else if (idx == ETHTOOL_LINK_MODE_FEC_BASER_BIT)
40*1b481fc3SMaciej Żenczykowski name = "BaseR";
41*1b481fc3SMaciej Żenczykowski
42*1b481fc3SMaciej Żenczykowski print_string(PRINT_ANY, NULL, " %s", name);
43*1b481fc3SMaciej Żenczykowski }
44*1b481fc3SMaciej Żenczykowski
fec_show_stats(const struct nlattr * nest)45*1b481fc3SMaciej Żenczykowski static int fec_show_stats(const struct nlattr *nest)
46*1b481fc3SMaciej Żenczykowski {
47*1b481fc3SMaciej Żenczykowski const struct nlattr *tb[ETHTOOL_A_FEC_STAT_MAX + 1] = {};
48*1b481fc3SMaciej Żenczykowski DECLARE_ATTR_TB_INFO(tb);
49*1b481fc3SMaciej Żenczykowski static const struct {
50*1b481fc3SMaciej Żenczykowski unsigned int attr;
51*1b481fc3SMaciej Żenczykowski char *name;
52*1b481fc3SMaciej Żenczykowski } stats[] = {
53*1b481fc3SMaciej Żenczykowski { ETHTOOL_A_FEC_STAT_CORRECTED, "corrected_blocks" },
54*1b481fc3SMaciej Żenczykowski { ETHTOOL_A_FEC_STAT_UNCORR, "uncorrectable_blocks" },
55*1b481fc3SMaciej Żenczykowski { ETHTOOL_A_FEC_STAT_CORR_BITS, "corrected_bits" },
56*1b481fc3SMaciej Żenczykowski };
57*1b481fc3SMaciej Żenczykowski bool header = false;
58*1b481fc3SMaciej Żenczykowski unsigned int i;
59*1b481fc3SMaciej Żenczykowski int ret;
60*1b481fc3SMaciej Żenczykowski
61*1b481fc3SMaciej Żenczykowski ret = mnl_attr_parse_nested(nest, attr_cb, &tb_info);
62*1b481fc3SMaciej Żenczykowski if (ret < 0)
63*1b481fc3SMaciej Żenczykowski return ret;
64*1b481fc3SMaciej Żenczykowski
65*1b481fc3SMaciej Żenczykowski open_json_object("statistics");
66*1b481fc3SMaciej Żenczykowski for (i = 0; i < ARRAY_SIZE(stats); i++) {
67*1b481fc3SMaciej Żenczykowski uint64_t *vals;
68*1b481fc3SMaciej Żenczykowski int lanes, l;
69*1b481fc3SMaciej Żenczykowski
70*1b481fc3SMaciej Żenczykowski if (!tb[stats[i].attr] ||
71*1b481fc3SMaciej Żenczykowski !mnl_attr_get_payload_len(tb[stats[i].attr]))
72*1b481fc3SMaciej Żenczykowski continue;
73*1b481fc3SMaciej Żenczykowski
74*1b481fc3SMaciej Żenczykowski if (!header && !is_json_context()) {
75*1b481fc3SMaciej Żenczykowski printf("Statistics:\n");
76*1b481fc3SMaciej Żenczykowski header = true;
77*1b481fc3SMaciej Żenczykowski }
78*1b481fc3SMaciej Żenczykowski
79*1b481fc3SMaciej Żenczykowski if (mnl_attr_get_payload_len(tb[stats[i].attr]) % 8) {
80*1b481fc3SMaciej Żenczykowski fprintf(stderr, "malformed netlink message (statistic)\n");
81*1b481fc3SMaciej Żenczykowski goto err_close_stats;
82*1b481fc3SMaciej Żenczykowski }
83*1b481fc3SMaciej Żenczykowski
84*1b481fc3SMaciej Żenczykowski vals = mnl_attr_get_payload(tb[stats[i].attr]);
85*1b481fc3SMaciej Żenczykowski lanes = mnl_attr_get_payload_len(tb[stats[i].attr]) / 8 - 1;
86*1b481fc3SMaciej Żenczykowski
87*1b481fc3SMaciej Żenczykowski if (!is_json_context()) {
88*1b481fc3SMaciej Żenczykowski fprintf(stdout, " %s: %" PRIu64 "\n",
89*1b481fc3SMaciej Żenczykowski stats[i].name, *vals++);
90*1b481fc3SMaciej Żenczykowski } else {
91*1b481fc3SMaciej Żenczykowski open_json_object(stats[i].name);
92*1b481fc3SMaciej Żenczykowski print_u64(PRINT_JSON, "total", NULL, *vals++);
93*1b481fc3SMaciej Żenczykowski }
94*1b481fc3SMaciej Żenczykowski
95*1b481fc3SMaciej Żenczykowski if (lanes)
96*1b481fc3SMaciej Żenczykowski open_json_array("lanes", "");
97*1b481fc3SMaciej Żenczykowski for (l = 0; l < lanes; l++) {
98*1b481fc3SMaciej Żenczykowski if (!is_json_context())
99*1b481fc3SMaciej Żenczykowski fprintf(stdout, " Lane %d: %" PRIu64 "\n",
100*1b481fc3SMaciej Żenczykowski l, *vals++);
101*1b481fc3SMaciej Żenczykowski else
102*1b481fc3SMaciej Żenczykowski print_u64(PRINT_JSON, NULL, NULL, *vals++);
103*1b481fc3SMaciej Żenczykowski }
104*1b481fc3SMaciej Żenczykowski if (lanes)
105*1b481fc3SMaciej Żenczykowski close_json_array("");
106*1b481fc3SMaciej Żenczykowski
107*1b481fc3SMaciej Żenczykowski close_json_object();
108*1b481fc3SMaciej Żenczykowski }
109*1b481fc3SMaciej Żenczykowski close_json_object();
110*1b481fc3SMaciej Żenczykowski
111*1b481fc3SMaciej Żenczykowski return 0;
112*1b481fc3SMaciej Żenczykowski
113*1b481fc3SMaciej Żenczykowski err_close_stats:
114*1b481fc3SMaciej Żenczykowski close_json_object();
115*1b481fc3SMaciej Żenczykowski return -1;
116*1b481fc3SMaciej Żenczykowski }
117*1b481fc3SMaciej Żenczykowski
fec_reply_cb(const struct nlmsghdr * nlhdr,void * data)118*1b481fc3SMaciej Żenczykowski int fec_reply_cb(const struct nlmsghdr *nlhdr, void *data)
119*1b481fc3SMaciej Żenczykowski {
120*1b481fc3SMaciej Żenczykowski const struct nlattr *tb[ETHTOOL_A_FEC_MAX + 1] = {};
121*1b481fc3SMaciej Żenczykowski DECLARE_ATTR_TB_INFO(tb);
122*1b481fc3SMaciej Żenczykowski struct nl_context *nlctx = data;
123*1b481fc3SMaciej Żenczykowski const struct stringset *lm_strings;
124*1b481fc3SMaciej Żenczykowski const char *name;
125*1b481fc3SMaciej Żenczykowski bool fa, empty;
126*1b481fc3SMaciej Żenczykowski bool silent;
127*1b481fc3SMaciej Żenczykowski int err_ret;
128*1b481fc3SMaciej Żenczykowski u32 active;
129*1b481fc3SMaciej Żenczykowski int ret;
130*1b481fc3SMaciej Żenczykowski
131*1b481fc3SMaciej Żenczykowski silent = nlctx->is_dump || nlctx->is_monitor;
132*1b481fc3SMaciej Żenczykowski err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR;
133*1b481fc3SMaciej Żenczykowski ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
134*1b481fc3SMaciej Żenczykowski if (ret < 0)
135*1b481fc3SMaciej Żenczykowski return err_ret;
136*1b481fc3SMaciej Żenczykowski nlctx->devname = get_dev_name(tb[ETHTOOL_A_FEC_HEADER]);
137*1b481fc3SMaciej Żenczykowski if (!dev_ok(nlctx))
138*1b481fc3SMaciej Żenczykowski return err_ret;
139*1b481fc3SMaciej Żenczykowski
140*1b481fc3SMaciej Żenczykowski ret = netlink_init_ethnl2_socket(nlctx);
141*1b481fc3SMaciej Żenczykowski if (ret < 0)
142*1b481fc3SMaciej Żenczykowski return err_ret;
143*1b481fc3SMaciej Żenczykowski lm_strings = global_stringset(ETH_SS_LINK_MODES, nlctx->ethnl2_socket);
144*1b481fc3SMaciej Żenczykowski
145*1b481fc3SMaciej Żenczykowski active = 0;
146*1b481fc3SMaciej Żenczykowski if (tb[ETHTOOL_A_FEC_ACTIVE])
147*1b481fc3SMaciej Żenczykowski active = mnl_attr_get_u32(tb[ETHTOOL_A_FEC_ACTIVE]);
148*1b481fc3SMaciej Żenczykowski
149*1b481fc3SMaciej Żenczykowski if (silent)
150*1b481fc3SMaciej Żenczykowski print_nl();
151*1b481fc3SMaciej Żenczykowski
152*1b481fc3SMaciej Żenczykowski open_json_object(NULL);
153*1b481fc3SMaciej Żenczykowski
154*1b481fc3SMaciej Żenczykowski print_string(PRINT_ANY, "ifname", "FEC parameters for %s:\n",
155*1b481fc3SMaciej Żenczykowski nlctx->devname);
156*1b481fc3SMaciej Żenczykowski
157*1b481fc3SMaciej Żenczykowski open_json_array("config", "Supported/Configured FEC encodings:");
158*1b481fc3SMaciej Żenczykowski fa = tb[ETHTOOL_A_FEC_AUTO] && mnl_attr_get_u8(tb[ETHTOOL_A_FEC_AUTO]);
159*1b481fc3SMaciej Żenczykowski if (fa)
160*1b481fc3SMaciej Żenczykowski print_string(PRINT_ANY, NULL, " %s", "Auto");
161*1b481fc3SMaciej Żenczykowski empty = !fa;
162*1b481fc3SMaciej Żenczykowski
163*1b481fc3SMaciej Żenczykowski ret = walk_bitset(tb[ETHTOOL_A_FEC_MODES], lm_strings, fec_mode_walk,
164*1b481fc3SMaciej Żenczykowski &empty);
165*1b481fc3SMaciej Żenczykowski if (ret < 0)
166*1b481fc3SMaciej Żenczykowski goto err_close_dev;
167*1b481fc3SMaciej Żenczykowski if (empty)
168*1b481fc3SMaciej Żenczykowski print_string(PRINT_ANY, NULL, " %s", "None");
169*1b481fc3SMaciej Żenczykowski close_json_array("\n");
170*1b481fc3SMaciej Żenczykowski
171*1b481fc3SMaciej Żenczykowski open_json_array("active", "Active FEC encoding:");
172*1b481fc3SMaciej Żenczykowski if (active) {
173*1b481fc3SMaciej Żenczykowski name = get_string(lm_strings, active);
174*1b481fc3SMaciej Żenczykowski if (name)
175*1b481fc3SMaciej Żenczykowski /* Take care of renames */
176*1b481fc3SMaciej Żenczykowski fec_mode_walk(active, name, true, NULL);
177*1b481fc3SMaciej Żenczykowski else
178*1b481fc3SMaciej Żenczykowski print_uint(PRINT_ANY, NULL, " BIT%u", active);
179*1b481fc3SMaciej Żenczykowski } else {
180*1b481fc3SMaciej Żenczykowski print_string(PRINT_ANY, NULL, " %s", "None");
181*1b481fc3SMaciej Żenczykowski }
182*1b481fc3SMaciej Żenczykowski close_json_array("\n");
183*1b481fc3SMaciej Żenczykowski
184*1b481fc3SMaciej Żenczykowski if (tb[ETHTOOL_A_FEC_STATS]) {
185*1b481fc3SMaciej Żenczykowski ret = fec_show_stats(tb[ETHTOOL_A_FEC_STATS]);
186*1b481fc3SMaciej Żenczykowski if (ret < 0)
187*1b481fc3SMaciej Żenczykowski goto err_close_dev;
188*1b481fc3SMaciej Żenczykowski }
189*1b481fc3SMaciej Żenczykowski
190*1b481fc3SMaciej Żenczykowski close_json_object();
191*1b481fc3SMaciej Żenczykowski
192*1b481fc3SMaciej Żenczykowski return MNL_CB_OK;
193*1b481fc3SMaciej Żenczykowski
194*1b481fc3SMaciej Żenczykowski err_close_dev:
195*1b481fc3SMaciej Żenczykowski close_json_object();
196*1b481fc3SMaciej Żenczykowski return err_ret;
197*1b481fc3SMaciej Żenczykowski }
198*1b481fc3SMaciej Żenczykowski
nl_gfec(struct cmd_context * ctx)199*1b481fc3SMaciej Żenczykowski int nl_gfec(struct cmd_context *ctx)
200*1b481fc3SMaciej Żenczykowski {
201*1b481fc3SMaciej Żenczykowski struct nl_context *nlctx = ctx->nlctx;
202*1b481fc3SMaciej Żenczykowski struct nl_socket *nlsk = nlctx->ethnl_socket;
203*1b481fc3SMaciej Żenczykowski u32 flags;
204*1b481fc3SMaciej Żenczykowski int ret;
205*1b481fc3SMaciej Żenczykowski
206*1b481fc3SMaciej Żenczykowski if (netlink_cmd_check(ctx, ETHTOOL_MSG_FEC_GET, true))
207*1b481fc3SMaciej Żenczykowski return -EOPNOTSUPP;
208*1b481fc3SMaciej Żenczykowski if (ctx->argc > 0) {
209*1b481fc3SMaciej Żenczykowski fprintf(stderr, "ethtool: unexpected parameter '%s'\n",
210*1b481fc3SMaciej Żenczykowski *ctx->argp);
211*1b481fc3SMaciej Żenczykowski return 1;
212*1b481fc3SMaciej Żenczykowski }
213*1b481fc3SMaciej Żenczykowski
214*1b481fc3SMaciej Żenczykowski flags = get_stats_flag(nlctx, ETHTOOL_MSG_FEC_GET,
215*1b481fc3SMaciej Żenczykowski ETHTOOL_A_FEC_HEADER);
216*1b481fc3SMaciej Żenczykowski ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_FEC_GET,
217*1b481fc3SMaciej Żenczykowski ETHTOOL_A_FEC_HEADER, flags);
218*1b481fc3SMaciej Żenczykowski if (ret < 0)
219*1b481fc3SMaciej Żenczykowski return ret;
220*1b481fc3SMaciej Żenczykowski
221*1b481fc3SMaciej Żenczykowski new_json_obj(ctx->json);
222*1b481fc3SMaciej Żenczykowski ret = nlsock_send_get_request(nlsk, fec_reply_cb);
223*1b481fc3SMaciej Żenczykowski delete_json_obj();
224*1b481fc3SMaciej Żenczykowski return ret;
225*1b481fc3SMaciej Żenczykowski }
226*1b481fc3SMaciej Żenczykowski
227*1b481fc3SMaciej Żenczykowski /* FEC_SET */
228*1b481fc3SMaciej Żenczykowski
strupc(char * dst,const char * src)229*1b481fc3SMaciej Żenczykowski static void strupc(char *dst, const char *src)
230*1b481fc3SMaciej Żenczykowski {
231*1b481fc3SMaciej Żenczykowski while (*src)
232*1b481fc3SMaciej Żenczykowski *dst++ = toupper(*src++);
233*1b481fc3SMaciej Żenczykowski *dst = '\0';
234*1b481fc3SMaciej Żenczykowski }
235*1b481fc3SMaciej Żenczykowski
fec_parse_bitset(struct nl_context * nlctx,uint16_t type,const void * data __maybe_unused,struct nl_msg_buff * msgbuff,void * dest)236*1b481fc3SMaciej Żenczykowski static int fec_parse_bitset(struct nl_context *nlctx, uint16_t type,
237*1b481fc3SMaciej Żenczykowski const void *data __maybe_unused,
238*1b481fc3SMaciej Żenczykowski struct nl_msg_buff *msgbuff, void *dest)
239*1b481fc3SMaciej Żenczykowski {
240*1b481fc3SMaciej Żenczykowski struct nlattr *bitset_attr;
241*1b481fc3SMaciej Żenczykowski struct nlattr *bits_attr;
242*1b481fc3SMaciej Żenczykowski struct nlattr *bit_attr;
243*1b481fc3SMaciej Żenczykowski char upper[ETH_GSTRING_LEN];
244*1b481fc3SMaciej Żenczykowski bool fec_auto = false;
245*1b481fc3SMaciej Żenczykowski int ret;
246*1b481fc3SMaciej Żenczykowski
247*1b481fc3SMaciej Żenczykowski if (!type || dest) {
248*1b481fc3SMaciej Żenczykowski fprintf(stderr, "ethtool (%s): internal error parsing '%s'\n",
249*1b481fc3SMaciej Żenczykowski nlctx->cmd, nlctx->param);
250*1b481fc3SMaciej Żenczykowski return -EFAULT;
251*1b481fc3SMaciej Żenczykowski }
252*1b481fc3SMaciej Żenczykowski
253*1b481fc3SMaciej Żenczykowski bitset_attr = ethnla_nest_start(msgbuff, type);
254*1b481fc3SMaciej Żenczykowski if (!bitset_attr)
255*1b481fc3SMaciej Żenczykowski return -EMSGSIZE;
256*1b481fc3SMaciej Żenczykowski ret = -EMSGSIZE;
257*1b481fc3SMaciej Żenczykowski if (ethnla_put_flag(msgbuff, ETHTOOL_A_BITSET_NOMASK, true))
258*1b481fc3SMaciej Żenczykowski goto err;
259*1b481fc3SMaciej Żenczykowski bits_attr = ethnla_nest_start(msgbuff, ETHTOOL_A_BITSET_BITS);
260*1b481fc3SMaciej Żenczykowski if (!bits_attr)
261*1b481fc3SMaciej Żenczykowski goto err;
262*1b481fc3SMaciej Żenczykowski
263*1b481fc3SMaciej Żenczykowski while (nlctx->argc > 0) {
264*1b481fc3SMaciej Żenczykowski const char *name = *nlctx->argp;
265*1b481fc3SMaciej Żenczykowski
266*1b481fc3SMaciej Żenczykowski if (!strcmp(name, "--")) {
267*1b481fc3SMaciej Żenczykowski nlctx->argp++;
268*1b481fc3SMaciej Żenczykowski nlctx->argc--;
269*1b481fc3SMaciej Żenczykowski break;
270*1b481fc3SMaciej Żenczykowski }
271*1b481fc3SMaciej Żenczykowski
272*1b481fc3SMaciej Żenczykowski if (!strcasecmp(name, "auto")) {
273*1b481fc3SMaciej Żenczykowski fec_auto = true;
274*1b481fc3SMaciej Żenczykowski goto next;
275*1b481fc3SMaciej Żenczykowski }
276*1b481fc3SMaciej Żenczykowski if (!strcasecmp(name, "off")) {
277*1b481fc3SMaciej Żenczykowski name = "None";
278*1b481fc3SMaciej Żenczykowski } else {
279*1b481fc3SMaciej Żenczykowski strupc(upper, name);
280*1b481fc3SMaciej Żenczykowski name = upper;
281*1b481fc3SMaciej Żenczykowski }
282*1b481fc3SMaciej Żenczykowski
283*1b481fc3SMaciej Żenczykowski ret = -EMSGSIZE;
284*1b481fc3SMaciej Żenczykowski bit_attr = ethnla_nest_start(msgbuff,
285*1b481fc3SMaciej Żenczykowski ETHTOOL_A_BITSET_BITS_BIT);
286*1b481fc3SMaciej Żenczykowski if (!bit_attr)
287*1b481fc3SMaciej Żenczykowski goto err;
288*1b481fc3SMaciej Żenczykowski if (ethnla_put_strz(msgbuff, ETHTOOL_A_BITSET_BIT_NAME, name))
289*1b481fc3SMaciej Żenczykowski goto err;
290*1b481fc3SMaciej Żenczykowski ethnla_nest_end(msgbuff, bit_attr);
291*1b481fc3SMaciej Żenczykowski
292*1b481fc3SMaciej Żenczykowski next:
293*1b481fc3SMaciej Żenczykowski nlctx->argp++;
294*1b481fc3SMaciej Żenczykowski nlctx->argc--;
295*1b481fc3SMaciej Żenczykowski }
296*1b481fc3SMaciej Żenczykowski
297*1b481fc3SMaciej Żenczykowski ethnla_nest_end(msgbuff, bits_attr);
298*1b481fc3SMaciej Żenczykowski ethnla_nest_end(msgbuff, bitset_attr);
299*1b481fc3SMaciej Żenczykowski
300*1b481fc3SMaciej Żenczykowski if (ethnla_put_u8(msgbuff, ETHTOOL_A_FEC_AUTO, fec_auto))
301*1b481fc3SMaciej Żenczykowski goto err;
302*1b481fc3SMaciej Żenczykowski
303*1b481fc3SMaciej Żenczykowski return 0;
304*1b481fc3SMaciej Żenczykowski err:
305*1b481fc3SMaciej Żenczykowski ethnla_nest_cancel(msgbuff, bitset_attr);
306*1b481fc3SMaciej Żenczykowski return ret;
307*1b481fc3SMaciej Żenczykowski }
308*1b481fc3SMaciej Żenczykowski
309*1b481fc3SMaciej Żenczykowski static const struct param_parser sfec_params[] = {
310*1b481fc3SMaciej Żenczykowski {
311*1b481fc3SMaciej Żenczykowski .arg = "encoding",
312*1b481fc3SMaciej Żenczykowski .type = ETHTOOL_A_FEC_MODES,
313*1b481fc3SMaciej Żenczykowski .handler = fec_parse_bitset,
314*1b481fc3SMaciej Żenczykowski .min_argc = 1,
315*1b481fc3SMaciej Żenczykowski },
316*1b481fc3SMaciej Żenczykowski {}
317*1b481fc3SMaciej Żenczykowski };
318*1b481fc3SMaciej Żenczykowski
nl_sfec(struct cmd_context * ctx)319*1b481fc3SMaciej Żenczykowski int nl_sfec(struct cmd_context *ctx)
320*1b481fc3SMaciej Żenczykowski {
321*1b481fc3SMaciej Żenczykowski struct nl_context *nlctx = ctx->nlctx;
322*1b481fc3SMaciej Żenczykowski struct nl_msg_buff *msgbuff;
323*1b481fc3SMaciej Żenczykowski struct nl_socket *nlsk;
324*1b481fc3SMaciej Żenczykowski int ret;
325*1b481fc3SMaciej Żenczykowski
326*1b481fc3SMaciej Żenczykowski if (netlink_cmd_check(ctx, ETHTOOL_MSG_FEC_SET, false))
327*1b481fc3SMaciej Żenczykowski return -EOPNOTSUPP;
328*1b481fc3SMaciej Żenczykowski if (!ctx->argc) {
329*1b481fc3SMaciej Żenczykowski fprintf(stderr, "ethtool (--set-fec): parameters missing\n");
330*1b481fc3SMaciej Żenczykowski return 1;
331*1b481fc3SMaciej Żenczykowski }
332*1b481fc3SMaciej Żenczykowski
333*1b481fc3SMaciej Żenczykowski nlctx->cmd = "--set-fec";
334*1b481fc3SMaciej Żenczykowski nlctx->argp = ctx->argp;
335*1b481fc3SMaciej Żenczykowski nlctx->argc = ctx->argc;
336*1b481fc3SMaciej Żenczykowski nlctx->devname = ctx->devname;
337*1b481fc3SMaciej Żenczykowski nlsk = nlctx->ethnl_socket;
338*1b481fc3SMaciej Żenczykowski msgbuff = &nlsk->msgbuff;
339*1b481fc3SMaciej Żenczykowski
340*1b481fc3SMaciej Żenczykowski ret = msg_init(nlctx, msgbuff, ETHTOOL_MSG_FEC_SET,
341*1b481fc3SMaciej Żenczykowski NLM_F_REQUEST | NLM_F_ACK);
342*1b481fc3SMaciej Żenczykowski if (ret < 0)
343*1b481fc3SMaciej Żenczykowski return 2;
344*1b481fc3SMaciej Żenczykowski if (ethnla_fill_header(msgbuff, ETHTOOL_A_FEC_HEADER,
345*1b481fc3SMaciej Żenczykowski ctx->devname, 0))
346*1b481fc3SMaciej Żenczykowski return -EMSGSIZE;
347*1b481fc3SMaciej Żenczykowski
348*1b481fc3SMaciej Żenczykowski ret = nl_parser(nlctx, sfec_params, NULL, PARSER_GROUP_NONE, NULL);
349*1b481fc3SMaciej Żenczykowski if (ret < 0)
350*1b481fc3SMaciej Żenczykowski return 1;
351*1b481fc3SMaciej Żenczykowski
352*1b481fc3SMaciej Żenczykowski ret = nlsock_sendmsg(nlsk, NULL);
353*1b481fc3SMaciej Żenczykowski if (ret < 0)
354*1b481fc3SMaciej Żenczykowski return 83;
355*1b481fc3SMaciej Żenczykowski ret = nlsock_process_reply(nlsk, nomsg_reply_cb, nlctx);
356*1b481fc3SMaciej Żenczykowski if (ret == 0)
357*1b481fc3SMaciej Żenczykowski return 0;
358*1b481fc3SMaciej Żenczykowski else
359*1b481fc3SMaciej Żenczykowski return nlctx->exit_code ?: 83;
360*1b481fc3SMaciej Żenczykowski }
361