drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlxsw/spectrum_matchall.c
Extension
.c
Size
14198 bytes
Lines
479
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 (err != -ENOENT) {
			NL_SET_ERR_MSG(f->common.extack, "Failed to get flower priorities");
			return err;
		}
		flower_prio_valid = false;
		/* No flower filters are installed in specified chain. */
	} else {
		flower_prio_valid = true;
	}

	if (protocol != htons(ETH_P_ALL)) {
		NL_SET_ERR_MSG(f->common.extack, "matchall rules only supported with 'all' protocol");
		return -EOPNOTSUPP;
	}

	mall_entry = kzalloc_obj(*mall_entry);
	if (!mall_entry)
		return -ENOMEM;
	mall_entry->cookie = f->cookie;
	mall_entry->priority = f->common.prio;
	mall_entry->ingress = mlxsw_sp_flow_block_is_ingress_bound(block);

	if (flower_prio_valid && mall_entry->ingress &&
	    mall_entry->priority >= flower_min_prio) {
		NL_SET_ERR_MSG(f->common.extack, "Failed to add behind existing flower rules");
		err = -EOPNOTSUPP;
		goto errout;
	}
	if (flower_prio_valid && !mall_entry->ingress &&
	    mall_entry->priority <= flower_max_prio) {
		NL_SET_ERR_MSG(f->common.extack, "Failed to add in front of existing flower rules");
		err = -EOPNOTSUPP;
		goto errout;
	}

	act = &f->rule->action.entries[0];

	switch (act->id) {
	case FLOW_ACTION_MIRRED:
		mall_entry->type = MLXSW_SP_MALL_ACTION_TYPE_MIRROR;
		mall_entry->mirror.to_dev = act->dev;
		break;
	case FLOW_ACTION_SAMPLE:
		mall_entry->type = MLXSW_SP_MALL_ACTION_TYPE_SAMPLE;
		mall_entry->sample.params.psample_group = act->sample.psample_group;
		mall_entry->sample.params.truncate = act->sample.truncate;
		mall_entry->sample.params.trunc_size = act->sample.trunc_size;
		mall_entry->sample.params.rate = act->sample.rate;
		break;
	default:
		err = -EOPNOTSUPP;
		goto errout;
	}

	list_for_each_entry(binding, &block->binding_list, list) {
		err = mlxsw_sp_mall_port_rule_add(binding->mlxsw_sp_port,
						  mall_entry, f->common.extack);
		if (err)
			goto rollback;
	}

	block->rule_count++;
	if (mall_entry->ingress)
		block->egress_blocker_rule_count++;
	else
		block->ingress_blocker_rule_count++;
	list_add_tail(&mall_entry->list, &block->mall.list);
	mlxsw_sp_mall_prio_update(block);
	return 0;

rollback:
	list_for_each_entry_continue_reverse(binding, &block->binding_list,
					     list)
		mlxsw_sp_mall_port_rule_del(binding->mlxsw_sp_port, mall_entry);
errout:
	kfree(mall_entry);
	return err;
}

void mlxsw_sp_mall_destroy(struct mlxsw_sp_flow_block *block,
			   struct tc_cls_matchall_offload *f)
{
	struct mlxsw_sp_flow_block_binding *binding;
	struct mlxsw_sp_mall_entry *mall_entry;

	mall_entry = mlxsw_sp_mall_entry_find(block, f->cookie);
	if (!mall_entry) {
		NL_SET_ERR_MSG(f->common.extack, "Entry not found");
		return;
	}

Annotation

Implementation Notes