drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
Extension
.c
Size
60930 bytes
Lines
1956
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

if (IS_ERR(miss_fg)) {
			esw_warn(esw->dev, "Failed to create miss flow group (err=%pe)\n",
				 miss_fg);
			miss_fg = NULL;
			goto skip_miss_flow;
		}

		miss_pkt_reformat = mlx5_esw_bridge_pkt_reformat_vlan_pop_create(esw);
		if (IS_ERR(miss_pkt_reformat)) {
			esw_warn(esw->dev,
				 "Failed to alloc packet reformat REMOVE_HEADER (err=%pe)\n",
				 miss_pkt_reformat);
			miss_pkt_reformat = NULL;
			mlx5_destroy_flow_group(miss_fg);
			miss_fg = NULL;
			goto skip_miss_flow;
		}

		miss_handle = mlx5_esw_bridge_egress_miss_flow_create(egress_ft,
								      br_offloads->skip_ft,
								      miss_pkt_reformat);
		if (IS_ERR(miss_handle)) {
			esw_warn(esw->dev, "Failed to create miss flow (err=%pe)\n",
				 miss_handle);
			miss_handle = NULL;
			mlx5_packet_reformat_dealloc(esw->dev, miss_pkt_reformat);
			miss_pkt_reformat = NULL;
			mlx5_destroy_flow_group(miss_fg);
			miss_fg = NULL;
			goto skip_miss_flow;
		}
	}
skip_miss_flow:

	bridge->egress_ft = egress_ft;
	bridge->egress_vlan_fg = vlan_fg;
	bridge->egress_qinq_fg = qinq_fg;
	bridge->egress_mac_fg = mac_fg;
	bridge->egress_miss_fg = miss_fg;
	bridge->egress_miss_pkt_reformat = miss_pkt_reformat;
	bridge->egress_miss_handle = miss_handle;
	return 0;

err_mac_fg:
	mlx5_destroy_flow_group(qinq_fg);
err_qinq_fg:
	mlx5_destroy_flow_group(vlan_fg);
err_vlan_fg:
	mlx5_destroy_flow_table(egress_ft);
	return err;
}

static void
mlx5_esw_bridge_egress_table_cleanup(struct mlx5_esw_bridge *bridge)
{
	if (bridge->egress_miss_handle)
		mlx5_del_flow_rules(bridge->egress_miss_handle);
	if (bridge->egress_miss_pkt_reformat)
		mlx5_packet_reformat_dealloc(bridge->br_offloads->esw->dev,
					     bridge->egress_miss_pkt_reformat);
	if (bridge->egress_miss_fg)
		mlx5_destroy_flow_group(bridge->egress_miss_fg);
	mlx5_destroy_flow_group(bridge->egress_mac_fg);
	mlx5_destroy_flow_group(bridge->egress_qinq_fg);
	mlx5_destroy_flow_group(bridge->egress_vlan_fg);
	mlx5_destroy_flow_table(bridge->egress_ft);
}

static struct mlx5_flow_handle *
mlx5_esw_bridge_ingress_flow_with_esw_create(u16 vport_num, const unsigned char *addr,
					     struct mlx5_esw_bridge_vlan *vlan,
					     struct mlx5_fc *counter,
					     struct mlx5_esw_bridge *bridge,
					     struct mlx5_eswitch *esw)
{
	struct mlx5_esw_bridge_offloads *br_offloads = bridge->br_offloads;
	struct mlx5_flow_act flow_act = {
		.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_COUNT,
		.flags = FLOW_ACT_NO_APPEND,
	};
	struct mlx5_flow_destination dests[2] = {};
	struct mlx5_flow_spec *rule_spec;
	struct mlx5_flow_handle *handle;
	u8 *smac_v, *smac_c;

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

	rule_spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS | MLX5_MATCH_MISC_PARAMETERS_2;

Annotation

Implementation Notes