+ return bytes;
+
+}
+
+/*
+ * vmsplice() pipe to io_u buffer
+ */
+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;
+
+ return vmsplice_io_u(io_u, nd->pipes[0], len);
+}
+
+/*
+ * vmsplice() io_u to pipe
+ */
+static int vmsplice_io_u_in(struct thread_data *td, struct io_u *io_u)
+{
+ struct netio_data *nd = td->io_ops->data;
+
+ return vmsplice_io_u(io_u, nd->pipes[1], io_u->xfer_buflen);
+}
+
+/*
+ * splice receive - transfer socket data into a pipe using splice, then map
+ * that pipe data into the io_u using vmsplice.
+ */
+static int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
+{
+ int ret;
+
+ ret = splice_in(td, io_u);
+ if (ret > 0)
+ return vmsplice_io_u_out(td, io_u, ret);
+
+ return ret;
+}
+
+/*
+ * splice transmit - map data from the io_u into a pipe by using vmsplice,
+ * then transfer that pipe to a socket using splice.
+ */
+static int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
+{
+ int ret;
+
+ ret = vmsplice_io_u_in(td, io_u);
+ if (ret > 0)
+ return splice_out(td, io_u, ret);
+
+ return ret;
+}
+#else
+static int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+#endif
+
+static int fio_netio_send(struct thread_data *td, struct io_u *io_u)
+{
+ struct netio_data *nd = td->io_ops->data;
+ struct netio_options *o = td->eo;
+ int ret, flags = OS_MSG_DONTWAIT;
+
+ do {
+ if (o->proto == FIO_TYPE_UDP) {
+ struct sockaddr *to = (struct sockaddr *) &nd->addr;
+
+ ret = sendto(io_u->file->fd, io_u->xfer_buf,
+ io_u->xfer_buflen, flags, to,
+ sizeof(*to));
+ } else {
+ /*
+ * if we are going to write more, set MSG_MORE
+ */
+#ifdef MSG_MORE
+ if (td->this_io_bytes[DDIR_WRITE] + io_u->xfer_buflen <
+ td->o.size)
+ flags |= MSG_MORE;
+#endif
+ ret = send(io_u->file->fd, io_u->xfer_buf,
+ io_u->xfer_buflen, flags);
+ }
+ if (ret > 0)
+ break;
+
+ ret = poll_wait(td, io_u->file->fd, POLLOUT);
+ if (ret <= 0)
+ break;
+
+ flags &= ~OS_MSG_DONTWAIT;
+ } while (1);
+
+ return ret;
+}
+
+static int is_udp_close(struct io_u *io_u, int len)
+{
+ struct udp_close_msg *msg;
+
+ if (len != sizeof(struct udp_close_msg))
+ return 0;
+
+ msg = io_u->xfer_buf;
+ if (ntohl(msg->magic) != FIO_LINK_CLOSE_MAGIC)