Blame SOURCES/0085-netdrv-net-mlx5-Refactor-ingress-acl-configuration.patch

d8f823
From ccb016735ab552893c77a5deeeef4d795c18448e Mon Sep 17 00:00:00 2001
d8f823
From: Alaa Hleihel <ahleihel@redhat.com>
d8f823
Date: Sun, 10 May 2020 15:04:02 -0400
d8f823
Subject: [PATCH 085/312] [netdrv] net/mlx5: Refactor ingress acl configuration
d8f823
d8f823
Message-id: <20200510150452.10307-38-ahleihel@redhat.com>
d8f823
Patchwork-id: 306661
d8f823
Patchwork-instance: patchwork
d8f823
O-Subject: [RHEL8.3 BZ 1789380 v2 37/87] net/mlx5: Refactor ingress acl configuration
d8f823
Bugzilla: 1789380
d8f823
RH-Acked-by: Kamal Heib <kheib@redhat.com>
d8f823
RH-Acked-by: Jarod Wilson <jarod@redhat.com>
d8f823
RH-Acked-by: Tony Camuso <tcamuso@redhat.com>
d8f823
RH-Acked-by: Jonathan Toppins <jtoppins@redhat.com>
d8f823
d8f823
Bugzilla: http://bugzilla.redhat.com/1789380
d8f823
Upstream: v5.5-rc1
d8f823
d8f823
commit 10652f39943ec19d32a6fa44a8523b0d40abcbcf
d8f823
Author: Parav Pandit <parav@mellanox.com>
d8f823
Date:   Mon Oct 28 23:35:26 2019 +0000
d8f823
d8f823
    net/mlx5: Refactor ingress acl configuration
d8f823
d8f823
    Drop, untagged, spoof check and untagged spoof check flow groups are
d8f823
    limited to legacy mode only.
d8f823
d8f823
    Therefore, following refactoring is done to
d8f823
    (a) improve code readability
d8f823
    (b) have better code split between legacy and offloads mode
d8f823
d8f823
    1. Move legacy flow groups under legacy structure
d8f823
    2. Add validity check for group deletion
d8f823
    3. Restrict scope of esw_vport_disable_ingress_acl to legacy mode
d8f823
    4. Rename esw_vport_enable_ingress_acl() to
d8f823
    esw_vport_create_ingress_acl_table() and limit its scope to
d8f823
    table creation
d8f823
    5. Introduce legacy flow groups creation helper
d8f823
    esw_legacy_create_ingress_acl_groups() and keep its scope to legacy mode
d8f823
    6. Reduce offloads ingress groups from 4 to just 1 metadata group
d8f823
    per vport
d8f823
    7. Removed redundant IS_ERR_OR_NULL as entries are marked NULL on free.
d8f823
    8. Shortern error message to remove redundant 'E-switch'
d8f823
d8f823
    Signed-off-by: Parav Pandit <parav@mellanox.com>
d8f823
    Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
d8f823
d8f823
Signed-off-by: Alaa Hleihel <ahleihel@redhat.com>
d8f823
Signed-off-by: Frantisek Hrbata <fhrbata@redhat.com>
d8f823
---
d8f823
 drivers/net/ethernet/mellanox/mlx5/core/eswitch.c  | 228 ++++++++++++---------
d8f823
 drivers/net/ethernet/mellanox/mlx5/core/eswitch.h  |  17 +-
d8f823
 .../ethernet/mellanox/mlx5/core/eswitch_offloads.c |  67 +++++-
d8f823
 3 files changed, 201 insertions(+), 111 deletions(-)
d8f823
d8f823
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
d8f823
index 97af7d793435..1937198405e1 100644
d8f823
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
d8f823
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
d8f823
@@ -1065,57 +1065,21 @@ void esw_vport_disable_egress_acl(struct mlx5_eswitch *esw,
d8f823
 	vport->egress.acl = NULL;
d8f823
 }
d8f823
 
d8f823
-int esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
d8f823
-				 struct mlx5_vport *vport)
d8f823
+static int
d8f823
+esw_vport_create_legacy_ingress_acl_groups(struct mlx5_eswitch *esw,
d8f823
+					   struct mlx5_vport *vport)
d8f823
 {
d8f823
 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
d8f823
 	struct mlx5_core_dev *dev = esw->dev;
d8f823
-	struct mlx5_flow_namespace *root_ns;
d8f823
-	struct mlx5_flow_table *acl;
d8f823
 	struct mlx5_flow_group *g;
d8f823
 	void *match_criteria;
d8f823
 	u32 *flow_group_in;
d8f823
-	/* The ingress acl table contains 4 groups
d8f823
-	 * (2 active rules at the same time -
d8f823
-	 *      1 allow rule from one of the first 3 groups.
d8f823
-	 *      1 drop rule from the last group):
d8f823
-	 * 1)Allow untagged traffic with smac=original mac.
d8f823
-	 * 2)Allow untagged traffic.
d8f823
-	 * 3)Allow traffic with smac=original mac.
d8f823
-	 * 4)Drop all other traffic.
d8f823
-	 */
d8f823
-	int table_size = 4;
d8f823
-	int err = 0;
d8f823
-
d8f823
-	if (!MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support))
d8f823
-		return -EOPNOTSUPP;
d8f823
-
d8f823
-	if (!IS_ERR_OR_NULL(vport->ingress.acl))
d8f823
-		return 0;
d8f823
-
d8f823
-	esw_debug(dev, "Create vport[%d] ingress ACL log_max_size(%d)\n",
d8f823
-		  vport->vport, MLX5_CAP_ESW_INGRESS_ACL(dev, log_max_ft_size));
d8f823
-
d8f823
-	root_ns = mlx5_get_flow_vport_acl_namespace(dev, MLX5_FLOW_NAMESPACE_ESW_INGRESS,
d8f823
-			mlx5_eswitch_vport_num_to_index(esw, vport->vport));
d8f823
-	if (!root_ns) {
d8f823
-		esw_warn(dev, "Failed to get E-Switch ingress flow namespace for vport (%d)\n", vport->vport);
d8f823
-		return -EOPNOTSUPP;
d8f823
-	}
d8f823
+	int err;
d8f823
 
d8f823
 	flow_group_in = kvzalloc(inlen, GFP_KERNEL);
d8f823
 	if (!flow_group_in)
d8f823
 		return -ENOMEM;
d8f823
 
d8f823
-	acl = mlx5_create_vport_flow_table(root_ns, 0, table_size, 0, vport->vport);
d8f823
-	if (IS_ERR(acl)) {
d8f823
-		err = PTR_ERR(acl);
d8f823
-		esw_warn(dev, "Failed to create E-Switch vport[%d] ingress flow Table, err(%d)\n",
d8f823
-			 vport->vport, err);
d8f823
-		goto out;
d8f823
-	}
d8f823
-	vport->ingress.acl = acl;
d8f823
-
d8f823
 	match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
d8f823
 
d8f823
 	MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
d8f823
@@ -1125,14 +1089,14 @@ int esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
d8f823
 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
d8f823
 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);
d8f823
 
d8f823
-	g = mlx5_create_flow_group(acl, flow_group_in);
d8f823
+	g = mlx5_create_flow_group(vport->ingress.acl, flow_group_in);
d8f823
 	if (IS_ERR(g)) {
d8f823
 		err = PTR_ERR(g);
d8f823
-		esw_warn(dev, "Failed to create E-Switch vport[%d] ingress untagged spoofchk flow group, err(%d)\n",
d8f823
+		esw_warn(dev, "vport[%d] ingress create untagged spoofchk flow group, err(%d)\n",
d8f823
 			 vport->vport, err);
d8f823
-		goto out;
d8f823
+		goto spoof_err;
d8f823
 	}
d8f823
-	vport->ingress.allow_untagged_spoofchk_grp = g;
d8f823
+	vport->ingress.legacy.allow_untagged_spoofchk_grp = g;
d8f823
 
d8f823
 	memset(flow_group_in, 0, inlen);
d8f823
 	MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
d8f823
@@ -1140,14 +1104,14 @@ int esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
d8f823
 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 1);
d8f823
 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1);
d8f823
 
d8f823
-	g = mlx5_create_flow_group(acl, flow_group_in);
d8f823
+	g = mlx5_create_flow_group(vport->ingress.acl, flow_group_in);
d8f823
 	if (IS_ERR(g)) {
d8f823
 		err = PTR_ERR(g);
d8f823
-		esw_warn(dev, "Failed to create E-Switch vport[%d] ingress untagged flow group, err(%d)\n",
d8f823
+		esw_warn(dev, "vport[%d] ingress create untagged flow group, err(%d)\n",
d8f823
 			 vport->vport, err);
d8f823
-		goto out;
d8f823
+		goto untagged_err;
d8f823
 	}
d8f823
-	vport->ingress.allow_untagged_only_grp = g;
d8f823
+	vport->ingress.legacy.allow_untagged_only_grp = g;
d8f823
 
d8f823
 	memset(flow_group_in, 0, inlen);
d8f823
 	MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
d8f823
@@ -1156,80 +1120,134 @@ int esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
d8f823
 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 2);
d8f823
 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 2);
d8f823
 
d8f823
-	g = mlx5_create_flow_group(acl, flow_group_in);
d8f823
+	g = mlx5_create_flow_group(vport->ingress.acl, flow_group_in);
d8f823
 	if (IS_ERR(g)) {
d8f823
 		err = PTR_ERR(g);
d8f823
-		esw_warn(dev, "Failed to create E-Switch vport[%d] ingress spoofchk flow group, err(%d)\n",
d8f823
+		esw_warn(dev, "vport[%d] ingress create spoofchk flow group, err(%d)\n",
d8f823
 			 vport->vport, err);
d8f823
-		goto out;
d8f823
+		goto allow_spoof_err;
d8f823
 	}
d8f823
-	vport->ingress.allow_spoofchk_only_grp = g;
d8f823
+	vport->ingress.legacy.allow_spoofchk_only_grp = g;
d8f823
 
d8f823
 	memset(flow_group_in, 0, inlen);
d8f823
 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 3);
d8f823
 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 3);
d8f823
 
d8f823
-	g = mlx5_create_flow_group(acl, flow_group_in);
d8f823
+	g = mlx5_create_flow_group(vport->ingress.acl, flow_group_in);
d8f823
 	if (IS_ERR(g)) {
d8f823
 		err = PTR_ERR(g);
d8f823
-		esw_warn(dev, "Failed to create E-Switch vport[%d] ingress drop flow group, err(%d)\n",
d8f823
+		esw_warn(dev, "vport[%d] ingress create drop flow group, err(%d)\n",
d8f823
 			 vport->vport, err);
d8f823
-		goto out;
d8f823
+		goto drop_err;
d8f823
 	}
d8f823
-	vport->ingress.drop_grp = g;
d8f823
+	vport->ingress.legacy.drop_grp = g;
d8f823
+	kvfree(flow_group_in);
d8f823
+	return 0;
d8f823
 
d8f823
-out:
d8f823
-	if (err) {
d8f823
-		if (!IS_ERR_OR_NULL(vport->ingress.allow_spoofchk_only_grp))
d8f823
-			mlx5_destroy_flow_group(
d8f823
-					vport->ingress.allow_spoofchk_only_grp);
d8f823
-		if (!IS_ERR_OR_NULL(vport->ingress.allow_untagged_only_grp))
d8f823
-			mlx5_destroy_flow_group(
d8f823
-					vport->ingress.allow_untagged_only_grp);
d8f823
-		if (!IS_ERR_OR_NULL(vport->ingress.allow_untagged_spoofchk_grp))
d8f823
-			mlx5_destroy_flow_group(
d8f823
-				vport->ingress.allow_untagged_spoofchk_grp);
d8f823
-		if (!IS_ERR_OR_NULL(vport->ingress.acl))
d8f823
-			mlx5_destroy_flow_table(vport->ingress.acl);
d8f823
+drop_err:
d8f823
+	if (!IS_ERR_OR_NULL(vport->ingress.legacy.allow_spoofchk_only_grp)) {
d8f823
+		mlx5_destroy_flow_group(vport->ingress.legacy.allow_spoofchk_only_grp);
d8f823
+		vport->ingress.legacy.allow_spoofchk_only_grp = NULL;
d8f823
 	}
d8f823
-
d8f823
+allow_spoof_err:
d8f823
+	if (!IS_ERR_OR_NULL(vport->ingress.legacy.allow_untagged_only_grp)) {
d8f823
+		mlx5_destroy_flow_group(vport->ingress.legacy.allow_untagged_only_grp);
d8f823
+		vport->ingress.legacy.allow_untagged_only_grp = NULL;
d8f823
+	}
d8f823
+untagged_err:
d8f823
+	if (!IS_ERR_OR_NULL(vport->ingress.legacy.allow_untagged_spoofchk_grp)) {
d8f823
+		mlx5_destroy_flow_group(vport->ingress.legacy.allow_untagged_spoofchk_grp);
d8f823
+		vport->ingress.legacy.allow_untagged_spoofchk_grp = NULL;
d8f823
+	}
d8f823
+spoof_err:
d8f823
 	kvfree(flow_group_in);
d8f823
 	return err;
d8f823
 }
d8f823
 
d8f823
+int esw_vport_create_ingress_acl_table(struct mlx5_eswitch *esw,
d8f823
+				       struct mlx5_vport *vport, int table_size)
d8f823
+{
d8f823
+	struct mlx5_core_dev *dev = esw->dev;
d8f823
+	struct mlx5_flow_namespace *root_ns;
d8f823
+	struct mlx5_flow_table *acl;
d8f823
+	int vport_index;
d8f823
+	int err;
d8f823
+
d8f823
+	if (!MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support))
d8f823
+		return -EOPNOTSUPP;
d8f823
+
d8f823
+	esw_debug(dev, "Create vport[%d] ingress ACL log_max_size(%d)\n",
d8f823
+		  vport->vport, MLX5_CAP_ESW_INGRESS_ACL(dev, log_max_ft_size));
d8f823
+
d8f823
+	vport_index = mlx5_eswitch_vport_num_to_index(esw, vport->vport);
d8f823
+	root_ns = mlx5_get_flow_vport_acl_namespace(dev, MLX5_FLOW_NAMESPACE_ESW_INGRESS,
d8f823
+						    vport_index);
d8f823
+	if (!root_ns) {
d8f823
+		esw_warn(dev, "Failed to get E-Switch ingress flow namespace for vport (%d)\n",
d8f823
+			 vport->vport);
d8f823
+		return -EOPNOTSUPP;
d8f823
+	}
d8f823
+
d8f823
+	acl = mlx5_create_vport_flow_table(root_ns, 0, table_size, 0, vport->vport);
d8f823
+	if (IS_ERR(acl)) {
d8f823
+		err = PTR_ERR(acl);
d8f823
+		esw_warn(dev, "vport[%d] ingress create flow Table, err(%d)\n",
d8f823
+			 vport->vport, err);
d8f823
+		return err;
d8f823
+	}
d8f823
+	vport->ingress.acl = acl;
d8f823
+	return 0;
d8f823
+}
d8f823
+
d8f823
+void esw_vport_destroy_ingress_acl_table(struct mlx5_vport *vport)
d8f823
+{
d8f823
+	if (!vport->ingress.acl)
d8f823
+		return;
d8f823
+
d8f823
+	mlx5_destroy_flow_table(vport->ingress.acl);
d8f823
+	vport->ingress.acl = NULL;
d8f823
+}
d8f823
+
d8f823
 void esw_vport_cleanup_ingress_rules(struct mlx5_eswitch *esw,
d8f823
 				     struct mlx5_vport *vport)
d8f823
 {
d8f823
-	if (!IS_ERR_OR_NULL(vport->ingress.legacy.drop_rule)) {
d8f823
+	if (vport->ingress.legacy.drop_rule) {
d8f823
 		mlx5_del_flow_rules(vport->ingress.legacy.drop_rule);
d8f823
 		vport->ingress.legacy.drop_rule = NULL;
d8f823
 	}
d8f823
 
d8f823
-	if (!IS_ERR_OR_NULL(vport->ingress.allow_rule)) {
d8f823
+	if (vport->ingress.allow_rule) {
d8f823
 		mlx5_del_flow_rules(vport->ingress.allow_rule);
d8f823
 		vport->ingress.allow_rule = NULL;
d8f823
 	}
d8f823
 }
d8f823
 
d8f823
-void esw_vport_disable_ingress_acl(struct mlx5_eswitch *esw,
d8f823
-				   struct mlx5_vport *vport)
d8f823
+static void esw_vport_disable_legacy_ingress_acl(struct mlx5_eswitch *esw,
d8f823
+						 struct mlx5_vport *vport)
d8f823
 {
d8f823
-	if (IS_ERR_OR_NULL(vport->ingress.acl))
d8f823
+	if (!vport->ingress.acl)
d8f823
 		return;
d8f823
 
d8f823
 	esw_debug(esw->dev, "Destroy vport[%d] E-Switch ingress ACL\n", vport->vport);
d8f823
 
d8f823
 	esw_vport_cleanup_ingress_rules(esw, vport);
d8f823
-	mlx5_destroy_flow_group(vport->ingress.allow_spoofchk_only_grp);
d8f823
-	mlx5_destroy_flow_group(vport->ingress.allow_untagged_only_grp);
d8f823
-	mlx5_destroy_flow_group(vport->ingress.allow_untagged_spoofchk_grp);
d8f823
-	mlx5_destroy_flow_group(vport->ingress.drop_grp);
d8f823
-	mlx5_destroy_flow_table(vport->ingress.acl);
d8f823
-	vport->ingress.acl = NULL;
d8f823
-	vport->ingress.drop_grp = NULL;
d8f823
-	vport->ingress.allow_spoofchk_only_grp = NULL;
d8f823
-	vport->ingress.allow_untagged_only_grp = NULL;
d8f823
-	vport->ingress.allow_untagged_spoofchk_grp = NULL;
d8f823
+	if (vport->ingress.legacy.allow_spoofchk_only_grp) {
d8f823
+		mlx5_destroy_flow_group(vport->ingress.legacy.allow_spoofchk_only_grp);
d8f823
+		vport->ingress.legacy.allow_spoofchk_only_grp = NULL;
d8f823
+	}
d8f823
+	if (vport->ingress.legacy.allow_untagged_only_grp) {
d8f823
+		mlx5_destroy_flow_group(vport->ingress.legacy.allow_untagged_only_grp);
d8f823
+		vport->ingress.legacy.allow_untagged_only_grp = NULL;
d8f823
+	}
d8f823
+	if (vport->ingress.legacy.allow_untagged_spoofchk_grp) {
d8f823
+		mlx5_destroy_flow_group(vport->ingress.legacy.allow_untagged_spoofchk_grp);
d8f823
+		vport->ingress.legacy.allow_untagged_spoofchk_grp = NULL;
d8f823
+	}
d8f823
+	if (vport->ingress.legacy.drop_grp) {
d8f823
+		mlx5_destroy_flow_group(vport->ingress.legacy.drop_grp);
d8f823
+		vport->ingress.legacy.drop_grp = NULL;
d8f823
+	}
d8f823
+	esw_vport_destroy_ingress_acl_table(vport);
d8f823
 }
d8f823
 
d8f823
 static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
d8f823
@@ -1244,19 +1262,36 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
d8f823
 	int err = 0;
d8f823
 	u8 *smac_v;
d8f823
 
d8f823
+	/* The ingress acl table contains 4 groups
d8f823
+	 * (2 active rules at the same time -
d8f823
+	 *      1 allow rule from one of the first 3 groups.
d8f823
+	 *      1 drop rule from the last group):
d8f823
+	 * 1)Allow untagged traffic with smac=original mac.
d8f823
+	 * 2)Allow untagged traffic.
d8f823
+	 * 3)Allow traffic with smac=original mac.
d8f823
+	 * 4)Drop all other traffic.
d8f823
+	 */
d8f823
+	int table_size = 4;
d8f823
+
d8f823
 	esw_vport_cleanup_ingress_rules(esw, vport);
d8f823
 
d8f823
 	if (!vport->info.vlan && !vport->info.qos && !vport->info.spoofchk) {
d8f823
-		esw_vport_disable_ingress_acl(esw, vport);
d8f823
+		esw_vport_disable_legacy_ingress_acl(esw, vport);
d8f823
 		return 0;
d8f823
 	}
d8f823
 
d8f823
-	err = esw_vport_enable_ingress_acl(esw, vport);
d8f823
-	if (err) {
d8f823
-		mlx5_core_warn(esw->dev,
d8f823
-			       "failed to enable ingress acl (%d) on vport[%d]\n",
d8f823
-			       err, vport->vport);
d8f823
-		return err;
d8f823
+	if (!vport->ingress.acl) {
d8f823
+		err = esw_vport_create_ingress_acl_table(esw, vport, table_size);
d8f823
+		if (err) {
d8f823
+			esw_warn(esw->dev,
d8f823
+				 "vport[%d] enable ingress acl err (%d)\n",
d8f823
+				 err, vport->vport);
d8f823
+			return err;
d8f823
+		}
d8f823
+
d8f823
+		err = esw_vport_create_legacy_ingress_acl_groups(esw, vport);
d8f823
+		if (err)
d8f823
+			goto out;
d8f823
 	}
d8f823
 
d8f823
 	esw_debug(esw->dev,
d8f823
@@ -1317,10 +1352,11 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
d8f823
 		vport->ingress.legacy.drop_rule = NULL;
d8f823
 		goto out;
d8f823
 	}
d8f823
+	kvfree(spec);
d8f823
+	return 0;
d8f823
 
d8f823
 out:
d8f823
-	if (err)
d8f823
-		esw_vport_cleanup_ingress_rules(esw, vport);
d8f823
+	esw_vport_disable_legacy_ingress_acl(esw, vport);
d8f823
 	kvfree(spec);
d8f823
 	return err;
d8f823
 }
d8f823
@@ -1700,7 +1736,7 @@ static int esw_vport_create_legacy_acl_tables(struct mlx5_eswitch *esw,
d8f823
 	return 0;
d8f823
 
d8f823
 egress_err:
d8f823
-	esw_vport_disable_ingress_acl(esw, vport);
d8f823
+	esw_vport_disable_legacy_ingress_acl(esw, vport);
d8f823
 	mlx5_fc_destroy(esw->dev, vport->egress.legacy.drop_counter);
d8f823
 	vport->egress.legacy.drop_counter = NULL;
d8f823
 
d8f823
@@ -1730,7 +1766,7 @@ static void esw_vport_destroy_legacy_acl_tables(struct mlx5_eswitch *esw,
d8f823
 	mlx5_fc_destroy(esw->dev, vport->egress.legacy.drop_counter);
d8f823
 	vport->egress.legacy.drop_counter = NULL;
d8f823
 
d8f823
-	esw_vport_disable_ingress_acl(esw, vport);
d8f823
+	esw_vport_disable_legacy_ingress_acl(esw, vport);
d8f823
 	mlx5_fc_destroy(esw->dev, vport->ingress.legacy.drop_counter);
d8f823
 	vport->ingress.legacy.drop_counter = NULL;
d8f823
 }
d8f823
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
d8f823
index 777224ed18bc..963d0df0d66b 100644
d8f823
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
d8f823
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
d8f823
@@ -65,25 +65,30 @@
d8f823
 
d8f823
 struct vport_ingress {
d8f823
 	struct mlx5_flow_table *acl;
d8f823
+#ifdef __GENKSYMS__
d8f823
 	struct mlx5_flow_group *allow_untagged_spoofchk_grp;
d8f823
 	struct mlx5_flow_group *allow_spoofchk_only_grp;
d8f823
 	struct mlx5_flow_group *allow_untagged_only_grp;
d8f823
 	struct mlx5_flow_group *drop_grp;
d8f823
-#ifdef __GENKSYMS__
d8f823
 	struct mlx5_modify_hdr   *modify_metadata;
d8f823
 	struct mlx5_flow_handle  *modify_metadata_rule;
d8f823
 #endif
d8f823
-	struct mlx5_flow_handle  *allow_rule;
d8f823
+	struct mlx5_flow_handle *allow_rule;
d8f823
 #ifdef __GENKSYMS__
d8f823
 	struct mlx5_flow_handle  *drop_rule;
d8f823
 	struct mlx5_fc           *drop_counter;
d8f823
 #endif
d8f823
 #ifndef __GENKSYMS__
d8f823
 	struct {
d8f823
+		struct mlx5_flow_group *allow_spoofchk_only_grp;
d8f823
+		struct mlx5_flow_group *allow_untagged_spoofchk_grp;
d8f823
+		struct mlx5_flow_group *allow_untagged_only_grp;
d8f823
+		struct mlx5_flow_group *drop_grp;
d8f823
 		struct mlx5_flow_handle *drop_rule;
d8f823
 		struct mlx5_fc *drop_counter;
d8f823
 	} legacy;
d8f823
 	struct {
d8f823
+		struct mlx5_flow_group *metadata_grp;
d8f823
 		struct mlx5_modify_hdr *modify_metadata;
d8f823
 		struct mlx5_flow_handle *modify_metadata_rule;
d8f823
 	} offloads;
d8f823
@@ -272,16 +277,16 @@ void esw_offloads_cleanup_reps(struct mlx5_eswitch *esw);
d8f823
 int esw_offloads_init_reps(struct mlx5_eswitch *esw);
d8f823
 void esw_vport_cleanup_ingress_rules(struct mlx5_eswitch *esw,
d8f823
 				     struct mlx5_vport *vport);
d8f823
-int esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
d8f823
-				 struct mlx5_vport *vport);
d8f823
+int esw_vport_create_ingress_acl_table(struct mlx5_eswitch *esw,
d8f823
+				       struct mlx5_vport *vport,
d8f823
+				       int table_size);
d8f823
+void esw_vport_destroy_ingress_acl_table(struct mlx5_vport *vport);
d8f823
 void esw_vport_cleanup_egress_rules(struct mlx5_eswitch *esw,
d8f823
 				    struct mlx5_vport *vport);
d8f823
 int esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,
d8f823
 				struct mlx5_vport *vport);
d8f823
 void esw_vport_disable_egress_acl(struct mlx5_eswitch *esw,
d8f823
 				  struct mlx5_vport *vport);
d8f823
-void esw_vport_disable_ingress_acl(struct mlx5_eswitch *esw,
d8f823
-				   struct mlx5_vport *vport);
d8f823
 int mlx5_esw_modify_vport_rate(struct mlx5_eswitch *esw, u16 vport_num,
d8f823
 			       u32 rate_mbps);
d8f823
 
d8f823
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
d8f823
index 767993b10110..7fe085fa3d29 100644
d8f823
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
d8f823
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
d8f823
@@ -1860,6 +1860,44 @@ static void esw_vport_del_ingress_acl_modify_metadata(struct mlx5_eswitch *esw,
d8f823
 	}
d8f823
 }
d8f823
 
d8f823
+static int esw_vport_create_ingress_acl_group(struct mlx5_eswitch *esw,
d8f823
+					      struct mlx5_vport *vport)
d8f823
+{
d8f823
+	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
d8f823
+	struct mlx5_flow_group *g;
d8f823
+	u32 *flow_group_in;
d8f823
+	int ret = 0;
d8f823
+
d8f823
+	flow_group_in = kvzalloc(inlen, GFP_KERNEL);
d8f823
+	if (!flow_group_in)
d8f823
+		return -ENOMEM;
d8f823
+
d8f823
+	memset(flow_group_in, 0, inlen);
d8f823
+	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
d8f823
+	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);
d8f823
+
d8f823
+	g = mlx5_create_flow_group(vport->ingress.acl, flow_group_in);
d8f823
+	if (IS_ERR(g)) {
d8f823
+		ret = PTR_ERR(g);
d8f823
+		esw_warn(esw->dev,
d8f823
+			 "Failed to create vport[%d] ingress metdata group, err(%d)\n",
d8f823
+			 vport->vport, ret);
d8f823
+		goto grp_err;
d8f823
+	}
d8f823
+	vport->ingress.offloads.metadata_grp = g;
d8f823
+grp_err:
d8f823
+	kvfree(flow_group_in);
d8f823
+	return ret;
d8f823
+}
d8f823
+
d8f823
+static void esw_vport_destroy_ingress_acl_group(struct mlx5_vport *vport)
d8f823
+{
d8f823
+	if (vport->ingress.offloads.metadata_grp) {
d8f823
+		mlx5_destroy_flow_group(vport->ingress.offloads.metadata_grp);
d8f823
+		vport->ingress.offloads.metadata_grp = NULL;
d8f823
+	}
d8f823
+}
d8f823
+
d8f823
 static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
d8f823
 				    struct mlx5_vport *vport)
d8f823
 {
d8f823
@@ -1870,8 +1908,7 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
d8f823
 		return 0;
d8f823
 
d8f823
 	esw_vport_cleanup_ingress_rules(esw, vport);
d8f823
-
d8f823
-	err = esw_vport_enable_ingress_acl(esw, vport);
d8f823
+	err = esw_vport_create_ingress_acl_table(esw, vport, 1);
d8f823
 	if (err) {
d8f823
 		esw_warn(esw->dev,
d8f823
 			 "failed to enable ingress acl (%d) on vport[%d]\n",
d8f823
@@ -1879,25 +1916,34 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
d8f823
 		return err;
d8f823
 	}
d8f823
 
d8f823
+	err = esw_vport_create_ingress_acl_group(esw, vport);
d8f823
+	if (err)
d8f823
+		goto group_err;
d8f823
+
d8f823
 	esw_debug(esw->dev,
d8f823
 		  "vport[%d] configure ingress rules\n", vport->vport);
d8f823
 
d8f823
 	if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
d8f823
 		err = esw_vport_add_ingress_acl_modify_metadata(esw, vport);
d8f823
 		if (err)
d8f823
-			goto out;
d8f823
+			goto metadata_err;
d8f823
 	}
d8f823
 
d8f823
 	if (MLX5_CAP_GEN(esw->dev, prio_tag_required) &&
d8f823
 	    mlx5_eswitch_is_vf_vport(esw, vport->vport)) {
d8f823
 		err = esw_vport_ingress_prio_tag_config(esw, vport);
d8f823
 		if (err)
d8f823
-			goto out;
d8f823
+			goto prio_tag_err;
d8f823
 	}
d8f823
+	return 0;
d8f823
 
d8f823
-out:
d8f823
-	if (err)
d8f823
-		esw_vport_disable_ingress_acl(esw, vport);
d8f823
+prio_tag_err:
d8f823
+	esw_vport_del_ingress_acl_modify_metadata(esw, vport);
d8f823
+metadata_err:
d8f823
+	esw_vport_cleanup_ingress_rules(esw, vport);
d8f823
+	esw_vport_destroy_ingress_acl_group(vport);
d8f823
+group_err:
d8f823
+	esw_vport_destroy_ingress_acl_table(vport);
d8f823
 	return err;
d8f823
 }
d8f823
 
d8f823
@@ -1978,7 +2024,8 @@ esw_vport_create_offloads_acl_tables(struct mlx5_eswitch *esw,
d8f823
 		err = esw_vport_egress_config(esw, vport);
d8f823
 		if (err) {
d8f823
 			esw_vport_del_ingress_acl_modify_metadata(esw, vport);
d8f823
-			esw_vport_disable_ingress_acl(esw, vport);
d8f823
+			esw_vport_cleanup_ingress_rules(esw, vport);
d8f823
+			esw_vport_destroy_ingress_acl_table(vport);
d8f823
 		}
d8f823
 	}
d8f823
 	return err;
d8f823
@@ -1990,7 +2037,9 @@ esw_vport_destroy_offloads_acl_tables(struct mlx5_eswitch *esw,
d8f823
 {
d8f823
 	esw_vport_disable_egress_acl(esw, vport);
d8f823
 	esw_vport_del_ingress_acl_modify_metadata(esw, vport);
d8f823
-	esw_vport_disable_ingress_acl(esw, vport);
d8f823
+	esw_vport_cleanup_ingress_rules(esw, vport);
d8f823
+	esw_vport_destroy_ingress_acl_group(vport);
d8f823
+	esw_vport_destroy_ingress_acl_table(vport);
d8f823
 }
d8f823
 
d8f823
 static int esw_create_uplink_offloads_acl_tables(struct mlx5_eswitch *esw)
d8f823
-- 
d8f823
2.13.6
d8f823