diff options
Diffstat (limited to 'tools/testing/selftests/net')
| -rw-r--r-- | tools/testing/selftests/net/.gitignore | 50 | ||||
| -rwxr-xr-x | tools/testing/selftests/net/forwarding/router_multicast.sh | 92 | ||||
| -rwxr-xr-x | tools/testing/selftests/net/forwarding/sch_red.sh | 1 | ||||
| -rw-r--r-- | tools/testing/selftests/net/io_uring_zerocopy_tx.c | 101 | ||||
| -rwxr-xr-x | tools/testing/selftests/net/io_uring_zerocopy_tx.sh | 10 | ||||
| -rw-r--r-- | tools/testing/selftests/net/reuseport_bpf.c | 2 | 
6 files changed, 159 insertions, 97 deletions
diff --git a/tools/testing/selftests/net/.gitignore b/tools/testing/selftests/net/.gitignore index 0e5751af6247..de7d5cc15f85 100644 --- a/tools/testing/selftests/net/.gitignore +++ b/tools/testing/selftests/net/.gitignore @@ -1,42 +1,42 @@  # SPDX-License-Identifier: GPL-2.0-only +cmsg_sender +fin_ack_lat +gro +hwtstamp_config +ioam6_parser +ip_defrag  ipsec +ipv6_flowlabel +ipv6_flowlabel_mgr  msg_zerocopy -socket +nettest  psock_fanout  psock_snd  psock_tpacket -stress_reuseport_listen +reuseaddr_conflict +reuseaddr_ports_exhausted  reuseport_addr_any  reuseport_bpf  reuseport_bpf_cpu  reuseport_bpf_numa  reuseport_dualstack -reuseaddr_conflict -tcp_mmap -udpgso -udpgso_bench_rx -udpgso_bench_tx -tcp_inq -tls -txring_overwrite -ip_defrag -ipv6_flowlabel -ipv6_flowlabel_mgr -so_txtime -tcp_fastopen_backup_key -nettest -fin_ack_lat -reuseaddr_ports_exhausted -hwtstamp_config  rxtimestamp -timestamping -txtimestamp +socket  so_netns_cookie +so_txtime +stress_reuseport_listen +tap +tcp_fastopen_backup_key +tcp_inq +tcp_mmap  test_unix_oob -gro -ioam6_parser +timestamping +tls  toeplitz  tun -cmsg_sender +txring_overwrite +txtimestamp +udpgso +udpgso_bench_rx +udpgso_bench_tx  unix_connect -tap
\ No newline at end of file diff --git a/tools/testing/selftests/net/forwarding/router_multicast.sh b/tools/testing/selftests/net/forwarding/router_multicast.sh index 57e90c873a2c..5a58b1ec8aef 100755 --- a/tools/testing/selftests/net/forwarding/router_multicast.sh +++ b/tools/testing/selftests/net/forwarding/router_multicast.sh @@ -28,7 +28,7 @@  # +------------------+       +------------------+  # -ALL_TESTS="mcast_v4 mcast_v6 rpf_v4 rpf_v6" +ALL_TESTS="mcast_v4 mcast_v6 rpf_v4 rpf_v6 unres_v4 unres_v6"  NUM_NETIFS=6  source lib.sh  source tc_common.sh @@ -406,6 +406,96 @@ rpf_v6()  	log_test "RPF IPv6"  } +unres_v4() +{ +	# Send a multicast packet not corresponding to an installed route, +	# causing the kernel to queue the packet for resolution and emit an +	# IGMPMSG_NOCACHE notification. smcrouted will react to this +	# notification by consulting its (*, G) list and installing an (S, G) +	# route, which will be used to forward the queued packet. + +	RET=0 + +	tc filter add dev $h2 ingress protocol ip pref 1 handle 1 flower \ +		dst_ip 225.1.2.3 ip_proto udp dst_port 12345 action drop +	tc filter add dev $h3 ingress protocol ip pref 1 handle 1 flower \ +		dst_ip 225.1.2.3 ip_proto udp dst_port 12345 action drop + +	# Forwarding should fail before installing a matching (*, G). +	$MZ $h1 -c 1 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \ +		-a 00:11:22:33:44:55 -b 01:00:5e:01:02:03 \ +		-A 198.51.100.2 -B 225.1.2.3 -q + +	tc_check_packets "dev $h2 ingress" 1 0 +	check_err $? "Multicast received on first host when should not" +	tc_check_packets "dev $h3 ingress" 1 0 +	check_err $? "Multicast received on second host when should not" + +	# Create (*, G). Will not be installed in the kernel. +	create_mcast_sg $rp1 0.0.0.0 225.1.2.3 $rp2 $rp3 + +	$MZ $h1 -c 1 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \ +		-a 00:11:22:33:44:55 -b 01:00:5e:01:02:03 \ +		-A 198.51.100.2 -B 225.1.2.3 -q + +	tc_check_packets "dev $h2 ingress" 1 1 +	check_err $? "Multicast not received on first host" +	tc_check_packets "dev $h3 ingress" 1 1 +	check_err $? "Multicast not received on second host" + +	delete_mcast_sg $rp1 0.0.0.0 225.1.2.3 $rp2 $rp3 + +	tc filter del dev $h3 ingress protocol ip pref 1 handle 1 flower +	tc filter del dev $h2 ingress protocol ip pref 1 handle 1 flower + +	log_test "Unresolved queue IPv4" +} + +unres_v6() +{ +	# Send a multicast packet not corresponding to an installed route, +	# causing the kernel to queue the packet for resolution and emit an +	# MRT6MSG_NOCACHE notification. smcrouted will react to this +	# notification by consulting its (*, G) list and installing an (S, G) +	# route, which will be used to forward the queued packet. + +	RET=0 + +	tc filter add dev $h2 ingress protocol ipv6 pref 1 handle 1 flower \ +		dst_ip ff0e::3 ip_proto udp dst_port 12345 action drop +	tc filter add dev $h3 ingress protocol ipv6 pref 1 handle 1 flower \ +		dst_ip ff0e::3 ip_proto udp dst_port 12345 action drop + +	# Forwarding should fail before installing a matching (*, G). +	$MZ $h1 -6 -c 1 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \ +		-a 00:11:22:33:44:55 -b 33:33:00:00:00:03 \ +		-A 2001:db8:1::2 -B ff0e::3 -q + +	tc_check_packets "dev $h2 ingress" 1 0 +	check_err $? "Multicast received on first host when should not" +	tc_check_packets "dev $h3 ingress" 1 0 +	check_err $? "Multicast received on second host when should not" + +	# Create (*, G). Will not be installed in the kernel. +	create_mcast_sg $rp1 :: ff0e::3 $rp2 $rp3 + +	$MZ $h1 -6 -c 1 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \ +		-a 00:11:22:33:44:55 -b 33:33:00:00:00:03 \ +		-A 2001:db8:1::2 -B ff0e::3 -q + +	tc_check_packets "dev $h2 ingress" 1 1 +	check_err $? "Multicast not received on first host" +	tc_check_packets "dev $h3 ingress" 1 1 +	check_err $? "Multicast not received on second host" + +	delete_mcast_sg $rp1 :: ff0e::3 $rp2 $rp3 + +	tc filter del dev $h3 ingress protocol ipv6 pref 1 handle 1 flower +	tc filter del dev $h2 ingress protocol ipv6 pref 1 handle 1 flower + +	log_test "Unresolved queue IPv6" +} +  trap cleanup EXIT  setup_prepare diff --git a/tools/testing/selftests/net/forwarding/sch_red.sh b/tools/testing/selftests/net/forwarding/sch_red.sh index e714bae473fb..81f31179ac88 100755 --- a/tools/testing/selftests/net/forwarding/sch_red.sh +++ b/tools/testing/selftests/net/forwarding/sch_red.sh @@ -1,3 +1,4 @@ +#!/bin/bash  # SPDX-License-Identifier: GPL-2.0  # This test sends one stream of traffic from H1 through a TBF shaper, to a RED diff --git a/tools/testing/selftests/net/io_uring_zerocopy_tx.c b/tools/testing/selftests/net/io_uring_zerocopy_tx.c index 9d64c560a2d6..8ce48aca8321 100644 --- a/tools/testing/selftests/net/io_uring_zerocopy_tx.c +++ b/tools/testing/selftests/net/io_uring_zerocopy_tx.c @@ -47,7 +47,6 @@ enum {  	MODE_MIXED	= 3,  }; -static bool cfg_flush		= false;  static bool cfg_cork		= false;  static int  cfg_mode		= MODE_ZC_FIXED;  static int  cfg_nr_reqs		= 8; @@ -166,21 +165,6 @@ static int io_uring_register_buffers(struct io_uring *ring,  	return (ret < 0) ? -errno : ret;  } -static int io_uring_register_notifications(struct io_uring *ring, -					   unsigned nr, -					   struct io_uring_notification_slot *slots) -{ -	int ret; -	struct io_uring_notification_register r = { -		.nr_slots = nr, -		.data = (unsigned long)slots, -	}; - -	ret = syscall(__NR_io_uring_register, ring->ring_fd, -		      IORING_REGISTER_NOTIFIERS, &r, sizeof(r)); -	return (ret < 0) ? -errno : ret; -} -  static int io_uring_mmap(int fd, struct io_uring_params *p,  			 struct io_uring_sq *sq, struct io_uring_cq *cq)  { @@ -297,11 +281,10 @@ static inline void io_uring_prep_send(struct io_uring_sqe *sqe, int sockfd,  static inline void io_uring_prep_sendzc(struct io_uring_sqe *sqe, int sockfd,  				        const void *buf, size_t len, int flags, -				        unsigned slot_idx, unsigned zc_flags) +				        unsigned zc_flags)  {  	io_uring_prep_send(sqe, sockfd, buf, len, flags); -	sqe->opcode = (__u8) IORING_OP_SENDZC_NOTIF; -	sqe->notification_idx = slot_idx; +	sqe->opcode = (__u8) IORING_OP_SEND_ZC;  	sqe->ioprio = zc_flags;  } @@ -374,7 +357,6 @@ static int do_setup_tx(int domain, int type, int protocol)  static void do_tx(int domain, int type, int protocol)  { -	struct io_uring_notification_slot b[1] = {{.tag = NOTIF_TAG}};  	struct io_uring_sqe *sqe;  	struct io_uring_cqe *cqe;  	unsigned long packets = 0, bytes = 0; @@ -390,10 +372,6 @@ static void do_tx(int domain, int type, int protocol)  	if (ret)  		error(1, ret, "io_uring: queue init"); -	ret = io_uring_register_notifications(&ring, 1, b); -	if (ret) -		error(1, ret, "io_uring: tx ctx registration"); -  	iov.iov_base = payload;  	iov.iov_len = cfg_payload_len; @@ -409,9 +387,8 @@ static void do_tx(int domain, int type, int protocol)  		for (i = 0; i < cfg_nr_reqs; i++) {  			unsigned zc_flags = 0;  			unsigned buf_idx = 0; -			unsigned slot_idx = 0;  			unsigned mode = cfg_mode; -			unsigned msg_flags = 0; +			unsigned msg_flags = MSG_WAITALL;  			if (cfg_mode == MODE_MIXED)  				mode = rand() % 3; @@ -423,13 +400,10 @@ static void do_tx(int domain, int type, int protocol)  						   cfg_payload_len, msg_flags);  				sqe->user_data = NONZC_TAG;  			} else { -				if (cfg_flush) { -					zc_flags |= IORING_RECVSEND_NOTIF_FLUSH; -					compl_cqes++; -				} +				compl_cqes++;  				io_uring_prep_sendzc(sqe, fd, payload,  						     cfg_payload_len, -						     msg_flags, slot_idx, zc_flags); +						     msg_flags, zc_flags);  				if (mode == MODE_ZC_FIXED) {  					sqe->ioprio |= IORING_RECVSEND_FIXED_BUF;  					sqe->buf_index = buf_idx; @@ -442,51 +416,57 @@ static void do_tx(int domain, int type, int protocol)  		if (ret != cfg_nr_reqs)  			error(1, ret, "submit"); +		if (cfg_cork) +			do_setsockopt(fd, IPPROTO_UDP, UDP_CORK, 0);  		for (i = 0; i < cfg_nr_reqs; i++) {  			ret = io_uring_wait_cqe(&ring, &cqe);  			if (ret)  				error(1, ret, "wait cqe"); -			if (cqe->user_data == NOTIF_TAG) { +			if (cqe->user_data != NONZC_TAG && +			    cqe->user_data != ZC_TAG) +				error(1, -EINVAL, "invalid cqe->user_data"); + +			if (cqe->flags & IORING_CQE_F_NOTIF) { +				if (cqe->flags & IORING_CQE_F_MORE) +					error(1, -EINVAL, "invalid notif flags");  				compl_cqes--;  				i--; -			} else if (cqe->user_data != NONZC_TAG && -				   cqe->user_data != ZC_TAG) { -				error(1, cqe->res, "invalid user_data"); -			} else if (cqe->res <= 0 && cqe->res != -EAGAIN) { +			} else if (cqe->res <= 0) { +				if (cqe->flags & IORING_CQE_F_MORE) +					error(1, cqe->res, "more with a failed send");  				error(1, cqe->res, "send failed");  			} else { -				if (cqe->res > 0) { -					packets++; -					bytes += cqe->res; -				} -				/* failed requests don't flush */ -				if (cfg_flush && -				    cqe->res <= 0 && -				    cqe->user_data == ZC_TAG) -					compl_cqes--; +				if (cqe->user_data == ZC_TAG && +				    !(cqe->flags & IORING_CQE_F_MORE)) +					error(1, cqe->res, "missing more flag"); +				packets++; +				bytes += cqe->res;  			}  			io_uring_cqe_seen(&ring);  		} -		if (cfg_cork) -			do_setsockopt(fd, IPPROTO_UDP, UDP_CORK, 0);  	} while (gettimeofday_ms() < tstop); -	if (close(fd)) -		error(1, errno, "close"); - -	fprintf(stderr, "tx=%lu (MB=%lu), tx/s=%lu (MB/s=%lu)\n", -			packets, bytes >> 20, -			packets / (cfg_runtime_ms / 1000), -			(bytes >> 20) / (cfg_runtime_ms / 1000)); -  	while (compl_cqes) {  		ret = io_uring_wait_cqe(&ring, &cqe);  		if (ret)  			error(1, ret, "wait cqe"); +		if (cqe->flags & IORING_CQE_F_MORE) +			error(1, -EINVAL, "invalid notif flags"); +		if (!(cqe->flags & IORING_CQE_F_NOTIF)) +			error(1, -EINVAL, "missing notif flag"); +  		io_uring_cqe_seen(&ring);  		compl_cqes--;  	} + +	fprintf(stderr, "tx=%lu (MB=%lu), tx/s=%lu (MB/s=%lu)\n", +			packets, bytes >> 20, +			packets / (cfg_runtime_ms / 1000), +			(bytes >> 20) / (cfg_runtime_ms / 1000)); + +	if (close(fd)) +		error(1, errno, "close");  }  static void do_test(int domain, int type, int protocol) @@ -500,8 +480,8 @@ static void do_test(int domain, int type, int 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); +	error(1, 0, "Usage: %s (-4|-6) (udp|tcp) -D<dst_ip> [-s<payload size>] " +		    "[-t<time s>] [-n<batch>] [-p<port>] [-m<mode>]", filepath);  }  static void parse_opts(int argc, char **argv) @@ -519,7 +499,7 @@ static void parse_opts(int argc, char **argv)  		usage(argv[0]);  	cfg_payload_len = max_payload_len; -	while ((c = getopt(argc, argv, "46D:p:s:t:n:fc:m:")) != -1) { +	while ((c = getopt(argc, argv, "46D:p:s:t:n:c:m:")) != -1) {  		switch (c) {  		case '4':  			if (cfg_family != PF_UNSPEC) @@ -548,9 +528,6 @@ static void parse_opts(int argc, char **argv)  		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; @@ -583,8 +560,6 @@ static void parse_opts(int argc, char **argv)  	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]);  } diff --git a/tools/testing/selftests/net/io_uring_zerocopy_tx.sh b/tools/testing/selftests/net/io_uring_zerocopy_tx.sh index 6a65e4437640..32aa6e9dacc2 100755 --- a/tools/testing/selftests/net/io_uring_zerocopy_tx.sh +++ b/tools/testing/selftests/net/io_uring_zerocopy_tx.sh @@ -25,15 +25,11 @@ 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 +		for mode in $(seq 1 3); do +			$0 "$IP" udp -m "$mode" -t 1 -n 32 +			$0 "$IP" tcp -m "$mode" -t 1 -n 32  		done  	done diff --git a/tools/testing/selftests/net/reuseport_bpf.c b/tools/testing/selftests/net/reuseport_bpf.c index 072d709c96b4..65aea27d761c 100644 --- a/tools/testing/selftests/net/reuseport_bpf.c +++ b/tools/testing/selftests/net/reuseport_bpf.c @@ -328,7 +328,7 @@ static void test_extra_filter(const struct test_params p)  	if (bind(fd1, addr, sockaddr_size()))  		error(1, errno, "failed to bind recv socket 1"); -	if (!bind(fd2, addr, sockaddr_size()) && errno != EADDRINUSE) +	if (!bind(fd2, addr, sockaddr_size()) || errno != EADDRINUSE)  		error(1, errno, "bind socket 2 should fail with EADDRINUSE");  	free(addr);  | 
