1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2016 Mellanox Technologies. All rights reserved. 4 * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com> 5 */ 6 7 #include "devl_internal.h" 8 9 static inline bool 10 devlink_rate_is_leaf(struct devlink_rate *devlink_rate) 11 { 12 return devlink_rate->type == DEVLINK_RATE_TYPE_LEAF; 13 } 14 15 bool devlink_rate_is_node(const struct devlink_rate *devlink_rate) 16 { 17 return devlink_rate->type == DEVLINK_RATE_TYPE_NODE; 18 } 19 20 static struct devlink_rate * 21 devlink_rate_leaf_get_from_info(struct devlink *devlink, struct genl_info *info) 22 { 23 struct devlink_rate *devlink_rate; 24 struct devlink_port *devlink_port; 25 26 devlink_port = devlink_port_get_from_attrs(devlink, info->attrs); 27 if (IS_ERR(devlink_port)) 28 return ERR_CAST(devlink_port); 29 devlink_rate = devlink_port->devlink_rate; 30 return devlink_rate ?: ERR_PTR(-ENODEV); 31 } 32 33 static struct devlink_rate * 34 devlink_rate_node_get_by_name(struct devlink *devlink, const char *node_name) 35 { 36 struct devlink_rate *devlink_rate; 37 38 list_for_each_entry(devlink_rate, &devlink->rate_list, list) { 39 if (devlink_rate_is_node(devlink_rate) && 40 !strcmp(node_name, devlink_rate->name)) 41 return devlink_rate; 42 } 43 return ERR_PTR(-ENODEV); 44 } 45 46 static struct devlink_rate * 47 devlink_rate_node_get_from_attrs(struct devlink *devlink, struct nlattr **attrs) 48 { 49 const char *rate_node_name; 50 size_t len; 51 52 if (!attrs[DEVLINK_ATTR_RATE_NODE_NAME]) 53 return ERR_PTR(-EINVAL); 54 rate_node_name = nla_data(attrs[DEVLINK_ATTR_RATE_NODE_NAME]); 55 len = strlen(rate_node_name); 56 /* Name cannot be empty or decimal number */ 57 if (!len || strspn(rate_node_name, "0123456789") == len) 58 return ERR_PTR(-EINVAL); 59 60 return devlink_rate_node_get_by_name(devlink, rate_node_name); 61 } 62 63 static struct devlink_rate * 64 devlink_rate_node_get_from_info(struct devlink *devlink, struct genl_info *info) 65 { 66 return devlink_rate_node_get_from_attrs(devlink, info->attrs); 67 } 68 69 static struct devlink_rate * 70 devlink_rate_get_from_info(struct devlink *devlink, struct genl_info *info) 71 { 72 struct nlattr **attrs = info->attrs; 73 74 if (attrs[DEVLINK_ATTR_PORT_INDEX]) 75 return devlink_rate_leaf_get_from_info(devlink, info); 76 else if (attrs[DEVLINK_ATTR_RATE_NODE_NAME]) 77 return devlink_rate_node_get_from_info(devlink, info); 78 else 79 return ERR_PTR(-EINVAL); 80 } 81 82 static int devlink_rate_put_tc_bws(struct sk_buff *msg, u32 *tc_bw) 83 { 84 struct nlattr *nla_tc_bw; 85 int i; 86 87 for (i = 0; i < DEVLINK_RATE_TCS_MAX; i++) { 88 nla_tc_bw = nla_nest_start(msg, DEVLINK_ATTR_RATE_TC_BWS); 89 if (!nla_tc_bw) 90 return -EMSGSIZE; 91 92 if (nla_put_u8(msg, DEVLINK_RATE_TC_ATTR_INDEX, i) || 93 nla_put_u32(msg, DEVLINK_RATE_TC_ATTR_BW, tc_bw[i])) 94 goto nla_put_failure; 95 96 nla_nest_end(msg, nla_tc_bw); 97 } 98 return 0; 99 100 nla_put_failure: 101 nla_nest_cancel(msg, nla_tc_bw); 102 return -EMSGSIZE; 103 } 104 105 static int devlink_nl_rate_fill(struct sk_buff *msg, 106 struct devlink_rate *devlink_rate, 107 enum devlink_command cmd, u32 portid, u32 seq, 108 int flags, struct netlink_ext_ack *extack) 109 { 110 struct devlink *devlink = devlink_rate->devlink; 111 void *hdr; 112 113 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 114 if (!hdr) 115 return -EMSGSIZE; 116 117 if (devlink_nl_put_handle(msg, devlink)) 118 goto nla_put_failure; 119 120 if (nla_put_u16(msg, DEVLINK_ATTR_RATE_TYPE, devlink_rate->type)) 121 goto nla_put_failure; 122 123 if (devlink_rate_is_leaf(devlink_rate)) { 124 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, 125 devlink_rate->devlink_port->index)) 126 goto nla_put_failure; 127 } else if (devlink_rate_is_node(devlink_rate)) { 128 if (nla_put_string(msg, DEVLINK_ATTR_RATE_NODE_NAME, 129 devlink_rate->name)) 130 goto nla_put_failure; 131 } 132 133 if (devlink_nl_put_u64(msg, DEVLINK_ATTR_RATE_TX_SHARE, 134 devlink_rate->tx_share)) 135 goto nla_put_failure; 136 137 if (devlink_nl_put_u64(msg, DEVLINK_ATTR_RATE_TX_MAX, 138 devlink_rate->tx_max)) 139 goto nla_put_failure; 140 141 if (nla_put_u32(msg, DEVLINK_ATTR_RATE_TX_PRIORITY, 142 devlink_rate->tx_priority)) 143 goto nla_put_failure; 144 145 if (nla_put_u32(msg, DEVLINK_ATTR_RATE_TX_WEIGHT, 146 devlink_rate->tx_weight)) 147 goto nla_put_failure; 148 149 if (devlink_rate->parent) 150 if (nla_put_string(msg, DEVLINK_ATTR_RATE_PARENT_NODE_NAME, 151 devlink_rate->parent->name)) 152 goto nla_put_failure; 153 154 if (devlink_rate_put_tc_bws(msg, devlink_rate->tc_bw)) 155 goto nla_put_failure; 156 157 genlmsg_end(msg, hdr); 158 return 0; 159 160 nla_put_failure: 161 genlmsg_cancel(msg, hdr); 162 return -EMSGSIZE; 163 } 164 165 static void devlink_rate_notify(struct devlink_rate *devlink_rate, 166 enum devlink_command cmd) 167 { 168 struct devlink *devlink = devlink_rate->devlink; 169 struct sk_buff *msg; 170 int err; 171 172 WARN_ON(cmd != DEVLINK_CMD_RATE_NEW && cmd != DEVLINK_CMD_RATE_DEL); 173 174 if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink)) 175 return; 176 177 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 178 if (!msg) 179 return; 180 181 err = devlink_nl_rate_fill(msg, devlink_rate, cmd, 0, 0, 0, NULL); 182 if (err) { 183 nlmsg_free(msg); 184 return; 185 } 186 187 devlink_nl_notify_send(devlink, msg); 188 } 189 190 void devlink_rates_notify_register(struct devlink *devlink) 191 { 192 struct devlink_rate *rate_node; 193 194 list_for_each_entry(rate_node, &devlink->rate_list, list) 195 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW); 196 } 197 198 void devlink_rates_notify_unregister(struct devlink *devlink) 199 { 200 struct devlink_rate *rate_node; 201 202 list_for_each_entry_reverse(rate_node, &devlink->rate_list, list) 203 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_DEL); 204 } 205 206 static int 207 devlink_nl_rate_get_dump_one(struct sk_buff *msg, struct devlink *devlink, 208 struct netlink_callback *cb, int flags) 209 { 210 struct devlink_nl_dump_state *state = devlink_dump_state(cb); 211 struct devlink_rate *devlink_rate; 212 int idx = 0; 213 int err = 0; 214 215 list_for_each_entry(devlink_rate, &devlink->rate_list, list) { 216 enum devlink_command cmd = DEVLINK_CMD_RATE_NEW; 217 u32 id = NETLINK_CB(cb->skb).portid; 218 219 if (idx < state->idx) { 220 idx++; 221 continue; 222 } 223 err = devlink_nl_rate_fill(msg, devlink_rate, cmd, id, 224 cb->nlh->nlmsg_seq, flags, NULL); 225 if (err) { 226 state->idx = idx; 227 break; 228 } 229 idx++; 230 } 231 232 return err; 233 } 234 235 int devlink_nl_rate_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) 236 { 237 return devlink_nl_dumpit(skb, cb, devlink_nl_rate_get_dump_one); 238 } 239 240 int devlink_nl_rate_get_doit(struct sk_buff *skb, struct genl_info *info) 241 { 242 struct devlink *devlink = info->user_ptr[0]; 243 struct devlink_rate *devlink_rate; 244 struct sk_buff *msg; 245 int err; 246 247 devlink_rate = devlink_rate_get_from_info(devlink, info); 248 if (IS_ERR(devlink_rate)) 249 return PTR_ERR(devlink_rate); 250 251 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 252 if (!msg) 253 return -ENOMEM; 254 255 err = devlink_nl_rate_fill(msg, devlink_rate, DEVLINK_CMD_RATE_NEW, 256 info->snd_portid, info->snd_seq, 0, 257 info->extack); 258 if (err) { 259 nlmsg_free(msg); 260 return err; 261 } 262 263 return genlmsg_reply(msg, info); 264 } 265 266 static bool 267 devlink_rate_is_parent_node(struct devlink_rate *devlink_rate, 268 struct devlink_rate *parent) 269 { 270 while (parent) { 271 if (parent == devlink_rate) 272 return true; 273 parent = parent->parent; 274 } 275 return false; 276 } 277 278 static int 279 devlink_nl_rate_parent_node_set(struct devlink_rate *devlink_rate, 280 struct genl_info *info, 281 struct nlattr *nla_parent) 282 { 283 struct devlink *devlink = devlink_rate->devlink; 284 const char *parent_name = nla_data(nla_parent); 285 const struct devlink_ops *ops = devlink->ops; 286 size_t len = strlen(parent_name); 287 struct devlink_rate *parent; 288 int err = -EOPNOTSUPP; 289 290 parent = devlink_rate->parent; 291 292 if (parent && !len) { 293 if (devlink_rate_is_leaf(devlink_rate)) 294 err = ops->rate_leaf_parent_set(devlink_rate, NULL, 295 devlink_rate->priv, NULL, 296 info->extack); 297 else if (devlink_rate_is_node(devlink_rate)) 298 err = ops->rate_node_parent_set(devlink_rate, NULL, 299 devlink_rate->priv, NULL, 300 info->extack); 301 if (err) 302 return err; 303 304 refcount_dec(&parent->refcnt); 305 devlink_rate->parent = NULL; 306 } else if (len) { 307 parent = devlink_rate_node_get_by_name(devlink, parent_name); 308 if (IS_ERR(parent)) 309 return -ENODEV; 310 311 if (parent == devlink_rate) { 312 NL_SET_ERR_MSG(info->extack, "Parent to self is not allowed"); 313 return -EINVAL; 314 } 315 316 if (devlink_rate_is_node(devlink_rate) && 317 devlink_rate_is_parent_node(devlink_rate, parent->parent)) { 318 NL_SET_ERR_MSG(info->extack, "Node is already a parent of parent node."); 319 return -EEXIST; 320 } 321 322 if (devlink_rate_is_leaf(devlink_rate)) 323 err = ops->rate_leaf_parent_set(devlink_rate, parent, 324 devlink_rate->priv, parent->priv, 325 info->extack); 326 else if (devlink_rate_is_node(devlink_rate)) 327 err = ops->rate_node_parent_set(devlink_rate, parent, 328 devlink_rate->priv, parent->priv, 329 info->extack); 330 if (err) 331 return err; 332 333 if (devlink_rate->parent) 334 /* we're reassigning to other parent in this case */ 335 refcount_dec(&devlink_rate->parent->refcnt); 336 337 refcount_inc(&parent->refcnt); 338 devlink_rate->parent = parent; 339 } 340 341 return 0; 342 } 343 344 static int devlink_nl_rate_tc_bw_parse(struct nlattr *parent_nest, u32 *tc_bw, 345 unsigned long *bitmap, 346 struct netlink_ext_ack *extack) 347 { 348 struct nlattr *tb[DEVLINK_RATE_TC_ATTR_MAX + 1]; 349 u8 tc_index; 350 int err; 351 352 err = nla_parse_nested(tb, DEVLINK_RATE_TC_ATTR_MAX, parent_nest, 353 devlink_dl_rate_tc_bws_nl_policy, extack); 354 if (err) 355 return err; 356 357 if (!tb[DEVLINK_RATE_TC_ATTR_INDEX]) { 358 NL_SET_ERR_ATTR_MISS(extack, parent_nest, 359 DEVLINK_RATE_TC_ATTR_INDEX); 360 return -EINVAL; 361 } 362 363 tc_index = nla_get_u8(tb[DEVLINK_RATE_TC_ATTR_INDEX]); 364 365 if (!tb[DEVLINK_RATE_TC_ATTR_BW]) { 366 NL_SET_ERR_ATTR_MISS(extack, parent_nest, 367 DEVLINK_RATE_TC_ATTR_BW); 368 return -EINVAL; 369 } 370 371 if (test_and_set_bit(tc_index, bitmap)) { 372 NL_SET_ERR_MSG_FMT(extack, 373 "Duplicate traffic class index specified (%u)", 374 tc_index); 375 return -EINVAL; 376 } 377 378 tc_bw[tc_index] = nla_get_u32(tb[DEVLINK_RATE_TC_ATTR_BW]); 379 380 return 0; 381 } 382 383 static int devlink_nl_rate_tc_bw_set(struct devlink_rate *devlink_rate, 384 struct genl_info *info) 385 { 386 DECLARE_BITMAP(bitmap, DEVLINK_RATE_TCS_MAX) = {}; 387 struct devlink *devlink = devlink_rate->devlink; 388 const struct devlink_ops *ops = devlink->ops; 389 u32 tc_bw[DEVLINK_RATE_TCS_MAX] = {}; 390 int rem, err = -EOPNOTSUPP, i; 391 struct nlattr *attr; 392 393 nlmsg_for_each_attr_type(attr, DEVLINK_ATTR_RATE_TC_BWS, info->nlhdr, 394 GENL_HDRLEN, rem) { 395 err = devlink_nl_rate_tc_bw_parse(attr, tc_bw, bitmap, 396 info->extack); 397 if (err) 398 return err; 399 } 400 401 for (i = 0; i < DEVLINK_RATE_TCS_MAX; i++) { 402 if (!test_bit(i, bitmap)) { 403 NL_SET_ERR_MSG_FMT(info->extack, 404 "Bandwidth values must be specified for all %u traffic classes", 405 DEVLINK_RATE_TCS_MAX); 406 return -EINVAL; 407 } 408 } 409 410 if (devlink_rate_is_leaf(devlink_rate)) 411 err = ops->rate_leaf_tc_bw_set(devlink_rate, devlink_rate->priv, 412 tc_bw, info->extack); 413 else if (devlink_rate_is_node(devlink_rate)) 414 err = ops->rate_node_tc_bw_set(devlink_rate, devlink_rate->priv, 415 tc_bw, info->extack); 416 417 if (err) 418 return err; 419 420 memcpy(devlink_rate->tc_bw, tc_bw, sizeof(tc_bw)); 421 422 return 0; 423 } 424 425 static int devlink_nl_rate_set(struct devlink_rate *devlink_rate, 426 const struct devlink_ops *ops, 427 struct genl_info *info) 428 { 429 struct nlattr *nla_parent, **attrs = info->attrs; 430 int err = -EOPNOTSUPP; 431 u32 priority; 432 u32 weight; 433 u64 rate; 434 435 if (attrs[DEVLINK_ATTR_RATE_TX_SHARE]) { 436 rate = nla_get_u64(attrs[DEVLINK_ATTR_RATE_TX_SHARE]); 437 if (devlink_rate_is_leaf(devlink_rate)) 438 err = ops->rate_leaf_tx_share_set(devlink_rate, devlink_rate->priv, 439 rate, info->extack); 440 else if (devlink_rate_is_node(devlink_rate)) 441 err = ops->rate_node_tx_share_set(devlink_rate, devlink_rate->priv, 442 rate, info->extack); 443 if (err) 444 return err; 445 devlink_rate->tx_share = rate; 446 } 447 448 if (attrs[DEVLINK_ATTR_RATE_TX_MAX]) { 449 rate = nla_get_u64(attrs[DEVLINK_ATTR_RATE_TX_MAX]); 450 if (devlink_rate_is_leaf(devlink_rate)) 451 err = ops->rate_leaf_tx_max_set(devlink_rate, devlink_rate->priv, 452 rate, info->extack); 453 else if (devlink_rate_is_node(devlink_rate)) 454 err = ops->rate_node_tx_max_set(devlink_rate, devlink_rate->priv, 455 rate, info->extack); 456 if (err) 457 return err; 458 devlink_rate->tx_max = rate; 459 } 460 461 if (attrs[DEVLINK_ATTR_RATE_TX_PRIORITY]) { 462 priority = nla_get_u32(attrs[DEVLINK_ATTR_RATE_TX_PRIORITY]); 463 if (devlink_rate_is_leaf(devlink_rate)) 464 err = ops->rate_leaf_tx_priority_set(devlink_rate, devlink_rate->priv, 465 priority, info->extack); 466 else if (devlink_rate_is_node(devlink_rate)) 467 err = ops->rate_node_tx_priority_set(devlink_rate, devlink_rate->priv, 468 priority, info->extack); 469 470 if (err) 471 return err; 472 devlink_rate->tx_priority = priority; 473 } 474 475 if (attrs[DEVLINK_ATTR_RATE_TX_WEIGHT]) { 476 weight = nla_get_u32(attrs[DEVLINK_ATTR_RATE_TX_WEIGHT]); 477 if (devlink_rate_is_leaf(devlink_rate)) 478 err = ops->rate_leaf_tx_weight_set(devlink_rate, devlink_rate->priv, 479 weight, info->extack); 480 else if (devlink_rate_is_node(devlink_rate)) 481 err = ops->rate_node_tx_weight_set(devlink_rate, devlink_rate->priv, 482 weight, info->extack); 483 484 if (err) 485 return err; 486 devlink_rate->tx_weight = weight; 487 } 488 489 if (attrs[DEVLINK_ATTR_RATE_TC_BWS]) { 490 err = devlink_nl_rate_tc_bw_set(devlink_rate, info); 491 if (err) 492 return err; 493 } 494 495 /* Keep parent setting last because it takes a reference. This function 496 * has no rollback, so failing after taking the ref would leak it. 497 */ 498 nla_parent = attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME]; 499 if (nla_parent) { 500 err = devlink_nl_rate_parent_node_set(devlink_rate, info, 501 nla_parent); 502 if (err) 503 return err; 504 } 505 506 return 0; 507 } 508 509 static bool devlink_rate_set_ops_supported(const struct devlink_ops *ops, 510 struct genl_info *info, 511 enum devlink_rate_type type) 512 { 513 struct nlattr **attrs = info->attrs; 514 515 if (type == DEVLINK_RATE_TYPE_LEAF) { 516 if (attrs[DEVLINK_ATTR_RATE_TX_SHARE] && !ops->rate_leaf_tx_share_set) { 517 NL_SET_ERR_MSG(info->extack, "TX share set isn't supported for the leafs"); 518 return false; 519 } 520 if (attrs[DEVLINK_ATTR_RATE_TX_MAX] && !ops->rate_leaf_tx_max_set) { 521 NL_SET_ERR_MSG(info->extack, "TX max set isn't supported for the leafs"); 522 return false; 523 } 524 if (attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME] && 525 !ops->rate_leaf_parent_set) { 526 NL_SET_ERR_MSG(info->extack, "Parent set isn't supported for the leafs"); 527 return false; 528 } 529 if (attrs[DEVLINK_ATTR_RATE_TX_PRIORITY] && !ops->rate_leaf_tx_priority_set) { 530 NL_SET_ERR_MSG_ATTR(info->extack, 531 attrs[DEVLINK_ATTR_RATE_TX_PRIORITY], 532 "TX priority set isn't supported for the leafs"); 533 return false; 534 } 535 if (attrs[DEVLINK_ATTR_RATE_TX_WEIGHT] && !ops->rate_leaf_tx_weight_set) { 536 NL_SET_ERR_MSG_ATTR(info->extack, 537 attrs[DEVLINK_ATTR_RATE_TX_WEIGHT], 538 "TX weight set isn't supported for the leafs"); 539 return false; 540 } 541 if (attrs[DEVLINK_ATTR_RATE_TC_BWS] && 542 !ops->rate_leaf_tc_bw_set) { 543 NL_SET_ERR_MSG_ATTR(info->extack, 544 attrs[DEVLINK_ATTR_RATE_TC_BWS], 545 "TC bandwidth set isn't supported for the leafs"); 546 return false; 547 } 548 } else if (type == DEVLINK_RATE_TYPE_NODE) { 549 if (attrs[DEVLINK_ATTR_RATE_TX_SHARE] && !ops->rate_node_tx_share_set) { 550 NL_SET_ERR_MSG(info->extack, "TX share set isn't supported for the nodes"); 551 return false; 552 } 553 if (attrs[DEVLINK_ATTR_RATE_TX_MAX] && !ops->rate_node_tx_max_set) { 554 NL_SET_ERR_MSG(info->extack, "TX max set isn't supported for the nodes"); 555 return false; 556 } 557 if (attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME] && 558 !ops->rate_node_parent_set) { 559 NL_SET_ERR_MSG(info->extack, "Parent set isn't supported for the nodes"); 560 return false; 561 } 562 if (attrs[DEVLINK_ATTR_RATE_TX_PRIORITY] && !ops->rate_node_tx_priority_set) { 563 NL_SET_ERR_MSG_ATTR(info->extack, 564 attrs[DEVLINK_ATTR_RATE_TX_PRIORITY], 565 "TX priority set isn't supported for the nodes"); 566 return false; 567 } 568 if (attrs[DEVLINK_ATTR_RATE_TX_WEIGHT] && !ops->rate_node_tx_weight_set) { 569 NL_SET_ERR_MSG_ATTR(info->extack, 570 attrs[DEVLINK_ATTR_RATE_TX_WEIGHT], 571 "TX weight set isn't supported for the nodes"); 572 return false; 573 } 574 if (attrs[DEVLINK_ATTR_RATE_TC_BWS] && 575 !ops->rate_node_tc_bw_set) { 576 NL_SET_ERR_MSG_ATTR(info->extack, 577 attrs[DEVLINK_ATTR_RATE_TC_BWS], 578 "TC bandwidth set isn't supported for the nodes"); 579 return false; 580 } 581 } else { 582 WARN(1, "Unknown type of rate object"); 583 return false; 584 } 585 586 return true; 587 } 588 589 int devlink_nl_rate_set_doit(struct sk_buff *skb, struct genl_info *info) 590 { 591 struct devlink *devlink = info->user_ptr[0]; 592 struct devlink_rate *devlink_rate; 593 const struct devlink_ops *ops; 594 int err; 595 596 devlink_rate = devlink_rate_get_from_info(devlink, info); 597 if (IS_ERR(devlink_rate)) 598 return PTR_ERR(devlink_rate); 599 600 ops = devlink->ops; 601 if (!ops || !devlink_rate_set_ops_supported(ops, info, devlink_rate->type)) 602 return -EOPNOTSUPP; 603 604 err = devlink_nl_rate_set(devlink_rate, ops, info); 605 606 if (!err) 607 devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_NEW); 608 return err; 609 } 610 611 int devlink_nl_rate_new_doit(struct sk_buff *skb, struct genl_info *info) 612 { 613 struct devlink *devlink = info->user_ptr[0]; 614 struct devlink_rate *rate_node; 615 const struct devlink_ops *ops; 616 int err; 617 618 ops = devlink->ops; 619 if (!ops || !ops->rate_node_new || !ops->rate_node_del) { 620 NL_SET_ERR_MSG(info->extack, "Rate nodes aren't supported"); 621 return -EOPNOTSUPP; 622 } 623 624 if (!devlink_rate_set_ops_supported(ops, info, DEVLINK_RATE_TYPE_NODE)) 625 return -EOPNOTSUPP; 626 627 rate_node = devlink_rate_node_get_from_attrs(devlink, info->attrs); 628 if (!IS_ERR(rate_node)) 629 return -EEXIST; 630 else if (rate_node == ERR_PTR(-EINVAL)) 631 return -EINVAL; 632 633 rate_node = kzalloc_obj(*rate_node); 634 if (!rate_node) 635 return -ENOMEM; 636 637 rate_node->devlink = devlink; 638 rate_node->type = DEVLINK_RATE_TYPE_NODE; 639 rate_node->name = nla_strdup(info->attrs[DEVLINK_ATTR_RATE_NODE_NAME], GFP_KERNEL); 640 if (!rate_node->name) { 641 err = -ENOMEM; 642 goto err_strdup; 643 } 644 645 err = ops->rate_node_new(rate_node, &rate_node->priv, info->extack); 646 if (err) 647 goto err_node_new; 648 649 err = devlink_nl_rate_set(rate_node, ops, info); 650 if (err) 651 goto err_rate_set; 652 653 refcount_set(&rate_node->refcnt, 1); 654 list_add(&rate_node->list, &devlink->rate_list); 655 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW); 656 return 0; 657 658 err_rate_set: 659 ops->rate_node_del(rate_node, rate_node->priv, info->extack); 660 err_node_new: 661 kfree(rate_node->name); 662 err_strdup: 663 kfree(rate_node); 664 return err; 665 } 666 667 int devlink_nl_rate_del_doit(struct sk_buff *skb, struct genl_info *info) 668 { 669 struct devlink *devlink = info->user_ptr[0]; 670 struct devlink_rate *rate_node; 671 int err; 672 673 rate_node = devlink_rate_node_get_from_info(devlink, info); 674 if (IS_ERR(rate_node)) 675 return PTR_ERR(rate_node); 676 677 if (refcount_read(&rate_node->refcnt) > 1) { 678 NL_SET_ERR_MSG(info->extack, "Node has children. Cannot delete node."); 679 return -EBUSY; 680 } 681 682 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_DEL); 683 err = devlink->ops->rate_node_del(rate_node, rate_node->priv, 684 info->extack); 685 if (rate_node->parent) 686 refcount_dec(&rate_node->parent->refcnt); 687 list_del(&rate_node->list); 688 kfree(rate_node->name); 689 kfree(rate_node); 690 return err; 691 } 692 693 int devlink_rates_check(struct devlink *devlink, 694 bool (*rate_filter)(const struct devlink_rate *), 695 struct netlink_ext_ack *extack) 696 { 697 struct devlink_rate *devlink_rate; 698 699 list_for_each_entry(devlink_rate, &devlink->rate_list, list) 700 if (!rate_filter || rate_filter(devlink_rate)) { 701 if (extack) 702 NL_SET_ERR_MSG(extack, "Rate node(s) exists."); 703 return -EBUSY; 704 } 705 return 0; 706 } 707 708 /** 709 * devl_rate_node_create - create devlink rate node 710 * @devlink: devlink instance 711 * @priv: driver private data 712 * @node_name: name of the resulting node 713 * @parent: parent devlink_rate struct 714 * 715 * Create devlink rate object of type node 716 */ 717 struct devlink_rate * 718 devl_rate_node_create(struct devlink *devlink, void *priv, char *node_name, 719 struct devlink_rate *parent) 720 { 721 struct devlink_rate *rate_node; 722 723 rate_node = devlink_rate_node_get_by_name(devlink, node_name); 724 if (!IS_ERR(rate_node)) 725 return ERR_PTR(-EEXIST); 726 727 rate_node = kzalloc_obj(*rate_node); 728 if (!rate_node) 729 return ERR_PTR(-ENOMEM); 730 731 rate_node->type = DEVLINK_RATE_TYPE_NODE; 732 rate_node->devlink = devlink; 733 rate_node->priv = priv; 734 735 rate_node->name = kstrdup(node_name, GFP_KERNEL); 736 if (!rate_node->name) { 737 kfree(rate_node); 738 return ERR_PTR(-ENOMEM); 739 } 740 741 if (parent) { 742 rate_node->parent = parent; 743 refcount_inc(&rate_node->parent->refcnt); 744 } 745 746 refcount_set(&rate_node->refcnt, 1); 747 list_add(&rate_node->list, &devlink->rate_list); 748 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW); 749 return rate_node; 750 } 751 EXPORT_SYMBOL_GPL(devl_rate_node_create); 752 753 /** 754 * devl_rate_leaf_create - create devlink rate leaf 755 * @devlink_port: devlink port object to create rate object on 756 * @priv: driver private data 757 * @parent: parent devlink_rate struct 758 * 759 * Create devlink rate object of type leaf on provided @devlink_port. 760 */ 761 int devl_rate_leaf_create(struct devlink_port *devlink_port, void *priv, 762 struct devlink_rate *parent) 763 { 764 struct devlink *devlink = devlink_port->devlink; 765 struct devlink_rate *devlink_rate; 766 767 devl_assert_locked(devlink_port->devlink); 768 769 if (WARN_ON(devlink_port->devlink_rate)) 770 return -EBUSY; 771 772 devlink_rate = kzalloc_obj(*devlink_rate); 773 if (!devlink_rate) 774 return -ENOMEM; 775 776 if (parent) { 777 devlink_rate->parent = parent; 778 refcount_inc(&devlink_rate->parent->refcnt); 779 } 780 781 devlink_rate->type = DEVLINK_RATE_TYPE_LEAF; 782 devlink_rate->devlink = devlink; 783 devlink_rate->devlink_port = devlink_port; 784 devlink_rate->priv = priv; 785 list_add_tail(&devlink_rate->list, &devlink->rate_list); 786 devlink_port->devlink_rate = devlink_rate; 787 devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_NEW); 788 789 return 0; 790 } 791 EXPORT_SYMBOL_GPL(devl_rate_leaf_create); 792 793 /** 794 * devl_rate_leaf_destroy - destroy devlink rate leaf 795 * 796 * @devlink_port: devlink port linked to the rate object 797 * 798 * Destroy the devlink rate object of type leaf on provided @devlink_port. 799 */ 800 void devl_rate_leaf_destroy(struct devlink_port *devlink_port) 801 { 802 struct devlink_rate *devlink_rate = devlink_port->devlink_rate; 803 804 devl_assert_locked(devlink_port->devlink); 805 if (!devlink_rate) 806 return; 807 808 devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_DEL); 809 if (devlink_rate->parent) 810 refcount_dec(&devlink_rate->parent->refcnt); 811 list_del(&devlink_rate->list); 812 devlink_port->devlink_rate = NULL; 813 kfree(devlink_rate); 814 } 815 EXPORT_SYMBOL_GPL(devl_rate_leaf_destroy); 816 817 /** 818 * devl_rate_nodes_destroy - destroy all devlink rate nodes on device 819 * @devlink: devlink instance 820 * 821 * Unset parent for all rate objects and destroy all rate nodes 822 * on specified device. 823 */ 824 void devl_rate_nodes_destroy(struct devlink *devlink) 825 { 826 const struct devlink_ops *ops = devlink->ops; 827 struct devlink_rate *devlink_rate, *tmp; 828 829 devl_assert_locked(devlink); 830 831 list_for_each_entry(devlink_rate, &devlink->rate_list, list) { 832 if (!devlink_rate->parent) 833 continue; 834 835 if (devlink_rate_is_leaf(devlink_rate)) 836 ops->rate_leaf_parent_set(devlink_rate, NULL, devlink_rate->priv, 837 NULL, NULL); 838 else if (devlink_rate_is_node(devlink_rate)) 839 ops->rate_node_parent_set(devlink_rate, NULL, devlink_rate->priv, 840 NULL, NULL); 841 842 refcount_dec(&devlink_rate->parent->refcnt); 843 devlink_rate->parent = NULL; 844 } 845 list_for_each_entry_safe(devlink_rate, tmp, &devlink->rate_list, list) { 846 if (devlink_rate_is_node(devlink_rate)) { 847 ops->rate_node_del(devlink_rate, devlink_rate->priv, NULL); 848 list_del(&devlink_rate->list); 849 kfree(devlink_rate->name); 850 kfree(devlink_rate); 851 } 852 } 853 } 854 EXPORT_SYMBOL_GPL(devl_rate_nodes_destroy); 855