net.c revision 5ba13ea6968cf2773f10d34376afe28ef81aeee5
1ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe/*
2da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe * net engine
3da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe *
4da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe * IO engine that reads/writes to/from sockets.
5da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe *
6ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe */
7ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#include <stdio.h>
8ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#include <stdlib.h>
9ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#include <unistd.h>
10ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#include <errno.h>
11ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#include <assert.h>
12ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#include <netinet/in.h>
13ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#include <arpa/inet.h>
14ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#include <netdb.h>
155fdd124a3b811993542825847f207587d5f4661eJens Axboe#include <sys/poll.h>
167292056a38857ded6f7a64f11d14d642772c31bdJens Axboe#include <sys/types.h>
177292056a38857ded6f7a64f11d14d642772c31bdJens Axboe#include <sys/socket.h>
18ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
19ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#include "../fio.h"
20ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
21b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestruct netio_data {
22b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	int listenfd;
23b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	int send_to_net;
249cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int use_splice;
25414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	int net_protocol;
269cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int pipes[2];
27b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	char host[64];
28b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct sockaddr_in addr;
29b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe};
30ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
31664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboestruct udp_close_msg {
32664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	uint32_t magic;
33664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	uint32_t cmd;
34664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe};
35664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
36664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboeenum {
37664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	FIO_LINK_CLOSE = 0x89,
38664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	FIO_LINK_CLOSE_MAGIC = 0x6c696e6b,
39664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe};
40664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
41371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe/*
42371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe * Return -1 for error and 'nr events' for a positive number
43371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe * of events
44371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe */
45371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboestatic int poll_wait(struct thread_data *td, int fd, short events)
46371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe{
47371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	struct pollfd pfd;
48371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	int ret;
49371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
50371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	while (!td->terminate) {
51371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		pfd.fd = fd;
52371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		pfd.events = events;
53371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		ret = poll(&pfd, 1, -1);
54371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		if (ret < 0) {
55371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe			if (errno == EINTR)
56d5b388a560783a61af7b424757bc6dead2309c28Jens Axboe				break;
57371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
58371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe			td_verror(td, errno, "poll");
59371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe			return -1;
60371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		} else if (!ret)
61371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe			continue;
62371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
63371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		break;
64371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	}
65371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
66371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	if (pfd.revents & events)
67371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		return 1;
68371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
69371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	return -1;
70371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe}
71371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
72ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboestatic int fio_netio_prep(struct thread_data *td, struct io_u *io_u)
73ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
74b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
75ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
767a6499dada619928267d26b4629b0c8623dc423aJens Axboe	/*
777a6499dada619928267d26b4629b0c8623dc423aJens Axboe	 * Make sure we don't see spurious reads to a receiver, and vice versa
787a6499dada619928267d26b4629b0c8623dc423aJens Axboe	 */
79b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	if ((nd->send_to_net && io_u->ddir == DDIR_READ) ||
80b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	    (!nd->send_to_net && io_u->ddir == DDIR_WRITE)) {
81e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, EINVAL, "bad direction");
827a6499dada619928267d26b4629b0c8623dc423aJens Axboe		return 1;
83ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
847a6499dada619928267d26b4629b0c8623dc423aJens Axboe
85f85ac25a7d5c9d5ba4d5c73363a6a2a461a9b013Jens Axboe	return 0;
86ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
87ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
885921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#ifdef FIO_HAVE_SPLICE
89cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int splice_io_u(int fdin, int fdout, unsigned int len)
90ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
919cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int bytes = 0;
927a6499dada619928267d26b4629b0c8623dc423aJens Axboe
939cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	while (len) {
94cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		int ret = splice(fdin, NULL, fdout, NULL, len, 0);
959cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
969cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		if (ret < 0) {
979cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			if (!bytes)
989cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe				bytes = ret;
999cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
1009cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			break;
1019cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		} else if (!ret)
1029cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			break;
1039cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
1049cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		bytes += ret;
105f657a2fbbb0deaf455edc478d73b664929bcb766Jens Axboe		len -= ret;
1069cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	}
1079cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
1089cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	return bytes;
1099cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
1109cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
1119cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe/*
112cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * Receive bytes from a socket and fill them into the internal pipe
1139cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe */
114cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int splice_in(struct thread_data *td, struct io_u *io_u)
1159cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
1169cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd = td->io_ops->data;
1179cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
118cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return splice_io_u(io_u->file->fd, nd->pipes[1], io_u->xfer_buflen);
1199cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
1209cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
1219cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe/*
122cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * Transmit 'len' bytes from the internal pipe
1239cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe */
124cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int splice_out(struct thread_data *td, struct io_u *io_u,
125cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		      unsigned int len)
1269cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
1279cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd = td->io_ops->data;
128cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe
129cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return splice_io_u(nd->pipes[0], io_u->file->fd, len);
130cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe}
131cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe
132cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int vmsplice_io_u(struct io_u *io_u, int fd, unsigned int len)
133cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe{
1349cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct iovec iov = {
1359cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		.iov_base = io_u->xfer_buf,
1369cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		.iov_len = len,
1379cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	};
1389cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int bytes = 0;
1399cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
1409cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	while (iov.iov_len) {
141cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		int ret = vmsplice(fd, &iov, 1, SPLICE_F_MOVE);
1429cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
1439cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		if (ret < 0) {
1449cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			if (!bytes)
1459cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe				bytes = ret;
1469cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			break;
1479cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		} else if (!ret)
1489cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			break;
1499cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
1509cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		iov.iov_len -= ret;
151cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		iov.iov_base += ret;
152f657a2fbbb0deaf455edc478d73b664929bcb766Jens Axboe		bytes += ret;
1539cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	}
1549cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
1559cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	return bytes;
156cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe
1579cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
1589cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
1599cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe/*
160cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * vmsplice() pipe to io_u buffer
1619cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe */
162cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int vmsplice_io_u_out(struct thread_data *td, struct io_u *io_u,
163cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe			     unsigned int len)
1649cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
1659cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd = td->io_ops->data;
1669cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
167cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return vmsplice_io_u(io_u, nd->pipes[0], len);
168cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe}
1699cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
170cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe/*
171cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * vmsplice() io_u to pipe
172cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe */
173cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int vmsplice_io_u_in(struct thread_data *td, struct io_u *io_u)
174cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe{
175cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	struct netio_data *nd = td->io_ops->data;
176ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
177cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return vmsplice_io_u(io_u, nd->pipes[1], io_u->xfer_buflen);
1789cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
1799cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
180cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe/*
181cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * splice receive - transfer socket data into a pipe using splice, then map
182cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * that pipe data into the io_u using vmsplice.
183cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe */
1849cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboestatic int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
1859cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
1869cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int ret;
1879cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
1889cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	ret = splice_in(td, io_u);
189cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	if (ret > 0)
190cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		return vmsplice_io_u_out(td, io_u, ret);
1919cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
192cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return ret;
1939cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
1949cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
195cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe/*
196cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * splice transmit - map data from the io_u into a pipe by using vmsplice,
197cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * then transfer that pipe to a socket using splice.
198cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe */
1999cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboestatic int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
2009cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
2019cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int ret;
2029cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
2039cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	ret = vmsplice_io_u_in(td, io_u);
204cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	if (ret > 0)
205cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		return splice_out(td, io_u, ret);
2069cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
207cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return ret;
2089cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
2095921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#else
2105921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboestatic int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
2115921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe{
212af8771b9b91eb2cd23a40aaa729bad4f78acb928Jens Axboe	errno = EOPNOTSUPP;
2135921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe	return -1;
2145921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe}
2155921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe
2165921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboestatic int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
2175921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe{
218af8771b9b91eb2cd23a40aaa729bad4f78acb928Jens Axboe	errno = EOPNOTSUPP;
2195921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe	return -1;
2205921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe}
2215921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
2229cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
2239cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboestatic int fio_netio_send(struct thread_data *td, struct io_u *io_u)
2249cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
225414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	struct netio_data *nd = td->io_ops->data;
2268e239cae8aae89f07a885ffcc985600ce9c65d5dJens Axboe	int ret, flags = OS_MSG_DONTWAIT;
227371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
228664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	do {
229664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		if (nd->net_protocol == IPPROTO_UDP) {
23062b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe			struct sockaddr *to = (struct sockaddr *) &nd->addr;
23162b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe
232664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			ret = sendto(io_u->file->fd, io_u->xfer_buf,
23362b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe					io_u->xfer_buflen, flags, to,
23462b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe					sizeof(*to));
235664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		} else {
236664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			/*
237664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			 * if we are going to write more, set MSG_MORE
238664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			 */
2395921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#ifdef MSG_MORE
240664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			if (td->this_io_bytes[DDIR_WRITE] + io_u->xfer_buflen <
241664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			    td->o.size)
242664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe				flags |= MSG_MORE;
2435921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
244664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			ret = send(io_u->file->fd, io_u->xfer_buf,
245664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe					io_u->xfer_buflen, flags);
246664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		}
247664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		if (ret > 0)
248664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			break;
2499cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
250664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		ret = poll_wait(td, io_u->file->fd, POLLOUT);
251664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		if (ret <= 0)
252664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			break;
253664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
2548e239cae8aae89f07a885ffcc985600ce9c65d5dJens Axboe		flags &= ~OS_MSG_DONTWAIT;
255664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	} while (1);
256664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
257664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	return ret;
258664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe}
259664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
260664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboestatic int is_udp_close(struct io_u *io_u, int len)
261664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe{
262664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	struct udp_close_msg *msg;
263664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
264664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	if (len != sizeof(struct udp_close_msg))
265664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		return 0;
266664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
267664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	msg = io_u->xfer_buf;
268664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	if (ntohl(msg->magic) != FIO_LINK_CLOSE_MAGIC)
269664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		return 0;
270664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	if (ntohl(msg->cmd) != FIO_LINK_CLOSE)
271664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		return 0;
272664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
273664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	return 1;
2749cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
2759cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
276414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboestatic int fio_netio_recv(struct thread_data *td, struct io_u *io_u)
2779cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
278414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	struct netio_data *nd = td->io_ops->data;
2798e239cae8aae89f07a885ffcc985600ce9c65d5dJens Axboe	int ret, flags = OS_MSG_DONTWAIT;
280664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
281664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	do {
282664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		if (nd->net_protocol == IPPROTO_UDP) {
2835ba13ea6968cf2773f10d34376afe28ef81aeee5Jens Axboe			fio_socklen_t len = sizeof(nd->addr);
28462b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe			struct sockaddr *from = (struct sockaddr *) &nd->addr;
285664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
286664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			ret = recvfrom(io_u->file->fd, io_u->xfer_buf,
28762b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe					io_u->xfer_buflen, flags, from, &len);
288664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			if (is_udp_close(io_u, ret)) {
289664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe				td->done = 1;
290664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe				return 0;
291664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			}
292664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		} else {
293664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			ret = recv(io_u->file->fd, io_u->xfer_buf,
294664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe					io_u->xfer_buflen, flags);
295664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		}
296664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		if (ret > 0)
297664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			break;
2989cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
299664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		ret = poll_wait(td, io_u->file->fd, POLLIN);
300664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		if (ret <= 0)
301664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			break;
3028e239cae8aae89f07a885ffcc985600ce9c65d5dJens Axboe		flags &= ~OS_MSG_DONTWAIT;
303664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		flags |= MSG_WAITALL;
304664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	} while (1);
305414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
306664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	return ret;
3079cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
3089cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
3099cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboestatic int fio_netio_queue(struct thread_data *td, struct io_u *io_u)
3109cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
3119cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd = td->io_ops->data;
3129cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int ret;
3139cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
3147101d9c24abec4be58a086d85d6d92ec6e6492e9Jens Axboe	fio_ro_check(td, io_u);
3157101d9c24abec4be58a086d85d6d92ec6e6492e9Jens Axboe
3169cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	if (io_u->ddir == DDIR_WRITE) {
317414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		if (!nd->use_splice || nd->net_protocol == IPPROTO_UDP)
3189cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			ret = fio_netio_send(td, io_u);
319414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		else
320414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			ret = fio_netio_splice_out(td, io_u);
321d4f12dd05cfb2e8e7a72604cd870e10f2394914eJens Axboe	} else if (io_u->ddir == DDIR_READ) {
322414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		if (!nd->use_splice || nd->net_protocol == IPPROTO_UDP)
323414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			ret = fio_netio_recv(td, io_u);
3249cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		else
325414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			ret = fio_netio_splice_in(td, io_u);
326d4f12dd05cfb2e8e7a72604cd870e10f2394914eJens Axboe	} else
3277a6499dada619928267d26b4629b0c8623dc423aJens Axboe		ret = 0;	/* must be a SYNC */
328ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
329cec6b55da1c282b5b91ad346c7804171fccf151eJens Axboe	if (ret != (int) io_u->xfer_buflen) {
33022819ec237297fc39435ed566bee01a4225bfb39Jens Axboe		if (ret >= 0) {
331cec6b55da1c282b5b91ad346c7804171fccf151eJens Axboe			io_u->resid = io_u->xfer_buflen - ret;
332cec6b55da1c282b5b91ad346c7804171fccf151eJens Axboe			io_u->error = 0;
33336167d82e5f49dee91c6d2cd426068edee90e36fJens Axboe			return FIO_Q_COMPLETED;
334414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		} else {
335414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			int err = errno;
336414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
337414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			if (io_u->ddir == DDIR_WRITE && err == EMSGSIZE)
338414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe				return FIO_Q_BUSY;
339414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
340414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			io_u->error = err;
341414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		}
342ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
343ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
34436167d82e5f49dee91c6d2cd426068edee90e36fJens Axboe	if (io_u->error)
345e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, io_u->error, "xfer");
346ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
34736167d82e5f49dee91c6d2cd426068edee90e36fJens Axboe	return FIO_Q_COMPLETED;
348ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
349ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
350b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic int fio_netio_connect(struct thread_data *td, struct fio_file *f)
351ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
352b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
353414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	int type;
354414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
355414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	if (nd->net_protocol == IPPROTO_TCP)
356414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		type = SOCK_STREAM;
357414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	else
358414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		type = SOCK_DGRAM;
359ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
360414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	f->fd = socket(AF_INET, type, nd->net_protocol);
361b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	if (f->fd < 0) {
362b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		td_verror(td, errno, "socket");
363b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		return 1;
364ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
365ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
366414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	if (nd->net_protocol == IPPROTO_UDP)
367414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		return 0;
368414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
369b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	if (connect(f->fd, (struct sockaddr *) &nd->addr, sizeof(nd->addr)) < 0) {
370b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		td_verror(td, errno, "connect");
371b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		return 1;
372ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
373ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
374ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	return 0;
375ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
376ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
377b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic int fio_netio_accept(struct thread_data *td, struct fio_file *f)
3785fdd124a3b811993542825847f207587d5f4661eJens Axboe{
379b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
3805ba13ea6968cf2773f10d34376afe28ef81aeee5Jens Axboe	fio_socklen_t socklen = sizeof(nd->addr);
3815fdd124a3b811993542825847f207587d5f4661eJens Axboe
382414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	if (nd->net_protocol == IPPROTO_UDP) {
383414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		f->fd = nd->listenfd;
384414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		return 0;
385414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	}
386414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
3876d86144dd10b05e8b82e9b895c35dd778e5e71abJens Axboe	log_info("fio: waiting for connection\n");
3885fdd124a3b811993542825847f207587d5f4661eJens Axboe
389371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	if (poll_wait(td, nd->listenfd, POLLIN) < 0)
390371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		return 1;
3910c09442b26216aed16f758712f744a2c54726cdbJens Axboe
392371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	f->fd = accept(nd->listenfd, (struct sockaddr *) &nd->addr, &socklen);
393371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	if (f->fd < 0) {
394371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		td_verror(td, errno, "accept");
395371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		return 1;
396b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	}
3975fdd124a3b811993542825847f207587d5f4661eJens Axboe
398b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	return 0;
399b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe}
400b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
401b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic int fio_netio_open_file(struct thread_data *td, struct fio_file *f)
402b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe{
403b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	if (td_read(td))
404b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		return fio_netio_accept(td, f);
405b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	else
406b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		return fio_netio_connect(td, f);
407b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe}
408b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
409664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboestatic void fio_netio_udp_close(struct thread_data *td, struct fio_file *f)
410664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe{
411664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	struct netio_data *nd = td->io_ops->data;
412664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	struct udp_close_msg msg;
41362b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe	struct sockaddr *to = (struct sockaddr *) &nd->addr;
414664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	int ret;
415664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
416664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	msg.magic = htonl(FIO_LINK_CLOSE_MAGIC);
417664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	msg.cmd = htonl(FIO_LINK_CLOSE);
418664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
41962b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe	ret = sendto(f->fd, &msg, sizeof(msg), MSG_WAITALL, to,
420664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			sizeof(nd->addr));
421664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	if (ret < 0)
422664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		td_verror(td, errno, "sendto udp link close");
423664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe}
424664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
425664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboestatic int fio_netio_close_file(struct thread_data *td, struct fio_file *f)
426664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe{
427664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	struct netio_data *nd = td->io_ops->data;
428664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
429664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	/*
430664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	 * If this is an UDP connection, notify the receiver that we are
431664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	 * closing down the link
432664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	 */
433664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	if (nd->net_protocol == IPPROTO_UDP)
434664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		fio_netio_udp_close(td, f);
435664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
436664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	return generic_close_file(td, f);
437664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe}
438664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
439b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic int fio_netio_setup_connect(struct thread_data *td, const char *host,
440b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe				   unsigned short port)
441b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe{
442b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
443b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
444b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	nd->addr.sin_family = AF_INET;
445b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	nd->addr.sin_port = htons(port);
446b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
447b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	if (inet_aton(host, &nd->addr.sin_addr) != 1) {
448b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		struct hostent *hent;
449b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
450b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		hent = gethostbyname(host);
451b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		if (!hent) {
452b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe			td_verror(td, errno, "gethostbyname");
453b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe			return 1;
4545fdd124a3b811993542825847f207587d5f4661eJens Axboe		}
455b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
456b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		memcpy(&nd->addr.sin_addr, hent->h_addr, 4);
4575fdd124a3b811993542825847f207587d5f4661eJens Axboe	}
4585fdd124a3b811993542825847f207587d5f4661eJens Axboe
4595fdd124a3b811993542825847f207587d5f4661eJens Axboe	return 0;
4605fdd124a3b811993542825847f207587d5f4661eJens Axboe}
4615fdd124a3b811993542825847f207587d5f4661eJens Axboe
462b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic int fio_netio_setup_listen(struct thread_data *td, short port)
463ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
464b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
465414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	int fd, opt, type;
466ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
467414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	if (nd->net_protocol == IPPROTO_TCP)
468414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		type = SOCK_STREAM;
469414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	else
470414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		type = SOCK_DGRAM;
471414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
472414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	fd = socket(AF_INET, type, nd->net_protocol);
473ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	if (fd < 0) {
474e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "socket");
475ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		return 1;
476ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
477ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
478ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	opt = 1;
479ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
480e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "setsockopt");
481ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		return 1;
482ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
4836bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe#ifdef SO_REUSEPORT
4846bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe	if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0) {
485e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "setsockopt");
4866bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe		return 1;
4876bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe	}
4886bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe#endif
489ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
490b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	nd->addr.sin_family = AF_INET;
491b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	nd->addr.sin_addr.s_addr = htonl(INADDR_ANY);
492b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	nd->addr.sin_port = htons(port);
493ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
494b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	if (bind(fd, (struct sockaddr *) &nd->addr, sizeof(nd->addr)) < 0) {
495e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "bind");
496ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		return 1;
497ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
498414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	if (nd->net_protocol == IPPROTO_TCP && listen(fd, 1) < 0) {
499e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "listen");
500ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		return 1;
501ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
502ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
503b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	nd->listenfd = fd;
504b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	return 0;
505ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
506ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
5079bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboestatic int fio_netio_init(struct thread_data *td)
508ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
509b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
510443662efa60d9082bc820641e7d1d31dd58d3ae1Jens Axboe	unsigned int port;
511b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	char host[64], buf[128];
512414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	char *sep, *portp, *modep;
513af52b3455ad892322aab2791282b6bd4efdfdbf3Jens Axboe	int ret;
514ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
515413dd459a7710ba421061e840dd9ac3161c70f20Jens Axboe	if (td_rw(td)) {
516ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		log_err("fio: network connections must be read OR write\n");
517ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		return 1;
518ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
51916d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe	if (td_random(td)) {
52016d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe		log_err("fio: network IO can't be random\n");
52116d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe		return 1;
52216d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe	}
523ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
5242dc1bbeb58edc85f2829eed6729862c438ea2353Jens Axboe	strcpy(buf, td->o.filename);
525ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
5269f9214f243701626a04b4a0f9aceec03b8b40e0fJens Axboe	sep = strchr(buf, '/');
527443662efa60d9082bc820641e7d1d31dd58d3ae1Jens Axboe	if (!sep)
528443662efa60d9082bc820641e7d1d31dd58d3ae1Jens Axboe		goto bad_host;
529ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
530ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	*sep = '\0';
531ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	sep++;
532ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	strcpy(host, buf);
533443662efa60d9082bc820641e7d1d31dd58d3ae1Jens Axboe	if (!strlen(host))
534443662efa60d9082bc820641e7d1d31dd58d3ae1Jens Axboe		goto bad_host;
535443662efa60d9082bc820641e7d1d31dd58d3ae1Jens Axboe
536414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	modep = NULL;
537414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	portp = sep;
538414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	sep = strchr(portp, '/');
539414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	if (sep) {
540414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		*sep = '\0';
541414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		modep = sep + 1;
542414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	}
543414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
544414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	port = strtol(portp, NULL, 10);
545443662efa60d9082bc820641e7d1d31dd58d3ae1Jens Axboe	if (!port || port > 65535)
546443662efa60d9082bc820641e7d1d31dd58d3ae1Jens Axboe		goto bad_host;
547ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
548414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	if (modep) {
5493f8fc5ad7d36fa171559e7b94b0fd211ba2a4561Jens Axboe		if (!strncmp("tcp", modep, strlen(modep)) ||
5503f8fc5ad7d36fa171559e7b94b0fd211ba2a4561Jens Axboe		    !strncmp("TCP", modep, strlen(modep)))
551414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			nd->net_protocol = IPPROTO_TCP;
5523f8fc5ad7d36fa171559e7b94b0fd211ba2a4561Jens Axboe		else if (!strncmp("udp", modep, strlen(modep)) ||
5533f8fc5ad7d36fa171559e7b94b0fd211ba2a4561Jens Axboe			 !strncmp("UDP", modep, strlen(modep)))
554414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			nd->net_protocol = IPPROTO_UDP;
555414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		else
556414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			goto bad_host;
557414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	} else
558414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		nd->net_protocol = IPPROTO_TCP;
559414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
560413dd459a7710ba421061e840dd9ac3161c70f20Jens Axboe	if (td_read(td)) {
561b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		nd->send_to_net = 0;
562ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		ret = fio_netio_setup_listen(td, port);
563ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	} else {
564b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		nd->send_to_net = 1;
565ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		ret = fio_netio_setup_connect(td, host, port);
566ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
567ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
5687bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe	return ret;
569443662efa60d9082bc820641e7d1d31dd58d3ae1Jens Axboebad_host:
570414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	log_err("fio: bad network host/port/protocol: %s\n", td->o.filename);
571443662efa60d9082bc820641e7d1d31dd58d3ae1Jens Axboe	return 1;
572ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
573ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
574b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic void fio_netio_cleanup(struct thread_data *td)
5759bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe{
576b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
577b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
578b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	if (nd) {
57964b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe		if (nd->listenfd != -1)
58064b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe			close(nd->listenfd);
58164b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe		if (nd->pipes[0] != -1)
58264b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe			close(nd->pipes[0]);
58364b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe		if (nd->pipes[1] != -1)
58464b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe			close(nd->pipes[1]);
58564b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe
586b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		free(nd);
587b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	}
588b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe}
589b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
590b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic int fio_netio_setup(struct thread_data *td)
591b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe{
5927bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe	struct netio_data *nd;
5937bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe
5947bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe	if (!td->io_ops->data) {
5957bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe		nd = malloc(sizeof(*nd));;
5967bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe
5977bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe		memset(nd, 0, sizeof(*nd));
5987bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe		nd->listenfd = -1;
59964b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe		nd->pipes[0] = nd->pipes[1] = -1;
6007bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe		td->io_ops->data = nd;
6017bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe	}
602b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
6039bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe	return 0;
6049bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe}
6059bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe
6065921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#ifdef FIO_HAVE_SPLICE
6079cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboestatic int fio_netio_setup_splice(struct thread_data *td)
6089cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
6099cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd;
6109cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
6119cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	fio_netio_setup(td);
6129cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
6139cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	nd = td->io_ops->data;
6149cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	if (nd) {
6159cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		if (pipe(nd->pipes) < 0)
6169cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			return 1;
6179cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
6189cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		nd->use_splice = 1;
6199cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		return 0;
6209cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	}
6219cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
6229cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	return 1;
6239cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
6249cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
6255921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboestatic struct ioengine_ops ioengine_splice = {
6265921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe	.name		= "netsplice",
627ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	.version	= FIO_IOOPS_VERSION,
628ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	.prep		= fio_netio_prep,
629ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	.queue		= fio_netio_queue,
6305921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe	.setup		= fio_netio_setup_splice,
6319bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe	.init		= fio_netio_init,
632b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	.cleanup	= fio_netio_cleanup,
633b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	.open_file	= fio_netio_open_file,
634b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	.close_file	= generic_close_file,
635ad830ed7386eff264bdb5189675d6dfa672bd16bJens Axboe	.flags		= FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR |
63603e20d687566753b90383571e5e152c5142bdffdBruce Cran			  FIO_SIGTERM | FIO_PIPEIO,
637ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe};
6385921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
639ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
6405921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboestatic struct ioengine_ops ioengine_rw = {
6415921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe	.name		= "net",
6429cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	.version	= FIO_IOOPS_VERSION,
6439cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	.prep		= fio_netio_prep,
6449cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	.queue		= fio_netio_queue,
6455921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe	.setup		= fio_netio_setup,
6469cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	.init		= fio_netio_init,
6479cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	.cleanup	= fio_netio_cleanup,
6489cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	.open_file	= fio_netio_open_file,
649664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	.close_file	= fio_netio_close_file,
650ad830ed7386eff264bdb5189675d6dfa672bd16bJens Axboe	.flags		= FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR |
65103e20d687566753b90383571e5e152c5142bdffdBruce Cran			  FIO_SIGTERM | FIO_PIPEIO,
6529cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe};
6539cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
654ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboestatic void fio_init fio_netio_register(void)
655ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
6569cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	register_ioengine(&ioengine_rw);
6575921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#ifdef FIO_HAVE_SPLICE
6589cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	register_ioengine(&ioengine_splice);
6595921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
660ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
661ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
662ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboestatic void fio_exit fio_netio_unregister(void)
663ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
6649cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	unregister_ioengine(&ioengine_rw);
6655921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#ifdef FIO_HAVE_SPLICE
6669cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	unregister_ioengine(&ioengine_splice);
6675921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
668ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
669