netlink: specs: devlink: add info-get dump op
[platform/kernel/linux-starfive.git] / tools / net / ynl / generated / devlink-user.c
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 /* DEVLINK_CMD_INFO_GET - dump */
720 void devlink_info_get_list_free(struct devlink_info_get_list *rsp)
721 {
722         struct devlink_info_get_list *next = rsp;
723
724         while ((void *)next != YNL_LIST_END) {
725                 unsigned int i;
726
727                 rsp = next;
728                 next = rsp->next;
729
730                 free(rsp->obj.bus_name);
731                 free(rsp->obj.dev_name);
732                 free(rsp->obj.info_driver_name);
733                 free(rsp->obj.info_serial_number);
734                 for (i = 0; i < rsp->obj.n_info_version_fixed; i++)
735                         devlink_dl_info_version_free(&rsp->obj.info_version_fixed[i]);
736                 free(rsp->obj.info_version_fixed);
737                 for (i = 0; i < rsp->obj.n_info_version_running; i++)
738                         devlink_dl_info_version_free(&rsp->obj.info_version_running[i]);
739                 free(rsp->obj.info_version_running);
740                 for (i = 0; i < rsp->obj.n_info_version_stored; i++)
741                         devlink_dl_info_version_free(&rsp->obj.info_version_stored[i]);
742                 free(rsp->obj.info_version_stored);
743                 free(rsp);
744         }
745 }
746
747 struct devlink_info_get_list *devlink_info_get_dump(struct ynl_sock *ys)
748 {
749         struct ynl_dump_state yds = {};
750         struct nlmsghdr *nlh;
751         int err;
752
753         yds.ys = ys;
754         yds.alloc_sz = sizeof(struct devlink_info_get_list);
755         yds.cb = devlink_info_get_rsp_parse;
756         yds.rsp_cmd = DEVLINK_CMD_INFO_GET;
757         yds.rsp_policy = &devlink_nest;
758
759         nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_INFO_GET, 1);
760
761         err = ynl_exec_dump(ys, nlh, &yds);
762         if (err < 0)
763                 goto free_list;
764
765         return yds.first;
766
767 free_list:
768         devlink_info_get_list_free(yds.first);
769         return NULL;
770 }
771
772 const struct ynl_family ynl_devlink_family =  {
773         .name           = "devlink",
774 };