* [dpdk-dev] [PATCH 0/4] net/tap: fix Rx cksum @ 2021-04-27 13:57 Olivier Matz 2021-04-27 13:57 ` [dpdk-dev] [PATCH 1/4] net/tap: fix Rx cksum flags on IP options packets Olivier Matz ` (4 more replies) 0 siblings, 5 replies; 28+ messages in thread From: Olivier Matz @ 2021-04-27 13:57 UTC (permalink / raw) To: dev; +Cc: Keith Wiles, Hongzhi Guo, Morten Brørup, Thomas Monjalon This patchset fixes the Rx checksum flags in net/tap driver. The first two patches are the effective fixes. The last 2 patches introduce a new checksum API to verify a L4 checksum and its unt test, in order to simplify the net/tap code, or any other code that has the same needs. The last 2 patches may be postponed to 20.08 if required. Olivier Matz (4): net/tap: fix Rx cksum flags on IP options packets net/tap: fix Rx cksum flags on TCP packets net: introduce functions to verify L4 checksums test/cksum: new test for L3/L4 checksum API MAINTAINERS | 1 + app/test/autotest_data.py | 6 + app/test/meson.build | 2 + app/test/test_cksum.c | 271 ++++++++++++++++++++++++++++++++++ drivers/net/tap/rte_eth_tap.c | 17 ++- lib/net/rte_ip.h | 124 +++++++++++++--- 6 files changed, 390 insertions(+), 31 deletions(-) create mode 100644 app/test/test_cksum.c -- 2.29.2 ^ permalink raw reply [flat|nested] 28+ messages in thread
* [dpdk-dev] [PATCH 1/4] net/tap: fix Rx cksum flags on IP options packets 2021-04-27 13:57 [dpdk-dev] [PATCH 0/4] net/tap: fix Rx cksum Olivier Matz @ 2021-04-27 13:57 ` Olivier Matz 2021-04-30 14:48 ` [dpdk-dev] [dpdk-stable] " Ferruh Yigit 2021-04-27 13:57 ` [dpdk-dev] [PATCH 2/4] net/tap: fix Rx cksum flags on TCP packets Olivier Matz ` (3 subsequent siblings) 4 siblings, 1 reply; 28+ messages in thread From: Olivier Matz @ 2021-04-27 13:57 UTC (permalink / raw) To: dev; +Cc: Keith Wiles, Hongzhi Guo, Morten Brørup, Thomas Monjalon, stable When packet type is IPV4_EXT, the checksum is always marked as good in the mbuf offload flags. Since we know the header lengths, we can easily call rte_ipv4_udptcp_cksum() in this case too. Fixes: 8ae3023387e9 ("net/tap: add Rx/Tx checksum offload support") Cc: stable@dpdk.org Signed-off-by: Olivier Matz <olivier.matz@6wind.com> --- drivers/net/tap/rte_eth_tap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c index 68baa18523..e7b185a4b5 100644 --- a/drivers/net/tap/rte_eth_tap.c +++ b/drivers/net/tap/rte_eth_tap.c @@ -350,7 +350,7 @@ tap_verify_csum(struct rte_mbuf *mbuf) /* Don't verify checksum for multi-segment packets. */ if (mbuf->nb_segs > 1) return; - if (l3 == RTE_PTYPE_L3_IPV4) { + if (l3 == RTE_PTYPE_L3_IPV4 || l3 == RTE_PTYPE_L3_IPV4_EXT) { if (l4 == RTE_PTYPE_L4_UDP) { udp_hdr = (struct rte_udp_hdr *)l4_hdr; if (udp_hdr->dgram_cksum == 0) { @@ -364,7 +364,7 @@ tap_verify_csum(struct rte_mbuf *mbuf) } } cksum = ~rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); - } else if (l3 == RTE_PTYPE_L3_IPV6) { + } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ cksum = ~rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); } mbuf->ol_flags |= cksum ? -- 2.29.2 ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [dpdk-dev] [dpdk-stable] [PATCH 1/4] net/tap: fix Rx cksum flags on IP options packets 2021-04-27 13:57 ` [dpdk-dev] [PATCH 1/4] net/tap: fix Rx cksum flags on IP options packets Olivier Matz @ 2021-04-30 14:48 ` Ferruh Yigit 2021-06-08 10:13 ` Andrew Rybchenko 0 siblings, 1 reply; 28+ messages in thread From: Ferruh Yigit @ 2021-04-30 14:48 UTC (permalink / raw) To: Olivier Matz, dev Cc: Keith Wiles, Hongzhi Guo, Morten Brørup, Thomas Monjalon, stable On 4/27/2021 2:57 PM, Olivier Matz wrote: > When packet type is IPV4_EXT, the checksum is always marked as good in > the mbuf offload flags. > > Since we know the header lengths, we can easily call > rte_ipv4_udptcp_cksum() in this case too. > > Fixes: 8ae3023387e9 ("net/tap: add Rx/Tx checksum offload support") > Cc: stable@dpdk.org > > Signed-off-by: Olivier Matz <olivier.matz@6wind.com> > --- > drivers/net/tap/rte_eth_tap.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c > index 68baa18523..e7b185a4b5 100644 > --- a/drivers/net/tap/rte_eth_tap.c > +++ b/drivers/net/tap/rte_eth_tap.c > @@ -350,7 +350,7 @@ tap_verify_csum(struct rte_mbuf *mbuf) > /* Don't verify checksum for multi-segment packets. */ > if (mbuf->nb_segs > 1) > return; > - if (l3 == RTE_PTYPE_L3_IPV4) { > + if (l3 == RTE_PTYPE_L3_IPV4 || l3 == RTE_PTYPE_L3_IPV4_EXT) { Should we take 'RTE_PTYPE_L3_IPV4_EXT_UNKNOWN' into account? > if (l4 == RTE_PTYPE_L4_UDP) { > udp_hdr = (struct rte_udp_hdr *)l4_hdr; > if (udp_hdr->dgram_cksum == 0) { > @@ -364,7 +364,7 @@ tap_verify_csum(struct rte_mbuf *mbuf) > } > } > cksum = ~rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); > - } else if (l3 == RTE_PTYPE_L3_IPV6) { > + } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ > cksum = ~rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); > } > mbuf->ol_flags |= cksum ? > ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [dpdk-dev] [dpdk-stable] [PATCH 1/4] net/tap: fix Rx cksum flags on IP options packets 2021-04-30 14:48 ` [dpdk-dev] [dpdk-stable] " Ferruh Yigit @ 2021-06-08 10:13 ` Andrew Rybchenko 2021-06-08 12:29 ` Olivier Matz 0 siblings, 1 reply; 28+ messages in thread From: Andrew Rybchenko @ 2021-06-08 10:13 UTC (permalink / raw) To: Ferruh Yigit, Olivier Matz, dev Cc: Keith Wiles, Hongzhi Guo, Morten Brørup, Thomas Monjalon, stable On 4/30/21 5:48 PM, Ferruh Yigit wrote: > On 4/27/2021 2:57 PM, Olivier Matz wrote: >> When packet type is IPV4_EXT, the checksum is always marked as good in >> the mbuf offload flags. >> >> Since we know the header lengths, we can easily call >> rte_ipv4_udptcp_cksum() in this case too. >> >> Fixes: 8ae3023387e9 ("net/tap: add Rx/Tx checksum offload support") >> Cc: stable@dpdk.org >> >> Signed-off-by: Olivier Matz <olivier.matz@6wind.com> >> --- >> drivers/net/tap/rte_eth_tap.c | 4 ++-- >> 1 file changed, 2 insertions(+), 2 deletions(-) >> >> diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c >> index 68baa18523..e7b185a4b5 100644 >> --- a/drivers/net/tap/rte_eth_tap.c >> +++ b/drivers/net/tap/rte_eth_tap.c >> @@ -350,7 +350,7 @@ tap_verify_csum(struct rte_mbuf *mbuf) >> /* Don't verify checksum for multi-segment packets. */ >> if (mbuf->nb_segs > 1) >> return; >> - if (l3 == RTE_PTYPE_L3_IPV4) { >> + if (l3 == RTE_PTYPE_L3_IPV4 || l3 == RTE_PTYPE_L3_IPV4_EXT) { > > Should we take 'RTE_PTYPE_L3_IPV4_EXT_UNKNOWN' into account? I think we should. > >> if (l4 == RTE_PTYPE_L4_UDP) { >> udp_hdr = (struct rte_udp_hdr *)l4_hdr; >> if (udp_hdr->dgram_cksum == 0) { >> @@ -364,7 +364,7 @@ tap_verify_csum(struct rte_mbuf *mbuf) >> } >> } >> cksum = ~rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); >> - } else if (l3 == RTE_PTYPE_L3_IPV6) { >> + } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ >> cksum = ~rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); >> } >> mbuf->ol_flags |= cksum ? >> ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [dpdk-dev] [dpdk-stable] [PATCH 1/4] net/tap: fix Rx cksum flags on IP options packets 2021-06-08 10:13 ` Andrew Rybchenko @ 2021-06-08 12:29 ` Olivier Matz 2021-06-08 12:34 ` Andrew Rybchenko 0 siblings, 1 reply; 28+ messages in thread From: Olivier Matz @ 2021-06-08 12:29 UTC (permalink / raw) To: Andrew Rybchenko Cc: Ferruh Yigit, dev, Keith Wiles, Hongzhi Guo, Morten Brørup, Thomas Monjalon, stable Hi Ferruh, Andrew, On Tue, Jun 08, 2021 at 01:13:59PM +0300, Andrew Rybchenko wrote: > On 4/30/21 5:48 PM, Ferruh Yigit wrote: > > On 4/27/2021 2:57 PM, Olivier Matz wrote: > >> When packet type is IPV4_EXT, the checksum is always marked as good in > >> the mbuf offload flags. > >> > >> Since we know the header lengths, we can easily call > >> rte_ipv4_udptcp_cksum() in this case too. > >> > >> Fixes: 8ae3023387e9 ("net/tap: add Rx/Tx checksum offload support") > >> Cc: stable@dpdk.org > >> > >> Signed-off-by: Olivier Matz <olivier.matz@6wind.com> > >> --- > >> drivers/net/tap/rte_eth_tap.c | 4 ++-- > >> 1 file changed, 2 insertions(+), 2 deletions(-) > >> > >> diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c > >> index 68baa18523..e7b185a4b5 100644 > >> --- a/drivers/net/tap/rte_eth_tap.c > >> +++ b/drivers/net/tap/rte_eth_tap.c > >> @@ -350,7 +350,7 @@ tap_verify_csum(struct rte_mbuf *mbuf) > >> /* Don't verify checksum for multi-segment packets. */ > >> if (mbuf->nb_segs > 1) > >> return; > >> - if (l3 == RTE_PTYPE_L3_IPV4) { > >> + if (l3 == RTE_PTYPE_L3_IPV4 || l3 == RTE_PTYPE_L3_IPV4_EXT) { > > > > Should we take 'RTE_PTYPE_L3_IPV4_EXT_UNKNOWN' into account? > > I think we should. I think 'RTE_PTYPE_L3_IPV4_EXT_UNKNOWN' cannot happen here: - mbuf->packet_type is generated by rte_net_get_ptype(), which cannot return 'RTE_PTYPE_L3_IPV4_EXT_UNKNOWN' - right above this code, we already returned if l3 is not in (RTE_PTYPE_L3_IPV4, RTE_PTYPE_L3_IPV4_EXT, RTE_PTYPE_L3_IPV6) > > > >> if (l4 == RTE_PTYPE_L4_UDP) { > >> udp_hdr = (struct rte_udp_hdr *)l4_hdr; > >> if (udp_hdr->dgram_cksum == 0) { > >> @@ -364,7 +364,7 @@ tap_verify_csum(struct rte_mbuf *mbuf) > >> } > >> } > >> cksum = ~rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); > >> - } else if (l3 == RTE_PTYPE_L3_IPV6) { > >> + } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ > >> cksum = ~rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); > >> } > >> mbuf->ol_flags |= cksum ? > >> > ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [dpdk-dev] [dpdk-stable] [PATCH 1/4] net/tap: fix Rx cksum flags on IP options packets 2021-06-08 12:29 ` Olivier Matz @ 2021-06-08 12:34 ` Andrew Rybchenko 2021-06-08 12:49 ` Olivier Matz 0 siblings, 1 reply; 28+ messages in thread From: Andrew Rybchenko @ 2021-06-08 12:34 UTC (permalink / raw) To: Olivier Matz Cc: Ferruh Yigit, dev, Keith Wiles, Hongzhi Guo, Morten Brørup, Thomas Monjalon, stable On 6/8/21 3:29 PM, Olivier Matz wrote: > Hi Ferruh, Andrew, > > On Tue, Jun 08, 2021 at 01:13:59PM +0300, Andrew Rybchenko wrote: >> On 4/30/21 5:48 PM, Ferruh Yigit wrote: >>> On 4/27/2021 2:57 PM, Olivier Matz wrote: >>>> When packet type is IPV4_EXT, the checksum is always marked as good in >>>> the mbuf offload flags. >>>> >>>> Since we know the header lengths, we can easily call >>>> rte_ipv4_udptcp_cksum() in this case too. >>>> >>>> Fixes: 8ae3023387e9 ("net/tap: add Rx/Tx checksum offload support") >>>> Cc: stable@dpdk.org >>>> >>>> Signed-off-by: Olivier Matz <olivier.matz@6wind.com> >>>> --- >>>> drivers/net/tap/rte_eth_tap.c | 4 ++-- >>>> 1 file changed, 2 insertions(+), 2 deletions(-) >>>> >>>> diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c >>>> index 68baa18523..e7b185a4b5 100644 >>>> --- a/drivers/net/tap/rte_eth_tap.c >>>> +++ b/drivers/net/tap/rte_eth_tap.c >>>> @@ -350,7 +350,7 @@ tap_verify_csum(struct rte_mbuf *mbuf) >>>> /* Don't verify checksum for multi-segment packets. */ >>>> if (mbuf->nb_segs > 1) >>>> return; >>>> - if (l3 == RTE_PTYPE_L3_IPV4) { >>>> + if (l3 == RTE_PTYPE_L3_IPV4 || l3 == RTE_PTYPE_L3_IPV4_EXT) { >>> >>> Should we take 'RTE_PTYPE_L3_IPV4_EXT_UNKNOWN' into account? >> >> I think we should. > > I think 'RTE_PTYPE_L3_IPV4_EXT_UNKNOWN' cannot happen here: > > - mbuf->packet_type is generated by (), which cannot > return 'RTE_PTYPE_L3_IPV4_EXT_UNKNOWN' My question if it is guaranteed and the only possible branch. Can application set packet_type itself and do not call rte_net_get_ptype(). Yes, typically application knows if it has IPv4 options in the header or not, but theoretically could be unaware as well. > - right above this code, we already returned if l3 is not in > (RTE_PTYPE_L3_IPV4, RTE_PTYPE_L3_IPV4_EXT, RTE_PTYPE_L3_IPV6) If so, it sounds like it should be allowed above as well. > >>> >>>> if (l4 == RTE_PTYPE_L4_UDP) { >>>> udp_hdr = (struct rte_udp_hdr *)l4_hdr; >>>> if (udp_hdr->dgram_cksum == 0) { >>>> @@ -364,7 +364,7 @@ tap_verify_csum(struct rte_mbuf *mbuf) >>>> } >>>> } >>>> cksum = ~rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); >>>> - } else if (l3 == RTE_PTYPE_L3_IPV6) { >>>> + } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ >>>> cksum = ~rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); >>>> } >>>> mbuf->ol_flags |= cksum ? >>>> >> ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [dpdk-dev] [dpdk-stable] [PATCH 1/4] net/tap: fix Rx cksum flags on IP options packets 2021-06-08 12:34 ` Andrew Rybchenko @ 2021-06-08 12:49 ` Olivier Matz 2021-06-08 13:57 ` Andrew Rybchenko 0 siblings, 1 reply; 28+ messages in thread From: Olivier Matz @ 2021-06-08 12:49 UTC (permalink / raw) To: Andrew Rybchenko Cc: Ferruh Yigit, dev, Keith Wiles, Hongzhi Guo, Morten Brørup, Thomas Monjalon, stable On Tue, Jun 08, 2021 at 03:34:36PM +0300, Andrew Rybchenko wrote: > On 6/8/21 3:29 PM, Olivier Matz wrote: > > Hi Ferruh, Andrew, > > > > On Tue, Jun 08, 2021 at 01:13:59PM +0300, Andrew Rybchenko wrote: > >> On 4/30/21 5:48 PM, Ferruh Yigit wrote: > >>> On 4/27/2021 2:57 PM, Olivier Matz wrote: > >>>> When packet type is IPV4_EXT, the checksum is always marked as good in > >>>> the mbuf offload flags. > >>>> > >>>> Since we know the header lengths, we can easily call > >>>> rte_ipv4_udptcp_cksum() in this case too. > >>>> > >>>> Fixes: 8ae3023387e9 ("net/tap: add Rx/Tx checksum offload support") > >>>> Cc: stable@dpdk.org > >>>> > >>>> Signed-off-by: Olivier Matz <olivier.matz@6wind.com> > >>>> --- > >>>> drivers/net/tap/rte_eth_tap.c | 4 ++-- > >>>> 1 file changed, 2 insertions(+), 2 deletions(-) > >>>> > >>>> diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c > >>>> index 68baa18523..e7b185a4b5 100644 > >>>> --- a/drivers/net/tap/rte_eth_tap.c > >>>> +++ b/drivers/net/tap/rte_eth_tap.c > >>>> @@ -350,7 +350,7 @@ tap_verify_csum(struct rte_mbuf *mbuf) > >>>> /* Don't verify checksum for multi-segment packets. */ > >>>> if (mbuf->nb_segs > 1) > >>>> return; > >>>> - if (l3 == RTE_PTYPE_L3_IPV4) { > >>>> + if (l3 == RTE_PTYPE_L3_IPV4 || l3 == RTE_PTYPE_L3_IPV4_EXT) { > >>> > >>> Should we take 'RTE_PTYPE_L3_IPV4_EXT_UNKNOWN' into account? > >> > >> I think we should. > > > > I think 'RTE_PTYPE_L3_IPV4_EXT_UNKNOWN' cannot happen here: > > > > - mbuf->packet_type is generated by > > (), which cannot > > return 'RTE_PTYPE_L3_IPV4_EXT_UNKNOWN' > > My question if it is guaranteed and the only possible branch. > Can application set packet_type itself and do not call > rte_net_get_ptype(). Yes, typically application knows > if it has IPv4 options in the header or not, but theoretically > could be unaware as well. This function is called on the Rx path from pmd_rx_burst(), so the application does not have access to the mbuf. The software parser that sets the packet type returns either RTE_PTYPE_L3_IPV4 if there is no option, or RTE_PTYPE_L3_IPV4_EXT else. The value RTE_PTYPE_L3_IPV4_EXT_UNKNOWN is used by PMDs that don't know if there are options. > > - right above this code, we already returned if l3 is not in > > (RTE_PTYPE_L3_IPV4, RTE_PTYPE_L3_IPV4_EXT, RTE_PTYPE_L3_IPV6) > > If so, it sounds like it should be allowed above as well. > > > > >>> > >>>> if (l4 == RTE_PTYPE_L4_UDP) { > >>>> udp_hdr = (struct rte_udp_hdr *)l4_hdr; > >>>> if (udp_hdr->dgram_cksum == 0) { > >>>> @@ -364,7 +364,7 @@ tap_verify_csum(struct rte_mbuf *mbuf) > >>>> } > >>>> } > >>>> cksum = ~rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); > >>>> - } else if (l3 == RTE_PTYPE_L3_IPV6) { > >>>> + } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ > >>>> cksum = ~rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); > >>>> } > >>>> mbuf->ol_flags |= cksum ? > >>>> > >> > ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [dpdk-dev] [dpdk-stable] [PATCH 1/4] net/tap: fix Rx cksum flags on IP options packets 2021-06-08 12:49 ` Olivier Matz @ 2021-06-08 13:57 ` Andrew Rybchenko 2021-06-08 14:30 ` Olivier Matz 0 siblings, 1 reply; 28+ messages in thread From: Andrew Rybchenko @ 2021-06-08 13:57 UTC (permalink / raw) To: Olivier Matz Cc: Ferruh Yigit, dev, Keith Wiles, Hongzhi Guo, Morten Brørup, Thomas Monjalon, stable On 6/8/21 3:49 PM, Olivier Matz wrote: > On Tue, Jun 08, 2021 at 03:34:36PM +0300, Andrew Rybchenko wrote: >> On 6/8/21 3:29 PM, Olivier Matz wrote: >>> Hi Ferruh, Andrew, >>> >>> On Tue, Jun 08, 2021 at 01:13:59PM +0300, Andrew Rybchenko wrote: >>>> On 4/30/21 5:48 PM, Ferruh Yigit wrote: >>>>> On 4/27/2021 2:57 PM, Olivier Matz wrote: >>>>>> When packet type is IPV4_EXT, the checksum is always marked as good in >>>>>> the mbuf offload flags. >>>>>> >>>>>> Since we know the header lengths, we can easily call >>>>>> rte_ipv4_udptcp_cksum() in this case too. >>>>>> >>>>>> Fixes: 8ae3023387e9 ("net/tap: add Rx/Tx checksum offload support") >>>>>> Cc: stable@dpdk.org >>>>>> >>>>>> Signed-off-by: Olivier Matz <olivier.matz@6wind.com> >>>>>> --- >>>>>> drivers/net/tap/rte_eth_tap.c | 4 ++-- >>>>>> 1 file changed, 2 insertions(+), 2 deletions(-) >>>>>> >>>>>> diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c >>>>>> index 68baa18523..e7b185a4b5 100644 >>>>>> --- a/drivers/net/tap/rte_eth_tap.c >>>>>> +++ b/drivers/net/tap/rte_eth_tap.c >>>>>> @@ -350,7 +350,7 @@ tap_verify_csum(struct rte_mbuf *mbuf) >>>>>> /* Don't verify checksum for multi-segment packets. */ >>>>>> if (mbuf->nb_segs > 1) >>>>>> return; >>>>>> - if (l3 == RTE_PTYPE_L3_IPV4) { >>>>>> + if (l3 == RTE_PTYPE_L3_IPV4 || l3 == RTE_PTYPE_L3_IPV4_EXT) { >>>>> >>>>> Should we take 'RTE_PTYPE_L3_IPV4_EXT_UNKNOWN' into account? >>>> >>>> I think we should. >>> >>> I think 'RTE_PTYPE_L3_IPV4_EXT_UNKNOWN' cannot happen here: >>> >>> - mbuf->packet_type is generated by >> >> (), which cannot >>> return 'RTE_PTYPE_L3_IPV4_EXT_UNKNOWN' >> >> My question if it is guaranteed and the only possible branch. >> Can application set packet_type itself and do not call >> rte_net_get_ptype(). Yes, typically application knows >> if it has IPv4 options in the header or not, but theoretically >> could be unaware as well. > > This function is called on the Rx path from pmd_rx_burst(), so > the application does not have access to the mbuf. > > The software parser that sets the packet type returns either > RTE_PTYPE_L3_IPV4 if there is no option, or RTE_PTYPE_L3_IPV4_EXT > else. The value RTE_PTYPE_L3_IPV4_EXT_UNKNOWN is used by PMDs that don't > know if there are options. I see. What I'm trying to say that there are non obvious assumptions here on rte_net_get_ptype() behaviour which can be changed. May be it makes sense to add comments here to highlight it. > >>> - right above this code, we already returned if l3 is not in >>> (RTE_PTYPE_L3_IPV4, RTE_PTYPE_L3_IPV4_EXT, RTE_PTYPE_L3_IPV6) >> >> If so, it sounds like it should be allowed above as well. >> >>> >>>>> >>>>>> if (l4 == RTE_PTYPE_L4_UDP) { >>>>>> udp_hdr = (struct rte_udp_hdr *)l4_hdr; >>>>>> if (udp_hdr->dgram_cksum == 0) { >>>>>> @@ -364,7 +364,7 @@ tap_verify_csum(struct rte_mbuf *mbuf) >>>>>> } >>>>>> } >>>>>> cksum = ~rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); >>>>>> - } else if (l3 == RTE_PTYPE_L3_IPV6) { >>>>>> + } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ >>>>>> cksum = ~rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); >>>>>> } >>>>>> mbuf->ol_flags |= cksum ? >>>>>> >>>> >> ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [dpdk-dev] [dpdk-stable] [PATCH 1/4] net/tap: fix Rx cksum flags on IP options packets 2021-06-08 13:57 ` Andrew Rybchenko @ 2021-06-08 14:30 ` Olivier Matz 0 siblings, 0 replies; 28+ messages in thread From: Olivier Matz @ 2021-06-08 14:30 UTC (permalink / raw) To: Andrew Rybchenko Cc: Ferruh Yigit, dev, Keith Wiles, Hongzhi Guo, Morten Brørup, Thomas Monjalon, stable On Tue, Jun 08, 2021 at 04:57:00PM +0300, Andrew Rybchenko wrote: > On 6/8/21 3:49 PM, Olivier Matz wrote: > > On Tue, Jun 08, 2021 at 03:34:36PM +0300, Andrew Rybchenko wrote: > >> On 6/8/21 3:29 PM, Olivier Matz wrote: > >>> Hi Ferruh, Andrew, > >>> > >>> On Tue, Jun 08, 2021 at 01:13:59PM +0300, Andrew Rybchenko wrote: > >>>> On 4/30/21 5:48 PM, Ferruh Yigit wrote: > >>>>> On 4/27/2021 2:57 PM, Olivier Matz wrote: > >>>>>> When packet type is IPV4_EXT, the checksum is always marked as good in > >>>>>> the mbuf offload flags. > >>>>>> > >>>>>> Since we know the header lengths, we can easily call > >>>>>> rte_ipv4_udptcp_cksum() in this case too. > >>>>>> > >>>>>> Fixes: 8ae3023387e9 ("net/tap: add Rx/Tx checksum offload support") > >>>>>> Cc: stable@dpdk.org > >>>>>> > >>>>>> Signed-off-by: Olivier Matz <olivier.matz@6wind.com> > >>>>>> --- > >>>>>> drivers/net/tap/rte_eth_tap.c | 4 ++-- > >>>>>> 1 file changed, 2 insertions(+), 2 deletions(-) > >>>>>> > >>>>>> diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c > >>>>>> index 68baa18523..e7b185a4b5 100644 > >>>>>> --- a/drivers/net/tap/rte_eth_tap.c > >>>>>> +++ b/drivers/net/tap/rte_eth_tap.c > >>>>>> @@ -350,7 +350,7 @@ tap_verify_csum(struct rte_mbuf *mbuf) > >>>>>> /* Don't verify checksum for multi-segment packets. */ > >>>>>> if (mbuf->nb_segs > 1) > >>>>>> return; > >>>>>> - if (l3 == RTE_PTYPE_L3_IPV4) { > >>>>>> + if (l3 == RTE_PTYPE_L3_IPV4 || l3 == RTE_PTYPE_L3_IPV4_EXT) { > >>>>> > >>>>> Should we take 'RTE_PTYPE_L3_IPV4_EXT_UNKNOWN' into account? > >>>> > >>>> I think we should. > >>> > >>> I think 'RTE_PTYPE_L3_IPV4_EXT_UNKNOWN' cannot happen here: > >>> > >>> - mbuf->packet_type is generated by > >> > >> (), which cannot > >>> return 'RTE_PTYPE_L3_IPV4_EXT_UNKNOWN' > >> > >> My question if it is guaranteed and the only possible branch. > >> Can application set packet_type itself and do not call > >> rte_net_get_ptype(). Yes, typically application knows > >> if it has IPv4 options in the header or not, but theoretically > >> could be unaware as well. > > > > This function is called on the Rx path from pmd_rx_burst(), so > > the application does not have access to the mbuf. > > > > The software parser that sets the packet type returns either > > RTE_PTYPE_L3_IPV4 if there is no option, or RTE_PTYPE_L3_IPV4_EXT > > else. The value RTE_PTYPE_L3_IPV4_EXT_UNKNOWN is used by PMDs that don't > > know if there are options. > > I see. What I'm trying to say that there are non > obvious assumptions here on rte_net_get_ptype() > behaviour which can be changed. May be it makes > sense to add comments here to highlight it. Ok, I'll add some words about it. Thanks! > > > > >>> - right above this code, we already returned if l3 is not in > >>> (RTE_PTYPE_L3_IPV4, RTE_PTYPE_L3_IPV4_EXT, RTE_PTYPE_L3_IPV6) > >> > >> If so, it sounds like it should be allowed above as well. > >> > >>> > >>>>> > >>>>>> if (l4 == RTE_PTYPE_L4_UDP) { > >>>>>> udp_hdr = (struct rte_udp_hdr *)l4_hdr; > >>>>>> if (udp_hdr->dgram_cksum == 0) { > >>>>>> @@ -364,7 +364,7 @@ tap_verify_csum(struct rte_mbuf *mbuf) > >>>>>> } > >>>>>> } > >>>>>> cksum = ~rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); > >>>>>> - } else if (l3 == RTE_PTYPE_L3_IPV6) { > >>>>>> + } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ > >>>>>> cksum = ~rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); > >>>>>> } > >>>>>> mbuf->ol_flags |= cksum ? > >>>>>> > >>>> > >> > ^ permalink raw reply [flat|nested] 28+ messages in thread
* [dpdk-dev] [PATCH 2/4] net/tap: fix Rx cksum flags on TCP packets 2021-04-27 13:57 [dpdk-dev] [PATCH 0/4] net/tap: fix Rx cksum Olivier Matz 2021-04-27 13:57 ` [dpdk-dev] [PATCH 1/4] net/tap: fix Rx cksum flags on IP options packets Olivier Matz @ 2021-04-27 13:57 ` Olivier Matz 2021-06-08 10:18 ` Andrew Rybchenko 2021-04-27 13:57 ` [dpdk-dev] [PATCH 3/4] net: introduce functions to verify L4 checksums Olivier Matz ` (2 subsequent siblings) 4 siblings, 1 reply; 28+ messages in thread From: Olivier Matz @ 2021-04-27 13:57 UTC (permalink / raw) To: dev; +Cc: Keith Wiles, Hongzhi Guo, Morten Brørup, Thomas Monjalon, stable Since commit d5df2ae0428a ("net: fix unneeded replacement of TCP checksum 0"), the functions rte_ipv4_udptcp_cksum() or rte_ipv6_udptcp_cksum() can return either 0x0000 or 0xffff when used to verify a packet containing a valid checksum. This new behavior broke the checksum verification in tap driver for TCP packets: these packets are marked with PKT_RX_L4_CKSUM_BAD. Fix this by checking the 2 possible values. A next commit will introduce a checksum verification helper to simplify this a bit. Fixes: d5df2ae0428a ("net: fix unneeded replacement of TCP checksum 0") Cc: stable@dpdk.org Signed-off-by: Olivier Matz <olivier.matz@6wind.com> --- drivers/net/tap/rte_eth_tap.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c index e7b185a4b5..71282e8065 100644 --- a/drivers/net/tap/rte_eth_tap.c +++ b/drivers/net/tap/rte_eth_tap.c @@ -346,6 +346,8 @@ tap_verify_csum(struct rte_mbuf *mbuf) return; } if (l4 == RTE_PTYPE_L4_UDP || l4 == RTE_PTYPE_L4_TCP) { + int cksum_ok; + l4_hdr = rte_pktmbuf_mtod_offset(mbuf, void *, l2_len + l3_len); /* Don't verify checksum for multi-segment packets. */ if (mbuf->nb_segs > 1) @@ -363,13 +365,13 @@ tap_verify_csum(struct rte_mbuf *mbuf) return; } } - cksum = ~rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); + cksum = rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ - cksum = ~rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); + cksum = rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); } - mbuf->ol_flags |= cksum ? - PKT_RX_L4_CKSUM_BAD : - PKT_RX_L4_CKSUM_GOOD; + cksum_ok = (cksum == 0) || (cksum == 0xffff); + mbuf->ol_flags |= cksum_ok ? + PKT_RX_L4_CKSUM_GOOD : PKT_RX_L4_CKSUM_BAD; } } -- 2.29.2 ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [dpdk-dev] [PATCH 2/4] net/tap: fix Rx cksum flags on TCP packets 2021-04-27 13:57 ` [dpdk-dev] [PATCH 2/4] net/tap: fix Rx cksum flags on TCP packets Olivier Matz @ 2021-06-08 10:18 ` Andrew Rybchenko 0 siblings, 0 replies; 28+ messages in thread From: Andrew Rybchenko @ 2021-06-08 10:18 UTC (permalink / raw) To: Olivier Matz, dev Cc: Keith Wiles, Hongzhi Guo, Morten Brørup, Thomas Monjalon, stable On 4/27/21 4:57 PM, Olivier Matz wrote: > Since commit d5df2ae0428a ("net: fix unneeded replacement of TCP > checksum 0"), the functions rte_ipv4_udptcp_cksum() or > rte_ipv6_udptcp_cksum() can return either 0x0000 or 0xffff when used to > verify a packet containing a valid checksum. > > This new behavior broke the checksum verification in tap driver for TCP > packets: these packets are marked with PKT_RX_L4_CKSUM_BAD. > > Fix this by checking the 2 possible values. A next commit will introduce > a checksum verification helper to simplify this a bit. > > Fixes: d5df2ae0428a ("net: fix unneeded replacement of TCP checksum 0") > Cc: stable@dpdk.org > > Signed-off-by: Olivier Matz <olivier.matz@6wind.com> Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru> ^ permalink raw reply [flat|nested] 28+ messages in thread
* [dpdk-dev] [PATCH 3/4] net: introduce functions to verify L4 checksums 2021-04-27 13:57 [dpdk-dev] [PATCH 0/4] net/tap: fix Rx cksum Olivier Matz 2021-04-27 13:57 ` [dpdk-dev] [PATCH 1/4] net/tap: fix Rx cksum flags on IP options packets Olivier Matz 2021-04-27 13:57 ` [dpdk-dev] [PATCH 2/4] net/tap: fix Rx cksum flags on TCP packets Olivier Matz @ 2021-04-27 13:57 ` Olivier Matz 2021-04-27 15:02 ` Morten Brørup ` (2 more replies) 2021-04-27 13:57 ` [dpdk-dev] [PATCH 4/4] test/cksum: new test for L3/L4 checksum API Olivier Matz 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 0/4] net/tap: fix Rx cksum Olivier Matz 4 siblings, 3 replies; 28+ messages in thread From: Olivier Matz @ 2021-04-27 13:57 UTC (permalink / raw) To: dev; +Cc: Keith Wiles, Hongzhi Guo, Morten Brørup, Thomas Monjalon Since commit d5df2ae0428a ("net: fix unneeded replacement of TCP checksum 0"), the functions rte_ipv4_udptcp_cksum() and rte_ipv6_udptcp_cksum() can return either 0x0000 or 0xffff when used to verify a packet containing a valid checksum. Since these functions should be used to calculate the checksum to set in a packet, introduce 2 new helpers for checksum verification. They return 0 if the checksum is valid in the packet. Use this new helper in net/tap driver. Signed-off-by: Olivier Matz <olivier.matz@6wind.com> --- drivers/net/tap/rte_eth_tap.c | 7 +- lib/net/rte_ip.h | 124 +++++++++++++++++++++++++++------- 2 files changed, 104 insertions(+), 27 deletions(-) diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c index 71282e8065..b14d5a1d55 100644 --- a/drivers/net/tap/rte_eth_tap.c +++ b/drivers/net/tap/rte_eth_tap.c @@ -365,11 +365,12 @@ tap_verify_csum(struct rte_mbuf *mbuf) return; } } - cksum = rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); + cksum_ok = !rte_ipv4_udptcp_cksum_verify(l3_hdr, + l4_hdr); } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ - cksum = rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); + cksum_ok = !rte_ipv6_udptcp_cksum_verify(l3_hdr, + l4_hdr); } - cksum_ok = (cksum == 0) || (cksum == 0xffff); mbuf->ol_flags |= cksum_ok ? PKT_RX_L4_CKSUM_GOOD : PKT_RX_L4_CKSUM_BAD; } diff --git a/lib/net/rte_ip.h b/lib/net/rte_ip.h index 8c189009b0..ef84bcc5bf 100644 --- a/lib/net/rte_ip.h +++ b/lib/net/rte_ip.h @@ -344,20 +344,10 @@ rte_ipv4_phdr_cksum(const struct rte_ipv4_hdr *ipv4_hdr, uint64_t ol_flags) } /** - * Process the IPv4 UDP or TCP checksum. - * - * The IP and layer 4 checksum must be set to 0 in the packet by - * the caller. - * - * @param ipv4_hdr - * The pointer to the contiguous IPv4 header. - * @param l4_hdr - * The pointer to the beginning of the L4 header. - * @return - * The complemented checksum to set in the IP packet. + * @internal Calculate the non-complemented IPv4 L4 checksum */ static inline uint16_t -rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) +__rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) { uint32_t cksum; uint32_t l3_len, l4_len; @@ -374,16 +364,62 @@ rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) cksum += rte_ipv4_phdr_cksum(ipv4_hdr, 0); cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); - cksum = (~cksum) & 0xffff; + + return (uint16_t)cksum; +} + +/** + * Process the IPv4 UDP or TCP checksum. + * + * The IP and layer 4 checksum must be set to 0 in the packet by + * the caller. + * + * @param ipv4_hdr + * The pointer to the contiguous IPv4 header. + * @param l4_hdr + * The pointer to the beginning of the L4 header. + * @return + * The complemented checksum to set in the IP packet. + */ +static inline uint16_t +rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) +{ + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); + + cksum = ~cksum; + /* - * Per RFC 768:If the computed checksum is zero for UDP, + * Per RFC 768: If the computed checksum is zero for UDP, * it is transmitted as all ones * (the equivalent in one's complement arithmetic). */ if (cksum == 0 && ipv4_hdr->next_proto_id == IPPROTO_UDP) cksum = 0xffff; - return (uint16_t)cksum; + return cksum; +} + +/** + * Validate the IPv4 UDP or TCP checksum. + * + * @param ipv4_hdr + * The pointer to the contiguous IPv4 header. + * @param l4_hdr + * The pointer to the beginning of the L4 header. + * @return + * Return 0 if the checksum is correct, else -1. + */ +__rte_experimental +static inline int +rte_ipv4_udptcp_cksum_verify(const struct rte_ipv4_hdr *ipv4_hdr, + const void *l4_hdr) +{ + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); + + if (cksum != 0xffff) + return -1; + + return 0; } /** @@ -448,6 +484,25 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags) return __rte_raw_cksum_reduce(sum); } +/** + * @internal Calculate the non-complemented IPv4 L4 checksum + */ +static inline uint16_t +__rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) +{ + uint32_t cksum; + uint32_t l4_len; + + l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len); + + cksum = rte_raw_cksum(l4_hdr, l4_len); + cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0); + + cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); + + return (uint16_t)cksum; +} + /** * Process the IPv6 UDP or TCP checksum. * @@ -464,16 +519,10 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags) static inline uint16_t rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) { - uint32_t cksum; - uint32_t l4_len; - - l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len); + uint16_t cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr); - cksum = rte_raw_cksum(l4_hdr, l4_len); - cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0); + cksum = ~cksum; - cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); - cksum = (~cksum) & 0xffff; /* * Per RFC 768: If the computed checksum is zero for UDP, * it is transmitted as all ones @@ -482,7 +531,34 @@ rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) if (cksum == 0 && ipv6_hdr->proto == IPPROTO_UDP) cksum = 0xffff; - return (uint16_t)cksum; + return cksum; +} + +/** + * Validate the IPv6 UDP or TCP checksum. + * + * The function accepts a 0 checksum, since it can exceptionally happen. See 8.1 + * (Upper-Layer Checksums) in RFC 8200. + * + * @param ipv6_hdr + * The pointer to the contiguous IPv6 header. + * @param l4_hdr + * The pointer to the beginning of the L4 header. + * @return + * Return 0 if the checksum is correct, else -1. + */ +__rte_experimental +static inline int +rte_ipv6_udptcp_cksum_verify(const struct rte_ipv6_hdr *ipv6_hdr, + const void *l4_hdr) +{ + uint16_t cksum; + + cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr); + if (cksum != 0xffff) + return -1; + + return 0; } /** IPv6 fragment extension header. */ -- 2.29.2 ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [dpdk-dev] [PATCH 3/4] net: introduce functions to verify L4 checksums 2021-04-27 13:57 ` [dpdk-dev] [PATCH 3/4] net: introduce functions to verify L4 checksums Olivier Matz @ 2021-04-27 15:02 ` Morten Brørup 2021-04-27 15:07 ` Morten Brørup 2021-04-30 15:42 ` Ferruh Yigit 2 siblings, 0 replies; 28+ messages in thread From: Morten Brørup @ 2021-04-27 15:02 UTC (permalink / raw) To: Olivier Matz, dev; +Cc: Keith Wiles, Hongzhi Guo, Thomas Monjalon > From: Olivier Matz [mailto:olivier.matz@6wind.com] > Sent: Tuesday, April 27, 2021 3:58 PM > > Since commit d5df2ae0428a ("net: fix unneeded replacement of TCP > checksum 0"), the functions rte_ipv4_udptcp_cksum() and > rte_ipv6_udptcp_cksum() can return either 0x0000 or 0xffff when used to > verify a packet containing a valid checksum. > > Since these functions should be used to calculate the checksum to set > in > a packet, introduce 2 new helpers for checksum verification. They > return > 0 if the checksum is valid in the packet. > > Use this new helper in net/tap driver. > > Signed-off-by: Olivier Matz <olivier.matz@6wind.com> > --- > drivers/net/tap/rte_eth_tap.c | 7 +- > lib/net/rte_ip.h | 124 +++++++++++++++++++++++++++------- > 2 files changed, 104 insertions(+), 27 deletions(-) > > diff --git a/drivers/net/tap/rte_eth_tap.c > b/drivers/net/tap/rte_eth_tap.c > index 71282e8065..b14d5a1d55 100644 > --- a/drivers/net/tap/rte_eth_tap.c > +++ b/drivers/net/tap/rte_eth_tap.c > @@ -365,11 +365,12 @@ tap_verify_csum(struct rte_mbuf *mbuf) > return; > } > } > - cksum = rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); > + cksum_ok = !rte_ipv4_udptcp_cksum_verify(l3_hdr, > + l4_hdr); > } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ > - cksum = rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); > + cksum_ok = !rte_ipv6_udptcp_cksum_verify(l3_hdr, > + l4_hdr); > } > - cksum_ok = (cksum == 0) || (cksum == 0xffff); > mbuf->ol_flags |= cksum_ok ? > PKT_RX_L4_CKSUM_GOOD : PKT_RX_L4_CKSUM_BAD; > } > diff --git a/lib/net/rte_ip.h b/lib/net/rte_ip.h > index 8c189009b0..ef84bcc5bf 100644 > --- a/lib/net/rte_ip.h > +++ b/lib/net/rte_ip.h > @@ -344,20 +344,10 @@ rte_ipv4_phdr_cksum(const struct rte_ipv4_hdr > *ipv4_hdr, uint64_t ol_flags) > } > > /** > - * Process the IPv4 UDP or TCP checksum. > - * > - * The IP and layer 4 checksum must be set to 0 in the packet by > - * the caller. > - * > - * @param ipv4_hdr > - * The pointer to the contiguous IPv4 header. > - * @param l4_hdr > - * The pointer to the beginning of the L4 header. > - * @return > - * The complemented checksum to set in the IP packet. > + * @internal Calculate the non-complemented IPv4 L4 checksum > */ > static inline uint16_t > -rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void > *l4_hdr) > +__rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const > void *l4_hdr) > { > uint32_t cksum; > uint32_t l3_len, l4_len; > @@ -374,16 +364,62 @@ rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr > *ipv4_hdr, const void *l4_hdr) > cksum += rte_ipv4_phdr_cksum(ipv4_hdr, 0); > > cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); > - cksum = (~cksum) & 0xffff; > + > + return (uint16_t)cksum; > +} > + > +/** > + * Process the IPv4 UDP or TCP checksum. > + * > + * The IP and layer 4 checksum must be set to 0 in the packet by > + * the caller. > + * > + * @param ipv4_hdr > + * The pointer to the contiguous IPv4 header. > + * @param l4_hdr > + * The pointer to the beginning of the L4 header. > + * @return > + * The complemented checksum to set in the IP packet. > + */ > +static inline uint16_t > +rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void > *l4_hdr) > +{ > + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); > + > + cksum = ~cksum; > + > /* > - * Per RFC 768:If the computed checksum is zero for UDP, > + * Per RFC 768: If the computed checksum is zero for UDP, > * it is transmitted as all ones > * (the equivalent in one's complement arithmetic). > */ > if (cksum == 0 && ipv4_hdr->next_proto_id == IPPROTO_UDP) > cksum = 0xffff; > > - return (uint16_t)cksum; > + return cksum; > +} The GCC static branch predictor treats the above comparison as likely. Playing around with Godbolt, I came up with this alternative: if (likely(cksum != 0)) return cksum; if (ipv4_hdr->next_proto_id == IPPROTO_UDP) return 0xffff; return cksum; > + > +/** > + * Validate the IPv4 UDP or TCP checksum. > + * > + * @param ipv4_hdr > + * The pointer to the contiguous IPv4 header. > + * @param l4_hdr > + * The pointer to the beginning of the L4 header. > + * @return > + * Return 0 if the checksum is correct, else -1. > + */ > +__rte_experimental > +static inline int > +rte_ipv4_udptcp_cksum_verify(const struct rte_ipv4_hdr *ipv4_hdr, > + const void *l4_hdr) > +{ > + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); > + > + if (cksum != 0xffff) > + return -1; The GCC static branch predictor treats the above comparison as likely, so I would prefer unlikely() around it. > + > + return 0; > } > > /** > @@ -448,6 +484,25 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr > *ipv6_hdr, uint64_t ol_flags) > return __rte_raw_cksum_reduce(sum); > } > > +/** > + * @internal Calculate the non-complemented IPv4 L4 checksum > + */ > +static inline uint16_t > +__rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const > void *l4_hdr) > +{ > + uint32_t cksum; > + uint32_t l4_len; > + > + l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len); > + > + cksum = rte_raw_cksum(l4_hdr, l4_len); > + cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0); > + > + cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); > + > + return (uint16_t)cksum; > +} > + > /** > * Process the IPv6 UDP or TCP checksum. > * > @@ -464,16 +519,10 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr > *ipv6_hdr, uint64_t ol_flags) > static inline uint16_t > rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void > *l4_hdr) > { > - uint32_t cksum; > - uint32_t l4_len; > - > - l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len); > + uint16_t cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr); > > - cksum = rte_raw_cksum(l4_hdr, l4_len); > - cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0); > + cksum = ~cksum; > > - cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); > - cksum = (~cksum) & 0xffff; > /* > * Per RFC 768: If the computed checksum is zero for UDP, > * it is transmitted as all ones > @@ -482,7 +531,34 @@ rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr > *ipv6_hdr, const void *l4_hdr) > if (cksum == 0 && ipv6_hdr->proto == IPPROTO_UDP) > cksum = 0xffff; Same comment about GCC static branch prediction as above. > > - return (uint16_t)cksum; > + return cksum; > +} > + > +/** > + * Validate the IPv6 UDP or TCP checksum. > + * > + * The function accepts a 0 checksum, since it can exceptionally > happen. See 8.1 > + * (Upper-Layer Checksums) in RFC 8200. > + * > + * @param ipv6_hdr > + * The pointer to the contiguous IPv6 header. > + * @param l4_hdr > + * The pointer to the beginning of the L4 header. > + * @return > + * Return 0 if the checksum is correct, else -1. > + */ > +__rte_experimental > +static inline int > +rte_ipv6_udptcp_cksum_verify(const struct rte_ipv6_hdr *ipv6_hdr, > + const void *l4_hdr) > +{ > + uint16_t cksum; > + > + cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr); > + if (cksum != 0xffff) > + return -1; Same comment about GCC static branch prediction as above. > + > + return 0; > } > > /** IPv6 fragment extension header. */ > -- > 2.29.2 > With or without my suggested modifications: Acked-by: Morten Brørup <mb@smartsharesystems.com> Without my suggested modifications: Reviewed-by: Morten Brørup <mb@smartsharesystems.com> ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [dpdk-dev] [PATCH 3/4] net: introduce functions to verify L4 checksums 2021-04-27 13:57 ` [dpdk-dev] [PATCH 3/4] net: introduce functions to verify L4 checksums Olivier Matz 2021-04-27 15:02 ` Morten Brørup @ 2021-04-27 15:07 ` Morten Brørup 2021-04-28 12:21 ` Olivier Matz 2021-04-30 15:42 ` Ferruh Yigit 2 siblings, 1 reply; 28+ messages in thread From: Morten Brørup @ 2021-04-27 15:07 UTC (permalink / raw) To: Olivier Matz, dev; +Cc: Keith Wiles, Hongzhi Guo, Thomas Monjalon > From: Olivier Matz [mailto:olivier.matz@6wind.com] > Sent: Tuesday, April 27, 2021 3:58 PM > > Since commit d5df2ae0428a ("net: fix unneeded replacement of TCP > checksum 0"), the functions rte_ipv4_udptcp_cksum() and > rte_ipv6_udptcp_cksum() can return either 0x0000 or 0xffff when used to > verify a packet containing a valid checksum. > > Since these functions should be used to calculate the checksum to set > in > a packet, introduce 2 new helpers for checksum verification. They > return > 0 if the checksum is valid in the packet. > > Use this new helper in net/tap driver. > > Signed-off-by: Olivier Matz <olivier.matz@6wind.com> > --- > drivers/net/tap/rte_eth_tap.c | 7 +- > lib/net/rte_ip.h | 124 +++++++++++++++++++++++++++------- > 2 files changed, 104 insertions(+), 27 deletions(-) > > diff --git a/drivers/net/tap/rte_eth_tap.c > b/drivers/net/tap/rte_eth_tap.c > index 71282e8065..b14d5a1d55 100644 > --- a/drivers/net/tap/rte_eth_tap.c > +++ b/drivers/net/tap/rte_eth_tap.c > @@ -365,11 +365,12 @@ tap_verify_csum(struct rte_mbuf *mbuf) > return; > } > } > - cksum = rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); > + cksum_ok = !rte_ipv4_udptcp_cksum_verify(l3_hdr, > + l4_hdr); > } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ > - cksum = rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); > + cksum_ok = !rte_ipv6_udptcp_cksum_verify(l3_hdr, > + l4_hdr); > } > - cksum_ok = (cksum == 0) || (cksum == 0xffff); > mbuf->ol_flags |= cksum_ok ? > PKT_RX_L4_CKSUM_GOOD : PKT_RX_L4_CKSUM_BAD; > } > diff --git a/lib/net/rte_ip.h b/lib/net/rte_ip.h > index 8c189009b0..ef84bcc5bf 100644 > --- a/lib/net/rte_ip.h > +++ b/lib/net/rte_ip.h > @@ -344,20 +344,10 @@ rte_ipv4_phdr_cksum(const struct rte_ipv4_hdr > *ipv4_hdr, uint64_t ol_flags) > } > > /** > - * Process the IPv4 UDP or TCP checksum. > - * > - * The IP and layer 4 checksum must be set to 0 in the packet by > - * the caller. > - * > - * @param ipv4_hdr > - * The pointer to the contiguous IPv4 header. > - * @param l4_hdr > - * The pointer to the beginning of the L4 header. > - * @return > - * The complemented checksum to set in the IP packet. > + * @internal Calculate the non-complemented IPv4 L4 checksum > */ > static inline uint16_t > -rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void > *l4_hdr) > +__rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const > void *l4_hdr) > { > uint32_t cksum; > uint32_t l3_len, l4_len; > @@ -374,16 +364,62 @@ rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr > *ipv4_hdr, const void *l4_hdr) > cksum += rte_ipv4_phdr_cksum(ipv4_hdr, 0); > > cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); > - cksum = (~cksum) & 0xffff; > + > + return (uint16_t)cksum; > +} > + > +/** > + * Process the IPv4 UDP or TCP checksum. > + * > + * The IP and layer 4 checksum must be set to 0 in the packet by > + * the caller. > + * > + * @param ipv4_hdr > + * The pointer to the contiguous IPv4 header. > + * @param l4_hdr > + * The pointer to the beginning of the L4 header. > + * @return > + * The complemented checksum to set in the IP packet. > + */ > +static inline uint16_t > +rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void > *l4_hdr) > +{ > + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); > + > + cksum = ~cksum; > + > /* > - * Per RFC 768:If the computed checksum is zero for UDP, > + * Per RFC 768: If the computed checksum is zero for UDP, > * it is transmitted as all ones > * (the equivalent in one's complement arithmetic). > */ > if (cksum == 0 && ipv4_hdr->next_proto_id == IPPROTO_UDP) > cksum = 0xffff; > > - return (uint16_t)cksum; > + return cksum; > +} The GCC static branch predictor treats the above comparison as likely. Playing around with Godbolt, I came up with this alternative: if (likely(cksum != 0)) return cksum; if (ipv4_hdr->next_proto_id == IPPROTO_UDP) return 0xffff; return 0; > + > +/** > + * Validate the IPv4 UDP or TCP checksum. > + * > + * @param ipv4_hdr > + * The pointer to the contiguous IPv4 header. > + * @param l4_hdr > + * The pointer to the beginning of the L4 header. > + * @return > + * Return 0 if the checksum is correct, else -1. > + */ > +__rte_experimental > +static inline int > +rte_ipv4_udptcp_cksum_verify(const struct rte_ipv4_hdr *ipv4_hdr, > + const void *l4_hdr) > +{ > + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); > + > + if (cksum != 0xffff) > + return -1; The GCC static branch predictor treats the above comparison as likely, so I would prefer unlikely() around it. > + > + return 0; > } > > /** > @@ -448,6 +484,25 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr > *ipv6_hdr, uint64_t ol_flags) > return __rte_raw_cksum_reduce(sum); > } > > +/** > + * @internal Calculate the non-complemented IPv4 L4 checksum > + */ > +static inline uint16_t > +__rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const > void *l4_hdr) > +{ > + uint32_t cksum; > + uint32_t l4_len; > + > + l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len); > + > + cksum = rte_raw_cksum(l4_hdr, l4_len); > + cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0); > + > + cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); > + > + return (uint16_t)cksum; > +} > + > /** > * Process the IPv6 UDP or TCP checksum. > * > @@ -464,16 +519,10 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr > *ipv6_hdr, uint64_t ol_flags) > static inline uint16_t > rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void > *l4_hdr) > { > - uint32_t cksum; > - uint32_t l4_len; > - > - l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len); > + uint16_t cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr); > > - cksum = rte_raw_cksum(l4_hdr, l4_len); > - cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0); > + cksum = ~cksum; > > - cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); > - cksum = (~cksum) & 0xffff; > /* > * Per RFC 768: If the computed checksum is zero for UDP, > * it is transmitted as all ones > @@ -482,7 +531,34 @@ rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr > *ipv6_hdr, const void *l4_hdr) > if (cksum == 0 && ipv6_hdr->proto == IPPROTO_UDP) > cksum = 0xffff; Same comment about GCC static branch prediction as above. > > - return (uint16_t)cksum; > + return cksum; > +} > + > +/** > + * Validate the IPv6 UDP or TCP checksum. > + * > + * The function accepts a 0 checksum, since it can exceptionally > happen. See 8.1 > + * (Upper-Layer Checksums) in RFC 8200. > + * > + * @param ipv6_hdr > + * The pointer to the contiguous IPv6 header. > + * @param l4_hdr > + * The pointer to the beginning of the L4 header. > + * @return > + * Return 0 if the checksum is correct, else -1. > + */ > +__rte_experimental > +static inline int > +rte_ipv6_udptcp_cksum_verify(const struct rte_ipv6_hdr *ipv6_hdr, > + const void *l4_hdr) > +{ > + uint16_t cksum; > + > + cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr); > + if (cksum != 0xffff) > + return -1; Same comment about GCC static branch prediction as above. > + > + return 0; > } > > /** IPv6 fragment extension header. */ > -- > 2.29.2 > With or without my suggested modifications: Acked-by: Morten Brørup <mb@smartsharesystems.com> Without my suggested modifications: Reviewed-by: Morten Brørup <mb@smartsharesystems.com> ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [dpdk-dev] [PATCH 3/4] net: introduce functions to verify L4 checksums 2021-04-27 15:07 ` Morten Brørup @ 2021-04-28 12:21 ` Olivier Matz 2021-04-28 12:42 ` Morten Brørup 0 siblings, 1 reply; 28+ messages in thread From: Olivier Matz @ 2021-04-28 12:21 UTC (permalink / raw) To: Morten Brørup; +Cc: dev, Keith Wiles, Hongzhi Guo, Thomas Monjalon Hi Morten, Thank you for the review. <...> On Tue, Apr 27, 2021 at 05:07:04PM +0200, Morten Brørup wrote: > > +static inline uint16_t > > +rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void > > *l4_hdr) > > +{ > > + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); > > + > > + cksum = ~cksum; > > + > > /* > > - * Per RFC 768:If the computed checksum is zero for UDP, > > + * Per RFC 768: If the computed checksum is zero for UDP, > > * it is transmitted as all ones > > * (the equivalent in one's complement arithmetic). > > */ > > if (cksum == 0 && ipv4_hdr->next_proto_id == IPPROTO_UDP) > > cksum = 0xffff; > > > > - return (uint16_t)cksum; > > + return cksum; > > +} > > The GCC static branch predictor treats the above comparison as likely. Playing around with Godbolt, I came up with this alternative: > > if (likely(cksum != 0)) return cksum; > if (ipv4_hdr->next_proto_id == IPPROTO_UDP) return 0xffff; > return 0; Good idea, this is indeed an unlikely branch. However this code was already present before this patch, so I suggest to add it as a specific optimization patch. > > + > > +/** > > + * Validate the IPv4 UDP or TCP checksum. > > + * > > + * @param ipv4_hdr > > + * The pointer to the contiguous IPv4 header. > > + * @param l4_hdr > > + * The pointer to the beginning of the L4 header. > > + * @return > > + * Return 0 if the checksum is correct, else -1. > > + */ > > +__rte_experimental > > +static inline int > > +rte_ipv4_udptcp_cksum_verify(const struct rte_ipv4_hdr *ipv4_hdr, > > + const void *l4_hdr) > > +{ > > + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); > > + > > + if (cksum != 0xffff) > > + return -1; > > The GCC static branch predictor treats the above comparison as likely, so I would prefer unlikely() around it. For this one, I'm less convinced: should we decide here whether the good or the bad checksum is more likely than the other? Given it's a static inline function, wouldn't it be better to let the application call it this way: if (likely(rte_ipv4_udptcp_cksum_verify(...) == 0)) ? Regards, Olivier ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [dpdk-dev] [PATCH 3/4] net: introduce functions to verify L4 checksums 2021-04-28 12:21 ` Olivier Matz @ 2021-04-28 12:42 ` Morten Brørup 0 siblings, 0 replies; 28+ messages in thread From: Morten Brørup @ 2021-04-28 12:42 UTC (permalink / raw) To: Olivier Matz; +Cc: dev, Keith Wiles, Hongzhi Guo, Thomas Monjalon > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Olivier Matz > Sent: Wednesday, April 28, 2021 2:22 PM > > Hi Morten, > > Thank you for the review. > > <...> > > On Tue, Apr 27, 2021 at 05:07:04PM +0200, Morten Brørup wrote: > > > +static inline uint16_t > > > +rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const > void > > > *l4_hdr) > > > +{ > > > + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); > > > + > > > + cksum = ~cksum; > > > + > > > /* > > > - * Per RFC 768:If the computed checksum is zero for UDP, > > > + * Per RFC 768: If the computed checksum is zero for UDP, > > > * it is transmitted as all ones > > > * (the equivalent in one's complement arithmetic). > > > */ > > > if (cksum == 0 && ipv4_hdr->next_proto_id == IPPROTO_UDP) > > > cksum = 0xffff; > > > > > > - return (uint16_t)cksum; > > > + return cksum; > > > +} > > > > The GCC static branch predictor treats the above comparison as > likely. Playing around with Godbolt, I came up with this alternative: > > > > if (likely(cksum != 0)) return cksum; > > if (ipv4_hdr->next_proto_id == IPPROTO_UDP) return 0xffff; > > return 0; > > Good idea, this is indeed an unlikely branch. > However this code was already present before this patch, > so I suggest to add it as a specific optimization patch. Please do. > > > > + > > > +/** > > > + * Validate the IPv4 UDP or TCP checksum. > > > + * > > > + * @param ipv4_hdr > > > + * The pointer to the contiguous IPv4 header. > > > + * @param l4_hdr > > > + * The pointer to the beginning of the L4 header. > > > + * @return > > > + * Return 0 if the checksum is correct, else -1. > > > + */ > > > +__rte_experimental > > > +static inline int > > > +rte_ipv4_udptcp_cksum_verify(const struct rte_ipv4_hdr *ipv4_hdr, > > > + const void *l4_hdr) > > > +{ > > > + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); > > > + > > > + if (cksum != 0xffff) > > > + return -1; > > > > The GCC static branch predictor treats the above comparison as > likely, so I would prefer unlikely() around it. > > For this one, I'm less convinced: should we decide here whether > the good or the bad checksum is more likely than the other? You are right... this may be a question of personal preference - or application specific preference. > > Given it's a static inline function, wouldn't it be better to let > the application call it this way: > if (likely(rte_ipv4_udptcp_cksum_verify(...) == 0)) ? > Good point. Double checking on Godbolt confirms the validity of your suggestion. > > Regards, > Olivier ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [dpdk-dev] [PATCH 3/4] net: introduce functions to verify L4 checksums 2021-04-27 13:57 ` [dpdk-dev] [PATCH 3/4] net: introduce functions to verify L4 checksums Olivier Matz 2021-04-27 15:02 ` Morten Brørup 2021-04-27 15:07 ` Morten Brørup @ 2021-04-30 15:42 ` Ferruh Yigit 2021-06-08 10:23 ` Andrew Rybchenko 2 siblings, 1 reply; 28+ messages in thread From: Ferruh Yigit @ 2021-04-30 15:42 UTC (permalink / raw) To: Olivier Matz, dev Cc: Keith Wiles, Hongzhi Guo, Morten Brørup, Thomas Monjalon On 4/27/2021 2:57 PM, Olivier Matz wrote: > Since commit d5df2ae0428a ("net: fix unneeded replacement of TCP > checksum 0"), the functions rte_ipv4_udptcp_cksum() and > rte_ipv6_udptcp_cksum() can return either 0x0000 or 0xffff when used to > verify a packet containing a valid checksum. > > Since these functions should be used to calculate the checksum to set in > a packet, introduce 2 new helpers for checksum verification. They return > 0 if the checksum is valid in the packet. > > Use this new helper in net/tap driver. > > Signed-off-by: Olivier Matz <olivier.matz@6wind.com> > --- > drivers/net/tap/rte_eth_tap.c | 7 +- > lib/net/rte_ip.h | 124 +++++++++++++++++++++++++++------- > 2 files changed, 104 insertions(+), 27 deletions(-) > > diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c > index 71282e8065..b14d5a1d55 100644 > --- a/drivers/net/tap/rte_eth_tap.c > +++ b/drivers/net/tap/rte_eth_tap.c > @@ -365,11 +365,12 @@ tap_verify_csum(struct rte_mbuf *mbuf) > return; > } > } > - cksum = rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); > + cksum_ok = !rte_ipv4_udptcp_cksum_verify(l3_hdr, > + l4_hdr); > } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ > - cksum = rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); > + cksum_ok = !rte_ipv6_udptcp_cksum_verify(l3_hdr, > + l4_hdr); > } > - cksum_ok = (cksum == 0) || (cksum == 0xffff); > mbuf->ol_flags |= cksum_ok ? > PKT_RX_L4_CKSUM_GOOD : PKT_RX_L4_CKSUM_BAD; > } > diff --git a/lib/net/rte_ip.h b/lib/net/rte_ip.h > index 8c189009b0..ef84bcc5bf 100644 > --- a/lib/net/rte_ip.h > +++ b/lib/net/rte_ip.h > @@ -344,20 +344,10 @@ rte_ipv4_phdr_cksum(const struct rte_ipv4_hdr *ipv4_hdr, uint64_t ol_flags) > } > > /** > - * Process the IPv4 UDP or TCP checksum. > - * > - * The IP and layer 4 checksum must be set to 0 in the packet by > - * the caller. > - * > - * @param ipv4_hdr > - * The pointer to the contiguous IPv4 header. > - * @param l4_hdr > - * The pointer to the beginning of the L4 header. > - * @return > - * The complemented checksum to set in the IP packet. > + * @internal Calculate the non-complemented IPv4 L4 checksum > */ > static inline uint16_t > -rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) > +__rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) > { > uint32_t cksum; > uint32_t l3_len, l4_len; > @@ -374,16 +364,62 @@ rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) > cksum += rte_ipv4_phdr_cksum(ipv4_hdr, 0); > > cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); > - cksum = (~cksum) & 0xffff; > + > + return (uint16_t)cksum; > +} > + > +/** > + * Process the IPv4 UDP or TCP checksum. > + * > + * The IP and layer 4 checksum must be set to 0 in the packet by > + * the caller. > + * > + * @param ipv4_hdr > + * The pointer to the contiguous IPv4 header. > + * @param l4_hdr > + * The pointer to the beginning of the L4 header. > + * @return > + * The complemented checksum to set in the IP packet. > + */ > +static inline uint16_t > +rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) > +{ > + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); > + > + cksum = ~cksum; > + > /* > - * Per RFC 768:If the computed checksum is zero for UDP, > + * Per RFC 768: If the computed checksum is zero for UDP, > * it is transmitted as all ones > * (the equivalent in one's complement arithmetic). > */ > if (cksum == 0 && ipv4_hdr->next_proto_id == IPPROTO_UDP) > cksum = 0xffff; > > - return (uint16_t)cksum; > + return cksum; > +} > + > +/** > + * Validate the IPv4 UDP or TCP checksum. > + * > + * @param ipv4_hdr > + * The pointer to the contiguous IPv4 header. > + * @param l4_hdr > + * The pointer to the beginning of the L4 header. > + * @return > + * Return 0 if the checksum is correct, else -1. > + */ > +__rte_experimental > +static inline int > +rte_ipv4_udptcp_cksum_verify(const struct rte_ipv4_hdr *ipv4_hdr, > + const void *l4_hdr) > +{ > + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); > + > + if (cksum != 0xffff) > + return -1; > + > + return 0; There is behavior change in tap verify, I am asking just to verify if expected, Previously for UDP, if calculated checksum is '0', the 'rte_ipv4_udptcp_cksum()' returns 0xFFFF. And 0xFFFF is taken as good checksum by tap PMD. With new 'rte_ipv4_udptcp_cksum_verify()', if calculated checksum is '0' it will be taken as bad checksum. I don't know if calculated checksum with valid checksum in place can return 0. Also for TCP, 'rte_ipv4_udptcp_cksum_verify()' doesn't have inversion (cksum = ~cksum;) seems changing pass/fail status of the checksum, unless I am not missing anything here. > } > > /** > @@ -448,6 +484,25 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags) > return __rte_raw_cksum_reduce(sum); > } > > +/** > + * @internal Calculate the non-complemented IPv4 L4 checksum > + */ > +static inline uint16_t > +__rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) > +{ > + uint32_t cksum; > + uint32_t l4_len; > + > + l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len); > + > + cksum = rte_raw_cksum(l4_hdr, l4_len); > + cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0); > + > + cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); > + > + return (uint16_t)cksum; > +} > + > /** > * Process the IPv6 UDP or TCP checksum. > * > @@ -464,16 +519,10 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags) > static inline uint16_t > rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) > { > - uint32_t cksum; > - uint32_t l4_len; > - > - l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len); > + uint16_t cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr); > > - cksum = rte_raw_cksum(l4_hdr, l4_len); > - cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0); > + cksum = ~cksum; > > - cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); > - cksum = (~cksum) & 0xffff; > /* > * Per RFC 768: If the computed checksum is zero for UDP, > * it is transmitted as all ones > @@ -482,7 +531,34 @@ rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) > if (cksum == 0 && ipv6_hdr->proto == IPPROTO_UDP) > cksum = 0xffff; > > - return (uint16_t)cksum; > + return cksum; > +} > + > +/** > + * Validate the IPv6 UDP or TCP checksum. > + * > + * The function accepts a 0 checksum, since it can exceptionally happen. See 8.1 > + * (Upper-Layer Checksums) in RFC 8200. > + * > + * @param ipv6_hdr > + * The pointer to the contiguous IPv6 header. > + * @param l4_hdr > + * The pointer to the beginning of the L4 header. > + * @return > + * Return 0 if the checksum is correct, else -1. > + */ > +__rte_experimental > +static inline int > +rte_ipv6_udptcp_cksum_verify(const struct rte_ipv6_hdr *ipv6_hdr, > + const void *l4_hdr) > +{ > + uint16_t cksum; > + > + cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr); > + if (cksum != 0xffff) > + return -1; > + > + return 0; > } Nitpicking but, 'rte_ipv4_udptcp_cksum_verify()' is almost same with this function ('rte_ipv6_udptcp_cksum_verify()') but they have different line spacing, can be good to have similar syntax for both. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [dpdk-dev] [PATCH 3/4] net: introduce functions to verify L4 checksums 2021-04-30 15:42 ` Ferruh Yigit @ 2021-06-08 10:23 ` Andrew Rybchenko 2021-06-08 12:29 ` Olivier Matz 0 siblings, 1 reply; 28+ messages in thread From: Andrew Rybchenko @ 2021-06-08 10:23 UTC (permalink / raw) To: Ferruh Yigit, Olivier Matz, dev Cc: Keith Wiles, Hongzhi Guo, Morten Brørup, Thomas Monjalon On 4/30/21 6:42 PM, Ferruh Yigit wrote: > On 4/27/2021 2:57 PM, Olivier Matz wrote: >> Since commit d5df2ae0428a ("net: fix unneeded replacement of TCP >> checksum 0"), the functions rte_ipv4_udptcp_cksum() and >> rte_ipv6_udptcp_cksum() can return either 0x0000 or 0xffff when used to >> verify a packet containing a valid checksum. >> >> Since these functions should be used to calculate the checksum to set in >> a packet, introduce 2 new helpers for checksum verification. They return >> 0 if the checksum is valid in the packet. >> >> Use this new helper in net/tap driver. >> >> Signed-off-by: Olivier Matz <olivier.matz@6wind.com> >> --- >> drivers/net/tap/rte_eth_tap.c | 7 +- >> lib/net/rte_ip.h | 124 +++++++++++++++++++++++++++------- >> 2 files changed, 104 insertions(+), 27 deletions(-) >> >> diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c >> index 71282e8065..b14d5a1d55 100644 >> --- a/drivers/net/tap/rte_eth_tap.c >> +++ b/drivers/net/tap/rte_eth_tap.c >> @@ -365,11 +365,12 @@ tap_verify_csum(struct rte_mbuf *mbuf) >> return; >> } >> } >> - cksum = rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); >> + cksum_ok = !rte_ipv4_udptcp_cksum_verify(l3_hdr, >> + l4_hdr); >> } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ >> - cksum = rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); >> + cksum_ok = !rte_ipv6_udptcp_cksum_verify(l3_hdr, >> + l4_hdr); >> } >> - cksum_ok = (cksum == 0) || (cksum == 0xffff); >> mbuf->ol_flags |= cksum_ok ? >> PKT_RX_L4_CKSUM_GOOD : PKT_RX_L4_CKSUM_BAD; >> } >> diff --git a/lib/net/rte_ip.h b/lib/net/rte_ip.h >> index 8c189009b0..ef84bcc5bf 100644 >> --- a/lib/net/rte_ip.h >> +++ b/lib/net/rte_ip.h >> @@ -344,20 +344,10 @@ rte_ipv4_phdr_cksum(const struct rte_ipv4_hdr *ipv4_hdr, uint64_t ol_flags) >> } >> >> /** >> - * Process the IPv4 UDP or TCP checksum. >> - * >> - * The IP and layer 4 checksum must be set to 0 in the packet by >> - * the caller. >> - * >> - * @param ipv4_hdr >> - * The pointer to the contiguous IPv4 header. >> - * @param l4_hdr >> - * The pointer to the beginning of the L4 header. >> - * @return >> - * The complemented checksum to set in the IP packet. >> + * @internal Calculate the non-complemented IPv4 L4 checksum >> */ >> static inline uint16_t >> -rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) >> +__rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) >> { >> uint32_t cksum; >> uint32_t l3_len, l4_len; >> @@ -374,16 +364,62 @@ rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) >> cksum += rte_ipv4_phdr_cksum(ipv4_hdr, 0); >> >> cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); >> - cksum = (~cksum) & 0xffff; >> + >> + return (uint16_t)cksum; >> +} >> + >> +/** >> + * Process the IPv4 UDP or TCP checksum. >> + * >> + * The IP and layer 4 checksum must be set to 0 in the packet by >> + * the caller. >> + * >> + * @param ipv4_hdr >> + * The pointer to the contiguous IPv4 header. >> + * @param l4_hdr >> + * The pointer to the beginning of the L4 header. >> + * @return >> + * The complemented checksum to set in the IP packet. >> + */ >> +static inline uint16_t >> +rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) >> +{ >> + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); >> + >> + cksum = ~cksum; >> + >> /* >> - * Per RFC 768:If the computed checksum is zero for UDP, >> + * Per RFC 768: If the computed checksum is zero for UDP, >> * it is transmitted as all ones >> * (the equivalent in one's complement arithmetic). >> */ >> if (cksum == 0 && ipv4_hdr->next_proto_id == IPPROTO_UDP) >> cksum = 0xffff; >> >> - return (uint16_t)cksum; >> + return cksum; >> +} >> + >> +/** >> + * Validate the IPv4 UDP or TCP checksum. >> + * >> + * @param ipv4_hdr >> + * The pointer to the contiguous IPv4 header. >> + * @param l4_hdr >> + * The pointer to the beginning of the L4 header. >> + * @return >> + * Return 0 if the checksum is correct, else -1. >> + */ >> +__rte_experimental >> +static inline int >> +rte_ipv4_udptcp_cksum_verify(const struct rte_ipv4_hdr *ipv4_hdr, >> + const void *l4_hdr) >> +{ >> + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); >> + >> + if (cksum != 0xffff) >> + return -1; >> + >> + return 0; > > There is behavior change in tap verify, I am asking just to verify if expected, > > Previously for UDP, if calculated checksum is '0', the 'rte_ipv4_udptcp_cksum()' > returns 0xFFFF. > And 0xFFFF is taken as good checksum by tap PMD. > > With new 'rte_ipv4_udptcp_cksum_verify()', if calculated checksum is '0' it will > be taken as bad checksum. > > I don't know if calculated checksum with valid checksum in place can return 0. > > > Also for TCP, 'rte_ipv4_udptcp_cksum_verify()' doesn't have inversion (cksum = > ~cksum;) seems changing pass/fail status of the checksum, unless I am not > missing anything here. Yes, it looks suspicious to me as well. Olivier, could you clarify, please. >> } >> >> /** >> @@ -448,6 +484,25 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags) >> return __rte_raw_cksum_reduce(sum); >> } >> >> +/** >> + * @internal Calculate the non-complemented IPv4 L4 checksum >> + */ >> +static inline uint16_t >> +__rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) >> +{ >> + uint32_t cksum; >> + uint32_t l4_len; >> + >> + l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len); >> + >> + cksum = rte_raw_cksum(l4_hdr, l4_len); >> + cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0); >> + >> + cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); >> + >> + return (uint16_t)cksum; >> +} >> + >> /** >> * Process the IPv6 UDP or TCP checksum. >> * >> @@ -464,16 +519,10 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags) >> static inline uint16_t >> rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) >> { >> - uint32_t cksum; >> - uint32_t l4_len; >> - >> - l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len); >> + uint16_t cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr); >> >> - cksum = rte_raw_cksum(l4_hdr, l4_len); >> - cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0); >> + cksum = ~cksum; >> >> - cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); >> - cksum = (~cksum) & 0xffff; >> /* >> * Per RFC 768: If the computed checksum is zero for UDP, >> * it is transmitted as all ones >> @@ -482,7 +531,34 @@ rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) >> if (cksum == 0 && ipv6_hdr->proto == IPPROTO_UDP) >> cksum = 0xffff; >> >> - return (uint16_t)cksum; >> + return cksum; >> +} >> + >> +/** >> + * Validate the IPv6 UDP or TCP checksum. >> + * >> + * The function accepts a 0 checksum, since it can exceptionally happen. See 8.1 >> + * (Upper-Layer Checksums) in RFC 8200. >> + * >> + * @param ipv6_hdr >> + * The pointer to the contiguous IPv6 header. >> + * @param l4_hdr >> + * The pointer to the beginning of the L4 header. >> + * @return >> + * Return 0 if the checksum is correct, else -1. >> + */ >> +__rte_experimental >> +static inline int >> +rte_ipv6_udptcp_cksum_verify(const struct rte_ipv6_hdr *ipv6_hdr, >> + const void *l4_hdr) >> +{ >> + uint16_t cksum; >> + >> + cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr); >> + if (cksum != 0xffff) >> + return -1; >> + >> + return 0; >> } > > Nitpicking but, 'rte_ipv4_udptcp_cksum_verify()' is almost same with this > function ('rte_ipv6_udptcp_cksum_verify()') but they have different line > spacing, can be good to have similar syntax for both. > ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [dpdk-dev] [PATCH 3/4] net: introduce functions to verify L4 checksums 2021-06-08 10:23 ` Andrew Rybchenko @ 2021-06-08 12:29 ` Olivier Matz 2021-06-08 12:39 ` Andrew Rybchenko 0 siblings, 1 reply; 28+ messages in thread From: Olivier Matz @ 2021-06-08 12:29 UTC (permalink / raw) To: Andrew Rybchenko Cc: Ferruh Yigit, dev, Keith Wiles, Hongzhi Guo, Morten Brørup, Thomas Monjalon Hi Ferruh, Andrew, On Tue, Jun 08, 2021 at 01:23:33PM +0300, Andrew Rybchenko wrote: > On 4/30/21 6:42 PM, Ferruh Yigit wrote: > > On 4/27/2021 2:57 PM, Olivier Matz wrote: > >> Since commit d5df2ae0428a ("net: fix unneeded replacement of TCP > >> checksum 0"), the functions rte_ipv4_udptcp_cksum() and > >> rte_ipv6_udptcp_cksum() can return either 0x0000 or 0xffff when used to > >> verify a packet containing a valid checksum. > >> > >> Since these functions should be used to calculate the checksum to set in > >> a packet, introduce 2 new helpers for checksum verification. They return > >> 0 if the checksum is valid in the packet. > >> > >> Use this new helper in net/tap driver. > >> > >> Signed-off-by: Olivier Matz <olivier.matz@6wind.com> > >> --- > >> drivers/net/tap/rte_eth_tap.c | 7 +- > >> lib/net/rte_ip.h | 124 +++++++++++++++++++++++++++------- > >> 2 files changed, 104 insertions(+), 27 deletions(-) > >> > >> diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c > >> index 71282e8065..b14d5a1d55 100644 > >> --- a/drivers/net/tap/rte_eth_tap.c > >> +++ b/drivers/net/tap/rte_eth_tap.c > >> @@ -365,11 +365,12 @@ tap_verify_csum(struct rte_mbuf *mbuf) > >> return; > >> } > >> } > >> - cksum = rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); > >> + cksum_ok = !rte_ipv4_udptcp_cksum_verify(l3_hdr, > >> + l4_hdr); > >> } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ > >> - cksum = rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); > >> + cksum_ok = !rte_ipv6_udptcp_cksum_verify(l3_hdr, > >> + l4_hdr); > >> } > >> - cksum_ok = (cksum == 0) || (cksum == 0xffff); > >> mbuf->ol_flags |= cksum_ok ? > >> PKT_RX_L4_CKSUM_GOOD : PKT_RX_L4_CKSUM_BAD; > >> } > >> diff --git a/lib/net/rte_ip.h b/lib/net/rte_ip.h > >> index 8c189009b0..ef84bcc5bf 100644 > >> --- a/lib/net/rte_ip.h > >> +++ b/lib/net/rte_ip.h > >> @@ -344,20 +344,10 @@ rte_ipv4_phdr_cksum(const struct rte_ipv4_hdr *ipv4_hdr, uint64_t ol_flags) > >> } > >> > >> /** > >> - * Process the IPv4 UDP or TCP checksum. > >> - * > >> - * The IP and layer 4 checksum must be set to 0 in the packet by > >> - * the caller. > >> - * > >> - * @param ipv4_hdr > >> - * The pointer to the contiguous IPv4 header. > >> - * @param l4_hdr > >> - * The pointer to the beginning of the L4 header. > >> - * @return > >> - * The complemented checksum to set in the IP packet. > >> + * @internal Calculate the non-complemented IPv4 L4 checksum > >> */ > >> static inline uint16_t > >> -rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) > >> +__rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) > >> { > >> uint32_t cksum; > >> uint32_t l3_len, l4_len; > >> @@ -374,16 +364,62 @@ rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) > >> cksum += rte_ipv4_phdr_cksum(ipv4_hdr, 0); > >> > >> cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); > >> - cksum = (~cksum) & 0xffff; > >> + > >> + return (uint16_t)cksum; > >> +} > >> + > >> +/** > >> + * Process the IPv4 UDP or TCP checksum. > >> + * > >> + * The IP and layer 4 checksum must be set to 0 in the packet by > >> + * the caller. > >> + * > >> + * @param ipv4_hdr > >> + * The pointer to the contiguous IPv4 header. > >> + * @param l4_hdr > >> + * The pointer to the beginning of the L4 header. > >> + * @return > >> + * The complemented checksum to set in the IP packet. > >> + */ > >> +static inline uint16_t > >> +rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) > >> +{ > >> + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); > >> + > >> + cksum = ~cksum; > >> + > >> /* > >> - * Per RFC 768:If the computed checksum is zero for UDP, > >> + * Per RFC 768: If the computed checksum is zero for UDP, > >> * it is transmitted as all ones > >> * (the equivalent in one's complement arithmetic). > >> */ > >> if (cksum == 0 && ipv4_hdr->next_proto_id == IPPROTO_UDP) > >> cksum = 0xffff; > >> > >> - return (uint16_t)cksum; > >> + return cksum; > >> +} > >> + > >> +/** > >> + * Validate the IPv4 UDP or TCP checksum. > >> + * > >> + * @param ipv4_hdr > >> + * The pointer to the contiguous IPv4 header. > >> + * @param l4_hdr > >> + * The pointer to the beginning of the L4 header. > >> + * @return > >> + * Return 0 if the checksum is correct, else -1. > >> + */ > >> +__rte_experimental > >> +static inline int > >> +rte_ipv4_udptcp_cksum_verify(const struct rte_ipv4_hdr *ipv4_hdr, > >> + const void *l4_hdr) > >> +{ > >> + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); > >> + > >> + if (cksum != 0xffff) > >> + return -1; > >> + > >> + return 0; > > > > There is behavior change in tap verify, I am asking just to verify if expected, > > > > Previously for UDP, if calculated checksum is '0', the 'rte_ipv4_udptcp_cksum()' > > returns 0xFFFF. > > And 0xFFFF is taken as good checksum by tap PMD. rte_ipv4_udptcp_cksum() cannot return 0xFFFF: this is only possible if all data is 0. Before verifying a udp packet, the user must check that it is not 0 (which means no checksum). In tcp, "Data offset" is never 0. Moreover, port=0 is a reserved value for both udp and tcp. > > With new 'rte_ipv4_udptcp_cksum_verify()', if calculated checksum is '0' it will > > be taken as bad checksum. > > > > I don't know if calculated checksum with valid checksum in place can return 0. > > > > > > Also for TCP, 'rte_ipv4_udptcp_cksum_verify()' doesn't have inversion (cksum = > > ~cksum;) seems changing pass/fail status of the checksum, unless I am not > > missing anything here. > > Yes, it looks suspicious to me as well. > > Olivier, could you clarify, please. Before commit d5df2ae0428a ("net: fix unneeded replacement of TCP checksum 0"), the behavior was: // rte_ipv4_udptcp_cksum() is 0xffff if checksum is valid // so cksum is 0 if checksum is valid cksum = ~rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); // ol_flags is set to PKT_RX_L4_CKSUM_GOOD if checksum is valid mbuf->ol_flags |= cksum ? PKT_RX_L4_CKSUM_BAD : PKT_RX_L4_CKSUM_GOOD; After commit d5df2ae0428a ("net: fix unneeded replacement of TCP checksum 0"), it is broken: // rte_ipv4_udptcp_cksum() is 0 (tcp) or 0xffff (udp) if checksum is valid // so cksum is 0xffff (tcp) or 0 (udp) if checksum is valid cksum = ~rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); // ol_flags is set to BAD (tcp) or GOOD (udp) if checksum is valid mbuf->ol_flags |= cksum ? PKT_RX_L4_CKSUM_BAD : PKT_RX_L4_CKSUM_GOOD; After patch 2/4 ("net/tap: fix Rx cksum flags on TCP packets"), the correct behavior is restored: // cksum is 0 (tcp) or 0xffff (udp) if checksum is valid // note: 0xffff for tcp cannot happen (there is at least 1 bit set in the header) // note: 0 for udp cannot happen (it is replaced by in rte_ipv4_udptcp_cksum()) cksum = rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); // cksum_ok is 1 if checksum is valid cksum_ok = (cksum == 0) || (cksum == 0xffff); // ol_flags is set to GOOD if checksum is valid mbuf->ol_flags |= cksum_ok ? PKT_RX_L4_CKSUM_GOOD : PKT_RX_L4_CKSUM_BAD; After this patch [3/4] ("net: introduce functions to verify L4 checksums"), it is simplified by using rte_ipv4_udptcp_cksum_verify(): // cksum_ok is 1 if checksum is valid cksum_ok = !rte_ipv4_udptcp_cksum_verify(l3_hdr, l4_hdr); // ol_flags is set to GOOD if checksum is valid mbuf->ol_flags |= cksum_ok ? PKT_RX_L4_CKSUM_GOOD : PKT_RX_L4_CKSUM_BAD; Olivier > > >> } > >> > >> /** > >> @@ -448,6 +484,25 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags) > >> return __rte_raw_cksum_reduce(sum); > >> } > >> > >> +/** > >> + * @internal Calculate the non-complemented IPv4 L4 checksum > >> + */ > >> +static inline uint16_t > >> +__rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) > >> +{ > >> + uint32_t cksum; > >> + uint32_t l4_len; > >> + > >> + l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len); > >> + > >> + cksum = rte_raw_cksum(l4_hdr, l4_len); > >> + cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0); > >> + > >> + cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); > >> + > >> + return (uint16_t)cksum; > >> +} > >> + > >> /** > >> * Process the IPv6 UDP or TCP checksum. > >> * > >> @@ -464,16 +519,10 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags) > >> static inline uint16_t > >> rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) > >> { > >> - uint32_t cksum; > >> - uint32_t l4_len; > >> - > >> - l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len); > >> + uint16_t cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr); > >> > >> - cksum = rte_raw_cksum(l4_hdr, l4_len); > >> - cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0); > >> + cksum = ~cksum; > >> > >> - cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); > >> - cksum = (~cksum) & 0xffff; > >> /* > >> * Per RFC 768: If the computed checksum is zero for UDP, > >> * it is transmitted as all ones > >> @@ -482,7 +531,34 @@ rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) > >> if (cksum == 0 && ipv6_hdr->proto == IPPROTO_UDP) > >> cksum = 0xffff; > >> > >> - return (uint16_t)cksum; > >> + return cksum; > >> +} > >> + > >> +/** > >> + * Validate the IPv6 UDP or TCP checksum. > >> + * > >> + * The function accepts a 0 checksum, since it can exceptionally happen. See 8.1 > >> + * (Upper-Layer Checksums) in RFC 8200. > >> + * > >> + * @param ipv6_hdr > >> + * The pointer to the contiguous IPv6 header. > >> + * @param l4_hdr > >> + * The pointer to the beginning of the L4 header. > >> + * @return > >> + * Return 0 if the checksum is correct, else -1. > >> + */ > >> +__rte_experimental > >> +static inline int > >> +rte_ipv6_udptcp_cksum_verify(const struct rte_ipv6_hdr *ipv6_hdr, > >> + const void *l4_hdr) > >> +{ > >> + uint16_t cksum; > >> + > >> + cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr); > >> + if (cksum != 0xffff) > >> + return -1; > >> + > >> + return 0; > >> } > > > > Nitpicking but, 'rte_ipv4_udptcp_cksum_verify()' is almost same with this > > function ('rte_ipv6_udptcp_cksum_verify()') but they have different line > > spacing, can be good to have similar syntax for both. > > > ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [dpdk-dev] [PATCH 3/4] net: introduce functions to verify L4 checksums 2021-06-08 12:29 ` Olivier Matz @ 2021-06-08 12:39 ` Andrew Rybchenko 2021-06-25 15:38 ` Ferruh Yigit 0 siblings, 1 reply; 28+ messages in thread From: Andrew Rybchenko @ 2021-06-08 12:39 UTC (permalink / raw) To: Olivier Matz Cc: Ferruh Yigit, dev, Keith Wiles, Hongzhi Guo, Morten Brørup, Thomas Monjalon On 6/8/21 3:29 PM, Olivier Matz wrote: > Hi Ferruh, Andrew, > > On Tue, Jun 08, 2021 at 01:23:33PM +0300, Andrew Rybchenko wrote: >> On 4/30/21 6:42 PM, Ferruh Yigit wrote: >>> On 4/27/2021 2:57 PM, Olivier Matz wrote: >>>> Since commit d5df2ae0428a ("net: fix unneeded replacement of TCP >>>> checksum 0"), the functions rte_ipv4_udptcp_cksum() and >>>> rte_ipv6_udptcp_cksum() can return either 0x0000 or 0xffff when used to >>>> verify a packet containing a valid checksum. >>>> >>>> Since these functions should be used to calculate the checksum to set in >>>> a packet, introduce 2 new helpers for checksum verification. They return >>>> 0 if the checksum is valid in the packet. >>>> >>>> Use this new helper in net/tap driver. >>>> >>>> Signed-off-by: Olivier Matz <olivier.matz@6wind.com> >>>> --- >>>> drivers/net/tap/rte_eth_tap.c | 7 +- >>>> lib/net/rte_ip.h | 124 +++++++++++++++++++++++++++------- >>>> 2 files changed, 104 insertions(+), 27 deletions(-) >>>> >>>> diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c >>>> index 71282e8065..b14d5a1d55 100644 >>>> --- a/drivers/net/tap/rte_eth_tap.c >>>> +++ b/drivers/net/tap/rte_eth_tap.c >>>> @@ -365,11 +365,12 @@ tap_verify_csum(struct rte_mbuf *mbuf) >>>> return; >>>> } >>>> } >>>> - cksum = rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); >>>> + cksum_ok = !rte_ipv4_udptcp_cksum_verify(l3_hdr, >>>> + l4_hdr); >>>> } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ >>>> - cksum = rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); >>>> + cksum_ok = !rte_ipv6_udptcp_cksum_verify(l3_hdr, >>>> + l4_hdr); >>>> } >>>> - cksum_ok = (cksum == 0) || (cksum == 0xffff); >>>> mbuf->ol_flags |= cksum_ok ? >>>> PKT_RX_L4_CKSUM_GOOD : PKT_RX_L4_CKSUM_BAD; >>>> } >>>> diff --git a/lib/net/rte_ip.h b/lib/net/rte_ip.h >>>> index 8c189009b0..ef84bcc5bf 100644 >>>> --- a/lib/net/rte_ip.h >>>> +++ b/lib/net/rte_ip.h >>>> @@ -344,20 +344,10 @@ rte_ipv4_phdr_cksum(const struct rte_ipv4_hdr *ipv4_hdr, uint64_t ol_flags) >>>> } >>>> >>>> /** >>>> - * Process the IPv4 UDP or TCP checksum. >>>> - * >>>> - * The IP and layer 4 checksum must be set to 0 in the packet by >>>> - * the caller. >>>> - * >>>> - * @param ipv4_hdr >>>> - * The pointer to the contiguous IPv4 header. >>>> - * @param l4_hdr >>>> - * The pointer to the beginning of the L4 header. >>>> - * @return >>>> - * The complemented checksum to set in the IP packet. >>>> + * @internal Calculate the non-complemented IPv4 L4 checksum >>>> */ >>>> static inline uint16_t >>>> -rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) >>>> +__rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) >>>> { >>>> uint32_t cksum; >>>> uint32_t l3_len, l4_len; >>>> @@ -374,16 +364,62 @@ rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) >>>> cksum += rte_ipv4_phdr_cksum(ipv4_hdr, 0); >>>> >>>> cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); >>>> - cksum = (~cksum) & 0xffff; >>>> + >>>> + return (uint16_t)cksum; >>>> +} >>>> + >>>> +/** >>>> + * Process the IPv4 UDP or TCP checksum. >>>> + * >>>> + * The IP and layer 4 checksum must be set to 0 in the packet by >>>> + * the caller. >>>> + * >>>> + * @param ipv4_hdr >>>> + * The pointer to the contiguous IPv4 header. >>>> + * @param l4_hdr >>>> + * The pointer to the beginning of the L4 header. >>>> + * @return >>>> + * The complemented checksum to set in the IP packet. >>>> + */ >>>> +static inline uint16_t >>>> +rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) >>>> +{ >>>> + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); >>>> + >>>> + cksum = ~cksum; >>>> + >>>> /* >>>> - * Per RFC 768:If the computed checksum is zero for UDP, >>>> + * Per RFC 768: If the computed checksum is zero for UDP, >>>> * it is transmitted as all ones >>>> * (the equivalent in one's complement arithmetic). >>>> */ >>>> if (cksum == 0 && ipv4_hdr->next_proto_id == IPPROTO_UDP) >>>> cksum = 0xffff; >>>> >>>> - return (uint16_t)cksum; >>>> + return cksum; >>>> +} >>>> + >>>> +/** >>>> + * Validate the IPv4 UDP or TCP checksum. >>>> + * >>>> + * @param ipv4_hdr >>>> + * The pointer to the contiguous IPv4 header. >>>> + * @param l4_hdr >>>> + * The pointer to the beginning of the L4 header. >>>> + * @return >>>> + * Return 0 if the checksum is correct, else -1. >>>> + */ >>>> +__rte_experimental >>>> +static inline int >>>> +rte_ipv4_udptcp_cksum_verify(const struct rte_ipv4_hdr *ipv4_hdr, >>>> + const void *l4_hdr) >>>> +{ >>>> + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); >>>> + >>>> + if (cksum != 0xffff) >>>> + return -1; >>>> + >>>> + return 0; >>> >>> There is behavior change in tap verify, I am asking just to verify if expected, >>> >>> Previously for UDP, if calculated checksum is '0', the 'rte_ipv4_udptcp_cksum()' >>> returns 0xFFFF. >>> And 0xFFFF is taken as good checksum by tap PMD. > > rte_ipv4_udptcp_cksum() cannot return 0xFFFF: this is only possible if > all data is 0. Before verifying a udp packet, the user must check that > it is not 0 (which means no checksum). In tcp, "Data offset" is never > 0. Moreover, port=0 is a reserved value for both udp and tcp. > >>> With new 'rte_ipv4_udptcp_cksum_verify()', if calculated checksum is '0' it will >>> be taken as bad checksum. >>> >>> I don't know if calculated checksum with valid checksum in place can return 0. >>> >>> >>> Also for TCP, 'rte_ipv4_udptcp_cksum_verify()' doesn't have inversion (cksum = >>> ~cksum;) seems changing pass/fail status of the checksum, unless I am not >>> missing anything here. >> >> Yes, it looks suspicious to me as well. >> >> Olivier, could you clarify, please. > > Before commit d5df2ae0428a ("net: fix unneeded replacement of TCP checksum 0"), > the behavior was: > > // rte_ipv4_udptcp_cksum() is 0xffff if checksum is valid > // so cksum is 0 if checksum is valid > cksum = ~rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); > // ol_flags is set to PKT_RX_L4_CKSUM_GOOD if checksum is valid > mbuf->ol_flags |= cksum ? PKT_RX_L4_CKSUM_BAD : PKT_RX_L4_CKSUM_GOOD; > > After commit d5df2ae0428a ("net: fix unneeded replacement of TCP checksum 0"), > it is broken: > > // rte_ipv4_udptcp_cksum() is 0 (tcp) or 0xffff (udp) if checksum is valid > // so cksum is 0xffff (tcp) or 0 (udp) if checksum is valid > cksum = ~rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); > // ol_flags is set to BAD (tcp) or GOOD (udp) if checksum is valid > mbuf->ol_flags |= cksum ? PKT_RX_L4_CKSUM_BAD : PKT_RX_L4_CKSUM_GOOD; > > After patch 2/4 ("net/tap: fix Rx cksum flags on TCP packets"), the > correct behavior is restored: > > // cksum is 0 (tcp) or 0xffff (udp) if checksum is valid > // note: 0xffff for tcp cannot happen (there is at least 1 bit set in the header) > // note: 0 for udp cannot happen (it is replaced by in rte_ipv4_udptcp_cksum()) > cksum = rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); > // cksum_ok is 1 if checksum is valid > cksum_ok = (cksum == 0) || (cksum == 0xffff); > // ol_flags is set to GOOD if checksum is valid > mbuf->ol_flags |= cksum_ok ? PKT_RX_L4_CKSUM_GOOD : PKT_RX_L4_CKSUM_BAD; > > After this patch [3/4] ("net: introduce functions to verify L4 checksums"), > it is simplified by using rte_ipv4_udptcp_cksum_verify(): > > // cksum_ok is 1 if checksum is valid > cksum_ok = !rte_ipv4_udptcp_cksum_verify(l3_hdr, l4_hdr); > // ol_flags is set to GOOD if checksum is valid > mbuf->ol_flags |= cksum_ok ? PKT_RX_L4_CKSUM_GOOD : PKT_RX_L4_CKSUM_BAD; > Many thanks for the detailed explanations. It replies to all my questions (even not asked, but kept in my head). Andrew. > Olivier > >> >>>> } >>>> >>>> /** >>>> @@ -448,6 +484,25 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags) >>>> return __rte_raw_cksum_reduce(sum); >>>> } >>>> >>>> +/** >>>> + * @internal Calculate the non-complemented IPv4 L4 checksum >>>> + */ >>>> +static inline uint16_t >>>> +__rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) >>>> +{ >>>> + uint32_t cksum; >>>> + uint32_t l4_len; >>>> + >>>> + l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len); >>>> + >>>> + cksum = rte_raw_cksum(l4_hdr, l4_len); >>>> + cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0); >>>> + >>>> + cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); >>>> + >>>> + return (uint16_t)cksum; >>>> +} >>>> + >>>> /** >>>> * Process the IPv6 UDP or TCP checksum. >>>> * >>>> @@ -464,16 +519,10 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags) >>>> static inline uint16_t >>>> rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) >>>> { >>>> - uint32_t cksum; >>>> - uint32_t l4_len; >>>> - >>>> - l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len); >>>> + uint16_t cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr); >>>> >>>> - cksum = rte_raw_cksum(l4_hdr, l4_len); >>>> - cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0); >>>> + cksum = ~cksum; >>>> >>>> - cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); >>>> - cksum = (~cksum) & 0xffff; >>>> /* >>>> * Per RFC 768: If the computed checksum is zero for UDP, >>>> * it is transmitted as all ones >>>> @@ -482,7 +531,34 @@ rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) >>>> if (cksum == 0 && ipv6_hdr->proto == IPPROTO_UDP) >>>> cksum = 0xffff; >>>> >>>> - return (uint16_t)cksum; >>>> + return cksum; >>>> +} >>>> + >>>> +/** >>>> + * Validate the IPv6 UDP or TCP checksum. >>>> + * >>>> + * The function accepts a 0 checksum, since it can exceptionally happen. See 8.1 >>>> + * (Upper-Layer Checksums) in RFC 8200. >>>> + * >>>> + * @param ipv6_hdr >>>> + * The pointer to the contiguous IPv6 header. >>>> + * @param l4_hdr >>>> + * The pointer to the beginning of the L4 header. >>>> + * @return >>>> + * Return 0 if the checksum is correct, else -1. >>>> + */ >>>> +__rte_experimental >>>> +static inline int >>>> +rte_ipv6_udptcp_cksum_verify(const struct rte_ipv6_hdr *ipv6_hdr, >>>> + const void *l4_hdr) >>>> +{ >>>> + uint16_t cksum; >>>> + >>>> + cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr); >>>> + if (cksum != 0xffff) >>>> + return -1; >>>> + >>>> + return 0; >>>> } >>> >>> Nitpicking but, 'rte_ipv4_udptcp_cksum_verify()' is almost same with this >>> function ('rte_ipv6_udptcp_cksum_verify()') but they have different line >>> spacing, can be good to have similar syntax for both. >>> >> ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [dpdk-dev] [PATCH 3/4] net: introduce functions to verify L4 checksums 2021-06-08 12:39 ` Andrew Rybchenko @ 2021-06-25 15:38 ` Ferruh Yigit 0 siblings, 0 replies; 28+ messages in thread From: Ferruh Yigit @ 2021-06-25 15:38 UTC (permalink / raw) To: Andrew Rybchenko, Olivier Matz Cc: Ferruh Yigit, dev, Keith Wiles, Hongzhi Guo, Morten Brørup, Thomas Monjalon On 6/8/2021 1:39 PM, Andrew Rybchenko wrote: > On 6/8/21 3:29 PM, Olivier Matz wrote: >> Hi Ferruh, Andrew, >> >> On Tue, Jun 08, 2021 at 01:23:33PM +0300, Andrew Rybchenko wrote: >>> On 4/30/21 6:42 PM, Ferruh Yigit wrote: >>>> On 4/27/2021 2:57 PM, Olivier Matz wrote: >>>>> Since commit d5df2ae0428a ("net: fix unneeded replacement of TCP >>>>> checksum 0"), the functions rte_ipv4_udptcp_cksum() and >>>>> rte_ipv6_udptcp_cksum() can return either 0x0000 or 0xffff when used to >>>>> verify a packet containing a valid checksum. >>>>> >>>>> Since these functions should be used to calculate the checksum to set in >>>>> a packet, introduce 2 new helpers for checksum verification. They return >>>>> 0 if the checksum is valid in the packet. >>>>> >>>>> Use this new helper in net/tap driver. >>>>> >>>>> Signed-off-by: Olivier Matz <olivier.matz@6wind.com> >>>>> --- >>>>> drivers/net/tap/rte_eth_tap.c | 7 +- >>>>> lib/net/rte_ip.h | 124 +++++++++++++++++++++++++++------- >>>>> 2 files changed, 104 insertions(+), 27 deletions(-) >>>>> >>>>> diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c >>>>> index 71282e8065..b14d5a1d55 100644 >>>>> --- a/drivers/net/tap/rte_eth_tap.c >>>>> +++ b/drivers/net/tap/rte_eth_tap.c >>>>> @@ -365,11 +365,12 @@ tap_verify_csum(struct rte_mbuf *mbuf) >>>>> return; >>>>> } >>>>> } >>>>> - cksum = rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); >>>>> + cksum_ok = !rte_ipv4_udptcp_cksum_verify(l3_hdr, >>>>> + l4_hdr); >>>>> } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ >>>>> - cksum = rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); >>>>> + cksum_ok = !rte_ipv6_udptcp_cksum_verify(l3_hdr, >>>>> + l4_hdr); >>>>> } >>>>> - cksum_ok = (cksum == 0) || (cksum == 0xffff); >>>>> mbuf->ol_flags |= cksum_ok ? >>>>> PKT_RX_L4_CKSUM_GOOD : PKT_RX_L4_CKSUM_BAD; >>>>> } >>>>> diff --git a/lib/net/rte_ip.h b/lib/net/rte_ip.h >>>>> index 8c189009b0..ef84bcc5bf 100644 >>>>> --- a/lib/net/rte_ip.h >>>>> +++ b/lib/net/rte_ip.h >>>>> @@ -344,20 +344,10 @@ rte_ipv4_phdr_cksum(const struct rte_ipv4_hdr *ipv4_hdr, uint64_t ol_flags) >>>>> } >>>>> >>>>> /** >>>>> - * Process the IPv4 UDP or TCP checksum. >>>>> - * >>>>> - * The IP and layer 4 checksum must be set to 0 in the packet by >>>>> - * the caller. >>>>> - * >>>>> - * @param ipv4_hdr >>>>> - * The pointer to the contiguous IPv4 header. >>>>> - * @param l4_hdr >>>>> - * The pointer to the beginning of the L4 header. >>>>> - * @return >>>>> - * The complemented checksum to set in the IP packet. >>>>> + * @internal Calculate the non-complemented IPv4 L4 checksum >>>>> */ >>>>> static inline uint16_t >>>>> -rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) >>>>> +__rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) >>>>> { >>>>> uint32_t cksum; >>>>> uint32_t l3_len, l4_len; >>>>> @@ -374,16 +364,62 @@ rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) >>>>> cksum += rte_ipv4_phdr_cksum(ipv4_hdr, 0); >>>>> >>>>> cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); >>>>> - cksum = (~cksum) & 0xffff; >>>>> + >>>>> + return (uint16_t)cksum; >>>>> +} >>>>> + >>>>> +/** >>>>> + * Process the IPv4 UDP or TCP checksum. >>>>> + * >>>>> + * The IP and layer 4 checksum must be set to 0 in the packet by >>>>> + * the caller. >>>>> + * >>>>> + * @param ipv4_hdr >>>>> + * The pointer to the contiguous IPv4 header. >>>>> + * @param l4_hdr >>>>> + * The pointer to the beginning of the L4 header. >>>>> + * @return >>>>> + * The complemented checksum to set in the IP packet. >>>>> + */ >>>>> +static inline uint16_t >>>>> +rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) >>>>> +{ >>>>> + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); >>>>> + >>>>> + cksum = ~cksum; >>>>> + >>>>> /* >>>>> - * Per RFC 768:If the computed checksum is zero for UDP, >>>>> + * Per RFC 768: If the computed checksum is zero for UDP, >>>>> * it is transmitted as all ones >>>>> * (the equivalent in one's complement arithmetic). >>>>> */ >>>>> if (cksum == 0 && ipv4_hdr->next_proto_id == IPPROTO_UDP) >>>>> cksum = 0xffff; >>>>> >>>>> - return (uint16_t)cksum; >>>>> + return cksum; >>>>> +} >>>>> + >>>>> +/** >>>>> + * Validate the IPv4 UDP or TCP checksum. >>>>> + * >>>>> + * @param ipv4_hdr >>>>> + * The pointer to the contiguous IPv4 header. >>>>> + * @param l4_hdr >>>>> + * The pointer to the beginning of the L4 header. >>>>> + * @return >>>>> + * Return 0 if the checksum is correct, else -1. >>>>> + */ >>>>> +__rte_experimental >>>>> +static inline int >>>>> +rte_ipv4_udptcp_cksum_verify(const struct rte_ipv4_hdr *ipv4_hdr, >>>>> + const void *l4_hdr) >>>>> +{ >>>>> + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); >>>>> + >>>>> + if (cksum != 0xffff) >>>>> + return -1; >>>>> + >>>>> + return 0; >>>> >>>> There is behavior change in tap verify, I am asking just to verify if expected, >>>> >>>> Previously for UDP, if calculated checksum is '0', the 'rte_ipv4_udptcp_cksum()' >>>> returns 0xFFFF. >>>> And 0xFFFF is taken as good checksum by tap PMD. >> >> rte_ipv4_udptcp_cksum() cannot return 0xFFFF: this is only possible if >> all data is 0. Before verifying a udp packet, the user must check that >> it is not 0 (which means no checksum). In tcp, "Data offset" is never >> 0. Moreover, port=0 is a reserved value for both udp and tcp. >> >>>> With new 'rte_ipv4_udptcp_cksum_verify()', if calculated checksum is '0' it will >>>> be taken as bad checksum. >>>> >>>> I don't know if calculated checksum with valid checksum in place can return 0. >>>> >>>> >>>> Also for TCP, 'rte_ipv4_udptcp_cksum_verify()' doesn't have inversion (cksum = >>>> ~cksum;) seems changing pass/fail status of the checksum, unless I am not >>>> missing anything here. >>> >>> Yes, it looks suspicious to me as well. >>> >>> Olivier, could you clarify, please. >> >> Before commit d5df2ae0428a ("net: fix unneeded replacement of TCP checksum 0"), >> the behavior was: >> >> // rte_ipv4_udptcp_cksum() is 0xffff if checksum is valid >> // so cksum is 0 if checksum is valid >> cksum = ~rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); >> // ol_flags is set to PKT_RX_L4_CKSUM_GOOD if checksum is valid >> mbuf->ol_flags |= cksum ? PKT_RX_L4_CKSUM_BAD : PKT_RX_L4_CKSUM_GOOD; >> >> After commit d5df2ae0428a ("net: fix unneeded replacement of TCP checksum 0"), >> it is broken: >> >> // rte_ipv4_udptcp_cksum() is 0 (tcp) or 0xffff (udp) if checksum is valid >> // so cksum is 0xffff (tcp) or 0 (udp) if checksum is valid >> cksum = ~rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); >> // ol_flags is set to BAD (tcp) or GOOD (udp) if checksum is valid >> mbuf->ol_flags |= cksum ? PKT_RX_L4_CKSUM_BAD : PKT_RX_L4_CKSUM_GOOD; >> >> After patch 2/4 ("net/tap: fix Rx cksum flags on TCP packets"), the >> correct behavior is restored: >> >> // cksum is 0 (tcp) or 0xffff (udp) if checksum is valid >> // note: 0xffff for tcp cannot happen (there is at least 1 bit set in the header) >> // note: 0 for udp cannot happen (it is replaced by in rte_ipv4_udptcp_cksum()) >> cksum = rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); >> // cksum_ok is 1 if checksum is valid >> cksum_ok = (cksum == 0) || (cksum == 0xffff); >> // ol_flags is set to GOOD if checksum is valid >> mbuf->ol_flags |= cksum_ok ? PKT_RX_L4_CKSUM_GOOD : PKT_RX_L4_CKSUM_BAD; >> >> After this patch [3/4] ("net: introduce functions to verify L4 checksums"), >> it is simplified by using rte_ipv4_udptcp_cksum_verify(): >> >> // cksum_ok is 1 if checksum is valid >> cksum_ok = !rte_ipv4_udptcp_cksum_verify(l3_hdr, l4_hdr); >> // ol_flags is set to GOOD if checksum is valid >> mbuf->ol_flags |= cksum_ok ? PKT_RX_L4_CKSUM_GOOD : PKT_RX_L4_CKSUM_BAD; >> > > Many thanks for the detailed explanations. It replies to all my > questions (even not asked, but kept in my head). > Thanks for clarification, after checking again with help of description above, it looks good to me. ^ permalink raw reply [flat|nested] 28+ messages in thread
* [dpdk-dev] [PATCH 4/4] test/cksum: new test for L3/L4 checksum API 2021-04-27 13:57 [dpdk-dev] [PATCH 0/4] net/tap: fix Rx cksum Olivier Matz ` (2 preceding siblings ...) 2021-04-27 13:57 ` [dpdk-dev] [PATCH 3/4] net: introduce functions to verify L4 checksums Olivier Matz @ 2021-04-27 13:57 ` Olivier Matz 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 0/4] net/tap: fix Rx cksum Olivier Matz 4 siblings, 0 replies; 28+ messages in thread From: Olivier Matz @ 2021-04-27 13:57 UTC (permalink / raw) To: dev; +Cc: Keith Wiles, Hongzhi Guo, Morten Brørup, Thomas Monjalon Add a simple unit test for checksum API. Signed-off-by: Olivier Matz <olivier.matz@6wind.com> --- MAINTAINERS | 1 + app/test/autotest_data.py | 6 + app/test/meson.build | 2 + app/test/test_cksum.c | 271 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 280 insertions(+) create mode 100644 app/test/test_cksum.c diff --git a/MAINTAINERS b/MAINTAINERS index 44f3d322ed..9fe7c92eac 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1309,6 +1309,7 @@ Packet processing Network headers M: Olivier Matz <olivier.matz@6wind.com> F: lib/net/ +F: app/test/test_cksum.c Packet CRC M: Jasvinder Singh <jasvinder.singh@intel.com> diff --git a/app/test/autotest_data.py b/app/test/autotest_data.py index 097638941f..2871ed8994 100644 --- a/app/test/autotest_data.py +++ b/app/test/autotest_data.py @@ -585,6 +585,12 @@ "Func": default_autotest, "Report": None, }, + { + "Name": "Checksum autotest", + "Command": "cksum_autotest", + "Func": default_autotest, + "Report": None, + }, # #Please always keep all dump tests at the end and together! # diff --git a/app/test/meson.build b/app/test/meson.build index 08c82d3d23..28d8a9a111 100644 --- a/app/test/meson.build +++ b/app/test/meson.build @@ -17,6 +17,7 @@ test_sources = files( 'test_bitmap.c', 'test_bpf.c', 'test_byteorder.c', + 'test_cksum.c', 'test_cmdline.c', 'test_cmdline_cirbuf.c', 'test_cmdline_etheraddr.c', @@ -189,6 +190,7 @@ fast_tests = [ ['atomic_autotest', false], ['bitops_autotest', true], ['byteorder_autotest', true], + ['cksum_autotest', true], ['cmdline_autotest', true], ['common_autotest', true], ['cpuflags_autotest', true], diff --git a/app/test/test_cksum.c b/app/test/test_cksum.c new file mode 100644 index 0000000000..cd983d7c01 --- /dev/null +++ b/app/test/test_cksum.c @@ -0,0 +1,271 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2021 6WIND S.A. + */ + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> + +#include <rte_net.h> +#include <rte_mbuf.h> +#include <rte_ip.h> + +#include "test.h" + +#define MEMPOOL_CACHE_SIZE 0 +#define MBUF_DATA_SIZE 256 +#define NB_MBUF 128 + +/* + * Test L3/L4 checksum API. + */ + +#define GOTO_FAIL(str, ...) do { \ + printf("cksum test FAILED (l.%d): <" str ">\n", \ + __LINE__, ##__VA_ARGS__); \ + goto fail; \ + } while (0) + +/* generated in scapy with Ether()/IP()/TCP())) */ +static const char test_cksum_ipv4_tcp[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00, + 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06, + 0x7c, 0xcd, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, + 0x00, 0x01, 0x00, 0x14, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02, + 0x20, 0x00, 0x91, 0x7c, 0x00, 0x00, + +}; + +/* generated in scapy with Ether()/IPv6()/TCP()) */ +static const char test_cksum_ipv6_tcp[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x14, 0x06, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x14, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x50, 0x02, 0x20, 0x00, 0x8f, 0x7d, + 0x00, 0x00, +}; + +/* generated in scapy with Ether()/IP()/UDP()/Raw('x')) */ +static const char test_cksum_ipv4_udp[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00, + 0x00, 0x1d, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11, + 0x7c, 0xcd, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, + 0x00, 0x01, 0x00, 0x35, 0x00, 0x35, 0x00, 0x09, + 0x89, 0x6f, 0x78, +}; + +/* generated in scapy with Ether()/IPv6()/UDP()/Raw('x')) */ +static const char test_cksum_ipv6_udp[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x86, 0xdd, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x11, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x35, + 0x00, 0x35, 0x00, 0x09, 0x87, 0x70, 0x78, +}; + +/* generated in scapy with Ether()/IP(options='\x00')/UDP()/Raw('x')) */ +static const char test_cksum_ipv4_opts_udp[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x46, 0x00, + 0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11, + 0x7b, 0xc9, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x35, 0x00, 0x09, 0x89, 0x6f, 0x78, +}; + +/* test l3/l4 checksum api */ +static int +test_l4_cksum(struct rte_mempool *pktmbuf_pool, const char *pktdata, size_t len) +{ + struct rte_net_hdr_lens hdr_lens; + struct rte_mbuf *m = NULL; + uint32_t packet_type; + uint16_t prev_cksum; + void *l3_hdr; + void *l4_hdr; + uint32_t l3; + uint32_t l4; + char *data; + + m = rte_pktmbuf_alloc(pktmbuf_pool); + if (m == NULL) + GOTO_FAIL("Cannot allocate mbuf"); + + data = rte_pktmbuf_append(m, len); + if (data == NULL) + GOTO_FAIL("Cannot append data"); + + memcpy(data, pktdata, len); + + packet_type = rte_net_get_ptype(m, &hdr_lens, RTE_PTYPE_ALL_MASK); + l3 = packet_type & RTE_PTYPE_L3_MASK; + l4 = packet_type & RTE_PTYPE_L4_MASK; + + l3_hdr = rte_pktmbuf_mtod_offset(m, void *, hdr_lens.l2_len); + l4_hdr = rte_pktmbuf_mtod_offset(m, void *, + hdr_lens.l2_len + hdr_lens.l3_len); + + if (l3 == RTE_PTYPE_L3_IPV4 || l3 == RTE_PTYPE_L3_IPV4_EXT) { + struct rte_ipv4_hdr *ip = l3_hdr; + + /* verify IPv4 checksum */ + if (rte_ipv4_cksum(l3_hdr) != 0) + GOTO_FAIL("invalid IPv4 checksum verification"); + + /* verify bad IPv4 checksum */ + ip->hdr_checksum++; + if (rte_ipv4_cksum(l3_hdr) == 0) + GOTO_FAIL("invalid IPv4 bad checksum verification"); + ip->hdr_checksum--; + + /* recalculate IPv4 checksum */ + prev_cksum = ip->hdr_checksum; + ip->hdr_checksum = 0; + ip->hdr_checksum = rte_ipv4_cksum(ip); + if (ip->hdr_checksum != prev_cksum) + GOTO_FAIL("invalid IPv4 checksum calculation"); + + /* verify L4 checksum */ + if (rte_ipv4_udptcp_cksum_verify(l3_hdr, l4_hdr) != 0) + GOTO_FAIL("invalid L4 checksum verification"); + + if (l4 == RTE_PTYPE_L4_TCP) { + struct rte_tcp_hdr *tcp = l4_hdr; + + /* verify bad TCP checksum */ + tcp->cksum++; + if (rte_ipv4_udptcp_cksum_verify(l3_hdr, l4_hdr) == 0) + GOTO_FAIL("invalid bad TCP checksum verification"); + tcp->cksum--; + + /* recalculate TCP checksum */ + prev_cksum = tcp->cksum; + tcp->cksum = 0; + tcp->cksum = rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); + if (tcp->cksum != prev_cksum) + GOTO_FAIL("invalid TCP checksum calculation"); + + } else if (l4 == RTE_PTYPE_L4_UDP) { + struct rte_udp_hdr *udp = l4_hdr; + + /* verify bad UDP checksum */ + udp->dgram_cksum++; + if (rte_ipv4_udptcp_cksum_verify(l3_hdr, l4_hdr) == 0) + GOTO_FAIL("invalid bad UDP checksum verification"); + udp->dgram_cksum--; + + /* recalculate UDP checksum */ + prev_cksum = udp->dgram_cksum; + udp->dgram_cksum = 0; + udp->dgram_cksum = rte_ipv4_udptcp_cksum(l3_hdr, + l4_hdr); + if (udp->dgram_cksum != prev_cksum) + GOTO_FAIL("invalid TCP checksum calculation"); + } + } else if (l3 == RTE_PTYPE_L3_IPV6 || l3 == RTE_PTYPE_L3_IPV6_EXT) { + if (rte_ipv6_udptcp_cksum_verify(l3_hdr, l4_hdr) != 0) + GOTO_FAIL("invalid L4 checksum verification"); + + if (l4 == RTE_PTYPE_L4_TCP) { + struct rte_tcp_hdr *tcp = l4_hdr; + + /* verify bad TCP checksum */ + tcp->cksum++; + if (rte_ipv6_udptcp_cksum_verify(l3_hdr, l4_hdr) == 0) + GOTO_FAIL("invalid bad TCP checksum verification"); + tcp->cksum--; + + /* recalculate TCP checksum */ + prev_cksum = tcp->cksum; + tcp->cksum = 0; + tcp->cksum = rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); + if (tcp->cksum != prev_cksum) + GOTO_FAIL("invalid TCP checksum calculation"); + + } else if (l4 == RTE_PTYPE_L4_UDP) { + struct rte_udp_hdr *udp = l4_hdr; + + /* verify bad UDP checksum */ + udp->dgram_cksum++; + if (rte_ipv6_udptcp_cksum_verify(l3_hdr, l4_hdr) == 0) + GOTO_FAIL("invalid bad UDP checksum verification"); + udp->dgram_cksum--; + + /* recalculate UDP checksum */ + prev_cksum = udp->dgram_cksum; + udp->dgram_cksum = 0; + udp->dgram_cksum = rte_ipv6_udptcp_cksum(l3_hdr, + l4_hdr); + if (udp->dgram_cksum != prev_cksum) + GOTO_FAIL("invalid TCP checksum calculation"); + } + } + + rte_pktmbuf_free(m); + + return 0; + +fail: + if (m) + rte_pktmbuf_free(m); + + return -1; +} + +static int +test_cksum(void) +{ + struct rte_mempool *pktmbuf_pool = NULL; + + /* create pktmbuf pool if it does not exist */ + pktmbuf_pool = rte_pktmbuf_pool_create("test_cksum_mbuf_pool", + NB_MBUF, MEMPOOL_CACHE_SIZE, 0, MBUF_DATA_SIZE, + SOCKET_ID_ANY); + + if (pktmbuf_pool == NULL) + GOTO_FAIL("cannot allocate mbuf pool"); + + if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv4_tcp, + sizeof(test_cksum_ipv4_tcp)) < 0) + GOTO_FAIL("checksum error on ipv4_tcp"); + + if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv6_tcp, + sizeof(test_cksum_ipv6_tcp)) < 0) + GOTO_FAIL("checksum error on ipv6_tcp"); + + if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv4_udp, + sizeof(test_cksum_ipv4_udp)) < 0) + GOTO_FAIL("checksum error on ipv4_udp"); + + if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv6_udp, + sizeof(test_cksum_ipv6_udp)) < 0) + GOTO_FAIL("checksum error on ipv6_udp"); + + if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv4_opts_udp, + sizeof(test_cksum_ipv4_opts_udp)) < 0) + GOTO_FAIL("checksum error on ipv4_opts_udp"); + + rte_mempool_free(pktmbuf_pool); + + return 0; + +fail: + rte_mempool_free(pktmbuf_pool); + + return -1; +} +#undef GOTO_FAIL + +REGISTER_TEST_COMMAND(cksum_autotest, test_cksum); -- 2.29.2 ^ permalink raw reply [flat|nested] 28+ messages in thread
* [dpdk-dev] [PATCH v2 0/4] net/tap: fix Rx cksum 2021-04-27 13:57 [dpdk-dev] [PATCH 0/4] net/tap: fix Rx cksum Olivier Matz ` (3 preceding siblings ...) 2021-04-27 13:57 ` [dpdk-dev] [PATCH 4/4] test/cksum: new test for L3/L4 checksum API Olivier Matz @ 2021-06-30 13:51 ` Olivier Matz 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 1/4] net/tap: fix Rx cksum flags on IP options packets Olivier Matz ` (4 more replies) 4 siblings, 5 replies; 28+ messages in thread From: Olivier Matz @ 2021-06-30 13:51 UTC (permalink / raw) To: dev; +Cc: guohongzhi1, keith.wiles, mb, thomas, ferruh.yigit, andrew.rybchenko This patchset fixes the Rx checksum flags in net/tap driver. The first two patches are the effective fixes. The last 2 patches introduce a new checksum API to verify a L4 checksum and its unt test, in order to simplify the net/tap code, or any other code that has the same needs. v2: * clarify why RTE_PTYPE_L3_IPV4_EXT_UNKNOWN cannot happen in tap_verify_csum() (patch 1) * align style of rte_ipv6_udptcp_cksum_verify() to rte_ipv4_udptcp_cksum_verify() (patch 3) * clarify comment above rte_ipv4_udptcp_cksum_verify() and rte_ipv6_udptcp_cksum_verify() (patch 3) Olivier Matz (4): net/tap: fix Rx cksum flags on IP options packets net/tap: fix Rx cksum flags on TCP packets net: introduce functions to verify L4 checksums test/cksum: new test for L3/L4 checksum API MAINTAINERS | 1 + app/test/autotest_data.py | 6 + app/test/meson.build | 2 + app/test/test_cksum.c | 271 ++++++++++++++++++++++++++++++++++ drivers/net/tap/rte_eth_tap.c | 23 ++- lib/net/rte_ip.h | 127 +++++++++++++--- 6 files changed, 398 insertions(+), 32 deletions(-) create mode 100644 app/test/test_cksum.c -- 2.29.2 ^ permalink raw reply [flat|nested] 28+ messages in thread
* [dpdk-dev] [PATCH v2 1/4] net/tap: fix Rx cksum flags on IP options packets 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 0/4] net/tap: fix Rx cksum Olivier Matz @ 2021-06-30 13:51 ` Olivier Matz 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 2/4] net/tap: fix Rx cksum flags on TCP packets Olivier Matz ` (3 subsequent siblings) 4 siblings, 0 replies; 28+ messages in thread From: Olivier Matz @ 2021-06-30 13:51 UTC (permalink / raw) To: dev Cc: guohongzhi1, keith.wiles, mb, thomas, ferruh.yigit, andrew.rybchenko, stable When packet type is IPV4_EXT, the checksum is always marked as good in the mbuf offload flags. Since we know the header lengths, we can easily call rte_ipv4_udptcp_cksum() in this case too. Fixes: 8ae3023387e9 ("net/tap: add Rx/Tx checksum offload support") Cc: stable@dpdk.org Signed-off-by: Olivier Matz <olivier.matz@6wind.com> --- drivers/net/tap/rte_eth_tap.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c index 5735988e7c..5513cfd2d7 100644 --- a/drivers/net/tap/rte_eth_tap.c +++ b/drivers/net/tap/rte_eth_tap.c @@ -342,7 +342,11 @@ tap_verify_csum(struct rte_mbuf *mbuf) rte_pktmbuf_data_len(mbuf)) return; } else { - /* IPv6 extensions are not supported */ + /* - RTE_PTYPE_L3_IPV4_EXT_UNKNOWN cannot happen because + * mbuf->packet_type is filled by rte_net_get_ptype() which + * never returns this value. + * - IPv6 extensions are not supported. + */ return; } if (l4 == RTE_PTYPE_L4_UDP || l4 == RTE_PTYPE_L4_TCP) { @@ -350,7 +354,7 @@ tap_verify_csum(struct rte_mbuf *mbuf) /* Don't verify checksum for multi-segment packets. */ if (mbuf->nb_segs > 1) return; - if (l3 == RTE_PTYPE_L3_IPV4) { + if (l3 == RTE_PTYPE_L3_IPV4 || l3 == RTE_PTYPE_L3_IPV4_EXT) { if (l4 == RTE_PTYPE_L4_UDP) { udp_hdr = (struct rte_udp_hdr *)l4_hdr; if (udp_hdr->dgram_cksum == 0) { @@ -364,7 +368,7 @@ tap_verify_csum(struct rte_mbuf *mbuf) } } cksum = ~rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); - } else if (l3 == RTE_PTYPE_L3_IPV6) { + } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ cksum = ~rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); } mbuf->ol_flags |= cksum ? -- 2.29.2 ^ permalink raw reply [flat|nested] 28+ messages in thread
* [dpdk-dev] [PATCH v2 2/4] net/tap: fix Rx cksum flags on TCP packets 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 0/4] net/tap: fix Rx cksum Olivier Matz 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 1/4] net/tap: fix Rx cksum flags on IP options packets Olivier Matz @ 2021-06-30 13:51 ` Olivier Matz 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 3/4] net: introduce functions to verify L4 checksums Olivier Matz ` (2 subsequent siblings) 4 siblings, 0 replies; 28+ messages in thread From: Olivier Matz @ 2021-06-30 13:51 UTC (permalink / raw) To: dev Cc: guohongzhi1, keith.wiles, mb, thomas, ferruh.yigit, andrew.rybchenko, stable Since commit d5df2ae0428a ("net: fix unneeded replacement of TCP checksum 0"), the functions rte_ipv4_udptcp_cksum() or rte_ipv6_udptcp_cksum() can return either 0x0000 or 0xffff when used to verify a packet containing a valid checksum. This new behavior broke the checksum verification in tap driver for TCP packets: these packets are marked with PKT_RX_L4_CKSUM_BAD. Fix this by checking the 2 possible values. A next commit will introduce a checksum verification helper to simplify this a bit. Fixes: d5df2ae0428a ("net: fix unneeded replacement of TCP checksum 0") Cc: stable@dpdk.org Signed-off-by: Olivier Matz <olivier.matz@6wind.com> Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru> --- drivers/net/tap/rte_eth_tap.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c index 5513cfd2d7..5429f611c1 100644 --- a/drivers/net/tap/rte_eth_tap.c +++ b/drivers/net/tap/rte_eth_tap.c @@ -350,6 +350,8 @@ tap_verify_csum(struct rte_mbuf *mbuf) return; } if (l4 == RTE_PTYPE_L4_UDP || l4 == RTE_PTYPE_L4_TCP) { + int cksum_ok; + l4_hdr = rte_pktmbuf_mtod_offset(mbuf, void *, l2_len + l3_len); /* Don't verify checksum for multi-segment packets. */ if (mbuf->nb_segs > 1) @@ -367,13 +369,13 @@ tap_verify_csum(struct rte_mbuf *mbuf) return; } } - cksum = ~rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); + cksum = rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ - cksum = ~rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); + cksum = rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); } - mbuf->ol_flags |= cksum ? - PKT_RX_L4_CKSUM_BAD : - PKT_RX_L4_CKSUM_GOOD; + cksum_ok = (cksum == 0) || (cksum == 0xffff); + mbuf->ol_flags |= cksum_ok ? + PKT_RX_L4_CKSUM_GOOD : PKT_RX_L4_CKSUM_BAD; } } -- 2.29.2 ^ permalink raw reply [flat|nested] 28+ messages in thread
* [dpdk-dev] [PATCH v2 3/4] net: introduce functions to verify L4 checksums 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 0/4] net/tap: fix Rx cksum Olivier Matz 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 1/4] net/tap: fix Rx cksum flags on IP options packets Olivier Matz 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 2/4] net/tap: fix Rx cksum flags on TCP packets Olivier Matz @ 2021-06-30 13:51 ` Olivier Matz 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 4/4] test/cksum: new test for L3/L4 checksum API Olivier Matz 2021-07-01 9:28 ` [dpdk-dev] [PATCH v2 0/4] net/tap: fix Rx cksum Andrew Rybchenko 4 siblings, 0 replies; 28+ messages in thread From: Olivier Matz @ 2021-06-30 13:51 UTC (permalink / raw) To: dev; +Cc: guohongzhi1, keith.wiles, mb, thomas, ferruh.yigit, andrew.rybchenko Since commit d5df2ae0428a ("net: fix unneeded replacement of TCP checksum 0"), the functions rte_ipv4_udptcp_cksum() and rte_ipv6_udptcp_cksum() can return either 0x0000 or 0xffff when used to verify a packet containing a valid checksum. Since these functions should be used to calculate the checksum to set in a packet, introduce 2 new helpers for checksum verification. They return 0 if the checksum is valid in the packet. Use this new helper in net/tap driver. Signed-off-by: Olivier Matz <olivier.matz@6wind.com> Acked-by: Morten Brørup <mb@smartsharesystems.com> --- drivers/net/tap/rte_eth_tap.c | 7 +- lib/net/rte_ip.h | 127 +++++++++++++++++++++++++++------- 2 files changed, 107 insertions(+), 27 deletions(-) diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c index 5429f611c1..2229eef059 100644 --- a/drivers/net/tap/rte_eth_tap.c +++ b/drivers/net/tap/rte_eth_tap.c @@ -369,11 +369,12 @@ tap_verify_csum(struct rte_mbuf *mbuf) return; } } - cksum = rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); + cksum_ok = !rte_ipv4_udptcp_cksum_verify(l3_hdr, + l4_hdr); } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */ - cksum = rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); + cksum_ok = !rte_ipv6_udptcp_cksum_verify(l3_hdr, + l4_hdr); } - cksum_ok = (cksum == 0) || (cksum == 0xffff); mbuf->ol_flags |= cksum_ok ? PKT_RX_L4_CKSUM_GOOD : PKT_RX_L4_CKSUM_BAD; } diff --git a/lib/net/rte_ip.h b/lib/net/rte_ip.h index 4b728969c1..05948b69b7 100644 --- a/lib/net/rte_ip.h +++ b/lib/net/rte_ip.h @@ -344,20 +344,10 @@ rte_ipv4_phdr_cksum(const struct rte_ipv4_hdr *ipv4_hdr, uint64_t ol_flags) } /** - * Process the IPv4 UDP or TCP checksum. - * - * The IP and layer 4 checksum must be set to 0 in the packet by - * the caller. - * - * @param ipv4_hdr - * The pointer to the contiguous IPv4 header. - * @param l4_hdr - * The pointer to the beginning of the L4 header. - * @return - * The complemented checksum to set in the IP packet. + * @internal Calculate the non-complemented IPv4 L4 checksum */ static inline uint16_t -rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) +__rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) { uint32_t cksum; uint32_t l3_len, l4_len; @@ -374,16 +364,65 @@ rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) cksum += rte_ipv4_phdr_cksum(ipv4_hdr, 0); cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); - cksum = (~cksum) & 0xffff; + + return (uint16_t)cksum; +} + +/** + * Process the IPv4 UDP or TCP checksum. + * + * The IP and layer 4 checksum must be set to 0 in the packet by + * the caller. + * + * @param ipv4_hdr + * The pointer to the contiguous IPv4 header. + * @param l4_hdr + * The pointer to the beginning of the L4 header. + * @return + * The complemented checksum to set in the IP packet. + */ +static inline uint16_t +rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) +{ + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); + + cksum = ~cksum; + /* - * Per RFC 768:If the computed checksum is zero for UDP, + * Per RFC 768: If the computed checksum is zero for UDP, * it is transmitted as all ones * (the equivalent in one's complement arithmetic). */ if (cksum == 0 && ipv4_hdr->next_proto_id == IPPROTO_UDP) cksum = 0xffff; - return (uint16_t)cksum; + return cksum; +} + +/** + * Validate the IPv4 UDP or TCP checksum. + * + * In case of UDP, the caller must first check if udp_hdr->dgram_cksum is 0 + * (i.e. no checksum). + * + * @param ipv4_hdr + * The pointer to the contiguous IPv4 header. + * @param l4_hdr + * The pointer to the beginning of the L4 header. + * @return + * Return 0 if the checksum is correct, else -1. + */ +__rte_experimental +static inline int +rte_ipv4_udptcp_cksum_verify(const struct rte_ipv4_hdr *ipv4_hdr, + const void *l4_hdr) +{ + uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr); + + if (cksum != 0xffff) + return -1; + + return 0; } /** @@ -448,6 +487,25 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags) return __rte_raw_cksum_reduce(sum); } +/** + * @internal Calculate the non-complemented IPv4 L4 checksum + */ +static inline uint16_t +__rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) +{ + uint32_t cksum; + uint32_t l4_len; + + l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len); + + cksum = rte_raw_cksum(l4_hdr, l4_len); + cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0); + + cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); + + return (uint16_t)cksum; +} + /** * Process the IPv6 UDP or TCP checksum. * @@ -464,16 +522,10 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags) static inline uint16_t rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) { - uint32_t cksum; - uint32_t l4_len; + uint16_t cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr); - l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len); - - cksum = rte_raw_cksum(l4_hdr, l4_len); - cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0); + cksum = ~cksum; - cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); - cksum = (~cksum) & 0xffff; /* * Per RFC 768: If the computed checksum is zero for UDP, * it is transmitted as all ones @@ -482,7 +534,34 @@ rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr) if (cksum == 0 && ipv6_hdr->proto == IPPROTO_UDP) cksum = 0xffff; - return (uint16_t)cksum; + return cksum; +} + +/** + * Validate the IPv6 UDP or TCP checksum. + * + * In case of UDP, the caller must first check if udp_hdr->dgram_cksum is 0: + * this is either invalid or means no checksum in some situations. See 8.1 + * (Upper-Layer Checksums) in RFC 8200. + * + * @param ipv6_hdr + * The pointer to the contiguous IPv6 header. + * @param l4_hdr + * The pointer to the beginning of the L4 header. + * @return + * Return 0 if the checksum is correct, else -1. + */ +__rte_experimental +static inline int +rte_ipv6_udptcp_cksum_verify(const struct rte_ipv6_hdr *ipv6_hdr, + const void *l4_hdr) +{ + uint16_t cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr); + + if (cksum != 0xffff) + return -1; + + return 0; } /** IPv6 fragment extension header. */ -- 2.29.2 ^ permalink raw reply [flat|nested] 28+ messages in thread
* [dpdk-dev] [PATCH v2 4/4] test/cksum: new test for L3/L4 checksum API 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 0/4] net/tap: fix Rx cksum Olivier Matz ` (2 preceding siblings ...) 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 3/4] net: introduce functions to verify L4 checksums Olivier Matz @ 2021-06-30 13:51 ` Olivier Matz 2021-07-01 9:28 ` [dpdk-dev] [PATCH v2 0/4] net/tap: fix Rx cksum Andrew Rybchenko 4 siblings, 0 replies; 28+ messages in thread From: Olivier Matz @ 2021-06-30 13:51 UTC (permalink / raw) To: dev; +Cc: guohongzhi1, keith.wiles, mb, thomas, ferruh.yigit, andrew.rybchenko Add a simple unit test for checksum API. Signed-off-by: Olivier Matz <olivier.matz@6wind.com> --- MAINTAINERS | 1 + app/test/autotest_data.py | 6 + app/test/meson.build | 2 + app/test/test_cksum.c | 271 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 280 insertions(+) create mode 100644 app/test/test_cksum.c diff --git a/MAINTAINERS b/MAINTAINERS index 5877a16971..4347555ebc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1314,6 +1314,7 @@ Packet processing Network headers M: Olivier Matz <olivier.matz@6wind.com> F: lib/net/ +F: app/test/test_cksum.c Packet CRC M: Jasvinder Singh <jasvinder.singh@intel.com> diff --git a/app/test/autotest_data.py b/app/test/autotest_data.py index 11f9c8640c..302d6374c1 100644 --- a/app/test/autotest_data.py +++ b/app/test/autotest_data.py @@ -567,6 +567,12 @@ "Func": default_autotest, "Report": None, }, + { + "Name": "Checksum autotest", + "Command": "cksum_autotest", + "Func": default_autotest, + "Report": None, + }, # #Please always keep all dump tests at the end and together! # diff --git a/app/test/meson.build b/app/test/meson.build index 0a5f425578..ef90b16f16 100644 --- a/app/test/meson.build +++ b/app/test/meson.build @@ -17,6 +17,7 @@ test_sources = files( 'test_bitmap.c', 'test_bpf.c', 'test_byteorder.c', + 'test_cksum.c', 'test_cmdline.c', 'test_cmdline_cirbuf.c', 'test_cmdline_etheraddr.c', @@ -188,6 +189,7 @@ fast_tests = [ ['atomic_autotest', false], ['bitops_autotest', true], ['byteorder_autotest', true], + ['cksum_autotest', true], ['cmdline_autotest', true], ['common_autotest', true], ['cpuflags_autotest', true], diff --git a/app/test/test_cksum.c b/app/test/test_cksum.c new file mode 100644 index 0000000000..cd983d7c01 --- /dev/null +++ b/app/test/test_cksum.c @@ -0,0 +1,271 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2021 6WIND S.A. + */ + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> + +#include <rte_net.h> +#include <rte_mbuf.h> +#include <rte_ip.h> + +#include "test.h" + +#define MEMPOOL_CACHE_SIZE 0 +#define MBUF_DATA_SIZE 256 +#define NB_MBUF 128 + +/* + * Test L3/L4 checksum API. + */ + +#define GOTO_FAIL(str, ...) do { \ + printf("cksum test FAILED (l.%d): <" str ">\n", \ + __LINE__, ##__VA_ARGS__); \ + goto fail; \ + } while (0) + +/* generated in scapy with Ether()/IP()/TCP())) */ +static const char test_cksum_ipv4_tcp[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00, + 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06, + 0x7c, 0xcd, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, + 0x00, 0x01, 0x00, 0x14, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02, + 0x20, 0x00, 0x91, 0x7c, 0x00, 0x00, + +}; + +/* generated in scapy with Ether()/IPv6()/TCP()) */ +static const char test_cksum_ipv6_tcp[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x14, 0x06, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x14, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x50, 0x02, 0x20, 0x00, 0x8f, 0x7d, + 0x00, 0x00, +}; + +/* generated in scapy with Ether()/IP()/UDP()/Raw('x')) */ +static const char test_cksum_ipv4_udp[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00, + 0x00, 0x1d, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11, + 0x7c, 0xcd, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, + 0x00, 0x01, 0x00, 0x35, 0x00, 0x35, 0x00, 0x09, + 0x89, 0x6f, 0x78, +}; + +/* generated in scapy with Ether()/IPv6()/UDP()/Raw('x')) */ +static const char test_cksum_ipv6_udp[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x86, 0xdd, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x11, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x35, + 0x00, 0x35, 0x00, 0x09, 0x87, 0x70, 0x78, +}; + +/* generated in scapy with Ether()/IP(options='\x00')/UDP()/Raw('x')) */ +static const char test_cksum_ipv4_opts_udp[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x46, 0x00, + 0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11, + 0x7b, 0xc9, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x35, 0x00, 0x09, 0x89, 0x6f, 0x78, +}; + +/* test l3/l4 checksum api */ +static int +test_l4_cksum(struct rte_mempool *pktmbuf_pool, const char *pktdata, size_t len) +{ + struct rte_net_hdr_lens hdr_lens; + struct rte_mbuf *m = NULL; + uint32_t packet_type; + uint16_t prev_cksum; + void *l3_hdr; + void *l4_hdr; + uint32_t l3; + uint32_t l4; + char *data; + + m = rte_pktmbuf_alloc(pktmbuf_pool); + if (m == NULL) + GOTO_FAIL("Cannot allocate mbuf"); + + data = rte_pktmbuf_append(m, len); + if (data == NULL) + GOTO_FAIL("Cannot append data"); + + memcpy(data, pktdata, len); + + packet_type = rte_net_get_ptype(m, &hdr_lens, RTE_PTYPE_ALL_MASK); + l3 = packet_type & RTE_PTYPE_L3_MASK; + l4 = packet_type & RTE_PTYPE_L4_MASK; + + l3_hdr = rte_pktmbuf_mtod_offset(m, void *, hdr_lens.l2_len); + l4_hdr = rte_pktmbuf_mtod_offset(m, void *, + hdr_lens.l2_len + hdr_lens.l3_len); + + if (l3 == RTE_PTYPE_L3_IPV4 || l3 == RTE_PTYPE_L3_IPV4_EXT) { + struct rte_ipv4_hdr *ip = l3_hdr; + + /* verify IPv4 checksum */ + if (rte_ipv4_cksum(l3_hdr) != 0) + GOTO_FAIL("invalid IPv4 checksum verification"); + + /* verify bad IPv4 checksum */ + ip->hdr_checksum++; + if (rte_ipv4_cksum(l3_hdr) == 0) + GOTO_FAIL("invalid IPv4 bad checksum verification"); + ip->hdr_checksum--; + + /* recalculate IPv4 checksum */ + prev_cksum = ip->hdr_checksum; + ip->hdr_checksum = 0; + ip->hdr_checksum = rte_ipv4_cksum(ip); + if (ip->hdr_checksum != prev_cksum) + GOTO_FAIL("invalid IPv4 checksum calculation"); + + /* verify L4 checksum */ + if (rte_ipv4_udptcp_cksum_verify(l3_hdr, l4_hdr) != 0) + GOTO_FAIL("invalid L4 checksum verification"); + + if (l4 == RTE_PTYPE_L4_TCP) { + struct rte_tcp_hdr *tcp = l4_hdr; + + /* verify bad TCP checksum */ + tcp->cksum++; + if (rte_ipv4_udptcp_cksum_verify(l3_hdr, l4_hdr) == 0) + GOTO_FAIL("invalid bad TCP checksum verification"); + tcp->cksum--; + + /* recalculate TCP checksum */ + prev_cksum = tcp->cksum; + tcp->cksum = 0; + tcp->cksum = rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); + if (tcp->cksum != prev_cksum) + GOTO_FAIL("invalid TCP checksum calculation"); + + } else if (l4 == RTE_PTYPE_L4_UDP) { + struct rte_udp_hdr *udp = l4_hdr; + + /* verify bad UDP checksum */ + udp->dgram_cksum++; + if (rte_ipv4_udptcp_cksum_verify(l3_hdr, l4_hdr) == 0) + GOTO_FAIL("invalid bad UDP checksum verification"); + udp->dgram_cksum--; + + /* recalculate UDP checksum */ + prev_cksum = udp->dgram_cksum; + udp->dgram_cksum = 0; + udp->dgram_cksum = rte_ipv4_udptcp_cksum(l3_hdr, + l4_hdr); + if (udp->dgram_cksum != prev_cksum) + GOTO_FAIL("invalid TCP checksum calculation"); + } + } else if (l3 == RTE_PTYPE_L3_IPV6 || l3 == RTE_PTYPE_L3_IPV6_EXT) { + if (rte_ipv6_udptcp_cksum_verify(l3_hdr, l4_hdr) != 0) + GOTO_FAIL("invalid L4 checksum verification"); + + if (l4 == RTE_PTYPE_L4_TCP) { + struct rte_tcp_hdr *tcp = l4_hdr; + + /* verify bad TCP checksum */ + tcp->cksum++; + if (rte_ipv6_udptcp_cksum_verify(l3_hdr, l4_hdr) == 0) + GOTO_FAIL("invalid bad TCP checksum verification"); + tcp->cksum--; + + /* recalculate TCP checksum */ + prev_cksum = tcp->cksum; + tcp->cksum = 0; + tcp->cksum = rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); + if (tcp->cksum != prev_cksum) + GOTO_FAIL("invalid TCP checksum calculation"); + + } else if (l4 == RTE_PTYPE_L4_UDP) { + struct rte_udp_hdr *udp = l4_hdr; + + /* verify bad UDP checksum */ + udp->dgram_cksum++; + if (rte_ipv6_udptcp_cksum_verify(l3_hdr, l4_hdr) == 0) + GOTO_FAIL("invalid bad UDP checksum verification"); + udp->dgram_cksum--; + + /* recalculate UDP checksum */ + prev_cksum = udp->dgram_cksum; + udp->dgram_cksum = 0; + udp->dgram_cksum = rte_ipv6_udptcp_cksum(l3_hdr, + l4_hdr); + if (udp->dgram_cksum != prev_cksum) + GOTO_FAIL("invalid TCP checksum calculation"); + } + } + + rte_pktmbuf_free(m); + + return 0; + +fail: + if (m) + rte_pktmbuf_free(m); + + return -1; +} + +static int +test_cksum(void) +{ + struct rte_mempool *pktmbuf_pool = NULL; + + /* create pktmbuf pool if it does not exist */ + pktmbuf_pool = rte_pktmbuf_pool_create("test_cksum_mbuf_pool", + NB_MBUF, MEMPOOL_CACHE_SIZE, 0, MBUF_DATA_SIZE, + SOCKET_ID_ANY); + + if (pktmbuf_pool == NULL) + GOTO_FAIL("cannot allocate mbuf pool"); + + if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv4_tcp, + sizeof(test_cksum_ipv4_tcp)) < 0) + GOTO_FAIL("checksum error on ipv4_tcp"); + + if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv6_tcp, + sizeof(test_cksum_ipv6_tcp)) < 0) + GOTO_FAIL("checksum error on ipv6_tcp"); + + if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv4_udp, + sizeof(test_cksum_ipv4_udp)) < 0) + GOTO_FAIL("checksum error on ipv4_udp"); + + if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv6_udp, + sizeof(test_cksum_ipv6_udp)) < 0) + GOTO_FAIL("checksum error on ipv6_udp"); + + if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv4_opts_udp, + sizeof(test_cksum_ipv4_opts_udp)) < 0) + GOTO_FAIL("checksum error on ipv4_opts_udp"); + + rte_mempool_free(pktmbuf_pool); + + return 0; + +fail: + rte_mempool_free(pktmbuf_pool); + + return -1; +} +#undef GOTO_FAIL + +REGISTER_TEST_COMMAND(cksum_autotest, test_cksum); -- 2.29.2 ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [dpdk-dev] [PATCH v2 0/4] net/tap: fix Rx cksum 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 0/4] net/tap: fix Rx cksum Olivier Matz ` (3 preceding siblings ...) 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 4/4] test/cksum: new test for L3/L4 checksum API Olivier Matz @ 2021-07-01 9:28 ` Andrew Rybchenko 4 siblings, 0 replies; 28+ messages in thread From: Andrew Rybchenko @ 2021-07-01 9:28 UTC (permalink / raw) To: Olivier Matz, dev; +Cc: guohongzhi1, keith.wiles, mb, thomas, ferruh.yigit On 6/30/21 4:51 PM, Olivier Matz wrote: > This patchset fixes the Rx checksum flags in net/tap > driver. The first two patches are the effective fixes. > > The last 2 patches introduce a new checksum API to > verify a L4 checksum and its unt test, in order to > simplify the net/tap code, or any other code that has > the same needs. > > v2: > > * clarify why RTE_PTYPE_L3_IPV4_EXT_UNKNOWN cannot happen in > tap_verify_csum() (patch 1) > * align style of rte_ipv6_udptcp_cksum_verify() to > rte_ipv4_udptcp_cksum_verify() (patch 3) > * clarify comment above rte_ipv4_udptcp_cksum_verify() and > rte_ipv6_udptcp_cksum_verify() (patch 3) > > > Olivier Matz (4): > net/tap: fix Rx cksum flags on IP options packets > net/tap: fix Rx cksum flags on TCP packets > net: introduce functions to verify L4 checksums > test/cksum: new test for L3/L4 checksum API > > MAINTAINERS | 1 + > app/test/autotest_data.py | 6 + > app/test/meson.build | 2 + > app/test/test_cksum.c | 271 ++++++++++++++++++++++++++++++++++ > drivers/net/tap/rte_eth_tap.c | 23 ++- > lib/net/rte_ip.h | 127 +++++++++++++--- > 6 files changed, 398 insertions(+), 32 deletions(-) > create mode 100644 app/test/test_cksum.c > Series-reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru> Applied, thanks. ^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2021-07-01 9:28 UTC | newest] Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-04-27 13:57 [dpdk-dev] [PATCH 0/4] net/tap: fix Rx cksum Olivier Matz 2021-04-27 13:57 ` [dpdk-dev] [PATCH 1/4] net/tap: fix Rx cksum flags on IP options packets Olivier Matz 2021-04-30 14:48 ` [dpdk-dev] [dpdk-stable] " Ferruh Yigit 2021-06-08 10:13 ` Andrew Rybchenko 2021-06-08 12:29 ` Olivier Matz 2021-06-08 12:34 ` Andrew Rybchenko 2021-06-08 12:49 ` Olivier Matz 2021-06-08 13:57 ` Andrew Rybchenko 2021-06-08 14:30 ` Olivier Matz 2021-04-27 13:57 ` [dpdk-dev] [PATCH 2/4] net/tap: fix Rx cksum flags on TCP packets Olivier Matz 2021-06-08 10:18 ` Andrew Rybchenko 2021-04-27 13:57 ` [dpdk-dev] [PATCH 3/4] net: introduce functions to verify L4 checksums Olivier Matz 2021-04-27 15:02 ` Morten Brørup 2021-04-27 15:07 ` Morten Brørup 2021-04-28 12:21 ` Olivier Matz 2021-04-28 12:42 ` Morten Brørup 2021-04-30 15:42 ` Ferruh Yigit 2021-06-08 10:23 ` Andrew Rybchenko 2021-06-08 12:29 ` Olivier Matz 2021-06-08 12:39 ` Andrew Rybchenko 2021-06-25 15:38 ` Ferruh Yigit 2021-04-27 13:57 ` [dpdk-dev] [PATCH 4/4] test/cksum: new test for L3/L4 checksum API Olivier Matz 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 0/4] net/tap: fix Rx cksum Olivier Matz 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 1/4] net/tap: fix Rx cksum flags on IP options packets Olivier Matz 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 2/4] net/tap: fix Rx cksum flags on TCP packets Olivier Matz 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 3/4] net: introduce functions to verify L4 checksums Olivier Matz 2021-06-30 13:51 ` [dpdk-dev] [PATCH v2 4/4] test/cksum: new test for L3/L4 checksum API Olivier Matz 2021-07-01 9:28 ` [dpdk-dev] [PATCH v2 0/4] net/tap: fix Rx cksum Andrew Rybchenko
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).