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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c
Extension
.c
Size
9928 bytes
Lines
339
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 mlx5_ct_fs_smfs_matcher {
	struct mlx5dr_matcher *dr_matcher;
	struct list_head list;
	int prio;
	refcount_t ref;
};

struct mlx5_ct_fs_smfs_matchers {
	struct mlx5_ct_fs_smfs_matcher smfs_matchers[6];
	struct list_head used;
};

struct mlx5_ct_fs_smfs {
	struct mlx5dr_table *ct_tbl, *ct_nat_tbl;
	struct mlx5_ct_fs_smfs_matchers matchers;
	struct mlx5_ct_fs_smfs_matchers matchers_nat;
	struct mlx5dr_action *fwd_action;
	struct mlx5_flow_table *ct_nat;
	struct mutex lock; /* Guards matchers */
};

struct mlx5_ct_fs_smfs_rule {
	struct mlx5_ct_fs_rule fs_rule;
	struct mlx5dr_rule *rule;
	struct mlx5dr_action *count_action;
	struct mlx5_ct_fs_smfs_matcher *smfs_matcher;
};

static inline void
mlx5_ct_fs_smfs_fill_mask(struct mlx5_ct_fs *fs, struct mlx5_flow_spec *spec, bool ipv4, bool tcp,
			  bool gre)
{
	void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, outer_headers);

	if (likely(MLX5_CAP_FLOWTABLE_NIC_RX(fs->dev, ft_field_support.outer_ip_version)))
		MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ip_version);
	else
		MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ethertype);

	MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ip_protocol);
	if (likely(ipv4)) {
		MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c,
				 src_ipv4_src_ipv6.ipv4_layout.ipv4);
		MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c,
				 dst_ipv4_dst_ipv6.ipv4_layout.ipv4);
	} else {
		memset(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
				    dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
		       0xFF,
		       MLX5_FLD_SZ_BYTES(fte_match_set_lyr_2_4,
					 dst_ipv4_dst_ipv6.ipv6_layout.ipv6));
		memset(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
				    src_ipv4_src_ipv6.ipv6_layout.ipv6),
		       0xFF,
		       MLX5_FLD_SZ_BYTES(fte_match_set_lyr_2_4,
					 src_ipv4_src_ipv6.ipv6_layout.ipv6));
	}

	if (likely(tcp)) {
		MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, tcp_sport);
		MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, tcp_dport);
		MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_flags,
			 ntohs(MLX5_CT_TCP_FLAGS_MASK));
	} else if (!gre) {
		MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, udp_sport);
		MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, udp_dport);
	}

	mlx5e_tc_match_to_reg_match(spec, ZONE_TO_REG, 0, MLX5_CT_ZONE_MASK);
}

static struct mlx5dr_matcher *
mlx5_ct_fs_smfs_matcher_create(struct mlx5_ct_fs *fs, struct mlx5dr_table *tbl, bool ipv4,
			       bool tcp, bool gre, u32 priority)
{
	struct mlx5dr_matcher *dr_matcher;
	struct mlx5_flow_spec *spec;

	spec = kvzalloc_obj(*spec);
	if (!spec)
		return ERR_PTR(-ENOMEM);

	mlx5_ct_fs_smfs_fill_mask(fs, spec, ipv4, tcp, gre);
	spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2 | MLX5_MATCH_OUTER_HEADERS;

	dr_matcher = mlx5_smfs_matcher_create(tbl, priority, spec);
	kvfree(spec);
	if (!dr_matcher)
		return ERR_PTR(-EINVAL);

Annotation

Implementation Notes