net.c revision f5cc3d0ea8acf13c8e722da6c2d485889968d132
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>
170fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe#include <sys/stat.h>
187292056a38857ded6f7a64f11d14d642772c31bdJens Axboe#include <sys/socket.h>
190fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe#include <sys/un.h>
20ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
21ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#include "../fio.h"
22ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
23b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestruct netio_data {
24b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	int listenfd;
259cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int use_splice;
269cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int pipes[2];
27b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct sockaddr_in addr;
280fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	struct sockaddr_un addr_un;
29b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe};
30ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
31de890a1e48d40238dac69f302708dde8719de240Steven Langstruct netio_options {
32de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct thread_data *td;
33de890a1e48d40238dac69f302708dde8719de240Steven Lang	unsigned int port;
34de890a1e48d40238dac69f302708dde8719de240Steven Lang	unsigned int proto;
35de890a1e48d40238dac69f302708dde8719de240Steven Lang	unsigned int listen;
36de890a1e48d40238dac69f302708dde8719de240Steven Lang};
37de890a1e48d40238dac69f302708dde8719de240Steven Lang
38664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboestruct udp_close_msg {
39664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	uint32_t magic;
40664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	uint32_t cmd;
41664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe};
42664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
43664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboeenum {
44664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	FIO_LINK_CLOSE = 0x89,
45664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	FIO_LINK_CLOSE_MAGIC = 0x6c696e6b,
460fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
470fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	FIO_TYPE_TCP	= 1,
480fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	FIO_TYPE_UDP	= 2,
490fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	FIO_TYPE_UNIX	= 3,
50664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe};
51664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
52de890a1e48d40238dac69f302708dde8719de240Steven Langstatic int str_hostname_cb(void *data, const char *input);
53de890a1e48d40238dac69f302708dde8719de240Steven Langstatic struct fio_option options[] = {
54de890a1e48d40238dac69f302708dde8719de240Steven Lang	{
55de890a1e48d40238dac69f302708dde8719de240Steven Lang		.name	= "hostname",
56de890a1e48d40238dac69f302708dde8719de240Steven Lang		.type	= FIO_OPT_STR_STORE,
57de890a1e48d40238dac69f302708dde8719de240Steven Lang		.cb	= str_hostname_cb,
58de890a1e48d40238dac69f302708dde8719de240Steven Lang		.help	= "Hostname for net IO engine",
59de890a1e48d40238dac69f302708dde8719de240Steven Lang	},
60de890a1e48d40238dac69f302708dde8719de240Steven Lang	{
61de890a1e48d40238dac69f302708dde8719de240Steven Lang		.name	= "port",
62de890a1e48d40238dac69f302708dde8719de240Steven Lang		.type	= FIO_OPT_INT,
63de890a1e48d40238dac69f302708dde8719de240Steven Lang		.off1	= offsetof(struct netio_options, port),
64de890a1e48d40238dac69f302708dde8719de240Steven Lang		.minval	= 1,
65de890a1e48d40238dac69f302708dde8719de240Steven Lang		.maxval	= 65535,
66de890a1e48d40238dac69f302708dde8719de240Steven Lang		.help	= "Port to use for TCP or UDP net connections",
67de890a1e48d40238dac69f302708dde8719de240Steven Lang	},
68de890a1e48d40238dac69f302708dde8719de240Steven Lang	{
69de890a1e48d40238dac69f302708dde8719de240Steven Lang		.name	= "protocol",
70de890a1e48d40238dac69f302708dde8719de240Steven Lang		.alias	= "proto",
71de890a1e48d40238dac69f302708dde8719de240Steven Lang		.type	= FIO_OPT_STR,
72de890a1e48d40238dac69f302708dde8719de240Steven Lang		.off1	= offsetof(struct netio_options, proto),
73de890a1e48d40238dac69f302708dde8719de240Steven Lang		.help	= "Network protocol to use",
74de890a1e48d40238dac69f302708dde8719de240Steven Lang		.def	= "tcp",
75de890a1e48d40238dac69f302708dde8719de240Steven Lang		.posval = {
76de890a1e48d40238dac69f302708dde8719de240Steven Lang			  { .ival = "tcp",
77de890a1e48d40238dac69f302708dde8719de240Steven Lang			    .oval = FIO_TYPE_TCP,
78de890a1e48d40238dac69f302708dde8719de240Steven Lang			    .help = "Transmission Control Protocol",
79de890a1e48d40238dac69f302708dde8719de240Steven Lang			  },
80de890a1e48d40238dac69f302708dde8719de240Steven Lang			  { .ival = "udp",
81de890a1e48d40238dac69f302708dde8719de240Steven Lang			    .oval = FIO_TYPE_UDP,
82f5cc3d0ea8acf13c8e722da6c2d485889968d132Bruce Cran			    .help = "User Datagram Protocol",
83de890a1e48d40238dac69f302708dde8719de240Steven Lang			  },
84de890a1e48d40238dac69f302708dde8719de240Steven Lang			  { .ival = "unix",
85de890a1e48d40238dac69f302708dde8719de240Steven Lang			    .oval = FIO_TYPE_UNIX,
86de890a1e48d40238dac69f302708dde8719de240Steven Lang			    .help = "UNIX domain socket",
87de890a1e48d40238dac69f302708dde8719de240Steven Lang			  },
88de890a1e48d40238dac69f302708dde8719de240Steven Lang		},
89de890a1e48d40238dac69f302708dde8719de240Steven Lang	},
90de890a1e48d40238dac69f302708dde8719de240Steven Lang	{
91de890a1e48d40238dac69f302708dde8719de240Steven Lang		.name	= "listen",
92de890a1e48d40238dac69f302708dde8719de240Steven Lang		.type	= FIO_OPT_STR_SET,
93de890a1e48d40238dac69f302708dde8719de240Steven Lang		.off1	= offsetof(struct netio_options, listen),
94de890a1e48d40238dac69f302708dde8719de240Steven Lang		.help	= "Listen for incoming TCP connections",
95de890a1e48d40238dac69f302708dde8719de240Steven Lang	},
96de890a1e48d40238dac69f302708dde8719de240Steven Lang	{
97de890a1e48d40238dac69f302708dde8719de240Steven Lang		.name	= NULL,
98de890a1e48d40238dac69f302708dde8719de240Steven Lang	},
99de890a1e48d40238dac69f302708dde8719de240Steven Lang};
100de890a1e48d40238dac69f302708dde8719de240Steven Lang
101371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe/*
102371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe * Return -1 for error and 'nr events' for a positive number
103371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe * of events
104371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe */
105371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboestatic int poll_wait(struct thread_data *td, int fd, short events)
106371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe{
107371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	struct pollfd pfd;
108371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	int ret;
109371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
110371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	while (!td->terminate) {
111371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		pfd.fd = fd;
112371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		pfd.events = events;
113371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		ret = poll(&pfd, 1, -1);
114371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		if (ret < 0) {
115371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe			if (errno == EINTR)
116d5b388a560783a61af7b424757bc6dead2309c28Jens Axboe				break;
117371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
118371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe			td_verror(td, errno, "poll");
119371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe			return -1;
120371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		} else if (!ret)
121371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe			continue;
122371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
123371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		break;
124371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	}
125371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
126371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	if (pfd.revents & events)
127371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		return 1;
128371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
129371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	return -1;
130371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe}
131371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
132ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboestatic int fio_netio_prep(struct thread_data *td, struct io_u *io_u)
133ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
134de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
135ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
1367a6499dada619928267d26b4629b0c8623dc423aJens Axboe	/*
1377a6499dada619928267d26b4629b0c8623dc423aJens Axboe	 * Make sure we don't see spurious reads to a receiver, and vice versa
1387a6499dada619928267d26b4629b0c8623dc423aJens Axboe	 */
139de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->proto == FIO_TYPE_TCP)
140de890a1e48d40238dac69f302708dde8719de240Steven Lang		return 0;
141de890a1e48d40238dac69f302708dde8719de240Steven Lang
142de890a1e48d40238dac69f302708dde8719de240Steven Lang	if ((o->listen && io_u->ddir == DDIR_WRITE) ||
143de890a1e48d40238dac69f302708dde8719de240Steven Lang	    (!o->listen && io_u->ddir == DDIR_READ)) {
144e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, EINVAL, "bad direction");
1457a6499dada619928267d26b4629b0c8623dc423aJens Axboe		return 1;
146ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
1477a6499dada619928267d26b4629b0c8623dc423aJens Axboe
148f85ac25a7d5c9d5ba4d5c73363a6a2a461a9b013Jens Axboe	return 0;
149ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
150ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
1515921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#ifdef FIO_HAVE_SPLICE
152cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int splice_io_u(int fdin, int fdout, unsigned int len)
153ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
1549cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int bytes = 0;
1557a6499dada619928267d26b4629b0c8623dc423aJens Axboe
1569cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	while (len) {
157cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		int ret = splice(fdin, NULL, fdout, NULL, len, 0);
1589cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
1599cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		if (ret < 0) {
1609cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			if (!bytes)
1619cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe				bytes = ret;
1629cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
1639cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			break;
1649cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		} else if (!ret)
1659cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			break;
1669cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
1679cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		bytes += ret;
168f657a2fbbb0deaf455edc478d73b664929bcb766Jens Axboe		len -= ret;
1699cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	}
1709cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
1719cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	return bytes;
1729cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
1739cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
1749cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe/*
175cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * Receive bytes from a socket and fill them into the internal pipe
1769cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe */
177cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int splice_in(struct thread_data *td, struct io_u *io_u)
1789cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
1799cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd = td->io_ops->data;
1809cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
181cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return splice_io_u(io_u->file->fd, nd->pipes[1], io_u->xfer_buflen);
1829cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
1839cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
1849cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe/*
185cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * Transmit 'len' bytes from the internal pipe
1869cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe */
187cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int splice_out(struct thread_data *td, struct io_u *io_u,
188cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		      unsigned int len)
1899cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
1909cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd = td->io_ops->data;
191cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe
192cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return splice_io_u(nd->pipes[0], io_u->file->fd, len);
193cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe}
194cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe
195cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int vmsplice_io_u(struct io_u *io_u, int fd, unsigned int len)
196cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe{
1979cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct iovec iov = {
1989cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		.iov_base = io_u->xfer_buf,
1999cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		.iov_len = len,
2009cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	};
2019cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int bytes = 0;
2029cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
2039cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	while (iov.iov_len) {
204cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		int ret = vmsplice(fd, &iov, 1, SPLICE_F_MOVE);
2059cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
2069cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		if (ret < 0) {
2079cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			if (!bytes)
2089cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe				bytes = ret;
2099cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			break;
2109cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		} else if (!ret)
2119cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			break;
2129cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
2139cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		iov.iov_len -= ret;
214cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		iov.iov_base += ret;
215f657a2fbbb0deaf455edc478d73b664929bcb766Jens Axboe		bytes += ret;
2169cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	}
2179cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
2189cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	return bytes;
219cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe
2209cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
2219cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
2229cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe/*
223cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * vmsplice() pipe to io_u buffer
2249cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe */
225cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int vmsplice_io_u_out(struct thread_data *td, struct io_u *io_u,
226cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe			     unsigned int len)
2279cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
2289cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd = td->io_ops->data;
2299cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
230cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return vmsplice_io_u(io_u, nd->pipes[0], len);
231cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe}
2329cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
233cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe/*
234cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * vmsplice() io_u to pipe
235cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe */
236cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int vmsplice_io_u_in(struct thread_data *td, struct io_u *io_u)
237cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe{
238cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	struct netio_data *nd = td->io_ops->data;
239ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
240cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return vmsplice_io_u(io_u, nd->pipes[1], io_u->xfer_buflen);
2419cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
2429cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
243cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe/*
244cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * splice receive - transfer socket data into a pipe using splice, then map
245cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * that pipe data into the io_u using vmsplice.
246cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe */
2479cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboestatic int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
2489cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
2499cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int ret;
2509cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
2519cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	ret = splice_in(td, io_u);
252cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	if (ret > 0)
253cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		return vmsplice_io_u_out(td, io_u, ret);
2549cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
255cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return ret;
2569cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
2579cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
258cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe/*
259cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * splice transmit - map data from the io_u into a pipe by using vmsplice,
260cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * then transfer that pipe to a socket using splice.
261cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe */
2629cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboestatic int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
2639cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
2649cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int ret;
2659cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
2669cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	ret = vmsplice_io_u_in(td, io_u);
267cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	if (ret > 0)
268cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		return splice_out(td, io_u, ret);
2699cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
270cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return ret;
2719cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
2725921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#else
2735921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboestatic int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
2745921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe{
275af8771b9b91eb2cd23a40aaa729bad4f78acb928Jens Axboe	errno = EOPNOTSUPP;
2765921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe	return -1;
2775921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe}
2785921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe
2795921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboestatic int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
2805921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe{
281af8771b9b91eb2cd23a40aaa729bad4f78acb928Jens Axboe	errno = EOPNOTSUPP;
2825921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe	return -1;
2835921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe}
2845921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
2859cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
2869cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboestatic int fio_netio_send(struct thread_data *td, struct io_u *io_u)
2879cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
288414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	struct netio_data *nd = td->io_ops->data;
289de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
2908e239cae8aae89f07a885ffcc985600ce9c65d5dJens Axboe	int ret, flags = OS_MSG_DONTWAIT;
291371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
292664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	do {
293de890a1e48d40238dac69f302708dde8719de240Steven Lang		if (o->proto == FIO_TYPE_UDP) {
29462b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe			struct sockaddr *to = (struct sockaddr *) &nd->addr;
29562b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe
296664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			ret = sendto(io_u->file->fd, io_u->xfer_buf,
29762b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe					io_u->xfer_buflen, flags, to,
29862b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe					sizeof(*to));
299664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		} else {
300664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			/*
301664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			 * if we are going to write more, set MSG_MORE
302664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			 */
3035921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#ifdef MSG_MORE
304664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			if (td->this_io_bytes[DDIR_WRITE] + io_u->xfer_buflen <
305664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			    td->o.size)
306664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe				flags |= MSG_MORE;
3075921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
308664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			ret = send(io_u->file->fd, io_u->xfer_buf,
309664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe					io_u->xfer_buflen, flags);
310664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		}
311664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		if (ret > 0)
312664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			break;
3139cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
314664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		ret = poll_wait(td, io_u->file->fd, POLLOUT);
315664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		if (ret <= 0)
316664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			break;
317664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
3188e239cae8aae89f07a885ffcc985600ce9c65d5dJens Axboe		flags &= ~OS_MSG_DONTWAIT;
319664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	} while (1);
320664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
321664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	return ret;
322664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe}
323664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
324664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboestatic int is_udp_close(struct io_u *io_u, int len)
325664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe{
326664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	struct udp_close_msg *msg;
327664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
328664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	if (len != sizeof(struct udp_close_msg))
329664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		return 0;
330664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
331664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	msg = io_u->xfer_buf;
332664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	if (ntohl(msg->magic) != FIO_LINK_CLOSE_MAGIC)
333664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		return 0;
334664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	if (ntohl(msg->cmd) != FIO_LINK_CLOSE)
335664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		return 0;
336664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
337664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	return 1;
3389cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
3399cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
340414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboestatic int fio_netio_recv(struct thread_data *td, struct io_u *io_u)
3419cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
342414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	struct netio_data *nd = td->io_ops->data;
343de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
3448e239cae8aae89f07a885ffcc985600ce9c65d5dJens Axboe	int ret, flags = OS_MSG_DONTWAIT;
345664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
346664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	do {
347de890a1e48d40238dac69f302708dde8719de240Steven Lang		if (o->proto == FIO_TYPE_UDP) {
3485ba13ea6968cf2773f10d34376afe28ef81aeee5Jens Axboe			fio_socklen_t len = sizeof(nd->addr);
34962b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe			struct sockaddr *from = (struct sockaddr *) &nd->addr;
350664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
351664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			ret = recvfrom(io_u->file->fd, io_u->xfer_buf,
35262b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe					io_u->xfer_buflen, flags, from, &len);
353664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			if (is_udp_close(io_u, ret)) {
354664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe				td->done = 1;
355664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe				return 0;
356664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			}
357664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		} else {
358664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			ret = recv(io_u->file->fd, io_u->xfer_buf,
359664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe					io_u->xfer_buflen, flags);
360664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		}
361664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		if (ret > 0)
362664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			break;
3639cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
364664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		ret = poll_wait(td, io_u->file->fd, POLLIN);
365664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		if (ret <= 0)
366664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			break;
3678e239cae8aae89f07a885ffcc985600ce9c65d5dJens Axboe		flags &= ~OS_MSG_DONTWAIT;
368664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		flags |= MSG_WAITALL;
369664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	} while (1);
370414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
371664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	return ret;
3729cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
3739cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
3749cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboestatic int fio_netio_queue(struct thread_data *td, struct io_u *io_u)
3759cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
3769cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd = td->io_ops->data;
377de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
3789cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int ret;
3799cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
3807101d9c24abec4be58a086d85d6d92ec6e6492e9Jens Axboe	fio_ro_check(td, io_u);
3817101d9c24abec4be58a086d85d6d92ec6e6492e9Jens Axboe
3829cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	if (io_u->ddir == DDIR_WRITE) {
383de890a1e48d40238dac69f302708dde8719de240Steven Lang		if (!nd->use_splice || o->proto == FIO_TYPE_UDP ||
384de890a1e48d40238dac69f302708dde8719de240Steven Lang		    o->proto == FIO_TYPE_UNIX)
3859cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			ret = fio_netio_send(td, io_u);
386414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		else
387414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			ret = fio_netio_splice_out(td, io_u);
388d4f12dd05cfb2e8e7a72604cd870e10f2394914eJens Axboe	} else if (io_u->ddir == DDIR_READ) {
389de890a1e48d40238dac69f302708dde8719de240Steven Lang		if (!nd->use_splice || o->proto == FIO_TYPE_UDP ||
390de890a1e48d40238dac69f302708dde8719de240Steven Lang		    o->proto == FIO_TYPE_UNIX)
391414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			ret = fio_netio_recv(td, io_u);
3929cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		else
393414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			ret = fio_netio_splice_in(td, io_u);
394d4f12dd05cfb2e8e7a72604cd870e10f2394914eJens Axboe	} else
3957a6499dada619928267d26b4629b0c8623dc423aJens Axboe		ret = 0;	/* must be a SYNC */
396ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
397cec6b55da1c282b5b91ad346c7804171fccf151eJens Axboe	if (ret != (int) io_u->xfer_buflen) {
39822819ec237297fc39435ed566bee01a4225bfb39Jens Axboe		if (ret >= 0) {
399cec6b55da1c282b5b91ad346c7804171fccf151eJens Axboe			io_u->resid = io_u->xfer_buflen - ret;
400cec6b55da1c282b5b91ad346c7804171fccf151eJens Axboe			io_u->error = 0;
40136167d82e5f49dee91c6d2cd426068edee90e36fJens Axboe			return FIO_Q_COMPLETED;
402414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		} else {
403414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			int err = errno;
404414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
405414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			if (io_u->ddir == DDIR_WRITE && err == EMSGSIZE)
406414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe				return FIO_Q_BUSY;
407414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
408414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			io_u->error = err;
409414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		}
410ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
411ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
41236167d82e5f49dee91c6d2cd426068edee90e36fJens Axboe	if (io_u->error)
413e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, io_u->error, "xfer");
414ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
41536167d82e5f49dee91c6d2cd426068edee90e36fJens Axboe	return FIO_Q_COMPLETED;
416ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
417ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
418b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic int fio_netio_connect(struct thread_data *td, struct fio_file *f)
419ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
420b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
421de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
4220fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	int type, domain;
423414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
424de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->proto == FIO_TYPE_TCP) {
4250fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		domain = AF_INET;
426414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		type = SOCK_STREAM;
427de890a1e48d40238dac69f302708dde8719de240Steven Lang	} else if (o->proto == FIO_TYPE_UDP) {
4280fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		domain = AF_INET;
429414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		type = SOCK_DGRAM;
430de890a1e48d40238dac69f302708dde8719de240Steven Lang	} else if (o->proto == FIO_TYPE_UNIX) {
4310fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		domain = AF_UNIX;
4320fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		type = SOCK_STREAM;
4330fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	} else {
434de890a1e48d40238dac69f302708dde8719de240Steven Lang		log_err("fio: bad network type %d\n", o->proto);
4350fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		f->fd = -1;
4360fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		return 1;
4370fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	}
438ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
4390fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	f->fd = socket(domain, type, 0);
440b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	if (f->fd < 0) {
441b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		td_verror(td, errno, "socket");
442b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		return 1;
443ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
444ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
445de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->proto == FIO_TYPE_UDP)
446414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		return 0;
447de890a1e48d40238dac69f302708dde8719de240Steven Lang	else if (o->proto == FIO_TYPE_TCP) {
4480fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		fio_socklen_t len = sizeof(nd->addr);
449414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
4500fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		if (connect(f->fd, (struct sockaddr *) &nd->addr, len) < 0) {
4510fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe			td_verror(td, errno, "connect");
452b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe			close(f->fd);
4530fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe			return 1;
4540fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		}
4550fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	} else {
4560fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		struct sockaddr_un *addr = &nd->addr_un;
4570fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		fio_socklen_t len;
4580fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
4590fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		len = sizeof(addr->sun_family) + strlen(addr->sun_path) + 1;
4600fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
4610fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		if (connect(f->fd, (struct sockaddr *) addr, len) < 0) {
4620fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe			td_verror(td, errno, "connect");
463b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe			close(f->fd);
4640fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe			return 1;
4650fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		}
466ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
467ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
468ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	return 0;
469ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
470ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
471b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic int fio_netio_accept(struct thread_data *td, struct fio_file *f)
4725fdd124a3b811993542825847f207587d5f4661eJens Axboe{
473b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
474de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
4755ba13ea6968cf2773f10d34376afe28ef81aeee5Jens Axboe	fio_socklen_t socklen = sizeof(nd->addr);
4765fdd124a3b811993542825847f207587d5f4661eJens Axboe
477de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->proto == FIO_TYPE_UDP) {
478414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		f->fd = nd->listenfd;
479414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		return 0;
480414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	}
481414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
4826d86144dd10b05e8b82e9b895c35dd778e5e71abJens Axboe	log_info("fio: waiting for connection\n");
4835fdd124a3b811993542825847f207587d5f4661eJens Axboe
484371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	if (poll_wait(td, nd->listenfd, POLLIN) < 0)
485371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		return 1;
4860c09442b26216aed16f758712f744a2c54726cdbJens Axboe
487371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	f->fd = accept(nd->listenfd, (struct sockaddr *) &nd->addr, &socklen);
488371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	if (f->fd < 0) {
489371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		td_verror(td, errno, "accept");
490371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		return 1;
491b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	}
4925fdd124a3b811993542825847f207587d5f4661eJens Axboe
493b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	return 0;
494b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe}
495b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
496b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic int fio_netio_open_file(struct thread_data *td, struct fio_file *f)
497b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe{
4980fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	int ret;
499991802b8a8857c3e8b8d54ae5b0dda589369fec1Yufei Ren	struct netio_options *o = td->eo;
5000fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
501991802b8a8857c3e8b8d54ae5b0dda589369fec1Yufei Ren	if (o->listen)
5020fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		ret = fio_netio_accept(td, f);
503b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	else
5040fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		ret = fio_netio_connect(td, f);
5050fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
5060fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	if (ret)
5070fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		f->fd = -1;
5080fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	return ret;
509b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe}
510b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
511664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboestatic void fio_netio_udp_close(struct thread_data *td, struct fio_file *f)
512664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe{
513664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	struct netio_data *nd = td->io_ops->data;
514664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	struct udp_close_msg msg;
51562b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe	struct sockaddr *to = (struct sockaddr *) &nd->addr;
516664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	int ret;
517664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
518664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	msg.magic = htonl(FIO_LINK_CLOSE_MAGIC);
519664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	msg.cmd = htonl(FIO_LINK_CLOSE);
520664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
52162b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe	ret = sendto(f->fd, &msg, sizeof(msg), MSG_WAITALL, to,
522664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			sizeof(nd->addr));
523664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	if (ret < 0)
524664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		td_verror(td, errno, "sendto udp link close");
525664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe}
526664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
527664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboestatic int fio_netio_close_file(struct thread_data *td, struct fio_file *f)
528664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe{
529de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
530664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
531664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	/*
532664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	 * If this is an UDP connection, notify the receiver that we are
533664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	 * closing down the link
534664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	 */
535de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->proto == FIO_TYPE_UDP)
536664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		fio_netio_udp_close(td, f);
537664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
538664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	return generic_close_file(td, f);
539664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe}
540664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
5410fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboestatic int fio_netio_setup_connect_inet(struct thread_data *td,
5420fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe					const char *host, unsigned short port)
543b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe{
544b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
545b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
546b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	nd->addr.sin_family = AF_INET;
547b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	nd->addr.sin_port = htons(port);
548b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
549b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	if (inet_aton(host, &nd->addr.sin_addr) != 1) {
550b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		struct hostent *hent;
551b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
552b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		hent = gethostbyname(host);
553b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		if (!hent) {
554b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe			td_verror(td, errno, "gethostbyname");
555b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe			return 1;
5565fdd124a3b811993542825847f207587d5f4661eJens Axboe		}
557b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
558b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		memcpy(&nd->addr.sin_addr, hent->h_addr, 4);
5595fdd124a3b811993542825847f207587d5f4661eJens Axboe	}
5605fdd124a3b811993542825847f207587d5f4661eJens Axboe
5615fdd124a3b811993542825847f207587d5f4661eJens Axboe	return 0;
5625fdd124a3b811993542825847f207587d5f4661eJens Axboe}
5635fdd124a3b811993542825847f207587d5f4661eJens Axboe
5640fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboestatic int fio_netio_setup_connect_unix(struct thread_data *td,
5650fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe					const char *path)
5660fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe{
5670fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	struct netio_data *nd = td->io_ops->data;
5680fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	struct sockaddr_un *soun = &nd->addr_un;
5690fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
5700fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	soun->sun_family = AF_UNIX;
5710fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	strcpy(soun->sun_path, path);
5720fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	return 0;
5730fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe}
5740fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
575de890a1e48d40238dac69f302708dde8719de240Steven Langstatic int fio_netio_setup_connect(struct thread_data *td)
5760fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe{
577de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
5780fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
579de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->proto == FIO_TYPE_UDP || o->proto == FIO_TYPE_TCP)
580de890a1e48d40238dac69f302708dde8719de240Steven Lang		return fio_netio_setup_connect_inet(td, td->o.filename,o->port);
5810fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	else
582de890a1e48d40238dac69f302708dde8719de240Steven Lang		return fio_netio_setup_connect_unix(td, td->o.filename);
5830fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe}
5840fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
5850fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboestatic int fio_netio_setup_listen_unix(struct thread_data *td, const char *path)
5860fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe{
5870fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	struct netio_data *nd = td->io_ops->data;
5880fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	struct sockaddr_un *addr = &nd->addr_un;
5890fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	mode_t mode;
5900fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	int len, fd;
5910fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
5920fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	fd = socket(AF_UNIX, SOCK_STREAM, 0);
5930fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	if (fd < 0) {
5940fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		log_err("fio: socket: %s\n", strerror(errno));
5950fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		return -1;
5960fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	}
5970fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
5980fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	mode = umask(000);
5990fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
6000fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	memset(addr, 0, sizeof(*addr));
6010fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	addr->sun_family = AF_UNIX;
6020fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	strcpy(addr->sun_path, path);
6030fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	unlink(path);
6040fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
6050fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	len = sizeof(addr->sun_family) + strlen(path) + 1;
6060fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
6070fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	if (bind(fd, (struct sockaddr *) addr, len) < 0) {
6080fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		log_err("fio: bind: %s\n", strerror(errno));
609b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe		close(fd);
6100fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		return -1;
6110fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	}
6120fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
6130fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	umask(mode);
6140fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	nd->listenfd = fd;
6150fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	return 0;
6160fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe}
6170fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
6180fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboestatic int fio_netio_setup_listen_inet(struct thread_data *td, short port)
619ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
620b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
621de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
622414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	int fd, opt, type;
623ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
624de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->proto == FIO_TYPE_TCP)
625414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		type = SOCK_STREAM;
626414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	else
627414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		type = SOCK_DGRAM;
628414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
6290fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	fd = socket(AF_INET, type, 0);
630ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	if (fd < 0) {
631e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "socket");
632ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		return 1;
633ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
634ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
635ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	opt = 1;
636ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
637e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "setsockopt");
638ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		return 1;
639ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
6406bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe#ifdef SO_REUSEPORT
6416bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe	if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0) {
642e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "setsockopt");
6436bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe		return 1;
6446bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe	}
6456bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe#endif
646ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
647b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	nd->addr.sin_family = AF_INET;
648b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	nd->addr.sin_addr.s_addr = htonl(INADDR_ANY);
649b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	nd->addr.sin_port = htons(port);
650ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
651b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	if (bind(fd, (struct sockaddr *) &nd->addr, sizeof(nd->addr)) < 0) {
652e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "bind");
653ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		return 1;
654ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
6550fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
6560fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	nd->listenfd = fd;
6570fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	return 0;
6580fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe}
6590fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
660de890a1e48d40238dac69f302708dde8719de240Steven Langstatic int fio_netio_setup_listen(struct thread_data *td)
6610fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe{
6620fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	struct netio_data *nd = td->io_ops->data;
663de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
6640fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	int ret;
6650fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
666de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->proto == FIO_TYPE_UDP || o->proto == FIO_TYPE_TCP)
667de890a1e48d40238dac69f302708dde8719de240Steven Lang		ret = fio_netio_setup_listen_inet(td, o->port);
6680fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	else
669de890a1e48d40238dac69f302708dde8719de240Steven Lang		ret = fio_netio_setup_listen_unix(td, td->o.filename);
6700fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
6710fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	if (ret)
6720fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		return ret;
673de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->proto == FIO_TYPE_UDP)
6740fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		return 0;
6750fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
6760fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	if (listen(nd->listenfd, 10) < 0) {
677e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "listen");
6780fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		nd->listenfd = -1;
679ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		return 1;
680ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
681ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
682b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	return 0;
683ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
684ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
6859bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboestatic int fio_netio_init(struct thread_data *td)
686ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
687de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
688af52b3455ad892322aab2791282b6bd4efdfdbf3Jens Axboe	int ret;
689ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
69016d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe	if (td_random(td)) {
69116d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe		log_err("fio: network IO can't be random\n");
69216d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe		return 1;
69316d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe	}
694ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
695de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->proto == FIO_TYPE_UNIX && o->port) {
696de890a1e48d40238dac69f302708dde8719de240Steven Lang		log_err("fio: network IO port not valid with unix socket\n");
697de890a1e48d40238dac69f302708dde8719de240Steven Lang		return 1;
698de890a1e48d40238dac69f302708dde8719de240Steven Lang	} else if (o->proto != FIO_TYPE_UNIX && !o->port) {
699de890a1e48d40238dac69f302708dde8719de240Steven Lang		log_err("fio: network IO requires port for tcp or udp\n");
700de890a1e48d40238dac69f302708dde8719de240Steven Lang		return 1;
701de890a1e48d40238dac69f302708dde8719de240Steven Lang	}
702ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
703de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->proto != FIO_TYPE_TCP) {
704de890a1e48d40238dac69f302708dde8719de240Steven Lang		if (o->listen) {
7059b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe			log_err("fio: listen only valid for TCP proto IO\n");
7069b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe			return 1;
707de890a1e48d40238dac69f302708dde8719de240Steven Lang		}
708de890a1e48d40238dac69f302708dde8719de240Steven Lang		if (td_rw(td)) {
7099b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe			log_err("fio: datagram network connections must be"
710de890a1e48d40238dac69f302708dde8719de240Steven Lang				   " read OR write\n");
7119b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe			return 1;
7129b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe		}
7139b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe		if (o->proto == FIO_TYPE_UNIX && !td->o.filename) {
7149b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe			log_err("fio: UNIX sockets need host/filename\n");
7159b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe			return 1;
716de890a1e48d40238dac69f302708dde8719de240Steven Lang		}
717de890a1e48d40238dac69f302708dde8719de240Steven Lang		o->listen = td_read(td);
718de890a1e48d40238dac69f302708dde8719de240Steven Lang	}
719443662efa60d9082bc820641e7d1d31dd58d3ae1Jens Axboe
720de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->proto != FIO_TYPE_UNIX && o->listen && td->o.filename) {
721de890a1e48d40238dac69f302708dde8719de240Steven Lang		log_err("fio: hostname not valid for inbound network IO\n");
722de890a1e48d40238dac69f302708dde8719de240Steven Lang		return 1;
723414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	}
7240fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
725de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->listen)
726de890a1e48d40238dac69f302708dde8719de240Steven Lang		ret = fio_netio_setup_listen(td);
7270fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	else
728de890a1e48d40238dac69f302708dde8719de240Steven Lang		ret = fio_netio_setup_connect(td);
729ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
7307bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe	return ret;
731ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
732ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
733b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic void fio_netio_cleanup(struct thread_data *td)
7349bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe{
735b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
736b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
737b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	if (nd) {
73864b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe		if (nd->listenfd != -1)
73964b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe			close(nd->listenfd);
74064b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe		if (nd->pipes[0] != -1)
74164b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe			close(nd->pipes[0]);
74264b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe		if (nd->pipes[1] != -1)
74364b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe			close(nd->pipes[1]);
74464b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe
745b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		free(nd);
746b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	}
747b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe}
748b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
749b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic int fio_netio_setup(struct thread_data *td)
750b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe{
7517bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe	struct netio_data *nd;
7527bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe
753de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (!td->files_index) {
754de890a1e48d40238dac69f302708dde8719de240Steven Lang		add_file(td, td->o.filename ?: "net");
755de890a1e48d40238dac69f302708dde8719de240Steven Lang		td->o.nr_files = td->o.nr_files ?: 1;
756de890a1e48d40238dac69f302708dde8719de240Steven Lang	}
757de890a1e48d40238dac69f302708dde8719de240Steven Lang
7587bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe	if (!td->io_ops->data) {
7597bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe		nd = malloc(sizeof(*nd));;
7607bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe
7617bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe		memset(nd, 0, sizeof(*nd));
7627bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe		nd->listenfd = -1;
76364b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe		nd->pipes[0] = nd->pipes[1] = -1;
7647bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe		td->io_ops->data = nd;
7657bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe	}
766b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
7679bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe	return 0;
7689bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe}
7699bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe
7705921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#ifdef FIO_HAVE_SPLICE
7719cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboestatic int fio_netio_setup_splice(struct thread_data *td)
7729cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
7739cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd;
7749cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
7759cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	fio_netio_setup(td);
7769cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
7779cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	nd = td->io_ops->data;
7789cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	if (nd) {
7799cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		if (pipe(nd->pipes) < 0)
7809cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			return 1;
7819cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
7829cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		nd->use_splice = 1;
7839cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		return 0;
7849cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	}
7859cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
7869cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	return 1;
7879cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
7889cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
7895921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboestatic struct ioengine_ops ioengine_splice = {
790de890a1e48d40238dac69f302708dde8719de240Steven Lang	.name			= "netsplice",
791de890a1e48d40238dac69f302708dde8719de240Steven Lang	.version		= FIO_IOOPS_VERSION,
792de890a1e48d40238dac69f302708dde8719de240Steven Lang	.prep			= fio_netio_prep,
793de890a1e48d40238dac69f302708dde8719de240Steven Lang	.queue			= fio_netio_queue,
794de890a1e48d40238dac69f302708dde8719de240Steven Lang	.setup			= fio_netio_setup_splice,
795de890a1e48d40238dac69f302708dde8719de240Steven Lang	.init			= fio_netio_init,
796de890a1e48d40238dac69f302708dde8719de240Steven Lang	.cleanup		= fio_netio_cleanup,
797de890a1e48d40238dac69f302708dde8719de240Steven Lang	.open_file		= fio_netio_open_file,
798de890a1e48d40238dac69f302708dde8719de240Steven Lang	.close_file		= generic_close_file,
799de890a1e48d40238dac69f302708dde8719de240Steven Lang	.options		= options,
800de890a1e48d40238dac69f302708dde8719de240Steven Lang	.option_struct_size	= sizeof(struct netio_options),
801de890a1e48d40238dac69f302708dde8719de240Steven Lang	.flags			= FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR |
802de890a1e48d40238dac69f302708dde8719de240Steven Lang				  FIO_SIGTERM | FIO_PIPEIO,
803ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe};
8045921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
805ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
8065921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboestatic struct ioengine_ops ioengine_rw = {
807de890a1e48d40238dac69f302708dde8719de240Steven Lang	.name			= "net",
808de890a1e48d40238dac69f302708dde8719de240Steven Lang	.version		= FIO_IOOPS_VERSION,
809de890a1e48d40238dac69f302708dde8719de240Steven Lang	.prep			= fio_netio_prep,
810de890a1e48d40238dac69f302708dde8719de240Steven Lang	.queue			= fio_netio_queue,
811de890a1e48d40238dac69f302708dde8719de240Steven Lang	.setup			= fio_netio_setup,
812de890a1e48d40238dac69f302708dde8719de240Steven Lang	.init			= fio_netio_init,
813de890a1e48d40238dac69f302708dde8719de240Steven Lang	.cleanup		= fio_netio_cleanup,
814de890a1e48d40238dac69f302708dde8719de240Steven Lang	.open_file		= fio_netio_open_file,
815de890a1e48d40238dac69f302708dde8719de240Steven Lang	.close_file		= fio_netio_close_file,
816de890a1e48d40238dac69f302708dde8719de240Steven Lang	.options		= options,
817de890a1e48d40238dac69f302708dde8719de240Steven Lang	.option_struct_size	= sizeof(struct netio_options),
818de890a1e48d40238dac69f302708dde8719de240Steven Lang	.flags			= FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR |
819de890a1e48d40238dac69f302708dde8719de240Steven Lang				  FIO_SIGTERM | FIO_PIPEIO,
8209cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe};
8219cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
822de890a1e48d40238dac69f302708dde8719de240Steven Langstatic int str_hostname_cb(void *data, const char *input)
823de890a1e48d40238dac69f302708dde8719de240Steven Lang{
824de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = data;
825de890a1e48d40238dac69f302708dde8719de240Steven Lang
826de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->td->o.filename)
827de890a1e48d40238dac69f302708dde8719de240Steven Lang		free(o->td->o.filename);
828de890a1e48d40238dac69f302708dde8719de240Steven Lang	o->td->o.filename = strdup(input);
829de890a1e48d40238dac69f302708dde8719de240Steven Lang	return 0;
830de890a1e48d40238dac69f302708dde8719de240Steven Lang}
831de890a1e48d40238dac69f302708dde8719de240Steven Lang
832ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboestatic void fio_init fio_netio_register(void)
833ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
8349cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	register_ioengine(&ioengine_rw);
8355921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#ifdef FIO_HAVE_SPLICE
8369cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	register_ioengine(&ioengine_splice);
8375921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
838ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
839ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
840ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboestatic void fio_exit fio_netio_unregister(void)
841ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
8429cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	unregister_ioengine(&ioengine_rw);
8435921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#ifdef FIO_HAVE_SPLICE
8449cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	unregister_ioengine(&ioengine_splice);
8455921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
846ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
847