The rte_raw_cksum_mbuf() performs rte_bswap16() on return value from __rte_raw_cksum() for odd-sized segments. However, __rte_raw_cksum() returns a 32-bit accumulator whose upper 16 bits may still contain carries that must be folded. Truncating those upper bits by passing to rte_bswap16() will produce an invalid checksum if they are non-zero.
This is surely a rare encounter in practice, as most NICs have hardware checksum offloads, and even then encountering an odd-sized SG segment is not common, but currently such a case would miscompute the checksum. I found this issue by accident when comparing RVVM networking stack packet checksuming to DPDK, and noticed that this looked incorrect. Fix this by folding the odd-sized segment checksum before bswap16. Signed-off-by: Eva Kurchatova <[email protected]> --- lib/net/rte_cksum.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/rte_cksum.h b/lib/net/rte_cksum.h index a8e8927952..391f998ee5 100644 --- a/lib/net/rte_cksum.h +++ b/lib/net/rte_cksum.h @@ -157,7 +157,7 @@ rte_raw_cksum_mbuf(const struct rte_mbuf *m, uint32_t off, uint32_t len, for (;;) { tmp = __rte_raw_cksum(buf, seglen, 0); if (done & 1) - tmp = rte_bswap16((uint16_t)tmp); + tmp = rte_bswap16(__rte_raw_cksum_reduce(tmp)); sum += tmp; done += seglen; if (done == len) -- 2.55.0

