udpgso_bench_rx supports UDP payload verification but rejects the
combination of TCP and verification mode. Its TCP receive path discards
the payload, so it cannot check the data generated by udpgso_bench_tx.

Read the TCP payload into a buffer when verification is requested
and check it against the transmitter's repeating alphabetic
pattern. Preserve the verification position across recv() calls
because TCP does not preserve send boundaries. Restart the pattern
at the payload length supplied with -l, matching the transmitter's
pattern restart on each message.

Require a nonzero -l value for TCP verification and retain the existing
discard path when verification is disabled.

Signed-off-by: shuo huang <[email protected]>
---
 tools/testing/selftests/net/udpgso_bench_rx.c | 51 +++++++++++++++----
 1 file changed, 42 insertions(+), 9 deletions(-)

diff --git a/tools/testing/selftests/net/udpgso_bench_rx.c 
b/tools/testing/selftests/net/udpgso_bench_rx.c
index 1cbadd267..5270a46d2 100644
--- a/tools/testing/selftests/net/udpgso_bench_rx.c
+++ b/tools/testing/selftests/net/udpgso_bench_rx.c
@@ -89,6 +89,11 @@ static unsigned long gettimeofday_ms(void)
        return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
 }
 
+static char expected_char(unsigned int off)
+{
+       return 'a' + (off % 26);
+}
+
 static void do_poll(int fd, int timeout_ms)
 {
        struct pollfd pfd;
@@ -161,14 +166,44 @@ static int do_socket(bool do_tcp)
        return fd;
 }
 
+static char sanitized_char(char val)
+{
+       return (val >= 'a' && val <= 'z') ? val : '.';
+}
+
+static void do_verify_tcp(const char *data, int len)
+{
+       static unsigned int stream_off;
+       int i;
+
+       for (i = 0; i < len; i++) {
+               char expected = expected_char(stream_off);
+
+               if (data[i] != expected)
+                       error(1, 0,
+                             "data[%d]: stream offset %u, %c(%hhu) != 
%c(%hhu)\n",
+                             i, stream_off,
+                             sanitized_char(data[i]), data[i],
+                             expected, expected);
+
+               stream_off++;
+               if (stream_off == cfg_expected_pkt_len)
+                       stream_off = 0;
+       }
+}
+
 /* Flush all outstanding bytes for the tcp receive queue */
 static void do_flush_tcp(int fd)
 {
+       static char rbuf[ETH_MAX_MTU];
        int ret;
 
        while (true) {
-               /* MSG_TRUNC flushes up to len bytes */
-               ret = recv(fd, NULL, 1 << 21, MSG_TRUNC | MSG_DONTWAIT);
+               if (cfg_verify)
+                       ret = recv(fd, rbuf, sizeof(rbuf), MSG_DONTWAIT);
+               else
+                       /* MSG_TRUNC flushes up to len bytes */
+                       ret = recv(fd, NULL, 1 << 21, MSG_TRUNC | MSG_DONTWAIT);
                if (ret == -1 && errno == EAGAIN)
                        return;
                if (ret == -1)
@@ -178,17 +213,15 @@ static void do_flush_tcp(int fd)
                        exit(0);
                }
 
+               if (cfg_verify)
+                       do_verify_tcp(rbuf, ret);
+
                packets++;
                bytes += ret;
        }
 
 }
 
-static char sanitized_char(char val)
-{
-       return (val >= 'a' && val <= 'z') ? val : '.';
-}
-
 static void do_verify_udp(const char *data, int len)
 {
        char cur = data[0];
@@ -347,8 +380,8 @@ static void parse_opts(int argc, char **argv)
        if (optind != argc)
                usage(argv[0]);
 
-       if (cfg_tcp && cfg_verify)
-               error(1, 0, "TODO: implement verify mode for tcp");
+       if (cfg_tcp && cfg_verify && !cfg_expected_pkt_len)
+               error(1, 0, "tcp verify mode requires -l");
 }
 
 static void do_recv(void)

base-commit: 08dbfad3f5040f5bdb6c529da20d6d4e81fefd72
-- 
2.34.1


Reply via email to