blob: 4804a206bad73cbd549f2c6e0fbf03daeb342448 [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;
Shawn Bohrerb93b6a22013-07-19 13:24:07 -050040 char * interface;
Steven Langde890a12011-11-09 14:03:34 +010041};
42
Jens Axboe664fb3b2009-01-19 13:26:36 +010043struct udp_close_msg {
44 uint32_t magic;
45 uint32_t cmd;
46};
47
48enum {
49 FIO_LINK_CLOSE = 0x89,
Jens Axboeb96d2432012-11-30 08:27:46 +010050 FIO_LINK_OPEN_CLOSE_MAGIC = 0x6c696e6b,
51 FIO_LINK_OPEN = 0x98,
Jens Axboe0fd666b2011-10-06 20:08:53 +020052
53 FIO_TYPE_TCP = 1,
54 FIO_TYPE_UDP = 2,
55 FIO_TYPE_UNIX = 3,
Jens Axboe664fb3b2009-01-19 13:26:36 +010056};
57
Steven Langde890a12011-11-09 14:03:34 +010058static int str_hostname_cb(void *data, const char *input);
59static struct fio_option options[] = {
60 {
61 .name = "hostname",
Jens Axboee8b0e952012-03-19 14:37:08 +010062 .lname = "net engine hostname",
Steven Langde890a12011-11-09 14:03:34 +010063 .type = FIO_OPT_STR_STORE,
64 .cb = str_hostname_cb,
65 .help = "Hostname for net IO engine",
Jens Axboee90a0ad2013-04-10 19:43:59 +020066 .category = FIO_OPT_C_ENGINE,
67 .group = FIO_OPT_G_NETIO,
Steven Langde890a12011-11-09 14:03:34 +010068 },
69 {
70 .name = "port",
Jens Axboee8b0e952012-03-19 14:37:08 +010071 .lname = "net engine port",
Steven Langde890a12011-11-09 14:03:34 +010072 .type = FIO_OPT_INT,
73 .off1 = offsetof(struct netio_options, port),
74 .minval = 1,
75 .maxval = 65535,
76 .help = "Port to use for TCP or UDP net connections",
Jens Axboee90a0ad2013-04-10 19:43:59 +020077 .category = FIO_OPT_C_ENGINE,
78 .group = FIO_OPT_G_NETIO,
Steven Langde890a12011-11-09 14:03:34 +010079 },
80 {
81 .name = "protocol",
Jens Axboee8b0e952012-03-19 14:37:08 +010082 .lname = "net engine protocol",
Steven Langde890a12011-11-09 14:03:34 +010083 .alias = "proto",
84 .type = FIO_OPT_STR,
85 .off1 = offsetof(struct netio_options, proto),
86 .help = "Network protocol to use",
87 .def = "tcp",
88 .posval = {
89 { .ival = "tcp",
90 .oval = FIO_TYPE_TCP,
91 .help = "Transmission Control Protocol",
92 },
93 { .ival = "udp",
94 .oval = FIO_TYPE_UDP,
Bruce Cranf5cc3d02012-10-10 08:17:44 -060095 .help = "User Datagram Protocol",
Steven Langde890a12011-11-09 14:03:34 +010096 },
97 { .ival = "unix",
98 .oval = FIO_TYPE_UNIX,
99 .help = "UNIX domain socket",
100 },
101 },
Jens Axboee90a0ad2013-04-10 19:43:59 +0200102 .category = FIO_OPT_C_ENGINE,
103 .group = FIO_OPT_G_NETIO,
Steven Langde890a12011-11-09 14:03:34 +0100104 },
Jens Axboe1eafa372013-01-31 10:19:51 +0100105#ifdef CONFIG_TCP_NODELAY
Steven Langde890a12011-11-09 14:03:34 +0100106 {
Steven Noonan70a78782012-11-28 14:52:36 -0800107 .name = "nodelay",
108 .type = FIO_OPT_BOOL,
109 .off1 = offsetof(struct netio_options, nodelay),
110 .help = "Use TCP_NODELAY on TCP connections",
Jens Axboee90a0ad2013-04-10 19:43:59 +0200111 .category = FIO_OPT_C_ENGINE,
112 .group = FIO_OPT_G_NETIO,
Steven Noonan70a78782012-11-28 14:52:36 -0800113 },
Jens Axboe1eafa372013-01-31 10:19:51 +0100114#endif
Steven Langde890a12011-11-09 14:03:34 +0100115 {
116 .name = "listen",
Jens Axboee8b0e952012-03-19 14:37:08 +0100117 .lname = "net engine listen",
Steven Langde890a12011-11-09 14:03:34 +0100118 .type = FIO_OPT_STR_SET,
119 .off1 = offsetof(struct netio_options, listen),
120 .help = "Listen for incoming TCP connections",
Jens Axboee90a0ad2013-04-10 19:43:59 +0200121 .category = FIO_OPT_C_ENGINE,
122 .group = FIO_OPT_G_NETIO,
Steven Langde890a12011-11-09 14:03:34 +0100123 },
124 {
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100125 .name = "pingpong",
126 .type = FIO_OPT_STR_SET,
127 .off1 = offsetof(struct netio_options, pingpong),
128 .help = "Ping-pong IO requests",
Jens Axboee90a0ad2013-04-10 19:43:59 +0200129 .category = FIO_OPT_C_ENGINE,
130 .group = FIO_OPT_G_NETIO,
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100131 },
132 {
Shawn Bohrerb93b6a22013-07-19 13:24:07 -0500133 .name = "interface",
134 .lname = "net engine interface",
135 .type = FIO_OPT_STR_STORE,
136 .off1 = offsetof(struct netio_options, interface),
137 .help = "Network interface to use",
138 .category = FIO_OPT_C_ENGINE,
139 .group = FIO_OPT_G_NETIO,
140 },
141 {
Steven Langde890a12011-11-09 14:03:34 +0100142 .name = NULL,
143 },
144};
145
Jens Axboe371d4562009-01-19 10:17:06 +0100146/*
147 * Return -1 for error and 'nr events' for a positive number
148 * of events
149 */
150static int poll_wait(struct thread_data *td, int fd, short events)
151{
152 struct pollfd pfd;
153 int ret;
154
155 while (!td->terminate) {
156 pfd.fd = fd;
157 pfd.events = events;
158 ret = poll(&pfd, 1, -1);
159 if (ret < 0) {
160 if (errno == EINTR)
Jens Axboed5b388a2009-01-19 12:38:27 +0100161 break;
Jens Axboe371d4562009-01-19 10:17:06 +0100162
163 td_verror(td, errno, "poll");
164 return -1;
165 } else if (!ret)
166 continue;
167
168 break;
169 }
170
171 if (pfd.revents & events)
172 return 1;
Jens Axboe371d4562009-01-19 10:17:06 +0100173
174 return -1;
175}
176
Shawn Bohrerb511c9a2013-07-19 13:24:06 -0500177static int fio_netio_is_multicast(const char *mcaddr)
178{
179 in_addr_t addr = inet_network(mcaddr);
180 if (addr == -1)
181 return 0;
182
183 if (inet_network("224.0.0.0") <= addr &&
184 inet_network("239.255.255.255") >= addr)
185 return 1;
186
187 return 0;
188}
189
190
Jens Axboeed92ac02007-02-06 14:43:52 +0100191static int fio_netio_prep(struct thread_data *td, struct io_u *io_u)
192{
Steven Langde890a12011-11-09 14:03:34 +0100193 struct netio_options *o = td->eo;
Jens Axboeed92ac02007-02-06 14:43:52 +0100194
Jens Axboe7a6499d2007-02-07 09:35:29 +0100195 /*
196 * Make sure we don't see spurious reads to a receiver, and vice versa
197 */
Steven Langde890a12011-11-09 14:03:34 +0100198 if (o->proto == FIO_TYPE_TCP)
199 return 0;
200
201 if ((o->listen && io_u->ddir == DDIR_WRITE) ||
202 (!o->listen && io_u->ddir == DDIR_READ)) {
Jens Axboee1161c32007-02-22 19:36:48 +0100203 td_verror(td, EINVAL, "bad direction");
Jens Axboe7a6499d2007-02-07 09:35:29 +0100204 return 1;
Jens Axboeed92ac02007-02-06 14:43:52 +0100205 }
Bruce Cran3f457be2012-10-10 13:37:41 +0100206
Jens Axboef85ac252008-03-01 18:09:49 +0100207 return 0;
Jens Axboeed92ac02007-02-06 14:43:52 +0100208}
209
Jens Axboe67bf9822013-01-10 11:23:19 +0100210#ifdef CONFIG_LINUX_SPLICE
Jens Axboecd963e12007-06-24 21:41:46 +0200211static int splice_io_u(int fdin, int fdout, unsigned int len)
Jens Axboe9cce02e2007-06-22 15:42:21 +0200212{
Jens Axboe9cce02e2007-06-22 15:42:21 +0200213 int bytes = 0;
214
215 while (len) {
Jens Axboecd963e12007-06-24 21:41:46 +0200216 int ret = splice(fdin, NULL, fdout, NULL, len, 0);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200217
218 if (ret < 0) {
219 if (!bytes)
220 bytes = ret;
221
222 break;
223 } else if (!ret)
224 break;
225
226 bytes += ret;
Jens Axboef657a2f2007-06-22 20:40:10 +0200227 len -= ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200228 }
229
230 return bytes;
231}
232
233/*
Jens Axboecd963e12007-06-24 21:41:46 +0200234 * Receive bytes from a socket and fill them into the internal pipe
235 */
236static int splice_in(struct thread_data *td, struct io_u *io_u)
237{
238 struct netio_data *nd = td->io_ops->data;
239
240 return splice_io_u(io_u->file->fd, nd->pipes[1], io_u->xfer_buflen);
241}
242
243/*
Jens Axboe9cce02e2007-06-22 15:42:21 +0200244 * Transmit 'len' bytes from the internal pipe
245 */
246static int splice_out(struct thread_data *td, struct io_u *io_u,
247 unsigned int len)
248{
249 struct netio_data *nd = td->io_ops->data;
Jens Axboecd963e12007-06-24 21:41:46 +0200250
251 return splice_io_u(nd->pipes[0], io_u->file->fd, len);
252}
253
254static int vmsplice_io_u(struct io_u *io_u, int fd, unsigned int len)
255{
256 struct iovec iov = {
257 .iov_base = io_u->xfer_buf,
258 .iov_len = len,
259 };
Jens Axboe9cce02e2007-06-22 15:42:21 +0200260 int bytes = 0;
261
Jens Axboecd963e12007-06-24 21:41:46 +0200262 while (iov.iov_len) {
263 int ret = vmsplice(fd, &iov, 1, SPLICE_F_MOVE);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200264
265 if (ret < 0) {
266 if (!bytes)
267 bytes = ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200268 break;
269 } else if (!ret)
270 break;
271
Jens Axboecd963e12007-06-24 21:41:46 +0200272 iov.iov_len -= ret;
273 iov.iov_base += ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200274 bytes += ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200275 }
276
277 return bytes;
Jens Axboecd963e12007-06-24 21:41:46 +0200278
Jens Axboe9cce02e2007-06-22 15:42:21 +0200279}
280
281/*
282 * vmsplice() pipe to io_u buffer
283 */
284static int vmsplice_io_u_out(struct thread_data *td, struct io_u *io_u,
285 unsigned int len)
286{
287 struct netio_data *nd = td->io_ops->data;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200288
Jens Axboecd963e12007-06-24 21:41:46 +0200289 return vmsplice_io_u(io_u, nd->pipes[0], len);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200290}
291
292/*
293 * vmsplice() io_u to pipe
294 */
295static int vmsplice_io_u_in(struct thread_data *td, struct io_u *io_u)
296{
297 struct netio_data *nd = td->io_ops->data;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200298
Jens Axboecd963e12007-06-24 21:41:46 +0200299 return vmsplice_io_u(io_u, nd->pipes[1], io_u->xfer_buflen);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200300}
301
Jens Axboecd963e12007-06-24 21:41:46 +0200302/*
303 * splice receive - transfer socket data into a pipe using splice, then map
304 * that pipe data into the io_u using vmsplice.
305 */
Jens Axboe9cce02e2007-06-22 15:42:21 +0200306static int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
307{
308 int ret;
309
310 ret = splice_in(td, io_u);
Jens Axboecd963e12007-06-24 21:41:46 +0200311 if (ret > 0)
312 return vmsplice_io_u_out(td, io_u, ret);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200313
Jens Axboecd963e12007-06-24 21:41:46 +0200314 return ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200315}
316
Jens Axboecd963e12007-06-24 21:41:46 +0200317/*
318 * splice transmit - map data from the io_u into a pipe by using vmsplice,
319 * then transfer that pipe to a socket using splice.
320 */
Jens Axboe9cce02e2007-06-22 15:42:21 +0200321static int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
322{
323 int ret;
324
325 ret = vmsplice_io_u_in(td, io_u);
Jens Axboecd963e12007-06-24 21:41:46 +0200326 if (ret > 0)
327 return splice_out(td, io_u, ret);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200328
Jens Axboecd963e12007-06-24 21:41:46 +0200329 return ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200330}
Jens Axboe5921e802008-05-30 15:02:38 +0200331#else
332static int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
333{
Jens Axboeaf8771b2008-05-30 22:58:28 +0200334 errno = EOPNOTSUPP;
Jens Axboe5921e802008-05-30 15:02:38 +0200335 return -1;
336}
337
338static int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
339{
Jens Axboeaf8771b2008-05-30 22:58:28 +0200340 errno = EOPNOTSUPP;
Jens Axboe5921e802008-05-30 15:02:38 +0200341 return -1;
342}
343#endif
Jens Axboe9cce02e2007-06-22 15:42:21 +0200344
345static int fio_netio_send(struct thread_data *td, struct io_u *io_u)
346{
Jens Axboe414c2a32009-01-16 13:21:15 +0100347 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100348 struct netio_options *o = td->eo;
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100349 int ret, flags = 0;
Jens Axboe371d4562009-01-19 10:17:06 +0100350
Jens Axboe664fb3b2009-01-19 13:26:36 +0100351 do {
Steven Langde890a12011-11-09 14:03:34 +0100352 if (o->proto == FIO_TYPE_UDP) {
Jens Axboe62b38922009-05-11 10:37:33 +0200353 struct sockaddr *to = (struct sockaddr *) &nd->addr;
354
Jens Axboe664fb3b2009-01-19 13:26:36 +0100355 ret = sendto(io_u->file->fd, io_u->xfer_buf,
Jens Axboe62b38922009-05-11 10:37:33 +0200356 io_u->xfer_buflen, flags, to,
357 sizeof(*to));
Jens Axboe664fb3b2009-01-19 13:26:36 +0100358 } else {
359 /*
360 * if we are going to write more, set MSG_MORE
361 */
Jens Axboe5921e802008-05-30 15:02:38 +0200362#ifdef MSG_MORE
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100363 if ((td->this_io_bytes[DDIR_WRITE] + io_u->xfer_buflen <
364 td->o.size) && !o->pingpong)
Jens Axboe664fb3b2009-01-19 13:26:36 +0100365 flags |= MSG_MORE;
Jens Axboe5921e802008-05-30 15:02:38 +0200366#endif
Jens Axboe664fb3b2009-01-19 13:26:36 +0100367 ret = send(io_u->file->fd, io_u->xfer_buf,
368 io_u->xfer_buflen, flags);
369 }
370 if (ret > 0)
371 break;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200372
Jens Axboe664fb3b2009-01-19 13:26:36 +0100373 ret = poll_wait(td, io_u->file->fd, POLLOUT);
374 if (ret <= 0)
375 break;
Jens Axboe664fb3b2009-01-19 13:26:36 +0100376 } while (1);
377
378 return ret;
379}
380
381static int is_udp_close(struct io_u *io_u, int len)
382{
383 struct udp_close_msg *msg;
384
385 if (len != sizeof(struct udp_close_msg))
386 return 0;
387
388 msg = io_u->xfer_buf;
Jens Axboeb96d2432012-11-30 08:27:46 +0100389 if (ntohl(msg->magic) != FIO_LINK_OPEN_CLOSE_MAGIC)
Jens Axboe664fb3b2009-01-19 13:26:36 +0100390 return 0;
391 if (ntohl(msg->cmd) != FIO_LINK_CLOSE)
392 return 0;
393
394 return 1;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200395}
396
Jens Axboe414c2a32009-01-16 13:21:15 +0100397static int fio_netio_recv(struct thread_data *td, struct io_u *io_u)
Jens Axboe9cce02e2007-06-22 15:42:21 +0200398{
Jens Axboe414c2a32009-01-16 13:21:15 +0100399 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100400 struct netio_options *o = td->eo;
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100401 int ret, flags = 0;
Jens Axboe371d4562009-01-19 10:17:06 +0100402
Jens Axboe664fb3b2009-01-19 13:26:36 +0100403 do {
Steven Langde890a12011-11-09 14:03:34 +0100404 if (o->proto == FIO_TYPE_UDP) {
Shawn Bohrerb511c9a2013-07-19 13:24:06 -0500405 socklen_t l;
406 socklen_t *len = &l;
407 struct sockaddr *from;
408
409 if (o->listen) {
410 from = (struct sockaddr *) &nd->addr;
411 *len = sizeof(nd->addr);
412 } else {
413 from = NULL;
414 len = NULL;
415 }
Jens Axboe9cce02e2007-06-22 15:42:21 +0200416
Jens Axboe664fb3b2009-01-19 13:26:36 +0100417 ret = recvfrom(io_u->file->fd, io_u->xfer_buf,
Shawn Bohrerb511c9a2013-07-19 13:24:06 -0500418 io_u->xfer_buflen, flags, from, len);
Jens Axboe664fb3b2009-01-19 13:26:36 +0100419 if (is_udp_close(io_u, ret)) {
420 td->done = 1;
421 return 0;
422 }
423 } else {
424 ret = recv(io_u->file->fd, io_u->xfer_buf,
425 io_u->xfer_buflen, flags);
426 }
427 if (ret > 0)
428 break;
Jens Axboe7d988f62012-11-29 19:57:35 +0100429 else if (!ret && (flags & MSG_WAITALL))
430 break;
Jens Axboe414c2a32009-01-16 13:21:15 +0100431
Jens Axboe664fb3b2009-01-19 13:26:36 +0100432 ret = poll_wait(td, io_u->file->fd, POLLIN);
433 if (ret <= 0)
434 break;
Jens Axboe664fb3b2009-01-19 13:26:36 +0100435 flags |= MSG_WAITALL;
436 } while (1);
437
438 return ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200439}
440
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100441static int __fio_netio_queue(struct thread_data *td, struct io_u *io_u,
442 enum fio_ddir ddir)
Jens Axboeed92ac02007-02-06 14:43:52 +0100443{
Jens Axboe9cce02e2007-06-22 15:42:21 +0200444 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100445 struct netio_options *o = td->eo;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200446 int ret;
Jens Axboeed92ac02007-02-06 14:43:52 +0100447
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100448 if (ddir == DDIR_WRITE) {
Steven Langde890a12011-11-09 14:03:34 +0100449 if (!nd->use_splice || o->proto == FIO_TYPE_UDP ||
450 o->proto == FIO_TYPE_UNIX)
Jens Axboe9cce02e2007-06-22 15:42:21 +0200451 ret = fio_netio_send(td, io_u);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200452 else
Jens Axboe414c2a32009-01-16 13:21:15 +0100453 ret = fio_netio_splice_out(td, io_u);
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100454 } else if (ddir == DDIR_READ) {
Steven Langde890a12011-11-09 14:03:34 +0100455 if (!nd->use_splice || o->proto == FIO_TYPE_UDP ||
456 o->proto == FIO_TYPE_UNIX)
Jens Axboe414c2a32009-01-16 13:21:15 +0100457 ret = fio_netio_recv(td, io_u);
458 else
459 ret = fio_netio_splice_in(td, io_u);
Jens Axboed4f12dd2007-02-08 12:59:02 +0100460 } else
Jens Axboe7a6499d2007-02-07 09:35:29 +0100461 ret = 0; /* must be a SYNC */
Jens Axboeed92ac02007-02-06 14:43:52 +0100462
Jens Axboecec6b552007-02-06 20:15:38 +0100463 if (ret != (int) io_u->xfer_buflen) {
Jens Axboe22819ec2007-02-18 07:47:14 +0100464 if (ret >= 0) {
Jens Axboecec6b552007-02-06 20:15:38 +0100465 io_u->resid = io_u->xfer_buflen - ret;
466 io_u->error = 0;
Jens Axboe36167d82007-02-18 05:41:31 +0100467 return FIO_Q_COMPLETED;
Jens Axboe414c2a32009-01-16 13:21:15 +0100468 } else {
469 int err = errno;
470
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100471 if (ddir == DDIR_WRITE && err == EMSGSIZE)
Jens Axboe414c2a32009-01-16 13:21:15 +0100472 return FIO_Q_BUSY;
473
474 io_u->error = err;
475 }
Jens Axboeed92ac02007-02-06 14:43:52 +0100476 }
477
Jens Axboe36167d82007-02-18 05:41:31 +0100478 if (io_u->error)
Jens Axboee1161c32007-02-22 19:36:48 +0100479 td_verror(td, io_u->error, "xfer");
Jens Axboeed92ac02007-02-06 14:43:52 +0100480
Jens Axboe36167d82007-02-18 05:41:31 +0100481 return FIO_Q_COMPLETED;
Jens Axboeed92ac02007-02-06 14:43:52 +0100482}
483
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100484static int fio_netio_queue(struct thread_data *td, struct io_u *io_u)
485{
486 struct netio_options *o = td->eo;
487 int ret;
488
489 fio_ro_check(td, io_u);
490
491 ret = __fio_netio_queue(td, io_u, io_u->ddir);
492 if (!o->pingpong || ret != FIO_Q_COMPLETED)
493 return ret;
494
495 /*
496 * For ping-pong mode, receive or send reply as needed
497 */
498 if (td_read(td) && io_u->ddir == DDIR_READ)
499 ret = __fio_netio_queue(td, io_u, DDIR_WRITE);
500 else if (td_write(td) && io_u->ddir == DDIR_WRITE)
501 ret = __fio_netio_queue(td, io_u, DDIR_READ);
502
503 return ret;
504}
505
Jens Axboeb5af8292007-03-08 12:43:13 +0100506static int fio_netio_connect(struct thread_data *td, struct fio_file *f)
Jens Axboeed92ac02007-02-06 14:43:52 +0100507{
Jens Axboeb5af8292007-03-08 12:43:13 +0100508 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100509 struct netio_options *o = td->eo;
Jens Axboe6264c7a2013-02-28 08:24:23 +0100510 int type, domain;
Jens Axboeed92ac02007-02-06 14:43:52 +0100511
Steven Langde890a12011-11-09 14:03:34 +0100512 if (o->proto == FIO_TYPE_TCP) {
Jens Axboe0fd666b2011-10-06 20:08:53 +0200513 domain = AF_INET;
Jens Axboe414c2a32009-01-16 13:21:15 +0100514 type = SOCK_STREAM;
Steven Langde890a12011-11-09 14:03:34 +0100515 } else if (o->proto == FIO_TYPE_UDP) {
Jens Axboe0fd666b2011-10-06 20:08:53 +0200516 domain = AF_INET;
Jens Axboe414c2a32009-01-16 13:21:15 +0100517 type = SOCK_DGRAM;
Steven Langde890a12011-11-09 14:03:34 +0100518 } else if (o->proto == FIO_TYPE_UNIX) {
Jens Axboe0fd666b2011-10-06 20:08:53 +0200519 domain = AF_UNIX;
520 type = SOCK_STREAM;
521 } else {
Steven Langde890a12011-11-09 14:03:34 +0100522 log_err("fio: bad network type %d\n", o->proto);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200523 f->fd = -1;
524 return 1;
525 }
Jens Axboe414c2a32009-01-16 13:21:15 +0100526
Jens Axboe0fd666b2011-10-06 20:08:53 +0200527 f->fd = socket(domain, type, 0);
Jens Axboeb5af8292007-03-08 12:43:13 +0100528 if (f->fd < 0) {
529 td_verror(td, errno, "socket");
530 return 1;
Jens Axboeed92ac02007-02-06 14:43:52 +0100531 }
532
Jens Axboe1eafa372013-01-31 10:19:51 +0100533#ifdef CONFIG_TCP_NODELAY
Steven Noonan70a78782012-11-28 14:52:36 -0800534 if (o->nodelay && o->proto == FIO_TYPE_TCP) {
Jens Axboe6264c7a2013-02-28 08:24:23 +0100535 int optval = 1;
536
Jens Axboe26e594a2013-01-30 21:52:37 +0100537 if (setsockopt(f->fd, IPPROTO_TCP, TCP_NODELAY, (void *) &optval, sizeof(int)) < 0) {
Steven Noonan70a78782012-11-28 14:52:36 -0800538 log_err("fio: cannot set TCP_NODELAY option on socket (%s), disable with 'nodelay=0'\n", strerror(errno));
539 return 1;
540 }
541 }
Jens Axboe1eafa372013-01-31 10:19:51 +0100542#endif
Steven Noonan70a78782012-11-28 14:52:36 -0800543
Shawn Bohrerb93b6a22013-07-19 13:24:07 -0500544 if (o->proto == FIO_TYPE_UDP) {
545 if (o->interface && fio_netio_is_multicast(td->o.filename)) {
546 struct in_addr interface_addr;
547 if (inet_aton(o->interface, &interface_addr) == 0) {
548 log_err("fio: interface not valid interface IP\n");
549 close(f->fd);
550 return 1;
551 }
552 if (setsockopt(f->fd, IPPROTO_IP, IP_MULTICAST_IF, &interface_addr, sizeof(interface_addr)) < 0) {
553 td_verror(td, errno, "setsockopt IP_MULTICAST_IF");
554 close(f->fd);
555 return 1;
556 }
557 }
Jens Axboe414c2a32009-01-16 13:21:15 +0100558 return 0;
Shawn Bohrerb93b6a22013-07-19 13:24:07 -0500559 } else if (o->proto == FIO_TYPE_TCP) {
Jens Axboe67bf9822013-01-10 11:23:19 +0100560 socklen_t len = sizeof(nd->addr);
Jens Axboe414c2a32009-01-16 13:21:15 +0100561
Jens Axboe0fd666b2011-10-06 20:08:53 +0200562 if (connect(f->fd, (struct sockaddr *) &nd->addr, len) < 0) {
563 td_verror(td, errno, "connect");
Jens Axboeb94cba42011-10-06 21:27:10 +0200564 close(f->fd);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200565 return 1;
566 }
567 } else {
568 struct sockaddr_un *addr = &nd->addr_un;
Jens Axboe67bf9822013-01-10 11:23:19 +0100569 socklen_t len;
Jens Axboe0fd666b2011-10-06 20:08:53 +0200570
571 len = sizeof(addr->sun_family) + strlen(addr->sun_path) + 1;
572
573 if (connect(f->fd, (struct sockaddr *) addr, len) < 0) {
574 td_verror(td, errno, "connect");
Jens Axboeb94cba42011-10-06 21:27:10 +0200575 close(f->fd);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200576 return 1;
577 }
Jens Axboeed92ac02007-02-06 14:43:52 +0100578 }
579
580 return 0;
Jens Axboeed92ac02007-02-06 14:43:52 +0100581}
582
Jens Axboeb5af8292007-03-08 12:43:13 +0100583static int fio_netio_accept(struct thread_data *td, struct fio_file *f)
Jens Axboe5fdd1242007-02-11 04:00:37 +0100584{
Jens Axboeb5af8292007-03-08 12:43:13 +0100585 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100586 struct netio_options *o = td->eo;
Jens Axboe67bf9822013-01-10 11:23:19 +0100587 socklen_t socklen = sizeof(nd->addr);
Jens Axboe6264c7a2013-02-28 08:24:23 +0100588 int state;
Jens Axboe5fdd1242007-02-11 04:00:37 +0100589
Steven Langde890a12011-11-09 14:03:34 +0100590 if (o->proto == FIO_TYPE_UDP) {
Jens Axboe414c2a32009-01-16 13:21:15 +0100591 f->fd = nd->listenfd;
592 return 0;
593 }
594
Jens Axboe859088d2012-11-29 20:02:50 +0100595 state = td->runstate;
596 td_set_runstate(td, TD_SETTING_UP);
597
Jens Axboe6d861442007-03-15 09:22:23 +0100598 log_info("fio: waiting for connection\n");
Jens Axboe5fdd1242007-02-11 04:00:37 +0100599
Jens Axboe371d4562009-01-19 10:17:06 +0100600 if (poll_wait(td, nd->listenfd, POLLIN) < 0)
Jens Axboe859088d2012-11-29 20:02:50 +0100601 goto err;
Jens Axboe5fdd1242007-02-11 04:00:37 +0100602
Jens Axboe371d4562009-01-19 10:17:06 +0100603 f->fd = accept(nd->listenfd, (struct sockaddr *) &nd->addr, &socklen);
604 if (f->fd < 0) {
605 td_verror(td, errno, "accept");
Jens Axboe859088d2012-11-29 20:02:50 +0100606 goto err;
Jens Axboe5fdd1242007-02-11 04:00:37 +0100607 }
608
Jens Axboe1eafa372013-01-31 10:19:51 +0100609#ifdef CONFIG_TCP_NODELAY
Steven Noonan70a78782012-11-28 14:52:36 -0800610 if (o->nodelay && o->proto == FIO_TYPE_TCP) {
Jens Axboe6264c7a2013-02-28 08:24:23 +0100611 int optval = 1;
612
Jens Axboe26e594a2013-01-30 21:52:37 +0100613 if (setsockopt(f->fd, IPPROTO_TCP, TCP_NODELAY, (void *) &optval, sizeof(int)) < 0) {
Steven Noonan70a78782012-11-28 14:52:36 -0800614 log_err("fio: cannot set TCP_NODELAY option on socket (%s), disable with 'nodelay=0'\n", strerror(errno));
615 return 1;
616 }
617 }
Jens Axboe1eafa372013-01-31 10:19:51 +0100618#endif
Steven Noonan70a78782012-11-28 14:52:36 -0800619
Jens Axboe0cae16f2012-11-30 16:22:31 +0100620 reset_all_stats(td);
Jens Axboe859088d2012-11-29 20:02:50 +0100621 td_set_runstate(td, state);
Jens Axboe5fdd1242007-02-11 04:00:37 +0100622 return 0;
Jens Axboe859088d2012-11-29 20:02:50 +0100623err:
624 td_set_runstate(td, state);
625 return 1;
Jens Axboeb5af8292007-03-08 12:43:13 +0100626}
627
Jens Axboe664fb3b2009-01-19 13:26:36 +0100628static void fio_netio_udp_close(struct thread_data *td, struct fio_file *f)
629{
630 struct netio_data *nd = td->io_ops->data;
631 struct udp_close_msg msg;
Jens Axboe62b38922009-05-11 10:37:33 +0200632 struct sockaddr *to = (struct sockaddr *) &nd->addr;
Jens Axboe664fb3b2009-01-19 13:26:36 +0100633 int ret;
634
Jens Axboeb96d2432012-11-30 08:27:46 +0100635 msg.magic = htonl(FIO_LINK_OPEN_CLOSE_MAGIC);
Jens Axboe664fb3b2009-01-19 13:26:36 +0100636 msg.cmd = htonl(FIO_LINK_CLOSE);
637
Jens Axboe1f819912013-01-23 17:21:41 -0700638 ret = sendto(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to,
Jens Axboe664fb3b2009-01-19 13:26:36 +0100639 sizeof(nd->addr));
640 if (ret < 0)
641 td_verror(td, errno, "sendto udp link close");
642}
643
644static int fio_netio_close_file(struct thread_data *td, struct fio_file *f)
645{
Steven Langde890a12011-11-09 14:03:34 +0100646 struct netio_options *o = td->eo;
Jens Axboe664fb3b2009-01-19 13:26:36 +0100647
648 /*
649 * If this is an UDP connection, notify the receiver that we are
650 * closing down the link
651 */
Steven Langde890a12011-11-09 14:03:34 +0100652 if (o->proto == FIO_TYPE_UDP)
Jens Axboe664fb3b2009-01-19 13:26:36 +0100653 fio_netio_udp_close(td, f);
654
655 return generic_close_file(td, f);
656}
657
Jens Axboeb96d2432012-11-30 08:27:46 +0100658static int fio_netio_udp_recv_open(struct thread_data *td, struct fio_file *f)
659{
660 struct netio_data *nd = td->io_ops->data;
661 struct udp_close_msg msg;
662 struct sockaddr *to = (struct sockaddr *) &nd->addr;
Jens Axboe67bf9822013-01-10 11:23:19 +0100663 socklen_t len = sizeof(nd->addr);
Jens Axboeb96d2432012-11-30 08:27:46 +0100664 int ret;
665
Jens Axboe1f819912013-01-23 17:21:41 -0700666 ret = recvfrom(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to, &len);
Jens Axboeb96d2432012-11-30 08:27:46 +0100667 if (ret < 0) {
Shawn Bohreree7062f2013-07-19 13:24:09 -0500668 td_verror(td, errno, "recvfrom udp link open");
Jens Axboeb96d2432012-11-30 08:27:46 +0100669 return ret;
670 }
671
672 if (ntohl(msg.magic) != FIO_LINK_OPEN_CLOSE_MAGIC ||
673 ntohl(msg.cmd) != FIO_LINK_OPEN) {
674 log_err("fio: bad udp open magic %x/%x\n", ntohl(msg.magic),
675 ntohl(msg.cmd));
676 return -1;
677 }
678
679 return 0;
680}
681
682static int fio_netio_udp_send_open(struct thread_data *td, struct fio_file *f)
683{
684 struct netio_data *nd = td->io_ops->data;
685 struct udp_close_msg msg;
686 struct sockaddr *to = (struct sockaddr *) &nd->addr;
687 int ret;
688
689 msg.magic = htonl(FIO_LINK_OPEN_CLOSE_MAGIC);
690 msg.cmd = htonl(FIO_LINK_OPEN);
691
Jens Axboe1f819912013-01-23 17:21:41 -0700692 ret = sendto(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to,
Jens Axboeb96d2432012-11-30 08:27:46 +0100693 sizeof(nd->addr));
694 if (ret < 0) {
695 td_verror(td, errno, "sendto udp link open");
696 return ret;
697 }
698
699 return 0;
700}
701
702static int fio_netio_open_file(struct thread_data *td, struct fio_file *f)
703{
704 int ret;
705 struct netio_options *o = td->eo;
706
707 if (o->listen)
708 ret = fio_netio_accept(td, f);
709 else
710 ret = fio_netio_connect(td, f);
711
712 if (ret) {
713 f->fd = -1;
714 return ret;
715 }
716
717 if (o->proto == FIO_TYPE_UDP) {
718 if (td_write(td))
719 ret = fio_netio_udp_send_open(td, f);
720 else {
721 int state;
722
723 state = td->runstate;
724 td_set_runstate(td, TD_SETTING_UP);
725 ret = fio_netio_udp_recv_open(td, f);
726 td_set_runstate(td, state);
727 }
728 }
729
730 if (ret)
731 fio_netio_close_file(td, f);
732
733 return ret;
734}
735
Jens Axboe0fd666b2011-10-06 20:08:53 +0200736static int fio_netio_setup_connect_inet(struct thread_data *td,
737 const char *host, unsigned short port)
Jens Axboeb5af8292007-03-08 12:43:13 +0100738{
739 struct netio_data *nd = td->io_ops->data;
740
Jens Axboe166dce42012-11-29 14:35:33 +0100741 if (!host) {
742 log_err("fio: connect with no host to connect to.\n");
743 if (td_read(td))
744 log_err("fio: did you forget to set 'listen'?\n");
745
746 td_verror(td, EINVAL, "no hostname= set");
747 return 1;
748 }
749
Jens Axboeb5af8292007-03-08 12:43:13 +0100750 nd->addr.sin_family = AF_INET;
751 nd->addr.sin_port = htons(port);
752
753 if (inet_aton(host, &nd->addr.sin_addr) != 1) {
754 struct hostent *hent;
755
756 hent = gethostbyname(host);
757 if (!hent) {
758 td_verror(td, errno, "gethostbyname");
759 return 1;
760 }
761
762 memcpy(&nd->addr.sin_addr, hent->h_addr, 4);
763 }
764
765 return 0;
766}
767
Jens Axboe0fd666b2011-10-06 20:08:53 +0200768static int fio_netio_setup_connect_unix(struct thread_data *td,
769 const char *path)
770{
771 struct netio_data *nd = td->io_ops->data;
772 struct sockaddr_un *soun = &nd->addr_un;
773
774 soun->sun_family = AF_UNIX;
775 strcpy(soun->sun_path, path);
776 return 0;
777}
778
Steven Langde890a12011-11-09 14:03:34 +0100779static int fio_netio_setup_connect(struct thread_data *td)
Jens Axboe0fd666b2011-10-06 20:08:53 +0200780{
Steven Langde890a12011-11-09 14:03:34 +0100781 struct netio_options *o = td->eo;
Jens Axboe0fd666b2011-10-06 20:08:53 +0200782
Steven Langde890a12011-11-09 14:03:34 +0100783 if (o->proto == FIO_TYPE_UDP || o->proto == FIO_TYPE_TCP)
784 return fio_netio_setup_connect_inet(td, td->o.filename,o->port);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200785 else
Steven Langde890a12011-11-09 14:03:34 +0100786 return fio_netio_setup_connect_unix(td, td->o.filename);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200787}
788
789static int fio_netio_setup_listen_unix(struct thread_data *td, const char *path)
790{
791 struct netio_data *nd = td->io_ops->data;
792 struct sockaddr_un *addr = &nd->addr_un;
793 mode_t mode;
794 int len, fd;
795
796 fd = socket(AF_UNIX, SOCK_STREAM, 0);
797 if (fd < 0) {
798 log_err("fio: socket: %s\n", strerror(errno));
799 return -1;
800 }
801
802 mode = umask(000);
803
804 memset(addr, 0, sizeof(*addr));
805 addr->sun_family = AF_UNIX;
806 strcpy(addr->sun_path, path);
807 unlink(path);
808
809 len = sizeof(addr->sun_family) + strlen(path) + 1;
810
811 if (bind(fd, (struct sockaddr *) addr, len) < 0) {
812 log_err("fio: bind: %s\n", strerror(errno));
Jens Axboeb94cba42011-10-06 21:27:10 +0200813 close(fd);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200814 return -1;
815 }
816
817 umask(mode);
818 nd->listenfd = fd;
819 return 0;
820}
821
822static int fio_netio_setup_listen_inet(struct thread_data *td, short port)
Jens Axboeb5af8292007-03-08 12:43:13 +0100823{
824 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100825 struct netio_options *o = td->eo;
Shawn Bohrerb511c9a2013-07-19 13:24:06 -0500826 struct ip_mreq mr;
827 struct sockaddr_in sin;
Jens Axboe414c2a32009-01-16 13:21:15 +0100828 int fd, opt, type;
Jens Axboeed92ac02007-02-06 14:43:52 +0100829
Shawn Bohrerb511c9a2013-07-19 13:24:06 -0500830 memset(&sin, 0, sizeof(sin));
Steven Langde890a12011-11-09 14:03:34 +0100831 if (o->proto == FIO_TYPE_TCP)
Jens Axboe414c2a32009-01-16 13:21:15 +0100832 type = SOCK_STREAM;
833 else
834 type = SOCK_DGRAM;
835
Jens Axboe0fd666b2011-10-06 20:08:53 +0200836 fd = socket(AF_INET, type, 0);
Jens Axboeed92ac02007-02-06 14:43:52 +0100837 if (fd < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100838 td_verror(td, errno, "socket");
Jens Axboeed92ac02007-02-06 14:43:52 +0100839 return 1;
840 }
841
842 opt = 1;
Jens Axboe26e594a2013-01-30 21:52:37 +0100843 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &opt, sizeof(opt)) < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100844 td_verror(td, errno, "setsockopt");
Shawn Bohrer4a93dec2013-07-19 13:24:10 -0500845 close(fd);
Jens Axboeed92ac02007-02-06 14:43:52 +0100846 return 1;
847 }
Jens Axboe6bedbfa2007-02-07 09:54:40 +0100848#ifdef SO_REUSEPORT
Jens Axboe26e594a2013-01-30 21:52:37 +0100849 if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (void *) &opt, sizeof(opt)) < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100850 td_verror(td, errno, "setsockopt");
Shawn Bohrer4a93dec2013-07-19 13:24:10 -0500851 close(fd);
Jens Axboe6bedbfa2007-02-07 09:54:40 +0100852 return 1;
853 }
854#endif
Jens Axboeed92ac02007-02-06 14:43:52 +0100855
Shawn Bohrerb511c9a2013-07-19 13:24:06 -0500856 if (td->o.filename){
857 if(o->proto != FIO_TYPE_UDP ||
858 !fio_netio_is_multicast(td->o.filename)) {
859 log_err("fio: hostname not valid for non-multicast inbound network IO\n");
860 close(fd);
861 return 1;
862 }
863
864 inet_aton(td->o.filename, &sin.sin_addr);
865
866 mr.imr_multiaddr = sin.sin_addr;
Shawn Bohrerb93b6a22013-07-19 13:24:07 -0500867 if (o->interface) {
868 if (inet_aton(o->interface, &mr.imr_interface) == 0) {
869 log_err("fio: interface not valid interface IP\n");
870 close(fd);
871 return 1;
872 }
873 } else {
874 mr.imr_interface.s_addr = htonl(INADDR_ANY);
875 }
Shawn Bohrerb511c9a2013-07-19 13:24:06 -0500876 if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr)) < 0) {
877 td_verror(td, errno, "setsockopt IP_ADD_MEMBERSHIP");
878 close(fd);
879 return 1;
880 }
881 }
882
Jens Axboeb5af8292007-03-08 12:43:13 +0100883 nd->addr.sin_family = AF_INET;
Shawn Bohrerb511c9a2013-07-19 13:24:06 -0500884 nd->addr.sin_addr.s_addr = sin.sin_addr.s_addr ? sin.sin_addr.s_addr : htonl(INADDR_ANY);
Jens Axboeb5af8292007-03-08 12:43:13 +0100885 nd->addr.sin_port = htons(port);
Jens Axboeed92ac02007-02-06 14:43:52 +0100886
Jens Axboeb5af8292007-03-08 12:43:13 +0100887 if (bind(fd, (struct sockaddr *) &nd->addr, sizeof(nd->addr)) < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100888 td_verror(td, errno, "bind");
Jens Axboeed92ac02007-02-06 14:43:52 +0100889 return 1;
890 }
Jens Axboe0fd666b2011-10-06 20:08:53 +0200891
892 nd->listenfd = fd;
893 return 0;
894}
895
Steven Langde890a12011-11-09 14:03:34 +0100896static int fio_netio_setup_listen(struct thread_data *td)
Jens Axboe0fd666b2011-10-06 20:08:53 +0200897{
898 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100899 struct netio_options *o = td->eo;
Jens Axboe0fd666b2011-10-06 20:08:53 +0200900 int ret;
901
Steven Langde890a12011-11-09 14:03:34 +0100902 if (o->proto == FIO_TYPE_UDP || o->proto == FIO_TYPE_TCP)
903 ret = fio_netio_setup_listen_inet(td, o->port);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200904 else
Steven Langde890a12011-11-09 14:03:34 +0100905 ret = fio_netio_setup_listen_unix(td, td->o.filename);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200906
907 if (ret)
908 return ret;
Steven Langde890a12011-11-09 14:03:34 +0100909 if (o->proto == FIO_TYPE_UDP)
Jens Axboe0fd666b2011-10-06 20:08:53 +0200910 return 0;
911
912 if (listen(nd->listenfd, 10) < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100913 td_verror(td, errno, "listen");
Jens Axboe0fd666b2011-10-06 20:08:53 +0200914 nd->listenfd = -1;
Jens Axboeed92ac02007-02-06 14:43:52 +0100915 return 1;
916 }
917
Jens Axboeb5af8292007-03-08 12:43:13 +0100918 return 0;
Jens Axboeed92ac02007-02-06 14:43:52 +0100919}
920
Jens Axboe9bec88e2007-03-02 08:55:48 +0100921static int fio_netio_init(struct thread_data *td)
Jens Axboeed92ac02007-02-06 14:43:52 +0100922{
Steven Langde890a12011-11-09 14:03:34 +0100923 struct netio_options *o = td->eo;
Jens Axboeaf52b342007-03-13 10:07:47 +0100924 int ret;
Jens Axboeed92ac02007-02-06 14:43:52 +0100925
Bruce Cran3f457be2012-10-10 13:37:41 +0100926#ifdef WIN32
927 WSADATA wsd;
928 WSAStartup(MAKEWORD(2,2), &wsd);
929#endif
930
Jens Axboe16d55aa2007-05-22 09:21:37 +0200931 if (td_random(td)) {
932 log_err("fio: network IO can't be random\n");
933 return 1;
934 }
Jens Axboeed92ac02007-02-06 14:43:52 +0100935
Steven Langde890a12011-11-09 14:03:34 +0100936 if (o->proto == FIO_TYPE_UNIX && o->port) {
937 log_err("fio: network IO port not valid with unix socket\n");
938 return 1;
939 } else if (o->proto != FIO_TYPE_UNIX && !o->port) {
940 log_err("fio: network IO requires port for tcp or udp\n");
941 return 1;
Jens Axboe414c2a32009-01-16 13:21:15 +0100942 }
Jens Axboe0fd666b2011-10-06 20:08:53 +0200943
Steven Langde890a12011-11-09 14:03:34 +0100944 if (o->proto != FIO_TYPE_TCP) {
945 if (o->listen) {
Jens Axboe9b986062011-12-19 08:57:18 +0100946 log_err("fio: listen only valid for TCP proto IO\n");
947 return 1;
Steven Langde890a12011-11-09 14:03:34 +0100948 }
949 if (td_rw(td)) {
Jens Axboe9b986062011-12-19 08:57:18 +0100950 log_err("fio: datagram network connections must be"
Steven Langde890a12011-11-09 14:03:34 +0100951 " read OR write\n");
Jens Axboe9b986062011-12-19 08:57:18 +0100952 return 1;
953 }
954 if (o->proto == FIO_TYPE_UNIX && !td->o.filename) {
955 log_err("fio: UNIX sockets need host/filename\n");
956 return 1;
Steven Langde890a12011-11-09 14:03:34 +0100957 }
958 o->listen = td_read(td);
959 }
960
Steven Langde890a12011-11-09 14:03:34 +0100961 if (o->listen)
962 ret = fio_netio_setup_listen(td);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200963 else
Steven Langde890a12011-11-09 14:03:34 +0100964 ret = fio_netio_setup_connect(td);
Jens Axboeed92ac02007-02-06 14:43:52 +0100965
Jens Axboe7bb48f82007-03-27 15:30:28 +0200966 return ret;
Jens Axboeed92ac02007-02-06 14:43:52 +0100967}
968
Jens Axboeb5af8292007-03-08 12:43:13 +0100969static void fio_netio_cleanup(struct thread_data *td)
Jens Axboe9bec88e2007-03-02 08:55:48 +0100970{
Jens Axboeb5af8292007-03-08 12:43:13 +0100971 struct netio_data *nd = td->io_ops->data;
972
973 if (nd) {
Jens Axboe64b24cd2007-06-24 21:28:39 +0200974 if (nd->listenfd != -1)
975 close(nd->listenfd);
976 if (nd->pipes[0] != -1)
977 close(nd->pipes[0]);
978 if (nd->pipes[1] != -1)
979 close(nd->pipes[1]);
980
Jens Axboeb5af8292007-03-08 12:43:13 +0100981 free(nd);
Jens Axboeb5af8292007-03-08 12:43:13 +0100982 }
983}
984
985static int fio_netio_setup(struct thread_data *td)
986{
Jens Axboe7bb48f82007-03-27 15:30:28 +0200987 struct netio_data *nd;
Jens Axboeb5af8292007-03-08 12:43:13 +0100988
Steven Langde890a12011-11-09 14:03:34 +0100989 if (!td->files_index) {
990 add_file(td, td->o.filename ?: "net");
991 td->o.nr_files = td->o.nr_files ?: 1;
992 }
993
Jens Axboe7bb48f82007-03-27 15:30:28 +0200994 if (!td->io_ops->data) {
995 nd = malloc(sizeof(*nd));;
996
997 memset(nd, 0, sizeof(*nd));
998 nd->listenfd = -1;
Jens Axboe64b24cd2007-06-24 21:28:39 +0200999 nd->pipes[0] = nd->pipes[1] = -1;
Jens Axboe7bb48f82007-03-27 15:30:28 +02001000 td->io_ops->data = nd;
Jens Axboe7bb48f82007-03-27 15:30:28 +02001001 }
1002
Jens Axboe9bec88e2007-03-02 08:55:48 +01001003 return 0;
1004}
1005
Jens Axboe36d80bc2012-11-30 21:46:06 +01001006static void fio_netio_terminate(struct thread_data *td)
1007{
1008 kill(td->pid, SIGUSR2);
1009}
1010
Jens Axboe67bf9822013-01-10 11:23:19 +01001011#ifdef CONFIG_LINUX_SPLICE
Jens Axboe9cce02e2007-06-22 15:42:21 +02001012static int fio_netio_setup_splice(struct thread_data *td)
1013{
1014 struct netio_data *nd;
1015
1016 fio_netio_setup(td);
1017
1018 nd = td->io_ops->data;
1019 if (nd) {
1020 if (pipe(nd->pipes) < 0)
1021 return 1;
1022
1023 nd->use_splice = 1;
1024 return 0;
1025 }
1026
1027 return 1;
1028}
1029
Jens Axboe5921e802008-05-30 15:02:38 +02001030static struct ioengine_ops ioengine_splice = {
Steven Langde890a12011-11-09 14:03:34 +01001031 .name = "netsplice",
1032 .version = FIO_IOOPS_VERSION,
1033 .prep = fio_netio_prep,
1034 .queue = fio_netio_queue,
1035 .setup = fio_netio_setup_splice,
1036 .init = fio_netio_init,
1037 .cleanup = fio_netio_cleanup,
1038 .open_file = fio_netio_open_file,
Jens Axboe36d80bc2012-11-30 21:46:06 +01001039 .close_file = fio_netio_close_file,
1040 .terminate = fio_netio_terminate,
Steven Langde890a12011-11-09 14:03:34 +01001041 .options = options,
1042 .option_struct_size = sizeof(struct netio_options),
1043 .flags = FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR |
Jens Axboe36d80bc2012-11-30 21:46:06 +01001044 FIO_PIPEIO,
Jens Axboe5921e802008-05-30 15:02:38 +02001045};
1046#endif
1047
Jens Axboe9cce02e2007-06-22 15:42:21 +02001048static struct ioengine_ops ioengine_rw = {
Steven Langde890a12011-11-09 14:03:34 +01001049 .name = "net",
1050 .version = FIO_IOOPS_VERSION,
1051 .prep = fio_netio_prep,
1052 .queue = fio_netio_queue,
1053 .setup = fio_netio_setup,
1054 .init = fio_netio_init,
1055 .cleanup = fio_netio_cleanup,
1056 .open_file = fio_netio_open_file,
1057 .close_file = fio_netio_close_file,
Jens Axboe36d80bc2012-11-30 21:46:06 +01001058 .terminate = fio_netio_terminate,
Steven Langde890a12011-11-09 14:03:34 +01001059 .options = options,
1060 .option_struct_size = sizeof(struct netio_options),
1061 .flags = FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR |
Steven Noonanad705bc2013-04-08 15:05:25 -07001062 FIO_PIPEIO | FIO_BIT_BASED,
Jens Axboeed92ac02007-02-06 14:43:52 +01001063};
1064
Steven Langde890a12011-11-09 14:03:34 +01001065static int str_hostname_cb(void *data, const char *input)
1066{
1067 struct netio_options *o = data;
1068
1069 if (o->td->o.filename)
1070 free(o->td->o.filename);
1071 o->td->o.filename = strdup(input);
1072 return 0;
1073}
1074
Jens Axboeed92ac02007-02-06 14:43:52 +01001075static void fio_init fio_netio_register(void)
1076{
Jens Axboe9cce02e2007-06-22 15:42:21 +02001077 register_ioengine(&ioengine_rw);
Jens Axboe67bf9822013-01-10 11:23:19 +01001078#ifdef CONFIG_LINUX_SPLICE
Jens Axboe9cce02e2007-06-22 15:42:21 +02001079 register_ioengine(&ioengine_splice);
Jens Axboe5921e802008-05-30 15:02:38 +02001080#endif
Jens Axboeed92ac02007-02-06 14:43:52 +01001081}
1082
1083static void fio_exit fio_netio_unregister(void)
1084{
Jens Axboe9cce02e2007-06-22 15:42:21 +02001085 unregister_ioengine(&ioengine_rw);
Jens Axboe67bf9822013-01-10 11:23:19 +01001086#ifdef CONFIG_LINUX_SPLICE
Jens Axboe9cce02e2007-06-22 15:42:21 +02001087 unregister_ioengine(&ioengine_splice);
Jens Axboe5921e802008-05-30 15:02:38 +02001088#endif
Jens Axboeed92ac02007-02-06 14:43:52 +01001089}