[BUG?] RDMA/siw: Terminate control bitfields have wrong wire layout

alu a <[email protected]> Sun, 2 Aug 2026 11:39:43 +0800
Newsgroups org.kernel.vger.linux-rdma
Message-ID <CAH+L_5YXj_bWqr+oOez16OBcDp8zRggJ8rM8zCo_hfSUrCeojg@mail.gmail.com>
Hello,

RFC 5040 Section 4.8, Figure 8 defines the 32-bit Terminate Control
field in network order as Layer (4 bits), EType (4 bits), Error Code
(8 bits), M/D/R (3 bits), and Reserved (13 bits).

On Linux master commit 2d2338c93da79b3bfe4b6099a931d9468d539952,
struct iwarp_terminate represents this field using native C bitfields:

https://github.com/torvalds/linux/blob/2d2338c93da79b3bfe4b6099a931d9468d539952/drivers/infiniband/sw/siw/iwarp.h#L176-L213

The setters assign those bitfields directly. siw_send_terminate() then
places the structure in iov[0] and passes it to kernel_sendmsg(), without
converting or repacking the final four bytes:

https://github.com/torvalds/linux/blob/2d2338c93da79b3bfe4b6099a931d9468d539952/drivers/infiniband/sw/siw/siw_qp.c#L402-L419

https://github.com/torvalds/linux/blob/2d2338c93da79b3bfe4b6099a931d9468d539952/drivers/infiniband/sw/siw/siw_qp.c#L557-L570

I copied the bitfield declaration into a minimal compiler-layout probe.
For a valid RDMAP Remote Protection / Cannot Invalidate Terminate with
Layer=0, EType=1, Error Code=9, and M=D=R=1, RFC 5040 requires these
four wire bytes:

  01 09 e0 00

The current declaration produced:

  x86-64 and AArch64 little-endian: 10 09 07 00
  AArch64 big-endian:               00 07 09 10

The little-endian results were obtained with Clang Linux targets and
verified by inspecting the object bytes with objdump. The big-endian
branch was checked with an AArch64 big-endian compiler target. Encoding
the same value as cpu_to_be32(0x0109e000) produced the expected bytes.

Based on this compiler-level check, the Terminate Control field appears
to use host bitfield layout on the wire. The TERM_MASK_* and TERM_FLAG_*
constants immediately below the structure already describe the RFC bit
positions, but the current accessors do not use them.

I have not reproduced this with a live SIW connection. Is there a
conversion or compiler-layout assumption I have missed, or should the
control field be represented as a single __be32 value and accessed with
the existing masks?

This finding came from an academic source-level RFC consistency review.

Best regards