From patchwork Sat Nov 16 08:53:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qi Zhang X-Patchwork-Id: 63051 Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id D51F4A04C0; Sat, 16 Nov 2019 09:50:57 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 107DD3423; Sat, 16 Nov 2019 09:50:57 +0100 (CET) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 84D5D2C27 for ; Sat, 16 Nov 2019 09:50:55 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 16 Nov 2019 00:50:54 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.68,311,1569308400"; d="scan'208";a="203780461" Received: from dpdk51.sh.intel.com ([10.67.110.245]) by fmsmga007.fm.intel.com with ESMTP; 16 Nov 2019 00:50:53 -0800 From: Qi Zhang To: beilei.xing@intel.com, yahui.cao@intel.com Cc: dev@dpdk.org, Qi Zhang Date: Sat, 16 Nov 2019 16:53:58 +0800 Message-Id: <20191116085358.30905-1-qi.z.zhang@intel.com> X-Mailer: git-send-email 2.13.6 Subject: [dpdk-dev] [PATCH] net/ice: fix FDIR flow type conflict X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" 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 --- 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..334b84430 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;