Commit 11614723 authored by Stanislav Fomichev's avatar Stanislav Fomichev Committed by Alexei Starovoitov
Browse files

xsk: Add option to calculate TX checksum in SW



For XDP_COPY mode, add a UMEM option XDP_UMEM_TX_SW_CSUM
to call skb_checksum_help in transmit path. Might be useful
to debugging issues with real hardware. I also use this mode
in the selftests.

Signed-off-by: default avatarStanislav Fomichev <sdf@google.com>
Link: https://lore.kernel.org/r/20231127190319.1190813-9-sdf@google.com


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent ce59f968
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -50,6 +50,15 @@ packet's ``struct xdp_desc`` descriptor should set ``XDP_TX_METADATA``
bit in the ``options`` field. Also note that in a multi-buffer packet
only the first chunk should carry the metadata.

Software TX Checksum
====================

For development and testing purposes its possible to pass
``XDP_UMEM_TX_SW_CSUM`` flag to ``XDP_UMEM_REG`` UMEM registration call.
In this case, when running in ``XDK_COPY`` mode, the TX checksum
is calculated on the CPU. Do not enable this option in production because
it will negatively affect performance.

Querying Device Capabilities
============================

+1 −0
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ struct xsk_buff_pool {
	bool uses_need_wakeup;
	bool dma_need_sync;
	bool unaligned;
	bool tx_sw_csum;
	void *addrs;
	/* Mutual exclusion of the completion ring in the SKB mode. Two cases to protect:
	 * NAPI TX thread and sendmsg error paths in the SKB destructor callback and when
+7 −1
Original line number Diff line number Diff line
@@ -35,6 +35,12 @@
/* Flags for xsk_umem_config flags */
#define XDP_UMEM_UNALIGNED_CHUNK_FLAG	(1 << 0)

/* Force checksum calculation in software. Can be used for testing or
 * working around potential HW issues. This option causes performance
 * degradation and only works in XDP_COPY mode.
 */
#define XDP_UMEM_TX_SW_CSUM		(1 << 1)

struct sockaddr_xdp {
	__u16 sxdp_family;
	__u16 sxdp_flags;
+6 −1
Original line number Diff line number Diff line
@@ -148,6 +148,11 @@ static int xdp_umem_account_pages(struct xdp_umem *umem)
	return 0;
}

#define XDP_UMEM_FLAGS_VALID ( \
		XDP_UMEM_UNALIGNED_CHUNK_FLAG | \
		XDP_UMEM_TX_SW_CSUM | \
	0)

static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
{
	bool unaligned_chunks = mr->flags & XDP_UMEM_UNALIGNED_CHUNK_FLAG;
@@ -167,7 +172,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
		return -EINVAL;
	}

	if (mr->flags & ~XDP_UMEM_UNALIGNED_CHUNK_FLAG)
	if (mr->flags & ~XDP_UMEM_FLAGS_VALID)
		return -EINVAL;

	if (!unaligned_chunks && !is_power_of_2(chunk_size))
+6 −0
Original line number Diff line number Diff line
@@ -744,6 +744,12 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs,
				skb->csum_start = hr + meta->request.csum_start;
				skb->csum_offset = meta->request.csum_offset;
				skb->ip_summed = CHECKSUM_PARTIAL;

				if (unlikely(xs->pool->tx_sw_csum)) {
					err = skb_checksum_help(skb);
					if (err)
						goto free_err;
				}
			}
		}
	}
Loading