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 nla_parent = attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME]; 490 if (nla_parent) { 491 err = devlink_nl_rate_parent_node_set(devlink_rate, info, 492 nla_parent); 493 if (err) 494 return err; 495 } 496 497 if (attrs[DEVLINK_ATTR_RATE_TC_BWS]) { 498 err = devlink_nl_rate_tc_bw_set(devlink_rate, info); 499 if (err) 500 return err; 501 } 502 503 return 0; 504 } 505 506 static bool devlink_rate_set_ops_supported(const struct devlink_ops *ops, 507 struct genl_info *info, 508 enum devlink_rate_type type) 509 { 510 struct nlattr **attrs = info->attrs; 511 512 if (type == DEVLINK_RATE_TYPE_LEAF) { 513 if (attrs[DEVLINK_ATTR_RATE_TX_SHARE] && !ops->rate_leaf_tx_share_set) { 514 NL_SET_ERR_MSG(info->extack, "TX share set isn't supported for the leafs"); 515 return false; 516 } 517 if (attrs[DEVLINK_ATTR_RATE_TX_MAX] && !ops->rate_leaf_tx_max_set) { 518 NL_SET_ERR_MSG(info->extack, "TX max set isn't supported for the leafs"); 519 return false; 520 } 521 if (attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME] && 522 !ops->rate_leaf_parent_set) { 523 NL_SET_ERR_MSG(info->extack, "Parent set isn't supported for the leafs"); 524 return false; 525 } 526 if (attrs[DEVLINK_ATTR_RATE_TX_PRIORITY] && !ops->rate_leaf_tx_priority_set) { 527 NL_SET_ERR_MSG_ATTR(info->extack, 528 attrs[DEVLINK_ATTR_RATE_TX_PRIORITY], 529 "TX priority set isn't supported for the leafs"); 530 return false; 531 } 532 if (attrs[DEVLINK_ATTR_RATE_TX_WEIGHT] && !ops->rate_leaf_tx_weight_set) { 533 NL_SET_ERR_MSG_ATTR(info->extack, 534 attrs[DEVLINK_ATTR_RATE_TX_WEIGHT], 535 "TX weight set isn't supported for the leafs"); 536 return false; 537 } 538 if (attrs[DEVLINK_ATTR_RATE_TC_BWS] && 539 !ops->rate_leaf_tc_bw_set) { 540 NL_SET_ERR_MSG_ATTR(info->extack, 541 attrs[DEVLINK_ATTR_RATE_TC_BWS], 542 "TC bandwidth set isn't supported for the leafs"); 543 return false; 544 } 545 } else if (type == DEVLINK_RATE_TYPE_NODE) { 546 if (attrs[DEVLINK_ATTR_RATE_TX_SHARE] && !ops->rate_node_tx_share_set) { 547 NL_SET_ERR_MSG(info->extack, "TX share set isn't supported for the nodes"); 548 return false; 549 } 550 if (attrs[DEVLINK_ATTR_RATE_TX_MAX] && !ops->rate_node_tx_max_set) { 551 NL_SET_ERR_MSG(info->extack, "TX max set isn't supported for the nodes"); 552 return false; 553 } 554 if (attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME] && 555 !ops->rate_node_parent_set) { 556 NL_SET_ERR_MSG(info->extack, "Parent set isn't supported for the nodes"); 557 return false; 558 } 559 if (attrs[DEVLINK_ATTR_RATE_TX_PRIORITY] && !ops->rate_node_tx_priority_set) { 560 NL_SET_ERR_MSG_ATTR(info->extack, 561 attrs[DEVLINK_ATTR_RATE_TX_PRIORITY], 562 "TX priority set isn't supported for the nodes"); 563 return false; 564 } 565 if (attrs[DEVLINK_ATTR_RATE_TX_WEIGHT] && !ops->rate_node_tx_weight_set) { 566 NL_SET_ERR_MSG_ATTR(info->extack, 567 attrs[DEVLINK_ATTR_RATE_TX_WEIGHT], 568 "TX weight set isn't supported for the nodes"); 569 return false; 570 } 571 if (attrs[DEVLINK_ATTR_RATE_TC_BWS] && 572 !ops->rate_node_tc_bw_set) { 573 NL_SET_ERR_MSG_ATTR(info->extack, 574 attrs[DEVLINK_ATTR_RATE_TC_BWS], 575 "TC bandwidth set isn't supported for the nodes"); 576 return false; 577 } 578 } else { 579 WARN(1, "Unknown type of rate object"); 580 return false; 581 } 582 583 return true; 584 } 585 586 int devlink_nl_rate_set_doit(struct sk_buff *skb, struct genl_info *info) 587 { 588 struct devlink *devlink = info->user_ptr[0]; 589 struct devlink_rate *devlink_rate; 590 const struct devlink_ops *ops; 591 int err; 592 593 devlink_rate = devlink_rate_get_from_info(devlink, info); 594 if (IS_ERR(devlink_rate)) 595 return PTR_ERR(devlink_rate); 596 597 ops = devlink->ops; 598 if (!ops || !devlink_rate_set_ops_supported(ops, info, devlink_rate->type)) 599 return -EOPNOTSUPP; 600 601 err = devlink_nl_rate_set(devlink_rate, ops, info); 602 603 if (!err) 604 devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_NEW); 605 return err; 606 } 607 608 int devlink_nl_rate_new_doit(struct sk_buff *skb, struct genl_info *info) 609 { 610 struct devlink *devlink = info->user_ptr[0]; 611 struct devlink_rate *rate_node; 612 const struct devlink_ops *ops; 613 int err; 614 615 ops = devlink->ops; 616 if (!ops || !ops->rate_node_new || !ops->rate_node_del) { 617 NL_SET_ERR_MSG(info->extack, "Rate nodes aren't supported"); 618 return -EOPNOTSUPP; 619 } 620 621 if (!devlink_rate_set_ops_supported(ops, info, DEVLINK_RATE_TYPE_NODE)) 622 return -EOPNOTSUPP; 623 624 rate_node = devlink_rate_node_get_from_attrs(devlink, info->attrs); 625 if (!IS_ERR(rate_node)) 626 return -EEXIST; 627 else if (rate_node == ERR_PTR(-EINVAL)) 628 return -EINVAL; 629 630 rate_node = kzalloc(sizeof(*rate_node), GFP_KERNEL); 631 if (!rate_node) 632 return -ENOMEM; 633 634 rate_node->devlink = devlink; 635 rate_node->type = DEVLINK_RATE_TYPE_NODE; 636 rate_node->name = nla_strdup(info->attrs[DEVLINK_ATTR_RATE_NODE_NAME], GFP_KERNEL); 637 if (!rate_node->name) { 638 err = -ENOMEM; 639 goto err_strdup; 640 } 641 642 err = ops->rate_node_new(rate_node, &rate_node->priv, info->extack); 643 if (err) 644 goto err_node_new; 645 646 err = devlink_nl_rate_set(rate_node, ops, info); 647 if (err) 648 goto err_rate_set; 649 650 refcount_set(&rate_node->refcnt, 1); 651 list_add(&rate_node->list, &devlink->rate_list); 652 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW); 653 return 0; 654 655 err_rate_set: 656 ops->rate_node_del(rate_node, rate_node->priv, info->extack); 657 err_node_new: 658 kfree(rate_node->name); 659 err_strdup: 660 kfree(rate_node); 661 return err; 662 } 663 664 int devlink_nl_rate_del_doit(struct sk_buff *skb, struct genl_info *info) 665 { 666 struct devlink *devlink = info->user_ptr[0]; 667 struct devlink_rate *rate_node; 668 int err; 669 670 rate_node = devlink_rate_node_get_from_info(devlink, info); 671 if (IS_ERR(rate_node)) 672 return PTR_ERR(rate_node); 673 674 if (refcount_read(&rate_node->refcnt) > 1) { 675 NL_SET_ERR_MSG(info->extack, "Node has children. Cannot delete node."); 676 return -EBUSY; 677 } 678 679 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_DEL); 680 err = devlink->ops->rate_node_del(rate_node, rate_node->priv, 681 info->extack); 682 if (rate_node->parent) 683 refcount_dec(&rate_node->parent->refcnt); 684 list_del(&rate_node->list); 685 kfree(rate_node->name); 686 kfree(rate_node); 687 return err; 688 } 689 690 int devlink_rates_check(struct devlink *devlink, 691 bool (*rate_filter)(const struct devlink_rate *), 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 (!rate_filter || rate_filter(devlink_rate)) { 698 if (extack) 699 NL_SET_ERR_MSG(extack, "Rate node(s) exists."); 700 return -EBUSY; 701 } 702 return 0; 703 } 704 705 /** 706 * devl_rate_node_create - create devlink rate node 707 * @devlink: devlink instance 708 * @priv: driver private data 709 * @node_name: name of the resulting node 710 * @parent: parent devlink_rate struct 711 * 712 * Create devlink rate object of type node 713 */ 714 struct devlink_rate * 715 devl_rate_node_create(struct devlink *devlink, void *priv, char *node_name, 716 struct devlink_rate *parent) 717 { 718 struct devlink_rate *rate_node; 719 720 rate_node = devlink_rate_node_get_by_name(devlink, node_name); 721 if (!IS_ERR(rate_node)) 722 return ERR_PTR(-EEXIST); 723 724 rate_node = kzalloc(sizeof(*rate_node), GFP_KERNEL); 725 if (!rate_node) 726 return ERR_PTR(-ENOMEM); 727 728 if (parent) { 729 rate_node->parent = parent; 730 refcount_inc(&rate_node->parent->refcnt); 731 } 732 733 rate_node->type = DEVLINK_RATE_TYPE_NODE; 734 rate_node->devlink = devlink; 735 rate_node->priv = priv; 736 737 rate_node->name = kstrdup(node_name, GFP_KERNEL); 738 if (!rate_node->name) { 739 kfree(rate_node); 740 return ERR_PTR(-ENOMEM); 741 } 742 743 refcount_set(&rate_node->refcnt, 1); 744 list_add(&rate_node->list, &devlink->rate_list); 745 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW); 746 return rate_node; 747 } 748 EXPORT_SYMBOL_GPL(devl_rate_node_create); 749 750 /** 751 * devl_rate_leaf_create - create devlink rate leaf 752 * @devlink_port: devlink port object to create rate object on 753 * @priv: driver private data 754 * @parent: parent devlink_rate struct 755 * 756 * Create devlink rate object of type leaf on provided @devlink_port. 757 */ 758 int devl_rate_leaf_create(struct devlink_port *devlink_port, void *priv, 759 struct devlink_rate *parent) 760 { 761 struct devlink *devlink = devlink_port->devlink; 762 struct devlink_rate *devlink_rate; 763 764 devl_assert_locked(devlink_port->devlink); 765 766 if (WARN_ON(devlink_port->devlink_rate)) 767 return -EBUSY; 768 769 devlink_rate = kzalloc(sizeof(*devlink_rate), GFP_KERNEL); 770 if (!devlink_rate) 771 return -ENOMEM; 772 773 if (parent) { 774 devlink_rate->parent = parent; 775 refcount_inc(&devlink_rate->parent->refcnt); 776 } 777 778 devlink_rate->type = DEVLINK_RATE_TYPE_LEAF; 779 devlink_rate->devlink = devlink; 780 devlink_rate->devlink_port = devlink_port; 781 devlink_rate->priv = priv; 782 list_add_tail(&devlink_rate->list, &devlink->rate_list); 783 devlink_port->devlink_rate = devlink_rate; 784 devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_NEW); 785 786 return 0; 787 } 788 EXPORT_SYMBOL_GPL(devl_rate_leaf_create); 789 790 /** 791 * devl_rate_leaf_destroy - destroy devlink rate leaf 792 * 793 * @devlink_port: devlink port linked to the rate object 794 * 795 * Destroy the devlink rate object of type leaf on provided @devlink_port. 796 */ 797 void devl_rate_leaf_destroy(struct devlink_port *devlink_port) 798 { 799 struct devlink_rate *devlink_rate = devlink_port->devlink_rate; 800 801 devl_assert_locked(devlink_port->devlink); 802 if (!devlink_rate) 803 return; 804 805 devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_DEL); 806 if (devlink_rate->parent) 807 refcount_dec(&devlink_rate->parent->refcnt); 808 list_del(&devlink_rate->list); 809 devlink_port->devlink_rate = NULL; 810 kfree(devlink_rate); 811 } 812 EXPORT_SYMBOL_GPL(devl_rate_leaf_destroy); 813 814 /** 815 * devl_rate_nodes_destroy - destroy all devlink rate nodes on device 816 * @devlink: devlink instance 817 * 818 * Unset parent for all rate objects and destroy all rate nodes 819 * on specified device. 820 */ 821 void devl_rate_nodes_destroy(struct devlink *devlink) 822 { 823 const struct devlink_ops *ops = devlink->ops; 824 struct devlink_rate *devlink_rate, *tmp; 825 826 devl_assert_locked(devlink); 827 828 list_for_each_entry(devlink_rate, &devlink->rate_list, list) { 829 if (!devlink_rate->parent) 830 continue; 831 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 refcount_dec(&devlink_rate->parent->refcnt); 840 devlink_rate->parent = NULL; 841 } 842 list_for_each_entry_safe(devlink_rate, tmp, &devlink->rate_list, list) { 843 if (devlink_rate_is_node(devlink_rate)) { 844 ops->rate_node_del(devlink_rate, devlink_rate->priv, NULL); 845 list_del(&devlink_rate->list); 846 kfree(devlink_rate->name); 847 kfree(devlink_rate); 848 } 849 } 850 } 851 EXPORT_SYMBOL_GPL(devl_rate_nodes_destroy); 852