xref: /dpdk/app/test/test_cksum.c (revision e0a8442ccd15bafbb7eb150c35331c8e3b828c53)
130a65c6cSOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause
230a65c6cSOlivier Matz  * Copyright 2021 6WIND S.A.
330a65c6cSOlivier Matz  */
430a65c6cSOlivier Matz 
530a65c6cSOlivier Matz #include <string.h>
630a65c6cSOlivier Matz #include <stdio.h>
730a65c6cSOlivier Matz #include <stdlib.h>
830a65c6cSOlivier Matz #include <stdint.h>
930a65c6cSOlivier Matz 
1030a65c6cSOlivier Matz #include <rte_net.h>
1130a65c6cSOlivier Matz #include <rte_mbuf.h>
1230a65c6cSOlivier Matz #include <rte_ip.h>
1330a65c6cSOlivier Matz 
1430a65c6cSOlivier Matz #include "test.h"
1530a65c6cSOlivier Matz 
1630a65c6cSOlivier Matz #define MEMPOOL_CACHE_SIZE      0
1730a65c6cSOlivier Matz #define MBUF_DATA_SIZE          256
1830a65c6cSOlivier Matz #define NB_MBUF                 128
1930a65c6cSOlivier Matz 
2030a65c6cSOlivier Matz /*
2130a65c6cSOlivier Matz  * Test L3/L4 checksum API.
2230a65c6cSOlivier Matz  */
2330a65c6cSOlivier Matz 
2430a65c6cSOlivier Matz #define GOTO_FAIL(str, ...) do {					\
2530a65c6cSOlivier Matz 		printf("cksum test FAILED (l.%d): <" str ">\n",		\
2630a65c6cSOlivier Matz 		       __LINE__,  ##__VA_ARGS__);			\
2730a65c6cSOlivier Matz 		goto fail;						\
2830a65c6cSOlivier Matz 	} while (0)
2930a65c6cSOlivier Matz 
3030a65c6cSOlivier Matz /* generated in scapy with Ether()/IP()/TCP())) */
3130a65c6cSOlivier Matz static const char test_cksum_ipv4_tcp[] = {
3230a65c6cSOlivier Matz 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
3330a65c6cSOlivier Matz 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
3430a65c6cSOlivier Matz 	0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06,
3530a65c6cSOlivier Matz 	0x7c, 0xcd, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00,
3630a65c6cSOlivier Matz 	0x00, 0x01, 0x00, 0x14, 0x00, 0x50, 0x00, 0x00,
3730a65c6cSOlivier Matz 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02,
3830a65c6cSOlivier Matz 	0x20, 0x00, 0x91, 0x7c, 0x00, 0x00,
3930a65c6cSOlivier Matz 
4030a65c6cSOlivier Matz };
4130a65c6cSOlivier Matz 
4230a65c6cSOlivier Matz /* generated in scapy with Ether()/IPv6()/TCP()) */
4330a65c6cSOlivier Matz static const char test_cksum_ipv6_tcp[] = {
4430a65c6cSOlivier Matz 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
4530a65c6cSOlivier Matz 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x60, 0x00,
4630a65c6cSOlivier Matz 	0x00, 0x00, 0x00, 0x14, 0x06, 0x40, 0x00, 0x00,
4730a65c6cSOlivier Matz 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4830a65c6cSOlivier Matz 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
4930a65c6cSOlivier Matz 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5030a65c6cSOlivier Matz 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x14,
5130a65c6cSOlivier Matz 	0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5230a65c6cSOlivier Matz 	0x00, 0x00, 0x50, 0x02, 0x20, 0x00, 0x8f, 0x7d,
5330a65c6cSOlivier Matz 	0x00, 0x00,
5430a65c6cSOlivier Matz };
5530a65c6cSOlivier Matz 
5630a65c6cSOlivier Matz /* generated in scapy with Ether()/IP()/UDP()/Raw('x')) */
5730a65c6cSOlivier Matz static const char test_cksum_ipv4_udp[] = {
5830a65c6cSOlivier Matz 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
5930a65c6cSOlivier Matz 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
6030a65c6cSOlivier Matz 	0x00, 0x1d, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11,
6130a65c6cSOlivier Matz 	0x7c, 0xcd, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00,
6230a65c6cSOlivier Matz 	0x00, 0x01, 0x00, 0x35, 0x00, 0x35, 0x00, 0x09,
6330a65c6cSOlivier Matz 	0x89, 0x6f, 0x78,
6430a65c6cSOlivier Matz };
6530a65c6cSOlivier Matz 
6630a65c6cSOlivier Matz /* generated in scapy with Ether()/IPv6()/UDP()/Raw('x')) */
6730a65c6cSOlivier Matz static const char test_cksum_ipv6_udp[] = {
6830a65c6cSOlivier Matz 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
6930a65c6cSOlivier Matz 	0x00, 0x00, 0x00, 0x00, 0x86, 0xdd, 0x60, 0x00,
7030a65c6cSOlivier Matz 	0x00, 0x00, 0x00, 0x09, 0x11, 0x40, 0x00, 0x00,
7130a65c6cSOlivier Matz 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7230a65c6cSOlivier Matz 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
7330a65c6cSOlivier Matz 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7430a65c6cSOlivier Matz 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x35,
7530a65c6cSOlivier Matz 	0x00, 0x35, 0x00, 0x09, 0x87, 0x70, 0x78,
7630a65c6cSOlivier Matz };
7730a65c6cSOlivier Matz 
7830a65c6cSOlivier Matz /* generated in scapy with Ether()/IP(options='\x00')/UDP()/Raw('x')) */
7930a65c6cSOlivier Matz static const char test_cksum_ipv4_opts_udp[] = {
8030a65c6cSOlivier Matz 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
8130a65c6cSOlivier Matz 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x46, 0x00,
8230a65c6cSOlivier Matz 	0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11,
8330a65c6cSOlivier Matz 	0x7b, 0xc9, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00,
8430a65c6cSOlivier Matz 	0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35,
8530a65c6cSOlivier Matz 	0x00, 0x35, 0x00, 0x09, 0x89, 0x6f, 0x78,
8630a65c6cSOlivier Matz };
8730a65c6cSOlivier Matz 
8830a65c6cSOlivier Matz /* test l3/l4 checksum api */
8930a65c6cSOlivier Matz static int
test_l4_cksum(struct rte_mempool * pktmbuf_pool,const char * pktdata,size_t len)9030a65c6cSOlivier Matz test_l4_cksum(struct rte_mempool *pktmbuf_pool, const char *pktdata, size_t len)
9130a65c6cSOlivier Matz {
9230a65c6cSOlivier Matz 	struct rte_net_hdr_lens hdr_lens;
9330a65c6cSOlivier Matz 	struct rte_mbuf *m = NULL;
9430a65c6cSOlivier Matz 	uint32_t packet_type;
9530a65c6cSOlivier Matz 	uint16_t prev_cksum;
9630a65c6cSOlivier Matz 	void *l3_hdr;
9730a65c6cSOlivier Matz 	void *l4_hdr;
9830a65c6cSOlivier Matz 	uint32_t l3;
9930a65c6cSOlivier Matz 	uint32_t l4;
10030a65c6cSOlivier Matz 	char *data;
10130a65c6cSOlivier Matz 
10230a65c6cSOlivier Matz 	m = rte_pktmbuf_alloc(pktmbuf_pool);
10330a65c6cSOlivier Matz 	if (m == NULL)
10430a65c6cSOlivier Matz 		GOTO_FAIL("Cannot allocate mbuf");
10530a65c6cSOlivier Matz 
10630a65c6cSOlivier Matz 	data = rte_pktmbuf_append(m, len);
10730a65c6cSOlivier Matz 	if (data == NULL)
10830a65c6cSOlivier Matz 		GOTO_FAIL("Cannot append data");
10930a65c6cSOlivier Matz 
11030a65c6cSOlivier Matz 	memcpy(data, pktdata, len);
11130a65c6cSOlivier Matz 
11230a65c6cSOlivier Matz 	packet_type = rte_net_get_ptype(m, &hdr_lens, RTE_PTYPE_ALL_MASK);
11330a65c6cSOlivier Matz 	l3 = packet_type & RTE_PTYPE_L3_MASK;
11430a65c6cSOlivier Matz 	l4 = packet_type & RTE_PTYPE_L4_MASK;
11530a65c6cSOlivier Matz 
11630a65c6cSOlivier Matz 	l3_hdr = rte_pktmbuf_mtod_offset(m, void *, hdr_lens.l2_len);
11730a65c6cSOlivier Matz 	l4_hdr = rte_pktmbuf_mtod_offset(m, void *,
11830a65c6cSOlivier Matz 					 hdr_lens.l2_len + hdr_lens.l3_len);
11930a65c6cSOlivier Matz 
12030a65c6cSOlivier Matz 	if (l3 == RTE_PTYPE_L3_IPV4 || l3 == RTE_PTYPE_L3_IPV4_EXT) {
12130a65c6cSOlivier Matz 		struct rte_ipv4_hdr *ip = l3_hdr;
12230a65c6cSOlivier Matz 
12330a65c6cSOlivier Matz 		/* verify IPv4 checksum */
12430a65c6cSOlivier Matz 		if (rte_ipv4_cksum(l3_hdr) != 0)
12530a65c6cSOlivier Matz 			GOTO_FAIL("invalid IPv4 checksum verification");
12630a65c6cSOlivier Matz 
12730a65c6cSOlivier Matz 		/* verify bad IPv4 checksum */
12830a65c6cSOlivier Matz 		ip->hdr_checksum++;
12930a65c6cSOlivier Matz 		if (rte_ipv4_cksum(l3_hdr) == 0)
13030a65c6cSOlivier Matz 			GOTO_FAIL("invalid IPv4 bad checksum verification");
13130a65c6cSOlivier Matz 		ip->hdr_checksum--;
13230a65c6cSOlivier Matz 
13330a65c6cSOlivier Matz 		/* recalculate IPv4 checksum */
13430a65c6cSOlivier Matz 		prev_cksum = ip->hdr_checksum;
13530a65c6cSOlivier Matz 		ip->hdr_checksum = 0;
13630a65c6cSOlivier Matz 		ip->hdr_checksum = rte_ipv4_cksum(ip);
13730a65c6cSOlivier Matz 		if (ip->hdr_checksum != prev_cksum)
13830a65c6cSOlivier Matz 			GOTO_FAIL("invalid IPv4 checksum calculation");
13930a65c6cSOlivier Matz 
14030a65c6cSOlivier Matz 		/* verify L4 checksum */
14130a65c6cSOlivier Matz 		if (rte_ipv4_udptcp_cksum_verify(l3_hdr, l4_hdr) != 0)
14230a65c6cSOlivier Matz 			GOTO_FAIL("invalid L4 checksum verification");
14330a65c6cSOlivier Matz 
14430a65c6cSOlivier Matz 		if (l4 == RTE_PTYPE_L4_TCP) {
14530a65c6cSOlivier Matz 			struct rte_tcp_hdr *tcp = l4_hdr;
14630a65c6cSOlivier Matz 
14730a65c6cSOlivier Matz 			/* verify bad TCP checksum */
14830a65c6cSOlivier Matz 			tcp->cksum++;
14930a65c6cSOlivier Matz 			if (rte_ipv4_udptcp_cksum_verify(l3_hdr, l4_hdr) == 0)
15030a65c6cSOlivier Matz 				GOTO_FAIL("invalid bad TCP checksum verification");
15130a65c6cSOlivier Matz 			tcp->cksum--;
15230a65c6cSOlivier Matz 
15330a65c6cSOlivier Matz 			/* recalculate TCP checksum */
15430a65c6cSOlivier Matz 			prev_cksum = tcp->cksum;
15530a65c6cSOlivier Matz 			tcp->cksum = 0;
15630a65c6cSOlivier Matz 			tcp->cksum = rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr);
15730a65c6cSOlivier Matz 			if (tcp->cksum != prev_cksum)
15830a65c6cSOlivier Matz 				GOTO_FAIL("invalid TCP checksum calculation");
15930a65c6cSOlivier Matz 
16030a65c6cSOlivier Matz 		} else if (l4 == RTE_PTYPE_L4_UDP) {
16130a65c6cSOlivier Matz 			struct rte_udp_hdr *udp = l4_hdr;
16230a65c6cSOlivier Matz 
16330a65c6cSOlivier Matz 			/* verify bad UDP checksum */
16430a65c6cSOlivier Matz 			udp->dgram_cksum++;
16530a65c6cSOlivier Matz 			if (rte_ipv4_udptcp_cksum_verify(l3_hdr, l4_hdr) == 0)
16630a65c6cSOlivier Matz 				GOTO_FAIL("invalid bad UDP checksum verification");
16730a65c6cSOlivier Matz 			udp->dgram_cksum--;
16830a65c6cSOlivier Matz 
16930a65c6cSOlivier Matz 			/* recalculate UDP checksum */
17030a65c6cSOlivier Matz 			prev_cksum = udp->dgram_cksum;
17130a65c6cSOlivier Matz 			udp->dgram_cksum = 0;
17230a65c6cSOlivier Matz 			udp->dgram_cksum = rte_ipv4_udptcp_cksum(l3_hdr,
17330a65c6cSOlivier Matz 								 l4_hdr);
17430a65c6cSOlivier Matz 			if (udp->dgram_cksum != prev_cksum)
17530a65c6cSOlivier Matz 				GOTO_FAIL("invalid TCP checksum calculation");
17630a65c6cSOlivier Matz 		}
17730a65c6cSOlivier Matz 	} else if (l3 == RTE_PTYPE_L3_IPV6 || l3 == RTE_PTYPE_L3_IPV6_EXT) {
17830a65c6cSOlivier Matz 		if (rte_ipv6_udptcp_cksum_verify(l3_hdr, l4_hdr) != 0)
17930a65c6cSOlivier Matz 			GOTO_FAIL("invalid L4 checksum verification");
18030a65c6cSOlivier Matz 
18130a65c6cSOlivier Matz 		if (l4 == RTE_PTYPE_L4_TCP) {
18230a65c6cSOlivier Matz 			struct rte_tcp_hdr *tcp = l4_hdr;
18330a65c6cSOlivier Matz 
18430a65c6cSOlivier Matz 			/* verify bad TCP checksum */
18530a65c6cSOlivier Matz 			tcp->cksum++;
18630a65c6cSOlivier Matz 			if (rte_ipv6_udptcp_cksum_verify(l3_hdr, l4_hdr) == 0)
18730a65c6cSOlivier Matz 				GOTO_FAIL("invalid bad TCP checksum verification");
18830a65c6cSOlivier Matz 			tcp->cksum--;
18930a65c6cSOlivier Matz 
19030a65c6cSOlivier Matz 			/* recalculate TCP checksum */
19130a65c6cSOlivier Matz 			prev_cksum = tcp->cksum;
19230a65c6cSOlivier Matz 			tcp->cksum = 0;
19330a65c6cSOlivier Matz 			tcp->cksum = rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr);
19430a65c6cSOlivier Matz 			if (tcp->cksum != prev_cksum)
19530a65c6cSOlivier Matz 				GOTO_FAIL("invalid TCP checksum calculation");
19630a65c6cSOlivier Matz 
19730a65c6cSOlivier Matz 		} else if (l4 == RTE_PTYPE_L4_UDP) {
19830a65c6cSOlivier Matz 			struct rte_udp_hdr *udp = l4_hdr;
19930a65c6cSOlivier Matz 
20030a65c6cSOlivier Matz 			/* verify bad UDP checksum */
20130a65c6cSOlivier Matz 			udp->dgram_cksum++;
20230a65c6cSOlivier Matz 			if (rte_ipv6_udptcp_cksum_verify(l3_hdr, l4_hdr) == 0)
20330a65c6cSOlivier Matz 				GOTO_FAIL("invalid bad UDP checksum verification");
20430a65c6cSOlivier Matz 			udp->dgram_cksum--;
20530a65c6cSOlivier Matz 
20630a65c6cSOlivier Matz 			/* recalculate UDP checksum */
20730a65c6cSOlivier Matz 			prev_cksum = udp->dgram_cksum;
20830a65c6cSOlivier Matz 			udp->dgram_cksum = 0;
20930a65c6cSOlivier Matz 			udp->dgram_cksum = rte_ipv6_udptcp_cksum(l3_hdr,
21030a65c6cSOlivier Matz 								 l4_hdr);
21130a65c6cSOlivier Matz 			if (udp->dgram_cksum != prev_cksum)
21230a65c6cSOlivier Matz 				GOTO_FAIL("invalid TCP checksum calculation");
21330a65c6cSOlivier Matz 		}
21430a65c6cSOlivier Matz 	}
21530a65c6cSOlivier Matz 
21630a65c6cSOlivier Matz 	rte_pktmbuf_free(m);
21730a65c6cSOlivier Matz 
21830a65c6cSOlivier Matz 	return 0;
21930a65c6cSOlivier Matz 
22030a65c6cSOlivier Matz fail:
22130a65c6cSOlivier Matz 	rte_pktmbuf_free(m);
22230a65c6cSOlivier Matz 
22330a65c6cSOlivier Matz 	return -1;
22430a65c6cSOlivier Matz }
22530a65c6cSOlivier Matz 
22630a65c6cSOlivier Matz static int
test_cksum(void)22730a65c6cSOlivier Matz test_cksum(void)
22830a65c6cSOlivier Matz {
22930a65c6cSOlivier Matz 	struct rte_mempool *pktmbuf_pool = NULL;
23030a65c6cSOlivier Matz 
23130a65c6cSOlivier Matz 	/* create pktmbuf pool if it does not exist */
23230a65c6cSOlivier Matz 	pktmbuf_pool = rte_pktmbuf_pool_create("test_cksum_mbuf_pool",
23330a65c6cSOlivier Matz 			NB_MBUF, MEMPOOL_CACHE_SIZE, 0, MBUF_DATA_SIZE,
23430a65c6cSOlivier Matz 			SOCKET_ID_ANY);
23530a65c6cSOlivier Matz 
23630a65c6cSOlivier Matz 	if (pktmbuf_pool == NULL)
23730a65c6cSOlivier Matz 		GOTO_FAIL("cannot allocate mbuf pool");
23830a65c6cSOlivier Matz 
23930a65c6cSOlivier Matz 	if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv4_tcp,
24030a65c6cSOlivier Matz 			  sizeof(test_cksum_ipv4_tcp)) < 0)
24130a65c6cSOlivier Matz 		GOTO_FAIL("checksum error on ipv4_tcp");
24230a65c6cSOlivier Matz 
24330a65c6cSOlivier Matz 	if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv6_tcp,
24430a65c6cSOlivier Matz 			  sizeof(test_cksum_ipv6_tcp)) < 0)
24530a65c6cSOlivier Matz 		GOTO_FAIL("checksum error on ipv6_tcp");
24630a65c6cSOlivier Matz 
24730a65c6cSOlivier Matz 	if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv4_udp,
24830a65c6cSOlivier Matz 			  sizeof(test_cksum_ipv4_udp)) < 0)
24930a65c6cSOlivier Matz 		GOTO_FAIL("checksum error on ipv4_udp");
25030a65c6cSOlivier Matz 
25130a65c6cSOlivier Matz 	if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv6_udp,
25230a65c6cSOlivier Matz 			  sizeof(test_cksum_ipv6_udp)) < 0)
25330a65c6cSOlivier Matz 		GOTO_FAIL("checksum error on ipv6_udp");
25430a65c6cSOlivier Matz 
25530a65c6cSOlivier Matz 	if (test_l4_cksum(pktmbuf_pool, test_cksum_ipv4_opts_udp,
25630a65c6cSOlivier Matz 			  sizeof(test_cksum_ipv4_opts_udp)) < 0)
25730a65c6cSOlivier Matz 		GOTO_FAIL("checksum error on ipv4_opts_udp");
25830a65c6cSOlivier Matz 
25930a65c6cSOlivier Matz 	rte_mempool_free(pktmbuf_pool);
26030a65c6cSOlivier Matz 
26130a65c6cSOlivier Matz 	return 0;
26230a65c6cSOlivier Matz 
26330a65c6cSOlivier Matz fail:
26430a65c6cSOlivier Matz 	rte_mempool_free(pktmbuf_pool);
26530a65c6cSOlivier Matz 
26630a65c6cSOlivier Matz 	return -1;
26730a65c6cSOlivier Matz }
26830a65c6cSOlivier Matz #undef GOTO_FAIL
26930a65c6cSOlivier Matz 
270*e0a8442cSBruce Richardson REGISTER_FAST_TEST(cksum_autotest, true, true, test_cksum);
271