diff options
author | Ido Schimmel <idosch@nvidia.com> | 2021-03-11 14:24:16 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2021-03-11 16:22:39 -0800 |
commit | cf31190ae0b788159a9874f0b28bbfde994741cd (patch) | |
tree | a06fea40c1ae27e95fe78d2cade39419aa68680b /drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c | |
parent | 34a277212c67a395b47b715aa89c4b4e2c957d42 (diff) |
mlxsw: spectrum_matchall: Implement sampling using mirroring
Spectrum-2 and later ASICs support sampling of packets by mirroring to
the CPU with probability. There are several advantages compared to the
legacy dedicated sampling mechanism:
* Extra metadata per-packet: Egress port, egress traffic class, traffic
class occupancy and end-to-end latency
* Ability to sample packets on egress / per-flow
Convert Spectrum-2 and later ASICs to perform sampling by mirroring to
the CPU with probability.
Subsequent patches will add support for egress / per-flow sampling and
expose the extra metadata.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c index ad1209df81ea..841a2de37f36 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c @@ -378,7 +378,60 @@ const struct mlxsw_sp_mall_ops mlxsw_sp1_mall_ops = { .sample_del = mlxsw_sp1_mall_sample_del, }; +static int mlxsw_sp2_mall_sample_add(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_port *mlxsw_sp_port, + u32 rate) +{ + struct mlxsw_sp_span_trigger_parms trigger_parms = {}; + struct mlxsw_sp_span_agent_parms agent_parms = { + .to_dev = NULL, /* Mirror to CPU. */ + .session_id = MLXSW_SP_SPAN_SESSION_ID_SAMPLING, + }; + struct mlxsw_sp_port_sample *sample; + int err; + + sample = rtnl_dereference(mlxsw_sp_port->sample); + + err = mlxsw_sp_span_agent_get(mlxsw_sp, &sample->span_id, &agent_parms); + if (err) + return err; + + err = mlxsw_sp_span_analyzed_port_get(mlxsw_sp_port, true); + if (err) + goto err_analyzed_port_get; + + trigger_parms.span_id = sample->span_id; + trigger_parms.probability_rate = rate; + err = mlxsw_sp_span_agent_bind(mlxsw_sp, MLXSW_SP_SPAN_TRIGGER_INGRESS, + mlxsw_sp_port, &trigger_parms); + if (err) + goto err_agent_bind; + + return 0; + +err_agent_bind: + mlxsw_sp_span_analyzed_port_put(mlxsw_sp_port, true); +err_analyzed_port_get: + mlxsw_sp_span_agent_put(mlxsw_sp, sample->span_id); + return err; +} + +static void mlxsw_sp2_mall_sample_del(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_port *mlxsw_sp_port) +{ + struct mlxsw_sp_span_trigger_parms trigger_parms = {}; + struct mlxsw_sp_port_sample *sample; + + sample = rtnl_dereference(mlxsw_sp_port->sample); + + trigger_parms.span_id = sample->span_id; + mlxsw_sp_span_agent_unbind(mlxsw_sp, MLXSW_SP_SPAN_TRIGGER_INGRESS, + mlxsw_sp_port, &trigger_parms); + mlxsw_sp_span_analyzed_port_put(mlxsw_sp_port, true); + mlxsw_sp_span_agent_put(mlxsw_sp, sample->span_id); +} + const struct mlxsw_sp_mall_ops mlxsw_sp2_mall_ops = { - .sample_add = mlxsw_sp1_mall_sample_add, - .sample_del = mlxsw_sp1_mall_sample_del, + .sample_add = mlxsw_sp2_mall_sample_add, + .sample_del = mlxsw_sp2_mall_sample_del, }; |