Commit e2a1a004 authored by Aya Levin's avatar Aya Levin Committed by Jakub Kicinski
Browse files

net/mlx5e: Add flow steering VLAN trap rule



Add flow group to the VLAN table to hold the catch-all VLAN rule. Add
API which adds/removes VLAN trap rule. This rule catches packets that
were destined to be dropped due to no-match with previous VLAN rules.
The trap rule steer these packets to the trap tir related to the
trap-RQ.

Signed-off-by: default avatarAya Levin <ayal@nvidia.com>
Reviewed-by: default avatarMoshe Shemesh <moshe@nvidia.com>
Reviewed-by: default avatarTariq Toukan <tariqt@nvidia.com>
Signed-off-by: default avatarTariq Toukan <tariqt@nvidia.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@nvidia.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 1c46d740
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ struct mlx5e_vlan_table {
	struct mlx5_flow_handle	*untagged_rule;
	struct mlx5_flow_handle	*any_cvlan_rule;
	struct mlx5_flow_handle	*any_svlan_rule;
	struct mlx5_flow_handle	*trap_rule;
	bool			cvlan_filter_disabled;
};

@@ -294,6 +295,8 @@ int mlx5e_create_flow_steering(struct mlx5e_priv *priv);
void mlx5e_destroy_flow_steering(struct mlx5e_priv *priv);

u8 mlx5e_get_proto_by_tunnel_type(enum mlx5e_tunnel_types tt);
int mlx5e_add_vlan_trap(struct mlx5e_priv *priv, int  trap_id, int tir_num);
void mlx5e_remove_vlan_trap(struct mlx5e_priv *priv);

#endif /* __MLX5E_FLOW_STEER_H__ */
+62 −2
Original line number Diff line number Diff line
@@ -305,6 +305,53 @@ static int mlx5e_add_any_vid_rules(struct mlx5e_priv *priv)
	return mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_STAG_VID, 0);
}

static struct mlx5_flow_handle *
mlx5e_add_trap_rule(struct mlx5_flow_table *ft, int trap_id, int tir_num)
{
	struct mlx5_flow_destination dest = {};
	MLX5_DECLARE_FLOW_ACT(flow_act);
	struct mlx5_flow_handle *rule;
	struct mlx5_flow_spec *spec;

	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
	if (!spec)
		return ERR_PTR(-ENOMEM);
	spec->flow_context.flags |= FLOW_CONTEXT_HAS_TAG;
	spec->flow_context.flow_tag = trap_id;
	dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
	dest.tir_num = tir_num;

	rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
	kvfree(spec);
	return rule;
}

int mlx5e_add_vlan_trap(struct mlx5e_priv *priv, int trap_id, int tir_num)
{
	struct mlx5_flow_table *ft = priv->fs.vlan.ft.t;
	struct mlx5_flow_handle *rule;
	int err;

	rule = mlx5e_add_trap_rule(ft, trap_id, tir_num);
	if (IS_ERR(rule)) {
		err = PTR_ERR(rule);
		priv->fs.vlan.trap_rule = NULL;
		netdev_err(priv->netdev, "%s: add VLAN trap rule failed, err %d\n",
			   __func__, err);
		return err;
	}
	priv->fs.vlan.trap_rule = rule;
	return 0;
}

void mlx5e_remove_vlan_trap(struct mlx5e_priv *priv)
{
	if (priv->fs.vlan.trap_rule) {
		mlx5_del_flow_rules(priv->fs.vlan.trap_rule);
		priv->fs.vlan.trap_rule = NULL;
	}
}

void mlx5e_enable_cvlan_filter(struct mlx5e_priv *priv)
{
	if (!priv->fs.vlan.cvlan_filter_disabled)
@@ -418,6 +465,8 @@ static void mlx5e_del_vlan_rules(struct mlx5e_priv *priv)

	WARN_ON_ONCE(!(test_bit(MLX5E_STATE_DESTROYING, &priv->state)));

	mlx5e_remove_vlan_trap(priv);

	/* must be called after DESTROY bit is set and
	 * set_rx_mode is called and flushed
	 */
@@ -1495,15 +1544,17 @@ static int mlx5e_create_l2_table(struct mlx5e_priv *priv)
	return err;
}

#define MLX5E_NUM_VLAN_GROUPS	4
#define MLX5E_NUM_VLAN_GROUPS	5
#define MLX5E_VLAN_GROUP0_SIZE	BIT(12)
#define MLX5E_VLAN_GROUP1_SIZE	BIT(12)
#define MLX5E_VLAN_GROUP2_SIZE	BIT(1)
#define MLX5E_VLAN_GROUP3_SIZE	BIT(0)
#define MLX5E_VLAN_GROUP_TRAP_SIZE BIT(0) /* must be last */
#define MLX5E_VLAN_TABLE_SIZE	(MLX5E_VLAN_GROUP0_SIZE +\
				 MLX5E_VLAN_GROUP1_SIZE +\
				 MLX5E_VLAN_GROUP2_SIZE +\
				 MLX5E_VLAN_GROUP3_SIZE)
				 MLX5E_VLAN_GROUP3_SIZE +\
				 MLX5E_VLAN_GROUP_TRAP_SIZE)

static int __mlx5e_create_vlan_table_groups(struct mlx5e_flow_table *ft, u32 *in,
					    int inlen)
@@ -1558,6 +1609,15 @@ static int __mlx5e_create_vlan_table_groups(struct mlx5e_flow_table *ft, u32 *in
		goto err_destroy_groups;
	ft->num_groups++;

	memset(in, 0, inlen);
	MLX5_SET_CFG(in, start_flow_index, ix);
	ix += MLX5E_VLAN_GROUP_TRAP_SIZE;
	MLX5_SET_CFG(in, end_flow_index, ix - 1);
	ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
	if (IS_ERR(ft->g[ft->num_groups]))
		goto err_destroy_groups;
	ft->num_groups++;

	return 0;

err_destroy_groups: