selftest/net: adjust io_uring sendzc notif handling
[platform/kernel/linux-starfive.git] / tools / testing / selftests / net / io_uring_zerocopy_tx.c
index 9d64c56..1542877 100644 (file)
@@ -47,7 +47,6 @@ enum {
        MODE_MIXED      = 3,
 };
 
-static bool cfg_flush          = false;
 static bool cfg_cork           = false;
 static int  cfg_mode           = MODE_ZC_FIXED;
 static int  cfg_nr_reqs                = 8;
@@ -166,21 +165,6 @@ static int io_uring_register_buffers(struct io_uring *ring,
        return (ret < 0) ? -errno : ret;
 }
 
-static int io_uring_register_notifications(struct io_uring *ring,
-                                          unsigned nr,
-                                          struct io_uring_notification_slot *slots)
-{
-       int ret;
-       struct io_uring_notification_register r = {
-               .nr_slots = nr,
-               .data = (unsigned long)slots,
-       };
-
-       ret = syscall(__NR_io_uring_register, ring->ring_fd,
-                     IORING_REGISTER_NOTIFIERS, &r, sizeof(r));
-       return (ret < 0) ? -errno : ret;
-}
-
 static int io_uring_mmap(int fd, struct io_uring_params *p,
                         struct io_uring_sq *sq, struct io_uring_cq *cq)
 {
@@ -297,11 +281,10 @@ static inline void io_uring_prep_send(struct io_uring_sqe *sqe, int sockfd,
 
 static inline void io_uring_prep_sendzc(struct io_uring_sqe *sqe, int sockfd,
                                        const void *buf, size_t len, int flags,
-                                       unsigned slot_idx, unsigned zc_flags)
+                                       unsigned zc_flags)
 {
        io_uring_prep_send(sqe, sockfd, buf, len, flags);
-       sqe->opcode = (__u8) IORING_OP_SENDZC_NOTIF;
-       sqe->notification_idx = slot_idx;
+       sqe->opcode = (__u8) IORING_OP_SEND_ZC;
        sqe->ioprio = zc_flags;
 }
 
@@ -374,7 +357,6 @@ static int do_setup_tx(int domain, int type, int protocol)
 
 static void do_tx(int domain, int type, int protocol)
 {
-       struct io_uring_notification_slot b[1] = {{.tag = NOTIF_TAG}};
        struct io_uring_sqe *sqe;
        struct io_uring_cqe *cqe;
        unsigned long packets = 0, bytes = 0;
@@ -390,10 +372,6 @@ static void do_tx(int domain, int type, int protocol)
        if (ret)
                error(1, ret, "io_uring: queue init");
 
-       ret = io_uring_register_notifications(&ring, 1, b);
-       if (ret)
-               error(1, ret, "io_uring: tx ctx registration");
-
        iov.iov_base = payload;
        iov.iov_len = cfg_payload_len;
 
@@ -409,9 +387,8 @@ static void do_tx(int domain, int type, int protocol)
                for (i = 0; i < cfg_nr_reqs; i++) {
                        unsigned zc_flags = 0;
                        unsigned buf_idx = 0;
-                       unsigned slot_idx = 0;
                        unsigned mode = cfg_mode;
-                       unsigned msg_flags = 0;
+                       unsigned msg_flags = MSG_WAITALL;
 
                        if (cfg_mode == MODE_MIXED)
                                mode = rand() % 3;
@@ -423,13 +400,9 @@ static void do_tx(int domain, int type, int protocol)
                                                   cfg_payload_len, msg_flags);
                                sqe->user_data = NONZC_TAG;
                        } else {
-                               if (cfg_flush) {
-                                       zc_flags |= IORING_RECVSEND_NOTIF_FLUSH;
-                                       compl_cqes++;
-                               }
                                io_uring_prep_sendzc(sqe, fd, payload,
                                                     cfg_payload_len,
-                                                    msg_flags, slot_idx, zc_flags);
+                                                    msg_flags, zc_flags);
                                if (mode == MODE_ZC_FIXED) {
                                        sqe->ioprio |= IORING_RECVSEND_FIXED_BUF;
                                        sqe->buf_index = buf_idx;
@@ -442,51 +415,62 @@ static void do_tx(int domain, int type, int protocol)
                if (ret != cfg_nr_reqs)
                        error(1, ret, "submit");
 
+               if (cfg_cork)
+                       do_setsockopt(fd, IPPROTO_UDP, UDP_CORK, 0);
                for (i = 0; i < cfg_nr_reqs; i++) {
                        ret = io_uring_wait_cqe(&ring, &cqe);
                        if (ret)
                                error(1, ret, "wait cqe");
 
-                       if (cqe->user_data == NOTIF_TAG) {
+                       if (cqe->user_data != NONZC_TAG &&
+                           cqe->user_data != ZC_TAG)
+                               error(1, -EINVAL, "invalid cqe->user_data");
+
+                       if (cqe->flags & IORING_CQE_F_NOTIF) {
+                               if (cqe->flags & IORING_CQE_F_MORE)
+                                       error(1, -EINVAL, "invalid notif flags");
+                               if (compl_cqes <= 0)
+                                       error(1, -EINVAL, "notification mismatch");
                                compl_cqes--;
                                i--;
-                       } else if (cqe->user_data != NONZC_TAG &&
-                                  cqe->user_data != ZC_TAG) {
-                               error(1, cqe->res, "invalid user_data");
-                       } else if (cqe->res <= 0 && cqe->res != -EAGAIN) {
+                               io_uring_cqe_seen(&ring);
+                               continue;
+                       }
+                       if (cqe->flags & IORING_CQE_F_MORE) {
+                               if (cqe->user_data != ZC_TAG)
+                                       error(1, cqe->res, "unexpected F_MORE");
+                               compl_cqes++;
+                       }
+                       if (cqe->res >= 0) {
+                               packets++;
+                               bytes += cqe->res;
+                       } else if (cqe->res != -EAGAIN) {
                                error(1, cqe->res, "send failed");
-                       } else {
-                               if (cqe->res > 0) {
-                                       packets++;
-                                       bytes += cqe->res;
-                               }
-                               /* failed requests don't flush */
-                               if (cfg_flush &&
-                                   cqe->res <= 0 &&
-                                   cqe->user_data == ZC_TAG)
-                                       compl_cqes--;
                        }
                        io_uring_cqe_seen(&ring);
                }
-               if (cfg_cork)
-                       do_setsockopt(fd, IPPROTO_UDP, UDP_CORK, 0);
        } while (gettimeofday_ms() < tstop);
 
-       if (close(fd))
-               error(1, errno, "close");
-
-       fprintf(stderr, "tx=%lu (MB=%lu), tx/s=%lu (MB/s=%lu)\n",
-                       packets, bytes >> 20,
-                       packets / (cfg_runtime_ms / 1000),
-                       (bytes >> 20) / (cfg_runtime_ms / 1000));
-
        while (compl_cqes) {
                ret = io_uring_wait_cqe(&ring, &cqe);
                if (ret)
                        error(1, ret, "wait cqe");
+               if (cqe->flags & IORING_CQE_F_MORE)
+                       error(1, -EINVAL, "invalid notif flags");
+               if (!(cqe->flags & IORING_CQE_F_NOTIF))
+                       error(1, -EINVAL, "missing notif flag");
+
                io_uring_cqe_seen(&ring);
                compl_cqes--;
        }
+
+       fprintf(stderr, "tx=%lu (MB=%lu), tx/s=%lu (MB/s=%lu)\n",
+                       packets, bytes >> 20,
+                       packets / (cfg_runtime_ms / 1000),
+                       (bytes >> 20) / (cfg_runtime_ms / 1000));
+
+       if (close(fd))
+               error(1, errno, "close");
 }
 
 static void do_test(int domain, int type, int protocol)
@@ -500,8 +484,8 @@ static void do_test(int domain, int type, int protocol)
 
 static void usage(const char *filepath)
 {
-       error(1, 0, "Usage: %s [-f] [-n<N>] [-z0] [-s<payload size>] "
-                   "(-4|-6) [-t<time s>] -D<dst_ip> udp", filepath);
+       error(1, 0, "Usage: %s (-4|-6) (udp|tcp) -D<dst_ip> [-s<payload size>] "
+                   "[-t<time s>] [-n<batch>] [-p<port>] [-m<mode>]", filepath);
 }
 
 static void parse_opts(int argc, char **argv)
@@ -519,7 +503,7 @@ static void parse_opts(int argc, char **argv)
                usage(argv[0]);
        cfg_payload_len = max_payload_len;
 
-       while ((c = getopt(argc, argv, "46D:p:s:t:n:fc:m:")) != -1) {
+       while ((c = getopt(argc, argv, "46D:p:s:t:n:c:m:")) != -1) {
                switch (c) {
                case '4':
                        if (cfg_family != PF_UNSPEC)
@@ -548,9 +532,6 @@ static void parse_opts(int argc, char **argv)
                case 'n':
                        cfg_nr_reqs = strtoul(optarg, NULL, 0);
                        break;
-               case 'f':
-                       cfg_flush = 1;
-                       break;
                case 'c':
                        cfg_cork = strtol(optarg, NULL, 0);
                        break;
@@ -583,8 +564,6 @@ static void parse_opts(int argc, char **argv)
 
        if (cfg_payload_len > max_payload_len)
                error(1, 0, "-s: payload exceeds max (%d)", max_payload_len);
-       if (cfg_mode == MODE_NONZC && cfg_flush)
-               error(1, 0, "-f: only zerocopy modes support notifications");
        if (optind != argc - 1)
                usage(argv[0]);
 }