[v1] net/ixgbe: adjust error for UDP with zero checksum
Checks
Commit Message
There is an 82599 errata that UDP frames with a zero checksum are
incorrectly marked as checksum invalid by the hardware. This was
leading to misleading PKT_RX_L4_CKSUM_BAD flag. This patch adds a
test around this checksum error flag set for this condition.
1. UDP Test
sendp(Ether()/IP()/UDP(chksum=0)/Raw("a"*100), iface="ens802f0")
port 0/queue 0: received 1 packets
ol_flags: PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_GOOD
2. TCP Test
sendp(Ether()/IP()/TCP(chksum=0)/Raw("a"*100), iface="ens802f0")
port 0/queue 0: received 1 packets
ol_flags: PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_GOOD
Bugzilla ID: 629
Cc: stable@dpdk.org
Signed-off-by: Haiyue Wang <haiyue.wang@intel.com>
---
doc/guides/nics/ixgbe.rst | 6 ++++
drivers/net/ixgbe/ixgbe_rxtx.c | 27 +++++++++++---
drivers/net/ixgbe/ixgbe_rxtx.h | 2 ++
drivers/net/ixgbe/ixgbe_rxtx_vec_sse.c | 49 ++++++++++++++++++++------
4 files changed, 70 insertions(+), 14 deletions(-)
Comments
Hello Haiyue,
Thanks for working on it quickly.
Cc: ARM maintainers.
On Tue, Feb 2, 2021 at 8:23 AM Haiyue Wang <haiyue.wang@intel.com> wrote:
>
> There is an 82599 errata that UDP frames with a zero checksum are
> incorrectly marked as checksum invalid by the hardware. This was
Maybe add a reference to the 82599 hw errata, is this listed in the datasheet?
> leading to misleading PKT_RX_L4_CKSUM_BAD flag. This patch adds a
> test around this checksum error flag set for this condition.
>
> 1. UDP Test
> sendp(Ether()/IP()/UDP(chksum=0)/Raw("a"*100), iface="ens802f0")
> port 0/queue 0: received 1 packets
> ol_flags: PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_GOOD
>
> 2. TCP Test
> sendp(Ether()/IP()/TCP(chksum=0)/Raw("a"*100), iface="ens802f0")
> port 0/queue 0: received 1 packets
> ol_flags: PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_GOOD
>
> Bugzilla ID: 629
The problem has always been present, so I would flag:
Fixes: af75078fece3 ("first public release")
> Cc: stable@dpdk.org
>
Reported-by: Paolo Valerio <pvalerio@redhat.com>
> Signed-off-by: Haiyue Wang <haiyue.wang@intel.com>
> ---
> doc/guides/nics/ixgbe.rst | 6 ++++
> drivers/net/ixgbe/ixgbe_rxtx.c | 27 +++++++++++---
> drivers/net/ixgbe/ixgbe_rxtx.h | 2 ++
> drivers/net/ixgbe/ixgbe_rxtx_vec_sse.c | 49 ++++++++++++++++++++------
> 4 files changed, 70 insertions(+), 14 deletions(-)
>
> diff --git a/doc/guides/nics/ixgbe.rst b/doc/guides/nics/ixgbe.rst
> index 696cbd93b..de210b7b8 100644
> --- a/doc/guides/nics/ixgbe.rst
> +++ b/doc/guides/nics/ixgbe.rst
> @@ -287,6 +287,12 @@ the VFs which are required.::
> Currently hot-plugging of representor ports is not supported so all required
> representors must be specified on the creation of the PF.
>
> +Limitations or Known issues
> +---------------------------
> +The 82599 hardware errata: UDP frames with a zero checksum can be marked as
> +checksum errors. To support zero checksum, the UDP checksum is always marked
> +as good.
> +
If the driver/hw can't report a valid checksum hint, it should
announce it does not know if the checksum is valid (neither bad, nor
good).
So the workaround for udp packets (on this hw model) would be to
report PKT_RX_L4_CKSUM_UNKNOWN.
The sw application will then have to recompute the checksum itself if needed.
Hi David,
> -----Original Message-----
> From: David Marchand <david.marchand@redhat.com>
> Sent: Tuesday, February 2, 2021 17:45
> To: Wang, Haiyue <haiyue.wang@intel.com>
> Cc: dev <dev@dpdk.org>; pvalerio@redhat.com; Aaron Conole <aconole@redhat.com>; Zhang, Qi Z
> <qi.z.zhang@intel.com>; Rong, Leyi <leyi.rong@intel.com>; Tu, Lijuan <lijuan.tu@intel.com>; dpdk
> stable <stable@dpdk.org>; Guo, Jia <jia.guo@intel.com>; Richardson, Bruce <bruce.richardson@intel.com>;
> Ananyev, Konstantin <konstantin.ananyev@intel.com>; Jerin Jacob Kollanukkaran <jerinj@marvell.com>;
> Ruifeng Wang (Arm Technology China) <ruifeng.wang@arm.com>
> Subject: Re: [PATCH v1] net/ixgbe: adjust error for UDP with zero checksum
>
> Hello Haiyue,
>
> Thanks for working on it quickly.
> Cc: ARM maintainers.
>
> On Tue, Feb 2, 2021 at 8:23 AM Haiyue Wang <haiyue.wang@intel.com> wrote:
> >
> > There is an 82599 errata that UDP frames with a zero checksum are
> > incorrectly marked as checksum invalid by the hardware. This was
>
> Maybe add a reference to the 82599 hw errata, is this listed in the datasheet?
>
I didn't find open and official doc, but on:
https://www.mouser.es/pdfdocs/82599specupdate.pdf
44 Integrity Error Reported for IPv4/UDP Packets
With Zero Checksum
Problem: According to the UDP specification “an all zero transmitted checksum value
means that the transmitter generated no checksum (for debugging or for higher
level protocols that don’t care)”, these packets should be received without a
checksum error notation. The 82599 reports an L4 integrity error if such packets
are received.
Implication: UDP packets without a checksum will have an L4 integrity error indication in the
Rx descriptor.
Workaround: If bits L4E and L4I are set in the Rx descriptor, the software driver should
check if the checksum is zero and then ignore this error.
Status: B0=Yes; No Fix
>
> > leading to misleading PKT_RX_L4_CKSUM_BAD flag. This patch adds a
> > test around this checksum error flag set for this condition.
> >
> > 1. UDP Test
> > sendp(Ether()/IP()/UDP(chksum=0)/Raw("a"*100), iface="ens802f0")
> > port 0/queue 0: received 1 packets
> > ol_flags: PKT_RX_L4_CKSUM_GOOD PKT_RX_IP_CKSUM_GOOD
> >
> > 2. TCP Test
> > sendp(Ether()/IP()/TCP(chksum=0)/Raw("a"*100), iface="ens802f0")
> > port 0/queue 0: received 1 packets
> > ol_flags: PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_GOOD
> >
> > Bugzilla ID: 629
>
> The problem has always been present, so I would flag:
> Fixes: af75078fece3 ("first public release")
>
> > Cc: stable@dpdk.org
> >
>
> Reported-by: Paolo Valerio <pvalerio@redhat.com>
> > Signed-off-by: Haiyue Wang <haiyue.wang@intel.com>
> > ---
> > doc/guides/nics/ixgbe.rst | 6 ++++
> > drivers/net/ixgbe/ixgbe_rxtx.c | 27 +++++++++++---
> > drivers/net/ixgbe/ixgbe_rxtx.h | 2 ++
> > drivers/net/ixgbe/ixgbe_rxtx_vec_sse.c | 49 ++++++++++++++++++++------
> > 4 files changed, 70 insertions(+), 14 deletions(-)
> >
> > diff --git a/doc/guides/nics/ixgbe.rst b/doc/guides/nics/ixgbe.rst
> > index 696cbd93b..de210b7b8 100644
> > --- a/doc/guides/nics/ixgbe.rst
> > +++ b/doc/guides/nics/ixgbe.rst
> > @@ -287,6 +287,12 @@ the VFs which are required.::
> > Currently hot-plugging of representor ports is not supported so all required
> > representors must be specified on the creation of the PF.
> >
> > +Limitations or Known issues
> > +---------------------------
> > +The 82599 hardware errata: UDP frames with a zero checksum can be marked as
> > +checksum errors. To support zero checksum, the UDP checksum is always marked
> > +as good.
> > +
>
> If the driver/hw can't report a valid checksum hint, it should
> announce it does not know if the checksum is valid (neither bad, nor
> good).
>
> So the workaround for udp packets (on this hw model) would be to
> report PKT_RX_L4_CKSUM_UNKNOWN.
> The sw application will then have to recompute the checksum itself if needed.
>
Make sense, but not sure the vector path can handle this more easily. Will try.
>
> --
> David Marchand
On Tue, Feb 2, 2021 at 1:42 PM Wang, Haiyue <haiyue.wang@intel.com> wrote:
> > If the driver/hw can't report a valid checksum hint, it should
> > announce it does not know if the checksum is valid (neither bad, nor
> > good).
> >
> > So the workaround for udp packets (on this hw model) would be to
> > report PKT_RX_L4_CKSUM_UNKNOWN.
> > The sw application will then have to recompute the checksum itself if needed.
> >
>
> Make sense, but not sure the vector path can handle this more easily. Will try.
Refining this a bit.
It looks like hw correctly reports "good" checksums, so maybe instead
report PKT_RX_L4_CKSUM_UNKNOWN only for reports of "bad" checksums
from the hw?
> -----Original Message-----
> From: David Marchand <david.marchand@redhat.com>
> Sent: Tuesday, February 2, 2021 17:45
> To: Wang, Haiyue <haiyue.wang@intel.com>
> Cc: dev <dev@dpdk.org>; pvalerio@redhat.com; Aaron Conole <aconole@redhat.com>; Zhang, Qi Z
> <qi.z.zhang@intel.com>; Rong, Leyi <leyi.rong@intel.com>; Tu, Lijuan <lijuan.tu@intel.com>; dpdk
> stable <stable@dpdk.org>; Guo, Jia <jia.guo@intel.com>; Richardson, Bruce <bruce.richardson@intel.com>;
> Ananyev, Konstantin <konstantin.ananyev@intel.com>; Jerin Jacob Kollanukkaran <jerinj@marvell.com>;
> Ruifeng Wang (Arm Technology China) <ruifeng.wang@arm.com>
> Subject: Re: [PATCH v1] net/ixgbe: adjust error for UDP with zero checksum
>
>
> If the driver/hw can't report a valid checksum hint, it should
> announce it does not know if the checksum is valid (neither bad, nor
> good).
>
> So the workaround for udp packets (on this hw model) would be to
> report PKT_RX_L4_CKSUM_UNKNOWN.
> The sw application will then have to recompute the checksum itself if needed.
>
Looks like this workaround will make OVS performance drop a lot, since
every UDP packet needs to do checksum by SW:
bool hwol_good_l4_csum = dp_packet_l4_checksum_valid(pkt)
|| dp_packet_hwol_tx_l4_checksum(pkt);
/* Validate the checksum only when hwol is not supported. */
if (extract_l4(&ctx->key, l4, dp_packet_l4_size(pkt),
&ctx->icmp_related, l3, !hwol_good_l4_csum,
NULL)) {
ctx->hash = conn_key_hash(&ctx->key, ct->hash_basis);
return true;
}
The lesser of the two rights, marking as good seems a little better.
>
> --
> David Marchand
> -----Original Message-----
> From: David Marchand <david.marchand@redhat.com>
> Sent: Tuesday, February 2, 2021 20:54
> To: Wang, Haiyue <haiyue.wang@intel.com>
> Cc: dev <dev@dpdk.org>; pvalerio@redhat.com; Aaron Conole <aconole@redhat.com>; Zhang, Qi Z
> <qi.z.zhang@intel.com>; Rong, Leyi <leyi.rong@intel.com>; Tu, Lijuan <lijuan.tu@intel.com>; dpdk
> stable <stable@dpdk.org>; Guo, Jia <jia.guo@intel.com>; Richardson, Bruce <bruce.richardson@intel.com>;
> Ananyev, Konstantin <konstantin.ananyev@intel.com>; Jerin Jacob Kollanukkaran <jerinj@marvell.com>;
> Ruifeng Wang (Arm Technology China) <ruifeng.wang@arm.com>
> Subject: Re: [PATCH v1] net/ixgbe: adjust error for UDP with zero checksum
>
> On Tue, Feb 2, 2021 at 1:42 PM Wang, Haiyue <haiyue.wang@intel.com> wrote:
> > > If the driver/hw can't report a valid checksum hint, it should
> > > announce it does not know if the checksum is valid (neither bad, nor
> > > good).
> > >
> > > So the workaround for udp packets (on this hw model) would be to
> > > report PKT_RX_L4_CKSUM_UNKNOWN.
> > > The sw application will then have to recompute the checksum itself if needed.
> > >
> >
> > Make sense, but not sure the vector path can handle this more easily. Will try.
>
> Refining this a bit.
> It looks like hw correctly reports "good" checksums, so maybe instead
> report PKT_RX_L4_CKSUM_UNKNOWN only for reports of "bad" checksums
> from the hw?
I guess Paolo will complain about the performance drop for zero checksum
UDP. ;-)
>
> --
> David Marchand
> -----Original Message-----
> From: Wang, Haiyue
> Sent: Tuesday, February 2, 2021 20:57
> To: David Marchand <david.marchand@redhat.com>
> Cc: dev <dev@dpdk.org>; pvalerio@redhat.com; Aaron Conole <aconole@redhat.com>; Zhang, Qi Z
> <qi.z.zhang@intel.com>; Rong, Leyi <leyi.rong@intel.com>; Tu, Lijuan <Lijuan.Tu@intel.com>; dpdk
> stable <stable@dpdk.org>; Guo, Jia <jia.guo@intel.com>; Richardson, Bruce <bruce.richardson@intel.com>;
> Ananyev, Konstantin <konstantin.ananyev@intel.com>; Jerin Jacob Kollanukkaran <jerinj@marvell.com>;
> Ruifeng Wang (Arm Technology China) <ruifeng.wang@arm.com>
> Subject: RE: [PATCH v1] net/ixgbe: adjust error for UDP with zero checksum
>
> > -----Original Message-----
> > From: David Marchand <david.marchand@redhat.com>
> > Sent: Tuesday, February 2, 2021 20:54
> > To: Wang, Haiyue <haiyue.wang@intel.com>
> > Cc: dev <dev@dpdk.org>; pvalerio@redhat.com; Aaron Conole <aconole@redhat.com>; Zhang, Qi Z
> > <qi.z.zhang@intel.com>; Rong, Leyi <leyi.rong@intel.com>; Tu, Lijuan <lijuan.tu@intel.com>; dpdk
> > stable <stable@dpdk.org>; Guo, Jia <jia.guo@intel.com>; Richardson, Bruce
> <bruce.richardson@intel.com>;
> > Ananyev, Konstantin <konstantin.ananyev@intel.com>; Jerin Jacob Kollanukkaran <jerinj@marvell.com>;
> > Ruifeng Wang (Arm Technology China) <ruifeng.wang@arm.com>
> > Subject: Re: [PATCH v1] net/ixgbe: adjust error for UDP with zero checksum
> >
> > On Tue, Feb 2, 2021 at 1:42 PM Wang, Haiyue <haiyue.wang@intel.com> wrote:
> > > > If the driver/hw can't report a valid checksum hint, it should
> > > > announce it does not know if the checksum is valid (neither bad, nor
> > > > good).
> > > >
> > > > So the workaround for udp packets (on this hw model) would be to
> > > > report PKT_RX_L4_CKSUM_UNKNOWN.
> > > > The sw application will then have to recompute the checksum itself if needed.
> > > >
> > >
> > > Make sense, but not sure the vector path can handle this more easily. Will try.
> >
> > Refining this a bit.
> > It looks like hw correctly reports "good" checksums, so maybe instead
> > report PKT_RX_L4_CKSUM_UNKNOWN only for reports of "bad" checksums
> > from the hw?
>
> I guess Paolo will complain about the performance drop for zero checksum
> UDP. ;-)
>
Deep into OVS for detail, 'PKT_RX_L4_CKSUM_UNKNOWN' is a graceful way. ;-)
Will work for this target.
/* Validation must be skipped if checksum is 0 on IPv4 packets */
return (udp->udp_csum == 0 && key->dl_type == htons(ETH_TYPE_IP))
|| (validate_checksum ? checksum_valid(key, data, size, l3) : true);
> >
> > --
> > David Marchand
"Wang, Haiyue" <haiyue.wang@intel.com> writes:
>> -----Original Message-----
>> From: Wang, Haiyue
>> Sent: Tuesday, February 2, 2021 20:57
>> To: David Marchand <david.marchand@redhat.com>
>> Cc: dev <dev@dpdk.org>; pvalerio@redhat.com; Aaron Conole <aconole@redhat.com>; Zhang, Qi Z
>> <qi.z.zhang@intel.com>; Rong, Leyi <leyi.rong@intel.com>; Tu, Lijuan <Lijuan.Tu@intel.com>; dpdk
>> stable <stable@dpdk.org>; Guo, Jia <jia.guo@intel.com>; Richardson, Bruce <bruce.richardson@intel.com>;
>> Ananyev, Konstantin <konstantin.ananyev@intel.com>; Jerin Jacob Kollanukkaran <jerinj@marvell.com>;
>> Ruifeng Wang (Arm Technology China) <ruifeng.wang@arm.com>
>> Subject: RE: [PATCH v1] net/ixgbe: adjust error for UDP with zero checksum
>>
>> > -----Original Message-----
>> > From: David Marchand <david.marchand@redhat.com>
>> > Sent: Tuesday, February 2, 2021 20:54
>> > To: Wang, Haiyue <haiyue.wang@intel.com>
>> > Cc: dev <dev@dpdk.org>; pvalerio@redhat.com; Aaron Conole <aconole@redhat.com>; Zhang, Qi Z
>> > <qi.z.zhang@intel.com>; Rong, Leyi <leyi.rong@intel.com>; Tu, Lijuan <lijuan.tu@intel.com>; dpdk
>> > stable <stable@dpdk.org>; Guo, Jia <jia.guo@intel.com>; Richardson, Bruce
>> <bruce.richardson@intel.com>;
>> > Ananyev, Konstantin <konstantin.ananyev@intel.com>; Jerin Jacob Kollanukkaran <jerinj@marvell.com>;
>> > Ruifeng Wang (Arm Technology China) <ruifeng.wang@arm.com>
>> > Subject: Re: [PATCH v1] net/ixgbe: adjust error for UDP with zero checksum
>> >
>> > On Tue, Feb 2, 2021 at 1:42 PM Wang, Haiyue <haiyue.wang@intel.com> wrote:
>> > > > If the driver/hw can't report a valid checksum hint, it should
>> > > > announce it does not know if the checksum is valid (neither bad, nor
>> > > > good).
>> > > >
>> > > > So the workaround for udp packets (on this hw model) would be to
>> > > > report PKT_RX_L4_CKSUM_UNKNOWN.
>> > > > The sw application will then have to recompute the checksum itself if needed.
>> > > >
>> > >
>> > > Make sense, but not sure the vector path can handle this more easily. Will try.
>> >
>> > Refining this a bit.
>> > It looks like hw correctly reports "good" checksums, so maybe instead
>> > report PKT_RX_L4_CKSUM_UNKNOWN only for reports of "bad" checksums
>> > from the hw?
>>
>> I guess Paolo will complain about the performance drop for zero checksum
>> UDP. ;-)
>>
:)
>
> Deep into OVS for detail, 'PKT_RX_L4_CKSUM_UNKNOWN' is a graceful way. ;-)
> Will work for this target.
yes, validation gets skipped in such case.
I'll be happy to test it once posted.
>
> /* Validation must be skipped if checksum is 0 on IPv4 packets */
> return (udp->udp_csum == 0 && key->dl_type == htons(ETH_TYPE_IP))
> || (validate_checksum ? checksum_valid(key, data, size, l3) : true);
>
>> >
>> > --
>> > David Marchand
@@ -287,6 +287,12 @@ the VFs which are required.::
Currently hot-plugging of representor ports is not supported so all required
representors must be specified on the creation of the PF.
+Limitations or Known issues
+---------------------------
+The 82599 hardware errata: UDP frames with a zero checksum can be marked as
+checksum errors. To support zero checksum, the UDP checksum is always marked
+as good.
+
Supported Chipsets and NICs
---------------------------
@@ -1466,7 +1466,8 @@ rx_desc_status_to_pkt_flags(uint32_t rx_status, uint64_t vlan_flags)
}
static inline uint64_t
-rx_desc_error_to_pkt_flags(uint32_t rx_status)
+rx_desc_error_to_pkt_flags(uint32_t rx_status, uint16_t pkt_info,
+ uint8_t rx_udp_csum_zero_err)
{
uint64_t pkt_flags;
@@ -1480,6 +1481,12 @@ rx_desc_error_to_pkt_flags(uint32_t rx_status)
PKT_RX_IP_CKSUM_BAD | PKT_RX_L4_CKSUM_GOOD,
PKT_RX_IP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD
};
+
+ if ((rx_status & IXGBE_RXDADV_ERR_TCPE) &&
+ (pkt_info & IXGBE_RXDADV_PKTTYPE_UDP) &&
+ rx_udp_csum_zero_err)
+ rx_status &= ~IXGBE_RXDADV_ERR_TCPE;
+
pkt_flags = error_to_pkt_flags_map[(rx_status >>
IXGBE_RXDADV_ERR_CKSUM_BIT) & IXGBE_RXDADV_ERR_CKSUM_MSK];
@@ -1569,7 +1576,9 @@ ixgbe_rx_scan_hw_ring(struct ixgbe_rx_queue *rxq)
/* convert descriptor fields to rte mbuf flags */
pkt_flags = rx_desc_status_to_pkt_flags(s[j],
vlan_flags);
- pkt_flags |= rx_desc_error_to_pkt_flags(s[j]);
+ pkt_flags |= rx_desc_error_to_pkt_flags(s[j],
+ (uint16_t)pkt_info[j],
+ rxq->rx_udp_csum_zero_err);
pkt_flags |= ixgbe_rxd_pkt_info_to_pkt_flags
((uint16_t)pkt_info[j]);
mb->ol_flags = pkt_flags;
@@ -1902,7 +1911,9 @@ ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
rxm->vlan_tci = rte_le_to_cpu_16(rxd.wb.upper.vlan);
pkt_flags = rx_desc_status_to_pkt_flags(staterr, vlan_flags);
- pkt_flags = pkt_flags | rx_desc_error_to_pkt_flags(staterr);
+ pkt_flags = pkt_flags |
+ rx_desc_error_to_pkt_flags(staterr, (uint16_t)pkt_info,
+ rxq->rx_udp_csum_zero_err);
pkt_flags = pkt_flags |
ixgbe_rxd_pkt_info_to_pkt_flags((uint16_t)pkt_info);
rxm->ol_flags = pkt_flags;
@@ -1995,7 +2006,8 @@ ixgbe_fill_cluster_head_buf(
head->vlan_tci = rte_le_to_cpu_16(desc->wb.upper.vlan);
pkt_info = rte_le_to_cpu_32(desc->wb.lower.lo_dword.data);
pkt_flags = rx_desc_status_to_pkt_flags(staterr, rxq->vlan_flags);
- pkt_flags |= rx_desc_error_to_pkt_flags(staterr);
+ pkt_flags |= rx_desc_error_to_pkt_flags(staterr, (uint16_t)pkt_info,
+ rxq->rx_udp_csum_zero_err);
pkt_flags |= ixgbe_rxd_pkt_info_to_pkt_flags((uint16_t)pkt_info);
head->ol_flags = pkt_flags;
head->packet_type =
@@ -3116,6 +3128,13 @@ ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev,
else
rxq->pkt_type_mask = IXGBE_PACKET_TYPE_MASK_82599;
+ /*
+ * 82599 errata, UDP frames with a 0 checksum can be marked as checksum
+ * errors.
+ */
+ if (hw->mac.type == ixgbe_mac_82599EB)
+ rxq->rx_udp_csum_zero_err = 1;
+
/*
* Allocate RX ring hardware descriptors. A memzone large enough to
* handle the maximum ring size is allocated in order to allow for
@@ -129,6 +129,8 @@ struct ixgbe_rx_queue {
uint8_t crc_len; /**< 0 if CRC stripped, 4 otherwise. */
uint8_t drop_en; /**< If not 0, set SRRCTL.Drop_En. */
uint8_t rx_deferred_start; /**< not in global dev start. */
+ /** UDP frames with a 0 checksum can be marked as checksum errors. */
+ uint8_t rx_udp_csum_zero_err;
/** flags to set in mbuf when a vlan is detected. */
uint64_t vlan_flags;
uint64_t offloads; /**< Rx offloads with DEV_RX_OFFLOAD_* */
@@ -132,9 +132,9 @@ desc_to_olflags_v_ipsec(__m128i descs[4], struct rte_mbuf **rx_pkts)
static inline void
desc_to_olflags_v(__m128i descs[4], __m128i mbuf_init, uint8_t vlan_flags,
- struct rte_mbuf **rx_pkts)
+ uint16_t udp_p_flag, struct rte_mbuf **rx_pkts)
{
- __m128i ptype0, ptype1, vtag0, vtag1, csum;
+ __m128i ptype0, ptype1, vtag0, vtag1, csum, vlan_csum_msk;
__m128i rearm0, rearm1, rearm2, rearm3;
/* mask everything except rss type */
@@ -154,13 +154,29 @@ desc_to_olflags_v(__m128i descs[4], __m128i mbuf_init, uint8_t vlan_flags,
PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, 0);
/* mask everything except vlan present and l4/ip csum error */
- const __m128i vlan_csum_msk = _mm_set_epi16(
- (IXGBE_RXDADV_ERR_TCPE | IXGBE_RXDADV_ERR_IPE) >> 16,
- (IXGBE_RXDADV_ERR_TCPE | IXGBE_RXDADV_ERR_IPE) >> 16,
- (IXGBE_RXDADV_ERR_TCPE | IXGBE_RXDADV_ERR_IPE) >> 16,
- (IXGBE_RXDADV_ERR_TCPE | IXGBE_RXDADV_ERR_IPE) >> 16,
- IXGBE_RXD_STAT_VP, IXGBE_RXD_STAT_VP,
- IXGBE_RXD_STAT_VP, IXGBE_RXD_STAT_VP);
+ const __m128i vlan_csum_all_msk = _mm_set_epi16
+ ((IXGBE_RXDADV_ERR_TCPE | IXGBE_RXDADV_ERR_IPE) >> 16,
+ (IXGBE_RXDADV_ERR_TCPE | IXGBE_RXDADV_ERR_IPE) >> 16,
+ (IXGBE_RXDADV_ERR_TCPE | IXGBE_RXDADV_ERR_IPE) >> 16,
+ (IXGBE_RXDADV_ERR_TCPE | IXGBE_RXDADV_ERR_IPE) >> 16,
+ IXGBE_RXD_STAT_VP, IXGBE_RXD_STAT_VP,
+ IXGBE_RXD_STAT_VP, IXGBE_RXD_STAT_VP);
+
+ /* mask everything except UDP header present */
+ const __m128i udptype_msk = _mm_set_epi16
+ (0, 0, 0, 0,
+ udp_p_flag, udp_p_flag, udp_p_flag, udp_p_flag);
+
+ /* convert UDP header present 16 bits 0x0200 to 8 bits 0x02, then get
+ * the TCP/UDP checksum error mask 8 bits ~0x40 from 32 bits value of
+ * 0x40000000.
+ */
+ const __m128i udp_csum_err_skip = _mm_set_epi8
+ (0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, ~(IXGBE_RXDADV_ERR_TCPE >> 24), 0, 0xFF);
+
/* map vlan present (0x8), IPE (0x2), L4E (0x1) to ol_flags */
const __m128i vlan_csum_map_lo = _mm_set_epi8(
0, 0, 0, 0,
@@ -188,9 +204,17 @@ desc_to_olflags_v(__m128i descs[4], __m128i mbuf_init, uint8_t vlan_flags,
vtag1 = _mm_unpackhi_epi16(descs[2], descs[3]);
ptype0 = _mm_unpacklo_epi32(ptype0, ptype1);
+ /* save the UDP header present information */
+ vlan_csum_msk = _mm_and_si128(ptype0, udptype_msk);
ptype0 = _mm_and_si128(ptype0, rsstype_msk);
ptype0 = _mm_shuffle_epi8(rss_flags, ptype0);
+ /* now the most significant 64 bits containing the UDP present */
+ vlan_csum_msk = _mm_slli_si128(vlan_csum_msk, 8);
+ /* use UDP present 0x02 index to get L4 checksum error mask ~0x40 */
+ vlan_csum_msk = _mm_shuffle_epi8(udp_csum_err_skip, vlan_csum_msk);
+ /* then mask out the L4 checksum error bit as needed */
+ vlan_csum_msk = _mm_and_si128(vlan_csum_all_msk, vlan_csum_msk);
vtag1 = _mm_unpacklo_epi32(vtag0, vtag1);
vtag1 = _mm_and_si128(vtag1, vlan_csum_msk);
@@ -341,6 +365,7 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
__m128i dd_check, eop_check;
__m128i mbuf_init;
uint8_t vlan_flags;
+ uint16_t udp_p_flag = 0; /* Rx Descriptor UDP header present */
/* nb_pkts has to be floor-aligned to RTE_IXGBE_DESCS_PER_LOOP */
nb_pkts = RTE_ALIGN_FLOOR(nb_pkts, RTE_IXGBE_DESCS_PER_LOOP);
@@ -365,6 +390,9 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
rte_cpu_to_le_32(IXGBE_RXDADV_STAT_DD)))
return 0;
+ if (rxq->rx_udp_csum_zero_err)
+ udp_p_flag = IXGBE_RXDADV_PKTTYPE_UDP;
+
/* 4 packets DD mask */
dd_check = _mm_set_epi64x(0x0000000100000001LL, 0x0000000100000001LL);
@@ -477,7 +505,8 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
sterr_tmp1 = _mm_unpackhi_epi32(descs[1], descs[0]);
/* set ol_flags with vlan packet type */
- desc_to_olflags_v(descs, mbuf_init, vlan_flags, &rx_pkts[pos]);
+ desc_to_olflags_v(descs, mbuf_init, vlan_flags, udp_p_flag,
+ &rx_pkts[pos]);
#ifdef RTE_LIB_SECURITY
if (unlikely(use_ipsec))