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 		unsigned int type = mnl_attr_get_type(attr);
130 
131 		if (type == DEVLINK_ATTR_INFO_VERSION_NAME) {
132 			unsigned int len;
133 
134 			if (ynl_attr_validate(yarg, attr))
135 				return MNL_CB_ERROR;
136 
137 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
138 			dst->_present.info_version_name_len = len;
139 			dst->info_version_name = malloc(len + 1);
140 			memcpy(dst->info_version_name, mnl_attr_get_str(attr), len);
141 			dst->info_version_name[len] = 0;
142 		} else if (type == DEVLINK_ATTR_INFO_VERSION_VALUE) {
143 			unsigned int len;
144 
145 			if (ynl_attr_validate(yarg, attr))
146 				return MNL_CB_ERROR;
147 
148 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
149 			dst->_present.info_version_value_len = len;
150 			dst->info_version_value = malloc(len + 1);
151 			memcpy(dst->info_version_value, mnl_attr_get_str(attr), len);
152 			dst->info_version_value[len] = 0;
153 		}
154 	}
155 
156 	return 0;
157 }
158 
159 void
160 devlink_dl_reload_stats_entry_free(struct devlink_dl_reload_stats_entry *obj)
161 {
162 }
163 
164 int devlink_dl_reload_stats_entry_parse(struct ynl_parse_arg *yarg,
165 					const struct nlattr *nested)
166 {
167 	struct devlink_dl_reload_stats_entry *dst = yarg->data;
168 	const struct nlattr *attr;
169 
170 	mnl_attr_for_each_nested(attr, nested) {
171 		unsigned int type = mnl_attr_get_type(attr);
172 
173 		if (type == DEVLINK_ATTR_RELOAD_STATS_LIMIT) {
174 			if (ynl_attr_validate(yarg, attr))
175 				return MNL_CB_ERROR;
176 			dst->_present.reload_stats_limit = 1;
177 			dst->reload_stats_limit = mnl_attr_get_u8(attr);
178 		} else if (type == DEVLINK_ATTR_RELOAD_STATS_VALUE) {
179 			if (ynl_attr_validate(yarg, attr))
180 				return MNL_CB_ERROR;
181 			dst->_present.reload_stats_value = 1;
182 			dst->reload_stats_value = mnl_attr_get_u32(attr);
183 		}
184 	}
185 
186 	return 0;
187 }
188 
189 void devlink_dl_reload_act_stats_free(struct devlink_dl_reload_act_stats *obj)
190 {
191 	unsigned int i;
192 
193 	for (i = 0; i < obj->n_reload_stats_entry; i++)
194 		devlink_dl_reload_stats_entry_free(&obj->reload_stats_entry[i]);
195 	free(obj->reload_stats_entry);
196 }
197 
198 int devlink_dl_reload_act_stats_parse(struct ynl_parse_arg *yarg,
199 				      const struct nlattr *nested)
200 {
201 	struct devlink_dl_reload_act_stats *dst = yarg->data;
202 	unsigned int n_reload_stats_entry = 0;
203 	const struct nlattr *attr;
204 	struct ynl_parse_arg parg;
205 	int i;
206 
207 	parg.ys = yarg->ys;
208 
209 	if (dst->reload_stats_entry)
210 		return ynl_error_parse(yarg, "attribute already present (dl-reload-act-stats.reload-stats-entry)");
211 
212 	mnl_attr_for_each_nested(attr, nested) {
213 		unsigned int type = mnl_attr_get_type(attr);
214 
215 		if (type == DEVLINK_ATTR_RELOAD_STATS_ENTRY) {
216 			n_reload_stats_entry++;
217 		}
218 	}
219 
220 	if (n_reload_stats_entry) {
221 		dst->reload_stats_entry = calloc(n_reload_stats_entry, sizeof(*dst->reload_stats_entry));
222 		dst->n_reload_stats_entry = n_reload_stats_entry;
223 		i = 0;
224 		parg.rsp_policy = &devlink_dl_reload_stats_entry_nest;
225 		mnl_attr_for_each_nested(attr, nested) {
226 			if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_STATS_ENTRY) {
227 				parg.data = &dst->reload_stats_entry[i];
228 				if (devlink_dl_reload_stats_entry_parse(&parg, attr))
229 					return MNL_CB_ERROR;
230 				i++;
231 			}
232 		}
233 	}
234 
235 	return 0;
236 }
237 
238 void devlink_dl_reload_act_info_free(struct devlink_dl_reload_act_info *obj)
239 {
240 	unsigned int i;
241 
242 	for (i = 0; i < obj->n_reload_action_stats; i++)
243 		devlink_dl_reload_act_stats_free(&obj->reload_action_stats[i]);
244 	free(obj->reload_action_stats);
245 }
246 
247 int devlink_dl_reload_act_info_parse(struct ynl_parse_arg *yarg,
248 				     const struct nlattr *nested)
249 {
250 	struct devlink_dl_reload_act_info *dst = yarg->data;
251 	unsigned int n_reload_action_stats = 0;
252 	const struct nlattr *attr;
253 	struct ynl_parse_arg parg;
254 	int i;
255 
256 	parg.ys = yarg->ys;
257 
258 	if (dst->reload_action_stats)
259 		return ynl_error_parse(yarg, "attribute already present (dl-reload-act-info.reload-action-stats)");
260 
261 	mnl_attr_for_each_nested(attr, nested) {
262 		unsigned int type = mnl_attr_get_type(attr);
263 
264 		if (type == DEVLINK_ATTR_RELOAD_ACTION) {
265 			if (ynl_attr_validate(yarg, attr))
266 				return MNL_CB_ERROR;
267 			dst->_present.reload_action = 1;
268 			dst->reload_action = mnl_attr_get_u8(attr);
269 		} else if (type == DEVLINK_ATTR_RELOAD_ACTION_STATS) {
270 			n_reload_action_stats++;
271 		}
272 	}
273 
274 	if (n_reload_action_stats) {
275 		dst->reload_action_stats = calloc(n_reload_action_stats, sizeof(*dst->reload_action_stats));
276 		dst->n_reload_action_stats = n_reload_action_stats;
277 		i = 0;
278 		parg.rsp_policy = &devlink_dl_reload_act_stats_nest;
279 		mnl_attr_for_each_nested(attr, nested) {
280 			if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_ACTION_STATS) {
281 				parg.data = &dst->reload_action_stats[i];
282 				if (devlink_dl_reload_act_stats_parse(&parg, attr))
283 					return MNL_CB_ERROR;
284 				i++;
285 			}
286 		}
287 	}
288 
289 	return 0;
290 }
291 
292 void devlink_dl_reload_stats_free(struct devlink_dl_reload_stats *obj)
293 {
294 	unsigned int i;
295 
296 	for (i = 0; i < obj->n_reload_action_info; i++)
297 		devlink_dl_reload_act_info_free(&obj->reload_action_info[i]);
298 	free(obj->reload_action_info);
299 }
300 
301 int devlink_dl_reload_stats_parse(struct ynl_parse_arg *yarg,
302 				  const struct nlattr *nested)
303 {
304 	struct devlink_dl_reload_stats *dst = yarg->data;
305 	unsigned int n_reload_action_info = 0;
306 	const struct nlattr *attr;
307 	struct ynl_parse_arg parg;
308 	int i;
309 
310 	parg.ys = yarg->ys;
311 
312 	if (dst->reload_action_info)
313 		return ynl_error_parse(yarg, "attribute already present (dl-reload-stats.reload-action-info)");
314 
315 	mnl_attr_for_each_nested(attr, nested) {
316 		unsigned int type = mnl_attr_get_type(attr);
317 
318 		if (type == DEVLINK_ATTR_RELOAD_ACTION_INFO) {
319 			n_reload_action_info++;
320 		}
321 	}
322 
323 	if (n_reload_action_info) {
324 		dst->reload_action_info = calloc(n_reload_action_info, sizeof(*dst->reload_action_info));
325 		dst->n_reload_action_info = n_reload_action_info;
326 		i = 0;
327 		parg.rsp_policy = &devlink_dl_reload_act_info_nest;
328 		mnl_attr_for_each_nested(attr, nested) {
329 			if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_ACTION_INFO) {
330 				parg.data = &dst->reload_action_info[i];
331 				if (devlink_dl_reload_act_info_parse(&parg, attr))
332 					return MNL_CB_ERROR;
333 				i++;
334 			}
335 		}
336 	}
337 
338 	return 0;
339 }
340 
341 void devlink_dl_dev_stats_free(struct devlink_dl_dev_stats *obj)
342 {
343 	devlink_dl_reload_stats_free(&obj->reload_stats);
344 	devlink_dl_reload_stats_free(&obj->remote_reload_stats);
345 }
346 
347 int devlink_dl_dev_stats_parse(struct ynl_parse_arg *yarg,
348 			       const struct nlattr *nested)
349 {
350 	struct devlink_dl_dev_stats *dst = yarg->data;
351 	const struct nlattr *attr;
352 	struct ynl_parse_arg parg;
353 
354 	parg.ys = yarg->ys;
355 
356 	mnl_attr_for_each_nested(attr, nested) {
357 		unsigned int type = mnl_attr_get_type(attr);
358 
359 		if (type == DEVLINK_ATTR_RELOAD_STATS) {
360 			if (ynl_attr_validate(yarg, attr))
361 				return MNL_CB_ERROR;
362 			dst->_present.reload_stats = 1;
363 
364 			parg.rsp_policy = &devlink_dl_reload_stats_nest;
365 			parg.data = &dst->reload_stats;
366 			if (devlink_dl_reload_stats_parse(&parg, attr))
367 				return MNL_CB_ERROR;
368 		} else if (type == DEVLINK_ATTR_REMOTE_RELOAD_STATS) {
369 			if (ynl_attr_validate(yarg, attr))
370 				return MNL_CB_ERROR;
371 			dst->_present.remote_reload_stats = 1;
372 
373 			parg.rsp_policy = &devlink_dl_reload_stats_nest;
374 			parg.data = &dst->remote_reload_stats;
375 			if (devlink_dl_reload_stats_parse(&parg, attr))
376 				return MNL_CB_ERROR;
377 		}
378 	}
379 
380 	return 0;
381 }
382 
383 /* ============== DEVLINK_CMD_GET ============== */
384 /* DEVLINK_CMD_GET - do */
385 void devlink_get_req_free(struct devlink_get_req *req)
386 {
387 	free(req->bus_name);
388 	free(req->dev_name);
389 	free(req);
390 }
391 
392 void devlink_get_rsp_free(struct devlink_get_rsp *rsp)
393 {
394 	free(rsp->bus_name);
395 	free(rsp->dev_name);
396 	devlink_dl_dev_stats_free(&rsp->dev_stats);
397 	free(rsp);
398 }
399 
400 int devlink_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
401 {
402 	struct ynl_parse_arg *yarg = data;
403 	struct devlink_get_rsp *dst;
404 	const struct nlattr *attr;
405 	struct ynl_parse_arg parg;
406 
407 	dst = yarg->data;
408 	parg.ys = yarg->ys;
409 
410 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
411 		unsigned int type = mnl_attr_get_type(attr);
412 
413 		if (type == DEVLINK_ATTR_BUS_NAME) {
414 			unsigned int len;
415 
416 			if (ynl_attr_validate(yarg, attr))
417 				return MNL_CB_ERROR;
418 
419 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
420 			dst->_present.bus_name_len = len;
421 			dst->bus_name = malloc(len + 1);
422 			memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
423 			dst->bus_name[len] = 0;
424 		} else if (type == DEVLINK_ATTR_DEV_NAME) {
425 			unsigned int len;
426 
427 			if (ynl_attr_validate(yarg, attr))
428 				return MNL_CB_ERROR;
429 
430 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
431 			dst->_present.dev_name_len = len;
432 			dst->dev_name = malloc(len + 1);
433 			memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
434 			dst->dev_name[len] = 0;
435 		} else if (type == DEVLINK_ATTR_RELOAD_FAILED) {
436 			if (ynl_attr_validate(yarg, attr))
437 				return MNL_CB_ERROR;
438 			dst->_present.reload_failed = 1;
439 			dst->reload_failed = mnl_attr_get_u8(attr);
440 		} else if (type == DEVLINK_ATTR_RELOAD_ACTION) {
441 			if (ynl_attr_validate(yarg, attr))
442 				return MNL_CB_ERROR;
443 			dst->_present.reload_action = 1;
444 			dst->reload_action = mnl_attr_get_u8(attr);
445 		} else if (type == DEVLINK_ATTR_DEV_STATS) {
446 			if (ynl_attr_validate(yarg, attr))
447 				return MNL_CB_ERROR;
448 			dst->_present.dev_stats = 1;
449 
450 			parg.rsp_policy = &devlink_dl_dev_stats_nest;
451 			parg.data = &dst->dev_stats;
452 			if (devlink_dl_dev_stats_parse(&parg, attr))
453 				return MNL_CB_ERROR;
454 		}
455 	}
456 
457 	return MNL_CB_OK;
458 }
459 
460 struct devlink_get_rsp *
461 devlink_get(struct ynl_sock *ys, struct devlink_get_req *req)
462 {
463 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
464 	struct devlink_get_rsp *rsp;
465 	struct nlmsghdr *nlh;
466 	int err;
467 
468 	nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_GET, 1);
469 	ys->req_policy = &devlink_nest;
470 	yrs.yarg.rsp_policy = &devlink_nest;
471 
472 	if (req->_present.bus_name_len)
473 		mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
474 	if (req->_present.dev_name_len)
475 		mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
476 
477 	rsp = calloc(1, sizeof(*rsp));
478 	yrs.yarg.data = rsp;
479 	yrs.cb = devlink_get_rsp_parse;
480 	yrs.rsp_cmd = 3;
481 
482 	err = ynl_exec(ys, nlh, &yrs);
483 	if (err < 0)
484 		goto err_free;
485 
486 	return rsp;
487 
488 err_free:
489 	devlink_get_rsp_free(rsp);
490 	return NULL;
491 }
492 
493 /* DEVLINK_CMD_GET - dump */
494 void devlink_get_list_free(struct devlink_get_list *rsp)
495 {
496 	struct devlink_get_list *next = rsp;
497 
498 	while ((void *)next != YNL_LIST_END) {
499 		rsp = next;
500 		next = rsp->next;
501 
502 		free(rsp->obj.bus_name);
503 		free(rsp->obj.dev_name);
504 		devlink_dl_dev_stats_free(&rsp->obj.dev_stats);
505 		free(rsp);
506 	}
507 }
508 
509 struct devlink_get_list *devlink_get_dump(struct ynl_sock *ys)
510 {
511 	struct ynl_dump_state yds = {};
512 	struct nlmsghdr *nlh;
513 	int err;
514 
515 	yds.ys = ys;
516 	yds.alloc_sz = sizeof(struct devlink_get_list);
517 	yds.cb = devlink_get_rsp_parse;
518 	yds.rsp_cmd = 3;
519 	yds.rsp_policy = &devlink_nest;
520 
521 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_GET, 1);
522 
523 	err = ynl_exec_dump(ys, nlh, &yds);
524 	if (err < 0)
525 		goto free_list;
526 
527 	return yds.first;
528 
529 free_list:
530 	devlink_get_list_free(yds.first);
531 	return NULL;
532 }
533 
534 /* ============== DEVLINK_CMD_INFO_GET ============== */
535 /* DEVLINK_CMD_INFO_GET - do */
536 void devlink_info_get_req_free(struct devlink_info_get_req *req)
537 {
538 	free(req->bus_name);
539 	free(req->dev_name);
540 	free(req);
541 }
542 
543 void devlink_info_get_rsp_free(struct devlink_info_get_rsp *rsp)
544 {
545 	unsigned int i;
546 
547 	free(rsp->bus_name);
548 	free(rsp->dev_name);
549 	free(rsp->info_driver_name);
550 	free(rsp->info_serial_number);
551 	for (i = 0; i < rsp->n_info_version_fixed; i++)
552 		devlink_dl_info_version_free(&rsp->info_version_fixed[i]);
553 	free(rsp->info_version_fixed);
554 	for (i = 0; i < rsp->n_info_version_running; i++)
555 		devlink_dl_info_version_free(&rsp->info_version_running[i]);
556 	free(rsp->info_version_running);
557 	for (i = 0; i < rsp->n_info_version_stored; i++)
558 		devlink_dl_info_version_free(&rsp->info_version_stored[i]);
559 	free(rsp->info_version_stored);
560 	free(rsp);
561 }
562 
563 int devlink_info_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
564 {
565 	unsigned int n_info_version_running = 0;
566 	unsigned int n_info_version_stored = 0;
567 	unsigned int n_info_version_fixed = 0;
568 	struct ynl_parse_arg *yarg = data;
569 	struct devlink_info_get_rsp *dst;
570 	const struct nlattr *attr;
571 	struct ynl_parse_arg parg;
572 	int i;
573 
574 	dst = yarg->data;
575 	parg.ys = yarg->ys;
576 
577 	if (dst->info_version_fixed)
578 		return ynl_error_parse(yarg, "attribute already present (devlink.info-version-fixed)");
579 	if (dst->info_version_running)
580 		return ynl_error_parse(yarg, "attribute already present (devlink.info-version-running)");
581 	if (dst->info_version_stored)
582 		return ynl_error_parse(yarg, "attribute already present (devlink.info-version-stored)");
583 
584 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
585 		unsigned int type = mnl_attr_get_type(attr);
586 
587 		if (type == DEVLINK_ATTR_BUS_NAME) {
588 			unsigned int len;
589 
590 			if (ynl_attr_validate(yarg, attr))
591 				return MNL_CB_ERROR;
592 
593 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
594 			dst->_present.bus_name_len = len;
595 			dst->bus_name = malloc(len + 1);
596 			memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
597 			dst->bus_name[len] = 0;
598 		} else if (type == DEVLINK_ATTR_DEV_NAME) {
599 			unsigned int len;
600 
601 			if (ynl_attr_validate(yarg, attr))
602 				return MNL_CB_ERROR;
603 
604 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
605 			dst->_present.dev_name_len = len;
606 			dst->dev_name = malloc(len + 1);
607 			memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
608 			dst->dev_name[len] = 0;
609 		} else if (type == DEVLINK_ATTR_INFO_DRIVER_NAME) {
610 			unsigned int len;
611 
612 			if (ynl_attr_validate(yarg, attr))
613 				return MNL_CB_ERROR;
614 
615 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
616 			dst->_present.info_driver_name_len = len;
617 			dst->info_driver_name = malloc(len + 1);
618 			memcpy(dst->info_driver_name, mnl_attr_get_str(attr), len);
619 			dst->info_driver_name[len] = 0;
620 		} else if (type == DEVLINK_ATTR_INFO_SERIAL_NUMBER) {
621 			unsigned int len;
622 
623 			if (ynl_attr_validate(yarg, attr))
624 				return MNL_CB_ERROR;
625 
626 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
627 			dst->_present.info_serial_number_len = len;
628 			dst->info_serial_number = malloc(len + 1);
629 			memcpy(dst->info_serial_number, mnl_attr_get_str(attr), len);
630 			dst->info_serial_number[len] = 0;
631 		} else if (type == DEVLINK_ATTR_INFO_VERSION_FIXED) {
632 			n_info_version_fixed++;
633 		} else if (type == DEVLINK_ATTR_INFO_VERSION_RUNNING) {
634 			n_info_version_running++;
635 		} else if (type == DEVLINK_ATTR_INFO_VERSION_STORED) {
636 			n_info_version_stored++;
637 		}
638 	}
639 
640 	if (n_info_version_fixed) {
641 		dst->info_version_fixed = calloc(n_info_version_fixed, sizeof(*dst->info_version_fixed));
642 		dst->n_info_version_fixed = n_info_version_fixed;
643 		i = 0;
644 		parg.rsp_policy = &devlink_dl_info_version_nest;
645 		mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
646 			if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_FIXED) {
647 				parg.data = &dst->info_version_fixed[i];
648 				if (devlink_dl_info_version_parse(&parg, attr))
649 					return MNL_CB_ERROR;
650 				i++;
651 			}
652 		}
653 	}
654 	if (n_info_version_running) {
655 		dst->info_version_running = calloc(n_info_version_running, sizeof(*dst->info_version_running));
656 		dst->n_info_version_running = n_info_version_running;
657 		i = 0;
658 		parg.rsp_policy = &devlink_dl_info_version_nest;
659 		mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
660 			if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_RUNNING) {
661 				parg.data = &dst->info_version_running[i];
662 				if (devlink_dl_info_version_parse(&parg, attr))
663 					return MNL_CB_ERROR;
664 				i++;
665 			}
666 		}
667 	}
668 	if (n_info_version_stored) {
669 		dst->info_version_stored = calloc(n_info_version_stored, sizeof(*dst->info_version_stored));
670 		dst->n_info_version_stored = n_info_version_stored;
671 		i = 0;
672 		parg.rsp_policy = &devlink_dl_info_version_nest;
673 		mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
674 			if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_STORED) {
675 				parg.data = &dst->info_version_stored[i];
676 				if (devlink_dl_info_version_parse(&parg, attr))
677 					return MNL_CB_ERROR;
678 				i++;
679 			}
680 		}
681 	}
682 
683 	return MNL_CB_OK;
684 }
685 
686 struct devlink_info_get_rsp *
687 devlink_info_get(struct ynl_sock *ys, struct devlink_info_get_req *req)
688 {
689 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
690 	struct devlink_info_get_rsp *rsp;
691 	struct nlmsghdr *nlh;
692 	int err;
693 
694 	nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_INFO_GET, 1);
695 	ys->req_policy = &devlink_nest;
696 	yrs.yarg.rsp_policy = &devlink_nest;
697 
698 	if (req->_present.bus_name_len)
699 		mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
700 	if (req->_present.dev_name_len)
701 		mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
702 
703 	rsp = calloc(1, sizeof(*rsp));
704 	yrs.yarg.data = rsp;
705 	yrs.cb = devlink_info_get_rsp_parse;
706 	yrs.rsp_cmd = DEVLINK_CMD_INFO_GET;
707 
708 	err = ynl_exec(ys, nlh, &yrs);
709 	if (err < 0)
710 		goto err_free;
711 
712 	return rsp;
713 
714 err_free:
715 	devlink_info_get_rsp_free(rsp);
716 	return NULL;
717 }
718 
719 const struct ynl_family ynl_devlink_family =  {
720 	.name		= "devlink",
721 };
722