All of lore.kernel.org
 help / color / mirror / Atom feed
From: "dust.li" <dust.li@linux.alibaba.com>
To: Pavel Begunkov <asml.silence@gmail.com>,
	io-uring@vger.kernel.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org
Cc: "David S . Miller" <davem@davemloft.net>,
	Jakub Kicinski <kuba@kernel.org>,
	Jonathan Lemon <jonathan.lemon@gmail.com>,
	Willem de Bruijn <willemb@google.com>,
	Jens Axboe <axboe@kernel.dk>, David Ahern <dsahern@kernel.org>,
	kernel-team@fb.com
Subject: Re: [PATCH net-next v5 27/27] selftests/io_uring: test zerocopy send
Date: Wed, 27 Jul 2022 16:01:01 +0800	[thread overview]
Message-ID: <20220727080101.GA14576@linux.alibaba.com> (raw)
In-Reply-To: <03d5ec78061cf52db420f88ed0b48eb8f47ce9f7.1657643355.git.asml.silence@gmail.com>

On Tue, Jul 12, 2022 at 09:52:51PM +0100, Pavel Begunkov wrote:
>Add selftests for io_uring zerocopy sends and io_uring's notification
>infrastructure. It's largely influenced by msg_zerocopy and uses it on
>the receive side.
>
>Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
>---
> tools/testing/selftests/net/Makefile          |   1 +
> .../selftests/net/io_uring_zerocopy_tx.c      | 605 ++++++++++++++++++
> .../selftests/net/io_uring_zerocopy_tx.sh     | 131 ++++
> 3 files changed, 737 insertions(+)
> create mode 100644 tools/testing/selftests/net/io_uring_zerocopy_tx.c
> create mode 100755 tools/testing/selftests/net/io_uring_zerocopy_tx.sh
>
>diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
>index 7ea54af55490..51261483744e 100644
>--- a/tools/testing/selftests/net/Makefile
>+++ b/tools/testing/selftests/net/Makefile
>@@ -59,6 +59,7 @@ TEST_GEN_FILES += toeplitz
> TEST_GEN_FILES += cmsg_sender
> TEST_GEN_FILES += stress_reuseport_listen
> TEST_PROGS += test_vxlan_vnifiltering.sh
>+TEST_GEN_FILES += io_uring_zerocopy_tx
> 
> TEST_FILES := settings
> 
>diff --git a/tools/testing/selftests/net/io_uring_zerocopy_tx.c b/tools/testing/selftests/net/io_uring_zerocopy_tx.c
>new file mode 100644
>index 000000000000..9d64c560a2d6
>--- /dev/null
>+++ b/tools/testing/selftests/net/io_uring_zerocopy_tx.c
>@@ -0,0 +1,605 @@
>+/* SPDX-License-Identifier: MIT */
>+/* based on linux-kernel/tools/testing/selftests/net/msg_zerocopy.c */
>+#include <assert.h>
>+#include <errno.h>
>+#include <error.h>
>+#include <fcntl.h>
>+#include <limits.h>
>+#include <stdbool.h>
>+#include <stdint.h>
>+#include <stdio.h>
>+#include <stdlib.h>
>+#include <string.h>
>+#include <unistd.h>
>+
>+#include <arpa/inet.h>
>+#include <linux/errqueue.h>
>+#include <linux/if_packet.h>
>+#include <linux/io_uring.h>
>+#include <linux/ipv6.h>
>+#include <linux/socket.h>
>+#include <linux/sockios.h>
>+#include <net/ethernet.h>
>+#include <net/if.h>
>+#include <netinet/in.h>
>+#include <netinet/ip.h>
>+#include <netinet/ip6.h>
>+#include <netinet/tcp.h>
>+#include <netinet/udp.h>
>+#include <sys/ioctl.h>
>+#include <sys/mman.h>
>+#include <sys/resource.h>
>+#include <sys/socket.h>
>+#include <sys/stat.h>
>+#include <sys/time.h>
>+#include <sys/types.h>
>+#include <sys/un.h>
>+#include <sys/wait.h>
>+
>+#define NOTIF_TAG 0xfffffffULL
>+#define NONZC_TAG 0
>+#define ZC_TAG 1
>+

<...>

>+static void do_test(int domain, int type, int protocol)
>+{
>+	int i;
>+
>+	for (i = 0; i < IP_MAXPACKET; i++)
>+		payload[i] = 'a' + (i % 26);
>+	do_tx(domain, type, protocol);
>+}
>+
>+static void usage(const char *filepath)
>+{
>+	error(1, 0, "Usage: %s [-f] [-n<N>] [-z0] [-s<payload size>] "
>+		    "(-4|-6) [-t<time s>] -D<dst_ip> udp", filepath);

A small flaw, the usage here doesn't match the real options in parse_opts().

Thanks

>+}
>+
>+static void parse_opts(int argc, char **argv)
>+{
>+	const int max_payload_len = sizeof(payload) -
>+				    sizeof(struct ipv6hdr) -
>+				    sizeof(struct tcphdr) -
>+				    40 /* max tcp options */;
>+	struct sockaddr_in6 *addr6 = (void *) &cfg_dst_addr;
>+	struct sockaddr_in *addr4 = (void *) &cfg_dst_addr;
>+	char *daddr = NULL;
>+	int c;
>+
>+	if (argc <= 1)
>+		usage(argv[0]);
>+	cfg_payload_len = max_payload_len;
>+
>+	while ((c = getopt(argc, argv, "46D:p:s:t:n:fc:m:")) != -1) {
>+		switch (c) {
>+		case '4':
>+			if (cfg_family != PF_UNSPEC)
>+				error(1, 0, "Pass one of -4 or -6");
>+			cfg_family = PF_INET;
>+			cfg_alen = sizeof(struct sockaddr_in);
>+			break;
>+		case '6':
>+			if (cfg_family != PF_UNSPEC)
>+				error(1, 0, "Pass one of -4 or -6");
>+			cfg_family = PF_INET6;
>+			cfg_alen = sizeof(struct sockaddr_in6);
>+			break;
>+		case 'D':
>+			daddr = optarg;
>+			break;
>+		case 'p':
>+			cfg_port = strtoul(optarg, NULL, 0);
>+			break;
>+		case 's':
>+			cfg_payload_len = strtoul(optarg, NULL, 0);
>+			break;
>+		case 't':
>+			cfg_runtime_ms = 200 + strtoul(optarg, NULL, 10) * 1000;
>+			break;
>+		case 'n':
>+			cfg_nr_reqs = strtoul(optarg, NULL, 0);
>+			break;
>+		case 'f':
>+			cfg_flush = 1;
>+			break;
>+		case 'c':
>+			cfg_cork = strtol(optarg, NULL, 0);
>+			break;
>+		case 'm':
>+			cfg_mode = strtol(optarg, NULL, 0);
>+			break;
>+		}
>+	}
>+
>+	switch (cfg_family) {
>+	case PF_INET:
>+		memset(addr4, 0, sizeof(*addr4));
>+		addr4->sin_family = AF_INET;
>+		addr4->sin_port = htons(cfg_port);
>+		if (daddr &&
>+		    inet_pton(AF_INET, daddr, &(addr4->sin_addr)) != 1)
>+			error(1, 0, "ipv4 parse error: %s", daddr);
>+		break;
>+	case PF_INET6:
>+		memset(addr6, 0, sizeof(*addr6));
>+		addr6->sin6_family = AF_INET6;
>+		addr6->sin6_port = htons(cfg_port);
>+		if (daddr &&
>+		    inet_pton(AF_INET6, daddr, &(addr6->sin6_addr)) != 1)
>+			error(1, 0, "ipv6 parse error: %s", daddr);
>+		break;
>+	default:
>+		error(1, 0, "illegal domain");
>+	}
>+
>+	if (cfg_payload_len > max_payload_len)
>+		error(1, 0, "-s: payload exceeds max (%d)", max_payload_len);
>+	if (cfg_mode == MODE_NONZC && cfg_flush)
>+		error(1, 0, "-f: only zerocopy modes support notifications");
>+	if (optind != argc - 1)
>+		usage(argv[0]);
>+}
>+
>+int main(int argc, char **argv)
>+{
>+	const char *cfg_test = argv[argc - 1];
>+
>+	parse_opts(argc, argv);
>+
>+	if (!strcmp(cfg_test, "tcp"))
>+		do_test(cfg_family, SOCK_STREAM, 0);
>+	else if (!strcmp(cfg_test, "udp"))
>+		do_test(cfg_family, SOCK_DGRAM, 0);
>+	else
>+		error(1, 0, "unknown cfg_test %s", cfg_test);
>+	return 0;
>+}
>diff --git a/tools/testing/selftests/net/io_uring_zerocopy_tx.sh b/tools/testing/selftests/net/io_uring_zerocopy_tx.sh
>new file mode 100755
>index 000000000000..6a65e4437640
>--- /dev/null
>+++ b/tools/testing/selftests/net/io_uring_zerocopy_tx.sh
>@@ -0,0 +1,131 @@
>+#!/bin/bash
>+#
>+# Send data between two processes across namespaces
>+# Run twice: once without and once with zerocopy
>+
>+set -e
>+
>+readonly DEV="veth0"
>+readonly DEV_MTU=65535
>+readonly BIN_TX="./io_uring_zerocopy_tx"
>+readonly BIN_RX="./msg_zerocopy"
>+
>+readonly RAND="$(mktemp -u XXXXXX)"
>+readonly NSPREFIX="ns-${RAND}"
>+readonly NS1="${NSPREFIX}1"
>+readonly NS2="${NSPREFIX}2"
>+
>+readonly SADDR4='192.168.1.1'
>+readonly DADDR4='192.168.1.2'
>+readonly SADDR6='fd::1'
>+readonly DADDR6='fd::2'
>+
>+readonly path_sysctl_mem="net.core.optmem_max"
>+
>+# No arguments: automated test
>+if [[ "$#" -eq "0" ]]; then
>+	IPs=( "4" "6" )
>+	protocols=( "tcp" "udp" )
>+
>+	for IP in "${IPs[@]}"; do
>+		for proto in "${protocols[@]}"; do
>+			for mode in $(seq 1 3); do
>+				$0 "$IP" "$proto" -m "$mode" -t 1 -n 32
>+				$0 "$IP" "$proto" -m "$mode" -t 1 -n 32 -f
>+				$0 "$IP" "$proto" -m "$mode" -t 1 -n 32 -c -f
>+			done
>+		done
>+	done
>+
>+	echo "OK. All tests passed"
>+	exit 0
>+fi
>+
>+# Argument parsing
>+if [[ "$#" -lt "2" ]]; then
>+	echo "Usage: $0 [4|6] [tcp|udp|raw|raw_hdrincl|packet|packet_dgram] <args>"
>+	exit 1
>+fi
>+
>+readonly IP="$1"
>+shift
>+readonly TXMODE="$1"
>+shift
>+readonly EXTRA_ARGS="$@"
>+
>+# Argument parsing: configure addresses
>+if [[ "${IP}" == "4" ]]; then
>+	readonly SADDR="${SADDR4}"
>+	readonly DADDR="${DADDR4}"
>+elif [[ "${IP}" == "6" ]]; then
>+	readonly SADDR="${SADDR6}"
>+	readonly DADDR="${DADDR6}"
>+else
>+	echo "Invalid IP version ${IP}"
>+	exit 1
>+fi
>+
>+# Argument parsing: select receive mode
>+#
>+# This differs from send mode for
>+# - packet:	use raw recv, because packet receives skb clones
>+# - raw_hdrinc: use raw recv, because hdrincl is a tx-only option
>+case "${TXMODE}" in
>+'packet' | 'packet_dgram' | 'raw_hdrincl')
>+	RXMODE='raw'
>+	;;
>+*)
>+	RXMODE="${TXMODE}"
>+	;;
>+esac
>+
>+# Start of state changes: install cleanup handler
>+save_sysctl_mem="$(sysctl -n ${path_sysctl_mem})"
>+
>+cleanup() {
>+	ip netns del "${NS2}"
>+	ip netns del "${NS1}"
>+	sysctl -w -q "${path_sysctl_mem}=${save_sysctl_mem}"
>+}
>+
>+trap cleanup EXIT
>+
>+# Configure system settings
>+sysctl -w -q "${path_sysctl_mem}=1000000"
>+
>+# Create virtual ethernet pair between network namespaces
>+ip netns add "${NS1}"
>+ip netns add "${NS2}"
>+
>+ip link add "${DEV}" mtu "${DEV_MTU}" netns "${NS1}" type veth \
>+  peer name "${DEV}" mtu "${DEV_MTU}" netns "${NS2}"
>+
>+# Bring the devices up
>+ip -netns "${NS1}" link set "${DEV}" up
>+ip -netns "${NS2}" link set "${DEV}" up
>+
>+# Set fixed MAC addresses on the devices
>+ip -netns "${NS1}" link set dev "${DEV}" address 02:02:02:02:02:02
>+ip -netns "${NS2}" link set dev "${DEV}" address 06:06:06:06:06:06
>+
>+# Add fixed IP addresses to the devices
>+ip -netns "${NS1}" addr add 192.168.1.1/24 dev "${DEV}"
>+ip -netns "${NS2}" addr add 192.168.1.2/24 dev "${DEV}"
>+ip -netns "${NS1}" addr add       fd::1/64 dev "${DEV}" nodad
>+ip -netns "${NS2}" addr add       fd::2/64 dev "${DEV}" nodad
>+
>+# Optionally disable sg or csum offload to test edge cases
>+# ip netns exec "${NS1}" ethtool -K "${DEV}" sg off
>+
>+do_test() {
>+	local readonly ARGS="$1"
>+
>+	echo "ipv${IP} ${TXMODE} ${ARGS}"
>+	ip netns exec "${NS2}" "${BIN_RX}" "-${IP}" -t 2 -C 2 -S "${SADDR}" -D "${DADDR}" -r "${RXMODE}" &
>+	sleep 0.2
>+	ip netns exec "${NS1}" "${BIN_TX}" "-${IP}" -t 1 -D "${DADDR}" ${ARGS} "${TXMODE}"
>+	wait
>+}
>+
>+do_test "${EXTRA_ARGS}"
>+echo ok
>-- 
>2.37.0

  reply	other threads:[~2022-07-27  8:01 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-12 20:52 [PATCH net-next v5 00/27] io_uring zerocopy send Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 01/27] ipv4: avoid partial copy for zc Pavel Begunkov
2022-07-19  1:54   ` Jakub Kicinski
2022-07-19  9:35     ` Willem de Bruijn
2022-07-21 10:03       ` Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 02/27] ipv6: " Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 03/27] skbuff: don't mix ubuf_info from different sources Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 04/27] skbuff: add SKBFL_DONT_ORPHAN flag Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 05/27] skbuff: carry external ubuf_info in msghdr Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 06/27] net: Allow custom iter handler " Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 07/27] net: introduce managed frags infrastructure Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 08/27] net: introduce __skb_fill_page_desc_noacc Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 09/27] ipv4/udp: support externally provided ubufs Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 10/27] ipv6/udp: " Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 11/27] tcp: " Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 12/27] io_uring: initialise msghdr::msg_ubuf Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 13/27] io_uring: export io_put_task() Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 14/27] io_uring: add zc notification infrastructure Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 15/27] io_uring: cache struct io_notif Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 16/27] io_uring: complete notifiers in tw Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 17/27] io_uring: add rsrc referencing for notifiers Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 18/27] io_uring: add notification slot registration Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 19/27] io_uring: wire send zc request type Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 20/27] io_uring: account locked pages for non-fixed zc Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 21/27] io_uring: allow to pass addr into sendzc Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 22/27] io_uring: sendzc with fixed buffers Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 23/27] io_uring: flush notifiers after sendzc Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 24/27] io_uring: rename IORING_OP_FILES_UPDATE Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 25/27] io_uring: add zc notification flush requests Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 26/27] io_uring: enable managed frags with register buffers Pavel Begunkov
2022-07-12 20:52 ` [PATCH net-next v5 27/27] selftests/io_uring: test zerocopy send Pavel Begunkov
2022-07-27  8:01   ` dust.li [this message]
2022-07-27  9:18     ` Pavel Begunkov
2022-07-20 12:46 ` (subset) [PATCH net-next v5 00/27] io_uring " Jens Axboe

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=20220727080101.GA14576@linux.alibaba.com \
    --to=dust.li@linux.alibaba.com \
    --cc=asml.silence@gmail.com \
    --cc=axboe@kernel.dk \
    --cc=davem@davemloft.net \
    --cc=dsahern@kernel.org \
    --cc=io-uring@vger.kernel.org \
    --cc=jonathan.lemon@gmail.com \
    --cc=kernel-team@fb.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=willemb@google.com \
    /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.