Commit cf31190a authored by Ido Schimmel's avatar Ido Schimmel Committed by David S. Miller
Browse files

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: default avatarIdo Schimmel <idosch@nvidia.com>
Reviewed-by: default avatarJiri Pirko <jiri@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 34a27721
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -238,6 +238,7 @@ struct mlxsw_sp_port_sample {
	u32 trunc_size;
	u32 rate;
	bool truncate;
	int span_id;	/* Relevant for Spectrum-2 onwards. */
};

struct mlxsw_sp_bridge_port;
+55 −2
Original line number Diff line number Diff line
@@ -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,
};
+1 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ struct mlxsw_sp_port;
 */
enum mlxsw_sp_span_session_id {
	MLXSW_SP_SPAN_SESSION_ID_BUFFER,
	MLXSW_SP_SPAN_SESSION_ID_SAMPLING,

	__MLXSW_SP_SPAN_SESSION_ID_MAX = 8,
};
+6 −2
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@ enum {
#define MLXSW_SP_TRAP_METADATA DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT

enum {
	/* Packet was mirrored from ingress. */
	MLXSW_SP_MIRROR_REASON_INGRESS = 1,
	/* Packet was early dropped. */
	MLXSW_SP_MIRROR_REASON_INGRESS_WRED = 9,
};
@@ -1753,6 +1755,7 @@ mlxsw_sp2_trap_group_items_arr[] = {
		.group = DEVLINK_TRAP_GROUP_GENERIC(ACL_SAMPLE, 0),
		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_PKT_SAMPLE,
		.priority = 0,
		.fixed_policer = true,
	},
};

@@ -1769,8 +1772,9 @@ mlxsw_sp2_trap_items_arr[] = {
		.trap = MLXSW_SP_TRAP_CONTROL(FLOW_ACTION_SAMPLE, ACL_SAMPLE,
					      MIRROR),
		.listeners_arr = {
			MLXSW_RXL(mlxsw_sp_rx_sample_listener, PKT_SAMPLE,
				  MIRROR_TO_CPU, false, SP_PKT_SAMPLE, DISCARD),
			MLXSW_RXL_MIRROR(mlxsw_sp_rx_sample_listener, 1,
					 SP_PKT_SAMPLE,
					 MLXSW_SP_MIRROR_REASON_INGRESS),
		},
	},
};