blob: 3a352de70e492fef403ecb8315287514a7cd1199 [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",
61 .type = FIO_OPT_STR_STORE,
62 .cb = str_hostname_cb,
63 .help = "Hostname for net IO engine",
Jens Axboee90a0ad2013-04-10 19:43:59 +020064 .category = FIO_OPT_C_ENGINE,
65 .group = FIO_OPT_G_NETIO,
Steven Langde890a12011-11-09 14:03:34 +010066 },
67 {
68 .name = "port",
69 .type = FIO_OPT_INT,
70 .off1 = offsetof(struct netio_options, port),
71 .minval = 1,
72 .maxval = 65535,
73 .help = "Port to use for TCP or UDP net connections",
Jens Axboee90a0ad2013-04-10 19:43:59 +020074 .category = FIO_OPT_C_ENGINE,
75 .group = FIO_OPT_G_NETIO,
Steven Langde890a12011-11-09 14:03:34 +010076 },
77 {
78 .name = "protocol",
79 .alias = "proto",
80 .type = FIO_OPT_STR,
81 .off1 = offsetof(struct netio_options, proto),
82 .help = "Network protocol to use",
83 .def = "tcp",
84 .posval = {
85 { .ival = "tcp",
86 .oval = FIO_TYPE_TCP,
87 .help = "Transmission Control Protocol",
88 },
89 { .ival = "udp",
90 .oval = FIO_TYPE_UDP,
Bruce Cranf5cc3d02012-10-10 08:17:44 -060091 .help = "User Datagram Protocol",
Steven Langde890a12011-11-09 14:03:34 +010092 },
93 { .ival = "unix",
94 .oval = FIO_TYPE_UNIX,
95 .help = "UNIX domain socket",
96 },
97 },
Jens Axboee90a0ad2013-04-10 19:43:59 +020098 .category = FIO_OPT_C_ENGINE,
99 .group = FIO_OPT_G_NETIO,
Steven Langde890a12011-11-09 14:03:34 +0100100 },
Jens Axboe1eafa372013-01-31 10:19:51 +0100101#ifdef CONFIG_TCP_NODELAY
Steven Langde890a12011-11-09 14:03:34 +0100102 {
Steven Noonan70a78782012-11-28 14:52:36 -0800103 .name = "nodelay",
104 .type = FIO_OPT_BOOL,
105 .off1 = offsetof(struct netio_options, nodelay),
106 .help = "Use TCP_NODELAY on TCP connections",
Jens Axboee90a0ad2013-04-10 19:43:59 +0200107 .category = FIO_OPT_C_ENGINE,
108 .group = FIO_OPT_G_NETIO,
Steven Noonan70a78782012-11-28 14:52:36 -0800109 },
Jens Axboe1eafa372013-01-31 10:19:51 +0100110#endif
Steven Noonan70a78782012-11-28 14:52:36 -0800111 {
Steven Langde890a12011-11-09 14:03:34 +0100112 .name = "listen",
113 .type = FIO_OPT_STR_SET,
114 .off1 = offsetof(struct netio_options, listen),
115 .help = "Listen for incoming TCP connections",
Jens Axboee90a0ad2013-04-10 19:43:59 +0200116 .category = FIO_OPT_C_ENGINE,
117 .group = FIO_OPT_G_NETIO,
Steven Langde890a12011-11-09 14:03:34 +0100118 },
119 {
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100120 .name = "pingpong",
121 .type = FIO_OPT_STR_SET,
122 .off1 = offsetof(struct netio_options, pingpong),
123 .help = "Ping-pong IO requests",
Jens Axboee90a0ad2013-04-10 19:43:59 +0200124 .category = FIO_OPT_C_ENGINE,
125 .group = FIO_OPT_G_NETIO,
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100126 },
127 {
Steven Langde890a12011-11-09 14:03:34 +0100128 .name = NULL,
129 },
130};
131
Jens Axboe371d4562009-01-19 10:17:06 +0100132/*
133 * Return -1 for error and 'nr events' for a positive number
134 * of events
135 */
136static int poll_wait(struct thread_data *td, int fd, short events)
137{
138 struct pollfd pfd;
139 int ret;
140
141 while (!td->terminate) {
142 pfd.fd = fd;
143 pfd.events = events;
144 ret = poll(&pfd, 1, -1);
145 if (ret < 0) {
146 if (errno == EINTR)
Jens Axboed5b388a2009-01-19 12:38:27 +0100147 break;
Jens Axboe371d4562009-01-19 10:17:06 +0100148
149 td_verror(td, errno, "poll");
150 return -1;
151 } else if (!ret)
152 continue;
153
154 break;
155 }
156
157 if (pfd.revents & events)
158 return 1;
Jens Axboe371d4562009-01-19 10:17:06 +0100159
160 return -1;
161}
162
Jens Axboeed92ac02007-02-06 14:43:52 +0100163static int fio_netio_prep(struct thread_data *td, struct io_u *io_u)
164{
Steven Langde890a12011-11-09 14:03:34 +0100165 struct netio_options *o = td->eo;
Jens Axboeed92ac02007-02-06 14:43:52 +0100166
Jens Axboe7a6499d2007-02-07 09:35:29 +0100167 /*
168 * Make sure we don't see spurious reads to a receiver, and vice versa
169 */
Steven Langde890a12011-11-09 14:03:34 +0100170 if (o->proto == FIO_TYPE_TCP)
171 return 0;
172
173 if ((o->listen && io_u->ddir == DDIR_WRITE) ||
174 (!o->listen && io_u->ddir == DDIR_READ)) {
Jens Axboee1161c32007-02-22 19:36:48 +0100175 td_verror(td, EINVAL, "bad direction");
Jens Axboe7a6499d2007-02-07 09:35:29 +0100176 return 1;
Jens Axboeed92ac02007-02-06 14:43:52 +0100177 }
Bruce Cran3f457be2012-10-10 13:37:41 +0100178
Jens Axboef85ac252008-03-01 18:09:49 +0100179 return 0;
Jens Axboeed92ac02007-02-06 14:43:52 +0100180}
181
Jens Axboe67bf9822013-01-10 11:23:19 +0100182#ifdef CONFIG_LINUX_SPLICE
Jens Axboecd963e12007-06-24 21:41:46 +0200183static int splice_io_u(int fdin, int fdout, unsigned int len)
Jens Axboe9cce02e2007-06-22 15:42:21 +0200184{
Jens Axboe9cce02e2007-06-22 15:42:21 +0200185 int bytes = 0;
186
187 while (len) {
Jens Axboecd963e12007-06-24 21:41:46 +0200188 int ret = splice(fdin, NULL, fdout, NULL, len, 0);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200189
190 if (ret < 0) {
191 if (!bytes)
192 bytes = ret;
193
194 break;
195 } else if (!ret)
196 break;
197
198 bytes += ret;
Jens Axboef657a2f2007-06-22 20:40:10 +0200199 len -= ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200200 }
201
202 return bytes;
203}
204
205/*
Jens Axboecd963e12007-06-24 21:41:46 +0200206 * Receive bytes from a socket and fill them into the internal pipe
207 */
208static int splice_in(struct thread_data *td, struct io_u *io_u)
209{
210 struct netio_data *nd = td->io_ops->data;
211
212 return splice_io_u(io_u->file->fd, nd->pipes[1], io_u->xfer_buflen);
213}
214
215/*
Jens Axboe9cce02e2007-06-22 15:42:21 +0200216 * Transmit 'len' bytes from the internal pipe
217 */
218static int splice_out(struct thread_data *td, struct io_u *io_u,
219 unsigned int len)
220{
221 struct netio_data *nd = td->io_ops->data;
Jens Axboecd963e12007-06-24 21:41:46 +0200222
223 return splice_io_u(nd->pipes[0], io_u->file->fd, len);
224}
225
226static int vmsplice_io_u(struct io_u *io_u, int fd, unsigned int len)
227{
228 struct iovec iov = {
229 .iov_base = io_u->xfer_buf,
230 .iov_len = len,
231 };
Jens Axboe9cce02e2007-06-22 15:42:21 +0200232 int bytes = 0;
233
Jens Axboecd963e12007-06-24 21:41:46 +0200234 while (iov.iov_len) {
235 int ret = vmsplice(fd, &iov, 1, SPLICE_F_MOVE);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200236
237 if (ret < 0) {
238 if (!bytes)
239 bytes = ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200240 break;
241 } else if (!ret)
242 break;
243
Jens Axboecd963e12007-06-24 21:41:46 +0200244 iov.iov_len -= ret;
245 iov.iov_base += ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200246 bytes += ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200247 }
248
249 return bytes;
Jens Axboecd963e12007-06-24 21:41:46 +0200250
Jens Axboe9cce02e2007-06-22 15:42:21 +0200251}
252
253/*
254 * vmsplice() pipe to io_u buffer
255 */
256static int vmsplice_io_u_out(struct thread_data *td, struct io_u *io_u,
257 unsigned int len)
258{
259 struct netio_data *nd = td->io_ops->data;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200260
Jens Axboecd963e12007-06-24 21:41:46 +0200261 return vmsplice_io_u(io_u, nd->pipes[0], len);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200262}
263
264/*
265 * vmsplice() io_u to pipe
266 */
267static int vmsplice_io_u_in(struct thread_data *td, struct io_u *io_u)
268{
269 struct netio_data *nd = td->io_ops->data;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200270
Jens Axboecd963e12007-06-24 21:41:46 +0200271 return vmsplice_io_u(io_u, nd->pipes[1], io_u->xfer_buflen);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200272}
273
Jens Axboecd963e12007-06-24 21:41:46 +0200274/*
275 * splice receive - transfer socket data into a pipe using splice, then map
276 * that pipe data into the io_u using vmsplice.
277 */
Jens Axboe9cce02e2007-06-22 15:42:21 +0200278static int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
279{
280 int ret;
281
282 ret = splice_in(td, io_u);
Jens Axboecd963e12007-06-24 21:41:46 +0200283 if (ret > 0)
284 return vmsplice_io_u_out(td, io_u, ret);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200285
Jens Axboecd963e12007-06-24 21:41:46 +0200286 return ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200287}
288
Jens Axboecd963e12007-06-24 21:41:46 +0200289/*
290 * splice transmit - map data from the io_u into a pipe by using vmsplice,
291 * then transfer that pipe to a socket using splice.
292 */
Jens Axboe9cce02e2007-06-22 15:42:21 +0200293static int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
294{
295 int ret;
296
297 ret = vmsplice_io_u_in(td, io_u);
Jens Axboecd963e12007-06-24 21:41:46 +0200298 if (ret > 0)
299 return splice_out(td, io_u, ret);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200300
Jens Axboecd963e12007-06-24 21:41:46 +0200301 return ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200302}
Jens Axboe5921e802008-05-30 15:02:38 +0200303#else
304static int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
305{
Jens Axboeaf8771b2008-05-30 22:58:28 +0200306 errno = EOPNOTSUPP;
Jens Axboe5921e802008-05-30 15:02:38 +0200307 return -1;
308}
309
310static int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
311{
Jens Axboeaf8771b2008-05-30 22:58:28 +0200312 errno = EOPNOTSUPP;
Jens Axboe5921e802008-05-30 15:02:38 +0200313 return -1;
314}
315#endif
Jens Axboe9cce02e2007-06-22 15:42:21 +0200316
317static int fio_netio_send(struct thread_data *td, struct io_u *io_u)
318{
Jens Axboe414c2a32009-01-16 13:21:15 +0100319 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100320 struct netio_options *o = td->eo;
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100321 int ret, flags = 0;
Jens Axboe371d4562009-01-19 10:17:06 +0100322
Jens Axboe664fb3b2009-01-19 13:26:36 +0100323 do {
Steven Langde890a12011-11-09 14:03:34 +0100324 if (o->proto == FIO_TYPE_UDP) {
Jens Axboe62b38922009-05-11 10:37:33 +0200325 struct sockaddr *to = (struct sockaddr *) &nd->addr;
326
Jens Axboe664fb3b2009-01-19 13:26:36 +0100327 ret = sendto(io_u->file->fd, io_u->xfer_buf,
Jens Axboe62b38922009-05-11 10:37:33 +0200328 io_u->xfer_buflen, flags, to,
329 sizeof(*to));
Jens Axboe664fb3b2009-01-19 13:26:36 +0100330 } else {
331 /*
332 * if we are going to write more, set MSG_MORE
333 */
Jens Axboe5921e802008-05-30 15:02:38 +0200334#ifdef MSG_MORE
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100335 if ((td->this_io_bytes[DDIR_WRITE] + io_u->xfer_buflen <
336 td->o.size) && !o->pingpong)
Jens Axboe664fb3b2009-01-19 13:26:36 +0100337 flags |= MSG_MORE;
Jens Axboe5921e802008-05-30 15:02:38 +0200338#endif
Jens Axboe664fb3b2009-01-19 13:26:36 +0100339 ret = send(io_u->file->fd, io_u->xfer_buf,
340 io_u->xfer_buflen, flags);
341 }
342 if (ret > 0)
343 break;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200344
Jens Axboe664fb3b2009-01-19 13:26:36 +0100345 ret = poll_wait(td, io_u->file->fd, POLLOUT);
346 if (ret <= 0)
347 break;
Jens Axboe664fb3b2009-01-19 13:26:36 +0100348 } while (1);
349
350 return ret;
351}
352
353static int is_udp_close(struct io_u *io_u, int len)
354{
355 struct udp_close_msg *msg;
356
357 if (len != sizeof(struct udp_close_msg))
358 return 0;
359
360 msg = io_u->xfer_buf;
Jens Axboeb96d2432012-11-30 08:27:46 +0100361 if (ntohl(msg->magic) != FIO_LINK_OPEN_CLOSE_MAGIC)
Jens Axboe664fb3b2009-01-19 13:26:36 +0100362 return 0;
363 if (ntohl(msg->cmd) != FIO_LINK_CLOSE)
364 return 0;
365
366 return 1;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200367}
368
Jens Axboe414c2a32009-01-16 13:21:15 +0100369static int fio_netio_recv(struct thread_data *td, struct io_u *io_u)
Jens Axboe9cce02e2007-06-22 15:42:21 +0200370{
Jens Axboe414c2a32009-01-16 13:21:15 +0100371 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100372 struct netio_options *o = td->eo;
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100373 int ret, flags = 0;
Jens Axboe371d4562009-01-19 10:17:06 +0100374
Jens Axboe664fb3b2009-01-19 13:26:36 +0100375 do {
Steven Langde890a12011-11-09 14:03:34 +0100376 if (o->proto == FIO_TYPE_UDP) {
Jens Axboe67bf9822013-01-10 11:23:19 +0100377 socklen_t len = sizeof(nd->addr);
Jens Axboe62b38922009-05-11 10:37:33 +0200378 struct sockaddr *from = (struct sockaddr *) &nd->addr;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200379
Jens Axboe664fb3b2009-01-19 13:26:36 +0100380 ret = recvfrom(io_u->file->fd, io_u->xfer_buf,
Jens Axboe62b38922009-05-11 10:37:33 +0200381 io_u->xfer_buflen, flags, from, &len);
Jens Axboe664fb3b2009-01-19 13:26:36 +0100382 if (is_udp_close(io_u, ret)) {
383 td->done = 1;
384 return 0;
385 }
386 } else {
387 ret = recv(io_u->file->fd, io_u->xfer_buf,
388 io_u->xfer_buflen, flags);
389 }
390 if (ret > 0)
391 break;
Jens Axboe7d988f62012-11-29 19:57:35 +0100392 else if (!ret && (flags & MSG_WAITALL))
393 break;
Jens Axboe414c2a32009-01-16 13:21:15 +0100394
Jens Axboe664fb3b2009-01-19 13:26:36 +0100395 ret = poll_wait(td, io_u->file->fd, POLLIN);
396 if (ret <= 0)
397 break;
Jens Axboe664fb3b2009-01-19 13:26:36 +0100398 flags |= MSG_WAITALL;
399 } while (1);
400
401 return ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200402}
403
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100404static int __fio_netio_queue(struct thread_data *td, struct io_u *io_u,
405 enum fio_ddir ddir)
Jens Axboeed92ac02007-02-06 14:43:52 +0100406{
Jens Axboe9cce02e2007-06-22 15:42:21 +0200407 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100408 struct netio_options *o = td->eo;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200409 int ret;
Jens Axboeed92ac02007-02-06 14:43:52 +0100410
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100411 if (ddir == DDIR_WRITE) {
Steven Langde890a12011-11-09 14:03:34 +0100412 if (!nd->use_splice || o->proto == FIO_TYPE_UDP ||
413 o->proto == FIO_TYPE_UNIX)
Jens Axboe9cce02e2007-06-22 15:42:21 +0200414 ret = fio_netio_send(td, io_u);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200415 else
Jens Axboe414c2a32009-01-16 13:21:15 +0100416 ret = fio_netio_splice_out(td, io_u);
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100417 } else if (ddir == DDIR_READ) {
Steven Langde890a12011-11-09 14:03:34 +0100418 if (!nd->use_splice || o->proto == FIO_TYPE_UDP ||
419 o->proto == FIO_TYPE_UNIX)
Jens Axboe414c2a32009-01-16 13:21:15 +0100420 ret = fio_netio_recv(td, io_u);
421 else
422 ret = fio_netio_splice_in(td, io_u);
Jens Axboed4f12dd2007-02-08 12:59:02 +0100423 } else
Jens Axboe7a6499d2007-02-07 09:35:29 +0100424 ret = 0; /* must be a SYNC */
Jens Axboeed92ac02007-02-06 14:43:52 +0100425
Jens Axboecec6b552007-02-06 20:15:38 +0100426 if (ret != (int) io_u->xfer_buflen) {
Jens Axboe22819ec2007-02-18 07:47:14 +0100427 if (ret >= 0) {
Jens Axboecec6b552007-02-06 20:15:38 +0100428 io_u->resid = io_u->xfer_buflen - ret;
429 io_u->error = 0;
Jens Axboe36167d82007-02-18 05:41:31 +0100430 return FIO_Q_COMPLETED;
Jens Axboe414c2a32009-01-16 13:21:15 +0100431 } else {
432 int err = errno;
433
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100434 if (ddir == DDIR_WRITE && err == EMSGSIZE)
Jens Axboe414c2a32009-01-16 13:21:15 +0100435 return FIO_Q_BUSY;
436
437 io_u->error = err;
438 }
Jens Axboeed92ac02007-02-06 14:43:52 +0100439 }
440
Jens Axboe36167d82007-02-18 05:41:31 +0100441 if (io_u->error)
Jens Axboee1161c32007-02-22 19:36:48 +0100442 td_verror(td, io_u->error, "xfer");
Jens Axboeed92ac02007-02-06 14:43:52 +0100443
Jens Axboe36167d82007-02-18 05:41:31 +0100444 return FIO_Q_COMPLETED;
Jens Axboeed92ac02007-02-06 14:43:52 +0100445}
446
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100447static int fio_netio_queue(struct thread_data *td, struct io_u *io_u)
448{
449 struct netio_options *o = td->eo;
450 int ret;
451
452 fio_ro_check(td, io_u);
453
454 ret = __fio_netio_queue(td, io_u, io_u->ddir);
455 if (!o->pingpong || ret != FIO_Q_COMPLETED)
456 return ret;
457
458 /*
459 * For ping-pong mode, receive or send reply as needed
460 */
461 if (td_read(td) && io_u->ddir == DDIR_READ)
462 ret = __fio_netio_queue(td, io_u, DDIR_WRITE);
463 else if (td_write(td) && io_u->ddir == DDIR_WRITE)
464 ret = __fio_netio_queue(td, io_u, DDIR_READ);
465
466 return ret;
467}
468
Jens Axboeb5af8292007-03-08 12:43:13 +0100469static int fio_netio_connect(struct thread_data *td, struct fio_file *f)
Jens Axboeed92ac02007-02-06 14:43:52 +0100470{
Jens Axboeb5af8292007-03-08 12:43:13 +0100471 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100472 struct netio_options *o = td->eo;
Jens Axboe6264c7a2013-02-28 08:24:23 +0100473 int type, domain;
Jens Axboeed92ac02007-02-06 14:43:52 +0100474
Steven Langde890a12011-11-09 14:03:34 +0100475 if (o->proto == FIO_TYPE_TCP) {
Jens Axboe0fd666b2011-10-06 20:08:53 +0200476 domain = AF_INET;
Jens Axboe414c2a32009-01-16 13:21:15 +0100477 type = SOCK_STREAM;
Steven Langde890a12011-11-09 14:03:34 +0100478 } else if (o->proto == FIO_TYPE_UDP) {
Jens Axboe0fd666b2011-10-06 20:08:53 +0200479 domain = AF_INET;
Jens Axboe414c2a32009-01-16 13:21:15 +0100480 type = SOCK_DGRAM;
Steven Langde890a12011-11-09 14:03:34 +0100481 } else if (o->proto == FIO_TYPE_UNIX) {
Jens Axboe0fd666b2011-10-06 20:08:53 +0200482 domain = AF_UNIX;
483 type = SOCK_STREAM;
484 } else {
Steven Langde890a12011-11-09 14:03:34 +0100485 log_err("fio: bad network type %d\n", o->proto);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200486 f->fd = -1;
487 return 1;
488 }
Jens Axboe414c2a32009-01-16 13:21:15 +0100489
Jens Axboe0fd666b2011-10-06 20:08:53 +0200490 f->fd = socket(domain, type, 0);
Jens Axboeb5af8292007-03-08 12:43:13 +0100491 if (f->fd < 0) {
492 td_verror(td, errno, "socket");
493 return 1;
Jens Axboeed92ac02007-02-06 14:43:52 +0100494 }
495
Jens Axboe1eafa372013-01-31 10:19:51 +0100496#ifdef CONFIG_TCP_NODELAY
Steven Noonan70a78782012-11-28 14:52:36 -0800497 if (o->nodelay && o->proto == FIO_TYPE_TCP) {
Jens Axboe6264c7a2013-02-28 08:24:23 +0100498 int optval = 1;
499
Jens Axboe26e594a2013-01-30 21:52:37 +0100500 if (setsockopt(f->fd, IPPROTO_TCP, TCP_NODELAY, (void *) &optval, sizeof(int)) < 0) {
Steven Noonan70a78782012-11-28 14:52:36 -0800501 log_err("fio: cannot set TCP_NODELAY option on socket (%s), disable with 'nodelay=0'\n", strerror(errno));
502 return 1;
503 }
504 }
Jens Axboe1eafa372013-01-31 10:19:51 +0100505#endif
Steven Noonan70a78782012-11-28 14:52:36 -0800506
Steven Langde890a12011-11-09 14:03:34 +0100507 if (o->proto == FIO_TYPE_UDP)
Jens Axboe414c2a32009-01-16 13:21:15 +0100508 return 0;
Steven Langde890a12011-11-09 14:03:34 +0100509 else if (o->proto == FIO_TYPE_TCP) {
Jens Axboe67bf9822013-01-10 11:23:19 +0100510 socklen_t len = sizeof(nd->addr);
Jens Axboe414c2a32009-01-16 13:21:15 +0100511
Jens Axboe0fd666b2011-10-06 20:08:53 +0200512 if (connect(f->fd, (struct sockaddr *) &nd->addr, len) < 0) {
513 td_verror(td, errno, "connect");
Jens Axboeb94cba42011-10-06 21:27:10 +0200514 close(f->fd);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200515 return 1;
516 }
517 } else {
518 struct sockaddr_un *addr = &nd->addr_un;
Jens Axboe67bf9822013-01-10 11:23:19 +0100519 socklen_t len;
Jens Axboe0fd666b2011-10-06 20:08:53 +0200520
521 len = sizeof(addr->sun_family) + strlen(addr->sun_path) + 1;
522
523 if (connect(f->fd, (struct sockaddr *) addr, len) < 0) {
524 td_verror(td, errno, "connect");
Jens Axboeb94cba42011-10-06 21:27:10 +0200525 close(f->fd);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200526 return 1;
527 }
Jens Axboeed92ac02007-02-06 14:43:52 +0100528 }
529
530 return 0;
Jens Axboeed92ac02007-02-06 14:43:52 +0100531}
532
Jens Axboeb5af8292007-03-08 12:43:13 +0100533static int fio_netio_accept(struct thread_data *td, struct fio_file *f)
Jens Axboe5fdd1242007-02-11 04:00:37 +0100534{
Jens Axboeb5af8292007-03-08 12:43:13 +0100535 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100536 struct netio_options *o = td->eo;
Jens Axboe67bf9822013-01-10 11:23:19 +0100537 socklen_t socklen = sizeof(nd->addr);
Jens Axboe6264c7a2013-02-28 08:24:23 +0100538 int state;
Jens Axboe5fdd1242007-02-11 04:00:37 +0100539
Steven Langde890a12011-11-09 14:03:34 +0100540 if (o->proto == FIO_TYPE_UDP) {
Jens Axboe414c2a32009-01-16 13:21:15 +0100541 f->fd = nd->listenfd;
542 return 0;
543 }
544
Jens Axboe859088d2012-11-29 20:02:50 +0100545 state = td->runstate;
546 td_set_runstate(td, TD_SETTING_UP);
547
Jens Axboe6d861442007-03-15 09:22:23 +0100548 log_info("fio: waiting for connection\n");
Jens Axboe5fdd1242007-02-11 04:00:37 +0100549
Jens Axboe371d4562009-01-19 10:17:06 +0100550 if (poll_wait(td, nd->listenfd, POLLIN) < 0)
Jens Axboe859088d2012-11-29 20:02:50 +0100551 goto err;
Jens Axboe5fdd1242007-02-11 04:00:37 +0100552
Jens Axboe371d4562009-01-19 10:17:06 +0100553 f->fd = accept(nd->listenfd, (struct sockaddr *) &nd->addr, &socklen);
554 if (f->fd < 0) {
555 td_verror(td, errno, "accept");
Jens Axboe859088d2012-11-29 20:02:50 +0100556 goto err;
Jens Axboe5fdd1242007-02-11 04:00:37 +0100557 }
558
Jens Axboe1eafa372013-01-31 10:19:51 +0100559#ifdef CONFIG_TCP_NODELAY
Steven Noonan70a78782012-11-28 14:52:36 -0800560 if (o->nodelay && o->proto == FIO_TYPE_TCP) {
Jens Axboe6264c7a2013-02-28 08:24:23 +0100561 int optval = 1;
562
Jens Axboe26e594a2013-01-30 21:52:37 +0100563 if (setsockopt(f->fd, IPPROTO_TCP, TCP_NODELAY, (void *) &optval, sizeof(int)) < 0) {
Steven Noonan70a78782012-11-28 14:52:36 -0800564 log_err("fio: cannot set TCP_NODELAY option on socket (%s), disable with 'nodelay=0'\n", strerror(errno));
565 return 1;
566 }
567 }
Jens Axboe1eafa372013-01-31 10:19:51 +0100568#endif
Steven Noonan70a78782012-11-28 14:52:36 -0800569
Jens Axboe0cae16f2012-11-30 16:22:31 +0100570 reset_all_stats(td);
Jens Axboe859088d2012-11-29 20:02:50 +0100571 td_set_runstate(td, state);
Jens Axboe5fdd1242007-02-11 04:00:37 +0100572 return 0;
Jens Axboe859088d2012-11-29 20:02:50 +0100573err:
574 td_set_runstate(td, state);
575 return 1;
Jens Axboe5fdd1242007-02-11 04:00:37 +0100576}
577
Jens Axboe664fb3b2009-01-19 13:26:36 +0100578static void fio_netio_udp_close(struct thread_data *td, struct fio_file *f)
579{
580 struct netio_data *nd = td->io_ops->data;
581 struct udp_close_msg msg;
Jens Axboe62b38922009-05-11 10:37:33 +0200582 struct sockaddr *to = (struct sockaddr *) &nd->addr;
Jens Axboe664fb3b2009-01-19 13:26:36 +0100583 int ret;
584
Jens Axboeb96d2432012-11-30 08:27:46 +0100585 msg.magic = htonl(FIO_LINK_OPEN_CLOSE_MAGIC);
Jens Axboe664fb3b2009-01-19 13:26:36 +0100586 msg.cmd = htonl(FIO_LINK_CLOSE);
587
Jens Axboe1f819912013-01-23 17:21:41 -0700588 ret = sendto(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to,
Jens Axboe664fb3b2009-01-19 13:26:36 +0100589 sizeof(nd->addr));
590 if (ret < 0)
591 td_verror(td, errno, "sendto udp link close");
592}
593
594static int fio_netio_close_file(struct thread_data *td, struct fio_file *f)
595{
Steven Langde890a12011-11-09 14:03:34 +0100596 struct netio_options *o = td->eo;
Jens Axboe664fb3b2009-01-19 13:26:36 +0100597
598 /*
599 * If this is an UDP connection, notify the receiver that we are
600 * closing down the link
601 */
Steven Langde890a12011-11-09 14:03:34 +0100602 if (o->proto == FIO_TYPE_UDP)
Jens Axboe664fb3b2009-01-19 13:26:36 +0100603 fio_netio_udp_close(td, f);
604
605 return generic_close_file(td, f);
606}
607
Jens Axboeb96d2432012-11-30 08:27:46 +0100608static int fio_netio_udp_recv_open(struct thread_data *td, struct fio_file *f)
609{
610 struct netio_data *nd = td->io_ops->data;
611 struct udp_close_msg msg;
612 struct sockaddr *to = (struct sockaddr *) &nd->addr;
Jens Axboe67bf9822013-01-10 11:23:19 +0100613 socklen_t len = sizeof(nd->addr);
Jens Axboeb96d2432012-11-30 08:27:46 +0100614 int ret;
615
Jens Axboe1f819912013-01-23 17:21:41 -0700616 ret = recvfrom(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to, &len);
Jens Axboeb96d2432012-11-30 08:27:46 +0100617 if (ret < 0) {
618 td_verror(td, errno, "sendto udp link open");
619 return ret;
620 }
621
622 if (ntohl(msg.magic) != FIO_LINK_OPEN_CLOSE_MAGIC ||
623 ntohl(msg.cmd) != FIO_LINK_OPEN) {
624 log_err("fio: bad udp open magic %x/%x\n", ntohl(msg.magic),
625 ntohl(msg.cmd));
626 return -1;
627 }
628
629 return 0;
630}
631
632static int fio_netio_udp_send_open(struct thread_data *td, struct fio_file *f)
633{
634 struct netio_data *nd = td->io_ops->data;
635 struct udp_close_msg msg;
636 struct sockaddr *to = (struct sockaddr *) &nd->addr;
637 int ret;
638
639 msg.magic = htonl(FIO_LINK_OPEN_CLOSE_MAGIC);
640 msg.cmd = htonl(FIO_LINK_OPEN);
641
Jens Axboe1f819912013-01-23 17:21:41 -0700642 ret = sendto(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to,
Jens Axboeb96d2432012-11-30 08:27:46 +0100643 sizeof(nd->addr));
644 if (ret < 0) {
645 td_verror(td, errno, "sendto udp link open");
646 return ret;
647 }
648
649 return 0;
650}
651
652static int fio_netio_open_file(struct thread_data *td, struct fio_file *f)
653{
654 int ret;
655 struct netio_options *o = td->eo;
656
657 if (o->listen)
658 ret = fio_netio_accept(td, f);
659 else
660 ret = fio_netio_connect(td, f);
661
662 if (ret) {
663 f->fd = -1;
664 return ret;
665 }
666
667 if (o->proto == FIO_TYPE_UDP) {
668 if (td_write(td))
669 ret = fio_netio_udp_send_open(td, f);
670 else {
671 int state;
672
673 state = td->runstate;
674 td_set_runstate(td, TD_SETTING_UP);
675 ret = fio_netio_udp_recv_open(td, f);
676 td_set_runstate(td, state);
677 }
678 }
679
680 if (ret)
681 fio_netio_close_file(td, f);
682
683 return ret;
684}
685
Jens Axboe0fd666b2011-10-06 20:08:53 +0200686static int fio_netio_setup_connect_inet(struct thread_data *td,
687 const char *host, unsigned short port)
Jens Axboeb5af8292007-03-08 12:43:13 +0100688{
689 struct netio_data *nd = td->io_ops->data;
690
Jens Axboe166dce42012-11-29 14:35:33 +0100691 if (!host) {
692 log_err("fio: connect with no host to connect to.\n");
693 if (td_read(td))
694 log_err("fio: did you forget to set 'listen'?\n");
695
696 td_verror(td, EINVAL, "no hostname= set");
697 return 1;
698 }
699
Jens Axboeb5af8292007-03-08 12:43:13 +0100700 nd->addr.sin_family = AF_INET;
701 nd->addr.sin_port = htons(port);
702
703 if (inet_aton(host, &nd->addr.sin_addr) != 1) {
704 struct hostent *hent;
705
706 hent = gethostbyname(host);
707 if (!hent) {
708 td_verror(td, errno, "gethostbyname");
709 return 1;
710 }
711
712 memcpy(&nd->addr.sin_addr, hent->h_addr, 4);
713 }
714
715 return 0;
716}
717
Jens Axboe0fd666b2011-10-06 20:08:53 +0200718static int fio_netio_setup_connect_unix(struct thread_data *td,
719 const char *path)
720{
721 struct netio_data *nd = td->io_ops->data;
722 struct sockaddr_un *soun = &nd->addr_un;
723
724 soun->sun_family = AF_UNIX;
725 strcpy(soun->sun_path, path);
726 return 0;
727}
728
Steven Langde890a12011-11-09 14:03:34 +0100729static int fio_netio_setup_connect(struct thread_data *td)
Jens Axboe0fd666b2011-10-06 20:08:53 +0200730{
Steven Langde890a12011-11-09 14:03:34 +0100731 struct netio_options *o = td->eo;
Jens Axboe0fd666b2011-10-06 20:08:53 +0200732
Steven Langde890a12011-11-09 14:03:34 +0100733 if (o->proto == FIO_TYPE_UDP || o->proto == FIO_TYPE_TCP)
734 return fio_netio_setup_connect_inet(td, td->o.filename,o->port);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200735 else
Steven Langde890a12011-11-09 14:03:34 +0100736 return fio_netio_setup_connect_unix(td, td->o.filename);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200737}
738
739static int fio_netio_setup_listen_unix(struct thread_data *td, const char *path)
740{
741 struct netio_data *nd = td->io_ops->data;
742 struct sockaddr_un *addr = &nd->addr_un;
743 mode_t mode;
744 int len, fd;
745
746 fd = socket(AF_UNIX, SOCK_STREAM, 0);
747 if (fd < 0) {
748 log_err("fio: socket: %s\n", strerror(errno));
749 return -1;
750 }
751
752 mode = umask(000);
753
754 memset(addr, 0, sizeof(*addr));
755 addr->sun_family = AF_UNIX;
756 strcpy(addr->sun_path, path);
757 unlink(path);
758
759 len = sizeof(addr->sun_family) + strlen(path) + 1;
760
761 if (bind(fd, (struct sockaddr *) addr, len) < 0) {
762 log_err("fio: bind: %s\n", strerror(errno));
Jens Axboeb94cba42011-10-06 21:27:10 +0200763 close(fd);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200764 return -1;
765 }
766
767 umask(mode);
768 nd->listenfd = fd;
769 return 0;
770}
771
772static int fio_netio_setup_listen_inet(struct thread_data *td, short port)
Jens Axboeb5af8292007-03-08 12:43:13 +0100773{
774 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100775 struct netio_options *o = td->eo;
Jens Axboe414c2a32009-01-16 13:21:15 +0100776 int fd, opt, type;
Jens Axboeed92ac02007-02-06 14:43:52 +0100777
Steven Langde890a12011-11-09 14:03:34 +0100778 if (o->proto == FIO_TYPE_TCP)
Jens Axboe414c2a32009-01-16 13:21:15 +0100779 type = SOCK_STREAM;
780 else
781 type = SOCK_DGRAM;
782
Jens Axboe0fd666b2011-10-06 20:08:53 +0200783 fd = socket(AF_INET, type, 0);
Jens Axboeed92ac02007-02-06 14:43:52 +0100784 if (fd < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100785 td_verror(td, errno, "socket");
Jens Axboeed92ac02007-02-06 14:43:52 +0100786 return 1;
787 }
788
789 opt = 1;
Jens Axboe26e594a2013-01-30 21:52:37 +0100790 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &opt, sizeof(opt)) < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100791 td_verror(td, errno, "setsockopt");
Jens Axboeed92ac02007-02-06 14:43:52 +0100792 return 1;
793 }
Jens Axboe6bedbfa2007-02-07 09:54:40 +0100794#ifdef SO_REUSEPORT
Jens Axboe26e594a2013-01-30 21:52:37 +0100795 if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (void *) &opt, sizeof(opt)) < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100796 td_verror(td, errno, "setsockopt");
Jens Axboe6bedbfa2007-02-07 09:54:40 +0100797 return 1;
798 }
799#endif
Jens Axboeed92ac02007-02-06 14:43:52 +0100800
Jens Axboeb5af8292007-03-08 12:43:13 +0100801 nd->addr.sin_family = AF_INET;
802 nd->addr.sin_addr.s_addr = htonl(INADDR_ANY);
803 nd->addr.sin_port = htons(port);
Jens Axboeed92ac02007-02-06 14:43:52 +0100804
Jens Axboeb5af8292007-03-08 12:43:13 +0100805 if (bind(fd, (struct sockaddr *) &nd->addr, sizeof(nd->addr)) < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100806 td_verror(td, errno, "bind");
Jens Axboeed92ac02007-02-06 14:43:52 +0100807 return 1;
808 }
Jens Axboe0fd666b2011-10-06 20:08:53 +0200809
810 nd->listenfd = fd;
811 return 0;
812}
813
Steven Langde890a12011-11-09 14:03:34 +0100814static int fio_netio_setup_listen(struct thread_data *td)
Jens Axboe0fd666b2011-10-06 20:08:53 +0200815{
816 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100817 struct netio_options *o = td->eo;
Jens Axboe0fd666b2011-10-06 20:08:53 +0200818 int ret;
819
Steven Langde890a12011-11-09 14:03:34 +0100820 if (o->proto == FIO_TYPE_UDP || o->proto == FIO_TYPE_TCP)
821 ret = fio_netio_setup_listen_inet(td, o->port);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200822 else
Steven Langde890a12011-11-09 14:03:34 +0100823 ret = fio_netio_setup_listen_unix(td, td->o.filename);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200824
825 if (ret)
826 return ret;
Steven Langde890a12011-11-09 14:03:34 +0100827 if (o->proto == FIO_TYPE_UDP)
Jens Axboe0fd666b2011-10-06 20:08:53 +0200828 return 0;
829
830 if (listen(nd->listenfd, 10) < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100831 td_verror(td, errno, "listen");
Jens Axboe0fd666b2011-10-06 20:08:53 +0200832 nd->listenfd = -1;
Jens Axboeed92ac02007-02-06 14:43:52 +0100833 return 1;
834 }
835
Jens Axboeb5af8292007-03-08 12:43:13 +0100836 return 0;
Jens Axboeed92ac02007-02-06 14:43:52 +0100837}
838
Jens Axboe9bec88e2007-03-02 08:55:48 +0100839static int fio_netio_init(struct thread_data *td)
Jens Axboeed92ac02007-02-06 14:43:52 +0100840{
Steven Langde890a12011-11-09 14:03:34 +0100841 struct netio_options *o = td->eo;
Jens Axboeaf52b342007-03-13 10:07:47 +0100842 int ret;
Jens Axboeed92ac02007-02-06 14:43:52 +0100843
Bruce Cran3f457be2012-10-10 13:37:41 +0100844#ifdef WIN32
845 WSADATA wsd;
846 WSAStartup(MAKEWORD(2,2), &wsd);
847#endif
848
Jens Axboe16d55aa2007-05-22 09:21:37 +0200849 if (td_random(td)) {
850 log_err("fio: network IO can't be random\n");
851 return 1;
852 }
Jens Axboeed92ac02007-02-06 14:43:52 +0100853
Steven Langde890a12011-11-09 14:03:34 +0100854 if (o->proto == FIO_TYPE_UNIX && o->port) {
855 log_err("fio: network IO port not valid with unix socket\n");
856 return 1;
857 } else if (o->proto != FIO_TYPE_UNIX && !o->port) {
858 log_err("fio: network IO requires port for tcp or udp\n");
859 return 1;
Jens Axboe414c2a32009-01-16 13:21:15 +0100860 }
Jens Axboe0fd666b2011-10-06 20:08:53 +0200861
Steven Langde890a12011-11-09 14:03:34 +0100862 if (o->proto != FIO_TYPE_TCP) {
863 if (o->listen) {
Jens Axboe9b986062011-12-19 08:57:18 +0100864 log_err("fio: listen only valid for TCP proto IO\n");
865 return 1;
Steven Langde890a12011-11-09 14:03:34 +0100866 }
867 if (td_rw(td)) {
Jens Axboe9b986062011-12-19 08:57:18 +0100868 log_err("fio: datagram network connections must be"
Steven Langde890a12011-11-09 14:03:34 +0100869 " read OR write\n");
Jens Axboe9b986062011-12-19 08:57:18 +0100870 return 1;
871 }
872 if (o->proto == FIO_TYPE_UNIX && !td->o.filename) {
873 log_err("fio: UNIX sockets need host/filename\n");
874 return 1;
Steven Langde890a12011-11-09 14:03:34 +0100875 }
876 o->listen = td_read(td);
877 }
878
879 if (o->proto != FIO_TYPE_UNIX && o->listen && td->o.filename) {
880 log_err("fio: hostname not valid for inbound network IO\n");
881 return 1;
882 }
883
884 if (o->listen)
885 ret = fio_netio_setup_listen(td);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200886 else
Steven Langde890a12011-11-09 14:03:34 +0100887 ret = fio_netio_setup_connect(td);
Jens Axboeed92ac02007-02-06 14:43:52 +0100888
Jens Axboe7bb48f82007-03-27 15:30:28 +0200889 return ret;
Jens Axboeed92ac02007-02-06 14:43:52 +0100890}
891
Jens Axboeb5af8292007-03-08 12:43:13 +0100892static void fio_netio_cleanup(struct thread_data *td)
Jens Axboe9bec88e2007-03-02 08:55:48 +0100893{
Jens Axboeb5af8292007-03-08 12:43:13 +0100894 struct netio_data *nd = td->io_ops->data;
895
896 if (nd) {
Jens Axboe64b24cd2007-06-24 21:28:39 +0200897 if (nd->listenfd != -1)
898 close(nd->listenfd);
899 if (nd->pipes[0] != -1)
900 close(nd->pipes[0]);
901 if (nd->pipes[1] != -1)
902 close(nd->pipes[1]);
903
Jens Axboeb5af8292007-03-08 12:43:13 +0100904 free(nd);
Jens Axboeb5af8292007-03-08 12:43:13 +0100905 }
906}
907
908static int fio_netio_setup(struct thread_data *td)
909{
Jens Axboe7bb48f82007-03-27 15:30:28 +0200910 struct netio_data *nd;
Jens Axboeb5af8292007-03-08 12:43:13 +0100911
Steven Langde890a12011-11-09 14:03:34 +0100912 if (!td->files_index) {
913 add_file(td, td->o.filename ?: "net");
914 td->o.nr_files = td->o.nr_files ?: 1;
915 }
916
Jens Axboe7bb48f82007-03-27 15:30:28 +0200917 if (!td->io_ops->data) {
918 nd = malloc(sizeof(*nd));;
919
920 memset(nd, 0, sizeof(*nd));
921 nd->listenfd = -1;
Jens Axboe64b24cd2007-06-24 21:28:39 +0200922 nd->pipes[0] = nd->pipes[1] = -1;
Jens Axboe7bb48f82007-03-27 15:30:28 +0200923 td->io_ops->data = nd;
Jens Axboe7bb48f82007-03-27 15:30:28 +0200924 }
925
Jens Axboe9bec88e2007-03-02 08:55:48 +0100926 return 0;
927}
928
Jens Axboe36d80bc2012-11-30 21:46:06 +0100929static void fio_netio_terminate(struct thread_data *td)
930{
931 kill(td->pid, SIGUSR2);
932}
933
Jens Axboe67bf9822013-01-10 11:23:19 +0100934#ifdef CONFIG_LINUX_SPLICE
Jens Axboe9cce02e2007-06-22 15:42:21 +0200935static int fio_netio_setup_splice(struct thread_data *td)
936{
937 struct netio_data *nd;
938
939 fio_netio_setup(td);
940
941 nd = td->io_ops->data;
942 if (nd) {
943 if (pipe(nd->pipes) < 0)
944 return 1;
945
946 nd->use_splice = 1;
947 return 0;
948 }
949
950 return 1;
951}
952
Jens Axboe5921e802008-05-30 15:02:38 +0200953static struct ioengine_ops ioengine_splice = {
Steven Langde890a12011-11-09 14:03:34 +0100954 .name = "netsplice",
955 .version = FIO_IOOPS_VERSION,
956 .prep = fio_netio_prep,
957 .queue = fio_netio_queue,
958 .setup = fio_netio_setup_splice,
959 .init = fio_netio_init,
960 .cleanup = fio_netio_cleanup,
961 .open_file = fio_netio_open_file,
Jens Axboe36d80bc2012-11-30 21:46:06 +0100962 .close_file = fio_netio_close_file,
963 .terminate = fio_netio_terminate,
Steven Langde890a12011-11-09 14:03:34 +0100964 .options = options,
965 .option_struct_size = sizeof(struct netio_options),
966 .flags = FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR |
Jens Axboe36d80bc2012-11-30 21:46:06 +0100967 FIO_PIPEIO,
Jens Axboe5921e802008-05-30 15:02:38 +0200968};
969#endif
970
Jens Axboe9cce02e2007-06-22 15:42:21 +0200971static struct ioengine_ops ioengine_rw = {
Steven Langde890a12011-11-09 14:03:34 +0100972 .name = "net",
973 .version = FIO_IOOPS_VERSION,
974 .prep = fio_netio_prep,
975 .queue = fio_netio_queue,
976 .setup = fio_netio_setup,
977 .init = fio_netio_init,
978 .cleanup = fio_netio_cleanup,
979 .open_file = fio_netio_open_file,
980 .close_file = fio_netio_close_file,
Jens Axboe36d80bc2012-11-30 21:46:06 +0100981 .terminate = fio_netio_terminate,
Steven Langde890a12011-11-09 14:03:34 +0100982 .options = options,
983 .option_struct_size = sizeof(struct netio_options),
984 .flags = FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR |
Steven Noonanad705bc2013-04-08 15:05:25 -0700985 FIO_PIPEIO | FIO_BIT_BASED,
Jens Axboeed92ac02007-02-06 14:43:52 +0100986};
987
Steven Langde890a12011-11-09 14:03:34 +0100988static int str_hostname_cb(void *data, const char *input)
989{
990 struct netio_options *o = data;
991
992 if (o->td->o.filename)
993 free(o->td->o.filename);
994 o->td->o.filename = strdup(input);
995 return 0;
996}
997
Jens Axboeed92ac02007-02-06 14:43:52 +0100998static void fio_init fio_netio_register(void)
999{
Jens Axboe9cce02e2007-06-22 15:42:21 +02001000 register_ioengine(&ioengine_rw);
Jens Axboe67bf9822013-01-10 11:23:19 +01001001#ifdef CONFIG_LINUX_SPLICE
Jens Axboe9cce02e2007-06-22 15:42:21 +02001002 register_ioengine(&ioengine_splice);
Jens Axboe5921e802008-05-30 15:02:38 +02001003#endif
Jens Axboeed92ac02007-02-06 14:43:52 +01001004}
1005
1006static void fio_exit fio_netio_unregister(void)
1007{
Jens Axboe9cce02e2007-06-22 15:42:21 +02001008 unregister_ioengine(&ioengine_rw);
Jens Axboe67bf9822013-01-10 11:23:19 +01001009#ifdef CONFIG_LINUX_SPLICE
Jens Axboe9cce02e2007-06-22 15:42:21 +02001010 unregister_ioengine(&ioengine_splice);
Jens Axboe5921e802008-05-30 15:02:38 +02001011#endif
Jens Axboeed92ac02007-02-06 14:43:52 +01001012}