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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/en/tc/int_port.c
Extension
.c
Size
12087 bytes
Lines
460
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_int_port {
	enum mlx5e_tc_int_port_type type;
	int ifindex;
	u32 match_metadata;
	u32 mapping;
	struct list_head list;
	struct mlx5_flow_handle *rx_rule;
	refcount_t refcnt;
	struct rcu_head rcu_head;
};

struct mlx5e_tc_int_port_priv {
	struct mlx5_core_dev *dev;
	struct mutex int_ports_lock; /* Protects int ports list */
	struct list_head int_ports; /* Uses int_ports_lock */
	u16 num_ports;
	bool ul_rep_rx_ready; /* Set when uplink is performing teardown */
	struct mapping_ctx *metadata_mapping; /* Metadata for source port rewrite and matching */
};

bool mlx5e_tc_int_port_supported(const struct mlx5_eswitch *esw)
{
	return mlx5_eswitch_vport_match_metadata_enabled(esw) &&
	       MLX5_CAP_GEN(esw->dev, reg_c_preserve);
}

u32 mlx5e_tc_int_port_get_metadata(struct mlx5e_tc_int_port *int_port)
{
	return int_port->match_metadata;
}

int mlx5e_tc_int_port_get_flow_source(struct mlx5e_tc_int_port *int_port)
{
	/* For egress forwarding we can have the case
	 * where the packet came from a vport and redirected
	 * to int port or it came from the uplink, going
	 * via internal port and hairpinned back to uplink
	 * so we set the source to any port in this case.
	 */
	return int_port->type == MLX5E_TC_INT_PORT_EGRESS ?
		MLX5_FLOW_CONTEXT_FLOW_SOURCE_ANY_VPORT :
		MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK;
}

u32 mlx5e_tc_int_port_get_metadata_for_match(struct mlx5e_tc_int_port *int_port)
{
	return int_port->match_metadata << (32 - ESW_SOURCE_PORT_METADATA_BITS);
}

static struct mlx5_flow_handle *
mlx5e_int_port_create_rx_rule(struct mlx5_eswitch *esw,
			      struct mlx5e_tc_int_port *int_port,
			      struct mlx5_flow_destination *dest)

{
	struct mlx5_flow_context *flow_context;
	struct mlx5_flow_act flow_act = {};
	struct mlx5_flow_handle *flow_rule;
	struct mlx5_flow_spec *spec;
	void *misc;

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

	misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_2);
	MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
		 mlx5e_tc_int_port_get_metadata_for_match(int_port));

	misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters_2);
	MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
		 mlx5_eswitch_get_vport_metadata_mask());

	spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;

	/* Overwrite flow tag with the int port metadata mapping
	 * instead of the chain mapping.
	 */
	flow_context = &spec->flow_context;
	flow_context->flags |= FLOW_CONTEXT_HAS_TAG;
	flow_context->flow_tag = int_port->mapping;
	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
	flow_rule = mlx5_add_flow_rules(esw->offloads.ft_offloads, spec,
					&flow_act, dest, 1);
	if (IS_ERR(flow_rule))
		mlx5_core_warn(esw->dev, "ft offloads: Failed to add internal vport rx rule err %pe\n",
			       flow_rule);

	kvfree(spec);

Annotation

Implementation Notes