Extend the existing the msg_zerocopy test to allow testing sendfile to ensure that notifications are generated. Signed-off-by: Joe Damato <jdamato@xxxxxxxxxx> --- tools/testing/selftests/net/msg_zerocopy.c | 54 ++++++++++++++++++++- tools/testing/selftests/net/msg_zerocopy.sh | 5 ++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/msg_zerocopy.c b/tools/testing/selftests/net/msg_zerocopy.c index 7ea5fb28c93d..20e334b25fbd 100644 --- a/tools/testing/selftests/net/msg_zerocopy.c +++ b/tools/testing/selftests/net/msg_zerocopy.c @@ -30,6 +30,7 @@ #include <arpa/inet.h> #include <error.h> #include <errno.h> +#include <fcntl.h> #include <limits.h> #include <linux/errqueue.h> #include <linux/if_packet.h> @@ -50,6 +51,7 @@ #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> +#include <sys/sendfile.h> #include <sys/socket.h> #include <sys/stat.h> #include <sys/time.h> @@ -74,6 +76,14 @@ #define MSG_ZEROCOPY 0x4000000 #endif +#ifndef SENDFILE_ZC +#define SENDFILE_ZC (0x2) +#endif + +#ifndef __NR_sendfile2 +#define __NR_sendfile2 467 +#endif + static int cfg_cork; static bool cfg_cork_mixed; static int cfg_cpu = -1; /* default: pin to last cpu */ @@ -87,6 +97,8 @@ static int cfg_verbose; static int cfg_waittime_ms = 500; static int cfg_notification_limit = 32; static bool cfg_zerocopy; +static bool cfg_sendfile; +static const char *cfg_sendfile_path; static socklen_t cfg_alen; static struct sockaddr_storage cfg_dst_addr; @@ -182,6 +194,37 @@ static void add_zcopy_cookie(struct msghdr *msg, uint32_t cookie) memcpy(CMSG_DATA(cm), &cookie, sizeof(cookie)); } +static bool do_sendfile(int fd) +{ + int from_fd = open(cfg_sendfile_path, O_RDONLY, 0); + struct stat buf; + ssize_t total = 0; + ssize_t ret = 0; + off_t off = 0; + + if (fd < 0) + error(1, errno, "couldn't open sendfile path"); + + if (fstat(from_fd, &buf)) + error(1, errno, "couldn't fstat"); + + while (total < buf.st_size) { + ret = syscall(__NR_sendfile2, fd, from_fd, &off, buf.st_size, + SENDFILE_ZC); + if (ret < 0) + error(1, errno, "unable to sendfile"); + total += ret; + sends_since_notify++; + bytes += ret; + packets++; + if (ret > 0) + expected_completions++; + } + + close(from_fd); + return total == buf.st_size; +} + static bool do_sendmsg(int fd, struct msghdr *msg, bool do_zerocopy, int domain) { int ret, len, i, flags; @@ -550,6 +593,8 @@ static void do_tx(int domain, int type, int protocol) do { if (cfg_cork) do_sendmsg_corked(fd, &msg); + else if (cfg_sendfile) + do_sendfile(fd); else do_sendmsg(fd, &msg, cfg_zerocopy, domain); @@ -715,7 +760,7 @@ static void parse_opts(int argc, char **argv) cfg_payload_len = max_payload_len; - while ((c = getopt(argc, argv, "46c:C:D:i:l:mp:rs:S:t:vz")) != -1) { + while ((c = getopt(argc, argv, "46c:C:D:i:l:mp:rs:S:t:vzf:w:")) != -1) { switch (c) { case '4': if (cfg_family != PF_UNSPEC) @@ -767,9 +812,16 @@ static void parse_opts(int argc, char **argv) case 'v': cfg_verbose++; break; + case 'f': + cfg_sendfile = true; + cfg_sendfile_path = optarg; + break; case 'z': cfg_zerocopy = true; break; + case 'w': + cfg_waittime_ms = 200 + strtoul(optarg, NULL, 10) * 1000; + break; } } diff --git a/tools/testing/selftests/net/msg_zerocopy.sh b/tools/testing/selftests/net/msg_zerocopy.sh index 89c22f5320e0..c735e4ab86b5 100755 --- a/tools/testing/selftests/net/msg_zerocopy.sh +++ b/tools/testing/selftests/net/msg_zerocopy.sh @@ -74,6 +74,7 @@ esac cleanup() { ip netns del "${NS2}" ip netns del "${NS1}" + rm -f sendfile_data } trap cleanup EXIT @@ -106,6 +107,9 @@ 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 +# create sendfile test data +dd if=/dev/zero of=sendfile_data bs=1M count=8 2> /dev/null + do_test() { local readonly ARGS="$1" @@ -118,4 +122,5 @@ do_test() { do_test "${EXTRA_ARGS}" do_test "-z ${EXTRA_ARGS}" +do_test "-z -f sendfile_data ${EXTRA_ARGS}" echo ok -- 2.43.0