All of lore.kernel.org
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH v2] net/ice: fix FDIR flow type conflict
@ 2019-11-16  8:59 Qi Zhang
  0 siblings, 0 replies; only message in thread
From: Qi Zhang @ 2019-11-16  8:59 UTC (permalink / raw)
  To: beilei.xing, yahui.cao; +Cc: dev, Qi Zhang

Flow type "IPv4 + UDP" or "IPv4 + TCP" is conflict with "IPv4 + any"
flow type. If a rule for IPv4 + any is created, we should reject any rule
for IPv4 + UDP otherwise the first rule may be impacted, same decision
should be made on a reverse order.
For IPv6 and IPv4 GTPU inner case, we have the same limitation.

Fixes: 109e8e06249e ("net/ice: configure HW flow director rule")

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---

v2:
- fix check patch issue.

 drivers/net/ice/ice_fdir_filter.c | 172 ++++++++++++++++++++++++++++++++++----
 1 file changed, 156 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ice/ice_fdir_filter.c b/drivers/net/ice/ice_fdir_filter.c
index 7876f4bbc..cc1d6d010 100644
--- a/drivers/net/ice/ice_fdir_filter.c
+++ b/drivers/net/ice/ice_fdir_filter.c
@@ -646,6 +646,153 @@ ice_fdir_teardown(struct ice_pf *pf)
 	}
 }
 
+static int ice_fdir_cur_prof_conflict(struct ice_pf *pf,
+				      enum ice_fltr_ptype ptype,
+				      struct ice_flow_seg_info *seg,
+				      bool is_tunnel)
+{
+	struct ice_hw *hw = ICE_PF_TO_HW(pf);
+	struct ice_flow_seg_info *ori_seg;
+	struct ice_fd_hw_prof *hw_prof;
+
+	hw_prof = hw->fdir_prof[ptype];
+	ori_seg = hw_prof->fdir_seg[is_tunnel];
+
+	/* profile does not exist */
+	if (!ori_seg)
+		return 0;
+
+	/* if no input set conflict, return -EAGAIN */
+	if ((!is_tunnel && !memcmp(ori_seg, seg, sizeof(*seg))) ||
+	    (is_tunnel && !memcmp(&ori_seg[1], &seg[1], sizeof(*seg)))) {
+		PMD_DRV_LOG(DEBUG, "Profile already exist for flow type %d.",
+			    ptype);
+		return -EAGAIN;
+	}
+
+	/* a rule with input set conflict already exist, so give up */
+	if (pf->fdir_fltr_cnt[ptype][is_tunnel]) {
+		PMD_DRV_LOG(DEBUG, "Failed to create profile for flow type %d due to conflict with exist rule.",
+			    ptype);
+		return -EINVAL;
+	}
+
+	/* it's safe to delete an empty profile */
+	ice_fdir_prof_rm(pf, ptype, is_tunnel);
+	return 0;
+}
+
+static bool ice_fdir_prof_resolve_conflict(struct ice_pf *pf,
+					   enum ice_fltr_ptype ptype,
+					   bool is_tunnel)
+{
+	struct ice_hw *hw = ICE_PF_TO_HW(pf);
+	struct ice_fd_hw_prof *hw_prof;
+	struct ice_flow_seg_info *seg;
+
+	hw_prof = hw->fdir_prof[ptype];
+	seg = hw_prof->fdir_seg[is_tunnel];
+
+	/* profile does not exist */
+	if (!seg)
+		return true;
+
+	/* profile exist and rule exist, fail to resolve the conflict */
+	if (pf->fdir_fltr_cnt[ptype][is_tunnel] != 0)
+		return false;
+
+	/* it's safe to delete an empty profile */
+	ice_fdir_prof_rm(pf, ptype, is_tunnel);
+
+	return true;
+}
+
+static int ice_fdir_cross_prof_conflict(struct ice_pf *pf,
+					enum ice_fltr_ptype ptype,
+					bool is_tunnel)
+{
+	enum ice_fltr_ptype cflct_ptype;
+
+	switch (ptype) {
+	/* IPv4 */
+	case ICE_FLTR_PTYPE_NONF_IPV4_UDP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_SCTP:
+		cflct_ptype = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
+		if (!ice_fdir_prof_resolve_conflict
+			(pf, cflct_ptype, is_tunnel))
+			goto err;
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV4_OTHER:
+		cflct_ptype = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
+		if (!ice_fdir_prof_resolve_conflict
+			(pf, cflct_ptype, is_tunnel))
+			goto err;
+		cflct_ptype = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
+		if (!ice_fdir_prof_resolve_conflict
+			(pf, cflct_ptype, is_tunnel))
+			goto err;
+		cflct_ptype = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
+		if (!ice_fdir_prof_resolve_conflict
+			(pf, cflct_ptype, is_tunnel))
+			goto err;
+		break;
+	/* IPv4 GTPU */
+	case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_UDP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_ICMP:
+		cflct_ptype = ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_OTHER;
+		if (!ice_fdir_prof_resolve_conflict
+			(pf, cflct_ptype, is_tunnel))
+			goto err;
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_OTHER:
+		cflct_ptype = ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_OTHER;
+		if (!ice_fdir_prof_resolve_conflict
+			(pf, cflct_ptype, is_tunnel))
+			goto err;
+		cflct_ptype = ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_OTHER;
+		if (!ice_fdir_prof_resolve_conflict
+			(pf, cflct_ptype, is_tunnel))
+			goto err;
+		cflct_ptype = ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_OTHER;
+		if (!ice_fdir_prof_resolve_conflict
+			(pf, cflct_ptype, is_tunnel))
+			goto err;
+		break;
+	/* IPv6 */
+	case ICE_FLTR_PTYPE_NONF_IPV6_UDP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_TCP:
+	case ICE_FLTR_PTYPE_NONF_IPV6_SCTP:
+		cflct_ptype = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
+		if (!ice_fdir_prof_resolve_conflict
+			(pf, cflct_ptype, is_tunnel))
+			goto err;
+		break;
+	case ICE_FLTR_PTYPE_NONF_IPV6_OTHER:
+		cflct_ptype = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
+		if (!ice_fdir_prof_resolve_conflict
+			(pf, cflct_ptype, is_tunnel))
+			goto err;
+		cflct_ptype = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
+		if (!ice_fdir_prof_resolve_conflict
+			(pf, cflct_ptype, is_tunnel))
+			goto err;
+		cflct_ptype = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
+		if (!ice_fdir_prof_resolve_conflict
+			(pf, cflct_ptype, is_tunnel))
+			goto err;
+		break;
+	default:
+		break;
+	}
+	return 0;
+err:
+	PMD_DRV_LOG(DEBUG, "Failed to create profile for flow type %d due to conflict with exist rule of flow type %d.",
+		    ptype, cflct_ptype);
+	return -EINVAL;
+}
+
 static int
 ice_fdir_hw_tbl_conf(struct ice_pf *pf, struct ice_vsi *vsi,
 		     struct ice_vsi *ctrl_vsi,
@@ -655,7 +802,6 @@ ice_fdir_hw_tbl_conf(struct ice_pf *pf, struct ice_vsi *vsi,
 {
 	struct ice_hw *hw = ICE_PF_TO_HW(pf);
 	enum ice_flow_dir dir = ICE_FLOW_RX;
-	struct ice_flow_seg_info *ori_seg;
 	struct ice_fd_hw_prof *hw_prof;
 	struct ice_flow_prof *prof;
 	uint64_t entry_1 = 0;
@@ -664,22 +810,15 @@ ice_fdir_hw_tbl_conf(struct ice_pf *pf, struct ice_vsi *vsi,
 	int ret;
 	uint64_t prof_id;
 
-	hw_prof = hw->fdir_prof[ptype];
-	ori_seg = hw_prof->fdir_seg[is_tunnel];
-	if (ori_seg) {
-		if (!is_tunnel) {
-			if (!memcmp(ori_seg, seg, sizeof(*seg)))
-				return -EAGAIN;
-		} else {
-			if (!memcmp(&ori_seg[1], &seg[1], sizeof(*seg)))
-				return -EAGAIN;
-		}
-
-		if (pf->fdir_fltr_cnt[ptype][is_tunnel])
-			return -EINVAL;
+	/* check if have input set conflict on current profile. */
+	ret = ice_fdir_cur_prof_conflict(pf, ptype, seg, is_tunnel);
+	if (ret)
+		return ret;
 
-		ice_fdir_prof_rm(pf, ptype, is_tunnel);
-	}
+	/* check if the profile is conflict with other profile. */
+	ret = ice_fdir_cross_prof_conflict(pf, ptype, is_tunnel);
+	if (ret)
+		return ret;
 
 	prof_id = ptype + is_tunnel * ICE_FLTR_PTYPE_MAX;
 	ret = ice_flow_add_prof(hw, ICE_BLK_FD, dir, prof_id, seg,
@@ -703,6 +842,7 @@ ice_fdir_hw_tbl_conf(struct ice_pf *pf, struct ice_vsi *vsi,
 		goto err_add_entry;
 	}
 
+	hw_prof = hw->fdir_prof[ptype];
 	pf->hw_prof_cnt[ptype][is_tunnel] = 0;
 	hw_prof->cnt = 0;
 	hw_prof->fdir_seg[is_tunnel] = seg;
-- 
2.13.6


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2019-11-16  8:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-16  8:59 [dpdk-dev] [PATCH v2] net/ice: fix FDIR flow type conflict Qi Zhang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.