fio: fix aio trim completion latencies
[fio.git] / engines / net.c
index eb72e2eee389857346c22cbe376f1c0c7fe36c9a..ca6fb344b89786123e824dfa60eb913b4db33d6f 100644 (file)
@@ -9,28 +9,27 @@
 #include <unistd.h>
 #include <signal.h>
 #include <errno.h>
-#include <assert.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 #include <arpa/inet.h>
 #include <netdb.h>
-#include <sys/poll.h>
-#include <sys/types.h>
+#include <poll.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 
 #include "../fio.h"
 #include "../verify.h"
+#include "../optgroup.h"
 
 struct netio_data {
        int listenfd;
        int use_splice;
+       int seq_off;
        int pipes[2];
        struct sockaddr_in addr;
        struct sockaddr_in6 addr6;
        struct sockaddr_un addr_un;
-       uint64_t udp_lost;
        uint64_t udp_send_seq;
        uint64_t udp_recv_seq;
 };
@@ -56,6 +55,7 @@ struct udp_close_msg {
 struct udp_seq {
        uint64_t magic;
        uint64_t seq;
+       uint64_t bs;
 };
 
 enum {
@@ -133,6 +133,7 @@ static struct fio_option options[] = {
 #ifdef CONFIG_TCP_NODELAY
        {
                .name   = "nodelay",
+               .lname  = "No Delay",
                .type   = FIO_OPT_BOOL,
                .off1   = offsetof(struct netio_options, nodelay),
                .help   = "Use TCP_NODELAY on TCP connections",
@@ -151,6 +152,7 @@ static struct fio_option options[] = {
        },
        {
                .name   = "pingpong",
+               .lname  = "Ping Pong",
                .type   = FIO_OPT_STR_SET,
                .off1   = offsetof(struct netio_options, pingpong),
                .help   = "Ping-pong IO requests",
@@ -372,7 +374,7 @@ static int splice_io_u(int fdin, int fdout, unsigned int len)
  */
 static int splice_in(struct thread_data *td, struct io_u *io_u)
 {
-       struct netio_data *nd = td->io_ops->data;
+       struct netio_data *nd = td->io_ops_data;
 
        return splice_io_u(io_u->file->fd, nd->pipes[1], io_u->xfer_buflen);
 }
@@ -383,7 +385,7 @@ static int splice_in(struct thread_data *td, struct io_u *io_u)
 static int splice_out(struct thread_data *td, struct io_u *io_u,
                      unsigned int len)
 {
-       struct netio_data *nd = td->io_ops->data;
+       struct netio_data *nd = td->io_ops_data;
 
        return splice_io_u(nd->pipes[0], io_u->file->fd, len);
 }
@@ -421,7 +423,7 @@ static int vmsplice_io_u(struct io_u *io_u, int fd, unsigned int len)
 static int vmsplice_io_u_out(struct thread_data *td, struct io_u *io_u,
                             unsigned int len)
 {
-       struct netio_data *nd = td->io_ops->data;
+       struct netio_data *nd = td->io_ops_data;
 
        return vmsplice_io_u(io_u, nd->pipes[0], len);
 }
@@ -431,7 +433,7 @@ static int vmsplice_io_u_out(struct thread_data *td, struct io_u *io_u,
  */
 static int vmsplice_io_u_in(struct thread_data *td, struct io_u *io_u)
 {
-       struct netio_data *nd = td->io_ops->data;
+       struct netio_data *nd = td->io_ops_data;
 
        return vmsplice_io_u(io_u, nd->pipes[1], io_u->xfer_buflen);
 }
@@ -483,31 +485,46 @@ static void store_udp_seq(struct netio_data *nd, struct io_u *io_u)
 {
        struct udp_seq *us;
 
+       if (io_u->xfer_buflen < sizeof(*us))
+               return;
+
        us = io_u->xfer_buf + io_u->xfer_buflen - sizeof(*us);
-       us->magic = cpu_to_le64(FIO_UDP_SEQ_MAGIC);
+       us->magic = cpu_to_le64((uint64_t) FIO_UDP_SEQ_MAGIC);
+       us->bs = cpu_to_le64((uint64_t) io_u->xfer_buflen);
        us->seq = cpu_to_le64(nd->udp_send_seq++);
 }
 
-static void verify_udp_seq(struct netio_data *nd, struct io_u *io_u)
+static void verify_udp_seq(struct thread_data *td, struct netio_data *nd,
+                          struct io_u *io_u)
 {
        struct udp_seq *us;
        uint64_t seq;
 
+       if (io_u->xfer_buflen < sizeof(*us))
+               return;
+
+       if (nd->seq_off)
+               return;
+
        us = io_u->xfer_buf + io_u->xfer_buflen - sizeof(*us);
        if (le64_to_cpu(us->magic) != FIO_UDP_SEQ_MAGIC)
                return;
+       if (le64_to_cpu(us->bs) != io_u->xfer_buflen) {
+               nd->seq_off = 1;
+               return;
+       }
 
        seq = le64_to_cpu(us->seq);
 
        if (seq != nd->udp_recv_seq)
-               nd->udp_lost += seq - nd->udp_recv_seq;
+               td->ts.drop_io_u[io_u->ddir] += seq - nd->udp_recv_seq;
 
        nd->udp_recv_seq = seq + 1;
 }
 
 static int fio_netio_send(struct thread_data *td, struct io_u *io_u)
 {
-       struct netio_data *nd = td->io_ops->data;
+       struct netio_data *nd = td->io_ops_data;
        struct netio_options *o = td->eo;
        int ret, flags = 0;
 
@@ -552,7 +569,7 @@ static int fio_netio_send(struct thread_data *td, struct io_u *io_u)
        return ret;
 }
 
-static int is_udp_close(struct io_u *io_u, int len)
+static int is_close_msg(struct io_u *io_u, int len)
 {
        struct udp_close_msg *msg;
 
@@ -560,9 +577,9 @@ static int is_udp_close(struct io_u *io_u, int len)
                return 0;
 
        msg = io_u->xfer_buf;
-       if (ntohl(msg->magic) != FIO_LINK_OPEN_CLOSE_MAGIC)
+       if (le32_to_cpu(msg->magic) != FIO_LINK_OPEN_CLOSE_MAGIC)
                return 0;
-       if (ntohl(msg->cmd) != FIO_LINK_CLOSE)
+       if (le32_to_cpu(msg->cmd) != FIO_LINK_CLOSE)
                return 0;
 
        return 1;
@@ -570,7 +587,7 @@ static int is_udp_close(struct io_u *io_u, int len)
 
 static int fio_netio_recv(struct thread_data *td, struct io_u *io_u)
 {
-       struct netio_data *nd = td->io_ops->data;
+       struct netio_data *nd = td->io_ops_data;
        struct netio_options *o = td->eo;
        int ret, flags = 0;
 
@@ -595,13 +612,18 @@ static int fio_netio_recv(struct thread_data *td, struct io_u *io_u)
                        ret = recvfrom(io_u->file->fd, io_u->xfer_buf,
                                        io_u->xfer_buflen, flags, from, len);
 
-                       if (is_udp_close(io_u, ret)) {
+                       if (is_close_msg(io_u, ret)) {
                                td->done = 1;
                                return 0;
                        }
                } else {
                        ret = recv(io_u->file->fd, io_u->xfer_buf,
                                        io_u->xfer_buflen, flags);
+
+                       if (is_close_msg(io_u, ret)) {
+                               td->done = 1;
+                               return 0;
+                       }
                }
                if (ret > 0)
                        break;
@@ -615,15 +637,16 @@ static int fio_netio_recv(struct thread_data *td, struct io_u *io_u)
        } while (1);
 
        if (is_udp(o) && td->o.verify == VERIFY_NONE)
-               verify_udp_seq(nd, io_u);
+               verify_udp_seq(td, nd, io_u);
 
        return ret;
 }
 
-static int __fio_netio_queue(struct thread_data *td, struct io_u *io_u,
-                            enum fio_ddir ddir)
+static enum fio_q_status __fio_netio_queue(struct thread_data *td,
+                                          struct io_u *io_u,
+                                          enum fio_ddir ddir)
 {
-       struct netio_data *nd = td->io_ops->data;
+       struct netio_data *nd = td->io_ops_data;
        struct netio_options *o = td->eo;
        int ret;
 
@@ -665,7 +688,8 @@ static int __fio_netio_queue(struct thread_data *td, struct io_u *io_u,
        return FIO_Q_COMPLETED;
 }
 
-static int fio_netio_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status fio_netio_queue(struct thread_data *td,
+                                        struct io_u *io_u)
 {
        struct netio_options *o = td->eo;
        int ret;
@@ -689,7 +713,7 @@ static int fio_netio_queue(struct thread_data *td, struct io_u *io_u)
 
 static int fio_netio_connect(struct thread_data *td, struct fio_file *f)
 {
-       struct netio_data *nd = td->io_ops->data;
+       struct netio_data *nd = td->io_ops_data;
        struct netio_options *o = td->eo;
        int type, domain;
 
@@ -804,7 +828,7 @@ static int fio_netio_connect(struct thread_data *td, struct fio_file *f)
 
 static int fio_netio_accept(struct thread_data *td, struct fio_file *f)
 {
-       struct netio_data *nd = td->io_ops->data;
+       struct netio_data *nd = td->io_ops_data;
        struct netio_options *o = td->eo;
        socklen_t socklen;
        int state;
@@ -854,9 +878,9 @@ err:
        return 1;
 }
 
-static void fio_netio_udp_close(struct thread_data *td, struct fio_file *f)
+static void fio_netio_send_close(struct thread_data *td, struct fio_file *f)
 {
-       struct netio_data *nd = td->io_ops->data;
+       struct netio_data *nd = td->io_ops_data;
        struct netio_options *o = td->eo;
        struct udp_close_msg msg;
        struct sockaddr *to;
@@ -871,8 +895,8 @@ static void fio_netio_udp_close(struct thread_data *td, struct fio_file *f)
                len = sizeof(nd->addr);
        }
 
-       msg.magic = htonl(FIO_LINK_OPEN_CLOSE_MAGIC);
-       msg.cmd = htonl(FIO_LINK_CLOSE);
+       msg.magic = cpu_to_le32((uint32_t) FIO_LINK_OPEN_CLOSE_MAGIC);
+       msg.cmd = cpu_to_le32((uint32_t) FIO_LINK_CLOSE);
 
        ret = sendto(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to, len);
        if (ret < 0)
@@ -881,21 +905,17 @@ static void fio_netio_udp_close(struct thread_data *td, struct fio_file *f)
 
 static int fio_netio_close_file(struct thread_data *td, struct fio_file *f)
 {
-       struct netio_options *o = td->eo;
-
        /*
-        * If this is an UDP connection, notify the receiver that we are
-        * closing down the link
+        * Notify the receiver that we are closing down the link
         */
-       if (is_udp(o))
-               fio_netio_udp_close(td, f);
+       fio_netio_send_close(td, f);
 
        return generic_close_file(td, f);
 }
 
 static int fio_netio_udp_recv_open(struct thread_data *td, struct fio_file *f)
 {
-       struct netio_data *nd = td->io_ops->data;
+       struct netio_data *nd = td->io_ops_data;
        struct netio_options *o = td->eo;
        struct udp_close_msg msg;
        struct sockaddr *to;
@@ -927,9 +947,9 @@ static int fio_netio_udp_recv_open(struct thread_data *td, struct fio_file *f)
        return 0;
 }
 
-static int fio_netio_udp_send_open(struct thread_data *td, struct fio_file *f)
+static int fio_netio_send_open(struct thread_data *td, struct fio_file *f)
 {
-       struct netio_data *nd = td->io_ops->data;
+       struct netio_data *nd = td->io_ops_data;
        struct netio_options *o = td->eo;
        struct udp_close_msg msg;
        struct sockaddr *to;
@@ -973,7 +993,7 @@ static int fio_netio_open_file(struct thread_data *td, struct fio_file *f)
 
        if (is_udp(o)) {
                if (td_write(td))
-                       ret = fio_netio_udp_send_open(td, f);
+                       ret = fio_netio_send_open(td, f);
                else {
                        int state;
 
@@ -1031,7 +1051,7 @@ static int fio_fill_addr(struct thread_data *td, const char *host, int af,
 static int fio_netio_setup_connect_inet(struct thread_data *td,
                                        const char *host, unsigned short port)
 {
-       struct netio_data *nd = td->io_ops->data;
+       struct netio_data *nd = td->io_ops_data;
        struct netio_options *o = td->eo;
        struct addrinfo *res = NULL;
        void *dst, *src;
@@ -1081,7 +1101,7 @@ static int fio_netio_setup_connect_inet(struct thread_data *td,
 static int fio_netio_setup_connect_unix(struct thread_data *td,
                                        const char *path)
 {
-       struct netio_data *nd = td->io_ops->data;
+       struct netio_data *nd = td->io_ops_data;
        struct sockaddr_un *soun = &nd->addr_un;
 
        soun->sun_family = AF_UNIX;
@@ -1102,7 +1122,7 @@ static int fio_netio_setup_connect(struct thread_data *td)
 
 static int fio_netio_setup_listen_unix(struct thread_data *td, const char *path)
 {
-       struct netio_data *nd = td->io_ops->data;
+       struct netio_data *nd = td->io_ops_data;
        struct sockaddr_un *addr = &nd->addr_un;
        mode_t mode;
        int len, fd;
@@ -1135,7 +1155,7 @@ static int fio_netio_setup_listen_unix(struct thread_data *td, const char *path)
 
 static int fio_netio_setup_listen_inet(struct thread_data *td, short port)
 {
-       struct netio_data *nd = td->io_ops->data;
+       struct netio_data *nd = td->io_ops_data;
        struct netio_options *o = td->eo;
        struct ip_mreq mr;
        struct sockaddr_in sin;
@@ -1198,7 +1218,7 @@ static int fio_netio_setup_listen_inet(struct thread_data *td, short port)
                        return 1;
                }
                if (is_ipv6(o)) {
-                       log_err("fio: IPv6 not supported for multicast network IO");
+                       log_err("fio: IPv6 not supported for multicast network IO\n");
                        close(fd);
                        return 1;
                }
@@ -1251,7 +1271,7 @@ static int fio_netio_setup_listen_inet(struct thread_data *td, short port)
 
 static int fio_netio_setup_listen(struct thread_data *td)
 {
-       struct netio_data *nd = td->io_ops->data;
+       struct netio_data *nd = td->io_ops_data;
        struct netio_options *o = td->eo;
        int ret;
 
@@ -1297,6 +1317,8 @@ static int fio_netio_init(struct thread_data *td)
                return 1;
        }
 
+       o->port += td->subjob_number;
+
        if (!is_tcp(o)) {
                if (o->listen) {
                        log_err("fio: listen only valid for TCP proto IO\n");
@@ -1324,7 +1346,7 @@ static int fio_netio_init(struct thread_data *td)
 
 static void fio_netio_cleanup(struct thread_data *td)
 {
-       struct netio_data *nd = td->io_ops->data;
+       struct netio_data *nd = td->io_ops_data;
 
        if (nd) {
                if (nd->listenfd != -1)
@@ -1348,13 +1370,13 @@ static int fio_netio_setup(struct thread_data *td)
                td->o.open_files++;
        }
 
-       if (!td->io_ops->data) {
-               nd = malloc(sizeof(*nd));;
+       if (!td->io_ops_data) {
+               nd = malloc(sizeof(*nd));
 
                memset(nd, 0, sizeof(*nd));
                nd->listenfd = -1;
                nd->pipes[0] = nd->pipes[1] = -1;
-               td->io_ops->data = nd;
+               td->io_ops_data = nd;
        }
 
        return 0;
@@ -1372,7 +1394,7 @@ static int fio_netio_setup_splice(struct thread_data *td)
 
        fio_netio_setup(td);
 
-       nd = td->io_ops->data;
+       nd = td->io_ops_data;
        if (nd) {
                if (pipe(nd->pipes) < 0)
                        return 1;