1*2d7be507SJakub Kicinski // SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
2*2d7be507SJakub Kicinski /* Do not edit directly, auto-generated from: */
3*2d7be507SJakub Kicinski /*	Documentation/netlink/specs/ethtool.yaml */
4*2d7be507SJakub Kicinski /* YNL-GEN user source */
5*2d7be507SJakub Kicinski /* YNL-ARG --user-header linux/ethtool_netlink.h --exclude-op stats-get */
6*2d7be507SJakub Kicinski 
7*2d7be507SJakub Kicinski #include <stdlib.h>
8*2d7be507SJakub Kicinski #include <string.h>
9*2d7be507SJakub Kicinski #include "ethtool-user.h"
10*2d7be507SJakub Kicinski #include "ynl.h"
11*2d7be507SJakub Kicinski #include <linux/ethtool.h>
12*2d7be507SJakub Kicinski 
13*2d7be507SJakub Kicinski #include <libmnl/libmnl.h>
14*2d7be507SJakub Kicinski #include <linux/genetlink.h>
15*2d7be507SJakub Kicinski 
16*2d7be507SJakub Kicinski #include "linux/ethtool_netlink.h"
17*2d7be507SJakub Kicinski 
18*2d7be507SJakub Kicinski /* Enums */
19*2d7be507SJakub Kicinski static const char * const ethtool_op_strmap[] = {
20*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_STRSET_GET] = "strset-get",
21*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_LINKINFO_GET] = "linkinfo-get",
22*2d7be507SJakub Kicinski 	[3] = "linkinfo-ntf",
23*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_LINKMODES_GET] = "linkmodes-get",
24*2d7be507SJakub Kicinski 	[5] = "linkmodes-ntf",
25*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_LINKSTATE_GET] = "linkstate-get",
26*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_DEBUG_GET] = "debug-get",
27*2d7be507SJakub Kicinski 	[8] = "debug-ntf",
28*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_WOL_GET] = "wol-get",
29*2d7be507SJakub Kicinski 	[10] = "wol-ntf",
30*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_FEATURES_GET] = "features-get",
31*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_FEATURES_SET] = "features-set",
32*2d7be507SJakub Kicinski 	[13] = "features-ntf",
33*2d7be507SJakub Kicinski 	[14] = "privflags-get",
34*2d7be507SJakub Kicinski 	[15] = "privflags-ntf",
35*2d7be507SJakub Kicinski 	[16] = "rings-get",
36*2d7be507SJakub Kicinski 	[17] = "rings-ntf",
37*2d7be507SJakub Kicinski 	[18] = "channels-get",
38*2d7be507SJakub Kicinski 	[19] = "channels-ntf",
39*2d7be507SJakub Kicinski 	[20] = "coalesce-get",
40*2d7be507SJakub Kicinski 	[21] = "coalesce-ntf",
41*2d7be507SJakub Kicinski 	[22] = "pause-get",
42*2d7be507SJakub Kicinski 	[23] = "pause-ntf",
43*2d7be507SJakub Kicinski 	[24] = "eee-get",
44*2d7be507SJakub Kicinski 	[25] = "eee-ntf",
45*2d7be507SJakub Kicinski 	[26] = "tsinfo-get",
46*2d7be507SJakub Kicinski 	[27] = "cable-test-ntf",
47*2d7be507SJakub Kicinski 	[28] = "cable-test-tdr-ntf",
48*2d7be507SJakub Kicinski 	[29] = "tunnel-info-get",
49*2d7be507SJakub Kicinski 	[30] = "fec-get",
50*2d7be507SJakub Kicinski 	[31] = "fec-ntf",
51*2d7be507SJakub Kicinski 	[32] = "module-eeprom-get",
52*2d7be507SJakub Kicinski 	[34] = "phc-vclocks-get",
53*2d7be507SJakub Kicinski 	[35] = "module-get",
54*2d7be507SJakub Kicinski 	[36] = "module-ntf",
55*2d7be507SJakub Kicinski 	[37] = "pse-get",
56*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_RSS_GET] = "rss-get",
57*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_PLCA_GET_CFG] = "plca-get-cfg",
58*2d7be507SJakub Kicinski 	[40] = "plca-get-status",
59*2d7be507SJakub Kicinski 	[41] = "plca-ntf",
60*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_MM_GET] = "mm-get",
61*2d7be507SJakub Kicinski 	[43] = "mm-ntf",
62*2d7be507SJakub Kicinski };
63*2d7be507SJakub Kicinski 
ethtool_op_str(int op)64*2d7be507SJakub Kicinski const char *ethtool_op_str(int op)
65*2d7be507SJakub Kicinski {
66*2d7be507SJakub Kicinski 	if (op < 0 || op >= (int)MNL_ARRAY_SIZE(ethtool_op_strmap))
67*2d7be507SJakub Kicinski 		return NULL;
68*2d7be507SJakub Kicinski 	return ethtool_op_strmap[op];
69*2d7be507SJakub Kicinski }
70*2d7be507SJakub Kicinski 
71*2d7be507SJakub Kicinski static const char * const ethtool_udp_tunnel_type_strmap[] = {
72*2d7be507SJakub Kicinski 	[0] = "vxlan",
73*2d7be507SJakub Kicinski 	[1] = "geneve",
74*2d7be507SJakub Kicinski 	[2] = "vxlan-gpe",
75*2d7be507SJakub Kicinski };
76*2d7be507SJakub Kicinski 
ethtool_udp_tunnel_type_str(int value)77*2d7be507SJakub Kicinski const char *ethtool_udp_tunnel_type_str(int value)
78*2d7be507SJakub Kicinski {
79*2d7be507SJakub Kicinski 	if (value < 0 || value >= (int)MNL_ARRAY_SIZE(ethtool_udp_tunnel_type_strmap))
80*2d7be507SJakub Kicinski 		return NULL;
81*2d7be507SJakub Kicinski 	return ethtool_udp_tunnel_type_strmap[value];
82*2d7be507SJakub Kicinski }
83*2d7be507SJakub Kicinski 
84*2d7be507SJakub Kicinski static const char * const ethtool_stringset_strmap[] = {
85*2d7be507SJakub Kicinski };
86*2d7be507SJakub Kicinski 
ethtool_stringset_str(enum ethtool_stringset value)87*2d7be507SJakub Kicinski const char *ethtool_stringset_str(enum ethtool_stringset value)
88*2d7be507SJakub Kicinski {
89*2d7be507SJakub Kicinski 	if (value < 0 || value >= (int)MNL_ARRAY_SIZE(ethtool_stringset_strmap))
90*2d7be507SJakub Kicinski 		return NULL;
91*2d7be507SJakub Kicinski 	return ethtool_stringset_strmap[value];
92*2d7be507SJakub Kicinski }
93*2d7be507SJakub Kicinski 
94*2d7be507SJakub Kicinski /* Policies */
95*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_header_policy[ETHTOOL_A_HEADER_MAX + 1] = {
96*2d7be507SJakub Kicinski 	[ETHTOOL_A_HEADER_DEV_INDEX] = { .name = "dev-index", .type = YNL_PT_U32, },
97*2d7be507SJakub Kicinski 	[ETHTOOL_A_HEADER_DEV_NAME] = { .name = "dev-name", .type = YNL_PT_NUL_STR, },
98*2d7be507SJakub Kicinski 	[ETHTOOL_A_HEADER_FLAGS] = { .name = "flags", .type = YNL_PT_U32, },
99*2d7be507SJakub Kicinski };
100*2d7be507SJakub Kicinski 
101*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_header_nest = {
102*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_HEADER_MAX,
103*2d7be507SJakub Kicinski 	.table = ethtool_header_policy,
104*2d7be507SJakub Kicinski };
105*2d7be507SJakub Kicinski 
106*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_pause_stat_policy[ETHTOOL_A_PAUSE_STAT_MAX + 1] = {
107*2d7be507SJakub Kicinski 	[ETHTOOL_A_PAUSE_STAT_PAD] = { .name = "pad", .type = YNL_PT_IGNORE, },
108*2d7be507SJakub Kicinski 	[ETHTOOL_A_PAUSE_STAT_TX_FRAMES] = { .name = "tx-frames", .type = YNL_PT_U64, },
109*2d7be507SJakub Kicinski 	[ETHTOOL_A_PAUSE_STAT_RX_FRAMES] = { .name = "rx-frames", .type = YNL_PT_U64, },
110*2d7be507SJakub Kicinski };
111*2d7be507SJakub Kicinski 
112*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_pause_stat_nest = {
113*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_PAUSE_STAT_MAX,
114*2d7be507SJakub Kicinski 	.table = ethtool_pause_stat_policy,
115*2d7be507SJakub Kicinski };
116*2d7be507SJakub Kicinski 
117*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_cable_test_tdr_cfg_policy[ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX + 1] = {
118*2d7be507SJakub Kicinski 	[ETHTOOL_A_CABLE_TEST_TDR_CFG_FIRST] = { .name = "first", .type = YNL_PT_U32, },
119*2d7be507SJakub Kicinski 	[ETHTOOL_A_CABLE_TEST_TDR_CFG_LAST] = { .name = "last", .type = YNL_PT_U32, },
120*2d7be507SJakub Kicinski 	[ETHTOOL_A_CABLE_TEST_TDR_CFG_STEP] = { .name = "step", .type = YNL_PT_U32, },
121*2d7be507SJakub Kicinski 	[ETHTOOL_A_CABLE_TEST_TDR_CFG_PAIR] = { .name = "pair", .type = YNL_PT_U8, },
122*2d7be507SJakub Kicinski };
123*2d7be507SJakub Kicinski 
124*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_cable_test_tdr_cfg_nest = {
125*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX,
126*2d7be507SJakub Kicinski 	.table = ethtool_cable_test_tdr_cfg_policy,
127*2d7be507SJakub Kicinski };
128*2d7be507SJakub Kicinski 
129*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_fec_stat_policy[ETHTOOL_A_FEC_STAT_MAX + 1] = {
130*2d7be507SJakub Kicinski 	[ETHTOOL_A_FEC_STAT_PAD] = { .name = "pad", .type = YNL_PT_IGNORE, },
131*2d7be507SJakub Kicinski 	[ETHTOOL_A_FEC_STAT_CORRECTED] = { .name = "corrected", .type = YNL_PT_BINARY,},
132*2d7be507SJakub Kicinski 	[ETHTOOL_A_FEC_STAT_UNCORR] = { .name = "uncorr", .type = YNL_PT_BINARY,},
133*2d7be507SJakub Kicinski 	[ETHTOOL_A_FEC_STAT_CORR_BITS] = { .name = "corr-bits", .type = YNL_PT_BINARY,},
134*2d7be507SJakub Kicinski };
135*2d7be507SJakub Kicinski 
136*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_fec_stat_nest = {
137*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_FEC_STAT_MAX,
138*2d7be507SJakub Kicinski 	.table = ethtool_fec_stat_policy,
139*2d7be507SJakub Kicinski };
140*2d7be507SJakub Kicinski 
141*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_mm_stat_policy[ETHTOOL_A_MM_STAT_MAX + 1] = {
142*2d7be507SJakub Kicinski 	[ETHTOOL_A_MM_STAT_PAD] = { .name = "pad", .type = YNL_PT_IGNORE, },
143*2d7be507SJakub Kicinski 	[ETHTOOL_A_MM_STAT_REASSEMBLY_ERRORS] = { .name = "reassembly-errors", .type = YNL_PT_U64, },
144*2d7be507SJakub Kicinski 	[ETHTOOL_A_MM_STAT_SMD_ERRORS] = { .name = "smd-errors", .type = YNL_PT_U64, },
145*2d7be507SJakub Kicinski 	[ETHTOOL_A_MM_STAT_REASSEMBLY_OK] = { .name = "reassembly-ok", .type = YNL_PT_U64, },
146*2d7be507SJakub Kicinski 	[ETHTOOL_A_MM_STAT_RX_FRAG_COUNT] = { .name = "rx-frag-count", .type = YNL_PT_U64, },
147*2d7be507SJakub Kicinski 	[ETHTOOL_A_MM_STAT_TX_FRAG_COUNT] = { .name = "tx-frag-count", .type = YNL_PT_U64, },
148*2d7be507SJakub Kicinski 	[ETHTOOL_A_MM_STAT_HOLD_COUNT] = { .name = "hold-count", .type = YNL_PT_U64, },
149*2d7be507SJakub Kicinski };
150*2d7be507SJakub Kicinski 
151*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_mm_stat_nest = {
152*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_MM_STAT_MAX,
153*2d7be507SJakub Kicinski 	.table = ethtool_mm_stat_policy,
154*2d7be507SJakub Kicinski };
155*2d7be507SJakub Kicinski 
156*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_cable_result_policy[ETHTOOL_A_CABLE_RESULT_MAX + 1] = {
157*2d7be507SJakub Kicinski 	[ETHTOOL_A_CABLE_RESULT_PAIR] = { .name = "pair", .type = YNL_PT_U8, },
158*2d7be507SJakub Kicinski 	[ETHTOOL_A_CABLE_RESULT_CODE] = { .name = "code", .type = YNL_PT_U8, },
159*2d7be507SJakub Kicinski };
160*2d7be507SJakub Kicinski 
161*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_cable_result_nest = {
162*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_CABLE_RESULT_MAX,
163*2d7be507SJakub Kicinski 	.table = ethtool_cable_result_policy,
164*2d7be507SJakub Kicinski };
165*2d7be507SJakub Kicinski 
166*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_cable_fault_length_policy[ETHTOOL_A_CABLE_FAULT_LENGTH_MAX + 1] = {
167*2d7be507SJakub Kicinski 	[ETHTOOL_A_CABLE_FAULT_LENGTH_PAIR] = { .name = "pair", .type = YNL_PT_U8, },
168*2d7be507SJakub Kicinski 	[ETHTOOL_A_CABLE_FAULT_LENGTH_CM] = { .name = "cm", .type = YNL_PT_U32, },
169*2d7be507SJakub Kicinski };
170*2d7be507SJakub Kicinski 
171*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_cable_fault_length_nest = {
172*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_CABLE_FAULT_LENGTH_MAX,
173*2d7be507SJakub Kicinski 	.table = ethtool_cable_fault_length_policy,
174*2d7be507SJakub Kicinski };
175*2d7be507SJakub Kicinski 
176*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_bitset_bit_policy[ETHTOOL_A_BITSET_BIT_MAX + 1] = {
177*2d7be507SJakub Kicinski 	[ETHTOOL_A_BITSET_BIT_INDEX] = { .name = "index", .type = YNL_PT_U32, },
178*2d7be507SJakub Kicinski 	[ETHTOOL_A_BITSET_BIT_NAME] = { .name = "name", .type = YNL_PT_NUL_STR, },
179*2d7be507SJakub Kicinski 	[ETHTOOL_A_BITSET_BIT_VALUE] = { .name = "value", .type = YNL_PT_FLAG, },
180*2d7be507SJakub Kicinski };
181*2d7be507SJakub Kicinski 
182*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_bitset_bit_nest = {
183*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_BITSET_BIT_MAX,
184*2d7be507SJakub Kicinski 	.table = ethtool_bitset_bit_policy,
185*2d7be507SJakub Kicinski };
186*2d7be507SJakub Kicinski 
187*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_tunnel_udp_entry_policy[ETHTOOL_A_TUNNEL_UDP_ENTRY_MAX + 1] = {
188*2d7be507SJakub Kicinski 	[ETHTOOL_A_TUNNEL_UDP_ENTRY_PORT] = { .name = "port", .type = YNL_PT_U16, },
189*2d7be507SJakub Kicinski 	[ETHTOOL_A_TUNNEL_UDP_ENTRY_TYPE] = { .name = "type", .type = YNL_PT_U32, },
190*2d7be507SJakub Kicinski };
191*2d7be507SJakub Kicinski 
192*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_tunnel_udp_entry_nest = {
193*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_TUNNEL_UDP_ENTRY_MAX,
194*2d7be507SJakub Kicinski 	.table = ethtool_tunnel_udp_entry_policy,
195*2d7be507SJakub Kicinski };
196*2d7be507SJakub Kicinski 
197*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_string_policy[ETHTOOL_A_STRING_MAX + 1] = {
198*2d7be507SJakub Kicinski 	[ETHTOOL_A_STRING_INDEX] = { .name = "index", .type = YNL_PT_U32, },
199*2d7be507SJakub Kicinski 	[ETHTOOL_A_STRING_VALUE] = { .name = "value", .type = YNL_PT_NUL_STR, },
200*2d7be507SJakub Kicinski };
201*2d7be507SJakub Kicinski 
202*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_string_nest = {
203*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_STRING_MAX,
204*2d7be507SJakub Kicinski 	.table = ethtool_string_policy,
205*2d7be507SJakub Kicinski };
206*2d7be507SJakub Kicinski 
207*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_cable_nest_policy[ETHTOOL_A_CABLE_NEST_MAX + 1] = {
208*2d7be507SJakub Kicinski 	[ETHTOOL_A_CABLE_NEST_RESULT] = { .name = "result", .type = YNL_PT_NEST, .nest = &ethtool_cable_result_nest, },
209*2d7be507SJakub Kicinski 	[ETHTOOL_A_CABLE_NEST_FAULT_LENGTH] = { .name = "fault-length", .type = YNL_PT_NEST, .nest = &ethtool_cable_fault_length_nest, },
210*2d7be507SJakub Kicinski };
211*2d7be507SJakub Kicinski 
212*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_cable_nest_nest = {
213*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_CABLE_NEST_MAX,
214*2d7be507SJakub Kicinski 	.table = ethtool_cable_nest_policy,
215*2d7be507SJakub Kicinski };
216*2d7be507SJakub Kicinski 
217*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_bitset_bits_policy[ETHTOOL_A_BITSET_BITS_MAX + 1] = {
218*2d7be507SJakub Kicinski 	[ETHTOOL_A_BITSET_BITS_BIT] = { .name = "bit", .type = YNL_PT_NEST, .nest = &ethtool_bitset_bit_nest, },
219*2d7be507SJakub Kicinski };
220*2d7be507SJakub Kicinski 
221*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_bitset_bits_nest = {
222*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_BITSET_BITS_MAX,
223*2d7be507SJakub Kicinski 	.table = ethtool_bitset_bits_policy,
224*2d7be507SJakub Kicinski };
225*2d7be507SJakub Kicinski 
226*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_strings_policy[ETHTOOL_A_STRINGS_MAX + 1] = {
227*2d7be507SJakub Kicinski 	[ETHTOOL_A_STRINGS_STRING] = { .name = "string", .type = YNL_PT_NEST, .nest = &ethtool_string_nest, },
228*2d7be507SJakub Kicinski };
229*2d7be507SJakub Kicinski 
230*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_strings_nest = {
231*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_STRINGS_MAX,
232*2d7be507SJakub Kicinski 	.table = ethtool_strings_policy,
233*2d7be507SJakub Kicinski };
234*2d7be507SJakub Kicinski 
235*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_bitset_policy[ETHTOOL_A_BITSET_MAX + 1] = {
236*2d7be507SJakub Kicinski 	[ETHTOOL_A_BITSET_NOMASK] = { .name = "nomask", .type = YNL_PT_FLAG, },
237*2d7be507SJakub Kicinski 	[ETHTOOL_A_BITSET_SIZE] = { .name = "size", .type = YNL_PT_U32, },
238*2d7be507SJakub Kicinski 	[ETHTOOL_A_BITSET_BITS] = { .name = "bits", .type = YNL_PT_NEST, .nest = &ethtool_bitset_bits_nest, },
239*2d7be507SJakub Kicinski };
240*2d7be507SJakub Kicinski 
241*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_bitset_nest = {
242*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_BITSET_MAX,
243*2d7be507SJakub Kicinski 	.table = ethtool_bitset_policy,
244*2d7be507SJakub Kicinski };
245*2d7be507SJakub Kicinski 
246*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_stringset_policy[ETHTOOL_A_STRINGSET_MAX + 1] = {
247*2d7be507SJakub Kicinski 	[ETHTOOL_A_STRINGSET_ID] = { .name = "id", .type = YNL_PT_U32, },
248*2d7be507SJakub Kicinski 	[ETHTOOL_A_STRINGSET_COUNT] = { .name = "count", .type = YNL_PT_U32, },
249*2d7be507SJakub Kicinski 	[ETHTOOL_A_STRINGSET_STRINGS] = { .name = "strings", .type = YNL_PT_NEST, .nest = &ethtool_strings_nest, },
250*2d7be507SJakub Kicinski };
251*2d7be507SJakub Kicinski 
252*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_stringset_nest = {
253*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_STRINGSET_MAX,
254*2d7be507SJakub Kicinski 	.table = ethtool_stringset_policy,
255*2d7be507SJakub Kicinski };
256*2d7be507SJakub Kicinski 
257*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_tunnel_udp_table_policy[ETHTOOL_A_TUNNEL_UDP_TABLE_MAX + 1] = {
258*2d7be507SJakub Kicinski 	[ETHTOOL_A_TUNNEL_UDP_TABLE_SIZE] = { .name = "size", .type = YNL_PT_U32, },
259*2d7be507SJakub Kicinski 	[ETHTOOL_A_TUNNEL_UDP_TABLE_TYPES] = { .name = "types", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
260*2d7be507SJakub Kicinski 	[ETHTOOL_A_TUNNEL_UDP_TABLE_ENTRY] = { .name = "entry", .type = YNL_PT_NEST, .nest = &ethtool_tunnel_udp_entry_nest, },
261*2d7be507SJakub Kicinski };
262*2d7be507SJakub Kicinski 
263*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_tunnel_udp_table_nest = {
264*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_TUNNEL_UDP_TABLE_MAX,
265*2d7be507SJakub Kicinski 	.table = ethtool_tunnel_udp_table_policy,
266*2d7be507SJakub Kicinski };
267*2d7be507SJakub Kicinski 
268*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_stringsets_policy[ETHTOOL_A_STRINGSETS_MAX + 1] = {
269*2d7be507SJakub Kicinski 	[ETHTOOL_A_STRINGSETS_STRINGSET] = { .name = "stringset", .type = YNL_PT_NEST, .nest = &ethtool_stringset_nest, },
270*2d7be507SJakub Kicinski };
271*2d7be507SJakub Kicinski 
272*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_stringsets_nest = {
273*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_STRINGSETS_MAX,
274*2d7be507SJakub Kicinski 	.table = ethtool_stringsets_policy,
275*2d7be507SJakub Kicinski };
276*2d7be507SJakub Kicinski 
277*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_tunnel_udp_policy[ETHTOOL_A_TUNNEL_UDP_MAX + 1] = {
278*2d7be507SJakub Kicinski 	[ETHTOOL_A_TUNNEL_UDP_TABLE] = { .name = "table", .type = YNL_PT_NEST, .nest = &ethtool_tunnel_udp_table_nest, },
279*2d7be507SJakub Kicinski };
280*2d7be507SJakub Kicinski 
281*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_tunnel_udp_nest = {
282*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_TUNNEL_UDP_MAX,
283*2d7be507SJakub Kicinski 	.table = ethtool_tunnel_udp_policy,
284*2d7be507SJakub Kicinski };
285*2d7be507SJakub Kicinski 
286*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_strset_policy[ETHTOOL_A_STRSET_MAX + 1] = {
287*2d7be507SJakub Kicinski 	[ETHTOOL_A_STRSET_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
288*2d7be507SJakub Kicinski 	[ETHTOOL_A_STRSET_STRINGSETS] = { .name = "stringsets", .type = YNL_PT_NEST, .nest = &ethtool_stringsets_nest, },
289*2d7be507SJakub Kicinski 	[ETHTOOL_A_STRSET_COUNTS_ONLY] = { .name = "counts-only", .type = YNL_PT_FLAG, },
290*2d7be507SJakub Kicinski };
291*2d7be507SJakub Kicinski 
292*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_strset_nest = {
293*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_STRSET_MAX,
294*2d7be507SJakub Kicinski 	.table = ethtool_strset_policy,
295*2d7be507SJakub Kicinski };
296*2d7be507SJakub Kicinski 
297*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_linkinfo_policy[ETHTOOL_A_LINKINFO_MAX + 1] = {
298*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKINFO_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
299*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKINFO_PORT] = { .name = "port", .type = YNL_PT_U8, },
300*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKINFO_PHYADDR] = { .name = "phyaddr", .type = YNL_PT_U8, },
301*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKINFO_TP_MDIX] = { .name = "tp-mdix", .type = YNL_PT_U8, },
302*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKINFO_TP_MDIX_CTRL] = { .name = "tp-mdix-ctrl", .type = YNL_PT_U8, },
303*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKINFO_TRANSCEIVER] = { .name = "transceiver", .type = YNL_PT_U8, },
304*2d7be507SJakub Kicinski };
305*2d7be507SJakub Kicinski 
306*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_linkinfo_nest = {
307*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_LINKINFO_MAX,
308*2d7be507SJakub Kicinski 	.table = ethtool_linkinfo_policy,
309*2d7be507SJakub Kicinski };
310*2d7be507SJakub Kicinski 
311*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_linkmodes_policy[ETHTOOL_A_LINKMODES_MAX + 1] = {
312*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKMODES_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
313*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKMODES_AUTONEG] = { .name = "autoneg", .type = YNL_PT_U8, },
314*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKMODES_OURS] = { .name = "ours", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
315*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKMODES_PEER] = { .name = "peer", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
316*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKMODES_SPEED] = { .name = "speed", .type = YNL_PT_U32, },
317*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKMODES_DUPLEX] = { .name = "duplex", .type = YNL_PT_U8, },
318*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG] = { .name = "master-slave-cfg", .type = YNL_PT_U8, },
319*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE] = { .name = "master-slave-state", .type = YNL_PT_U8, },
320*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKMODES_LANES] = { .name = "lanes", .type = YNL_PT_U32, },
321*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKMODES_RATE_MATCHING] = { .name = "rate-matching", .type = YNL_PT_U8, },
322*2d7be507SJakub Kicinski };
323*2d7be507SJakub Kicinski 
324*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_linkmodes_nest = {
325*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_LINKMODES_MAX,
326*2d7be507SJakub Kicinski 	.table = ethtool_linkmodes_policy,
327*2d7be507SJakub Kicinski };
328*2d7be507SJakub Kicinski 
329*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_linkstate_policy[ETHTOOL_A_LINKSTATE_MAX + 1] = {
330*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKSTATE_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
331*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKSTATE_LINK] = { .name = "link", .type = YNL_PT_U8, },
332*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKSTATE_SQI] = { .name = "sqi", .type = YNL_PT_U32, },
333*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKSTATE_SQI_MAX] = { .name = "sqi-max", .type = YNL_PT_U32, },
334*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKSTATE_EXT_STATE] = { .name = "ext-state", .type = YNL_PT_U8, },
335*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKSTATE_EXT_SUBSTATE] = { .name = "ext-substate", .type = YNL_PT_U8, },
336*2d7be507SJakub Kicinski 	[ETHTOOL_A_LINKSTATE_EXT_DOWN_CNT] = { .name = "ext-down-cnt", .type = YNL_PT_U32, },
337*2d7be507SJakub Kicinski };
338*2d7be507SJakub Kicinski 
339*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_linkstate_nest = {
340*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_LINKSTATE_MAX,
341*2d7be507SJakub Kicinski 	.table = ethtool_linkstate_policy,
342*2d7be507SJakub Kicinski };
343*2d7be507SJakub Kicinski 
344*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_debug_policy[ETHTOOL_A_DEBUG_MAX + 1] = {
345*2d7be507SJakub Kicinski 	[ETHTOOL_A_DEBUG_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
346*2d7be507SJakub Kicinski 	[ETHTOOL_A_DEBUG_MSGMASK] = { .name = "msgmask", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
347*2d7be507SJakub Kicinski };
348*2d7be507SJakub Kicinski 
349*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_debug_nest = {
350*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_DEBUG_MAX,
351*2d7be507SJakub Kicinski 	.table = ethtool_debug_policy,
352*2d7be507SJakub Kicinski };
353*2d7be507SJakub Kicinski 
354*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_wol_policy[ETHTOOL_A_WOL_MAX + 1] = {
355*2d7be507SJakub Kicinski 	[ETHTOOL_A_WOL_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
356*2d7be507SJakub Kicinski 	[ETHTOOL_A_WOL_MODES] = { .name = "modes", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
357*2d7be507SJakub Kicinski 	[ETHTOOL_A_WOL_SOPASS] = { .name = "sopass", .type = YNL_PT_BINARY,},
358*2d7be507SJakub Kicinski };
359*2d7be507SJakub Kicinski 
360*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_wol_nest = {
361*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_WOL_MAX,
362*2d7be507SJakub Kicinski 	.table = ethtool_wol_policy,
363*2d7be507SJakub Kicinski };
364*2d7be507SJakub Kicinski 
365*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_features_policy[ETHTOOL_A_FEATURES_MAX + 1] = {
366*2d7be507SJakub Kicinski 	[ETHTOOL_A_FEATURES_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
367*2d7be507SJakub Kicinski 	[ETHTOOL_A_FEATURES_HW] = { .name = "hw", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
368*2d7be507SJakub Kicinski 	[ETHTOOL_A_FEATURES_WANTED] = { .name = "wanted", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
369*2d7be507SJakub Kicinski 	[ETHTOOL_A_FEATURES_ACTIVE] = { .name = "active", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
370*2d7be507SJakub Kicinski 	[ETHTOOL_A_FEATURES_NOCHANGE] = { .name = "nochange", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
371*2d7be507SJakub Kicinski };
372*2d7be507SJakub Kicinski 
373*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_features_nest = {
374*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_FEATURES_MAX,
375*2d7be507SJakub Kicinski 	.table = ethtool_features_policy,
376*2d7be507SJakub Kicinski };
377*2d7be507SJakub Kicinski 
378*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_privflags_policy[ETHTOOL_A_PRIVFLAGS_MAX + 1] = {
379*2d7be507SJakub Kicinski 	[ETHTOOL_A_PRIVFLAGS_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
380*2d7be507SJakub Kicinski 	[ETHTOOL_A_PRIVFLAGS_FLAGS] = { .name = "flags", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
381*2d7be507SJakub Kicinski };
382*2d7be507SJakub Kicinski 
383*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_privflags_nest = {
384*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_PRIVFLAGS_MAX,
385*2d7be507SJakub Kicinski 	.table = ethtool_privflags_policy,
386*2d7be507SJakub Kicinski };
387*2d7be507SJakub Kicinski 
388*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_rings_policy[ETHTOOL_A_RINGS_MAX + 1] = {
389*2d7be507SJakub Kicinski 	[ETHTOOL_A_RINGS_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
390*2d7be507SJakub Kicinski 	[ETHTOOL_A_RINGS_RX_MAX] = { .name = "rx-max", .type = YNL_PT_U32, },
391*2d7be507SJakub Kicinski 	[ETHTOOL_A_RINGS_RX_MINI_MAX] = { .name = "rx-mini-max", .type = YNL_PT_U32, },
392*2d7be507SJakub Kicinski 	[ETHTOOL_A_RINGS_RX_JUMBO_MAX] = { .name = "rx-jumbo-max", .type = YNL_PT_U32, },
393*2d7be507SJakub Kicinski 	[ETHTOOL_A_RINGS_TX_MAX] = { .name = "tx-max", .type = YNL_PT_U32, },
394*2d7be507SJakub Kicinski 	[ETHTOOL_A_RINGS_RX] = { .name = "rx", .type = YNL_PT_U32, },
395*2d7be507SJakub Kicinski 	[ETHTOOL_A_RINGS_RX_MINI] = { .name = "rx-mini", .type = YNL_PT_U32, },
396*2d7be507SJakub Kicinski 	[ETHTOOL_A_RINGS_RX_JUMBO] = { .name = "rx-jumbo", .type = YNL_PT_U32, },
397*2d7be507SJakub Kicinski 	[ETHTOOL_A_RINGS_TX] = { .name = "tx", .type = YNL_PT_U32, },
398*2d7be507SJakub Kicinski 	[ETHTOOL_A_RINGS_RX_BUF_LEN] = { .name = "rx-buf-len", .type = YNL_PT_U32, },
399*2d7be507SJakub Kicinski 	[ETHTOOL_A_RINGS_TCP_DATA_SPLIT] = { .name = "tcp-data-split", .type = YNL_PT_U8, },
400*2d7be507SJakub Kicinski 	[ETHTOOL_A_RINGS_CQE_SIZE] = { .name = "cqe-size", .type = YNL_PT_U32, },
401*2d7be507SJakub Kicinski 	[ETHTOOL_A_RINGS_TX_PUSH] = { .name = "tx-push", .type = YNL_PT_U8, },
402*2d7be507SJakub Kicinski 	[ETHTOOL_A_RINGS_RX_PUSH] = { .name = "rx-push", .type = YNL_PT_U8, },
403*2d7be507SJakub Kicinski 	[ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN] = { .name = "tx-push-buf-len", .type = YNL_PT_U32, },
404*2d7be507SJakub Kicinski 	[ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX] = { .name = "tx-push-buf-len-max", .type = YNL_PT_U32, },
405*2d7be507SJakub Kicinski };
406*2d7be507SJakub Kicinski 
407*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_rings_nest = {
408*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_RINGS_MAX,
409*2d7be507SJakub Kicinski 	.table = ethtool_rings_policy,
410*2d7be507SJakub Kicinski };
411*2d7be507SJakub Kicinski 
412*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_channels_policy[ETHTOOL_A_CHANNELS_MAX + 1] = {
413*2d7be507SJakub Kicinski 	[ETHTOOL_A_CHANNELS_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
414*2d7be507SJakub Kicinski 	[ETHTOOL_A_CHANNELS_RX_MAX] = { .name = "rx-max", .type = YNL_PT_U32, },
415*2d7be507SJakub Kicinski 	[ETHTOOL_A_CHANNELS_TX_MAX] = { .name = "tx-max", .type = YNL_PT_U32, },
416*2d7be507SJakub Kicinski 	[ETHTOOL_A_CHANNELS_OTHER_MAX] = { .name = "other-max", .type = YNL_PT_U32, },
417*2d7be507SJakub Kicinski 	[ETHTOOL_A_CHANNELS_COMBINED_MAX] = { .name = "combined-max", .type = YNL_PT_U32, },
418*2d7be507SJakub Kicinski 	[ETHTOOL_A_CHANNELS_RX_COUNT] = { .name = "rx-count", .type = YNL_PT_U32, },
419*2d7be507SJakub Kicinski 	[ETHTOOL_A_CHANNELS_TX_COUNT] = { .name = "tx-count", .type = YNL_PT_U32, },
420*2d7be507SJakub Kicinski 	[ETHTOOL_A_CHANNELS_OTHER_COUNT] = { .name = "other-count", .type = YNL_PT_U32, },
421*2d7be507SJakub Kicinski 	[ETHTOOL_A_CHANNELS_COMBINED_COUNT] = { .name = "combined-count", .type = YNL_PT_U32, },
422*2d7be507SJakub Kicinski };
423*2d7be507SJakub Kicinski 
424*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_channels_nest = {
425*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_CHANNELS_MAX,
426*2d7be507SJakub Kicinski 	.table = ethtool_channels_policy,
427*2d7be507SJakub Kicinski };
428*2d7be507SJakub Kicinski 
429*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_coalesce_policy[ETHTOOL_A_COALESCE_MAX + 1] = {
430*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
431*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_RX_USECS] = { .name = "rx-usecs", .type = YNL_PT_U32, },
432*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_RX_MAX_FRAMES] = { .name = "rx-max-frames", .type = YNL_PT_U32, },
433*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_RX_USECS_IRQ] = { .name = "rx-usecs-irq", .type = YNL_PT_U32, },
434*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ] = { .name = "rx-max-frames-irq", .type = YNL_PT_U32, },
435*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_TX_USECS] = { .name = "tx-usecs", .type = YNL_PT_U32, },
436*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_TX_MAX_FRAMES] = { .name = "tx-max-frames", .type = YNL_PT_U32, },
437*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_TX_USECS_IRQ] = { .name = "tx-usecs-irq", .type = YNL_PT_U32, },
438*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ] = { .name = "tx-max-frames-irq", .type = YNL_PT_U32, },
439*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_STATS_BLOCK_USECS] = { .name = "stats-block-usecs", .type = YNL_PT_U32, },
440*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX] = { .name = "use-adaptive-rx", .type = YNL_PT_U8, },
441*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_USE_ADAPTIVE_TX] = { .name = "use-adaptive-tx", .type = YNL_PT_U8, },
442*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_PKT_RATE_LOW] = { .name = "pkt-rate-low", .type = YNL_PT_U32, },
443*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_RX_USECS_LOW] = { .name = "rx-usecs-low", .type = YNL_PT_U32, },
444*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW] = { .name = "rx-max-frames-low", .type = YNL_PT_U32, },
445*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_TX_USECS_LOW] = { .name = "tx-usecs-low", .type = YNL_PT_U32, },
446*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW] = { .name = "tx-max-frames-low", .type = YNL_PT_U32, },
447*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_PKT_RATE_HIGH] = { .name = "pkt-rate-high", .type = YNL_PT_U32, },
448*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_RX_USECS_HIGH] = { .name = "rx-usecs-high", .type = YNL_PT_U32, },
449*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH] = { .name = "rx-max-frames-high", .type = YNL_PT_U32, },
450*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_TX_USECS_HIGH] = { .name = "tx-usecs-high", .type = YNL_PT_U32, },
451*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH] = { .name = "tx-max-frames-high", .type = YNL_PT_U32, },
452*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL] = { .name = "rate-sample-interval", .type = YNL_PT_U32, },
453*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_USE_CQE_MODE_TX] = { .name = "use-cqe-mode-tx", .type = YNL_PT_U8, },
454*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_USE_CQE_MODE_RX] = { .name = "use-cqe-mode-rx", .type = YNL_PT_U8, },
455*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES] = { .name = "tx-aggr-max-bytes", .type = YNL_PT_U32, },
456*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES] = { .name = "tx-aggr-max-frames", .type = YNL_PT_U32, },
457*2d7be507SJakub Kicinski 	[ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS] = { .name = "tx-aggr-time-usecs", .type = YNL_PT_U32, },
458*2d7be507SJakub Kicinski };
459*2d7be507SJakub Kicinski 
460*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_coalesce_nest = {
461*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_COALESCE_MAX,
462*2d7be507SJakub Kicinski 	.table = ethtool_coalesce_policy,
463*2d7be507SJakub Kicinski };
464*2d7be507SJakub Kicinski 
465*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_pause_policy[ETHTOOL_A_PAUSE_MAX + 1] = {
466*2d7be507SJakub Kicinski 	[ETHTOOL_A_PAUSE_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
467*2d7be507SJakub Kicinski 	[ETHTOOL_A_PAUSE_AUTONEG] = { .name = "autoneg", .type = YNL_PT_U8, },
468*2d7be507SJakub Kicinski 	[ETHTOOL_A_PAUSE_RX] = { .name = "rx", .type = YNL_PT_U8, },
469*2d7be507SJakub Kicinski 	[ETHTOOL_A_PAUSE_TX] = { .name = "tx", .type = YNL_PT_U8, },
470*2d7be507SJakub Kicinski 	[ETHTOOL_A_PAUSE_STATS] = { .name = "stats", .type = YNL_PT_NEST, .nest = &ethtool_pause_stat_nest, },
471*2d7be507SJakub Kicinski 	[ETHTOOL_A_PAUSE_STATS_SRC] = { .name = "stats-src", .type = YNL_PT_U32, },
472*2d7be507SJakub Kicinski };
473*2d7be507SJakub Kicinski 
474*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_pause_nest = {
475*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_PAUSE_MAX,
476*2d7be507SJakub Kicinski 	.table = ethtool_pause_policy,
477*2d7be507SJakub Kicinski };
478*2d7be507SJakub Kicinski 
479*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_eee_policy[ETHTOOL_A_EEE_MAX + 1] = {
480*2d7be507SJakub Kicinski 	[ETHTOOL_A_EEE_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
481*2d7be507SJakub Kicinski 	[ETHTOOL_A_EEE_MODES_OURS] = { .name = "modes-ours", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
482*2d7be507SJakub Kicinski 	[ETHTOOL_A_EEE_MODES_PEER] = { .name = "modes-peer", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
483*2d7be507SJakub Kicinski 	[ETHTOOL_A_EEE_ACTIVE] = { .name = "active", .type = YNL_PT_U8, },
484*2d7be507SJakub Kicinski 	[ETHTOOL_A_EEE_ENABLED] = { .name = "enabled", .type = YNL_PT_U8, },
485*2d7be507SJakub Kicinski 	[ETHTOOL_A_EEE_TX_LPI_ENABLED] = { .name = "tx-lpi-enabled", .type = YNL_PT_U8, },
486*2d7be507SJakub Kicinski 	[ETHTOOL_A_EEE_TX_LPI_TIMER] = { .name = "tx-lpi-timer", .type = YNL_PT_U32, },
487*2d7be507SJakub Kicinski };
488*2d7be507SJakub Kicinski 
489*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_eee_nest = {
490*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_EEE_MAX,
491*2d7be507SJakub Kicinski 	.table = ethtool_eee_policy,
492*2d7be507SJakub Kicinski };
493*2d7be507SJakub Kicinski 
494*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_tsinfo_policy[ETHTOOL_A_TSINFO_MAX + 1] = {
495*2d7be507SJakub Kicinski 	[ETHTOOL_A_TSINFO_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
496*2d7be507SJakub Kicinski 	[ETHTOOL_A_TSINFO_TIMESTAMPING] = { .name = "timestamping", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
497*2d7be507SJakub Kicinski 	[ETHTOOL_A_TSINFO_TX_TYPES] = { .name = "tx-types", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
498*2d7be507SJakub Kicinski 	[ETHTOOL_A_TSINFO_RX_FILTERS] = { .name = "rx-filters", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
499*2d7be507SJakub Kicinski 	[ETHTOOL_A_TSINFO_PHC_INDEX] = { .name = "phc-index", .type = YNL_PT_U32, },
500*2d7be507SJakub Kicinski };
501*2d7be507SJakub Kicinski 
502*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_tsinfo_nest = {
503*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_TSINFO_MAX,
504*2d7be507SJakub Kicinski 	.table = ethtool_tsinfo_policy,
505*2d7be507SJakub Kicinski };
506*2d7be507SJakub Kicinski 
507*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_cable_test_policy[ETHTOOL_A_CABLE_TEST_MAX + 1] = {
508*2d7be507SJakub Kicinski 	[ETHTOOL_A_CABLE_TEST_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
509*2d7be507SJakub Kicinski };
510*2d7be507SJakub Kicinski 
511*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_cable_test_nest = {
512*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_CABLE_TEST_MAX,
513*2d7be507SJakub Kicinski 	.table = ethtool_cable_test_policy,
514*2d7be507SJakub Kicinski };
515*2d7be507SJakub Kicinski 
516*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_cable_test_ntf_policy[ETHTOOL_A_CABLE_TEST_NTF_MAX + 1] = {
517*2d7be507SJakub Kicinski 	[ETHTOOL_A_CABLE_TEST_NTF_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
518*2d7be507SJakub Kicinski 	[ETHTOOL_A_CABLE_TEST_NTF_STATUS] = { .name = "status", .type = YNL_PT_U8, },
519*2d7be507SJakub Kicinski 	[ETHTOOL_A_CABLE_TEST_NTF_NEST] = { .name = "nest", .type = YNL_PT_NEST, .nest = &ethtool_cable_nest_nest, },
520*2d7be507SJakub Kicinski };
521*2d7be507SJakub Kicinski 
522*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_cable_test_ntf_nest = {
523*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_CABLE_TEST_NTF_MAX,
524*2d7be507SJakub Kicinski 	.table = ethtool_cable_test_ntf_policy,
525*2d7be507SJakub Kicinski };
526*2d7be507SJakub Kicinski 
527*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_cable_test_tdr_policy[ETHTOOL_A_CABLE_TEST_TDR_MAX + 1] = {
528*2d7be507SJakub Kicinski 	[ETHTOOL_A_CABLE_TEST_TDR_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
529*2d7be507SJakub Kicinski 	[ETHTOOL_A_CABLE_TEST_TDR_CFG] = { .name = "cfg", .type = YNL_PT_NEST, .nest = &ethtool_cable_test_tdr_cfg_nest, },
530*2d7be507SJakub Kicinski };
531*2d7be507SJakub Kicinski 
532*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_cable_test_tdr_nest = {
533*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_CABLE_TEST_TDR_MAX,
534*2d7be507SJakub Kicinski 	.table = ethtool_cable_test_tdr_policy,
535*2d7be507SJakub Kicinski };
536*2d7be507SJakub Kicinski 
537*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_cable_test_tdr_ntf_policy[ETHTOOL_A_CABLE_TEST_TDR_NTF_MAX + 1] = {
538*2d7be507SJakub Kicinski 	[ETHTOOL_A_CABLE_TEST_TDR_NTF_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
539*2d7be507SJakub Kicinski 	[ETHTOOL_A_CABLE_TEST_TDR_NTF_STATUS] = { .name = "status", .type = YNL_PT_U8, },
540*2d7be507SJakub Kicinski 	[ETHTOOL_A_CABLE_TEST_TDR_NTF_NEST] = { .name = "nest", .type = YNL_PT_NEST, .nest = &ethtool_cable_nest_nest, },
541*2d7be507SJakub Kicinski };
542*2d7be507SJakub Kicinski 
543*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_cable_test_tdr_ntf_nest = {
544*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_CABLE_TEST_TDR_NTF_MAX,
545*2d7be507SJakub Kicinski 	.table = ethtool_cable_test_tdr_ntf_policy,
546*2d7be507SJakub Kicinski };
547*2d7be507SJakub Kicinski 
548*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_tunnel_info_policy[ETHTOOL_A_TUNNEL_INFO_MAX + 1] = {
549*2d7be507SJakub Kicinski 	[ETHTOOL_A_TUNNEL_INFO_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
550*2d7be507SJakub Kicinski 	[ETHTOOL_A_TUNNEL_INFO_UDP_PORTS] = { .name = "udp-ports", .type = YNL_PT_NEST, .nest = &ethtool_tunnel_udp_nest, },
551*2d7be507SJakub Kicinski };
552*2d7be507SJakub Kicinski 
553*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_tunnel_info_nest = {
554*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_TUNNEL_INFO_MAX,
555*2d7be507SJakub Kicinski 	.table = ethtool_tunnel_info_policy,
556*2d7be507SJakub Kicinski };
557*2d7be507SJakub Kicinski 
558*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_fec_policy[ETHTOOL_A_FEC_MAX + 1] = {
559*2d7be507SJakub Kicinski 	[ETHTOOL_A_FEC_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
560*2d7be507SJakub Kicinski 	[ETHTOOL_A_FEC_MODES] = { .name = "modes", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
561*2d7be507SJakub Kicinski 	[ETHTOOL_A_FEC_AUTO] = { .name = "auto", .type = YNL_PT_U8, },
562*2d7be507SJakub Kicinski 	[ETHTOOL_A_FEC_ACTIVE] = { .name = "active", .type = YNL_PT_U32, },
563*2d7be507SJakub Kicinski 	[ETHTOOL_A_FEC_STATS] = { .name = "stats", .type = YNL_PT_NEST, .nest = &ethtool_fec_stat_nest, },
564*2d7be507SJakub Kicinski };
565*2d7be507SJakub Kicinski 
566*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_fec_nest = {
567*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_FEC_MAX,
568*2d7be507SJakub Kicinski 	.table = ethtool_fec_policy,
569*2d7be507SJakub Kicinski };
570*2d7be507SJakub Kicinski 
571*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_module_eeprom_policy[ETHTOOL_A_MODULE_EEPROM_MAX + 1] = {
572*2d7be507SJakub Kicinski 	[ETHTOOL_A_MODULE_EEPROM_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
573*2d7be507SJakub Kicinski 	[ETHTOOL_A_MODULE_EEPROM_OFFSET] = { .name = "offset", .type = YNL_PT_U32, },
574*2d7be507SJakub Kicinski 	[ETHTOOL_A_MODULE_EEPROM_LENGTH] = { .name = "length", .type = YNL_PT_U32, },
575*2d7be507SJakub Kicinski 	[ETHTOOL_A_MODULE_EEPROM_PAGE] = { .name = "page", .type = YNL_PT_U8, },
576*2d7be507SJakub Kicinski 	[ETHTOOL_A_MODULE_EEPROM_BANK] = { .name = "bank", .type = YNL_PT_U8, },
577*2d7be507SJakub Kicinski 	[ETHTOOL_A_MODULE_EEPROM_I2C_ADDRESS] = { .name = "i2c-address", .type = YNL_PT_U8, },
578*2d7be507SJakub Kicinski 	[ETHTOOL_A_MODULE_EEPROM_DATA] = { .name = "data", .type = YNL_PT_BINARY,},
579*2d7be507SJakub Kicinski };
580*2d7be507SJakub Kicinski 
581*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_module_eeprom_nest = {
582*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_MODULE_EEPROM_MAX,
583*2d7be507SJakub Kicinski 	.table = ethtool_module_eeprom_policy,
584*2d7be507SJakub Kicinski };
585*2d7be507SJakub Kicinski 
586*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_phc_vclocks_policy[ETHTOOL_A_PHC_VCLOCKS_MAX + 1] = {
587*2d7be507SJakub Kicinski 	[ETHTOOL_A_PHC_VCLOCKS_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
588*2d7be507SJakub Kicinski 	[ETHTOOL_A_PHC_VCLOCKS_NUM] = { .name = "num", .type = YNL_PT_U32, },
589*2d7be507SJakub Kicinski 	[ETHTOOL_A_PHC_VCLOCKS_INDEX] = { .name = "index", .type = YNL_PT_BINARY,},
590*2d7be507SJakub Kicinski };
591*2d7be507SJakub Kicinski 
592*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_phc_vclocks_nest = {
593*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_PHC_VCLOCKS_MAX,
594*2d7be507SJakub Kicinski 	.table = ethtool_phc_vclocks_policy,
595*2d7be507SJakub Kicinski };
596*2d7be507SJakub Kicinski 
597*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_module_policy[ETHTOOL_A_MODULE_MAX + 1] = {
598*2d7be507SJakub Kicinski 	[ETHTOOL_A_MODULE_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
599*2d7be507SJakub Kicinski 	[ETHTOOL_A_MODULE_POWER_MODE_POLICY] = { .name = "power-mode-policy", .type = YNL_PT_U8, },
600*2d7be507SJakub Kicinski 	[ETHTOOL_A_MODULE_POWER_MODE] = { .name = "power-mode", .type = YNL_PT_U8, },
601*2d7be507SJakub Kicinski };
602*2d7be507SJakub Kicinski 
603*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_module_nest = {
604*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_MODULE_MAX,
605*2d7be507SJakub Kicinski 	.table = ethtool_module_policy,
606*2d7be507SJakub Kicinski };
607*2d7be507SJakub Kicinski 
608*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_pse_policy[ETHTOOL_A_PSE_MAX + 1] = {
609*2d7be507SJakub Kicinski 	[ETHTOOL_A_PSE_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
610*2d7be507SJakub Kicinski 	[ETHTOOL_A_PODL_PSE_ADMIN_STATE] = { .name = "admin-state", .type = YNL_PT_U32, },
611*2d7be507SJakub Kicinski 	[ETHTOOL_A_PODL_PSE_ADMIN_CONTROL] = { .name = "admin-control", .type = YNL_PT_U32, },
612*2d7be507SJakub Kicinski 	[ETHTOOL_A_PODL_PSE_PW_D_STATUS] = { .name = "pw-d-status", .type = YNL_PT_U32, },
613*2d7be507SJakub Kicinski };
614*2d7be507SJakub Kicinski 
615*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_pse_nest = {
616*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_PSE_MAX,
617*2d7be507SJakub Kicinski 	.table = ethtool_pse_policy,
618*2d7be507SJakub Kicinski };
619*2d7be507SJakub Kicinski 
620*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_rss_policy[ETHTOOL_A_RSS_MAX + 1] = {
621*2d7be507SJakub Kicinski 	[ETHTOOL_A_RSS_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
622*2d7be507SJakub Kicinski 	[ETHTOOL_A_RSS_CONTEXT] = { .name = "context", .type = YNL_PT_U32, },
623*2d7be507SJakub Kicinski 	[ETHTOOL_A_RSS_HFUNC] = { .name = "hfunc", .type = YNL_PT_U32, },
624*2d7be507SJakub Kicinski 	[ETHTOOL_A_RSS_INDIR] = { .name = "indir", .type = YNL_PT_BINARY,},
625*2d7be507SJakub Kicinski 	[ETHTOOL_A_RSS_HKEY] = { .name = "hkey", .type = YNL_PT_BINARY,},
626*2d7be507SJakub Kicinski };
627*2d7be507SJakub Kicinski 
628*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_rss_nest = {
629*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_RSS_MAX,
630*2d7be507SJakub Kicinski 	.table = ethtool_rss_policy,
631*2d7be507SJakub Kicinski };
632*2d7be507SJakub Kicinski 
633*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_plca_policy[ETHTOOL_A_PLCA_MAX + 1] = {
634*2d7be507SJakub Kicinski 	[ETHTOOL_A_PLCA_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
635*2d7be507SJakub Kicinski 	[ETHTOOL_A_PLCA_VERSION] = { .name = "version", .type = YNL_PT_U16, },
636*2d7be507SJakub Kicinski 	[ETHTOOL_A_PLCA_ENABLED] = { .name = "enabled", .type = YNL_PT_U8, },
637*2d7be507SJakub Kicinski 	[ETHTOOL_A_PLCA_STATUS] = { .name = "status", .type = YNL_PT_U8, },
638*2d7be507SJakub Kicinski 	[ETHTOOL_A_PLCA_NODE_CNT] = { .name = "node-cnt", .type = YNL_PT_U32, },
639*2d7be507SJakub Kicinski 	[ETHTOOL_A_PLCA_NODE_ID] = { .name = "node-id", .type = YNL_PT_U32, },
640*2d7be507SJakub Kicinski 	[ETHTOOL_A_PLCA_TO_TMR] = { .name = "to-tmr", .type = YNL_PT_U32, },
641*2d7be507SJakub Kicinski 	[ETHTOOL_A_PLCA_BURST_CNT] = { .name = "burst-cnt", .type = YNL_PT_U32, },
642*2d7be507SJakub Kicinski 	[ETHTOOL_A_PLCA_BURST_TMR] = { .name = "burst-tmr", .type = YNL_PT_U32, },
643*2d7be507SJakub Kicinski };
644*2d7be507SJakub Kicinski 
645*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_plca_nest = {
646*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_PLCA_MAX,
647*2d7be507SJakub Kicinski 	.table = ethtool_plca_policy,
648*2d7be507SJakub Kicinski };
649*2d7be507SJakub Kicinski 
650*2d7be507SJakub Kicinski struct ynl_policy_attr ethtool_mm_policy[ETHTOOL_A_MM_MAX + 1] = {
651*2d7be507SJakub Kicinski 	[ETHTOOL_A_MM_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
652*2d7be507SJakub Kicinski 	[ETHTOOL_A_MM_PMAC_ENABLED] = { .name = "pmac-enabled", .type = YNL_PT_U8, },
653*2d7be507SJakub Kicinski 	[ETHTOOL_A_MM_TX_ENABLED] = { .name = "tx-enabled", .type = YNL_PT_U8, },
654*2d7be507SJakub Kicinski 	[ETHTOOL_A_MM_TX_ACTIVE] = { .name = "tx-active", .type = YNL_PT_U8, },
655*2d7be507SJakub Kicinski 	[ETHTOOL_A_MM_TX_MIN_FRAG_SIZE] = { .name = "tx-min-frag-size", .type = YNL_PT_U32, },
656*2d7be507SJakub Kicinski 	[ETHTOOL_A_MM_RX_MIN_FRAG_SIZE] = { .name = "rx-min-frag-size", .type = YNL_PT_U32, },
657*2d7be507SJakub Kicinski 	[ETHTOOL_A_MM_VERIFY_ENABLED] = { .name = "verify-enabled", .type = YNL_PT_U8, },
658*2d7be507SJakub Kicinski 	[ETHTOOL_A_MM_VERIFY_STATUS] = { .name = "verify-status", .type = YNL_PT_U8, },
659*2d7be507SJakub Kicinski 	[ETHTOOL_A_MM_VERIFY_TIME] = { .name = "verify-time", .type = YNL_PT_U32, },
660*2d7be507SJakub Kicinski 	[ETHTOOL_A_MM_MAX_VERIFY_TIME] = { .name = "max-verify-time", .type = YNL_PT_U32, },
661*2d7be507SJakub Kicinski 	[ETHTOOL_A_MM_STATS] = { .name = "stats", .type = YNL_PT_NEST, .nest = &ethtool_mm_stat_nest, },
662*2d7be507SJakub Kicinski };
663*2d7be507SJakub Kicinski 
664*2d7be507SJakub Kicinski struct ynl_policy_nest ethtool_mm_nest = {
665*2d7be507SJakub Kicinski 	.max_attr = ETHTOOL_A_MM_MAX,
666*2d7be507SJakub Kicinski 	.table = ethtool_mm_policy,
667*2d7be507SJakub Kicinski };
668*2d7be507SJakub Kicinski 
669*2d7be507SJakub Kicinski /* Common nested types */
ethtool_header_free(struct ethtool_header * obj)670*2d7be507SJakub Kicinski void ethtool_header_free(struct ethtool_header *obj)
671*2d7be507SJakub Kicinski {
672*2d7be507SJakub Kicinski 	free(obj->dev_name);
673*2d7be507SJakub Kicinski }
674*2d7be507SJakub Kicinski 
ethtool_header_put(struct nlmsghdr * nlh,unsigned int attr_type,struct ethtool_header * obj)675*2d7be507SJakub Kicinski int ethtool_header_put(struct nlmsghdr *nlh, unsigned int attr_type,
676*2d7be507SJakub Kicinski 		       struct ethtool_header *obj)
677*2d7be507SJakub Kicinski {
678*2d7be507SJakub Kicinski 	struct nlattr *nest;
679*2d7be507SJakub Kicinski 
680*2d7be507SJakub Kicinski 	nest = mnl_attr_nest_start(nlh, attr_type);
681*2d7be507SJakub Kicinski 	if (obj->_present.dev_index)
682*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_HEADER_DEV_INDEX, obj->dev_index);
683*2d7be507SJakub Kicinski 	if (obj->_present.dev_name_len)
684*2d7be507SJakub Kicinski 		mnl_attr_put_strz(nlh, ETHTOOL_A_HEADER_DEV_NAME, obj->dev_name);
685*2d7be507SJakub Kicinski 	if (obj->_present.flags)
686*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_HEADER_FLAGS, obj->flags);
687*2d7be507SJakub Kicinski 	mnl_attr_nest_end(nlh, nest);
688*2d7be507SJakub Kicinski 
689*2d7be507SJakub Kicinski 	return 0;
690*2d7be507SJakub Kicinski }
691*2d7be507SJakub Kicinski 
ethtool_header_parse(struct ynl_parse_arg * yarg,const struct nlattr * nested)692*2d7be507SJakub Kicinski int ethtool_header_parse(struct ynl_parse_arg *yarg,
693*2d7be507SJakub Kicinski 			 const struct nlattr *nested)
694*2d7be507SJakub Kicinski {
695*2d7be507SJakub Kicinski 	struct ethtool_header *dst = yarg->data;
696*2d7be507SJakub Kicinski 	const struct nlattr *attr;
697*2d7be507SJakub Kicinski 
698*2d7be507SJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
699*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
700*2d7be507SJakub Kicinski 
701*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_HEADER_DEV_INDEX) {
702*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
703*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
704*2d7be507SJakub Kicinski 			dst->_present.dev_index = 1;
705*2d7be507SJakub Kicinski 			dst->dev_index = mnl_attr_get_u32(attr);
706*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_HEADER_DEV_NAME) {
707*2d7be507SJakub Kicinski 			unsigned int len;
708*2d7be507SJakub Kicinski 
709*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
710*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
711*2d7be507SJakub Kicinski 
712*2d7be507SJakub Kicinski 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
713*2d7be507SJakub Kicinski 			dst->_present.dev_name_len = len;
714*2d7be507SJakub Kicinski 			dst->dev_name = malloc(len + 1);
715*2d7be507SJakub Kicinski 			memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
716*2d7be507SJakub Kicinski 			dst->dev_name[len] = 0;
717*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_HEADER_FLAGS) {
718*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
719*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
720*2d7be507SJakub Kicinski 			dst->_present.flags = 1;
721*2d7be507SJakub Kicinski 			dst->flags = mnl_attr_get_u32(attr);
722*2d7be507SJakub Kicinski 		}
723*2d7be507SJakub Kicinski 	}
724*2d7be507SJakub Kicinski 
725*2d7be507SJakub Kicinski 	return 0;
726*2d7be507SJakub Kicinski }
727*2d7be507SJakub Kicinski 
ethtool_pause_stat_free(struct ethtool_pause_stat * obj)728*2d7be507SJakub Kicinski void ethtool_pause_stat_free(struct ethtool_pause_stat *obj)
729*2d7be507SJakub Kicinski {
730*2d7be507SJakub Kicinski }
731*2d7be507SJakub Kicinski 
ethtool_pause_stat_put(struct nlmsghdr * nlh,unsigned int attr_type,struct ethtool_pause_stat * obj)732*2d7be507SJakub Kicinski int ethtool_pause_stat_put(struct nlmsghdr *nlh, unsigned int attr_type,
733*2d7be507SJakub Kicinski 			   struct ethtool_pause_stat *obj)
734*2d7be507SJakub Kicinski {
735*2d7be507SJakub Kicinski 	struct nlattr *nest;
736*2d7be507SJakub Kicinski 
737*2d7be507SJakub Kicinski 	nest = mnl_attr_nest_start(nlh, attr_type);
738*2d7be507SJakub Kicinski 	if (obj->_present.tx_frames)
739*2d7be507SJakub Kicinski 		mnl_attr_put_u64(nlh, ETHTOOL_A_PAUSE_STAT_TX_FRAMES, obj->tx_frames);
740*2d7be507SJakub Kicinski 	if (obj->_present.rx_frames)
741*2d7be507SJakub Kicinski 		mnl_attr_put_u64(nlh, ETHTOOL_A_PAUSE_STAT_RX_FRAMES, obj->rx_frames);
742*2d7be507SJakub Kicinski 	mnl_attr_nest_end(nlh, nest);
743*2d7be507SJakub Kicinski 
744*2d7be507SJakub Kicinski 	return 0;
745*2d7be507SJakub Kicinski }
746*2d7be507SJakub Kicinski 
ethtool_pause_stat_parse(struct ynl_parse_arg * yarg,const struct nlattr * nested)747*2d7be507SJakub Kicinski int ethtool_pause_stat_parse(struct ynl_parse_arg *yarg,
748*2d7be507SJakub Kicinski 			     const struct nlattr *nested)
749*2d7be507SJakub Kicinski {
750*2d7be507SJakub Kicinski 	struct ethtool_pause_stat *dst = yarg->data;
751*2d7be507SJakub Kicinski 	const struct nlattr *attr;
752*2d7be507SJakub Kicinski 
753*2d7be507SJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
754*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
755*2d7be507SJakub Kicinski 
756*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_PAUSE_STAT_TX_FRAMES) {
757*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
758*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
759*2d7be507SJakub Kicinski 			dst->_present.tx_frames = 1;
760*2d7be507SJakub Kicinski 			dst->tx_frames = mnl_attr_get_u64(attr);
761*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PAUSE_STAT_RX_FRAMES) {
762*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
763*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
764*2d7be507SJakub Kicinski 			dst->_present.rx_frames = 1;
765*2d7be507SJakub Kicinski 			dst->rx_frames = mnl_attr_get_u64(attr);
766*2d7be507SJakub Kicinski 		}
767*2d7be507SJakub Kicinski 	}
768*2d7be507SJakub Kicinski 
769*2d7be507SJakub Kicinski 	return 0;
770*2d7be507SJakub Kicinski }
771*2d7be507SJakub Kicinski 
ethtool_cable_test_tdr_cfg_free(struct ethtool_cable_test_tdr_cfg * obj)772*2d7be507SJakub Kicinski void ethtool_cable_test_tdr_cfg_free(struct ethtool_cable_test_tdr_cfg *obj)
773*2d7be507SJakub Kicinski {
774*2d7be507SJakub Kicinski }
775*2d7be507SJakub Kicinski 
ethtool_fec_stat_free(struct ethtool_fec_stat * obj)776*2d7be507SJakub Kicinski void ethtool_fec_stat_free(struct ethtool_fec_stat *obj)
777*2d7be507SJakub Kicinski {
778*2d7be507SJakub Kicinski 	free(obj->corrected);
779*2d7be507SJakub Kicinski 	free(obj->uncorr);
780*2d7be507SJakub Kicinski 	free(obj->corr_bits);
781*2d7be507SJakub Kicinski }
782*2d7be507SJakub Kicinski 
ethtool_fec_stat_put(struct nlmsghdr * nlh,unsigned int attr_type,struct ethtool_fec_stat * obj)783*2d7be507SJakub Kicinski int ethtool_fec_stat_put(struct nlmsghdr *nlh, unsigned int attr_type,
784*2d7be507SJakub Kicinski 			 struct ethtool_fec_stat *obj)
785*2d7be507SJakub Kicinski {
786*2d7be507SJakub Kicinski 	struct nlattr *nest;
787*2d7be507SJakub Kicinski 
788*2d7be507SJakub Kicinski 	nest = mnl_attr_nest_start(nlh, attr_type);
789*2d7be507SJakub Kicinski 	if (obj->_present.corrected_len)
790*2d7be507SJakub Kicinski 		mnl_attr_put(nlh, ETHTOOL_A_FEC_STAT_CORRECTED, obj->_present.corrected_len, obj->corrected);
791*2d7be507SJakub Kicinski 	if (obj->_present.uncorr_len)
792*2d7be507SJakub Kicinski 		mnl_attr_put(nlh, ETHTOOL_A_FEC_STAT_UNCORR, obj->_present.uncorr_len, obj->uncorr);
793*2d7be507SJakub Kicinski 	if (obj->_present.corr_bits_len)
794*2d7be507SJakub Kicinski 		mnl_attr_put(nlh, ETHTOOL_A_FEC_STAT_CORR_BITS, obj->_present.corr_bits_len, obj->corr_bits);
795*2d7be507SJakub Kicinski 	mnl_attr_nest_end(nlh, nest);
796*2d7be507SJakub Kicinski 
797*2d7be507SJakub Kicinski 	return 0;
798*2d7be507SJakub Kicinski }
799*2d7be507SJakub Kicinski 
ethtool_fec_stat_parse(struct ynl_parse_arg * yarg,const struct nlattr * nested)800*2d7be507SJakub Kicinski int ethtool_fec_stat_parse(struct ynl_parse_arg *yarg,
801*2d7be507SJakub Kicinski 			   const struct nlattr *nested)
802*2d7be507SJakub Kicinski {
803*2d7be507SJakub Kicinski 	struct ethtool_fec_stat *dst = yarg->data;
804*2d7be507SJakub Kicinski 	const struct nlattr *attr;
805*2d7be507SJakub Kicinski 
806*2d7be507SJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
807*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
808*2d7be507SJakub Kicinski 
809*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_FEC_STAT_CORRECTED) {
810*2d7be507SJakub Kicinski 			unsigned int len;
811*2d7be507SJakub Kicinski 
812*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
813*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
814*2d7be507SJakub Kicinski 
815*2d7be507SJakub Kicinski 			len = mnl_attr_get_payload_len(attr);
816*2d7be507SJakub Kicinski 			dst->_present.corrected_len = len;
817*2d7be507SJakub Kicinski 			dst->corrected = malloc(len);
818*2d7be507SJakub Kicinski 			memcpy(dst->corrected, mnl_attr_get_payload(attr), len);
819*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_FEC_STAT_UNCORR) {
820*2d7be507SJakub Kicinski 			unsigned int len;
821*2d7be507SJakub Kicinski 
822*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
823*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
824*2d7be507SJakub Kicinski 
825*2d7be507SJakub Kicinski 			len = mnl_attr_get_payload_len(attr);
826*2d7be507SJakub Kicinski 			dst->_present.uncorr_len = len;
827*2d7be507SJakub Kicinski 			dst->uncorr = malloc(len);
828*2d7be507SJakub Kicinski 			memcpy(dst->uncorr, mnl_attr_get_payload(attr), len);
829*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_FEC_STAT_CORR_BITS) {
830*2d7be507SJakub Kicinski 			unsigned int len;
831*2d7be507SJakub Kicinski 
832*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
833*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
834*2d7be507SJakub Kicinski 
835*2d7be507SJakub Kicinski 			len = mnl_attr_get_payload_len(attr);
836*2d7be507SJakub Kicinski 			dst->_present.corr_bits_len = len;
837*2d7be507SJakub Kicinski 			dst->corr_bits = malloc(len);
838*2d7be507SJakub Kicinski 			memcpy(dst->corr_bits, mnl_attr_get_payload(attr), len);
839*2d7be507SJakub Kicinski 		}
840*2d7be507SJakub Kicinski 	}
841*2d7be507SJakub Kicinski 
842*2d7be507SJakub Kicinski 	return 0;
843*2d7be507SJakub Kicinski }
844*2d7be507SJakub Kicinski 
ethtool_mm_stat_free(struct ethtool_mm_stat * obj)845*2d7be507SJakub Kicinski void ethtool_mm_stat_free(struct ethtool_mm_stat *obj)
846*2d7be507SJakub Kicinski {
847*2d7be507SJakub Kicinski }
848*2d7be507SJakub Kicinski 
ethtool_mm_stat_parse(struct ynl_parse_arg * yarg,const struct nlattr * nested)849*2d7be507SJakub Kicinski int ethtool_mm_stat_parse(struct ynl_parse_arg *yarg,
850*2d7be507SJakub Kicinski 			  const struct nlattr *nested)
851*2d7be507SJakub Kicinski {
852*2d7be507SJakub Kicinski 	struct ethtool_mm_stat *dst = yarg->data;
853*2d7be507SJakub Kicinski 	const struct nlattr *attr;
854*2d7be507SJakub Kicinski 
855*2d7be507SJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
856*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
857*2d7be507SJakub Kicinski 
858*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_MM_STAT_REASSEMBLY_ERRORS) {
859*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
860*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
861*2d7be507SJakub Kicinski 			dst->_present.reassembly_errors = 1;
862*2d7be507SJakub Kicinski 			dst->reassembly_errors = mnl_attr_get_u64(attr);
863*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MM_STAT_SMD_ERRORS) {
864*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
865*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
866*2d7be507SJakub Kicinski 			dst->_present.smd_errors = 1;
867*2d7be507SJakub Kicinski 			dst->smd_errors = mnl_attr_get_u64(attr);
868*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MM_STAT_REASSEMBLY_OK) {
869*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
870*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
871*2d7be507SJakub Kicinski 			dst->_present.reassembly_ok = 1;
872*2d7be507SJakub Kicinski 			dst->reassembly_ok = mnl_attr_get_u64(attr);
873*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MM_STAT_RX_FRAG_COUNT) {
874*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
875*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
876*2d7be507SJakub Kicinski 			dst->_present.rx_frag_count = 1;
877*2d7be507SJakub Kicinski 			dst->rx_frag_count = mnl_attr_get_u64(attr);
878*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MM_STAT_TX_FRAG_COUNT) {
879*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
880*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
881*2d7be507SJakub Kicinski 			dst->_present.tx_frag_count = 1;
882*2d7be507SJakub Kicinski 			dst->tx_frag_count = mnl_attr_get_u64(attr);
883*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MM_STAT_HOLD_COUNT) {
884*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
885*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
886*2d7be507SJakub Kicinski 			dst->_present.hold_count = 1;
887*2d7be507SJakub Kicinski 			dst->hold_count = mnl_attr_get_u64(attr);
888*2d7be507SJakub Kicinski 		}
889*2d7be507SJakub Kicinski 	}
890*2d7be507SJakub Kicinski 
891*2d7be507SJakub Kicinski 	return 0;
892*2d7be507SJakub Kicinski }
893*2d7be507SJakub Kicinski 
ethtool_cable_result_free(struct ethtool_cable_result * obj)894*2d7be507SJakub Kicinski void ethtool_cable_result_free(struct ethtool_cable_result *obj)
895*2d7be507SJakub Kicinski {
896*2d7be507SJakub Kicinski }
897*2d7be507SJakub Kicinski 
ethtool_cable_result_parse(struct ynl_parse_arg * yarg,const struct nlattr * nested)898*2d7be507SJakub Kicinski int ethtool_cable_result_parse(struct ynl_parse_arg *yarg,
899*2d7be507SJakub Kicinski 			       const struct nlattr *nested)
900*2d7be507SJakub Kicinski {
901*2d7be507SJakub Kicinski 	struct ethtool_cable_result *dst = yarg->data;
902*2d7be507SJakub Kicinski 	const struct nlattr *attr;
903*2d7be507SJakub Kicinski 
904*2d7be507SJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
905*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
906*2d7be507SJakub Kicinski 
907*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_CABLE_RESULT_PAIR) {
908*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
909*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
910*2d7be507SJakub Kicinski 			dst->_present.pair = 1;
911*2d7be507SJakub Kicinski 			dst->pair = mnl_attr_get_u8(attr);
912*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_CABLE_RESULT_CODE) {
913*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
914*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
915*2d7be507SJakub Kicinski 			dst->_present.code = 1;
916*2d7be507SJakub Kicinski 			dst->code = mnl_attr_get_u8(attr);
917*2d7be507SJakub Kicinski 		}
918*2d7be507SJakub Kicinski 	}
919*2d7be507SJakub Kicinski 
920*2d7be507SJakub Kicinski 	return 0;
921*2d7be507SJakub Kicinski }
922*2d7be507SJakub Kicinski 
ethtool_cable_fault_length_free(struct ethtool_cable_fault_length * obj)923*2d7be507SJakub Kicinski void ethtool_cable_fault_length_free(struct ethtool_cable_fault_length *obj)
924*2d7be507SJakub Kicinski {
925*2d7be507SJakub Kicinski }
926*2d7be507SJakub Kicinski 
ethtool_cable_fault_length_parse(struct ynl_parse_arg * yarg,const struct nlattr * nested)927*2d7be507SJakub Kicinski int ethtool_cable_fault_length_parse(struct ynl_parse_arg *yarg,
928*2d7be507SJakub Kicinski 				     const struct nlattr *nested)
929*2d7be507SJakub Kicinski {
930*2d7be507SJakub Kicinski 	struct ethtool_cable_fault_length *dst = yarg->data;
931*2d7be507SJakub Kicinski 	const struct nlattr *attr;
932*2d7be507SJakub Kicinski 
933*2d7be507SJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
934*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
935*2d7be507SJakub Kicinski 
936*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_CABLE_FAULT_LENGTH_PAIR) {
937*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
938*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
939*2d7be507SJakub Kicinski 			dst->_present.pair = 1;
940*2d7be507SJakub Kicinski 			dst->pair = mnl_attr_get_u8(attr);
941*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_CABLE_FAULT_LENGTH_CM) {
942*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
943*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
944*2d7be507SJakub Kicinski 			dst->_present.cm = 1;
945*2d7be507SJakub Kicinski 			dst->cm = mnl_attr_get_u32(attr);
946*2d7be507SJakub Kicinski 		}
947*2d7be507SJakub Kicinski 	}
948*2d7be507SJakub Kicinski 
949*2d7be507SJakub Kicinski 	return 0;
950*2d7be507SJakub Kicinski }
951*2d7be507SJakub Kicinski 
ethtool_bitset_bit_free(struct ethtool_bitset_bit * obj)952*2d7be507SJakub Kicinski void ethtool_bitset_bit_free(struct ethtool_bitset_bit *obj)
953*2d7be507SJakub Kicinski {
954*2d7be507SJakub Kicinski 	free(obj->name);
955*2d7be507SJakub Kicinski }
956*2d7be507SJakub Kicinski 
ethtool_bitset_bit_put(struct nlmsghdr * nlh,unsigned int attr_type,struct ethtool_bitset_bit * obj)957*2d7be507SJakub Kicinski int ethtool_bitset_bit_put(struct nlmsghdr *nlh, unsigned int attr_type,
958*2d7be507SJakub Kicinski 			   struct ethtool_bitset_bit *obj)
959*2d7be507SJakub Kicinski {
960*2d7be507SJakub Kicinski 	struct nlattr *nest;
961*2d7be507SJakub Kicinski 
962*2d7be507SJakub Kicinski 	nest = mnl_attr_nest_start(nlh, attr_type);
963*2d7be507SJakub Kicinski 	if (obj->_present.index)
964*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_BITSET_BIT_INDEX, obj->index);
965*2d7be507SJakub Kicinski 	if (obj->_present.name_len)
966*2d7be507SJakub Kicinski 		mnl_attr_put_strz(nlh, ETHTOOL_A_BITSET_BIT_NAME, obj->name);
967*2d7be507SJakub Kicinski 	if (obj->_present.value)
968*2d7be507SJakub Kicinski 		mnl_attr_put(nlh, ETHTOOL_A_BITSET_BIT_VALUE, 0, NULL);
969*2d7be507SJakub Kicinski 	mnl_attr_nest_end(nlh, nest);
970*2d7be507SJakub Kicinski 
971*2d7be507SJakub Kicinski 	return 0;
972*2d7be507SJakub Kicinski }
973*2d7be507SJakub Kicinski 
ethtool_bitset_bit_parse(struct ynl_parse_arg * yarg,const struct nlattr * nested)974*2d7be507SJakub Kicinski int ethtool_bitset_bit_parse(struct ynl_parse_arg *yarg,
975*2d7be507SJakub Kicinski 			     const struct nlattr *nested)
976*2d7be507SJakub Kicinski {
977*2d7be507SJakub Kicinski 	struct ethtool_bitset_bit *dst = yarg->data;
978*2d7be507SJakub Kicinski 	const struct nlattr *attr;
979*2d7be507SJakub Kicinski 
980*2d7be507SJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
981*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
982*2d7be507SJakub Kicinski 
983*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_BITSET_BIT_INDEX) {
984*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
985*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
986*2d7be507SJakub Kicinski 			dst->_present.index = 1;
987*2d7be507SJakub Kicinski 			dst->index = mnl_attr_get_u32(attr);
988*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_BITSET_BIT_NAME) {
989*2d7be507SJakub Kicinski 			unsigned int len;
990*2d7be507SJakub Kicinski 
991*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
992*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
993*2d7be507SJakub Kicinski 
994*2d7be507SJakub Kicinski 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
995*2d7be507SJakub Kicinski 			dst->_present.name_len = len;
996*2d7be507SJakub Kicinski 			dst->name = malloc(len + 1);
997*2d7be507SJakub Kicinski 			memcpy(dst->name, mnl_attr_get_str(attr), len);
998*2d7be507SJakub Kicinski 			dst->name[len] = 0;
999*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_BITSET_BIT_VALUE) {
1000*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1001*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1002*2d7be507SJakub Kicinski 			dst->_present.value = 1;
1003*2d7be507SJakub Kicinski 		}
1004*2d7be507SJakub Kicinski 	}
1005*2d7be507SJakub Kicinski 
1006*2d7be507SJakub Kicinski 	return 0;
1007*2d7be507SJakub Kicinski }
1008*2d7be507SJakub Kicinski 
ethtool_tunnel_udp_entry_free(struct ethtool_tunnel_udp_entry * obj)1009*2d7be507SJakub Kicinski void ethtool_tunnel_udp_entry_free(struct ethtool_tunnel_udp_entry *obj)
1010*2d7be507SJakub Kicinski {
1011*2d7be507SJakub Kicinski }
1012*2d7be507SJakub Kicinski 
ethtool_tunnel_udp_entry_parse(struct ynl_parse_arg * yarg,const struct nlattr * nested)1013*2d7be507SJakub Kicinski int ethtool_tunnel_udp_entry_parse(struct ynl_parse_arg *yarg,
1014*2d7be507SJakub Kicinski 				   const struct nlattr *nested)
1015*2d7be507SJakub Kicinski {
1016*2d7be507SJakub Kicinski 	struct ethtool_tunnel_udp_entry *dst = yarg->data;
1017*2d7be507SJakub Kicinski 	const struct nlattr *attr;
1018*2d7be507SJakub Kicinski 
1019*2d7be507SJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
1020*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
1021*2d7be507SJakub Kicinski 
1022*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_TUNNEL_UDP_ENTRY_PORT) {
1023*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1024*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1025*2d7be507SJakub Kicinski 			dst->_present.port = 1;
1026*2d7be507SJakub Kicinski 			dst->port = mnl_attr_get_u16(attr);
1027*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_TUNNEL_UDP_ENTRY_TYPE) {
1028*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1029*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1030*2d7be507SJakub Kicinski 			dst->_present.type = 1;
1031*2d7be507SJakub Kicinski 			dst->type = mnl_attr_get_u32(attr);
1032*2d7be507SJakub Kicinski 		}
1033*2d7be507SJakub Kicinski 	}
1034*2d7be507SJakub Kicinski 
1035*2d7be507SJakub Kicinski 	return 0;
1036*2d7be507SJakub Kicinski }
1037*2d7be507SJakub Kicinski 
ethtool_string_free(struct ethtool_string * obj)1038*2d7be507SJakub Kicinski void ethtool_string_free(struct ethtool_string *obj)
1039*2d7be507SJakub Kicinski {
1040*2d7be507SJakub Kicinski 	free(obj->value);
1041*2d7be507SJakub Kicinski }
1042*2d7be507SJakub Kicinski 
ethtool_string_put(struct nlmsghdr * nlh,unsigned int attr_type,struct ethtool_string * obj)1043*2d7be507SJakub Kicinski int ethtool_string_put(struct nlmsghdr *nlh, unsigned int attr_type,
1044*2d7be507SJakub Kicinski 		       struct ethtool_string *obj)
1045*2d7be507SJakub Kicinski {
1046*2d7be507SJakub Kicinski 	struct nlattr *nest;
1047*2d7be507SJakub Kicinski 
1048*2d7be507SJakub Kicinski 	nest = mnl_attr_nest_start(nlh, attr_type);
1049*2d7be507SJakub Kicinski 	if (obj->_present.index)
1050*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_STRING_INDEX, obj->index);
1051*2d7be507SJakub Kicinski 	if (obj->_present.value_len)
1052*2d7be507SJakub Kicinski 		mnl_attr_put_strz(nlh, ETHTOOL_A_STRING_VALUE, obj->value);
1053*2d7be507SJakub Kicinski 	mnl_attr_nest_end(nlh, nest);
1054*2d7be507SJakub Kicinski 
1055*2d7be507SJakub Kicinski 	return 0;
1056*2d7be507SJakub Kicinski }
1057*2d7be507SJakub Kicinski 
ethtool_string_parse(struct ynl_parse_arg * yarg,const struct nlattr * nested)1058*2d7be507SJakub Kicinski int ethtool_string_parse(struct ynl_parse_arg *yarg,
1059*2d7be507SJakub Kicinski 			 const struct nlattr *nested)
1060*2d7be507SJakub Kicinski {
1061*2d7be507SJakub Kicinski 	struct ethtool_string *dst = yarg->data;
1062*2d7be507SJakub Kicinski 	const struct nlattr *attr;
1063*2d7be507SJakub Kicinski 
1064*2d7be507SJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
1065*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
1066*2d7be507SJakub Kicinski 
1067*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_STRING_INDEX) {
1068*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1069*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1070*2d7be507SJakub Kicinski 			dst->_present.index = 1;
1071*2d7be507SJakub Kicinski 			dst->index = mnl_attr_get_u32(attr);
1072*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_STRING_VALUE) {
1073*2d7be507SJakub Kicinski 			unsigned int len;
1074*2d7be507SJakub Kicinski 
1075*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1076*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1077*2d7be507SJakub Kicinski 
1078*2d7be507SJakub Kicinski 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
1079*2d7be507SJakub Kicinski 			dst->_present.value_len = len;
1080*2d7be507SJakub Kicinski 			dst->value = malloc(len + 1);
1081*2d7be507SJakub Kicinski 			memcpy(dst->value, mnl_attr_get_str(attr), len);
1082*2d7be507SJakub Kicinski 			dst->value[len] = 0;
1083*2d7be507SJakub Kicinski 		}
1084*2d7be507SJakub Kicinski 	}
1085*2d7be507SJakub Kicinski 
1086*2d7be507SJakub Kicinski 	return 0;
1087*2d7be507SJakub Kicinski }
1088*2d7be507SJakub Kicinski 
ethtool_cable_nest_free(struct ethtool_cable_nest * obj)1089*2d7be507SJakub Kicinski void ethtool_cable_nest_free(struct ethtool_cable_nest *obj)
1090*2d7be507SJakub Kicinski {
1091*2d7be507SJakub Kicinski 	ethtool_cable_result_free(&obj->result);
1092*2d7be507SJakub Kicinski 	ethtool_cable_fault_length_free(&obj->fault_length);
1093*2d7be507SJakub Kicinski }
1094*2d7be507SJakub Kicinski 
ethtool_cable_nest_parse(struct ynl_parse_arg * yarg,const struct nlattr * nested)1095*2d7be507SJakub Kicinski int ethtool_cable_nest_parse(struct ynl_parse_arg *yarg,
1096*2d7be507SJakub Kicinski 			     const struct nlattr *nested)
1097*2d7be507SJakub Kicinski {
1098*2d7be507SJakub Kicinski 	struct ethtool_cable_nest *dst = yarg->data;
1099*2d7be507SJakub Kicinski 	const struct nlattr *attr;
1100*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
1101*2d7be507SJakub Kicinski 
1102*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
1103*2d7be507SJakub Kicinski 
1104*2d7be507SJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
1105*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
1106*2d7be507SJakub Kicinski 
1107*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_CABLE_NEST_RESULT) {
1108*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1109*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1110*2d7be507SJakub Kicinski 			dst->_present.result = 1;
1111*2d7be507SJakub Kicinski 
1112*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_cable_result_nest;
1113*2d7be507SJakub Kicinski 			parg.data = &dst->result;
1114*2d7be507SJakub Kicinski 			if (ethtool_cable_result_parse(&parg, attr))
1115*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1116*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_CABLE_NEST_FAULT_LENGTH) {
1117*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1118*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1119*2d7be507SJakub Kicinski 			dst->_present.fault_length = 1;
1120*2d7be507SJakub Kicinski 
1121*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_cable_fault_length_nest;
1122*2d7be507SJakub Kicinski 			parg.data = &dst->fault_length;
1123*2d7be507SJakub Kicinski 			if (ethtool_cable_fault_length_parse(&parg, attr))
1124*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1125*2d7be507SJakub Kicinski 		}
1126*2d7be507SJakub Kicinski 	}
1127*2d7be507SJakub Kicinski 
1128*2d7be507SJakub Kicinski 	return 0;
1129*2d7be507SJakub Kicinski }
1130*2d7be507SJakub Kicinski 
ethtool_bitset_bits_free(struct ethtool_bitset_bits * obj)1131*2d7be507SJakub Kicinski void ethtool_bitset_bits_free(struct ethtool_bitset_bits *obj)
1132*2d7be507SJakub Kicinski {
1133*2d7be507SJakub Kicinski 	unsigned int i;
1134*2d7be507SJakub Kicinski 
1135*2d7be507SJakub Kicinski 	for (i = 0; i < obj->n_bit; i++)
1136*2d7be507SJakub Kicinski 		ethtool_bitset_bit_free(&obj->bit[i]);
1137*2d7be507SJakub Kicinski 	free(obj->bit);
1138*2d7be507SJakub Kicinski }
1139*2d7be507SJakub Kicinski 
ethtool_bitset_bits_put(struct nlmsghdr * nlh,unsigned int attr_type,struct ethtool_bitset_bits * obj)1140*2d7be507SJakub Kicinski int ethtool_bitset_bits_put(struct nlmsghdr *nlh, unsigned int attr_type,
1141*2d7be507SJakub Kicinski 			    struct ethtool_bitset_bits *obj)
1142*2d7be507SJakub Kicinski {
1143*2d7be507SJakub Kicinski 	struct nlattr *nest;
1144*2d7be507SJakub Kicinski 
1145*2d7be507SJakub Kicinski 	nest = mnl_attr_nest_start(nlh, attr_type);
1146*2d7be507SJakub Kicinski 	for (unsigned int i = 0; i < obj->n_bit; i++)
1147*2d7be507SJakub Kicinski 		ethtool_bitset_bit_put(nlh, ETHTOOL_A_BITSET_BITS_BIT, &obj->bit[i]);
1148*2d7be507SJakub Kicinski 	mnl_attr_nest_end(nlh, nest);
1149*2d7be507SJakub Kicinski 
1150*2d7be507SJakub Kicinski 	return 0;
1151*2d7be507SJakub Kicinski }
1152*2d7be507SJakub Kicinski 
ethtool_bitset_bits_parse(struct ynl_parse_arg * yarg,const struct nlattr * nested)1153*2d7be507SJakub Kicinski int ethtool_bitset_bits_parse(struct ynl_parse_arg *yarg,
1154*2d7be507SJakub Kicinski 			      const struct nlattr *nested)
1155*2d7be507SJakub Kicinski {
1156*2d7be507SJakub Kicinski 	struct ethtool_bitset_bits *dst = yarg->data;
1157*2d7be507SJakub Kicinski 	const struct nlattr *attr;
1158*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
1159*2d7be507SJakub Kicinski 	unsigned int n_bit = 0;
1160*2d7be507SJakub Kicinski 	int i;
1161*2d7be507SJakub Kicinski 
1162*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
1163*2d7be507SJakub Kicinski 
1164*2d7be507SJakub Kicinski 	if (dst->bit)
1165*2d7be507SJakub Kicinski 		return ynl_error_parse(yarg, "attribute already present (bitset-bits.bit)");
1166*2d7be507SJakub Kicinski 
1167*2d7be507SJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
1168*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
1169*2d7be507SJakub Kicinski 
1170*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_BITSET_BITS_BIT) {
1171*2d7be507SJakub Kicinski 			n_bit++;
1172*2d7be507SJakub Kicinski 		}
1173*2d7be507SJakub Kicinski 	}
1174*2d7be507SJakub Kicinski 
1175*2d7be507SJakub Kicinski 	if (n_bit) {
1176*2d7be507SJakub Kicinski 		dst->bit = calloc(n_bit, sizeof(*dst->bit));
1177*2d7be507SJakub Kicinski 		dst->n_bit = n_bit;
1178*2d7be507SJakub Kicinski 		i = 0;
1179*2d7be507SJakub Kicinski 		parg.rsp_policy = &ethtool_bitset_bit_nest;
1180*2d7be507SJakub Kicinski 		mnl_attr_for_each_nested(attr, nested) {
1181*2d7be507SJakub Kicinski 			if (mnl_attr_get_type(attr) == ETHTOOL_A_BITSET_BITS_BIT) {
1182*2d7be507SJakub Kicinski 				parg.data = &dst->bit[i];
1183*2d7be507SJakub Kicinski 				if (ethtool_bitset_bit_parse(&parg, attr))
1184*2d7be507SJakub Kicinski 					return MNL_CB_ERROR;
1185*2d7be507SJakub Kicinski 				i++;
1186*2d7be507SJakub Kicinski 			}
1187*2d7be507SJakub Kicinski 		}
1188*2d7be507SJakub Kicinski 	}
1189*2d7be507SJakub Kicinski 
1190*2d7be507SJakub Kicinski 	return 0;
1191*2d7be507SJakub Kicinski }
1192*2d7be507SJakub Kicinski 
ethtool_strings_free(struct ethtool_strings * obj)1193*2d7be507SJakub Kicinski void ethtool_strings_free(struct ethtool_strings *obj)
1194*2d7be507SJakub Kicinski {
1195*2d7be507SJakub Kicinski 	unsigned int i;
1196*2d7be507SJakub Kicinski 
1197*2d7be507SJakub Kicinski 	for (i = 0; i < obj->n_string; i++)
1198*2d7be507SJakub Kicinski 		ethtool_string_free(&obj->string[i]);
1199*2d7be507SJakub Kicinski 	free(obj->string);
1200*2d7be507SJakub Kicinski }
1201*2d7be507SJakub Kicinski 
ethtool_strings_put(struct nlmsghdr * nlh,unsigned int attr_type,struct ethtool_strings * obj)1202*2d7be507SJakub Kicinski int ethtool_strings_put(struct nlmsghdr *nlh, unsigned int attr_type,
1203*2d7be507SJakub Kicinski 			struct ethtool_strings *obj)
1204*2d7be507SJakub Kicinski {
1205*2d7be507SJakub Kicinski 	struct nlattr *nest;
1206*2d7be507SJakub Kicinski 
1207*2d7be507SJakub Kicinski 	nest = mnl_attr_nest_start(nlh, attr_type);
1208*2d7be507SJakub Kicinski 	for (unsigned int i = 0; i < obj->n_string; i++)
1209*2d7be507SJakub Kicinski 		ethtool_string_put(nlh, ETHTOOL_A_STRINGS_STRING, &obj->string[i]);
1210*2d7be507SJakub Kicinski 	mnl_attr_nest_end(nlh, nest);
1211*2d7be507SJakub Kicinski 
1212*2d7be507SJakub Kicinski 	return 0;
1213*2d7be507SJakub Kicinski }
1214*2d7be507SJakub Kicinski 
ethtool_strings_parse(struct ynl_parse_arg * yarg,const struct nlattr * nested)1215*2d7be507SJakub Kicinski int ethtool_strings_parse(struct ynl_parse_arg *yarg,
1216*2d7be507SJakub Kicinski 			  const struct nlattr *nested)
1217*2d7be507SJakub Kicinski {
1218*2d7be507SJakub Kicinski 	struct ethtool_strings *dst = yarg->data;
1219*2d7be507SJakub Kicinski 	const struct nlattr *attr;
1220*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
1221*2d7be507SJakub Kicinski 	unsigned int n_string = 0;
1222*2d7be507SJakub Kicinski 	int i;
1223*2d7be507SJakub Kicinski 
1224*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
1225*2d7be507SJakub Kicinski 
1226*2d7be507SJakub Kicinski 	if (dst->string)
1227*2d7be507SJakub Kicinski 		return ynl_error_parse(yarg, "attribute already present (strings.string)");
1228*2d7be507SJakub Kicinski 
1229*2d7be507SJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
1230*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
1231*2d7be507SJakub Kicinski 
1232*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_STRINGS_STRING) {
1233*2d7be507SJakub Kicinski 			n_string++;
1234*2d7be507SJakub Kicinski 		}
1235*2d7be507SJakub Kicinski 	}
1236*2d7be507SJakub Kicinski 
1237*2d7be507SJakub Kicinski 	if (n_string) {
1238*2d7be507SJakub Kicinski 		dst->string = calloc(n_string, sizeof(*dst->string));
1239*2d7be507SJakub Kicinski 		dst->n_string = n_string;
1240*2d7be507SJakub Kicinski 		i = 0;
1241*2d7be507SJakub Kicinski 		parg.rsp_policy = &ethtool_string_nest;
1242*2d7be507SJakub Kicinski 		mnl_attr_for_each_nested(attr, nested) {
1243*2d7be507SJakub Kicinski 			if (mnl_attr_get_type(attr) == ETHTOOL_A_STRINGS_STRING) {
1244*2d7be507SJakub Kicinski 				parg.data = &dst->string[i];
1245*2d7be507SJakub Kicinski 				if (ethtool_string_parse(&parg, attr))
1246*2d7be507SJakub Kicinski 					return MNL_CB_ERROR;
1247*2d7be507SJakub Kicinski 				i++;
1248*2d7be507SJakub Kicinski 			}
1249*2d7be507SJakub Kicinski 		}
1250*2d7be507SJakub Kicinski 	}
1251*2d7be507SJakub Kicinski 
1252*2d7be507SJakub Kicinski 	return 0;
1253*2d7be507SJakub Kicinski }
1254*2d7be507SJakub Kicinski 
ethtool_bitset_free(struct ethtool_bitset * obj)1255*2d7be507SJakub Kicinski void ethtool_bitset_free(struct ethtool_bitset *obj)
1256*2d7be507SJakub Kicinski {
1257*2d7be507SJakub Kicinski 	ethtool_bitset_bits_free(&obj->bits);
1258*2d7be507SJakub Kicinski }
1259*2d7be507SJakub Kicinski 
ethtool_bitset_put(struct nlmsghdr * nlh,unsigned int attr_type,struct ethtool_bitset * obj)1260*2d7be507SJakub Kicinski int ethtool_bitset_put(struct nlmsghdr *nlh, unsigned int attr_type,
1261*2d7be507SJakub Kicinski 		       struct ethtool_bitset *obj)
1262*2d7be507SJakub Kicinski {
1263*2d7be507SJakub Kicinski 	struct nlattr *nest;
1264*2d7be507SJakub Kicinski 
1265*2d7be507SJakub Kicinski 	nest = mnl_attr_nest_start(nlh, attr_type);
1266*2d7be507SJakub Kicinski 	if (obj->_present.nomask)
1267*2d7be507SJakub Kicinski 		mnl_attr_put(nlh, ETHTOOL_A_BITSET_NOMASK, 0, NULL);
1268*2d7be507SJakub Kicinski 	if (obj->_present.size)
1269*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_BITSET_SIZE, obj->size);
1270*2d7be507SJakub Kicinski 	if (obj->_present.bits)
1271*2d7be507SJakub Kicinski 		ethtool_bitset_bits_put(nlh, ETHTOOL_A_BITSET_BITS, &obj->bits);
1272*2d7be507SJakub Kicinski 	mnl_attr_nest_end(nlh, nest);
1273*2d7be507SJakub Kicinski 
1274*2d7be507SJakub Kicinski 	return 0;
1275*2d7be507SJakub Kicinski }
1276*2d7be507SJakub Kicinski 
ethtool_bitset_parse(struct ynl_parse_arg * yarg,const struct nlattr * nested)1277*2d7be507SJakub Kicinski int ethtool_bitset_parse(struct ynl_parse_arg *yarg,
1278*2d7be507SJakub Kicinski 			 const struct nlattr *nested)
1279*2d7be507SJakub Kicinski {
1280*2d7be507SJakub Kicinski 	struct ethtool_bitset *dst = yarg->data;
1281*2d7be507SJakub Kicinski 	const struct nlattr *attr;
1282*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
1283*2d7be507SJakub Kicinski 
1284*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
1285*2d7be507SJakub Kicinski 
1286*2d7be507SJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
1287*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
1288*2d7be507SJakub Kicinski 
1289*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_BITSET_NOMASK) {
1290*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1291*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1292*2d7be507SJakub Kicinski 			dst->_present.nomask = 1;
1293*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_BITSET_SIZE) {
1294*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1295*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1296*2d7be507SJakub Kicinski 			dst->_present.size = 1;
1297*2d7be507SJakub Kicinski 			dst->size = mnl_attr_get_u32(attr);
1298*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_BITSET_BITS) {
1299*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1300*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1301*2d7be507SJakub Kicinski 			dst->_present.bits = 1;
1302*2d7be507SJakub Kicinski 
1303*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_bits_nest;
1304*2d7be507SJakub Kicinski 			parg.data = &dst->bits;
1305*2d7be507SJakub Kicinski 			if (ethtool_bitset_bits_parse(&parg, attr))
1306*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1307*2d7be507SJakub Kicinski 		}
1308*2d7be507SJakub Kicinski 	}
1309*2d7be507SJakub Kicinski 
1310*2d7be507SJakub Kicinski 	return 0;
1311*2d7be507SJakub Kicinski }
1312*2d7be507SJakub Kicinski 
ethtool_stringset_free(struct ethtool_stringset_ * obj)1313*2d7be507SJakub Kicinski void ethtool_stringset_free(struct ethtool_stringset_ *obj)
1314*2d7be507SJakub Kicinski {
1315*2d7be507SJakub Kicinski 	unsigned int i;
1316*2d7be507SJakub Kicinski 
1317*2d7be507SJakub Kicinski 	for (i = 0; i < obj->n_strings; i++)
1318*2d7be507SJakub Kicinski 		ethtool_strings_free(&obj->strings[i]);
1319*2d7be507SJakub Kicinski 	free(obj->strings);
1320*2d7be507SJakub Kicinski }
1321*2d7be507SJakub Kicinski 
ethtool_stringset_put(struct nlmsghdr * nlh,unsigned int attr_type,struct ethtool_stringset_ * obj)1322*2d7be507SJakub Kicinski int ethtool_stringset_put(struct nlmsghdr *nlh, unsigned int attr_type,
1323*2d7be507SJakub Kicinski 			  struct ethtool_stringset_ *obj)
1324*2d7be507SJakub Kicinski {
1325*2d7be507SJakub Kicinski 	struct nlattr *nest;
1326*2d7be507SJakub Kicinski 
1327*2d7be507SJakub Kicinski 	nest = mnl_attr_nest_start(nlh, attr_type);
1328*2d7be507SJakub Kicinski 	if (obj->_present.id)
1329*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_STRINGSET_ID, obj->id);
1330*2d7be507SJakub Kicinski 	if (obj->_present.count)
1331*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_STRINGSET_COUNT, obj->count);
1332*2d7be507SJakub Kicinski 	for (unsigned int i = 0; i < obj->n_strings; i++)
1333*2d7be507SJakub Kicinski 		ethtool_strings_put(nlh, ETHTOOL_A_STRINGSET_STRINGS, &obj->strings[i]);
1334*2d7be507SJakub Kicinski 	mnl_attr_nest_end(nlh, nest);
1335*2d7be507SJakub Kicinski 
1336*2d7be507SJakub Kicinski 	return 0;
1337*2d7be507SJakub Kicinski }
1338*2d7be507SJakub Kicinski 
ethtool_stringset_parse(struct ynl_parse_arg * yarg,const struct nlattr * nested)1339*2d7be507SJakub Kicinski int ethtool_stringset_parse(struct ynl_parse_arg *yarg,
1340*2d7be507SJakub Kicinski 			    const struct nlattr *nested)
1341*2d7be507SJakub Kicinski {
1342*2d7be507SJakub Kicinski 	struct ethtool_stringset_ *dst = yarg->data;
1343*2d7be507SJakub Kicinski 	unsigned int n_strings = 0;
1344*2d7be507SJakub Kicinski 	const struct nlattr *attr;
1345*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
1346*2d7be507SJakub Kicinski 	int i;
1347*2d7be507SJakub Kicinski 
1348*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
1349*2d7be507SJakub Kicinski 
1350*2d7be507SJakub Kicinski 	if (dst->strings)
1351*2d7be507SJakub Kicinski 		return ynl_error_parse(yarg, "attribute already present (stringset.strings)");
1352*2d7be507SJakub Kicinski 
1353*2d7be507SJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
1354*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
1355*2d7be507SJakub Kicinski 
1356*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_STRINGSET_ID) {
1357*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1358*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1359*2d7be507SJakub Kicinski 			dst->_present.id = 1;
1360*2d7be507SJakub Kicinski 			dst->id = mnl_attr_get_u32(attr);
1361*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_STRINGSET_COUNT) {
1362*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1363*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1364*2d7be507SJakub Kicinski 			dst->_present.count = 1;
1365*2d7be507SJakub Kicinski 			dst->count = mnl_attr_get_u32(attr);
1366*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_STRINGSET_STRINGS) {
1367*2d7be507SJakub Kicinski 			n_strings++;
1368*2d7be507SJakub Kicinski 		}
1369*2d7be507SJakub Kicinski 	}
1370*2d7be507SJakub Kicinski 
1371*2d7be507SJakub Kicinski 	if (n_strings) {
1372*2d7be507SJakub Kicinski 		dst->strings = calloc(n_strings, sizeof(*dst->strings));
1373*2d7be507SJakub Kicinski 		dst->n_strings = n_strings;
1374*2d7be507SJakub Kicinski 		i = 0;
1375*2d7be507SJakub Kicinski 		parg.rsp_policy = &ethtool_strings_nest;
1376*2d7be507SJakub Kicinski 		mnl_attr_for_each_nested(attr, nested) {
1377*2d7be507SJakub Kicinski 			if (mnl_attr_get_type(attr) == ETHTOOL_A_STRINGSET_STRINGS) {
1378*2d7be507SJakub Kicinski 				parg.data = &dst->strings[i];
1379*2d7be507SJakub Kicinski 				if (ethtool_strings_parse(&parg, attr))
1380*2d7be507SJakub Kicinski 					return MNL_CB_ERROR;
1381*2d7be507SJakub Kicinski 				i++;
1382*2d7be507SJakub Kicinski 			}
1383*2d7be507SJakub Kicinski 		}
1384*2d7be507SJakub Kicinski 	}
1385*2d7be507SJakub Kicinski 
1386*2d7be507SJakub Kicinski 	return 0;
1387*2d7be507SJakub Kicinski }
1388*2d7be507SJakub Kicinski 
ethtool_tunnel_udp_table_free(struct ethtool_tunnel_udp_table * obj)1389*2d7be507SJakub Kicinski void ethtool_tunnel_udp_table_free(struct ethtool_tunnel_udp_table *obj)
1390*2d7be507SJakub Kicinski {
1391*2d7be507SJakub Kicinski 	unsigned int i;
1392*2d7be507SJakub Kicinski 
1393*2d7be507SJakub Kicinski 	ethtool_bitset_free(&obj->types);
1394*2d7be507SJakub Kicinski 	for (i = 0; i < obj->n_entry; i++)
1395*2d7be507SJakub Kicinski 		ethtool_tunnel_udp_entry_free(&obj->entry[i]);
1396*2d7be507SJakub Kicinski 	free(obj->entry);
1397*2d7be507SJakub Kicinski }
1398*2d7be507SJakub Kicinski 
ethtool_tunnel_udp_table_parse(struct ynl_parse_arg * yarg,const struct nlattr * nested)1399*2d7be507SJakub Kicinski int ethtool_tunnel_udp_table_parse(struct ynl_parse_arg *yarg,
1400*2d7be507SJakub Kicinski 				   const struct nlattr *nested)
1401*2d7be507SJakub Kicinski {
1402*2d7be507SJakub Kicinski 	struct ethtool_tunnel_udp_table *dst = yarg->data;
1403*2d7be507SJakub Kicinski 	const struct nlattr *attr;
1404*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
1405*2d7be507SJakub Kicinski 	unsigned int n_entry = 0;
1406*2d7be507SJakub Kicinski 	int i;
1407*2d7be507SJakub Kicinski 
1408*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
1409*2d7be507SJakub Kicinski 
1410*2d7be507SJakub Kicinski 	if (dst->entry)
1411*2d7be507SJakub Kicinski 		return ynl_error_parse(yarg, "attribute already present (tunnel-udp-table.entry)");
1412*2d7be507SJakub Kicinski 
1413*2d7be507SJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
1414*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
1415*2d7be507SJakub Kicinski 
1416*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_TUNNEL_UDP_TABLE_SIZE) {
1417*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1418*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1419*2d7be507SJakub Kicinski 			dst->_present.size = 1;
1420*2d7be507SJakub Kicinski 			dst->size = mnl_attr_get_u32(attr);
1421*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_TUNNEL_UDP_TABLE_TYPES) {
1422*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1423*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1424*2d7be507SJakub Kicinski 			dst->_present.types = 1;
1425*2d7be507SJakub Kicinski 
1426*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
1427*2d7be507SJakub Kicinski 			parg.data = &dst->types;
1428*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
1429*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1430*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_TUNNEL_UDP_TABLE_ENTRY) {
1431*2d7be507SJakub Kicinski 			n_entry++;
1432*2d7be507SJakub Kicinski 		}
1433*2d7be507SJakub Kicinski 	}
1434*2d7be507SJakub Kicinski 
1435*2d7be507SJakub Kicinski 	if (n_entry) {
1436*2d7be507SJakub Kicinski 		dst->entry = calloc(n_entry, sizeof(*dst->entry));
1437*2d7be507SJakub Kicinski 		dst->n_entry = n_entry;
1438*2d7be507SJakub Kicinski 		i = 0;
1439*2d7be507SJakub Kicinski 		parg.rsp_policy = &ethtool_tunnel_udp_entry_nest;
1440*2d7be507SJakub Kicinski 		mnl_attr_for_each_nested(attr, nested) {
1441*2d7be507SJakub Kicinski 			if (mnl_attr_get_type(attr) == ETHTOOL_A_TUNNEL_UDP_TABLE_ENTRY) {
1442*2d7be507SJakub Kicinski 				parg.data = &dst->entry[i];
1443*2d7be507SJakub Kicinski 				if (ethtool_tunnel_udp_entry_parse(&parg, attr))
1444*2d7be507SJakub Kicinski 					return MNL_CB_ERROR;
1445*2d7be507SJakub Kicinski 				i++;
1446*2d7be507SJakub Kicinski 			}
1447*2d7be507SJakub Kicinski 		}
1448*2d7be507SJakub Kicinski 	}
1449*2d7be507SJakub Kicinski 
1450*2d7be507SJakub Kicinski 	return 0;
1451*2d7be507SJakub Kicinski }
1452*2d7be507SJakub Kicinski 
ethtool_stringsets_free(struct ethtool_stringsets * obj)1453*2d7be507SJakub Kicinski void ethtool_stringsets_free(struct ethtool_stringsets *obj)
1454*2d7be507SJakub Kicinski {
1455*2d7be507SJakub Kicinski 	unsigned int i;
1456*2d7be507SJakub Kicinski 
1457*2d7be507SJakub Kicinski 	for (i = 0; i < obj->n_stringset; i++)
1458*2d7be507SJakub Kicinski 		ethtool_stringset_free(&obj->stringset[i]);
1459*2d7be507SJakub Kicinski 	free(obj->stringset);
1460*2d7be507SJakub Kicinski }
1461*2d7be507SJakub Kicinski 
ethtool_stringsets_put(struct nlmsghdr * nlh,unsigned int attr_type,struct ethtool_stringsets * obj)1462*2d7be507SJakub Kicinski int ethtool_stringsets_put(struct nlmsghdr *nlh, unsigned int attr_type,
1463*2d7be507SJakub Kicinski 			   struct ethtool_stringsets *obj)
1464*2d7be507SJakub Kicinski {
1465*2d7be507SJakub Kicinski 	struct nlattr *nest;
1466*2d7be507SJakub Kicinski 
1467*2d7be507SJakub Kicinski 	nest = mnl_attr_nest_start(nlh, attr_type);
1468*2d7be507SJakub Kicinski 	for (unsigned int i = 0; i < obj->n_stringset; i++)
1469*2d7be507SJakub Kicinski 		ethtool_stringset_put(nlh, ETHTOOL_A_STRINGSETS_STRINGSET, &obj->stringset[i]);
1470*2d7be507SJakub Kicinski 	mnl_attr_nest_end(nlh, nest);
1471*2d7be507SJakub Kicinski 
1472*2d7be507SJakub Kicinski 	return 0;
1473*2d7be507SJakub Kicinski }
1474*2d7be507SJakub Kicinski 
ethtool_stringsets_parse(struct ynl_parse_arg * yarg,const struct nlattr * nested)1475*2d7be507SJakub Kicinski int ethtool_stringsets_parse(struct ynl_parse_arg *yarg,
1476*2d7be507SJakub Kicinski 			     const struct nlattr *nested)
1477*2d7be507SJakub Kicinski {
1478*2d7be507SJakub Kicinski 	struct ethtool_stringsets *dst = yarg->data;
1479*2d7be507SJakub Kicinski 	unsigned int n_stringset = 0;
1480*2d7be507SJakub Kicinski 	const struct nlattr *attr;
1481*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
1482*2d7be507SJakub Kicinski 	int i;
1483*2d7be507SJakub Kicinski 
1484*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
1485*2d7be507SJakub Kicinski 
1486*2d7be507SJakub Kicinski 	if (dst->stringset)
1487*2d7be507SJakub Kicinski 		return ynl_error_parse(yarg, "attribute already present (stringsets.stringset)");
1488*2d7be507SJakub Kicinski 
1489*2d7be507SJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
1490*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
1491*2d7be507SJakub Kicinski 
1492*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_STRINGSETS_STRINGSET) {
1493*2d7be507SJakub Kicinski 			n_stringset++;
1494*2d7be507SJakub Kicinski 		}
1495*2d7be507SJakub Kicinski 	}
1496*2d7be507SJakub Kicinski 
1497*2d7be507SJakub Kicinski 	if (n_stringset) {
1498*2d7be507SJakub Kicinski 		dst->stringset = calloc(n_stringset, sizeof(*dst->stringset));
1499*2d7be507SJakub Kicinski 		dst->n_stringset = n_stringset;
1500*2d7be507SJakub Kicinski 		i = 0;
1501*2d7be507SJakub Kicinski 		parg.rsp_policy = &ethtool_stringset_nest;
1502*2d7be507SJakub Kicinski 		mnl_attr_for_each_nested(attr, nested) {
1503*2d7be507SJakub Kicinski 			if (mnl_attr_get_type(attr) == ETHTOOL_A_STRINGSETS_STRINGSET) {
1504*2d7be507SJakub Kicinski 				parg.data = &dst->stringset[i];
1505*2d7be507SJakub Kicinski 				if (ethtool_stringset_parse(&parg, attr))
1506*2d7be507SJakub Kicinski 					return MNL_CB_ERROR;
1507*2d7be507SJakub Kicinski 				i++;
1508*2d7be507SJakub Kicinski 			}
1509*2d7be507SJakub Kicinski 		}
1510*2d7be507SJakub Kicinski 	}
1511*2d7be507SJakub Kicinski 
1512*2d7be507SJakub Kicinski 	return 0;
1513*2d7be507SJakub Kicinski }
1514*2d7be507SJakub Kicinski 
ethtool_tunnel_udp_free(struct ethtool_tunnel_udp * obj)1515*2d7be507SJakub Kicinski void ethtool_tunnel_udp_free(struct ethtool_tunnel_udp *obj)
1516*2d7be507SJakub Kicinski {
1517*2d7be507SJakub Kicinski 	ethtool_tunnel_udp_table_free(&obj->table);
1518*2d7be507SJakub Kicinski }
1519*2d7be507SJakub Kicinski 
ethtool_tunnel_udp_parse(struct ynl_parse_arg * yarg,const struct nlattr * nested)1520*2d7be507SJakub Kicinski int ethtool_tunnel_udp_parse(struct ynl_parse_arg *yarg,
1521*2d7be507SJakub Kicinski 			     const struct nlattr *nested)
1522*2d7be507SJakub Kicinski {
1523*2d7be507SJakub Kicinski 	struct ethtool_tunnel_udp *dst = yarg->data;
1524*2d7be507SJakub Kicinski 	const struct nlattr *attr;
1525*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
1526*2d7be507SJakub Kicinski 
1527*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
1528*2d7be507SJakub Kicinski 
1529*2d7be507SJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
1530*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
1531*2d7be507SJakub Kicinski 
1532*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_TUNNEL_UDP_TABLE) {
1533*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1534*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1535*2d7be507SJakub Kicinski 			dst->_present.table = 1;
1536*2d7be507SJakub Kicinski 
1537*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_tunnel_udp_table_nest;
1538*2d7be507SJakub Kicinski 			parg.data = &dst->table;
1539*2d7be507SJakub Kicinski 			if (ethtool_tunnel_udp_table_parse(&parg, attr))
1540*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1541*2d7be507SJakub Kicinski 		}
1542*2d7be507SJakub Kicinski 	}
1543*2d7be507SJakub Kicinski 
1544*2d7be507SJakub Kicinski 	return 0;
1545*2d7be507SJakub Kicinski }
1546*2d7be507SJakub Kicinski 
1547*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_STRSET_GET ============== */
1548*2d7be507SJakub Kicinski /* ETHTOOL_MSG_STRSET_GET - do */
ethtool_strset_get_req_free(struct ethtool_strset_get_req * req)1549*2d7be507SJakub Kicinski void ethtool_strset_get_req_free(struct ethtool_strset_get_req *req)
1550*2d7be507SJakub Kicinski {
1551*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
1552*2d7be507SJakub Kicinski 	ethtool_stringsets_free(&req->stringsets);
1553*2d7be507SJakub Kicinski 	free(req);
1554*2d7be507SJakub Kicinski }
1555*2d7be507SJakub Kicinski 
ethtool_strset_get_rsp_free(struct ethtool_strset_get_rsp * rsp)1556*2d7be507SJakub Kicinski void ethtool_strset_get_rsp_free(struct ethtool_strset_get_rsp *rsp)
1557*2d7be507SJakub Kicinski {
1558*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
1559*2d7be507SJakub Kicinski 	ethtool_stringsets_free(&rsp->stringsets);
1560*2d7be507SJakub Kicinski 	free(rsp);
1561*2d7be507SJakub Kicinski }
1562*2d7be507SJakub Kicinski 
ethtool_strset_get_rsp_parse(const struct nlmsghdr * nlh,void * data)1563*2d7be507SJakub Kicinski int ethtool_strset_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
1564*2d7be507SJakub Kicinski {
1565*2d7be507SJakub Kicinski 	struct ethtool_strset_get_rsp *dst;
1566*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
1567*2d7be507SJakub Kicinski 	const struct nlattr *attr;
1568*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
1569*2d7be507SJakub Kicinski 
1570*2d7be507SJakub Kicinski 	dst = yarg->data;
1571*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
1572*2d7be507SJakub Kicinski 
1573*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
1574*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
1575*2d7be507SJakub Kicinski 
1576*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_STRSET_HEADER) {
1577*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1578*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1579*2d7be507SJakub Kicinski 			dst->_present.header = 1;
1580*2d7be507SJakub Kicinski 
1581*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
1582*2d7be507SJakub Kicinski 			parg.data = &dst->header;
1583*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
1584*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1585*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_STRSET_STRINGSETS) {
1586*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1587*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1588*2d7be507SJakub Kicinski 			dst->_present.stringsets = 1;
1589*2d7be507SJakub Kicinski 
1590*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_stringsets_nest;
1591*2d7be507SJakub Kicinski 			parg.data = &dst->stringsets;
1592*2d7be507SJakub Kicinski 			if (ethtool_stringsets_parse(&parg, attr))
1593*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1594*2d7be507SJakub Kicinski 		}
1595*2d7be507SJakub Kicinski 	}
1596*2d7be507SJakub Kicinski 
1597*2d7be507SJakub Kicinski 	return MNL_CB_OK;
1598*2d7be507SJakub Kicinski }
1599*2d7be507SJakub Kicinski 
1600*2d7be507SJakub Kicinski struct ethtool_strset_get_rsp *
ethtool_strset_get(struct ynl_sock * ys,struct ethtool_strset_get_req * req)1601*2d7be507SJakub Kicinski ethtool_strset_get(struct ynl_sock *ys, struct ethtool_strset_get_req *req)
1602*2d7be507SJakub Kicinski {
1603*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
1604*2d7be507SJakub Kicinski 	struct ethtool_strset_get_rsp *rsp;
1605*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
1606*2d7be507SJakub Kicinski 	int err;
1607*2d7be507SJakub Kicinski 
1608*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_STRSET_GET, 1);
1609*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_strset_nest;
1610*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_strset_nest;
1611*2d7be507SJakub Kicinski 
1612*2d7be507SJakub Kicinski 	if (req->_present.header)
1613*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_STRSET_HEADER, &req->header);
1614*2d7be507SJakub Kicinski 	if (req->_present.stringsets)
1615*2d7be507SJakub Kicinski 		ethtool_stringsets_put(nlh, ETHTOOL_A_STRSET_STRINGSETS, &req->stringsets);
1616*2d7be507SJakub Kicinski 	if (req->_present.counts_only)
1617*2d7be507SJakub Kicinski 		mnl_attr_put(nlh, ETHTOOL_A_STRSET_COUNTS_ONLY, 0, NULL);
1618*2d7be507SJakub Kicinski 
1619*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
1620*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
1621*2d7be507SJakub Kicinski 	yrs.cb = ethtool_strset_get_rsp_parse;
1622*2d7be507SJakub Kicinski 	yrs.rsp_cmd = ETHTOOL_MSG_STRSET_GET;
1623*2d7be507SJakub Kicinski 
1624*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
1625*2d7be507SJakub Kicinski 	if (err < 0)
1626*2d7be507SJakub Kicinski 		goto err_free;
1627*2d7be507SJakub Kicinski 
1628*2d7be507SJakub Kicinski 	return rsp;
1629*2d7be507SJakub Kicinski 
1630*2d7be507SJakub Kicinski err_free:
1631*2d7be507SJakub Kicinski 	ethtool_strset_get_rsp_free(rsp);
1632*2d7be507SJakub Kicinski 	return NULL;
1633*2d7be507SJakub Kicinski }
1634*2d7be507SJakub Kicinski 
1635*2d7be507SJakub Kicinski /* ETHTOOL_MSG_STRSET_GET - dump */
ethtool_strset_get_list_free(struct ethtool_strset_get_list * rsp)1636*2d7be507SJakub Kicinski void ethtool_strset_get_list_free(struct ethtool_strset_get_list *rsp)
1637*2d7be507SJakub Kicinski {
1638*2d7be507SJakub Kicinski 	struct ethtool_strset_get_list *next = rsp;
1639*2d7be507SJakub Kicinski 
1640*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
1641*2d7be507SJakub Kicinski 		rsp = next;
1642*2d7be507SJakub Kicinski 		next = rsp->next;
1643*2d7be507SJakub Kicinski 
1644*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
1645*2d7be507SJakub Kicinski 		ethtool_stringsets_free(&rsp->obj.stringsets);
1646*2d7be507SJakub Kicinski 		free(rsp);
1647*2d7be507SJakub Kicinski 	}
1648*2d7be507SJakub Kicinski }
1649*2d7be507SJakub Kicinski 
1650*2d7be507SJakub Kicinski struct ethtool_strset_get_list *
ethtool_strset_get_dump(struct ynl_sock * ys,struct ethtool_strset_get_req_dump * req)1651*2d7be507SJakub Kicinski ethtool_strset_get_dump(struct ynl_sock *ys,
1652*2d7be507SJakub Kicinski 			struct ethtool_strset_get_req_dump *req)
1653*2d7be507SJakub Kicinski {
1654*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
1655*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
1656*2d7be507SJakub Kicinski 	int err;
1657*2d7be507SJakub Kicinski 
1658*2d7be507SJakub Kicinski 	yds.ys = ys;
1659*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_strset_get_list);
1660*2d7be507SJakub Kicinski 	yds.cb = ethtool_strset_get_rsp_parse;
1661*2d7be507SJakub Kicinski 	yds.rsp_cmd = ETHTOOL_MSG_STRSET_GET;
1662*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_strset_nest;
1663*2d7be507SJakub Kicinski 
1664*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_STRSET_GET, 1);
1665*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_strset_nest;
1666*2d7be507SJakub Kicinski 
1667*2d7be507SJakub Kicinski 	if (req->_present.header)
1668*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_STRSET_HEADER, &req->header);
1669*2d7be507SJakub Kicinski 	if (req->_present.stringsets)
1670*2d7be507SJakub Kicinski 		ethtool_stringsets_put(nlh, ETHTOOL_A_STRSET_STRINGSETS, &req->stringsets);
1671*2d7be507SJakub Kicinski 	if (req->_present.counts_only)
1672*2d7be507SJakub Kicinski 		mnl_attr_put(nlh, ETHTOOL_A_STRSET_COUNTS_ONLY, 0, NULL);
1673*2d7be507SJakub Kicinski 
1674*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
1675*2d7be507SJakub Kicinski 	if (err < 0)
1676*2d7be507SJakub Kicinski 		goto free_list;
1677*2d7be507SJakub Kicinski 
1678*2d7be507SJakub Kicinski 	return yds.first;
1679*2d7be507SJakub Kicinski 
1680*2d7be507SJakub Kicinski free_list:
1681*2d7be507SJakub Kicinski 	ethtool_strset_get_list_free(yds.first);
1682*2d7be507SJakub Kicinski 	return NULL;
1683*2d7be507SJakub Kicinski }
1684*2d7be507SJakub Kicinski 
1685*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_LINKINFO_GET ============== */
1686*2d7be507SJakub Kicinski /* ETHTOOL_MSG_LINKINFO_GET - do */
ethtool_linkinfo_get_req_free(struct ethtool_linkinfo_get_req * req)1687*2d7be507SJakub Kicinski void ethtool_linkinfo_get_req_free(struct ethtool_linkinfo_get_req *req)
1688*2d7be507SJakub Kicinski {
1689*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
1690*2d7be507SJakub Kicinski 	free(req);
1691*2d7be507SJakub Kicinski }
1692*2d7be507SJakub Kicinski 
ethtool_linkinfo_get_rsp_free(struct ethtool_linkinfo_get_rsp * rsp)1693*2d7be507SJakub Kicinski void ethtool_linkinfo_get_rsp_free(struct ethtool_linkinfo_get_rsp *rsp)
1694*2d7be507SJakub Kicinski {
1695*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
1696*2d7be507SJakub Kicinski 	free(rsp);
1697*2d7be507SJakub Kicinski }
1698*2d7be507SJakub Kicinski 
ethtool_linkinfo_get_rsp_parse(const struct nlmsghdr * nlh,void * data)1699*2d7be507SJakub Kicinski int ethtool_linkinfo_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
1700*2d7be507SJakub Kicinski {
1701*2d7be507SJakub Kicinski 	struct ethtool_linkinfo_get_rsp *dst;
1702*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
1703*2d7be507SJakub Kicinski 	const struct nlattr *attr;
1704*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
1705*2d7be507SJakub Kicinski 
1706*2d7be507SJakub Kicinski 	dst = yarg->data;
1707*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
1708*2d7be507SJakub Kicinski 
1709*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
1710*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
1711*2d7be507SJakub Kicinski 
1712*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_LINKINFO_HEADER) {
1713*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1714*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1715*2d7be507SJakub Kicinski 			dst->_present.header = 1;
1716*2d7be507SJakub Kicinski 
1717*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
1718*2d7be507SJakub Kicinski 			parg.data = &dst->header;
1719*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
1720*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1721*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKINFO_PORT) {
1722*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1723*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1724*2d7be507SJakub Kicinski 			dst->_present.port = 1;
1725*2d7be507SJakub Kicinski 			dst->port = mnl_attr_get_u8(attr);
1726*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKINFO_PHYADDR) {
1727*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1728*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1729*2d7be507SJakub Kicinski 			dst->_present.phyaddr = 1;
1730*2d7be507SJakub Kicinski 			dst->phyaddr = mnl_attr_get_u8(attr);
1731*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKINFO_TP_MDIX) {
1732*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1733*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1734*2d7be507SJakub Kicinski 			dst->_present.tp_mdix = 1;
1735*2d7be507SJakub Kicinski 			dst->tp_mdix = mnl_attr_get_u8(attr);
1736*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKINFO_TP_MDIX_CTRL) {
1737*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1738*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1739*2d7be507SJakub Kicinski 			dst->_present.tp_mdix_ctrl = 1;
1740*2d7be507SJakub Kicinski 			dst->tp_mdix_ctrl = mnl_attr_get_u8(attr);
1741*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKINFO_TRANSCEIVER) {
1742*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1743*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1744*2d7be507SJakub Kicinski 			dst->_present.transceiver = 1;
1745*2d7be507SJakub Kicinski 			dst->transceiver = mnl_attr_get_u8(attr);
1746*2d7be507SJakub Kicinski 		}
1747*2d7be507SJakub Kicinski 	}
1748*2d7be507SJakub Kicinski 
1749*2d7be507SJakub Kicinski 	return MNL_CB_OK;
1750*2d7be507SJakub Kicinski }
1751*2d7be507SJakub Kicinski 
1752*2d7be507SJakub Kicinski struct ethtool_linkinfo_get_rsp *
ethtool_linkinfo_get(struct ynl_sock * ys,struct ethtool_linkinfo_get_req * req)1753*2d7be507SJakub Kicinski ethtool_linkinfo_get(struct ynl_sock *ys, struct ethtool_linkinfo_get_req *req)
1754*2d7be507SJakub Kicinski {
1755*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
1756*2d7be507SJakub Kicinski 	struct ethtool_linkinfo_get_rsp *rsp;
1757*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
1758*2d7be507SJakub Kicinski 	int err;
1759*2d7be507SJakub Kicinski 
1760*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_LINKINFO_GET, 1);
1761*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_linkinfo_nest;
1762*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_linkinfo_nest;
1763*2d7be507SJakub Kicinski 
1764*2d7be507SJakub Kicinski 	if (req->_present.header)
1765*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_LINKINFO_HEADER, &req->header);
1766*2d7be507SJakub Kicinski 
1767*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
1768*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
1769*2d7be507SJakub Kicinski 	yrs.cb = ethtool_linkinfo_get_rsp_parse;
1770*2d7be507SJakub Kicinski 	yrs.rsp_cmd = ETHTOOL_MSG_LINKINFO_GET;
1771*2d7be507SJakub Kicinski 
1772*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
1773*2d7be507SJakub Kicinski 	if (err < 0)
1774*2d7be507SJakub Kicinski 		goto err_free;
1775*2d7be507SJakub Kicinski 
1776*2d7be507SJakub Kicinski 	return rsp;
1777*2d7be507SJakub Kicinski 
1778*2d7be507SJakub Kicinski err_free:
1779*2d7be507SJakub Kicinski 	ethtool_linkinfo_get_rsp_free(rsp);
1780*2d7be507SJakub Kicinski 	return NULL;
1781*2d7be507SJakub Kicinski }
1782*2d7be507SJakub Kicinski 
1783*2d7be507SJakub Kicinski /* ETHTOOL_MSG_LINKINFO_GET - dump */
ethtool_linkinfo_get_list_free(struct ethtool_linkinfo_get_list * rsp)1784*2d7be507SJakub Kicinski void ethtool_linkinfo_get_list_free(struct ethtool_linkinfo_get_list *rsp)
1785*2d7be507SJakub Kicinski {
1786*2d7be507SJakub Kicinski 	struct ethtool_linkinfo_get_list *next = rsp;
1787*2d7be507SJakub Kicinski 
1788*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
1789*2d7be507SJakub Kicinski 		rsp = next;
1790*2d7be507SJakub Kicinski 		next = rsp->next;
1791*2d7be507SJakub Kicinski 
1792*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
1793*2d7be507SJakub Kicinski 		free(rsp);
1794*2d7be507SJakub Kicinski 	}
1795*2d7be507SJakub Kicinski }
1796*2d7be507SJakub Kicinski 
1797*2d7be507SJakub Kicinski struct ethtool_linkinfo_get_list *
ethtool_linkinfo_get_dump(struct ynl_sock * ys,struct ethtool_linkinfo_get_req_dump * req)1798*2d7be507SJakub Kicinski ethtool_linkinfo_get_dump(struct ynl_sock *ys,
1799*2d7be507SJakub Kicinski 			  struct ethtool_linkinfo_get_req_dump *req)
1800*2d7be507SJakub Kicinski {
1801*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
1802*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
1803*2d7be507SJakub Kicinski 	int err;
1804*2d7be507SJakub Kicinski 
1805*2d7be507SJakub Kicinski 	yds.ys = ys;
1806*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_linkinfo_get_list);
1807*2d7be507SJakub Kicinski 	yds.cb = ethtool_linkinfo_get_rsp_parse;
1808*2d7be507SJakub Kicinski 	yds.rsp_cmd = ETHTOOL_MSG_LINKINFO_GET;
1809*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_linkinfo_nest;
1810*2d7be507SJakub Kicinski 
1811*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_LINKINFO_GET, 1);
1812*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_linkinfo_nest;
1813*2d7be507SJakub Kicinski 
1814*2d7be507SJakub Kicinski 	if (req->_present.header)
1815*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_LINKINFO_HEADER, &req->header);
1816*2d7be507SJakub Kicinski 
1817*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
1818*2d7be507SJakub Kicinski 	if (err < 0)
1819*2d7be507SJakub Kicinski 		goto free_list;
1820*2d7be507SJakub Kicinski 
1821*2d7be507SJakub Kicinski 	return yds.first;
1822*2d7be507SJakub Kicinski 
1823*2d7be507SJakub Kicinski free_list:
1824*2d7be507SJakub Kicinski 	ethtool_linkinfo_get_list_free(yds.first);
1825*2d7be507SJakub Kicinski 	return NULL;
1826*2d7be507SJakub Kicinski }
1827*2d7be507SJakub Kicinski 
1828*2d7be507SJakub Kicinski /* ETHTOOL_MSG_LINKINFO_GET - notify */
ethtool_linkinfo_get_ntf_free(struct ethtool_linkinfo_get_ntf * rsp)1829*2d7be507SJakub Kicinski void ethtool_linkinfo_get_ntf_free(struct ethtool_linkinfo_get_ntf *rsp)
1830*2d7be507SJakub Kicinski {
1831*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->obj.header);
1832*2d7be507SJakub Kicinski 	free(rsp);
1833*2d7be507SJakub Kicinski }
1834*2d7be507SJakub Kicinski 
1835*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_LINKINFO_SET ============== */
1836*2d7be507SJakub Kicinski /* ETHTOOL_MSG_LINKINFO_SET - do */
ethtool_linkinfo_set_req_free(struct ethtool_linkinfo_set_req * req)1837*2d7be507SJakub Kicinski void ethtool_linkinfo_set_req_free(struct ethtool_linkinfo_set_req *req)
1838*2d7be507SJakub Kicinski {
1839*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
1840*2d7be507SJakub Kicinski 	free(req);
1841*2d7be507SJakub Kicinski }
1842*2d7be507SJakub Kicinski 
ethtool_linkinfo_set(struct ynl_sock * ys,struct ethtool_linkinfo_set_req * req)1843*2d7be507SJakub Kicinski int ethtool_linkinfo_set(struct ynl_sock *ys,
1844*2d7be507SJakub Kicinski 			 struct ethtool_linkinfo_set_req *req)
1845*2d7be507SJakub Kicinski {
1846*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
1847*2d7be507SJakub Kicinski 	int err;
1848*2d7be507SJakub Kicinski 
1849*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_LINKINFO_SET, 1);
1850*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_linkinfo_nest;
1851*2d7be507SJakub Kicinski 
1852*2d7be507SJakub Kicinski 	if (req->_present.header)
1853*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_LINKINFO_HEADER, &req->header);
1854*2d7be507SJakub Kicinski 	if (req->_present.port)
1855*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_LINKINFO_PORT, req->port);
1856*2d7be507SJakub Kicinski 	if (req->_present.phyaddr)
1857*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_LINKINFO_PHYADDR, req->phyaddr);
1858*2d7be507SJakub Kicinski 	if (req->_present.tp_mdix)
1859*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_LINKINFO_TP_MDIX, req->tp_mdix);
1860*2d7be507SJakub Kicinski 	if (req->_present.tp_mdix_ctrl)
1861*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_LINKINFO_TP_MDIX_CTRL, req->tp_mdix_ctrl);
1862*2d7be507SJakub Kicinski 	if (req->_present.transceiver)
1863*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_LINKINFO_TRANSCEIVER, req->transceiver);
1864*2d7be507SJakub Kicinski 
1865*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, NULL);
1866*2d7be507SJakub Kicinski 	if (err < 0)
1867*2d7be507SJakub Kicinski 		return -1;
1868*2d7be507SJakub Kicinski 
1869*2d7be507SJakub Kicinski 	return 0;
1870*2d7be507SJakub Kicinski }
1871*2d7be507SJakub Kicinski 
1872*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_LINKMODES_GET ============== */
1873*2d7be507SJakub Kicinski /* ETHTOOL_MSG_LINKMODES_GET - do */
ethtool_linkmodes_get_req_free(struct ethtool_linkmodes_get_req * req)1874*2d7be507SJakub Kicinski void ethtool_linkmodes_get_req_free(struct ethtool_linkmodes_get_req *req)
1875*2d7be507SJakub Kicinski {
1876*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
1877*2d7be507SJakub Kicinski 	free(req);
1878*2d7be507SJakub Kicinski }
1879*2d7be507SJakub Kicinski 
ethtool_linkmodes_get_rsp_free(struct ethtool_linkmodes_get_rsp * rsp)1880*2d7be507SJakub Kicinski void ethtool_linkmodes_get_rsp_free(struct ethtool_linkmodes_get_rsp *rsp)
1881*2d7be507SJakub Kicinski {
1882*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
1883*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->ours);
1884*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->peer);
1885*2d7be507SJakub Kicinski 	free(rsp);
1886*2d7be507SJakub Kicinski }
1887*2d7be507SJakub Kicinski 
ethtool_linkmodes_get_rsp_parse(const struct nlmsghdr * nlh,void * data)1888*2d7be507SJakub Kicinski int ethtool_linkmodes_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
1889*2d7be507SJakub Kicinski {
1890*2d7be507SJakub Kicinski 	struct ethtool_linkmodes_get_rsp *dst;
1891*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
1892*2d7be507SJakub Kicinski 	const struct nlattr *attr;
1893*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
1894*2d7be507SJakub Kicinski 
1895*2d7be507SJakub Kicinski 	dst = yarg->data;
1896*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
1897*2d7be507SJakub Kicinski 
1898*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
1899*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
1900*2d7be507SJakub Kicinski 
1901*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_LINKMODES_HEADER) {
1902*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1903*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1904*2d7be507SJakub Kicinski 			dst->_present.header = 1;
1905*2d7be507SJakub Kicinski 
1906*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
1907*2d7be507SJakub Kicinski 			parg.data = &dst->header;
1908*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
1909*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1910*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKMODES_AUTONEG) {
1911*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1912*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1913*2d7be507SJakub Kicinski 			dst->_present.autoneg = 1;
1914*2d7be507SJakub Kicinski 			dst->autoneg = mnl_attr_get_u8(attr);
1915*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKMODES_OURS) {
1916*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1917*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1918*2d7be507SJakub Kicinski 			dst->_present.ours = 1;
1919*2d7be507SJakub Kicinski 
1920*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
1921*2d7be507SJakub Kicinski 			parg.data = &dst->ours;
1922*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
1923*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1924*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKMODES_PEER) {
1925*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1926*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1927*2d7be507SJakub Kicinski 			dst->_present.peer = 1;
1928*2d7be507SJakub Kicinski 
1929*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
1930*2d7be507SJakub Kicinski 			parg.data = &dst->peer;
1931*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
1932*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1933*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKMODES_SPEED) {
1934*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1935*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1936*2d7be507SJakub Kicinski 			dst->_present.speed = 1;
1937*2d7be507SJakub Kicinski 			dst->speed = mnl_attr_get_u32(attr);
1938*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKMODES_DUPLEX) {
1939*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1940*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1941*2d7be507SJakub Kicinski 			dst->_present.duplex = 1;
1942*2d7be507SJakub Kicinski 			dst->duplex = mnl_attr_get_u8(attr);
1943*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG) {
1944*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1945*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1946*2d7be507SJakub Kicinski 			dst->_present.master_slave_cfg = 1;
1947*2d7be507SJakub Kicinski 			dst->master_slave_cfg = mnl_attr_get_u8(attr);
1948*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE) {
1949*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1950*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1951*2d7be507SJakub Kicinski 			dst->_present.master_slave_state = 1;
1952*2d7be507SJakub Kicinski 			dst->master_slave_state = mnl_attr_get_u8(attr);
1953*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKMODES_LANES) {
1954*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1955*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1956*2d7be507SJakub Kicinski 			dst->_present.lanes = 1;
1957*2d7be507SJakub Kicinski 			dst->lanes = mnl_attr_get_u32(attr);
1958*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKMODES_RATE_MATCHING) {
1959*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1960*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
1961*2d7be507SJakub Kicinski 			dst->_present.rate_matching = 1;
1962*2d7be507SJakub Kicinski 			dst->rate_matching = mnl_attr_get_u8(attr);
1963*2d7be507SJakub Kicinski 		}
1964*2d7be507SJakub Kicinski 	}
1965*2d7be507SJakub Kicinski 
1966*2d7be507SJakub Kicinski 	return MNL_CB_OK;
1967*2d7be507SJakub Kicinski }
1968*2d7be507SJakub Kicinski 
1969*2d7be507SJakub Kicinski struct ethtool_linkmodes_get_rsp *
ethtool_linkmodes_get(struct ynl_sock * ys,struct ethtool_linkmodes_get_req * req)1970*2d7be507SJakub Kicinski ethtool_linkmodes_get(struct ynl_sock *ys,
1971*2d7be507SJakub Kicinski 		      struct ethtool_linkmodes_get_req *req)
1972*2d7be507SJakub Kicinski {
1973*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
1974*2d7be507SJakub Kicinski 	struct ethtool_linkmodes_get_rsp *rsp;
1975*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
1976*2d7be507SJakub Kicinski 	int err;
1977*2d7be507SJakub Kicinski 
1978*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_LINKMODES_GET, 1);
1979*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_linkmodes_nest;
1980*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_linkmodes_nest;
1981*2d7be507SJakub Kicinski 
1982*2d7be507SJakub Kicinski 	if (req->_present.header)
1983*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_LINKMODES_HEADER, &req->header);
1984*2d7be507SJakub Kicinski 
1985*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
1986*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
1987*2d7be507SJakub Kicinski 	yrs.cb = ethtool_linkmodes_get_rsp_parse;
1988*2d7be507SJakub Kicinski 	yrs.rsp_cmd = ETHTOOL_MSG_LINKMODES_GET;
1989*2d7be507SJakub Kicinski 
1990*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
1991*2d7be507SJakub Kicinski 	if (err < 0)
1992*2d7be507SJakub Kicinski 		goto err_free;
1993*2d7be507SJakub Kicinski 
1994*2d7be507SJakub Kicinski 	return rsp;
1995*2d7be507SJakub Kicinski 
1996*2d7be507SJakub Kicinski err_free:
1997*2d7be507SJakub Kicinski 	ethtool_linkmodes_get_rsp_free(rsp);
1998*2d7be507SJakub Kicinski 	return NULL;
1999*2d7be507SJakub Kicinski }
2000*2d7be507SJakub Kicinski 
2001*2d7be507SJakub Kicinski /* ETHTOOL_MSG_LINKMODES_GET - dump */
ethtool_linkmodes_get_list_free(struct ethtool_linkmodes_get_list * rsp)2002*2d7be507SJakub Kicinski void ethtool_linkmodes_get_list_free(struct ethtool_linkmodes_get_list *rsp)
2003*2d7be507SJakub Kicinski {
2004*2d7be507SJakub Kicinski 	struct ethtool_linkmodes_get_list *next = rsp;
2005*2d7be507SJakub Kicinski 
2006*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
2007*2d7be507SJakub Kicinski 		rsp = next;
2008*2d7be507SJakub Kicinski 		next = rsp->next;
2009*2d7be507SJakub Kicinski 
2010*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
2011*2d7be507SJakub Kicinski 		ethtool_bitset_free(&rsp->obj.ours);
2012*2d7be507SJakub Kicinski 		ethtool_bitset_free(&rsp->obj.peer);
2013*2d7be507SJakub Kicinski 		free(rsp);
2014*2d7be507SJakub Kicinski 	}
2015*2d7be507SJakub Kicinski }
2016*2d7be507SJakub Kicinski 
2017*2d7be507SJakub Kicinski struct ethtool_linkmodes_get_list *
ethtool_linkmodes_get_dump(struct ynl_sock * ys,struct ethtool_linkmodes_get_req_dump * req)2018*2d7be507SJakub Kicinski ethtool_linkmodes_get_dump(struct ynl_sock *ys,
2019*2d7be507SJakub Kicinski 			   struct ethtool_linkmodes_get_req_dump *req)
2020*2d7be507SJakub Kicinski {
2021*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
2022*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
2023*2d7be507SJakub Kicinski 	int err;
2024*2d7be507SJakub Kicinski 
2025*2d7be507SJakub Kicinski 	yds.ys = ys;
2026*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_linkmodes_get_list);
2027*2d7be507SJakub Kicinski 	yds.cb = ethtool_linkmodes_get_rsp_parse;
2028*2d7be507SJakub Kicinski 	yds.rsp_cmd = ETHTOOL_MSG_LINKMODES_GET;
2029*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_linkmodes_nest;
2030*2d7be507SJakub Kicinski 
2031*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_LINKMODES_GET, 1);
2032*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_linkmodes_nest;
2033*2d7be507SJakub Kicinski 
2034*2d7be507SJakub Kicinski 	if (req->_present.header)
2035*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_LINKMODES_HEADER, &req->header);
2036*2d7be507SJakub Kicinski 
2037*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
2038*2d7be507SJakub Kicinski 	if (err < 0)
2039*2d7be507SJakub Kicinski 		goto free_list;
2040*2d7be507SJakub Kicinski 
2041*2d7be507SJakub Kicinski 	return yds.first;
2042*2d7be507SJakub Kicinski 
2043*2d7be507SJakub Kicinski free_list:
2044*2d7be507SJakub Kicinski 	ethtool_linkmodes_get_list_free(yds.first);
2045*2d7be507SJakub Kicinski 	return NULL;
2046*2d7be507SJakub Kicinski }
2047*2d7be507SJakub Kicinski 
2048*2d7be507SJakub Kicinski /* ETHTOOL_MSG_LINKMODES_GET - notify */
ethtool_linkmodes_get_ntf_free(struct ethtool_linkmodes_get_ntf * rsp)2049*2d7be507SJakub Kicinski void ethtool_linkmodes_get_ntf_free(struct ethtool_linkmodes_get_ntf *rsp)
2050*2d7be507SJakub Kicinski {
2051*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->obj.header);
2052*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->obj.ours);
2053*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->obj.peer);
2054*2d7be507SJakub Kicinski 	free(rsp);
2055*2d7be507SJakub Kicinski }
2056*2d7be507SJakub Kicinski 
2057*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_LINKMODES_SET ============== */
2058*2d7be507SJakub Kicinski /* ETHTOOL_MSG_LINKMODES_SET - do */
ethtool_linkmodes_set_req_free(struct ethtool_linkmodes_set_req * req)2059*2d7be507SJakub Kicinski void ethtool_linkmodes_set_req_free(struct ethtool_linkmodes_set_req *req)
2060*2d7be507SJakub Kicinski {
2061*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
2062*2d7be507SJakub Kicinski 	ethtool_bitset_free(&req->ours);
2063*2d7be507SJakub Kicinski 	ethtool_bitset_free(&req->peer);
2064*2d7be507SJakub Kicinski 	free(req);
2065*2d7be507SJakub Kicinski }
2066*2d7be507SJakub Kicinski 
ethtool_linkmodes_set(struct ynl_sock * ys,struct ethtool_linkmodes_set_req * req)2067*2d7be507SJakub Kicinski int ethtool_linkmodes_set(struct ynl_sock *ys,
2068*2d7be507SJakub Kicinski 			  struct ethtool_linkmodes_set_req *req)
2069*2d7be507SJakub Kicinski {
2070*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
2071*2d7be507SJakub Kicinski 	int err;
2072*2d7be507SJakub Kicinski 
2073*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_LINKMODES_SET, 1);
2074*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_linkmodes_nest;
2075*2d7be507SJakub Kicinski 
2076*2d7be507SJakub Kicinski 	if (req->_present.header)
2077*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_LINKMODES_HEADER, &req->header);
2078*2d7be507SJakub Kicinski 	if (req->_present.autoneg)
2079*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_LINKMODES_AUTONEG, req->autoneg);
2080*2d7be507SJakub Kicinski 	if (req->_present.ours)
2081*2d7be507SJakub Kicinski 		ethtool_bitset_put(nlh, ETHTOOL_A_LINKMODES_OURS, &req->ours);
2082*2d7be507SJakub Kicinski 	if (req->_present.peer)
2083*2d7be507SJakub Kicinski 		ethtool_bitset_put(nlh, ETHTOOL_A_LINKMODES_PEER, &req->peer);
2084*2d7be507SJakub Kicinski 	if (req->_present.speed)
2085*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_LINKMODES_SPEED, req->speed);
2086*2d7be507SJakub Kicinski 	if (req->_present.duplex)
2087*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_LINKMODES_DUPLEX, req->duplex);
2088*2d7be507SJakub Kicinski 	if (req->_present.master_slave_cfg)
2089*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG, req->master_slave_cfg);
2090*2d7be507SJakub Kicinski 	if (req->_present.master_slave_state)
2091*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE, req->master_slave_state);
2092*2d7be507SJakub Kicinski 	if (req->_present.lanes)
2093*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_LINKMODES_LANES, req->lanes);
2094*2d7be507SJakub Kicinski 	if (req->_present.rate_matching)
2095*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_LINKMODES_RATE_MATCHING, req->rate_matching);
2096*2d7be507SJakub Kicinski 
2097*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, NULL);
2098*2d7be507SJakub Kicinski 	if (err < 0)
2099*2d7be507SJakub Kicinski 		return -1;
2100*2d7be507SJakub Kicinski 
2101*2d7be507SJakub Kicinski 	return 0;
2102*2d7be507SJakub Kicinski }
2103*2d7be507SJakub Kicinski 
2104*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_LINKSTATE_GET ============== */
2105*2d7be507SJakub Kicinski /* ETHTOOL_MSG_LINKSTATE_GET - do */
ethtool_linkstate_get_req_free(struct ethtool_linkstate_get_req * req)2106*2d7be507SJakub Kicinski void ethtool_linkstate_get_req_free(struct ethtool_linkstate_get_req *req)
2107*2d7be507SJakub Kicinski {
2108*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
2109*2d7be507SJakub Kicinski 	free(req);
2110*2d7be507SJakub Kicinski }
2111*2d7be507SJakub Kicinski 
ethtool_linkstate_get_rsp_free(struct ethtool_linkstate_get_rsp * rsp)2112*2d7be507SJakub Kicinski void ethtool_linkstate_get_rsp_free(struct ethtool_linkstate_get_rsp *rsp)
2113*2d7be507SJakub Kicinski {
2114*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
2115*2d7be507SJakub Kicinski 	free(rsp);
2116*2d7be507SJakub Kicinski }
2117*2d7be507SJakub Kicinski 
ethtool_linkstate_get_rsp_parse(const struct nlmsghdr * nlh,void * data)2118*2d7be507SJakub Kicinski int ethtool_linkstate_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
2119*2d7be507SJakub Kicinski {
2120*2d7be507SJakub Kicinski 	struct ethtool_linkstate_get_rsp *dst;
2121*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
2122*2d7be507SJakub Kicinski 	const struct nlattr *attr;
2123*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
2124*2d7be507SJakub Kicinski 
2125*2d7be507SJakub Kicinski 	dst = yarg->data;
2126*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
2127*2d7be507SJakub Kicinski 
2128*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
2129*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
2130*2d7be507SJakub Kicinski 
2131*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_LINKSTATE_HEADER) {
2132*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2133*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2134*2d7be507SJakub Kicinski 			dst->_present.header = 1;
2135*2d7be507SJakub Kicinski 
2136*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
2137*2d7be507SJakub Kicinski 			parg.data = &dst->header;
2138*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
2139*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2140*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKSTATE_LINK) {
2141*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2142*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2143*2d7be507SJakub Kicinski 			dst->_present.link = 1;
2144*2d7be507SJakub Kicinski 			dst->link = mnl_attr_get_u8(attr);
2145*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKSTATE_SQI) {
2146*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2147*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2148*2d7be507SJakub Kicinski 			dst->_present.sqi = 1;
2149*2d7be507SJakub Kicinski 			dst->sqi = mnl_attr_get_u32(attr);
2150*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKSTATE_SQI_MAX) {
2151*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2152*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2153*2d7be507SJakub Kicinski 			dst->_present.sqi_max = 1;
2154*2d7be507SJakub Kicinski 			dst->sqi_max = mnl_attr_get_u32(attr);
2155*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKSTATE_EXT_STATE) {
2156*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2157*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2158*2d7be507SJakub Kicinski 			dst->_present.ext_state = 1;
2159*2d7be507SJakub Kicinski 			dst->ext_state = mnl_attr_get_u8(attr);
2160*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKSTATE_EXT_SUBSTATE) {
2161*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2162*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2163*2d7be507SJakub Kicinski 			dst->_present.ext_substate = 1;
2164*2d7be507SJakub Kicinski 			dst->ext_substate = mnl_attr_get_u8(attr);
2165*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_LINKSTATE_EXT_DOWN_CNT) {
2166*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2167*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2168*2d7be507SJakub Kicinski 			dst->_present.ext_down_cnt = 1;
2169*2d7be507SJakub Kicinski 			dst->ext_down_cnt = mnl_attr_get_u32(attr);
2170*2d7be507SJakub Kicinski 		}
2171*2d7be507SJakub Kicinski 	}
2172*2d7be507SJakub Kicinski 
2173*2d7be507SJakub Kicinski 	return MNL_CB_OK;
2174*2d7be507SJakub Kicinski }
2175*2d7be507SJakub Kicinski 
2176*2d7be507SJakub Kicinski struct ethtool_linkstate_get_rsp *
ethtool_linkstate_get(struct ynl_sock * ys,struct ethtool_linkstate_get_req * req)2177*2d7be507SJakub Kicinski ethtool_linkstate_get(struct ynl_sock *ys,
2178*2d7be507SJakub Kicinski 		      struct ethtool_linkstate_get_req *req)
2179*2d7be507SJakub Kicinski {
2180*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
2181*2d7be507SJakub Kicinski 	struct ethtool_linkstate_get_rsp *rsp;
2182*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
2183*2d7be507SJakub Kicinski 	int err;
2184*2d7be507SJakub Kicinski 
2185*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_LINKSTATE_GET, 1);
2186*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_linkstate_nest;
2187*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_linkstate_nest;
2188*2d7be507SJakub Kicinski 
2189*2d7be507SJakub Kicinski 	if (req->_present.header)
2190*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_LINKSTATE_HEADER, &req->header);
2191*2d7be507SJakub Kicinski 
2192*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
2193*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
2194*2d7be507SJakub Kicinski 	yrs.cb = ethtool_linkstate_get_rsp_parse;
2195*2d7be507SJakub Kicinski 	yrs.rsp_cmd = ETHTOOL_MSG_LINKSTATE_GET;
2196*2d7be507SJakub Kicinski 
2197*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
2198*2d7be507SJakub Kicinski 	if (err < 0)
2199*2d7be507SJakub Kicinski 		goto err_free;
2200*2d7be507SJakub Kicinski 
2201*2d7be507SJakub Kicinski 	return rsp;
2202*2d7be507SJakub Kicinski 
2203*2d7be507SJakub Kicinski err_free:
2204*2d7be507SJakub Kicinski 	ethtool_linkstate_get_rsp_free(rsp);
2205*2d7be507SJakub Kicinski 	return NULL;
2206*2d7be507SJakub Kicinski }
2207*2d7be507SJakub Kicinski 
2208*2d7be507SJakub Kicinski /* ETHTOOL_MSG_LINKSTATE_GET - dump */
ethtool_linkstate_get_list_free(struct ethtool_linkstate_get_list * rsp)2209*2d7be507SJakub Kicinski void ethtool_linkstate_get_list_free(struct ethtool_linkstate_get_list *rsp)
2210*2d7be507SJakub Kicinski {
2211*2d7be507SJakub Kicinski 	struct ethtool_linkstate_get_list *next = rsp;
2212*2d7be507SJakub Kicinski 
2213*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
2214*2d7be507SJakub Kicinski 		rsp = next;
2215*2d7be507SJakub Kicinski 		next = rsp->next;
2216*2d7be507SJakub Kicinski 
2217*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
2218*2d7be507SJakub Kicinski 		free(rsp);
2219*2d7be507SJakub Kicinski 	}
2220*2d7be507SJakub Kicinski }
2221*2d7be507SJakub Kicinski 
2222*2d7be507SJakub Kicinski struct ethtool_linkstate_get_list *
ethtool_linkstate_get_dump(struct ynl_sock * ys,struct ethtool_linkstate_get_req_dump * req)2223*2d7be507SJakub Kicinski ethtool_linkstate_get_dump(struct ynl_sock *ys,
2224*2d7be507SJakub Kicinski 			   struct ethtool_linkstate_get_req_dump *req)
2225*2d7be507SJakub Kicinski {
2226*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
2227*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
2228*2d7be507SJakub Kicinski 	int err;
2229*2d7be507SJakub Kicinski 
2230*2d7be507SJakub Kicinski 	yds.ys = ys;
2231*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_linkstate_get_list);
2232*2d7be507SJakub Kicinski 	yds.cb = ethtool_linkstate_get_rsp_parse;
2233*2d7be507SJakub Kicinski 	yds.rsp_cmd = ETHTOOL_MSG_LINKSTATE_GET;
2234*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_linkstate_nest;
2235*2d7be507SJakub Kicinski 
2236*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_LINKSTATE_GET, 1);
2237*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_linkstate_nest;
2238*2d7be507SJakub Kicinski 
2239*2d7be507SJakub Kicinski 	if (req->_present.header)
2240*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_LINKSTATE_HEADER, &req->header);
2241*2d7be507SJakub Kicinski 
2242*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
2243*2d7be507SJakub Kicinski 	if (err < 0)
2244*2d7be507SJakub Kicinski 		goto free_list;
2245*2d7be507SJakub Kicinski 
2246*2d7be507SJakub Kicinski 	return yds.first;
2247*2d7be507SJakub Kicinski 
2248*2d7be507SJakub Kicinski free_list:
2249*2d7be507SJakub Kicinski 	ethtool_linkstate_get_list_free(yds.first);
2250*2d7be507SJakub Kicinski 	return NULL;
2251*2d7be507SJakub Kicinski }
2252*2d7be507SJakub Kicinski 
2253*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_DEBUG_GET ============== */
2254*2d7be507SJakub Kicinski /* ETHTOOL_MSG_DEBUG_GET - do */
ethtool_debug_get_req_free(struct ethtool_debug_get_req * req)2255*2d7be507SJakub Kicinski void ethtool_debug_get_req_free(struct ethtool_debug_get_req *req)
2256*2d7be507SJakub Kicinski {
2257*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
2258*2d7be507SJakub Kicinski 	free(req);
2259*2d7be507SJakub Kicinski }
2260*2d7be507SJakub Kicinski 
ethtool_debug_get_rsp_free(struct ethtool_debug_get_rsp * rsp)2261*2d7be507SJakub Kicinski void ethtool_debug_get_rsp_free(struct ethtool_debug_get_rsp *rsp)
2262*2d7be507SJakub Kicinski {
2263*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
2264*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->msgmask);
2265*2d7be507SJakub Kicinski 	free(rsp);
2266*2d7be507SJakub Kicinski }
2267*2d7be507SJakub Kicinski 
ethtool_debug_get_rsp_parse(const struct nlmsghdr * nlh,void * data)2268*2d7be507SJakub Kicinski int ethtool_debug_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
2269*2d7be507SJakub Kicinski {
2270*2d7be507SJakub Kicinski 	struct ethtool_debug_get_rsp *dst;
2271*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
2272*2d7be507SJakub Kicinski 	const struct nlattr *attr;
2273*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
2274*2d7be507SJakub Kicinski 
2275*2d7be507SJakub Kicinski 	dst = yarg->data;
2276*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
2277*2d7be507SJakub Kicinski 
2278*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
2279*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
2280*2d7be507SJakub Kicinski 
2281*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_DEBUG_HEADER) {
2282*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2283*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2284*2d7be507SJakub Kicinski 			dst->_present.header = 1;
2285*2d7be507SJakub Kicinski 
2286*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
2287*2d7be507SJakub Kicinski 			parg.data = &dst->header;
2288*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
2289*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2290*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_DEBUG_MSGMASK) {
2291*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2292*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2293*2d7be507SJakub Kicinski 			dst->_present.msgmask = 1;
2294*2d7be507SJakub Kicinski 
2295*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
2296*2d7be507SJakub Kicinski 			parg.data = &dst->msgmask;
2297*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
2298*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2299*2d7be507SJakub Kicinski 		}
2300*2d7be507SJakub Kicinski 	}
2301*2d7be507SJakub Kicinski 
2302*2d7be507SJakub Kicinski 	return MNL_CB_OK;
2303*2d7be507SJakub Kicinski }
2304*2d7be507SJakub Kicinski 
2305*2d7be507SJakub Kicinski struct ethtool_debug_get_rsp *
ethtool_debug_get(struct ynl_sock * ys,struct ethtool_debug_get_req * req)2306*2d7be507SJakub Kicinski ethtool_debug_get(struct ynl_sock *ys, struct ethtool_debug_get_req *req)
2307*2d7be507SJakub Kicinski {
2308*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
2309*2d7be507SJakub Kicinski 	struct ethtool_debug_get_rsp *rsp;
2310*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
2311*2d7be507SJakub Kicinski 	int err;
2312*2d7be507SJakub Kicinski 
2313*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_DEBUG_GET, 1);
2314*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_debug_nest;
2315*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_debug_nest;
2316*2d7be507SJakub Kicinski 
2317*2d7be507SJakub Kicinski 	if (req->_present.header)
2318*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_DEBUG_HEADER, &req->header);
2319*2d7be507SJakub Kicinski 
2320*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
2321*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
2322*2d7be507SJakub Kicinski 	yrs.cb = ethtool_debug_get_rsp_parse;
2323*2d7be507SJakub Kicinski 	yrs.rsp_cmd = ETHTOOL_MSG_DEBUG_GET;
2324*2d7be507SJakub Kicinski 
2325*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
2326*2d7be507SJakub Kicinski 	if (err < 0)
2327*2d7be507SJakub Kicinski 		goto err_free;
2328*2d7be507SJakub Kicinski 
2329*2d7be507SJakub Kicinski 	return rsp;
2330*2d7be507SJakub Kicinski 
2331*2d7be507SJakub Kicinski err_free:
2332*2d7be507SJakub Kicinski 	ethtool_debug_get_rsp_free(rsp);
2333*2d7be507SJakub Kicinski 	return NULL;
2334*2d7be507SJakub Kicinski }
2335*2d7be507SJakub Kicinski 
2336*2d7be507SJakub Kicinski /* ETHTOOL_MSG_DEBUG_GET - dump */
ethtool_debug_get_list_free(struct ethtool_debug_get_list * rsp)2337*2d7be507SJakub Kicinski void ethtool_debug_get_list_free(struct ethtool_debug_get_list *rsp)
2338*2d7be507SJakub Kicinski {
2339*2d7be507SJakub Kicinski 	struct ethtool_debug_get_list *next = rsp;
2340*2d7be507SJakub Kicinski 
2341*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
2342*2d7be507SJakub Kicinski 		rsp = next;
2343*2d7be507SJakub Kicinski 		next = rsp->next;
2344*2d7be507SJakub Kicinski 
2345*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
2346*2d7be507SJakub Kicinski 		ethtool_bitset_free(&rsp->obj.msgmask);
2347*2d7be507SJakub Kicinski 		free(rsp);
2348*2d7be507SJakub Kicinski 	}
2349*2d7be507SJakub Kicinski }
2350*2d7be507SJakub Kicinski 
2351*2d7be507SJakub Kicinski struct ethtool_debug_get_list *
ethtool_debug_get_dump(struct ynl_sock * ys,struct ethtool_debug_get_req_dump * req)2352*2d7be507SJakub Kicinski ethtool_debug_get_dump(struct ynl_sock *ys,
2353*2d7be507SJakub Kicinski 		       struct ethtool_debug_get_req_dump *req)
2354*2d7be507SJakub Kicinski {
2355*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
2356*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
2357*2d7be507SJakub Kicinski 	int err;
2358*2d7be507SJakub Kicinski 
2359*2d7be507SJakub Kicinski 	yds.ys = ys;
2360*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_debug_get_list);
2361*2d7be507SJakub Kicinski 	yds.cb = ethtool_debug_get_rsp_parse;
2362*2d7be507SJakub Kicinski 	yds.rsp_cmd = ETHTOOL_MSG_DEBUG_GET;
2363*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_debug_nest;
2364*2d7be507SJakub Kicinski 
2365*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_DEBUG_GET, 1);
2366*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_debug_nest;
2367*2d7be507SJakub Kicinski 
2368*2d7be507SJakub Kicinski 	if (req->_present.header)
2369*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_DEBUG_HEADER, &req->header);
2370*2d7be507SJakub Kicinski 
2371*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
2372*2d7be507SJakub Kicinski 	if (err < 0)
2373*2d7be507SJakub Kicinski 		goto free_list;
2374*2d7be507SJakub Kicinski 
2375*2d7be507SJakub Kicinski 	return yds.first;
2376*2d7be507SJakub Kicinski 
2377*2d7be507SJakub Kicinski free_list:
2378*2d7be507SJakub Kicinski 	ethtool_debug_get_list_free(yds.first);
2379*2d7be507SJakub Kicinski 	return NULL;
2380*2d7be507SJakub Kicinski }
2381*2d7be507SJakub Kicinski 
2382*2d7be507SJakub Kicinski /* ETHTOOL_MSG_DEBUG_GET - notify */
ethtool_debug_get_ntf_free(struct ethtool_debug_get_ntf * rsp)2383*2d7be507SJakub Kicinski void ethtool_debug_get_ntf_free(struct ethtool_debug_get_ntf *rsp)
2384*2d7be507SJakub Kicinski {
2385*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->obj.header);
2386*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->obj.msgmask);
2387*2d7be507SJakub Kicinski 	free(rsp);
2388*2d7be507SJakub Kicinski }
2389*2d7be507SJakub Kicinski 
2390*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_DEBUG_SET ============== */
2391*2d7be507SJakub Kicinski /* ETHTOOL_MSG_DEBUG_SET - do */
ethtool_debug_set_req_free(struct ethtool_debug_set_req * req)2392*2d7be507SJakub Kicinski void ethtool_debug_set_req_free(struct ethtool_debug_set_req *req)
2393*2d7be507SJakub Kicinski {
2394*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
2395*2d7be507SJakub Kicinski 	ethtool_bitset_free(&req->msgmask);
2396*2d7be507SJakub Kicinski 	free(req);
2397*2d7be507SJakub Kicinski }
2398*2d7be507SJakub Kicinski 
ethtool_debug_set(struct ynl_sock * ys,struct ethtool_debug_set_req * req)2399*2d7be507SJakub Kicinski int ethtool_debug_set(struct ynl_sock *ys, struct ethtool_debug_set_req *req)
2400*2d7be507SJakub Kicinski {
2401*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
2402*2d7be507SJakub Kicinski 	int err;
2403*2d7be507SJakub Kicinski 
2404*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_DEBUG_SET, 1);
2405*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_debug_nest;
2406*2d7be507SJakub Kicinski 
2407*2d7be507SJakub Kicinski 	if (req->_present.header)
2408*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_DEBUG_HEADER, &req->header);
2409*2d7be507SJakub Kicinski 	if (req->_present.msgmask)
2410*2d7be507SJakub Kicinski 		ethtool_bitset_put(nlh, ETHTOOL_A_DEBUG_MSGMASK, &req->msgmask);
2411*2d7be507SJakub Kicinski 
2412*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, NULL);
2413*2d7be507SJakub Kicinski 	if (err < 0)
2414*2d7be507SJakub Kicinski 		return -1;
2415*2d7be507SJakub Kicinski 
2416*2d7be507SJakub Kicinski 	return 0;
2417*2d7be507SJakub Kicinski }
2418*2d7be507SJakub Kicinski 
2419*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_WOL_GET ============== */
2420*2d7be507SJakub Kicinski /* ETHTOOL_MSG_WOL_GET - do */
ethtool_wol_get_req_free(struct ethtool_wol_get_req * req)2421*2d7be507SJakub Kicinski void ethtool_wol_get_req_free(struct ethtool_wol_get_req *req)
2422*2d7be507SJakub Kicinski {
2423*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
2424*2d7be507SJakub Kicinski 	free(req);
2425*2d7be507SJakub Kicinski }
2426*2d7be507SJakub Kicinski 
ethtool_wol_get_rsp_free(struct ethtool_wol_get_rsp * rsp)2427*2d7be507SJakub Kicinski void ethtool_wol_get_rsp_free(struct ethtool_wol_get_rsp *rsp)
2428*2d7be507SJakub Kicinski {
2429*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
2430*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->modes);
2431*2d7be507SJakub Kicinski 	free(rsp->sopass);
2432*2d7be507SJakub Kicinski 	free(rsp);
2433*2d7be507SJakub Kicinski }
2434*2d7be507SJakub Kicinski 
ethtool_wol_get_rsp_parse(const struct nlmsghdr * nlh,void * data)2435*2d7be507SJakub Kicinski int ethtool_wol_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
2436*2d7be507SJakub Kicinski {
2437*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
2438*2d7be507SJakub Kicinski 	struct ethtool_wol_get_rsp *dst;
2439*2d7be507SJakub Kicinski 	const struct nlattr *attr;
2440*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
2441*2d7be507SJakub Kicinski 
2442*2d7be507SJakub Kicinski 	dst = yarg->data;
2443*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
2444*2d7be507SJakub Kicinski 
2445*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
2446*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
2447*2d7be507SJakub Kicinski 
2448*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_WOL_HEADER) {
2449*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2450*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2451*2d7be507SJakub Kicinski 			dst->_present.header = 1;
2452*2d7be507SJakub Kicinski 
2453*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
2454*2d7be507SJakub Kicinski 			parg.data = &dst->header;
2455*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
2456*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2457*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_WOL_MODES) {
2458*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2459*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2460*2d7be507SJakub Kicinski 			dst->_present.modes = 1;
2461*2d7be507SJakub Kicinski 
2462*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
2463*2d7be507SJakub Kicinski 			parg.data = &dst->modes;
2464*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
2465*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2466*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_WOL_SOPASS) {
2467*2d7be507SJakub Kicinski 			unsigned int len;
2468*2d7be507SJakub Kicinski 
2469*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2470*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2471*2d7be507SJakub Kicinski 
2472*2d7be507SJakub Kicinski 			len = mnl_attr_get_payload_len(attr);
2473*2d7be507SJakub Kicinski 			dst->_present.sopass_len = len;
2474*2d7be507SJakub Kicinski 			dst->sopass = malloc(len);
2475*2d7be507SJakub Kicinski 			memcpy(dst->sopass, mnl_attr_get_payload(attr), len);
2476*2d7be507SJakub Kicinski 		}
2477*2d7be507SJakub Kicinski 	}
2478*2d7be507SJakub Kicinski 
2479*2d7be507SJakub Kicinski 	return MNL_CB_OK;
2480*2d7be507SJakub Kicinski }
2481*2d7be507SJakub Kicinski 
2482*2d7be507SJakub Kicinski struct ethtool_wol_get_rsp *
ethtool_wol_get(struct ynl_sock * ys,struct ethtool_wol_get_req * req)2483*2d7be507SJakub Kicinski ethtool_wol_get(struct ynl_sock *ys, struct ethtool_wol_get_req *req)
2484*2d7be507SJakub Kicinski {
2485*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
2486*2d7be507SJakub Kicinski 	struct ethtool_wol_get_rsp *rsp;
2487*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
2488*2d7be507SJakub Kicinski 	int err;
2489*2d7be507SJakub Kicinski 
2490*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_WOL_GET, 1);
2491*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_wol_nest;
2492*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_wol_nest;
2493*2d7be507SJakub Kicinski 
2494*2d7be507SJakub Kicinski 	if (req->_present.header)
2495*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_WOL_HEADER, &req->header);
2496*2d7be507SJakub Kicinski 
2497*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
2498*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
2499*2d7be507SJakub Kicinski 	yrs.cb = ethtool_wol_get_rsp_parse;
2500*2d7be507SJakub Kicinski 	yrs.rsp_cmd = ETHTOOL_MSG_WOL_GET;
2501*2d7be507SJakub Kicinski 
2502*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
2503*2d7be507SJakub Kicinski 	if (err < 0)
2504*2d7be507SJakub Kicinski 		goto err_free;
2505*2d7be507SJakub Kicinski 
2506*2d7be507SJakub Kicinski 	return rsp;
2507*2d7be507SJakub Kicinski 
2508*2d7be507SJakub Kicinski err_free:
2509*2d7be507SJakub Kicinski 	ethtool_wol_get_rsp_free(rsp);
2510*2d7be507SJakub Kicinski 	return NULL;
2511*2d7be507SJakub Kicinski }
2512*2d7be507SJakub Kicinski 
2513*2d7be507SJakub Kicinski /* ETHTOOL_MSG_WOL_GET - dump */
ethtool_wol_get_list_free(struct ethtool_wol_get_list * rsp)2514*2d7be507SJakub Kicinski void ethtool_wol_get_list_free(struct ethtool_wol_get_list *rsp)
2515*2d7be507SJakub Kicinski {
2516*2d7be507SJakub Kicinski 	struct ethtool_wol_get_list *next = rsp;
2517*2d7be507SJakub Kicinski 
2518*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
2519*2d7be507SJakub Kicinski 		rsp = next;
2520*2d7be507SJakub Kicinski 		next = rsp->next;
2521*2d7be507SJakub Kicinski 
2522*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
2523*2d7be507SJakub Kicinski 		ethtool_bitset_free(&rsp->obj.modes);
2524*2d7be507SJakub Kicinski 		free(rsp->obj.sopass);
2525*2d7be507SJakub Kicinski 		free(rsp);
2526*2d7be507SJakub Kicinski 	}
2527*2d7be507SJakub Kicinski }
2528*2d7be507SJakub Kicinski 
2529*2d7be507SJakub Kicinski struct ethtool_wol_get_list *
ethtool_wol_get_dump(struct ynl_sock * ys,struct ethtool_wol_get_req_dump * req)2530*2d7be507SJakub Kicinski ethtool_wol_get_dump(struct ynl_sock *ys, struct ethtool_wol_get_req_dump *req)
2531*2d7be507SJakub Kicinski {
2532*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
2533*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
2534*2d7be507SJakub Kicinski 	int err;
2535*2d7be507SJakub Kicinski 
2536*2d7be507SJakub Kicinski 	yds.ys = ys;
2537*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_wol_get_list);
2538*2d7be507SJakub Kicinski 	yds.cb = ethtool_wol_get_rsp_parse;
2539*2d7be507SJakub Kicinski 	yds.rsp_cmd = ETHTOOL_MSG_WOL_GET;
2540*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_wol_nest;
2541*2d7be507SJakub Kicinski 
2542*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_WOL_GET, 1);
2543*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_wol_nest;
2544*2d7be507SJakub Kicinski 
2545*2d7be507SJakub Kicinski 	if (req->_present.header)
2546*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_WOL_HEADER, &req->header);
2547*2d7be507SJakub Kicinski 
2548*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
2549*2d7be507SJakub Kicinski 	if (err < 0)
2550*2d7be507SJakub Kicinski 		goto free_list;
2551*2d7be507SJakub Kicinski 
2552*2d7be507SJakub Kicinski 	return yds.first;
2553*2d7be507SJakub Kicinski 
2554*2d7be507SJakub Kicinski free_list:
2555*2d7be507SJakub Kicinski 	ethtool_wol_get_list_free(yds.first);
2556*2d7be507SJakub Kicinski 	return NULL;
2557*2d7be507SJakub Kicinski }
2558*2d7be507SJakub Kicinski 
2559*2d7be507SJakub Kicinski /* ETHTOOL_MSG_WOL_GET - notify */
ethtool_wol_get_ntf_free(struct ethtool_wol_get_ntf * rsp)2560*2d7be507SJakub Kicinski void ethtool_wol_get_ntf_free(struct ethtool_wol_get_ntf *rsp)
2561*2d7be507SJakub Kicinski {
2562*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->obj.header);
2563*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->obj.modes);
2564*2d7be507SJakub Kicinski 	free(rsp->obj.sopass);
2565*2d7be507SJakub Kicinski 	free(rsp);
2566*2d7be507SJakub Kicinski }
2567*2d7be507SJakub Kicinski 
2568*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_WOL_SET ============== */
2569*2d7be507SJakub Kicinski /* ETHTOOL_MSG_WOL_SET - do */
ethtool_wol_set_req_free(struct ethtool_wol_set_req * req)2570*2d7be507SJakub Kicinski void ethtool_wol_set_req_free(struct ethtool_wol_set_req *req)
2571*2d7be507SJakub Kicinski {
2572*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
2573*2d7be507SJakub Kicinski 	ethtool_bitset_free(&req->modes);
2574*2d7be507SJakub Kicinski 	free(req->sopass);
2575*2d7be507SJakub Kicinski 	free(req);
2576*2d7be507SJakub Kicinski }
2577*2d7be507SJakub Kicinski 
ethtool_wol_set(struct ynl_sock * ys,struct ethtool_wol_set_req * req)2578*2d7be507SJakub Kicinski int ethtool_wol_set(struct ynl_sock *ys, struct ethtool_wol_set_req *req)
2579*2d7be507SJakub Kicinski {
2580*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
2581*2d7be507SJakub Kicinski 	int err;
2582*2d7be507SJakub Kicinski 
2583*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_WOL_SET, 1);
2584*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_wol_nest;
2585*2d7be507SJakub Kicinski 
2586*2d7be507SJakub Kicinski 	if (req->_present.header)
2587*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_WOL_HEADER, &req->header);
2588*2d7be507SJakub Kicinski 	if (req->_present.modes)
2589*2d7be507SJakub Kicinski 		ethtool_bitset_put(nlh, ETHTOOL_A_WOL_MODES, &req->modes);
2590*2d7be507SJakub Kicinski 	if (req->_present.sopass_len)
2591*2d7be507SJakub Kicinski 		mnl_attr_put(nlh, ETHTOOL_A_WOL_SOPASS, req->_present.sopass_len, req->sopass);
2592*2d7be507SJakub Kicinski 
2593*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, NULL);
2594*2d7be507SJakub Kicinski 	if (err < 0)
2595*2d7be507SJakub Kicinski 		return -1;
2596*2d7be507SJakub Kicinski 
2597*2d7be507SJakub Kicinski 	return 0;
2598*2d7be507SJakub Kicinski }
2599*2d7be507SJakub Kicinski 
2600*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_FEATURES_GET ============== */
2601*2d7be507SJakub Kicinski /* ETHTOOL_MSG_FEATURES_GET - do */
ethtool_features_get_req_free(struct ethtool_features_get_req * req)2602*2d7be507SJakub Kicinski void ethtool_features_get_req_free(struct ethtool_features_get_req *req)
2603*2d7be507SJakub Kicinski {
2604*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
2605*2d7be507SJakub Kicinski 	free(req);
2606*2d7be507SJakub Kicinski }
2607*2d7be507SJakub Kicinski 
ethtool_features_get_rsp_free(struct ethtool_features_get_rsp * rsp)2608*2d7be507SJakub Kicinski void ethtool_features_get_rsp_free(struct ethtool_features_get_rsp *rsp)
2609*2d7be507SJakub Kicinski {
2610*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
2611*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->hw);
2612*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->wanted);
2613*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->active);
2614*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->nochange);
2615*2d7be507SJakub Kicinski 	free(rsp);
2616*2d7be507SJakub Kicinski }
2617*2d7be507SJakub Kicinski 
ethtool_features_get_rsp_parse(const struct nlmsghdr * nlh,void * data)2618*2d7be507SJakub Kicinski int ethtool_features_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
2619*2d7be507SJakub Kicinski {
2620*2d7be507SJakub Kicinski 	struct ethtool_features_get_rsp *dst;
2621*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
2622*2d7be507SJakub Kicinski 	const struct nlattr *attr;
2623*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
2624*2d7be507SJakub Kicinski 
2625*2d7be507SJakub Kicinski 	dst = yarg->data;
2626*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
2627*2d7be507SJakub Kicinski 
2628*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
2629*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
2630*2d7be507SJakub Kicinski 
2631*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_FEATURES_HEADER) {
2632*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2633*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2634*2d7be507SJakub Kicinski 			dst->_present.header = 1;
2635*2d7be507SJakub Kicinski 
2636*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
2637*2d7be507SJakub Kicinski 			parg.data = &dst->header;
2638*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
2639*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2640*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_FEATURES_HW) {
2641*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2642*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2643*2d7be507SJakub Kicinski 			dst->_present.hw = 1;
2644*2d7be507SJakub Kicinski 
2645*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
2646*2d7be507SJakub Kicinski 			parg.data = &dst->hw;
2647*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
2648*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2649*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_FEATURES_WANTED) {
2650*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2651*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2652*2d7be507SJakub Kicinski 			dst->_present.wanted = 1;
2653*2d7be507SJakub Kicinski 
2654*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
2655*2d7be507SJakub Kicinski 			parg.data = &dst->wanted;
2656*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
2657*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2658*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_FEATURES_ACTIVE) {
2659*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2660*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2661*2d7be507SJakub Kicinski 			dst->_present.active = 1;
2662*2d7be507SJakub Kicinski 
2663*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
2664*2d7be507SJakub Kicinski 			parg.data = &dst->active;
2665*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
2666*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2667*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_FEATURES_NOCHANGE) {
2668*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2669*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2670*2d7be507SJakub Kicinski 			dst->_present.nochange = 1;
2671*2d7be507SJakub Kicinski 
2672*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
2673*2d7be507SJakub Kicinski 			parg.data = &dst->nochange;
2674*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
2675*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2676*2d7be507SJakub Kicinski 		}
2677*2d7be507SJakub Kicinski 	}
2678*2d7be507SJakub Kicinski 
2679*2d7be507SJakub Kicinski 	return MNL_CB_OK;
2680*2d7be507SJakub Kicinski }
2681*2d7be507SJakub Kicinski 
2682*2d7be507SJakub Kicinski struct ethtool_features_get_rsp *
ethtool_features_get(struct ynl_sock * ys,struct ethtool_features_get_req * req)2683*2d7be507SJakub Kicinski ethtool_features_get(struct ynl_sock *ys, struct ethtool_features_get_req *req)
2684*2d7be507SJakub Kicinski {
2685*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
2686*2d7be507SJakub Kicinski 	struct ethtool_features_get_rsp *rsp;
2687*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
2688*2d7be507SJakub Kicinski 	int err;
2689*2d7be507SJakub Kicinski 
2690*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_FEATURES_GET, 1);
2691*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_features_nest;
2692*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_features_nest;
2693*2d7be507SJakub Kicinski 
2694*2d7be507SJakub Kicinski 	if (req->_present.header)
2695*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_FEATURES_HEADER, &req->header);
2696*2d7be507SJakub Kicinski 
2697*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
2698*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
2699*2d7be507SJakub Kicinski 	yrs.cb = ethtool_features_get_rsp_parse;
2700*2d7be507SJakub Kicinski 	yrs.rsp_cmd = ETHTOOL_MSG_FEATURES_GET;
2701*2d7be507SJakub Kicinski 
2702*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
2703*2d7be507SJakub Kicinski 	if (err < 0)
2704*2d7be507SJakub Kicinski 		goto err_free;
2705*2d7be507SJakub Kicinski 
2706*2d7be507SJakub Kicinski 	return rsp;
2707*2d7be507SJakub Kicinski 
2708*2d7be507SJakub Kicinski err_free:
2709*2d7be507SJakub Kicinski 	ethtool_features_get_rsp_free(rsp);
2710*2d7be507SJakub Kicinski 	return NULL;
2711*2d7be507SJakub Kicinski }
2712*2d7be507SJakub Kicinski 
2713*2d7be507SJakub Kicinski /* ETHTOOL_MSG_FEATURES_GET - dump */
ethtool_features_get_list_free(struct ethtool_features_get_list * rsp)2714*2d7be507SJakub Kicinski void ethtool_features_get_list_free(struct ethtool_features_get_list *rsp)
2715*2d7be507SJakub Kicinski {
2716*2d7be507SJakub Kicinski 	struct ethtool_features_get_list *next = rsp;
2717*2d7be507SJakub Kicinski 
2718*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
2719*2d7be507SJakub Kicinski 		rsp = next;
2720*2d7be507SJakub Kicinski 		next = rsp->next;
2721*2d7be507SJakub Kicinski 
2722*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
2723*2d7be507SJakub Kicinski 		ethtool_bitset_free(&rsp->obj.hw);
2724*2d7be507SJakub Kicinski 		ethtool_bitset_free(&rsp->obj.wanted);
2725*2d7be507SJakub Kicinski 		ethtool_bitset_free(&rsp->obj.active);
2726*2d7be507SJakub Kicinski 		ethtool_bitset_free(&rsp->obj.nochange);
2727*2d7be507SJakub Kicinski 		free(rsp);
2728*2d7be507SJakub Kicinski 	}
2729*2d7be507SJakub Kicinski }
2730*2d7be507SJakub Kicinski 
2731*2d7be507SJakub Kicinski struct ethtool_features_get_list *
ethtool_features_get_dump(struct ynl_sock * ys,struct ethtool_features_get_req_dump * req)2732*2d7be507SJakub Kicinski ethtool_features_get_dump(struct ynl_sock *ys,
2733*2d7be507SJakub Kicinski 			  struct ethtool_features_get_req_dump *req)
2734*2d7be507SJakub Kicinski {
2735*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
2736*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
2737*2d7be507SJakub Kicinski 	int err;
2738*2d7be507SJakub Kicinski 
2739*2d7be507SJakub Kicinski 	yds.ys = ys;
2740*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_features_get_list);
2741*2d7be507SJakub Kicinski 	yds.cb = ethtool_features_get_rsp_parse;
2742*2d7be507SJakub Kicinski 	yds.rsp_cmd = ETHTOOL_MSG_FEATURES_GET;
2743*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_features_nest;
2744*2d7be507SJakub Kicinski 
2745*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_FEATURES_GET, 1);
2746*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_features_nest;
2747*2d7be507SJakub Kicinski 
2748*2d7be507SJakub Kicinski 	if (req->_present.header)
2749*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_FEATURES_HEADER, &req->header);
2750*2d7be507SJakub Kicinski 
2751*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
2752*2d7be507SJakub Kicinski 	if (err < 0)
2753*2d7be507SJakub Kicinski 		goto free_list;
2754*2d7be507SJakub Kicinski 
2755*2d7be507SJakub Kicinski 	return yds.first;
2756*2d7be507SJakub Kicinski 
2757*2d7be507SJakub Kicinski free_list:
2758*2d7be507SJakub Kicinski 	ethtool_features_get_list_free(yds.first);
2759*2d7be507SJakub Kicinski 	return NULL;
2760*2d7be507SJakub Kicinski }
2761*2d7be507SJakub Kicinski 
2762*2d7be507SJakub Kicinski /* ETHTOOL_MSG_FEATURES_GET - notify */
ethtool_features_get_ntf_free(struct ethtool_features_get_ntf * rsp)2763*2d7be507SJakub Kicinski void ethtool_features_get_ntf_free(struct ethtool_features_get_ntf *rsp)
2764*2d7be507SJakub Kicinski {
2765*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->obj.header);
2766*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->obj.hw);
2767*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->obj.wanted);
2768*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->obj.active);
2769*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->obj.nochange);
2770*2d7be507SJakub Kicinski 	free(rsp);
2771*2d7be507SJakub Kicinski }
2772*2d7be507SJakub Kicinski 
2773*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_FEATURES_SET ============== */
2774*2d7be507SJakub Kicinski /* ETHTOOL_MSG_FEATURES_SET - do */
ethtool_features_set_req_free(struct ethtool_features_set_req * req)2775*2d7be507SJakub Kicinski void ethtool_features_set_req_free(struct ethtool_features_set_req *req)
2776*2d7be507SJakub Kicinski {
2777*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
2778*2d7be507SJakub Kicinski 	ethtool_bitset_free(&req->hw);
2779*2d7be507SJakub Kicinski 	ethtool_bitset_free(&req->wanted);
2780*2d7be507SJakub Kicinski 	ethtool_bitset_free(&req->active);
2781*2d7be507SJakub Kicinski 	ethtool_bitset_free(&req->nochange);
2782*2d7be507SJakub Kicinski 	free(req);
2783*2d7be507SJakub Kicinski }
2784*2d7be507SJakub Kicinski 
ethtool_features_set_rsp_free(struct ethtool_features_set_rsp * rsp)2785*2d7be507SJakub Kicinski void ethtool_features_set_rsp_free(struct ethtool_features_set_rsp *rsp)
2786*2d7be507SJakub Kicinski {
2787*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
2788*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->hw);
2789*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->wanted);
2790*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->active);
2791*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->nochange);
2792*2d7be507SJakub Kicinski 	free(rsp);
2793*2d7be507SJakub Kicinski }
2794*2d7be507SJakub Kicinski 
ethtool_features_set_rsp_parse(const struct nlmsghdr * nlh,void * data)2795*2d7be507SJakub Kicinski int ethtool_features_set_rsp_parse(const struct nlmsghdr *nlh, void *data)
2796*2d7be507SJakub Kicinski {
2797*2d7be507SJakub Kicinski 	struct ethtool_features_set_rsp *dst;
2798*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
2799*2d7be507SJakub Kicinski 	const struct nlattr *attr;
2800*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
2801*2d7be507SJakub Kicinski 
2802*2d7be507SJakub Kicinski 	dst = yarg->data;
2803*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
2804*2d7be507SJakub Kicinski 
2805*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
2806*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
2807*2d7be507SJakub Kicinski 
2808*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_FEATURES_HEADER) {
2809*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2810*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2811*2d7be507SJakub Kicinski 			dst->_present.header = 1;
2812*2d7be507SJakub Kicinski 
2813*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
2814*2d7be507SJakub Kicinski 			parg.data = &dst->header;
2815*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
2816*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2817*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_FEATURES_HW) {
2818*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2819*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2820*2d7be507SJakub Kicinski 			dst->_present.hw = 1;
2821*2d7be507SJakub Kicinski 
2822*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
2823*2d7be507SJakub Kicinski 			parg.data = &dst->hw;
2824*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
2825*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2826*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_FEATURES_WANTED) {
2827*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2828*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2829*2d7be507SJakub Kicinski 			dst->_present.wanted = 1;
2830*2d7be507SJakub Kicinski 
2831*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
2832*2d7be507SJakub Kicinski 			parg.data = &dst->wanted;
2833*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
2834*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2835*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_FEATURES_ACTIVE) {
2836*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2837*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2838*2d7be507SJakub Kicinski 			dst->_present.active = 1;
2839*2d7be507SJakub Kicinski 
2840*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
2841*2d7be507SJakub Kicinski 			parg.data = &dst->active;
2842*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
2843*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2844*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_FEATURES_NOCHANGE) {
2845*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2846*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2847*2d7be507SJakub Kicinski 			dst->_present.nochange = 1;
2848*2d7be507SJakub Kicinski 
2849*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
2850*2d7be507SJakub Kicinski 			parg.data = &dst->nochange;
2851*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
2852*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2853*2d7be507SJakub Kicinski 		}
2854*2d7be507SJakub Kicinski 	}
2855*2d7be507SJakub Kicinski 
2856*2d7be507SJakub Kicinski 	return MNL_CB_OK;
2857*2d7be507SJakub Kicinski }
2858*2d7be507SJakub Kicinski 
2859*2d7be507SJakub Kicinski struct ethtool_features_set_rsp *
ethtool_features_set(struct ynl_sock * ys,struct ethtool_features_set_req * req)2860*2d7be507SJakub Kicinski ethtool_features_set(struct ynl_sock *ys, struct ethtool_features_set_req *req)
2861*2d7be507SJakub Kicinski {
2862*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
2863*2d7be507SJakub Kicinski 	struct ethtool_features_set_rsp *rsp;
2864*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
2865*2d7be507SJakub Kicinski 	int err;
2866*2d7be507SJakub Kicinski 
2867*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_FEATURES_SET, 1);
2868*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_features_nest;
2869*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_features_nest;
2870*2d7be507SJakub Kicinski 
2871*2d7be507SJakub Kicinski 	if (req->_present.header)
2872*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_FEATURES_HEADER, &req->header);
2873*2d7be507SJakub Kicinski 	if (req->_present.hw)
2874*2d7be507SJakub Kicinski 		ethtool_bitset_put(nlh, ETHTOOL_A_FEATURES_HW, &req->hw);
2875*2d7be507SJakub Kicinski 	if (req->_present.wanted)
2876*2d7be507SJakub Kicinski 		ethtool_bitset_put(nlh, ETHTOOL_A_FEATURES_WANTED, &req->wanted);
2877*2d7be507SJakub Kicinski 	if (req->_present.active)
2878*2d7be507SJakub Kicinski 		ethtool_bitset_put(nlh, ETHTOOL_A_FEATURES_ACTIVE, &req->active);
2879*2d7be507SJakub Kicinski 	if (req->_present.nochange)
2880*2d7be507SJakub Kicinski 		ethtool_bitset_put(nlh, ETHTOOL_A_FEATURES_NOCHANGE, &req->nochange);
2881*2d7be507SJakub Kicinski 
2882*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
2883*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
2884*2d7be507SJakub Kicinski 	yrs.cb = ethtool_features_set_rsp_parse;
2885*2d7be507SJakub Kicinski 	yrs.rsp_cmd = ETHTOOL_MSG_FEATURES_SET;
2886*2d7be507SJakub Kicinski 
2887*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
2888*2d7be507SJakub Kicinski 	if (err < 0)
2889*2d7be507SJakub Kicinski 		goto err_free;
2890*2d7be507SJakub Kicinski 
2891*2d7be507SJakub Kicinski 	return rsp;
2892*2d7be507SJakub Kicinski 
2893*2d7be507SJakub Kicinski err_free:
2894*2d7be507SJakub Kicinski 	ethtool_features_set_rsp_free(rsp);
2895*2d7be507SJakub Kicinski 	return NULL;
2896*2d7be507SJakub Kicinski }
2897*2d7be507SJakub Kicinski 
2898*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_PRIVFLAGS_GET ============== */
2899*2d7be507SJakub Kicinski /* ETHTOOL_MSG_PRIVFLAGS_GET - do */
ethtool_privflags_get_req_free(struct ethtool_privflags_get_req * req)2900*2d7be507SJakub Kicinski void ethtool_privflags_get_req_free(struct ethtool_privflags_get_req *req)
2901*2d7be507SJakub Kicinski {
2902*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
2903*2d7be507SJakub Kicinski 	free(req);
2904*2d7be507SJakub Kicinski }
2905*2d7be507SJakub Kicinski 
ethtool_privflags_get_rsp_free(struct ethtool_privflags_get_rsp * rsp)2906*2d7be507SJakub Kicinski void ethtool_privflags_get_rsp_free(struct ethtool_privflags_get_rsp *rsp)
2907*2d7be507SJakub Kicinski {
2908*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
2909*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->flags);
2910*2d7be507SJakub Kicinski 	free(rsp);
2911*2d7be507SJakub Kicinski }
2912*2d7be507SJakub Kicinski 
ethtool_privflags_get_rsp_parse(const struct nlmsghdr * nlh,void * data)2913*2d7be507SJakub Kicinski int ethtool_privflags_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
2914*2d7be507SJakub Kicinski {
2915*2d7be507SJakub Kicinski 	struct ethtool_privflags_get_rsp *dst;
2916*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
2917*2d7be507SJakub Kicinski 	const struct nlattr *attr;
2918*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
2919*2d7be507SJakub Kicinski 
2920*2d7be507SJakub Kicinski 	dst = yarg->data;
2921*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
2922*2d7be507SJakub Kicinski 
2923*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
2924*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
2925*2d7be507SJakub Kicinski 
2926*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_PRIVFLAGS_HEADER) {
2927*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2928*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2929*2d7be507SJakub Kicinski 			dst->_present.header = 1;
2930*2d7be507SJakub Kicinski 
2931*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
2932*2d7be507SJakub Kicinski 			parg.data = &dst->header;
2933*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
2934*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2935*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PRIVFLAGS_FLAGS) {
2936*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2937*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2938*2d7be507SJakub Kicinski 			dst->_present.flags = 1;
2939*2d7be507SJakub Kicinski 
2940*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
2941*2d7be507SJakub Kicinski 			parg.data = &dst->flags;
2942*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
2943*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
2944*2d7be507SJakub Kicinski 		}
2945*2d7be507SJakub Kicinski 	}
2946*2d7be507SJakub Kicinski 
2947*2d7be507SJakub Kicinski 	return MNL_CB_OK;
2948*2d7be507SJakub Kicinski }
2949*2d7be507SJakub Kicinski 
2950*2d7be507SJakub Kicinski struct ethtool_privflags_get_rsp *
ethtool_privflags_get(struct ynl_sock * ys,struct ethtool_privflags_get_req * req)2951*2d7be507SJakub Kicinski ethtool_privflags_get(struct ynl_sock *ys,
2952*2d7be507SJakub Kicinski 		      struct ethtool_privflags_get_req *req)
2953*2d7be507SJakub Kicinski {
2954*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
2955*2d7be507SJakub Kicinski 	struct ethtool_privflags_get_rsp *rsp;
2956*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
2957*2d7be507SJakub Kicinski 	int err;
2958*2d7be507SJakub Kicinski 
2959*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PRIVFLAGS_GET, 1);
2960*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_privflags_nest;
2961*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_privflags_nest;
2962*2d7be507SJakub Kicinski 
2963*2d7be507SJakub Kicinski 	if (req->_present.header)
2964*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_PRIVFLAGS_HEADER, &req->header);
2965*2d7be507SJakub Kicinski 
2966*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
2967*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
2968*2d7be507SJakub Kicinski 	yrs.cb = ethtool_privflags_get_rsp_parse;
2969*2d7be507SJakub Kicinski 	yrs.rsp_cmd = 14;
2970*2d7be507SJakub Kicinski 
2971*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
2972*2d7be507SJakub Kicinski 	if (err < 0)
2973*2d7be507SJakub Kicinski 		goto err_free;
2974*2d7be507SJakub Kicinski 
2975*2d7be507SJakub Kicinski 	return rsp;
2976*2d7be507SJakub Kicinski 
2977*2d7be507SJakub Kicinski err_free:
2978*2d7be507SJakub Kicinski 	ethtool_privflags_get_rsp_free(rsp);
2979*2d7be507SJakub Kicinski 	return NULL;
2980*2d7be507SJakub Kicinski }
2981*2d7be507SJakub Kicinski 
2982*2d7be507SJakub Kicinski /* ETHTOOL_MSG_PRIVFLAGS_GET - dump */
ethtool_privflags_get_list_free(struct ethtool_privflags_get_list * rsp)2983*2d7be507SJakub Kicinski void ethtool_privflags_get_list_free(struct ethtool_privflags_get_list *rsp)
2984*2d7be507SJakub Kicinski {
2985*2d7be507SJakub Kicinski 	struct ethtool_privflags_get_list *next = rsp;
2986*2d7be507SJakub Kicinski 
2987*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
2988*2d7be507SJakub Kicinski 		rsp = next;
2989*2d7be507SJakub Kicinski 		next = rsp->next;
2990*2d7be507SJakub Kicinski 
2991*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
2992*2d7be507SJakub Kicinski 		ethtool_bitset_free(&rsp->obj.flags);
2993*2d7be507SJakub Kicinski 		free(rsp);
2994*2d7be507SJakub Kicinski 	}
2995*2d7be507SJakub Kicinski }
2996*2d7be507SJakub Kicinski 
2997*2d7be507SJakub Kicinski struct ethtool_privflags_get_list *
ethtool_privflags_get_dump(struct ynl_sock * ys,struct ethtool_privflags_get_req_dump * req)2998*2d7be507SJakub Kicinski ethtool_privflags_get_dump(struct ynl_sock *ys,
2999*2d7be507SJakub Kicinski 			   struct ethtool_privflags_get_req_dump *req)
3000*2d7be507SJakub Kicinski {
3001*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
3002*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
3003*2d7be507SJakub Kicinski 	int err;
3004*2d7be507SJakub Kicinski 
3005*2d7be507SJakub Kicinski 	yds.ys = ys;
3006*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_privflags_get_list);
3007*2d7be507SJakub Kicinski 	yds.cb = ethtool_privflags_get_rsp_parse;
3008*2d7be507SJakub Kicinski 	yds.rsp_cmd = 14;
3009*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_privflags_nest;
3010*2d7be507SJakub Kicinski 
3011*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_PRIVFLAGS_GET, 1);
3012*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_privflags_nest;
3013*2d7be507SJakub Kicinski 
3014*2d7be507SJakub Kicinski 	if (req->_present.header)
3015*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_PRIVFLAGS_HEADER, &req->header);
3016*2d7be507SJakub Kicinski 
3017*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
3018*2d7be507SJakub Kicinski 	if (err < 0)
3019*2d7be507SJakub Kicinski 		goto free_list;
3020*2d7be507SJakub Kicinski 
3021*2d7be507SJakub Kicinski 	return yds.first;
3022*2d7be507SJakub Kicinski 
3023*2d7be507SJakub Kicinski free_list:
3024*2d7be507SJakub Kicinski 	ethtool_privflags_get_list_free(yds.first);
3025*2d7be507SJakub Kicinski 	return NULL;
3026*2d7be507SJakub Kicinski }
3027*2d7be507SJakub Kicinski 
3028*2d7be507SJakub Kicinski /* ETHTOOL_MSG_PRIVFLAGS_GET - notify */
ethtool_privflags_get_ntf_free(struct ethtool_privflags_get_ntf * rsp)3029*2d7be507SJakub Kicinski void ethtool_privflags_get_ntf_free(struct ethtool_privflags_get_ntf *rsp)
3030*2d7be507SJakub Kicinski {
3031*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->obj.header);
3032*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->obj.flags);
3033*2d7be507SJakub Kicinski 	free(rsp);
3034*2d7be507SJakub Kicinski }
3035*2d7be507SJakub Kicinski 
3036*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_PRIVFLAGS_SET ============== */
3037*2d7be507SJakub Kicinski /* ETHTOOL_MSG_PRIVFLAGS_SET - do */
ethtool_privflags_set_req_free(struct ethtool_privflags_set_req * req)3038*2d7be507SJakub Kicinski void ethtool_privflags_set_req_free(struct ethtool_privflags_set_req *req)
3039*2d7be507SJakub Kicinski {
3040*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
3041*2d7be507SJakub Kicinski 	ethtool_bitset_free(&req->flags);
3042*2d7be507SJakub Kicinski 	free(req);
3043*2d7be507SJakub Kicinski }
3044*2d7be507SJakub Kicinski 
ethtool_privflags_set(struct ynl_sock * ys,struct ethtool_privflags_set_req * req)3045*2d7be507SJakub Kicinski int ethtool_privflags_set(struct ynl_sock *ys,
3046*2d7be507SJakub Kicinski 			  struct ethtool_privflags_set_req *req)
3047*2d7be507SJakub Kicinski {
3048*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
3049*2d7be507SJakub Kicinski 	int err;
3050*2d7be507SJakub Kicinski 
3051*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PRIVFLAGS_SET, 1);
3052*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_privflags_nest;
3053*2d7be507SJakub Kicinski 
3054*2d7be507SJakub Kicinski 	if (req->_present.header)
3055*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_PRIVFLAGS_HEADER, &req->header);
3056*2d7be507SJakub Kicinski 	if (req->_present.flags)
3057*2d7be507SJakub Kicinski 		ethtool_bitset_put(nlh, ETHTOOL_A_PRIVFLAGS_FLAGS, &req->flags);
3058*2d7be507SJakub Kicinski 
3059*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, NULL);
3060*2d7be507SJakub Kicinski 	if (err < 0)
3061*2d7be507SJakub Kicinski 		return -1;
3062*2d7be507SJakub Kicinski 
3063*2d7be507SJakub Kicinski 	return 0;
3064*2d7be507SJakub Kicinski }
3065*2d7be507SJakub Kicinski 
3066*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_RINGS_GET ============== */
3067*2d7be507SJakub Kicinski /* ETHTOOL_MSG_RINGS_GET - do */
ethtool_rings_get_req_free(struct ethtool_rings_get_req * req)3068*2d7be507SJakub Kicinski void ethtool_rings_get_req_free(struct ethtool_rings_get_req *req)
3069*2d7be507SJakub Kicinski {
3070*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
3071*2d7be507SJakub Kicinski 	free(req);
3072*2d7be507SJakub Kicinski }
3073*2d7be507SJakub Kicinski 
ethtool_rings_get_rsp_free(struct ethtool_rings_get_rsp * rsp)3074*2d7be507SJakub Kicinski void ethtool_rings_get_rsp_free(struct ethtool_rings_get_rsp *rsp)
3075*2d7be507SJakub Kicinski {
3076*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
3077*2d7be507SJakub Kicinski 	free(rsp);
3078*2d7be507SJakub Kicinski }
3079*2d7be507SJakub Kicinski 
ethtool_rings_get_rsp_parse(const struct nlmsghdr * nlh,void * data)3080*2d7be507SJakub Kicinski int ethtool_rings_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
3081*2d7be507SJakub Kicinski {
3082*2d7be507SJakub Kicinski 	struct ethtool_rings_get_rsp *dst;
3083*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
3084*2d7be507SJakub Kicinski 	const struct nlattr *attr;
3085*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
3086*2d7be507SJakub Kicinski 
3087*2d7be507SJakub Kicinski 	dst = yarg->data;
3088*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
3089*2d7be507SJakub Kicinski 
3090*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
3091*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
3092*2d7be507SJakub Kicinski 
3093*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_RINGS_HEADER) {
3094*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3095*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3096*2d7be507SJakub Kicinski 			dst->_present.header = 1;
3097*2d7be507SJakub Kicinski 
3098*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
3099*2d7be507SJakub Kicinski 			parg.data = &dst->header;
3100*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
3101*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3102*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_RINGS_RX_MAX) {
3103*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3104*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3105*2d7be507SJakub Kicinski 			dst->_present.rx_max = 1;
3106*2d7be507SJakub Kicinski 			dst->rx_max = mnl_attr_get_u32(attr);
3107*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_RINGS_RX_MINI_MAX) {
3108*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3109*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3110*2d7be507SJakub Kicinski 			dst->_present.rx_mini_max = 1;
3111*2d7be507SJakub Kicinski 			dst->rx_mini_max = mnl_attr_get_u32(attr);
3112*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_RINGS_RX_JUMBO_MAX) {
3113*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3114*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3115*2d7be507SJakub Kicinski 			dst->_present.rx_jumbo_max = 1;
3116*2d7be507SJakub Kicinski 			dst->rx_jumbo_max = mnl_attr_get_u32(attr);
3117*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_RINGS_TX_MAX) {
3118*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3119*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3120*2d7be507SJakub Kicinski 			dst->_present.tx_max = 1;
3121*2d7be507SJakub Kicinski 			dst->tx_max = mnl_attr_get_u32(attr);
3122*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_RINGS_RX) {
3123*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3124*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3125*2d7be507SJakub Kicinski 			dst->_present.rx = 1;
3126*2d7be507SJakub Kicinski 			dst->rx = mnl_attr_get_u32(attr);
3127*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_RINGS_RX_MINI) {
3128*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3129*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3130*2d7be507SJakub Kicinski 			dst->_present.rx_mini = 1;
3131*2d7be507SJakub Kicinski 			dst->rx_mini = mnl_attr_get_u32(attr);
3132*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_RINGS_RX_JUMBO) {
3133*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3134*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3135*2d7be507SJakub Kicinski 			dst->_present.rx_jumbo = 1;
3136*2d7be507SJakub Kicinski 			dst->rx_jumbo = mnl_attr_get_u32(attr);
3137*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_RINGS_TX) {
3138*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3139*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3140*2d7be507SJakub Kicinski 			dst->_present.tx = 1;
3141*2d7be507SJakub Kicinski 			dst->tx = mnl_attr_get_u32(attr);
3142*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_RINGS_RX_BUF_LEN) {
3143*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3144*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3145*2d7be507SJakub Kicinski 			dst->_present.rx_buf_len = 1;
3146*2d7be507SJakub Kicinski 			dst->rx_buf_len = mnl_attr_get_u32(attr);
3147*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_RINGS_TCP_DATA_SPLIT) {
3148*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3149*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3150*2d7be507SJakub Kicinski 			dst->_present.tcp_data_split = 1;
3151*2d7be507SJakub Kicinski 			dst->tcp_data_split = mnl_attr_get_u8(attr);
3152*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_RINGS_CQE_SIZE) {
3153*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3154*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3155*2d7be507SJakub Kicinski 			dst->_present.cqe_size = 1;
3156*2d7be507SJakub Kicinski 			dst->cqe_size = mnl_attr_get_u32(attr);
3157*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_RINGS_TX_PUSH) {
3158*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3159*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3160*2d7be507SJakub Kicinski 			dst->_present.tx_push = 1;
3161*2d7be507SJakub Kicinski 			dst->tx_push = mnl_attr_get_u8(attr);
3162*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_RINGS_RX_PUSH) {
3163*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3164*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3165*2d7be507SJakub Kicinski 			dst->_present.rx_push = 1;
3166*2d7be507SJakub Kicinski 			dst->rx_push = mnl_attr_get_u8(attr);
3167*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN) {
3168*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3169*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3170*2d7be507SJakub Kicinski 			dst->_present.tx_push_buf_len = 1;
3171*2d7be507SJakub Kicinski 			dst->tx_push_buf_len = mnl_attr_get_u32(attr);
3172*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX) {
3173*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3174*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3175*2d7be507SJakub Kicinski 			dst->_present.tx_push_buf_len_max = 1;
3176*2d7be507SJakub Kicinski 			dst->tx_push_buf_len_max = mnl_attr_get_u32(attr);
3177*2d7be507SJakub Kicinski 		}
3178*2d7be507SJakub Kicinski 	}
3179*2d7be507SJakub Kicinski 
3180*2d7be507SJakub Kicinski 	return MNL_CB_OK;
3181*2d7be507SJakub Kicinski }
3182*2d7be507SJakub Kicinski 
3183*2d7be507SJakub Kicinski struct ethtool_rings_get_rsp *
ethtool_rings_get(struct ynl_sock * ys,struct ethtool_rings_get_req * req)3184*2d7be507SJakub Kicinski ethtool_rings_get(struct ynl_sock *ys, struct ethtool_rings_get_req *req)
3185*2d7be507SJakub Kicinski {
3186*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
3187*2d7be507SJakub Kicinski 	struct ethtool_rings_get_rsp *rsp;
3188*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
3189*2d7be507SJakub Kicinski 	int err;
3190*2d7be507SJakub Kicinski 
3191*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_RINGS_GET, 1);
3192*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_rings_nest;
3193*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_rings_nest;
3194*2d7be507SJakub Kicinski 
3195*2d7be507SJakub Kicinski 	if (req->_present.header)
3196*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_RINGS_HEADER, &req->header);
3197*2d7be507SJakub Kicinski 
3198*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
3199*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
3200*2d7be507SJakub Kicinski 	yrs.cb = ethtool_rings_get_rsp_parse;
3201*2d7be507SJakub Kicinski 	yrs.rsp_cmd = 16;
3202*2d7be507SJakub Kicinski 
3203*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
3204*2d7be507SJakub Kicinski 	if (err < 0)
3205*2d7be507SJakub Kicinski 		goto err_free;
3206*2d7be507SJakub Kicinski 
3207*2d7be507SJakub Kicinski 	return rsp;
3208*2d7be507SJakub Kicinski 
3209*2d7be507SJakub Kicinski err_free:
3210*2d7be507SJakub Kicinski 	ethtool_rings_get_rsp_free(rsp);
3211*2d7be507SJakub Kicinski 	return NULL;
3212*2d7be507SJakub Kicinski }
3213*2d7be507SJakub Kicinski 
3214*2d7be507SJakub Kicinski /* ETHTOOL_MSG_RINGS_GET - dump */
ethtool_rings_get_list_free(struct ethtool_rings_get_list * rsp)3215*2d7be507SJakub Kicinski void ethtool_rings_get_list_free(struct ethtool_rings_get_list *rsp)
3216*2d7be507SJakub Kicinski {
3217*2d7be507SJakub Kicinski 	struct ethtool_rings_get_list *next = rsp;
3218*2d7be507SJakub Kicinski 
3219*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
3220*2d7be507SJakub Kicinski 		rsp = next;
3221*2d7be507SJakub Kicinski 		next = rsp->next;
3222*2d7be507SJakub Kicinski 
3223*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
3224*2d7be507SJakub Kicinski 		free(rsp);
3225*2d7be507SJakub Kicinski 	}
3226*2d7be507SJakub Kicinski }
3227*2d7be507SJakub Kicinski 
3228*2d7be507SJakub Kicinski struct ethtool_rings_get_list *
ethtool_rings_get_dump(struct ynl_sock * ys,struct ethtool_rings_get_req_dump * req)3229*2d7be507SJakub Kicinski ethtool_rings_get_dump(struct ynl_sock *ys,
3230*2d7be507SJakub Kicinski 		       struct ethtool_rings_get_req_dump *req)
3231*2d7be507SJakub Kicinski {
3232*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
3233*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
3234*2d7be507SJakub Kicinski 	int err;
3235*2d7be507SJakub Kicinski 
3236*2d7be507SJakub Kicinski 	yds.ys = ys;
3237*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_rings_get_list);
3238*2d7be507SJakub Kicinski 	yds.cb = ethtool_rings_get_rsp_parse;
3239*2d7be507SJakub Kicinski 	yds.rsp_cmd = 16;
3240*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_rings_nest;
3241*2d7be507SJakub Kicinski 
3242*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_RINGS_GET, 1);
3243*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_rings_nest;
3244*2d7be507SJakub Kicinski 
3245*2d7be507SJakub Kicinski 	if (req->_present.header)
3246*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_RINGS_HEADER, &req->header);
3247*2d7be507SJakub Kicinski 
3248*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
3249*2d7be507SJakub Kicinski 	if (err < 0)
3250*2d7be507SJakub Kicinski 		goto free_list;
3251*2d7be507SJakub Kicinski 
3252*2d7be507SJakub Kicinski 	return yds.first;
3253*2d7be507SJakub Kicinski 
3254*2d7be507SJakub Kicinski free_list:
3255*2d7be507SJakub Kicinski 	ethtool_rings_get_list_free(yds.first);
3256*2d7be507SJakub Kicinski 	return NULL;
3257*2d7be507SJakub Kicinski }
3258*2d7be507SJakub Kicinski 
3259*2d7be507SJakub Kicinski /* ETHTOOL_MSG_RINGS_GET - notify */
ethtool_rings_get_ntf_free(struct ethtool_rings_get_ntf * rsp)3260*2d7be507SJakub Kicinski void ethtool_rings_get_ntf_free(struct ethtool_rings_get_ntf *rsp)
3261*2d7be507SJakub Kicinski {
3262*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->obj.header);
3263*2d7be507SJakub Kicinski 	free(rsp);
3264*2d7be507SJakub Kicinski }
3265*2d7be507SJakub Kicinski 
3266*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_RINGS_SET ============== */
3267*2d7be507SJakub Kicinski /* ETHTOOL_MSG_RINGS_SET - do */
ethtool_rings_set_req_free(struct ethtool_rings_set_req * req)3268*2d7be507SJakub Kicinski void ethtool_rings_set_req_free(struct ethtool_rings_set_req *req)
3269*2d7be507SJakub Kicinski {
3270*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
3271*2d7be507SJakub Kicinski 	free(req);
3272*2d7be507SJakub Kicinski }
3273*2d7be507SJakub Kicinski 
ethtool_rings_set(struct ynl_sock * ys,struct ethtool_rings_set_req * req)3274*2d7be507SJakub Kicinski int ethtool_rings_set(struct ynl_sock *ys, struct ethtool_rings_set_req *req)
3275*2d7be507SJakub Kicinski {
3276*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
3277*2d7be507SJakub Kicinski 	int err;
3278*2d7be507SJakub Kicinski 
3279*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_RINGS_SET, 1);
3280*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_rings_nest;
3281*2d7be507SJakub Kicinski 
3282*2d7be507SJakub Kicinski 	if (req->_present.header)
3283*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_RINGS_HEADER, &req->header);
3284*2d7be507SJakub Kicinski 	if (req->_present.rx_max)
3285*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_RX_MAX, req->rx_max);
3286*2d7be507SJakub Kicinski 	if (req->_present.rx_mini_max)
3287*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_RX_MINI_MAX, req->rx_mini_max);
3288*2d7be507SJakub Kicinski 	if (req->_present.rx_jumbo_max)
3289*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_RX_JUMBO_MAX, req->rx_jumbo_max);
3290*2d7be507SJakub Kicinski 	if (req->_present.tx_max)
3291*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_TX_MAX, req->tx_max);
3292*2d7be507SJakub Kicinski 	if (req->_present.rx)
3293*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_RX, req->rx);
3294*2d7be507SJakub Kicinski 	if (req->_present.rx_mini)
3295*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_RX_MINI, req->rx_mini);
3296*2d7be507SJakub Kicinski 	if (req->_present.rx_jumbo)
3297*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_RX_JUMBO, req->rx_jumbo);
3298*2d7be507SJakub Kicinski 	if (req->_present.tx)
3299*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_TX, req->tx);
3300*2d7be507SJakub Kicinski 	if (req->_present.rx_buf_len)
3301*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_RX_BUF_LEN, req->rx_buf_len);
3302*2d7be507SJakub Kicinski 	if (req->_present.tcp_data_split)
3303*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_RINGS_TCP_DATA_SPLIT, req->tcp_data_split);
3304*2d7be507SJakub Kicinski 	if (req->_present.cqe_size)
3305*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_CQE_SIZE, req->cqe_size);
3306*2d7be507SJakub Kicinski 	if (req->_present.tx_push)
3307*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_RINGS_TX_PUSH, req->tx_push);
3308*2d7be507SJakub Kicinski 	if (req->_present.rx_push)
3309*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_RINGS_RX_PUSH, req->rx_push);
3310*2d7be507SJakub Kicinski 	if (req->_present.tx_push_buf_len)
3311*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN, req->tx_push_buf_len);
3312*2d7be507SJakub Kicinski 	if (req->_present.tx_push_buf_len_max)
3313*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX, req->tx_push_buf_len_max);
3314*2d7be507SJakub Kicinski 
3315*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, NULL);
3316*2d7be507SJakub Kicinski 	if (err < 0)
3317*2d7be507SJakub Kicinski 		return -1;
3318*2d7be507SJakub Kicinski 
3319*2d7be507SJakub Kicinski 	return 0;
3320*2d7be507SJakub Kicinski }
3321*2d7be507SJakub Kicinski 
3322*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_CHANNELS_GET ============== */
3323*2d7be507SJakub Kicinski /* ETHTOOL_MSG_CHANNELS_GET - do */
ethtool_channels_get_req_free(struct ethtool_channels_get_req * req)3324*2d7be507SJakub Kicinski void ethtool_channels_get_req_free(struct ethtool_channels_get_req *req)
3325*2d7be507SJakub Kicinski {
3326*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
3327*2d7be507SJakub Kicinski 	free(req);
3328*2d7be507SJakub Kicinski }
3329*2d7be507SJakub Kicinski 
ethtool_channels_get_rsp_free(struct ethtool_channels_get_rsp * rsp)3330*2d7be507SJakub Kicinski void ethtool_channels_get_rsp_free(struct ethtool_channels_get_rsp *rsp)
3331*2d7be507SJakub Kicinski {
3332*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
3333*2d7be507SJakub Kicinski 	free(rsp);
3334*2d7be507SJakub Kicinski }
3335*2d7be507SJakub Kicinski 
ethtool_channels_get_rsp_parse(const struct nlmsghdr * nlh,void * data)3336*2d7be507SJakub Kicinski int ethtool_channels_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
3337*2d7be507SJakub Kicinski {
3338*2d7be507SJakub Kicinski 	struct ethtool_channels_get_rsp *dst;
3339*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
3340*2d7be507SJakub Kicinski 	const struct nlattr *attr;
3341*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
3342*2d7be507SJakub Kicinski 
3343*2d7be507SJakub Kicinski 	dst = yarg->data;
3344*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
3345*2d7be507SJakub Kicinski 
3346*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
3347*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
3348*2d7be507SJakub Kicinski 
3349*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_CHANNELS_HEADER) {
3350*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3351*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3352*2d7be507SJakub Kicinski 			dst->_present.header = 1;
3353*2d7be507SJakub Kicinski 
3354*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
3355*2d7be507SJakub Kicinski 			parg.data = &dst->header;
3356*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
3357*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3358*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_CHANNELS_RX_MAX) {
3359*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3360*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3361*2d7be507SJakub Kicinski 			dst->_present.rx_max = 1;
3362*2d7be507SJakub Kicinski 			dst->rx_max = mnl_attr_get_u32(attr);
3363*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_CHANNELS_TX_MAX) {
3364*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3365*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3366*2d7be507SJakub Kicinski 			dst->_present.tx_max = 1;
3367*2d7be507SJakub Kicinski 			dst->tx_max = mnl_attr_get_u32(attr);
3368*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_CHANNELS_OTHER_MAX) {
3369*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3370*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3371*2d7be507SJakub Kicinski 			dst->_present.other_max = 1;
3372*2d7be507SJakub Kicinski 			dst->other_max = mnl_attr_get_u32(attr);
3373*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_CHANNELS_COMBINED_MAX) {
3374*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3375*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3376*2d7be507SJakub Kicinski 			dst->_present.combined_max = 1;
3377*2d7be507SJakub Kicinski 			dst->combined_max = mnl_attr_get_u32(attr);
3378*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_CHANNELS_RX_COUNT) {
3379*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3380*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3381*2d7be507SJakub Kicinski 			dst->_present.rx_count = 1;
3382*2d7be507SJakub Kicinski 			dst->rx_count = mnl_attr_get_u32(attr);
3383*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_CHANNELS_TX_COUNT) {
3384*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3385*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3386*2d7be507SJakub Kicinski 			dst->_present.tx_count = 1;
3387*2d7be507SJakub Kicinski 			dst->tx_count = mnl_attr_get_u32(attr);
3388*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_CHANNELS_OTHER_COUNT) {
3389*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3390*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3391*2d7be507SJakub Kicinski 			dst->_present.other_count = 1;
3392*2d7be507SJakub Kicinski 			dst->other_count = mnl_attr_get_u32(attr);
3393*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_CHANNELS_COMBINED_COUNT) {
3394*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3395*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3396*2d7be507SJakub Kicinski 			dst->_present.combined_count = 1;
3397*2d7be507SJakub Kicinski 			dst->combined_count = mnl_attr_get_u32(attr);
3398*2d7be507SJakub Kicinski 		}
3399*2d7be507SJakub Kicinski 	}
3400*2d7be507SJakub Kicinski 
3401*2d7be507SJakub Kicinski 	return MNL_CB_OK;
3402*2d7be507SJakub Kicinski }
3403*2d7be507SJakub Kicinski 
3404*2d7be507SJakub Kicinski struct ethtool_channels_get_rsp *
ethtool_channels_get(struct ynl_sock * ys,struct ethtool_channels_get_req * req)3405*2d7be507SJakub Kicinski ethtool_channels_get(struct ynl_sock *ys, struct ethtool_channels_get_req *req)
3406*2d7be507SJakub Kicinski {
3407*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
3408*2d7be507SJakub Kicinski 	struct ethtool_channels_get_rsp *rsp;
3409*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
3410*2d7be507SJakub Kicinski 	int err;
3411*2d7be507SJakub Kicinski 
3412*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_CHANNELS_GET, 1);
3413*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_channels_nest;
3414*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_channels_nest;
3415*2d7be507SJakub Kicinski 
3416*2d7be507SJakub Kicinski 	if (req->_present.header)
3417*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_CHANNELS_HEADER, &req->header);
3418*2d7be507SJakub Kicinski 
3419*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
3420*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
3421*2d7be507SJakub Kicinski 	yrs.cb = ethtool_channels_get_rsp_parse;
3422*2d7be507SJakub Kicinski 	yrs.rsp_cmd = 18;
3423*2d7be507SJakub Kicinski 
3424*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
3425*2d7be507SJakub Kicinski 	if (err < 0)
3426*2d7be507SJakub Kicinski 		goto err_free;
3427*2d7be507SJakub Kicinski 
3428*2d7be507SJakub Kicinski 	return rsp;
3429*2d7be507SJakub Kicinski 
3430*2d7be507SJakub Kicinski err_free:
3431*2d7be507SJakub Kicinski 	ethtool_channels_get_rsp_free(rsp);
3432*2d7be507SJakub Kicinski 	return NULL;
3433*2d7be507SJakub Kicinski }
3434*2d7be507SJakub Kicinski 
3435*2d7be507SJakub Kicinski /* ETHTOOL_MSG_CHANNELS_GET - dump */
ethtool_channels_get_list_free(struct ethtool_channels_get_list * rsp)3436*2d7be507SJakub Kicinski void ethtool_channels_get_list_free(struct ethtool_channels_get_list *rsp)
3437*2d7be507SJakub Kicinski {
3438*2d7be507SJakub Kicinski 	struct ethtool_channels_get_list *next = rsp;
3439*2d7be507SJakub Kicinski 
3440*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
3441*2d7be507SJakub Kicinski 		rsp = next;
3442*2d7be507SJakub Kicinski 		next = rsp->next;
3443*2d7be507SJakub Kicinski 
3444*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
3445*2d7be507SJakub Kicinski 		free(rsp);
3446*2d7be507SJakub Kicinski 	}
3447*2d7be507SJakub Kicinski }
3448*2d7be507SJakub Kicinski 
3449*2d7be507SJakub Kicinski struct ethtool_channels_get_list *
ethtool_channels_get_dump(struct ynl_sock * ys,struct ethtool_channels_get_req_dump * req)3450*2d7be507SJakub Kicinski ethtool_channels_get_dump(struct ynl_sock *ys,
3451*2d7be507SJakub Kicinski 			  struct ethtool_channels_get_req_dump *req)
3452*2d7be507SJakub Kicinski {
3453*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
3454*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
3455*2d7be507SJakub Kicinski 	int err;
3456*2d7be507SJakub Kicinski 
3457*2d7be507SJakub Kicinski 	yds.ys = ys;
3458*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_channels_get_list);
3459*2d7be507SJakub Kicinski 	yds.cb = ethtool_channels_get_rsp_parse;
3460*2d7be507SJakub Kicinski 	yds.rsp_cmd = 18;
3461*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_channels_nest;
3462*2d7be507SJakub Kicinski 
3463*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_CHANNELS_GET, 1);
3464*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_channels_nest;
3465*2d7be507SJakub Kicinski 
3466*2d7be507SJakub Kicinski 	if (req->_present.header)
3467*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_CHANNELS_HEADER, &req->header);
3468*2d7be507SJakub Kicinski 
3469*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
3470*2d7be507SJakub Kicinski 	if (err < 0)
3471*2d7be507SJakub Kicinski 		goto free_list;
3472*2d7be507SJakub Kicinski 
3473*2d7be507SJakub Kicinski 	return yds.first;
3474*2d7be507SJakub Kicinski 
3475*2d7be507SJakub Kicinski free_list:
3476*2d7be507SJakub Kicinski 	ethtool_channels_get_list_free(yds.first);
3477*2d7be507SJakub Kicinski 	return NULL;
3478*2d7be507SJakub Kicinski }
3479*2d7be507SJakub Kicinski 
3480*2d7be507SJakub Kicinski /* ETHTOOL_MSG_CHANNELS_GET - notify */
ethtool_channels_get_ntf_free(struct ethtool_channels_get_ntf * rsp)3481*2d7be507SJakub Kicinski void ethtool_channels_get_ntf_free(struct ethtool_channels_get_ntf *rsp)
3482*2d7be507SJakub Kicinski {
3483*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->obj.header);
3484*2d7be507SJakub Kicinski 	free(rsp);
3485*2d7be507SJakub Kicinski }
3486*2d7be507SJakub Kicinski 
3487*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_CHANNELS_SET ============== */
3488*2d7be507SJakub Kicinski /* ETHTOOL_MSG_CHANNELS_SET - do */
ethtool_channels_set_req_free(struct ethtool_channels_set_req * req)3489*2d7be507SJakub Kicinski void ethtool_channels_set_req_free(struct ethtool_channels_set_req *req)
3490*2d7be507SJakub Kicinski {
3491*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
3492*2d7be507SJakub Kicinski 	free(req);
3493*2d7be507SJakub Kicinski }
3494*2d7be507SJakub Kicinski 
ethtool_channels_set(struct ynl_sock * ys,struct ethtool_channels_set_req * req)3495*2d7be507SJakub Kicinski int ethtool_channels_set(struct ynl_sock *ys,
3496*2d7be507SJakub Kicinski 			 struct ethtool_channels_set_req *req)
3497*2d7be507SJakub Kicinski {
3498*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
3499*2d7be507SJakub Kicinski 	int err;
3500*2d7be507SJakub Kicinski 
3501*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_CHANNELS_SET, 1);
3502*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_channels_nest;
3503*2d7be507SJakub Kicinski 
3504*2d7be507SJakub Kicinski 	if (req->_present.header)
3505*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_CHANNELS_HEADER, &req->header);
3506*2d7be507SJakub Kicinski 	if (req->_present.rx_max)
3507*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_CHANNELS_RX_MAX, req->rx_max);
3508*2d7be507SJakub Kicinski 	if (req->_present.tx_max)
3509*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_CHANNELS_TX_MAX, req->tx_max);
3510*2d7be507SJakub Kicinski 	if (req->_present.other_max)
3511*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_CHANNELS_OTHER_MAX, req->other_max);
3512*2d7be507SJakub Kicinski 	if (req->_present.combined_max)
3513*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_CHANNELS_COMBINED_MAX, req->combined_max);
3514*2d7be507SJakub Kicinski 	if (req->_present.rx_count)
3515*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_CHANNELS_RX_COUNT, req->rx_count);
3516*2d7be507SJakub Kicinski 	if (req->_present.tx_count)
3517*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_CHANNELS_TX_COUNT, req->tx_count);
3518*2d7be507SJakub Kicinski 	if (req->_present.other_count)
3519*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_CHANNELS_OTHER_COUNT, req->other_count);
3520*2d7be507SJakub Kicinski 	if (req->_present.combined_count)
3521*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_CHANNELS_COMBINED_COUNT, req->combined_count);
3522*2d7be507SJakub Kicinski 
3523*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, NULL);
3524*2d7be507SJakub Kicinski 	if (err < 0)
3525*2d7be507SJakub Kicinski 		return -1;
3526*2d7be507SJakub Kicinski 
3527*2d7be507SJakub Kicinski 	return 0;
3528*2d7be507SJakub Kicinski }
3529*2d7be507SJakub Kicinski 
3530*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_COALESCE_GET ============== */
3531*2d7be507SJakub Kicinski /* ETHTOOL_MSG_COALESCE_GET - do */
ethtool_coalesce_get_req_free(struct ethtool_coalesce_get_req * req)3532*2d7be507SJakub Kicinski void ethtool_coalesce_get_req_free(struct ethtool_coalesce_get_req *req)
3533*2d7be507SJakub Kicinski {
3534*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
3535*2d7be507SJakub Kicinski 	free(req);
3536*2d7be507SJakub Kicinski }
3537*2d7be507SJakub Kicinski 
ethtool_coalesce_get_rsp_free(struct ethtool_coalesce_get_rsp * rsp)3538*2d7be507SJakub Kicinski void ethtool_coalesce_get_rsp_free(struct ethtool_coalesce_get_rsp *rsp)
3539*2d7be507SJakub Kicinski {
3540*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
3541*2d7be507SJakub Kicinski 	free(rsp);
3542*2d7be507SJakub Kicinski }
3543*2d7be507SJakub Kicinski 
ethtool_coalesce_get_rsp_parse(const struct nlmsghdr * nlh,void * data)3544*2d7be507SJakub Kicinski int ethtool_coalesce_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
3545*2d7be507SJakub Kicinski {
3546*2d7be507SJakub Kicinski 	struct ethtool_coalesce_get_rsp *dst;
3547*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
3548*2d7be507SJakub Kicinski 	const struct nlattr *attr;
3549*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
3550*2d7be507SJakub Kicinski 
3551*2d7be507SJakub Kicinski 	dst = yarg->data;
3552*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
3553*2d7be507SJakub Kicinski 
3554*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
3555*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
3556*2d7be507SJakub Kicinski 
3557*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_COALESCE_HEADER) {
3558*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3559*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3560*2d7be507SJakub Kicinski 			dst->_present.header = 1;
3561*2d7be507SJakub Kicinski 
3562*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
3563*2d7be507SJakub Kicinski 			parg.data = &dst->header;
3564*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
3565*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3566*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_RX_USECS) {
3567*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3568*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3569*2d7be507SJakub Kicinski 			dst->_present.rx_usecs = 1;
3570*2d7be507SJakub Kicinski 			dst->rx_usecs = mnl_attr_get_u32(attr);
3571*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_RX_MAX_FRAMES) {
3572*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3573*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3574*2d7be507SJakub Kicinski 			dst->_present.rx_max_frames = 1;
3575*2d7be507SJakub Kicinski 			dst->rx_max_frames = mnl_attr_get_u32(attr);
3576*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_RX_USECS_IRQ) {
3577*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3578*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3579*2d7be507SJakub Kicinski 			dst->_present.rx_usecs_irq = 1;
3580*2d7be507SJakub Kicinski 			dst->rx_usecs_irq = mnl_attr_get_u32(attr);
3581*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ) {
3582*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3583*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3584*2d7be507SJakub Kicinski 			dst->_present.rx_max_frames_irq = 1;
3585*2d7be507SJakub Kicinski 			dst->rx_max_frames_irq = mnl_attr_get_u32(attr);
3586*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_TX_USECS) {
3587*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3588*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3589*2d7be507SJakub Kicinski 			dst->_present.tx_usecs = 1;
3590*2d7be507SJakub Kicinski 			dst->tx_usecs = mnl_attr_get_u32(attr);
3591*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_TX_MAX_FRAMES) {
3592*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3593*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3594*2d7be507SJakub Kicinski 			dst->_present.tx_max_frames = 1;
3595*2d7be507SJakub Kicinski 			dst->tx_max_frames = mnl_attr_get_u32(attr);
3596*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_TX_USECS_IRQ) {
3597*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3598*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3599*2d7be507SJakub Kicinski 			dst->_present.tx_usecs_irq = 1;
3600*2d7be507SJakub Kicinski 			dst->tx_usecs_irq = mnl_attr_get_u32(attr);
3601*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ) {
3602*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3603*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3604*2d7be507SJakub Kicinski 			dst->_present.tx_max_frames_irq = 1;
3605*2d7be507SJakub Kicinski 			dst->tx_max_frames_irq = mnl_attr_get_u32(attr);
3606*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_STATS_BLOCK_USECS) {
3607*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3608*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3609*2d7be507SJakub Kicinski 			dst->_present.stats_block_usecs = 1;
3610*2d7be507SJakub Kicinski 			dst->stats_block_usecs = mnl_attr_get_u32(attr);
3611*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX) {
3612*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3613*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3614*2d7be507SJakub Kicinski 			dst->_present.use_adaptive_rx = 1;
3615*2d7be507SJakub Kicinski 			dst->use_adaptive_rx = mnl_attr_get_u8(attr);
3616*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_USE_ADAPTIVE_TX) {
3617*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3618*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3619*2d7be507SJakub Kicinski 			dst->_present.use_adaptive_tx = 1;
3620*2d7be507SJakub Kicinski 			dst->use_adaptive_tx = mnl_attr_get_u8(attr);
3621*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_PKT_RATE_LOW) {
3622*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3623*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3624*2d7be507SJakub Kicinski 			dst->_present.pkt_rate_low = 1;
3625*2d7be507SJakub Kicinski 			dst->pkt_rate_low = mnl_attr_get_u32(attr);
3626*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_RX_USECS_LOW) {
3627*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3628*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3629*2d7be507SJakub Kicinski 			dst->_present.rx_usecs_low = 1;
3630*2d7be507SJakub Kicinski 			dst->rx_usecs_low = mnl_attr_get_u32(attr);
3631*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW) {
3632*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3633*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3634*2d7be507SJakub Kicinski 			dst->_present.rx_max_frames_low = 1;
3635*2d7be507SJakub Kicinski 			dst->rx_max_frames_low = mnl_attr_get_u32(attr);
3636*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_TX_USECS_LOW) {
3637*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3638*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3639*2d7be507SJakub Kicinski 			dst->_present.tx_usecs_low = 1;
3640*2d7be507SJakub Kicinski 			dst->tx_usecs_low = mnl_attr_get_u32(attr);
3641*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW) {
3642*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3643*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3644*2d7be507SJakub Kicinski 			dst->_present.tx_max_frames_low = 1;
3645*2d7be507SJakub Kicinski 			dst->tx_max_frames_low = mnl_attr_get_u32(attr);
3646*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_PKT_RATE_HIGH) {
3647*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3648*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3649*2d7be507SJakub Kicinski 			dst->_present.pkt_rate_high = 1;
3650*2d7be507SJakub Kicinski 			dst->pkt_rate_high = mnl_attr_get_u32(attr);
3651*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_RX_USECS_HIGH) {
3652*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3653*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3654*2d7be507SJakub Kicinski 			dst->_present.rx_usecs_high = 1;
3655*2d7be507SJakub Kicinski 			dst->rx_usecs_high = mnl_attr_get_u32(attr);
3656*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH) {
3657*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3658*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3659*2d7be507SJakub Kicinski 			dst->_present.rx_max_frames_high = 1;
3660*2d7be507SJakub Kicinski 			dst->rx_max_frames_high = mnl_attr_get_u32(attr);
3661*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_TX_USECS_HIGH) {
3662*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3663*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3664*2d7be507SJakub Kicinski 			dst->_present.tx_usecs_high = 1;
3665*2d7be507SJakub Kicinski 			dst->tx_usecs_high = mnl_attr_get_u32(attr);
3666*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH) {
3667*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3668*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3669*2d7be507SJakub Kicinski 			dst->_present.tx_max_frames_high = 1;
3670*2d7be507SJakub Kicinski 			dst->tx_max_frames_high = mnl_attr_get_u32(attr);
3671*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL) {
3672*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3673*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3674*2d7be507SJakub Kicinski 			dst->_present.rate_sample_interval = 1;
3675*2d7be507SJakub Kicinski 			dst->rate_sample_interval = mnl_attr_get_u32(attr);
3676*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_USE_CQE_MODE_TX) {
3677*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3678*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3679*2d7be507SJakub Kicinski 			dst->_present.use_cqe_mode_tx = 1;
3680*2d7be507SJakub Kicinski 			dst->use_cqe_mode_tx = mnl_attr_get_u8(attr);
3681*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_USE_CQE_MODE_RX) {
3682*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3683*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3684*2d7be507SJakub Kicinski 			dst->_present.use_cqe_mode_rx = 1;
3685*2d7be507SJakub Kicinski 			dst->use_cqe_mode_rx = mnl_attr_get_u8(attr);
3686*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES) {
3687*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3688*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3689*2d7be507SJakub Kicinski 			dst->_present.tx_aggr_max_bytes = 1;
3690*2d7be507SJakub Kicinski 			dst->tx_aggr_max_bytes = mnl_attr_get_u32(attr);
3691*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES) {
3692*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3693*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3694*2d7be507SJakub Kicinski 			dst->_present.tx_aggr_max_frames = 1;
3695*2d7be507SJakub Kicinski 			dst->tx_aggr_max_frames = mnl_attr_get_u32(attr);
3696*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS) {
3697*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3698*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3699*2d7be507SJakub Kicinski 			dst->_present.tx_aggr_time_usecs = 1;
3700*2d7be507SJakub Kicinski 			dst->tx_aggr_time_usecs = mnl_attr_get_u32(attr);
3701*2d7be507SJakub Kicinski 		}
3702*2d7be507SJakub Kicinski 	}
3703*2d7be507SJakub Kicinski 
3704*2d7be507SJakub Kicinski 	return MNL_CB_OK;
3705*2d7be507SJakub Kicinski }
3706*2d7be507SJakub Kicinski 
3707*2d7be507SJakub Kicinski struct ethtool_coalesce_get_rsp *
ethtool_coalesce_get(struct ynl_sock * ys,struct ethtool_coalesce_get_req * req)3708*2d7be507SJakub Kicinski ethtool_coalesce_get(struct ynl_sock *ys, struct ethtool_coalesce_get_req *req)
3709*2d7be507SJakub Kicinski {
3710*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
3711*2d7be507SJakub Kicinski 	struct ethtool_coalesce_get_rsp *rsp;
3712*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
3713*2d7be507SJakub Kicinski 	int err;
3714*2d7be507SJakub Kicinski 
3715*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_COALESCE_GET, 1);
3716*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_coalesce_nest;
3717*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_coalesce_nest;
3718*2d7be507SJakub Kicinski 
3719*2d7be507SJakub Kicinski 	if (req->_present.header)
3720*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_COALESCE_HEADER, &req->header);
3721*2d7be507SJakub Kicinski 
3722*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
3723*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
3724*2d7be507SJakub Kicinski 	yrs.cb = ethtool_coalesce_get_rsp_parse;
3725*2d7be507SJakub Kicinski 	yrs.rsp_cmd = 20;
3726*2d7be507SJakub Kicinski 
3727*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
3728*2d7be507SJakub Kicinski 	if (err < 0)
3729*2d7be507SJakub Kicinski 		goto err_free;
3730*2d7be507SJakub Kicinski 
3731*2d7be507SJakub Kicinski 	return rsp;
3732*2d7be507SJakub Kicinski 
3733*2d7be507SJakub Kicinski err_free:
3734*2d7be507SJakub Kicinski 	ethtool_coalesce_get_rsp_free(rsp);
3735*2d7be507SJakub Kicinski 	return NULL;
3736*2d7be507SJakub Kicinski }
3737*2d7be507SJakub Kicinski 
3738*2d7be507SJakub Kicinski /* ETHTOOL_MSG_COALESCE_GET - dump */
ethtool_coalesce_get_list_free(struct ethtool_coalesce_get_list * rsp)3739*2d7be507SJakub Kicinski void ethtool_coalesce_get_list_free(struct ethtool_coalesce_get_list *rsp)
3740*2d7be507SJakub Kicinski {
3741*2d7be507SJakub Kicinski 	struct ethtool_coalesce_get_list *next = rsp;
3742*2d7be507SJakub Kicinski 
3743*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
3744*2d7be507SJakub Kicinski 		rsp = next;
3745*2d7be507SJakub Kicinski 		next = rsp->next;
3746*2d7be507SJakub Kicinski 
3747*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
3748*2d7be507SJakub Kicinski 		free(rsp);
3749*2d7be507SJakub Kicinski 	}
3750*2d7be507SJakub Kicinski }
3751*2d7be507SJakub Kicinski 
3752*2d7be507SJakub Kicinski struct ethtool_coalesce_get_list *
ethtool_coalesce_get_dump(struct ynl_sock * ys,struct ethtool_coalesce_get_req_dump * req)3753*2d7be507SJakub Kicinski ethtool_coalesce_get_dump(struct ynl_sock *ys,
3754*2d7be507SJakub Kicinski 			  struct ethtool_coalesce_get_req_dump *req)
3755*2d7be507SJakub Kicinski {
3756*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
3757*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
3758*2d7be507SJakub Kicinski 	int err;
3759*2d7be507SJakub Kicinski 
3760*2d7be507SJakub Kicinski 	yds.ys = ys;
3761*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_coalesce_get_list);
3762*2d7be507SJakub Kicinski 	yds.cb = ethtool_coalesce_get_rsp_parse;
3763*2d7be507SJakub Kicinski 	yds.rsp_cmd = 20;
3764*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_coalesce_nest;
3765*2d7be507SJakub Kicinski 
3766*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_COALESCE_GET, 1);
3767*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_coalesce_nest;
3768*2d7be507SJakub Kicinski 
3769*2d7be507SJakub Kicinski 	if (req->_present.header)
3770*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_COALESCE_HEADER, &req->header);
3771*2d7be507SJakub Kicinski 
3772*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
3773*2d7be507SJakub Kicinski 	if (err < 0)
3774*2d7be507SJakub Kicinski 		goto free_list;
3775*2d7be507SJakub Kicinski 
3776*2d7be507SJakub Kicinski 	return yds.first;
3777*2d7be507SJakub Kicinski 
3778*2d7be507SJakub Kicinski free_list:
3779*2d7be507SJakub Kicinski 	ethtool_coalesce_get_list_free(yds.first);
3780*2d7be507SJakub Kicinski 	return NULL;
3781*2d7be507SJakub Kicinski }
3782*2d7be507SJakub Kicinski 
3783*2d7be507SJakub Kicinski /* ETHTOOL_MSG_COALESCE_GET - notify */
ethtool_coalesce_get_ntf_free(struct ethtool_coalesce_get_ntf * rsp)3784*2d7be507SJakub Kicinski void ethtool_coalesce_get_ntf_free(struct ethtool_coalesce_get_ntf *rsp)
3785*2d7be507SJakub Kicinski {
3786*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->obj.header);
3787*2d7be507SJakub Kicinski 	free(rsp);
3788*2d7be507SJakub Kicinski }
3789*2d7be507SJakub Kicinski 
3790*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_COALESCE_SET ============== */
3791*2d7be507SJakub Kicinski /* ETHTOOL_MSG_COALESCE_SET - do */
ethtool_coalesce_set_req_free(struct ethtool_coalesce_set_req * req)3792*2d7be507SJakub Kicinski void ethtool_coalesce_set_req_free(struct ethtool_coalesce_set_req *req)
3793*2d7be507SJakub Kicinski {
3794*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
3795*2d7be507SJakub Kicinski 	free(req);
3796*2d7be507SJakub Kicinski }
3797*2d7be507SJakub Kicinski 
ethtool_coalesce_set(struct ynl_sock * ys,struct ethtool_coalesce_set_req * req)3798*2d7be507SJakub Kicinski int ethtool_coalesce_set(struct ynl_sock *ys,
3799*2d7be507SJakub Kicinski 			 struct ethtool_coalesce_set_req *req)
3800*2d7be507SJakub Kicinski {
3801*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
3802*2d7be507SJakub Kicinski 	int err;
3803*2d7be507SJakub Kicinski 
3804*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_COALESCE_SET, 1);
3805*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_coalesce_nest;
3806*2d7be507SJakub Kicinski 
3807*2d7be507SJakub Kicinski 	if (req->_present.header)
3808*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_COALESCE_HEADER, &req->header);
3809*2d7be507SJakub Kicinski 	if (req->_present.rx_usecs)
3810*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_RX_USECS, req->rx_usecs);
3811*2d7be507SJakub Kicinski 	if (req->_present.rx_max_frames)
3812*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_RX_MAX_FRAMES, req->rx_max_frames);
3813*2d7be507SJakub Kicinski 	if (req->_present.rx_usecs_irq)
3814*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_RX_USECS_IRQ, req->rx_usecs_irq);
3815*2d7be507SJakub Kicinski 	if (req->_present.rx_max_frames_irq)
3816*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ, req->rx_max_frames_irq);
3817*2d7be507SJakub Kicinski 	if (req->_present.tx_usecs)
3818*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_USECS, req->tx_usecs);
3819*2d7be507SJakub Kicinski 	if (req->_present.tx_max_frames)
3820*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_MAX_FRAMES, req->tx_max_frames);
3821*2d7be507SJakub Kicinski 	if (req->_present.tx_usecs_irq)
3822*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_USECS_IRQ, req->tx_usecs_irq);
3823*2d7be507SJakub Kicinski 	if (req->_present.tx_max_frames_irq)
3824*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ, req->tx_max_frames_irq);
3825*2d7be507SJakub Kicinski 	if (req->_present.stats_block_usecs)
3826*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_STATS_BLOCK_USECS, req->stats_block_usecs);
3827*2d7be507SJakub Kicinski 	if (req->_present.use_adaptive_rx)
3828*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX, req->use_adaptive_rx);
3829*2d7be507SJakub Kicinski 	if (req->_present.use_adaptive_tx)
3830*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_COALESCE_USE_ADAPTIVE_TX, req->use_adaptive_tx);
3831*2d7be507SJakub Kicinski 	if (req->_present.pkt_rate_low)
3832*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_PKT_RATE_LOW, req->pkt_rate_low);
3833*2d7be507SJakub Kicinski 	if (req->_present.rx_usecs_low)
3834*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_RX_USECS_LOW, req->rx_usecs_low);
3835*2d7be507SJakub Kicinski 	if (req->_present.rx_max_frames_low)
3836*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW, req->rx_max_frames_low);
3837*2d7be507SJakub Kicinski 	if (req->_present.tx_usecs_low)
3838*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_USECS_LOW, req->tx_usecs_low);
3839*2d7be507SJakub Kicinski 	if (req->_present.tx_max_frames_low)
3840*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW, req->tx_max_frames_low);
3841*2d7be507SJakub Kicinski 	if (req->_present.pkt_rate_high)
3842*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_PKT_RATE_HIGH, req->pkt_rate_high);
3843*2d7be507SJakub Kicinski 	if (req->_present.rx_usecs_high)
3844*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_RX_USECS_HIGH, req->rx_usecs_high);
3845*2d7be507SJakub Kicinski 	if (req->_present.rx_max_frames_high)
3846*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH, req->rx_max_frames_high);
3847*2d7be507SJakub Kicinski 	if (req->_present.tx_usecs_high)
3848*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_USECS_HIGH, req->tx_usecs_high);
3849*2d7be507SJakub Kicinski 	if (req->_present.tx_max_frames_high)
3850*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH, req->tx_max_frames_high);
3851*2d7be507SJakub Kicinski 	if (req->_present.rate_sample_interval)
3852*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL, req->rate_sample_interval);
3853*2d7be507SJakub Kicinski 	if (req->_present.use_cqe_mode_tx)
3854*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_COALESCE_USE_CQE_MODE_TX, req->use_cqe_mode_tx);
3855*2d7be507SJakub Kicinski 	if (req->_present.use_cqe_mode_rx)
3856*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_COALESCE_USE_CQE_MODE_RX, req->use_cqe_mode_rx);
3857*2d7be507SJakub Kicinski 	if (req->_present.tx_aggr_max_bytes)
3858*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES, req->tx_aggr_max_bytes);
3859*2d7be507SJakub Kicinski 	if (req->_present.tx_aggr_max_frames)
3860*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES, req->tx_aggr_max_frames);
3861*2d7be507SJakub Kicinski 	if (req->_present.tx_aggr_time_usecs)
3862*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS, req->tx_aggr_time_usecs);
3863*2d7be507SJakub Kicinski 
3864*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, NULL);
3865*2d7be507SJakub Kicinski 	if (err < 0)
3866*2d7be507SJakub Kicinski 		return -1;
3867*2d7be507SJakub Kicinski 
3868*2d7be507SJakub Kicinski 	return 0;
3869*2d7be507SJakub Kicinski }
3870*2d7be507SJakub Kicinski 
3871*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_PAUSE_GET ============== */
3872*2d7be507SJakub Kicinski /* ETHTOOL_MSG_PAUSE_GET - do */
ethtool_pause_get_req_free(struct ethtool_pause_get_req * req)3873*2d7be507SJakub Kicinski void ethtool_pause_get_req_free(struct ethtool_pause_get_req *req)
3874*2d7be507SJakub Kicinski {
3875*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
3876*2d7be507SJakub Kicinski 	free(req);
3877*2d7be507SJakub Kicinski }
3878*2d7be507SJakub Kicinski 
ethtool_pause_get_rsp_free(struct ethtool_pause_get_rsp * rsp)3879*2d7be507SJakub Kicinski void ethtool_pause_get_rsp_free(struct ethtool_pause_get_rsp *rsp)
3880*2d7be507SJakub Kicinski {
3881*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
3882*2d7be507SJakub Kicinski 	ethtool_pause_stat_free(&rsp->stats);
3883*2d7be507SJakub Kicinski 	free(rsp);
3884*2d7be507SJakub Kicinski }
3885*2d7be507SJakub Kicinski 
ethtool_pause_get_rsp_parse(const struct nlmsghdr * nlh,void * data)3886*2d7be507SJakub Kicinski int ethtool_pause_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
3887*2d7be507SJakub Kicinski {
3888*2d7be507SJakub Kicinski 	struct ethtool_pause_get_rsp *dst;
3889*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
3890*2d7be507SJakub Kicinski 	const struct nlattr *attr;
3891*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
3892*2d7be507SJakub Kicinski 
3893*2d7be507SJakub Kicinski 	dst = yarg->data;
3894*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
3895*2d7be507SJakub Kicinski 
3896*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
3897*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
3898*2d7be507SJakub Kicinski 
3899*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_PAUSE_HEADER) {
3900*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3901*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3902*2d7be507SJakub Kicinski 			dst->_present.header = 1;
3903*2d7be507SJakub Kicinski 
3904*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
3905*2d7be507SJakub Kicinski 			parg.data = &dst->header;
3906*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
3907*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3908*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PAUSE_AUTONEG) {
3909*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3910*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3911*2d7be507SJakub Kicinski 			dst->_present.autoneg = 1;
3912*2d7be507SJakub Kicinski 			dst->autoneg = mnl_attr_get_u8(attr);
3913*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PAUSE_RX) {
3914*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3915*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3916*2d7be507SJakub Kicinski 			dst->_present.rx = 1;
3917*2d7be507SJakub Kicinski 			dst->rx = mnl_attr_get_u8(attr);
3918*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PAUSE_TX) {
3919*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3920*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3921*2d7be507SJakub Kicinski 			dst->_present.tx = 1;
3922*2d7be507SJakub Kicinski 			dst->tx = mnl_attr_get_u8(attr);
3923*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PAUSE_STATS) {
3924*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3925*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3926*2d7be507SJakub Kicinski 			dst->_present.stats = 1;
3927*2d7be507SJakub Kicinski 
3928*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_pause_stat_nest;
3929*2d7be507SJakub Kicinski 			parg.data = &dst->stats;
3930*2d7be507SJakub Kicinski 			if (ethtool_pause_stat_parse(&parg, attr))
3931*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3932*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PAUSE_STATS_SRC) {
3933*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3934*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
3935*2d7be507SJakub Kicinski 			dst->_present.stats_src = 1;
3936*2d7be507SJakub Kicinski 			dst->stats_src = mnl_attr_get_u32(attr);
3937*2d7be507SJakub Kicinski 		}
3938*2d7be507SJakub Kicinski 	}
3939*2d7be507SJakub Kicinski 
3940*2d7be507SJakub Kicinski 	return MNL_CB_OK;
3941*2d7be507SJakub Kicinski }
3942*2d7be507SJakub Kicinski 
3943*2d7be507SJakub Kicinski struct ethtool_pause_get_rsp *
ethtool_pause_get(struct ynl_sock * ys,struct ethtool_pause_get_req * req)3944*2d7be507SJakub Kicinski ethtool_pause_get(struct ynl_sock *ys, struct ethtool_pause_get_req *req)
3945*2d7be507SJakub Kicinski {
3946*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
3947*2d7be507SJakub Kicinski 	struct ethtool_pause_get_rsp *rsp;
3948*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
3949*2d7be507SJakub Kicinski 	int err;
3950*2d7be507SJakub Kicinski 
3951*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PAUSE_GET, 1);
3952*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_pause_nest;
3953*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_pause_nest;
3954*2d7be507SJakub Kicinski 
3955*2d7be507SJakub Kicinski 	if (req->_present.header)
3956*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_PAUSE_HEADER, &req->header);
3957*2d7be507SJakub Kicinski 
3958*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
3959*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
3960*2d7be507SJakub Kicinski 	yrs.cb = ethtool_pause_get_rsp_parse;
3961*2d7be507SJakub Kicinski 	yrs.rsp_cmd = 22;
3962*2d7be507SJakub Kicinski 
3963*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
3964*2d7be507SJakub Kicinski 	if (err < 0)
3965*2d7be507SJakub Kicinski 		goto err_free;
3966*2d7be507SJakub Kicinski 
3967*2d7be507SJakub Kicinski 	return rsp;
3968*2d7be507SJakub Kicinski 
3969*2d7be507SJakub Kicinski err_free:
3970*2d7be507SJakub Kicinski 	ethtool_pause_get_rsp_free(rsp);
3971*2d7be507SJakub Kicinski 	return NULL;
3972*2d7be507SJakub Kicinski }
3973*2d7be507SJakub Kicinski 
3974*2d7be507SJakub Kicinski /* ETHTOOL_MSG_PAUSE_GET - dump */
ethtool_pause_get_list_free(struct ethtool_pause_get_list * rsp)3975*2d7be507SJakub Kicinski void ethtool_pause_get_list_free(struct ethtool_pause_get_list *rsp)
3976*2d7be507SJakub Kicinski {
3977*2d7be507SJakub Kicinski 	struct ethtool_pause_get_list *next = rsp;
3978*2d7be507SJakub Kicinski 
3979*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
3980*2d7be507SJakub Kicinski 		rsp = next;
3981*2d7be507SJakub Kicinski 		next = rsp->next;
3982*2d7be507SJakub Kicinski 
3983*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
3984*2d7be507SJakub Kicinski 		ethtool_pause_stat_free(&rsp->obj.stats);
3985*2d7be507SJakub Kicinski 		free(rsp);
3986*2d7be507SJakub Kicinski 	}
3987*2d7be507SJakub Kicinski }
3988*2d7be507SJakub Kicinski 
3989*2d7be507SJakub Kicinski struct ethtool_pause_get_list *
ethtool_pause_get_dump(struct ynl_sock * ys,struct ethtool_pause_get_req_dump * req)3990*2d7be507SJakub Kicinski ethtool_pause_get_dump(struct ynl_sock *ys,
3991*2d7be507SJakub Kicinski 		       struct ethtool_pause_get_req_dump *req)
3992*2d7be507SJakub Kicinski {
3993*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
3994*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
3995*2d7be507SJakub Kicinski 	int err;
3996*2d7be507SJakub Kicinski 
3997*2d7be507SJakub Kicinski 	yds.ys = ys;
3998*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_pause_get_list);
3999*2d7be507SJakub Kicinski 	yds.cb = ethtool_pause_get_rsp_parse;
4000*2d7be507SJakub Kicinski 	yds.rsp_cmd = 22;
4001*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_pause_nest;
4002*2d7be507SJakub Kicinski 
4003*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_PAUSE_GET, 1);
4004*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_pause_nest;
4005*2d7be507SJakub Kicinski 
4006*2d7be507SJakub Kicinski 	if (req->_present.header)
4007*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_PAUSE_HEADER, &req->header);
4008*2d7be507SJakub Kicinski 
4009*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
4010*2d7be507SJakub Kicinski 	if (err < 0)
4011*2d7be507SJakub Kicinski 		goto free_list;
4012*2d7be507SJakub Kicinski 
4013*2d7be507SJakub Kicinski 	return yds.first;
4014*2d7be507SJakub Kicinski 
4015*2d7be507SJakub Kicinski free_list:
4016*2d7be507SJakub Kicinski 	ethtool_pause_get_list_free(yds.first);
4017*2d7be507SJakub Kicinski 	return NULL;
4018*2d7be507SJakub Kicinski }
4019*2d7be507SJakub Kicinski 
4020*2d7be507SJakub Kicinski /* ETHTOOL_MSG_PAUSE_GET - notify */
ethtool_pause_get_ntf_free(struct ethtool_pause_get_ntf * rsp)4021*2d7be507SJakub Kicinski void ethtool_pause_get_ntf_free(struct ethtool_pause_get_ntf *rsp)
4022*2d7be507SJakub Kicinski {
4023*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->obj.header);
4024*2d7be507SJakub Kicinski 	ethtool_pause_stat_free(&rsp->obj.stats);
4025*2d7be507SJakub Kicinski 	free(rsp);
4026*2d7be507SJakub Kicinski }
4027*2d7be507SJakub Kicinski 
4028*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_PAUSE_SET ============== */
4029*2d7be507SJakub Kicinski /* ETHTOOL_MSG_PAUSE_SET - do */
ethtool_pause_set_req_free(struct ethtool_pause_set_req * req)4030*2d7be507SJakub Kicinski void ethtool_pause_set_req_free(struct ethtool_pause_set_req *req)
4031*2d7be507SJakub Kicinski {
4032*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
4033*2d7be507SJakub Kicinski 	ethtool_pause_stat_free(&req->stats);
4034*2d7be507SJakub Kicinski 	free(req);
4035*2d7be507SJakub Kicinski }
4036*2d7be507SJakub Kicinski 
ethtool_pause_set(struct ynl_sock * ys,struct ethtool_pause_set_req * req)4037*2d7be507SJakub Kicinski int ethtool_pause_set(struct ynl_sock *ys, struct ethtool_pause_set_req *req)
4038*2d7be507SJakub Kicinski {
4039*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
4040*2d7be507SJakub Kicinski 	int err;
4041*2d7be507SJakub Kicinski 
4042*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PAUSE_SET, 1);
4043*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_pause_nest;
4044*2d7be507SJakub Kicinski 
4045*2d7be507SJakub Kicinski 	if (req->_present.header)
4046*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_PAUSE_HEADER, &req->header);
4047*2d7be507SJakub Kicinski 	if (req->_present.autoneg)
4048*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_PAUSE_AUTONEG, req->autoneg);
4049*2d7be507SJakub Kicinski 	if (req->_present.rx)
4050*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_PAUSE_RX, req->rx);
4051*2d7be507SJakub Kicinski 	if (req->_present.tx)
4052*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_PAUSE_TX, req->tx);
4053*2d7be507SJakub Kicinski 	if (req->_present.stats)
4054*2d7be507SJakub Kicinski 		ethtool_pause_stat_put(nlh, ETHTOOL_A_PAUSE_STATS, &req->stats);
4055*2d7be507SJakub Kicinski 	if (req->_present.stats_src)
4056*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_PAUSE_STATS_SRC, req->stats_src);
4057*2d7be507SJakub Kicinski 
4058*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, NULL);
4059*2d7be507SJakub Kicinski 	if (err < 0)
4060*2d7be507SJakub Kicinski 		return -1;
4061*2d7be507SJakub Kicinski 
4062*2d7be507SJakub Kicinski 	return 0;
4063*2d7be507SJakub Kicinski }
4064*2d7be507SJakub Kicinski 
4065*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_EEE_GET ============== */
4066*2d7be507SJakub Kicinski /* ETHTOOL_MSG_EEE_GET - do */
ethtool_eee_get_req_free(struct ethtool_eee_get_req * req)4067*2d7be507SJakub Kicinski void ethtool_eee_get_req_free(struct ethtool_eee_get_req *req)
4068*2d7be507SJakub Kicinski {
4069*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
4070*2d7be507SJakub Kicinski 	free(req);
4071*2d7be507SJakub Kicinski }
4072*2d7be507SJakub Kicinski 
ethtool_eee_get_rsp_free(struct ethtool_eee_get_rsp * rsp)4073*2d7be507SJakub Kicinski void ethtool_eee_get_rsp_free(struct ethtool_eee_get_rsp *rsp)
4074*2d7be507SJakub Kicinski {
4075*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
4076*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->modes_ours);
4077*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->modes_peer);
4078*2d7be507SJakub Kicinski 	free(rsp);
4079*2d7be507SJakub Kicinski }
4080*2d7be507SJakub Kicinski 
ethtool_eee_get_rsp_parse(const struct nlmsghdr * nlh,void * data)4081*2d7be507SJakub Kicinski int ethtool_eee_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
4082*2d7be507SJakub Kicinski {
4083*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
4084*2d7be507SJakub Kicinski 	struct ethtool_eee_get_rsp *dst;
4085*2d7be507SJakub Kicinski 	const struct nlattr *attr;
4086*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
4087*2d7be507SJakub Kicinski 
4088*2d7be507SJakub Kicinski 	dst = yarg->data;
4089*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
4090*2d7be507SJakub Kicinski 
4091*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
4092*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
4093*2d7be507SJakub Kicinski 
4094*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_EEE_HEADER) {
4095*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4096*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4097*2d7be507SJakub Kicinski 			dst->_present.header = 1;
4098*2d7be507SJakub Kicinski 
4099*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
4100*2d7be507SJakub Kicinski 			parg.data = &dst->header;
4101*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
4102*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4103*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_EEE_MODES_OURS) {
4104*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4105*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4106*2d7be507SJakub Kicinski 			dst->_present.modes_ours = 1;
4107*2d7be507SJakub Kicinski 
4108*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
4109*2d7be507SJakub Kicinski 			parg.data = &dst->modes_ours;
4110*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
4111*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4112*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_EEE_MODES_PEER) {
4113*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4114*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4115*2d7be507SJakub Kicinski 			dst->_present.modes_peer = 1;
4116*2d7be507SJakub Kicinski 
4117*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
4118*2d7be507SJakub Kicinski 			parg.data = &dst->modes_peer;
4119*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
4120*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4121*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_EEE_ACTIVE) {
4122*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4123*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4124*2d7be507SJakub Kicinski 			dst->_present.active = 1;
4125*2d7be507SJakub Kicinski 			dst->active = mnl_attr_get_u8(attr);
4126*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_EEE_ENABLED) {
4127*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4128*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4129*2d7be507SJakub Kicinski 			dst->_present.enabled = 1;
4130*2d7be507SJakub Kicinski 			dst->enabled = mnl_attr_get_u8(attr);
4131*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_EEE_TX_LPI_ENABLED) {
4132*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4133*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4134*2d7be507SJakub Kicinski 			dst->_present.tx_lpi_enabled = 1;
4135*2d7be507SJakub Kicinski 			dst->tx_lpi_enabled = mnl_attr_get_u8(attr);
4136*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_EEE_TX_LPI_TIMER) {
4137*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4138*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4139*2d7be507SJakub Kicinski 			dst->_present.tx_lpi_timer = 1;
4140*2d7be507SJakub Kicinski 			dst->tx_lpi_timer = mnl_attr_get_u32(attr);
4141*2d7be507SJakub Kicinski 		}
4142*2d7be507SJakub Kicinski 	}
4143*2d7be507SJakub Kicinski 
4144*2d7be507SJakub Kicinski 	return MNL_CB_OK;
4145*2d7be507SJakub Kicinski }
4146*2d7be507SJakub Kicinski 
4147*2d7be507SJakub Kicinski struct ethtool_eee_get_rsp *
ethtool_eee_get(struct ynl_sock * ys,struct ethtool_eee_get_req * req)4148*2d7be507SJakub Kicinski ethtool_eee_get(struct ynl_sock *ys, struct ethtool_eee_get_req *req)
4149*2d7be507SJakub Kicinski {
4150*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
4151*2d7be507SJakub Kicinski 	struct ethtool_eee_get_rsp *rsp;
4152*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
4153*2d7be507SJakub Kicinski 	int err;
4154*2d7be507SJakub Kicinski 
4155*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_EEE_GET, 1);
4156*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_eee_nest;
4157*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_eee_nest;
4158*2d7be507SJakub Kicinski 
4159*2d7be507SJakub Kicinski 	if (req->_present.header)
4160*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_EEE_HEADER, &req->header);
4161*2d7be507SJakub Kicinski 
4162*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
4163*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
4164*2d7be507SJakub Kicinski 	yrs.cb = ethtool_eee_get_rsp_parse;
4165*2d7be507SJakub Kicinski 	yrs.rsp_cmd = 24;
4166*2d7be507SJakub Kicinski 
4167*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
4168*2d7be507SJakub Kicinski 	if (err < 0)
4169*2d7be507SJakub Kicinski 		goto err_free;
4170*2d7be507SJakub Kicinski 
4171*2d7be507SJakub Kicinski 	return rsp;
4172*2d7be507SJakub Kicinski 
4173*2d7be507SJakub Kicinski err_free:
4174*2d7be507SJakub Kicinski 	ethtool_eee_get_rsp_free(rsp);
4175*2d7be507SJakub Kicinski 	return NULL;
4176*2d7be507SJakub Kicinski }
4177*2d7be507SJakub Kicinski 
4178*2d7be507SJakub Kicinski /* ETHTOOL_MSG_EEE_GET - dump */
ethtool_eee_get_list_free(struct ethtool_eee_get_list * rsp)4179*2d7be507SJakub Kicinski void ethtool_eee_get_list_free(struct ethtool_eee_get_list *rsp)
4180*2d7be507SJakub Kicinski {
4181*2d7be507SJakub Kicinski 	struct ethtool_eee_get_list *next = rsp;
4182*2d7be507SJakub Kicinski 
4183*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
4184*2d7be507SJakub Kicinski 		rsp = next;
4185*2d7be507SJakub Kicinski 		next = rsp->next;
4186*2d7be507SJakub Kicinski 
4187*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
4188*2d7be507SJakub Kicinski 		ethtool_bitset_free(&rsp->obj.modes_ours);
4189*2d7be507SJakub Kicinski 		ethtool_bitset_free(&rsp->obj.modes_peer);
4190*2d7be507SJakub Kicinski 		free(rsp);
4191*2d7be507SJakub Kicinski 	}
4192*2d7be507SJakub Kicinski }
4193*2d7be507SJakub Kicinski 
4194*2d7be507SJakub Kicinski struct ethtool_eee_get_list *
ethtool_eee_get_dump(struct ynl_sock * ys,struct ethtool_eee_get_req_dump * req)4195*2d7be507SJakub Kicinski ethtool_eee_get_dump(struct ynl_sock *ys, struct ethtool_eee_get_req_dump *req)
4196*2d7be507SJakub Kicinski {
4197*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
4198*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
4199*2d7be507SJakub Kicinski 	int err;
4200*2d7be507SJakub Kicinski 
4201*2d7be507SJakub Kicinski 	yds.ys = ys;
4202*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_eee_get_list);
4203*2d7be507SJakub Kicinski 	yds.cb = ethtool_eee_get_rsp_parse;
4204*2d7be507SJakub Kicinski 	yds.rsp_cmd = 24;
4205*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_eee_nest;
4206*2d7be507SJakub Kicinski 
4207*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_EEE_GET, 1);
4208*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_eee_nest;
4209*2d7be507SJakub Kicinski 
4210*2d7be507SJakub Kicinski 	if (req->_present.header)
4211*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_EEE_HEADER, &req->header);
4212*2d7be507SJakub Kicinski 
4213*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
4214*2d7be507SJakub Kicinski 	if (err < 0)
4215*2d7be507SJakub Kicinski 		goto free_list;
4216*2d7be507SJakub Kicinski 
4217*2d7be507SJakub Kicinski 	return yds.first;
4218*2d7be507SJakub Kicinski 
4219*2d7be507SJakub Kicinski free_list:
4220*2d7be507SJakub Kicinski 	ethtool_eee_get_list_free(yds.first);
4221*2d7be507SJakub Kicinski 	return NULL;
4222*2d7be507SJakub Kicinski }
4223*2d7be507SJakub Kicinski 
4224*2d7be507SJakub Kicinski /* ETHTOOL_MSG_EEE_GET - notify */
ethtool_eee_get_ntf_free(struct ethtool_eee_get_ntf * rsp)4225*2d7be507SJakub Kicinski void ethtool_eee_get_ntf_free(struct ethtool_eee_get_ntf *rsp)
4226*2d7be507SJakub Kicinski {
4227*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->obj.header);
4228*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->obj.modes_ours);
4229*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->obj.modes_peer);
4230*2d7be507SJakub Kicinski 	free(rsp);
4231*2d7be507SJakub Kicinski }
4232*2d7be507SJakub Kicinski 
4233*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_EEE_SET ============== */
4234*2d7be507SJakub Kicinski /* ETHTOOL_MSG_EEE_SET - do */
ethtool_eee_set_req_free(struct ethtool_eee_set_req * req)4235*2d7be507SJakub Kicinski void ethtool_eee_set_req_free(struct ethtool_eee_set_req *req)
4236*2d7be507SJakub Kicinski {
4237*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
4238*2d7be507SJakub Kicinski 	ethtool_bitset_free(&req->modes_ours);
4239*2d7be507SJakub Kicinski 	ethtool_bitset_free(&req->modes_peer);
4240*2d7be507SJakub Kicinski 	free(req);
4241*2d7be507SJakub Kicinski }
4242*2d7be507SJakub Kicinski 
ethtool_eee_set(struct ynl_sock * ys,struct ethtool_eee_set_req * req)4243*2d7be507SJakub Kicinski int ethtool_eee_set(struct ynl_sock *ys, struct ethtool_eee_set_req *req)
4244*2d7be507SJakub Kicinski {
4245*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
4246*2d7be507SJakub Kicinski 	int err;
4247*2d7be507SJakub Kicinski 
4248*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_EEE_SET, 1);
4249*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_eee_nest;
4250*2d7be507SJakub Kicinski 
4251*2d7be507SJakub Kicinski 	if (req->_present.header)
4252*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_EEE_HEADER, &req->header);
4253*2d7be507SJakub Kicinski 	if (req->_present.modes_ours)
4254*2d7be507SJakub Kicinski 		ethtool_bitset_put(nlh, ETHTOOL_A_EEE_MODES_OURS, &req->modes_ours);
4255*2d7be507SJakub Kicinski 	if (req->_present.modes_peer)
4256*2d7be507SJakub Kicinski 		ethtool_bitset_put(nlh, ETHTOOL_A_EEE_MODES_PEER, &req->modes_peer);
4257*2d7be507SJakub Kicinski 	if (req->_present.active)
4258*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_EEE_ACTIVE, req->active);
4259*2d7be507SJakub Kicinski 	if (req->_present.enabled)
4260*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_EEE_ENABLED, req->enabled);
4261*2d7be507SJakub Kicinski 	if (req->_present.tx_lpi_enabled)
4262*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_EEE_TX_LPI_ENABLED, req->tx_lpi_enabled);
4263*2d7be507SJakub Kicinski 	if (req->_present.tx_lpi_timer)
4264*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_EEE_TX_LPI_TIMER, req->tx_lpi_timer);
4265*2d7be507SJakub Kicinski 
4266*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, NULL);
4267*2d7be507SJakub Kicinski 	if (err < 0)
4268*2d7be507SJakub Kicinski 		return -1;
4269*2d7be507SJakub Kicinski 
4270*2d7be507SJakub Kicinski 	return 0;
4271*2d7be507SJakub Kicinski }
4272*2d7be507SJakub Kicinski 
4273*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_TSINFO_GET ============== */
4274*2d7be507SJakub Kicinski /* ETHTOOL_MSG_TSINFO_GET - do */
ethtool_tsinfo_get_req_free(struct ethtool_tsinfo_get_req * req)4275*2d7be507SJakub Kicinski void ethtool_tsinfo_get_req_free(struct ethtool_tsinfo_get_req *req)
4276*2d7be507SJakub Kicinski {
4277*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
4278*2d7be507SJakub Kicinski 	free(req);
4279*2d7be507SJakub Kicinski }
4280*2d7be507SJakub Kicinski 
ethtool_tsinfo_get_rsp_free(struct ethtool_tsinfo_get_rsp * rsp)4281*2d7be507SJakub Kicinski void ethtool_tsinfo_get_rsp_free(struct ethtool_tsinfo_get_rsp *rsp)
4282*2d7be507SJakub Kicinski {
4283*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
4284*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->timestamping);
4285*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->tx_types);
4286*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->rx_filters);
4287*2d7be507SJakub Kicinski 	free(rsp);
4288*2d7be507SJakub Kicinski }
4289*2d7be507SJakub Kicinski 
ethtool_tsinfo_get_rsp_parse(const struct nlmsghdr * nlh,void * data)4290*2d7be507SJakub Kicinski int ethtool_tsinfo_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
4291*2d7be507SJakub Kicinski {
4292*2d7be507SJakub Kicinski 	struct ethtool_tsinfo_get_rsp *dst;
4293*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
4294*2d7be507SJakub Kicinski 	const struct nlattr *attr;
4295*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
4296*2d7be507SJakub Kicinski 
4297*2d7be507SJakub Kicinski 	dst = yarg->data;
4298*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
4299*2d7be507SJakub Kicinski 
4300*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
4301*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
4302*2d7be507SJakub Kicinski 
4303*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_TSINFO_HEADER) {
4304*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4305*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4306*2d7be507SJakub Kicinski 			dst->_present.header = 1;
4307*2d7be507SJakub Kicinski 
4308*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
4309*2d7be507SJakub Kicinski 			parg.data = &dst->header;
4310*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
4311*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4312*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_TSINFO_TIMESTAMPING) {
4313*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4314*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4315*2d7be507SJakub Kicinski 			dst->_present.timestamping = 1;
4316*2d7be507SJakub Kicinski 
4317*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
4318*2d7be507SJakub Kicinski 			parg.data = &dst->timestamping;
4319*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
4320*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4321*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_TSINFO_TX_TYPES) {
4322*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4323*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4324*2d7be507SJakub Kicinski 			dst->_present.tx_types = 1;
4325*2d7be507SJakub Kicinski 
4326*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
4327*2d7be507SJakub Kicinski 			parg.data = &dst->tx_types;
4328*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
4329*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4330*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_TSINFO_RX_FILTERS) {
4331*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4332*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4333*2d7be507SJakub Kicinski 			dst->_present.rx_filters = 1;
4334*2d7be507SJakub Kicinski 
4335*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
4336*2d7be507SJakub Kicinski 			parg.data = &dst->rx_filters;
4337*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
4338*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4339*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_TSINFO_PHC_INDEX) {
4340*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4341*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4342*2d7be507SJakub Kicinski 			dst->_present.phc_index = 1;
4343*2d7be507SJakub Kicinski 			dst->phc_index = mnl_attr_get_u32(attr);
4344*2d7be507SJakub Kicinski 		}
4345*2d7be507SJakub Kicinski 	}
4346*2d7be507SJakub Kicinski 
4347*2d7be507SJakub Kicinski 	return MNL_CB_OK;
4348*2d7be507SJakub Kicinski }
4349*2d7be507SJakub Kicinski 
4350*2d7be507SJakub Kicinski struct ethtool_tsinfo_get_rsp *
ethtool_tsinfo_get(struct ynl_sock * ys,struct ethtool_tsinfo_get_req * req)4351*2d7be507SJakub Kicinski ethtool_tsinfo_get(struct ynl_sock *ys, struct ethtool_tsinfo_get_req *req)
4352*2d7be507SJakub Kicinski {
4353*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
4354*2d7be507SJakub Kicinski 	struct ethtool_tsinfo_get_rsp *rsp;
4355*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
4356*2d7be507SJakub Kicinski 	int err;
4357*2d7be507SJakub Kicinski 
4358*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_TSINFO_GET, 1);
4359*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_tsinfo_nest;
4360*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_tsinfo_nest;
4361*2d7be507SJakub Kicinski 
4362*2d7be507SJakub Kicinski 	if (req->_present.header)
4363*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_TSINFO_HEADER, &req->header);
4364*2d7be507SJakub Kicinski 
4365*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
4366*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
4367*2d7be507SJakub Kicinski 	yrs.cb = ethtool_tsinfo_get_rsp_parse;
4368*2d7be507SJakub Kicinski 	yrs.rsp_cmd = 26;
4369*2d7be507SJakub Kicinski 
4370*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
4371*2d7be507SJakub Kicinski 	if (err < 0)
4372*2d7be507SJakub Kicinski 		goto err_free;
4373*2d7be507SJakub Kicinski 
4374*2d7be507SJakub Kicinski 	return rsp;
4375*2d7be507SJakub Kicinski 
4376*2d7be507SJakub Kicinski err_free:
4377*2d7be507SJakub Kicinski 	ethtool_tsinfo_get_rsp_free(rsp);
4378*2d7be507SJakub Kicinski 	return NULL;
4379*2d7be507SJakub Kicinski }
4380*2d7be507SJakub Kicinski 
4381*2d7be507SJakub Kicinski /* ETHTOOL_MSG_TSINFO_GET - dump */
ethtool_tsinfo_get_list_free(struct ethtool_tsinfo_get_list * rsp)4382*2d7be507SJakub Kicinski void ethtool_tsinfo_get_list_free(struct ethtool_tsinfo_get_list *rsp)
4383*2d7be507SJakub Kicinski {
4384*2d7be507SJakub Kicinski 	struct ethtool_tsinfo_get_list *next = rsp;
4385*2d7be507SJakub Kicinski 
4386*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
4387*2d7be507SJakub Kicinski 		rsp = next;
4388*2d7be507SJakub Kicinski 		next = rsp->next;
4389*2d7be507SJakub Kicinski 
4390*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
4391*2d7be507SJakub Kicinski 		ethtool_bitset_free(&rsp->obj.timestamping);
4392*2d7be507SJakub Kicinski 		ethtool_bitset_free(&rsp->obj.tx_types);
4393*2d7be507SJakub Kicinski 		ethtool_bitset_free(&rsp->obj.rx_filters);
4394*2d7be507SJakub Kicinski 		free(rsp);
4395*2d7be507SJakub Kicinski 	}
4396*2d7be507SJakub Kicinski }
4397*2d7be507SJakub Kicinski 
4398*2d7be507SJakub Kicinski struct ethtool_tsinfo_get_list *
ethtool_tsinfo_get_dump(struct ynl_sock * ys,struct ethtool_tsinfo_get_req_dump * req)4399*2d7be507SJakub Kicinski ethtool_tsinfo_get_dump(struct ynl_sock *ys,
4400*2d7be507SJakub Kicinski 			struct ethtool_tsinfo_get_req_dump *req)
4401*2d7be507SJakub Kicinski {
4402*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
4403*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
4404*2d7be507SJakub Kicinski 	int err;
4405*2d7be507SJakub Kicinski 
4406*2d7be507SJakub Kicinski 	yds.ys = ys;
4407*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_tsinfo_get_list);
4408*2d7be507SJakub Kicinski 	yds.cb = ethtool_tsinfo_get_rsp_parse;
4409*2d7be507SJakub Kicinski 	yds.rsp_cmd = 26;
4410*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_tsinfo_nest;
4411*2d7be507SJakub Kicinski 
4412*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_TSINFO_GET, 1);
4413*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_tsinfo_nest;
4414*2d7be507SJakub Kicinski 
4415*2d7be507SJakub Kicinski 	if (req->_present.header)
4416*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_TSINFO_HEADER, &req->header);
4417*2d7be507SJakub Kicinski 
4418*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
4419*2d7be507SJakub Kicinski 	if (err < 0)
4420*2d7be507SJakub Kicinski 		goto free_list;
4421*2d7be507SJakub Kicinski 
4422*2d7be507SJakub Kicinski 	return yds.first;
4423*2d7be507SJakub Kicinski 
4424*2d7be507SJakub Kicinski free_list:
4425*2d7be507SJakub Kicinski 	ethtool_tsinfo_get_list_free(yds.first);
4426*2d7be507SJakub Kicinski 	return NULL;
4427*2d7be507SJakub Kicinski }
4428*2d7be507SJakub Kicinski 
4429*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_CABLE_TEST_ACT ============== */
4430*2d7be507SJakub Kicinski /* ETHTOOL_MSG_CABLE_TEST_ACT - do */
ethtool_cable_test_act_req_free(struct ethtool_cable_test_act_req * req)4431*2d7be507SJakub Kicinski void ethtool_cable_test_act_req_free(struct ethtool_cable_test_act_req *req)
4432*2d7be507SJakub Kicinski {
4433*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
4434*2d7be507SJakub Kicinski 	free(req);
4435*2d7be507SJakub Kicinski }
4436*2d7be507SJakub Kicinski 
ethtool_cable_test_act(struct ynl_sock * ys,struct ethtool_cable_test_act_req * req)4437*2d7be507SJakub Kicinski int ethtool_cable_test_act(struct ynl_sock *ys,
4438*2d7be507SJakub Kicinski 			   struct ethtool_cable_test_act_req *req)
4439*2d7be507SJakub Kicinski {
4440*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
4441*2d7be507SJakub Kicinski 	int err;
4442*2d7be507SJakub Kicinski 
4443*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_CABLE_TEST_ACT, 1);
4444*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_cable_test_nest;
4445*2d7be507SJakub Kicinski 
4446*2d7be507SJakub Kicinski 	if (req->_present.header)
4447*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_CABLE_TEST_HEADER, &req->header);
4448*2d7be507SJakub Kicinski 
4449*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, NULL);
4450*2d7be507SJakub Kicinski 	if (err < 0)
4451*2d7be507SJakub Kicinski 		return -1;
4452*2d7be507SJakub Kicinski 
4453*2d7be507SJakub Kicinski 	return 0;
4454*2d7be507SJakub Kicinski }
4455*2d7be507SJakub Kicinski 
4456*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_CABLE_TEST_TDR_ACT ============== */
4457*2d7be507SJakub Kicinski /* ETHTOOL_MSG_CABLE_TEST_TDR_ACT - do */
4458*2d7be507SJakub Kicinski void
ethtool_cable_test_tdr_act_req_free(struct ethtool_cable_test_tdr_act_req * req)4459*2d7be507SJakub Kicinski ethtool_cable_test_tdr_act_req_free(struct ethtool_cable_test_tdr_act_req *req)
4460*2d7be507SJakub Kicinski {
4461*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
4462*2d7be507SJakub Kicinski 	free(req);
4463*2d7be507SJakub Kicinski }
4464*2d7be507SJakub Kicinski 
ethtool_cable_test_tdr_act(struct ynl_sock * ys,struct ethtool_cable_test_tdr_act_req * req)4465*2d7be507SJakub Kicinski int ethtool_cable_test_tdr_act(struct ynl_sock *ys,
4466*2d7be507SJakub Kicinski 			       struct ethtool_cable_test_tdr_act_req *req)
4467*2d7be507SJakub Kicinski {
4468*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
4469*2d7be507SJakub Kicinski 	int err;
4470*2d7be507SJakub Kicinski 
4471*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_CABLE_TEST_TDR_ACT, 1);
4472*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_cable_test_tdr_nest;
4473*2d7be507SJakub Kicinski 
4474*2d7be507SJakub Kicinski 	if (req->_present.header)
4475*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_CABLE_TEST_TDR_HEADER, &req->header);
4476*2d7be507SJakub Kicinski 
4477*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, NULL);
4478*2d7be507SJakub Kicinski 	if (err < 0)
4479*2d7be507SJakub Kicinski 		return -1;
4480*2d7be507SJakub Kicinski 
4481*2d7be507SJakub Kicinski 	return 0;
4482*2d7be507SJakub Kicinski }
4483*2d7be507SJakub Kicinski 
4484*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_TUNNEL_INFO_GET ============== */
4485*2d7be507SJakub Kicinski /* ETHTOOL_MSG_TUNNEL_INFO_GET - do */
ethtool_tunnel_info_get_req_free(struct ethtool_tunnel_info_get_req * req)4486*2d7be507SJakub Kicinski void ethtool_tunnel_info_get_req_free(struct ethtool_tunnel_info_get_req *req)
4487*2d7be507SJakub Kicinski {
4488*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
4489*2d7be507SJakub Kicinski 	free(req);
4490*2d7be507SJakub Kicinski }
4491*2d7be507SJakub Kicinski 
ethtool_tunnel_info_get_rsp_free(struct ethtool_tunnel_info_get_rsp * rsp)4492*2d7be507SJakub Kicinski void ethtool_tunnel_info_get_rsp_free(struct ethtool_tunnel_info_get_rsp *rsp)
4493*2d7be507SJakub Kicinski {
4494*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
4495*2d7be507SJakub Kicinski 	ethtool_tunnel_udp_free(&rsp->udp_ports);
4496*2d7be507SJakub Kicinski 	free(rsp);
4497*2d7be507SJakub Kicinski }
4498*2d7be507SJakub Kicinski 
ethtool_tunnel_info_get_rsp_parse(const struct nlmsghdr * nlh,void * data)4499*2d7be507SJakub Kicinski int ethtool_tunnel_info_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
4500*2d7be507SJakub Kicinski {
4501*2d7be507SJakub Kicinski 	struct ethtool_tunnel_info_get_rsp *dst;
4502*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
4503*2d7be507SJakub Kicinski 	const struct nlattr *attr;
4504*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
4505*2d7be507SJakub Kicinski 
4506*2d7be507SJakub Kicinski 	dst = yarg->data;
4507*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
4508*2d7be507SJakub Kicinski 
4509*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
4510*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
4511*2d7be507SJakub Kicinski 
4512*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_TUNNEL_INFO_HEADER) {
4513*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4514*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4515*2d7be507SJakub Kicinski 			dst->_present.header = 1;
4516*2d7be507SJakub Kicinski 
4517*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
4518*2d7be507SJakub Kicinski 			parg.data = &dst->header;
4519*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
4520*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4521*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_TUNNEL_INFO_UDP_PORTS) {
4522*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4523*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4524*2d7be507SJakub Kicinski 			dst->_present.udp_ports = 1;
4525*2d7be507SJakub Kicinski 
4526*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_tunnel_udp_nest;
4527*2d7be507SJakub Kicinski 			parg.data = &dst->udp_ports;
4528*2d7be507SJakub Kicinski 			if (ethtool_tunnel_udp_parse(&parg, attr))
4529*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4530*2d7be507SJakub Kicinski 		}
4531*2d7be507SJakub Kicinski 	}
4532*2d7be507SJakub Kicinski 
4533*2d7be507SJakub Kicinski 	return MNL_CB_OK;
4534*2d7be507SJakub Kicinski }
4535*2d7be507SJakub Kicinski 
4536*2d7be507SJakub Kicinski struct ethtool_tunnel_info_get_rsp *
ethtool_tunnel_info_get(struct ynl_sock * ys,struct ethtool_tunnel_info_get_req * req)4537*2d7be507SJakub Kicinski ethtool_tunnel_info_get(struct ynl_sock *ys,
4538*2d7be507SJakub Kicinski 			struct ethtool_tunnel_info_get_req *req)
4539*2d7be507SJakub Kicinski {
4540*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
4541*2d7be507SJakub Kicinski 	struct ethtool_tunnel_info_get_rsp *rsp;
4542*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
4543*2d7be507SJakub Kicinski 	int err;
4544*2d7be507SJakub Kicinski 
4545*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_TUNNEL_INFO_GET, 1);
4546*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_tunnel_info_nest;
4547*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_tunnel_info_nest;
4548*2d7be507SJakub Kicinski 
4549*2d7be507SJakub Kicinski 	if (req->_present.header)
4550*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_TUNNEL_INFO_HEADER, &req->header);
4551*2d7be507SJakub Kicinski 
4552*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
4553*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
4554*2d7be507SJakub Kicinski 	yrs.cb = ethtool_tunnel_info_get_rsp_parse;
4555*2d7be507SJakub Kicinski 	yrs.rsp_cmd = 29;
4556*2d7be507SJakub Kicinski 
4557*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
4558*2d7be507SJakub Kicinski 	if (err < 0)
4559*2d7be507SJakub Kicinski 		goto err_free;
4560*2d7be507SJakub Kicinski 
4561*2d7be507SJakub Kicinski 	return rsp;
4562*2d7be507SJakub Kicinski 
4563*2d7be507SJakub Kicinski err_free:
4564*2d7be507SJakub Kicinski 	ethtool_tunnel_info_get_rsp_free(rsp);
4565*2d7be507SJakub Kicinski 	return NULL;
4566*2d7be507SJakub Kicinski }
4567*2d7be507SJakub Kicinski 
4568*2d7be507SJakub Kicinski /* ETHTOOL_MSG_TUNNEL_INFO_GET - dump */
4569*2d7be507SJakub Kicinski void
ethtool_tunnel_info_get_list_free(struct ethtool_tunnel_info_get_list * rsp)4570*2d7be507SJakub Kicinski ethtool_tunnel_info_get_list_free(struct ethtool_tunnel_info_get_list *rsp)
4571*2d7be507SJakub Kicinski {
4572*2d7be507SJakub Kicinski 	struct ethtool_tunnel_info_get_list *next = rsp;
4573*2d7be507SJakub Kicinski 
4574*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
4575*2d7be507SJakub Kicinski 		rsp = next;
4576*2d7be507SJakub Kicinski 		next = rsp->next;
4577*2d7be507SJakub Kicinski 
4578*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
4579*2d7be507SJakub Kicinski 		ethtool_tunnel_udp_free(&rsp->obj.udp_ports);
4580*2d7be507SJakub Kicinski 		free(rsp);
4581*2d7be507SJakub Kicinski 	}
4582*2d7be507SJakub Kicinski }
4583*2d7be507SJakub Kicinski 
4584*2d7be507SJakub Kicinski struct ethtool_tunnel_info_get_list *
ethtool_tunnel_info_get_dump(struct ynl_sock * ys,struct ethtool_tunnel_info_get_req_dump * req)4585*2d7be507SJakub Kicinski ethtool_tunnel_info_get_dump(struct ynl_sock *ys,
4586*2d7be507SJakub Kicinski 			     struct ethtool_tunnel_info_get_req_dump *req)
4587*2d7be507SJakub Kicinski {
4588*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
4589*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
4590*2d7be507SJakub Kicinski 	int err;
4591*2d7be507SJakub Kicinski 
4592*2d7be507SJakub Kicinski 	yds.ys = ys;
4593*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_tunnel_info_get_list);
4594*2d7be507SJakub Kicinski 	yds.cb = ethtool_tunnel_info_get_rsp_parse;
4595*2d7be507SJakub Kicinski 	yds.rsp_cmd = 29;
4596*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_tunnel_info_nest;
4597*2d7be507SJakub Kicinski 
4598*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_TUNNEL_INFO_GET, 1);
4599*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_tunnel_info_nest;
4600*2d7be507SJakub Kicinski 
4601*2d7be507SJakub Kicinski 	if (req->_present.header)
4602*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_TUNNEL_INFO_HEADER, &req->header);
4603*2d7be507SJakub Kicinski 
4604*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
4605*2d7be507SJakub Kicinski 	if (err < 0)
4606*2d7be507SJakub Kicinski 		goto free_list;
4607*2d7be507SJakub Kicinski 
4608*2d7be507SJakub Kicinski 	return yds.first;
4609*2d7be507SJakub Kicinski 
4610*2d7be507SJakub Kicinski free_list:
4611*2d7be507SJakub Kicinski 	ethtool_tunnel_info_get_list_free(yds.first);
4612*2d7be507SJakub Kicinski 	return NULL;
4613*2d7be507SJakub Kicinski }
4614*2d7be507SJakub Kicinski 
4615*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_FEC_GET ============== */
4616*2d7be507SJakub Kicinski /* ETHTOOL_MSG_FEC_GET - do */
ethtool_fec_get_req_free(struct ethtool_fec_get_req * req)4617*2d7be507SJakub Kicinski void ethtool_fec_get_req_free(struct ethtool_fec_get_req *req)
4618*2d7be507SJakub Kicinski {
4619*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
4620*2d7be507SJakub Kicinski 	free(req);
4621*2d7be507SJakub Kicinski }
4622*2d7be507SJakub Kicinski 
ethtool_fec_get_rsp_free(struct ethtool_fec_get_rsp * rsp)4623*2d7be507SJakub Kicinski void ethtool_fec_get_rsp_free(struct ethtool_fec_get_rsp *rsp)
4624*2d7be507SJakub Kicinski {
4625*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
4626*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->modes);
4627*2d7be507SJakub Kicinski 	ethtool_fec_stat_free(&rsp->stats);
4628*2d7be507SJakub Kicinski 	free(rsp);
4629*2d7be507SJakub Kicinski }
4630*2d7be507SJakub Kicinski 
ethtool_fec_get_rsp_parse(const struct nlmsghdr * nlh,void * data)4631*2d7be507SJakub Kicinski int ethtool_fec_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
4632*2d7be507SJakub Kicinski {
4633*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
4634*2d7be507SJakub Kicinski 	struct ethtool_fec_get_rsp *dst;
4635*2d7be507SJakub Kicinski 	const struct nlattr *attr;
4636*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
4637*2d7be507SJakub Kicinski 
4638*2d7be507SJakub Kicinski 	dst = yarg->data;
4639*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
4640*2d7be507SJakub Kicinski 
4641*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
4642*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
4643*2d7be507SJakub Kicinski 
4644*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_FEC_HEADER) {
4645*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4646*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4647*2d7be507SJakub Kicinski 			dst->_present.header = 1;
4648*2d7be507SJakub Kicinski 
4649*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
4650*2d7be507SJakub Kicinski 			parg.data = &dst->header;
4651*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
4652*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4653*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_FEC_MODES) {
4654*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4655*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4656*2d7be507SJakub Kicinski 			dst->_present.modes = 1;
4657*2d7be507SJakub Kicinski 
4658*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_bitset_nest;
4659*2d7be507SJakub Kicinski 			parg.data = &dst->modes;
4660*2d7be507SJakub Kicinski 			if (ethtool_bitset_parse(&parg, attr))
4661*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4662*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_FEC_AUTO) {
4663*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4664*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4665*2d7be507SJakub Kicinski 			dst->_present.auto_ = 1;
4666*2d7be507SJakub Kicinski 			dst->auto_ = mnl_attr_get_u8(attr);
4667*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_FEC_ACTIVE) {
4668*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4669*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4670*2d7be507SJakub Kicinski 			dst->_present.active = 1;
4671*2d7be507SJakub Kicinski 			dst->active = mnl_attr_get_u32(attr);
4672*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_FEC_STATS) {
4673*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4674*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4675*2d7be507SJakub Kicinski 			dst->_present.stats = 1;
4676*2d7be507SJakub Kicinski 
4677*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_fec_stat_nest;
4678*2d7be507SJakub Kicinski 			parg.data = &dst->stats;
4679*2d7be507SJakub Kicinski 			if (ethtool_fec_stat_parse(&parg, attr))
4680*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4681*2d7be507SJakub Kicinski 		}
4682*2d7be507SJakub Kicinski 	}
4683*2d7be507SJakub Kicinski 
4684*2d7be507SJakub Kicinski 	return MNL_CB_OK;
4685*2d7be507SJakub Kicinski }
4686*2d7be507SJakub Kicinski 
4687*2d7be507SJakub Kicinski struct ethtool_fec_get_rsp *
ethtool_fec_get(struct ynl_sock * ys,struct ethtool_fec_get_req * req)4688*2d7be507SJakub Kicinski ethtool_fec_get(struct ynl_sock *ys, struct ethtool_fec_get_req *req)
4689*2d7be507SJakub Kicinski {
4690*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
4691*2d7be507SJakub Kicinski 	struct ethtool_fec_get_rsp *rsp;
4692*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
4693*2d7be507SJakub Kicinski 	int err;
4694*2d7be507SJakub Kicinski 
4695*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_FEC_GET, 1);
4696*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_fec_nest;
4697*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_fec_nest;
4698*2d7be507SJakub Kicinski 
4699*2d7be507SJakub Kicinski 	if (req->_present.header)
4700*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_FEC_HEADER, &req->header);
4701*2d7be507SJakub Kicinski 
4702*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
4703*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
4704*2d7be507SJakub Kicinski 	yrs.cb = ethtool_fec_get_rsp_parse;
4705*2d7be507SJakub Kicinski 	yrs.rsp_cmd = 30;
4706*2d7be507SJakub Kicinski 
4707*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
4708*2d7be507SJakub Kicinski 	if (err < 0)
4709*2d7be507SJakub Kicinski 		goto err_free;
4710*2d7be507SJakub Kicinski 
4711*2d7be507SJakub Kicinski 	return rsp;
4712*2d7be507SJakub Kicinski 
4713*2d7be507SJakub Kicinski err_free:
4714*2d7be507SJakub Kicinski 	ethtool_fec_get_rsp_free(rsp);
4715*2d7be507SJakub Kicinski 	return NULL;
4716*2d7be507SJakub Kicinski }
4717*2d7be507SJakub Kicinski 
4718*2d7be507SJakub Kicinski /* ETHTOOL_MSG_FEC_GET - dump */
ethtool_fec_get_list_free(struct ethtool_fec_get_list * rsp)4719*2d7be507SJakub Kicinski void ethtool_fec_get_list_free(struct ethtool_fec_get_list *rsp)
4720*2d7be507SJakub Kicinski {
4721*2d7be507SJakub Kicinski 	struct ethtool_fec_get_list *next = rsp;
4722*2d7be507SJakub Kicinski 
4723*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
4724*2d7be507SJakub Kicinski 		rsp = next;
4725*2d7be507SJakub Kicinski 		next = rsp->next;
4726*2d7be507SJakub Kicinski 
4727*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
4728*2d7be507SJakub Kicinski 		ethtool_bitset_free(&rsp->obj.modes);
4729*2d7be507SJakub Kicinski 		ethtool_fec_stat_free(&rsp->obj.stats);
4730*2d7be507SJakub Kicinski 		free(rsp);
4731*2d7be507SJakub Kicinski 	}
4732*2d7be507SJakub Kicinski }
4733*2d7be507SJakub Kicinski 
4734*2d7be507SJakub Kicinski struct ethtool_fec_get_list *
ethtool_fec_get_dump(struct ynl_sock * ys,struct ethtool_fec_get_req_dump * req)4735*2d7be507SJakub Kicinski ethtool_fec_get_dump(struct ynl_sock *ys, struct ethtool_fec_get_req_dump *req)
4736*2d7be507SJakub Kicinski {
4737*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
4738*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
4739*2d7be507SJakub Kicinski 	int err;
4740*2d7be507SJakub Kicinski 
4741*2d7be507SJakub Kicinski 	yds.ys = ys;
4742*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_fec_get_list);
4743*2d7be507SJakub Kicinski 	yds.cb = ethtool_fec_get_rsp_parse;
4744*2d7be507SJakub Kicinski 	yds.rsp_cmd = 30;
4745*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_fec_nest;
4746*2d7be507SJakub Kicinski 
4747*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_FEC_GET, 1);
4748*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_fec_nest;
4749*2d7be507SJakub Kicinski 
4750*2d7be507SJakub Kicinski 	if (req->_present.header)
4751*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_FEC_HEADER, &req->header);
4752*2d7be507SJakub Kicinski 
4753*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
4754*2d7be507SJakub Kicinski 	if (err < 0)
4755*2d7be507SJakub Kicinski 		goto free_list;
4756*2d7be507SJakub Kicinski 
4757*2d7be507SJakub Kicinski 	return yds.first;
4758*2d7be507SJakub Kicinski 
4759*2d7be507SJakub Kicinski free_list:
4760*2d7be507SJakub Kicinski 	ethtool_fec_get_list_free(yds.first);
4761*2d7be507SJakub Kicinski 	return NULL;
4762*2d7be507SJakub Kicinski }
4763*2d7be507SJakub Kicinski 
4764*2d7be507SJakub Kicinski /* ETHTOOL_MSG_FEC_GET - notify */
ethtool_fec_get_ntf_free(struct ethtool_fec_get_ntf * rsp)4765*2d7be507SJakub Kicinski void ethtool_fec_get_ntf_free(struct ethtool_fec_get_ntf *rsp)
4766*2d7be507SJakub Kicinski {
4767*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->obj.header);
4768*2d7be507SJakub Kicinski 	ethtool_bitset_free(&rsp->obj.modes);
4769*2d7be507SJakub Kicinski 	ethtool_fec_stat_free(&rsp->obj.stats);
4770*2d7be507SJakub Kicinski 	free(rsp);
4771*2d7be507SJakub Kicinski }
4772*2d7be507SJakub Kicinski 
4773*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_FEC_SET ============== */
4774*2d7be507SJakub Kicinski /* ETHTOOL_MSG_FEC_SET - do */
ethtool_fec_set_req_free(struct ethtool_fec_set_req * req)4775*2d7be507SJakub Kicinski void ethtool_fec_set_req_free(struct ethtool_fec_set_req *req)
4776*2d7be507SJakub Kicinski {
4777*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
4778*2d7be507SJakub Kicinski 	ethtool_bitset_free(&req->modes);
4779*2d7be507SJakub Kicinski 	ethtool_fec_stat_free(&req->stats);
4780*2d7be507SJakub Kicinski 	free(req);
4781*2d7be507SJakub Kicinski }
4782*2d7be507SJakub Kicinski 
ethtool_fec_set(struct ynl_sock * ys,struct ethtool_fec_set_req * req)4783*2d7be507SJakub Kicinski int ethtool_fec_set(struct ynl_sock *ys, struct ethtool_fec_set_req *req)
4784*2d7be507SJakub Kicinski {
4785*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
4786*2d7be507SJakub Kicinski 	int err;
4787*2d7be507SJakub Kicinski 
4788*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_FEC_SET, 1);
4789*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_fec_nest;
4790*2d7be507SJakub Kicinski 
4791*2d7be507SJakub Kicinski 	if (req->_present.header)
4792*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_FEC_HEADER, &req->header);
4793*2d7be507SJakub Kicinski 	if (req->_present.modes)
4794*2d7be507SJakub Kicinski 		ethtool_bitset_put(nlh, ETHTOOL_A_FEC_MODES, &req->modes);
4795*2d7be507SJakub Kicinski 	if (req->_present.auto_)
4796*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_FEC_AUTO, req->auto_);
4797*2d7be507SJakub Kicinski 	if (req->_present.active)
4798*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_FEC_ACTIVE, req->active);
4799*2d7be507SJakub Kicinski 	if (req->_present.stats)
4800*2d7be507SJakub Kicinski 		ethtool_fec_stat_put(nlh, ETHTOOL_A_FEC_STATS, &req->stats);
4801*2d7be507SJakub Kicinski 
4802*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, NULL);
4803*2d7be507SJakub Kicinski 	if (err < 0)
4804*2d7be507SJakub Kicinski 		return -1;
4805*2d7be507SJakub Kicinski 
4806*2d7be507SJakub Kicinski 	return 0;
4807*2d7be507SJakub Kicinski }
4808*2d7be507SJakub Kicinski 
4809*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_MODULE_EEPROM_GET ============== */
4810*2d7be507SJakub Kicinski /* ETHTOOL_MSG_MODULE_EEPROM_GET - do */
4811*2d7be507SJakub Kicinski void
ethtool_module_eeprom_get_req_free(struct ethtool_module_eeprom_get_req * req)4812*2d7be507SJakub Kicinski ethtool_module_eeprom_get_req_free(struct ethtool_module_eeprom_get_req *req)
4813*2d7be507SJakub Kicinski {
4814*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
4815*2d7be507SJakub Kicinski 	free(req);
4816*2d7be507SJakub Kicinski }
4817*2d7be507SJakub Kicinski 
4818*2d7be507SJakub Kicinski void
ethtool_module_eeprom_get_rsp_free(struct ethtool_module_eeprom_get_rsp * rsp)4819*2d7be507SJakub Kicinski ethtool_module_eeprom_get_rsp_free(struct ethtool_module_eeprom_get_rsp *rsp)
4820*2d7be507SJakub Kicinski {
4821*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
4822*2d7be507SJakub Kicinski 	free(rsp->data);
4823*2d7be507SJakub Kicinski 	free(rsp);
4824*2d7be507SJakub Kicinski }
4825*2d7be507SJakub Kicinski 
ethtool_module_eeprom_get_rsp_parse(const struct nlmsghdr * nlh,void * data)4826*2d7be507SJakub Kicinski int ethtool_module_eeprom_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
4827*2d7be507SJakub Kicinski {
4828*2d7be507SJakub Kicinski 	struct ethtool_module_eeprom_get_rsp *dst;
4829*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
4830*2d7be507SJakub Kicinski 	const struct nlattr *attr;
4831*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
4832*2d7be507SJakub Kicinski 
4833*2d7be507SJakub Kicinski 	dst = yarg->data;
4834*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
4835*2d7be507SJakub Kicinski 
4836*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
4837*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
4838*2d7be507SJakub Kicinski 
4839*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_MODULE_EEPROM_HEADER) {
4840*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4841*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4842*2d7be507SJakub Kicinski 			dst->_present.header = 1;
4843*2d7be507SJakub Kicinski 
4844*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
4845*2d7be507SJakub Kicinski 			parg.data = &dst->header;
4846*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
4847*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4848*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MODULE_EEPROM_OFFSET) {
4849*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4850*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4851*2d7be507SJakub Kicinski 			dst->_present.offset = 1;
4852*2d7be507SJakub Kicinski 			dst->offset = mnl_attr_get_u32(attr);
4853*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MODULE_EEPROM_LENGTH) {
4854*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4855*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4856*2d7be507SJakub Kicinski 			dst->_present.length = 1;
4857*2d7be507SJakub Kicinski 			dst->length = mnl_attr_get_u32(attr);
4858*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MODULE_EEPROM_PAGE) {
4859*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4860*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4861*2d7be507SJakub Kicinski 			dst->_present.page = 1;
4862*2d7be507SJakub Kicinski 			dst->page = mnl_attr_get_u8(attr);
4863*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MODULE_EEPROM_BANK) {
4864*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4865*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4866*2d7be507SJakub Kicinski 			dst->_present.bank = 1;
4867*2d7be507SJakub Kicinski 			dst->bank = mnl_attr_get_u8(attr);
4868*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MODULE_EEPROM_I2C_ADDRESS) {
4869*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4870*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4871*2d7be507SJakub Kicinski 			dst->_present.i2c_address = 1;
4872*2d7be507SJakub Kicinski 			dst->i2c_address = mnl_attr_get_u8(attr);
4873*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MODULE_EEPROM_DATA) {
4874*2d7be507SJakub Kicinski 			unsigned int len;
4875*2d7be507SJakub Kicinski 
4876*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4877*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4878*2d7be507SJakub Kicinski 
4879*2d7be507SJakub Kicinski 			len = mnl_attr_get_payload_len(attr);
4880*2d7be507SJakub Kicinski 			dst->_present.data_len = len;
4881*2d7be507SJakub Kicinski 			dst->data = malloc(len);
4882*2d7be507SJakub Kicinski 			memcpy(dst->data, mnl_attr_get_payload(attr), len);
4883*2d7be507SJakub Kicinski 		}
4884*2d7be507SJakub Kicinski 	}
4885*2d7be507SJakub Kicinski 
4886*2d7be507SJakub Kicinski 	return MNL_CB_OK;
4887*2d7be507SJakub Kicinski }
4888*2d7be507SJakub Kicinski 
4889*2d7be507SJakub Kicinski struct ethtool_module_eeprom_get_rsp *
ethtool_module_eeprom_get(struct ynl_sock * ys,struct ethtool_module_eeprom_get_req * req)4890*2d7be507SJakub Kicinski ethtool_module_eeprom_get(struct ynl_sock *ys,
4891*2d7be507SJakub Kicinski 			  struct ethtool_module_eeprom_get_req *req)
4892*2d7be507SJakub Kicinski {
4893*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
4894*2d7be507SJakub Kicinski 	struct ethtool_module_eeprom_get_rsp *rsp;
4895*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
4896*2d7be507SJakub Kicinski 	int err;
4897*2d7be507SJakub Kicinski 
4898*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_MODULE_EEPROM_GET, 1);
4899*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_module_eeprom_nest;
4900*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_module_eeprom_nest;
4901*2d7be507SJakub Kicinski 
4902*2d7be507SJakub Kicinski 	if (req->_present.header)
4903*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_MODULE_EEPROM_HEADER, &req->header);
4904*2d7be507SJakub Kicinski 
4905*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
4906*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
4907*2d7be507SJakub Kicinski 	yrs.cb = ethtool_module_eeprom_get_rsp_parse;
4908*2d7be507SJakub Kicinski 	yrs.rsp_cmd = 32;
4909*2d7be507SJakub Kicinski 
4910*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
4911*2d7be507SJakub Kicinski 	if (err < 0)
4912*2d7be507SJakub Kicinski 		goto err_free;
4913*2d7be507SJakub Kicinski 
4914*2d7be507SJakub Kicinski 	return rsp;
4915*2d7be507SJakub Kicinski 
4916*2d7be507SJakub Kicinski err_free:
4917*2d7be507SJakub Kicinski 	ethtool_module_eeprom_get_rsp_free(rsp);
4918*2d7be507SJakub Kicinski 	return NULL;
4919*2d7be507SJakub Kicinski }
4920*2d7be507SJakub Kicinski 
4921*2d7be507SJakub Kicinski /* ETHTOOL_MSG_MODULE_EEPROM_GET - dump */
4922*2d7be507SJakub Kicinski void
ethtool_module_eeprom_get_list_free(struct ethtool_module_eeprom_get_list * rsp)4923*2d7be507SJakub Kicinski ethtool_module_eeprom_get_list_free(struct ethtool_module_eeprom_get_list *rsp)
4924*2d7be507SJakub Kicinski {
4925*2d7be507SJakub Kicinski 	struct ethtool_module_eeprom_get_list *next = rsp;
4926*2d7be507SJakub Kicinski 
4927*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
4928*2d7be507SJakub Kicinski 		rsp = next;
4929*2d7be507SJakub Kicinski 		next = rsp->next;
4930*2d7be507SJakub Kicinski 
4931*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
4932*2d7be507SJakub Kicinski 		free(rsp->obj.data);
4933*2d7be507SJakub Kicinski 		free(rsp);
4934*2d7be507SJakub Kicinski 	}
4935*2d7be507SJakub Kicinski }
4936*2d7be507SJakub Kicinski 
4937*2d7be507SJakub Kicinski struct ethtool_module_eeprom_get_list *
ethtool_module_eeprom_get_dump(struct ynl_sock * ys,struct ethtool_module_eeprom_get_req_dump * req)4938*2d7be507SJakub Kicinski ethtool_module_eeprom_get_dump(struct ynl_sock *ys,
4939*2d7be507SJakub Kicinski 			       struct ethtool_module_eeprom_get_req_dump *req)
4940*2d7be507SJakub Kicinski {
4941*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
4942*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
4943*2d7be507SJakub Kicinski 	int err;
4944*2d7be507SJakub Kicinski 
4945*2d7be507SJakub Kicinski 	yds.ys = ys;
4946*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_module_eeprom_get_list);
4947*2d7be507SJakub Kicinski 	yds.cb = ethtool_module_eeprom_get_rsp_parse;
4948*2d7be507SJakub Kicinski 	yds.rsp_cmd = 32;
4949*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_module_eeprom_nest;
4950*2d7be507SJakub Kicinski 
4951*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_MODULE_EEPROM_GET, 1);
4952*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_module_eeprom_nest;
4953*2d7be507SJakub Kicinski 
4954*2d7be507SJakub Kicinski 	if (req->_present.header)
4955*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_MODULE_EEPROM_HEADER, &req->header);
4956*2d7be507SJakub Kicinski 
4957*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
4958*2d7be507SJakub Kicinski 	if (err < 0)
4959*2d7be507SJakub Kicinski 		goto free_list;
4960*2d7be507SJakub Kicinski 
4961*2d7be507SJakub Kicinski 	return yds.first;
4962*2d7be507SJakub Kicinski 
4963*2d7be507SJakub Kicinski free_list:
4964*2d7be507SJakub Kicinski 	ethtool_module_eeprom_get_list_free(yds.first);
4965*2d7be507SJakub Kicinski 	return NULL;
4966*2d7be507SJakub Kicinski }
4967*2d7be507SJakub Kicinski 
4968*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_PHC_VCLOCKS_GET ============== */
4969*2d7be507SJakub Kicinski /* ETHTOOL_MSG_PHC_VCLOCKS_GET - do */
ethtool_phc_vclocks_get_req_free(struct ethtool_phc_vclocks_get_req * req)4970*2d7be507SJakub Kicinski void ethtool_phc_vclocks_get_req_free(struct ethtool_phc_vclocks_get_req *req)
4971*2d7be507SJakub Kicinski {
4972*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
4973*2d7be507SJakub Kicinski 	free(req);
4974*2d7be507SJakub Kicinski }
4975*2d7be507SJakub Kicinski 
ethtool_phc_vclocks_get_rsp_free(struct ethtool_phc_vclocks_get_rsp * rsp)4976*2d7be507SJakub Kicinski void ethtool_phc_vclocks_get_rsp_free(struct ethtool_phc_vclocks_get_rsp *rsp)
4977*2d7be507SJakub Kicinski {
4978*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
4979*2d7be507SJakub Kicinski 	free(rsp);
4980*2d7be507SJakub Kicinski }
4981*2d7be507SJakub Kicinski 
ethtool_phc_vclocks_get_rsp_parse(const struct nlmsghdr * nlh,void * data)4982*2d7be507SJakub Kicinski int ethtool_phc_vclocks_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
4983*2d7be507SJakub Kicinski {
4984*2d7be507SJakub Kicinski 	struct ethtool_phc_vclocks_get_rsp *dst;
4985*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
4986*2d7be507SJakub Kicinski 	const struct nlattr *attr;
4987*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
4988*2d7be507SJakub Kicinski 
4989*2d7be507SJakub Kicinski 	dst = yarg->data;
4990*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
4991*2d7be507SJakub Kicinski 
4992*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
4993*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
4994*2d7be507SJakub Kicinski 
4995*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_PHC_VCLOCKS_HEADER) {
4996*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4997*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
4998*2d7be507SJakub Kicinski 			dst->_present.header = 1;
4999*2d7be507SJakub Kicinski 
5000*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
5001*2d7be507SJakub Kicinski 			parg.data = &dst->header;
5002*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
5003*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5004*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PHC_VCLOCKS_NUM) {
5005*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5006*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5007*2d7be507SJakub Kicinski 			dst->_present.num = 1;
5008*2d7be507SJakub Kicinski 			dst->num = mnl_attr_get_u32(attr);
5009*2d7be507SJakub Kicinski 		}
5010*2d7be507SJakub Kicinski 	}
5011*2d7be507SJakub Kicinski 
5012*2d7be507SJakub Kicinski 	return MNL_CB_OK;
5013*2d7be507SJakub Kicinski }
5014*2d7be507SJakub Kicinski 
5015*2d7be507SJakub Kicinski struct ethtool_phc_vclocks_get_rsp *
ethtool_phc_vclocks_get(struct ynl_sock * ys,struct ethtool_phc_vclocks_get_req * req)5016*2d7be507SJakub Kicinski ethtool_phc_vclocks_get(struct ynl_sock *ys,
5017*2d7be507SJakub Kicinski 			struct ethtool_phc_vclocks_get_req *req)
5018*2d7be507SJakub Kicinski {
5019*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
5020*2d7be507SJakub Kicinski 	struct ethtool_phc_vclocks_get_rsp *rsp;
5021*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
5022*2d7be507SJakub Kicinski 	int err;
5023*2d7be507SJakub Kicinski 
5024*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PHC_VCLOCKS_GET, 1);
5025*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_phc_vclocks_nest;
5026*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_phc_vclocks_nest;
5027*2d7be507SJakub Kicinski 
5028*2d7be507SJakub Kicinski 	if (req->_present.header)
5029*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_PHC_VCLOCKS_HEADER, &req->header);
5030*2d7be507SJakub Kicinski 
5031*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
5032*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
5033*2d7be507SJakub Kicinski 	yrs.cb = ethtool_phc_vclocks_get_rsp_parse;
5034*2d7be507SJakub Kicinski 	yrs.rsp_cmd = 34;
5035*2d7be507SJakub Kicinski 
5036*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
5037*2d7be507SJakub Kicinski 	if (err < 0)
5038*2d7be507SJakub Kicinski 		goto err_free;
5039*2d7be507SJakub Kicinski 
5040*2d7be507SJakub Kicinski 	return rsp;
5041*2d7be507SJakub Kicinski 
5042*2d7be507SJakub Kicinski err_free:
5043*2d7be507SJakub Kicinski 	ethtool_phc_vclocks_get_rsp_free(rsp);
5044*2d7be507SJakub Kicinski 	return NULL;
5045*2d7be507SJakub Kicinski }
5046*2d7be507SJakub Kicinski 
5047*2d7be507SJakub Kicinski /* ETHTOOL_MSG_PHC_VCLOCKS_GET - dump */
5048*2d7be507SJakub Kicinski void
ethtool_phc_vclocks_get_list_free(struct ethtool_phc_vclocks_get_list * rsp)5049*2d7be507SJakub Kicinski ethtool_phc_vclocks_get_list_free(struct ethtool_phc_vclocks_get_list *rsp)
5050*2d7be507SJakub Kicinski {
5051*2d7be507SJakub Kicinski 	struct ethtool_phc_vclocks_get_list *next = rsp;
5052*2d7be507SJakub Kicinski 
5053*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
5054*2d7be507SJakub Kicinski 		rsp = next;
5055*2d7be507SJakub Kicinski 		next = rsp->next;
5056*2d7be507SJakub Kicinski 
5057*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
5058*2d7be507SJakub Kicinski 		free(rsp);
5059*2d7be507SJakub Kicinski 	}
5060*2d7be507SJakub Kicinski }
5061*2d7be507SJakub Kicinski 
5062*2d7be507SJakub Kicinski struct ethtool_phc_vclocks_get_list *
ethtool_phc_vclocks_get_dump(struct ynl_sock * ys,struct ethtool_phc_vclocks_get_req_dump * req)5063*2d7be507SJakub Kicinski ethtool_phc_vclocks_get_dump(struct ynl_sock *ys,
5064*2d7be507SJakub Kicinski 			     struct ethtool_phc_vclocks_get_req_dump *req)
5065*2d7be507SJakub Kicinski {
5066*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
5067*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
5068*2d7be507SJakub Kicinski 	int err;
5069*2d7be507SJakub Kicinski 
5070*2d7be507SJakub Kicinski 	yds.ys = ys;
5071*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_phc_vclocks_get_list);
5072*2d7be507SJakub Kicinski 	yds.cb = ethtool_phc_vclocks_get_rsp_parse;
5073*2d7be507SJakub Kicinski 	yds.rsp_cmd = 34;
5074*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_phc_vclocks_nest;
5075*2d7be507SJakub Kicinski 
5076*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_PHC_VCLOCKS_GET, 1);
5077*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_phc_vclocks_nest;
5078*2d7be507SJakub Kicinski 
5079*2d7be507SJakub Kicinski 	if (req->_present.header)
5080*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_PHC_VCLOCKS_HEADER, &req->header);
5081*2d7be507SJakub Kicinski 
5082*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
5083*2d7be507SJakub Kicinski 	if (err < 0)
5084*2d7be507SJakub Kicinski 		goto free_list;
5085*2d7be507SJakub Kicinski 
5086*2d7be507SJakub Kicinski 	return yds.first;
5087*2d7be507SJakub Kicinski 
5088*2d7be507SJakub Kicinski free_list:
5089*2d7be507SJakub Kicinski 	ethtool_phc_vclocks_get_list_free(yds.first);
5090*2d7be507SJakub Kicinski 	return NULL;
5091*2d7be507SJakub Kicinski }
5092*2d7be507SJakub Kicinski 
5093*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_MODULE_GET ============== */
5094*2d7be507SJakub Kicinski /* ETHTOOL_MSG_MODULE_GET - do */
ethtool_module_get_req_free(struct ethtool_module_get_req * req)5095*2d7be507SJakub Kicinski void ethtool_module_get_req_free(struct ethtool_module_get_req *req)
5096*2d7be507SJakub Kicinski {
5097*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
5098*2d7be507SJakub Kicinski 	free(req);
5099*2d7be507SJakub Kicinski }
5100*2d7be507SJakub Kicinski 
ethtool_module_get_rsp_free(struct ethtool_module_get_rsp * rsp)5101*2d7be507SJakub Kicinski void ethtool_module_get_rsp_free(struct ethtool_module_get_rsp *rsp)
5102*2d7be507SJakub Kicinski {
5103*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
5104*2d7be507SJakub Kicinski 	free(rsp);
5105*2d7be507SJakub Kicinski }
5106*2d7be507SJakub Kicinski 
ethtool_module_get_rsp_parse(const struct nlmsghdr * nlh,void * data)5107*2d7be507SJakub Kicinski int ethtool_module_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
5108*2d7be507SJakub Kicinski {
5109*2d7be507SJakub Kicinski 	struct ethtool_module_get_rsp *dst;
5110*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
5111*2d7be507SJakub Kicinski 	const struct nlattr *attr;
5112*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
5113*2d7be507SJakub Kicinski 
5114*2d7be507SJakub Kicinski 	dst = yarg->data;
5115*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
5116*2d7be507SJakub Kicinski 
5117*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
5118*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
5119*2d7be507SJakub Kicinski 
5120*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_MODULE_HEADER) {
5121*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5122*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5123*2d7be507SJakub Kicinski 			dst->_present.header = 1;
5124*2d7be507SJakub Kicinski 
5125*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
5126*2d7be507SJakub Kicinski 			parg.data = &dst->header;
5127*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
5128*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5129*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MODULE_POWER_MODE_POLICY) {
5130*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5131*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5132*2d7be507SJakub Kicinski 			dst->_present.power_mode_policy = 1;
5133*2d7be507SJakub Kicinski 			dst->power_mode_policy = mnl_attr_get_u8(attr);
5134*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MODULE_POWER_MODE) {
5135*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5136*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5137*2d7be507SJakub Kicinski 			dst->_present.power_mode = 1;
5138*2d7be507SJakub Kicinski 			dst->power_mode = mnl_attr_get_u8(attr);
5139*2d7be507SJakub Kicinski 		}
5140*2d7be507SJakub Kicinski 	}
5141*2d7be507SJakub Kicinski 
5142*2d7be507SJakub Kicinski 	return MNL_CB_OK;
5143*2d7be507SJakub Kicinski }
5144*2d7be507SJakub Kicinski 
5145*2d7be507SJakub Kicinski struct ethtool_module_get_rsp *
ethtool_module_get(struct ynl_sock * ys,struct ethtool_module_get_req * req)5146*2d7be507SJakub Kicinski ethtool_module_get(struct ynl_sock *ys, struct ethtool_module_get_req *req)
5147*2d7be507SJakub Kicinski {
5148*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
5149*2d7be507SJakub Kicinski 	struct ethtool_module_get_rsp *rsp;
5150*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
5151*2d7be507SJakub Kicinski 	int err;
5152*2d7be507SJakub Kicinski 
5153*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_MODULE_GET, 1);
5154*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_module_nest;
5155*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_module_nest;
5156*2d7be507SJakub Kicinski 
5157*2d7be507SJakub Kicinski 	if (req->_present.header)
5158*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_MODULE_HEADER, &req->header);
5159*2d7be507SJakub Kicinski 
5160*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
5161*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
5162*2d7be507SJakub Kicinski 	yrs.cb = ethtool_module_get_rsp_parse;
5163*2d7be507SJakub Kicinski 	yrs.rsp_cmd = 35;
5164*2d7be507SJakub Kicinski 
5165*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
5166*2d7be507SJakub Kicinski 	if (err < 0)
5167*2d7be507SJakub Kicinski 		goto err_free;
5168*2d7be507SJakub Kicinski 
5169*2d7be507SJakub Kicinski 	return rsp;
5170*2d7be507SJakub Kicinski 
5171*2d7be507SJakub Kicinski err_free:
5172*2d7be507SJakub Kicinski 	ethtool_module_get_rsp_free(rsp);
5173*2d7be507SJakub Kicinski 	return NULL;
5174*2d7be507SJakub Kicinski }
5175*2d7be507SJakub Kicinski 
5176*2d7be507SJakub Kicinski /* ETHTOOL_MSG_MODULE_GET - dump */
ethtool_module_get_list_free(struct ethtool_module_get_list * rsp)5177*2d7be507SJakub Kicinski void ethtool_module_get_list_free(struct ethtool_module_get_list *rsp)
5178*2d7be507SJakub Kicinski {
5179*2d7be507SJakub Kicinski 	struct ethtool_module_get_list *next = rsp;
5180*2d7be507SJakub Kicinski 
5181*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
5182*2d7be507SJakub Kicinski 		rsp = next;
5183*2d7be507SJakub Kicinski 		next = rsp->next;
5184*2d7be507SJakub Kicinski 
5185*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
5186*2d7be507SJakub Kicinski 		free(rsp);
5187*2d7be507SJakub Kicinski 	}
5188*2d7be507SJakub Kicinski }
5189*2d7be507SJakub Kicinski 
5190*2d7be507SJakub Kicinski struct ethtool_module_get_list *
ethtool_module_get_dump(struct ynl_sock * ys,struct ethtool_module_get_req_dump * req)5191*2d7be507SJakub Kicinski ethtool_module_get_dump(struct ynl_sock *ys,
5192*2d7be507SJakub Kicinski 			struct ethtool_module_get_req_dump *req)
5193*2d7be507SJakub Kicinski {
5194*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
5195*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
5196*2d7be507SJakub Kicinski 	int err;
5197*2d7be507SJakub Kicinski 
5198*2d7be507SJakub Kicinski 	yds.ys = ys;
5199*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_module_get_list);
5200*2d7be507SJakub Kicinski 	yds.cb = ethtool_module_get_rsp_parse;
5201*2d7be507SJakub Kicinski 	yds.rsp_cmd = 35;
5202*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_module_nest;
5203*2d7be507SJakub Kicinski 
5204*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_MODULE_GET, 1);
5205*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_module_nest;
5206*2d7be507SJakub Kicinski 
5207*2d7be507SJakub Kicinski 	if (req->_present.header)
5208*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_MODULE_HEADER, &req->header);
5209*2d7be507SJakub Kicinski 
5210*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
5211*2d7be507SJakub Kicinski 	if (err < 0)
5212*2d7be507SJakub Kicinski 		goto free_list;
5213*2d7be507SJakub Kicinski 
5214*2d7be507SJakub Kicinski 	return yds.first;
5215*2d7be507SJakub Kicinski 
5216*2d7be507SJakub Kicinski free_list:
5217*2d7be507SJakub Kicinski 	ethtool_module_get_list_free(yds.first);
5218*2d7be507SJakub Kicinski 	return NULL;
5219*2d7be507SJakub Kicinski }
5220*2d7be507SJakub Kicinski 
5221*2d7be507SJakub Kicinski /* ETHTOOL_MSG_MODULE_GET - notify */
ethtool_module_get_ntf_free(struct ethtool_module_get_ntf * rsp)5222*2d7be507SJakub Kicinski void ethtool_module_get_ntf_free(struct ethtool_module_get_ntf *rsp)
5223*2d7be507SJakub Kicinski {
5224*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->obj.header);
5225*2d7be507SJakub Kicinski 	free(rsp);
5226*2d7be507SJakub Kicinski }
5227*2d7be507SJakub Kicinski 
5228*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_MODULE_SET ============== */
5229*2d7be507SJakub Kicinski /* ETHTOOL_MSG_MODULE_SET - do */
ethtool_module_set_req_free(struct ethtool_module_set_req * req)5230*2d7be507SJakub Kicinski void ethtool_module_set_req_free(struct ethtool_module_set_req *req)
5231*2d7be507SJakub Kicinski {
5232*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
5233*2d7be507SJakub Kicinski 	free(req);
5234*2d7be507SJakub Kicinski }
5235*2d7be507SJakub Kicinski 
ethtool_module_set(struct ynl_sock * ys,struct ethtool_module_set_req * req)5236*2d7be507SJakub Kicinski int ethtool_module_set(struct ynl_sock *ys, struct ethtool_module_set_req *req)
5237*2d7be507SJakub Kicinski {
5238*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
5239*2d7be507SJakub Kicinski 	int err;
5240*2d7be507SJakub Kicinski 
5241*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_MODULE_SET, 1);
5242*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_module_nest;
5243*2d7be507SJakub Kicinski 
5244*2d7be507SJakub Kicinski 	if (req->_present.header)
5245*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_MODULE_HEADER, &req->header);
5246*2d7be507SJakub Kicinski 	if (req->_present.power_mode_policy)
5247*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_MODULE_POWER_MODE_POLICY, req->power_mode_policy);
5248*2d7be507SJakub Kicinski 	if (req->_present.power_mode)
5249*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_MODULE_POWER_MODE, req->power_mode);
5250*2d7be507SJakub Kicinski 
5251*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, NULL);
5252*2d7be507SJakub Kicinski 	if (err < 0)
5253*2d7be507SJakub Kicinski 		return -1;
5254*2d7be507SJakub Kicinski 
5255*2d7be507SJakub Kicinski 	return 0;
5256*2d7be507SJakub Kicinski }
5257*2d7be507SJakub Kicinski 
5258*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_PSE_GET ============== */
5259*2d7be507SJakub Kicinski /* ETHTOOL_MSG_PSE_GET - do */
ethtool_pse_get_req_free(struct ethtool_pse_get_req * req)5260*2d7be507SJakub Kicinski void ethtool_pse_get_req_free(struct ethtool_pse_get_req *req)
5261*2d7be507SJakub Kicinski {
5262*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
5263*2d7be507SJakub Kicinski 	free(req);
5264*2d7be507SJakub Kicinski }
5265*2d7be507SJakub Kicinski 
ethtool_pse_get_rsp_free(struct ethtool_pse_get_rsp * rsp)5266*2d7be507SJakub Kicinski void ethtool_pse_get_rsp_free(struct ethtool_pse_get_rsp *rsp)
5267*2d7be507SJakub Kicinski {
5268*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
5269*2d7be507SJakub Kicinski 	free(rsp);
5270*2d7be507SJakub Kicinski }
5271*2d7be507SJakub Kicinski 
ethtool_pse_get_rsp_parse(const struct nlmsghdr * nlh,void * data)5272*2d7be507SJakub Kicinski int ethtool_pse_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
5273*2d7be507SJakub Kicinski {
5274*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
5275*2d7be507SJakub Kicinski 	struct ethtool_pse_get_rsp *dst;
5276*2d7be507SJakub Kicinski 	const struct nlattr *attr;
5277*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
5278*2d7be507SJakub Kicinski 
5279*2d7be507SJakub Kicinski 	dst = yarg->data;
5280*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
5281*2d7be507SJakub Kicinski 
5282*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
5283*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
5284*2d7be507SJakub Kicinski 
5285*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_PSE_HEADER) {
5286*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5287*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5288*2d7be507SJakub Kicinski 			dst->_present.header = 1;
5289*2d7be507SJakub Kicinski 
5290*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
5291*2d7be507SJakub Kicinski 			parg.data = &dst->header;
5292*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
5293*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5294*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PODL_PSE_ADMIN_STATE) {
5295*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5296*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5297*2d7be507SJakub Kicinski 			dst->_present.admin_state = 1;
5298*2d7be507SJakub Kicinski 			dst->admin_state = mnl_attr_get_u32(attr);
5299*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PODL_PSE_ADMIN_CONTROL) {
5300*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5301*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5302*2d7be507SJakub Kicinski 			dst->_present.admin_control = 1;
5303*2d7be507SJakub Kicinski 			dst->admin_control = mnl_attr_get_u32(attr);
5304*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PODL_PSE_PW_D_STATUS) {
5305*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5306*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5307*2d7be507SJakub Kicinski 			dst->_present.pw_d_status = 1;
5308*2d7be507SJakub Kicinski 			dst->pw_d_status = mnl_attr_get_u32(attr);
5309*2d7be507SJakub Kicinski 		}
5310*2d7be507SJakub Kicinski 	}
5311*2d7be507SJakub Kicinski 
5312*2d7be507SJakub Kicinski 	return MNL_CB_OK;
5313*2d7be507SJakub Kicinski }
5314*2d7be507SJakub Kicinski 
5315*2d7be507SJakub Kicinski struct ethtool_pse_get_rsp *
ethtool_pse_get(struct ynl_sock * ys,struct ethtool_pse_get_req * req)5316*2d7be507SJakub Kicinski ethtool_pse_get(struct ynl_sock *ys, struct ethtool_pse_get_req *req)
5317*2d7be507SJakub Kicinski {
5318*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
5319*2d7be507SJakub Kicinski 	struct ethtool_pse_get_rsp *rsp;
5320*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
5321*2d7be507SJakub Kicinski 	int err;
5322*2d7be507SJakub Kicinski 
5323*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PSE_GET, 1);
5324*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_pse_nest;
5325*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_pse_nest;
5326*2d7be507SJakub Kicinski 
5327*2d7be507SJakub Kicinski 	if (req->_present.header)
5328*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_PSE_HEADER, &req->header);
5329*2d7be507SJakub Kicinski 
5330*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
5331*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
5332*2d7be507SJakub Kicinski 	yrs.cb = ethtool_pse_get_rsp_parse;
5333*2d7be507SJakub Kicinski 	yrs.rsp_cmd = 37;
5334*2d7be507SJakub Kicinski 
5335*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
5336*2d7be507SJakub Kicinski 	if (err < 0)
5337*2d7be507SJakub Kicinski 		goto err_free;
5338*2d7be507SJakub Kicinski 
5339*2d7be507SJakub Kicinski 	return rsp;
5340*2d7be507SJakub Kicinski 
5341*2d7be507SJakub Kicinski err_free:
5342*2d7be507SJakub Kicinski 	ethtool_pse_get_rsp_free(rsp);
5343*2d7be507SJakub Kicinski 	return NULL;
5344*2d7be507SJakub Kicinski }
5345*2d7be507SJakub Kicinski 
5346*2d7be507SJakub Kicinski /* ETHTOOL_MSG_PSE_GET - dump */
ethtool_pse_get_list_free(struct ethtool_pse_get_list * rsp)5347*2d7be507SJakub Kicinski void ethtool_pse_get_list_free(struct ethtool_pse_get_list *rsp)
5348*2d7be507SJakub Kicinski {
5349*2d7be507SJakub Kicinski 	struct ethtool_pse_get_list *next = rsp;
5350*2d7be507SJakub Kicinski 
5351*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
5352*2d7be507SJakub Kicinski 		rsp = next;
5353*2d7be507SJakub Kicinski 		next = rsp->next;
5354*2d7be507SJakub Kicinski 
5355*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
5356*2d7be507SJakub Kicinski 		free(rsp);
5357*2d7be507SJakub Kicinski 	}
5358*2d7be507SJakub Kicinski }
5359*2d7be507SJakub Kicinski 
5360*2d7be507SJakub Kicinski struct ethtool_pse_get_list *
ethtool_pse_get_dump(struct ynl_sock * ys,struct ethtool_pse_get_req_dump * req)5361*2d7be507SJakub Kicinski ethtool_pse_get_dump(struct ynl_sock *ys, struct ethtool_pse_get_req_dump *req)
5362*2d7be507SJakub Kicinski {
5363*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
5364*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
5365*2d7be507SJakub Kicinski 	int err;
5366*2d7be507SJakub Kicinski 
5367*2d7be507SJakub Kicinski 	yds.ys = ys;
5368*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_pse_get_list);
5369*2d7be507SJakub Kicinski 	yds.cb = ethtool_pse_get_rsp_parse;
5370*2d7be507SJakub Kicinski 	yds.rsp_cmd = 37;
5371*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_pse_nest;
5372*2d7be507SJakub Kicinski 
5373*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_PSE_GET, 1);
5374*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_pse_nest;
5375*2d7be507SJakub Kicinski 
5376*2d7be507SJakub Kicinski 	if (req->_present.header)
5377*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_PSE_HEADER, &req->header);
5378*2d7be507SJakub Kicinski 
5379*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
5380*2d7be507SJakub Kicinski 	if (err < 0)
5381*2d7be507SJakub Kicinski 		goto free_list;
5382*2d7be507SJakub Kicinski 
5383*2d7be507SJakub Kicinski 	return yds.first;
5384*2d7be507SJakub Kicinski 
5385*2d7be507SJakub Kicinski free_list:
5386*2d7be507SJakub Kicinski 	ethtool_pse_get_list_free(yds.first);
5387*2d7be507SJakub Kicinski 	return NULL;
5388*2d7be507SJakub Kicinski }
5389*2d7be507SJakub Kicinski 
5390*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_PSE_SET ============== */
5391*2d7be507SJakub Kicinski /* ETHTOOL_MSG_PSE_SET - do */
ethtool_pse_set_req_free(struct ethtool_pse_set_req * req)5392*2d7be507SJakub Kicinski void ethtool_pse_set_req_free(struct ethtool_pse_set_req *req)
5393*2d7be507SJakub Kicinski {
5394*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
5395*2d7be507SJakub Kicinski 	free(req);
5396*2d7be507SJakub Kicinski }
5397*2d7be507SJakub Kicinski 
ethtool_pse_set(struct ynl_sock * ys,struct ethtool_pse_set_req * req)5398*2d7be507SJakub Kicinski int ethtool_pse_set(struct ynl_sock *ys, struct ethtool_pse_set_req *req)
5399*2d7be507SJakub Kicinski {
5400*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
5401*2d7be507SJakub Kicinski 	int err;
5402*2d7be507SJakub Kicinski 
5403*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PSE_SET, 1);
5404*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_pse_nest;
5405*2d7be507SJakub Kicinski 
5406*2d7be507SJakub Kicinski 	if (req->_present.header)
5407*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_PSE_HEADER, &req->header);
5408*2d7be507SJakub Kicinski 	if (req->_present.admin_state)
5409*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_PODL_PSE_ADMIN_STATE, req->admin_state);
5410*2d7be507SJakub Kicinski 	if (req->_present.admin_control)
5411*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_PODL_PSE_ADMIN_CONTROL, req->admin_control);
5412*2d7be507SJakub Kicinski 	if (req->_present.pw_d_status)
5413*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_PODL_PSE_PW_D_STATUS, req->pw_d_status);
5414*2d7be507SJakub Kicinski 
5415*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, NULL);
5416*2d7be507SJakub Kicinski 	if (err < 0)
5417*2d7be507SJakub Kicinski 		return -1;
5418*2d7be507SJakub Kicinski 
5419*2d7be507SJakub Kicinski 	return 0;
5420*2d7be507SJakub Kicinski }
5421*2d7be507SJakub Kicinski 
5422*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_RSS_GET ============== */
5423*2d7be507SJakub Kicinski /* ETHTOOL_MSG_RSS_GET - do */
ethtool_rss_get_req_free(struct ethtool_rss_get_req * req)5424*2d7be507SJakub Kicinski void ethtool_rss_get_req_free(struct ethtool_rss_get_req *req)
5425*2d7be507SJakub Kicinski {
5426*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
5427*2d7be507SJakub Kicinski 	free(req);
5428*2d7be507SJakub Kicinski }
5429*2d7be507SJakub Kicinski 
ethtool_rss_get_rsp_free(struct ethtool_rss_get_rsp * rsp)5430*2d7be507SJakub Kicinski void ethtool_rss_get_rsp_free(struct ethtool_rss_get_rsp *rsp)
5431*2d7be507SJakub Kicinski {
5432*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
5433*2d7be507SJakub Kicinski 	free(rsp->indir);
5434*2d7be507SJakub Kicinski 	free(rsp->hkey);
5435*2d7be507SJakub Kicinski 	free(rsp);
5436*2d7be507SJakub Kicinski }
5437*2d7be507SJakub Kicinski 
ethtool_rss_get_rsp_parse(const struct nlmsghdr * nlh,void * data)5438*2d7be507SJakub Kicinski int ethtool_rss_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
5439*2d7be507SJakub Kicinski {
5440*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
5441*2d7be507SJakub Kicinski 	struct ethtool_rss_get_rsp *dst;
5442*2d7be507SJakub Kicinski 	const struct nlattr *attr;
5443*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
5444*2d7be507SJakub Kicinski 
5445*2d7be507SJakub Kicinski 	dst = yarg->data;
5446*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
5447*2d7be507SJakub Kicinski 
5448*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
5449*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
5450*2d7be507SJakub Kicinski 
5451*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_RSS_HEADER) {
5452*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5453*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5454*2d7be507SJakub Kicinski 			dst->_present.header = 1;
5455*2d7be507SJakub Kicinski 
5456*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
5457*2d7be507SJakub Kicinski 			parg.data = &dst->header;
5458*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
5459*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5460*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_RSS_CONTEXT) {
5461*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5462*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5463*2d7be507SJakub Kicinski 			dst->_present.context = 1;
5464*2d7be507SJakub Kicinski 			dst->context = mnl_attr_get_u32(attr);
5465*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_RSS_HFUNC) {
5466*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5467*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5468*2d7be507SJakub Kicinski 			dst->_present.hfunc = 1;
5469*2d7be507SJakub Kicinski 			dst->hfunc = mnl_attr_get_u32(attr);
5470*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_RSS_INDIR) {
5471*2d7be507SJakub Kicinski 			unsigned int len;
5472*2d7be507SJakub Kicinski 
5473*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5474*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5475*2d7be507SJakub Kicinski 
5476*2d7be507SJakub Kicinski 			len = mnl_attr_get_payload_len(attr);
5477*2d7be507SJakub Kicinski 			dst->_present.indir_len = len;
5478*2d7be507SJakub Kicinski 			dst->indir = malloc(len);
5479*2d7be507SJakub Kicinski 			memcpy(dst->indir, mnl_attr_get_payload(attr), len);
5480*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_RSS_HKEY) {
5481*2d7be507SJakub Kicinski 			unsigned int len;
5482*2d7be507SJakub Kicinski 
5483*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5484*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5485*2d7be507SJakub Kicinski 
5486*2d7be507SJakub Kicinski 			len = mnl_attr_get_payload_len(attr);
5487*2d7be507SJakub Kicinski 			dst->_present.hkey_len = len;
5488*2d7be507SJakub Kicinski 			dst->hkey = malloc(len);
5489*2d7be507SJakub Kicinski 			memcpy(dst->hkey, mnl_attr_get_payload(attr), len);
5490*2d7be507SJakub Kicinski 		}
5491*2d7be507SJakub Kicinski 	}
5492*2d7be507SJakub Kicinski 
5493*2d7be507SJakub Kicinski 	return MNL_CB_OK;
5494*2d7be507SJakub Kicinski }
5495*2d7be507SJakub Kicinski 
5496*2d7be507SJakub Kicinski struct ethtool_rss_get_rsp *
ethtool_rss_get(struct ynl_sock * ys,struct ethtool_rss_get_req * req)5497*2d7be507SJakub Kicinski ethtool_rss_get(struct ynl_sock *ys, struct ethtool_rss_get_req *req)
5498*2d7be507SJakub Kicinski {
5499*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
5500*2d7be507SJakub Kicinski 	struct ethtool_rss_get_rsp *rsp;
5501*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
5502*2d7be507SJakub Kicinski 	int err;
5503*2d7be507SJakub Kicinski 
5504*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_RSS_GET, 1);
5505*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_rss_nest;
5506*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_rss_nest;
5507*2d7be507SJakub Kicinski 
5508*2d7be507SJakub Kicinski 	if (req->_present.header)
5509*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_RSS_HEADER, &req->header);
5510*2d7be507SJakub Kicinski 
5511*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
5512*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
5513*2d7be507SJakub Kicinski 	yrs.cb = ethtool_rss_get_rsp_parse;
5514*2d7be507SJakub Kicinski 	yrs.rsp_cmd = ETHTOOL_MSG_RSS_GET;
5515*2d7be507SJakub Kicinski 
5516*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
5517*2d7be507SJakub Kicinski 	if (err < 0)
5518*2d7be507SJakub Kicinski 		goto err_free;
5519*2d7be507SJakub Kicinski 
5520*2d7be507SJakub Kicinski 	return rsp;
5521*2d7be507SJakub Kicinski 
5522*2d7be507SJakub Kicinski err_free:
5523*2d7be507SJakub Kicinski 	ethtool_rss_get_rsp_free(rsp);
5524*2d7be507SJakub Kicinski 	return NULL;
5525*2d7be507SJakub Kicinski }
5526*2d7be507SJakub Kicinski 
5527*2d7be507SJakub Kicinski /* ETHTOOL_MSG_RSS_GET - dump */
ethtool_rss_get_list_free(struct ethtool_rss_get_list * rsp)5528*2d7be507SJakub Kicinski void ethtool_rss_get_list_free(struct ethtool_rss_get_list *rsp)
5529*2d7be507SJakub Kicinski {
5530*2d7be507SJakub Kicinski 	struct ethtool_rss_get_list *next = rsp;
5531*2d7be507SJakub Kicinski 
5532*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
5533*2d7be507SJakub Kicinski 		rsp = next;
5534*2d7be507SJakub Kicinski 		next = rsp->next;
5535*2d7be507SJakub Kicinski 
5536*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
5537*2d7be507SJakub Kicinski 		free(rsp->obj.indir);
5538*2d7be507SJakub Kicinski 		free(rsp->obj.hkey);
5539*2d7be507SJakub Kicinski 		free(rsp);
5540*2d7be507SJakub Kicinski 	}
5541*2d7be507SJakub Kicinski }
5542*2d7be507SJakub Kicinski 
5543*2d7be507SJakub Kicinski struct ethtool_rss_get_list *
ethtool_rss_get_dump(struct ynl_sock * ys,struct ethtool_rss_get_req_dump * req)5544*2d7be507SJakub Kicinski ethtool_rss_get_dump(struct ynl_sock *ys, struct ethtool_rss_get_req_dump *req)
5545*2d7be507SJakub Kicinski {
5546*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
5547*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
5548*2d7be507SJakub Kicinski 	int err;
5549*2d7be507SJakub Kicinski 
5550*2d7be507SJakub Kicinski 	yds.ys = ys;
5551*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_rss_get_list);
5552*2d7be507SJakub Kicinski 	yds.cb = ethtool_rss_get_rsp_parse;
5553*2d7be507SJakub Kicinski 	yds.rsp_cmd = ETHTOOL_MSG_RSS_GET;
5554*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_rss_nest;
5555*2d7be507SJakub Kicinski 
5556*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_RSS_GET, 1);
5557*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_rss_nest;
5558*2d7be507SJakub Kicinski 
5559*2d7be507SJakub Kicinski 	if (req->_present.header)
5560*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_RSS_HEADER, &req->header);
5561*2d7be507SJakub Kicinski 
5562*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
5563*2d7be507SJakub Kicinski 	if (err < 0)
5564*2d7be507SJakub Kicinski 		goto free_list;
5565*2d7be507SJakub Kicinski 
5566*2d7be507SJakub Kicinski 	return yds.first;
5567*2d7be507SJakub Kicinski 
5568*2d7be507SJakub Kicinski free_list:
5569*2d7be507SJakub Kicinski 	ethtool_rss_get_list_free(yds.first);
5570*2d7be507SJakub Kicinski 	return NULL;
5571*2d7be507SJakub Kicinski }
5572*2d7be507SJakub Kicinski 
5573*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_PLCA_GET_CFG ============== */
5574*2d7be507SJakub Kicinski /* ETHTOOL_MSG_PLCA_GET_CFG - do */
ethtool_plca_get_cfg_req_free(struct ethtool_plca_get_cfg_req * req)5575*2d7be507SJakub Kicinski void ethtool_plca_get_cfg_req_free(struct ethtool_plca_get_cfg_req *req)
5576*2d7be507SJakub Kicinski {
5577*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
5578*2d7be507SJakub Kicinski 	free(req);
5579*2d7be507SJakub Kicinski }
5580*2d7be507SJakub Kicinski 
ethtool_plca_get_cfg_rsp_free(struct ethtool_plca_get_cfg_rsp * rsp)5581*2d7be507SJakub Kicinski void ethtool_plca_get_cfg_rsp_free(struct ethtool_plca_get_cfg_rsp *rsp)
5582*2d7be507SJakub Kicinski {
5583*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
5584*2d7be507SJakub Kicinski 	free(rsp);
5585*2d7be507SJakub Kicinski }
5586*2d7be507SJakub Kicinski 
ethtool_plca_get_cfg_rsp_parse(const struct nlmsghdr * nlh,void * data)5587*2d7be507SJakub Kicinski int ethtool_plca_get_cfg_rsp_parse(const struct nlmsghdr *nlh, void *data)
5588*2d7be507SJakub Kicinski {
5589*2d7be507SJakub Kicinski 	struct ethtool_plca_get_cfg_rsp *dst;
5590*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
5591*2d7be507SJakub Kicinski 	const struct nlattr *attr;
5592*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
5593*2d7be507SJakub Kicinski 
5594*2d7be507SJakub Kicinski 	dst = yarg->data;
5595*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
5596*2d7be507SJakub Kicinski 
5597*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
5598*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
5599*2d7be507SJakub Kicinski 
5600*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_PLCA_HEADER) {
5601*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5602*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5603*2d7be507SJakub Kicinski 			dst->_present.header = 1;
5604*2d7be507SJakub Kicinski 
5605*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
5606*2d7be507SJakub Kicinski 			parg.data = &dst->header;
5607*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
5608*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5609*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PLCA_VERSION) {
5610*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5611*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5612*2d7be507SJakub Kicinski 			dst->_present.version = 1;
5613*2d7be507SJakub Kicinski 			dst->version = mnl_attr_get_u16(attr);
5614*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PLCA_ENABLED) {
5615*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5616*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5617*2d7be507SJakub Kicinski 			dst->_present.enabled = 1;
5618*2d7be507SJakub Kicinski 			dst->enabled = mnl_attr_get_u8(attr);
5619*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PLCA_STATUS) {
5620*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5621*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5622*2d7be507SJakub Kicinski 			dst->_present.status = 1;
5623*2d7be507SJakub Kicinski 			dst->status = mnl_attr_get_u8(attr);
5624*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PLCA_NODE_CNT) {
5625*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5626*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5627*2d7be507SJakub Kicinski 			dst->_present.node_cnt = 1;
5628*2d7be507SJakub Kicinski 			dst->node_cnt = mnl_attr_get_u32(attr);
5629*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PLCA_NODE_ID) {
5630*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5631*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5632*2d7be507SJakub Kicinski 			dst->_present.node_id = 1;
5633*2d7be507SJakub Kicinski 			dst->node_id = mnl_attr_get_u32(attr);
5634*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PLCA_TO_TMR) {
5635*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5636*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5637*2d7be507SJakub Kicinski 			dst->_present.to_tmr = 1;
5638*2d7be507SJakub Kicinski 			dst->to_tmr = mnl_attr_get_u32(attr);
5639*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PLCA_BURST_CNT) {
5640*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5641*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5642*2d7be507SJakub Kicinski 			dst->_present.burst_cnt = 1;
5643*2d7be507SJakub Kicinski 			dst->burst_cnt = mnl_attr_get_u32(attr);
5644*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PLCA_BURST_TMR) {
5645*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5646*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5647*2d7be507SJakub Kicinski 			dst->_present.burst_tmr = 1;
5648*2d7be507SJakub Kicinski 			dst->burst_tmr = mnl_attr_get_u32(attr);
5649*2d7be507SJakub Kicinski 		}
5650*2d7be507SJakub Kicinski 	}
5651*2d7be507SJakub Kicinski 
5652*2d7be507SJakub Kicinski 	return MNL_CB_OK;
5653*2d7be507SJakub Kicinski }
5654*2d7be507SJakub Kicinski 
5655*2d7be507SJakub Kicinski struct ethtool_plca_get_cfg_rsp *
ethtool_plca_get_cfg(struct ynl_sock * ys,struct ethtool_plca_get_cfg_req * req)5656*2d7be507SJakub Kicinski ethtool_plca_get_cfg(struct ynl_sock *ys, struct ethtool_plca_get_cfg_req *req)
5657*2d7be507SJakub Kicinski {
5658*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
5659*2d7be507SJakub Kicinski 	struct ethtool_plca_get_cfg_rsp *rsp;
5660*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
5661*2d7be507SJakub Kicinski 	int err;
5662*2d7be507SJakub Kicinski 
5663*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PLCA_GET_CFG, 1);
5664*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_plca_nest;
5665*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_plca_nest;
5666*2d7be507SJakub Kicinski 
5667*2d7be507SJakub Kicinski 	if (req->_present.header)
5668*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_PLCA_HEADER, &req->header);
5669*2d7be507SJakub Kicinski 
5670*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
5671*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
5672*2d7be507SJakub Kicinski 	yrs.cb = ethtool_plca_get_cfg_rsp_parse;
5673*2d7be507SJakub Kicinski 	yrs.rsp_cmd = ETHTOOL_MSG_PLCA_GET_CFG;
5674*2d7be507SJakub Kicinski 
5675*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
5676*2d7be507SJakub Kicinski 	if (err < 0)
5677*2d7be507SJakub Kicinski 		goto err_free;
5678*2d7be507SJakub Kicinski 
5679*2d7be507SJakub Kicinski 	return rsp;
5680*2d7be507SJakub Kicinski 
5681*2d7be507SJakub Kicinski err_free:
5682*2d7be507SJakub Kicinski 	ethtool_plca_get_cfg_rsp_free(rsp);
5683*2d7be507SJakub Kicinski 	return NULL;
5684*2d7be507SJakub Kicinski }
5685*2d7be507SJakub Kicinski 
5686*2d7be507SJakub Kicinski /* ETHTOOL_MSG_PLCA_GET_CFG - dump */
ethtool_plca_get_cfg_list_free(struct ethtool_plca_get_cfg_list * rsp)5687*2d7be507SJakub Kicinski void ethtool_plca_get_cfg_list_free(struct ethtool_plca_get_cfg_list *rsp)
5688*2d7be507SJakub Kicinski {
5689*2d7be507SJakub Kicinski 	struct ethtool_plca_get_cfg_list *next = rsp;
5690*2d7be507SJakub Kicinski 
5691*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
5692*2d7be507SJakub Kicinski 		rsp = next;
5693*2d7be507SJakub Kicinski 		next = rsp->next;
5694*2d7be507SJakub Kicinski 
5695*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
5696*2d7be507SJakub Kicinski 		free(rsp);
5697*2d7be507SJakub Kicinski 	}
5698*2d7be507SJakub Kicinski }
5699*2d7be507SJakub Kicinski 
5700*2d7be507SJakub Kicinski struct ethtool_plca_get_cfg_list *
ethtool_plca_get_cfg_dump(struct ynl_sock * ys,struct ethtool_plca_get_cfg_req_dump * req)5701*2d7be507SJakub Kicinski ethtool_plca_get_cfg_dump(struct ynl_sock *ys,
5702*2d7be507SJakub Kicinski 			  struct ethtool_plca_get_cfg_req_dump *req)
5703*2d7be507SJakub Kicinski {
5704*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
5705*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
5706*2d7be507SJakub Kicinski 	int err;
5707*2d7be507SJakub Kicinski 
5708*2d7be507SJakub Kicinski 	yds.ys = ys;
5709*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_plca_get_cfg_list);
5710*2d7be507SJakub Kicinski 	yds.cb = ethtool_plca_get_cfg_rsp_parse;
5711*2d7be507SJakub Kicinski 	yds.rsp_cmd = ETHTOOL_MSG_PLCA_GET_CFG;
5712*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_plca_nest;
5713*2d7be507SJakub Kicinski 
5714*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_PLCA_GET_CFG, 1);
5715*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_plca_nest;
5716*2d7be507SJakub Kicinski 
5717*2d7be507SJakub Kicinski 	if (req->_present.header)
5718*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_PLCA_HEADER, &req->header);
5719*2d7be507SJakub Kicinski 
5720*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
5721*2d7be507SJakub Kicinski 	if (err < 0)
5722*2d7be507SJakub Kicinski 		goto free_list;
5723*2d7be507SJakub Kicinski 
5724*2d7be507SJakub Kicinski 	return yds.first;
5725*2d7be507SJakub Kicinski 
5726*2d7be507SJakub Kicinski free_list:
5727*2d7be507SJakub Kicinski 	ethtool_plca_get_cfg_list_free(yds.first);
5728*2d7be507SJakub Kicinski 	return NULL;
5729*2d7be507SJakub Kicinski }
5730*2d7be507SJakub Kicinski 
5731*2d7be507SJakub Kicinski /* ETHTOOL_MSG_PLCA_GET_CFG - notify */
ethtool_plca_get_cfg_ntf_free(struct ethtool_plca_get_cfg_ntf * rsp)5732*2d7be507SJakub Kicinski void ethtool_plca_get_cfg_ntf_free(struct ethtool_plca_get_cfg_ntf *rsp)
5733*2d7be507SJakub Kicinski {
5734*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->obj.header);
5735*2d7be507SJakub Kicinski 	free(rsp);
5736*2d7be507SJakub Kicinski }
5737*2d7be507SJakub Kicinski 
5738*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_PLCA_SET_CFG ============== */
5739*2d7be507SJakub Kicinski /* ETHTOOL_MSG_PLCA_SET_CFG - do */
ethtool_plca_set_cfg_req_free(struct ethtool_plca_set_cfg_req * req)5740*2d7be507SJakub Kicinski void ethtool_plca_set_cfg_req_free(struct ethtool_plca_set_cfg_req *req)
5741*2d7be507SJakub Kicinski {
5742*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
5743*2d7be507SJakub Kicinski 	free(req);
5744*2d7be507SJakub Kicinski }
5745*2d7be507SJakub Kicinski 
ethtool_plca_set_cfg(struct ynl_sock * ys,struct ethtool_plca_set_cfg_req * req)5746*2d7be507SJakub Kicinski int ethtool_plca_set_cfg(struct ynl_sock *ys,
5747*2d7be507SJakub Kicinski 			 struct ethtool_plca_set_cfg_req *req)
5748*2d7be507SJakub Kicinski {
5749*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
5750*2d7be507SJakub Kicinski 	int err;
5751*2d7be507SJakub Kicinski 
5752*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PLCA_SET_CFG, 1);
5753*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_plca_nest;
5754*2d7be507SJakub Kicinski 
5755*2d7be507SJakub Kicinski 	if (req->_present.header)
5756*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_PLCA_HEADER, &req->header);
5757*2d7be507SJakub Kicinski 	if (req->_present.version)
5758*2d7be507SJakub Kicinski 		mnl_attr_put_u16(nlh, ETHTOOL_A_PLCA_VERSION, req->version);
5759*2d7be507SJakub Kicinski 	if (req->_present.enabled)
5760*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_PLCA_ENABLED, req->enabled);
5761*2d7be507SJakub Kicinski 	if (req->_present.status)
5762*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_PLCA_STATUS, req->status);
5763*2d7be507SJakub Kicinski 	if (req->_present.node_cnt)
5764*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_PLCA_NODE_CNT, req->node_cnt);
5765*2d7be507SJakub Kicinski 	if (req->_present.node_id)
5766*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_PLCA_NODE_ID, req->node_id);
5767*2d7be507SJakub Kicinski 	if (req->_present.to_tmr)
5768*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_PLCA_TO_TMR, req->to_tmr);
5769*2d7be507SJakub Kicinski 	if (req->_present.burst_cnt)
5770*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_PLCA_BURST_CNT, req->burst_cnt);
5771*2d7be507SJakub Kicinski 	if (req->_present.burst_tmr)
5772*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_PLCA_BURST_TMR, req->burst_tmr);
5773*2d7be507SJakub Kicinski 
5774*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, NULL);
5775*2d7be507SJakub Kicinski 	if (err < 0)
5776*2d7be507SJakub Kicinski 		return -1;
5777*2d7be507SJakub Kicinski 
5778*2d7be507SJakub Kicinski 	return 0;
5779*2d7be507SJakub Kicinski }
5780*2d7be507SJakub Kicinski 
5781*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_PLCA_GET_STATUS ============== */
5782*2d7be507SJakub Kicinski /* ETHTOOL_MSG_PLCA_GET_STATUS - do */
ethtool_plca_get_status_req_free(struct ethtool_plca_get_status_req * req)5783*2d7be507SJakub Kicinski void ethtool_plca_get_status_req_free(struct ethtool_plca_get_status_req *req)
5784*2d7be507SJakub Kicinski {
5785*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
5786*2d7be507SJakub Kicinski 	free(req);
5787*2d7be507SJakub Kicinski }
5788*2d7be507SJakub Kicinski 
ethtool_plca_get_status_rsp_free(struct ethtool_plca_get_status_rsp * rsp)5789*2d7be507SJakub Kicinski void ethtool_plca_get_status_rsp_free(struct ethtool_plca_get_status_rsp *rsp)
5790*2d7be507SJakub Kicinski {
5791*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
5792*2d7be507SJakub Kicinski 	free(rsp);
5793*2d7be507SJakub Kicinski }
5794*2d7be507SJakub Kicinski 
ethtool_plca_get_status_rsp_parse(const struct nlmsghdr * nlh,void * data)5795*2d7be507SJakub Kicinski int ethtool_plca_get_status_rsp_parse(const struct nlmsghdr *nlh, void *data)
5796*2d7be507SJakub Kicinski {
5797*2d7be507SJakub Kicinski 	struct ethtool_plca_get_status_rsp *dst;
5798*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
5799*2d7be507SJakub Kicinski 	const struct nlattr *attr;
5800*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
5801*2d7be507SJakub Kicinski 
5802*2d7be507SJakub Kicinski 	dst = yarg->data;
5803*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
5804*2d7be507SJakub Kicinski 
5805*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
5806*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
5807*2d7be507SJakub Kicinski 
5808*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_PLCA_HEADER) {
5809*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5810*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5811*2d7be507SJakub Kicinski 			dst->_present.header = 1;
5812*2d7be507SJakub Kicinski 
5813*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
5814*2d7be507SJakub Kicinski 			parg.data = &dst->header;
5815*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
5816*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5817*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PLCA_VERSION) {
5818*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5819*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5820*2d7be507SJakub Kicinski 			dst->_present.version = 1;
5821*2d7be507SJakub Kicinski 			dst->version = mnl_attr_get_u16(attr);
5822*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PLCA_ENABLED) {
5823*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5824*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5825*2d7be507SJakub Kicinski 			dst->_present.enabled = 1;
5826*2d7be507SJakub Kicinski 			dst->enabled = mnl_attr_get_u8(attr);
5827*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PLCA_STATUS) {
5828*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5829*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5830*2d7be507SJakub Kicinski 			dst->_present.status = 1;
5831*2d7be507SJakub Kicinski 			dst->status = mnl_attr_get_u8(attr);
5832*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PLCA_NODE_CNT) {
5833*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5834*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5835*2d7be507SJakub Kicinski 			dst->_present.node_cnt = 1;
5836*2d7be507SJakub Kicinski 			dst->node_cnt = mnl_attr_get_u32(attr);
5837*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PLCA_NODE_ID) {
5838*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5839*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5840*2d7be507SJakub Kicinski 			dst->_present.node_id = 1;
5841*2d7be507SJakub Kicinski 			dst->node_id = mnl_attr_get_u32(attr);
5842*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PLCA_TO_TMR) {
5843*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5844*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5845*2d7be507SJakub Kicinski 			dst->_present.to_tmr = 1;
5846*2d7be507SJakub Kicinski 			dst->to_tmr = mnl_attr_get_u32(attr);
5847*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PLCA_BURST_CNT) {
5848*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5849*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5850*2d7be507SJakub Kicinski 			dst->_present.burst_cnt = 1;
5851*2d7be507SJakub Kicinski 			dst->burst_cnt = mnl_attr_get_u32(attr);
5852*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_PLCA_BURST_TMR) {
5853*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5854*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5855*2d7be507SJakub Kicinski 			dst->_present.burst_tmr = 1;
5856*2d7be507SJakub Kicinski 			dst->burst_tmr = mnl_attr_get_u32(attr);
5857*2d7be507SJakub Kicinski 		}
5858*2d7be507SJakub Kicinski 	}
5859*2d7be507SJakub Kicinski 
5860*2d7be507SJakub Kicinski 	return MNL_CB_OK;
5861*2d7be507SJakub Kicinski }
5862*2d7be507SJakub Kicinski 
5863*2d7be507SJakub Kicinski struct ethtool_plca_get_status_rsp *
ethtool_plca_get_status(struct ynl_sock * ys,struct ethtool_plca_get_status_req * req)5864*2d7be507SJakub Kicinski ethtool_plca_get_status(struct ynl_sock *ys,
5865*2d7be507SJakub Kicinski 			struct ethtool_plca_get_status_req *req)
5866*2d7be507SJakub Kicinski {
5867*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
5868*2d7be507SJakub Kicinski 	struct ethtool_plca_get_status_rsp *rsp;
5869*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
5870*2d7be507SJakub Kicinski 	int err;
5871*2d7be507SJakub Kicinski 
5872*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PLCA_GET_STATUS, 1);
5873*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_plca_nest;
5874*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_plca_nest;
5875*2d7be507SJakub Kicinski 
5876*2d7be507SJakub Kicinski 	if (req->_present.header)
5877*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_PLCA_HEADER, &req->header);
5878*2d7be507SJakub Kicinski 
5879*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
5880*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
5881*2d7be507SJakub Kicinski 	yrs.cb = ethtool_plca_get_status_rsp_parse;
5882*2d7be507SJakub Kicinski 	yrs.rsp_cmd = 40;
5883*2d7be507SJakub Kicinski 
5884*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
5885*2d7be507SJakub Kicinski 	if (err < 0)
5886*2d7be507SJakub Kicinski 		goto err_free;
5887*2d7be507SJakub Kicinski 
5888*2d7be507SJakub Kicinski 	return rsp;
5889*2d7be507SJakub Kicinski 
5890*2d7be507SJakub Kicinski err_free:
5891*2d7be507SJakub Kicinski 	ethtool_plca_get_status_rsp_free(rsp);
5892*2d7be507SJakub Kicinski 	return NULL;
5893*2d7be507SJakub Kicinski }
5894*2d7be507SJakub Kicinski 
5895*2d7be507SJakub Kicinski /* ETHTOOL_MSG_PLCA_GET_STATUS - dump */
5896*2d7be507SJakub Kicinski void
ethtool_plca_get_status_list_free(struct ethtool_plca_get_status_list * rsp)5897*2d7be507SJakub Kicinski ethtool_plca_get_status_list_free(struct ethtool_plca_get_status_list *rsp)
5898*2d7be507SJakub Kicinski {
5899*2d7be507SJakub Kicinski 	struct ethtool_plca_get_status_list *next = rsp;
5900*2d7be507SJakub Kicinski 
5901*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
5902*2d7be507SJakub Kicinski 		rsp = next;
5903*2d7be507SJakub Kicinski 		next = rsp->next;
5904*2d7be507SJakub Kicinski 
5905*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
5906*2d7be507SJakub Kicinski 		free(rsp);
5907*2d7be507SJakub Kicinski 	}
5908*2d7be507SJakub Kicinski }
5909*2d7be507SJakub Kicinski 
5910*2d7be507SJakub Kicinski struct ethtool_plca_get_status_list *
ethtool_plca_get_status_dump(struct ynl_sock * ys,struct ethtool_plca_get_status_req_dump * req)5911*2d7be507SJakub Kicinski ethtool_plca_get_status_dump(struct ynl_sock *ys,
5912*2d7be507SJakub Kicinski 			     struct ethtool_plca_get_status_req_dump *req)
5913*2d7be507SJakub Kicinski {
5914*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
5915*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
5916*2d7be507SJakub Kicinski 	int err;
5917*2d7be507SJakub Kicinski 
5918*2d7be507SJakub Kicinski 	yds.ys = ys;
5919*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_plca_get_status_list);
5920*2d7be507SJakub Kicinski 	yds.cb = ethtool_plca_get_status_rsp_parse;
5921*2d7be507SJakub Kicinski 	yds.rsp_cmd = 40;
5922*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_plca_nest;
5923*2d7be507SJakub Kicinski 
5924*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_PLCA_GET_STATUS, 1);
5925*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_plca_nest;
5926*2d7be507SJakub Kicinski 
5927*2d7be507SJakub Kicinski 	if (req->_present.header)
5928*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_PLCA_HEADER, &req->header);
5929*2d7be507SJakub Kicinski 
5930*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
5931*2d7be507SJakub Kicinski 	if (err < 0)
5932*2d7be507SJakub Kicinski 		goto free_list;
5933*2d7be507SJakub Kicinski 
5934*2d7be507SJakub Kicinski 	return yds.first;
5935*2d7be507SJakub Kicinski 
5936*2d7be507SJakub Kicinski free_list:
5937*2d7be507SJakub Kicinski 	ethtool_plca_get_status_list_free(yds.first);
5938*2d7be507SJakub Kicinski 	return NULL;
5939*2d7be507SJakub Kicinski }
5940*2d7be507SJakub Kicinski 
5941*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_MM_GET ============== */
5942*2d7be507SJakub Kicinski /* ETHTOOL_MSG_MM_GET - do */
ethtool_mm_get_req_free(struct ethtool_mm_get_req * req)5943*2d7be507SJakub Kicinski void ethtool_mm_get_req_free(struct ethtool_mm_get_req *req)
5944*2d7be507SJakub Kicinski {
5945*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
5946*2d7be507SJakub Kicinski 	free(req);
5947*2d7be507SJakub Kicinski }
5948*2d7be507SJakub Kicinski 
ethtool_mm_get_rsp_free(struct ethtool_mm_get_rsp * rsp)5949*2d7be507SJakub Kicinski void ethtool_mm_get_rsp_free(struct ethtool_mm_get_rsp *rsp)
5950*2d7be507SJakub Kicinski {
5951*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->header);
5952*2d7be507SJakub Kicinski 	ethtool_mm_stat_free(&rsp->stats);
5953*2d7be507SJakub Kicinski 	free(rsp);
5954*2d7be507SJakub Kicinski }
5955*2d7be507SJakub Kicinski 
ethtool_mm_get_rsp_parse(const struct nlmsghdr * nlh,void * data)5956*2d7be507SJakub Kicinski int ethtool_mm_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
5957*2d7be507SJakub Kicinski {
5958*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
5959*2d7be507SJakub Kicinski 	struct ethtool_mm_get_rsp *dst;
5960*2d7be507SJakub Kicinski 	const struct nlattr *attr;
5961*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
5962*2d7be507SJakub Kicinski 
5963*2d7be507SJakub Kicinski 	dst = yarg->data;
5964*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
5965*2d7be507SJakub Kicinski 
5966*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
5967*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
5968*2d7be507SJakub Kicinski 
5969*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_MM_HEADER) {
5970*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5971*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5972*2d7be507SJakub Kicinski 			dst->_present.header = 1;
5973*2d7be507SJakub Kicinski 
5974*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
5975*2d7be507SJakub Kicinski 			parg.data = &dst->header;
5976*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
5977*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5978*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MM_PMAC_ENABLED) {
5979*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5980*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5981*2d7be507SJakub Kicinski 			dst->_present.pmac_enabled = 1;
5982*2d7be507SJakub Kicinski 			dst->pmac_enabled = mnl_attr_get_u8(attr);
5983*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MM_TX_ENABLED) {
5984*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5985*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5986*2d7be507SJakub Kicinski 			dst->_present.tx_enabled = 1;
5987*2d7be507SJakub Kicinski 			dst->tx_enabled = mnl_attr_get_u8(attr);
5988*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MM_TX_ACTIVE) {
5989*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5990*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5991*2d7be507SJakub Kicinski 			dst->_present.tx_active = 1;
5992*2d7be507SJakub Kicinski 			dst->tx_active = mnl_attr_get_u8(attr);
5993*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MM_TX_MIN_FRAG_SIZE) {
5994*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5995*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
5996*2d7be507SJakub Kicinski 			dst->_present.tx_min_frag_size = 1;
5997*2d7be507SJakub Kicinski 			dst->tx_min_frag_size = mnl_attr_get_u32(attr);
5998*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MM_RX_MIN_FRAG_SIZE) {
5999*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
6000*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
6001*2d7be507SJakub Kicinski 			dst->_present.rx_min_frag_size = 1;
6002*2d7be507SJakub Kicinski 			dst->rx_min_frag_size = mnl_attr_get_u32(attr);
6003*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MM_VERIFY_ENABLED) {
6004*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
6005*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
6006*2d7be507SJakub Kicinski 			dst->_present.verify_enabled = 1;
6007*2d7be507SJakub Kicinski 			dst->verify_enabled = mnl_attr_get_u8(attr);
6008*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MM_VERIFY_TIME) {
6009*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
6010*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
6011*2d7be507SJakub Kicinski 			dst->_present.verify_time = 1;
6012*2d7be507SJakub Kicinski 			dst->verify_time = mnl_attr_get_u32(attr);
6013*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MM_MAX_VERIFY_TIME) {
6014*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
6015*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
6016*2d7be507SJakub Kicinski 			dst->_present.max_verify_time = 1;
6017*2d7be507SJakub Kicinski 			dst->max_verify_time = mnl_attr_get_u32(attr);
6018*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_MM_STATS) {
6019*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
6020*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
6021*2d7be507SJakub Kicinski 			dst->_present.stats = 1;
6022*2d7be507SJakub Kicinski 
6023*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_mm_stat_nest;
6024*2d7be507SJakub Kicinski 			parg.data = &dst->stats;
6025*2d7be507SJakub Kicinski 			if (ethtool_mm_stat_parse(&parg, attr))
6026*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
6027*2d7be507SJakub Kicinski 		}
6028*2d7be507SJakub Kicinski 	}
6029*2d7be507SJakub Kicinski 
6030*2d7be507SJakub Kicinski 	return MNL_CB_OK;
6031*2d7be507SJakub Kicinski }
6032*2d7be507SJakub Kicinski 
6033*2d7be507SJakub Kicinski struct ethtool_mm_get_rsp *
ethtool_mm_get(struct ynl_sock * ys,struct ethtool_mm_get_req * req)6034*2d7be507SJakub Kicinski ethtool_mm_get(struct ynl_sock *ys, struct ethtool_mm_get_req *req)
6035*2d7be507SJakub Kicinski {
6036*2d7be507SJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
6037*2d7be507SJakub Kicinski 	struct ethtool_mm_get_rsp *rsp;
6038*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
6039*2d7be507SJakub Kicinski 	int err;
6040*2d7be507SJakub Kicinski 
6041*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_MM_GET, 1);
6042*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_mm_nest;
6043*2d7be507SJakub Kicinski 	yrs.yarg.rsp_policy = &ethtool_mm_nest;
6044*2d7be507SJakub Kicinski 
6045*2d7be507SJakub Kicinski 	if (req->_present.header)
6046*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_MM_HEADER, &req->header);
6047*2d7be507SJakub Kicinski 
6048*2d7be507SJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
6049*2d7be507SJakub Kicinski 	yrs.yarg.data = rsp;
6050*2d7be507SJakub Kicinski 	yrs.cb = ethtool_mm_get_rsp_parse;
6051*2d7be507SJakub Kicinski 	yrs.rsp_cmd = ETHTOOL_MSG_MM_GET;
6052*2d7be507SJakub Kicinski 
6053*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
6054*2d7be507SJakub Kicinski 	if (err < 0)
6055*2d7be507SJakub Kicinski 		goto err_free;
6056*2d7be507SJakub Kicinski 
6057*2d7be507SJakub Kicinski 	return rsp;
6058*2d7be507SJakub Kicinski 
6059*2d7be507SJakub Kicinski err_free:
6060*2d7be507SJakub Kicinski 	ethtool_mm_get_rsp_free(rsp);
6061*2d7be507SJakub Kicinski 	return NULL;
6062*2d7be507SJakub Kicinski }
6063*2d7be507SJakub Kicinski 
6064*2d7be507SJakub Kicinski /* ETHTOOL_MSG_MM_GET - dump */
ethtool_mm_get_list_free(struct ethtool_mm_get_list * rsp)6065*2d7be507SJakub Kicinski void ethtool_mm_get_list_free(struct ethtool_mm_get_list *rsp)
6066*2d7be507SJakub Kicinski {
6067*2d7be507SJakub Kicinski 	struct ethtool_mm_get_list *next = rsp;
6068*2d7be507SJakub Kicinski 
6069*2d7be507SJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
6070*2d7be507SJakub Kicinski 		rsp = next;
6071*2d7be507SJakub Kicinski 		next = rsp->next;
6072*2d7be507SJakub Kicinski 
6073*2d7be507SJakub Kicinski 		ethtool_header_free(&rsp->obj.header);
6074*2d7be507SJakub Kicinski 		ethtool_mm_stat_free(&rsp->obj.stats);
6075*2d7be507SJakub Kicinski 		free(rsp);
6076*2d7be507SJakub Kicinski 	}
6077*2d7be507SJakub Kicinski }
6078*2d7be507SJakub Kicinski 
6079*2d7be507SJakub Kicinski struct ethtool_mm_get_list *
ethtool_mm_get_dump(struct ynl_sock * ys,struct ethtool_mm_get_req_dump * req)6080*2d7be507SJakub Kicinski ethtool_mm_get_dump(struct ynl_sock *ys, struct ethtool_mm_get_req_dump *req)
6081*2d7be507SJakub Kicinski {
6082*2d7be507SJakub Kicinski 	struct ynl_dump_state yds = {};
6083*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
6084*2d7be507SJakub Kicinski 	int err;
6085*2d7be507SJakub Kicinski 
6086*2d7be507SJakub Kicinski 	yds.ys = ys;
6087*2d7be507SJakub Kicinski 	yds.alloc_sz = sizeof(struct ethtool_mm_get_list);
6088*2d7be507SJakub Kicinski 	yds.cb = ethtool_mm_get_rsp_parse;
6089*2d7be507SJakub Kicinski 	yds.rsp_cmd = ETHTOOL_MSG_MM_GET;
6090*2d7be507SJakub Kicinski 	yds.rsp_policy = &ethtool_mm_nest;
6091*2d7be507SJakub Kicinski 
6092*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_MM_GET, 1);
6093*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_mm_nest;
6094*2d7be507SJakub Kicinski 
6095*2d7be507SJakub Kicinski 	if (req->_present.header)
6096*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_MM_HEADER, &req->header);
6097*2d7be507SJakub Kicinski 
6098*2d7be507SJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
6099*2d7be507SJakub Kicinski 	if (err < 0)
6100*2d7be507SJakub Kicinski 		goto free_list;
6101*2d7be507SJakub Kicinski 
6102*2d7be507SJakub Kicinski 	return yds.first;
6103*2d7be507SJakub Kicinski 
6104*2d7be507SJakub Kicinski free_list:
6105*2d7be507SJakub Kicinski 	ethtool_mm_get_list_free(yds.first);
6106*2d7be507SJakub Kicinski 	return NULL;
6107*2d7be507SJakub Kicinski }
6108*2d7be507SJakub Kicinski 
6109*2d7be507SJakub Kicinski /* ETHTOOL_MSG_MM_GET - notify */
ethtool_mm_get_ntf_free(struct ethtool_mm_get_ntf * rsp)6110*2d7be507SJakub Kicinski void ethtool_mm_get_ntf_free(struct ethtool_mm_get_ntf *rsp)
6111*2d7be507SJakub Kicinski {
6112*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->obj.header);
6113*2d7be507SJakub Kicinski 	ethtool_mm_stat_free(&rsp->obj.stats);
6114*2d7be507SJakub Kicinski 	free(rsp);
6115*2d7be507SJakub Kicinski }
6116*2d7be507SJakub Kicinski 
6117*2d7be507SJakub Kicinski /* ============== ETHTOOL_MSG_MM_SET ============== */
6118*2d7be507SJakub Kicinski /* ETHTOOL_MSG_MM_SET - do */
ethtool_mm_set_req_free(struct ethtool_mm_set_req * req)6119*2d7be507SJakub Kicinski void ethtool_mm_set_req_free(struct ethtool_mm_set_req *req)
6120*2d7be507SJakub Kicinski {
6121*2d7be507SJakub Kicinski 	ethtool_header_free(&req->header);
6122*2d7be507SJakub Kicinski 	free(req);
6123*2d7be507SJakub Kicinski }
6124*2d7be507SJakub Kicinski 
ethtool_mm_set(struct ynl_sock * ys,struct ethtool_mm_set_req * req)6125*2d7be507SJakub Kicinski int ethtool_mm_set(struct ynl_sock *ys, struct ethtool_mm_set_req *req)
6126*2d7be507SJakub Kicinski {
6127*2d7be507SJakub Kicinski 	struct nlmsghdr *nlh;
6128*2d7be507SJakub Kicinski 	int err;
6129*2d7be507SJakub Kicinski 
6130*2d7be507SJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_MM_SET, 1);
6131*2d7be507SJakub Kicinski 	ys->req_policy = &ethtool_mm_nest;
6132*2d7be507SJakub Kicinski 
6133*2d7be507SJakub Kicinski 	if (req->_present.header)
6134*2d7be507SJakub Kicinski 		ethtool_header_put(nlh, ETHTOOL_A_MM_HEADER, &req->header);
6135*2d7be507SJakub Kicinski 	if (req->_present.verify_enabled)
6136*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_MM_VERIFY_ENABLED, req->verify_enabled);
6137*2d7be507SJakub Kicinski 	if (req->_present.verify_time)
6138*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_MM_VERIFY_TIME, req->verify_time);
6139*2d7be507SJakub Kicinski 	if (req->_present.tx_enabled)
6140*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_MM_TX_ENABLED, req->tx_enabled);
6141*2d7be507SJakub Kicinski 	if (req->_present.pmac_enabled)
6142*2d7be507SJakub Kicinski 		mnl_attr_put_u8(nlh, ETHTOOL_A_MM_PMAC_ENABLED, req->pmac_enabled);
6143*2d7be507SJakub Kicinski 	if (req->_present.tx_min_frag_size)
6144*2d7be507SJakub Kicinski 		mnl_attr_put_u32(nlh, ETHTOOL_A_MM_TX_MIN_FRAG_SIZE, req->tx_min_frag_size);
6145*2d7be507SJakub Kicinski 
6146*2d7be507SJakub Kicinski 	err = ynl_exec(ys, nlh, NULL);
6147*2d7be507SJakub Kicinski 	if (err < 0)
6148*2d7be507SJakub Kicinski 		return -1;
6149*2d7be507SJakub Kicinski 
6150*2d7be507SJakub Kicinski 	return 0;
6151*2d7be507SJakub Kicinski }
6152*2d7be507SJakub Kicinski 
6153*2d7be507SJakub Kicinski /* ETHTOOL_MSG_CABLE_TEST_NTF - event */
ethtool_cable_test_ntf_rsp_parse(const struct nlmsghdr * nlh,void * data)6154*2d7be507SJakub Kicinski int ethtool_cable_test_ntf_rsp_parse(const struct nlmsghdr *nlh, void *data)
6155*2d7be507SJakub Kicinski {
6156*2d7be507SJakub Kicinski 	struct ethtool_cable_test_ntf_rsp *dst;
6157*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
6158*2d7be507SJakub Kicinski 	const struct nlattr *attr;
6159*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
6160*2d7be507SJakub Kicinski 
6161*2d7be507SJakub Kicinski 	dst = yarg->data;
6162*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
6163*2d7be507SJakub Kicinski 
6164*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
6165*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
6166*2d7be507SJakub Kicinski 
6167*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_CABLE_TEST_NTF_HEADER) {
6168*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
6169*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
6170*2d7be507SJakub Kicinski 			dst->_present.header = 1;
6171*2d7be507SJakub Kicinski 
6172*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
6173*2d7be507SJakub Kicinski 			parg.data = &dst->header;
6174*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
6175*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
6176*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_CABLE_TEST_NTF_STATUS) {
6177*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
6178*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
6179*2d7be507SJakub Kicinski 			dst->_present.status = 1;
6180*2d7be507SJakub Kicinski 			dst->status = mnl_attr_get_u8(attr);
6181*2d7be507SJakub Kicinski 		}
6182*2d7be507SJakub Kicinski 	}
6183*2d7be507SJakub Kicinski 
6184*2d7be507SJakub Kicinski 	return MNL_CB_OK;
6185*2d7be507SJakub Kicinski }
6186*2d7be507SJakub Kicinski 
ethtool_cable_test_ntf_free(struct ethtool_cable_test_ntf * rsp)6187*2d7be507SJakub Kicinski void ethtool_cable_test_ntf_free(struct ethtool_cable_test_ntf *rsp)
6188*2d7be507SJakub Kicinski {
6189*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->obj.header);
6190*2d7be507SJakub Kicinski 	free(rsp);
6191*2d7be507SJakub Kicinski }
6192*2d7be507SJakub Kicinski 
6193*2d7be507SJakub Kicinski /* ETHTOOL_MSG_CABLE_TEST_TDR_NTF - event */
ethtool_cable_test_tdr_ntf_rsp_parse(const struct nlmsghdr * nlh,void * data)6194*2d7be507SJakub Kicinski int ethtool_cable_test_tdr_ntf_rsp_parse(const struct nlmsghdr *nlh,
6195*2d7be507SJakub Kicinski 					 void *data)
6196*2d7be507SJakub Kicinski {
6197*2d7be507SJakub Kicinski 	struct ethtool_cable_test_tdr_ntf_rsp *dst;
6198*2d7be507SJakub Kicinski 	struct ynl_parse_arg *yarg = data;
6199*2d7be507SJakub Kicinski 	const struct nlattr *attr;
6200*2d7be507SJakub Kicinski 	struct ynl_parse_arg parg;
6201*2d7be507SJakub Kicinski 
6202*2d7be507SJakub Kicinski 	dst = yarg->data;
6203*2d7be507SJakub Kicinski 	parg.ys = yarg->ys;
6204*2d7be507SJakub Kicinski 
6205*2d7be507SJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
6206*2d7be507SJakub Kicinski 		unsigned int type = mnl_attr_get_type(attr);
6207*2d7be507SJakub Kicinski 
6208*2d7be507SJakub Kicinski 		if (type == ETHTOOL_A_CABLE_TEST_TDR_NTF_HEADER) {
6209*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
6210*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
6211*2d7be507SJakub Kicinski 			dst->_present.header = 1;
6212*2d7be507SJakub Kicinski 
6213*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_header_nest;
6214*2d7be507SJakub Kicinski 			parg.data = &dst->header;
6215*2d7be507SJakub Kicinski 			if (ethtool_header_parse(&parg, attr))
6216*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
6217*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_CABLE_TEST_TDR_NTF_STATUS) {
6218*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
6219*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
6220*2d7be507SJakub Kicinski 			dst->_present.status = 1;
6221*2d7be507SJakub Kicinski 			dst->status = mnl_attr_get_u8(attr);
6222*2d7be507SJakub Kicinski 		} else if (type == ETHTOOL_A_CABLE_TEST_TDR_NTF_NEST) {
6223*2d7be507SJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
6224*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
6225*2d7be507SJakub Kicinski 			dst->_present.nest = 1;
6226*2d7be507SJakub Kicinski 
6227*2d7be507SJakub Kicinski 			parg.rsp_policy = &ethtool_cable_nest_nest;
6228*2d7be507SJakub Kicinski 			parg.data = &dst->nest;
6229*2d7be507SJakub Kicinski 			if (ethtool_cable_nest_parse(&parg, attr))
6230*2d7be507SJakub Kicinski 				return MNL_CB_ERROR;
6231*2d7be507SJakub Kicinski 		}
6232*2d7be507SJakub Kicinski 	}
6233*2d7be507SJakub Kicinski 
6234*2d7be507SJakub Kicinski 	return MNL_CB_OK;
6235*2d7be507SJakub Kicinski }
6236*2d7be507SJakub Kicinski 
ethtool_cable_test_tdr_ntf_free(struct ethtool_cable_test_tdr_ntf * rsp)6237*2d7be507SJakub Kicinski void ethtool_cable_test_tdr_ntf_free(struct ethtool_cable_test_tdr_ntf *rsp)
6238*2d7be507SJakub Kicinski {
6239*2d7be507SJakub Kicinski 	ethtool_header_free(&rsp->obj.header);
6240*2d7be507SJakub Kicinski 	ethtool_cable_nest_free(&rsp->obj.nest);
6241*2d7be507SJakub Kicinski 	free(rsp);
6242*2d7be507SJakub Kicinski }
6243*2d7be507SJakub Kicinski 
6244*2d7be507SJakub Kicinski static const struct ynl_ntf_info ethtool_ntf_info[] =  {
6245*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_LINKINFO_NTF] =  {
6246*2d7be507SJakub Kicinski 		.alloc_sz	= sizeof(struct ethtool_linkinfo_get_ntf),
6247*2d7be507SJakub Kicinski 		.cb		= ethtool_linkinfo_get_rsp_parse,
6248*2d7be507SJakub Kicinski 		.policy		= &ethtool_linkinfo_nest,
6249*2d7be507SJakub Kicinski 		.free		= (void *)ethtool_linkinfo_get_ntf_free,
6250*2d7be507SJakub Kicinski 	},
6251*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_LINKMODES_NTF] =  {
6252*2d7be507SJakub Kicinski 		.alloc_sz	= sizeof(struct ethtool_linkmodes_get_ntf),
6253*2d7be507SJakub Kicinski 		.cb		= ethtool_linkmodes_get_rsp_parse,
6254*2d7be507SJakub Kicinski 		.policy		= &ethtool_linkmodes_nest,
6255*2d7be507SJakub Kicinski 		.free		= (void *)ethtool_linkmodes_get_ntf_free,
6256*2d7be507SJakub Kicinski 	},
6257*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_DEBUG_NTF] =  {
6258*2d7be507SJakub Kicinski 		.alloc_sz	= sizeof(struct ethtool_debug_get_ntf),
6259*2d7be507SJakub Kicinski 		.cb		= ethtool_debug_get_rsp_parse,
6260*2d7be507SJakub Kicinski 		.policy		= &ethtool_debug_nest,
6261*2d7be507SJakub Kicinski 		.free		= (void *)ethtool_debug_get_ntf_free,
6262*2d7be507SJakub Kicinski 	},
6263*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_WOL_NTF] =  {
6264*2d7be507SJakub Kicinski 		.alloc_sz	= sizeof(struct ethtool_wol_get_ntf),
6265*2d7be507SJakub Kicinski 		.cb		= ethtool_wol_get_rsp_parse,
6266*2d7be507SJakub Kicinski 		.policy		= &ethtool_wol_nest,
6267*2d7be507SJakub Kicinski 		.free		= (void *)ethtool_wol_get_ntf_free,
6268*2d7be507SJakub Kicinski 	},
6269*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_FEATURES_NTF] =  {
6270*2d7be507SJakub Kicinski 		.alloc_sz	= sizeof(struct ethtool_features_get_ntf),
6271*2d7be507SJakub Kicinski 		.cb		= ethtool_features_get_rsp_parse,
6272*2d7be507SJakub Kicinski 		.policy		= &ethtool_features_nest,
6273*2d7be507SJakub Kicinski 		.free		= (void *)ethtool_features_get_ntf_free,
6274*2d7be507SJakub Kicinski 	},
6275*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_PRIVFLAGS_NTF] =  {
6276*2d7be507SJakub Kicinski 		.alloc_sz	= sizeof(struct ethtool_privflags_get_ntf),
6277*2d7be507SJakub Kicinski 		.cb		= ethtool_privflags_get_rsp_parse,
6278*2d7be507SJakub Kicinski 		.policy		= &ethtool_privflags_nest,
6279*2d7be507SJakub Kicinski 		.free		= (void *)ethtool_privflags_get_ntf_free,
6280*2d7be507SJakub Kicinski 	},
6281*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_RINGS_NTF] =  {
6282*2d7be507SJakub Kicinski 		.alloc_sz	= sizeof(struct ethtool_rings_get_ntf),
6283*2d7be507SJakub Kicinski 		.cb		= ethtool_rings_get_rsp_parse,
6284*2d7be507SJakub Kicinski 		.policy		= &ethtool_rings_nest,
6285*2d7be507SJakub Kicinski 		.free		= (void *)ethtool_rings_get_ntf_free,
6286*2d7be507SJakub Kicinski 	},
6287*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_CHANNELS_NTF] =  {
6288*2d7be507SJakub Kicinski 		.alloc_sz	= sizeof(struct ethtool_channels_get_ntf),
6289*2d7be507SJakub Kicinski 		.cb		= ethtool_channels_get_rsp_parse,
6290*2d7be507SJakub Kicinski 		.policy		= &ethtool_channels_nest,
6291*2d7be507SJakub Kicinski 		.free		= (void *)ethtool_channels_get_ntf_free,
6292*2d7be507SJakub Kicinski 	},
6293*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_COALESCE_NTF] =  {
6294*2d7be507SJakub Kicinski 		.alloc_sz	= sizeof(struct ethtool_coalesce_get_ntf),
6295*2d7be507SJakub Kicinski 		.cb		= ethtool_coalesce_get_rsp_parse,
6296*2d7be507SJakub Kicinski 		.policy		= &ethtool_coalesce_nest,
6297*2d7be507SJakub Kicinski 		.free		= (void *)ethtool_coalesce_get_ntf_free,
6298*2d7be507SJakub Kicinski 	},
6299*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_PAUSE_NTF] =  {
6300*2d7be507SJakub Kicinski 		.alloc_sz	= sizeof(struct ethtool_pause_get_ntf),
6301*2d7be507SJakub Kicinski 		.cb		= ethtool_pause_get_rsp_parse,
6302*2d7be507SJakub Kicinski 		.policy		= &ethtool_pause_nest,
6303*2d7be507SJakub Kicinski 		.free		= (void *)ethtool_pause_get_ntf_free,
6304*2d7be507SJakub Kicinski 	},
6305*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_EEE_NTF] =  {
6306*2d7be507SJakub Kicinski 		.alloc_sz	= sizeof(struct ethtool_eee_get_ntf),
6307*2d7be507SJakub Kicinski 		.cb		= ethtool_eee_get_rsp_parse,
6308*2d7be507SJakub Kicinski 		.policy		= &ethtool_eee_nest,
6309*2d7be507SJakub Kicinski 		.free		= (void *)ethtool_eee_get_ntf_free,
6310*2d7be507SJakub Kicinski 	},
6311*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_CABLE_TEST_NTF] =  {
6312*2d7be507SJakub Kicinski 		.alloc_sz	= sizeof(struct ethtool_cable_test_ntf),
6313*2d7be507SJakub Kicinski 		.cb		= ethtool_cable_test_ntf_rsp_parse,
6314*2d7be507SJakub Kicinski 		.policy		= &ethtool_cable_test_ntf_nest,
6315*2d7be507SJakub Kicinski 		.free		= (void *)ethtool_cable_test_ntf_free,
6316*2d7be507SJakub Kicinski 	},
6317*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_CABLE_TEST_TDR_NTF] =  {
6318*2d7be507SJakub Kicinski 		.alloc_sz	= sizeof(struct ethtool_cable_test_tdr_ntf),
6319*2d7be507SJakub Kicinski 		.cb		= ethtool_cable_test_tdr_ntf_rsp_parse,
6320*2d7be507SJakub Kicinski 		.policy		= &ethtool_cable_test_tdr_ntf_nest,
6321*2d7be507SJakub Kicinski 		.free		= (void *)ethtool_cable_test_tdr_ntf_free,
6322*2d7be507SJakub Kicinski 	},
6323*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_FEC_NTF] =  {
6324*2d7be507SJakub Kicinski 		.alloc_sz	= sizeof(struct ethtool_fec_get_ntf),
6325*2d7be507SJakub Kicinski 		.cb		= ethtool_fec_get_rsp_parse,
6326*2d7be507SJakub Kicinski 		.policy		= &ethtool_fec_nest,
6327*2d7be507SJakub Kicinski 		.free		= (void *)ethtool_fec_get_ntf_free,
6328*2d7be507SJakub Kicinski 	},
6329*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_MODULE_NTF] =  {
6330*2d7be507SJakub Kicinski 		.alloc_sz	= sizeof(struct ethtool_module_get_ntf),
6331*2d7be507SJakub Kicinski 		.cb		= ethtool_module_get_rsp_parse,
6332*2d7be507SJakub Kicinski 		.policy		= &ethtool_module_nest,
6333*2d7be507SJakub Kicinski 		.free		= (void *)ethtool_module_get_ntf_free,
6334*2d7be507SJakub Kicinski 	},
6335*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_PLCA_NTF] =  {
6336*2d7be507SJakub Kicinski 		.alloc_sz	= sizeof(struct ethtool_plca_get_cfg_ntf),
6337*2d7be507SJakub Kicinski 		.cb		= ethtool_plca_get_cfg_rsp_parse,
6338*2d7be507SJakub Kicinski 		.policy		= &ethtool_plca_nest,
6339*2d7be507SJakub Kicinski 		.free		= (void *)ethtool_plca_get_cfg_ntf_free,
6340*2d7be507SJakub Kicinski 	},
6341*2d7be507SJakub Kicinski 	[ETHTOOL_MSG_MM_NTF] =  {
6342*2d7be507SJakub Kicinski 		.alloc_sz	= sizeof(struct ethtool_mm_get_ntf),
6343*2d7be507SJakub Kicinski 		.cb		= ethtool_mm_get_rsp_parse,
6344*2d7be507SJakub Kicinski 		.policy		= &ethtool_mm_nest,
6345*2d7be507SJakub Kicinski 		.free		= (void *)ethtool_mm_get_ntf_free,
6346*2d7be507SJakub Kicinski 	},
6347*2d7be507SJakub Kicinski };
6348*2d7be507SJakub Kicinski 
6349*2d7be507SJakub Kicinski const struct ynl_family ynl_ethtool_family =  {
6350*2d7be507SJakub Kicinski 	.name		= "ethtool",
6351*2d7be507SJakub Kicinski 	.ntf_info	= ethtool_ntf_info,
6352*2d7be507SJakub Kicinski 	.ntf_info_size	= MNL_ARRAY_SIZE(ethtool_ntf_info),
6353*2d7be507SJakub Kicinski };
6354