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