All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bui Quang Minh <minhquangbui99@gmail.com>
To: linux-kernel@vger.kernel.org, netdev@vger.kernel.org
Cc: davem@davemloft.net, kuba@kernel.org, yoshfuji@linux-ipv6.org,
	dsahern@kernel.org, willemb@google.com, pabeni@redhat.com,
	avagin@gmail.com, alexander@mihalicyn.com,
	minhquangbui99@gmail.com, lesedorucalin01@gmail.com
Subject: [PATCH v2 2/2] selftests: Add udp_repair test
Date: Wed, 11 Aug 2021 22:47:49 +0700	[thread overview]
Message-ID: <20210811154749.7023-1-minhquangbui99@gmail.com> (raw)

This is a simple test for UDP_REPAIR in 3 cases:
 - Socket is an udp4 socket
 - Socket is an udp6 socket with pending ipv4 packets
 - Socket is an udp6 socket with pending ipv6 packets

Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
---
 tools/testing/selftests/net/.gitignore   |   1 +
 tools/testing/selftests/net/Makefile     |   1 +
 tools/testing/selftests/net/udp_repair.c | 218 +++++++++++++++++++++++
 3 files changed, 220 insertions(+)
 create mode 100644 tools/testing/selftests/net/udp_repair.c

diff --git a/tools/testing/selftests/net/.gitignore b/tools/testing/selftests/net/.gitignore
index 19deb9cdf72f..c9daab1721d5 100644
--- a/tools/testing/selftests/net/.gitignore
+++ b/tools/testing/selftests/net/.gitignore
@@ -31,3 +31,4 @@ rxtimestamp
 timestamping
 txtimestamp
 so_netns_cookie
+udp_repair
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index 4f9f73e7a299..602f798c8880 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -42,6 +42,7 @@ TEST_GEN_FILES += gro
 TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
 TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict tls
 TEST_GEN_FILES += toeplitz
+TEST_GEN_PROGS += udp_repair
 
 TEST_FILES := settings
 
diff --git a/tools/testing/selftests/net/udp_repair.c b/tools/testing/selftests/net/udp_repair.c
new file mode 100644
index 000000000000..1b2c53129c71
--- /dev/null
+++ b/tools/testing/selftests/net/udp_repair.c
@@ -0,0 +1,218 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <string.h>
+#include <unistd.h>
+#include <error.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/udp.h>
+
+#define PORT 5000
+#define BUF_SIZE 256
+
+#define UDP_REPAIR	2
+
+char send_buf[BUF_SIZE];
+struct udp_dump {
+	union {
+		struct sockaddr_in addr_v4;
+		struct sockaddr_in6 addr_v6;
+	};
+	char buf[BUF_SIZE];
+};
+
+struct sockaddr_in addr_v4;
+struct sockaddr_in6 addr_v6;
+
+int udp_server(int is_udp4)
+{
+	int sock, ret;
+	unsigned short family;
+	struct sockaddr *server_addr;
+	unsigned int addr_len;
+
+	if (is_udp4) {
+		family = AF_INET;
+		server_addr = (struct sockaddr *) &addr_v4;
+		addr_len = sizeof(addr_v4);
+	} else {
+		family = AF_INET6;
+		server_addr = (struct sockaddr *) &addr_v6;
+		addr_len = sizeof(addr_v6);
+	}
+
+	sock = socket(family, SOCK_DGRAM, IPPROTO_UDP);
+	if (sock < 0)
+		error(1, errno, "socket server");
+
+	ret = bind(sock, server_addr, addr_len);
+	if (ret < 0)
+		error(1, errno, "bind server socket");
+
+	return sock;
+}
+
+void server_recv(int sock)
+{
+	char recv_buf[BUF_SIZE];
+	int ret;
+
+	ret = recv(sock, recv_buf, sizeof(recv_buf), 0);
+	if (ret < 0)
+		error(1, errno, "recv in server");
+
+	if (memcmp(recv_buf, send_buf, BUF_SIZE))
+		error(1, 0, "recv: data mismatch");
+}
+
+int create_corked_udp_client(int is_udp4)
+{
+	int sock, ret, val = 1;
+	unsigned short family = is_udp4 ? AF_INET : AF_INET6;
+
+	sock = socket(family, SOCK_DGRAM, IPPROTO_UDP);
+	if (sock < 0)
+		error(1, errno, "socket client");
+
+	ret = setsockopt(sock, SOL_UDP, UDP_CORK, &val, sizeof(val));
+	if (ret < 0)
+		error(1, errno, "setsockopt cork udp");
+
+	return sock;
+}
+
+struct udp_dump *checkpoint(int sock, int is_udp4)
+{
+	int ret, val;
+	unsigned int addr_len;
+	struct udp_dump *dump;
+	struct sockaddr *addr;
+
+	dump = malloc(sizeof(*dump));
+	if (!dump)
+		error(1, 0, "malloc");
+
+	if (is_udp4) {
+		addr = (struct sockaddr *) &dump->addr_v4;
+		addr_len = sizeof(dump->addr_v4);
+	} else {
+		addr = (struct sockaddr *) &dump->addr_v6;
+		addr_len = sizeof(dump->addr_v6);
+	}
+
+	val = 1;
+	ret = setsockopt(sock, SOL_UDP, UDP_REPAIR, &val, sizeof(val));
+	if (ret < 0)
+		error(1, errno, "setsockopt udp_repair");
+
+	val = 0;
+	ret = setsockopt(sock, SOL_SOCKET, SO_PEEK_OFF, &val, sizeof(val));
+	if (ret < 0)
+		error(1, errno, "setsockopt so_peek_off");
+
+	ret = recvfrom(sock, dump->buf, BUF_SIZE / 2, MSG_PEEK,
+		       addr, &addr_len);
+	if (ret < 0)
+		error(1, errno, "dumping send queue");
+
+	ret = recvfrom(sock, dump->buf + BUF_SIZE / 2,
+		       BUF_SIZE - BUF_SIZE / 2, MSG_PEEK,
+		       addr, &addr_len);
+	if (ret < 0)
+		error(1, errno, "dumping send queue");
+
+	if (memcmp(dump->buf, send_buf, BUF_SIZE))
+		error(1, 0, "dump: data mismatch");
+
+	return dump;
+}
+
+void restore(int sock, struct udp_dump *dump, int is_udp4)
+{
+	struct sockaddr *addr;
+	int val;
+	unsigned int addr_len;
+
+	if (is_udp4) {
+		addr = (struct sockaddr *) &dump->addr_v4;
+		addr_len = sizeof(dump->addr_v4);
+	} else {
+		addr = (struct sockaddr *) &dump->addr_v6;
+		addr_len = sizeof(dump->addr_v6);
+	}
+
+	if (sendto(sock, dump->buf, BUF_SIZE, 0, addr, addr_len) < 0)
+		error(1, errno, "send data");
+
+	val = 0;
+	if (setsockopt(sock, SOL_UDP, UDP_CORK, &val, sizeof(val)) < 0)
+		error(1, errno, "setsockopt un-cork udp");
+}
+
+void run_test(int is_udp4_sock, int is_udp4_packet)
+{
+	int server_sock, client_sock, ret, val;
+	struct udp_dump *dump;
+	struct sockaddr *addr;
+	unsigned int addr_len;
+
+	if (is_udp4_packet) {
+		addr = (struct sockaddr *) &addr_v4;
+		addr_len = sizeof(addr_v4);
+	} else {
+		addr = (struct sockaddr *) &addr_v6;
+		addr_len = sizeof(addr_v6);
+	}
+
+	server_sock = udp_server(is_udp4_packet);
+	client_sock = create_corked_udp_client(is_udp4_sock);
+
+	ret = sendto(client_sock, send_buf, sizeof(send_buf), 0,
+	       addr, addr_len);
+	if (ret < 0)
+		error(1, errno, "send data");
+
+	dump = checkpoint(client_sock, is_udp4_sock);
+	close(client_sock);
+
+	client_sock = create_corked_udp_client(is_udp4_sock);
+	restore(client_sock, dump, is_udp4_sock);
+
+	val = 0;
+	setsockopt(client_sock, SOL_UDP, UDP_CORK, &val, sizeof(val));
+	server_recv(server_sock);
+
+	close(server_sock);
+	close(client_sock);
+}
+
+void init(void)
+{
+	addr_v4.sin_family	= AF_INET;
+	addr_v4.sin_port	= htons(PORT);
+	addr_v4.sin_addr.s_addr	= inet_addr("127.0.0.1");
+
+	addr_v6.sin6_family	= AF_INET6;
+	addr_v6.sin6_port	= htons(PORT);
+	inet_pton(AF_INET6, "::1", &addr_v6.sin6_addr);
+
+	memset(send_buf, 'A', BUF_SIZE / 2);
+	memset(send_buf + BUF_SIZE / 2, 'B', BUF_SIZE - BUF_SIZE / 2);
+}
+
+int main(void)
+{
+	init();
+	fprintf(stderr, "Test udp4 socket\n");
+	run_test(1, 1);
+	fprintf(stderr, "Test udp6 socket sending udp4 packet\n");
+	run_test(0, 1);
+	fprintf(stderr, "Test udp6 socket sending udp6 packet\n");
+	run_test(0, 0);
+	fprintf(stderr, "Ok\n");
+	return 0;
+}
-- 
2.17.1


                 reply	other threads:[~2021-08-11 15:49 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210811154749.7023-1-minhquangbui99@gmail.com \
    --to=minhquangbui99@gmail.com \
    --cc=alexander@mihalicyn.com \
    --cc=avagin@gmail.com \
    --cc=davem@davemloft.net \
    --cc=dsahern@kernel.org \
    --cc=kuba@kernel.org \
    --cc=lesedorucalin01@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=willemb@google.com \
    --cc=yoshfuji@linux-ipv6.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.