Commit b539264a authored by Sean Anderson's avatar Sean Anderson Committed by Wen Zhiwei
Browse files

selftests: net: csum: Fix checksums for packets with non-zero padding

stable inclusion
from stable-v6.6.52
commit 033a71efabac967241c885ee469823b0d560f4e6
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IAYXOD

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=033a71efabac967241c885ee469823b0d560f4e6



--------------------------------

[ Upstream commit e8a63d473b49011a68a748aea1c8aefa046ebacf ]

Padding is not included in UDP and TCP checksums. Therefore, reduce the
length of the checksummed data to include only the data in the IP
payload. This fixes spurious reported checksum failures like

rx: pkt: sport=33000 len=26 csum=0xc850 verify=0xf9fe
pkt: bad csum

Technically it is possible for there to be trailing bytes after the UDP
data but before the Ethernet padding (e.g. if sizeof(ip) + sizeof(udp) +
udp.len < ip.len). However, we don't generate such packets.

Fixes: 91a7de85 ("selftests/net: add csum offload test")
Signed-off-by: default avatarSean Anderson <sean.anderson@linux.dev>
Reviewed-by: default avatarWillem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20240906210743.627413-1-sean.anderson@linux.dev


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarWen Zhiwei <wenzhiwei@kylinos.cn>
parent 30c2ec36
Loading
Loading
Loading
Loading
+14 −2
Original line number Diff line number Diff line
@@ -654,10 +654,16 @@ static int recv_verify_packet_ipv4(void *nh, int len)
{
	struct iphdr *iph = nh;
	uint16_t proto = cfg_encap ? IPPROTO_UDP : cfg_proto;
	uint16_t ip_len;

	if (len < sizeof(*iph) || iph->protocol != proto)
		return -1;

	ip_len = ntohs(iph->tot_len);
	if (ip_len > len || ip_len < sizeof(*iph))
		return -1;

	len = ip_len;
	iph_addr_p = &iph->saddr;
	if (proto == IPPROTO_TCP)
		return recv_verify_packet_tcp(iph + 1, len - sizeof(*iph));
@@ -669,16 +675,22 @@ static int recv_verify_packet_ipv6(void *nh, int len)
{
	struct ipv6hdr *ip6h = nh;
	uint16_t proto = cfg_encap ? IPPROTO_UDP : cfg_proto;
	uint16_t ip_len;

	if (len < sizeof(*ip6h) || ip6h->nexthdr != proto)
		return -1;

	ip_len = ntohs(ip6h->payload_len);
	if (ip_len > len - sizeof(*ip6h))
		return -1;

	len = ip_len;
	iph_addr_p = &ip6h->saddr;

	if (proto == IPPROTO_TCP)
		return recv_verify_packet_tcp(ip6h + 1, len - sizeof(*ip6h));
		return recv_verify_packet_tcp(ip6h + 1, len);
	else
		return recv_verify_packet_udp(ip6h + 1, len - sizeof(*ip6h));
		return recv_verify_packet_udp(ip6h + 1, len);
}

/* return whether auxdata includes TP_STATUS_CSUM_VALID */