xref: /openbmc/linux/tools/net/ynl/generated/devlink-user.c (revision 5d1a30eb989afb22b60e7d3985984ebcb00bf598)
1*5d1a30ebSJakub Kicinski // SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
2*5d1a30ebSJakub Kicinski /* Do not edit directly, auto-generated from: */
3*5d1a30ebSJakub Kicinski /*	Documentation/netlink/specs/devlink.yaml */
4*5d1a30ebSJakub Kicinski /* YNL-GEN user source */
5*5d1a30ebSJakub Kicinski 
6*5d1a30ebSJakub Kicinski #include <stdlib.h>
7*5d1a30ebSJakub Kicinski #include "devlink-user.h"
8*5d1a30ebSJakub Kicinski #include "ynl.h"
9*5d1a30ebSJakub Kicinski #include <linux/devlink.h>
10*5d1a30ebSJakub Kicinski 
11*5d1a30ebSJakub Kicinski #include <stdlib.h>
12*5d1a30ebSJakub Kicinski #include <stdio.h>
13*5d1a30ebSJakub Kicinski #include <string.h>
14*5d1a30ebSJakub Kicinski #include <libmnl/libmnl.h>
15*5d1a30ebSJakub Kicinski #include <linux/genetlink.h>
16*5d1a30ebSJakub Kicinski 
17*5d1a30ebSJakub Kicinski /* Enums */
18*5d1a30ebSJakub Kicinski static const char * const devlink_op_strmap[] = {
19*5d1a30ebSJakub Kicinski 	[3] = "get",
20*5d1a30ebSJakub Kicinski 	[DEVLINK_CMD_INFO_GET] = "info-get",
21*5d1a30ebSJakub Kicinski };
22*5d1a30ebSJakub Kicinski 
23*5d1a30ebSJakub Kicinski const char *devlink_op_str(int op)
24*5d1a30ebSJakub Kicinski {
25*5d1a30ebSJakub Kicinski 	if (op < 0 || op >= (int)MNL_ARRAY_SIZE(devlink_op_strmap))
26*5d1a30ebSJakub Kicinski 		return NULL;
27*5d1a30ebSJakub Kicinski 	return devlink_op_strmap[op];
28*5d1a30ebSJakub Kicinski }
29*5d1a30ebSJakub Kicinski 
30*5d1a30ebSJakub Kicinski /* Policies */
31*5d1a30ebSJakub Kicinski struct ynl_policy_attr devlink_dl_info_version_policy[DEVLINK_ATTR_MAX + 1] = {
32*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_INFO_VERSION_NAME] = { .name = "info-version-name", .type = YNL_PT_NUL_STR, },
33*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_INFO_VERSION_VALUE] = { .name = "info-version-value", .type = YNL_PT_NUL_STR, },
34*5d1a30ebSJakub Kicinski };
35*5d1a30ebSJakub Kicinski 
36*5d1a30ebSJakub Kicinski struct ynl_policy_nest devlink_dl_info_version_nest = {
37*5d1a30ebSJakub Kicinski 	.max_attr = DEVLINK_ATTR_MAX,
38*5d1a30ebSJakub Kicinski 	.table = devlink_dl_info_version_policy,
39*5d1a30ebSJakub Kicinski };
40*5d1a30ebSJakub Kicinski 
41*5d1a30ebSJakub Kicinski struct ynl_policy_attr devlink_dl_reload_stats_entry_policy[DEVLINK_ATTR_MAX + 1] = {
42*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_STATS_LIMIT] = { .name = "reload-stats-limit", .type = YNL_PT_U8, },
43*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_STATS_VALUE] = { .name = "reload-stats-value", .type = YNL_PT_U32, },
44*5d1a30ebSJakub Kicinski };
45*5d1a30ebSJakub Kicinski 
46*5d1a30ebSJakub Kicinski struct ynl_policy_nest devlink_dl_reload_stats_entry_nest = {
47*5d1a30ebSJakub Kicinski 	.max_attr = DEVLINK_ATTR_MAX,
48*5d1a30ebSJakub Kicinski 	.table = devlink_dl_reload_stats_entry_policy,
49*5d1a30ebSJakub Kicinski };
50*5d1a30ebSJakub Kicinski 
51*5d1a30ebSJakub Kicinski struct ynl_policy_attr devlink_dl_reload_act_stats_policy[DEVLINK_ATTR_MAX + 1] = {
52*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_STATS_ENTRY] = { .name = "reload-stats-entry", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_stats_entry_nest, },
53*5d1a30ebSJakub Kicinski };
54*5d1a30ebSJakub Kicinski 
55*5d1a30ebSJakub Kicinski struct ynl_policy_nest devlink_dl_reload_act_stats_nest = {
56*5d1a30ebSJakub Kicinski 	.max_attr = DEVLINK_ATTR_MAX,
57*5d1a30ebSJakub Kicinski 	.table = devlink_dl_reload_act_stats_policy,
58*5d1a30ebSJakub Kicinski };
59*5d1a30ebSJakub Kicinski 
60*5d1a30ebSJakub Kicinski struct ynl_policy_attr devlink_dl_reload_act_info_policy[DEVLINK_ATTR_MAX + 1] = {
61*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_ACTION] = { .name = "reload-action", .type = YNL_PT_U8, },
62*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_ACTION_STATS] = { .name = "reload-action-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_act_stats_nest, },
63*5d1a30ebSJakub Kicinski };
64*5d1a30ebSJakub Kicinski 
65*5d1a30ebSJakub Kicinski struct ynl_policy_nest devlink_dl_reload_act_info_nest = {
66*5d1a30ebSJakub Kicinski 	.max_attr = DEVLINK_ATTR_MAX,
67*5d1a30ebSJakub Kicinski 	.table = devlink_dl_reload_act_info_policy,
68*5d1a30ebSJakub Kicinski };
69*5d1a30ebSJakub Kicinski 
70*5d1a30ebSJakub Kicinski struct ynl_policy_attr devlink_dl_reload_stats_policy[DEVLINK_ATTR_MAX + 1] = {
71*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_ACTION_INFO] = { .name = "reload-action-info", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_act_info_nest, },
72*5d1a30ebSJakub Kicinski };
73*5d1a30ebSJakub Kicinski 
74*5d1a30ebSJakub Kicinski struct ynl_policy_nest devlink_dl_reload_stats_nest = {
75*5d1a30ebSJakub Kicinski 	.max_attr = DEVLINK_ATTR_MAX,
76*5d1a30ebSJakub Kicinski 	.table = devlink_dl_reload_stats_policy,
77*5d1a30ebSJakub Kicinski };
78*5d1a30ebSJakub Kicinski 
79*5d1a30ebSJakub Kicinski struct ynl_policy_attr devlink_dl_dev_stats_policy[DEVLINK_ATTR_MAX + 1] = {
80*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_STATS] = { .name = "reload-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_stats_nest, },
81*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_REMOTE_RELOAD_STATS] = { .name = "remote-reload-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_stats_nest, },
82*5d1a30ebSJakub Kicinski };
83*5d1a30ebSJakub Kicinski 
84*5d1a30ebSJakub Kicinski struct ynl_policy_nest devlink_dl_dev_stats_nest = {
85*5d1a30ebSJakub Kicinski 	.max_attr = DEVLINK_ATTR_MAX,
86*5d1a30ebSJakub Kicinski 	.table = devlink_dl_dev_stats_policy,
87*5d1a30ebSJakub Kicinski };
88*5d1a30ebSJakub Kicinski 
89*5d1a30ebSJakub Kicinski struct ynl_policy_attr devlink_policy[DEVLINK_ATTR_MAX + 1] = {
90*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_BUS_NAME] = { .name = "bus-name", .type = YNL_PT_NUL_STR, },
91*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_DEV_NAME] = { .name = "dev-name", .type = YNL_PT_NUL_STR, },
92*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_PORT_INDEX] = { .name = "port-index", .type = YNL_PT_U32, },
93*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_INFO_DRIVER_NAME] = { .name = "info-driver-name", .type = YNL_PT_NUL_STR, },
94*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_INFO_SERIAL_NUMBER] = { .name = "info-serial-number", .type = YNL_PT_NUL_STR, },
95*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_INFO_VERSION_FIXED] = { .name = "info-version-fixed", .type = YNL_PT_NEST, .nest = &devlink_dl_info_version_nest, },
96*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_INFO_VERSION_RUNNING] = { .name = "info-version-running", .type = YNL_PT_NEST, .nest = &devlink_dl_info_version_nest, },
97*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_INFO_VERSION_STORED] = { .name = "info-version-stored", .type = YNL_PT_NEST, .nest = &devlink_dl_info_version_nest, },
98*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_INFO_VERSION_NAME] = { .name = "info-version-name", .type = YNL_PT_NUL_STR, },
99*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_INFO_VERSION_VALUE] = { .name = "info-version-value", .type = YNL_PT_NUL_STR, },
100*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_FAILED] = { .name = "reload-failed", .type = YNL_PT_U8, },
101*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_ACTION] = { .name = "reload-action", .type = YNL_PT_U8, },
102*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_DEV_STATS] = { .name = "dev-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_dev_stats_nest, },
103*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_STATS] = { .name = "reload-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_stats_nest, },
104*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_STATS_ENTRY] = { .name = "reload-stats-entry", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_stats_entry_nest, },
105*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_STATS_LIMIT] = { .name = "reload-stats-limit", .type = YNL_PT_U8, },
106*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_STATS_VALUE] = { .name = "reload-stats-value", .type = YNL_PT_U32, },
107*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_REMOTE_RELOAD_STATS] = { .name = "remote-reload-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_stats_nest, },
108*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_ACTION_INFO] = { .name = "reload-action-info", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_act_info_nest, },
109*5d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_ACTION_STATS] = { .name = "reload-action-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_act_stats_nest, },
110*5d1a30ebSJakub Kicinski };
111*5d1a30ebSJakub Kicinski 
112*5d1a30ebSJakub Kicinski struct ynl_policy_nest devlink_nest = {
113*5d1a30ebSJakub Kicinski 	.max_attr = DEVLINK_ATTR_MAX,
114*5d1a30ebSJakub Kicinski 	.table = devlink_policy,
115*5d1a30ebSJakub Kicinski };
116*5d1a30ebSJakub Kicinski 
117*5d1a30ebSJakub Kicinski /* Common nested types */
118*5d1a30ebSJakub Kicinski void devlink_dl_info_version_free(struct devlink_dl_info_version *obj)
119*5d1a30ebSJakub Kicinski {
120*5d1a30ebSJakub Kicinski 	free(obj->info_version_name);
121*5d1a30ebSJakub Kicinski 	free(obj->info_version_value);
122*5d1a30ebSJakub Kicinski }
123*5d1a30ebSJakub Kicinski 
124*5d1a30ebSJakub Kicinski int devlink_dl_info_version_parse(struct ynl_parse_arg *yarg,
125*5d1a30ebSJakub Kicinski 				  const struct nlattr *nested)
126*5d1a30ebSJakub Kicinski {
127*5d1a30ebSJakub Kicinski 	struct devlink_dl_info_version *dst = yarg->data;
128*5d1a30ebSJakub Kicinski 	const struct nlattr *attr;
129*5d1a30ebSJakub Kicinski 
130*5d1a30ebSJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
131*5d1a30ebSJakub Kicinski 		if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_NAME) {
132*5d1a30ebSJakub Kicinski 			unsigned int len;
133*5d1a30ebSJakub Kicinski 
134*5d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
135*5d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
136*5d1a30ebSJakub Kicinski 
137*5d1a30ebSJakub Kicinski 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
138*5d1a30ebSJakub Kicinski 			dst->_present.info_version_name_len = len;
139*5d1a30ebSJakub Kicinski 			dst->info_version_name = malloc(len + 1);
140*5d1a30ebSJakub Kicinski 			memcpy(dst->info_version_name, mnl_attr_get_str(attr), len);
141*5d1a30ebSJakub Kicinski 			dst->info_version_name[len] = 0;
142*5d1a30ebSJakub Kicinski 		}
143*5d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_VALUE) {
144*5d1a30ebSJakub Kicinski 			unsigned int len;
145*5d1a30ebSJakub Kicinski 
146*5d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
147*5d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
148*5d1a30ebSJakub Kicinski 
149*5d1a30ebSJakub Kicinski 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
150*5d1a30ebSJakub Kicinski 			dst->_present.info_version_value_len = len;
151*5d1a30ebSJakub Kicinski 			dst->info_version_value = malloc(len + 1);
152*5d1a30ebSJakub Kicinski 			memcpy(dst->info_version_value, mnl_attr_get_str(attr), len);
153*5d1a30ebSJakub Kicinski 			dst->info_version_value[len] = 0;
154*5d1a30ebSJakub Kicinski 		}
155*5d1a30ebSJakub Kicinski 	}
156*5d1a30ebSJakub Kicinski 
157*5d1a30ebSJakub Kicinski 	return 0;
158*5d1a30ebSJakub Kicinski }
159*5d1a30ebSJakub Kicinski 
160*5d1a30ebSJakub Kicinski void
161*5d1a30ebSJakub Kicinski devlink_dl_reload_stats_entry_free(struct devlink_dl_reload_stats_entry *obj)
162*5d1a30ebSJakub Kicinski {
163*5d1a30ebSJakub Kicinski }
164*5d1a30ebSJakub Kicinski 
165*5d1a30ebSJakub Kicinski int devlink_dl_reload_stats_entry_parse(struct ynl_parse_arg *yarg,
166*5d1a30ebSJakub Kicinski 					const struct nlattr *nested)
167*5d1a30ebSJakub Kicinski {
168*5d1a30ebSJakub Kicinski 	struct devlink_dl_reload_stats_entry *dst = yarg->data;
169*5d1a30ebSJakub Kicinski 	const struct nlattr *attr;
170*5d1a30ebSJakub Kicinski 
171*5d1a30ebSJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
172*5d1a30ebSJakub Kicinski 		if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_STATS_LIMIT) {
173*5d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
174*5d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
175*5d1a30ebSJakub Kicinski 			dst->_present.reload_stats_limit = 1;
176*5d1a30ebSJakub Kicinski 			dst->reload_stats_limit = mnl_attr_get_u8(attr);
177*5d1a30ebSJakub Kicinski 		}
178*5d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_STATS_VALUE) {
179*5d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
180*5d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
181*5d1a30ebSJakub Kicinski 			dst->_present.reload_stats_value = 1;
182*5d1a30ebSJakub Kicinski 			dst->reload_stats_value = mnl_attr_get_u32(attr);
183*5d1a30ebSJakub Kicinski 		}
184*5d1a30ebSJakub Kicinski 	}
185*5d1a30ebSJakub Kicinski 
186*5d1a30ebSJakub Kicinski 	return 0;
187*5d1a30ebSJakub Kicinski }
188*5d1a30ebSJakub Kicinski 
189*5d1a30ebSJakub Kicinski void devlink_dl_reload_act_stats_free(struct devlink_dl_reload_act_stats *obj)
190*5d1a30ebSJakub Kicinski {
191*5d1a30ebSJakub Kicinski 	unsigned int i;
192*5d1a30ebSJakub Kicinski 
193*5d1a30ebSJakub Kicinski 	for (i = 0; i < obj->n_reload_stats_entry; i++)
194*5d1a30ebSJakub Kicinski 		devlink_dl_reload_stats_entry_free(&obj->reload_stats_entry[i]);
195*5d1a30ebSJakub Kicinski 	free(obj->reload_stats_entry);
196*5d1a30ebSJakub Kicinski }
197*5d1a30ebSJakub Kicinski 
198*5d1a30ebSJakub Kicinski int devlink_dl_reload_act_stats_parse(struct ynl_parse_arg *yarg,
199*5d1a30ebSJakub Kicinski 				      const struct nlattr *nested)
200*5d1a30ebSJakub Kicinski {
201*5d1a30ebSJakub Kicinski 	struct devlink_dl_reload_act_stats *dst = yarg->data;
202*5d1a30ebSJakub Kicinski 	unsigned int n_reload_stats_entry = 0;
203*5d1a30ebSJakub Kicinski 	const struct nlattr *attr;
204*5d1a30ebSJakub Kicinski 	struct ynl_parse_arg parg;
205*5d1a30ebSJakub Kicinski 	int i;
206*5d1a30ebSJakub Kicinski 
207*5d1a30ebSJakub Kicinski 	parg.ys = yarg->ys;
208*5d1a30ebSJakub Kicinski 
209*5d1a30ebSJakub Kicinski 	if (dst->reload_stats_entry)
210*5d1a30ebSJakub Kicinski 		return ynl_error_parse(yarg, "attribute already present (dl-reload-act-stats.reload-stats-entry)");
211*5d1a30ebSJakub Kicinski 
212*5d1a30ebSJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
213*5d1a30ebSJakub Kicinski 		if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_STATS_ENTRY) {
214*5d1a30ebSJakub Kicinski 			n_reload_stats_entry++;
215*5d1a30ebSJakub Kicinski 		}
216*5d1a30ebSJakub Kicinski 	}
217*5d1a30ebSJakub Kicinski 
218*5d1a30ebSJakub Kicinski 	if (n_reload_stats_entry) {
219*5d1a30ebSJakub Kicinski 		dst->reload_stats_entry = calloc(n_reload_stats_entry, sizeof(*dst->reload_stats_entry));
220*5d1a30ebSJakub Kicinski 		dst->n_reload_stats_entry = n_reload_stats_entry;
221*5d1a30ebSJakub Kicinski 		i = 0;
222*5d1a30ebSJakub Kicinski 		parg.rsp_policy = &devlink_dl_reload_stats_entry_nest;
223*5d1a30ebSJakub Kicinski 		mnl_attr_for_each_nested(attr, nested) {
224*5d1a30ebSJakub Kicinski 			if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_STATS_ENTRY) {
225*5d1a30ebSJakub Kicinski 				parg.data = &dst->reload_stats_entry[i];
226*5d1a30ebSJakub Kicinski 				if (devlink_dl_reload_stats_entry_parse(&parg, attr))
227*5d1a30ebSJakub Kicinski 					return MNL_CB_ERROR;
228*5d1a30ebSJakub Kicinski 				i++;
229*5d1a30ebSJakub Kicinski 			}
230*5d1a30ebSJakub Kicinski 		}
231*5d1a30ebSJakub Kicinski 	}
232*5d1a30ebSJakub Kicinski 
233*5d1a30ebSJakub Kicinski 	return 0;
234*5d1a30ebSJakub Kicinski }
235*5d1a30ebSJakub Kicinski 
236*5d1a30ebSJakub Kicinski void devlink_dl_reload_act_info_free(struct devlink_dl_reload_act_info *obj)
237*5d1a30ebSJakub Kicinski {
238*5d1a30ebSJakub Kicinski 	unsigned int i;
239*5d1a30ebSJakub Kicinski 
240*5d1a30ebSJakub Kicinski 	for (i = 0; i < obj->n_reload_action_stats; i++)
241*5d1a30ebSJakub Kicinski 		devlink_dl_reload_act_stats_free(&obj->reload_action_stats[i]);
242*5d1a30ebSJakub Kicinski 	free(obj->reload_action_stats);
243*5d1a30ebSJakub Kicinski }
244*5d1a30ebSJakub Kicinski 
245*5d1a30ebSJakub Kicinski int devlink_dl_reload_act_info_parse(struct ynl_parse_arg *yarg,
246*5d1a30ebSJakub Kicinski 				     const struct nlattr *nested)
247*5d1a30ebSJakub Kicinski {
248*5d1a30ebSJakub Kicinski 	struct devlink_dl_reload_act_info *dst = yarg->data;
249*5d1a30ebSJakub Kicinski 	unsigned int n_reload_action_stats = 0;
250*5d1a30ebSJakub Kicinski 	const struct nlattr *attr;
251*5d1a30ebSJakub Kicinski 	struct ynl_parse_arg parg;
252*5d1a30ebSJakub Kicinski 	int i;
253*5d1a30ebSJakub Kicinski 
254*5d1a30ebSJakub Kicinski 	parg.ys = yarg->ys;
255*5d1a30ebSJakub Kicinski 
256*5d1a30ebSJakub Kicinski 	if (dst->reload_action_stats)
257*5d1a30ebSJakub Kicinski 		return ynl_error_parse(yarg, "attribute already present (dl-reload-act-info.reload-action-stats)");
258*5d1a30ebSJakub Kicinski 
259*5d1a30ebSJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
260*5d1a30ebSJakub Kicinski 		if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_ACTION) {
261*5d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
262*5d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
263*5d1a30ebSJakub Kicinski 			dst->_present.reload_action = 1;
264*5d1a30ebSJakub Kicinski 			dst->reload_action = mnl_attr_get_u8(attr);
265*5d1a30ebSJakub Kicinski 		}
266*5d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_ACTION_STATS) {
267*5d1a30ebSJakub Kicinski 			n_reload_action_stats++;
268*5d1a30ebSJakub Kicinski 		}
269*5d1a30ebSJakub Kicinski 	}
270*5d1a30ebSJakub Kicinski 
271*5d1a30ebSJakub Kicinski 	if (n_reload_action_stats) {
272*5d1a30ebSJakub Kicinski 		dst->reload_action_stats = calloc(n_reload_action_stats, sizeof(*dst->reload_action_stats));
273*5d1a30ebSJakub Kicinski 		dst->n_reload_action_stats = n_reload_action_stats;
274*5d1a30ebSJakub Kicinski 		i = 0;
275*5d1a30ebSJakub Kicinski 		parg.rsp_policy = &devlink_dl_reload_act_stats_nest;
276*5d1a30ebSJakub Kicinski 		mnl_attr_for_each_nested(attr, nested) {
277*5d1a30ebSJakub Kicinski 			if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_ACTION_STATS) {
278*5d1a30ebSJakub Kicinski 				parg.data = &dst->reload_action_stats[i];
279*5d1a30ebSJakub Kicinski 				if (devlink_dl_reload_act_stats_parse(&parg, attr))
280*5d1a30ebSJakub Kicinski 					return MNL_CB_ERROR;
281*5d1a30ebSJakub Kicinski 				i++;
282*5d1a30ebSJakub Kicinski 			}
283*5d1a30ebSJakub Kicinski 		}
284*5d1a30ebSJakub Kicinski 	}
285*5d1a30ebSJakub Kicinski 
286*5d1a30ebSJakub Kicinski 	return 0;
287*5d1a30ebSJakub Kicinski }
288*5d1a30ebSJakub Kicinski 
289*5d1a30ebSJakub Kicinski void devlink_dl_reload_stats_free(struct devlink_dl_reload_stats *obj)
290*5d1a30ebSJakub Kicinski {
291*5d1a30ebSJakub Kicinski 	unsigned int i;
292*5d1a30ebSJakub Kicinski 
293*5d1a30ebSJakub Kicinski 	for (i = 0; i < obj->n_reload_action_info; i++)
294*5d1a30ebSJakub Kicinski 		devlink_dl_reload_act_info_free(&obj->reload_action_info[i]);
295*5d1a30ebSJakub Kicinski 	free(obj->reload_action_info);
296*5d1a30ebSJakub Kicinski }
297*5d1a30ebSJakub Kicinski 
298*5d1a30ebSJakub Kicinski int devlink_dl_reload_stats_parse(struct ynl_parse_arg *yarg,
299*5d1a30ebSJakub Kicinski 				  const struct nlattr *nested)
300*5d1a30ebSJakub Kicinski {
301*5d1a30ebSJakub Kicinski 	struct devlink_dl_reload_stats *dst = yarg->data;
302*5d1a30ebSJakub Kicinski 	unsigned int n_reload_action_info = 0;
303*5d1a30ebSJakub Kicinski 	const struct nlattr *attr;
304*5d1a30ebSJakub Kicinski 	struct ynl_parse_arg parg;
305*5d1a30ebSJakub Kicinski 	int i;
306*5d1a30ebSJakub Kicinski 
307*5d1a30ebSJakub Kicinski 	parg.ys = yarg->ys;
308*5d1a30ebSJakub Kicinski 
309*5d1a30ebSJakub Kicinski 	if (dst->reload_action_info)
310*5d1a30ebSJakub Kicinski 		return ynl_error_parse(yarg, "attribute already present (dl-reload-stats.reload-action-info)");
311*5d1a30ebSJakub Kicinski 
312*5d1a30ebSJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
313*5d1a30ebSJakub Kicinski 		if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_ACTION_INFO) {
314*5d1a30ebSJakub Kicinski 			n_reload_action_info++;
315*5d1a30ebSJakub Kicinski 		}
316*5d1a30ebSJakub Kicinski 	}
317*5d1a30ebSJakub Kicinski 
318*5d1a30ebSJakub Kicinski 	if (n_reload_action_info) {
319*5d1a30ebSJakub Kicinski 		dst->reload_action_info = calloc(n_reload_action_info, sizeof(*dst->reload_action_info));
320*5d1a30ebSJakub Kicinski 		dst->n_reload_action_info = n_reload_action_info;
321*5d1a30ebSJakub Kicinski 		i = 0;
322*5d1a30ebSJakub Kicinski 		parg.rsp_policy = &devlink_dl_reload_act_info_nest;
323*5d1a30ebSJakub Kicinski 		mnl_attr_for_each_nested(attr, nested) {
324*5d1a30ebSJakub Kicinski 			if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_ACTION_INFO) {
325*5d1a30ebSJakub Kicinski 				parg.data = &dst->reload_action_info[i];
326*5d1a30ebSJakub Kicinski 				if (devlink_dl_reload_act_info_parse(&parg, attr))
327*5d1a30ebSJakub Kicinski 					return MNL_CB_ERROR;
328*5d1a30ebSJakub Kicinski 				i++;
329*5d1a30ebSJakub Kicinski 			}
330*5d1a30ebSJakub Kicinski 		}
331*5d1a30ebSJakub Kicinski 	}
332*5d1a30ebSJakub Kicinski 
333*5d1a30ebSJakub Kicinski 	return 0;
334*5d1a30ebSJakub Kicinski }
335*5d1a30ebSJakub Kicinski 
336*5d1a30ebSJakub Kicinski void devlink_dl_dev_stats_free(struct devlink_dl_dev_stats *obj)
337*5d1a30ebSJakub Kicinski {
338*5d1a30ebSJakub Kicinski 	devlink_dl_reload_stats_free(&obj->reload_stats);
339*5d1a30ebSJakub Kicinski 	devlink_dl_reload_stats_free(&obj->remote_reload_stats);
340*5d1a30ebSJakub Kicinski }
341*5d1a30ebSJakub Kicinski 
342*5d1a30ebSJakub Kicinski int devlink_dl_dev_stats_parse(struct ynl_parse_arg *yarg,
343*5d1a30ebSJakub Kicinski 			       const struct nlattr *nested)
344*5d1a30ebSJakub Kicinski {
345*5d1a30ebSJakub Kicinski 	struct devlink_dl_dev_stats *dst = yarg->data;
346*5d1a30ebSJakub Kicinski 	const struct nlattr *attr;
347*5d1a30ebSJakub Kicinski 	struct ynl_parse_arg parg;
348*5d1a30ebSJakub Kicinski 
349*5d1a30ebSJakub Kicinski 	parg.ys = yarg->ys;
350*5d1a30ebSJakub Kicinski 
351*5d1a30ebSJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
352*5d1a30ebSJakub Kicinski 		if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_STATS) {
353*5d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
354*5d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
355*5d1a30ebSJakub Kicinski 			dst->_present.reload_stats = 1;
356*5d1a30ebSJakub Kicinski 
357*5d1a30ebSJakub Kicinski 			parg.rsp_policy = &devlink_dl_reload_stats_nest;
358*5d1a30ebSJakub Kicinski 			parg.data = &dst->reload_stats;
359*5d1a30ebSJakub Kicinski 			if (devlink_dl_reload_stats_parse(&parg, attr))
360*5d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
361*5d1a30ebSJakub Kicinski 		}
362*5d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_REMOTE_RELOAD_STATS) {
363*5d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
364*5d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
365*5d1a30ebSJakub Kicinski 			dst->_present.remote_reload_stats = 1;
366*5d1a30ebSJakub Kicinski 
367*5d1a30ebSJakub Kicinski 			parg.rsp_policy = &devlink_dl_reload_stats_nest;
368*5d1a30ebSJakub Kicinski 			parg.data = &dst->remote_reload_stats;
369*5d1a30ebSJakub Kicinski 			if (devlink_dl_reload_stats_parse(&parg, attr))
370*5d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
371*5d1a30ebSJakub Kicinski 		}
372*5d1a30ebSJakub Kicinski 	}
373*5d1a30ebSJakub Kicinski 
374*5d1a30ebSJakub Kicinski 	return 0;
375*5d1a30ebSJakub Kicinski }
376*5d1a30ebSJakub Kicinski 
377*5d1a30ebSJakub Kicinski /* ============== DEVLINK_CMD_GET ============== */
378*5d1a30ebSJakub Kicinski /* DEVLINK_CMD_GET - do */
379*5d1a30ebSJakub Kicinski void devlink_get_req_free(struct devlink_get_req *req)
380*5d1a30ebSJakub Kicinski {
381*5d1a30ebSJakub Kicinski 	free(req->bus_name);
382*5d1a30ebSJakub Kicinski 	free(req->dev_name);
383*5d1a30ebSJakub Kicinski 	free(req);
384*5d1a30ebSJakub Kicinski }
385*5d1a30ebSJakub Kicinski 
386*5d1a30ebSJakub Kicinski void devlink_get_rsp_free(struct devlink_get_rsp *rsp)
387*5d1a30ebSJakub Kicinski {
388*5d1a30ebSJakub Kicinski 	free(rsp->bus_name);
389*5d1a30ebSJakub Kicinski 	free(rsp->dev_name);
390*5d1a30ebSJakub Kicinski 	devlink_dl_dev_stats_free(&rsp->dev_stats);
391*5d1a30ebSJakub Kicinski 	free(rsp);
392*5d1a30ebSJakub Kicinski }
393*5d1a30ebSJakub Kicinski 
394*5d1a30ebSJakub Kicinski int devlink_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
395*5d1a30ebSJakub Kicinski {
396*5d1a30ebSJakub Kicinski 	struct ynl_parse_arg *yarg = data;
397*5d1a30ebSJakub Kicinski 	struct devlink_get_rsp *dst;
398*5d1a30ebSJakub Kicinski 	const struct nlattr *attr;
399*5d1a30ebSJakub Kicinski 	struct ynl_parse_arg parg;
400*5d1a30ebSJakub Kicinski 
401*5d1a30ebSJakub Kicinski 	dst = yarg->data;
402*5d1a30ebSJakub Kicinski 	parg.ys = yarg->ys;
403*5d1a30ebSJakub Kicinski 
404*5d1a30ebSJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
405*5d1a30ebSJakub Kicinski 		if (mnl_attr_get_type(attr) == DEVLINK_ATTR_BUS_NAME) {
406*5d1a30ebSJakub Kicinski 			unsigned int len;
407*5d1a30ebSJakub Kicinski 
408*5d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
409*5d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
410*5d1a30ebSJakub Kicinski 
411*5d1a30ebSJakub Kicinski 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
412*5d1a30ebSJakub Kicinski 			dst->_present.bus_name_len = len;
413*5d1a30ebSJakub Kicinski 			dst->bus_name = malloc(len + 1);
414*5d1a30ebSJakub Kicinski 			memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
415*5d1a30ebSJakub Kicinski 			dst->bus_name[len] = 0;
416*5d1a30ebSJakub Kicinski 		}
417*5d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_DEV_NAME) {
418*5d1a30ebSJakub Kicinski 			unsigned int len;
419*5d1a30ebSJakub Kicinski 
420*5d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
421*5d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
422*5d1a30ebSJakub Kicinski 
423*5d1a30ebSJakub Kicinski 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
424*5d1a30ebSJakub Kicinski 			dst->_present.dev_name_len = len;
425*5d1a30ebSJakub Kicinski 			dst->dev_name = malloc(len + 1);
426*5d1a30ebSJakub Kicinski 			memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
427*5d1a30ebSJakub Kicinski 			dst->dev_name[len] = 0;
428*5d1a30ebSJakub Kicinski 		}
429*5d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_FAILED) {
430*5d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
431*5d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
432*5d1a30ebSJakub Kicinski 			dst->_present.reload_failed = 1;
433*5d1a30ebSJakub Kicinski 			dst->reload_failed = mnl_attr_get_u8(attr);
434*5d1a30ebSJakub Kicinski 		}
435*5d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_ACTION) {
436*5d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
437*5d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
438*5d1a30ebSJakub Kicinski 			dst->_present.reload_action = 1;
439*5d1a30ebSJakub Kicinski 			dst->reload_action = mnl_attr_get_u8(attr);
440*5d1a30ebSJakub Kicinski 		}
441*5d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_DEV_STATS) {
442*5d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
443*5d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
444*5d1a30ebSJakub Kicinski 			dst->_present.dev_stats = 1;
445*5d1a30ebSJakub Kicinski 
446*5d1a30ebSJakub Kicinski 			parg.rsp_policy = &devlink_dl_dev_stats_nest;
447*5d1a30ebSJakub Kicinski 			parg.data = &dst->dev_stats;
448*5d1a30ebSJakub Kicinski 			if (devlink_dl_dev_stats_parse(&parg, attr))
449*5d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
450*5d1a30ebSJakub Kicinski 		}
451*5d1a30ebSJakub Kicinski 	}
452*5d1a30ebSJakub Kicinski 
453*5d1a30ebSJakub Kicinski 	return MNL_CB_OK;
454*5d1a30ebSJakub Kicinski }
455*5d1a30ebSJakub Kicinski 
456*5d1a30ebSJakub Kicinski struct devlink_get_rsp *
457*5d1a30ebSJakub Kicinski devlink_get(struct ynl_sock *ys, struct devlink_get_req *req)
458*5d1a30ebSJakub Kicinski {
459*5d1a30ebSJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
460*5d1a30ebSJakub Kicinski 	struct devlink_get_rsp *rsp;
461*5d1a30ebSJakub Kicinski 	struct nlmsghdr *nlh;
462*5d1a30ebSJakub Kicinski 	int err;
463*5d1a30ebSJakub Kicinski 
464*5d1a30ebSJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_GET, 1);
465*5d1a30ebSJakub Kicinski 	ys->req_policy = &devlink_nest;
466*5d1a30ebSJakub Kicinski 	yrs.yarg.rsp_policy = &devlink_nest;
467*5d1a30ebSJakub Kicinski 
468*5d1a30ebSJakub Kicinski 	if (req->_present.bus_name_len)
469*5d1a30ebSJakub Kicinski 		mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
470*5d1a30ebSJakub Kicinski 	if (req->_present.dev_name_len)
471*5d1a30ebSJakub Kicinski 		mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
472*5d1a30ebSJakub Kicinski 
473*5d1a30ebSJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
474*5d1a30ebSJakub Kicinski 	yrs.yarg.data = rsp;
475*5d1a30ebSJakub Kicinski 	yrs.cb = devlink_get_rsp_parse;
476*5d1a30ebSJakub Kicinski 	yrs.rsp_cmd = 3;
477*5d1a30ebSJakub Kicinski 
478*5d1a30ebSJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
479*5d1a30ebSJakub Kicinski 	if (err < 0)
480*5d1a30ebSJakub Kicinski 		goto err_free;
481*5d1a30ebSJakub Kicinski 
482*5d1a30ebSJakub Kicinski 	return rsp;
483*5d1a30ebSJakub Kicinski 
484*5d1a30ebSJakub Kicinski err_free:
485*5d1a30ebSJakub Kicinski 	devlink_get_rsp_free(rsp);
486*5d1a30ebSJakub Kicinski 	return NULL;
487*5d1a30ebSJakub Kicinski }
488*5d1a30ebSJakub Kicinski 
489*5d1a30ebSJakub Kicinski /* DEVLINK_CMD_GET - dump */
490*5d1a30ebSJakub Kicinski void devlink_get_list_free(struct devlink_get_list *rsp)
491*5d1a30ebSJakub Kicinski {
492*5d1a30ebSJakub Kicinski 	struct devlink_get_list *next = rsp;
493*5d1a30ebSJakub Kicinski 
494*5d1a30ebSJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
495*5d1a30ebSJakub Kicinski 		rsp = next;
496*5d1a30ebSJakub Kicinski 		next = rsp->next;
497*5d1a30ebSJakub Kicinski 
498*5d1a30ebSJakub Kicinski 		free(rsp->obj.bus_name);
499*5d1a30ebSJakub Kicinski 		free(rsp->obj.dev_name);
500*5d1a30ebSJakub Kicinski 		devlink_dl_dev_stats_free(&rsp->obj.dev_stats);
501*5d1a30ebSJakub Kicinski 		free(rsp);
502*5d1a30ebSJakub Kicinski 	}
503*5d1a30ebSJakub Kicinski }
504*5d1a30ebSJakub Kicinski 
505*5d1a30ebSJakub Kicinski struct devlink_get_list *devlink_get_dump(struct ynl_sock *ys)
506*5d1a30ebSJakub Kicinski {
507*5d1a30ebSJakub Kicinski 	struct ynl_dump_state yds = {};
508*5d1a30ebSJakub Kicinski 	struct nlmsghdr *nlh;
509*5d1a30ebSJakub Kicinski 	int err;
510*5d1a30ebSJakub Kicinski 
511*5d1a30ebSJakub Kicinski 	yds.ys = ys;
512*5d1a30ebSJakub Kicinski 	yds.alloc_sz = sizeof(struct devlink_get_list);
513*5d1a30ebSJakub Kicinski 	yds.cb = devlink_get_rsp_parse;
514*5d1a30ebSJakub Kicinski 	yds.rsp_cmd = 3;
515*5d1a30ebSJakub Kicinski 	yds.rsp_policy = &devlink_nest;
516*5d1a30ebSJakub Kicinski 
517*5d1a30ebSJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_GET, 1);
518*5d1a30ebSJakub Kicinski 
519*5d1a30ebSJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
520*5d1a30ebSJakub Kicinski 	if (err < 0)
521*5d1a30ebSJakub Kicinski 		goto free_list;
522*5d1a30ebSJakub Kicinski 
523*5d1a30ebSJakub Kicinski 	return yds.first;
524*5d1a30ebSJakub Kicinski 
525*5d1a30ebSJakub Kicinski free_list:
526*5d1a30ebSJakub Kicinski 	devlink_get_list_free(yds.first);
527*5d1a30ebSJakub Kicinski 	return NULL;
528*5d1a30ebSJakub Kicinski }
529*5d1a30ebSJakub Kicinski 
530*5d1a30ebSJakub Kicinski /* ============== DEVLINK_CMD_INFO_GET ============== */
531*5d1a30ebSJakub Kicinski /* DEVLINK_CMD_INFO_GET - do */
532*5d1a30ebSJakub Kicinski void devlink_info_get_req_free(struct devlink_info_get_req *req)
533*5d1a30ebSJakub Kicinski {
534*5d1a30ebSJakub Kicinski 	free(req->bus_name);
535*5d1a30ebSJakub Kicinski 	free(req->dev_name);
536*5d1a30ebSJakub Kicinski 	free(req);
537*5d1a30ebSJakub Kicinski }
538*5d1a30ebSJakub Kicinski 
539*5d1a30ebSJakub Kicinski void devlink_info_get_rsp_free(struct devlink_info_get_rsp *rsp)
540*5d1a30ebSJakub Kicinski {
541*5d1a30ebSJakub Kicinski 	unsigned int i;
542*5d1a30ebSJakub Kicinski 
543*5d1a30ebSJakub Kicinski 	free(rsp->bus_name);
544*5d1a30ebSJakub Kicinski 	free(rsp->dev_name);
545*5d1a30ebSJakub Kicinski 	free(rsp->info_driver_name);
546*5d1a30ebSJakub Kicinski 	free(rsp->info_serial_number);
547*5d1a30ebSJakub Kicinski 	for (i = 0; i < rsp->n_info_version_fixed; i++)
548*5d1a30ebSJakub Kicinski 		devlink_dl_info_version_free(&rsp->info_version_fixed[i]);
549*5d1a30ebSJakub Kicinski 	free(rsp->info_version_fixed);
550*5d1a30ebSJakub Kicinski 	for (i = 0; i < rsp->n_info_version_running; i++)
551*5d1a30ebSJakub Kicinski 		devlink_dl_info_version_free(&rsp->info_version_running[i]);
552*5d1a30ebSJakub Kicinski 	free(rsp->info_version_running);
553*5d1a30ebSJakub Kicinski 	for (i = 0; i < rsp->n_info_version_stored; i++)
554*5d1a30ebSJakub Kicinski 		devlink_dl_info_version_free(&rsp->info_version_stored[i]);
555*5d1a30ebSJakub Kicinski 	free(rsp->info_version_stored);
556*5d1a30ebSJakub Kicinski 	free(rsp);
557*5d1a30ebSJakub Kicinski }
558*5d1a30ebSJakub Kicinski 
559*5d1a30ebSJakub Kicinski int devlink_info_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
560*5d1a30ebSJakub Kicinski {
561*5d1a30ebSJakub Kicinski 	unsigned int n_info_version_running = 0;
562*5d1a30ebSJakub Kicinski 	unsigned int n_info_version_stored = 0;
563*5d1a30ebSJakub Kicinski 	unsigned int n_info_version_fixed = 0;
564*5d1a30ebSJakub Kicinski 	struct ynl_parse_arg *yarg = data;
565*5d1a30ebSJakub Kicinski 	struct devlink_info_get_rsp *dst;
566*5d1a30ebSJakub Kicinski 	const struct nlattr *attr;
567*5d1a30ebSJakub Kicinski 	struct ynl_parse_arg parg;
568*5d1a30ebSJakub Kicinski 	int i;
569*5d1a30ebSJakub Kicinski 
570*5d1a30ebSJakub Kicinski 	dst = yarg->data;
571*5d1a30ebSJakub Kicinski 	parg.ys = yarg->ys;
572*5d1a30ebSJakub Kicinski 
573*5d1a30ebSJakub Kicinski 	if (dst->info_version_fixed)
574*5d1a30ebSJakub Kicinski 		return ynl_error_parse(yarg, "attribute already present (devlink.info-version-fixed)");
575*5d1a30ebSJakub Kicinski 	if (dst->info_version_running)
576*5d1a30ebSJakub Kicinski 		return ynl_error_parse(yarg, "attribute already present (devlink.info-version-running)");
577*5d1a30ebSJakub Kicinski 	if (dst->info_version_stored)
578*5d1a30ebSJakub Kicinski 		return ynl_error_parse(yarg, "attribute already present (devlink.info-version-stored)");
579*5d1a30ebSJakub Kicinski 
580*5d1a30ebSJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
581*5d1a30ebSJakub Kicinski 		if (mnl_attr_get_type(attr) == DEVLINK_ATTR_BUS_NAME) {
582*5d1a30ebSJakub Kicinski 			unsigned int len;
583*5d1a30ebSJakub Kicinski 
584*5d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
585*5d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
586*5d1a30ebSJakub Kicinski 
587*5d1a30ebSJakub Kicinski 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
588*5d1a30ebSJakub Kicinski 			dst->_present.bus_name_len = len;
589*5d1a30ebSJakub Kicinski 			dst->bus_name = malloc(len + 1);
590*5d1a30ebSJakub Kicinski 			memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
591*5d1a30ebSJakub Kicinski 			dst->bus_name[len] = 0;
592*5d1a30ebSJakub Kicinski 		}
593*5d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_DEV_NAME) {
594*5d1a30ebSJakub Kicinski 			unsigned int len;
595*5d1a30ebSJakub Kicinski 
596*5d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
597*5d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
598*5d1a30ebSJakub Kicinski 
599*5d1a30ebSJakub Kicinski 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
600*5d1a30ebSJakub Kicinski 			dst->_present.dev_name_len = len;
601*5d1a30ebSJakub Kicinski 			dst->dev_name = malloc(len + 1);
602*5d1a30ebSJakub Kicinski 			memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
603*5d1a30ebSJakub Kicinski 			dst->dev_name[len] = 0;
604*5d1a30ebSJakub Kicinski 		}
605*5d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_DRIVER_NAME) {
606*5d1a30ebSJakub Kicinski 			unsigned int len;
607*5d1a30ebSJakub Kicinski 
608*5d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
609*5d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
610*5d1a30ebSJakub Kicinski 
611*5d1a30ebSJakub Kicinski 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
612*5d1a30ebSJakub Kicinski 			dst->_present.info_driver_name_len = len;
613*5d1a30ebSJakub Kicinski 			dst->info_driver_name = malloc(len + 1);
614*5d1a30ebSJakub Kicinski 			memcpy(dst->info_driver_name, mnl_attr_get_str(attr), len);
615*5d1a30ebSJakub Kicinski 			dst->info_driver_name[len] = 0;
616*5d1a30ebSJakub Kicinski 		}
617*5d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_SERIAL_NUMBER) {
618*5d1a30ebSJakub Kicinski 			unsigned int len;
619*5d1a30ebSJakub Kicinski 
620*5d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
621*5d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
622*5d1a30ebSJakub Kicinski 
623*5d1a30ebSJakub Kicinski 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
624*5d1a30ebSJakub Kicinski 			dst->_present.info_serial_number_len = len;
625*5d1a30ebSJakub Kicinski 			dst->info_serial_number = malloc(len + 1);
626*5d1a30ebSJakub Kicinski 			memcpy(dst->info_serial_number, mnl_attr_get_str(attr), len);
627*5d1a30ebSJakub Kicinski 			dst->info_serial_number[len] = 0;
628*5d1a30ebSJakub Kicinski 		}
629*5d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_FIXED) {
630*5d1a30ebSJakub Kicinski 			n_info_version_fixed++;
631*5d1a30ebSJakub Kicinski 		}
632*5d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_RUNNING) {
633*5d1a30ebSJakub Kicinski 			n_info_version_running++;
634*5d1a30ebSJakub Kicinski 		}
635*5d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_STORED) {
636*5d1a30ebSJakub Kicinski 			n_info_version_stored++;
637*5d1a30ebSJakub Kicinski 		}
638*5d1a30ebSJakub Kicinski 	}
639*5d1a30ebSJakub Kicinski 
640*5d1a30ebSJakub Kicinski 	if (n_info_version_fixed) {
641*5d1a30ebSJakub Kicinski 		dst->info_version_fixed = calloc(n_info_version_fixed, sizeof(*dst->info_version_fixed));
642*5d1a30ebSJakub Kicinski 		dst->n_info_version_fixed = n_info_version_fixed;
643*5d1a30ebSJakub Kicinski 		i = 0;
644*5d1a30ebSJakub Kicinski 		parg.rsp_policy = &devlink_dl_info_version_nest;
645*5d1a30ebSJakub Kicinski 		mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
646*5d1a30ebSJakub Kicinski 			if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_FIXED) {
647*5d1a30ebSJakub Kicinski 				parg.data = &dst->info_version_fixed[i];
648*5d1a30ebSJakub Kicinski 				if (devlink_dl_info_version_parse(&parg, attr))
649*5d1a30ebSJakub Kicinski 					return MNL_CB_ERROR;
650*5d1a30ebSJakub Kicinski 				i++;
651*5d1a30ebSJakub Kicinski 			}
652*5d1a30ebSJakub Kicinski 		}
653*5d1a30ebSJakub Kicinski 	}
654*5d1a30ebSJakub Kicinski 	if (n_info_version_running) {
655*5d1a30ebSJakub Kicinski 		dst->info_version_running = calloc(n_info_version_running, sizeof(*dst->info_version_running));
656*5d1a30ebSJakub Kicinski 		dst->n_info_version_running = n_info_version_running;
657*5d1a30ebSJakub Kicinski 		i = 0;
658*5d1a30ebSJakub Kicinski 		parg.rsp_policy = &devlink_dl_info_version_nest;
659*5d1a30ebSJakub Kicinski 		mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
660*5d1a30ebSJakub Kicinski 			if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_RUNNING) {
661*5d1a30ebSJakub Kicinski 				parg.data = &dst->info_version_running[i];
662*5d1a30ebSJakub Kicinski 				if (devlink_dl_info_version_parse(&parg, attr))
663*5d1a30ebSJakub Kicinski 					return MNL_CB_ERROR;
664*5d1a30ebSJakub Kicinski 				i++;
665*5d1a30ebSJakub Kicinski 			}
666*5d1a30ebSJakub Kicinski 		}
667*5d1a30ebSJakub Kicinski 	}
668*5d1a30ebSJakub Kicinski 	if (n_info_version_stored) {
669*5d1a30ebSJakub Kicinski 		dst->info_version_stored = calloc(n_info_version_stored, sizeof(*dst->info_version_stored));
670*5d1a30ebSJakub Kicinski 		dst->n_info_version_stored = n_info_version_stored;
671*5d1a30ebSJakub Kicinski 		i = 0;
672*5d1a30ebSJakub Kicinski 		parg.rsp_policy = &devlink_dl_info_version_nest;
673*5d1a30ebSJakub Kicinski 		mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
674*5d1a30ebSJakub Kicinski 			if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_STORED) {
675*5d1a30ebSJakub Kicinski 				parg.data = &dst->info_version_stored[i];
676*5d1a30ebSJakub Kicinski 				if (devlink_dl_info_version_parse(&parg, attr))
677*5d1a30ebSJakub Kicinski 					return MNL_CB_ERROR;
678*5d1a30ebSJakub Kicinski 				i++;
679*5d1a30ebSJakub Kicinski 			}
680*5d1a30ebSJakub Kicinski 		}
681*5d1a30ebSJakub Kicinski 	}
682*5d1a30ebSJakub Kicinski 
683*5d1a30ebSJakub Kicinski 	return MNL_CB_OK;
684*5d1a30ebSJakub Kicinski }
685*5d1a30ebSJakub Kicinski 
686*5d1a30ebSJakub Kicinski struct devlink_info_get_rsp *
687*5d1a30ebSJakub Kicinski devlink_info_get(struct ynl_sock *ys, struct devlink_info_get_req *req)
688*5d1a30ebSJakub Kicinski {
689*5d1a30ebSJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
690*5d1a30ebSJakub Kicinski 	struct devlink_info_get_rsp *rsp;
691*5d1a30ebSJakub Kicinski 	struct nlmsghdr *nlh;
692*5d1a30ebSJakub Kicinski 	int err;
693*5d1a30ebSJakub Kicinski 
694*5d1a30ebSJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_INFO_GET, 1);
695*5d1a30ebSJakub Kicinski 	ys->req_policy = &devlink_nest;
696*5d1a30ebSJakub Kicinski 	yrs.yarg.rsp_policy = &devlink_nest;
697*5d1a30ebSJakub Kicinski 
698*5d1a30ebSJakub Kicinski 	if (req->_present.bus_name_len)
699*5d1a30ebSJakub Kicinski 		mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
700*5d1a30ebSJakub Kicinski 	if (req->_present.dev_name_len)
701*5d1a30ebSJakub Kicinski 		mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
702*5d1a30ebSJakub Kicinski 
703*5d1a30ebSJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
704*5d1a30ebSJakub Kicinski 	yrs.yarg.data = rsp;
705*5d1a30ebSJakub Kicinski 	yrs.cb = devlink_info_get_rsp_parse;
706*5d1a30ebSJakub Kicinski 	yrs.rsp_cmd = DEVLINK_CMD_INFO_GET;
707*5d1a30ebSJakub Kicinski 
708*5d1a30ebSJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
709*5d1a30ebSJakub Kicinski 	if (err < 0)
710*5d1a30ebSJakub Kicinski 		goto err_free;
711*5d1a30ebSJakub Kicinski 
712*5d1a30ebSJakub Kicinski 	return rsp;
713*5d1a30ebSJakub Kicinski 
714*5d1a30ebSJakub Kicinski err_free:
715*5d1a30ebSJakub Kicinski 	devlink_info_get_rsp_free(rsp);
716*5d1a30ebSJakub Kicinski 	return NULL;
717*5d1a30ebSJakub Kicinski }
718*5d1a30ebSJakub Kicinski 
719*5d1a30ebSJakub Kicinski const struct ynl_family ynl_devlink_family =  {
720*5d1a30ebSJakub Kicinski 	.name		= "devlink",
721*5d1a30ebSJakub Kicinski };
722