Commit 0c1f391d authored by Jiri Pirko's avatar Jiri Pirko Committed by David S. Miller
Browse files

mlxsw: spectrum_flower: Implement support for ingress device matching



Benefit from the previously extended flow_dissector infrastructure and
offload matching on ingress port.

Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d8e94614
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -623,6 +623,15 @@ enum mlxsw_sp_acl_profile {
	MLXSW_SP_ACL_PROFILE_MR,
};

struct mlxsw_sp_acl_block {
	struct list_head binding_list;
	struct mlxsw_sp_acl_ruleset *ruleset_zero;
	struct mlxsw_sp *mlxsw_sp;
	unsigned int rule_count;
	unsigned int disable_count;
	struct net *net;
};

struct mlxsw_afk *mlxsw_sp_acl_afk(struct mlxsw_sp_acl *acl);
struct mlxsw_sp *mlxsw_sp_acl_block_mlxsw_sp(struct mlxsw_sp_acl_block *block);
unsigned int mlxsw_sp_acl_block_rule_count(struct mlxsw_sp_acl_block *block);
+1 −8
Original line number Diff line number Diff line
@@ -45,14 +45,6 @@ struct mlxsw_sp_acl_block_binding {
	bool ingress;
};

struct mlxsw_sp_acl_block {
	struct list_head binding_list;
	struct mlxsw_sp_acl_ruleset *ruleset_zero;
	struct mlxsw_sp *mlxsw_sp;
	unsigned int rule_count;
	unsigned int disable_count;
};

struct mlxsw_sp_acl_ruleset_ht_key {
	struct mlxsw_sp_acl_block *block;
	u32 chain_index;
@@ -221,6 +213,7 @@ struct mlxsw_sp_acl_block *mlxsw_sp_acl_block_create(struct mlxsw_sp *mlxsw_sp,
		return NULL;
	INIT_LIST_HEAD(&block->binding_list);
	block->mlxsw_sp = mlxsw_sp;
	block->net = net;
	return block;
}

+49 −1
Original line number Diff line number Diff line
@@ -120,6 +120,49 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
	return 0;
}

static int mlxsw_sp_flower_parse_meta(struct mlxsw_sp_acl_rule_info *rulei,
				      struct tc_cls_flower_offload *f,
				      struct mlxsw_sp_acl_block *block)
{
	struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f);
	struct mlxsw_sp_port *mlxsw_sp_port;
	struct net_device *ingress_dev;
	struct flow_match_meta match;

	if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META))
		return 0;

	flow_rule_match_meta(rule, &match);
	if (match.mask->ingress_ifindex != 0xFFFFFFFF) {
		NL_SET_ERR_MSG_MOD(f->common.extack, "Unsupported ingress ifindex mask");
		return -EINVAL;
	}

	ingress_dev = __dev_get_by_index(block->net,
					 match.key->ingress_ifindex);
	if (!ingress_dev) {
		NL_SET_ERR_MSG_MOD(f->common.extack, "Can't find specified ingress port to match on");
		return -EINVAL;
	}

	if (!mlxsw_sp_port_dev_check(ingress_dev)) {
		NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on non-mlxsw ingress port");
		return -EINVAL;
	}

	mlxsw_sp_port = netdev_priv(ingress_dev);
	if (mlxsw_sp_port->mlxsw_sp != block->mlxsw_sp) {
		NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on a port from different device");
		return -EINVAL;
	}

	mlxsw_sp_acl_rulei_keymask_u32(rulei,
				       MLXSW_AFK_ELEMENT_SRC_SYS_PORT,
				       mlxsw_sp_port->local_port,
				       0xFFFFFFFF);
	return 0;
}

static void mlxsw_sp_flower_parse_ipv4(struct mlxsw_sp_acl_rule_info *rulei,
				       struct tc_cls_flower_offload *f)
{
@@ -267,7 +310,8 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp,
	int err;

	if (dissector->used_keys &
	    ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
	    ~(BIT(FLOW_DISSECTOR_KEY_META) |
	      BIT(FLOW_DISSECTOR_KEY_CONTROL) |
	      BIT(FLOW_DISSECTOR_KEY_BASIC) |
	      BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
	      BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
@@ -283,6 +327,10 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp,

	mlxsw_sp_acl_rulei_priority(rulei, f->common.prio);

	err = mlxsw_sp_flower_parse_meta(rulei, f, block);
	if (err)
		return err;

	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
		struct flow_match_control match;