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