From: Geliang Tang <tanggeliang@kylinos.cn>
Adds wait_for_ack() helper using TIOCOUTQ/SIOCOUTQNSD ioctls to synchronize
tests by waiting for data acknowledgment before proceeding.
These codes are from mptcp_inq.c.
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
.../selftests/net/mptcp/mptcp_sockopt.c | 42 ++++++++++++++++++-
1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index fc65157a41ee..b8e8fec8979f 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -21,11 +21,13 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/random.h>
+#include <sys/ioctl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <linux/tcp.h>
+#include <linux/sockios.h>
static int pf = AF_INET;
static int proto_tx = IPPROTO_MPTCP;
@@ -593,10 +595,43 @@ static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
do_getsockopt_mptcp_full_info(s, fd);
}
+/* wait up to timeout milliseconds */
+static void wait_for_ack(int fd, int timeout, size_t total)
+{
+ int i;
+
+ for (i = 0; i < timeout; i++) {
+ int nsd, ret, queued = -1;
+ struct timespec req;
+
+ ret = ioctl(fd, TIOCOUTQ, &queued);
+ if (ret < 0)
+ die_perror("TIOCOUTQ");
+
+ ret = ioctl(fd, SIOCOUTQNSD, &nsd);
+ if (ret < 0)
+ die_perror("SIOCOUTQNSD");
+
+ if ((size_t)queued > total)
+ xerror("TIOCOUTQ %u, but only %zu expected\n", queued, total);
+ assert(nsd <= queued);
+
+ if (queued == 0)
+ return;
+
+ /* wait for peer to ack rx of all data */
+ req.tv_sec = 0;
+ req.tv_nsec = 1 * 1000 * 1000ul; /* 1ms */
+ nanosleep(&req, NULL);
+ }
+
+ xerror("still tx data queued after %u ms\n", timeout);
+}
+
static void connect_one_server(int fd, int unixfd)
{
char buf[4096], buf2[4096];
- size_t len, i, total;
+ size_t len, i, total, sent;
struct so_state s;
bool eof = false;
ssize_t ret;
@@ -667,10 +702,13 @@ static void connect_one_server(int fd, int unixfd)
total = rand() % (16 * 1024 * 1024);
total += (1 * 1024 * 1024);
+ sent = total;
ret = write(unixfd, &total, sizeof(total));
assert(ret == (ssize_t)sizeof(total));
+ wait_for_ack(fd, 5000, len);
+
while (total > 0) {
if (total > sizeof(buf))
len = sizeof(buf);
@@ -691,6 +729,8 @@ static void connect_one_server(int fd, int unixfd)
assert(ret == 4);
assert(strncmp(buf2, "shut", 4) == 0);
+ wait_for_ack(fd, 5000, sent);
+
ret = write(fd, buf, 1);
assert(ret == 1);
close(fd);
--
2.48.1