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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c
Extension
.c
Size
33284 bytes
Lines
1135
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 (bridge->vlan_proto == ETH_P_8021Q) {
			MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
					 outer_headers.cvlan_tag);
			MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value,
					 outer_headers.cvlan_tag);
		} else if (bridge->vlan_proto == ETH_P_8021AD) {
			MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
					 outer_headers.svlan_tag);
			MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value,
					 outer_headers.svlan_tag);
		}
		MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
				 outer_headers.first_vid);
		MLX5_SET(fte_match_param, rule_spec->match_value, outer_headers.first_vid,
			 entry->key.vid);
	}

	handle = mlx5_add_flow_rules(bridge->egress_ft, rule_spec, &flow_act, dests, num_dests);

	kvfree(dests);
	kvfree(rule_spec);
	return handle;
}

static int
mlx5_esw_bridge_port_mdb_offload(struct mlx5_esw_bridge_port *port,
				 struct mlx5_esw_bridge_mdb_entry *entry)
{
	struct mlx5_flow_handle *handle;

	handle = mlx5_esw_bridge_mdb_flow_create(port->esw_owner_vhca_id, entry, port->bridge);
	if (entry->egress_handle) {
		mlx5_del_flow_rules(entry->egress_handle);
		entry->egress_handle = NULL;
	}
	if (IS_ERR(handle))
		return PTR_ERR(handle);

	entry->egress_handle = handle;
	return 0;
}

static struct mlx5_esw_bridge_mdb_entry *
mlx5_esw_bridge_mdb_lookup(struct mlx5_esw_bridge *bridge,
			   const unsigned char *addr, u16 vid)
{
	struct mlx5_esw_bridge_mdb_key key = {};

	ether_addr_copy(key.addr, addr);
	key.vid = vid;
	return rhashtable_lookup_fast(&bridge->mdb_ht, &key, mdb_ht_params);
}

static struct mlx5_esw_bridge_mdb_entry *
mlx5_esw_bridge_port_mdb_entry_init(struct mlx5_esw_bridge_port *port,
				    const unsigned char *addr, u16 vid)
{
	struct mlx5_esw_bridge *bridge = port->bridge;
	struct mlx5_esw_bridge_mdb_entry *entry;
	int err;

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

	ether_addr_copy(entry->key.addr, addr);
	entry->key.vid = vid;
	xa_init(&entry->ports);
	err = rhashtable_insert_fast(&bridge->mdb_ht, &entry->ht_node, mdb_ht_params);
	if (err)
		goto err_ht_insert;

	list_add(&entry->list, &bridge->mdb_list);

	return entry;

err_ht_insert:
	xa_destroy(&entry->ports);
	kvfree(entry);
	return ERR_PTR(err);
}

static void mlx5_esw_bridge_port_mdb_entry_cleanup(struct mlx5_esw_bridge *bridge,
						   struct mlx5_esw_bridge_mdb_entry *entry)
{
	if (entry->egress_handle)
		mlx5_del_flow_rules(entry->egress_handle);
	list_del(&entry->list);
	rhashtable_remove_fast(&bridge->mdb_ht, &entry->ht_node, mdb_ht_params);
	xa_destroy(&entry->ports);

Annotation

Implementation Notes