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>
10842805f55b6dd021edbb5259a775c148ef18fa9cSteven Noonan#include <signal.h>
11ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#include <errno.h>
12ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#include <assert.h>
13ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#include <netinet/in.h>
1470a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan#include <netinet/tcp.h>
15ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#include <arpa/inet.h>
16ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#include <netdb.h>
175fdd124a3b811993542825847f207587d5f4661eJens Axboe#include <sys/poll.h>
187292056a38857ded6f7a64f11d14d642772c31bdJens Axboe#include <sys/types.h>
190fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe#include <sys/stat.h>
207292056a38857ded6f7a64f11d14d642772c31bdJens Axboe#include <sys/socket.h>
210fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe#include <sys/un.h>
22ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
23ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#include "../fio.h"
24ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
25b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestruct netio_data {
26b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	int listenfd;
279cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int use_splice;
289cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int pipes[2];
29b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct sockaddr_in addr;
3049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	struct sockaddr_in6 addr6;
310fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	struct sockaddr_un addr_un;
32b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe};
33ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
34de890a1e48d40238dac69f302708dde8719de240Steven Langstruct netio_options {
35de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct thread_data *td;
36de890a1e48d40238dac69f302708dde8719de240Steven Lang	unsigned int port;
37de890a1e48d40238dac69f302708dde8719de240Steven Lang	unsigned int proto;
38de890a1e48d40238dac69f302708dde8719de240Steven Lang	unsigned int listen;
396f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	unsigned int pingpong;
4070a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan	unsigned int nodelay;
41d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer	unsigned int ttl;
42f16b7405fff7c3fc1da421b6bdf8552cc99c3156Bruce Cran	char *intfc;
43de890a1e48d40238dac69f302708dde8719de240Steven Lang};
44de890a1e48d40238dac69f302708dde8719de240Steven Lang
45664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboestruct udp_close_msg {
46664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	uint32_t magic;
47664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	uint32_t cmd;
48664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe};
49664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
50664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboeenum {
51664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	FIO_LINK_CLOSE = 0x89,
52b96d243044023b28731341d290943b5d47a5f794Jens Axboe	FIO_LINK_OPEN_CLOSE_MAGIC = 0x6c696e6b,
53b96d243044023b28731341d290943b5d47a5f794Jens Axboe	FIO_LINK_OPEN = 0x98,
540fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
550fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	FIO_TYPE_TCP	= 1,
560fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	FIO_TYPE_UDP	= 2,
570fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	FIO_TYPE_UNIX	= 3,
5849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	FIO_TYPE_TCP_V6	= 4,
5949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	FIO_TYPE_UDP_V6	= 5,
60664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe};
61664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
62de890a1e48d40238dac69f302708dde8719de240Steven Langstatic int str_hostname_cb(void *data, const char *input);
63de890a1e48d40238dac69f302708dde8719de240Steven Langstatic struct fio_option options[] = {
64de890a1e48d40238dac69f302708dde8719de240Steven Lang	{
65de890a1e48d40238dac69f302708dde8719de240Steven Lang		.name	= "hostname",
66e8b0e958cd219cabb1154e2b06036863a7d6dbd7Jens Axboe		.lname	= "net engine hostname",
67de890a1e48d40238dac69f302708dde8719de240Steven Lang		.type	= FIO_OPT_STR_STORE,
68de890a1e48d40238dac69f302708dde8719de240Steven Lang		.cb	= str_hostname_cb,
69de890a1e48d40238dac69f302708dde8719de240Steven Lang		.help	= "Hostname for net IO engine",
70e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.category = FIO_OPT_C_ENGINE,
71e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.group	= FIO_OPT_G_NETIO,
72de890a1e48d40238dac69f302708dde8719de240Steven Lang	},
73de890a1e48d40238dac69f302708dde8719de240Steven Lang	{
74de890a1e48d40238dac69f302708dde8719de240Steven Lang		.name	= "port",
75e8b0e958cd219cabb1154e2b06036863a7d6dbd7Jens Axboe		.lname	= "net engine port",
76de890a1e48d40238dac69f302708dde8719de240Steven Lang		.type	= FIO_OPT_INT,
77de890a1e48d40238dac69f302708dde8719de240Steven Lang		.off1	= offsetof(struct netio_options, port),
78de890a1e48d40238dac69f302708dde8719de240Steven Lang		.minval	= 1,
79de890a1e48d40238dac69f302708dde8719de240Steven Lang		.maxval	= 65535,
80de890a1e48d40238dac69f302708dde8719de240Steven Lang		.help	= "Port to use for TCP or UDP net connections",
81e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.category = FIO_OPT_C_ENGINE,
82e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.group	= FIO_OPT_G_NETIO,
83de890a1e48d40238dac69f302708dde8719de240Steven Lang	},
84de890a1e48d40238dac69f302708dde8719de240Steven Lang	{
85de890a1e48d40238dac69f302708dde8719de240Steven Lang		.name	= "protocol",
86e8b0e958cd219cabb1154e2b06036863a7d6dbd7Jens Axboe		.lname	= "net engine protocol",
87de890a1e48d40238dac69f302708dde8719de240Steven Lang		.alias	= "proto",
88de890a1e48d40238dac69f302708dde8719de240Steven Lang		.type	= FIO_OPT_STR,
89de890a1e48d40238dac69f302708dde8719de240Steven Lang		.off1	= offsetof(struct netio_options, proto),
90de890a1e48d40238dac69f302708dde8719de240Steven Lang		.help	= "Network protocol to use",
91de890a1e48d40238dac69f302708dde8719de240Steven Lang		.def	= "tcp",
92de890a1e48d40238dac69f302708dde8719de240Steven Lang		.posval = {
93de890a1e48d40238dac69f302708dde8719de240Steven Lang			  { .ival = "tcp",
94de890a1e48d40238dac69f302708dde8719de240Steven Lang			    .oval = FIO_TYPE_TCP,
95de890a1e48d40238dac69f302708dde8719de240Steven Lang			    .help = "Transmission Control Protocol",
96de890a1e48d40238dac69f302708dde8719de240Steven Lang			  },
97eb2323108392e65ab7c4e4c5cbd74a1597b60187Jens Axboe#ifdef CONFIG_IPV6
9849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			  { .ival = "tcpv6",
9949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			    .oval = FIO_TYPE_TCP_V6,
10049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			    .help = "Transmission Control Protocol V6",
10149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			  },
102eb2323108392e65ab7c4e4c5cbd74a1597b60187Jens Axboe#endif
103de890a1e48d40238dac69f302708dde8719de240Steven Lang			  { .ival = "udp",
104de890a1e48d40238dac69f302708dde8719de240Steven Lang			    .oval = FIO_TYPE_UDP,
105f5cc3d0ea8acf13c8e722da6c2d485889968d132Bruce Cran			    .help = "User Datagram Protocol",
106de890a1e48d40238dac69f302708dde8719de240Steven Lang			  },
107eb2323108392e65ab7c4e4c5cbd74a1597b60187Jens Axboe#ifdef CONFIG_IPV6
10849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			  { .ival = "udpv6",
10949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			    .oval = FIO_TYPE_UDP_V6,
11049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			    .help = "User Datagram Protocol V6",
11149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			  },
112eb2323108392e65ab7c4e4c5cbd74a1597b60187Jens Axboe#endif
113de890a1e48d40238dac69f302708dde8719de240Steven Lang			  { .ival = "unix",
114de890a1e48d40238dac69f302708dde8719de240Steven Lang			    .oval = FIO_TYPE_UNIX,
115de890a1e48d40238dac69f302708dde8719de240Steven Lang			    .help = "UNIX domain socket",
116de890a1e48d40238dac69f302708dde8719de240Steven Lang			  },
117de890a1e48d40238dac69f302708dde8719de240Steven Lang		},
118e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.category = FIO_OPT_C_ENGINE,
119e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.group	= FIO_OPT_G_NETIO,
120de890a1e48d40238dac69f302708dde8719de240Steven Lang	},
1211eafa37ac57bb08ca21af8ab76bd7848ae2e7c97Jens Axboe#ifdef CONFIG_TCP_NODELAY
122de890a1e48d40238dac69f302708dde8719de240Steven Lang	{
12370a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan		.name	= "nodelay",
12470a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan		.type	= FIO_OPT_BOOL,
12570a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan		.off1	= offsetof(struct netio_options, nodelay),
12670a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan		.help	= "Use TCP_NODELAY on TCP connections",
127e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.category = FIO_OPT_C_ENGINE,
128e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.group	= FIO_OPT_G_NETIO,
12970a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan	},
1301eafa37ac57bb08ca21af8ab76bd7848ae2e7c97Jens Axboe#endif
131de890a1e48d40238dac69f302708dde8719de240Steven Lang	{
132de890a1e48d40238dac69f302708dde8719de240Steven Lang		.name	= "listen",
133e8b0e958cd219cabb1154e2b06036863a7d6dbd7Jens Axboe		.lname	= "net engine listen",
134de890a1e48d40238dac69f302708dde8719de240Steven Lang		.type	= FIO_OPT_STR_SET,
135de890a1e48d40238dac69f302708dde8719de240Steven Lang		.off1	= offsetof(struct netio_options, listen),
136de890a1e48d40238dac69f302708dde8719de240Steven Lang		.help	= "Listen for incoming TCP connections",
137e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.category = FIO_OPT_C_ENGINE,
138e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.group	= FIO_OPT_G_NETIO,
139de890a1e48d40238dac69f302708dde8719de240Steven Lang	},
140de890a1e48d40238dac69f302708dde8719de240Steven Lang	{
1416f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe		.name	= "pingpong",
1426f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe		.type	= FIO_OPT_STR_SET,
1436f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe		.off1	= offsetof(struct netio_options, pingpong),
1446f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe		.help	= "Ping-pong IO requests",
145e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.category = FIO_OPT_C_ENGINE,
146e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.group	= FIO_OPT_G_NETIO,
1476f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	},
1486f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	{
149b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer		.name	= "interface",
150b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer		.lname	= "net engine interface",
151b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer		.type	= FIO_OPT_STR_STORE,
152f16b7405fff7c3fc1da421b6bdf8552cc99c3156Bruce Cran		.off1	= offsetof(struct netio_options, intfc),
153b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer		.help	= "Network interface to use",
154b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer		.category = FIO_OPT_C_ENGINE,
155b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer		.group	= FIO_OPT_G_NETIO,
156b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer	},
157b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer	{
158d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		.name	= "ttl",
159d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		.lname	= "net engine multicast ttl",
160d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		.type	= FIO_OPT_INT,
161d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		.off1	= offsetof(struct netio_options, ttl),
162d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		.def    = "1",
163d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		.minval	= 0,
164d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		.help	= "Time-to-live value for outgoing UDP multicast packets",
165d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		.category = FIO_OPT_C_ENGINE,
166d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		.group	= FIO_OPT_G_NETIO,
167d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer	},
168d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer	{
169de890a1e48d40238dac69f302708dde8719de240Steven Lang		.name	= NULL,
170de890a1e48d40238dac69f302708dde8719de240Steven Lang	},
171de890a1e48d40238dac69f302708dde8719de240Steven Lang};
172de890a1e48d40238dac69f302708dde8719de240Steven Lang
17349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboestatic inline int is_udp(struct netio_options *o)
17449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe{
17549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	return o->proto == FIO_TYPE_UDP || o->proto == FIO_TYPE_UDP_V6;
17649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe}
17749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
17849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboestatic inline int is_tcp(struct netio_options *o)
17949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe{
18049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	return o->proto == FIO_TYPE_TCP || o->proto == FIO_TYPE_TCP_V6;
18149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe}
18249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
18349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboestatic inline int is_ipv6(struct netio_options *o)
18449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe{
18549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	return o->proto == FIO_TYPE_UDP_V6 || o->proto == FIO_TYPE_TCP_V6;
18649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe}
18749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
188371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe/*
189371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe * Return -1 for error and 'nr events' for a positive number
190371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe * of events
191371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe */
192371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboestatic int poll_wait(struct thread_data *td, int fd, short events)
193371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe{
194371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	struct pollfd pfd;
195371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	int ret;
196371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
197371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	while (!td->terminate) {
198371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		pfd.fd = fd;
199371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		pfd.events = events;
200371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		ret = poll(&pfd, 1, -1);
201371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		if (ret < 0) {
202371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe			if (errno == EINTR)
203d5b388a560783a61af7b424757bc6dead2309c28Jens Axboe				break;
204371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
205371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe			td_verror(td, errno, "poll");
206371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe			return -1;
207371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		} else if (!ret)
208371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe			continue;
209371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
210371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		break;
211371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	}
212371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
213371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	if (pfd.revents & events)
214371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		return 1;
215371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
216371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	return -1;
217371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe}
218371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
219b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrerstatic int fio_netio_is_multicast(const char *mcaddr)
220b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer{
221b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer	in_addr_t addr = inet_network(mcaddr);
222b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer	if (addr == -1)
223b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer		return 0;
224b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer
225b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer	if (inet_network("224.0.0.0") <= addr &&
226b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer	    inet_network("239.255.255.255") >= addr)
227b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer		return 1;
228b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer
229b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer	return 0;
230b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer}
231b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer
232b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer
233ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboestatic int fio_netio_prep(struct thread_data *td, struct io_u *io_u)
234ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
235de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
236ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
2377a6499dada619928267d26b4629b0c8623dc423aJens Axboe	/*
2387a6499dada619928267d26b4629b0c8623dc423aJens Axboe	 * Make sure we don't see spurious reads to a receiver, and vice versa
2397a6499dada619928267d26b4629b0c8623dc423aJens Axboe	 */
24049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_tcp(o))
241de890a1e48d40238dac69f302708dde8719de240Steven Lang		return 0;
242de890a1e48d40238dac69f302708dde8719de240Steven Lang
243de890a1e48d40238dac69f302708dde8719de240Steven Lang	if ((o->listen && io_u->ddir == DDIR_WRITE) ||
244de890a1e48d40238dac69f302708dde8719de240Steven Lang	    (!o->listen && io_u->ddir == DDIR_READ)) {
245e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, EINVAL, "bad direction");
2467a6499dada619928267d26b4629b0c8623dc423aJens Axboe		return 1;
247ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
2483f457bea08a6bd60d99950c59c5432b8e78c69e2Bruce Cran
249f85ac25a7d5c9d5ba4d5c73363a6a2a461a9b013Jens Axboe	return 0;
250ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
251ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
25267bf982340d95ca98098ea050b54b4c7adb116c0Jens Axboe#ifdef CONFIG_LINUX_SPLICE
253cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int splice_io_u(int fdin, int fdout, unsigned int len)
254ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
2559cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int bytes = 0;
2567a6499dada619928267d26b4629b0c8623dc423aJens Axboe
2579cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	while (len) {
258cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		int ret = splice(fdin, NULL, fdout, NULL, len, 0);
2599cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
2609cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		if (ret < 0) {
2619cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			if (!bytes)
2629cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe				bytes = ret;
2639cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
2649cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			break;
2659cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		} else if (!ret)
2669cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			break;
2679cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
2689cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		bytes += ret;
269f657a2fbbb0deaf455edc478d73b664929bcb766Jens Axboe		len -= ret;
2709cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	}
2719cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
2729cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	return bytes;
2739cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
2749cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
2759cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe/*
276cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * Receive bytes from a socket and fill them into the internal pipe
2779cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe */
278cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int splice_in(struct thread_data *td, struct io_u *io_u)
2799cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
2809cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd = td->io_ops->data;
2819cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
282cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return splice_io_u(io_u->file->fd, nd->pipes[1], io_u->xfer_buflen);
2839cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
2849cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
2859cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe/*
286cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * Transmit 'len' bytes from the internal pipe
2879cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe */
288cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int splice_out(struct thread_data *td, struct io_u *io_u,
289cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		      unsigned int len)
2909cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
2919cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd = td->io_ops->data;
292cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe
293cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return splice_io_u(nd->pipes[0], io_u->file->fd, len);
294cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe}
295cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe
296cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int vmsplice_io_u(struct io_u *io_u, int fd, unsigned int len)
297cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe{
2989cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct iovec iov = {
2999cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		.iov_base = io_u->xfer_buf,
3009cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		.iov_len = len,
3019cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	};
3029cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int bytes = 0;
3039cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
3049cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	while (iov.iov_len) {
305cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		int ret = vmsplice(fd, &iov, 1, SPLICE_F_MOVE);
3069cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
3079cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		if (ret < 0) {
3089cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			if (!bytes)
3099cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe				bytes = ret;
3109cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			break;
3119cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		} else if (!ret)
3129cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			break;
3139cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
3149cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		iov.iov_len -= ret;
315cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		iov.iov_base += ret;
316f657a2fbbb0deaf455edc478d73b664929bcb766Jens Axboe		bytes += ret;
3179cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	}
3189cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
3199cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	return bytes;
320cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe
3219cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
3229cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
3239cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe/*
324cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * vmsplice() pipe to io_u buffer
3259cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe */
326cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int vmsplice_io_u_out(struct thread_data *td, struct io_u *io_u,
327cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe			     unsigned int len)
3289cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
3299cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd = td->io_ops->data;
3309cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
331cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return vmsplice_io_u(io_u, nd->pipes[0], len);
332cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe}
3339cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
334cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe/*
335cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * vmsplice() io_u to pipe
336cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe */
337cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int vmsplice_io_u_in(struct thread_data *td, struct io_u *io_u)
338cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe{
339cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	struct netio_data *nd = td->io_ops->data;
340ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
341cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return vmsplice_io_u(io_u, nd->pipes[1], io_u->xfer_buflen);
3429cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
3439cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
344cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe/*
345cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * splice receive - transfer socket data into a pipe using splice, then map
346cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * that pipe data into the io_u using vmsplice.
347cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe */
3489cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboestatic int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
3499cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
3509cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int ret;
3519cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
3529cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	ret = splice_in(td, io_u);
353cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	if (ret > 0)
354cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		return vmsplice_io_u_out(td, io_u, ret);
3559cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
356cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return ret;
3579cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
3589cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
359cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe/*
360cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * splice transmit - map data from the io_u into a pipe by using vmsplice,
361cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * then transfer that pipe to a socket using splice.
362cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe */
3639cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboestatic int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
3649cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
3659cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int ret;
3669cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
3679cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	ret = vmsplice_io_u_in(td, io_u);
368cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	if (ret > 0)
369cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		return splice_out(td, io_u, ret);
3709cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
371cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return ret;
3729cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
3735921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#else
3745921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboestatic int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
3755921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe{
376af8771b9b91eb2cd23a40aaa729bad4f78acb928Jens Axboe	errno = EOPNOTSUPP;
3775921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe	return -1;
3785921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe}
3795921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe
3805921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboestatic int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
3815921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe{
382af8771b9b91eb2cd23a40aaa729bad4f78acb928Jens Axboe	errno = EOPNOTSUPP;
3835921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe	return -1;
3845921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe}
3855921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
3869cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
3879cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboestatic int fio_netio_send(struct thread_data *td, struct io_u *io_u)
3889cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
389414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	struct netio_data *nd = td->io_ops->data;
390de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
3916f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	int ret, flags = 0;
392371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
393664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	do {
39449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		if (is_udp(o)) {
39510aa136bddbaa7c845ab4eacb4a9a4a88d6657a3Jens Axboe			const struct sockaddr *to;
39649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			socklen_t len;
39749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
39849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			if (is_ipv6(o)) {
39949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe				to = (struct sockaddr *) &nd->addr6;
40049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe				len = sizeof(nd->addr6);
40149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			} else {
40249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe				to = (struct sockaddr *) &nd->addr;
40349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe				len = sizeof(nd->addr);
40449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			}
40562b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe
406664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			ret = sendto(io_u->file->fd, io_u->xfer_buf,
40749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe					io_u->xfer_buflen, flags, to, len);
408664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		} else {
409664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			/*
410664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			 * if we are going to write more, set MSG_MORE
411664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			 */
4125921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#ifdef MSG_MORE
4136f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe			if ((td->this_io_bytes[DDIR_WRITE] + io_u->xfer_buflen <
4146f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe			    td->o.size) && !o->pingpong)
415664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe				flags |= MSG_MORE;
4165921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
417664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			ret = send(io_u->file->fd, io_u->xfer_buf,
418664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe					io_u->xfer_buflen, flags);
419664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		}
420664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		if (ret > 0)
421664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			break;
4229cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
423664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		ret = poll_wait(td, io_u->file->fd, POLLOUT);
424664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		if (ret <= 0)
425664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			break;
426664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	} while (1);
427664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
428664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	return ret;
429664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe}
430664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
431664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboestatic int is_udp_close(struct io_u *io_u, int len)
432664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe{
433664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	struct udp_close_msg *msg;
434664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
435664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	if (len != sizeof(struct udp_close_msg))
436664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		return 0;
437664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
438664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	msg = io_u->xfer_buf;
439b96d243044023b28731341d290943b5d47a5f794Jens Axboe	if (ntohl(msg->magic) != FIO_LINK_OPEN_CLOSE_MAGIC)
440664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		return 0;
441664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	if (ntohl(msg->cmd) != FIO_LINK_CLOSE)
442664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		return 0;
443664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
444664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	return 1;
4459cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
4469cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
447414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboestatic int fio_netio_recv(struct thread_data *td, struct io_u *io_u)
4489cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
449414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	struct netio_data *nd = td->io_ops->data;
450de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
4516f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	int ret, flags = 0;
452664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
453664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	do {
45449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		if (is_udp(o)) {
455b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			struct sockaddr *from;
45649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			socklen_t l, *len = &l;
457b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer
458b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			if (o->listen) {
45949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe				if (!is_ipv6(o)) {
46049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe					from = (struct sockaddr *) &nd->addr;
46149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe					*len = sizeof(nd->addr);
46249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe				} else {
46349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe					from = (struct sockaddr *) &nd->addr6;
46449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe					*len = sizeof(nd->addr6);
46549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe				}
466b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			} else {
467b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer				from = NULL;
468b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer				len = NULL;
469b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			}
470664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
471664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			ret = recvfrom(io_u->file->fd, io_u->xfer_buf,
472b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer					io_u->xfer_buflen, flags, from, len);
473664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			if (is_udp_close(io_u, ret)) {
474664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe				td->done = 1;
475664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe				return 0;
476664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			}
477664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		} else {
478664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			ret = recv(io_u->file->fd, io_u->xfer_buf,
479664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe					io_u->xfer_buflen, flags);
480664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		}
481664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		if (ret > 0)
482664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			break;
4837d988f68c7f0ff6bd4c9e558c4defbd9a544b167Jens Axboe		else if (!ret && (flags & MSG_WAITALL))
4847d988f68c7f0ff6bd4c9e558c4defbd9a544b167Jens Axboe			break;
4859cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
486664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		ret = poll_wait(td, io_u->file->fd, POLLIN);
487664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		if (ret <= 0)
488664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			break;
489664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		flags |= MSG_WAITALL;
490664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	} while (1);
491414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
492664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	return ret;
4939cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
4949cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
4956f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboestatic int __fio_netio_queue(struct thread_data *td, struct io_u *io_u,
4966f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe			     enum fio_ddir ddir)
4979cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
4989cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd = td->io_ops->data;
499de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
5009cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int ret;
5019cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
5026f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	if (ddir == DDIR_WRITE) {
50349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		if (!nd->use_splice || is_udp(o) ||
504de890a1e48d40238dac69f302708dde8719de240Steven Lang		    o->proto == FIO_TYPE_UNIX)
5059cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			ret = fio_netio_send(td, io_u);
506414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		else
507414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			ret = fio_netio_splice_out(td, io_u);
5086f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	} else if (ddir == DDIR_READ) {
50949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		if (!nd->use_splice || is_udp(o) ||
510de890a1e48d40238dac69f302708dde8719de240Steven Lang		    o->proto == FIO_TYPE_UNIX)
511414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			ret = fio_netio_recv(td, io_u);
5129cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		else
513414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			ret = fio_netio_splice_in(td, io_u);
514d4f12dd05cfb2e8e7a72604cd870e10f2394914eJens Axboe	} else
5157a6499dada619928267d26b4629b0c8623dc423aJens Axboe		ret = 0;	/* must be a SYNC */
516ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
517cec6b55da1c282b5b91ad346c7804171fccf151eJens Axboe	if (ret != (int) io_u->xfer_buflen) {
51822819ec237297fc39435ed566bee01a4225bfb39Jens Axboe		if (ret >= 0) {
519cec6b55da1c282b5b91ad346c7804171fccf151eJens Axboe			io_u->resid = io_u->xfer_buflen - ret;
520cec6b55da1c282b5b91ad346c7804171fccf151eJens Axboe			io_u->error = 0;
52136167d82e5f49dee91c6d2cd426068edee90e36fJens Axboe			return FIO_Q_COMPLETED;
522414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		} else {
523414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			int err = errno;
524414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
5256f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe			if (ddir == DDIR_WRITE && err == EMSGSIZE)
526414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe				return FIO_Q_BUSY;
527414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
528414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			io_u->error = err;
529414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		}
530ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
531ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
53236167d82e5f49dee91c6d2cd426068edee90e36fJens Axboe	if (io_u->error)
533e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, io_u->error, "xfer");
534ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
53536167d82e5f49dee91c6d2cd426068edee90e36fJens Axboe	return FIO_Q_COMPLETED;
536ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
537ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
5386f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboestatic int fio_netio_queue(struct thread_data *td, struct io_u *io_u)
5396f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe{
5406f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	struct netio_options *o = td->eo;
5416f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	int ret;
5426f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe
5436f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	fio_ro_check(td, io_u);
5446f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe
5456f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	ret = __fio_netio_queue(td, io_u, io_u->ddir);
5466f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	if (!o->pingpong || ret != FIO_Q_COMPLETED)
5476f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe		return ret;
5486f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe
5496f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	/*
5506f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	 * For ping-pong mode, receive or send reply as needed
5516f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	 */
5526f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	if (td_read(td) && io_u->ddir == DDIR_READ)
5536f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe		ret = __fio_netio_queue(td, io_u, DDIR_WRITE);
5546f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	else if (td_write(td) && io_u->ddir == DDIR_WRITE)
5556f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe		ret = __fio_netio_queue(td, io_u, DDIR_READ);
5566f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe
5576f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	return ret;
5586f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe}
5596f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe
560b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic int fio_netio_connect(struct thread_data *td, struct fio_file *f)
561ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
562b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
563de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
5646264c7a8ddd0998f371604c227d3aea491922681Jens Axboe	int type, domain;
565414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
566de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->proto == FIO_TYPE_TCP) {
5670fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		domain = AF_INET;
568414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		type = SOCK_STREAM;
56949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else if (o->proto == FIO_TYPE_TCP_V6) {
57049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		domain = AF_INET6;
57149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		type = SOCK_STREAM;
572de890a1e48d40238dac69f302708dde8719de240Steven Lang	} else if (o->proto == FIO_TYPE_UDP) {
5730fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		domain = AF_INET;
574414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		type = SOCK_DGRAM;
57549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else if (o->proto == FIO_TYPE_UDP_V6) {
57649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		domain = AF_INET6;
57749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		type = SOCK_DGRAM;
578de890a1e48d40238dac69f302708dde8719de240Steven Lang	} else if (o->proto == FIO_TYPE_UNIX) {
5790fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		domain = AF_UNIX;
5800fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		type = SOCK_STREAM;
5810fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	} else {
582de890a1e48d40238dac69f302708dde8719de240Steven Lang		log_err("fio: bad network type %d\n", o->proto);
5830fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		f->fd = -1;
5840fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		return 1;
5850fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	}
586ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
5870fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	f->fd = socket(domain, type, 0);
588b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	if (f->fd < 0) {
589b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		td_verror(td, errno, "socket");
590b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		return 1;
591ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
592ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
5931eafa37ac57bb08ca21af8ab76bd7848ae2e7c97Jens Axboe#ifdef CONFIG_TCP_NODELAY
59449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (o->nodelay && is_tcp(o)) {
5956264c7a8ddd0998f371604c227d3aea491922681Jens Axboe		int optval = 1;
5966264c7a8ddd0998f371604c227d3aea491922681Jens Axboe
59726e594a55a54d47ce0a0784c27c6f851c83d101aJens Axboe		if (setsockopt(f->fd, IPPROTO_TCP, TCP_NODELAY, (void *) &optval, sizeof(int)) < 0) {
59870a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan			log_err("fio: cannot set TCP_NODELAY option on socket (%s), disable with 'nodelay=0'\n", strerror(errno));
59970a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan			return 1;
60070a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan		}
60170a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan	}
6021eafa37ac57bb08ca21af8ab76bd7848ae2e7c97Jens Axboe#endif
60370a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan
60449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_udp(o)) {
605d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		if (!fio_netio_is_multicast(td->o.filename))
606d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer			return 0;
60749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		if (is_ipv6(o)) {
60849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			log_err("fio: multicast not supported on IPv6\n");
60949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			close(f->fd);
61049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			return 1;
61149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		}
612d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer
613f16b7405fff7c3fc1da421b6bdf8552cc99c3156Bruce Cran		if (o->intfc) {
614b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer			struct in_addr interface_addr;
61549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
616f16b7405fff7c3fc1da421b6bdf8552cc99c3156Bruce Cran			if (inet_aton(o->intfc, &interface_addr) == 0) {
617b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer				log_err("fio: interface not valid interface IP\n");
618b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer				close(f->fd);
619b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer				return 1;
620b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer			}
621f16b7405fff7c3fc1da421b6bdf8552cc99c3156Bruce Cran			if (setsockopt(f->fd, IPPROTO_IP, IP_MULTICAST_IF, (const char*)&interface_addr, sizeof(interface_addr)) < 0) {
622b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer				td_verror(td, errno, "setsockopt IP_MULTICAST_IF");
623b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer				close(f->fd);
624b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer				return 1;
625b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer			}
626b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer		}
627f16b7405fff7c3fc1da421b6bdf8552cc99c3156Bruce Cran		if (setsockopt(f->fd, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&o->ttl, sizeof(o->ttl)) < 0) {
628d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer			td_verror(td, errno, "setsockopt IP_MULTICAST_TTL");
629d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer			close(f->fd);
630d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer			return 1;
631d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		}
632414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		return 0;
633b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer	} else if (o->proto == FIO_TYPE_TCP) {
63467bf982340d95ca98098ea050b54b4c7adb116c0Jens Axboe		socklen_t len = sizeof(nd->addr);
635414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
6360fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		if (connect(f->fd, (struct sockaddr *) &nd->addr, len) < 0) {
6370fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe			td_verror(td, errno, "connect");
638b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe			close(f->fd);
6390fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe			return 1;
6400fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		}
64149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else if (o->proto == FIO_TYPE_TCP_V6) {
64249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		socklen_t len = sizeof(nd->addr6);
64349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
64449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		if (connect(f->fd, (struct sockaddr *) &nd->addr6, len) < 0) {
64549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			td_verror(td, errno, "connect");
64649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			close(f->fd);
64749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			return 1;
64849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		}
64949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
6500fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	} else {
6510fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		struct sockaddr_un *addr = &nd->addr_un;
65267bf982340d95ca98098ea050b54b4c7adb116c0Jens Axboe		socklen_t len;
6530fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
6540fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		len = sizeof(addr->sun_family) + strlen(addr->sun_path) + 1;
6550fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
6560fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		if (connect(f->fd, (struct sockaddr *) addr, len) < 0) {
6570fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe			td_verror(td, errno, "connect");
658b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe			close(f->fd);
6590fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe			return 1;
6600fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		}
661ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
662ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
663ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	return 0;
664ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
665ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
666b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic int fio_netio_accept(struct thread_data *td, struct fio_file *f)
6675fdd124a3b811993542825847f207587d5f4661eJens Axboe{
668b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
669de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
67049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	socklen_t socklen;
6716264c7a8ddd0998f371604c227d3aea491922681Jens Axboe	int state;
6725fdd124a3b811993542825847f207587d5f4661eJens Axboe
67349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_udp(o)) {
674414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		f->fd = nd->listenfd;
675414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		return 0;
676414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	}
677414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
678859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe	state = td->runstate;
679859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe	td_set_runstate(td, TD_SETTING_UP);
680859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe
6816d86144dd10b05e8b82e9b895c35dd778e5e71abJens Axboe	log_info("fio: waiting for connection\n");
6825fdd124a3b811993542825847f207587d5f4661eJens Axboe
683371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	if (poll_wait(td, nd->listenfd, POLLIN) < 0)
684859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe		goto err;
6850c09442b26216aed16f758712f744a2c54726cdbJens Axboe
68649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (o->proto == FIO_TYPE_TCP) {
68749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		socklen = sizeof(nd->addr);
68849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		f->fd = accept(nd->listenfd, (struct sockaddr *) &nd->addr, &socklen);
68949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else {
69049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		socklen = sizeof(nd->addr6);
69149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		f->fd = accept(nd->listenfd, (struct sockaddr *) &nd->addr6, &socklen);
69249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	}
69349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
694371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	if (f->fd < 0) {
695371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		td_verror(td, errno, "accept");
696859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe		goto err;
697b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	}
6985fdd124a3b811993542825847f207587d5f4661eJens Axboe
6991eafa37ac57bb08ca21af8ab76bd7848ae2e7c97Jens Axboe#ifdef CONFIG_TCP_NODELAY
70049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (o->nodelay && is_tcp(o)) {
7016264c7a8ddd0998f371604c227d3aea491922681Jens Axboe		int optval = 1;
7026264c7a8ddd0998f371604c227d3aea491922681Jens Axboe
70326e594a55a54d47ce0a0784c27c6f851c83d101aJens Axboe		if (setsockopt(f->fd, IPPROTO_TCP, TCP_NODELAY, (void *) &optval, sizeof(int)) < 0) {
70470a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan			log_err("fio: cannot set TCP_NODELAY option on socket (%s), disable with 'nodelay=0'\n", strerror(errno));
70570a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan			return 1;
70670a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan		}
70770a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan	}
7081eafa37ac57bb08ca21af8ab76bd7848ae2e7c97Jens Axboe#endif
70970a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan
7100cae16ffe3e4ca17cdb88fe64d357b7cde643f6aJens Axboe	reset_all_stats(td);
711859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe	td_set_runstate(td, state);
712b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	return 0;
713859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboeerr:
714859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe	td_set_runstate(td, state);
715859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe	return 1;
716b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe}
717b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
718664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboestatic void fio_netio_udp_close(struct thread_data *td, struct fio_file *f)
719664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe{
720664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	struct netio_data *nd = td->io_ops->data;
72149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	struct netio_options *o = td->eo;
722664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	struct udp_close_msg msg;
72349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	struct sockaddr *to;
72449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	socklen_t len;
725664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	int ret;
726664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
72749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_ipv6(o)) {
72849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		to = (struct sockaddr *) &nd->addr6;
72949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		len = sizeof(nd->addr6);
73049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else {
73149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		to = (struct sockaddr *) &nd->addr;
73249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		len = sizeof(nd->addr);
73349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	}
73449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
735b96d243044023b28731341d290943b5d47a5f794Jens Axboe	msg.magic = htonl(FIO_LINK_OPEN_CLOSE_MAGIC);
736664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	msg.cmd = htonl(FIO_LINK_CLOSE);
737664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
73849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	ret = sendto(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to, len);
739664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	if (ret < 0)
740664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		td_verror(td, errno, "sendto udp link close");
741664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe}
742664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
743664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboestatic int fio_netio_close_file(struct thread_data *td, struct fio_file *f)
744664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe{
745de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
746664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
747664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	/*
748664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	 * If this is an UDP connection, notify the receiver that we are
749664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	 * closing down the link
750664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	 */
75149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_udp(o))
752664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		fio_netio_udp_close(td, f);
753664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
754664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	return generic_close_file(td, f);
755664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe}
756664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
757b96d243044023b28731341d290943b5d47a5f794Jens Axboestatic int fio_netio_udp_recv_open(struct thread_data *td, struct fio_file *f)
758b96d243044023b28731341d290943b5d47a5f794Jens Axboe{
759b96d243044023b28731341d290943b5d47a5f794Jens Axboe	struct netio_data *nd = td->io_ops->data;
76049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	struct netio_options *o = td->eo;
761b96d243044023b28731341d290943b5d47a5f794Jens Axboe	struct udp_close_msg msg;
76249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	struct sockaddr *to;
76349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	socklen_t len;
764b96d243044023b28731341d290943b5d47a5f794Jens Axboe	int ret;
765b96d243044023b28731341d290943b5d47a5f794Jens Axboe
76649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_ipv6(o)) {
76749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		len = sizeof(nd->addr6);
76849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		to = (struct sockaddr *) &nd->addr6;
76949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else {
77049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		len = sizeof(nd->addr);
77149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		to = (struct sockaddr *) &nd->addr;
77249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	}
77349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
7741f81991ed356dd7257aef2c715ba9a24d9af93a5Jens Axboe	ret = recvfrom(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to, &len);
775b96d243044023b28731341d290943b5d47a5f794Jens Axboe	if (ret < 0) {
776ee7062fdd7c2fdc0a0427343b5c5c119e7c08032Shawn Bohrer		td_verror(td, errno, "recvfrom udp link open");
777b96d243044023b28731341d290943b5d47a5f794Jens Axboe		return ret;
778b96d243044023b28731341d290943b5d47a5f794Jens Axboe	}
779b96d243044023b28731341d290943b5d47a5f794Jens Axboe
780b96d243044023b28731341d290943b5d47a5f794Jens Axboe	if (ntohl(msg.magic) != FIO_LINK_OPEN_CLOSE_MAGIC ||
781b96d243044023b28731341d290943b5d47a5f794Jens Axboe	    ntohl(msg.cmd) != FIO_LINK_OPEN) {
782b96d243044023b28731341d290943b5d47a5f794Jens Axboe		log_err("fio: bad udp open magic %x/%x\n", ntohl(msg.magic),
783b96d243044023b28731341d290943b5d47a5f794Jens Axboe								ntohl(msg.cmd));
784b96d243044023b28731341d290943b5d47a5f794Jens Axboe		return -1;
785b96d243044023b28731341d290943b5d47a5f794Jens Axboe	}
786b96d243044023b28731341d290943b5d47a5f794Jens Axboe
787b96d243044023b28731341d290943b5d47a5f794Jens Axboe	return 0;
788b96d243044023b28731341d290943b5d47a5f794Jens Axboe}
789b96d243044023b28731341d290943b5d47a5f794Jens Axboe
790b96d243044023b28731341d290943b5d47a5f794Jens Axboestatic int fio_netio_udp_send_open(struct thread_data *td, struct fio_file *f)
791b96d243044023b28731341d290943b5d47a5f794Jens Axboe{
792b96d243044023b28731341d290943b5d47a5f794Jens Axboe	struct netio_data *nd = td->io_ops->data;
79349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	struct netio_options *o = td->eo;
794b96d243044023b28731341d290943b5d47a5f794Jens Axboe	struct udp_close_msg msg;
79549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	struct sockaddr *to;
79649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	socklen_t len;
797b96d243044023b28731341d290943b5d47a5f794Jens Axboe	int ret;
798b96d243044023b28731341d290943b5d47a5f794Jens Axboe
79949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_ipv6(o)) {
80049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		len = sizeof(nd->addr6);
80149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		to = (struct sockaddr *) &nd->addr6;
80249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else {
80349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		len = sizeof(nd->addr);
80449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		to = (struct sockaddr *) &nd->addr;
80549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	}
80649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
807b96d243044023b28731341d290943b5d47a5f794Jens Axboe	msg.magic = htonl(FIO_LINK_OPEN_CLOSE_MAGIC);
808b96d243044023b28731341d290943b5d47a5f794Jens Axboe	msg.cmd = htonl(FIO_LINK_OPEN);
809b96d243044023b28731341d290943b5d47a5f794Jens Axboe
81049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	ret = sendto(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to, len);
811b96d243044023b28731341d290943b5d47a5f794Jens Axboe	if (ret < 0) {
812b96d243044023b28731341d290943b5d47a5f794Jens Axboe		td_verror(td, errno, "sendto udp link open");
813b96d243044023b28731341d290943b5d47a5f794Jens Axboe		return ret;
814b96d243044023b28731341d290943b5d47a5f794Jens Axboe	}
815b96d243044023b28731341d290943b5d47a5f794Jens Axboe
816b96d243044023b28731341d290943b5d47a5f794Jens Axboe	return 0;
817b96d243044023b28731341d290943b5d47a5f794Jens Axboe}
818b96d243044023b28731341d290943b5d47a5f794Jens Axboe
819b96d243044023b28731341d290943b5d47a5f794Jens Axboestatic int fio_netio_open_file(struct thread_data *td, struct fio_file *f)
820b96d243044023b28731341d290943b5d47a5f794Jens Axboe{
821b96d243044023b28731341d290943b5d47a5f794Jens Axboe	int ret;
822b96d243044023b28731341d290943b5d47a5f794Jens Axboe	struct netio_options *o = td->eo;
823b96d243044023b28731341d290943b5d47a5f794Jens Axboe
824b96d243044023b28731341d290943b5d47a5f794Jens Axboe	if (o->listen)
825b96d243044023b28731341d290943b5d47a5f794Jens Axboe		ret = fio_netio_accept(td, f);
826b96d243044023b28731341d290943b5d47a5f794Jens Axboe	else
827b96d243044023b28731341d290943b5d47a5f794Jens Axboe		ret = fio_netio_connect(td, f);
828b96d243044023b28731341d290943b5d47a5f794Jens Axboe
829b96d243044023b28731341d290943b5d47a5f794Jens Axboe	if (ret) {
830b96d243044023b28731341d290943b5d47a5f794Jens Axboe		f->fd = -1;
831b96d243044023b28731341d290943b5d47a5f794Jens Axboe		return ret;
832b96d243044023b28731341d290943b5d47a5f794Jens Axboe	}
833b96d243044023b28731341d290943b5d47a5f794Jens Axboe
83449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_udp(o)) {
835b96d243044023b28731341d290943b5d47a5f794Jens Axboe		if (td_write(td))
836b96d243044023b28731341d290943b5d47a5f794Jens Axboe			ret = fio_netio_udp_send_open(td, f);
837b96d243044023b28731341d290943b5d47a5f794Jens Axboe		else {
838b96d243044023b28731341d290943b5d47a5f794Jens Axboe			int state;
839b96d243044023b28731341d290943b5d47a5f794Jens Axboe
840b96d243044023b28731341d290943b5d47a5f794Jens Axboe			state = td->runstate;
841b96d243044023b28731341d290943b5d47a5f794Jens Axboe			td_set_runstate(td, TD_SETTING_UP);
842b96d243044023b28731341d290943b5d47a5f794Jens Axboe			ret = fio_netio_udp_recv_open(td, f);
843b96d243044023b28731341d290943b5d47a5f794Jens Axboe			td_set_runstate(td, state);
844b96d243044023b28731341d290943b5d47a5f794Jens Axboe		}
845b96d243044023b28731341d290943b5d47a5f794Jens Axboe	}
846b96d243044023b28731341d290943b5d47a5f794Jens Axboe
847b96d243044023b28731341d290943b5d47a5f794Jens Axboe	if (ret)
848b96d243044023b28731341d290943b5d47a5f794Jens Axboe		fio_netio_close_file(td, f);
849b96d243044023b28731341d290943b5d47a5f794Jens Axboe
850b96d243044023b28731341d290943b5d47a5f794Jens Axboe	return ret;
851b96d243044023b28731341d290943b5d47a5f794Jens Axboe}
852b96d243044023b28731341d290943b5d47a5f794Jens Axboe
8530b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboestatic int fio_fill_addr(struct thread_data *td, const char *host, int af,
8540b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe			 void *dst, struct addrinfo **res)
8550b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe{
8560b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	struct netio_options *o = td->eo;
8570b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	struct addrinfo hints;
8580b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	int ret;
8590b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe
8600b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	if (inet_pton(af, host, dst))
8610b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		return 0;
8620b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe
8630b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	memset(&hints, 0, sizeof(hints));
8640b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe
8650b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	if (is_tcp(o))
8660b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		hints.ai_socktype = SOCK_STREAM;
8670b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	else
8680b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		hints.ai_socktype = SOCK_DGRAM;
8690b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe
870b1b1be2a569fb9226fa1ebbfed91f34322ce1c9cJens Axboe	if (is_ipv6(o))
871b1b1be2a569fb9226fa1ebbfed91f34322ce1c9cJens Axboe		hints.ai_family = AF_INET6;
872b1b1be2a569fb9226fa1ebbfed91f34322ce1c9cJens Axboe	else
873b1b1be2a569fb9226fa1ebbfed91f34322ce1c9cJens Axboe		hints.ai_family = AF_INET;
874b1b1be2a569fb9226fa1ebbfed91f34322ce1c9cJens Axboe
8750b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	ret = getaddrinfo(host, NULL, &hints, res);
8760b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	if (ret) {
8770b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		int e = EINVAL;
8780b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		char str[128];
8790b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe
8800b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		if (ret == EAI_SYSTEM)
8810b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe			e = errno;
8820b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe
8830b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		snprintf(str, sizeof(str), "getaddrinfo: %s", gai_strerror(ret));
8840b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		td_verror(td, e, str);
8850b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		return 1;
8860b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	}
8870b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe
8880b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	return 0;
8890b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe}
8900b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe
8910fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboestatic int fio_netio_setup_connect_inet(struct thread_data *td,
8920fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe					const char *host, unsigned short port)
893b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe{
894b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
89549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	struct netio_options *o = td->eo;
8960b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	struct addrinfo *res = NULL;
8970b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	void *dst, *src;
8980b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	int af, len;
899b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
900166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe	if (!host) {
901166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe		log_err("fio: connect with no host to connect to.\n");
902166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe		if (td_read(td))
903166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe			log_err("fio: did you forget to set 'listen'?\n");
904166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe
905166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe		td_verror(td, EINVAL, "no hostname= set");
906166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe		return 1;
907166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe	}
908166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe
9090b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	nd->addr.sin_family = AF_INET;
9100b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	nd->addr.sin_port = htons(port);
9110b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	nd->addr6.sin6_family = AF_INET6;
9120b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	nd->addr6.sin6_port = htons(port);
913b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
9140b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	if (is_ipv6(o)) {
9150b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		af = AF_INET6;
91668631b36e37e1ecaadc1e5697ead4adc21640562Jens Axboe		dst = &nd->addr6.sin6_addr;
91749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else {
9180b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		af = AF_INET;
91968631b36e37e1ecaadc1e5697ead4adc21640562Jens Axboe		dst = &nd->addr.sin_addr;
9200b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	}
92149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
9220b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	if (fio_fill_addr(td, host, af, dst, &res))
9230b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		return 1;
92449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
9250b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	if (!res)
9260b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		return 0;
92749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
9280b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	if (is_ipv6(o)) {
9290b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		len = sizeof(nd->addr6.sin6_addr);
9300b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		src = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
9310b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	} else {
9320b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		len = sizeof(nd->addr.sin_addr);
9330b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		src = &((struct sockaddr_in *) res->ai_addr)->sin_addr;
9345fdd124a3b811993542825847f207587d5f4661eJens Axboe	}
9355fdd124a3b811993542825847f207587d5f4661eJens Axboe
9360b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	memcpy(dst, src, len);
9370b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	freeaddrinfo(res);
9385fdd124a3b811993542825847f207587d5f4661eJens Axboe	return 0;
9395fdd124a3b811993542825847f207587d5f4661eJens Axboe}
9405fdd124a3b811993542825847f207587d5f4661eJens Axboe
9410fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboestatic int fio_netio_setup_connect_unix(struct thread_data *td,
9420fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe					const char *path)
9430fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe{
9440fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	struct netio_data *nd = td->io_ops->data;
9450fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	struct sockaddr_un *soun = &nd->addr_un;
9460fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
9470fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	soun->sun_family = AF_UNIX;
9484b159fa61a9c3ed7e00c8135189c184dcc48c69fJens Axboe	memset(soun->sun_path, 0, sizeof(soun->sun_path));
9494b159fa61a9c3ed7e00c8135189c184dcc48c69fJens Axboe	strncpy(soun->sun_path, path, sizeof(soun->sun_path) - 1);
9500fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	return 0;
9510fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe}
9520fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
953de890a1e48d40238dac69f302708dde8719de240Steven Langstatic int fio_netio_setup_connect(struct thread_data *td)
9540fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe{
955de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
9560fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
95749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_udp(o) || is_tcp(o))
958de890a1e48d40238dac69f302708dde8719de240Steven Lang		return fio_netio_setup_connect_inet(td, td->o.filename,o->port);
9590fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	else
960de890a1e48d40238dac69f302708dde8719de240Steven Lang		return fio_netio_setup_connect_unix(td, td->o.filename);
9610fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe}
9620fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
9630fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboestatic int fio_netio_setup_listen_unix(struct thread_data *td, const char *path)
9640fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe{
9650fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	struct netio_data *nd = td->io_ops->data;
9660fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	struct sockaddr_un *addr = &nd->addr_un;
9670fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	mode_t mode;
9680fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	int len, fd;
9690fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
9700fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	fd = socket(AF_UNIX, SOCK_STREAM, 0);
9710fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	if (fd < 0) {
9720fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		log_err("fio: socket: %s\n", strerror(errno));
9730fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		return -1;
9740fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	}
9750fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
9760fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	mode = umask(000);
9770fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
9780fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	memset(addr, 0, sizeof(*addr));
9790fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	addr->sun_family = AF_UNIX;
9804b159fa61a9c3ed7e00c8135189c184dcc48c69fJens Axboe	strncpy(addr->sun_path, path, sizeof(addr->sun_path) - 1);
9810fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	unlink(path);
9820fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
9830fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	len = sizeof(addr->sun_family) + strlen(path) + 1;
9840fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
9850fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	if (bind(fd, (struct sockaddr *) addr, len) < 0) {
9860fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		log_err("fio: bind: %s\n", strerror(errno));
987b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe		close(fd);
9880fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		return -1;
9890fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	}
9900fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
9910fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	umask(mode);
9920fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	nd->listenfd = fd;
9930fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	return 0;
9940fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe}
9950fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
9960fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboestatic int fio_netio_setup_listen_inet(struct thread_data *td, short port)
997ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
998b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
999de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
1000b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer	struct ip_mreq mr;
1001b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer	struct sockaddr_in sin;
100249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	struct sockaddr *saddr;
100349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	int fd, opt, type, domain;
100449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	socklen_t len;
1005ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
1006b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer	memset(&sin, 0, sizeof(sin));
100749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
100849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (o->proto == FIO_TYPE_TCP) {
1009414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		type = SOCK_STREAM;
101049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		domain = AF_INET;
101149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else if (o->proto == FIO_TYPE_TCP_V6) {
101249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		type = SOCK_STREAM;
101349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		domain = AF_INET6;
101449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else if (o->proto == FIO_TYPE_UDP) {
1015414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		type = SOCK_DGRAM;
101649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		domain = AF_INET;
101749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else if (o->proto == FIO_TYPE_UDP_V6) {
101849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		type = SOCK_DGRAM;
101949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		domain = AF_INET6;
102049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else {
102149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		log_err("fio: unknown proto %d\n", o->proto);
102249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		return 1;
102349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	}
1024414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
102549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	fd = socket(domain, type, 0);
1026ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	if (fd < 0) {
1027e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "socket");
1028ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		return 1;
1029ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
1030ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
1031ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	opt = 1;
103226e594a55a54d47ce0a0784c27c6f851c83d101aJens Axboe	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &opt, sizeof(opt)) < 0) {
1033e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "setsockopt");
10344a93dec2a85f4a979421638fde2877268c470ab1Shawn Bohrer		close(fd);
1035ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		return 1;
1036ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
10376bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe#ifdef SO_REUSEPORT
103826e594a55a54d47ce0a0784c27c6f851c83d101aJens Axboe	if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (void *) &opt, sizeof(opt)) < 0) {
1039e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "setsockopt");
10404a93dec2a85f4a979421638fde2877268c470ab1Shawn Bohrer		close(fd);
10416bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe		return 1;
10426bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe	}
10436bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe#endif
1044ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
10456611e9c767bad5c903c8ac59b9ae8409315dbca2Jens Axboe	if (td->o.filename) {
104649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		if (!is_udp(o) || !fio_netio_is_multicast(td->o.filename)) {
1047b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			log_err("fio: hostname not valid for non-multicast inbound network IO\n");
1048b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			close(fd);
1049b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			return 1;
1050b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer		}
10516611e9c767bad5c903c8ac59b9ae8409315dbca2Jens Axboe		if (is_ipv6(o)) {
10526611e9c767bad5c903c8ac59b9ae8409315dbca2Jens Axboe			log_err("fio: IPv6 not supported for multicast network IO");
10536611e9c767bad5c903c8ac59b9ae8409315dbca2Jens Axboe			close(fd);
10546611e9c767bad5c903c8ac59b9ae8409315dbca2Jens Axboe			return 1;
10556611e9c767bad5c903c8ac59b9ae8409315dbca2Jens Axboe		}
1056b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer
1057b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer		inet_aton(td->o.filename, &sin.sin_addr);
1058b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer
1059b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer		mr.imr_multiaddr = sin.sin_addr;
1060f16b7405fff7c3fc1da421b6bdf8552cc99c3156Bruce Cran		if (o->intfc) {
1061f16b7405fff7c3fc1da421b6bdf8552cc99c3156Bruce Cran			if (inet_aton(o->intfc, &mr.imr_interface) == 0) {
1062b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer				log_err("fio: interface not valid interface IP\n");
1063b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer				close(fd);
1064b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer				return 1;
1065b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer			}
1066b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer		} else {
1067b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer			mr.imr_interface.s_addr = htonl(INADDR_ANY);
1068b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer		}
10696611e9c767bad5c903c8ac59b9ae8409315dbca2Jens Axboe
1070f16b7405fff7c3fc1da421b6bdf8552cc99c3156Bruce Cran		if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mr, sizeof(mr)) < 0) {
1071b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			td_verror(td, errno, "setsockopt IP_ADD_MEMBERSHIP");
1072b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			close(fd);
1073b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			return 1;
1074b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer		}
1075b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer	}
1076b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer
107749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (!is_ipv6(o)) {
107849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		saddr = (struct sockaddr *) &nd->addr;
107949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		len = sizeof(nd->addr);
108049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
108149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		nd->addr.sin_family = AF_INET;
108249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		nd->addr.sin_addr.s_addr = sin.sin_addr.s_addr ? sin.sin_addr.s_addr : htonl(INADDR_ANY);
108349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		nd->addr.sin_port = htons(port);
108449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else {
108549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		saddr = (struct sockaddr *) &nd->addr6;
108649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		len = sizeof(nd->addr6);
108749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
108849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		nd->addr6.sin6_family = AF_INET6;
108966f7a56f70e40e9e953c47fae3a3432e87cd0cb7Jens Axboe		nd->addr6.sin6_addr = in6addr_any;
109049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		nd->addr6.sin6_port = htons(port);
109149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	}
1092ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
109349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (bind(fd, saddr, len) < 0) {
1094d19cedd63494cf8aef6443fb2ce866cd7a977b98Jens Axboe		close(fd);
1095e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "bind");
1096ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		return 1;
1097ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
10980fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
10990fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	nd->listenfd = fd;
11000fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	return 0;
11010fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe}
11020fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
1103de890a1e48d40238dac69f302708dde8719de240Steven Langstatic int fio_netio_setup_listen(struct thread_data *td)
11040fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe{
11050fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	struct netio_data *nd = td->io_ops->data;
1106de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
11070fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	int ret;
11080fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
110949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_udp(o) || is_tcp(o))
1110de890a1e48d40238dac69f302708dde8719de240Steven Lang		ret = fio_netio_setup_listen_inet(td, o->port);
11110fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	else
1112de890a1e48d40238dac69f302708dde8719de240Steven Lang		ret = fio_netio_setup_listen_unix(td, td->o.filename);
11130fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
11140fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	if (ret)
11150fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		return ret;
111649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_udp(o))
11170fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		return 0;
11180fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
11190fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	if (listen(nd->listenfd, 10) < 0) {
1120e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "listen");
11210fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		nd->listenfd = -1;
1122ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		return 1;
1123ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
1124ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
1125b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	return 0;
1126ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
1127ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
11289bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboestatic int fio_netio_init(struct thread_data *td)
1129ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
1130de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
1131af52b3455ad892322aab2791282b6bd4efdfdbf3Jens Axboe	int ret;
1132ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
11333f457bea08a6bd60d99950c59c5432b8e78c69e2Bruce Cran#ifdef WIN32
11343f457bea08a6bd60d99950c59c5432b8e78c69e2Bruce Cran	WSADATA wsd;
11353f457bea08a6bd60d99950c59c5432b8e78c69e2Bruce Cran	WSAStartup(MAKEWORD(2,2), &wsd);
11363f457bea08a6bd60d99950c59c5432b8e78c69e2Bruce Cran#endif
11373f457bea08a6bd60d99950c59c5432b8e78c69e2Bruce Cran
113816d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe	if (td_random(td)) {
113916d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe		log_err("fio: network IO can't be random\n");
114016d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe		return 1;
114116d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe	}
1142ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
1143de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->proto == FIO_TYPE_UNIX && o->port) {
1144de890a1e48d40238dac69f302708dde8719de240Steven Lang		log_err("fio: network IO port not valid with unix socket\n");
1145de890a1e48d40238dac69f302708dde8719de240Steven Lang		return 1;
1146de890a1e48d40238dac69f302708dde8719de240Steven Lang	} else if (o->proto != FIO_TYPE_UNIX && !o->port) {
1147de890a1e48d40238dac69f302708dde8719de240Steven Lang		log_err("fio: network IO requires port for tcp or udp\n");
1148de890a1e48d40238dac69f302708dde8719de240Steven Lang		return 1;
1149de890a1e48d40238dac69f302708dde8719de240Steven Lang	}
1150ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
115149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (!is_tcp(o)) {
1152de890a1e48d40238dac69f302708dde8719de240Steven Lang		if (o->listen) {
11539b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe			log_err("fio: listen only valid for TCP proto IO\n");
11549b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe			return 1;
1155de890a1e48d40238dac69f302708dde8719de240Steven Lang		}
1156de890a1e48d40238dac69f302708dde8719de240Steven Lang		if (td_rw(td)) {
11579b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe			log_err("fio: datagram network connections must be"
1158de890a1e48d40238dac69f302708dde8719de240Steven Lang				   " read OR write\n");
11599b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe			return 1;
11609b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe		}
11619b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe		if (o->proto == FIO_TYPE_UNIX && !td->o.filename) {
11629b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe			log_err("fio: UNIX sockets need host/filename\n");
11639b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe			return 1;
1164de890a1e48d40238dac69f302708dde8719de240Steven Lang		}
1165de890a1e48d40238dac69f302708dde8719de240Steven Lang		o->listen = td_read(td);
1166de890a1e48d40238dac69f302708dde8719de240Steven Lang	}
1167443662efa60d9082bc820641e7d1d31dd58d3ae1Jens Axboe
1168de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->listen)
1169de890a1e48d40238dac69f302708dde8719de240Steven Lang		ret = fio_netio_setup_listen(td);
11700fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	else
1171de890a1e48d40238dac69f302708dde8719de240Steven Lang		ret = fio_netio_setup_connect(td);
1172ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
11737bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe	return ret;
1174ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
1175ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
1176b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic void fio_netio_cleanup(struct thread_data *td)
11779bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe{
1178b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
1179b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
1180b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	if (nd) {
118164b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe		if (nd->listenfd != -1)
118264b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe			close(nd->listenfd);
118364b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe		if (nd->pipes[0] != -1)
118464b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe			close(nd->pipes[0]);
118564b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe		if (nd->pipes[1] != -1)
118664b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe			close(nd->pipes[1]);
118764b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe
1188b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		free(nd);
1189b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	}
1190b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe}
1191b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
1192b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic int fio_netio_setup(struct thread_data *td)
1193b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe{
11947bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe	struct netio_data *nd;
11957bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe
1196de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (!td->files_index) {
11975903e7b7907854014478b6febfc5645a203ff59eJens Axboe		add_file(td, td->o.filename ?: "net", 0, 0);
1198de890a1e48d40238dac69f302708dde8719de240Steven Lang		td->o.nr_files = td->o.nr_files ?: 1;
1199b53f2c545d8335380b507bd7281178c25d27ddf0Jens Axboe		td->o.open_files++;
1200de890a1e48d40238dac69f302708dde8719de240Steven Lang	}
1201de890a1e48d40238dac69f302708dde8719de240Steven Lang
12027bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe	if (!td->io_ops->data) {
12037bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe		nd = malloc(sizeof(*nd));;
12047bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe
12057bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe		memset(nd, 0, sizeof(*nd));
12067bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe		nd->listenfd = -1;
120764b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe		nd->pipes[0] = nd->pipes[1] = -1;
12087bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe		td->io_ops->data = nd;
12097bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe	}
1210b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
12119bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe	return 0;
12129bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe}
12139bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe
121436d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboestatic void fio_netio_terminate(struct thread_data *td)
121536d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe{
121636d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe	kill(td->pid, SIGUSR2);
121736d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe}
121836d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe
121967bf982340d95ca98098ea050b54b4c7adb116c0Jens Axboe#ifdef CONFIG_LINUX_SPLICE
12209cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboestatic int fio_netio_setup_splice(struct thread_data *td)
12219cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
12229cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd;
12239cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
12249cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	fio_netio_setup(td);
12259cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
12269cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	nd = td->io_ops->data;
12279cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	if (nd) {
12289cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		if (pipe(nd->pipes) < 0)
12299cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			return 1;
12309cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
12319cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		nd->use_splice = 1;
12329cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		return 0;
12339cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	}
12349cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
12359cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	return 1;
12369cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
12379cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
12385921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboestatic struct ioengine_ops ioengine_splice = {
1239de890a1e48d40238dac69f302708dde8719de240Steven Lang	.name			= "netsplice",
1240de890a1e48d40238dac69f302708dde8719de240Steven Lang	.version		= FIO_IOOPS_VERSION,
1241de890a1e48d40238dac69f302708dde8719de240Steven Lang	.prep			= fio_netio_prep,
1242de890a1e48d40238dac69f302708dde8719de240Steven Lang	.queue			= fio_netio_queue,
1243de890a1e48d40238dac69f302708dde8719de240Steven Lang	.setup			= fio_netio_setup_splice,
1244de890a1e48d40238dac69f302708dde8719de240Steven Lang	.init			= fio_netio_init,
1245de890a1e48d40238dac69f302708dde8719de240Steven Lang	.cleanup		= fio_netio_cleanup,
1246de890a1e48d40238dac69f302708dde8719de240Steven Lang	.open_file		= fio_netio_open_file,
124736d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe	.close_file		= fio_netio_close_file,
124836d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe	.terminate		= fio_netio_terminate,
1249de890a1e48d40238dac69f302708dde8719de240Steven Lang	.options		= options,
1250de890a1e48d40238dac69f302708dde8719de240Steven Lang	.option_struct_size	= sizeof(struct netio_options),
1251de890a1e48d40238dac69f302708dde8719de240Steven Lang	.flags			= FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR |
125236d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe				  FIO_PIPEIO,
1253ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe};
12545921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
1255ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
12565921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboestatic struct ioengine_ops ioengine_rw = {
1257de890a1e48d40238dac69f302708dde8719de240Steven Lang	.name			= "net",
1258de890a1e48d40238dac69f302708dde8719de240Steven Lang	.version		= FIO_IOOPS_VERSION,
1259de890a1e48d40238dac69f302708dde8719de240Steven Lang	.prep			= fio_netio_prep,
1260de890a1e48d40238dac69f302708dde8719de240Steven Lang	.queue			= fio_netio_queue,
1261de890a1e48d40238dac69f302708dde8719de240Steven Lang	.setup			= fio_netio_setup,
1262de890a1e48d40238dac69f302708dde8719de240Steven Lang	.init			= fio_netio_init,
1263de890a1e48d40238dac69f302708dde8719de240Steven Lang	.cleanup		= fio_netio_cleanup,
1264de890a1e48d40238dac69f302708dde8719de240Steven Lang	.open_file		= fio_netio_open_file,
1265de890a1e48d40238dac69f302708dde8719de240Steven Lang	.close_file		= fio_netio_close_file,
126636d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe	.terminate		= fio_netio_terminate,
1267de890a1e48d40238dac69f302708dde8719de240Steven Lang	.options		= options,
1268de890a1e48d40238dac69f302708dde8719de240Steven Lang	.option_struct_size	= sizeof(struct netio_options),
1269de890a1e48d40238dac69f302708dde8719de240Steven Lang	.flags			= FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR |
1270ad705bcb7e79a7cdb9891db17b4c40b13b6c30c3Steven Noonan				  FIO_PIPEIO | FIO_BIT_BASED,
12719cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe};
12729cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
1273de890a1e48d40238dac69f302708dde8719de240Steven Langstatic int str_hostname_cb(void *data, const char *input)
1274de890a1e48d40238dac69f302708dde8719de240Steven Lang{
1275de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = data;
1276de890a1e48d40238dac69f302708dde8719de240Steven Lang
1277de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->td->o.filename)
1278de890a1e48d40238dac69f302708dde8719de240Steven Lang		free(o->td->o.filename);
1279de890a1e48d40238dac69f302708dde8719de240Steven Lang	o->td->o.filename = strdup(input);
1280de890a1e48d40238dac69f302708dde8719de240Steven Lang	return 0;
1281de890a1e48d40238dac69f302708dde8719de240Steven Lang}
1282de890a1e48d40238dac69f302708dde8719de240Steven Lang
1283ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboestatic void fio_init fio_netio_register(void)
1284ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
12859cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	register_ioengine(&ioengine_rw);
128667bf982340d95ca98098ea050b54b4c7adb116c0Jens Axboe#ifdef CONFIG_LINUX_SPLICE
12879cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	register_ioengine(&ioengine_splice);
12885921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
1289ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
1290ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
1291ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboestatic void fio_exit fio_netio_unregister(void)
1292ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
12939cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	unregister_ioengine(&ioengine_rw);
129467bf982340d95ca98098ea050b54b4c7adb116c0Jens Axboe#ifdef CONFIG_LINUX_SPLICE
12959cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	unregister_ioengine(&ioengine_splice);
12965921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
1297ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
1298