Commit 93305635 authored by Stanislav Fomichev's avatar Stanislav Fomichev Committed by Jakub Kicinski
Browse files

selftests: ncdevmem: Switch to AF_INET6



Use dualstack socket to support both v4 and v6. v4-mapped-v6 address
can be used to do v4.

Reviewed-by: default avatarMina Almasry <almasrymina@google.com>
Reviewed-by: default avatarJoe Damato <jdamato@fastly.com>
Signed-off-by: default avatarStanislav Fomichev <sdf@fomichev.me>
Link: https://patch.msgid.link/20241107181211.3934153-7-sdf@fomichev.me


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent d3ca35c6
Loading
Loading
Loading
Loading
+68 −29
Original line number Diff line number Diff line
@@ -242,13 +242,26 @@ static int configure_channels(unsigned int rx, unsigned int tx)
	return run_command("sudo ethtool -L %s rx %u tx %u", ifname, rx, tx);
}

static int configure_flow_steering(void)
static int configure_flow_steering(struct sockaddr_in6 *server_sin)
{
	return run_command("sudo ethtool -N %s flow-type tcp4 %s %s dst-ip %s %s %s dst-port %s queue %d >&2",
	const char *type = "tcp6";
	const char *server_addr;
	char buf[40];

	inet_ntop(AF_INET6, &server_sin->sin6_addr, buf, sizeof(buf));
	server_addr = buf;

	if (IN6_IS_ADDR_V4MAPPED(&server_sin->sin6_addr)) {
		type = "tcp4";
		server_addr = strrchr(server_addr, ':') + 1;
	}

	return run_command("sudo ethtool -N %s flow-type %s %s %s dst-ip %s %s %s dst-port %s queue %d >&2",
			   ifname,
			   type,
			   client_ip ? "src-ip" : "",
			   client_ip ?: "",
			   server_ip,
			   server_addr,
			   client_ip ? "src-port" : "",
			   client_ip ? port : "",
			   port, start_queue);
@@ -299,13 +312,51 @@ static int bind_rx_queue(unsigned int ifindex, unsigned int dmabuf_fd,
	return -1;
}

static void enable_reuseaddr(int fd)
{
	int opt = 1;
	int ret;

	ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
	if (ret)
		error(1, errno, "%s: [FAIL, SO_REUSEPORT]\n", TEST_PREFIX);

	ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
	if (ret)
		error(1, errno, "%s: [FAIL, SO_REUSEADDR]\n", TEST_PREFIX);
}

static int parse_address(const char *str, int port, struct sockaddr_in6 *sin6)
{
	int ret;

	sin6->sin6_family = AF_INET6;
	sin6->sin6_port = htons(port);

	ret = inet_pton(sin6->sin6_family, str, &sin6->sin6_addr);
	if (ret != 1) {
		/* fallback to plain IPv4 */
		ret = inet_pton(AF_INET, str, &sin6->sin6_addr.s6_addr32[3]);
		if (ret != 1)
			return -1;

		/* add ::ffff prefix */
		sin6->sin6_addr.s6_addr32[0] = 0;
		sin6->sin6_addr.s6_addr32[1] = 0;
		sin6->sin6_addr.s6_addr16[4] = 0;
		sin6->sin6_addr.s6_addr16[5] = 0xffff;
	}

	return 0;
}

int do_server(struct memory_buffer *mem)
{
	char ctrl_data[sizeof(int) * 20000];
	struct netdev_queue_id *queues;
	size_t non_page_aligned_frags = 0;
	struct sockaddr_in client_addr;
	struct sockaddr_in server_sin;
	struct sockaddr_in6 client_addr;
	struct sockaddr_in6 server_sin;
	size_t page_aligned_frags = 0;
	size_t total_received = 0;
	socklen_t client_addr_len;
@@ -317,9 +368,12 @@ int do_server(struct memory_buffer *mem)
	int socket_fd;
	int client_fd;
	size_t i = 0;
	int opt = 1;
	int ret;

	ret = parse_address(server_ip, atoi(port), &server_sin);
	if (ret < 0)
		error(1, 0, "parse server address");

	if (reset_flow_steering())
		error(1, 0, "Failed to reset flow steering\n");

@@ -328,7 +382,7 @@ int do_server(struct memory_buffer *mem)
		error(1, 0, "Failed to configure rss\n");

	/* Flow steer our devmem flows to start_queue */
	if (configure_flow_steering())
	if (configure_flow_steering(&server_sin))
		error(1, 0, "Failed to configure flow steering\n");

	sleep(1);
@@ -349,29 +403,14 @@ int do_server(struct memory_buffer *mem)
	if (!tmp_mem)
		error(1, ENOMEM, "malloc failed");

	server_sin.sin_family = AF_INET;
	server_sin.sin_port = htons(atoi(port));

	ret = inet_pton(server_sin.sin_family, server_ip, &server_sin.sin_addr);
	if (ret < 0)
		error(1, errno, "%s: [FAIL, create socket]\n", TEST_PREFIX);

	socket_fd = socket(server_sin.sin_family, SOCK_STREAM, 0);
	socket_fd = socket(AF_INET6, SOCK_STREAM, 0);
	if (socket_fd < 0)
		error(1, errno, "%s: [FAIL, create socket]\n", TEST_PREFIX);

	ret = setsockopt(socket_fd, SOL_SOCKET, SO_REUSEPORT, &opt,
			 sizeof(opt));
	if (ret)
		error(1, errno, "%s: [FAIL, set sock opt]\n", TEST_PREFIX);

	ret = setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt,
			 sizeof(opt));
	if (ret)
		error(1, errno, "%s: [FAIL, set sock opt]\n", TEST_PREFIX);
	enable_reuseaddr(socket_fd);

	fprintf(stderr, "binding to address %s:%d\n", server_ip,
		ntohs(server_sin.sin_port));
		ntohs(server_sin.sin6_port));

	ret = bind(socket_fd, &server_sin, sizeof(server_sin));
	if (ret)
@@ -383,16 +422,16 @@ int do_server(struct memory_buffer *mem)

	client_addr_len = sizeof(client_addr);

	inet_ntop(server_sin.sin_family, &server_sin.sin_addr, buffer,
	inet_ntop(AF_INET6, &server_sin.sin6_addr, buffer,
		  sizeof(buffer));
	fprintf(stderr, "Waiting or connection on %s:%d\n", buffer,
		ntohs(server_sin.sin_port));
		ntohs(server_sin.sin6_port));
	client_fd = accept(socket_fd, &client_addr, &client_addr_len);

	inet_ntop(client_addr.sin_family, &client_addr.sin_addr, buffer,
	inet_ntop(AF_INET6, &client_addr.sin6_addr, buffer,
		  sizeof(buffer));
	fprintf(stderr, "Got connection from %s:%d\n", buffer,
		ntohs(client_addr.sin_port));
		ntohs(client_addr.sin6_port));

	while (1) {
		struct iovec iov = { .iov_base = iobuf,