diff --git a/tmp/ynl_build-tmp.Gsi08P/old-code/ethtool-user.c b/tmp/ynl_build-tmp.Gsi08P/new-code/ethtool-user.c index 69af993e32b6..c4b1159b2c62 100644 --- a/tmp/ynl_build-tmp.Gsi08P/old-code/ethtool-user.c +++ b/tmp/ynl_build-tmp.Gsi08P/new-code/ethtool-user.c @@ -71,6 +71,8 @@ static const char * const ethtool_op_strmap[] = { [52] = "rss-create-ntf", [53] = "rss-delete-ntf", [54] = "mse-get", + [55] = "loopback-get", + [56] = "loopback-ntf", }; const char *ethtool_op_str(int op) @@ -240,6 +242,34 @@ const char *ethtool_rxfh_fields_str(int value) return ethtool_rxfh_fields_strmap[value]; } +static const char * const ethtool_loopback_component_strmap[] = { + [0] = "mac", + [1] = "phy", + [2] = "module", +}; + +const char * +ethtool_loopback_component_str(enum ethtool_loopback_component value) +{ + if (value < 0 || value >= (int)YNL_ARRAY_SIZE(ethtool_loopback_component_strmap)) + return NULL; + return ethtool_loopback_component_strmap[value]; +} + +static const char * const ethtool_loopback_direction_strmap[] = { + [0] = "local", + [1] = "remote", +}; + +const char * +ethtool_loopback_direction_str(enum ethtool_loopback_direction value) +{ + value = ffs(value) - 1; + if (value < 0 || value >= (int)YNL_ARRAY_SIZE(ethtool_loopback_direction_strmap)) + return NULL; + return ethtool_loopback_direction_strmap[value]; +} + /* Policies */ const struct ynl_policy_attr ethtool_header_policy[ETHTOOL_A_HEADER_MAX + 1] = { [ETHTOOL_A_HEADER_UNSPEC] = { .name = "unspec", .type = YNL_PT_REJECT, }, @@ -389,6 +419,21 @@ const struct ynl_policy_nest ethtool_mse_snapshot_nest = { .table = ethtool_mse_snapshot_policy, }; +const struct ynl_policy_attr ethtool_loopback_entry_policy[ETHTOOL_A_LOOPBACK_ENTRY_MAX + 1] = { + [ETHTOOL_A_LOOPBACK_ENTRY_UNSPEC] = { .name = "unspec", .type = YNL_PT_REJECT, }, + [ETHTOOL_A_LOOPBACK_ENTRY_COMPONENT] = { .name = "component", .type = YNL_PT_U32, }, + [ETHTOOL_A_LOOPBACK_ENTRY_NAME] = { .name = "name", .type = YNL_PT_NUL_STR, }, + [ETHTOOL_A_LOOPBACK_ENTRY_ID] = { .name = "id", .type = YNL_PT_U32, }, + [ETHTOOL_A_LOOPBACK_ENTRY_DEPTH] = { .name = "depth", .type = YNL_PT_U8, }, + [ETHTOOL_A_LOOPBACK_ENTRY_SUPPORTED] = { .name = "supported", .type = YNL_PT_U8, }, + [ETHTOOL_A_LOOPBACK_ENTRY_DIRECTION] = { .name = "direction", .type = YNL_PT_U8, }, +}; + +const struct ynl_policy_nest ethtool_loopback_entry_nest = { + .max_attr = ETHTOOL_A_LOOPBACK_ENTRY_MAX, + .table = ethtool_loopback_entry_policy, +}; + const struct ynl_policy_attr ethtool_irq_moderation_policy[ETHTOOL_A_IRQ_MODERATION_MAX + 1] = { [ETHTOOL_A_IRQ_MODERATION_UNSPEC] = { .name = "unspec", .type = YNL_PT_REJECT, }, [ETHTOOL_A_IRQ_MODERATION_USEC] = { .name = "usec", .type = YNL_PT_U32, }, @@ -1093,6 +1138,17 @@ const struct ynl_policy_nest ethtool_mse_nest = { .table = ethtool_mse_policy, }; +const struct ynl_policy_attr ethtool_loopback_policy[ETHTOOL_A_LOOPBACK_MAX + 1] = { + [ETHTOOL_A_LOOPBACK_UNSPEC] = { .name = "unspec", .type = YNL_PT_REJECT, }, + [ETHTOOL_A_LOOPBACK_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = ðtool_header_nest, }, + [ETHTOOL_A_LOOPBACK_ENTRY] = { .name = "entry", .type = YNL_PT_NEST, .nest = ðtool_loopback_entry_nest, }, +}; + +const struct ynl_policy_nest ethtool_loopback_nest = { + .max_attr = ETHTOOL_A_LOOPBACK_MAX, + .table = ethtool_loopback_policy, +}; + /* Common nested types */ void ethtool_header_free(struct ethtool_header *obj) { @@ -1667,6 +1723,84 @@ int ethtool_mse_snapshot_parse(struct ynl_parse_arg *yarg, return 0; } +void ethtool_loopback_entry_free(struct ethtool_loopback_entry *obj) +{ + free(obj->name); +} + +int ethtool_loopback_entry_put(struct nlmsghdr *nlh, unsigned int attr_type, + struct ethtool_loopback_entry *obj) +{ + struct nlattr *nest; + + nest = ynl_attr_nest_start(nlh, attr_type); + if (obj->_present.component) + ynl_attr_put_u32(nlh, ETHTOOL_A_LOOPBACK_ENTRY_COMPONENT, obj->component); + if (obj->_len.name) + ynl_attr_put_str(nlh, ETHTOOL_A_LOOPBACK_ENTRY_NAME, obj->name); + if (obj->_present.id) + ynl_attr_put_u32(nlh, ETHTOOL_A_LOOPBACK_ENTRY_ID, obj->id); + if (obj->_present.depth) + ynl_attr_put_u8(nlh, ETHTOOL_A_LOOPBACK_ENTRY_DEPTH, obj->depth); + if (obj->_present.supported) + ynl_attr_put_u8(nlh, ETHTOOL_A_LOOPBACK_ENTRY_SUPPORTED, obj->supported); + if (obj->_present.direction) + ynl_attr_put_u8(nlh, ETHTOOL_A_LOOPBACK_ENTRY_DIRECTION, obj->direction); + ynl_attr_nest_end(nlh, nest); + + return 0; +} + +int ethtool_loopback_entry_parse(struct ynl_parse_arg *yarg, + const struct nlattr *nested) +{ + struct ethtool_loopback_entry *dst = yarg->data; + const struct nlattr *attr; + unsigned int len; + + ynl_attr_for_each_nested(attr, nested) { + unsigned int type = ynl_attr_type(attr); + + if (type == ETHTOOL_A_LOOPBACK_ENTRY_COMPONENT) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + dst->_present.component = 1; + dst->component = ynl_attr_get_u32(attr); + } else if (type == ETHTOOL_A_LOOPBACK_ENTRY_NAME) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + + len = strnlen(ynl_attr_get_str(attr), ynl_attr_data_len(attr)); + dst->_len.name = len; + dst->name = malloc(len + 1); + memcpy(dst->name, ynl_attr_get_str(attr), len); + dst->name[len] = 0; + } else if (type == ETHTOOL_A_LOOPBACK_ENTRY_ID) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + dst->_present.id = 1; + dst->id = ynl_attr_get_u32(attr); + } else if (type == ETHTOOL_A_LOOPBACK_ENTRY_DEPTH) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + dst->_present.depth = 1; + dst->depth = ynl_attr_get_u8(attr); + } else if (type == ETHTOOL_A_LOOPBACK_ENTRY_SUPPORTED) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + dst->_present.supported = 1; + dst->supported = ynl_attr_get_u8(attr); + } else if (type == ETHTOOL_A_LOOPBACK_ENTRY_DIRECTION) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + dst->_present.direction = 1; + dst->direction = ynl_attr_get_u8(attr); + } + } + + return 0; +} + void ethtool_irq_moderation_free(struct ethtool_irq_moderation *obj) { } @@ -8662,6 +8796,215 @@ ethtool_mse_get_dump(struct ynl_sock *ys, struct ethtool_mse_get_req_dump *req) return NULL; } +/* ============== ETHTOOL_MSG_LOOPBACK_GET ============== */ +/* ETHTOOL_MSG_LOOPBACK_GET - do */ +void ethtool_loopback_get_req_free(struct ethtool_loopback_get_req *req) +{ + ethtool_header_free(&req->header); + free(req); +} + +void ethtool_loopback_get_rsp_free(struct ethtool_loopback_get_rsp *rsp) +{ + unsigned int i; + + ethtool_header_free(&rsp->header); + for (i = 0; i < rsp->_count.entry; i++) + ethtool_loopback_entry_free(&rsp->entry[i]); + free(rsp->entry); + free(rsp); +} + +int ethtool_loopback_get_rsp_parse(const struct nlmsghdr *nlh, + struct ynl_parse_arg *yarg) +{ + struct ethtool_loopback_get_rsp *dst; + const struct nlattr *attr; + struct ynl_parse_arg parg; + unsigned int n_entry = 0; + int i; + + dst = yarg->data; + parg.ys = yarg->ys; + + if (dst->entry) + return ynl_error_parse(yarg, "attribute already present (loopback.entry)"); + + ynl_attr_for_each(attr, nlh, yarg->ys->family->hdr_len) { + unsigned int type = ynl_attr_type(attr); + + if (type == ETHTOOL_A_LOOPBACK_HEADER) { + if (ynl_attr_validate(yarg, attr)) + return YNL_PARSE_CB_ERROR; + dst->_present.header = 1; + + parg.rsp_policy = ðtool_header_nest; + parg.data = &dst->header; + if (ethtool_header_parse(&parg, attr)) + return YNL_PARSE_CB_ERROR; + } else if (type == ETHTOOL_A_LOOPBACK_ENTRY) { + n_entry++; + } + } + + if (n_entry) { + dst->entry = calloc(n_entry, sizeof(*dst->entry)); + dst->_count.entry = n_entry; + i = 0; + parg.rsp_policy = ðtool_loopback_entry_nest; + ynl_attr_for_each(attr, nlh, yarg->ys->family->hdr_len) { + if (ynl_attr_type(attr) == ETHTOOL_A_LOOPBACK_ENTRY) { + parg.data = &dst->entry[i]; + if (ethtool_loopback_entry_parse(&parg, attr)) + return YNL_PARSE_CB_ERROR; + i++; + } + } + } + + return YNL_PARSE_CB_OK; +} + +struct ethtool_loopback_get_rsp * +ethtool_loopback_get(struct ynl_sock *ys, struct ethtool_loopback_get_req *req) +{ + struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; + struct ethtool_loopback_get_rsp *rsp; + struct nlmsghdr *nlh; + int err; + + nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_LOOPBACK_GET, 1); + ys->req_policy = ðtool_loopback_nest; + ys->req_hdr_len = ys->family->hdr_len; + yrs.yarg.rsp_policy = ðtool_loopback_nest; + + if (req->_present.header) + ethtool_header_put(nlh, ETHTOOL_A_LOOPBACK_HEADER, &req->header); + + rsp = calloc(1, sizeof(*rsp)); + yrs.yarg.data = rsp; + yrs.cb = ethtool_loopback_get_rsp_parse; + yrs.rsp_cmd = 55; + + err = ynl_exec(ys, nlh, &yrs); + if (err < 0) + goto err_free; + + return rsp; + +err_free: + ethtool_loopback_get_rsp_free(rsp); + return NULL; +} + +/* ETHTOOL_MSG_LOOPBACK_GET - dump */ +void +ethtool_loopback_get_req_dump_free(struct ethtool_loopback_get_req_dump *req) +{ + ethtool_header_free(&req->header); + free(req); +} + +void ethtool_loopback_get_list_free(struct ethtool_loopback_get_list *rsp) +{ + struct ethtool_loopback_get_list *next = rsp; + + while ((void *)next != YNL_LIST_END) { + unsigned int i; + + rsp = next; + next = rsp->next; + + ethtool_header_free(&rsp->obj.header); + for (i = 0; i < rsp->obj._count.entry; i++) + ethtool_loopback_entry_free(&rsp->obj.entry[i]); + free(rsp->obj.entry); + free(rsp); + } +} + +struct ethtool_loopback_get_list * +ethtool_loopback_get_dump(struct ynl_sock *ys, + struct ethtool_loopback_get_req_dump *req) +{ + struct ynl_dump_state yds = {}; + struct nlmsghdr *nlh; + int err; + + yds.yarg.ys = ys; + yds.yarg.rsp_policy = ðtool_loopback_nest; + yds.yarg.data = NULL; + yds.alloc_sz = sizeof(struct ethtool_loopback_get_list); + yds.cb = ethtool_loopback_get_rsp_parse; + yds.rsp_cmd = 55; + + nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_LOOPBACK_GET, 1); + ys->req_policy = ðtool_loopback_nest; + ys->req_hdr_len = ys->family->hdr_len; + + if (req->_present.header) + ethtool_header_put(nlh, ETHTOOL_A_LOOPBACK_HEADER, &req->header); + + err = ynl_exec_dump(ys, nlh, &yds); + if (err < 0) + goto free_list; + + return yds.first; + +free_list: + ethtool_loopback_get_list_free(yds.first); + return NULL; +} + +/* ETHTOOL_MSG_LOOPBACK_GET - notify */ +void ethtool_loopback_get_ntf_free(struct ethtool_loopback_get_ntf *rsp) +{ + unsigned int i; + + ethtool_header_free(&rsp->obj.header); + for (i = 0; i < rsp->obj._count.entry; i++) + ethtool_loopback_entry_free(&rsp->obj.entry[i]); + free(rsp->obj.entry); + free(rsp); +} + +/* ============== ETHTOOL_MSG_LOOPBACK_SET ============== */ +/* ETHTOOL_MSG_LOOPBACK_SET - do */ +void ethtool_loopback_set_req_free(struct ethtool_loopback_set_req *req) +{ + unsigned int i; + + ethtool_header_free(&req->header); + for (i = 0; i < req->_count.entry; i++) + ethtool_loopback_entry_free(&req->entry[i]); + free(req->entry); + free(req); +} + +int ethtool_loopback_set(struct ynl_sock *ys, + struct ethtool_loopback_set_req *req) +{ + struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; + struct nlmsghdr *nlh; + unsigned int i; + int err; + + nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_LOOPBACK_SET, 1); + ys->req_policy = ðtool_loopback_nest; + ys->req_hdr_len = ys->family->hdr_len; + + if (req->_present.header) + ethtool_header_put(nlh, ETHTOOL_A_LOOPBACK_HEADER, &req->header); + for (i = 0; i < req->_count.entry; i++) + ethtool_loopback_entry_put(nlh, ETHTOOL_A_LOOPBACK_ENTRY, &req->entry[i]); + + err = ynl_exec(ys, nlh, &yrs); + if (err < 0) + return -1; + + return 0; +} + /* ETHTOOL_MSG_CABLE_TEST_NTF - event */ int ethtool_cable_test_ntf_rsp_parse(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg) @@ -9032,6 +9375,12 @@ static const struct ynl_ntf_info ethtool_ntf_info[] = { .policy = ðtool_rss_nest, .free = (void *)ethtool_rss_delete_ntf_free, }, + [ETHTOOL_MSG_LOOPBACK_NTF] = { + .alloc_sz = sizeof(struct ethtool_loopback_get_ntf), + .cb = ethtool_loopback_get_rsp_parse, + .policy = ðtool_loopback_nest, + .free = (void *)ethtool_loopback_get_ntf_free, + }, }; const struct ynl_family ynl_ethtool_family = { diff --git a/tmp/ynl_build-tmp.Gsi08P/old-code/ethtool-user.h b/tmp/ynl_build-tmp.Gsi08P/new-code/ethtool-user.h index c0e79cacf192..b9f791c06b16 100644 --- a/tmp/ynl_build-tmp.Gsi08P/old-code/ethtool-user.h +++ b/tmp/ynl_build-tmp.Gsi08P/new-code/ethtool-user.h @@ -33,6 +33,10 @@ const char *ethtool_hwtstamp_source_str(enum hwtstamp_source value); const char *ethtool_pse_event_str(enum ethtool_pse_event value); const char *ethtool_input_xfrm_str(int value); const char *ethtool_rxfh_fields_str(int value); +const char * +ethtool_loopback_component_str(enum ethtool_loopback_component value); +const char * +ethtool_loopback_direction_str(enum ethtool_loopback_direction value); /* Common nested types */ struct ethtool_header { @@ -215,6 +219,79 @@ struct ethtool_mse_snapshot { __u64 worst_peak_mse; }; +struct ethtool_loopback_entry { + struct { + __u32 component:1; + __u32 id:1; + __u32 depth:1; + __u32 supported:1; + __u32 direction:1; + } _present; + struct { + __u32 name; + } _len; + + enum ethtool_loopback_component component; + char *name; + __u32 id; + __u8 depth; + __u8 supported; + __u8 direction; +}; + +static inline struct ethtool_loopback_entry * +ethtool_loopback_entry_alloc(unsigned int n) +{ + return calloc(n, sizeof(struct ethtool_loopback_entry)); +} + +void ethtool_loopback_entry_free(struct ethtool_loopback_entry *obj); + +static inline void +ethtool_loopback_entry_set_component(struct ethtool_loopback_entry *obj, + enum ethtool_loopback_component component) +{ + obj->_present.component = 1; + obj->component = component; +} +static inline void +ethtool_loopback_entry_set_name(struct ethtool_loopback_entry *obj, + const char *name) +{ + free(obj->name); + obj->_len.name = strlen(name); + obj->name = malloc(obj->_len.name + 1); + memcpy(obj->name, name, obj->_len.name); + obj->name[obj->_len.name] = 0; +} +static inline void +ethtool_loopback_entry_set_id(struct ethtool_loopback_entry *obj, __u32 id) +{ + obj->_present.id = 1; + obj->id = id; +} +static inline void +ethtool_loopback_entry_set_depth(struct ethtool_loopback_entry *obj, + __u8 depth) +{ + obj->_present.depth = 1; + obj->depth = depth; +} +static inline void +ethtool_loopback_entry_set_supported(struct ethtool_loopback_entry *obj, + __u8 supported) +{ + obj->_present.supported = 1; + obj->supported = supported; +} +static inline void +ethtool_loopback_entry_set_direction(struct ethtool_loopback_entry *obj, + __u8 direction) +{ + obj->_present.direction = 1; + obj->direction = direction; +} + struct ethtool_irq_moderation { struct { __u32 usec:1; @@ -8379,6 +8456,230 @@ void ethtool_mse_get_list_free(struct ethtool_mse_get_list *rsp); struct ethtool_mse_get_list * ethtool_mse_get_dump(struct ynl_sock *ys, struct ethtool_mse_get_req_dump *req); +/* ============== ETHTOOL_MSG_LOOPBACK_GET ============== */ +/* ETHTOOL_MSG_LOOPBACK_GET - do */ +struct ethtool_loopback_get_req { + struct { + __u32 header:1; + } _present; + + struct ethtool_header header; +}; + +static inline struct ethtool_loopback_get_req * +ethtool_loopback_get_req_alloc(void) +{ + return calloc(1, sizeof(struct ethtool_loopback_get_req)); +} +void ethtool_loopback_get_req_free(struct ethtool_loopback_get_req *req); + +static inline void +ethtool_loopback_get_req_set_header_dev_index(struct ethtool_loopback_get_req *req, + __u32 dev_index) +{ + req->_present.header = 1; + req->header._present.dev_index = 1; + req->header.dev_index = dev_index; +} +static inline void +ethtool_loopback_get_req_set_header_dev_name(struct ethtool_loopback_get_req *req, + const char *dev_name) +{ + req->_present.header = 1; + free(req->header.dev_name); + req->header._len.dev_name = strlen(dev_name); + req->header.dev_name = malloc(req->header._len.dev_name + 1); + memcpy(req->header.dev_name, dev_name, req->header._len.dev_name); + req->header.dev_name[req->header._len.dev_name] = 0; +} +static inline void +ethtool_loopback_get_req_set_header_flags(struct ethtool_loopback_get_req *req, + __u32 flags) +{ + req->_present.header = 1; + req->header._present.flags = 1; + req->header.flags = flags; +} +static inline void +ethtool_loopback_get_req_set_header_phy_index(struct ethtool_loopback_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} + +struct ethtool_loopback_get_rsp { + struct { + __u32 header:1; + } _present; + struct { + __u32 entry; + } _count; + + struct ethtool_header header; + struct ethtool_loopback_entry *entry; +}; + +void ethtool_loopback_get_rsp_free(struct ethtool_loopback_get_rsp *rsp); + +/* + * Get loopback configuration and capabilities. + */ +struct ethtool_loopback_get_rsp * +ethtool_loopback_get(struct ynl_sock *ys, struct ethtool_loopback_get_req *req); + +/* ETHTOOL_MSG_LOOPBACK_GET - dump */ +struct ethtool_loopback_get_req_dump { + struct { + __u32 header:1; + } _present; + + struct ethtool_header header; +}; + +static inline struct ethtool_loopback_get_req_dump * +ethtool_loopback_get_req_dump_alloc(void) +{ + return calloc(1, sizeof(struct ethtool_loopback_get_req_dump)); +} +void +ethtool_loopback_get_req_dump_free(struct ethtool_loopback_get_req_dump *req); + +static inline void +ethtool_loopback_get_req_dump_set_header_dev_index(struct ethtool_loopback_get_req_dump *req, + __u32 dev_index) +{ + req->_present.header = 1; + req->header._present.dev_index = 1; + req->header.dev_index = dev_index; +} +static inline void +ethtool_loopback_get_req_dump_set_header_dev_name(struct ethtool_loopback_get_req_dump *req, + const char *dev_name) +{ + req->_present.header = 1; + free(req->header.dev_name); + req->header._len.dev_name = strlen(dev_name); + req->header.dev_name = malloc(req->header._len.dev_name + 1); + memcpy(req->header.dev_name, dev_name, req->header._len.dev_name); + req->header.dev_name[req->header._len.dev_name] = 0; +} +static inline void +ethtool_loopback_get_req_dump_set_header_flags(struct ethtool_loopback_get_req_dump *req, + __u32 flags) +{ + req->_present.header = 1; + req->header._present.flags = 1; + req->header.flags = flags; +} +static inline void +ethtool_loopback_get_req_dump_set_header_phy_index(struct ethtool_loopback_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} + +struct ethtool_loopback_get_list { + struct ethtool_loopback_get_list *next; + struct ethtool_loopback_get_rsp obj __attribute__((aligned(8))); +}; + +void ethtool_loopback_get_list_free(struct ethtool_loopback_get_list *rsp); + +struct ethtool_loopback_get_list * +ethtool_loopback_get_dump(struct ynl_sock *ys, + struct ethtool_loopback_get_req_dump *req); + +/* ETHTOOL_MSG_LOOPBACK_GET - notify */ +struct ethtool_loopback_get_ntf { + __u16 family; + __u8 cmd; + struct ynl_ntf_base_type *next; + void (*free)(struct ethtool_loopback_get_ntf *ntf); + struct ethtool_loopback_get_rsp obj __attribute__((aligned(8))); +}; + +void ethtool_loopback_get_ntf_free(struct ethtool_loopback_get_ntf *rsp); + +/* ============== ETHTOOL_MSG_LOOPBACK_SET ============== */ +/* ETHTOOL_MSG_LOOPBACK_SET - do */ +struct ethtool_loopback_set_req { + struct { + __u32 header:1; + } _present; + struct { + __u32 entry; + } _count; + + struct ethtool_header header; + struct ethtool_loopback_entry *entry; +}; + +static inline struct ethtool_loopback_set_req * +ethtool_loopback_set_req_alloc(void) +{ + return calloc(1, sizeof(struct ethtool_loopback_set_req)); +} +void ethtool_loopback_set_req_free(struct ethtool_loopback_set_req *req); + +static inline void +ethtool_loopback_set_req_set_header_dev_index(struct ethtool_loopback_set_req *req, + __u32 dev_index) +{ + req->_present.header = 1; + req->header._present.dev_index = 1; + req->header.dev_index = dev_index; +} +static inline void +ethtool_loopback_set_req_set_header_dev_name(struct ethtool_loopback_set_req *req, + const char *dev_name) +{ + req->_present.header = 1; + free(req->header.dev_name); + req->header._len.dev_name = strlen(dev_name); + req->header.dev_name = malloc(req->header._len.dev_name + 1); + memcpy(req->header.dev_name, dev_name, req->header._len.dev_name); + req->header.dev_name[req->header._len.dev_name] = 0; +} +static inline void +ethtool_loopback_set_req_set_header_flags(struct ethtool_loopback_set_req *req, + __u32 flags) +{ + req->_present.header = 1; + req->header._present.flags = 1; + req->header.flags = flags; +} +static inline void +ethtool_loopback_set_req_set_header_phy_index(struct ethtool_loopback_set_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} +static inline void +__ethtool_loopback_set_req_set_entry(struct ethtool_loopback_set_req *req, + struct ethtool_loopback_entry *entry, + unsigned int n_entry) +{ + unsigned int i; + + for (i = 0; i < req->_count.entry; i++) + ethtool_loopback_entry_free(&req->entry[i]); + free(req->entry); + req->entry = entry; + req->_count.entry = n_entry; +} + +/* + * Set loopback configuration. + */ +int ethtool_loopback_set(struct ynl_sock *ys, + struct ethtool_loopback_set_req *req); + /* ETHTOOL_MSG_CABLE_TEST_NTF - event */ struct ethtool_cable_test_ntf_rsp { struct {