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