blob: b4ed5df9787b46005d364bfe1b5a0382a6c44219 [file] [log] [blame]
Jens Axboeed92ac02007-02-06 14:43:52 +01001/*
Jens Axboeda751ca2007-03-14 10:59:33 +01002 * net engine
3 *
4 * IO engine that reads/writes to/from sockets.
5 *
Jens Axboeed92ac02007-02-06 14:43:52 +01006 */
7#include <stdio.h>
8#include <stdlib.h>
9#include <unistd.h>
Steven Noonan842805f2012-12-01 08:16:55 +000010#include <signal.h>
Jens Axboeed92ac02007-02-06 14:43:52 +010011#include <errno.h>
12#include <assert.h>
13#include <netinet/in.h>
Steven Noonan70a78782012-11-28 14:52:36 -080014#include <netinet/tcp.h>
Jens Axboeed92ac02007-02-06 14:43:52 +010015#include <arpa/inet.h>
16#include <netdb.h>
Jens Axboe5fdd1242007-02-11 04:00:37 +010017#include <sys/poll.h>
Jens Axboe72920562008-06-02 12:30:06 +020018#include <sys/types.h>
Jens Axboe0fd666b2011-10-06 20:08:53 +020019#include <sys/stat.h>
Jens Axboe72920562008-06-02 12:30:06 +020020#include <sys/socket.h>
Jens Axboe0fd666b2011-10-06 20:08:53 +020021#include <sys/un.h>
Jens Axboeed92ac02007-02-06 14:43:52 +010022
23#include "../fio.h"
Jens Axboeed92ac02007-02-06 14:43:52 +010024
Jens Axboeb5af8292007-03-08 12:43:13 +010025struct netio_data {
26 int listenfd;
Jens Axboe9cce02e2007-06-22 15:42:21 +020027 int use_splice;
28 int pipes[2];
Jens Axboeb5af8292007-03-08 12:43:13 +010029 struct sockaddr_in addr;
Jens Axboe0fd666b2011-10-06 20:08:53 +020030 struct sockaddr_un addr_un;
Jens Axboeb5af8292007-03-08 12:43:13 +010031};
Jens Axboeed92ac02007-02-06 14:43:52 +010032
Steven Langde890a12011-11-09 14:03:34 +010033struct netio_options {
34 struct thread_data *td;
35 unsigned int port;
36 unsigned int proto;
37 unsigned int listen;
Jens Axboe6f73a7f2012-11-30 09:59:20 +010038 unsigned int pingpong;
Steven Noonan70a78782012-11-28 14:52:36 -080039 unsigned int nodelay;
Steven Langde890a12011-11-09 14:03:34 +010040};
41
Jens Axboe664fb3b2009-01-19 13:26:36 +010042struct udp_close_msg {
43 uint32_t magic;
44 uint32_t cmd;
45};
46
47enum {
48 FIO_LINK_CLOSE = 0x89,
Jens Axboeb96d2432012-11-30 08:27:46 +010049 FIO_LINK_OPEN_CLOSE_MAGIC = 0x6c696e6b,
50 FIO_LINK_OPEN = 0x98,
Jens Axboe0fd666b2011-10-06 20:08:53 +020051
52 FIO_TYPE_TCP = 1,
53 FIO_TYPE_UDP = 2,
54 FIO_TYPE_UNIX = 3,
Jens Axboe664fb3b2009-01-19 13:26:36 +010055};
56
Steven Langde890a12011-11-09 14:03:34 +010057static int str_hostname_cb(void *data, const char *input);
58static struct fio_option options[] = {
59 {
60 .name = "hostname",
Jens Axboee8b0e952012-03-19 14:37:08 +010061 .lname = "net engine hostname",
Steven Langde890a12011-11-09 14:03:34 +010062 .type = FIO_OPT_STR_STORE,
63 .cb = str_hostname_cb,
64 .help = "Hostname for net IO engine",
Jens Axboee90a0ad2013-04-10 19:43:59 +020065 .category = FIO_OPT_C_ENGINE,
66 .group = FIO_OPT_G_NETIO,
Steven Langde890a12011-11-09 14:03:34 +010067 },
68 {
69 .name = "port",
Jens Axboee8b0e952012-03-19 14:37:08 +010070 .lname = "net engine port",
Steven Langde890a12011-11-09 14:03:34 +010071 .type = FIO_OPT_INT,
72 .off1 = offsetof(struct netio_options, port),
73 .minval = 1,
74 .maxval = 65535,
75 .help = "Port to use for TCP or UDP net connections",
Jens Axboee90a0ad2013-04-10 19:43:59 +020076 .category = FIO_OPT_C_ENGINE,
77 .group = FIO_OPT_G_NETIO,
Steven Langde890a12011-11-09 14:03:34 +010078 },
79 {
80 .name = "protocol",
Jens Axboee8b0e952012-03-19 14:37:08 +010081 .lname = "net engine protocol",
Steven Langde890a12011-11-09 14:03:34 +010082 .alias = "proto",
83 .type = FIO_OPT_STR,
84 .off1 = offsetof(struct netio_options, proto),
85 .help = "Network protocol to use",
86 .def = "tcp",
87 .posval = {
88 { .ival = "tcp",
89 .oval = FIO_TYPE_TCP,
90 .help = "Transmission Control Protocol",
91 },
92 { .ival = "udp",
93 .oval = FIO_TYPE_UDP,
Bruce Cranf5cc3d02012-10-10 08:17:44 -060094 .help = "User Datagram Protocol",
Steven Langde890a12011-11-09 14:03:34 +010095 },
96 { .ival = "unix",
97 .oval = FIO_TYPE_UNIX,
98 .help = "UNIX domain socket",
99 },
100 },
Jens Axboee90a0ad2013-04-10 19:43:59 +0200101 .category = FIO_OPT_C_ENGINE,
102 .group = FIO_OPT_G_NETIO,
Steven Langde890a12011-11-09 14:03:34 +0100103 },
Jens Axboe1eafa372013-01-31 10:19:51 +0100104#ifdef CONFIG_TCP_NODELAY
Steven Langde890a12011-11-09 14:03:34 +0100105 {
Steven Noonan70a78782012-11-28 14:52:36 -0800106 .name = "nodelay",
107 .type = FIO_OPT_BOOL,
108 .off1 = offsetof(struct netio_options, nodelay),
109 .help = "Use TCP_NODELAY on TCP connections",
Jens Axboee90a0ad2013-04-10 19:43:59 +0200110 .category = FIO_OPT_C_ENGINE,
111 .group = FIO_OPT_G_NETIO,
Steven Noonan70a78782012-11-28 14:52:36 -0800112 },
Jens Axboe1eafa372013-01-31 10:19:51 +0100113#endif
Steven Langde890a12011-11-09 14:03:34 +0100114 {
115 .name = "listen",
Jens Axboee8b0e952012-03-19 14:37:08 +0100116 .lname = "net engine listen",
Steven Langde890a12011-11-09 14:03:34 +0100117 .type = FIO_OPT_STR_SET,
118 .off1 = offsetof(struct netio_options, listen),
119 .help = "Listen for incoming TCP connections",
Jens Axboee90a0ad2013-04-10 19:43:59 +0200120 .category = FIO_OPT_C_ENGINE,
121 .group = FIO_OPT_G_NETIO,
Steven Langde890a12011-11-09 14:03:34 +0100122 },
123 {
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100124 .name = "pingpong",
125 .type = FIO_OPT_STR_SET,
126 .off1 = offsetof(struct netio_options, pingpong),
127 .help = "Ping-pong IO requests",
Jens Axboee90a0ad2013-04-10 19:43:59 +0200128 .category = FIO_OPT_C_ENGINE,
129 .group = FIO_OPT_G_NETIO,
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100130 },
131 {
Steven Langde890a12011-11-09 14:03:34 +0100132 .name = NULL,
133 },
134};
135
Jens Axboe371d4562009-01-19 10:17:06 +0100136/*
137 * Return -1 for error and 'nr events' for a positive number
138 * of events
139 */
140static int poll_wait(struct thread_data *td, int fd, short events)
141{
142 struct pollfd pfd;
143 int ret;
144
145 while (!td->terminate) {
146 pfd.fd = fd;
147 pfd.events = events;
148 ret = poll(&pfd, 1, -1);
149 if (ret < 0) {
150 if (errno == EINTR)
Jens Axboed5b388a2009-01-19 12:38:27 +0100151 break;
Jens Axboe371d4562009-01-19 10:17:06 +0100152
153 td_verror(td, errno, "poll");
154 return -1;
155 } else if (!ret)
156 continue;
157
158 break;
159 }
160
161 if (pfd.revents & events)
162 return 1;
Jens Axboe371d4562009-01-19 10:17:06 +0100163
164 return -1;
165}
166
Jens Axboeed92ac02007-02-06 14:43:52 +0100167static int fio_netio_prep(struct thread_data *td, struct io_u *io_u)
168{
Steven Langde890a12011-11-09 14:03:34 +0100169 struct netio_options *o = td->eo;
Jens Axboeed92ac02007-02-06 14:43:52 +0100170
Jens Axboe7a6499d2007-02-07 09:35:29 +0100171 /*
172 * Make sure we don't see spurious reads to a receiver, and vice versa
173 */
Steven Langde890a12011-11-09 14:03:34 +0100174 if (o->proto == FIO_TYPE_TCP)
175 return 0;
176
177 if ((o->listen && io_u->ddir == DDIR_WRITE) ||
178 (!o->listen && io_u->ddir == DDIR_READ)) {
Jens Axboee1161c32007-02-22 19:36:48 +0100179 td_verror(td, EINVAL, "bad direction");
Jens Axboe7a6499d2007-02-07 09:35:29 +0100180 return 1;
Jens Axboeed92ac02007-02-06 14:43:52 +0100181 }
Bruce Cran3f457be2012-10-10 13:37:41 +0100182
Jens Axboef85ac252008-03-01 18:09:49 +0100183 return 0;
Jens Axboeed92ac02007-02-06 14:43:52 +0100184}
185
Jens Axboe67bf9822013-01-10 11:23:19 +0100186#ifdef CONFIG_LINUX_SPLICE
Jens Axboecd963e12007-06-24 21:41:46 +0200187static int splice_io_u(int fdin, int fdout, unsigned int len)
Jens Axboe9cce02e2007-06-22 15:42:21 +0200188{
Jens Axboe9cce02e2007-06-22 15:42:21 +0200189 int bytes = 0;
190
191 while (len) {
Jens Axboecd963e12007-06-24 21:41:46 +0200192 int ret = splice(fdin, NULL, fdout, NULL, len, 0);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200193
194 if (ret < 0) {
195 if (!bytes)
196 bytes = ret;
197
198 break;
199 } else if (!ret)
200 break;
201
202 bytes += ret;
Jens Axboef657a2f2007-06-22 20:40:10 +0200203 len -= ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200204 }
205
206 return bytes;
207}
208
209/*
Jens Axboecd963e12007-06-24 21:41:46 +0200210 * Receive bytes from a socket and fill them into the internal pipe
211 */
212static int splice_in(struct thread_data *td, struct io_u *io_u)
213{
214 struct netio_data *nd = td->io_ops->data;
215
216 return splice_io_u(io_u->file->fd, nd->pipes[1], io_u->xfer_buflen);
217}
218
219/*
Jens Axboe9cce02e2007-06-22 15:42:21 +0200220 * Transmit 'len' bytes from the internal pipe
221 */
222static int splice_out(struct thread_data *td, struct io_u *io_u,
223 unsigned int len)
224{
225 struct netio_data *nd = td->io_ops->data;
Jens Axboecd963e12007-06-24 21:41:46 +0200226
227 return splice_io_u(nd->pipes[0], io_u->file->fd, len);
228}
229
230static int vmsplice_io_u(struct io_u *io_u, int fd, unsigned int len)
231{
232 struct iovec iov = {
233 .iov_base = io_u->xfer_buf,
234 .iov_len = len,
235 };
Jens Axboe9cce02e2007-06-22 15:42:21 +0200236 int bytes = 0;
237
Jens Axboecd963e12007-06-24 21:41:46 +0200238 while (iov.iov_len) {
239 int ret = vmsplice(fd, &iov, 1, SPLICE_F_MOVE);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200240
241 if (ret < 0) {
242 if (!bytes)
243 bytes = ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200244 break;
245 } else if (!ret)
246 break;
247
Jens Axboecd963e12007-06-24 21:41:46 +0200248 iov.iov_len -= ret;
249 iov.iov_base += ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200250 bytes += ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200251 }
252
253 return bytes;
Jens Axboecd963e12007-06-24 21:41:46 +0200254
Jens Axboe9cce02e2007-06-22 15:42:21 +0200255}
256
257/*
258 * vmsplice() pipe to io_u buffer
259 */
260static int vmsplice_io_u_out(struct thread_data *td, struct io_u *io_u,
261 unsigned int len)
262{
263 struct netio_data *nd = td->io_ops->data;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200264
Jens Axboecd963e12007-06-24 21:41:46 +0200265 return vmsplice_io_u(io_u, nd->pipes[0], len);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200266}
267
268/*
269 * vmsplice() io_u to pipe
270 */
271static int vmsplice_io_u_in(struct thread_data *td, struct io_u *io_u)
272{
273 struct netio_data *nd = td->io_ops->data;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200274
Jens Axboecd963e12007-06-24 21:41:46 +0200275 return vmsplice_io_u(io_u, nd->pipes[1], io_u->xfer_buflen);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200276}
277
Jens Axboecd963e12007-06-24 21:41:46 +0200278/*
279 * splice receive - transfer socket data into a pipe using splice, then map
280 * that pipe data into the io_u using vmsplice.
281 */
Jens Axboe9cce02e2007-06-22 15:42:21 +0200282static int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
283{
284 int ret;
285
286 ret = splice_in(td, io_u);
Jens Axboecd963e12007-06-24 21:41:46 +0200287 if (ret > 0)
288 return vmsplice_io_u_out(td, io_u, ret);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200289
Jens Axboecd963e12007-06-24 21:41:46 +0200290 return ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200291}
292
Jens Axboecd963e12007-06-24 21:41:46 +0200293/*
294 * splice transmit - map data from the io_u into a pipe by using vmsplice,
295 * then transfer that pipe to a socket using splice.
296 */
Jens Axboe9cce02e2007-06-22 15:42:21 +0200297static int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
298{
299 int ret;
300
301 ret = vmsplice_io_u_in(td, io_u);
Jens Axboecd963e12007-06-24 21:41:46 +0200302 if (ret > 0)
303 return splice_out(td, io_u, ret);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200304
Jens Axboecd963e12007-06-24 21:41:46 +0200305 return ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200306}
Jens Axboe5921e802008-05-30 15:02:38 +0200307#else
308static int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
309{
Jens Axboeaf8771b2008-05-30 22:58:28 +0200310 errno = EOPNOTSUPP;
Jens Axboe5921e802008-05-30 15:02:38 +0200311 return -1;
312}
313
314static int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
315{
Jens Axboeaf8771b2008-05-30 22:58:28 +0200316 errno = EOPNOTSUPP;
Jens Axboe5921e802008-05-30 15:02:38 +0200317 return -1;
318}
319#endif
Jens Axboe9cce02e2007-06-22 15:42:21 +0200320
321static int fio_netio_send(struct thread_data *td, struct io_u *io_u)
322{
Jens Axboe414c2a32009-01-16 13:21:15 +0100323 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100324 struct netio_options *o = td->eo;
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100325 int ret, flags = 0;
Jens Axboe371d4562009-01-19 10:17:06 +0100326
Jens Axboe664fb3b2009-01-19 13:26:36 +0100327 do {
Steven Langde890a12011-11-09 14:03:34 +0100328 if (o->proto == FIO_TYPE_UDP) {
Jens Axboe62b38922009-05-11 10:37:33 +0200329 struct sockaddr *to = (struct sockaddr *) &nd->addr;
330
Jens Axboe664fb3b2009-01-19 13:26:36 +0100331 ret = sendto(io_u->file->fd, io_u->xfer_buf,
Jens Axboe62b38922009-05-11 10:37:33 +0200332 io_u->xfer_buflen, flags, to,
333 sizeof(*to));
Jens Axboe664fb3b2009-01-19 13:26:36 +0100334 } else {
335 /*
336 * if we are going to write more, set MSG_MORE
337 */
Jens Axboe5921e802008-05-30 15:02:38 +0200338#ifdef MSG_MORE
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100339 if ((td->this_io_bytes[DDIR_WRITE] + io_u->xfer_buflen <
340 td->o.size) && !o->pingpong)
Jens Axboe664fb3b2009-01-19 13:26:36 +0100341 flags |= MSG_MORE;
Jens Axboe5921e802008-05-30 15:02:38 +0200342#endif
Jens Axboe664fb3b2009-01-19 13:26:36 +0100343 ret = send(io_u->file->fd, io_u->xfer_buf,
344 io_u->xfer_buflen, flags);
345 }
346 if (ret > 0)
347 break;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200348
Jens Axboe664fb3b2009-01-19 13:26:36 +0100349 ret = poll_wait(td, io_u->file->fd, POLLOUT);
350 if (ret <= 0)
351 break;
Jens Axboe664fb3b2009-01-19 13:26:36 +0100352 } while (1);
353
354 return ret;
355}
356
357static int is_udp_close(struct io_u *io_u, int len)
358{
359 struct udp_close_msg *msg;
360
361 if (len != sizeof(struct udp_close_msg))
362 return 0;
363
364 msg = io_u->xfer_buf;
Jens Axboeb96d2432012-11-30 08:27:46 +0100365 if (ntohl(msg->magic) != FIO_LINK_OPEN_CLOSE_MAGIC)
Jens Axboe664fb3b2009-01-19 13:26:36 +0100366 return 0;
367 if (ntohl(msg->cmd) != FIO_LINK_CLOSE)
368 return 0;
369
370 return 1;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200371}
372
Jens Axboe414c2a32009-01-16 13:21:15 +0100373static int fio_netio_recv(struct thread_data *td, struct io_u *io_u)
Jens Axboe9cce02e2007-06-22 15:42:21 +0200374{
Jens Axboe414c2a32009-01-16 13:21:15 +0100375 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100376 struct netio_options *o = td->eo;
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100377 int ret, flags = 0;
Jens Axboe371d4562009-01-19 10:17:06 +0100378
Jens Axboe664fb3b2009-01-19 13:26:36 +0100379 do {
Steven Langde890a12011-11-09 14:03:34 +0100380 if (o->proto == FIO_TYPE_UDP) {
Jens Axboe67bf9822013-01-10 11:23:19 +0100381 socklen_t len = sizeof(nd->addr);
Jens Axboe62b38922009-05-11 10:37:33 +0200382 struct sockaddr *from = (struct sockaddr *) &nd->addr;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200383
Jens Axboe664fb3b2009-01-19 13:26:36 +0100384 ret = recvfrom(io_u->file->fd, io_u->xfer_buf,
Jens Axboe62b38922009-05-11 10:37:33 +0200385 io_u->xfer_buflen, flags, from, &len);
Jens Axboe664fb3b2009-01-19 13:26:36 +0100386 if (is_udp_close(io_u, ret)) {
387 td->done = 1;
388 return 0;
389 }
390 } else {
391 ret = recv(io_u->file->fd, io_u->xfer_buf,
392 io_u->xfer_buflen, flags);
393 }
394 if (ret > 0)
395 break;
Jens Axboe7d988f62012-11-29 19:57:35 +0100396 else if (!ret && (flags & MSG_WAITALL))
397 break;
Jens Axboe414c2a32009-01-16 13:21:15 +0100398
Jens Axboe664fb3b2009-01-19 13:26:36 +0100399 ret = poll_wait(td, io_u->file->fd, POLLIN);
400 if (ret <= 0)
401 break;
Jens Axboe664fb3b2009-01-19 13:26:36 +0100402 flags |= MSG_WAITALL;
403 } while (1);
404
405 return ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200406}
407
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100408static int __fio_netio_queue(struct thread_data *td, struct io_u *io_u,
409 enum fio_ddir ddir)
Jens Axboeed92ac02007-02-06 14:43:52 +0100410{
Jens Axboe9cce02e2007-06-22 15:42:21 +0200411 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100412 struct netio_options *o = td->eo;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200413 int ret;
Jens Axboeed92ac02007-02-06 14:43:52 +0100414
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100415 if (ddir == DDIR_WRITE) {
Steven Langde890a12011-11-09 14:03:34 +0100416 if (!nd->use_splice || o->proto == FIO_TYPE_UDP ||
417 o->proto == FIO_TYPE_UNIX)
Jens Axboe9cce02e2007-06-22 15:42:21 +0200418 ret = fio_netio_send(td, io_u);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200419 else
Jens Axboe414c2a32009-01-16 13:21:15 +0100420 ret = fio_netio_splice_out(td, io_u);
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100421 } else if (ddir == DDIR_READ) {
Steven Langde890a12011-11-09 14:03:34 +0100422 if (!nd->use_splice || o->proto == FIO_TYPE_UDP ||
423 o->proto == FIO_TYPE_UNIX)
Jens Axboe414c2a32009-01-16 13:21:15 +0100424 ret = fio_netio_recv(td, io_u);
425 else
426 ret = fio_netio_splice_in(td, io_u);
Jens Axboed4f12dd2007-02-08 12:59:02 +0100427 } else
Jens Axboe7a6499d2007-02-07 09:35:29 +0100428 ret = 0; /* must be a SYNC */
Jens Axboeed92ac02007-02-06 14:43:52 +0100429
Jens Axboecec6b552007-02-06 20:15:38 +0100430 if (ret != (int) io_u->xfer_buflen) {
Jens Axboe22819ec2007-02-18 07:47:14 +0100431 if (ret >= 0) {
Jens Axboecec6b552007-02-06 20:15:38 +0100432 io_u->resid = io_u->xfer_buflen - ret;
433 io_u->error = 0;
Jens Axboe36167d82007-02-18 05:41:31 +0100434 return FIO_Q_COMPLETED;
Jens Axboe414c2a32009-01-16 13:21:15 +0100435 } else {
436 int err = errno;
437
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100438 if (ddir == DDIR_WRITE && err == EMSGSIZE)
Jens Axboe414c2a32009-01-16 13:21:15 +0100439 return FIO_Q_BUSY;
440
441 io_u->error = err;
442 }
Jens Axboeed92ac02007-02-06 14:43:52 +0100443 }
444
Jens Axboe36167d82007-02-18 05:41:31 +0100445 if (io_u->error)
Jens Axboee1161c32007-02-22 19:36:48 +0100446 td_verror(td, io_u->error, "xfer");
Jens Axboeed92ac02007-02-06 14:43:52 +0100447
Jens Axboe36167d82007-02-18 05:41:31 +0100448 return FIO_Q_COMPLETED;
Jens Axboeed92ac02007-02-06 14:43:52 +0100449}
450
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100451static int fio_netio_queue(struct thread_data *td, struct io_u *io_u)
452{
453 struct netio_options *o = td->eo;
454 int ret;
455
456 fio_ro_check(td, io_u);
457
458 ret = __fio_netio_queue(td, io_u, io_u->ddir);
459 if (!o->pingpong || ret != FIO_Q_COMPLETED)
460 return ret;
461
462 /*
463 * For ping-pong mode, receive or send reply as needed
464 */
465 if (td_read(td) && io_u->ddir == DDIR_READ)
466 ret = __fio_netio_queue(td, io_u, DDIR_WRITE);
467 else if (td_write(td) && io_u->ddir == DDIR_WRITE)
468 ret = __fio_netio_queue(td, io_u, DDIR_READ);
469
470 return ret;
471}
472
Jens Axboeb5af8292007-03-08 12:43:13 +0100473static int fio_netio_connect(struct thread_data *td, struct fio_file *f)
Jens Axboeed92ac02007-02-06 14:43:52 +0100474{
Jens Axboeb5af8292007-03-08 12:43:13 +0100475 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100476 struct netio_options *o = td->eo;
Jens Axboe6264c7a2013-02-28 08:24:23 +0100477 int type, domain;
Jens Axboeed92ac02007-02-06 14:43:52 +0100478
Steven Langde890a12011-11-09 14:03:34 +0100479 if (o->proto == FIO_TYPE_TCP) {
Jens Axboe0fd666b2011-10-06 20:08:53 +0200480 domain = AF_INET;
Jens Axboe414c2a32009-01-16 13:21:15 +0100481 type = SOCK_STREAM;
Steven Langde890a12011-11-09 14:03:34 +0100482 } else if (o->proto == FIO_TYPE_UDP) {
Jens Axboe0fd666b2011-10-06 20:08:53 +0200483 domain = AF_INET;
Jens Axboe414c2a32009-01-16 13:21:15 +0100484 type = SOCK_DGRAM;
Steven Langde890a12011-11-09 14:03:34 +0100485 } else if (o->proto == FIO_TYPE_UNIX) {
Jens Axboe0fd666b2011-10-06 20:08:53 +0200486 domain = AF_UNIX;
487 type = SOCK_STREAM;
488 } else {
Steven Langde890a12011-11-09 14:03:34 +0100489 log_err("fio: bad network type %d\n", o->proto);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200490 f->fd = -1;
491 return 1;
492 }
Jens Axboe414c2a32009-01-16 13:21:15 +0100493
Jens Axboe0fd666b2011-10-06 20:08:53 +0200494 f->fd = socket(domain, type, 0);
Jens Axboeb5af8292007-03-08 12:43:13 +0100495 if (f->fd < 0) {
496 td_verror(td, errno, "socket");
497 return 1;
Jens Axboeed92ac02007-02-06 14:43:52 +0100498 }
499
Jens Axboe1eafa372013-01-31 10:19:51 +0100500#ifdef CONFIG_TCP_NODELAY
Steven Noonan70a78782012-11-28 14:52:36 -0800501 if (o->nodelay && o->proto == FIO_TYPE_TCP) {
Jens Axboe6264c7a2013-02-28 08:24:23 +0100502 int optval = 1;
503
Jens Axboe26e594a2013-01-30 21:52:37 +0100504 if (setsockopt(f->fd, IPPROTO_TCP, TCP_NODELAY, (void *) &optval, sizeof(int)) < 0) {
Steven Noonan70a78782012-11-28 14:52:36 -0800505 log_err("fio: cannot set TCP_NODELAY option on socket (%s), disable with 'nodelay=0'\n", strerror(errno));
506 return 1;
507 }
508 }
Jens Axboe1eafa372013-01-31 10:19:51 +0100509#endif
Steven Noonan70a78782012-11-28 14:52:36 -0800510
Steven Langde890a12011-11-09 14:03:34 +0100511 if (o->proto == FIO_TYPE_UDP)
Jens Axboe414c2a32009-01-16 13:21:15 +0100512 return 0;
Steven Langde890a12011-11-09 14:03:34 +0100513 else if (o->proto == FIO_TYPE_TCP) {
Jens Axboe67bf9822013-01-10 11:23:19 +0100514 socklen_t len = sizeof(nd->addr);
Jens Axboe414c2a32009-01-16 13:21:15 +0100515
Jens Axboe0fd666b2011-10-06 20:08:53 +0200516 if (connect(f->fd, (struct sockaddr *) &nd->addr, len) < 0) {
517 td_verror(td, errno, "connect");
Jens Axboeb94cba42011-10-06 21:27:10 +0200518 close(f->fd);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200519 return 1;
520 }
521 } else {
522 struct sockaddr_un *addr = &nd->addr_un;
Jens Axboe67bf9822013-01-10 11:23:19 +0100523 socklen_t len;
Jens Axboe0fd666b2011-10-06 20:08:53 +0200524
525 len = sizeof(addr->sun_family) + strlen(addr->sun_path) + 1;
526
527 if (connect(f->fd, (struct sockaddr *) addr, len) < 0) {
528 td_verror(td, errno, "connect");
Jens Axboeb94cba42011-10-06 21:27:10 +0200529 close(f->fd);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200530 return 1;
531 }
Jens Axboeed92ac02007-02-06 14:43:52 +0100532 }
533
534 return 0;
Jens Axboeed92ac02007-02-06 14:43:52 +0100535}
536
Jens Axboeb5af8292007-03-08 12:43:13 +0100537static int fio_netio_accept(struct thread_data *td, struct fio_file *f)
Jens Axboe5fdd1242007-02-11 04:00:37 +0100538{
Jens Axboeb5af8292007-03-08 12:43:13 +0100539 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100540 struct netio_options *o = td->eo;
Jens Axboe67bf9822013-01-10 11:23:19 +0100541 socklen_t socklen = sizeof(nd->addr);
Jens Axboe6264c7a2013-02-28 08:24:23 +0100542 int state;
Jens Axboe5fdd1242007-02-11 04:00:37 +0100543
Steven Langde890a12011-11-09 14:03:34 +0100544 if (o->proto == FIO_TYPE_UDP) {
Jens Axboe414c2a32009-01-16 13:21:15 +0100545 f->fd = nd->listenfd;
546 return 0;
547 }
548
Jens Axboe859088d2012-11-29 20:02:50 +0100549 state = td->runstate;
550 td_set_runstate(td, TD_SETTING_UP);
551
Jens Axboe6d861442007-03-15 09:22:23 +0100552 log_info("fio: waiting for connection\n");
Jens Axboe5fdd1242007-02-11 04:00:37 +0100553
Jens Axboe371d4562009-01-19 10:17:06 +0100554 if (poll_wait(td, nd->listenfd, POLLIN) < 0)
Jens Axboe859088d2012-11-29 20:02:50 +0100555 goto err;
Jens Axboe5fdd1242007-02-11 04:00:37 +0100556
Jens Axboe371d4562009-01-19 10:17:06 +0100557 f->fd = accept(nd->listenfd, (struct sockaddr *) &nd->addr, &socklen);
558 if (f->fd < 0) {
559 td_verror(td, errno, "accept");
Jens Axboe859088d2012-11-29 20:02:50 +0100560 goto err;
Jens Axboe5fdd1242007-02-11 04:00:37 +0100561 }
562
Jens Axboe1eafa372013-01-31 10:19:51 +0100563#ifdef CONFIG_TCP_NODELAY
Steven Noonan70a78782012-11-28 14:52:36 -0800564 if (o->nodelay && o->proto == FIO_TYPE_TCP) {
Jens Axboe6264c7a2013-02-28 08:24:23 +0100565 int optval = 1;
566
Jens Axboe26e594a2013-01-30 21:52:37 +0100567 if (setsockopt(f->fd, IPPROTO_TCP, TCP_NODELAY, (void *) &optval, sizeof(int)) < 0) {
Steven Noonan70a78782012-11-28 14:52:36 -0800568 log_err("fio: cannot set TCP_NODELAY option on socket (%s), disable with 'nodelay=0'\n", strerror(errno));
569 return 1;
570 }
571 }
Jens Axboe1eafa372013-01-31 10:19:51 +0100572#endif
Steven Noonan70a78782012-11-28 14:52:36 -0800573
Jens Axboe0cae16f2012-11-30 16:22:31 +0100574 reset_all_stats(td);
Jens Axboe859088d2012-11-29 20:02:50 +0100575 td_set_runstate(td, state);
Jens Axboe5fdd1242007-02-11 04:00:37 +0100576 return 0;
Jens Axboe859088d2012-11-29 20:02:50 +0100577err:
578 td_set_runstate(td, state);
579 return 1;
Jens Axboeb5af8292007-03-08 12:43:13 +0100580}
581
Jens Axboe664fb3b2009-01-19 13:26:36 +0100582static void fio_netio_udp_close(struct thread_data *td, struct fio_file *f)
583{
584 struct netio_data *nd = td->io_ops->data;
585 struct udp_close_msg msg;
Jens Axboe62b38922009-05-11 10:37:33 +0200586 struct sockaddr *to = (struct sockaddr *) &nd->addr;
Jens Axboe664fb3b2009-01-19 13:26:36 +0100587 int ret;
588
Jens Axboeb96d2432012-11-30 08:27:46 +0100589 msg.magic = htonl(FIO_LINK_OPEN_CLOSE_MAGIC);
Jens Axboe664fb3b2009-01-19 13:26:36 +0100590 msg.cmd = htonl(FIO_LINK_CLOSE);
591
Jens Axboe1f819912013-01-23 17:21:41 -0700592 ret = sendto(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to,
Jens Axboe664fb3b2009-01-19 13:26:36 +0100593 sizeof(nd->addr));
594 if (ret < 0)
595 td_verror(td, errno, "sendto udp link close");
596}
597
598static int fio_netio_close_file(struct thread_data *td, struct fio_file *f)
599{
Steven Langde890a12011-11-09 14:03:34 +0100600 struct netio_options *o = td->eo;
Jens Axboe664fb3b2009-01-19 13:26:36 +0100601
602 /*
603 * If this is an UDP connection, notify the receiver that we are
604 * closing down the link
605 */
Steven Langde890a12011-11-09 14:03:34 +0100606 if (o->proto == FIO_TYPE_UDP)
Jens Axboe664fb3b2009-01-19 13:26:36 +0100607 fio_netio_udp_close(td, f);
608
609 return generic_close_file(td, f);
610}
611
Jens Axboeb96d2432012-11-30 08:27:46 +0100612static int fio_netio_udp_recv_open(struct thread_data *td, struct fio_file *f)
613{
614 struct netio_data *nd = td->io_ops->data;
615 struct udp_close_msg msg;
616 struct sockaddr *to = (struct sockaddr *) &nd->addr;
Jens Axboe67bf9822013-01-10 11:23:19 +0100617 socklen_t len = sizeof(nd->addr);
Jens Axboeb96d2432012-11-30 08:27:46 +0100618 int ret;
619
Jens Axboe1f819912013-01-23 17:21:41 -0700620 ret = recvfrom(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to, &len);
Jens Axboeb96d2432012-11-30 08:27:46 +0100621 if (ret < 0) {
Shawn Bohreree7062f2013-07-19 13:24:09 -0500622 td_verror(td, errno, "recvfrom udp link open");
Jens Axboeb96d2432012-11-30 08:27:46 +0100623 return ret;
624 }
625
626 if (ntohl(msg.magic) != FIO_LINK_OPEN_CLOSE_MAGIC ||
627 ntohl(msg.cmd) != FIO_LINK_OPEN) {
628 log_err("fio: bad udp open magic %x/%x\n", ntohl(msg.magic),
629 ntohl(msg.cmd));
630 return -1;
631 }
632
633 return 0;
634}
635
636static int fio_netio_udp_send_open(struct thread_data *td, struct fio_file *f)
637{
638 struct netio_data *nd = td->io_ops->data;
639 struct udp_close_msg msg;
640 struct sockaddr *to = (struct sockaddr *) &nd->addr;
641 int ret;
642
643 msg.magic = htonl(FIO_LINK_OPEN_CLOSE_MAGIC);
644 msg.cmd = htonl(FIO_LINK_OPEN);
645
Jens Axboe1f819912013-01-23 17:21:41 -0700646 ret = sendto(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to,
Jens Axboeb96d2432012-11-30 08:27:46 +0100647 sizeof(nd->addr));
648 if (ret < 0) {
649 td_verror(td, errno, "sendto udp link open");
650 return ret;
651 }
652
653 return 0;
654}
655
656static int fio_netio_open_file(struct thread_data *td, struct fio_file *f)
657{
658 int ret;
659 struct netio_options *o = td->eo;
660
661 if (o->listen)
662 ret = fio_netio_accept(td, f);
663 else
664 ret = fio_netio_connect(td, f);
665
666 if (ret) {
667 f->fd = -1;
668 return ret;
669 }
670
671 if (o->proto == FIO_TYPE_UDP) {
672 if (td_write(td))
673 ret = fio_netio_udp_send_open(td, f);
674 else {
675 int state;
676
677 state = td->runstate;
678 td_set_runstate(td, TD_SETTING_UP);
679 ret = fio_netio_udp_recv_open(td, f);
680 td_set_runstate(td, state);
681 }
682 }
683
684 if (ret)
685 fio_netio_close_file(td, f);
686
687 return ret;
688}
689
Jens Axboe0fd666b2011-10-06 20:08:53 +0200690static int fio_netio_setup_connect_inet(struct thread_data *td,
691 const char *host, unsigned short port)
Jens Axboeb5af8292007-03-08 12:43:13 +0100692{
693 struct netio_data *nd = td->io_ops->data;
694
Jens Axboe166dce42012-11-29 14:35:33 +0100695 if (!host) {
696 log_err("fio: connect with no host to connect to.\n");
697 if (td_read(td))
698 log_err("fio: did you forget to set 'listen'?\n");
699
700 td_verror(td, EINVAL, "no hostname= set");
701 return 1;
702 }
703
Jens Axboeb5af8292007-03-08 12:43:13 +0100704 nd->addr.sin_family = AF_INET;
705 nd->addr.sin_port = htons(port);
706
707 if (inet_aton(host, &nd->addr.sin_addr) != 1) {
708 struct hostent *hent;
709
710 hent = gethostbyname(host);
711 if (!hent) {
712 td_verror(td, errno, "gethostbyname");
713 return 1;
714 }
715
716 memcpy(&nd->addr.sin_addr, hent->h_addr, 4);
717 }
718
719 return 0;
720}
721
Jens Axboe0fd666b2011-10-06 20:08:53 +0200722static int fio_netio_setup_connect_unix(struct thread_data *td,
723 const char *path)
724{
725 struct netio_data *nd = td->io_ops->data;
726 struct sockaddr_un *soun = &nd->addr_un;
727
728 soun->sun_family = AF_UNIX;
729 strcpy(soun->sun_path, path);
730 return 0;
731}
732
Steven Langde890a12011-11-09 14:03:34 +0100733static int fio_netio_setup_connect(struct thread_data *td)
Jens Axboe0fd666b2011-10-06 20:08:53 +0200734{
Steven Langde890a12011-11-09 14:03:34 +0100735 struct netio_options *o = td->eo;
Jens Axboe0fd666b2011-10-06 20:08:53 +0200736
Steven Langde890a12011-11-09 14:03:34 +0100737 if (o->proto == FIO_TYPE_UDP || o->proto == FIO_TYPE_TCP)
738 return fio_netio_setup_connect_inet(td, td->o.filename,o->port);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200739 else
Steven Langde890a12011-11-09 14:03:34 +0100740 return fio_netio_setup_connect_unix(td, td->o.filename);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200741}
742
743static int fio_netio_setup_listen_unix(struct thread_data *td, const char *path)
744{
745 struct netio_data *nd = td->io_ops->data;
746 struct sockaddr_un *addr = &nd->addr_un;
747 mode_t mode;
748 int len, fd;
749
750 fd = socket(AF_UNIX, SOCK_STREAM, 0);
751 if (fd < 0) {
752 log_err("fio: socket: %s\n", strerror(errno));
753 return -1;
754 }
755
756 mode = umask(000);
757
758 memset(addr, 0, sizeof(*addr));
759 addr->sun_family = AF_UNIX;
760 strcpy(addr->sun_path, path);
761 unlink(path);
762
763 len = sizeof(addr->sun_family) + strlen(path) + 1;
764
765 if (bind(fd, (struct sockaddr *) addr, len) < 0) {
766 log_err("fio: bind: %s\n", strerror(errno));
Jens Axboeb94cba42011-10-06 21:27:10 +0200767 close(fd);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200768 return -1;
769 }
770
771 umask(mode);
772 nd->listenfd = fd;
773 return 0;
774}
775
776static int fio_netio_setup_listen_inet(struct thread_data *td, short port)
Jens Axboeb5af8292007-03-08 12:43:13 +0100777{
778 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100779 struct netio_options *o = td->eo;
Jens Axboe414c2a32009-01-16 13:21:15 +0100780 int fd, opt, type;
Jens Axboeed92ac02007-02-06 14:43:52 +0100781
Steven Langde890a12011-11-09 14:03:34 +0100782 if (o->proto == FIO_TYPE_TCP)
Jens Axboe414c2a32009-01-16 13:21:15 +0100783 type = SOCK_STREAM;
784 else
785 type = SOCK_DGRAM;
786
Jens Axboe0fd666b2011-10-06 20:08:53 +0200787 fd = socket(AF_INET, type, 0);
Jens Axboeed92ac02007-02-06 14:43:52 +0100788 if (fd < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100789 td_verror(td, errno, "socket");
Jens Axboeed92ac02007-02-06 14:43:52 +0100790 return 1;
791 }
792
793 opt = 1;
Jens Axboe26e594a2013-01-30 21:52:37 +0100794 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &opt, sizeof(opt)) < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100795 td_verror(td, errno, "setsockopt");
Shawn Bohrer4a93dec2013-07-19 13:24:10 -0500796 close(fd);
Jens Axboeed92ac02007-02-06 14:43:52 +0100797 return 1;
798 }
Jens Axboe6bedbfa2007-02-07 09:54:40 +0100799#ifdef SO_REUSEPORT
Jens Axboe26e594a2013-01-30 21:52:37 +0100800 if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (void *) &opt, sizeof(opt)) < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100801 td_verror(td, errno, "setsockopt");
Shawn Bohrer4a93dec2013-07-19 13:24:10 -0500802 close(fd);
Jens Axboe6bedbfa2007-02-07 09:54:40 +0100803 return 1;
804 }
805#endif
Jens Axboeed92ac02007-02-06 14:43:52 +0100806
Jens Axboeb5af8292007-03-08 12:43:13 +0100807 nd->addr.sin_family = AF_INET;
808 nd->addr.sin_addr.s_addr = htonl(INADDR_ANY);
809 nd->addr.sin_port = htons(port);
Jens Axboeed92ac02007-02-06 14:43:52 +0100810
Jens Axboeb5af8292007-03-08 12:43:13 +0100811 if (bind(fd, (struct sockaddr *) &nd->addr, sizeof(nd->addr)) < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100812 td_verror(td, errno, "bind");
Jens Axboeed92ac02007-02-06 14:43:52 +0100813 return 1;
814 }
Jens Axboe0fd666b2011-10-06 20:08:53 +0200815
816 nd->listenfd = fd;
817 return 0;
818}
819
Steven Langde890a12011-11-09 14:03:34 +0100820static int fio_netio_setup_listen(struct thread_data *td)
Jens Axboe0fd666b2011-10-06 20:08:53 +0200821{
822 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100823 struct netio_options *o = td->eo;
Jens Axboe0fd666b2011-10-06 20:08:53 +0200824 int ret;
825
Steven Langde890a12011-11-09 14:03:34 +0100826 if (o->proto == FIO_TYPE_UDP || o->proto == FIO_TYPE_TCP)
827 ret = fio_netio_setup_listen_inet(td, o->port);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200828 else
Steven Langde890a12011-11-09 14:03:34 +0100829 ret = fio_netio_setup_listen_unix(td, td->o.filename);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200830
831 if (ret)
832 return ret;
Steven Langde890a12011-11-09 14:03:34 +0100833 if (o->proto == FIO_TYPE_UDP)
Jens Axboe0fd666b2011-10-06 20:08:53 +0200834 return 0;
835
836 if (listen(nd->listenfd, 10) < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100837 td_verror(td, errno, "listen");
Jens Axboe0fd666b2011-10-06 20:08:53 +0200838 nd->listenfd = -1;
Jens Axboeed92ac02007-02-06 14:43:52 +0100839 return 1;
840 }
841
Jens Axboeb5af8292007-03-08 12:43:13 +0100842 return 0;
Jens Axboeed92ac02007-02-06 14:43:52 +0100843}
844
Jens Axboe9bec88e2007-03-02 08:55:48 +0100845static int fio_netio_init(struct thread_data *td)
Jens Axboeed92ac02007-02-06 14:43:52 +0100846{
Steven Langde890a12011-11-09 14:03:34 +0100847 struct netio_options *o = td->eo;
Jens Axboeaf52b342007-03-13 10:07:47 +0100848 int ret;
Jens Axboeed92ac02007-02-06 14:43:52 +0100849
Bruce Cran3f457be2012-10-10 13:37:41 +0100850#ifdef WIN32
851 WSADATA wsd;
852 WSAStartup(MAKEWORD(2,2), &wsd);
853#endif
854
Jens Axboe16d55aa2007-05-22 09:21:37 +0200855 if (td_random(td)) {
856 log_err("fio: network IO can't be random\n");
857 return 1;
858 }
Jens Axboeed92ac02007-02-06 14:43:52 +0100859
Steven Langde890a12011-11-09 14:03:34 +0100860 if (o->proto == FIO_TYPE_UNIX && o->port) {
861 log_err("fio: network IO port not valid with unix socket\n");
862 return 1;
863 } else if (o->proto != FIO_TYPE_UNIX && !o->port) {
864 log_err("fio: network IO requires port for tcp or udp\n");
865 return 1;
Jens Axboe414c2a32009-01-16 13:21:15 +0100866 }
Jens Axboe0fd666b2011-10-06 20:08:53 +0200867
Steven Langde890a12011-11-09 14:03:34 +0100868 if (o->proto != FIO_TYPE_TCP) {
869 if (o->listen) {
Jens Axboe9b986062011-12-19 08:57:18 +0100870 log_err("fio: listen only valid for TCP proto IO\n");
871 return 1;
Steven Langde890a12011-11-09 14:03:34 +0100872 }
873 if (td_rw(td)) {
Jens Axboe9b986062011-12-19 08:57:18 +0100874 log_err("fio: datagram network connections must be"
Steven Langde890a12011-11-09 14:03:34 +0100875 " read OR write\n");
Jens Axboe9b986062011-12-19 08:57:18 +0100876 return 1;
877 }
878 if (o->proto == FIO_TYPE_UNIX && !td->o.filename) {
879 log_err("fio: UNIX sockets need host/filename\n");
880 return 1;
Steven Langde890a12011-11-09 14:03:34 +0100881 }
882 o->listen = td_read(td);
883 }
884
885 if (o->proto != FIO_TYPE_UNIX && o->listen && td->o.filename) {
886 log_err("fio: hostname not valid for inbound network IO\n");
887 return 1;
888 }
889
890 if (o->listen)
891 ret = fio_netio_setup_listen(td);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200892 else
Steven Langde890a12011-11-09 14:03:34 +0100893 ret = fio_netio_setup_connect(td);
Jens Axboeed92ac02007-02-06 14:43:52 +0100894
Jens Axboe7bb48f82007-03-27 15:30:28 +0200895 return ret;
Jens Axboeed92ac02007-02-06 14:43:52 +0100896}
897
Jens Axboeb5af8292007-03-08 12:43:13 +0100898static void fio_netio_cleanup(struct thread_data *td)
Jens Axboe9bec88e2007-03-02 08:55:48 +0100899{
Jens Axboeb5af8292007-03-08 12:43:13 +0100900 struct netio_data *nd = td->io_ops->data;
901
902 if (nd) {
Jens Axboe64b24cd2007-06-24 21:28:39 +0200903 if (nd->listenfd != -1)
904 close(nd->listenfd);
905 if (nd->pipes[0] != -1)
906 close(nd->pipes[0]);
907 if (nd->pipes[1] != -1)
908 close(nd->pipes[1]);
909
Jens Axboeb5af8292007-03-08 12:43:13 +0100910 free(nd);
Jens Axboeb5af8292007-03-08 12:43:13 +0100911 }
912}
913
914static int fio_netio_setup(struct thread_data *td)
915{
Jens Axboe7bb48f82007-03-27 15:30:28 +0200916 struct netio_data *nd;
Jens Axboeb5af8292007-03-08 12:43:13 +0100917
Steven Langde890a12011-11-09 14:03:34 +0100918 if (!td->files_index) {
919 add_file(td, td->o.filename ?: "net");
920 td->o.nr_files = td->o.nr_files ?: 1;
921 }
922
Jens Axboe7bb48f82007-03-27 15:30:28 +0200923 if (!td->io_ops->data) {
924 nd = malloc(sizeof(*nd));;
925
926 memset(nd, 0, sizeof(*nd));
927 nd->listenfd = -1;
Jens Axboe64b24cd2007-06-24 21:28:39 +0200928 nd->pipes[0] = nd->pipes[1] = -1;
Jens Axboe7bb48f82007-03-27 15:30:28 +0200929 td->io_ops->data = nd;
Jens Axboe7bb48f82007-03-27 15:30:28 +0200930 }
931
Jens Axboe9bec88e2007-03-02 08:55:48 +0100932 return 0;
933}
934
Jens Axboe36d80bc2012-11-30 21:46:06 +0100935static void fio_netio_terminate(struct thread_data *td)
936{
937 kill(td->pid, SIGUSR2);
938}
939
Jens Axboe67bf9822013-01-10 11:23:19 +0100940#ifdef CONFIG_LINUX_SPLICE
Jens Axboe9cce02e2007-06-22 15:42:21 +0200941static int fio_netio_setup_splice(struct thread_data *td)
942{
943 struct netio_data *nd;
944
945 fio_netio_setup(td);
946
947 nd = td->io_ops->data;
948 if (nd) {
949 if (pipe(nd->pipes) < 0)
950 return 1;
951
952 nd->use_splice = 1;
953 return 0;
954 }
955
956 return 1;
957}
958
Jens Axboe5921e802008-05-30 15:02:38 +0200959static struct ioengine_ops ioengine_splice = {
Steven Langde890a12011-11-09 14:03:34 +0100960 .name = "netsplice",
961 .version = FIO_IOOPS_VERSION,
962 .prep = fio_netio_prep,
963 .queue = fio_netio_queue,
964 .setup = fio_netio_setup_splice,
965 .init = fio_netio_init,
966 .cleanup = fio_netio_cleanup,
967 .open_file = fio_netio_open_file,
Jens Axboe36d80bc2012-11-30 21:46:06 +0100968 .close_file = fio_netio_close_file,
969 .terminate = fio_netio_terminate,
Steven Langde890a12011-11-09 14:03:34 +0100970 .options = options,
971 .option_struct_size = sizeof(struct netio_options),
972 .flags = FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR |
Jens Axboe36d80bc2012-11-30 21:46:06 +0100973 FIO_PIPEIO,
Jens Axboe5921e802008-05-30 15:02:38 +0200974};
975#endif
976
Jens Axboe9cce02e2007-06-22 15:42:21 +0200977static struct ioengine_ops ioengine_rw = {
Steven Langde890a12011-11-09 14:03:34 +0100978 .name = "net",
979 .version = FIO_IOOPS_VERSION,
980 .prep = fio_netio_prep,
981 .queue = fio_netio_queue,
982 .setup = fio_netio_setup,
983 .init = fio_netio_init,
984 .cleanup = fio_netio_cleanup,
985 .open_file = fio_netio_open_file,
986 .close_file = fio_netio_close_file,
Jens Axboe36d80bc2012-11-30 21:46:06 +0100987 .terminate = fio_netio_terminate,
Steven Langde890a12011-11-09 14:03:34 +0100988 .options = options,
989 .option_struct_size = sizeof(struct netio_options),
990 .flags = FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR |
Steven Noonanad705bc2013-04-08 15:05:25 -0700991 FIO_PIPEIO | FIO_BIT_BASED,
Jens Axboeed92ac02007-02-06 14:43:52 +0100992};
993
Steven Langde890a12011-11-09 14:03:34 +0100994static int str_hostname_cb(void *data, const char *input)
995{
996 struct netio_options *o = data;
997
998 if (o->td->o.filename)
999 free(o->td->o.filename);
1000 o->td->o.filename = strdup(input);
1001 return 0;
1002}
1003
Jens Axboeed92ac02007-02-06 14:43:52 +01001004static void fio_init fio_netio_register(void)
1005{
Jens Axboe9cce02e2007-06-22 15:42:21 +02001006 register_ioengine(&ioengine_rw);
Jens Axboe67bf9822013-01-10 11:23:19 +01001007#ifdef CONFIG_LINUX_SPLICE
Jens Axboe9cce02e2007-06-22 15:42:21 +02001008 register_ioengine(&ioengine_splice);
Jens Axboe5921e802008-05-30 15:02:38 +02001009#endif
Jens Axboeed92ac02007-02-06 14:43:52 +01001010}
1011
1012static void fio_exit fio_netio_unregister(void)
1013{
Jens Axboe9cce02e2007-06-22 15:42:21 +02001014 unregister_ioengine(&ioengine_rw);
Jens Axboe67bf9822013-01-10 11:23:19 +01001015#ifdef CONFIG_LINUX_SPLICE
Jens Axboe9cce02e2007-06-22 15:42:21 +02001016 unregister_ioengine(&ioengine_splice);
Jens Axboe5921e802008-05-30 15:02:38 +02001017#endif
Jens Axboeed92ac02007-02-06 14:43:52 +01001018}