Commit af2b7e5b authored by Zijian Zhang's avatar Zijian Zhang Committed by Jakub Kicinski

selftests: fix OOM in msg_zerocopy selftest

In selftests/net/msg_zerocopy.c, it has a while loop keeps calling sendmsg
on a socket with MSG_ZEROCOPY flag, and it will recv the notifications
until the socket is not writable. Typically, it will start the receiving
process after around 30+ sendmsgs. However, as the introduction of commit
dfa2f048 ("tcp: get rid of sysctl_tcp_adv_win_scale"), the sender is
always writable and does not get any chance to run recv notifications.
The selftest always exits with OUT_OF_MEMORY because the memory used by
opt_skb exceeds the net.core.optmem_max. Meanwhile, it could be set to a
different value to trigger OOM on older kernels too.

Thus, we introduce "cfg_notification_limit" to force sender to receive
notifications after some number of sendmsgs.

Fixes: 07b65c5b ("test: add msg_zerocopy test")
Signed-off-by: default avatarZijian Zhang <zijianzhang@bytedance.com>
Signed-off-by: default avatarXiaochun Lu <xiaochun.lu@bytedance.com>
Reviewed-by: default avatarWillem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20240701225349.3395580-2-zijianzhang@bytedance.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent f66738dc
...@@ -85,6 +85,7 @@ static bool cfg_rx; ...@@ -85,6 +85,7 @@ static bool cfg_rx;
static int cfg_runtime_ms = 4200; static int cfg_runtime_ms = 4200;
static int cfg_verbose; static int cfg_verbose;
static int cfg_waittime_ms = 500; static int cfg_waittime_ms = 500;
static int cfg_notification_limit = 32;
static bool cfg_zerocopy; static bool cfg_zerocopy;
static socklen_t cfg_alen; static socklen_t cfg_alen;
...@@ -95,6 +96,7 @@ static char payload[IP_MAXPACKET]; ...@@ -95,6 +96,7 @@ static char payload[IP_MAXPACKET];
static long packets, bytes, completions, expected_completions; static long packets, bytes, completions, expected_completions;
static int zerocopied = -1; static int zerocopied = -1;
static uint32_t next_completion; static uint32_t next_completion;
static uint32_t sends_since_notify;
static unsigned long gettimeofday_ms(void) static unsigned long gettimeofday_ms(void)
{ {
...@@ -208,6 +210,7 @@ static bool do_sendmsg(int fd, struct msghdr *msg, bool do_zerocopy, int domain) ...@@ -208,6 +210,7 @@ static bool do_sendmsg(int fd, struct msghdr *msg, bool do_zerocopy, int domain)
error(1, errno, "send"); error(1, errno, "send");
if (cfg_verbose && ret != len) if (cfg_verbose && ret != len)
fprintf(stderr, "send: ret=%u != %u\n", ret, len); fprintf(stderr, "send: ret=%u != %u\n", ret, len);
sends_since_notify++;
if (len) { if (len) {
packets++; packets++;
...@@ -460,6 +463,7 @@ static bool do_recv_completion(int fd, int domain) ...@@ -460,6 +463,7 @@ static bool do_recv_completion(int fd, int domain)
static void do_recv_completions(int fd, int domain) static void do_recv_completions(int fd, int domain)
{ {
while (do_recv_completion(fd, domain)) {} while (do_recv_completion(fd, domain)) {}
sends_since_notify = 0;
} }
/* Wait for all remaining completions on the errqueue */ /* Wait for all remaining completions on the errqueue */
...@@ -549,6 +553,9 @@ static void do_tx(int domain, int type, int protocol) ...@@ -549,6 +553,9 @@ static void do_tx(int domain, int type, int protocol)
else else
do_sendmsg(fd, &msg, cfg_zerocopy, domain); do_sendmsg(fd, &msg, cfg_zerocopy, domain);
if (cfg_zerocopy && sends_since_notify >= cfg_notification_limit)
do_recv_completions(fd, domain);
while (!do_poll(fd, POLLOUT)) { while (!do_poll(fd, POLLOUT)) {
if (cfg_zerocopy) if (cfg_zerocopy)
do_recv_completions(fd, domain); do_recv_completions(fd, domain);
...@@ -708,7 +715,7 @@ static void parse_opts(int argc, char **argv) ...@@ -708,7 +715,7 @@ static void parse_opts(int argc, char **argv)
cfg_payload_len = max_payload_len; cfg_payload_len = max_payload_len;
while ((c = getopt(argc, argv, "46c:C:D:i:mp:rs:S:t:vz")) != -1) { while ((c = getopt(argc, argv, "46c:C:D:i:l:mp:rs:S:t:vz")) != -1) {
switch (c) { switch (c) {
case '4': case '4':
if (cfg_family != PF_UNSPEC) if (cfg_family != PF_UNSPEC)
...@@ -736,6 +743,9 @@ static void parse_opts(int argc, char **argv) ...@@ -736,6 +743,9 @@ static void parse_opts(int argc, char **argv)
if (cfg_ifindex == 0) if (cfg_ifindex == 0)
error(1, errno, "invalid iface: %s", optarg); error(1, errno, "invalid iface: %s", optarg);
break; break;
case 'l':
cfg_notification_limit = strtoul(optarg, NULL, 0);
break;
case 'm': case 'm':
cfg_cork_mixed = true; cfg_cork_mixed = true;
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment