Commit aa09b7e0 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'fix-oom-and-order-check-in-msg_zerocopy-selftest'

Zijian Zhang says:

====================
fix OOM and order check 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.

And, we find that when lock debugging is on, notifications may not come in
order. Thus, we have order checking outputs managed by cfg_verbose, to
avoid too many outputs in this case.
====================

Link: https://patch.msgid.link/20240701225349.3395580-1-zijianzhang@bytedance.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents f66738dc 7d6d8f0c
...@@ -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++;
...@@ -435,7 +438,7 @@ static bool do_recv_completion(int fd, int domain) ...@@ -435,7 +438,7 @@ static bool do_recv_completion(int fd, int domain)
/* Detect notification gaps. These should not happen often, if at all. /* Detect notification gaps. These should not happen often, if at all.
* Gaps can occur due to drops, reordering and retransmissions. * Gaps can occur due to drops, reordering and retransmissions.
*/ */
if (lo != next_completion) if (cfg_verbose && lo != next_completion)
fprintf(stderr, "gap: %u..%u does not append to %u\n", fprintf(stderr, "gap: %u..%u does not append to %u\n",
lo, hi, next_completion); lo, hi, next_completion);
next_completion = hi + 1; next_completion = hi + 1;
...@@ -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