xref: /openbmc/linux/tools/net/ynl/generated/devlink-user.c (revision 9b52fd4b630526aa78bde8f9c6217954c71dc6a5)
15d1a30ebSJakub Kicinski // SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
25d1a30ebSJakub Kicinski /* Do not edit directly, auto-generated from: */
35d1a30ebSJakub Kicinski /*	Documentation/netlink/specs/devlink.yaml */
45d1a30ebSJakub Kicinski /* YNL-GEN user source */
55d1a30ebSJakub Kicinski 
65d1a30ebSJakub Kicinski #include <stdlib.h>
7*9b52fd4bSJakub Kicinski #include <string.h>
85d1a30ebSJakub Kicinski #include "devlink-user.h"
95d1a30ebSJakub Kicinski #include "ynl.h"
105d1a30ebSJakub Kicinski #include <linux/devlink.h>
115d1a30ebSJakub Kicinski 
125d1a30ebSJakub Kicinski #include <libmnl/libmnl.h>
135d1a30ebSJakub Kicinski #include <linux/genetlink.h>
145d1a30ebSJakub Kicinski 
155d1a30ebSJakub Kicinski /* Enums */
165d1a30ebSJakub Kicinski static const char * const devlink_op_strmap[] = {
175d1a30ebSJakub Kicinski 	[3] = "get",
185d1a30ebSJakub Kicinski 	[DEVLINK_CMD_INFO_GET] = "info-get",
195d1a30ebSJakub Kicinski };
205d1a30ebSJakub Kicinski 
215d1a30ebSJakub Kicinski const char *devlink_op_str(int op)
225d1a30ebSJakub Kicinski {
235d1a30ebSJakub Kicinski 	if (op < 0 || op >= (int)MNL_ARRAY_SIZE(devlink_op_strmap))
245d1a30ebSJakub Kicinski 		return NULL;
255d1a30ebSJakub Kicinski 	return devlink_op_strmap[op];
265d1a30ebSJakub Kicinski }
275d1a30ebSJakub Kicinski 
285d1a30ebSJakub Kicinski /* Policies */
295d1a30ebSJakub Kicinski struct ynl_policy_attr devlink_dl_info_version_policy[DEVLINK_ATTR_MAX + 1] = {
305d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_INFO_VERSION_NAME] = { .name = "info-version-name", .type = YNL_PT_NUL_STR, },
315d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_INFO_VERSION_VALUE] = { .name = "info-version-value", .type = YNL_PT_NUL_STR, },
325d1a30ebSJakub Kicinski };
335d1a30ebSJakub Kicinski 
345d1a30ebSJakub Kicinski struct ynl_policy_nest devlink_dl_info_version_nest = {
355d1a30ebSJakub Kicinski 	.max_attr = DEVLINK_ATTR_MAX,
365d1a30ebSJakub Kicinski 	.table = devlink_dl_info_version_policy,
375d1a30ebSJakub Kicinski };
385d1a30ebSJakub Kicinski 
395d1a30ebSJakub Kicinski struct ynl_policy_attr devlink_dl_reload_stats_entry_policy[DEVLINK_ATTR_MAX + 1] = {
405d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_STATS_LIMIT] = { .name = "reload-stats-limit", .type = YNL_PT_U8, },
415d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_STATS_VALUE] = { .name = "reload-stats-value", .type = YNL_PT_U32, },
425d1a30ebSJakub Kicinski };
435d1a30ebSJakub Kicinski 
445d1a30ebSJakub Kicinski struct ynl_policy_nest devlink_dl_reload_stats_entry_nest = {
455d1a30ebSJakub Kicinski 	.max_attr = DEVLINK_ATTR_MAX,
465d1a30ebSJakub Kicinski 	.table = devlink_dl_reload_stats_entry_policy,
475d1a30ebSJakub Kicinski };
485d1a30ebSJakub Kicinski 
495d1a30ebSJakub Kicinski struct ynl_policy_attr devlink_dl_reload_act_stats_policy[DEVLINK_ATTR_MAX + 1] = {
505d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_STATS_ENTRY] = { .name = "reload-stats-entry", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_stats_entry_nest, },
515d1a30ebSJakub Kicinski };
525d1a30ebSJakub Kicinski 
535d1a30ebSJakub Kicinski struct ynl_policy_nest devlink_dl_reload_act_stats_nest = {
545d1a30ebSJakub Kicinski 	.max_attr = DEVLINK_ATTR_MAX,
555d1a30ebSJakub Kicinski 	.table = devlink_dl_reload_act_stats_policy,
565d1a30ebSJakub Kicinski };
575d1a30ebSJakub Kicinski 
585d1a30ebSJakub Kicinski struct ynl_policy_attr devlink_dl_reload_act_info_policy[DEVLINK_ATTR_MAX + 1] = {
595d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_ACTION] = { .name = "reload-action", .type = YNL_PT_U8, },
605d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_ACTION_STATS] = { .name = "reload-action-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_act_stats_nest, },
615d1a30ebSJakub Kicinski };
625d1a30ebSJakub Kicinski 
635d1a30ebSJakub Kicinski struct ynl_policy_nest devlink_dl_reload_act_info_nest = {
645d1a30ebSJakub Kicinski 	.max_attr = DEVLINK_ATTR_MAX,
655d1a30ebSJakub Kicinski 	.table = devlink_dl_reload_act_info_policy,
665d1a30ebSJakub Kicinski };
675d1a30ebSJakub Kicinski 
685d1a30ebSJakub Kicinski struct ynl_policy_attr devlink_dl_reload_stats_policy[DEVLINK_ATTR_MAX + 1] = {
695d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_ACTION_INFO] = { .name = "reload-action-info", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_act_info_nest, },
705d1a30ebSJakub Kicinski };
715d1a30ebSJakub Kicinski 
725d1a30ebSJakub Kicinski struct ynl_policy_nest devlink_dl_reload_stats_nest = {
735d1a30ebSJakub Kicinski 	.max_attr = DEVLINK_ATTR_MAX,
745d1a30ebSJakub Kicinski 	.table = devlink_dl_reload_stats_policy,
755d1a30ebSJakub Kicinski };
765d1a30ebSJakub Kicinski 
775d1a30ebSJakub Kicinski struct ynl_policy_attr devlink_dl_dev_stats_policy[DEVLINK_ATTR_MAX + 1] = {
785d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_STATS] = { .name = "reload-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_stats_nest, },
795d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_REMOTE_RELOAD_STATS] = { .name = "remote-reload-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_stats_nest, },
805d1a30ebSJakub Kicinski };
815d1a30ebSJakub Kicinski 
825d1a30ebSJakub Kicinski struct ynl_policy_nest devlink_dl_dev_stats_nest = {
835d1a30ebSJakub Kicinski 	.max_attr = DEVLINK_ATTR_MAX,
845d1a30ebSJakub Kicinski 	.table = devlink_dl_dev_stats_policy,
855d1a30ebSJakub Kicinski };
865d1a30ebSJakub Kicinski 
875d1a30ebSJakub Kicinski struct ynl_policy_attr devlink_policy[DEVLINK_ATTR_MAX + 1] = {
885d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_BUS_NAME] = { .name = "bus-name", .type = YNL_PT_NUL_STR, },
895d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_DEV_NAME] = { .name = "dev-name", .type = YNL_PT_NUL_STR, },
905d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_PORT_INDEX] = { .name = "port-index", .type = YNL_PT_U32, },
915d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_INFO_DRIVER_NAME] = { .name = "info-driver-name", .type = YNL_PT_NUL_STR, },
925d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_INFO_SERIAL_NUMBER] = { .name = "info-serial-number", .type = YNL_PT_NUL_STR, },
935d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_INFO_VERSION_FIXED] = { .name = "info-version-fixed", .type = YNL_PT_NEST, .nest = &devlink_dl_info_version_nest, },
945d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_INFO_VERSION_RUNNING] = { .name = "info-version-running", .type = YNL_PT_NEST, .nest = &devlink_dl_info_version_nest, },
955d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_INFO_VERSION_STORED] = { .name = "info-version-stored", .type = YNL_PT_NEST, .nest = &devlink_dl_info_version_nest, },
965d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_INFO_VERSION_NAME] = { .name = "info-version-name", .type = YNL_PT_NUL_STR, },
975d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_INFO_VERSION_VALUE] = { .name = "info-version-value", .type = YNL_PT_NUL_STR, },
985d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_FAILED] = { .name = "reload-failed", .type = YNL_PT_U8, },
995d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_ACTION] = { .name = "reload-action", .type = YNL_PT_U8, },
1005d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_DEV_STATS] = { .name = "dev-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_dev_stats_nest, },
1015d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_STATS] = { .name = "reload-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_stats_nest, },
1025d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_STATS_ENTRY] = { .name = "reload-stats-entry", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_stats_entry_nest, },
1035d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_STATS_LIMIT] = { .name = "reload-stats-limit", .type = YNL_PT_U8, },
1045d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_STATS_VALUE] = { .name = "reload-stats-value", .type = YNL_PT_U32, },
1055d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_REMOTE_RELOAD_STATS] = { .name = "remote-reload-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_stats_nest, },
1065d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_ACTION_INFO] = { .name = "reload-action-info", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_act_info_nest, },
1075d1a30ebSJakub Kicinski 	[DEVLINK_ATTR_RELOAD_ACTION_STATS] = { .name = "reload-action-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_act_stats_nest, },
1085d1a30ebSJakub Kicinski };
1095d1a30ebSJakub Kicinski 
1105d1a30ebSJakub Kicinski struct ynl_policy_nest devlink_nest = {
1115d1a30ebSJakub Kicinski 	.max_attr = DEVLINK_ATTR_MAX,
1125d1a30ebSJakub Kicinski 	.table = devlink_policy,
1135d1a30ebSJakub Kicinski };
1145d1a30ebSJakub Kicinski 
1155d1a30ebSJakub Kicinski /* Common nested types */
1165d1a30ebSJakub Kicinski void devlink_dl_info_version_free(struct devlink_dl_info_version *obj)
1175d1a30ebSJakub Kicinski {
1185d1a30ebSJakub Kicinski 	free(obj->info_version_name);
1195d1a30ebSJakub Kicinski 	free(obj->info_version_value);
1205d1a30ebSJakub Kicinski }
1215d1a30ebSJakub Kicinski 
1225d1a30ebSJakub Kicinski int devlink_dl_info_version_parse(struct ynl_parse_arg *yarg,
1235d1a30ebSJakub Kicinski 				  const struct nlattr *nested)
1245d1a30ebSJakub Kicinski {
1255d1a30ebSJakub Kicinski 	struct devlink_dl_info_version *dst = yarg->data;
1265d1a30ebSJakub Kicinski 	const struct nlattr *attr;
1275d1a30ebSJakub Kicinski 
1285d1a30ebSJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
1295d1a30ebSJakub Kicinski 		if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_NAME) {
1305d1a30ebSJakub Kicinski 			unsigned int len;
1315d1a30ebSJakub Kicinski 
1325d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1335d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
1345d1a30ebSJakub Kicinski 
1355d1a30ebSJakub Kicinski 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
1365d1a30ebSJakub Kicinski 			dst->_present.info_version_name_len = len;
1375d1a30ebSJakub Kicinski 			dst->info_version_name = malloc(len + 1);
1385d1a30ebSJakub Kicinski 			memcpy(dst->info_version_name, mnl_attr_get_str(attr), len);
1395d1a30ebSJakub Kicinski 			dst->info_version_name[len] = 0;
1405d1a30ebSJakub Kicinski 		}
1415d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_VALUE) {
1425d1a30ebSJakub Kicinski 			unsigned int len;
1435d1a30ebSJakub Kicinski 
1445d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1455d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
1465d1a30ebSJakub Kicinski 
1475d1a30ebSJakub Kicinski 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
1485d1a30ebSJakub Kicinski 			dst->_present.info_version_value_len = len;
1495d1a30ebSJakub Kicinski 			dst->info_version_value = malloc(len + 1);
1505d1a30ebSJakub Kicinski 			memcpy(dst->info_version_value, mnl_attr_get_str(attr), len);
1515d1a30ebSJakub Kicinski 			dst->info_version_value[len] = 0;
1525d1a30ebSJakub Kicinski 		}
1535d1a30ebSJakub Kicinski 	}
1545d1a30ebSJakub Kicinski 
1555d1a30ebSJakub Kicinski 	return 0;
1565d1a30ebSJakub Kicinski }
1575d1a30ebSJakub Kicinski 
1585d1a30ebSJakub Kicinski void
1595d1a30ebSJakub Kicinski devlink_dl_reload_stats_entry_free(struct devlink_dl_reload_stats_entry *obj)
1605d1a30ebSJakub Kicinski {
1615d1a30ebSJakub Kicinski }
1625d1a30ebSJakub Kicinski 
1635d1a30ebSJakub Kicinski int devlink_dl_reload_stats_entry_parse(struct ynl_parse_arg *yarg,
1645d1a30ebSJakub Kicinski 					const struct nlattr *nested)
1655d1a30ebSJakub Kicinski {
1665d1a30ebSJakub Kicinski 	struct devlink_dl_reload_stats_entry *dst = yarg->data;
1675d1a30ebSJakub Kicinski 	const struct nlattr *attr;
1685d1a30ebSJakub Kicinski 
1695d1a30ebSJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
1705d1a30ebSJakub Kicinski 		if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_STATS_LIMIT) {
1715d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1725d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
1735d1a30ebSJakub Kicinski 			dst->_present.reload_stats_limit = 1;
1745d1a30ebSJakub Kicinski 			dst->reload_stats_limit = mnl_attr_get_u8(attr);
1755d1a30ebSJakub Kicinski 		}
1765d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_STATS_VALUE) {
1775d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
1785d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
1795d1a30ebSJakub Kicinski 			dst->_present.reload_stats_value = 1;
1805d1a30ebSJakub Kicinski 			dst->reload_stats_value = mnl_attr_get_u32(attr);
1815d1a30ebSJakub Kicinski 		}
1825d1a30ebSJakub Kicinski 	}
1835d1a30ebSJakub Kicinski 
1845d1a30ebSJakub Kicinski 	return 0;
1855d1a30ebSJakub Kicinski }
1865d1a30ebSJakub Kicinski 
1875d1a30ebSJakub Kicinski void devlink_dl_reload_act_stats_free(struct devlink_dl_reload_act_stats *obj)
1885d1a30ebSJakub Kicinski {
1895d1a30ebSJakub Kicinski 	unsigned int i;
1905d1a30ebSJakub Kicinski 
1915d1a30ebSJakub Kicinski 	for (i = 0; i < obj->n_reload_stats_entry; i++)
1925d1a30ebSJakub Kicinski 		devlink_dl_reload_stats_entry_free(&obj->reload_stats_entry[i]);
1935d1a30ebSJakub Kicinski 	free(obj->reload_stats_entry);
1945d1a30ebSJakub Kicinski }
1955d1a30ebSJakub Kicinski 
1965d1a30ebSJakub Kicinski int devlink_dl_reload_act_stats_parse(struct ynl_parse_arg *yarg,
1975d1a30ebSJakub Kicinski 				      const struct nlattr *nested)
1985d1a30ebSJakub Kicinski {
1995d1a30ebSJakub Kicinski 	struct devlink_dl_reload_act_stats *dst = yarg->data;
2005d1a30ebSJakub Kicinski 	unsigned int n_reload_stats_entry = 0;
2015d1a30ebSJakub Kicinski 	const struct nlattr *attr;
2025d1a30ebSJakub Kicinski 	struct ynl_parse_arg parg;
2035d1a30ebSJakub Kicinski 	int i;
2045d1a30ebSJakub Kicinski 
2055d1a30ebSJakub Kicinski 	parg.ys = yarg->ys;
2065d1a30ebSJakub Kicinski 
2075d1a30ebSJakub Kicinski 	if (dst->reload_stats_entry)
2085d1a30ebSJakub Kicinski 		return ynl_error_parse(yarg, "attribute already present (dl-reload-act-stats.reload-stats-entry)");
2095d1a30ebSJakub Kicinski 
2105d1a30ebSJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
2115d1a30ebSJakub Kicinski 		if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_STATS_ENTRY) {
2125d1a30ebSJakub Kicinski 			n_reload_stats_entry++;
2135d1a30ebSJakub Kicinski 		}
2145d1a30ebSJakub Kicinski 	}
2155d1a30ebSJakub Kicinski 
2165d1a30ebSJakub Kicinski 	if (n_reload_stats_entry) {
2175d1a30ebSJakub Kicinski 		dst->reload_stats_entry = calloc(n_reload_stats_entry, sizeof(*dst->reload_stats_entry));
2185d1a30ebSJakub Kicinski 		dst->n_reload_stats_entry = n_reload_stats_entry;
2195d1a30ebSJakub Kicinski 		i = 0;
2205d1a30ebSJakub Kicinski 		parg.rsp_policy = &devlink_dl_reload_stats_entry_nest;
2215d1a30ebSJakub Kicinski 		mnl_attr_for_each_nested(attr, nested) {
2225d1a30ebSJakub Kicinski 			if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_STATS_ENTRY) {
2235d1a30ebSJakub Kicinski 				parg.data = &dst->reload_stats_entry[i];
2245d1a30ebSJakub Kicinski 				if (devlink_dl_reload_stats_entry_parse(&parg, attr))
2255d1a30ebSJakub Kicinski 					return MNL_CB_ERROR;
2265d1a30ebSJakub Kicinski 				i++;
2275d1a30ebSJakub Kicinski 			}
2285d1a30ebSJakub Kicinski 		}
2295d1a30ebSJakub Kicinski 	}
2305d1a30ebSJakub Kicinski 
2315d1a30ebSJakub Kicinski 	return 0;
2325d1a30ebSJakub Kicinski }
2335d1a30ebSJakub Kicinski 
2345d1a30ebSJakub Kicinski void devlink_dl_reload_act_info_free(struct devlink_dl_reload_act_info *obj)
2355d1a30ebSJakub Kicinski {
2365d1a30ebSJakub Kicinski 	unsigned int i;
2375d1a30ebSJakub Kicinski 
2385d1a30ebSJakub Kicinski 	for (i = 0; i < obj->n_reload_action_stats; i++)
2395d1a30ebSJakub Kicinski 		devlink_dl_reload_act_stats_free(&obj->reload_action_stats[i]);
2405d1a30ebSJakub Kicinski 	free(obj->reload_action_stats);
2415d1a30ebSJakub Kicinski }
2425d1a30ebSJakub Kicinski 
2435d1a30ebSJakub Kicinski int devlink_dl_reload_act_info_parse(struct ynl_parse_arg *yarg,
2445d1a30ebSJakub Kicinski 				     const struct nlattr *nested)
2455d1a30ebSJakub Kicinski {
2465d1a30ebSJakub Kicinski 	struct devlink_dl_reload_act_info *dst = yarg->data;
2475d1a30ebSJakub Kicinski 	unsigned int n_reload_action_stats = 0;
2485d1a30ebSJakub Kicinski 	const struct nlattr *attr;
2495d1a30ebSJakub Kicinski 	struct ynl_parse_arg parg;
2505d1a30ebSJakub Kicinski 	int i;
2515d1a30ebSJakub Kicinski 
2525d1a30ebSJakub Kicinski 	parg.ys = yarg->ys;
2535d1a30ebSJakub Kicinski 
2545d1a30ebSJakub Kicinski 	if (dst->reload_action_stats)
2555d1a30ebSJakub Kicinski 		return ynl_error_parse(yarg, "attribute already present (dl-reload-act-info.reload-action-stats)");
2565d1a30ebSJakub Kicinski 
2575d1a30ebSJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
2585d1a30ebSJakub Kicinski 		if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_ACTION) {
2595d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
2605d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
2615d1a30ebSJakub Kicinski 			dst->_present.reload_action = 1;
2625d1a30ebSJakub Kicinski 			dst->reload_action = mnl_attr_get_u8(attr);
2635d1a30ebSJakub Kicinski 		}
2645d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_ACTION_STATS) {
2655d1a30ebSJakub Kicinski 			n_reload_action_stats++;
2665d1a30ebSJakub Kicinski 		}
2675d1a30ebSJakub Kicinski 	}
2685d1a30ebSJakub Kicinski 
2695d1a30ebSJakub Kicinski 	if (n_reload_action_stats) {
2705d1a30ebSJakub Kicinski 		dst->reload_action_stats = calloc(n_reload_action_stats, sizeof(*dst->reload_action_stats));
2715d1a30ebSJakub Kicinski 		dst->n_reload_action_stats = n_reload_action_stats;
2725d1a30ebSJakub Kicinski 		i = 0;
2735d1a30ebSJakub Kicinski 		parg.rsp_policy = &devlink_dl_reload_act_stats_nest;
2745d1a30ebSJakub Kicinski 		mnl_attr_for_each_nested(attr, nested) {
2755d1a30ebSJakub Kicinski 			if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_ACTION_STATS) {
2765d1a30ebSJakub Kicinski 				parg.data = &dst->reload_action_stats[i];
2775d1a30ebSJakub Kicinski 				if (devlink_dl_reload_act_stats_parse(&parg, attr))
2785d1a30ebSJakub Kicinski 					return MNL_CB_ERROR;
2795d1a30ebSJakub Kicinski 				i++;
2805d1a30ebSJakub Kicinski 			}
2815d1a30ebSJakub Kicinski 		}
2825d1a30ebSJakub Kicinski 	}
2835d1a30ebSJakub Kicinski 
2845d1a30ebSJakub Kicinski 	return 0;
2855d1a30ebSJakub Kicinski }
2865d1a30ebSJakub Kicinski 
2875d1a30ebSJakub Kicinski void devlink_dl_reload_stats_free(struct devlink_dl_reload_stats *obj)
2885d1a30ebSJakub Kicinski {
2895d1a30ebSJakub Kicinski 	unsigned int i;
2905d1a30ebSJakub Kicinski 
2915d1a30ebSJakub Kicinski 	for (i = 0; i < obj->n_reload_action_info; i++)
2925d1a30ebSJakub Kicinski 		devlink_dl_reload_act_info_free(&obj->reload_action_info[i]);
2935d1a30ebSJakub Kicinski 	free(obj->reload_action_info);
2945d1a30ebSJakub Kicinski }
2955d1a30ebSJakub Kicinski 
2965d1a30ebSJakub Kicinski int devlink_dl_reload_stats_parse(struct ynl_parse_arg *yarg,
2975d1a30ebSJakub Kicinski 				  const struct nlattr *nested)
2985d1a30ebSJakub Kicinski {
2995d1a30ebSJakub Kicinski 	struct devlink_dl_reload_stats *dst = yarg->data;
3005d1a30ebSJakub Kicinski 	unsigned int n_reload_action_info = 0;
3015d1a30ebSJakub Kicinski 	const struct nlattr *attr;
3025d1a30ebSJakub Kicinski 	struct ynl_parse_arg parg;
3035d1a30ebSJakub Kicinski 	int i;
3045d1a30ebSJakub Kicinski 
3055d1a30ebSJakub Kicinski 	parg.ys = yarg->ys;
3065d1a30ebSJakub Kicinski 
3075d1a30ebSJakub Kicinski 	if (dst->reload_action_info)
3085d1a30ebSJakub Kicinski 		return ynl_error_parse(yarg, "attribute already present (dl-reload-stats.reload-action-info)");
3095d1a30ebSJakub Kicinski 
3105d1a30ebSJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
3115d1a30ebSJakub Kicinski 		if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_ACTION_INFO) {
3125d1a30ebSJakub Kicinski 			n_reload_action_info++;
3135d1a30ebSJakub Kicinski 		}
3145d1a30ebSJakub Kicinski 	}
3155d1a30ebSJakub Kicinski 
3165d1a30ebSJakub Kicinski 	if (n_reload_action_info) {
3175d1a30ebSJakub Kicinski 		dst->reload_action_info = calloc(n_reload_action_info, sizeof(*dst->reload_action_info));
3185d1a30ebSJakub Kicinski 		dst->n_reload_action_info = n_reload_action_info;
3195d1a30ebSJakub Kicinski 		i = 0;
3205d1a30ebSJakub Kicinski 		parg.rsp_policy = &devlink_dl_reload_act_info_nest;
3215d1a30ebSJakub Kicinski 		mnl_attr_for_each_nested(attr, nested) {
3225d1a30ebSJakub Kicinski 			if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_ACTION_INFO) {
3235d1a30ebSJakub Kicinski 				parg.data = &dst->reload_action_info[i];
3245d1a30ebSJakub Kicinski 				if (devlink_dl_reload_act_info_parse(&parg, attr))
3255d1a30ebSJakub Kicinski 					return MNL_CB_ERROR;
3265d1a30ebSJakub Kicinski 				i++;
3275d1a30ebSJakub Kicinski 			}
3285d1a30ebSJakub Kicinski 		}
3295d1a30ebSJakub Kicinski 	}
3305d1a30ebSJakub Kicinski 
3315d1a30ebSJakub Kicinski 	return 0;
3325d1a30ebSJakub Kicinski }
3335d1a30ebSJakub Kicinski 
3345d1a30ebSJakub Kicinski void devlink_dl_dev_stats_free(struct devlink_dl_dev_stats *obj)
3355d1a30ebSJakub Kicinski {
3365d1a30ebSJakub Kicinski 	devlink_dl_reload_stats_free(&obj->reload_stats);
3375d1a30ebSJakub Kicinski 	devlink_dl_reload_stats_free(&obj->remote_reload_stats);
3385d1a30ebSJakub Kicinski }
3395d1a30ebSJakub Kicinski 
3405d1a30ebSJakub Kicinski int devlink_dl_dev_stats_parse(struct ynl_parse_arg *yarg,
3415d1a30ebSJakub Kicinski 			       const struct nlattr *nested)
3425d1a30ebSJakub Kicinski {
3435d1a30ebSJakub Kicinski 	struct devlink_dl_dev_stats *dst = yarg->data;
3445d1a30ebSJakub Kicinski 	const struct nlattr *attr;
3455d1a30ebSJakub Kicinski 	struct ynl_parse_arg parg;
3465d1a30ebSJakub Kicinski 
3475d1a30ebSJakub Kicinski 	parg.ys = yarg->ys;
3485d1a30ebSJakub Kicinski 
3495d1a30ebSJakub Kicinski 	mnl_attr_for_each_nested(attr, nested) {
3505d1a30ebSJakub Kicinski 		if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_STATS) {
3515d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3525d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
3535d1a30ebSJakub Kicinski 			dst->_present.reload_stats = 1;
3545d1a30ebSJakub Kicinski 
3555d1a30ebSJakub Kicinski 			parg.rsp_policy = &devlink_dl_reload_stats_nest;
3565d1a30ebSJakub Kicinski 			parg.data = &dst->reload_stats;
3575d1a30ebSJakub Kicinski 			if (devlink_dl_reload_stats_parse(&parg, attr))
3585d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
3595d1a30ebSJakub Kicinski 		}
3605d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_REMOTE_RELOAD_STATS) {
3615d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
3625d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
3635d1a30ebSJakub Kicinski 			dst->_present.remote_reload_stats = 1;
3645d1a30ebSJakub Kicinski 
3655d1a30ebSJakub Kicinski 			parg.rsp_policy = &devlink_dl_reload_stats_nest;
3665d1a30ebSJakub Kicinski 			parg.data = &dst->remote_reload_stats;
3675d1a30ebSJakub Kicinski 			if (devlink_dl_reload_stats_parse(&parg, attr))
3685d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
3695d1a30ebSJakub Kicinski 		}
3705d1a30ebSJakub Kicinski 	}
3715d1a30ebSJakub Kicinski 
3725d1a30ebSJakub Kicinski 	return 0;
3735d1a30ebSJakub Kicinski }
3745d1a30ebSJakub Kicinski 
3755d1a30ebSJakub Kicinski /* ============== DEVLINK_CMD_GET ============== */
3765d1a30ebSJakub Kicinski /* DEVLINK_CMD_GET - do */
3775d1a30ebSJakub Kicinski void devlink_get_req_free(struct devlink_get_req *req)
3785d1a30ebSJakub Kicinski {
3795d1a30ebSJakub Kicinski 	free(req->bus_name);
3805d1a30ebSJakub Kicinski 	free(req->dev_name);
3815d1a30ebSJakub Kicinski 	free(req);
3825d1a30ebSJakub Kicinski }
3835d1a30ebSJakub Kicinski 
3845d1a30ebSJakub Kicinski void devlink_get_rsp_free(struct devlink_get_rsp *rsp)
3855d1a30ebSJakub Kicinski {
3865d1a30ebSJakub Kicinski 	free(rsp->bus_name);
3875d1a30ebSJakub Kicinski 	free(rsp->dev_name);
3885d1a30ebSJakub Kicinski 	devlink_dl_dev_stats_free(&rsp->dev_stats);
3895d1a30ebSJakub Kicinski 	free(rsp);
3905d1a30ebSJakub Kicinski }
3915d1a30ebSJakub Kicinski 
3925d1a30ebSJakub Kicinski int devlink_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
3935d1a30ebSJakub Kicinski {
3945d1a30ebSJakub Kicinski 	struct ynl_parse_arg *yarg = data;
3955d1a30ebSJakub Kicinski 	struct devlink_get_rsp *dst;
3965d1a30ebSJakub Kicinski 	const struct nlattr *attr;
3975d1a30ebSJakub Kicinski 	struct ynl_parse_arg parg;
3985d1a30ebSJakub Kicinski 
3995d1a30ebSJakub Kicinski 	dst = yarg->data;
4005d1a30ebSJakub Kicinski 	parg.ys = yarg->ys;
4015d1a30ebSJakub Kicinski 
4025d1a30ebSJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
4035d1a30ebSJakub Kicinski 		if (mnl_attr_get_type(attr) == DEVLINK_ATTR_BUS_NAME) {
4045d1a30ebSJakub Kicinski 			unsigned int len;
4055d1a30ebSJakub Kicinski 
4065d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4075d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
4085d1a30ebSJakub Kicinski 
4095d1a30ebSJakub Kicinski 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
4105d1a30ebSJakub Kicinski 			dst->_present.bus_name_len = len;
4115d1a30ebSJakub Kicinski 			dst->bus_name = malloc(len + 1);
4125d1a30ebSJakub Kicinski 			memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
4135d1a30ebSJakub Kicinski 			dst->bus_name[len] = 0;
4145d1a30ebSJakub Kicinski 		}
4155d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_DEV_NAME) {
4165d1a30ebSJakub Kicinski 			unsigned int len;
4175d1a30ebSJakub Kicinski 
4185d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4195d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
4205d1a30ebSJakub Kicinski 
4215d1a30ebSJakub Kicinski 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
4225d1a30ebSJakub Kicinski 			dst->_present.dev_name_len = len;
4235d1a30ebSJakub Kicinski 			dst->dev_name = malloc(len + 1);
4245d1a30ebSJakub Kicinski 			memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
4255d1a30ebSJakub Kicinski 			dst->dev_name[len] = 0;
4265d1a30ebSJakub Kicinski 		}
4275d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_FAILED) {
4285d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4295d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
4305d1a30ebSJakub Kicinski 			dst->_present.reload_failed = 1;
4315d1a30ebSJakub Kicinski 			dst->reload_failed = mnl_attr_get_u8(attr);
4325d1a30ebSJakub Kicinski 		}
4335d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_ACTION) {
4345d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4355d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
4365d1a30ebSJakub Kicinski 			dst->_present.reload_action = 1;
4375d1a30ebSJakub Kicinski 			dst->reload_action = mnl_attr_get_u8(attr);
4385d1a30ebSJakub Kicinski 		}
4395d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_DEV_STATS) {
4405d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
4415d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
4425d1a30ebSJakub Kicinski 			dst->_present.dev_stats = 1;
4435d1a30ebSJakub Kicinski 
4445d1a30ebSJakub Kicinski 			parg.rsp_policy = &devlink_dl_dev_stats_nest;
4455d1a30ebSJakub Kicinski 			parg.data = &dst->dev_stats;
4465d1a30ebSJakub Kicinski 			if (devlink_dl_dev_stats_parse(&parg, attr))
4475d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
4485d1a30ebSJakub Kicinski 		}
4495d1a30ebSJakub Kicinski 	}
4505d1a30ebSJakub Kicinski 
4515d1a30ebSJakub Kicinski 	return MNL_CB_OK;
4525d1a30ebSJakub Kicinski }
4535d1a30ebSJakub Kicinski 
4545d1a30ebSJakub Kicinski struct devlink_get_rsp *
4555d1a30ebSJakub Kicinski devlink_get(struct ynl_sock *ys, struct devlink_get_req *req)
4565d1a30ebSJakub Kicinski {
4575d1a30ebSJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
4585d1a30ebSJakub Kicinski 	struct devlink_get_rsp *rsp;
4595d1a30ebSJakub Kicinski 	struct nlmsghdr *nlh;
4605d1a30ebSJakub Kicinski 	int err;
4615d1a30ebSJakub Kicinski 
4625d1a30ebSJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_GET, 1);
4635d1a30ebSJakub Kicinski 	ys->req_policy = &devlink_nest;
4645d1a30ebSJakub Kicinski 	yrs.yarg.rsp_policy = &devlink_nest;
4655d1a30ebSJakub Kicinski 
4665d1a30ebSJakub Kicinski 	if (req->_present.bus_name_len)
4675d1a30ebSJakub Kicinski 		mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
4685d1a30ebSJakub Kicinski 	if (req->_present.dev_name_len)
4695d1a30ebSJakub Kicinski 		mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
4705d1a30ebSJakub Kicinski 
4715d1a30ebSJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
4725d1a30ebSJakub Kicinski 	yrs.yarg.data = rsp;
4735d1a30ebSJakub Kicinski 	yrs.cb = devlink_get_rsp_parse;
4745d1a30ebSJakub Kicinski 	yrs.rsp_cmd = 3;
4755d1a30ebSJakub Kicinski 
4765d1a30ebSJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
4775d1a30ebSJakub Kicinski 	if (err < 0)
4785d1a30ebSJakub Kicinski 		goto err_free;
4795d1a30ebSJakub Kicinski 
4805d1a30ebSJakub Kicinski 	return rsp;
4815d1a30ebSJakub Kicinski 
4825d1a30ebSJakub Kicinski err_free:
4835d1a30ebSJakub Kicinski 	devlink_get_rsp_free(rsp);
4845d1a30ebSJakub Kicinski 	return NULL;
4855d1a30ebSJakub Kicinski }
4865d1a30ebSJakub Kicinski 
4875d1a30ebSJakub Kicinski /* DEVLINK_CMD_GET - dump */
4885d1a30ebSJakub Kicinski void devlink_get_list_free(struct devlink_get_list *rsp)
4895d1a30ebSJakub Kicinski {
4905d1a30ebSJakub Kicinski 	struct devlink_get_list *next = rsp;
4915d1a30ebSJakub Kicinski 
4925d1a30ebSJakub Kicinski 	while ((void *)next != YNL_LIST_END) {
4935d1a30ebSJakub Kicinski 		rsp = next;
4945d1a30ebSJakub Kicinski 		next = rsp->next;
4955d1a30ebSJakub Kicinski 
4965d1a30ebSJakub Kicinski 		free(rsp->obj.bus_name);
4975d1a30ebSJakub Kicinski 		free(rsp->obj.dev_name);
4985d1a30ebSJakub Kicinski 		devlink_dl_dev_stats_free(&rsp->obj.dev_stats);
4995d1a30ebSJakub Kicinski 		free(rsp);
5005d1a30ebSJakub Kicinski 	}
5015d1a30ebSJakub Kicinski }
5025d1a30ebSJakub Kicinski 
5035d1a30ebSJakub Kicinski struct devlink_get_list *devlink_get_dump(struct ynl_sock *ys)
5045d1a30ebSJakub Kicinski {
5055d1a30ebSJakub Kicinski 	struct ynl_dump_state yds = {};
5065d1a30ebSJakub Kicinski 	struct nlmsghdr *nlh;
5075d1a30ebSJakub Kicinski 	int err;
5085d1a30ebSJakub Kicinski 
5095d1a30ebSJakub Kicinski 	yds.ys = ys;
5105d1a30ebSJakub Kicinski 	yds.alloc_sz = sizeof(struct devlink_get_list);
5115d1a30ebSJakub Kicinski 	yds.cb = devlink_get_rsp_parse;
5125d1a30ebSJakub Kicinski 	yds.rsp_cmd = 3;
5135d1a30ebSJakub Kicinski 	yds.rsp_policy = &devlink_nest;
5145d1a30ebSJakub Kicinski 
5155d1a30ebSJakub Kicinski 	nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_GET, 1);
5165d1a30ebSJakub Kicinski 
5175d1a30ebSJakub Kicinski 	err = ynl_exec_dump(ys, nlh, &yds);
5185d1a30ebSJakub Kicinski 	if (err < 0)
5195d1a30ebSJakub Kicinski 		goto free_list;
5205d1a30ebSJakub Kicinski 
5215d1a30ebSJakub Kicinski 	return yds.first;
5225d1a30ebSJakub Kicinski 
5235d1a30ebSJakub Kicinski free_list:
5245d1a30ebSJakub Kicinski 	devlink_get_list_free(yds.first);
5255d1a30ebSJakub Kicinski 	return NULL;
5265d1a30ebSJakub Kicinski }
5275d1a30ebSJakub Kicinski 
5285d1a30ebSJakub Kicinski /* ============== DEVLINK_CMD_INFO_GET ============== */
5295d1a30ebSJakub Kicinski /* DEVLINK_CMD_INFO_GET - do */
5305d1a30ebSJakub Kicinski void devlink_info_get_req_free(struct devlink_info_get_req *req)
5315d1a30ebSJakub Kicinski {
5325d1a30ebSJakub Kicinski 	free(req->bus_name);
5335d1a30ebSJakub Kicinski 	free(req->dev_name);
5345d1a30ebSJakub Kicinski 	free(req);
5355d1a30ebSJakub Kicinski }
5365d1a30ebSJakub Kicinski 
5375d1a30ebSJakub Kicinski void devlink_info_get_rsp_free(struct devlink_info_get_rsp *rsp)
5385d1a30ebSJakub Kicinski {
5395d1a30ebSJakub Kicinski 	unsigned int i;
5405d1a30ebSJakub Kicinski 
5415d1a30ebSJakub Kicinski 	free(rsp->bus_name);
5425d1a30ebSJakub Kicinski 	free(rsp->dev_name);
5435d1a30ebSJakub Kicinski 	free(rsp->info_driver_name);
5445d1a30ebSJakub Kicinski 	free(rsp->info_serial_number);
5455d1a30ebSJakub Kicinski 	for (i = 0; i < rsp->n_info_version_fixed; i++)
5465d1a30ebSJakub Kicinski 		devlink_dl_info_version_free(&rsp->info_version_fixed[i]);
5475d1a30ebSJakub Kicinski 	free(rsp->info_version_fixed);
5485d1a30ebSJakub Kicinski 	for (i = 0; i < rsp->n_info_version_running; i++)
5495d1a30ebSJakub Kicinski 		devlink_dl_info_version_free(&rsp->info_version_running[i]);
5505d1a30ebSJakub Kicinski 	free(rsp->info_version_running);
5515d1a30ebSJakub Kicinski 	for (i = 0; i < rsp->n_info_version_stored; i++)
5525d1a30ebSJakub Kicinski 		devlink_dl_info_version_free(&rsp->info_version_stored[i]);
5535d1a30ebSJakub Kicinski 	free(rsp->info_version_stored);
5545d1a30ebSJakub Kicinski 	free(rsp);
5555d1a30ebSJakub Kicinski }
5565d1a30ebSJakub Kicinski 
5575d1a30ebSJakub Kicinski int devlink_info_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
5585d1a30ebSJakub Kicinski {
5595d1a30ebSJakub Kicinski 	unsigned int n_info_version_running = 0;
5605d1a30ebSJakub Kicinski 	unsigned int n_info_version_stored = 0;
5615d1a30ebSJakub Kicinski 	unsigned int n_info_version_fixed = 0;
5625d1a30ebSJakub Kicinski 	struct ynl_parse_arg *yarg = data;
5635d1a30ebSJakub Kicinski 	struct devlink_info_get_rsp *dst;
5645d1a30ebSJakub Kicinski 	const struct nlattr *attr;
5655d1a30ebSJakub Kicinski 	struct ynl_parse_arg parg;
5665d1a30ebSJakub Kicinski 	int i;
5675d1a30ebSJakub Kicinski 
5685d1a30ebSJakub Kicinski 	dst = yarg->data;
5695d1a30ebSJakub Kicinski 	parg.ys = yarg->ys;
5705d1a30ebSJakub Kicinski 
5715d1a30ebSJakub Kicinski 	if (dst->info_version_fixed)
5725d1a30ebSJakub Kicinski 		return ynl_error_parse(yarg, "attribute already present (devlink.info-version-fixed)");
5735d1a30ebSJakub Kicinski 	if (dst->info_version_running)
5745d1a30ebSJakub Kicinski 		return ynl_error_parse(yarg, "attribute already present (devlink.info-version-running)");
5755d1a30ebSJakub Kicinski 	if (dst->info_version_stored)
5765d1a30ebSJakub Kicinski 		return ynl_error_parse(yarg, "attribute already present (devlink.info-version-stored)");
5775d1a30ebSJakub Kicinski 
5785d1a30ebSJakub Kicinski 	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
5795d1a30ebSJakub Kicinski 		if (mnl_attr_get_type(attr) == DEVLINK_ATTR_BUS_NAME) {
5805d1a30ebSJakub Kicinski 			unsigned int len;
5815d1a30ebSJakub Kicinski 
5825d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5835d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
5845d1a30ebSJakub Kicinski 
5855d1a30ebSJakub Kicinski 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
5865d1a30ebSJakub Kicinski 			dst->_present.bus_name_len = len;
5875d1a30ebSJakub Kicinski 			dst->bus_name = malloc(len + 1);
5885d1a30ebSJakub Kicinski 			memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
5895d1a30ebSJakub Kicinski 			dst->bus_name[len] = 0;
5905d1a30ebSJakub Kicinski 		}
5915d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_DEV_NAME) {
5925d1a30ebSJakub Kicinski 			unsigned int len;
5935d1a30ebSJakub Kicinski 
5945d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
5955d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
5965d1a30ebSJakub Kicinski 
5975d1a30ebSJakub Kicinski 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
5985d1a30ebSJakub Kicinski 			dst->_present.dev_name_len = len;
5995d1a30ebSJakub Kicinski 			dst->dev_name = malloc(len + 1);
6005d1a30ebSJakub Kicinski 			memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
6015d1a30ebSJakub Kicinski 			dst->dev_name[len] = 0;
6025d1a30ebSJakub Kicinski 		}
6035d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_DRIVER_NAME) {
6045d1a30ebSJakub Kicinski 			unsigned int len;
6055d1a30ebSJakub Kicinski 
6065d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
6075d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
6085d1a30ebSJakub Kicinski 
6095d1a30ebSJakub Kicinski 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
6105d1a30ebSJakub Kicinski 			dst->_present.info_driver_name_len = len;
6115d1a30ebSJakub Kicinski 			dst->info_driver_name = malloc(len + 1);
6125d1a30ebSJakub Kicinski 			memcpy(dst->info_driver_name, mnl_attr_get_str(attr), len);
6135d1a30ebSJakub Kicinski 			dst->info_driver_name[len] = 0;
6145d1a30ebSJakub Kicinski 		}
6155d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_SERIAL_NUMBER) {
6165d1a30ebSJakub Kicinski 			unsigned int len;
6175d1a30ebSJakub Kicinski 
6185d1a30ebSJakub Kicinski 			if (ynl_attr_validate(yarg, attr))
6195d1a30ebSJakub Kicinski 				return MNL_CB_ERROR;
6205d1a30ebSJakub Kicinski 
6215d1a30ebSJakub Kicinski 			len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
6225d1a30ebSJakub Kicinski 			dst->_present.info_serial_number_len = len;
6235d1a30ebSJakub Kicinski 			dst->info_serial_number = malloc(len + 1);
6245d1a30ebSJakub Kicinski 			memcpy(dst->info_serial_number, mnl_attr_get_str(attr), len);
6255d1a30ebSJakub Kicinski 			dst->info_serial_number[len] = 0;
6265d1a30ebSJakub Kicinski 		}
6275d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_FIXED) {
6285d1a30ebSJakub Kicinski 			n_info_version_fixed++;
6295d1a30ebSJakub Kicinski 		}
6305d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_RUNNING) {
6315d1a30ebSJakub Kicinski 			n_info_version_running++;
6325d1a30ebSJakub Kicinski 		}
6335d1a30ebSJakub Kicinski 		else if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_STORED) {
6345d1a30ebSJakub Kicinski 			n_info_version_stored++;
6355d1a30ebSJakub Kicinski 		}
6365d1a30ebSJakub Kicinski 	}
6375d1a30ebSJakub Kicinski 
6385d1a30ebSJakub Kicinski 	if (n_info_version_fixed) {
6395d1a30ebSJakub Kicinski 		dst->info_version_fixed = calloc(n_info_version_fixed, sizeof(*dst->info_version_fixed));
6405d1a30ebSJakub Kicinski 		dst->n_info_version_fixed = n_info_version_fixed;
6415d1a30ebSJakub Kicinski 		i = 0;
6425d1a30ebSJakub Kicinski 		parg.rsp_policy = &devlink_dl_info_version_nest;
6435d1a30ebSJakub Kicinski 		mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
6445d1a30ebSJakub Kicinski 			if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_FIXED) {
6455d1a30ebSJakub Kicinski 				parg.data = &dst->info_version_fixed[i];
6465d1a30ebSJakub Kicinski 				if (devlink_dl_info_version_parse(&parg, attr))
6475d1a30ebSJakub Kicinski 					return MNL_CB_ERROR;
6485d1a30ebSJakub Kicinski 				i++;
6495d1a30ebSJakub Kicinski 			}
6505d1a30ebSJakub Kicinski 		}
6515d1a30ebSJakub Kicinski 	}
6525d1a30ebSJakub Kicinski 	if (n_info_version_running) {
6535d1a30ebSJakub Kicinski 		dst->info_version_running = calloc(n_info_version_running, sizeof(*dst->info_version_running));
6545d1a30ebSJakub Kicinski 		dst->n_info_version_running = n_info_version_running;
6555d1a30ebSJakub Kicinski 		i = 0;
6565d1a30ebSJakub Kicinski 		parg.rsp_policy = &devlink_dl_info_version_nest;
6575d1a30ebSJakub Kicinski 		mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
6585d1a30ebSJakub Kicinski 			if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_RUNNING) {
6595d1a30ebSJakub Kicinski 				parg.data = &dst->info_version_running[i];
6605d1a30ebSJakub Kicinski 				if (devlink_dl_info_version_parse(&parg, attr))
6615d1a30ebSJakub Kicinski 					return MNL_CB_ERROR;
6625d1a30ebSJakub Kicinski 				i++;
6635d1a30ebSJakub Kicinski 			}
6645d1a30ebSJakub Kicinski 		}
6655d1a30ebSJakub Kicinski 	}
6665d1a30ebSJakub Kicinski 	if (n_info_version_stored) {
6675d1a30ebSJakub Kicinski 		dst->info_version_stored = calloc(n_info_version_stored, sizeof(*dst->info_version_stored));
6685d1a30ebSJakub Kicinski 		dst->n_info_version_stored = n_info_version_stored;
6695d1a30ebSJakub Kicinski 		i = 0;
6705d1a30ebSJakub Kicinski 		parg.rsp_policy = &devlink_dl_info_version_nest;
6715d1a30ebSJakub Kicinski 		mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
6725d1a30ebSJakub Kicinski 			if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_STORED) {
6735d1a30ebSJakub Kicinski 				parg.data = &dst->info_version_stored[i];
6745d1a30ebSJakub Kicinski 				if (devlink_dl_info_version_parse(&parg, attr))
6755d1a30ebSJakub Kicinski 					return MNL_CB_ERROR;
6765d1a30ebSJakub Kicinski 				i++;
6775d1a30ebSJakub Kicinski 			}
6785d1a30ebSJakub Kicinski 		}
6795d1a30ebSJakub Kicinski 	}
6805d1a30ebSJakub Kicinski 
6815d1a30ebSJakub Kicinski 	return MNL_CB_OK;
6825d1a30ebSJakub Kicinski }
6835d1a30ebSJakub Kicinski 
6845d1a30ebSJakub Kicinski struct devlink_info_get_rsp *
6855d1a30ebSJakub Kicinski devlink_info_get(struct ynl_sock *ys, struct devlink_info_get_req *req)
6865d1a30ebSJakub Kicinski {
6875d1a30ebSJakub Kicinski 	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
6885d1a30ebSJakub Kicinski 	struct devlink_info_get_rsp *rsp;
6895d1a30ebSJakub Kicinski 	struct nlmsghdr *nlh;
6905d1a30ebSJakub Kicinski 	int err;
6915d1a30ebSJakub Kicinski 
6925d1a30ebSJakub Kicinski 	nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_INFO_GET, 1);
6935d1a30ebSJakub Kicinski 	ys->req_policy = &devlink_nest;
6945d1a30ebSJakub Kicinski 	yrs.yarg.rsp_policy = &devlink_nest;
6955d1a30ebSJakub Kicinski 
6965d1a30ebSJakub Kicinski 	if (req->_present.bus_name_len)
6975d1a30ebSJakub Kicinski 		mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
6985d1a30ebSJakub Kicinski 	if (req->_present.dev_name_len)
6995d1a30ebSJakub Kicinski 		mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
7005d1a30ebSJakub Kicinski 
7015d1a30ebSJakub Kicinski 	rsp = calloc(1, sizeof(*rsp));
7025d1a30ebSJakub Kicinski 	yrs.yarg.data = rsp;
7035d1a30ebSJakub Kicinski 	yrs.cb = devlink_info_get_rsp_parse;
7045d1a30ebSJakub Kicinski 	yrs.rsp_cmd = DEVLINK_CMD_INFO_GET;
7055d1a30ebSJakub Kicinski 
7065d1a30ebSJakub Kicinski 	err = ynl_exec(ys, nlh, &yrs);
7075d1a30ebSJakub Kicinski 	if (err < 0)
7085d1a30ebSJakub Kicinski 		goto err_free;
7095d1a30ebSJakub Kicinski 
7105d1a30ebSJakub Kicinski 	return rsp;
7115d1a30ebSJakub Kicinski 
7125d1a30ebSJakub Kicinski err_free:
7135d1a30ebSJakub Kicinski 	devlink_info_get_rsp_free(rsp);
7145d1a30ebSJakub Kicinski 	return NULL;
7155d1a30ebSJakub Kicinski }
7165d1a30ebSJakub Kicinski 
7175d1a30ebSJakub Kicinski const struct ynl_family ynl_devlink_family =  {
7185d1a30ebSJakub Kicinski 	.name		= "devlink",
7195d1a30ebSJakub Kicinski };
720