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 <xiaoyun.li@intel.com> --- drivers/net/i40e/i40e_flow.c | 89 ++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 9 deletions(-) diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index 4d44282312..86d96d9a11 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,58 @@ 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,sepc=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
> -----Original Message----- > From: Li, Xiaoyun <xiaoyun.li@intel.com> > Sent: Friday, February 26, 2021 4:15 PM > To: dev@dpdk.org; Xing, Beilei <beilei.xing@intel.com>; Guo, Jia > <jia.guo@intel.com>; Finn, Emma <emma.finn@intel.com> > Cc: Li, Xiaoyun <xiaoyun.li@intel.com>; stable@dpdk.org > Subject: [PATCH] net/i40e: fix IPv4 fragment offload issue > > 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 <xiaoyun.li@intel.com> > --- > drivers/net/i40e/i40e_flow.c | 89 ++++++++++++++++++++++++++++++++---- > 1 file changed, 80 insertions(+), 9 deletions(-) > > diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index > 4d44282312..86d96d9a11 100644 > --- a/drivers/net/i40e/i40e_flow.c > +++ b/drivers/net/i40e/i40e_flow.c > + "Invalid IPv4 " > + "fragment_offset mask"); Needn't split the comments line. > + return -rte_errno; > + } > + /* > + * non-frag rule: > + * mask=0x3fff,sepc=0 Typo: sepc->spec > + * 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"); Same as above. > + 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
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 <xiaoyun.li@intel.com> --- 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
Hi
> -----Original Message-----
> From: Xing, Beilei <beilei.xing@intel.com>
> Sent: Tuesday, March 2, 2021 14:54
> To: Li, Xiaoyun <xiaoyun.li@intel.com>; dev@dpdk.org; Guo, Jia
> <jia.guo@intel.com>; Finn, Emma <emma.finn@intel.com>
> Cc: stable@dpdk.org
> Subject: RE: [PATCH] net/i40e: fix IPv4 fragment offload issue
>
>
>
> > -----Original Message-----
> > From: Li, Xiaoyun <xiaoyun.li@intel.com>
> > Sent: Friday, February 26, 2021 4:15 PM
> > To: dev@dpdk.org; Xing, Beilei <beilei.xing@intel.com>; Guo, Jia
> > <jia.guo@intel.com>; Finn, Emma <emma.finn@intel.com>
> > Cc: Li, Xiaoyun <xiaoyun.li@intel.com>; stable@dpdk.org
> > Subject: [PATCH] net/i40e: fix IPv4 fragment offload issue
> >
> > 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 <xiaoyun.li@intel.com>
> > ---
> > drivers/net/i40e/i40e_flow.c | 89
> > ++++++++++++++++++++++++++++++++----
> > 1 file changed, 80 insertions(+), 9 deletions(-)
> >
> > diff --git a/drivers/net/i40e/i40e_flow.c
> > b/drivers/net/i40e/i40e_flow.c index
> > 4d44282312..86d96d9a11 100644
> > --- a/drivers/net/i40e/i40e_flow.c
> > +++ b/drivers/net/i40e/i40e_flow.c
>
>
> > + "Invalid IPv4 "
> > + "fragment_offset mask");
>
> Needn't split the comments line.
>
> > + return -rte_errno;
> > + }
> > + /*
> > + * non-frag rule:
> > + * mask=0x3fff,sepc=0
>
> Typo: sepc->spec
>
> > + * 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");
>
> Same as above.
>
> > + 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
Thanks for the review. Will update them in v2.
BRs
Xiaoyun
> -----Original Message-----
> From: Li, Xiaoyun <xiaoyun.li@intel.com>
> Sent: Tuesday, March 2, 2021 3:03 PM
> To: Xing, Beilei <beilei.xing@intel.com>; Guo, Jia <jia.guo@intel.com>; Lu,
> Wenzhuo <wenzhuo.lu@intel.com>
> Cc: dev@dpdk.org; Li, Xiaoyun <xiaoyun.li@intel.com>; stable@dpdk.org
> Subject: [PATCH v2] net/i40e: fix IPv4 fragment offload issue
>
> 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 <xiaoyun.li@intel.com>
Acked-by: Beilei Xing <beilei.xing@intel.com>
> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Xing, Beilei
> Sent: Tuesday, March 2, 2021 3:17 PM
> To: Li, Xiaoyun <xiaoyun.li@intel.com>; Guo, Jia <jia.guo@intel.com>; Lu,
> Wenzhuo <wenzhuo.lu@intel.com>
> Cc: dev@dpdk.org; stable@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v2] net/i40e: fix IPv4 fragment offload issue
>
>
>
> > -----Original Message-----
> > From: Li, Xiaoyun <xiaoyun.li@intel.com>
> > Sent: Tuesday, March 2, 2021 3:03 PM
> > To: Xing, Beilei <beilei.xing@intel.com>; Guo, Jia
> > <jia.guo@intel.com>; Lu, Wenzhuo <wenzhuo.lu@intel.com>
> > Cc: dev@dpdk.org; Li, Xiaoyun <xiaoyun.li@intel.com>; stable@dpdk.org
> > Subject: [PATCH v2] net/i40e: fix IPv4 fragment offload issue
> >
> > 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 <xiaoyun.li@intel.com>
>
> Acked-by: Beilei Xing <beilei.xing@intel.com>
Applied to dpdk-next-net-intel.
Thanks
Qi