Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'devlink-Preparations-for-trap-policers-support'

Ido Schimmel says:

====================
devlink: Preparations for trap policers support

This patch set prepares the code for devlink-trap policer support in a
follow-up patch set [1][2]. No functional changes intended.

Policers are going to be added as attributes of packet trap groups,
which are entities used to aggregate logically related packet traps.
This will allow users, for example, to limit all the packets that
encountered an exception during routing to 10Kpps.

However, currently, device drivers register their packet trap groups
implicitly when they register their packet traps via
devlink_traps_register(). This makes it difficult to pass additional
attributes for the groups. For example, the policer bound to the group.

Therefore, this patch set converts device drivers to explicitly register
their packet trap groups. This will later allow these drivers to
register the group with additional attributes, if any.
====================

Acked-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

+202 -115
+31 -7
drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
··· 132 132 133 133 #define MLXSW_SP_TRAP_DROP(_id, _group_id) \ 134 134 DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \ 135 - DEVLINK_TRAP_GROUP_GENERIC(_group_id), \ 135 + DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ 136 136 MLXSW_SP_TRAP_METADATA) 137 137 138 138 #define MLXSW_SP_TRAP_DROP_EXT(_id, _group_id, _metadata) \ 139 139 DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \ 140 - DEVLINK_TRAP_GROUP_GENERIC(_group_id), \ 140 + DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ 141 141 MLXSW_SP_TRAP_METADATA | (_metadata)) 142 142 143 143 #define MLXSW_SP_TRAP_DRIVER_DROP(_id, _group_id) \ 144 144 DEVLINK_TRAP_DRIVER(DROP, DROP, DEVLINK_MLXSW_TRAP_ID_##_id, \ 145 145 DEVLINK_MLXSW_TRAP_NAME_##_id, \ 146 - DEVLINK_TRAP_GROUP_GENERIC(_group_id), \ 146 + DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ 147 147 MLXSW_SP_TRAP_METADATA) 148 148 149 149 #define MLXSW_SP_TRAP_EXCEPTION(_id, _group_id) \ 150 150 DEVLINK_TRAP_GENERIC(EXCEPTION, TRAP, _id, \ 151 - DEVLINK_TRAP_GROUP_GENERIC(_group_id), \ 151 + DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ 152 152 MLXSW_SP_TRAP_METADATA) 153 153 154 154 #define MLXSW_SP_RXL_DISCARD(_id, _group_id) \ ··· 164 164 #define MLXSW_SP_RXL_EXCEPTION(_id, _group_id, _action) \ 165 165 MLXSW_RXL(mlxsw_sp_rx_exception_listener, _id, \ 166 166 _action, false, SP_##_group_id, SET_FW_DEFAULT) 167 + 168 + static const struct devlink_trap_group mlxsw_sp_trap_groups_arr[] = { 169 + DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS), 170 + DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS), 171 + DEVLINK_TRAP_GROUP_GENERIC(TUNNEL_DROPS), 172 + DEVLINK_TRAP_GROUP_GENERIC(ACL_DROPS), 173 + }; 167 174 168 175 static const struct devlink_trap mlxsw_sp_traps_arr[] = { 169 176 MLXSW_SP_TRAP_DROP(SMAC_MC, L2_DROPS), ··· 325 318 326 319 int mlxsw_sp_devlink_traps_init(struct mlxsw_sp *mlxsw_sp) 327 320 { 321 + size_t groups_count = ARRAY_SIZE(mlxsw_sp_trap_groups_arr); 328 322 struct devlink *devlink = priv_to_devlink(mlxsw_sp->core); 329 323 int err; 330 324 ··· 341 333 ARRAY_SIZE(mlxsw_sp_listeners_arr))) 342 334 return -EINVAL; 343 335 344 - return devlink_traps_register(devlink, mlxsw_sp_traps_arr, 345 - ARRAY_SIZE(mlxsw_sp_traps_arr), 346 - mlxsw_sp); 336 + err = devlink_trap_groups_register(devlink, mlxsw_sp_trap_groups_arr, 337 + groups_count); 338 + if (err) 339 + return err; 340 + 341 + err = devlink_traps_register(devlink, mlxsw_sp_traps_arr, 342 + ARRAY_SIZE(mlxsw_sp_traps_arr), mlxsw_sp); 343 + if (err) 344 + goto err_traps_register; 345 + 346 + return 0; 347 + 348 + err_traps_register: 349 + devlink_trap_groups_unregister(devlink, mlxsw_sp_trap_groups_arr, 350 + groups_count); 351 + return err; 347 352 } 348 353 349 354 void mlxsw_sp_devlink_traps_fini(struct mlxsw_sp *mlxsw_sp) 350 355 { 356 + size_t groups_count = ARRAY_SIZE(mlxsw_sp_trap_groups_arr); 351 357 struct devlink *devlink = priv_to_devlink(mlxsw_sp->core); 352 358 353 359 devlink_traps_unregister(devlink, mlxsw_sp_traps_arr, 354 360 ARRAY_SIZE(mlxsw_sp_traps_arr)); 361 + devlink_trap_groups_unregister(devlink, mlxsw_sp_trap_groups_arr, 362 + groups_count); 355 363 } 356 364 357 365 int mlxsw_sp_trap_init(struct mlxsw_core *mlxsw_core,
+22 -5
drivers/net/netdevsim/dev.c
··· 381 381 382 382 #define NSIM_TRAP_DROP(_id, _group_id) \ 383 383 DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \ 384 - DEVLINK_TRAP_GROUP_GENERIC(_group_id), \ 384 + DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ 385 385 NSIM_TRAP_METADATA) 386 386 #define NSIM_TRAP_DROP_EXT(_id, _group_id, _metadata) \ 387 387 DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \ 388 - DEVLINK_TRAP_GROUP_GENERIC(_group_id), \ 388 + DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ 389 389 NSIM_TRAP_METADATA | (_metadata)) 390 390 #define NSIM_TRAP_EXCEPTION(_id, _group_id) \ 391 391 DEVLINK_TRAP_GENERIC(EXCEPTION, TRAP, _id, \ 392 - DEVLINK_TRAP_GROUP_GENERIC(_group_id), \ 392 + DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ 393 393 NSIM_TRAP_METADATA) 394 394 #define NSIM_TRAP_DRIVER_EXCEPTION(_id, _group_id) \ 395 395 DEVLINK_TRAP_DRIVER(EXCEPTION, TRAP, NSIM_TRAP_ID_##_id, \ 396 396 NSIM_TRAP_NAME_##_id, \ 397 - DEVLINK_TRAP_GROUP_GENERIC(_group_id), \ 397 + DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ 398 398 NSIM_TRAP_METADATA) 399 + 400 + static const struct devlink_trap_group nsim_trap_groups_arr[] = { 401 + DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS), 402 + DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS), 403 + DEVLINK_TRAP_GROUP_GENERIC(BUFFER_DROPS), 404 + DEVLINK_TRAP_GROUP_GENERIC(ACL_DROPS), 405 + }; 399 406 400 407 static const struct devlink_trap nsim_traps_arr[] = { 401 408 NSIM_TRAP_DROP(SMAC_MC, L2_DROPS), ··· 563 556 nsim_trap_data->nsim_dev = nsim_dev; 564 557 nsim_dev->trap_data = nsim_trap_data; 565 558 559 + err = devlink_trap_groups_register(devlink, nsim_trap_groups_arr, 560 + ARRAY_SIZE(nsim_trap_groups_arr)); 561 + if (err) 562 + goto err_trap_items_free; 563 + 566 564 err = devlink_traps_register(devlink, nsim_traps_arr, 567 565 ARRAY_SIZE(nsim_traps_arr), NULL); 568 566 if (err) 569 - goto err_trap_items_free; 567 + goto err_trap_groups_unregister; 570 568 571 569 INIT_DELAYED_WORK(&nsim_dev->trap_data->trap_report_dw, 572 570 nsim_dev_trap_report_work); ··· 580 568 581 569 return 0; 582 570 571 + err_trap_groups_unregister: 572 + devlink_trap_groups_unregister(devlink, nsim_trap_groups_arr, 573 + ARRAY_SIZE(nsim_trap_groups_arr)); 583 574 err_trap_items_free: 584 575 kfree(nsim_trap_data->trap_items_arr); 585 576 err_trap_data_free: ··· 597 582 cancel_delayed_work_sync(&nsim_dev->trap_data->trap_report_dw); 598 583 devlink_traps_unregister(devlink, nsim_traps_arr, 599 584 ARRAY_SIZE(nsim_traps_arr)); 585 + devlink_trap_groups_unregister(devlink, nsim_trap_groups_arr, 586 + ARRAY_SIZE(nsim_trap_groups_arr)); 600 587 kfree(nsim_dev->trap_data->trap_items_arr); 601 588 kfree(nsim_dev->trap_data); 602 589 }
+13 -6
include/net/devlink.h
··· 553 553 * @generic: Whether the trap is generic or not. 554 554 * @id: Trap identifier. 555 555 * @name: Trap name. 556 - * @group: Immutable packet trap group attributes. 556 + * @init_group_id: Initial group identifier. 557 557 * @metadata_cap: Metadata types that can be provided by the trap. 558 558 * 559 559 * Describes immutable attributes of packet traps that drivers register with ··· 565 565 bool generic; 566 566 u16 id; 567 567 const char *name; 568 - struct devlink_trap_group group; 568 + u16 init_group_id; 569 569 u32 metadata_cap; 570 570 }; 571 571 ··· 694 694 #define DEVLINK_TRAP_GROUP_GENERIC_NAME_ACL_DROPS \ 695 695 "acl_drops" 696 696 697 - #define DEVLINK_TRAP_GENERIC(_type, _init_action, _id, _group, _metadata_cap) \ 697 + #define DEVLINK_TRAP_GENERIC(_type, _init_action, _id, _group_id, \ 698 + _metadata_cap) \ 698 699 { \ 699 700 .type = DEVLINK_TRAP_TYPE_##_type, \ 700 701 .init_action = DEVLINK_TRAP_ACTION_##_init_action, \ 701 702 .generic = true, \ 702 703 .id = DEVLINK_TRAP_GENERIC_ID_##_id, \ 703 704 .name = DEVLINK_TRAP_GENERIC_NAME_##_id, \ 704 - .group = _group, \ 705 + .init_group_id = _group_id, \ 705 706 .metadata_cap = _metadata_cap, \ 706 707 } 707 708 708 - #define DEVLINK_TRAP_DRIVER(_type, _init_action, _id, _name, _group, \ 709 + #define DEVLINK_TRAP_DRIVER(_type, _init_action, _id, _name, _group_id, \ 709 710 _metadata_cap) \ 710 711 { \ 711 712 .type = DEVLINK_TRAP_TYPE_##_type, \ ··· 714 713 .generic = false, \ 715 714 .id = _id, \ 716 715 .name = _name, \ 717 - .group = _group, \ 716 + .init_group_id = _group_id, \ 718 717 .metadata_cap = _metadata_cap, \ 719 718 } 720 719 ··· 1058 1057 void *trap_ctx, struct devlink_port *in_devlink_port, 1059 1058 const struct flow_action_cookie *fa_cookie); 1060 1059 void *devlink_trap_ctx_priv(void *trap_ctx); 1060 + int devlink_trap_groups_register(struct devlink *devlink, 1061 + const struct devlink_trap_group *groups, 1062 + size_t groups_count); 1063 + void devlink_trap_groups_unregister(struct devlink *devlink, 1064 + const struct devlink_trap_group *groups, 1065 + size_t groups_count); 1061 1066 1062 1067 #if IS_ENABLED(CONFIG_NET_DEVLINK) 1063 1068
+136 -97
net/core/devlink.c
··· 5456 5456 /** 5457 5457 * struct devlink_trap_group_item - Packet trap group attributes. 5458 5458 * @group: Immutable packet trap group attributes. 5459 - * @refcount: Number of trap items using the group. 5460 5459 * @list: trap_group_list member. 5461 5460 * @stats: Trap group statistics. 5462 5461 * 5463 5462 * Describes packet trap group attributes. Created by devlink during trap 5464 - * registration. 5463 + * group registration. 5465 5464 */ 5466 5465 struct devlink_trap_group_item { 5467 5466 const struct devlink_trap_group *group; 5468 - refcount_t refcount; 5469 5467 struct list_head list; 5470 5468 struct devlink_stats __percpu *stats; 5471 5469 }; ··· 5816 5818 } 5817 5819 5818 5820 static struct devlink_trap_group_item * 5821 + devlink_trap_group_item_lookup_by_id(struct devlink *devlink, u16 id) 5822 + { 5823 + struct devlink_trap_group_item *group_item; 5824 + 5825 + list_for_each_entry(group_item, &devlink->trap_group_list, list) { 5826 + if (group_item->group->id == id) 5827 + return group_item; 5828 + } 5829 + 5830 + return NULL; 5831 + } 5832 + 5833 + static struct devlink_trap_group_item * 5819 5834 devlink_trap_group_item_get_from_info(struct devlink *devlink, 5820 5835 struct genl_info *info) 5821 5836 { ··· 5966 5955 int err; 5967 5956 5968 5957 list_for_each_entry(trap_item, &devlink->trap_list, list) { 5969 - if (strcmp(trap_item->trap->group.name, group_name)) 5958 + if (strcmp(trap_item->group_item->group->name, group_name)) 5970 5959 continue; 5971 5960 err = __devlink_trap_action_set(devlink, trap_item, 5972 5961 trap_action, extack); ··· 7877 7866 7878 7867 static int devlink_trap_verify(const struct devlink_trap *trap) 7879 7868 { 7880 - if (!trap || !trap->name || !trap->group.name) 7869 + if (!trap || !trap->name) 7881 7870 return -EINVAL; 7882 7871 7883 7872 if (trap->generic) ··· 7948 7937 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 7949 7938 } 7950 7939 7951 - static struct devlink_trap_group_item * 7952 - devlink_trap_group_item_create(struct devlink *devlink, 7953 - const struct devlink_trap_group *group) 7954 - { 7955 - struct devlink_trap_group_item *group_item; 7956 - int err; 7957 - 7958 - err = devlink_trap_group_verify(group); 7959 - if (err) 7960 - return ERR_PTR(err); 7961 - 7962 - group_item = kzalloc(sizeof(*group_item), GFP_KERNEL); 7963 - if (!group_item) 7964 - return ERR_PTR(-ENOMEM); 7965 - 7966 - group_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats); 7967 - if (!group_item->stats) { 7968 - err = -ENOMEM; 7969 - goto err_stats_alloc; 7970 - } 7971 - 7972 - group_item->group = group; 7973 - refcount_set(&group_item->refcount, 1); 7974 - 7975 - if (devlink->ops->trap_group_init) { 7976 - err = devlink->ops->trap_group_init(devlink, group); 7977 - if (err) 7978 - goto err_group_init; 7979 - } 7980 - 7981 - list_add_tail(&group_item->list, &devlink->trap_group_list); 7982 - devlink_trap_group_notify(devlink, group_item, 7983 - DEVLINK_CMD_TRAP_GROUP_NEW); 7984 - 7985 - return group_item; 7986 - 7987 - err_group_init: 7988 - free_percpu(group_item->stats); 7989 - err_stats_alloc: 7990 - kfree(group_item); 7991 - return ERR_PTR(err); 7992 - } 7993 - 7994 - static void 7995 - devlink_trap_group_item_destroy(struct devlink *devlink, 7996 - struct devlink_trap_group_item *group_item) 7997 - { 7998 - devlink_trap_group_notify(devlink, group_item, 7999 - DEVLINK_CMD_TRAP_GROUP_DEL); 8000 - list_del(&group_item->list); 8001 - free_percpu(group_item->stats); 8002 - kfree(group_item); 8003 - } 8004 - 8005 - static struct devlink_trap_group_item * 8006 - devlink_trap_group_item_get(struct devlink *devlink, 8007 - const struct devlink_trap_group *group) 8008 - { 8009 - struct devlink_trap_group_item *group_item; 8010 - 8011 - group_item = devlink_trap_group_item_lookup(devlink, group->name); 8012 - if (group_item) { 8013 - refcount_inc(&group_item->refcount); 8014 - return group_item; 8015 - } 8016 - 8017 - return devlink_trap_group_item_create(devlink, group); 8018 - } 8019 - 8020 - static void 8021 - devlink_trap_group_item_put(struct devlink *devlink, 8022 - struct devlink_trap_group_item *group_item) 8023 - { 8024 - if (!refcount_dec_and_test(&group_item->refcount)) 8025 - return; 8026 - 8027 - devlink_trap_group_item_destroy(devlink, group_item); 8028 - } 8029 - 8030 7940 static int 8031 7941 devlink_trap_item_group_link(struct devlink *devlink, 8032 7942 struct devlink_trap_item *trap_item) 8033 7943 { 7944 + u16 group_id = trap_item->trap->init_group_id; 8034 7945 struct devlink_trap_group_item *group_item; 8035 7946 8036 - group_item = devlink_trap_group_item_get(devlink, 8037 - &trap_item->trap->group); 8038 - if (IS_ERR(group_item)) 8039 - return PTR_ERR(group_item); 7947 + group_item = devlink_trap_group_item_lookup_by_id(devlink, group_id); 7948 + if (WARN_ON_ONCE(!group_item)) 7949 + return -EINVAL; 8040 7950 8041 7951 trap_item->group_item = group_item; 8042 7952 8043 7953 return 0; 8044 - } 8045 - 8046 - static void 8047 - devlink_trap_item_group_unlink(struct devlink *devlink, 8048 - struct devlink_trap_item *trap_item) 8049 - { 8050 - devlink_trap_group_item_put(devlink, trap_item->group_item); 8051 7954 } 8052 7955 8053 7956 static void devlink_trap_notify(struct devlink *devlink, ··· 8026 8101 return 0; 8027 8102 8028 8103 err_trap_init: 8029 - devlink_trap_item_group_unlink(devlink, trap_item); 8030 8104 err_group_link: 8031 8105 free_percpu(trap_item->stats); 8032 8106 err_stats_alloc: ··· 8046 8122 list_del(&trap_item->list); 8047 8123 if (devlink->ops->trap_fini) 8048 8124 devlink->ops->trap_fini(devlink, trap, trap_item); 8049 - devlink_trap_item_group_unlink(devlink, trap_item); 8050 8125 free_percpu(trap_item->stats); 8051 8126 kfree(trap_item); 8052 8127 } ··· 8200 8277 return trap_item->priv; 8201 8278 } 8202 8279 EXPORT_SYMBOL_GPL(devlink_trap_ctx_priv); 8280 + 8281 + static int 8282 + devlink_trap_group_register(struct devlink *devlink, 8283 + const struct devlink_trap_group *group) 8284 + { 8285 + struct devlink_trap_group_item *group_item; 8286 + int err; 8287 + 8288 + if (devlink_trap_group_item_lookup(devlink, group->name)) 8289 + return -EEXIST; 8290 + 8291 + group_item = kzalloc(sizeof(*group_item), GFP_KERNEL); 8292 + if (!group_item) 8293 + return -ENOMEM; 8294 + 8295 + group_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats); 8296 + if (!group_item->stats) { 8297 + err = -ENOMEM; 8298 + goto err_stats_alloc; 8299 + } 8300 + 8301 + group_item->group = group; 8302 + 8303 + if (devlink->ops->trap_group_init) { 8304 + err = devlink->ops->trap_group_init(devlink, group); 8305 + if (err) 8306 + goto err_group_init; 8307 + } 8308 + 8309 + list_add_tail(&group_item->list, &devlink->trap_group_list); 8310 + devlink_trap_group_notify(devlink, group_item, 8311 + DEVLINK_CMD_TRAP_GROUP_NEW); 8312 + 8313 + return 0; 8314 + 8315 + err_group_init: 8316 + free_percpu(group_item->stats); 8317 + err_stats_alloc: 8318 + kfree(group_item); 8319 + return err; 8320 + } 8321 + 8322 + static void 8323 + devlink_trap_group_unregister(struct devlink *devlink, 8324 + const struct devlink_trap_group *group) 8325 + { 8326 + struct devlink_trap_group_item *group_item; 8327 + 8328 + group_item = devlink_trap_group_item_lookup(devlink, group->name); 8329 + if (WARN_ON_ONCE(!group_item)) 8330 + return; 8331 + 8332 + devlink_trap_group_notify(devlink, group_item, 8333 + DEVLINK_CMD_TRAP_GROUP_DEL); 8334 + list_del(&group_item->list); 8335 + free_percpu(group_item->stats); 8336 + kfree(group_item); 8337 + } 8338 + 8339 + /** 8340 + * devlink_trap_groups_register - Register packet trap groups with devlink. 8341 + * @devlink: devlink. 8342 + * @groups: Packet trap groups. 8343 + * @groups_count: Count of provided packet trap groups. 8344 + * 8345 + * Return: Non-zero value on failure. 8346 + */ 8347 + int devlink_trap_groups_register(struct devlink *devlink, 8348 + const struct devlink_trap_group *groups, 8349 + size_t groups_count) 8350 + { 8351 + int i, err; 8352 + 8353 + mutex_lock(&devlink->lock); 8354 + for (i = 0; i < groups_count; i++) { 8355 + const struct devlink_trap_group *group = &groups[i]; 8356 + 8357 + err = devlink_trap_group_verify(group); 8358 + if (err) 8359 + goto err_trap_group_verify; 8360 + 8361 + err = devlink_trap_group_register(devlink, group); 8362 + if (err) 8363 + goto err_trap_group_register; 8364 + } 8365 + mutex_unlock(&devlink->lock); 8366 + 8367 + return 0; 8368 + 8369 + err_trap_group_register: 8370 + err_trap_group_verify: 8371 + for (i--; i >= 0; i--) 8372 + devlink_trap_group_unregister(devlink, &groups[i]); 8373 + mutex_unlock(&devlink->lock); 8374 + return err; 8375 + } 8376 + EXPORT_SYMBOL_GPL(devlink_trap_groups_register); 8377 + 8378 + /** 8379 + * devlink_trap_groups_unregister - Unregister packet trap groups from devlink. 8380 + * @devlink: devlink. 8381 + * @groups: Packet trap groups. 8382 + * @groups_count: Count of provided packet trap groups. 8383 + */ 8384 + void devlink_trap_groups_unregister(struct devlink *devlink, 8385 + const struct devlink_trap_group *groups, 8386 + size_t groups_count) 8387 + { 8388 + int i; 8389 + 8390 + mutex_lock(&devlink->lock); 8391 + for (i = groups_count - 1; i >= 0; i--) 8392 + devlink_trap_group_unregister(devlink, &groups[i]); 8393 + mutex_unlock(&devlink->lock); 8394 + } 8395 + EXPORT_SYMBOL_GPL(devlink_trap_groups_unregister); 8203 8396 8204 8397 static void __devlink_compat_running_version(struct devlink *devlink, 8205 8398 char *buf, size_t len)