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"
24da91d7597e025cf8f12667b218433b02e5494296Jens Axboe#include "../verify.h"
25ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
26b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestruct netio_data {
27b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	int listenfd;
289cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int use_splice;
2997909a1816a53059992a937852ffc040a0234757Jens Axboe	int seq_off;
309cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int pipes[2];
31b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct sockaddr_in addr;
3249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	struct sockaddr_in6 addr6;
330fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	struct sockaddr_un addr_un;
34da91d7597e025cf8f12667b218433b02e5494296Jens Axboe	uint64_t udp_send_seq;
35da91d7597e025cf8f12667b218433b02e5494296Jens Axboe	uint64_t udp_recv_seq;
36b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe};
37ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
38de890a1e48d40238dac69f302708dde8719de240Steven Langstruct netio_options {
39de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct thread_data *td;
40de890a1e48d40238dac69f302708dde8719de240Steven Lang	unsigned int port;
41de890a1e48d40238dac69f302708dde8719de240Steven Lang	unsigned int proto;
42de890a1e48d40238dac69f302708dde8719de240Steven Lang	unsigned int listen;
436f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	unsigned int pingpong;
4470a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan	unsigned int nodelay;
45d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer	unsigned int ttl;
46531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	unsigned int window_size;
475e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe	unsigned int mss;
48f16b7405fff7c3fc1da421b6bdf8552cc99c3156Bruce Cran	char *intfc;
49de890a1e48d40238dac69f302708dde8719de240Steven Lang};
50de890a1e48d40238dac69f302708dde8719de240Steven Lang
51664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboestruct udp_close_msg {
52664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	uint32_t magic;
53664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	uint32_t cmd;
54664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe};
55664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
56da91d7597e025cf8f12667b218433b02e5494296Jens Axboestruct udp_seq {
57da91d7597e025cf8f12667b218433b02e5494296Jens Axboe	uint64_t magic;
58da91d7597e025cf8f12667b218433b02e5494296Jens Axboe	uint64_t seq;
5997909a1816a53059992a937852ffc040a0234757Jens Axboe	uint64_t bs;
60da91d7597e025cf8f12667b218433b02e5494296Jens Axboe};
61da91d7597e025cf8f12667b218433b02e5494296Jens Axboe
62664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboeenum {
63664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	FIO_LINK_CLOSE = 0x89,
64b96d243044023b28731341d290943b5d47a5f794Jens Axboe	FIO_LINK_OPEN_CLOSE_MAGIC = 0x6c696e6b,
65b96d243044023b28731341d290943b5d47a5f794Jens Axboe	FIO_LINK_OPEN = 0x98,
66da91d7597e025cf8f12667b218433b02e5494296Jens Axboe	FIO_UDP_SEQ_MAGIC = 0x657375716e556563ULL,
670fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
680fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	FIO_TYPE_TCP	= 1,
690fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	FIO_TYPE_UDP	= 2,
700fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	FIO_TYPE_UNIX	= 3,
7149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	FIO_TYPE_TCP_V6	= 4,
7249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	FIO_TYPE_UDP_V6	= 5,
73664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe};
74664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
75de890a1e48d40238dac69f302708dde8719de240Steven Langstatic int str_hostname_cb(void *data, const char *input);
76de890a1e48d40238dac69f302708dde8719de240Steven Langstatic struct fio_option options[] = {
77de890a1e48d40238dac69f302708dde8719de240Steven Lang	{
78de890a1e48d40238dac69f302708dde8719de240Steven Lang		.name	= "hostname",
79e8b0e958cd219cabb1154e2b06036863a7d6dbd7Jens Axboe		.lname	= "net engine hostname",
80de890a1e48d40238dac69f302708dde8719de240Steven Lang		.type	= FIO_OPT_STR_STORE,
81de890a1e48d40238dac69f302708dde8719de240Steven Lang		.cb	= str_hostname_cb,
82de890a1e48d40238dac69f302708dde8719de240Steven Lang		.help	= "Hostname for net IO engine",
83e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.category = FIO_OPT_C_ENGINE,
84e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.group	= FIO_OPT_G_NETIO,
85de890a1e48d40238dac69f302708dde8719de240Steven Lang	},
86de890a1e48d40238dac69f302708dde8719de240Steven Lang	{
87de890a1e48d40238dac69f302708dde8719de240Steven Lang		.name	= "port",
88e8b0e958cd219cabb1154e2b06036863a7d6dbd7Jens Axboe		.lname	= "net engine port",
89de890a1e48d40238dac69f302708dde8719de240Steven Lang		.type	= FIO_OPT_INT,
90de890a1e48d40238dac69f302708dde8719de240Steven Lang		.off1	= offsetof(struct netio_options, port),
91de890a1e48d40238dac69f302708dde8719de240Steven Lang		.minval	= 1,
92de890a1e48d40238dac69f302708dde8719de240Steven Lang		.maxval	= 65535,
93de890a1e48d40238dac69f302708dde8719de240Steven Lang		.help	= "Port to use for TCP or UDP net connections",
94e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.category = FIO_OPT_C_ENGINE,
95e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.group	= FIO_OPT_G_NETIO,
96de890a1e48d40238dac69f302708dde8719de240Steven Lang	},
97de890a1e48d40238dac69f302708dde8719de240Steven Lang	{
98de890a1e48d40238dac69f302708dde8719de240Steven Lang		.name	= "protocol",
99e8b0e958cd219cabb1154e2b06036863a7d6dbd7Jens Axboe		.lname	= "net engine protocol",
100de890a1e48d40238dac69f302708dde8719de240Steven Lang		.alias	= "proto",
101de890a1e48d40238dac69f302708dde8719de240Steven Lang		.type	= FIO_OPT_STR,
102de890a1e48d40238dac69f302708dde8719de240Steven Lang		.off1	= offsetof(struct netio_options, proto),
103de890a1e48d40238dac69f302708dde8719de240Steven Lang		.help	= "Network protocol to use",
104de890a1e48d40238dac69f302708dde8719de240Steven Lang		.def	= "tcp",
105de890a1e48d40238dac69f302708dde8719de240Steven Lang		.posval = {
106de890a1e48d40238dac69f302708dde8719de240Steven Lang			  { .ival = "tcp",
107de890a1e48d40238dac69f302708dde8719de240Steven Lang			    .oval = FIO_TYPE_TCP,
108de890a1e48d40238dac69f302708dde8719de240Steven Lang			    .help = "Transmission Control Protocol",
109de890a1e48d40238dac69f302708dde8719de240Steven Lang			  },
110eb2323108392e65ab7c4e4c5cbd74a1597b60187Jens Axboe#ifdef CONFIG_IPV6
11149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			  { .ival = "tcpv6",
11249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			    .oval = FIO_TYPE_TCP_V6,
11349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			    .help = "Transmission Control Protocol V6",
11449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			  },
115eb2323108392e65ab7c4e4c5cbd74a1597b60187Jens Axboe#endif
116de890a1e48d40238dac69f302708dde8719de240Steven Lang			  { .ival = "udp",
117de890a1e48d40238dac69f302708dde8719de240Steven Lang			    .oval = FIO_TYPE_UDP,
118f5cc3d0ea8acf13c8e722da6c2d485889968d132Bruce Cran			    .help = "User Datagram Protocol",
119de890a1e48d40238dac69f302708dde8719de240Steven Lang			  },
120eb2323108392e65ab7c4e4c5cbd74a1597b60187Jens Axboe#ifdef CONFIG_IPV6
12149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			  { .ival = "udpv6",
12249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			    .oval = FIO_TYPE_UDP_V6,
12349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			    .help = "User Datagram Protocol V6",
12449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			  },
125eb2323108392e65ab7c4e4c5cbd74a1597b60187Jens Axboe#endif
126de890a1e48d40238dac69f302708dde8719de240Steven Lang			  { .ival = "unix",
127de890a1e48d40238dac69f302708dde8719de240Steven Lang			    .oval = FIO_TYPE_UNIX,
128de890a1e48d40238dac69f302708dde8719de240Steven Lang			    .help = "UNIX domain socket",
129de890a1e48d40238dac69f302708dde8719de240Steven Lang			  },
130de890a1e48d40238dac69f302708dde8719de240Steven Lang		},
131e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.category = FIO_OPT_C_ENGINE,
132e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.group	= FIO_OPT_G_NETIO,
133de890a1e48d40238dac69f302708dde8719de240Steven Lang	},
1341eafa37ac57bb08ca21af8ab76bd7848ae2e7c97Jens Axboe#ifdef CONFIG_TCP_NODELAY
135de890a1e48d40238dac69f302708dde8719de240Steven Lang	{
13670a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan		.name	= "nodelay",
13770a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan		.type	= FIO_OPT_BOOL,
13870a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan		.off1	= offsetof(struct netio_options, nodelay),
13970a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan		.help	= "Use TCP_NODELAY on TCP connections",
140e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.category = FIO_OPT_C_ENGINE,
141e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.group	= FIO_OPT_G_NETIO,
14270a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan	},
1431eafa37ac57bb08ca21af8ab76bd7848ae2e7c97Jens Axboe#endif
144de890a1e48d40238dac69f302708dde8719de240Steven Lang	{
145de890a1e48d40238dac69f302708dde8719de240Steven Lang		.name	= "listen",
146e8b0e958cd219cabb1154e2b06036863a7d6dbd7Jens Axboe		.lname	= "net engine listen",
147de890a1e48d40238dac69f302708dde8719de240Steven Lang		.type	= FIO_OPT_STR_SET,
148de890a1e48d40238dac69f302708dde8719de240Steven Lang		.off1	= offsetof(struct netio_options, listen),
149de890a1e48d40238dac69f302708dde8719de240Steven Lang		.help	= "Listen for incoming TCP connections",
150e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.category = FIO_OPT_C_ENGINE,
151e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.group	= FIO_OPT_G_NETIO,
152de890a1e48d40238dac69f302708dde8719de240Steven Lang	},
153de890a1e48d40238dac69f302708dde8719de240Steven Lang	{
1546f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe		.name	= "pingpong",
1556f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe		.type	= FIO_OPT_STR_SET,
1566f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe		.off1	= offsetof(struct netio_options, pingpong),
1576f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe		.help	= "Ping-pong IO requests",
158e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.category = FIO_OPT_C_ENGINE,
159e90a0adf85f75a65c02b22ba3766dff0d9d82ae6Jens Axboe		.group	= FIO_OPT_G_NETIO,
1606f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	},
1616f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	{
162b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer		.name	= "interface",
163b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer		.lname	= "net engine interface",
164b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer		.type	= FIO_OPT_STR_STORE,
165f16b7405fff7c3fc1da421b6bdf8552cc99c3156Bruce Cran		.off1	= offsetof(struct netio_options, intfc),
166b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer		.help	= "Network interface to use",
167b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer		.category = FIO_OPT_C_ENGINE,
168b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer		.group	= FIO_OPT_G_NETIO,
169b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer	},
170b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer	{
171d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		.name	= "ttl",
172d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		.lname	= "net engine multicast ttl",
173d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		.type	= FIO_OPT_INT,
174d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		.off1	= offsetof(struct netio_options, ttl),
175d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		.def    = "1",
176d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		.minval	= 0,
177d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		.help	= "Time-to-live value for outgoing UDP multicast packets",
178d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		.category = FIO_OPT_C_ENGINE,
179d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		.group	= FIO_OPT_G_NETIO,
180d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer	},
181531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe#ifdef CONFIG_NET_WINDOWSIZE
182531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	{
183531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe		.name	= "window_size",
184531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe		.lname	= "Window Size",
185531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe		.type	= FIO_OPT_INT,
186531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe		.off1	= offsetof(struct netio_options, window_size),
187531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe		.minval	= 0,
188531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe		.help	= "Set socket buffer window size",
189531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe		.category = FIO_OPT_C_ENGINE,
190531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe		.group	= FIO_OPT_G_NETIO,
191531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	},
192531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe#endif
1935e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe#ifdef CONFIG_NET_MSS
1945e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe	{
1955e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe		.name	= "mss",
1965e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe		.lname	= "Maximum segment size",
1975e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe		.type	= FIO_OPT_INT,
1985e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe		.off1	= offsetof(struct netio_options, mss),
1995e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe		.minval	= 0,
2005e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe		.help	= "Set TCP maximum segment size",
2015e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe		.category = FIO_OPT_C_ENGINE,
2025e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe		.group	= FIO_OPT_G_NETIO,
2035e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe	},
2045e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe#endif
205d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer	{
206de890a1e48d40238dac69f302708dde8719de240Steven Lang		.name	= NULL,
207de890a1e48d40238dac69f302708dde8719de240Steven Lang	},
208de890a1e48d40238dac69f302708dde8719de240Steven Lang};
209de890a1e48d40238dac69f302708dde8719de240Steven Lang
21049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboestatic inline int is_udp(struct netio_options *o)
21149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe{
21249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	return o->proto == FIO_TYPE_UDP || o->proto == FIO_TYPE_UDP_V6;
21349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe}
21449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
21549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboestatic inline int is_tcp(struct netio_options *o)
21649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe{
21749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	return o->proto == FIO_TYPE_TCP || o->proto == FIO_TYPE_TCP_V6;
21849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe}
21949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
22049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboestatic inline int is_ipv6(struct netio_options *o)
22149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe{
22249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	return o->proto == FIO_TYPE_UDP_V6 || o->proto == FIO_TYPE_TCP_V6;
22349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe}
22449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
225531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboestatic int set_window_size(struct thread_data *td, int fd)
226531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe{
227531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe#ifdef CONFIG_NET_WINDOWSIZE
228531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	struct netio_options *o = td->eo;
229531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	unsigned int wss;
230531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	int snd, rcv, ret;
231531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe
232531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	if (!o->window_size)
233531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe		return 0;
234531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe
235531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	rcv = o->listen || o->pingpong;
236531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	snd = !o->listen || o->pingpong;
237531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	wss = o->window_size;
238531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	ret = 0;
239531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe
240531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	if (rcv) {
241531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe		ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void *) &wss,
242531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe					sizeof(wss));
243531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe		if (ret < 0)
244531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe			td_verror(td, errno, "rcvbuf window size");
245531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	}
246531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	if (snd && !ret) {
247531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe		ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void *) &wss,
248531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe					sizeof(wss));
249531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe		if (ret < 0)
250531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe			td_verror(td, errno, "sndbuf window size");
251531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	}
252531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe
253531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	return ret;
254531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe#else
255531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	td_verror(td, -EINVAL, "setsockopt window size");
256531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	return -1;
257531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe#endif
258531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe}
259531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe
2605e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboestatic int set_mss(struct thread_data *td, int fd)
2615e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe{
2625e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe#ifdef CONFIG_NET_MSS
2635e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe	struct netio_options *o = td->eo;
2645e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe	unsigned int mss;
2655e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe	int ret;
2665e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe
2675e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe	if (!o->mss || !is_tcp(o))
2685e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe		return 0;
2695e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe
2705e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe	mss = o->mss;
2715e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe	ret = setsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, (void *) &mss,
2725e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe				sizeof(mss));
2735e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe	if (ret < 0)
2745e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe		td_verror(td, errno, "setsockopt TCP_MAXSEG");
2755e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe
2765e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe	return ret;
2775e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe#else
2785e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe	td_verror(td, -EINVAL, "setsockopt TCP_MAXSEG");
2795e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe	return -1;
2805e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe#endif
2815e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe}
2825e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe
2835e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe
284371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe/*
285371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe * Return -1 for error and 'nr events' for a positive number
286371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe * of events
287371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe */
288371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboestatic int poll_wait(struct thread_data *td, int fd, short events)
289371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe{
290371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	struct pollfd pfd;
291371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	int ret;
292371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
293371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	while (!td->terminate) {
294371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		pfd.fd = fd;
295371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		pfd.events = events;
296371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		ret = poll(&pfd, 1, -1);
297371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		if (ret < 0) {
298371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe			if (errno == EINTR)
299d5b388a560783a61af7b424757bc6dead2309c28Jens Axboe				break;
300371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
301371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe			td_verror(td, errno, "poll");
302371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe			return -1;
303371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		} else if (!ret)
304371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe			continue;
305371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
306371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		break;
307371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	}
308371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
309371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	if (pfd.revents & events)
310371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		return 1;
311371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
312371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	return -1;
313371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe}
314371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
315b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrerstatic int fio_netio_is_multicast(const char *mcaddr)
316b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer{
317b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer	in_addr_t addr = inet_network(mcaddr);
318b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer	if (addr == -1)
319b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer		return 0;
320b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer
321b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer	if (inet_network("224.0.0.0") <= addr &&
322b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer	    inet_network("239.255.255.255") >= addr)
323b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer		return 1;
324b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer
325b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer	return 0;
326b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer}
327b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer
328b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer
329ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboestatic int fio_netio_prep(struct thread_data *td, struct io_u *io_u)
330ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
331de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
332ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
3337a6499dada619928267d26b4629b0c8623dc423aJens Axboe	/*
3347a6499dada619928267d26b4629b0c8623dc423aJens Axboe	 * Make sure we don't see spurious reads to a receiver, and vice versa
3357a6499dada619928267d26b4629b0c8623dc423aJens Axboe	 */
33649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_tcp(o))
337de890a1e48d40238dac69f302708dde8719de240Steven Lang		return 0;
338de890a1e48d40238dac69f302708dde8719de240Steven Lang
339de890a1e48d40238dac69f302708dde8719de240Steven Lang	if ((o->listen && io_u->ddir == DDIR_WRITE) ||
340de890a1e48d40238dac69f302708dde8719de240Steven Lang	    (!o->listen && io_u->ddir == DDIR_READ)) {
341e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, EINVAL, "bad direction");
3427a6499dada619928267d26b4629b0c8623dc423aJens Axboe		return 1;
343ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
3443f457bea08a6bd60d99950c59c5432b8e78c69e2Bruce Cran
345f85ac25a7d5c9d5ba4d5c73363a6a2a461a9b013Jens Axboe	return 0;
346ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
347ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
34867bf982340d95ca98098ea050b54b4c7adb116c0Jens Axboe#ifdef CONFIG_LINUX_SPLICE
349cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int splice_io_u(int fdin, int fdout, unsigned int len)
350ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
3519cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int bytes = 0;
3527a6499dada619928267d26b4629b0c8623dc423aJens Axboe
3539cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	while (len) {
354cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		int ret = splice(fdin, NULL, fdout, NULL, len, 0);
3559cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
3569cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		if (ret < 0) {
3579cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			if (!bytes)
3589cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe				bytes = ret;
3599cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
3609cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			break;
3619cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		} else if (!ret)
3629cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			break;
3639cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
3649cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		bytes += ret;
365f657a2fbbb0deaf455edc478d73b664929bcb766Jens Axboe		len -= ret;
3669cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	}
3679cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
3689cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	return bytes;
3699cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
3709cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
3719cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe/*
372cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * Receive bytes from a socket and fill them into the internal pipe
3739cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe */
374cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int splice_in(struct thread_data *td, struct io_u *io_u)
3759cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
3769cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd = td->io_ops->data;
3779cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
378cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return splice_io_u(io_u->file->fd, nd->pipes[1], io_u->xfer_buflen);
3799cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
3809cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
3819cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe/*
382cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * Transmit 'len' bytes from the internal pipe
3839cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe */
384cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int splice_out(struct thread_data *td, struct io_u *io_u,
385cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		      unsigned int len)
3869cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
3879cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd = td->io_ops->data;
388cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe
389cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return splice_io_u(nd->pipes[0], io_u->file->fd, len);
390cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe}
391cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe
392cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int vmsplice_io_u(struct io_u *io_u, int fd, unsigned int len)
393cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe{
3949cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct iovec iov = {
3959cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		.iov_base = io_u->xfer_buf,
3969cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		.iov_len = len,
3979cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	};
3989cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int bytes = 0;
3999cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
4009cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	while (iov.iov_len) {
401cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		int ret = vmsplice(fd, &iov, 1, SPLICE_F_MOVE);
4029cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
4039cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		if (ret < 0) {
4049cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			if (!bytes)
4059cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe				bytes = ret;
4069cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			break;
4079cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		} else if (!ret)
4089cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			break;
4099cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
4109cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		iov.iov_len -= ret;
411cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		iov.iov_base += ret;
412f657a2fbbb0deaf455edc478d73b664929bcb766Jens Axboe		bytes += ret;
4139cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	}
4149cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
4159cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	return bytes;
416cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe
4179cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
4189cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
4199cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe/*
420cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * vmsplice() pipe to io_u buffer
4219cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe */
422cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int vmsplice_io_u_out(struct thread_data *td, struct io_u *io_u,
423cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe			     unsigned int len)
4249cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
4259cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd = td->io_ops->data;
4269cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
427cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return vmsplice_io_u(io_u, nd->pipes[0], len);
428cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe}
4299cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
430cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe/*
431cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * vmsplice() io_u to pipe
432cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe */
433cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboestatic int vmsplice_io_u_in(struct thread_data *td, struct io_u *io_u)
434cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe{
435cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	struct netio_data *nd = td->io_ops->data;
436ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
437cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return vmsplice_io_u(io_u, nd->pipes[1], io_u->xfer_buflen);
4389cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
4399cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
440cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe/*
441cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * splice receive - transfer socket data into a pipe using splice, then map
442cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * that pipe data into the io_u using vmsplice.
443cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe */
4449cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboestatic int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
4459cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
4469cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int ret;
4479cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
4489cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	ret = splice_in(td, io_u);
449cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	if (ret > 0)
450cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		return vmsplice_io_u_out(td, io_u, ret);
4519cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
452cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return ret;
4539cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
4549cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
455cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe/*
456cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * splice transmit - map data from the io_u into a pipe by using vmsplice,
457cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe * then transfer that pipe to a socket using splice.
458cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe */
4599cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboestatic int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
4609cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
4619cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int ret;
4629cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
4639cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	ret = vmsplice_io_u_in(td, io_u);
464cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	if (ret > 0)
465cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe		return splice_out(td, io_u, ret);
4669cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
467cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe	return ret;
4689cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
4695921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#else
4705921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboestatic int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
4715921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe{
472af8771b9b91eb2cd23a40aaa729bad4f78acb928Jens Axboe	errno = EOPNOTSUPP;
4735921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe	return -1;
4745921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe}
4755921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe
4765921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboestatic int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
4775921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe{
478af8771b9b91eb2cd23a40aaa729bad4f78acb928Jens Axboe	errno = EOPNOTSUPP;
4795921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe	return -1;
4805921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe}
4815921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
4829cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
483da91d7597e025cf8f12667b218433b02e5494296Jens Axboestatic void store_udp_seq(struct netio_data *nd, struct io_u *io_u)
484da91d7597e025cf8f12667b218433b02e5494296Jens Axboe{
485da91d7597e025cf8f12667b218433b02e5494296Jens Axboe	struct udp_seq *us;
486da91d7597e025cf8f12667b218433b02e5494296Jens Axboe
487868902df131bcef342fb735b89027f6139d47c7fSteven Noonan	if (io_u->xfer_buflen < sizeof(*us))
488868902df131bcef342fb735b89027f6139d47c7fSteven Noonan		return;
489868902df131bcef342fb735b89027f6139d47c7fSteven Noonan
490da91d7597e025cf8f12667b218433b02e5494296Jens Axboe	us = io_u->xfer_buf + io_u->xfer_buflen - sizeof(*us);
491768ae05c2d4c5332c574a6470a23d1f522803f02Jens Axboe	us->magic = cpu_to_le64((uint64_t) FIO_UDP_SEQ_MAGIC);
49297909a1816a53059992a937852ffc040a0234757Jens Axboe	us->bs = cpu_to_le64((uint64_t) io_u->xfer_buflen);
493da91d7597e025cf8f12667b218433b02e5494296Jens Axboe	us->seq = cpu_to_le64(nd->udp_send_seq++);
494da91d7597e025cf8f12667b218433b02e5494296Jens Axboe}
495da91d7597e025cf8f12667b218433b02e5494296Jens Axboe
49667e149c4c2b580089287813246344908770c3be9Jens Axboestatic void verify_udp_seq(struct thread_data *td, struct netio_data *nd,
49767e149c4c2b580089287813246344908770c3be9Jens Axboe			   struct io_u *io_u)
498da91d7597e025cf8f12667b218433b02e5494296Jens Axboe{
499da91d7597e025cf8f12667b218433b02e5494296Jens Axboe	struct udp_seq *us;
500da91d7597e025cf8f12667b218433b02e5494296Jens Axboe	uint64_t seq;
501da91d7597e025cf8f12667b218433b02e5494296Jens Axboe
502868902df131bcef342fb735b89027f6139d47c7fSteven Noonan	if (io_u->xfer_buflen < sizeof(*us))
503868902df131bcef342fb735b89027f6139d47c7fSteven Noonan		return;
504868902df131bcef342fb735b89027f6139d47c7fSteven Noonan
50597909a1816a53059992a937852ffc040a0234757Jens Axboe	if (nd->seq_off)
50697909a1816a53059992a937852ffc040a0234757Jens Axboe		return;
50797909a1816a53059992a937852ffc040a0234757Jens Axboe
508da91d7597e025cf8f12667b218433b02e5494296Jens Axboe	us = io_u->xfer_buf + io_u->xfer_buflen - sizeof(*us);
509da91d7597e025cf8f12667b218433b02e5494296Jens Axboe	if (le64_to_cpu(us->magic) != FIO_UDP_SEQ_MAGIC)
510da91d7597e025cf8f12667b218433b02e5494296Jens Axboe		return;
51197909a1816a53059992a937852ffc040a0234757Jens Axboe	if (le64_to_cpu(us->bs) != io_u->xfer_buflen) {
51297909a1816a53059992a937852ffc040a0234757Jens Axboe		nd->seq_off = 1;
51397909a1816a53059992a937852ffc040a0234757Jens Axboe		return;
51497909a1816a53059992a937852ffc040a0234757Jens Axboe	}
515da91d7597e025cf8f12667b218433b02e5494296Jens Axboe
516da91d7597e025cf8f12667b218433b02e5494296Jens Axboe	seq = le64_to_cpu(us->seq);
517da91d7597e025cf8f12667b218433b02e5494296Jens Axboe
518da91d7597e025cf8f12667b218433b02e5494296Jens Axboe	if (seq != nd->udp_recv_seq)
51967e149c4c2b580089287813246344908770c3be9Jens Axboe		td->ts.drop_io_u[io_u->ddir] += seq - nd->udp_recv_seq;
520da91d7597e025cf8f12667b218433b02e5494296Jens Axboe
521da91d7597e025cf8f12667b218433b02e5494296Jens Axboe	nd->udp_recv_seq = seq + 1;
522da91d7597e025cf8f12667b218433b02e5494296Jens Axboe}
523da91d7597e025cf8f12667b218433b02e5494296Jens Axboe
5249cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboestatic int fio_netio_send(struct thread_data *td, struct io_u *io_u)
5259cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
526414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	struct netio_data *nd = td->io_ops->data;
527de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
5286f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	int ret, flags = 0;
529371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe
530664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	do {
53149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		if (is_udp(o)) {
53210aa136bddbaa7c845ab4eacb4a9a4a88d6657a3Jens Axboe			const struct sockaddr *to;
53349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			socklen_t len;
53449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
53549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			if (is_ipv6(o)) {
53649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe				to = (struct sockaddr *) &nd->addr6;
53749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe				len = sizeof(nd->addr6);
53849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			} else {
53949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe				to = (struct sockaddr *) &nd->addr;
54049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe				len = sizeof(nd->addr);
54149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			}
54262b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe
543da91d7597e025cf8f12667b218433b02e5494296Jens Axboe			if (td->o.verify == VERIFY_NONE)
544da91d7597e025cf8f12667b218433b02e5494296Jens Axboe				store_udp_seq(nd, io_u);
545da91d7597e025cf8f12667b218433b02e5494296Jens Axboe
546664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			ret = sendto(io_u->file->fd, io_u->xfer_buf,
54749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe					io_u->xfer_buflen, flags, to, len);
548664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		} else {
549664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			/*
550664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			 * if we are going to write more, set MSG_MORE
551664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			 */
5525921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#ifdef MSG_MORE
5536f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe			if ((td->this_io_bytes[DDIR_WRITE] + io_u->xfer_buflen <
5546f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe			    td->o.size) && !o->pingpong)
555664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe				flags |= MSG_MORE;
5565921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
557664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			ret = send(io_u->file->fd, io_u->xfer_buf,
558664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe					io_u->xfer_buflen, flags);
559664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		}
560664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		if (ret > 0)
561664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			break;
5629cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
563664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		ret = poll_wait(td, io_u->file->fd, POLLOUT);
564664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		if (ret <= 0)
565664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			break;
566664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	} while (1);
567664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
568664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	return ret;
569664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe}
570664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
57180436e168b57c1f988c63f9dfb0db6f51a998403Jens Axboestatic int is_close_msg(struct io_u *io_u, int len)
572664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe{
573664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	struct udp_close_msg *msg;
574664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
575664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	if (len != sizeof(struct udp_close_msg))
576664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		return 0;
577664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
578664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	msg = io_u->xfer_buf;
57980436e168b57c1f988c63f9dfb0db6f51a998403Jens Axboe	if (le32_to_cpu(msg->magic) != FIO_LINK_OPEN_CLOSE_MAGIC)
580664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		return 0;
58180436e168b57c1f988c63f9dfb0db6f51a998403Jens Axboe	if (le32_to_cpu(msg->cmd) != FIO_LINK_CLOSE)
582664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		return 0;
583664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
584664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	return 1;
5859cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
5869cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
587414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboestatic int fio_netio_recv(struct thread_data *td, struct io_u *io_u)
5889cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
589414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	struct netio_data *nd = td->io_ops->data;
590de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
5916f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	int ret, flags = 0;
592664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
593664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	do {
59449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		if (is_udp(o)) {
595b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			struct sockaddr *from;
59649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			socklen_t l, *len = &l;
597b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer
598b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			if (o->listen) {
59949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe				if (!is_ipv6(o)) {
60049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe					from = (struct sockaddr *) &nd->addr;
60149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe					*len = sizeof(nd->addr);
60249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe				} else {
60349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe					from = (struct sockaddr *) &nd->addr6;
60449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe					*len = sizeof(nd->addr6);
60549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe				}
606b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			} else {
607b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer				from = NULL;
608b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer				len = NULL;
609b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			}
610664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
611664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			ret = recvfrom(io_u->file->fd, io_u->xfer_buf,
612b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer					io_u->xfer_buflen, flags, from, len);
613da91d7597e025cf8f12667b218433b02e5494296Jens Axboe
61480436e168b57c1f988c63f9dfb0db6f51a998403Jens Axboe			if (is_close_msg(io_u, ret)) {
615664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe				td->done = 1;
616664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe				return 0;
617664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			}
618664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		} else {
619664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			ret = recv(io_u->file->fd, io_u->xfer_buf,
620664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe					io_u->xfer_buflen, flags);
62180436e168b57c1f988c63f9dfb0db6f51a998403Jens Axboe
62280436e168b57c1f988c63f9dfb0db6f51a998403Jens Axboe			if (is_close_msg(io_u, ret)) {
62380436e168b57c1f988c63f9dfb0db6f51a998403Jens Axboe				td->done = 1;
62480436e168b57c1f988c63f9dfb0db6f51a998403Jens Axboe				return 0;
62580436e168b57c1f988c63f9dfb0db6f51a998403Jens Axboe			}
626664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		}
627664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		if (ret > 0)
628664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			break;
6297d988f68c7f0ff6bd4c9e558c4defbd9a544b167Jens Axboe		else if (!ret && (flags & MSG_WAITALL))
6307d988f68c7f0ff6bd4c9e558c4defbd9a544b167Jens Axboe			break;
6319cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
632664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		ret = poll_wait(td, io_u->file->fd, POLLIN);
633664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		if (ret <= 0)
634664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe			break;
635664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		flags |= MSG_WAITALL;
636664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	} while (1);
637414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
638da91d7597e025cf8f12667b218433b02e5494296Jens Axboe	if (is_udp(o) && td->o.verify == VERIFY_NONE)
63967e149c4c2b580089287813246344908770c3be9Jens Axboe		verify_udp_seq(td, nd, io_u);
640da91d7597e025cf8f12667b218433b02e5494296Jens Axboe
641664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	return ret;
6429cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
6439cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
6446f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboestatic int __fio_netio_queue(struct thread_data *td, struct io_u *io_u,
6456f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe			     enum fio_ddir ddir)
6469cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
6479cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd = td->io_ops->data;
648de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
6499cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	int ret;
6509cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
6516f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	if (ddir == DDIR_WRITE) {
65249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		if (!nd->use_splice || is_udp(o) ||
653de890a1e48d40238dac69f302708dde8719de240Steven Lang		    o->proto == FIO_TYPE_UNIX)
6549cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			ret = fio_netio_send(td, io_u);
655414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		else
656414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			ret = fio_netio_splice_out(td, io_u);
6576f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	} else if (ddir == DDIR_READ) {
65849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		if (!nd->use_splice || is_udp(o) ||
659de890a1e48d40238dac69f302708dde8719de240Steven Lang		    o->proto == FIO_TYPE_UNIX)
660414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			ret = fio_netio_recv(td, io_u);
6619cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		else
662414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			ret = fio_netio_splice_in(td, io_u);
663d4f12dd05cfb2e8e7a72604cd870e10f2394914eJens Axboe	} else
6647a6499dada619928267d26b4629b0c8623dc423aJens Axboe		ret = 0;	/* must be a SYNC */
665ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
666cec6b55da1c282b5b91ad346c7804171fccf151eJens Axboe	if (ret != (int) io_u->xfer_buflen) {
6670ecdd7f38e521cb55677264437fca6597976fd49Jens Axboe		if (ret > 0) {
668cec6b55da1c282b5b91ad346c7804171fccf151eJens Axboe			io_u->resid = io_u->xfer_buflen - ret;
669cec6b55da1c282b5b91ad346c7804171fccf151eJens Axboe			io_u->error = 0;
67036167d82e5f49dee91c6d2cd426068edee90e36fJens Axboe			return FIO_Q_COMPLETED;
6710ecdd7f38e521cb55677264437fca6597976fd49Jens Axboe		} else if (!ret)
6720ecdd7f38e521cb55677264437fca6597976fd49Jens Axboe			return FIO_Q_BUSY;
6730ecdd7f38e521cb55677264437fca6597976fd49Jens Axboe		else {
674414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			int err = errno;
675414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
6766f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe			if (ddir == DDIR_WRITE && err == EMSGSIZE)
677414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe				return FIO_Q_BUSY;
678414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
679414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe			io_u->error = err;
680414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		}
681ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
682ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
68336167d82e5f49dee91c6d2cd426068edee90e36fJens Axboe	if (io_u->error)
684e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, io_u->error, "xfer");
685ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
68636167d82e5f49dee91c6d2cd426068edee90e36fJens Axboe	return FIO_Q_COMPLETED;
687ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
688ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
6896f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboestatic int fio_netio_queue(struct thread_data *td, struct io_u *io_u)
6906f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe{
6916f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	struct netio_options *o = td->eo;
6926f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	int ret;
6936f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe
6946f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	fio_ro_check(td, io_u);
6956f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe
6966f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	ret = __fio_netio_queue(td, io_u, io_u->ddir);
6976f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	if (!o->pingpong || ret != FIO_Q_COMPLETED)
6986f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe		return ret;
6996f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe
7006f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	/*
7016f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	 * For ping-pong mode, receive or send reply as needed
7026f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	 */
7036f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	if (td_read(td) && io_u->ddir == DDIR_READ)
7046f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe		ret = __fio_netio_queue(td, io_u, DDIR_WRITE);
7056f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	else if (td_write(td) && io_u->ddir == DDIR_WRITE)
7066f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe		ret = __fio_netio_queue(td, io_u, DDIR_READ);
7076f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe
7086f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe	return ret;
7096f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe}
7106f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe
711b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic int fio_netio_connect(struct thread_data *td, struct fio_file *f)
712ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
713b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
714de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
7156264c7a8ddd0998f371604c227d3aea491922681Jens Axboe	int type, domain;
716414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
717de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->proto == FIO_TYPE_TCP) {
7180fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		domain = AF_INET;
719414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		type = SOCK_STREAM;
72049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else if (o->proto == FIO_TYPE_TCP_V6) {
72149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		domain = AF_INET6;
72249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		type = SOCK_STREAM;
723de890a1e48d40238dac69f302708dde8719de240Steven Lang	} else if (o->proto == FIO_TYPE_UDP) {
7240fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		domain = AF_INET;
725414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		type = SOCK_DGRAM;
72649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else if (o->proto == FIO_TYPE_UDP_V6) {
72749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		domain = AF_INET6;
72849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		type = SOCK_DGRAM;
729de890a1e48d40238dac69f302708dde8719de240Steven Lang	} else if (o->proto == FIO_TYPE_UNIX) {
7300fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		domain = AF_UNIX;
7310fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		type = SOCK_STREAM;
7320fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	} else {
733de890a1e48d40238dac69f302708dde8719de240Steven Lang		log_err("fio: bad network type %d\n", o->proto);
7340fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		f->fd = -1;
7350fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		return 1;
7360fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	}
737ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
7380fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	f->fd = socket(domain, type, 0);
739b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	if (f->fd < 0) {
740b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		td_verror(td, errno, "socket");
741b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		return 1;
742ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
743ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
7441eafa37ac57bb08ca21af8ab76bd7848ae2e7c97Jens Axboe#ifdef CONFIG_TCP_NODELAY
74549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (o->nodelay && is_tcp(o)) {
7466264c7a8ddd0998f371604c227d3aea491922681Jens Axboe		int optval = 1;
7476264c7a8ddd0998f371604c227d3aea491922681Jens Axboe
74826e594a55a54d47ce0a0784c27c6f851c83d101aJens Axboe		if (setsockopt(f->fd, IPPROTO_TCP, TCP_NODELAY, (void *) &optval, sizeof(int)) < 0) {
74970a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan			log_err("fio: cannot set TCP_NODELAY option on socket (%s), disable with 'nodelay=0'\n", strerror(errno));
75070a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan			return 1;
75170a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan		}
75270a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan	}
7531eafa37ac57bb08ca21af8ab76bd7848ae2e7c97Jens Axboe#endif
75470a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan
755531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	if (set_window_size(td, f->fd)) {
756531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe		close(f->fd);
757531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe		return 1;
758531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	}
7595e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe	if (set_mss(td, f->fd)) {
7605e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe		close(f->fd);
7615e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe		return 1;
7625e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe	}
763531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe
76449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_udp(o)) {
765d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		if (!fio_netio_is_multicast(td->o.filename))
766d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer			return 0;
76749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		if (is_ipv6(o)) {
76849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			log_err("fio: multicast not supported on IPv6\n");
76949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			close(f->fd);
77049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			return 1;
77149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		}
772d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer
773f16b7405fff7c3fc1da421b6bdf8552cc99c3156Bruce Cran		if (o->intfc) {
774b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer			struct in_addr interface_addr;
77549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
776f16b7405fff7c3fc1da421b6bdf8552cc99c3156Bruce Cran			if (inet_aton(o->intfc, &interface_addr) == 0) {
777b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer				log_err("fio: interface not valid interface IP\n");
778b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer				close(f->fd);
779b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer				return 1;
780b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer			}
781f16b7405fff7c3fc1da421b6bdf8552cc99c3156Bruce Cran			if (setsockopt(f->fd, IPPROTO_IP, IP_MULTICAST_IF, (const char*)&interface_addr, sizeof(interface_addr)) < 0) {
782b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer				td_verror(td, errno, "setsockopt IP_MULTICAST_IF");
783b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer				close(f->fd);
784b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer				return 1;
785b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer			}
786b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer		}
787f16b7405fff7c3fc1da421b6bdf8552cc99c3156Bruce Cran		if (setsockopt(f->fd, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&o->ttl, sizeof(o->ttl)) < 0) {
788d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer			td_verror(td, errno, "setsockopt IP_MULTICAST_TTL");
789d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer			close(f->fd);
790d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer			return 1;
791d3a623deee774b82e4f92c6b9b4b0233b0f4454cShawn Bohrer		}
792414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		return 0;
793b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer	} else if (o->proto == FIO_TYPE_TCP) {
79467bf982340d95ca98098ea050b54b4c7adb116c0Jens Axboe		socklen_t len = sizeof(nd->addr);
795414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
7960fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		if (connect(f->fd, (struct sockaddr *) &nd->addr, len) < 0) {
7970fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe			td_verror(td, errno, "connect");
798b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe			close(f->fd);
7990fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe			return 1;
8000fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		}
80149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else if (o->proto == FIO_TYPE_TCP_V6) {
80249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		socklen_t len = sizeof(nd->addr6);
80349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
80449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		if (connect(f->fd, (struct sockaddr *) &nd->addr6, len) < 0) {
80549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			td_verror(td, errno, "connect");
80649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			close(f->fd);
80749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe			return 1;
80849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		}
80949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
8100fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	} else {
8110fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		struct sockaddr_un *addr = &nd->addr_un;
81267bf982340d95ca98098ea050b54b4c7adb116c0Jens Axboe		socklen_t len;
8130fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
8140fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		len = sizeof(addr->sun_family) + strlen(addr->sun_path) + 1;
8150fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
8160fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		if (connect(f->fd, (struct sockaddr *) addr, len) < 0) {
8170fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe			td_verror(td, errno, "connect");
818b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe			close(f->fd);
8190fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe			return 1;
8200fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		}
821ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
822ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
823ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	return 0;
824ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
825ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
826b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic int fio_netio_accept(struct thread_data *td, struct fio_file *f)
8275fdd124a3b811993542825847f207587d5f4661eJens Axboe{
828b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
829de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
83049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	socklen_t socklen;
8316264c7a8ddd0998f371604c227d3aea491922681Jens Axboe	int state;
8325fdd124a3b811993542825847f207587d5f4661eJens Axboe
83349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_udp(o)) {
834414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		f->fd = nd->listenfd;
835414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		return 0;
836414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe	}
837414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
838859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe	state = td->runstate;
839859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe	td_set_runstate(td, TD_SETTING_UP);
840859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe
8416d86144dd10b05e8b82e9b895c35dd778e5e71abJens Axboe	log_info("fio: waiting for connection\n");
8425fdd124a3b811993542825847f207587d5f4661eJens Axboe
843371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	if (poll_wait(td, nd->listenfd, POLLIN) < 0)
844859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe		goto err;
8450c09442b26216aed16f758712f744a2c54726cdbJens Axboe
84649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (o->proto == FIO_TYPE_TCP) {
84749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		socklen = sizeof(nd->addr);
84849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		f->fd = accept(nd->listenfd, (struct sockaddr *) &nd->addr, &socklen);
84949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else {
85049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		socklen = sizeof(nd->addr6);
85149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		f->fd = accept(nd->listenfd, (struct sockaddr *) &nd->addr6, &socklen);
85249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	}
85349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
854371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe	if (f->fd < 0) {
855371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe		td_verror(td, errno, "accept");
856859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe		goto err;
857b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	}
8585fdd124a3b811993542825847f207587d5f4661eJens Axboe
8591eafa37ac57bb08ca21af8ab76bd7848ae2e7c97Jens Axboe#ifdef CONFIG_TCP_NODELAY
86049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (o->nodelay && is_tcp(o)) {
8616264c7a8ddd0998f371604c227d3aea491922681Jens Axboe		int optval = 1;
8626264c7a8ddd0998f371604c227d3aea491922681Jens Axboe
86326e594a55a54d47ce0a0784c27c6f851c83d101aJens Axboe		if (setsockopt(f->fd, IPPROTO_TCP, TCP_NODELAY, (void *) &optval, sizeof(int)) < 0) {
86470a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan			log_err("fio: cannot set TCP_NODELAY option on socket (%s), disable with 'nodelay=0'\n", strerror(errno));
86570a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan			return 1;
86670a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan		}
86770a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan	}
8681eafa37ac57bb08ca21af8ab76bd7848ae2e7c97Jens Axboe#endif
86970a7878c00e130affc3e0bd7d59bd83d57c3268eSteven Noonan
8700cae16ffe3e4ca17cdb88fe64d357b7cde643f6aJens Axboe	reset_all_stats(td);
871859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe	td_set_runstate(td, state);
872b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	return 0;
873859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboeerr:
874859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe	td_set_runstate(td, state);
875859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe	return 1;
876b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe}
877b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
87880436e168b57c1f988c63f9dfb0db6f51a998403Jens Axboestatic void fio_netio_send_close(struct thread_data *td, struct fio_file *f)
879664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe{
880664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	struct netio_data *nd = td->io_ops->data;
88149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	struct netio_options *o = td->eo;
882664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	struct udp_close_msg msg;
88349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	struct sockaddr *to;
88449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	socklen_t len;
885664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	int ret;
886664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
88749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_ipv6(o)) {
88849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		to = (struct sockaddr *) &nd->addr6;
88949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		len = sizeof(nd->addr6);
89049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else {
89149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		to = (struct sockaddr *) &nd->addr;
89249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		len = sizeof(nd->addr);
89349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	}
89449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
89580436e168b57c1f988c63f9dfb0db6f51a998403Jens Axboe	msg.magic = cpu_to_le32((uint32_t) FIO_LINK_OPEN_CLOSE_MAGIC);
89680436e168b57c1f988c63f9dfb0db6f51a998403Jens Axboe	msg.cmd = cpu_to_le32((uint32_t) FIO_LINK_CLOSE);
897664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
89849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	ret = sendto(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to, len);
899664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	if (ret < 0)
900664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe		td_verror(td, errno, "sendto udp link close");
901664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe}
902664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
903664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboestatic int fio_netio_close_file(struct thread_data *td, struct fio_file *f)
904664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe{
905664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	/*
90680436e168b57c1f988c63f9dfb0db6f51a998403Jens Axboe	 * Notify the receiver that we are closing down the link
907664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	 */
90880436e168b57c1f988c63f9dfb0db6f51a998403Jens Axboe	fio_netio_send_close(td, f);
909664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
910664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe	return generic_close_file(td, f);
911664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe}
912664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe
913b96d243044023b28731341d290943b5d47a5f794Jens Axboestatic int fio_netio_udp_recv_open(struct thread_data *td, struct fio_file *f)
914b96d243044023b28731341d290943b5d47a5f794Jens Axboe{
915b96d243044023b28731341d290943b5d47a5f794Jens Axboe	struct netio_data *nd = td->io_ops->data;
91649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	struct netio_options *o = td->eo;
917b96d243044023b28731341d290943b5d47a5f794Jens Axboe	struct udp_close_msg msg;
91849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	struct sockaddr *to;
91949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	socklen_t len;
920b96d243044023b28731341d290943b5d47a5f794Jens Axboe	int ret;
921b96d243044023b28731341d290943b5d47a5f794Jens Axboe
92249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_ipv6(o)) {
92349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		len = sizeof(nd->addr6);
92449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		to = (struct sockaddr *) &nd->addr6;
92549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else {
92649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		len = sizeof(nd->addr);
92749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		to = (struct sockaddr *) &nd->addr;
92849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	}
92949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
9301f81991ed356dd7257aef2c715ba9a24d9af93a5Jens Axboe	ret = recvfrom(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to, &len);
931b96d243044023b28731341d290943b5d47a5f794Jens Axboe	if (ret < 0) {
932ee7062fdd7c2fdc0a0427343b5c5c119e7c08032Shawn Bohrer		td_verror(td, errno, "recvfrom udp link open");
933b96d243044023b28731341d290943b5d47a5f794Jens Axboe		return ret;
934b96d243044023b28731341d290943b5d47a5f794Jens Axboe	}
935b96d243044023b28731341d290943b5d47a5f794Jens Axboe
936b96d243044023b28731341d290943b5d47a5f794Jens Axboe	if (ntohl(msg.magic) != FIO_LINK_OPEN_CLOSE_MAGIC ||
937b96d243044023b28731341d290943b5d47a5f794Jens Axboe	    ntohl(msg.cmd) != FIO_LINK_OPEN) {
938b96d243044023b28731341d290943b5d47a5f794Jens Axboe		log_err("fio: bad udp open magic %x/%x\n", ntohl(msg.magic),
939b96d243044023b28731341d290943b5d47a5f794Jens Axboe								ntohl(msg.cmd));
940b96d243044023b28731341d290943b5d47a5f794Jens Axboe		return -1;
941b96d243044023b28731341d290943b5d47a5f794Jens Axboe	}
942b96d243044023b28731341d290943b5d47a5f794Jens Axboe
943da91d7597e025cf8f12667b218433b02e5494296Jens Axboe	fio_gettime(&td->start, NULL);
944b96d243044023b28731341d290943b5d47a5f794Jens Axboe	return 0;
945b96d243044023b28731341d290943b5d47a5f794Jens Axboe}
946b96d243044023b28731341d290943b5d47a5f794Jens Axboe
94780436e168b57c1f988c63f9dfb0db6f51a998403Jens Axboestatic int fio_netio_send_open(struct thread_data *td, struct fio_file *f)
948b96d243044023b28731341d290943b5d47a5f794Jens Axboe{
949b96d243044023b28731341d290943b5d47a5f794Jens Axboe	struct netio_data *nd = td->io_ops->data;
95049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	struct netio_options *o = td->eo;
951b96d243044023b28731341d290943b5d47a5f794Jens Axboe	struct udp_close_msg msg;
95249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	struct sockaddr *to;
95349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	socklen_t len;
954b96d243044023b28731341d290943b5d47a5f794Jens Axboe	int ret;
955b96d243044023b28731341d290943b5d47a5f794Jens Axboe
95649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_ipv6(o)) {
95749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		len = sizeof(nd->addr6);
95849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		to = (struct sockaddr *) &nd->addr6;
95949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else {
96049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		len = sizeof(nd->addr);
96149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		to = (struct sockaddr *) &nd->addr;
96249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	}
96349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
964b96d243044023b28731341d290943b5d47a5f794Jens Axboe	msg.magic = htonl(FIO_LINK_OPEN_CLOSE_MAGIC);
965b96d243044023b28731341d290943b5d47a5f794Jens Axboe	msg.cmd = htonl(FIO_LINK_OPEN);
966b96d243044023b28731341d290943b5d47a5f794Jens Axboe
96749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	ret = sendto(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to, len);
968b96d243044023b28731341d290943b5d47a5f794Jens Axboe	if (ret < 0) {
969b96d243044023b28731341d290943b5d47a5f794Jens Axboe		td_verror(td, errno, "sendto udp link open");
970b96d243044023b28731341d290943b5d47a5f794Jens Axboe		return ret;
971b96d243044023b28731341d290943b5d47a5f794Jens Axboe	}
972b96d243044023b28731341d290943b5d47a5f794Jens Axboe
973b96d243044023b28731341d290943b5d47a5f794Jens Axboe	return 0;
974b96d243044023b28731341d290943b5d47a5f794Jens Axboe}
975b96d243044023b28731341d290943b5d47a5f794Jens Axboe
976b96d243044023b28731341d290943b5d47a5f794Jens Axboestatic int fio_netio_open_file(struct thread_data *td, struct fio_file *f)
977b96d243044023b28731341d290943b5d47a5f794Jens Axboe{
978b96d243044023b28731341d290943b5d47a5f794Jens Axboe	int ret;
979b96d243044023b28731341d290943b5d47a5f794Jens Axboe	struct netio_options *o = td->eo;
980b96d243044023b28731341d290943b5d47a5f794Jens Axboe
981b96d243044023b28731341d290943b5d47a5f794Jens Axboe	if (o->listen)
982b96d243044023b28731341d290943b5d47a5f794Jens Axboe		ret = fio_netio_accept(td, f);
983b96d243044023b28731341d290943b5d47a5f794Jens Axboe	else
984b96d243044023b28731341d290943b5d47a5f794Jens Axboe		ret = fio_netio_connect(td, f);
985b96d243044023b28731341d290943b5d47a5f794Jens Axboe
986b96d243044023b28731341d290943b5d47a5f794Jens Axboe	if (ret) {
987b96d243044023b28731341d290943b5d47a5f794Jens Axboe		f->fd = -1;
988b96d243044023b28731341d290943b5d47a5f794Jens Axboe		return ret;
989b96d243044023b28731341d290943b5d47a5f794Jens Axboe	}
990b96d243044023b28731341d290943b5d47a5f794Jens Axboe
99149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_udp(o)) {
992b96d243044023b28731341d290943b5d47a5f794Jens Axboe		if (td_write(td))
99380436e168b57c1f988c63f9dfb0db6f51a998403Jens Axboe			ret = fio_netio_send_open(td, f);
994b96d243044023b28731341d290943b5d47a5f794Jens Axboe		else {
995b96d243044023b28731341d290943b5d47a5f794Jens Axboe			int state;
996b96d243044023b28731341d290943b5d47a5f794Jens Axboe
997b96d243044023b28731341d290943b5d47a5f794Jens Axboe			state = td->runstate;
998b96d243044023b28731341d290943b5d47a5f794Jens Axboe			td_set_runstate(td, TD_SETTING_UP);
999b96d243044023b28731341d290943b5d47a5f794Jens Axboe			ret = fio_netio_udp_recv_open(td, f);
1000b96d243044023b28731341d290943b5d47a5f794Jens Axboe			td_set_runstate(td, state);
1001b96d243044023b28731341d290943b5d47a5f794Jens Axboe		}
1002b96d243044023b28731341d290943b5d47a5f794Jens Axboe	}
1003b96d243044023b28731341d290943b5d47a5f794Jens Axboe
1004b96d243044023b28731341d290943b5d47a5f794Jens Axboe	if (ret)
1005b96d243044023b28731341d290943b5d47a5f794Jens Axboe		fio_netio_close_file(td, f);
1006b96d243044023b28731341d290943b5d47a5f794Jens Axboe
1007b96d243044023b28731341d290943b5d47a5f794Jens Axboe	return ret;
1008b96d243044023b28731341d290943b5d47a5f794Jens Axboe}
1009b96d243044023b28731341d290943b5d47a5f794Jens Axboe
10100b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboestatic int fio_fill_addr(struct thread_data *td, const char *host, int af,
10110b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe			 void *dst, struct addrinfo **res)
10120b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe{
10130b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	struct netio_options *o = td->eo;
10140b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	struct addrinfo hints;
10150b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	int ret;
10160b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe
10170b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	if (inet_pton(af, host, dst))
10180b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		return 0;
10190b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe
10200b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	memset(&hints, 0, sizeof(hints));
10210b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe
10220b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	if (is_tcp(o))
10230b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		hints.ai_socktype = SOCK_STREAM;
10240b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	else
10250b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		hints.ai_socktype = SOCK_DGRAM;
10260b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe
1027b1b1be2a569fb9226fa1ebbfed91f34322ce1c9cJens Axboe	if (is_ipv6(o))
1028b1b1be2a569fb9226fa1ebbfed91f34322ce1c9cJens Axboe		hints.ai_family = AF_INET6;
1029b1b1be2a569fb9226fa1ebbfed91f34322ce1c9cJens Axboe	else
1030b1b1be2a569fb9226fa1ebbfed91f34322ce1c9cJens Axboe		hints.ai_family = AF_INET;
1031b1b1be2a569fb9226fa1ebbfed91f34322ce1c9cJens Axboe
10320b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	ret = getaddrinfo(host, NULL, &hints, res);
10330b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	if (ret) {
10340b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		int e = EINVAL;
10350b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		char str[128];
10360b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe
10370b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		if (ret == EAI_SYSTEM)
10380b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe			e = errno;
10390b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe
10400b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		snprintf(str, sizeof(str), "getaddrinfo: %s", gai_strerror(ret));
10410b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		td_verror(td, e, str);
10420b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		return 1;
10430b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	}
10440b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe
10450b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	return 0;
10460b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe}
10470b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe
10480fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboestatic int fio_netio_setup_connect_inet(struct thread_data *td,
10490fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe					const char *host, unsigned short port)
1050b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe{
1051b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
105249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	struct netio_options *o = td->eo;
10530b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	struct addrinfo *res = NULL;
10540b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	void *dst, *src;
10550b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	int af, len;
1056b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
1057166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe	if (!host) {
1058166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe		log_err("fio: connect with no host to connect to.\n");
1059166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe		if (td_read(td))
1060166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe			log_err("fio: did you forget to set 'listen'?\n");
1061166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe
1062166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe		td_verror(td, EINVAL, "no hostname= set");
1063166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe		return 1;
1064166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe	}
1065166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe
10660b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	nd->addr.sin_family = AF_INET;
10670b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	nd->addr.sin_port = htons(port);
10680b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	nd->addr6.sin6_family = AF_INET6;
10690b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	nd->addr6.sin6_port = htons(port);
1070b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
10710b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	if (is_ipv6(o)) {
10720b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		af = AF_INET6;
107368631b36e37e1ecaadc1e5697ead4adc21640562Jens Axboe		dst = &nd->addr6.sin6_addr;
107449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else {
10750b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		af = AF_INET;
107668631b36e37e1ecaadc1e5697ead4adc21640562Jens Axboe		dst = &nd->addr.sin_addr;
10770b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	}
107849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
10790b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	if (fio_fill_addr(td, host, af, dst, &res))
10800b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		return 1;
108149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
10820b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	if (!res)
10830b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		return 0;
108449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
10850b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	if (is_ipv6(o)) {
10860b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		len = sizeof(nd->addr6.sin6_addr);
10870b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		src = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
10880b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	} else {
10890b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		len = sizeof(nd->addr.sin_addr);
10900b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe		src = &((struct sockaddr_in *) res->ai_addr)->sin_addr;
10915fdd124a3b811993542825847f207587d5f4661eJens Axboe	}
10925fdd124a3b811993542825847f207587d5f4661eJens Axboe
10930b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	memcpy(dst, src, len);
10940b783341927056e62ca2178c2ca74cca2c7b0100Jens Axboe	freeaddrinfo(res);
10955fdd124a3b811993542825847f207587d5f4661eJens Axboe	return 0;
10965fdd124a3b811993542825847f207587d5f4661eJens Axboe}
10975fdd124a3b811993542825847f207587d5f4661eJens Axboe
10980fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboestatic int fio_netio_setup_connect_unix(struct thread_data *td,
10990fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe					const char *path)
11000fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe{
11010fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	struct netio_data *nd = td->io_ops->data;
11020fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	struct sockaddr_un *soun = &nd->addr_un;
11030fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
11040fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	soun->sun_family = AF_UNIX;
11054b159fa61a9c3ed7e00c8135189c184dcc48c69fJens Axboe	memset(soun->sun_path, 0, sizeof(soun->sun_path));
11064b159fa61a9c3ed7e00c8135189c184dcc48c69fJens Axboe	strncpy(soun->sun_path, path, sizeof(soun->sun_path) - 1);
11070fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	return 0;
11080fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe}
11090fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
1110de890a1e48d40238dac69f302708dde8719de240Steven Langstatic int fio_netio_setup_connect(struct thread_data *td)
11110fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe{
1112de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
11130fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
111449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_udp(o) || is_tcp(o))
1115de890a1e48d40238dac69f302708dde8719de240Steven Lang		return fio_netio_setup_connect_inet(td, td->o.filename,o->port);
11160fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	else
1117de890a1e48d40238dac69f302708dde8719de240Steven Lang		return fio_netio_setup_connect_unix(td, td->o.filename);
11180fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe}
11190fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
11200fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboestatic int fio_netio_setup_listen_unix(struct thread_data *td, const char *path)
11210fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe{
11220fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	struct netio_data *nd = td->io_ops->data;
11230fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	struct sockaddr_un *addr = &nd->addr_un;
11240fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	mode_t mode;
11250fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	int len, fd;
11260fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
11270fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	fd = socket(AF_UNIX, SOCK_STREAM, 0);
11280fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	if (fd < 0) {
11290fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		log_err("fio: socket: %s\n", strerror(errno));
11300fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		return -1;
11310fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	}
11320fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
11330fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	mode = umask(000);
11340fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
11350fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	memset(addr, 0, sizeof(*addr));
11360fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	addr->sun_family = AF_UNIX;
11374b159fa61a9c3ed7e00c8135189c184dcc48c69fJens Axboe	strncpy(addr->sun_path, path, sizeof(addr->sun_path) - 1);
11380fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	unlink(path);
11390fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
11400fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	len = sizeof(addr->sun_family) + strlen(path) + 1;
11410fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
11420fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	if (bind(fd, (struct sockaddr *) addr, len) < 0) {
11430fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		log_err("fio: bind: %s\n", strerror(errno));
1144b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe		close(fd);
11450fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		return -1;
11460fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	}
11470fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
11480fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	umask(mode);
11490fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	nd->listenfd = fd;
11500fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	return 0;
11510fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe}
11520fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
11530fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboestatic int fio_netio_setup_listen_inet(struct thread_data *td, short port)
1154ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
1155b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
1156de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
1157b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer	struct ip_mreq mr;
1158b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer	struct sockaddr_in sin;
115949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	struct sockaddr *saddr;
116049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	int fd, opt, type, domain;
116149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	socklen_t len;
1162ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
1163b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer	memset(&sin, 0, sizeof(sin));
116449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
116549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (o->proto == FIO_TYPE_TCP) {
1166414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		type = SOCK_STREAM;
116749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		domain = AF_INET;
116849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else if (o->proto == FIO_TYPE_TCP_V6) {
116949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		type = SOCK_STREAM;
117049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		domain = AF_INET6;
117149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else if (o->proto == FIO_TYPE_UDP) {
1172414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe		type = SOCK_DGRAM;
117349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		domain = AF_INET;
117449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else if (o->proto == FIO_TYPE_UDP_V6) {
117549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		type = SOCK_DGRAM;
117649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		domain = AF_INET6;
117749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else {
117849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		log_err("fio: unknown proto %d\n", o->proto);
117949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		return 1;
118049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	}
1181414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe
118249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	fd = socket(domain, type, 0);
1183ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	if (fd < 0) {
1184e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "socket");
1185ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		return 1;
1186ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
1187ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
1188ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	opt = 1;
118926e594a55a54d47ce0a0784c27c6f851c83d101aJens Axboe	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &opt, sizeof(opt)) < 0) {
1190e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "setsockopt");
11914a93dec2a85f4a979421638fde2877268c470ab1Shawn Bohrer		close(fd);
1192ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		return 1;
1193ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
11946bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe#ifdef SO_REUSEPORT
119526e594a55a54d47ce0a0784c27c6f851c83d101aJens Axboe	if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (void *) &opt, sizeof(opt)) < 0) {
1196e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "setsockopt");
11974a93dec2a85f4a979421638fde2877268c470ab1Shawn Bohrer		close(fd);
11986bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe		return 1;
11996bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe	}
12006bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe#endif
1201ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
1202531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	if (set_window_size(td, fd)) {
1203531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe		close(fd);
1204531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe		return 1;
1205531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe	}
12065e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe	if (set_mss(td, fd)) {
12075e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe		close(fd);
12085e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe		return 1;
12095e34ceafd6ea07785c470c8a8cd7cae740493743Jens Axboe	}
1210531e67afb01714c03a3aad00911a5c897f3f9e1dJens Axboe
12116611e9c767bad5c903c8ac59b9ae8409315dbca2Jens Axboe	if (td->o.filename) {
121249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		if (!is_udp(o) || !fio_netio_is_multicast(td->o.filename)) {
1213b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			log_err("fio: hostname not valid for non-multicast inbound network IO\n");
1214b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			close(fd);
1215b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			return 1;
1216b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer		}
12176611e9c767bad5c903c8ac59b9ae8409315dbca2Jens Axboe		if (is_ipv6(o)) {
12186611e9c767bad5c903c8ac59b9ae8409315dbca2Jens Axboe			log_err("fio: IPv6 not supported for multicast network IO");
12196611e9c767bad5c903c8ac59b9ae8409315dbca2Jens Axboe			close(fd);
12206611e9c767bad5c903c8ac59b9ae8409315dbca2Jens Axboe			return 1;
12216611e9c767bad5c903c8ac59b9ae8409315dbca2Jens Axboe		}
1222b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer
1223b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer		inet_aton(td->o.filename, &sin.sin_addr);
1224b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer
1225b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer		mr.imr_multiaddr = sin.sin_addr;
1226f16b7405fff7c3fc1da421b6bdf8552cc99c3156Bruce Cran		if (o->intfc) {
1227f16b7405fff7c3fc1da421b6bdf8552cc99c3156Bruce Cran			if (inet_aton(o->intfc, &mr.imr_interface) == 0) {
1228b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer				log_err("fio: interface not valid interface IP\n");
1229b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer				close(fd);
1230b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer				return 1;
1231b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer			}
1232b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer		} else {
1233b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer			mr.imr_interface.s_addr = htonl(INADDR_ANY);
1234b93b6a2e1e0d9b919d0b2d4106d3abe415234a46Shawn Bohrer		}
12356611e9c767bad5c903c8ac59b9ae8409315dbca2Jens Axboe
1236f16b7405fff7c3fc1da421b6bdf8552cc99c3156Bruce Cran		if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mr, sizeof(mr)) < 0) {
1237b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			td_verror(td, errno, "setsockopt IP_ADD_MEMBERSHIP");
1238b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			close(fd);
1239b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer			return 1;
1240b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer		}
1241b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer	}
1242b511c9aaa5f289596b05743c5b8e40451017129cShawn Bohrer
124349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (!is_ipv6(o)) {
124449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		saddr = (struct sockaddr *) &nd->addr;
124549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		len = sizeof(nd->addr);
124649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
124749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		nd->addr.sin_family = AF_INET;
124849ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		nd->addr.sin_addr.s_addr = sin.sin_addr.s_addr ? sin.sin_addr.s_addr : htonl(INADDR_ANY);
124949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		nd->addr.sin_port = htons(port);
125049ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	} else {
125149ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		saddr = (struct sockaddr *) &nd->addr6;
125249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		len = sizeof(nd->addr6);
125349ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe
125449ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		nd->addr6.sin6_family = AF_INET6;
125566f7a56f70e40e9e953c47fae3a3432e87cd0cb7Jens Axboe		nd->addr6.sin6_addr = in6addr_any;
125649ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe		nd->addr6.sin6_port = htons(port);
125749ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	}
1258ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
125949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (bind(fd, saddr, len) < 0) {
1260d19cedd63494cf8aef6443fb2ce866cd7a977b98Jens Axboe		close(fd);
1261e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "bind");
1262ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		return 1;
1263ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
12640fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
12650fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	nd->listenfd = fd;
12660fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	return 0;
12670fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe}
12680fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
1269de890a1e48d40238dac69f302708dde8719de240Steven Langstatic int fio_netio_setup_listen(struct thread_data *td)
12700fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe{
12710fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	struct netio_data *nd = td->io_ops->data;
1272de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
12730fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	int ret;
12740fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
127549ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_udp(o) || is_tcp(o))
1276de890a1e48d40238dac69f302708dde8719de240Steven Lang		ret = fio_netio_setup_listen_inet(td, o->port);
12770fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	else
1278de890a1e48d40238dac69f302708dde8719de240Steven Lang		ret = fio_netio_setup_listen_unix(td, td->o.filename);
12790fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
12800fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	if (ret)
12810fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		return ret;
128249ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (is_udp(o))
12830fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		return 0;
12840fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe
12850fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	if (listen(nd->listenfd, 10) < 0) {
1286e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe		td_verror(td, errno, "listen");
12870fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe		nd->listenfd = -1;
1288ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe		return 1;
1289ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe	}
1290ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
1291b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	return 0;
1292ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
1293ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
12949bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboestatic int fio_netio_init(struct thread_data *td)
1295ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
1296de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = td->eo;
1297af52b3455ad892322aab2791282b6bd4efdfdbf3Jens Axboe	int ret;
1298ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
12993f457bea08a6bd60d99950c59c5432b8e78c69e2Bruce Cran#ifdef WIN32
13003f457bea08a6bd60d99950c59c5432b8e78c69e2Bruce Cran	WSADATA wsd;
13013f457bea08a6bd60d99950c59c5432b8e78c69e2Bruce Cran	WSAStartup(MAKEWORD(2,2), &wsd);
13023f457bea08a6bd60d99950c59c5432b8e78c69e2Bruce Cran#endif
13033f457bea08a6bd60d99950c59c5432b8e78c69e2Bruce Cran
130416d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe	if (td_random(td)) {
130516d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe		log_err("fio: network IO can't be random\n");
130616d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe		return 1;
130716d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe	}
1308ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
1309de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->proto == FIO_TYPE_UNIX && o->port) {
1310de890a1e48d40238dac69f302708dde8719de240Steven Lang		log_err("fio: network IO port not valid with unix socket\n");
1311de890a1e48d40238dac69f302708dde8719de240Steven Lang		return 1;
1312de890a1e48d40238dac69f302708dde8719de240Steven Lang	} else if (o->proto != FIO_TYPE_UNIX && !o->port) {
1313de890a1e48d40238dac69f302708dde8719de240Steven Lang		log_err("fio: network IO requires port for tcp or udp\n");
1314de890a1e48d40238dac69f302708dde8719de240Steven Lang		return 1;
1315de890a1e48d40238dac69f302708dde8719de240Steven Lang	}
1316ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
1317a9b3c6926fa5a2d98ded0a37e6fdc41f05b6b9f0Jens Axboe	o->port += td->subjob_number;
1318a9b3c6926fa5a2d98ded0a37e6fdc41f05b6b9f0Jens Axboe
131949ccb8c10036ca0dca1238558c390f61f769c3c9Jens Axboe	if (!is_tcp(o)) {
1320de890a1e48d40238dac69f302708dde8719de240Steven Lang		if (o->listen) {
13219b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe			log_err("fio: listen only valid for TCP proto IO\n");
13229b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe			return 1;
1323de890a1e48d40238dac69f302708dde8719de240Steven Lang		}
1324de890a1e48d40238dac69f302708dde8719de240Steven Lang		if (td_rw(td)) {
13259b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe			log_err("fio: datagram network connections must be"
1326de890a1e48d40238dac69f302708dde8719de240Steven Lang				   " read OR write\n");
13279b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe			return 1;
13289b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe		}
13299b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe		if (o->proto == FIO_TYPE_UNIX && !td->o.filename) {
13309b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe			log_err("fio: UNIX sockets need host/filename\n");
13319b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe			return 1;
1332de890a1e48d40238dac69f302708dde8719de240Steven Lang		}
1333de890a1e48d40238dac69f302708dde8719de240Steven Lang		o->listen = td_read(td);
1334de890a1e48d40238dac69f302708dde8719de240Steven Lang	}
1335443662efa60d9082bc820641e7d1d31dd58d3ae1Jens Axboe
1336de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->listen)
1337de890a1e48d40238dac69f302708dde8719de240Steven Lang		ret = fio_netio_setup_listen(td);
13380fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe	else
1339de890a1e48d40238dac69f302708dde8719de240Steven Lang		ret = fio_netio_setup_connect(td);
1340ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
13417bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe	return ret;
1342ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
1343ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
1344b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic void fio_netio_cleanup(struct thread_data *td)
13459bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe{
1346b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	struct netio_data *nd = td->io_ops->data;
1347b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
1348b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	if (nd) {
134964b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe		if (nd->listenfd != -1)
135064b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe			close(nd->listenfd);
135164b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe		if (nd->pipes[0] != -1)
135264b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe			close(nd->pipes[0]);
135364b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe		if (nd->pipes[1] != -1)
135464b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe			close(nd->pipes[1]);
135564b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe
1356b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe		free(nd);
1357b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe	}
1358b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe}
1359b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
1360b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboestatic int fio_netio_setup(struct thread_data *td)
1361b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe{
13627bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe	struct netio_data *nd;
13637bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe
1364de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (!td->files_index) {
13655903e7b7907854014478b6febfc5645a203ff59eJens Axboe		add_file(td, td->o.filename ?: "net", 0, 0);
1366de890a1e48d40238dac69f302708dde8719de240Steven Lang		td->o.nr_files = td->o.nr_files ?: 1;
1367b53f2c545d8335380b507bd7281178c25d27ddf0Jens Axboe		td->o.open_files++;
1368de890a1e48d40238dac69f302708dde8719de240Steven Lang	}
1369de890a1e48d40238dac69f302708dde8719de240Steven Lang
13707bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe	if (!td->io_ops->data) {
13717bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe		nd = malloc(sizeof(*nd));;
13727bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe
13737bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe		memset(nd, 0, sizeof(*nd));
13747bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe		nd->listenfd = -1;
137564b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe		nd->pipes[0] = nd->pipes[1] = -1;
13767bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe		td->io_ops->data = nd;
13777bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe	}
1378b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe
13799bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe	return 0;
13809bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe}
13819bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe
138236d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboestatic void fio_netio_terminate(struct thread_data *td)
138336d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe{
1384e5f7caafa1eb8dc6343cea57cb5dc43e5774f058Jens Axboe	kill(td->pid, SIGTERM);
138536d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe}
138636d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe
138767bf982340d95ca98098ea050b54b4c7adb116c0Jens Axboe#ifdef CONFIG_LINUX_SPLICE
13889cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboestatic int fio_netio_setup_splice(struct thread_data *td)
13899cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe{
13909cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	struct netio_data *nd;
13919cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
13929cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	fio_netio_setup(td);
13939cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
13949cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	nd = td->io_ops->data;
13959cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	if (nd) {
13969cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		if (pipe(nd->pipes) < 0)
13979cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe			return 1;
13989cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
13999cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		nd->use_splice = 1;
14009cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe		return 0;
14019cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	}
14029cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
14039cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	return 1;
14049cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe}
14059cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
14065921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboestatic struct ioengine_ops ioengine_splice = {
1407de890a1e48d40238dac69f302708dde8719de240Steven Lang	.name			= "netsplice",
1408de890a1e48d40238dac69f302708dde8719de240Steven Lang	.version		= FIO_IOOPS_VERSION,
1409de890a1e48d40238dac69f302708dde8719de240Steven Lang	.prep			= fio_netio_prep,
1410de890a1e48d40238dac69f302708dde8719de240Steven Lang	.queue			= fio_netio_queue,
1411de890a1e48d40238dac69f302708dde8719de240Steven Lang	.setup			= fio_netio_setup_splice,
1412de890a1e48d40238dac69f302708dde8719de240Steven Lang	.init			= fio_netio_init,
1413de890a1e48d40238dac69f302708dde8719de240Steven Lang	.cleanup		= fio_netio_cleanup,
1414de890a1e48d40238dac69f302708dde8719de240Steven Lang	.open_file		= fio_netio_open_file,
141536d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe	.close_file		= fio_netio_close_file,
141636d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe	.terminate		= fio_netio_terminate,
1417de890a1e48d40238dac69f302708dde8719de240Steven Lang	.options		= options,
1418de890a1e48d40238dac69f302708dde8719de240Steven Lang	.option_struct_size	= sizeof(struct netio_options),
1419de890a1e48d40238dac69f302708dde8719de240Steven Lang	.flags			= FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR |
142036d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe				  FIO_PIPEIO,
1421ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe};
14225921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
1423ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
14245921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboestatic struct ioengine_ops ioengine_rw = {
1425de890a1e48d40238dac69f302708dde8719de240Steven Lang	.name			= "net",
1426de890a1e48d40238dac69f302708dde8719de240Steven Lang	.version		= FIO_IOOPS_VERSION,
1427de890a1e48d40238dac69f302708dde8719de240Steven Lang	.prep			= fio_netio_prep,
1428de890a1e48d40238dac69f302708dde8719de240Steven Lang	.queue			= fio_netio_queue,
1429de890a1e48d40238dac69f302708dde8719de240Steven Lang	.setup			= fio_netio_setup,
1430de890a1e48d40238dac69f302708dde8719de240Steven Lang	.init			= fio_netio_init,
1431de890a1e48d40238dac69f302708dde8719de240Steven Lang	.cleanup		= fio_netio_cleanup,
1432de890a1e48d40238dac69f302708dde8719de240Steven Lang	.open_file		= fio_netio_open_file,
1433de890a1e48d40238dac69f302708dde8719de240Steven Lang	.close_file		= fio_netio_close_file,
143436d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe	.terminate		= fio_netio_terminate,
1435de890a1e48d40238dac69f302708dde8719de240Steven Lang	.options		= options,
1436de890a1e48d40238dac69f302708dde8719de240Steven Lang	.option_struct_size	= sizeof(struct netio_options),
1437de890a1e48d40238dac69f302708dde8719de240Steven Lang	.flags			= FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR |
1438ad705bcb7e79a7cdb9891db17b4c40b13b6c30c3Steven Noonan				  FIO_PIPEIO | FIO_BIT_BASED,
14399cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe};
14409cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe
1441de890a1e48d40238dac69f302708dde8719de240Steven Langstatic int str_hostname_cb(void *data, const char *input)
1442de890a1e48d40238dac69f302708dde8719de240Steven Lang{
1443de890a1e48d40238dac69f302708dde8719de240Steven Lang	struct netio_options *o = data;
1444de890a1e48d40238dac69f302708dde8719de240Steven Lang
1445de890a1e48d40238dac69f302708dde8719de240Steven Lang	if (o->td->o.filename)
1446de890a1e48d40238dac69f302708dde8719de240Steven Lang		free(o->td->o.filename);
1447de890a1e48d40238dac69f302708dde8719de240Steven Lang	o->td->o.filename = strdup(input);
1448de890a1e48d40238dac69f302708dde8719de240Steven Lang	return 0;
1449de890a1e48d40238dac69f302708dde8719de240Steven Lang}
1450de890a1e48d40238dac69f302708dde8719de240Steven Lang
1451ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboestatic void fio_init fio_netio_register(void)
1452ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
14539cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	register_ioengine(&ioengine_rw);
145467bf982340d95ca98098ea050b54b4c7adb116c0Jens Axboe#ifdef CONFIG_LINUX_SPLICE
14559cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	register_ioengine(&ioengine_splice);
14565921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
1457ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
1458ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe
1459ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboestatic void fio_exit fio_netio_unregister(void)
1460ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe{
14619cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	unregister_ioengine(&ioengine_rw);
146267bf982340d95ca98098ea050b54b4c7adb116c0Jens Axboe#ifdef CONFIG_LINUX_SPLICE
14639cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe	unregister_ioengine(&ioengine_splice);
14645921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif
1465ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe}
1466