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 <trace/events/devlink.h> 8 9 #include "devl_internal.h" 10 11 struct devlink_stats { 12 u64_stats_t rx_bytes; 13 u64_stats_t rx_packets; 14 struct u64_stats_sync syncp; 15 }; 16 17 /** 18 * struct devlink_trap_policer_item - Packet trap policer attributes. 19 * @policer: Immutable packet trap policer attributes. 20 * @rate: Rate in packets / sec. 21 * @burst: Burst size in packets. 22 * @list: trap_policer_list member. 23 * 24 * Describes packet trap policer attributes. Created by devlink during trap 25 * policer registration. 26 */ 27 struct devlink_trap_policer_item { 28 const struct devlink_trap_policer *policer; 29 u64 rate; 30 u64 burst; 31 struct list_head list; 32 }; 33 34 /** 35 * struct devlink_trap_group_item - Packet trap group attributes. 36 * @group: Immutable packet trap group attributes. 37 * @policer_item: Associated policer item. Can be NULL. 38 * @list: trap_group_list member. 39 * @stats: Trap group statistics. 40 * 41 * Describes packet trap group attributes. Created by devlink during trap 42 * group registration. 43 */ 44 struct devlink_trap_group_item { 45 const struct devlink_trap_group *group; 46 struct devlink_trap_policer_item *policer_item; 47 struct list_head list; 48 struct devlink_stats __percpu *stats; 49 }; 50 51 /** 52 * struct devlink_trap_item - Packet trap attributes. 53 * @trap: Immutable packet trap attributes. 54 * @group_item: Associated group item. 55 * @list: trap_list member. 56 * @action: Trap action. 57 * @stats: Trap statistics. 58 * @priv: Driver private information. 59 * 60 * Describes both mutable and immutable packet trap attributes. Created by 61 * devlink during trap registration and used for all trap related operations. 62 */ 63 struct devlink_trap_item { 64 const struct devlink_trap *trap; 65 struct devlink_trap_group_item *group_item; 66 struct list_head list; 67 enum devlink_trap_action action; 68 struct devlink_stats __percpu *stats; 69 void *priv; 70 }; 71 72 static struct devlink_trap_policer_item * 73 devlink_trap_policer_item_lookup(struct devlink *devlink, u32 id) 74 { 75 struct devlink_trap_policer_item *policer_item; 76 77 list_for_each_entry(policer_item, &devlink->trap_policer_list, list) { 78 if (policer_item->policer->id == id) 79 return policer_item; 80 } 81 82 return NULL; 83 } 84 85 static struct devlink_trap_item * 86 devlink_trap_item_lookup(struct devlink *devlink, const char *name) 87 { 88 struct devlink_trap_item *trap_item; 89 90 list_for_each_entry(trap_item, &devlink->trap_list, list) { 91 if (!strcmp(trap_item->trap->name, name)) 92 return trap_item; 93 } 94 95 return NULL; 96 } 97 98 static struct devlink_trap_item * 99 devlink_trap_item_get_from_info(struct devlink *devlink, 100 struct genl_info *info) 101 { 102 struct nlattr *attr; 103 104 if (!info->attrs[DEVLINK_ATTR_TRAP_NAME]) 105 return NULL; 106 attr = info->attrs[DEVLINK_ATTR_TRAP_NAME]; 107 108 return devlink_trap_item_lookup(devlink, nla_data(attr)); 109 } 110 111 static int 112 devlink_trap_action_get_from_info(struct genl_info *info, 113 enum devlink_trap_action *p_trap_action) 114 { 115 u8 val; 116 117 val = nla_get_u8(info->attrs[DEVLINK_ATTR_TRAP_ACTION]); 118 switch (val) { 119 case DEVLINK_TRAP_ACTION_DROP: 120 case DEVLINK_TRAP_ACTION_TRAP: 121 case DEVLINK_TRAP_ACTION_MIRROR: 122 *p_trap_action = val; 123 break; 124 default: 125 return -EINVAL; 126 } 127 128 return 0; 129 } 130 131 static int devlink_trap_metadata_put(struct sk_buff *msg, 132 const struct devlink_trap *trap) 133 { 134 struct nlattr *attr; 135 136 attr = nla_nest_start(msg, DEVLINK_ATTR_TRAP_METADATA); 137 if (!attr) 138 return -EMSGSIZE; 139 140 if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT) && 141 nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_IN_PORT)) 142 goto nla_put_failure; 143 if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE) && 144 nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_FA_COOKIE)) 145 goto nla_put_failure; 146 147 nla_nest_end(msg, attr); 148 149 return 0; 150 151 nla_put_failure: 152 nla_nest_cancel(msg, attr); 153 return -EMSGSIZE; 154 } 155 156 static void devlink_trap_stats_read(struct devlink_stats __percpu *trap_stats, 157 struct devlink_stats *stats) 158 { 159 int i; 160 161 memset(stats, 0, sizeof(*stats)); 162 for_each_possible_cpu(i) { 163 struct devlink_stats *cpu_stats; 164 u64 rx_packets, rx_bytes; 165 unsigned int start; 166 167 cpu_stats = per_cpu_ptr(trap_stats, i); 168 do { 169 start = u64_stats_fetch_begin(&cpu_stats->syncp); 170 rx_packets = u64_stats_read(&cpu_stats->rx_packets); 171 rx_bytes = u64_stats_read(&cpu_stats->rx_bytes); 172 } while (u64_stats_fetch_retry(&cpu_stats->syncp, start)); 173 174 u64_stats_add(&stats->rx_packets, rx_packets); 175 u64_stats_add(&stats->rx_bytes, rx_bytes); 176 } 177 } 178 179 static int 180 devlink_trap_group_stats_put(struct sk_buff *msg, 181 struct devlink_stats __percpu *trap_stats) 182 { 183 struct devlink_stats stats; 184 struct nlattr *attr; 185 186 devlink_trap_stats_read(trap_stats, &stats); 187 188 attr = nla_nest_start(msg, DEVLINK_ATTR_STATS); 189 if (!attr) 190 return -EMSGSIZE; 191 192 if (devlink_nl_put_u64(msg, DEVLINK_ATTR_STATS_RX_PACKETS, 193 u64_stats_read(&stats.rx_packets))) 194 goto nla_put_failure; 195 196 if (devlink_nl_put_u64(msg, DEVLINK_ATTR_STATS_RX_BYTES, 197 u64_stats_read(&stats.rx_bytes))) 198 goto nla_put_failure; 199 200 nla_nest_end(msg, attr); 201 202 return 0; 203 204 nla_put_failure: 205 nla_nest_cancel(msg, attr); 206 return -EMSGSIZE; 207 } 208 209 static int devlink_trap_stats_put(struct sk_buff *msg, struct devlink *devlink, 210 const struct devlink_trap_item *trap_item) 211 { 212 struct devlink_stats stats; 213 struct nlattr *attr; 214 u64 drops = 0; 215 int err; 216 217 if (devlink->ops->trap_drop_counter_get) { 218 err = devlink->ops->trap_drop_counter_get(devlink, 219 trap_item->trap, 220 &drops); 221 if (err) 222 return err; 223 } 224 225 devlink_trap_stats_read(trap_item->stats, &stats); 226 227 attr = nla_nest_start(msg, DEVLINK_ATTR_STATS); 228 if (!attr) 229 return -EMSGSIZE; 230 231 if (devlink->ops->trap_drop_counter_get && 232 devlink_nl_put_u64(msg, DEVLINK_ATTR_STATS_RX_DROPPED, drops)) 233 goto nla_put_failure; 234 235 if (devlink_nl_put_u64(msg, DEVLINK_ATTR_STATS_RX_PACKETS, 236 u64_stats_read(&stats.rx_packets))) 237 goto nla_put_failure; 238 239 if (devlink_nl_put_u64(msg, DEVLINK_ATTR_STATS_RX_BYTES, 240 u64_stats_read(&stats.rx_bytes))) 241 goto nla_put_failure; 242 243 nla_nest_end(msg, attr); 244 245 return 0; 246 247 nla_put_failure: 248 nla_nest_cancel(msg, attr); 249 return -EMSGSIZE; 250 } 251 252 static int devlink_nl_trap_fill(struct sk_buff *msg, struct devlink *devlink, 253 const struct devlink_trap_item *trap_item, 254 enum devlink_command cmd, u32 portid, u32 seq, 255 int flags) 256 { 257 struct devlink_trap_group_item *group_item = trap_item->group_item; 258 void *hdr; 259 int err; 260 261 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 262 if (!hdr) 263 return -EMSGSIZE; 264 265 if (devlink_nl_put_handle(msg, devlink)) 266 goto nla_put_failure; 267 268 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME, 269 group_item->group->name)) 270 goto nla_put_failure; 271 272 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_NAME, trap_item->trap->name)) 273 goto nla_put_failure; 274 275 if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_TYPE, trap_item->trap->type)) 276 goto nla_put_failure; 277 278 if (trap_item->trap->generic && 279 nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC)) 280 goto nla_put_failure; 281 282 if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_ACTION, trap_item->action)) 283 goto nla_put_failure; 284 285 err = devlink_trap_metadata_put(msg, trap_item->trap); 286 if (err) 287 goto nla_put_failure; 288 289 err = devlink_trap_stats_put(msg, devlink, trap_item); 290 if (err) 291 goto nla_put_failure; 292 293 genlmsg_end(msg, hdr); 294 295 return 0; 296 297 nla_put_failure: 298 genlmsg_cancel(msg, hdr); 299 return -EMSGSIZE; 300 } 301 302 int devlink_nl_trap_get_doit(struct sk_buff *skb, struct genl_info *info) 303 { 304 struct netlink_ext_ack *extack = info->extack; 305 struct devlink *devlink = info->user_ptr[0]; 306 struct devlink_trap_item *trap_item; 307 struct sk_buff *msg; 308 int err; 309 310 if (list_empty(&devlink->trap_list)) 311 return -EOPNOTSUPP; 312 313 trap_item = devlink_trap_item_get_from_info(devlink, info); 314 if (!trap_item) { 315 NL_SET_ERR_MSG(extack, "Device did not register this trap"); 316 return -ENOENT; 317 } 318 319 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 320 if (!msg) 321 return -ENOMEM; 322 323 err = devlink_nl_trap_fill(msg, devlink, trap_item, 324 DEVLINK_CMD_TRAP_NEW, info->snd_portid, 325 info->snd_seq, 0); 326 if (err) 327 goto err_trap_fill; 328 329 return genlmsg_reply(msg, info); 330 331 err_trap_fill: 332 nlmsg_free(msg); 333 return err; 334 } 335 336 static int devlink_nl_trap_get_dump_one(struct sk_buff *msg, 337 struct devlink *devlink, 338 struct netlink_callback *cb, int flags) 339 { 340 struct devlink_nl_dump_state *state = devlink_dump_state(cb); 341 struct devlink_trap_item *trap_item; 342 int idx = 0; 343 int err = 0; 344 345 list_for_each_entry(trap_item, &devlink->trap_list, list) { 346 if (idx < state->idx) { 347 idx++; 348 continue; 349 } 350 err = devlink_nl_trap_fill(msg, devlink, trap_item, 351 DEVLINK_CMD_TRAP_NEW, 352 NETLINK_CB(cb->skb).portid, 353 cb->nlh->nlmsg_seq, flags); 354 if (err) { 355 state->idx = idx; 356 break; 357 } 358 idx++; 359 } 360 361 return err; 362 } 363 364 int devlink_nl_trap_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) 365 { 366 return devlink_nl_dumpit(skb, cb, devlink_nl_trap_get_dump_one); 367 } 368 369 static int __devlink_trap_action_set(struct devlink *devlink, 370 struct devlink_trap_item *trap_item, 371 enum devlink_trap_action trap_action, 372 struct netlink_ext_ack *extack) 373 { 374 int err; 375 376 if (trap_item->action != trap_action && 377 trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP) { 378 NL_SET_ERR_MSG(extack, "Cannot change action of non-drop traps. Skipping"); 379 return 0; 380 } 381 382 err = devlink->ops->trap_action_set(devlink, trap_item->trap, 383 trap_action, extack); 384 if (err) 385 return err; 386 387 trap_item->action = trap_action; 388 389 return 0; 390 } 391 392 static int devlink_trap_action_set(struct devlink *devlink, 393 struct devlink_trap_item *trap_item, 394 struct genl_info *info) 395 { 396 enum devlink_trap_action trap_action; 397 int err; 398 399 if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION]) 400 return 0; 401 402 err = devlink_trap_action_get_from_info(info, &trap_action); 403 if (err) { 404 NL_SET_ERR_MSG(info->extack, "Invalid trap action"); 405 return -EINVAL; 406 } 407 408 return __devlink_trap_action_set(devlink, trap_item, trap_action, 409 info->extack); 410 } 411 412 int devlink_nl_trap_set_doit(struct sk_buff *skb, struct genl_info *info) 413 { 414 struct netlink_ext_ack *extack = info->extack; 415 struct devlink *devlink = info->user_ptr[0]; 416 struct devlink_trap_item *trap_item; 417 418 if (list_empty(&devlink->trap_list)) 419 return -EOPNOTSUPP; 420 421 trap_item = devlink_trap_item_get_from_info(devlink, info); 422 if (!trap_item) { 423 NL_SET_ERR_MSG(extack, "Device did not register this trap"); 424 return -ENOENT; 425 } 426 427 return devlink_trap_action_set(devlink, trap_item, info); 428 } 429 430 static struct devlink_trap_group_item * 431 devlink_trap_group_item_lookup(struct devlink *devlink, const char *name) 432 { 433 struct devlink_trap_group_item *group_item; 434 435 list_for_each_entry(group_item, &devlink->trap_group_list, list) { 436 if (!strcmp(group_item->group->name, name)) 437 return group_item; 438 } 439 440 return NULL; 441 } 442 443 static struct devlink_trap_group_item * 444 devlink_trap_group_item_lookup_by_id(struct devlink *devlink, u16 id) 445 { 446 struct devlink_trap_group_item *group_item; 447 448 list_for_each_entry(group_item, &devlink->trap_group_list, list) { 449 if (group_item->group->id == id) 450 return group_item; 451 } 452 453 return NULL; 454 } 455 456 static struct devlink_trap_group_item * 457 devlink_trap_group_item_get_from_info(struct devlink *devlink, 458 struct genl_info *info) 459 { 460 char *name; 461 462 if (!info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME]) 463 return NULL; 464 name = nla_data(info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME]); 465 466 return devlink_trap_group_item_lookup(devlink, name); 467 } 468 469 static int 470 devlink_nl_trap_group_fill(struct sk_buff *msg, struct devlink *devlink, 471 const struct devlink_trap_group_item *group_item, 472 enum devlink_command cmd, u32 portid, u32 seq, 473 int flags) 474 { 475 void *hdr; 476 int err; 477 478 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 479 if (!hdr) 480 return -EMSGSIZE; 481 482 if (devlink_nl_put_handle(msg, devlink)) 483 goto nla_put_failure; 484 485 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME, 486 group_item->group->name)) 487 goto nla_put_failure; 488 489 if (group_item->group->generic && 490 nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC)) 491 goto nla_put_failure; 492 493 if (group_item->policer_item && 494 nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID, 495 group_item->policer_item->policer->id)) 496 goto nla_put_failure; 497 498 err = devlink_trap_group_stats_put(msg, group_item->stats); 499 if (err) 500 goto nla_put_failure; 501 502 genlmsg_end(msg, hdr); 503 504 return 0; 505 506 nla_put_failure: 507 genlmsg_cancel(msg, hdr); 508 return -EMSGSIZE; 509 } 510 511 int devlink_nl_trap_group_get_doit(struct sk_buff *skb, struct genl_info *info) 512 { 513 struct netlink_ext_ack *extack = info->extack; 514 struct devlink *devlink = info->user_ptr[0]; 515 struct devlink_trap_group_item *group_item; 516 struct sk_buff *msg; 517 int err; 518 519 if (list_empty(&devlink->trap_group_list)) 520 return -EOPNOTSUPP; 521 522 group_item = devlink_trap_group_item_get_from_info(devlink, info); 523 if (!group_item) { 524 NL_SET_ERR_MSG(extack, "Device did not register this trap group"); 525 return -ENOENT; 526 } 527 528 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 529 if (!msg) 530 return -ENOMEM; 531 532 err = devlink_nl_trap_group_fill(msg, devlink, group_item, 533 DEVLINK_CMD_TRAP_GROUP_NEW, 534 info->snd_portid, info->snd_seq, 0); 535 if (err) 536 goto err_trap_group_fill; 537 538 return genlmsg_reply(msg, info); 539 540 err_trap_group_fill: 541 nlmsg_free(msg); 542 return err; 543 } 544 545 static int devlink_nl_trap_group_get_dump_one(struct sk_buff *msg, 546 struct devlink *devlink, 547 struct netlink_callback *cb, 548 int flags) 549 { 550 struct devlink_nl_dump_state *state = devlink_dump_state(cb); 551 struct devlink_trap_group_item *group_item; 552 int idx = 0; 553 int err = 0; 554 555 list_for_each_entry(group_item, &devlink->trap_group_list, list) { 556 if (idx < state->idx) { 557 idx++; 558 continue; 559 } 560 err = devlink_nl_trap_group_fill(msg, devlink, group_item, 561 DEVLINK_CMD_TRAP_GROUP_NEW, 562 NETLINK_CB(cb->skb).portid, 563 cb->nlh->nlmsg_seq, flags); 564 if (err) { 565 state->idx = idx; 566 break; 567 } 568 idx++; 569 } 570 571 return err; 572 } 573 574 int devlink_nl_trap_group_get_dumpit(struct sk_buff *skb, 575 struct netlink_callback *cb) 576 { 577 return devlink_nl_dumpit(skb, cb, devlink_nl_trap_group_get_dump_one); 578 } 579 580 static int 581 __devlink_trap_group_action_set(struct devlink *devlink, 582 struct devlink_trap_group_item *group_item, 583 enum devlink_trap_action trap_action, 584 struct netlink_ext_ack *extack) 585 { 586 const char *group_name = group_item->group->name; 587 struct devlink_trap_item *trap_item; 588 int err; 589 590 if (devlink->ops->trap_group_action_set) { 591 err = devlink->ops->trap_group_action_set(devlink, group_item->group, 592 trap_action, extack); 593 if (err) 594 return err; 595 596 list_for_each_entry(trap_item, &devlink->trap_list, list) { 597 if (strcmp(trap_item->group_item->group->name, group_name)) 598 continue; 599 if (trap_item->action != trap_action && 600 trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP) 601 continue; 602 trap_item->action = trap_action; 603 } 604 605 return 0; 606 } 607 608 list_for_each_entry(trap_item, &devlink->trap_list, list) { 609 if (strcmp(trap_item->group_item->group->name, group_name)) 610 continue; 611 err = __devlink_trap_action_set(devlink, trap_item, 612 trap_action, extack); 613 if (err) 614 return err; 615 } 616 617 return 0; 618 } 619 620 static int 621 devlink_trap_group_action_set(struct devlink *devlink, 622 struct devlink_trap_group_item *group_item, 623 struct genl_info *info, bool *p_modified) 624 { 625 enum devlink_trap_action trap_action; 626 int err; 627 628 if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION]) 629 return 0; 630 631 err = devlink_trap_action_get_from_info(info, &trap_action); 632 if (err) { 633 NL_SET_ERR_MSG(info->extack, "Invalid trap action"); 634 return -EINVAL; 635 } 636 637 err = __devlink_trap_group_action_set(devlink, group_item, trap_action, 638 info->extack); 639 if (err) 640 return err; 641 642 *p_modified = true; 643 644 return 0; 645 } 646 647 static int devlink_trap_group_set(struct devlink *devlink, 648 struct devlink_trap_group_item *group_item, 649 struct genl_info *info) 650 { 651 struct devlink_trap_policer_item *policer_item; 652 struct netlink_ext_ack *extack = info->extack; 653 const struct devlink_trap_policer *policer; 654 struct nlattr **attrs = info->attrs; 655 u32 policer_id; 656 int err; 657 658 if (!attrs[DEVLINK_ATTR_TRAP_POLICER_ID]) 659 return 0; 660 661 if (!devlink->ops->trap_group_set) 662 return -EOPNOTSUPP; 663 664 policer_id = nla_get_u32(attrs[DEVLINK_ATTR_TRAP_POLICER_ID]); 665 policer_item = devlink_trap_policer_item_lookup(devlink, policer_id); 666 if (policer_id && !policer_item) { 667 NL_SET_ERR_MSG(extack, "Device did not register this trap policer"); 668 return -ENOENT; 669 } 670 policer = policer_item ? policer_item->policer : NULL; 671 672 err = devlink->ops->trap_group_set(devlink, group_item->group, policer, 673 extack); 674 if (err) 675 return err; 676 677 group_item->policer_item = policer_item; 678 679 return 0; 680 } 681 682 int devlink_nl_trap_group_set_doit(struct sk_buff *skb, struct genl_info *info) 683 { 684 struct netlink_ext_ack *extack = info->extack; 685 struct devlink *devlink = info->user_ptr[0]; 686 struct devlink_trap_group_item *group_item; 687 bool modified = false; 688 int err; 689 690 if (list_empty(&devlink->trap_group_list)) 691 return -EOPNOTSUPP; 692 693 group_item = devlink_trap_group_item_get_from_info(devlink, info); 694 if (!group_item) { 695 NL_SET_ERR_MSG(extack, "Device did not register this trap group"); 696 return -ENOENT; 697 } 698 699 err = devlink_trap_group_action_set(devlink, group_item, info, 700 &modified); 701 if (err) 702 return err; 703 704 err = devlink_trap_group_set(devlink, group_item, info); 705 if (err) 706 goto err_trap_group_set; 707 708 return 0; 709 710 err_trap_group_set: 711 if (modified) 712 NL_SET_ERR_MSG(extack, "Trap group set failed, but some changes were committed already"); 713 return err; 714 } 715 716 static struct devlink_trap_policer_item * 717 devlink_trap_policer_item_get_from_info(struct devlink *devlink, 718 struct genl_info *info) 719 { 720 u32 id; 721 722 if (!info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID]) 723 return NULL; 724 id = nla_get_u32(info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID]); 725 726 return devlink_trap_policer_item_lookup(devlink, id); 727 } 728 729 static int 730 devlink_trap_policer_stats_put(struct sk_buff *msg, struct devlink *devlink, 731 const struct devlink_trap_policer *policer) 732 { 733 struct nlattr *attr; 734 u64 drops; 735 int err; 736 737 if (!devlink->ops->trap_policer_counter_get) 738 return 0; 739 740 err = devlink->ops->trap_policer_counter_get(devlink, policer, &drops); 741 if (err) 742 return err; 743 744 attr = nla_nest_start(msg, DEVLINK_ATTR_STATS); 745 if (!attr) 746 return -EMSGSIZE; 747 748 if (devlink_nl_put_u64(msg, DEVLINK_ATTR_STATS_RX_DROPPED, drops)) 749 goto nla_put_failure; 750 751 nla_nest_end(msg, attr); 752 753 return 0; 754 755 nla_put_failure: 756 nla_nest_cancel(msg, attr); 757 return -EMSGSIZE; 758 } 759 760 static int 761 devlink_nl_trap_policer_fill(struct sk_buff *msg, struct devlink *devlink, 762 const struct devlink_trap_policer_item *policer_item, 763 enum devlink_command cmd, u32 portid, u32 seq, 764 int flags) 765 { 766 void *hdr; 767 int err; 768 769 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 770 if (!hdr) 771 return -EMSGSIZE; 772 773 if (devlink_nl_put_handle(msg, devlink)) 774 goto nla_put_failure; 775 776 if (nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID, 777 policer_item->policer->id)) 778 goto nla_put_failure; 779 780 if (devlink_nl_put_u64(msg, DEVLINK_ATTR_TRAP_POLICER_RATE, 781 policer_item->rate)) 782 goto nla_put_failure; 783 784 if (devlink_nl_put_u64(msg, DEVLINK_ATTR_TRAP_POLICER_BURST, 785 policer_item->burst)) 786 goto nla_put_failure; 787 788 err = devlink_trap_policer_stats_put(msg, devlink, 789 policer_item->policer); 790 if (err) 791 goto nla_put_failure; 792 793 genlmsg_end(msg, hdr); 794 795 return 0; 796 797 nla_put_failure: 798 genlmsg_cancel(msg, hdr); 799 return -EMSGSIZE; 800 } 801 802 int devlink_nl_trap_policer_get_doit(struct sk_buff *skb, 803 struct genl_info *info) 804 { 805 struct devlink_trap_policer_item *policer_item; 806 struct netlink_ext_ack *extack = info->extack; 807 struct devlink *devlink = info->user_ptr[0]; 808 struct sk_buff *msg; 809 int err; 810 811 if (list_empty(&devlink->trap_policer_list)) 812 return -EOPNOTSUPP; 813 814 policer_item = devlink_trap_policer_item_get_from_info(devlink, info); 815 if (!policer_item) { 816 NL_SET_ERR_MSG(extack, "Device did not register this trap policer"); 817 return -ENOENT; 818 } 819 820 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 821 if (!msg) 822 return -ENOMEM; 823 824 err = devlink_nl_trap_policer_fill(msg, devlink, policer_item, 825 DEVLINK_CMD_TRAP_POLICER_NEW, 826 info->snd_portid, info->snd_seq, 0); 827 if (err) 828 goto err_trap_policer_fill; 829 830 return genlmsg_reply(msg, info); 831 832 err_trap_policer_fill: 833 nlmsg_free(msg); 834 return err; 835 } 836 837 static int devlink_nl_trap_policer_get_dump_one(struct sk_buff *msg, 838 struct devlink *devlink, 839 struct netlink_callback *cb, 840 int flags) 841 { 842 struct devlink_nl_dump_state *state = devlink_dump_state(cb); 843 struct devlink_trap_policer_item *policer_item; 844 int idx = 0; 845 int err = 0; 846 847 list_for_each_entry(policer_item, &devlink->trap_policer_list, list) { 848 if (idx < state->idx) { 849 idx++; 850 continue; 851 } 852 err = devlink_nl_trap_policer_fill(msg, devlink, policer_item, 853 DEVLINK_CMD_TRAP_POLICER_NEW, 854 NETLINK_CB(cb->skb).portid, 855 cb->nlh->nlmsg_seq, flags); 856 if (err) { 857 state->idx = idx; 858 break; 859 } 860 idx++; 861 } 862 863 return err; 864 } 865 866 int devlink_nl_trap_policer_get_dumpit(struct sk_buff *skb, 867 struct netlink_callback *cb) 868 { 869 return devlink_nl_dumpit(skb, cb, devlink_nl_trap_policer_get_dump_one); 870 } 871 872 static int 873 devlink_trap_policer_set(struct devlink *devlink, 874 struct devlink_trap_policer_item *policer_item, 875 struct genl_info *info) 876 { 877 struct netlink_ext_ack *extack = info->extack; 878 struct nlattr **attrs = info->attrs; 879 u64 rate, burst; 880 int err; 881 882 rate = policer_item->rate; 883 burst = policer_item->burst; 884 885 if (attrs[DEVLINK_ATTR_TRAP_POLICER_RATE]) 886 rate = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_RATE]); 887 888 if (attrs[DEVLINK_ATTR_TRAP_POLICER_BURST]) 889 burst = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_BURST]); 890 891 if (rate < policer_item->policer->min_rate) { 892 NL_SET_ERR_MSG(extack, "Policer rate lower than limit"); 893 return -EINVAL; 894 } 895 896 if (rate > policer_item->policer->max_rate) { 897 NL_SET_ERR_MSG(extack, "Policer rate higher than limit"); 898 return -EINVAL; 899 } 900 901 if (burst < policer_item->policer->min_burst) { 902 NL_SET_ERR_MSG(extack, "Policer burst size lower than limit"); 903 return -EINVAL; 904 } 905 906 if (burst > policer_item->policer->max_burst) { 907 NL_SET_ERR_MSG(extack, "Policer burst size higher than limit"); 908 return -EINVAL; 909 } 910 911 err = devlink->ops->trap_policer_set(devlink, policer_item->policer, 912 rate, burst, info->extack); 913 if (err) 914 return err; 915 916 policer_item->rate = rate; 917 policer_item->burst = burst; 918 919 return 0; 920 } 921 922 int devlink_nl_trap_policer_set_doit(struct sk_buff *skb, 923 struct genl_info *info) 924 { 925 struct devlink_trap_policer_item *policer_item; 926 struct netlink_ext_ack *extack = info->extack; 927 struct devlink *devlink = info->user_ptr[0]; 928 929 if (list_empty(&devlink->trap_policer_list)) 930 return -EOPNOTSUPP; 931 932 if (!devlink->ops->trap_policer_set) 933 return -EOPNOTSUPP; 934 935 policer_item = devlink_trap_policer_item_get_from_info(devlink, info); 936 if (!policer_item) { 937 NL_SET_ERR_MSG(extack, "Device did not register this trap policer"); 938 return -ENOENT; 939 } 940 941 return devlink_trap_policer_set(devlink, policer_item, info); 942 } 943 944 #define DEVLINK_TRAP(_id, _type) \ 945 { \ 946 .type = DEVLINK_TRAP_TYPE_##_type, \ 947 .id = DEVLINK_TRAP_GENERIC_ID_##_id, \ 948 .name = DEVLINK_TRAP_GENERIC_NAME_##_id, \ 949 } 950 951 static const struct devlink_trap devlink_trap_generic[] = { 952 DEVLINK_TRAP(SMAC_MC, DROP), 953 DEVLINK_TRAP(VLAN_TAG_MISMATCH, DROP), 954 DEVLINK_TRAP(INGRESS_VLAN_FILTER, DROP), 955 DEVLINK_TRAP(INGRESS_STP_FILTER, DROP), 956 DEVLINK_TRAP(EMPTY_TX_LIST, DROP), 957 DEVLINK_TRAP(PORT_LOOPBACK_FILTER, DROP), 958 DEVLINK_TRAP(BLACKHOLE_ROUTE, DROP), 959 DEVLINK_TRAP(TTL_ERROR, EXCEPTION), 960 DEVLINK_TRAP(TAIL_DROP, DROP), 961 DEVLINK_TRAP(NON_IP_PACKET, DROP), 962 DEVLINK_TRAP(UC_DIP_MC_DMAC, DROP), 963 DEVLINK_TRAP(DIP_LB, DROP), 964 DEVLINK_TRAP(SIP_MC, DROP), 965 DEVLINK_TRAP(SIP_LB, DROP), 966 DEVLINK_TRAP(CORRUPTED_IP_HDR, DROP), 967 DEVLINK_TRAP(IPV4_SIP_BC, DROP), 968 DEVLINK_TRAP(IPV6_MC_DIP_RESERVED_SCOPE, DROP), 969 DEVLINK_TRAP(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE, DROP), 970 DEVLINK_TRAP(MTU_ERROR, EXCEPTION), 971 DEVLINK_TRAP(UNRESOLVED_NEIGH, EXCEPTION), 972 DEVLINK_TRAP(RPF, EXCEPTION), 973 DEVLINK_TRAP(REJECT_ROUTE, EXCEPTION), 974 DEVLINK_TRAP(IPV4_LPM_UNICAST_MISS, EXCEPTION), 975 DEVLINK_TRAP(IPV6_LPM_UNICAST_MISS, EXCEPTION), 976 DEVLINK_TRAP(NON_ROUTABLE, DROP), 977 DEVLINK_TRAP(DECAP_ERROR, EXCEPTION), 978 DEVLINK_TRAP(OVERLAY_SMAC_MC, DROP), 979 DEVLINK_TRAP(INGRESS_FLOW_ACTION_DROP, DROP), 980 DEVLINK_TRAP(EGRESS_FLOW_ACTION_DROP, DROP), 981 DEVLINK_TRAP(STP, CONTROL), 982 DEVLINK_TRAP(LACP, CONTROL), 983 DEVLINK_TRAP(LLDP, CONTROL), 984 DEVLINK_TRAP(IGMP_QUERY, CONTROL), 985 DEVLINK_TRAP(IGMP_V1_REPORT, CONTROL), 986 DEVLINK_TRAP(IGMP_V2_REPORT, CONTROL), 987 DEVLINK_TRAP(IGMP_V3_REPORT, CONTROL), 988 DEVLINK_TRAP(IGMP_V2_LEAVE, CONTROL), 989 DEVLINK_TRAP(MLD_QUERY, CONTROL), 990 DEVLINK_TRAP(MLD_V1_REPORT, CONTROL), 991 DEVLINK_TRAP(MLD_V2_REPORT, CONTROL), 992 DEVLINK_TRAP(MLD_V1_DONE, CONTROL), 993 DEVLINK_TRAP(IPV4_DHCP, CONTROL), 994 DEVLINK_TRAP(IPV6_DHCP, CONTROL), 995 DEVLINK_TRAP(ARP_REQUEST, CONTROL), 996 DEVLINK_TRAP(ARP_RESPONSE, CONTROL), 997 DEVLINK_TRAP(ARP_OVERLAY, CONTROL), 998 DEVLINK_TRAP(IPV6_NEIGH_SOLICIT, CONTROL), 999 DEVLINK_TRAP(IPV6_NEIGH_ADVERT, CONTROL), 1000 DEVLINK_TRAP(IPV4_BFD, CONTROL), 1001 DEVLINK_TRAP(IPV6_BFD, CONTROL), 1002 DEVLINK_TRAP(IPV4_OSPF, CONTROL), 1003 DEVLINK_TRAP(IPV6_OSPF, CONTROL), 1004 DEVLINK_TRAP(IPV4_BGP, CONTROL), 1005 DEVLINK_TRAP(IPV6_BGP, CONTROL), 1006 DEVLINK_TRAP(IPV4_VRRP, CONTROL), 1007 DEVLINK_TRAP(IPV6_VRRP, CONTROL), 1008 DEVLINK_TRAP(IPV4_PIM, CONTROL), 1009 DEVLINK_TRAP(IPV6_PIM, CONTROL), 1010 DEVLINK_TRAP(UC_LB, CONTROL), 1011 DEVLINK_TRAP(LOCAL_ROUTE, CONTROL), 1012 DEVLINK_TRAP(EXTERNAL_ROUTE, CONTROL), 1013 DEVLINK_TRAP(IPV6_UC_DIP_LINK_LOCAL_SCOPE, CONTROL), 1014 DEVLINK_TRAP(IPV6_DIP_ALL_NODES, CONTROL), 1015 DEVLINK_TRAP(IPV6_DIP_ALL_ROUTERS, CONTROL), 1016 DEVLINK_TRAP(IPV6_ROUTER_SOLICIT, CONTROL), 1017 DEVLINK_TRAP(IPV6_ROUTER_ADVERT, CONTROL), 1018 DEVLINK_TRAP(IPV6_REDIRECT, CONTROL), 1019 DEVLINK_TRAP(IPV4_ROUTER_ALERT, CONTROL), 1020 DEVLINK_TRAP(IPV6_ROUTER_ALERT, CONTROL), 1021 DEVLINK_TRAP(PTP_EVENT, CONTROL), 1022 DEVLINK_TRAP(PTP_GENERAL, CONTROL), 1023 DEVLINK_TRAP(FLOW_ACTION_SAMPLE, CONTROL), 1024 DEVLINK_TRAP(FLOW_ACTION_TRAP, CONTROL), 1025 DEVLINK_TRAP(EARLY_DROP, DROP), 1026 DEVLINK_TRAP(VXLAN_PARSING, DROP), 1027 DEVLINK_TRAP(LLC_SNAP_PARSING, DROP), 1028 DEVLINK_TRAP(VLAN_PARSING, DROP), 1029 DEVLINK_TRAP(PPPOE_PPP_PARSING, DROP), 1030 DEVLINK_TRAP(MPLS_PARSING, DROP), 1031 DEVLINK_TRAP(ARP_PARSING, DROP), 1032 DEVLINK_TRAP(IP_1_PARSING, DROP), 1033 DEVLINK_TRAP(IP_N_PARSING, DROP), 1034 DEVLINK_TRAP(GRE_PARSING, DROP), 1035 DEVLINK_TRAP(UDP_PARSING, DROP), 1036 DEVLINK_TRAP(TCP_PARSING, DROP), 1037 DEVLINK_TRAP(IPSEC_PARSING, DROP), 1038 DEVLINK_TRAP(SCTP_PARSING, DROP), 1039 DEVLINK_TRAP(DCCP_PARSING, DROP), 1040 DEVLINK_TRAP(GTP_PARSING, DROP), 1041 DEVLINK_TRAP(ESP_PARSING, DROP), 1042 DEVLINK_TRAP(BLACKHOLE_NEXTHOP, DROP), 1043 DEVLINK_TRAP(DMAC_FILTER, DROP), 1044 DEVLINK_TRAP(EAPOL, CONTROL), 1045 DEVLINK_TRAP(LOCKED_PORT, DROP), 1046 }; 1047 1048 #define DEVLINK_TRAP_GROUP(_id) \ 1049 { \ 1050 .id = DEVLINK_TRAP_GROUP_GENERIC_ID_##_id, \ 1051 .name = DEVLINK_TRAP_GROUP_GENERIC_NAME_##_id, \ 1052 } 1053 1054 static const struct devlink_trap_group devlink_trap_group_generic[] = { 1055 DEVLINK_TRAP_GROUP(L2_DROPS), 1056 DEVLINK_TRAP_GROUP(L3_DROPS), 1057 DEVLINK_TRAP_GROUP(L3_EXCEPTIONS), 1058 DEVLINK_TRAP_GROUP(BUFFER_DROPS), 1059 DEVLINK_TRAP_GROUP(TUNNEL_DROPS), 1060 DEVLINK_TRAP_GROUP(ACL_DROPS), 1061 DEVLINK_TRAP_GROUP(STP), 1062 DEVLINK_TRAP_GROUP(LACP), 1063 DEVLINK_TRAP_GROUP(LLDP), 1064 DEVLINK_TRAP_GROUP(MC_SNOOPING), 1065 DEVLINK_TRAP_GROUP(DHCP), 1066 DEVLINK_TRAP_GROUP(NEIGH_DISCOVERY), 1067 DEVLINK_TRAP_GROUP(BFD), 1068 DEVLINK_TRAP_GROUP(OSPF), 1069 DEVLINK_TRAP_GROUP(BGP), 1070 DEVLINK_TRAP_GROUP(VRRP), 1071 DEVLINK_TRAP_GROUP(PIM), 1072 DEVLINK_TRAP_GROUP(UC_LB), 1073 DEVLINK_TRAP_GROUP(LOCAL_DELIVERY), 1074 DEVLINK_TRAP_GROUP(EXTERNAL_DELIVERY), 1075 DEVLINK_TRAP_GROUP(IPV6), 1076 DEVLINK_TRAP_GROUP(PTP_EVENT), 1077 DEVLINK_TRAP_GROUP(PTP_GENERAL), 1078 DEVLINK_TRAP_GROUP(ACL_SAMPLE), 1079 DEVLINK_TRAP_GROUP(ACL_TRAP), 1080 DEVLINK_TRAP_GROUP(PARSER_ERROR_DROPS), 1081 DEVLINK_TRAP_GROUP(EAPOL), 1082 }; 1083 1084 static int devlink_trap_generic_verify(const struct devlink_trap *trap) 1085 { 1086 if (trap->id > DEVLINK_TRAP_GENERIC_ID_MAX) 1087 return -EINVAL; 1088 1089 if (strcmp(trap->name, devlink_trap_generic[trap->id].name)) 1090 return -EINVAL; 1091 1092 if (trap->type != devlink_trap_generic[trap->id].type) 1093 return -EINVAL; 1094 1095 return 0; 1096 } 1097 1098 static int devlink_trap_driver_verify(const struct devlink_trap *trap) 1099 { 1100 int i; 1101 1102 if (trap->id <= DEVLINK_TRAP_GENERIC_ID_MAX) 1103 return -EINVAL; 1104 1105 for (i = 0; i < ARRAY_SIZE(devlink_trap_generic); i++) { 1106 if (!strcmp(trap->name, devlink_trap_generic[i].name)) 1107 return -EEXIST; 1108 } 1109 1110 return 0; 1111 } 1112 1113 static int devlink_trap_verify(const struct devlink_trap *trap) 1114 { 1115 if (!trap || !trap->name) 1116 return -EINVAL; 1117 1118 if (trap->generic) 1119 return devlink_trap_generic_verify(trap); 1120 else 1121 return devlink_trap_driver_verify(trap); 1122 } 1123 1124 static int 1125 devlink_trap_group_generic_verify(const struct devlink_trap_group *group) 1126 { 1127 if (group->id > DEVLINK_TRAP_GROUP_GENERIC_ID_MAX) 1128 return -EINVAL; 1129 1130 if (strcmp(group->name, devlink_trap_group_generic[group->id].name)) 1131 return -EINVAL; 1132 1133 return 0; 1134 } 1135 1136 static int 1137 devlink_trap_group_driver_verify(const struct devlink_trap_group *group) 1138 { 1139 int i; 1140 1141 if (group->id <= DEVLINK_TRAP_GROUP_GENERIC_ID_MAX) 1142 return -EINVAL; 1143 1144 for (i = 0; i < ARRAY_SIZE(devlink_trap_group_generic); i++) { 1145 if (!strcmp(group->name, devlink_trap_group_generic[i].name)) 1146 return -EEXIST; 1147 } 1148 1149 return 0; 1150 } 1151 1152 static int devlink_trap_group_verify(const struct devlink_trap_group *group) 1153 { 1154 if (group->generic) 1155 return devlink_trap_group_generic_verify(group); 1156 else 1157 return devlink_trap_group_driver_verify(group); 1158 } 1159 1160 static void 1161 devlink_trap_group_notify(struct devlink *devlink, 1162 const struct devlink_trap_group_item *group_item, 1163 enum devlink_command cmd) 1164 { 1165 struct sk_buff *msg; 1166 int err; 1167 1168 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_GROUP_NEW && 1169 cmd != DEVLINK_CMD_TRAP_GROUP_DEL); 1170 1171 if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink)) 1172 return; 1173 1174 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1175 if (!msg) 1176 return; 1177 1178 err = devlink_nl_trap_group_fill(msg, devlink, group_item, cmd, 0, 0, 1179 0); 1180 if (err) { 1181 nlmsg_free(msg); 1182 return; 1183 } 1184 1185 devlink_nl_notify_send(devlink, msg); 1186 } 1187 1188 void devlink_trap_groups_notify_register(struct devlink *devlink) 1189 { 1190 struct devlink_trap_group_item *group_item; 1191 1192 list_for_each_entry(group_item, &devlink->trap_group_list, list) 1193 devlink_trap_group_notify(devlink, group_item, 1194 DEVLINK_CMD_TRAP_GROUP_NEW); 1195 } 1196 1197 void devlink_trap_groups_notify_unregister(struct devlink *devlink) 1198 { 1199 struct devlink_trap_group_item *group_item; 1200 1201 list_for_each_entry_reverse(group_item, &devlink->trap_group_list, list) 1202 devlink_trap_group_notify(devlink, group_item, 1203 DEVLINK_CMD_TRAP_GROUP_DEL); 1204 } 1205 1206 static int 1207 devlink_trap_item_group_link(struct devlink *devlink, 1208 struct devlink_trap_item *trap_item) 1209 { 1210 u16 group_id = trap_item->trap->init_group_id; 1211 struct devlink_trap_group_item *group_item; 1212 1213 group_item = devlink_trap_group_item_lookup_by_id(devlink, group_id); 1214 if (WARN_ON_ONCE(!group_item)) 1215 return -EINVAL; 1216 1217 trap_item->group_item = group_item; 1218 1219 return 0; 1220 } 1221 1222 static void devlink_trap_notify(struct devlink *devlink, 1223 const struct devlink_trap_item *trap_item, 1224 enum devlink_command cmd) 1225 { 1226 struct sk_buff *msg; 1227 int err; 1228 1229 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_NEW && 1230 cmd != DEVLINK_CMD_TRAP_DEL); 1231 1232 if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink)) 1233 return; 1234 1235 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1236 if (!msg) 1237 return; 1238 1239 err = devlink_nl_trap_fill(msg, devlink, trap_item, cmd, 0, 0, 0); 1240 if (err) { 1241 nlmsg_free(msg); 1242 return; 1243 } 1244 1245 devlink_nl_notify_send(devlink, msg); 1246 } 1247 1248 void devlink_traps_notify_register(struct devlink *devlink) 1249 { 1250 struct devlink_trap_item *trap_item; 1251 1252 list_for_each_entry(trap_item, &devlink->trap_list, list) 1253 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW); 1254 } 1255 1256 void devlink_traps_notify_unregister(struct devlink *devlink) 1257 { 1258 struct devlink_trap_item *trap_item; 1259 1260 list_for_each_entry_reverse(trap_item, &devlink->trap_list, list) 1261 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL); 1262 } 1263 1264 static int 1265 devlink_trap_register(struct devlink *devlink, 1266 const struct devlink_trap *trap, void *priv) 1267 { 1268 struct devlink_trap_item *trap_item; 1269 int err; 1270 1271 if (devlink_trap_item_lookup(devlink, trap->name)) 1272 return -EEXIST; 1273 1274 trap_item = kzalloc(sizeof(*trap_item), GFP_KERNEL); 1275 if (!trap_item) 1276 return -ENOMEM; 1277 1278 trap_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats); 1279 if (!trap_item->stats) { 1280 err = -ENOMEM; 1281 goto err_stats_alloc; 1282 } 1283 1284 trap_item->trap = trap; 1285 trap_item->action = trap->init_action; 1286 trap_item->priv = priv; 1287 1288 err = devlink_trap_item_group_link(devlink, trap_item); 1289 if (err) 1290 goto err_group_link; 1291 1292 err = devlink->ops->trap_init(devlink, trap, trap_item); 1293 if (err) 1294 goto err_trap_init; 1295 1296 list_add_tail(&trap_item->list, &devlink->trap_list); 1297 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW); 1298 1299 return 0; 1300 1301 err_trap_init: 1302 err_group_link: 1303 free_percpu(trap_item->stats); 1304 err_stats_alloc: 1305 kfree(trap_item); 1306 return err; 1307 } 1308 1309 static void devlink_trap_unregister(struct devlink *devlink, 1310 const struct devlink_trap *trap) 1311 { 1312 struct devlink_trap_item *trap_item; 1313 1314 trap_item = devlink_trap_item_lookup(devlink, trap->name); 1315 if (WARN_ON_ONCE(!trap_item)) 1316 return; 1317 1318 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL); 1319 list_del(&trap_item->list); 1320 if (devlink->ops->trap_fini) 1321 devlink->ops->trap_fini(devlink, trap, trap_item); 1322 free_percpu(trap_item->stats); 1323 kfree(trap_item); 1324 } 1325 1326 static void devlink_trap_disable(struct devlink *devlink, 1327 const struct devlink_trap *trap) 1328 { 1329 struct devlink_trap_item *trap_item; 1330 1331 trap_item = devlink_trap_item_lookup(devlink, trap->name); 1332 if (WARN_ON_ONCE(!trap_item)) 1333 return; 1334 1335 devlink->ops->trap_action_set(devlink, trap, DEVLINK_TRAP_ACTION_DROP, 1336 NULL); 1337 trap_item->action = DEVLINK_TRAP_ACTION_DROP; 1338 } 1339 1340 /** 1341 * devl_traps_register - Register packet traps with devlink. 1342 * @devlink: devlink. 1343 * @traps: Packet traps. 1344 * @traps_count: Count of provided packet traps. 1345 * @priv: Driver private information. 1346 * 1347 * Return: Non-zero value on failure. 1348 */ 1349 int devl_traps_register(struct devlink *devlink, 1350 const struct devlink_trap *traps, 1351 size_t traps_count, void *priv) 1352 { 1353 int i, err; 1354 1355 if (!devlink->ops->trap_init || !devlink->ops->trap_action_set) 1356 return -EINVAL; 1357 1358 devl_assert_locked(devlink); 1359 for (i = 0; i < traps_count; i++) { 1360 const struct devlink_trap *trap = &traps[i]; 1361 1362 err = devlink_trap_verify(trap); 1363 if (err) 1364 goto err_trap_verify; 1365 1366 err = devlink_trap_register(devlink, trap, priv); 1367 if (err) 1368 goto err_trap_register; 1369 } 1370 1371 return 0; 1372 1373 err_trap_register: 1374 err_trap_verify: 1375 for (i--; i >= 0; i--) 1376 devlink_trap_unregister(devlink, &traps[i]); 1377 return err; 1378 } 1379 EXPORT_SYMBOL_GPL(devl_traps_register); 1380 1381 /** 1382 * devlink_traps_register - Register packet traps with devlink. 1383 * @devlink: devlink. 1384 * @traps: Packet traps. 1385 * @traps_count: Count of provided packet traps. 1386 * @priv: Driver private information. 1387 * 1388 * Context: Takes and release devlink->lock <mutex>. 1389 * 1390 * Return: Non-zero value on failure. 1391 */ 1392 int devlink_traps_register(struct devlink *devlink, 1393 const struct devlink_trap *traps, 1394 size_t traps_count, void *priv) 1395 { 1396 int err; 1397 1398 devl_lock(devlink); 1399 err = devl_traps_register(devlink, traps, traps_count, priv); 1400 devl_unlock(devlink); 1401 return err; 1402 } 1403 EXPORT_SYMBOL_GPL(devlink_traps_register); 1404 1405 /** 1406 * devl_traps_unregister - Unregister packet traps from devlink. 1407 * @devlink: devlink. 1408 * @traps: Packet traps. 1409 * @traps_count: Count of provided packet traps. 1410 */ 1411 void devl_traps_unregister(struct devlink *devlink, 1412 const struct devlink_trap *traps, 1413 size_t traps_count) 1414 { 1415 int i; 1416 1417 devl_assert_locked(devlink); 1418 /* Make sure we do not have any packets in-flight while unregistering 1419 * traps by disabling all of them and waiting for a grace period. 1420 */ 1421 for (i = traps_count - 1; i >= 0; i--) 1422 devlink_trap_disable(devlink, &traps[i]); 1423 synchronize_rcu(); 1424 for (i = traps_count - 1; i >= 0; i--) 1425 devlink_trap_unregister(devlink, &traps[i]); 1426 } 1427 EXPORT_SYMBOL_GPL(devl_traps_unregister); 1428 1429 /** 1430 * devlink_traps_unregister - Unregister packet traps from devlink. 1431 * @devlink: devlink. 1432 * @traps: Packet traps. 1433 * @traps_count: Count of provided packet traps. 1434 * 1435 * Context: Takes and release devlink->lock <mutex>. 1436 */ 1437 void devlink_traps_unregister(struct devlink *devlink, 1438 const struct devlink_trap *traps, 1439 size_t traps_count) 1440 { 1441 devl_lock(devlink); 1442 devl_traps_unregister(devlink, traps, traps_count); 1443 devl_unlock(devlink); 1444 } 1445 EXPORT_SYMBOL_GPL(devlink_traps_unregister); 1446 1447 static void 1448 devlink_trap_stats_update(struct devlink_stats __percpu *trap_stats, 1449 size_t skb_len) 1450 { 1451 struct devlink_stats *stats; 1452 1453 stats = this_cpu_ptr(trap_stats); 1454 u64_stats_update_begin(&stats->syncp); 1455 u64_stats_add(&stats->rx_bytes, skb_len); 1456 u64_stats_inc(&stats->rx_packets); 1457 u64_stats_update_end(&stats->syncp); 1458 } 1459 1460 static void 1461 devlink_trap_report_metadata_set(struct devlink_trap_metadata *metadata, 1462 const struct devlink_trap_item *trap_item, 1463 struct devlink_port *in_devlink_port, 1464 const struct flow_action_cookie *fa_cookie) 1465 { 1466 metadata->trap_name = trap_item->trap->name; 1467 metadata->trap_group_name = trap_item->group_item->group->name; 1468 metadata->fa_cookie = fa_cookie; 1469 metadata->trap_type = trap_item->trap->type; 1470 1471 spin_lock(&in_devlink_port->type_lock); 1472 if (in_devlink_port->type == DEVLINK_PORT_TYPE_ETH) 1473 metadata->input_dev = in_devlink_port->type_eth.netdev; 1474 spin_unlock(&in_devlink_port->type_lock); 1475 } 1476 1477 /** 1478 * devlink_trap_report - Report trapped packet to drop monitor. 1479 * @devlink: devlink. 1480 * @skb: Trapped packet. 1481 * @trap_ctx: Trap context. 1482 * @in_devlink_port: Input devlink port. 1483 * @fa_cookie: Flow action cookie. Could be NULL. 1484 */ 1485 void devlink_trap_report(struct devlink *devlink, struct sk_buff *skb, 1486 void *trap_ctx, struct devlink_port *in_devlink_port, 1487 const struct flow_action_cookie *fa_cookie) 1488 1489 { 1490 struct devlink_trap_item *trap_item = trap_ctx; 1491 1492 devlink_trap_stats_update(trap_item->stats, skb->len); 1493 devlink_trap_stats_update(trap_item->group_item->stats, skb->len); 1494 1495 if (tracepoint_enabled(devlink_trap_report)) { 1496 struct devlink_trap_metadata metadata = {}; 1497 1498 devlink_trap_report_metadata_set(&metadata, trap_item, 1499 in_devlink_port, fa_cookie); 1500 trace_devlink_trap_report(devlink, skb, &metadata); 1501 } 1502 } 1503 EXPORT_SYMBOL_GPL(devlink_trap_report); 1504 1505 /** 1506 * devlink_trap_ctx_priv - Trap context to driver private information. 1507 * @trap_ctx: Trap context. 1508 * 1509 * Return: Driver private information passed during registration. 1510 */ 1511 void *devlink_trap_ctx_priv(void *trap_ctx) 1512 { 1513 struct devlink_trap_item *trap_item = trap_ctx; 1514 1515 return trap_item->priv; 1516 } 1517 EXPORT_SYMBOL_GPL(devlink_trap_ctx_priv); 1518 1519 static int 1520 devlink_trap_group_item_policer_link(struct devlink *devlink, 1521 struct devlink_trap_group_item *group_item) 1522 { 1523 u32 policer_id = group_item->group->init_policer_id; 1524 struct devlink_trap_policer_item *policer_item; 1525 1526 if (policer_id == 0) 1527 return 0; 1528 1529 policer_item = devlink_trap_policer_item_lookup(devlink, policer_id); 1530 if (WARN_ON_ONCE(!policer_item)) 1531 return -EINVAL; 1532 1533 group_item->policer_item = policer_item; 1534 1535 return 0; 1536 } 1537 1538 static int 1539 devlink_trap_group_register(struct devlink *devlink, 1540 const struct devlink_trap_group *group) 1541 { 1542 struct devlink_trap_group_item *group_item; 1543 int err; 1544 1545 if (devlink_trap_group_item_lookup(devlink, group->name)) 1546 return -EEXIST; 1547 1548 group_item = kzalloc(sizeof(*group_item), GFP_KERNEL); 1549 if (!group_item) 1550 return -ENOMEM; 1551 1552 group_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats); 1553 if (!group_item->stats) { 1554 err = -ENOMEM; 1555 goto err_stats_alloc; 1556 } 1557 1558 group_item->group = group; 1559 1560 err = devlink_trap_group_item_policer_link(devlink, group_item); 1561 if (err) 1562 goto err_policer_link; 1563 1564 if (devlink->ops->trap_group_init) { 1565 err = devlink->ops->trap_group_init(devlink, group); 1566 if (err) 1567 goto err_group_init; 1568 } 1569 1570 list_add_tail(&group_item->list, &devlink->trap_group_list); 1571 devlink_trap_group_notify(devlink, group_item, 1572 DEVLINK_CMD_TRAP_GROUP_NEW); 1573 1574 return 0; 1575 1576 err_group_init: 1577 err_policer_link: 1578 free_percpu(group_item->stats); 1579 err_stats_alloc: 1580 kfree(group_item); 1581 return err; 1582 } 1583 1584 static void 1585 devlink_trap_group_unregister(struct devlink *devlink, 1586 const struct devlink_trap_group *group) 1587 { 1588 struct devlink_trap_group_item *group_item; 1589 1590 group_item = devlink_trap_group_item_lookup(devlink, group->name); 1591 if (WARN_ON_ONCE(!group_item)) 1592 return; 1593 1594 devlink_trap_group_notify(devlink, group_item, 1595 DEVLINK_CMD_TRAP_GROUP_DEL); 1596 list_del(&group_item->list); 1597 free_percpu(group_item->stats); 1598 kfree(group_item); 1599 } 1600 1601 /** 1602 * devl_trap_groups_register - Register packet trap groups with devlink. 1603 * @devlink: devlink. 1604 * @groups: Packet trap groups. 1605 * @groups_count: Count of provided packet trap groups. 1606 * 1607 * Return: Non-zero value on failure. 1608 */ 1609 int devl_trap_groups_register(struct devlink *devlink, 1610 const struct devlink_trap_group *groups, 1611 size_t groups_count) 1612 { 1613 int i, err; 1614 1615 devl_assert_locked(devlink); 1616 for (i = 0; i < groups_count; i++) { 1617 const struct devlink_trap_group *group = &groups[i]; 1618 1619 err = devlink_trap_group_verify(group); 1620 if (err) 1621 goto err_trap_group_verify; 1622 1623 err = devlink_trap_group_register(devlink, group); 1624 if (err) 1625 goto err_trap_group_register; 1626 } 1627 1628 return 0; 1629 1630 err_trap_group_register: 1631 err_trap_group_verify: 1632 for (i--; i >= 0; i--) 1633 devlink_trap_group_unregister(devlink, &groups[i]); 1634 return err; 1635 } 1636 EXPORT_SYMBOL_GPL(devl_trap_groups_register); 1637 1638 /** 1639 * devlink_trap_groups_register - Register packet trap groups with devlink. 1640 * @devlink: devlink. 1641 * @groups: Packet trap groups. 1642 * @groups_count: Count of provided packet trap groups. 1643 * 1644 * Context: Takes and release devlink->lock <mutex>. 1645 * 1646 * Return: Non-zero value on failure. 1647 */ 1648 int devlink_trap_groups_register(struct devlink *devlink, 1649 const struct devlink_trap_group *groups, 1650 size_t groups_count) 1651 { 1652 int err; 1653 1654 devl_lock(devlink); 1655 err = devl_trap_groups_register(devlink, groups, groups_count); 1656 devl_unlock(devlink); 1657 return err; 1658 } 1659 EXPORT_SYMBOL_GPL(devlink_trap_groups_register); 1660 1661 /** 1662 * devl_trap_groups_unregister - Unregister packet trap groups from devlink. 1663 * @devlink: devlink. 1664 * @groups: Packet trap groups. 1665 * @groups_count: Count of provided packet trap groups. 1666 */ 1667 void devl_trap_groups_unregister(struct devlink *devlink, 1668 const struct devlink_trap_group *groups, 1669 size_t groups_count) 1670 { 1671 int i; 1672 1673 devl_assert_locked(devlink); 1674 for (i = groups_count - 1; i >= 0; i--) 1675 devlink_trap_group_unregister(devlink, &groups[i]); 1676 } 1677 EXPORT_SYMBOL_GPL(devl_trap_groups_unregister); 1678 1679 /** 1680 * devlink_trap_groups_unregister - Unregister packet trap groups from devlink. 1681 * @devlink: devlink. 1682 * @groups: Packet trap groups. 1683 * @groups_count: Count of provided packet trap groups. 1684 * 1685 * Context: Takes and release devlink->lock <mutex>. 1686 */ 1687 void devlink_trap_groups_unregister(struct devlink *devlink, 1688 const struct devlink_trap_group *groups, 1689 size_t groups_count) 1690 { 1691 devl_lock(devlink); 1692 devl_trap_groups_unregister(devlink, groups, groups_count); 1693 devl_unlock(devlink); 1694 } 1695 EXPORT_SYMBOL_GPL(devlink_trap_groups_unregister); 1696 1697 static void 1698 devlink_trap_policer_notify(struct devlink *devlink, 1699 const struct devlink_trap_policer_item *policer_item, 1700 enum devlink_command cmd) 1701 { 1702 struct sk_buff *msg; 1703 int err; 1704 1705 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_POLICER_NEW && 1706 cmd != DEVLINK_CMD_TRAP_POLICER_DEL); 1707 1708 if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink)) 1709 return; 1710 1711 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1712 if (!msg) 1713 return; 1714 1715 err = devlink_nl_trap_policer_fill(msg, devlink, policer_item, cmd, 0, 1716 0, 0); 1717 if (err) { 1718 nlmsg_free(msg); 1719 return; 1720 } 1721 1722 devlink_nl_notify_send(devlink, msg); 1723 } 1724 1725 void devlink_trap_policers_notify_register(struct devlink *devlink) 1726 { 1727 struct devlink_trap_policer_item *policer_item; 1728 1729 list_for_each_entry(policer_item, &devlink->trap_policer_list, list) 1730 devlink_trap_policer_notify(devlink, policer_item, 1731 DEVLINK_CMD_TRAP_POLICER_NEW); 1732 } 1733 1734 void devlink_trap_policers_notify_unregister(struct devlink *devlink) 1735 { 1736 struct devlink_trap_policer_item *policer_item; 1737 1738 list_for_each_entry_reverse(policer_item, &devlink->trap_policer_list, 1739 list) 1740 devlink_trap_policer_notify(devlink, policer_item, 1741 DEVLINK_CMD_TRAP_POLICER_DEL); 1742 } 1743 1744 static int 1745 devlink_trap_policer_register(struct devlink *devlink, 1746 const struct devlink_trap_policer *policer) 1747 { 1748 struct devlink_trap_policer_item *policer_item; 1749 int err; 1750 1751 if (devlink_trap_policer_item_lookup(devlink, policer->id)) 1752 return -EEXIST; 1753 1754 policer_item = kzalloc(sizeof(*policer_item), GFP_KERNEL); 1755 if (!policer_item) 1756 return -ENOMEM; 1757 1758 policer_item->policer = policer; 1759 policer_item->rate = policer->init_rate; 1760 policer_item->burst = policer->init_burst; 1761 1762 if (devlink->ops->trap_policer_init) { 1763 err = devlink->ops->trap_policer_init(devlink, policer); 1764 if (err) 1765 goto err_policer_init; 1766 } 1767 1768 list_add_tail(&policer_item->list, &devlink->trap_policer_list); 1769 devlink_trap_policer_notify(devlink, policer_item, 1770 DEVLINK_CMD_TRAP_POLICER_NEW); 1771 1772 return 0; 1773 1774 err_policer_init: 1775 kfree(policer_item); 1776 return err; 1777 } 1778 1779 static void 1780 devlink_trap_policer_unregister(struct devlink *devlink, 1781 const struct devlink_trap_policer *policer) 1782 { 1783 struct devlink_trap_policer_item *policer_item; 1784 1785 policer_item = devlink_trap_policer_item_lookup(devlink, policer->id); 1786 if (WARN_ON_ONCE(!policer_item)) 1787 return; 1788 1789 devlink_trap_policer_notify(devlink, policer_item, 1790 DEVLINK_CMD_TRAP_POLICER_DEL); 1791 list_del(&policer_item->list); 1792 if (devlink->ops->trap_policer_fini) 1793 devlink->ops->trap_policer_fini(devlink, policer); 1794 kfree(policer_item); 1795 } 1796 1797 /** 1798 * devl_trap_policers_register - Register packet trap policers with devlink. 1799 * @devlink: devlink. 1800 * @policers: Packet trap policers. 1801 * @policers_count: Count of provided packet trap policers. 1802 * 1803 * Return: Non-zero value on failure. 1804 */ 1805 int 1806 devl_trap_policers_register(struct devlink *devlink, 1807 const struct devlink_trap_policer *policers, 1808 size_t policers_count) 1809 { 1810 int i, err; 1811 1812 devl_assert_locked(devlink); 1813 for (i = 0; i < policers_count; i++) { 1814 const struct devlink_trap_policer *policer = &policers[i]; 1815 1816 if (WARN_ON(policer->id == 0 || 1817 policer->max_rate < policer->min_rate || 1818 policer->max_burst < policer->min_burst)) { 1819 err = -EINVAL; 1820 goto err_trap_policer_verify; 1821 } 1822 1823 err = devlink_trap_policer_register(devlink, policer); 1824 if (err) 1825 goto err_trap_policer_register; 1826 } 1827 return 0; 1828 1829 err_trap_policer_register: 1830 err_trap_policer_verify: 1831 for (i--; i >= 0; i--) 1832 devlink_trap_policer_unregister(devlink, &policers[i]); 1833 return err; 1834 } 1835 EXPORT_SYMBOL_GPL(devl_trap_policers_register); 1836 1837 /** 1838 * devl_trap_policers_unregister - Unregister packet trap policers from devlink. 1839 * @devlink: devlink. 1840 * @policers: Packet trap policers. 1841 * @policers_count: Count of provided packet trap policers. 1842 */ 1843 void 1844 devl_trap_policers_unregister(struct devlink *devlink, 1845 const struct devlink_trap_policer *policers, 1846 size_t policers_count) 1847 { 1848 int i; 1849 1850 devl_assert_locked(devlink); 1851 for (i = policers_count - 1; i >= 0; i--) 1852 devlink_trap_policer_unregister(devlink, &policers[i]); 1853 } 1854 EXPORT_SYMBOL_GPL(devl_trap_policers_unregister); 1855