Skip to contentSkip to conversation

rte_ipv6_hdr.version is encoded in the wrong byte on little-endian platforms

DPDK/core Bug 1679 [email protected] 1 participant 1 message Mar 24, 2025

lore
Share & tools
lore
#0 lore raw

https://bugs.dpdk.org/show_bug.cgi?id=1679

            Bug ID: 1679
           Summary: rte_ipv6_hdr.version is encoded in the wrong byte on
                    little-endian platforms
           Product: DPDK
           Version: 24.11
          Hardware: All
                OS: All
            Status: UNCONFIRMED
          Severity: normal
          Priority: Normal
         Component: core
          Assignee: [email protected]
          Reporter: [email protected]

Target Milestone: ---

Created attachment 304
--> https://bugs.dpdk.org/attachment.cgi?id=304&action=edit
patch to reproduce the issue with testpmd

When setting the version field in a struct rte_ipv6_hdr, the compiler-generated code stores the value in the wrong byte of the vtc_flow field on little-endian architectures such as x86_64. As a result, the encoded IPv6 version value is not in the expected network byte order, and version checks (such as rte_ipv6_check_version()) fail.

I encountered this issue while writing new unit tests for the DPDK Grout project, which exposed the incorrect version encoding. The issue is reproducible with GCC 13 and 14 and Clang 15, 16, and 18 on Ubuntu 24.04 (x86_64), but it does not reproduce on ARM.

Example output with the patch provided:

$ ./build/app/dpdk-testpmd
version is bad
0 0 0 60

This suggests that 0x60 (i.e., version = 6) is incorrectly stored in the 4th byte of vtc_flow (i.e., ((uint8_t *)&vtc_flow)[3]), whereas the 1st byte ([0], the MSB in network byte order) should hold the version field.

Assembly dump with objdump:

memset(&ip, 0, sizeof(ip));
movzbl -0x9d(%rbp), %eax ; ← accesses byte offset +3 from ip

and    $0xf, %eax
or     $0x60, %eax
mov    %al, -0x9d(%rbp)   ; ← stores version into 4th byte

If ip is located at -0xa0(%rbp), then the offset -0x9d(%rbp) corresponds to byte 3 (i.e., ip + 3).
But the version field should be encoded in the first byte (ip + 0) to follow network byte order.

This problem appears since we added bitfield for the version field in rte_ipv6_hdr in : https://git.dpdk.org/dpdk/commit/?id=cba27998dc8

The behavior of bitfield layout in C is implementation-defined, as stated in WG14/N1256 (C99 draft standard), section 6.7.2.1, paragraphs 10 and 11:

“The order of allocation of bit-fields within a unit (high-order to
low-order or low-order to high-order) is implementation-defined.”

Grout PR demonstrating the issue:
- https://github.com/DPDK/grout/pull/189

Signature · 2 lines
You are receiving this mail because:
You are the assignee for the bug.