From 08e335f6ad35a019f4cb1a74badc2f4bceb63bcf Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Mon, 3 Aug 2020 19:11:33 +0300 Subject: [PATCH 1/9] devlink: Add early_drop trap Add the packet trap that can report packets that were ECN marked due to RED AQM. Signed-off-by: Amit Cohen Signed-off-by: Petr Machata Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- Documentation/networking/devlink/devlink-trap.rst | 4 ++++ include/net/devlink.h | 3 +++ net/core/devlink.c | 1 + 3 files changed, 8 insertions(+) diff --git a/Documentation/networking/devlink/devlink-trap.rst b/Documentation/networking/devlink/devlink-trap.rst index 2014307fbe634..7a798352b45d1 100644 --- a/Documentation/networking/devlink/devlink-trap.rst +++ b/Documentation/networking/devlink/devlink-trap.rst @@ -405,6 +405,10 @@ be added to the following table: - ``control`` - Traps packets logged during processing of flow action trap (e.g., via tc's trap action) + * - ``early_drop`` + - ``drop`` + - Traps packets dropped due to the RED (Random Early Detection) algorithm + (i.e., early drops) Driver-specific Packet Traps ============================ diff --git a/include/net/devlink.h b/include/net/devlink.h index 0606967cb5010..fd3ae07604925 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -703,6 +703,7 @@ enum devlink_trap_generic_id { DEVLINK_TRAP_GENERIC_ID_PTP_GENERAL, DEVLINK_TRAP_GENERIC_ID_FLOW_ACTION_SAMPLE, DEVLINK_TRAP_GENERIC_ID_FLOW_ACTION_TRAP, + DEVLINK_TRAP_GENERIC_ID_EARLY_DROP, /* Add new generic trap IDs above */ __DEVLINK_TRAP_GENERIC_ID_MAX, @@ -891,6 +892,8 @@ enum devlink_trap_group_generic_id { "flow_action_sample" #define DEVLINK_TRAP_GENERIC_NAME_FLOW_ACTION_TRAP \ "flow_action_trap" +#define DEVLINK_TRAP_GENERIC_NAME_EARLY_DROP \ + "early_drop" #define DEVLINK_TRAP_GROUP_GENERIC_NAME_L2_DROPS \ "l2_drops" diff --git a/net/core/devlink.c b/net/core/devlink.c index 5fdebb7289e9e..bde4c29a30bcd 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -8801,6 +8801,7 @@ static const struct devlink_trap devlink_trap_generic[] = { DEVLINK_TRAP(PTP_GENERAL, CONTROL), DEVLINK_TRAP(FLOW_ACTION_SAMPLE, CONTROL), DEVLINK_TRAP(FLOW_ACTION_TRAP, CONTROL), + DEVLINK_TRAP(EARLY_DROP, DROP), }; #define DEVLINK_TRAP_GROUP(_id) \ From c88e11e04716ab4ed51d5972ea04c7b70b6e9d8a Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 3 Aug 2020 19:11:34 +0300 Subject: [PATCH 2/9] devlink: Pass extack when setting trap's action and group's parameters A later patch will refuse to set the action of certain traps in mlxsw and also to change the policer binding of certain groups. Pass extack so that failure could be communicated clearly to user space. Reviewed-by: Petr Machata Reviewed-by: Jiri Pirko Signed-off-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 10 ++++++---- drivers/net/ethernet/mellanox/mlxsw/core.h | 6 ++++-- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 6 ++++-- drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c | 13 ++++++++----- drivers/net/netdevsim/dev.c | 6 ++++-- include/net/devlink.h | 6 ++++-- net/core/devlink.c | 8 +++++--- 7 files changed, 35 insertions(+), 20 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 866381e72960d..08d101138fbe1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -1177,14 +1177,15 @@ static void mlxsw_devlink_trap_fini(struct devlink *devlink, static int mlxsw_devlink_trap_action_set(struct devlink *devlink, const struct devlink_trap *trap, - enum devlink_trap_action action) + enum devlink_trap_action action, + struct netlink_ext_ack *extack) { struct mlxsw_core *mlxsw_core = devlink_priv(devlink); struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; if (!mlxsw_driver->trap_action_set) return -EOPNOTSUPP; - return mlxsw_driver->trap_action_set(mlxsw_core, trap, action); + return mlxsw_driver->trap_action_set(mlxsw_core, trap, action, extack); } static int @@ -1202,14 +1203,15 @@ mlxsw_devlink_trap_group_init(struct devlink *devlink, static int mlxsw_devlink_trap_group_set(struct devlink *devlink, const struct devlink_trap_group *group, - const struct devlink_trap_policer *policer) + const struct devlink_trap_policer *policer, + struct netlink_ext_ack *extack) { struct mlxsw_core *mlxsw_core = devlink_priv(devlink); struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; if (!mlxsw_driver->trap_group_set) return -EOPNOTSUPP; - return mlxsw_driver->trap_group_set(mlxsw_core, group, policer); + return mlxsw_driver->trap_group_set(mlxsw_core, group, policer, extack); } static int diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index c1c1e039323aa..219ce89e629ac 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -326,12 +326,14 @@ struct mlxsw_driver { const struct devlink_trap *trap, void *trap_ctx); int (*trap_action_set)(struct mlxsw_core *mlxsw_core, const struct devlink_trap *trap, - enum devlink_trap_action action); + enum devlink_trap_action action, + struct netlink_ext_ack *extack); int (*trap_group_init)(struct mlxsw_core *mlxsw_core, const struct devlink_trap_group *group); int (*trap_group_set)(struct mlxsw_core *mlxsw_core, const struct devlink_trap_group *group, - const struct devlink_trap_policer *policer); + const struct devlink_trap_policer *policer, + struct netlink_ext_ack *extack); int (*trap_policer_init)(struct mlxsw_core *mlxsw_core, const struct devlink_trap_policer *policer); void (*trap_policer_fini)(struct mlxsw_core *mlxsw_core, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 6ab1b6d725af5..866a1193f12b8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -1177,12 +1177,14 @@ void mlxsw_sp_trap_fini(struct mlxsw_core *mlxsw_core, const struct devlink_trap *trap, void *trap_ctx); int mlxsw_sp_trap_action_set(struct mlxsw_core *mlxsw_core, const struct devlink_trap *trap, - enum devlink_trap_action action); + enum devlink_trap_action action, + struct netlink_ext_ack *extack); int mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core, const struct devlink_trap_group *group); int mlxsw_sp_trap_group_set(struct mlxsw_core *mlxsw_core, const struct devlink_trap_group *group, - const struct devlink_trap_policer *policer); + const struct devlink_trap_policer *policer, + struct netlink_ext_ack *extack); int mlxsw_sp_trap_policer_init(struct mlxsw_core *mlxsw_core, const struct devlink_trap_policer *policer); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c index 1e38dfe7cf64d..00b6cb9d2306f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c @@ -1352,7 +1352,8 @@ void mlxsw_sp_trap_fini(struct mlxsw_core *mlxsw_core, int mlxsw_sp_trap_action_set(struct mlxsw_core *mlxsw_core, const struct devlink_trap *trap, - enum devlink_trap_action action) + enum devlink_trap_action action, + struct netlink_ext_ack *extack) { struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); const struct mlxsw_sp_trap_item *trap_item; @@ -1392,7 +1393,7 @@ int mlxsw_sp_trap_action_set(struct mlxsw_core *mlxsw_core, static int __mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core, const struct devlink_trap_group *group, - u32 policer_id) + u32 policer_id, struct netlink_ext_ack *extack) { struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); u16 hw_policer_id = MLXSW_REG_HTGT_INVALID_POLICER; @@ -1422,16 +1423,18 @@ int mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core, const struct devlink_trap_group *group) { return __mlxsw_sp_trap_group_init(mlxsw_core, group, - group->init_policer_id); + group->init_policer_id, NULL); } int mlxsw_sp_trap_group_set(struct mlxsw_core *mlxsw_core, const struct devlink_trap_group *group, - const struct devlink_trap_policer *policer) + const struct devlink_trap_policer *policer, + struct netlink_ext_ack *extack) { u32 policer_id = policer ? policer->id : 0; - return __mlxsw_sp_trap_group_init(mlxsw_core, group, policer_id); + return __mlxsw_sp_trap_group_init(mlxsw_core, group, policer_id, + extack); } static int diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index ce719c830a77a..32f339fedb216 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -810,7 +810,8 @@ static int nsim_dev_devlink_trap_init(struct devlink *devlink, static int nsim_dev_devlink_trap_action_set(struct devlink *devlink, const struct devlink_trap *trap, - enum devlink_trap_action action) + enum devlink_trap_action action, + struct netlink_ext_ack *extack) { struct nsim_dev *nsim_dev = devlink_priv(devlink); struct nsim_trap_item *nsim_trap_item; @@ -829,7 +830,8 @@ nsim_dev_devlink_trap_action_set(struct devlink *devlink, static int nsim_dev_devlink_trap_group_set(struct devlink *devlink, const struct devlink_trap_group *group, - const struct devlink_trap_policer *policer) + const struct devlink_trap_policer *policer, + struct netlink_ext_ack *extack) { struct nsim_dev *nsim_dev = devlink_priv(devlink); diff --git a/include/net/devlink.h b/include/net/devlink.h index fd3ae07604925..8f3c8a4432382 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -1077,7 +1077,8 @@ struct devlink_ops { */ int (*trap_action_set)(struct devlink *devlink, const struct devlink_trap *trap, - enum devlink_trap_action action); + enum devlink_trap_action action, + struct netlink_ext_ack *extack); /** * @trap_group_init: Trap group initialization function. * @@ -1094,7 +1095,8 @@ struct devlink_ops { */ int (*trap_group_set)(struct devlink *devlink, const struct devlink_trap_group *group, - const struct devlink_trap_policer *policer); + const struct devlink_trap_policer *policer, + struct netlink_ext_ack *extack); /** * @trap_policer_init: Trap policer initialization function. * diff --git a/net/core/devlink.c b/net/core/devlink.c index bde4c29a30bcd..e674f0f46dc2b 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -6423,7 +6423,7 @@ static int __devlink_trap_action_set(struct devlink *devlink, } err = devlink->ops->trap_action_set(devlink, trap_item->trap, - trap_action); + trap_action, extack); if (err) return err; @@ -6713,7 +6713,8 @@ static int devlink_trap_group_set(struct devlink *devlink, } policer = policer_item ? policer_item->policer : NULL; - err = devlink->ops->trap_group_set(devlink, group_item->group, policer); + err = devlink->ops->trap_group_set(devlink, group_item->group, policer, + extack); if (err) return err; @@ -9051,7 +9052,8 @@ static void devlink_trap_disable(struct devlink *devlink, if (WARN_ON_ONCE(!trap_item)) return; - devlink->ops->trap_action_set(devlink, trap, DEVLINK_TRAP_ACTION_DROP); + devlink->ops->trap_action_set(devlink, trap, DEVLINK_TRAP_ACTION_DROP, + NULL); trap_item->action = DEVLINK_TRAP_ACTION_DROP; } From 76ba292cc7d7b760ee3e25aba353fb7ab86e64d3 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 3 Aug 2020 19:11:35 +0300 Subject: [PATCH 3/9] mlxsw: spectrum_trap: Use 'size_t' for array sizes Use 'size_t' instead of 'u64' for array sizes, as this this is correct type to use for expressions involving sizeof(). Suggested-by: Petr Machata Reviewed-by: Petr Machata Reviewed-by: Jiri Pirko Signed-off-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c | 4 ++-- drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c index 00b6cb9d2306f..47bc11a861ccb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c @@ -1063,10 +1063,10 @@ static int mlxsw_sp_trap_dummy_group_init(struct mlxsw_sp *mlxsw_sp) static int mlxsw_sp_trap_policer_items_arr_init(struct mlxsw_sp *mlxsw_sp) { + size_t arr_size = ARRAY_SIZE(mlxsw_sp_trap_policer_items_arr); size_t elem_size = sizeof(struct mlxsw_sp_trap_policer_item); - u64 arr_size = ARRAY_SIZE(mlxsw_sp_trap_policer_items_arr); struct mlxsw_sp_trap *trap = mlxsw_sp->trap; - u64 free_policers = 0; + size_t free_policers = 0; u32 last_id; int i; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h index 13ac412f4d532..a0560fb030eec 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h @@ -9,13 +9,13 @@ struct mlxsw_sp_trap { struct mlxsw_sp_trap_policer_item *policer_items_arr; - u64 policers_count; /* Number of registered policers */ + size_t policers_count; /* Number of registered policers */ struct mlxsw_sp_trap_group_item *group_items_arr; - u64 groups_count; /* Number of registered groups */ + size_t groups_count; /* Number of registered groups */ struct mlxsw_sp_trap_item *trap_items_arr; - u64 traps_count; /* Number of registered traps */ + size_t traps_count; /* Number of registered traps */ u16 thin_policer_hw_id; From 928345c08b72dd175d4eefa24900f09706a9a3b5 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Mon, 3 Aug 2020 19:11:36 +0300 Subject: [PATCH 4/9] mlxsw: spectrum_span: On policer_id_base_ref_count, use dec_and_test When unsetting policer base, the SPAN code currently uses refcount_dec(). However that function splats when the counter reaches zero, because reaching zero without actually testing is in general indicative of a missing cleanup. There is no cleanup to be done here, but nonetheless, use refcount_dec_and_test() as required. Signed-off-by: Petr Machata Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c index 323eaf979aea3..5c959a9951996 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c @@ -837,7 +837,8 @@ static int mlxsw_sp_span_policer_id_base_set(struct mlxsw_sp_span *span, static void mlxsw_sp_span_policer_id_base_unset(struct mlxsw_sp_span *span) { - refcount_dec(&span->policer_id_base_ref_count); + if (refcount_dec_and_test(&span->policer_id_base_ref_count)) + span->policer_id_base = 0; } static struct mlxsw_sp_span_entry * From 36d1fd687d56d807cc65210f14712349919c13e8 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 3 Aug 2020 19:11:37 +0300 Subject: [PATCH 5/9] mlxsw: spectrum_trap: Allow for per-ASIC trap groups initialization Subsequent patches will need to register different trap groups for Spectrum-1 and Spectrum-2 onwards. Enable that by invoking a per-ASIC operation during trap groups initialization. Reviewed-by: Petr Machata Reviewed-by: Jiri Pirko Signed-off-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum.c | 3 + .../net/ethernet/mellanox/mlxsw/spectrum.h | 1 + .../ethernet/mellanox/mlxsw/spectrum_trap.c | 89 +++++++++++++++++-- .../ethernet/mellanox/mlxsw/spectrum_trap.h | 9 ++ 4 files changed, 93 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 519eb44e4097a..fdf9aa8314b29 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3055,6 +3055,7 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core, mlxsw_sp->ptp_ops = &mlxsw_sp1_ptp_ops; mlxsw_sp->span_ops = &mlxsw_sp1_span_ops; mlxsw_sp->policer_core_ops = &mlxsw_sp1_policer_core_ops; + mlxsw_sp->trap_ops = &mlxsw_sp1_trap_ops; mlxsw_sp->listeners = mlxsw_sp1_listener; mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp1_listener); mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP1; @@ -3084,6 +3085,7 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core, mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops; mlxsw_sp->span_ops = &mlxsw_sp2_span_ops; mlxsw_sp->policer_core_ops = &mlxsw_sp2_policer_core_ops; + mlxsw_sp->trap_ops = &mlxsw_sp2_trap_ops; mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP2; return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack); @@ -3111,6 +3113,7 @@ static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core, mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops; mlxsw_sp->span_ops = &mlxsw_sp3_span_ops; mlxsw_sp->policer_core_ops = &mlxsw_sp2_policer_core_ops; + mlxsw_sp->trap_ops = &mlxsw_sp2_trap_ops; mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP3; return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 866a1193f12b8..b808f6b4d670b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -177,6 +177,7 @@ struct mlxsw_sp { const struct mlxsw_sp_ptp_ops *ptp_ops; const struct mlxsw_sp_span_ops *span_ops; const struct mlxsw_sp_policer_core_ops *policer_core_ops; + const struct mlxsw_sp_trap_ops *trap_ops; const struct mlxsw_listener *listeners; size_t listeners_count; u32 lowest_shaper_bs; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c index 47bc11a861ccb..3726be5c02b4f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c @@ -1159,6 +1159,43 @@ static void mlxsw_sp_trap_policers_fini(struct mlxsw_sp *mlxsw_sp) mlxsw_sp_trap_policer_items_arr_fini(mlxsw_sp); } +static int mlxsw_sp_trap_group_items_arr_init(struct mlxsw_sp *mlxsw_sp) +{ + size_t common_groups_count = ARRAY_SIZE(mlxsw_sp_trap_group_items_arr); + const struct mlxsw_sp_trap_group_item *spec_group_items_arr; + size_t elem_size = sizeof(struct mlxsw_sp_trap_group_item); + struct mlxsw_sp_trap *trap = mlxsw_sp->trap; + size_t groups_count, spec_groups_count; + int err; + + err = mlxsw_sp->trap_ops->groups_init(mlxsw_sp, &spec_group_items_arr, + &spec_groups_count); + if (err) + return err; + + /* The group items array is created by concatenating the common trap + * group items and the ASIC-specific trap group items. + */ + groups_count = common_groups_count + spec_groups_count; + trap->group_items_arr = kcalloc(groups_count, elem_size, GFP_KERNEL); + if (!trap->group_items_arr) + return -ENOMEM; + + memcpy(trap->group_items_arr, mlxsw_sp_trap_group_items_arr, + elem_size * common_groups_count); + memcpy(trap->group_items_arr + common_groups_count, + spec_group_items_arr, elem_size * spec_groups_count); + + trap->groups_count = groups_count; + + return 0; +} + +static void mlxsw_sp_trap_group_items_arr_fini(struct mlxsw_sp *mlxsw_sp) +{ + kfree(mlxsw_sp->trap->group_items_arr); +} + static int mlxsw_sp_trap_groups_init(struct mlxsw_sp *mlxsw_sp) { struct devlink *devlink = priv_to_devlink(mlxsw_sp->core); @@ -1166,13 +1203,9 @@ static int mlxsw_sp_trap_groups_init(struct mlxsw_sp *mlxsw_sp) struct mlxsw_sp_trap *trap = mlxsw_sp->trap; int err, i; - trap->group_items_arr = kmemdup(mlxsw_sp_trap_group_items_arr, - sizeof(mlxsw_sp_trap_group_items_arr), - GFP_KERNEL); - if (!trap->group_items_arr) - return -ENOMEM; - - trap->groups_count = ARRAY_SIZE(mlxsw_sp_trap_group_items_arr); + err = mlxsw_sp_trap_group_items_arr_init(mlxsw_sp); + if (err) + return err; for (i = 0; i < trap->groups_count; i++) { group_item = &trap->group_items_arr[i]; @@ -1189,7 +1222,7 @@ static int mlxsw_sp_trap_groups_init(struct mlxsw_sp *mlxsw_sp) group_item = &trap->group_items_arr[i]; devlink_trap_groups_unregister(devlink, &group_item->group, 1); } - kfree(trap->group_items_arr); + mlxsw_sp_trap_group_items_arr_fini(mlxsw_sp); return err; } @@ -1205,7 +1238,7 @@ static void mlxsw_sp_trap_groups_fini(struct mlxsw_sp *mlxsw_sp) group_item = &trap->group_items_arr[i]; devlink_trap_groups_unregister(devlink, &group_item->group, 1); } - kfree(trap->group_items_arr); + mlxsw_sp_trap_group_items_arr_fini(mlxsw_sp); } static bool @@ -1579,3 +1612,41 @@ mlxsw_sp_trap_policer_counter_get(struct mlxsw_core *mlxsw_core, return 0; } + +static const struct mlxsw_sp_trap_group_item +mlxsw_sp1_trap_group_items_arr[] = { +}; + +static int +mlxsw_sp1_trap_groups_init(struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_trap_group_item **arr, + size_t *p_groups_count) +{ + *arr = mlxsw_sp1_trap_group_items_arr; + *p_groups_count = ARRAY_SIZE(mlxsw_sp1_trap_group_items_arr); + + return 0; +} + +const struct mlxsw_sp_trap_ops mlxsw_sp1_trap_ops = { + .groups_init = mlxsw_sp1_trap_groups_init, +}; + +static const struct mlxsw_sp_trap_group_item +mlxsw_sp2_trap_group_items_arr[] = { +}; + +static int +mlxsw_sp2_trap_groups_init(struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_trap_group_item **arr, + size_t *p_groups_count) +{ + *arr = mlxsw_sp2_trap_group_items_arr; + *p_groups_count = ARRAY_SIZE(mlxsw_sp2_trap_group_items_arr); + + return 0; +} + +const struct mlxsw_sp_trap_ops mlxsw_sp2_trap_ops = { + .groups_init = mlxsw_sp2_trap_groups_init, +}; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h index a0560fb030eec..4ae5212b9a482 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h @@ -23,4 +23,13 @@ struct mlxsw_sp_trap { unsigned long policers_usage[]; /* Usage bitmap */ }; +struct mlxsw_sp_trap_ops { + int (*groups_init)(struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_trap_group_item **arr, + size_t *p_groups_count); +}; + +extern const struct mlxsw_sp_trap_ops mlxsw_sp1_trap_ops; +extern const struct mlxsw_sp_trap_ops mlxsw_sp2_trap_ops; + #endif From 869c7be940e50aa14845fcdb7a9d67c18be7e27a Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 3 Aug 2020 19:11:38 +0300 Subject: [PATCH 6/9] mlxsw: spectrum_trap: Allow for per-ASIC traps initialization Subsequent patches will need to register different traps for Spectrum-1 and Spectrum-2 onwards. Enable that by invoking a per-ASIC operation during traps initialization. Reviewed-by: Petr Machata Reviewed-by: Jiri Pirko Signed-off-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_trap.c | 81 ++++++++++++++++--- .../ethernet/mellanox/mlxsw/spectrum_trap.h | 3 + 2 files changed, 75 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c index 3726be5c02b4f..93dd88abbe234 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c @@ -1247,6 +1247,43 @@ mlxsw_sp_trap_listener_is_valid(const struct mlxsw_listener *listener) return listener->trap_id != 0; } +static int mlxsw_sp_trap_items_arr_init(struct mlxsw_sp *mlxsw_sp) +{ + size_t common_traps_count = ARRAY_SIZE(mlxsw_sp_trap_items_arr); + const struct mlxsw_sp_trap_item *spec_trap_items_arr; + size_t elem_size = sizeof(struct mlxsw_sp_trap_item); + struct mlxsw_sp_trap *trap = mlxsw_sp->trap; + size_t traps_count, spec_traps_count; + int err; + + err = mlxsw_sp->trap_ops->traps_init(mlxsw_sp, &spec_trap_items_arr, + &spec_traps_count); + if (err) + return err; + + /* The trap items array is created by concatenating the common trap + * items and the ASIC-specific trap items. + */ + traps_count = common_traps_count + spec_traps_count; + trap->trap_items_arr = kcalloc(traps_count, elem_size, GFP_KERNEL); + if (!trap->trap_items_arr) + return -ENOMEM; + + memcpy(trap->trap_items_arr, mlxsw_sp_trap_items_arr, + elem_size * common_traps_count); + memcpy(trap->trap_items_arr + common_traps_count, + spec_trap_items_arr, elem_size * spec_traps_count); + + trap->traps_count = traps_count; + + return 0; +} + +static void mlxsw_sp_trap_items_arr_fini(struct mlxsw_sp *mlxsw_sp) +{ + kfree(mlxsw_sp->trap->trap_items_arr); +} + static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp) { struct devlink *devlink = priv_to_devlink(mlxsw_sp->core); @@ -1254,13 +1291,9 @@ static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp) const struct mlxsw_sp_trap_item *trap_item; int err, i; - trap->trap_items_arr = kmemdup(mlxsw_sp_trap_items_arr, - sizeof(mlxsw_sp_trap_items_arr), - GFP_KERNEL); - if (!trap->trap_items_arr) - return -ENOMEM; - - trap->traps_count = ARRAY_SIZE(mlxsw_sp_trap_items_arr); + err = mlxsw_sp_trap_items_arr_init(mlxsw_sp); + if (err) + return err; for (i = 0; i < trap->traps_count; i++) { trap_item = &trap->trap_items_arr[i]; @@ -1277,7 +1310,7 @@ static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp) trap_item = &trap->trap_items_arr[i]; devlink_traps_unregister(devlink, &trap_item->trap, 1); } - kfree(trap->trap_items_arr); + mlxsw_sp_trap_items_arr_fini(mlxsw_sp); return err; } @@ -1293,7 +1326,7 @@ static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp) trap_item = &trap->trap_items_arr[i]; devlink_traps_unregister(devlink, &trap_item->trap, 1); } - kfree(trap->trap_items_arr); + mlxsw_sp_trap_items_arr_fini(mlxsw_sp); } int mlxsw_sp_devlink_traps_init(struct mlxsw_sp *mlxsw_sp) @@ -1617,6 +1650,10 @@ static const struct mlxsw_sp_trap_group_item mlxsw_sp1_trap_group_items_arr[] = { }; +static const struct mlxsw_sp_trap_item +mlxsw_sp1_trap_items_arr[] = { +}; + static int mlxsw_sp1_trap_groups_init(struct mlxsw_sp *mlxsw_sp, const struct mlxsw_sp_trap_group_item **arr, @@ -1628,14 +1665,29 @@ mlxsw_sp1_trap_groups_init(struct mlxsw_sp *mlxsw_sp, return 0; } +static int mlxsw_sp1_traps_init(struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_trap_item **arr, + size_t *p_traps_count) +{ + *arr = mlxsw_sp1_trap_items_arr; + *p_traps_count = ARRAY_SIZE(mlxsw_sp1_trap_items_arr); + + return 0; +} + const struct mlxsw_sp_trap_ops mlxsw_sp1_trap_ops = { .groups_init = mlxsw_sp1_trap_groups_init, + .traps_init = mlxsw_sp1_traps_init, }; static const struct mlxsw_sp_trap_group_item mlxsw_sp2_trap_group_items_arr[] = { }; +static const struct mlxsw_sp_trap_item +mlxsw_sp2_trap_items_arr[] = { +}; + static int mlxsw_sp2_trap_groups_init(struct mlxsw_sp *mlxsw_sp, const struct mlxsw_sp_trap_group_item **arr, @@ -1647,6 +1699,17 @@ mlxsw_sp2_trap_groups_init(struct mlxsw_sp *mlxsw_sp, return 0; } +static int mlxsw_sp2_traps_init(struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_trap_item **arr, + size_t *p_traps_count) +{ + *arr = mlxsw_sp2_trap_items_arr; + *p_traps_count = ARRAY_SIZE(mlxsw_sp2_trap_items_arr); + + return 0; +} + const struct mlxsw_sp_trap_ops mlxsw_sp2_trap_ops = { .groups_init = mlxsw_sp2_trap_groups_init, + .traps_init = mlxsw_sp2_traps_init, }; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h index 4ae5212b9a482..b8df684bedef0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.h @@ -27,6 +27,9 @@ struct mlxsw_sp_trap_ops { int (*groups_init)(struct mlxsw_sp *mlxsw_sp, const struct mlxsw_sp_trap_group_item **arr, size_t *p_groups_count); + int (*traps_init)(struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_trap_item **arr, + size_t *p_traps_count); }; extern const struct mlxsw_sp_trap_ops mlxsw_sp1_trap_ops; From 6687e953f44fdb4683adb899a963adba45cffa5d Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 3 Aug 2020 19:11:39 +0300 Subject: [PATCH 7/9] mlxsw: spectrum_trap: Add early_drop trap As previously explained, packets that are dropped due to buffer related reasons (e.g., tail drop, early drop) can be mirrored to the CPU port. These packets are then trapped with one of the "mirror session" traps and their CQE includes the reason for which the packet was mirrored. Register with devlink a new trap, early_drop, and initialize the corresponding Rx listener with the appropriate mirror reason. Return an error in case user tries to change the traps' action, as this is not supported. Since Spectrum-1 does not support these traps, the above is only done for Spectrum-2 onwards. Signed-off-by: Petr Machata Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.h | 13 ++++-- drivers/net/ethernet/mellanox/mlxsw/reg.h | 1 + .../ethernet/mellanox/mlxsw/spectrum_trap.c | 42 +++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 219ce89e629ac..11af3308f8cc8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -89,13 +89,15 @@ struct mlxsw_listener { }; #define __MLXSW_RXL(_func, _trap_id, _en_action, _is_ctrl, _en_trap_group, \ - _dis_action, _enabled_on_register, _dis_trap_group) \ + _dis_action, _enabled_on_register, _dis_trap_group, \ + _mirror_reason) \ { \ .trap_id = MLXSW_TRAP_ID_##_trap_id, \ .rx_listener = \ { \ .func = _func, \ .local_port = MLXSW_PORT_DONT_CARE, \ + .mirror_reason = _mirror_reason, \ .trap_id = MLXSW_TRAP_ID_##_trap_id, \ }, \ .en_action = MLXSW_REG_HPKT_ACTION_##_en_action, \ @@ -109,12 +111,17 @@ struct mlxsw_listener { #define MLXSW_RXL(_func, _trap_id, _en_action, _is_ctrl, _trap_group, \ _dis_action) \ __MLXSW_RXL(_func, _trap_id, _en_action, _is_ctrl, _trap_group, \ - _dis_action, true, _trap_group) + _dis_action, true, _trap_group, 0) #define MLXSW_RXL_DIS(_func, _trap_id, _en_action, _is_ctrl, _en_trap_group, \ _dis_action, _dis_trap_group) \ __MLXSW_RXL(_func, _trap_id, _en_action, _is_ctrl, _en_trap_group, \ - _dis_action, false, _dis_trap_group) + _dis_action, false, _dis_trap_group, 0) + +#define MLXSW_RXL_MIRROR(_func, _session_id, _trap_group, _mirror_reason) \ + __MLXSW_RXL(_func, MIRROR_SESSION##_session_id, TRAP_TO_CPU, false, \ + _trap_group, TRAP_TO_CPU, true, _trap_group, \ + _mirror_reason) #define MLXSW_EVENTL(_func, _trap_id, _trap_group) \ { \ diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 28a2576eb783c..079b080de7f73 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -5614,6 +5614,7 @@ enum mlxsw_reg_htgt_trap_group { MLXSW_REG_HTGT_TRAP_GROUP_SP_L3_EXCEPTIONS, MLXSW_REG_HTGT_TRAP_GROUP_SP_TUNNEL_DISCARDS, MLXSW_REG_HTGT_TRAP_GROUP_SP_ACL_DISCARDS, + MLXSW_REG_HTGT_TRAP_GROUP_SP_BUFFER_DISCARDS, __MLXSW_REG_HTGT_TRAP_GROUP_MAX, MLXSW_REG_HTGT_TRAP_GROUP_MAX = __MLXSW_REG_HTGT_TRAP_GROUP_MAX - 1 diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c index 93dd88abbe234..16bf154076b3b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c @@ -21,6 +21,7 @@ struct mlxsw_sp_trap_group_item { struct devlink_trap_group group; u16 hw_group_id; u8 priority; + u8 fixed_policer:1; /* Whether policer binding can change */ }; #define MLXSW_SP_TRAP_LISTENERS_MAX 3 @@ -28,6 +29,7 @@ struct mlxsw_sp_trap_group_item { struct mlxsw_sp_trap_item { struct devlink_trap trap; struct mlxsw_listener listeners_arr[MLXSW_SP_TRAP_LISTENERS_MAX]; + u8 is_source:1; }; /* All driver-specific traps must be documented in @@ -46,6 +48,11 @@ enum { #define MLXSW_SP_TRAP_METADATA DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT +enum { + /* Packet was early dropped. */ + MLXSW_SP_MIRROR_REASON_INGRESS_WRED = 9, +}; + static int mlxsw_sp_rx_listener(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb, u8 local_port, struct mlxsw_sp_port *mlxsw_sp_port) @@ -222,6 +229,11 @@ static void mlxsw_sp_rx_sample_listener(struct sk_buff *skb, u8 local_port, DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ MLXSW_SP_TRAP_METADATA | (_metadata)) +#define MLXSW_SP_TRAP_BUFFER_DROP(_id) \ + DEVLINK_TRAP_GENERIC(DROP, TRAP, _id, \ + DEVLINK_TRAP_GROUP_GENERIC_ID_BUFFER_DROPS, \ + MLXSW_SP_TRAP_METADATA) + #define MLXSW_SP_TRAP_DRIVER_DROP(_id, _group_id) \ DEVLINK_TRAP_DRIVER(DROP, DROP, DEVLINK_MLXSW_TRAP_ID_##_id, \ DEVLINK_MLXSW_TRAP_NAME_##_id, \ @@ -248,6 +260,10 @@ static void mlxsw_sp_rx_sample_listener(struct sk_buff *skb, u8 local_port, TRAP_EXCEPTION_TO_CPU, false, SP_##_en_group_id, \ SET_FW_DEFAULT, SP_##_dis_group_id) +#define MLXSW_SP_RXL_BUFFER_DISCARD(_mirror_reason) \ + MLXSW_RXL_MIRROR(mlxsw_sp_rx_drop_listener, 0, SP_BUFFER_DISCARDS, \ + MLXSW_SP_MIRROR_REASON_##_mirror_reason) + #define MLXSW_SP_RXL_EXCEPTION(_id, _group_id, _action) \ MLXSW_RXL(mlxsw_sp_rx_mark_listener, _id, \ _action, false, SP_##_group_id, SET_FW_DEFAULT) @@ -331,6 +347,9 @@ mlxsw_sp_trap_policer_items_arr[] = { { .policer = MLXSW_SP_TRAP_POLICER(19, 1024, 512), }, + { + .policer = MLXSW_SP_TRAP_POLICER(20, 10240, 4096), + }, }; static const struct mlxsw_sp_trap_group_item mlxsw_sp_trap_group_items_arr[] = { @@ -1429,6 +1448,11 @@ int mlxsw_sp_trap_action_set(struct mlxsw_core *mlxsw_core, if (WARN_ON(!trap_item)) return -EINVAL; + if (trap_item->is_source) { + NL_SET_ERR_MSG_MOD(extack, "Changing the action of source traps is not supported"); + return -EOPNOTSUPP; + } + for (i = 0; i < MLXSW_SP_TRAP_LISTENERS_MAX; i++) { const struct mlxsw_listener *listener; bool enabled; @@ -1470,6 +1494,11 @@ __mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core, if (WARN_ON(!group_item)) return -EINVAL; + if (group_item->fixed_policer && policer_id != group->init_policer_id) { + NL_SET_ERR_MSG_MOD(extack, "Changing the policer binding of this group is not supported"); + return -EOPNOTSUPP; + } + if (policer_id) { struct mlxsw_sp_trap_policer_item *policer_item; @@ -1682,10 +1711,23 @@ const struct mlxsw_sp_trap_ops mlxsw_sp1_trap_ops = { static const struct mlxsw_sp_trap_group_item mlxsw_sp2_trap_group_items_arr[] = { + { + .group = DEVLINK_TRAP_GROUP_GENERIC(BUFFER_DROPS, 20), + .hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_BUFFER_DISCARDS, + .priority = 0, + .fixed_policer = true, + }, }; static const struct mlxsw_sp_trap_item mlxsw_sp2_trap_items_arr[] = { + { + .trap = MLXSW_SP_TRAP_BUFFER_DROP(EARLY_DROP), + .listeners_arr = { + MLXSW_SP_RXL_BUFFER_DISCARD(INGRESS_WRED), + }, + .is_source = true, + }, }; static int From 54a9238589c533690c241fd3667a67d376d0a9cf Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Mon, 3 Aug 2020 19:11:40 +0300 Subject: [PATCH 8/9] mlxsw: spectrum_qdisc: Offload action trap for qevents When offloading action trap on a qevent, pass to_dev of NULL to the SPAN module to trigger the mirror to the CPU port. Query the buffer drops policer and use it for policing of the trapped traffic. Signed-off-by: Petr Machata Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum.h | 7 ++ .../ethernet/mellanox/mlxsw/spectrum_qdisc.c | 75 +++++++++++++++---- .../ethernet/mellanox/mlxsw/spectrum_trap.c | 26 +++++++ 3 files changed, 95 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index b808f6b4d670b..f9ba59641b4df 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -984,6 +984,10 @@ struct mlxsw_sp_mall_mirror_entry { int span_id; }; +struct mlxsw_sp_mall_trap_entry { + int span_id; +}; + struct mlxsw_sp_mall_entry { struct list_head list; unsigned long cookie; @@ -992,6 +996,7 @@ struct mlxsw_sp_mall_entry { bool ingress; union { struct mlxsw_sp_mall_mirror_entry mirror; + struct mlxsw_sp_mall_trap_entry trap; struct mlxsw_sp_port_sample sample; }; struct rcu_head rcu; @@ -1199,6 +1204,8 @@ int mlxsw_sp_trap_policer_counter_get(struct mlxsw_core *mlxsw_core, const struct devlink_trap_policer *policer, u64 *p_drops); +int mlxsw_sp_trap_group_policer_hw_id_get(struct mlxsw_sp *mlxsw_sp, u16 id, + bool *p_enabled, u16 *p_hw_id); static inline struct net *mlxsw_sp_net(struct mlxsw_sp *mlxsw_sp) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c index a5ce1eec54183..964fd444bb10c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c @@ -1289,19 +1289,18 @@ struct mlxsw_sp_qevent_binding { static LIST_HEAD(mlxsw_sp_qevent_block_cb_list); -static int mlxsw_sp_qevent_mirror_configure(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_mall_entry *mall_entry, - struct mlxsw_sp_qevent_binding *qevent_binding) +static int mlxsw_sp_qevent_span_configure(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_mall_entry *mall_entry, + struct mlxsw_sp_qevent_binding *qevent_binding, + const struct mlxsw_sp_span_agent_parms *agent_parms, + int *p_span_id) { struct mlxsw_sp_port *mlxsw_sp_port = qevent_binding->mlxsw_sp_port; struct mlxsw_sp_span_trigger_parms trigger_parms = {}; - struct mlxsw_sp_span_agent_parms agent_parms = { - .to_dev = mall_entry->mirror.to_dev, - }; int span_id; int err; - err = mlxsw_sp_span_agent_get(mlxsw_sp, &span_id, &agent_parms); + err = mlxsw_sp_span_agent_get(mlxsw_sp, &span_id, agent_parms); if (err) return err; @@ -1320,7 +1319,7 @@ static int mlxsw_sp_qevent_mirror_configure(struct mlxsw_sp *mlxsw_sp, if (err) goto err_trigger_enable; - mall_entry->mirror.span_id = span_id; + *p_span_id = span_id; return 0; err_trigger_enable: @@ -1333,13 +1332,13 @@ static int mlxsw_sp_qevent_mirror_configure(struct mlxsw_sp *mlxsw_sp, return err; } -static void mlxsw_sp_qevent_mirror_deconfigure(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_mall_entry *mall_entry, - struct mlxsw_sp_qevent_binding *qevent_binding) +static void mlxsw_sp_qevent_span_deconfigure(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_qevent_binding *qevent_binding, + int span_id) { struct mlxsw_sp_port *mlxsw_sp_port = qevent_binding->mlxsw_sp_port; struct mlxsw_sp_span_trigger_parms trigger_parms = { - .span_id = mall_entry->mirror.span_id, + .span_id = span_id, }; mlxsw_sp_span_trigger_disable(mlxsw_sp_port, qevent_binding->span_trigger, @@ -1347,7 +1346,51 @@ static void mlxsw_sp_qevent_mirror_deconfigure(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_span_agent_unbind(mlxsw_sp, qevent_binding->span_trigger, mlxsw_sp_port, &trigger_parms); mlxsw_sp_span_analyzed_port_put(mlxsw_sp_port, true); - mlxsw_sp_span_agent_put(mlxsw_sp, mall_entry->mirror.span_id); + mlxsw_sp_span_agent_put(mlxsw_sp, span_id); +} + +static int mlxsw_sp_qevent_mirror_configure(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_mall_entry *mall_entry, + struct mlxsw_sp_qevent_binding *qevent_binding) +{ + struct mlxsw_sp_span_agent_parms agent_parms = { + .to_dev = mall_entry->mirror.to_dev, + }; + + return mlxsw_sp_qevent_span_configure(mlxsw_sp, mall_entry, qevent_binding, + &agent_parms, &mall_entry->mirror.span_id); +} + +static void mlxsw_sp_qevent_mirror_deconfigure(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_mall_entry *mall_entry, + struct mlxsw_sp_qevent_binding *qevent_binding) +{ + mlxsw_sp_qevent_span_deconfigure(mlxsw_sp, qevent_binding, mall_entry->mirror.span_id); +} + +static int mlxsw_sp_qevent_trap_configure(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_mall_entry *mall_entry, + struct mlxsw_sp_qevent_binding *qevent_binding) +{ + struct mlxsw_sp_span_agent_parms agent_parms = {}; + int err; + + err = mlxsw_sp_trap_group_policer_hw_id_get(mlxsw_sp, + DEVLINK_TRAP_GROUP_GENERIC_ID_BUFFER_DROPS, + &agent_parms.policer_enable, + &agent_parms.policer_id); + if (err) + return err; + + return mlxsw_sp_qevent_span_configure(mlxsw_sp, mall_entry, qevent_binding, + &agent_parms, &mall_entry->trap.span_id); +} + +static void mlxsw_sp_qevent_trap_deconfigure(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_mall_entry *mall_entry, + struct mlxsw_sp_qevent_binding *qevent_binding) +{ + mlxsw_sp_qevent_span_deconfigure(mlxsw_sp, qevent_binding, mall_entry->trap.span_id); } static int mlxsw_sp_qevent_entry_configure(struct mlxsw_sp *mlxsw_sp, @@ -1357,6 +1400,8 @@ static int mlxsw_sp_qevent_entry_configure(struct mlxsw_sp *mlxsw_sp, switch (mall_entry->type) { case MLXSW_SP_MALL_ACTION_TYPE_MIRROR: return mlxsw_sp_qevent_mirror_configure(mlxsw_sp, mall_entry, qevent_binding); + case MLXSW_SP_MALL_ACTION_TYPE_TRAP: + return mlxsw_sp_qevent_trap_configure(mlxsw_sp, mall_entry, qevent_binding); default: /* This should have been validated away. */ WARN_ON(1); @@ -1371,6 +1416,8 @@ static void mlxsw_sp_qevent_entry_deconfigure(struct mlxsw_sp *mlxsw_sp, switch (mall_entry->type) { case MLXSW_SP_MALL_ACTION_TYPE_MIRROR: return mlxsw_sp_qevent_mirror_deconfigure(mlxsw_sp, mall_entry, qevent_binding); + case MLXSW_SP_MALL_ACTION_TYPE_TRAP: + return mlxsw_sp_qevent_trap_deconfigure(mlxsw_sp, mall_entry, qevent_binding); default: WARN_ON(1); return; @@ -1490,6 +1537,8 @@ static int mlxsw_sp_qevent_mall_replace(struct mlxsw_sp *mlxsw_sp, if (act->id == FLOW_ACTION_MIRRED) { mall_entry->type = MLXSW_SP_MALL_ACTION_TYPE_MIRROR; mall_entry->mirror.to_dev = act->dev; + } else if (act->id == FLOW_ACTION_TRAP) { + mall_entry->type = MLXSW_SP_MALL_ACTION_TYPE_TRAP; } else { NL_SET_ERR_MSG(f->common.extack, "Unsupported action"); err = -EOPNOTSUPP; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c index 16bf154076b3b..2e41c5519c1b7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c @@ -1675,6 +1675,32 @@ mlxsw_sp_trap_policer_counter_get(struct mlxsw_core *mlxsw_core, return 0; } +int mlxsw_sp_trap_group_policer_hw_id_get(struct mlxsw_sp *mlxsw_sp, u16 id, + bool *p_enabled, u16 *p_hw_id) +{ + struct mlxsw_sp_trap_policer_item *pol_item; + struct mlxsw_sp_trap_group_item *gr_item; + u32 pol_id; + + gr_item = mlxsw_sp_trap_group_item_lookup(mlxsw_sp, id); + if (!gr_item) + return -ENOENT; + + pol_id = gr_item->group.init_policer_id; + if (!pol_id) { + *p_enabled = false; + return 0; + } + + pol_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp, pol_id); + if (WARN_ON(!pol_item)) + return -ENOENT; + + *p_enabled = true; + *p_hw_id = pol_item->hw_id; + return 0; +} + static const struct mlxsw_sp_trap_group_item mlxsw_sp1_trap_group_items_arr[] = { }; From 8fb6ac457d5be8516eeed2b92342f7f95c448275 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Mon, 3 Aug 2020 19:11:41 +0300 Subject: [PATCH 9/9] selftests: mlxsw: RED: Test offload of trapping on RED qevents Add a selftest for RED early_drop and mark qevents when a trap action is attached at the associated block. Signed-off-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../drivers/net/mlxsw/sch_red_core.sh | 35 +++++++++++++++---- .../drivers/net/mlxsw/sch_red_ets.sh | 11 ++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh b/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh index 45042105ead76..517297a14ecfe 100644 --- a/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh @@ -568,17 +568,12 @@ do_drop_test() busywait 1100 until_counter_is ">= $((base + 1))" $fetch_counter >/dev/null check_fail $? "Spurious packets observed without buffer pressure" - qevent_rule_uninstall_$subtest - # Push to the queue until it's at the limit. The configured limit is # rounded by the qdisc and then by the driver, so this is the best we - # can do to get to the real limit of the system. Do this with the rules - # uninstalled so that the inevitable drops don't get counted. + # can do to get to the real limit of the system. build_backlog $vlan $((3 * limit / 2)) udp >/dev/null - qevent_rule_install_$subtest base=$($fetch_counter) - send_packets $vlan udp 11 now=$(busywait 1100 until_counter_is ">= $((base + 10))" $fetch_counter) @@ -631,3 +626,31 @@ do_drop_mirror_test() tc filter del dev $h2 ingress pref 1 handle 101 flower } + +qevent_rule_install_trap() +{ + tc filter add block 10 pref 1234 handle 102 matchall skip_sw \ + action trap hw_stats disabled +} + +qevent_rule_uninstall_trap() +{ + tc filter del block 10 pref 1234 handle 102 matchall +} + +qevent_counter_fetch_trap() +{ + local trap_name=$1; shift + + devlink_trap_rx_packets_get "$trap_name" +} + +do_drop_trap_test() +{ + local vlan=$1; shift + local limit=$1; shift + local trap_name=$1; shift + + do_drop_test "$vlan" "$limit" "$trap_name" trap \ + "qevent_counter_fetch_trap $trap_name" +} diff --git a/tools/testing/selftests/drivers/net/mlxsw/sch_red_ets.sh b/tools/testing/selftests/drivers/net/mlxsw/sch_red_ets.sh index c8968b041beaf..3f007c5f8361c 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/sch_red_ets.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/sch_red_ets.sh @@ -8,6 +8,7 @@ ALL_TESTS=" red_test mc_backlog_test red_mirror_test + red_trap_test " : ${QDISC:=ets} source sch_red_core.sh @@ -94,6 +95,16 @@ red_mirror_test() uninstall_qdisc } +red_trap_test() +{ + install_qdisc qevent early_drop block 10 + + do_drop_trap_test 10 $BACKLOG1 early_drop + do_drop_trap_test 11 $BACKLOG2 early_drop + + uninstall_qdisc +} + trap cleanup EXIT setup_prepare