drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.c
Extension
.c
Size
20081 bytes
Lines
656
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct mlx5e_tc_psample {
	struct mlx5_eswitch *esw;
	struct mlx5_flow_table *termtbl;
	struct mlx5_flow_handle *termtbl_rule;
	DECLARE_HASHTABLE(hashtbl, 8);
	struct mutex ht_lock; /* protect hashtbl */
	DECLARE_HASHTABLE(restore_hashtbl, 8);
	struct mutex restore_lock; /* protect restore_hashtbl */
	struct mlx5e_post_act *post_act;
};

struct mlx5e_sampler {
	struct hlist_node hlist;
	u32 sampler_id;
	u32 sample_ratio;
	u32 sample_table_id;
	u32 default_table_id;
	int count;
};

struct mlx5e_sample_flow {
	struct mlx5e_sampler *sampler;
	struct mlx5e_sample_restore *restore;
	struct mlx5_flow_attr *pre_attr;
	struct mlx5_flow_handle *pre_rule;
	struct mlx5_flow_attr *post_attr;
	struct mlx5_flow_handle *post_rule;
};

struct mlx5e_sample_restore {
	struct hlist_node hlist;
	struct mlx5_modify_hdr *modify_hdr;
	struct mlx5_flow_handle *rule;
	u32 obj_id;
	int count;
};

static int
sampler_termtbl_create(struct mlx5e_tc_psample *tc_psample)
{
	struct mlx5_eswitch *esw = tc_psample->esw;
	struct mlx5_flow_table_attr ft_attr = {};
	struct mlx5_flow_destination dest = {};
	struct mlx5_core_dev *dev = esw->dev;
	struct mlx5_flow_namespace *root_ns;
	struct mlx5_flow_act act = {};
	int err;

	if (!MLX5_CAP_ESW_FLOWTABLE_FDB(dev, termination_table))  {
		mlx5_core_warn(dev, "termination table is not supported\n");
		return -EOPNOTSUPP;
	}

	root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB);
	if (!root_ns) {
		mlx5_core_warn(dev, "failed to get FDB flow namespace\n");
		return -EOPNOTSUPP;
	}

	ft_attr.flags = MLX5_FLOW_TABLE_TERMINATION | MLX5_FLOW_TABLE_UNMANAGED;
	ft_attr.autogroup.max_num_groups = 1;
	ft_attr.prio = FDB_SLOW_PATH;
	ft_attr.max_fte = 1;
	ft_attr.level = 1;
	tc_psample->termtbl = mlx5_create_auto_grouped_flow_table(root_ns, &ft_attr);
	if (IS_ERR(tc_psample->termtbl)) {
		err = PTR_ERR(tc_psample->termtbl);
		mlx5_core_warn(dev, "failed to create termtbl, err: %d\n", err);
		return err;
	}

	act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
	dest.vport.num = esw->manager_vport;
	dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
	tc_psample->termtbl_rule = mlx5_add_flow_rules(tc_psample->termtbl, NULL, &act, &dest, 1);
	if (IS_ERR(tc_psample->termtbl_rule)) {
		err = PTR_ERR(tc_psample->termtbl_rule);
		mlx5_core_warn(dev, "failed to create termtbl rule, err: %d\n", err);
		mlx5_destroy_flow_table(tc_psample->termtbl);
		return err;
	}

	return 0;
}

static void
sampler_termtbl_destroy(struct mlx5e_tc_psample *tc_psample)
{
	mlx5_del_flow_rules(tc_psample->termtbl_rule);
	mlx5_destroy_flow_table(tc_psample->termtbl);

Annotation

Implementation Notes