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