From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 1D4D5A055D for ; Tue, 2 Mar 2021 08:06:56 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 1370F406B4; Tue, 2 Mar 2021 08:06:56 +0100 (CET) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by mails.dpdk.org (Postfix) with ESMTP id CC7DD40142; Tue, 2 Mar 2021 08:06:53 +0100 (CET) IronPort-SDR: lmcKRKB3xRDQ5tEAhANY/5Ct92ENqXAmAnQ6EXYSdvU33R980qogBt2ZgdlR2R7Lc1qnAEjUyE oi95GdKThkIA== X-IronPort-AV: E=McAfee;i="6000,8403,9910"; a="186830077" X-IronPort-AV: E=Sophos;i="5.81,216,1610438400"; d="scan'208";a="186830077" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2021 23:06:52 -0800 IronPort-SDR: xPOpuAvdDHgdZU4EhkZedRf1dXTypH3RdG1Lo/yC4MNXfCcgr3dWaaslSRD6taJ2UjtzfY3iPb K9GxX1wylSDg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,216,1610438400"; d="scan'208";a="444627300" Received: from dpdk-xiaoyunl.sh.intel.com ([10.67.111.154]) by orsmga001.jf.intel.com with ESMTP; 01 Mar 2021 23:06:50 -0800 From: Xiaoyun Li To: Beilei Xing , Jeff Guo , Wenzhuo Lu Cc: dev@dpdk.org, Xiaoyun Li , stable@dpdk.org Date: Tue, 2 Mar 2021 15:03:20 +0800 Message-Id: <20210302070320.1872968-1-xiaoyun.li@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210226081438.1693788-1-xiaoyun.li@intel.com> References: <20210226081438.1693788-1-xiaoyun.li@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [dpdk-stable] [PATCH v2] net/i40e: fix IPv4 fragment offload issue X-BeenThere: stable@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: patches for DPDK stable branches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: stable-bounces@dpdk.org Sender: "stable" IPv4 fragment_offset mask was required to be 0 no matter what the spec value was. But zero mask means not caring about fragment_offset field then both non-frag and frag packets should hit the rule. But the actual fragment rules should be like the following: Only non-fragment packets can hit Rule 1: Rule 1: mask=0x3fff, spec=0 Only fragment packets can hit rule 2: Rule 2: mask=0x3fff, spec=0x8, last=0x2000 This patch allows the above rules. Fixes: 42044b69c67d ("net/i40e: support input set selection for FDIR") Cc: stable@dpdk.org Signed-off-by: Xiaoyun Li --- v2: * Fixed a typo. * Print comment in one line. drivers/net/i40e/i40e_flow.c | 87 ++++++++++++++++++++++++++++++++---- 1 file changed, 78 insertions(+), 9 deletions(-) diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index 4d44282312..3e514d5f38 100644 --- a/drivers/net/i40e/i40e_flow.c +++ b/drivers/net/i40e/i40e_flow.c @@ -2433,7 +2433,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, const struct rte_flow_item *item = pattern; const struct rte_flow_item_eth *eth_spec, *eth_mask; const struct rte_flow_item_vlan *vlan_spec, *vlan_mask; - const struct rte_flow_item_ipv4 *ipv4_spec, *ipv4_mask; + const struct rte_flow_item_ipv4 *ipv4_spec, *ipv4_last, *ipv4_mask; const struct rte_flow_item_ipv6 *ipv6_spec, *ipv6_mask; const struct rte_flow_item_tcp *tcp_spec, *tcp_mask; const struct rte_flow_item_udp *udp_spec, *udp_mask; @@ -2446,7 +2446,6 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, uint8_t pctype = 0; uint64_t input_set = I40E_INSET_NONE; - uint16_t frag_off; enum rte_flow_item_type item_type; enum rte_flow_item_type next_type; enum rte_flow_item_type l3 = RTE_FLOW_ITEM_TYPE_END; @@ -2472,7 +2471,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, memset(len_arr, 0, sizeof(len_arr)); filter->input.flow_ext.customized_pctype = false; for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) { - if (item->last) { + if (item->last && item->type != RTE_FLOW_ITEM_TYPE_IPV4) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, @@ -2611,15 +2610,40 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, l3 = RTE_FLOW_ITEM_TYPE_IPV4; ipv4_spec = item->spec; ipv4_mask = item->mask; + ipv4_last = item->last; pctype = I40E_FILTER_PCTYPE_NONF_IPV4_OTHER; layer_idx = I40E_FLXPLD_L3_IDX; + if (ipv4_last) { + if (!ipv4_spec || !ipv4_mask || !outer_ip) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Not support range"); + return -rte_errno; + } + /* Only fragment_offset supports range */ + if (ipv4_last->hdr.version_ihl || + ipv4_last->hdr.type_of_service || + ipv4_last->hdr.total_length || + ipv4_last->hdr.packet_id || + ipv4_last->hdr.time_to_live || + ipv4_last->hdr.next_proto_id || + ipv4_last->hdr.hdr_checksum || + ipv4_last->hdr.src_addr || + ipv4_last->hdr.dst_addr) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Not support range"); + return -rte_errno; + } + } if (ipv4_spec && ipv4_mask && outer_ip) { /* Check IPv4 mask and update input set */ if (ipv4_mask->hdr.version_ihl || ipv4_mask->hdr.total_length || ipv4_mask->hdr.packet_id || - ipv4_mask->hdr.fragment_offset || ipv4_mask->hdr.hdr_checksum) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, @@ -2640,11 +2664,56 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, input_set |= I40E_INSET_IPV4_PROTO; /* Check if it is fragment. */ - frag_off = ipv4_spec->hdr.fragment_offset; - frag_off = rte_be_to_cpu_16(frag_off); - if (frag_off & RTE_IPV4_HDR_OFFSET_MASK || - frag_off & RTE_IPV4_HDR_MF_FLAG) - pctype = I40E_FILTER_PCTYPE_FRAG_IPV4; + uint16_t frag_mask = + ipv4_mask->hdr.fragment_offset; + uint16_t frag_spec = + ipv4_spec->hdr.fragment_offset; + uint16_t frag_last = 0; + if (ipv4_last) + frag_last = + ipv4_last->hdr.fragment_offset; + if (frag_mask) { + frag_mask = rte_be_to_cpu_16(frag_mask); + frag_spec = rte_be_to_cpu_16(frag_spec); + frag_last = rte_be_to_cpu_16(frag_last); + /* frag_off mask has to be 0x3fff */ + if (frag_mask != + (RTE_IPV4_HDR_OFFSET_MASK | + RTE_IPV4_HDR_MF_FLAG)) { + rte_flow_error_set(error, + EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Invalid IPv4 fragment_offset mask"); + return -rte_errno; + } + /* + * non-frag rule: + * mask=0x3fff,spec=0 + * frag rule: + * mask=0x3fff,spec=0x8,last=0x2000 + */ + if (frag_spec == + (1 << RTE_IPV4_HDR_FO_SHIFT) && + frag_last == RTE_IPV4_HDR_MF_FLAG) { + pctype = + I40E_FILTER_PCTYPE_FRAG_IPV4; + } else if (frag_spec || frag_last) { + rte_flow_error_set(error, + EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Invalid IPv4 fragment_offset rule"); + return -rte_errno; + } + } else if (frag_spec || frag_last) { + rte_flow_error_set(error, + EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Invalid fragment_offset"); + return -rte_errno; + } if (input_set & (I40E_INSET_DMAC | I40E_INSET_SMAC)) { if (input_set & (I40E_INSET_IPV4_SRC | -- 2.25.1