[PATCH] app/testpmd: fix L4 protocol retrieval from L3 header
huangdengdui
huangdengdui at huawei.com
Tue Sep 16 08:34:25 CEST 2025
On 2025/9/16 0:39, Stephen Hemminger wrote:
> On Sat, 30 Aug 2025 09:29:13 +0800
> Dengdui Huang <huangdengdui at huawei.com> wrote:
>
>> Currently, when retrieving the L4 protocol from the L3 header,
>> the case of IPv6 with extension headers is not handled correctly.
>> This patch fixes it.
>>
>> Fixes: 76730c7b9b5a ("app/testpmd: use packet type parsing API")
>> Cc: stable at dpdk.org
>>
>> Signed-off-by: Dengdui Huang <huangdengdui at huawei.com>
>> ---
>> app/test-pmd/csumonly.c | 39 ++++++++++++++++-----------------------
>> 1 file changed, 16 insertions(+), 23 deletions(-)
>>
>> diff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c
>> index d355dbd8c0..a6e872e5a4 100644
>> --- a/app/test-pmd/csumonly.c
>> +++ b/app/test-pmd/csumonly.c
>> @@ -525,20 +525,8 @@ get_tunnel_ol_flags_by_ptype(uint32_t ptype)
>> }
>> }
>>
>> -static void
>> -parse_inner_l4_proto(void *outer_l3_hdr,
>> - struct testpmd_offload_info *info)
>> -{
>> - struct rte_ipv4_hdr *ipv4_hdr = outer_l3_hdr;
>> - struct rte_ipv6_hdr *ipv6_hdr = outer_l3_hdr;
>> - if (info->ethertype == _htons(RTE_ETHER_TYPE_IPV4))
>> - info->l4_proto = ipv4_hdr->next_proto_id;
>> - else
>> - info->l4_proto = ipv6_hdr->proto;
>> -}
>> -
>> static uint8_t
>> -parse_l4_proto(const struct rte_mbuf *m, uint32_t off, uint32_t ptype)
>> +parse_l4_proto(const struct rte_mbuf *m, uint32_t off, uint32_t ptype, bool parse_inner)
>> {
>> int frag = 0, ret;
>>
>> @@ -557,16 +545,19 @@ parse_l4_proto(const struct rte_mbuf *m, uint32_t off, uint32_t ptype)
>> if (unlikely(ip6h == NULL))
>> return 0;
>>
>> - if ((ptype & RTE_PTYPE_INNER_L3_MASK) ==
>> - RTE_PTYPE_INNER_L3_IPV6_EXT) {
>> - ret = rte_net_skip_ip6_ext(ip6h->proto, m, &off, &frag);
>> - if (ret < 0)
>> - return 0;
>> - return ret;
>> - }
>> + if (!parse_inner && (ptype & RTE_PTYPE_L3_MASK) != RTE_PTYPE_L3_IPV6_EXT)
>> + return ip6h->proto;
>> +
>> + if (parse_inner && (ptype & RTE_PTYPE_INNER_L3_MASK) != RTE_PTYPE_INNER_L3_IPV6_EXT)
>> + return ip6h->proto;
>>
>> - return ip6h->proto;
>> + off += sizeof(struct rte_ipv6_hdr);
>> + ret = rte_net_skip_ip6_ext(ip6h->proto, m, &off, &frag);
>> + if (ret < 0)
>> + return 0;
>> + return ret;
>> }
>> +
>> return 0;
>> }
>>
>> @@ -705,7 +696,7 @@ pkt_burst_checksum_forward(struct fwd_stream *fs)
>> info.l4_len = hdr_lens.l4_len;
>> info.ethertype = get_ethertype_by_ptype(eth_hdr,
>> ptype & RTE_PTYPE_L3_MASK);
>> - info.l4_proto = parse_l4_proto(m, info.l2_len, ptype);
>> + info.l4_proto = parse_l4_proto(m, info.l2_len, ptype, false);
>
>
> Setting parse_inner to false would cause l4_proto to be set to the extension
> header type (rather than the real L4 protocol). Was this change intentional?
> Looks like it would cause checksum to be computed incorrectly for simple
> case of IPV6 with extension header and TCP.
>
Setting `parse_inner` to `false` does not result in `l4_proto` being assigned as an extended header type.
The purpose of `parse_inner` is solely to indicate whether the `parse_l4_proto` function is handling the outer packet header or the inner packet header.
Perhaps renaming the variable to `is_inner` would be more appropriate.
More information about the dev
mailing list