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 struct devlink_sb { 10 struct list_head list; 11 unsigned int index; 12 u32 size; 13 u16 ingress_pools_count; 14 u16 egress_pools_count; 15 u16 ingress_tc_count; 16 u16 egress_tc_count; 17 }; 18 19 static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb) 20 { 21 return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count; 22 } 23 24 static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink, 25 unsigned int sb_index) 26 { 27 struct devlink_sb *devlink_sb; 28 29 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 30 if (devlink_sb->index == sb_index) 31 return devlink_sb; 32 } 33 return NULL; 34 } 35 36 static bool devlink_sb_index_exists(struct devlink *devlink, 37 unsigned int sb_index) 38 { 39 return devlink_sb_get_by_index(devlink, sb_index); 40 } 41 42 static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink, 43 struct nlattr **attrs) 44 { 45 if (attrs[DEVLINK_ATTR_SB_INDEX]) { 46 u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]); 47 struct devlink_sb *devlink_sb; 48 49 devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 50 if (!devlink_sb) 51 return ERR_PTR(-ENODEV); 52 return devlink_sb; 53 } 54 return ERR_PTR(-EINVAL); 55 } 56 57 static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink, 58 struct genl_info *info) 59 { 60 return devlink_sb_get_from_attrs(devlink, info->attrs); 61 } 62 63 static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb, 64 struct nlattr **attrs, 65 u16 *p_pool_index) 66 { 67 u16 val; 68 69 if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX]) 70 return -EINVAL; 71 72 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]); 73 if (val >= devlink_sb_pool_count(devlink_sb)) 74 return -EINVAL; 75 *p_pool_index = val; 76 return 0; 77 } 78 79 static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb, 80 struct genl_info *info, 81 u16 *p_pool_index) 82 { 83 return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs, 84 p_pool_index); 85 } 86 87 static int 88 devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs, 89 enum devlink_sb_pool_type *p_pool_type) 90 { 91 u8 val; 92 93 if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE]) 94 return -EINVAL; 95 96 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]); 97 if (val != DEVLINK_SB_POOL_TYPE_INGRESS && 98 val != DEVLINK_SB_POOL_TYPE_EGRESS) 99 return -EINVAL; 100 *p_pool_type = val; 101 return 0; 102 } 103 104 static int 105 devlink_sb_pool_type_get_from_info(struct genl_info *info, 106 enum devlink_sb_pool_type *p_pool_type) 107 { 108 return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type); 109 } 110 111 static int 112 devlink_sb_th_type_get_from_attrs(struct nlattr **attrs, 113 enum devlink_sb_threshold_type *p_th_type) 114 { 115 u8 val; 116 117 if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]) 118 return -EINVAL; 119 120 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]); 121 if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC && 122 val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC) 123 return -EINVAL; 124 *p_th_type = val; 125 return 0; 126 } 127 128 static int 129 devlink_sb_th_type_get_from_info(struct genl_info *info, 130 enum devlink_sb_threshold_type *p_th_type) 131 { 132 return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type); 133 } 134 135 static int 136 devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb, 137 struct nlattr **attrs, 138 enum devlink_sb_pool_type pool_type, 139 u16 *p_tc_index) 140 { 141 u16 val; 142 143 if (!attrs[DEVLINK_ATTR_SB_TC_INDEX]) 144 return -EINVAL; 145 146 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]); 147 if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS && 148 val >= devlink_sb->ingress_tc_count) 149 return -EINVAL; 150 if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS && 151 val >= devlink_sb->egress_tc_count) 152 return -EINVAL; 153 *p_tc_index = val; 154 return 0; 155 } 156 157 static int 158 devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb, 159 struct genl_info *info, 160 enum devlink_sb_pool_type pool_type, 161 u16 *p_tc_index) 162 { 163 return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs, 164 pool_type, p_tc_index); 165 } 166 167 static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink, 168 struct devlink_sb *devlink_sb, 169 enum devlink_command cmd, u32 portid, 170 u32 seq, int flags) 171 { 172 void *hdr; 173 174 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 175 if (!hdr) 176 return -EMSGSIZE; 177 178 if (devlink_nl_put_handle(msg, devlink)) 179 goto nla_put_failure; 180 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 181 goto nla_put_failure; 182 if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size)) 183 goto nla_put_failure; 184 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT, 185 devlink_sb->ingress_pools_count)) 186 goto nla_put_failure; 187 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT, 188 devlink_sb->egress_pools_count)) 189 goto nla_put_failure; 190 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT, 191 devlink_sb->ingress_tc_count)) 192 goto nla_put_failure; 193 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT, 194 devlink_sb->egress_tc_count)) 195 goto nla_put_failure; 196 197 genlmsg_end(msg, hdr); 198 return 0; 199 200 nla_put_failure: 201 genlmsg_cancel(msg, hdr); 202 return -EMSGSIZE; 203 } 204 205 int devlink_nl_sb_get_doit(struct sk_buff *skb, struct genl_info *info) 206 { 207 struct devlink *devlink = info->user_ptr[0]; 208 struct devlink_sb *devlink_sb; 209 struct sk_buff *msg; 210 int err; 211 212 devlink_sb = devlink_sb_get_from_info(devlink, info); 213 if (IS_ERR(devlink_sb)) 214 return PTR_ERR(devlink_sb); 215 216 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 217 if (!msg) 218 return -ENOMEM; 219 220 err = devlink_nl_sb_fill(msg, devlink, devlink_sb, 221 DEVLINK_CMD_SB_NEW, 222 info->snd_portid, info->snd_seq, 0); 223 if (err) { 224 nlmsg_free(msg); 225 return err; 226 } 227 228 return genlmsg_reply(msg, info); 229 } 230 231 static int 232 devlink_nl_sb_get_dump_one(struct sk_buff *msg, struct devlink *devlink, 233 struct netlink_callback *cb, int flags) 234 { 235 struct devlink_nl_dump_state *state = devlink_dump_state(cb); 236 struct devlink_sb *devlink_sb; 237 int idx = 0; 238 int err = 0; 239 240 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 241 if (idx < state->idx) { 242 idx++; 243 continue; 244 } 245 err = devlink_nl_sb_fill(msg, devlink, devlink_sb, 246 DEVLINK_CMD_SB_NEW, 247 NETLINK_CB(cb->skb).portid, 248 cb->nlh->nlmsg_seq, flags); 249 if (err) { 250 state->idx = idx; 251 break; 252 } 253 idx++; 254 } 255 256 return err; 257 } 258 259 int devlink_nl_sb_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) 260 { 261 return devlink_nl_dumpit(skb, cb, devlink_nl_sb_get_dump_one); 262 } 263 264 static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink, 265 struct devlink_sb *devlink_sb, 266 u16 pool_index, enum devlink_command cmd, 267 u32 portid, u32 seq, int flags) 268 { 269 struct devlink_sb_pool_info pool_info; 270 void *hdr; 271 int err; 272 273 err = devlink->ops->sb_pool_get(devlink, devlink_sb->index, 274 pool_index, &pool_info); 275 if (err) 276 return err; 277 278 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 279 if (!hdr) 280 return -EMSGSIZE; 281 282 if (devlink_nl_put_handle(msg, devlink)) 283 goto nla_put_failure; 284 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 285 goto nla_put_failure; 286 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 287 goto nla_put_failure; 288 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type)) 289 goto nla_put_failure; 290 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size)) 291 goto nla_put_failure; 292 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE, 293 pool_info.threshold_type)) 294 goto nla_put_failure; 295 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_CELL_SIZE, 296 pool_info.cell_size)) 297 goto nla_put_failure; 298 299 genlmsg_end(msg, hdr); 300 return 0; 301 302 nla_put_failure: 303 genlmsg_cancel(msg, hdr); 304 return -EMSGSIZE; 305 } 306 307 int devlink_nl_sb_pool_get_doit(struct sk_buff *skb, struct genl_info *info) 308 { 309 struct devlink *devlink = info->user_ptr[0]; 310 struct devlink_sb *devlink_sb; 311 struct sk_buff *msg; 312 u16 pool_index; 313 int err; 314 315 devlink_sb = devlink_sb_get_from_info(devlink, info); 316 if (IS_ERR(devlink_sb)) 317 return PTR_ERR(devlink_sb); 318 319 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 320 &pool_index); 321 if (err) 322 return err; 323 324 if (!devlink->ops->sb_pool_get) 325 return -EOPNOTSUPP; 326 327 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 328 if (!msg) 329 return -ENOMEM; 330 331 err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index, 332 DEVLINK_CMD_SB_POOL_NEW, 333 info->snd_portid, info->snd_seq, 0); 334 if (err) { 335 nlmsg_free(msg); 336 return err; 337 } 338 339 return genlmsg_reply(msg, info); 340 } 341 342 static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, 343 struct devlink *devlink, 344 struct devlink_sb *devlink_sb, 345 u32 portid, u32 seq, int flags) 346 { 347 u16 pool_count = devlink_sb_pool_count(devlink_sb); 348 u16 pool_index; 349 int err; 350 351 for (pool_index = 0; pool_index < pool_count; pool_index++) { 352 if (*p_idx < start) { 353 (*p_idx)++; 354 continue; 355 } 356 err = devlink_nl_sb_pool_fill(msg, devlink, 357 devlink_sb, 358 pool_index, 359 DEVLINK_CMD_SB_POOL_NEW, 360 portid, seq, flags); 361 if (err) 362 return err; 363 (*p_idx)++; 364 } 365 return 0; 366 } 367 368 static int 369 devlink_nl_sb_pool_get_dump_one(struct sk_buff *msg, struct devlink *devlink, 370 struct netlink_callback *cb, int flags) 371 { 372 struct devlink_nl_dump_state *state = devlink_dump_state(cb); 373 struct devlink_sb *devlink_sb; 374 int err = 0; 375 int idx = 0; 376 377 if (!devlink->ops->sb_pool_get) 378 return 0; 379 380 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 381 err = __sb_pool_get_dumpit(msg, state->idx, &idx, 382 devlink, devlink_sb, 383 NETLINK_CB(cb->skb).portid, 384 cb->nlh->nlmsg_seq, flags); 385 if (err == -EOPNOTSUPP) { 386 err = 0; 387 } else if (err) { 388 state->idx = idx; 389 break; 390 } 391 } 392 393 return err; 394 } 395 396 int devlink_nl_sb_pool_get_dumpit(struct sk_buff *skb, 397 struct netlink_callback *cb) 398 { 399 return devlink_nl_dumpit(skb, cb, devlink_nl_sb_pool_get_dump_one); 400 } 401 402 static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index, 403 u16 pool_index, u32 size, 404 enum devlink_sb_threshold_type threshold_type, 405 struct netlink_ext_ack *extack) 406 407 { 408 const struct devlink_ops *ops = devlink->ops; 409 410 if (ops->sb_pool_set) 411 return ops->sb_pool_set(devlink, sb_index, pool_index, 412 size, threshold_type, extack); 413 return -EOPNOTSUPP; 414 } 415 416 int devlink_nl_sb_pool_set_doit(struct sk_buff *skb, struct genl_info *info) 417 { 418 struct devlink *devlink = info->user_ptr[0]; 419 enum devlink_sb_threshold_type threshold_type; 420 struct devlink_sb *devlink_sb; 421 u16 pool_index; 422 u32 size; 423 int err; 424 425 devlink_sb = devlink_sb_get_from_info(devlink, info); 426 if (IS_ERR(devlink_sb)) 427 return PTR_ERR(devlink_sb); 428 429 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 430 &pool_index); 431 if (err) 432 return err; 433 434 err = devlink_sb_th_type_get_from_info(info, &threshold_type); 435 if (err) 436 return err; 437 438 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_POOL_SIZE)) 439 return -EINVAL; 440 441 size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]); 442 return devlink_sb_pool_set(devlink, devlink_sb->index, 443 pool_index, size, threshold_type, 444 info->extack); 445 } 446 447 static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg, 448 struct devlink *devlink, 449 struct devlink_port *devlink_port, 450 struct devlink_sb *devlink_sb, 451 u16 pool_index, 452 enum devlink_command cmd, 453 u32 portid, u32 seq, int flags) 454 { 455 const struct devlink_ops *ops = devlink->ops; 456 u32 threshold; 457 void *hdr; 458 int err; 459 460 err = ops->sb_port_pool_get(devlink_port, devlink_sb->index, 461 pool_index, &threshold); 462 if (err) 463 return err; 464 465 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 466 if (!hdr) 467 return -EMSGSIZE; 468 469 if (devlink_nl_put_handle(msg, devlink)) 470 goto nla_put_failure; 471 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 472 goto nla_put_failure; 473 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 474 goto nla_put_failure; 475 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 476 goto nla_put_failure; 477 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 478 goto nla_put_failure; 479 480 if (ops->sb_occ_port_pool_get) { 481 u32 cur; 482 u32 max; 483 484 err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index, 485 pool_index, &cur, &max); 486 if (err && err != -EOPNOTSUPP) 487 goto sb_occ_get_failure; 488 if (!err) { 489 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) 490 goto nla_put_failure; 491 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) 492 goto nla_put_failure; 493 } 494 } 495 496 genlmsg_end(msg, hdr); 497 return 0; 498 499 nla_put_failure: 500 err = -EMSGSIZE; 501 sb_occ_get_failure: 502 genlmsg_cancel(msg, hdr); 503 return err; 504 } 505 506 int devlink_nl_sb_port_pool_get_doit(struct sk_buff *skb, 507 struct genl_info *info) 508 { 509 struct devlink_port *devlink_port = info->user_ptr[1]; 510 struct devlink *devlink = devlink_port->devlink; 511 struct devlink_sb *devlink_sb; 512 struct sk_buff *msg; 513 u16 pool_index; 514 int err; 515 516 devlink_sb = devlink_sb_get_from_info(devlink, info); 517 if (IS_ERR(devlink_sb)) 518 return PTR_ERR(devlink_sb); 519 520 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 521 &pool_index); 522 if (err) 523 return err; 524 525 if (!devlink->ops->sb_port_pool_get) 526 return -EOPNOTSUPP; 527 528 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 529 if (!msg) 530 return -ENOMEM; 531 532 err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port, 533 devlink_sb, pool_index, 534 DEVLINK_CMD_SB_PORT_POOL_NEW, 535 info->snd_portid, info->snd_seq, 0); 536 if (err) { 537 nlmsg_free(msg); 538 return err; 539 } 540 541 return genlmsg_reply(msg, info); 542 } 543 544 static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, 545 struct devlink *devlink, 546 struct devlink_sb *devlink_sb, 547 u32 portid, u32 seq, int flags) 548 { 549 struct devlink_port *devlink_port; 550 u16 pool_count = devlink_sb_pool_count(devlink_sb); 551 unsigned long port_index; 552 u16 pool_index; 553 int err; 554 555 xa_for_each(&devlink->ports, port_index, devlink_port) { 556 for (pool_index = 0; pool_index < pool_count; pool_index++) { 557 if (*p_idx < start) { 558 (*p_idx)++; 559 continue; 560 } 561 err = devlink_nl_sb_port_pool_fill(msg, devlink, 562 devlink_port, 563 devlink_sb, 564 pool_index, 565 DEVLINK_CMD_SB_PORT_POOL_NEW, 566 portid, seq, flags); 567 if (err) 568 return err; 569 (*p_idx)++; 570 } 571 } 572 return 0; 573 } 574 575 static int 576 devlink_nl_sb_port_pool_get_dump_one(struct sk_buff *msg, 577 struct devlink *devlink, 578 struct netlink_callback *cb, int flags) 579 { 580 struct devlink_nl_dump_state *state = devlink_dump_state(cb); 581 struct devlink_sb *devlink_sb; 582 int idx = 0; 583 int err = 0; 584 585 if (!devlink->ops->sb_port_pool_get) 586 return 0; 587 588 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 589 err = __sb_port_pool_get_dumpit(msg, state->idx, &idx, 590 devlink, devlink_sb, 591 NETLINK_CB(cb->skb).portid, 592 cb->nlh->nlmsg_seq, flags); 593 if (err == -EOPNOTSUPP) { 594 err = 0; 595 } else if (err) { 596 state->idx = idx; 597 break; 598 } 599 } 600 601 return err; 602 } 603 604 int devlink_nl_sb_port_pool_get_dumpit(struct sk_buff *skb, 605 struct netlink_callback *cb) 606 { 607 return devlink_nl_dumpit(skb, cb, devlink_nl_sb_port_pool_get_dump_one); 608 } 609 610 static int devlink_sb_port_pool_set(struct devlink_port *devlink_port, 611 unsigned int sb_index, u16 pool_index, 612 u32 threshold, 613 struct netlink_ext_ack *extack) 614 615 { 616 const struct devlink_ops *ops = devlink_port->devlink->ops; 617 618 if (ops->sb_port_pool_set) 619 return ops->sb_port_pool_set(devlink_port, sb_index, 620 pool_index, threshold, extack); 621 return -EOPNOTSUPP; 622 } 623 624 int devlink_nl_sb_port_pool_set_doit(struct sk_buff *skb, 625 struct genl_info *info) 626 { 627 struct devlink_port *devlink_port = info->user_ptr[1]; 628 struct devlink *devlink = info->user_ptr[0]; 629 struct devlink_sb *devlink_sb; 630 u16 pool_index; 631 u32 threshold; 632 int err; 633 634 devlink_sb = devlink_sb_get_from_info(devlink, info); 635 if (IS_ERR(devlink_sb)) 636 return PTR_ERR(devlink_sb); 637 638 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 639 &pool_index); 640 if (err) 641 return err; 642 643 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_THRESHOLD)) 644 return -EINVAL; 645 646 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); 647 return devlink_sb_port_pool_set(devlink_port, devlink_sb->index, 648 pool_index, threshold, info->extack); 649 } 650 651 static int 652 devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink, 653 struct devlink_port *devlink_port, 654 struct devlink_sb *devlink_sb, u16 tc_index, 655 enum devlink_sb_pool_type pool_type, 656 enum devlink_command cmd, 657 u32 portid, u32 seq, int flags) 658 { 659 const struct devlink_ops *ops = devlink->ops; 660 u16 pool_index; 661 u32 threshold; 662 void *hdr; 663 int err; 664 665 err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index, 666 tc_index, pool_type, 667 &pool_index, &threshold); 668 if (err) 669 return err; 670 671 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 672 if (!hdr) 673 return -EMSGSIZE; 674 675 if (devlink_nl_put_handle(msg, devlink)) 676 goto nla_put_failure; 677 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 678 goto nla_put_failure; 679 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 680 goto nla_put_failure; 681 if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index)) 682 goto nla_put_failure; 683 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type)) 684 goto nla_put_failure; 685 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 686 goto nla_put_failure; 687 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 688 goto nla_put_failure; 689 690 if (ops->sb_occ_tc_port_bind_get) { 691 u32 cur; 692 u32 max; 693 694 err = ops->sb_occ_tc_port_bind_get(devlink_port, 695 devlink_sb->index, 696 tc_index, pool_type, 697 &cur, &max); 698 if (err && err != -EOPNOTSUPP) 699 return err; 700 if (!err) { 701 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) 702 goto nla_put_failure; 703 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) 704 goto nla_put_failure; 705 } 706 } 707 708 genlmsg_end(msg, hdr); 709 return 0; 710 711 nla_put_failure: 712 genlmsg_cancel(msg, hdr); 713 return -EMSGSIZE; 714 } 715 716 int devlink_nl_sb_tc_pool_bind_get_doit(struct sk_buff *skb, 717 struct genl_info *info) 718 { 719 struct devlink_port *devlink_port = info->user_ptr[1]; 720 struct devlink *devlink = devlink_port->devlink; 721 struct devlink_sb *devlink_sb; 722 struct sk_buff *msg; 723 enum devlink_sb_pool_type pool_type; 724 u16 tc_index; 725 int err; 726 727 devlink_sb = devlink_sb_get_from_info(devlink, info); 728 if (IS_ERR(devlink_sb)) 729 return PTR_ERR(devlink_sb); 730 731 err = devlink_sb_pool_type_get_from_info(info, &pool_type); 732 if (err) 733 return err; 734 735 err = devlink_sb_tc_index_get_from_info(devlink_sb, info, 736 pool_type, &tc_index); 737 if (err) 738 return err; 739 740 if (!devlink->ops->sb_tc_pool_bind_get) 741 return -EOPNOTSUPP; 742 743 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 744 if (!msg) 745 return -ENOMEM; 746 747 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port, 748 devlink_sb, tc_index, pool_type, 749 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 750 info->snd_portid, 751 info->snd_seq, 0); 752 if (err) { 753 nlmsg_free(msg); 754 return err; 755 } 756 757 return genlmsg_reply(msg, info); 758 } 759 760 static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg, 761 int start, int *p_idx, 762 struct devlink *devlink, 763 struct devlink_sb *devlink_sb, 764 u32 portid, u32 seq, int flags) 765 { 766 struct devlink_port *devlink_port; 767 unsigned long port_index; 768 u16 tc_index; 769 int err; 770 771 xa_for_each(&devlink->ports, port_index, devlink_port) { 772 for (tc_index = 0; 773 tc_index < devlink_sb->ingress_tc_count; tc_index++) { 774 if (*p_idx < start) { 775 (*p_idx)++; 776 continue; 777 } 778 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, 779 devlink_port, 780 devlink_sb, 781 tc_index, 782 DEVLINK_SB_POOL_TYPE_INGRESS, 783 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 784 portid, seq, 785 flags); 786 if (err) 787 return err; 788 (*p_idx)++; 789 } 790 for (tc_index = 0; 791 tc_index < devlink_sb->egress_tc_count; tc_index++) { 792 if (*p_idx < start) { 793 (*p_idx)++; 794 continue; 795 } 796 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, 797 devlink_port, 798 devlink_sb, 799 tc_index, 800 DEVLINK_SB_POOL_TYPE_EGRESS, 801 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 802 portid, seq, 803 flags); 804 if (err) 805 return err; 806 (*p_idx)++; 807 } 808 } 809 return 0; 810 } 811 812 static int devlink_nl_sb_tc_pool_bind_get_dump_one(struct sk_buff *msg, 813 struct devlink *devlink, 814 struct netlink_callback *cb, 815 int flags) 816 { 817 struct devlink_nl_dump_state *state = devlink_dump_state(cb); 818 struct devlink_sb *devlink_sb; 819 int idx = 0; 820 int err = 0; 821 822 if (!devlink->ops->sb_tc_pool_bind_get) 823 return 0; 824 825 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 826 err = __sb_tc_pool_bind_get_dumpit(msg, state->idx, &idx, 827 devlink, devlink_sb, 828 NETLINK_CB(cb->skb).portid, 829 cb->nlh->nlmsg_seq, flags); 830 if (err == -EOPNOTSUPP) { 831 err = 0; 832 } else if (err) { 833 state->idx = idx; 834 break; 835 } 836 } 837 838 return err; 839 } 840 841 int devlink_nl_sb_tc_pool_bind_get_dumpit(struct sk_buff *skb, 842 struct netlink_callback *cb) 843 { 844 return devlink_nl_dumpit(skb, cb, 845 devlink_nl_sb_tc_pool_bind_get_dump_one); 846 } 847 848 static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port, 849 unsigned int sb_index, u16 tc_index, 850 enum devlink_sb_pool_type pool_type, 851 u16 pool_index, u32 threshold, 852 struct netlink_ext_ack *extack) 853 854 { 855 const struct devlink_ops *ops = devlink_port->devlink->ops; 856 857 if (ops->sb_tc_pool_bind_set) 858 return ops->sb_tc_pool_bind_set(devlink_port, sb_index, 859 tc_index, pool_type, 860 pool_index, threshold, extack); 861 return -EOPNOTSUPP; 862 } 863 864 int devlink_nl_sb_tc_pool_bind_set_doit(struct sk_buff *skb, 865 struct genl_info *info) 866 { 867 struct devlink_port *devlink_port = info->user_ptr[1]; 868 struct devlink *devlink = info->user_ptr[0]; 869 enum devlink_sb_pool_type pool_type; 870 struct devlink_sb *devlink_sb; 871 u16 tc_index; 872 u16 pool_index; 873 u32 threshold; 874 int err; 875 876 devlink_sb = devlink_sb_get_from_info(devlink, info); 877 if (IS_ERR(devlink_sb)) 878 return PTR_ERR(devlink_sb); 879 880 err = devlink_sb_pool_type_get_from_info(info, &pool_type); 881 if (err) 882 return err; 883 884 err = devlink_sb_tc_index_get_from_info(devlink_sb, info, 885 pool_type, &tc_index); 886 if (err) 887 return err; 888 889 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 890 &pool_index); 891 if (err) 892 return err; 893 894 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_THRESHOLD)) 895 return -EINVAL; 896 897 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); 898 return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index, 899 tc_index, pool_type, 900 pool_index, threshold, info->extack); 901 } 902 903 int devlink_nl_sb_occ_snapshot_doit(struct sk_buff *skb, struct genl_info *info) 904 { 905 struct devlink *devlink = info->user_ptr[0]; 906 const struct devlink_ops *ops = devlink->ops; 907 struct devlink_sb *devlink_sb; 908 909 devlink_sb = devlink_sb_get_from_info(devlink, info); 910 if (IS_ERR(devlink_sb)) 911 return PTR_ERR(devlink_sb); 912 913 if (ops->sb_occ_snapshot) 914 return ops->sb_occ_snapshot(devlink, devlink_sb->index); 915 return -EOPNOTSUPP; 916 } 917 918 int devlink_nl_sb_occ_max_clear_doit(struct sk_buff *skb, 919 struct genl_info *info) 920 { 921 struct devlink *devlink = info->user_ptr[0]; 922 const struct devlink_ops *ops = devlink->ops; 923 struct devlink_sb *devlink_sb; 924 925 devlink_sb = devlink_sb_get_from_info(devlink, info); 926 if (IS_ERR(devlink_sb)) 927 return PTR_ERR(devlink_sb); 928 929 if (ops->sb_occ_max_clear) 930 return ops->sb_occ_max_clear(devlink, devlink_sb->index); 931 return -EOPNOTSUPP; 932 } 933 934 int devl_sb_register(struct devlink *devlink, unsigned int sb_index, 935 u32 size, u16 ingress_pools_count, 936 u16 egress_pools_count, u16 ingress_tc_count, 937 u16 egress_tc_count) 938 { 939 struct devlink_sb *devlink_sb; 940 941 lockdep_assert_held(&devlink->lock); 942 943 if (devlink_sb_index_exists(devlink, sb_index)) 944 return -EEXIST; 945 946 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL); 947 if (!devlink_sb) 948 return -ENOMEM; 949 devlink_sb->index = sb_index; 950 devlink_sb->size = size; 951 devlink_sb->ingress_pools_count = ingress_pools_count; 952 devlink_sb->egress_pools_count = egress_pools_count; 953 devlink_sb->ingress_tc_count = ingress_tc_count; 954 devlink_sb->egress_tc_count = egress_tc_count; 955 list_add_tail(&devlink_sb->list, &devlink->sb_list); 956 return 0; 957 } 958 EXPORT_SYMBOL_GPL(devl_sb_register); 959 960 int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, 961 u32 size, u16 ingress_pools_count, 962 u16 egress_pools_count, u16 ingress_tc_count, 963 u16 egress_tc_count) 964 { 965 int err; 966 967 devl_lock(devlink); 968 err = devl_sb_register(devlink, sb_index, size, ingress_pools_count, 969 egress_pools_count, ingress_tc_count, 970 egress_tc_count); 971 devl_unlock(devlink); 972 return err; 973 } 974 EXPORT_SYMBOL_GPL(devlink_sb_register); 975 976 void devl_sb_unregister(struct devlink *devlink, unsigned int sb_index) 977 { 978 struct devlink_sb *devlink_sb; 979 980 lockdep_assert_held(&devlink->lock); 981 982 devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 983 WARN_ON(!devlink_sb); 984 list_del(&devlink_sb->list); 985 kfree(devlink_sb); 986 } 987 EXPORT_SYMBOL_GPL(devl_sb_unregister); 988 989 void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index) 990 { 991 devl_lock(devlink); 992 devl_sb_unregister(devlink, sb_index); 993 devl_unlock(devlink); 994 } 995 EXPORT_SYMBOL_GPL(devlink_sb_unregister); 996
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.