blob: b2c1283454090ed42554908c6642dd130e37cc59 [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
Shawn Bohrerb511c9a2013-07-19 13:24:06 -0500167static int fio_netio_is_multicast(const char *mcaddr)
168{
169 in_addr_t addr = inet_network(mcaddr);
170 if (addr == -1)
171 return 0;
172
173 if (inet_network("224.0.0.0") <= addr &&
174 inet_network("239.255.255.255") >= addr)
175 return 1;
176
177 return 0;
178}
179
180
Jens Axboeed92ac02007-02-06 14:43:52 +0100181static int fio_netio_prep(struct thread_data *td, struct io_u *io_u)
182{
Steven Langde890a12011-11-09 14:03:34 +0100183 struct netio_options *o = td->eo;
Jens Axboeed92ac02007-02-06 14:43:52 +0100184
Jens Axboe7a6499d2007-02-07 09:35:29 +0100185 /*
186 * Make sure we don't see spurious reads to a receiver, and vice versa
187 */
Steven Langde890a12011-11-09 14:03:34 +0100188 if (o->proto == FIO_TYPE_TCP)
189 return 0;
190
191 if ((o->listen && io_u->ddir == DDIR_WRITE) ||
192 (!o->listen && io_u->ddir == DDIR_READ)) {
Jens Axboee1161c32007-02-22 19:36:48 +0100193 td_verror(td, EINVAL, "bad direction");
Jens Axboe7a6499d2007-02-07 09:35:29 +0100194 return 1;
Jens Axboeed92ac02007-02-06 14:43:52 +0100195 }
Bruce Cran3f457be2012-10-10 13:37:41 +0100196
Jens Axboef85ac252008-03-01 18:09:49 +0100197 return 0;
Jens Axboeed92ac02007-02-06 14:43:52 +0100198}
199
Jens Axboe67bf9822013-01-10 11:23:19 +0100200#ifdef CONFIG_LINUX_SPLICE
Jens Axboecd963e12007-06-24 21:41:46 +0200201static int splice_io_u(int fdin, int fdout, unsigned int len)
Jens Axboe9cce02e2007-06-22 15:42:21 +0200202{
Jens Axboe9cce02e2007-06-22 15:42:21 +0200203 int bytes = 0;
204
205 while (len) {
Jens Axboecd963e12007-06-24 21:41:46 +0200206 int ret = splice(fdin, NULL, fdout, NULL, len, 0);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200207
208 if (ret < 0) {
209 if (!bytes)
210 bytes = ret;
211
212 break;
213 } else if (!ret)
214 break;
215
216 bytes += ret;
Jens Axboef657a2f2007-06-22 20:40:10 +0200217 len -= ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200218 }
219
220 return bytes;
221}
222
223/*
Jens Axboecd963e12007-06-24 21:41:46 +0200224 * Receive bytes from a socket and fill them into the internal pipe
225 */
226static int splice_in(struct thread_data *td, struct io_u *io_u)
227{
228 struct netio_data *nd = td->io_ops->data;
229
230 return splice_io_u(io_u->file->fd, nd->pipes[1], io_u->xfer_buflen);
231}
232
233/*
Jens Axboe9cce02e2007-06-22 15:42:21 +0200234 * Transmit 'len' bytes from the internal pipe
235 */
236static int splice_out(struct thread_data *td, struct io_u *io_u,
237 unsigned int len)
238{
239 struct netio_data *nd = td->io_ops->data;
Jens Axboecd963e12007-06-24 21:41:46 +0200240
241 return splice_io_u(nd->pipes[0], io_u->file->fd, len);
242}
243
244static int vmsplice_io_u(struct io_u *io_u, int fd, unsigned int len)
245{
246 struct iovec iov = {
247 .iov_base = io_u->xfer_buf,
248 .iov_len = len,
249 };
Jens Axboe9cce02e2007-06-22 15:42:21 +0200250 int bytes = 0;
251
Jens Axboecd963e12007-06-24 21:41:46 +0200252 while (iov.iov_len) {
253 int ret = vmsplice(fd, &iov, 1, SPLICE_F_MOVE);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200254
255 if (ret < 0) {
256 if (!bytes)
257 bytes = ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200258 break;
259 } else if (!ret)
260 break;
261
Jens Axboecd963e12007-06-24 21:41:46 +0200262 iov.iov_len -= ret;
263 iov.iov_base += ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200264 bytes += ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200265 }
266
267 return bytes;
Jens Axboecd963e12007-06-24 21:41:46 +0200268
Jens Axboe9cce02e2007-06-22 15:42:21 +0200269}
270
271/*
272 * vmsplice() pipe to io_u buffer
273 */
274static int vmsplice_io_u_out(struct thread_data *td, struct io_u *io_u,
275 unsigned int len)
276{
277 struct netio_data *nd = td->io_ops->data;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200278
Jens Axboecd963e12007-06-24 21:41:46 +0200279 return vmsplice_io_u(io_u, nd->pipes[0], len);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200280}
281
282/*
283 * vmsplice() io_u to pipe
284 */
285static int vmsplice_io_u_in(struct thread_data *td, struct io_u *io_u)
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[1], io_u->xfer_buflen);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200290}
291
Jens Axboecd963e12007-06-24 21:41:46 +0200292/*
293 * splice receive - transfer socket data into a pipe using splice, then map
294 * that pipe data into the io_u using vmsplice.
295 */
Jens Axboe9cce02e2007-06-22 15:42:21 +0200296static int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
297{
298 int ret;
299
300 ret = splice_in(td, io_u);
Jens Axboecd963e12007-06-24 21:41:46 +0200301 if (ret > 0)
302 return vmsplice_io_u_out(td, io_u, ret);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200303
Jens Axboecd963e12007-06-24 21:41:46 +0200304 return ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200305}
306
Jens Axboecd963e12007-06-24 21:41:46 +0200307/*
308 * splice transmit - map data from the io_u into a pipe by using vmsplice,
309 * then transfer that pipe to a socket using splice.
310 */
Jens Axboe9cce02e2007-06-22 15:42:21 +0200311static int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
312{
313 int ret;
314
315 ret = vmsplice_io_u_in(td, io_u);
Jens Axboecd963e12007-06-24 21:41:46 +0200316 if (ret > 0)
317 return splice_out(td, io_u, ret);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200318
Jens Axboecd963e12007-06-24 21:41:46 +0200319 return ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200320}
Jens Axboe5921e802008-05-30 15:02:38 +0200321#else
322static int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
323{
Jens Axboeaf8771b2008-05-30 22:58:28 +0200324 errno = EOPNOTSUPP;
Jens Axboe5921e802008-05-30 15:02:38 +0200325 return -1;
326}
327
328static int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
329{
Jens Axboeaf8771b2008-05-30 22:58:28 +0200330 errno = EOPNOTSUPP;
Jens Axboe5921e802008-05-30 15:02:38 +0200331 return -1;
332}
333#endif
Jens Axboe9cce02e2007-06-22 15:42:21 +0200334
335static int fio_netio_send(struct thread_data *td, struct io_u *io_u)
336{
Jens Axboe414c2a32009-01-16 13:21:15 +0100337 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100338 struct netio_options *o = td->eo;
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100339 int ret, flags = 0;
Jens Axboe371d4562009-01-19 10:17:06 +0100340
Jens Axboe664fb3b2009-01-19 13:26:36 +0100341 do {
Steven Langde890a12011-11-09 14:03:34 +0100342 if (o->proto == FIO_TYPE_UDP) {
Jens Axboe62b38922009-05-11 10:37:33 +0200343 struct sockaddr *to = (struct sockaddr *) &nd->addr;
344
Jens Axboe664fb3b2009-01-19 13:26:36 +0100345 ret = sendto(io_u->file->fd, io_u->xfer_buf,
Jens Axboe62b38922009-05-11 10:37:33 +0200346 io_u->xfer_buflen, flags, to,
347 sizeof(*to));
Jens Axboe664fb3b2009-01-19 13:26:36 +0100348 } else {
349 /*
350 * if we are going to write more, set MSG_MORE
351 */
Jens Axboe5921e802008-05-30 15:02:38 +0200352#ifdef MSG_MORE
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100353 if ((td->this_io_bytes[DDIR_WRITE] + io_u->xfer_buflen <
354 td->o.size) && !o->pingpong)
Jens Axboe664fb3b2009-01-19 13:26:36 +0100355 flags |= MSG_MORE;
Jens Axboe5921e802008-05-30 15:02:38 +0200356#endif
Jens Axboe664fb3b2009-01-19 13:26:36 +0100357 ret = send(io_u->file->fd, io_u->xfer_buf,
358 io_u->xfer_buflen, flags);
359 }
360 if (ret > 0)
361 break;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200362
Jens Axboe664fb3b2009-01-19 13:26:36 +0100363 ret = poll_wait(td, io_u->file->fd, POLLOUT);
364 if (ret <= 0)
365 break;
Jens Axboe664fb3b2009-01-19 13:26:36 +0100366 } while (1);
367
368 return ret;
369}
370
371static int is_udp_close(struct io_u *io_u, int len)
372{
373 struct udp_close_msg *msg;
374
375 if (len != sizeof(struct udp_close_msg))
376 return 0;
377
378 msg = io_u->xfer_buf;
Jens Axboeb96d2432012-11-30 08:27:46 +0100379 if (ntohl(msg->magic) != FIO_LINK_OPEN_CLOSE_MAGIC)
Jens Axboe664fb3b2009-01-19 13:26:36 +0100380 return 0;
381 if (ntohl(msg->cmd) != FIO_LINK_CLOSE)
382 return 0;
383
384 return 1;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200385}
386
Jens Axboe414c2a32009-01-16 13:21:15 +0100387static int fio_netio_recv(struct thread_data *td, struct io_u *io_u)
Jens Axboe9cce02e2007-06-22 15:42:21 +0200388{
Jens Axboe414c2a32009-01-16 13:21:15 +0100389 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100390 struct netio_options *o = td->eo;
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100391 int ret, flags = 0;
Jens Axboe371d4562009-01-19 10:17:06 +0100392
Jens Axboe664fb3b2009-01-19 13:26:36 +0100393 do {
Steven Langde890a12011-11-09 14:03:34 +0100394 if (o->proto == FIO_TYPE_UDP) {
Shawn Bohrerb511c9a2013-07-19 13:24:06 -0500395 socklen_t l;
396 socklen_t *len = &l;
397 struct sockaddr *from;
398
399 if (o->listen) {
400 from = (struct sockaddr *) &nd->addr;
401 *len = sizeof(nd->addr);
402 } else {
403 from = NULL;
404 len = NULL;
405 }
Jens Axboe9cce02e2007-06-22 15:42:21 +0200406
Jens Axboe664fb3b2009-01-19 13:26:36 +0100407 ret = recvfrom(io_u->file->fd, io_u->xfer_buf,
Shawn Bohrerb511c9a2013-07-19 13:24:06 -0500408 io_u->xfer_buflen, flags, from, len);
Jens Axboe664fb3b2009-01-19 13:26:36 +0100409 if (is_udp_close(io_u, ret)) {
410 td->done = 1;
411 return 0;
412 }
413 } else {
414 ret = recv(io_u->file->fd, io_u->xfer_buf,
415 io_u->xfer_buflen, flags);
416 }
417 if (ret > 0)
418 break;
Jens Axboe7d988f62012-11-29 19:57:35 +0100419 else if (!ret && (flags & MSG_WAITALL))
420 break;
Jens Axboe414c2a32009-01-16 13:21:15 +0100421
Jens Axboe664fb3b2009-01-19 13:26:36 +0100422 ret = poll_wait(td, io_u->file->fd, POLLIN);
423 if (ret <= 0)
424 break;
Jens Axboe664fb3b2009-01-19 13:26:36 +0100425 flags |= MSG_WAITALL;
426 } while (1);
427
428 return ret;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200429}
430
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100431static int __fio_netio_queue(struct thread_data *td, struct io_u *io_u,
432 enum fio_ddir ddir)
Jens Axboeed92ac02007-02-06 14:43:52 +0100433{
Jens Axboe9cce02e2007-06-22 15:42:21 +0200434 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100435 struct netio_options *o = td->eo;
Jens Axboe9cce02e2007-06-22 15:42:21 +0200436 int ret;
Jens Axboeed92ac02007-02-06 14:43:52 +0100437
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100438 if (ddir == DDIR_WRITE) {
Steven Langde890a12011-11-09 14:03:34 +0100439 if (!nd->use_splice || o->proto == FIO_TYPE_UDP ||
440 o->proto == FIO_TYPE_UNIX)
Jens Axboe9cce02e2007-06-22 15:42:21 +0200441 ret = fio_netio_send(td, io_u);
Jens Axboe9cce02e2007-06-22 15:42:21 +0200442 else
Jens Axboe414c2a32009-01-16 13:21:15 +0100443 ret = fio_netio_splice_out(td, io_u);
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100444 } else if (ddir == DDIR_READ) {
Steven Langde890a12011-11-09 14:03:34 +0100445 if (!nd->use_splice || o->proto == FIO_TYPE_UDP ||
446 o->proto == FIO_TYPE_UNIX)
Jens Axboe414c2a32009-01-16 13:21:15 +0100447 ret = fio_netio_recv(td, io_u);
448 else
449 ret = fio_netio_splice_in(td, io_u);
Jens Axboed4f12dd2007-02-08 12:59:02 +0100450 } else
Jens Axboe7a6499d2007-02-07 09:35:29 +0100451 ret = 0; /* must be a SYNC */
Jens Axboeed92ac02007-02-06 14:43:52 +0100452
Jens Axboecec6b552007-02-06 20:15:38 +0100453 if (ret != (int) io_u->xfer_buflen) {
Jens Axboe22819ec2007-02-18 07:47:14 +0100454 if (ret >= 0) {
Jens Axboecec6b552007-02-06 20:15:38 +0100455 io_u->resid = io_u->xfer_buflen - ret;
456 io_u->error = 0;
Jens Axboe36167d82007-02-18 05:41:31 +0100457 return FIO_Q_COMPLETED;
Jens Axboe414c2a32009-01-16 13:21:15 +0100458 } else {
459 int err = errno;
460
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100461 if (ddir == DDIR_WRITE && err == EMSGSIZE)
Jens Axboe414c2a32009-01-16 13:21:15 +0100462 return FIO_Q_BUSY;
463
464 io_u->error = err;
465 }
Jens Axboeed92ac02007-02-06 14:43:52 +0100466 }
467
Jens Axboe36167d82007-02-18 05:41:31 +0100468 if (io_u->error)
Jens Axboee1161c32007-02-22 19:36:48 +0100469 td_verror(td, io_u->error, "xfer");
Jens Axboeed92ac02007-02-06 14:43:52 +0100470
Jens Axboe36167d82007-02-18 05:41:31 +0100471 return FIO_Q_COMPLETED;
Jens Axboeed92ac02007-02-06 14:43:52 +0100472}
473
Jens Axboe6f73a7f2012-11-30 09:59:20 +0100474static int fio_netio_queue(struct thread_data *td, struct io_u *io_u)
475{
476 struct netio_options *o = td->eo;
477 int ret;
478
479 fio_ro_check(td, io_u);
480
481 ret = __fio_netio_queue(td, io_u, io_u->ddir);
482 if (!o->pingpong || ret != FIO_Q_COMPLETED)
483 return ret;
484
485 /*
486 * For ping-pong mode, receive or send reply as needed
487 */
488 if (td_read(td) && io_u->ddir == DDIR_READ)
489 ret = __fio_netio_queue(td, io_u, DDIR_WRITE);
490 else if (td_write(td) && io_u->ddir == DDIR_WRITE)
491 ret = __fio_netio_queue(td, io_u, DDIR_READ);
492
493 return ret;
494}
495
Jens Axboeb5af8292007-03-08 12:43:13 +0100496static int fio_netio_connect(struct thread_data *td, struct fio_file *f)
Jens Axboeed92ac02007-02-06 14:43:52 +0100497{
Jens Axboeb5af8292007-03-08 12:43:13 +0100498 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100499 struct netio_options *o = td->eo;
Jens Axboe6264c7a2013-02-28 08:24:23 +0100500 int type, domain;
Jens Axboeed92ac02007-02-06 14:43:52 +0100501
Steven Langde890a12011-11-09 14:03:34 +0100502 if (o->proto == FIO_TYPE_TCP) {
Jens Axboe0fd666b2011-10-06 20:08:53 +0200503 domain = AF_INET;
Jens Axboe414c2a32009-01-16 13:21:15 +0100504 type = SOCK_STREAM;
Steven Langde890a12011-11-09 14:03:34 +0100505 } else if (o->proto == FIO_TYPE_UDP) {
Jens Axboe0fd666b2011-10-06 20:08:53 +0200506 domain = AF_INET;
Jens Axboe414c2a32009-01-16 13:21:15 +0100507 type = SOCK_DGRAM;
Steven Langde890a12011-11-09 14:03:34 +0100508 } else if (o->proto == FIO_TYPE_UNIX) {
Jens Axboe0fd666b2011-10-06 20:08:53 +0200509 domain = AF_UNIX;
510 type = SOCK_STREAM;
511 } else {
Steven Langde890a12011-11-09 14:03:34 +0100512 log_err("fio: bad network type %d\n", o->proto);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200513 f->fd = -1;
514 return 1;
515 }
Jens Axboe414c2a32009-01-16 13:21:15 +0100516
Jens Axboe0fd666b2011-10-06 20:08:53 +0200517 f->fd = socket(domain, type, 0);
Jens Axboeb5af8292007-03-08 12:43:13 +0100518 if (f->fd < 0) {
519 td_verror(td, errno, "socket");
520 return 1;
Jens Axboeed92ac02007-02-06 14:43:52 +0100521 }
522
Jens Axboe1eafa372013-01-31 10:19:51 +0100523#ifdef CONFIG_TCP_NODELAY
Steven Noonan70a78782012-11-28 14:52:36 -0800524 if (o->nodelay && o->proto == FIO_TYPE_TCP) {
Jens Axboe6264c7a2013-02-28 08:24:23 +0100525 int optval = 1;
526
Jens Axboe26e594a2013-01-30 21:52:37 +0100527 if (setsockopt(f->fd, IPPROTO_TCP, TCP_NODELAY, (void *) &optval, sizeof(int)) < 0) {
Steven Noonan70a78782012-11-28 14:52:36 -0800528 log_err("fio: cannot set TCP_NODELAY option on socket (%s), disable with 'nodelay=0'\n", strerror(errno));
529 return 1;
530 }
531 }
Jens Axboe1eafa372013-01-31 10:19:51 +0100532#endif
Steven Noonan70a78782012-11-28 14:52:36 -0800533
Steven Langde890a12011-11-09 14:03:34 +0100534 if (o->proto == FIO_TYPE_UDP)
Jens Axboe414c2a32009-01-16 13:21:15 +0100535 return 0;
Steven Langde890a12011-11-09 14:03:34 +0100536 else if (o->proto == FIO_TYPE_TCP) {
Jens Axboe67bf9822013-01-10 11:23:19 +0100537 socklen_t len = sizeof(nd->addr);
Jens Axboe414c2a32009-01-16 13:21:15 +0100538
Jens Axboe0fd666b2011-10-06 20:08:53 +0200539 if (connect(f->fd, (struct sockaddr *) &nd->addr, len) < 0) {
540 td_verror(td, errno, "connect");
Jens Axboeb94cba42011-10-06 21:27:10 +0200541 close(f->fd);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200542 return 1;
543 }
544 } else {
545 struct sockaddr_un *addr = &nd->addr_un;
Jens Axboe67bf9822013-01-10 11:23:19 +0100546 socklen_t len;
Jens Axboe0fd666b2011-10-06 20:08:53 +0200547
548 len = sizeof(addr->sun_family) + strlen(addr->sun_path) + 1;
549
550 if (connect(f->fd, (struct sockaddr *) addr, len) < 0) {
551 td_verror(td, errno, "connect");
Jens Axboeb94cba42011-10-06 21:27:10 +0200552 close(f->fd);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200553 return 1;
554 }
Jens Axboeed92ac02007-02-06 14:43:52 +0100555 }
556
557 return 0;
Jens Axboeed92ac02007-02-06 14:43:52 +0100558}
559
Jens Axboeb5af8292007-03-08 12:43:13 +0100560static int fio_netio_accept(struct thread_data *td, struct fio_file *f)
Jens Axboe5fdd1242007-02-11 04:00:37 +0100561{
Jens Axboeb5af8292007-03-08 12:43:13 +0100562 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100563 struct netio_options *o = td->eo;
Jens Axboe67bf9822013-01-10 11:23:19 +0100564 socklen_t socklen = sizeof(nd->addr);
Jens Axboe6264c7a2013-02-28 08:24:23 +0100565 int state;
Jens Axboe5fdd1242007-02-11 04:00:37 +0100566
Steven Langde890a12011-11-09 14:03:34 +0100567 if (o->proto == FIO_TYPE_UDP) {
Jens Axboe414c2a32009-01-16 13:21:15 +0100568 f->fd = nd->listenfd;
569 return 0;
570 }
571
Jens Axboe859088d2012-11-29 20:02:50 +0100572 state = td->runstate;
573 td_set_runstate(td, TD_SETTING_UP);
574
Jens Axboe6d861442007-03-15 09:22:23 +0100575 log_info("fio: waiting for connection\n");
Jens Axboe5fdd1242007-02-11 04:00:37 +0100576
Jens Axboe371d4562009-01-19 10:17:06 +0100577 if (poll_wait(td, nd->listenfd, POLLIN) < 0)
Jens Axboe859088d2012-11-29 20:02:50 +0100578 goto err;
Jens Axboe5fdd1242007-02-11 04:00:37 +0100579
Jens Axboe371d4562009-01-19 10:17:06 +0100580 f->fd = accept(nd->listenfd, (struct sockaddr *) &nd->addr, &socklen);
581 if (f->fd < 0) {
582 td_verror(td, errno, "accept");
Jens Axboe859088d2012-11-29 20:02:50 +0100583 goto err;
Jens Axboe5fdd1242007-02-11 04:00:37 +0100584 }
585
Jens Axboe1eafa372013-01-31 10:19:51 +0100586#ifdef CONFIG_TCP_NODELAY
Steven Noonan70a78782012-11-28 14:52:36 -0800587 if (o->nodelay && o->proto == FIO_TYPE_TCP) {
Jens Axboe6264c7a2013-02-28 08:24:23 +0100588 int optval = 1;
589
Jens Axboe26e594a2013-01-30 21:52:37 +0100590 if (setsockopt(f->fd, IPPROTO_TCP, TCP_NODELAY, (void *) &optval, sizeof(int)) < 0) {
Steven Noonan70a78782012-11-28 14:52:36 -0800591 log_err("fio: cannot set TCP_NODELAY option on socket (%s), disable with 'nodelay=0'\n", strerror(errno));
592 return 1;
593 }
594 }
Jens Axboe1eafa372013-01-31 10:19:51 +0100595#endif
Steven Noonan70a78782012-11-28 14:52:36 -0800596
Jens Axboe0cae16f2012-11-30 16:22:31 +0100597 reset_all_stats(td);
Jens Axboe859088d2012-11-29 20:02:50 +0100598 td_set_runstate(td, state);
Jens Axboe5fdd1242007-02-11 04:00:37 +0100599 return 0;
Jens Axboe859088d2012-11-29 20:02:50 +0100600err:
601 td_set_runstate(td, state);
602 return 1;
Jens Axboeb5af8292007-03-08 12:43:13 +0100603}
604
Jens Axboe664fb3b2009-01-19 13:26:36 +0100605static void fio_netio_udp_close(struct thread_data *td, struct fio_file *f)
606{
607 struct netio_data *nd = td->io_ops->data;
608 struct udp_close_msg msg;
Jens Axboe62b38922009-05-11 10:37:33 +0200609 struct sockaddr *to = (struct sockaddr *) &nd->addr;
Jens Axboe664fb3b2009-01-19 13:26:36 +0100610 int ret;
611
Jens Axboeb96d2432012-11-30 08:27:46 +0100612 msg.magic = htonl(FIO_LINK_OPEN_CLOSE_MAGIC);
Jens Axboe664fb3b2009-01-19 13:26:36 +0100613 msg.cmd = htonl(FIO_LINK_CLOSE);
614
Jens Axboe1f819912013-01-23 17:21:41 -0700615 ret = sendto(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to,
Jens Axboe664fb3b2009-01-19 13:26:36 +0100616 sizeof(nd->addr));
617 if (ret < 0)
618 td_verror(td, errno, "sendto udp link close");
619}
620
621static int fio_netio_close_file(struct thread_data *td, struct fio_file *f)
622{
Steven Langde890a12011-11-09 14:03:34 +0100623 struct netio_options *o = td->eo;
Jens Axboe664fb3b2009-01-19 13:26:36 +0100624
625 /*
626 * If this is an UDP connection, notify the receiver that we are
627 * closing down the link
628 */
Steven Langde890a12011-11-09 14:03:34 +0100629 if (o->proto == FIO_TYPE_UDP)
Jens Axboe664fb3b2009-01-19 13:26:36 +0100630 fio_netio_udp_close(td, f);
631
632 return generic_close_file(td, f);
633}
634
Jens Axboeb96d2432012-11-30 08:27:46 +0100635static int fio_netio_udp_recv_open(struct thread_data *td, struct fio_file *f)
636{
637 struct netio_data *nd = td->io_ops->data;
638 struct udp_close_msg msg;
639 struct sockaddr *to = (struct sockaddr *) &nd->addr;
Jens Axboe67bf9822013-01-10 11:23:19 +0100640 socklen_t len = sizeof(nd->addr);
Jens Axboeb96d2432012-11-30 08:27:46 +0100641 int ret;
642
Jens Axboe1f819912013-01-23 17:21:41 -0700643 ret = recvfrom(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to, &len);
Jens Axboeb96d2432012-11-30 08:27:46 +0100644 if (ret < 0) {
Shawn Bohreree7062f2013-07-19 13:24:09 -0500645 td_verror(td, errno, "recvfrom udp link open");
Jens Axboeb96d2432012-11-30 08:27:46 +0100646 return ret;
647 }
648
649 if (ntohl(msg.magic) != FIO_LINK_OPEN_CLOSE_MAGIC ||
650 ntohl(msg.cmd) != FIO_LINK_OPEN) {
651 log_err("fio: bad udp open magic %x/%x\n", ntohl(msg.magic),
652 ntohl(msg.cmd));
653 return -1;
654 }
655
656 return 0;
657}
658
659static int fio_netio_udp_send_open(struct thread_data *td, struct fio_file *f)
660{
661 struct netio_data *nd = td->io_ops->data;
662 struct udp_close_msg msg;
663 struct sockaddr *to = (struct sockaddr *) &nd->addr;
664 int ret;
665
666 msg.magic = htonl(FIO_LINK_OPEN_CLOSE_MAGIC);
667 msg.cmd = htonl(FIO_LINK_OPEN);
668
Jens Axboe1f819912013-01-23 17:21:41 -0700669 ret = sendto(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to,
Jens Axboeb96d2432012-11-30 08:27:46 +0100670 sizeof(nd->addr));
671 if (ret < 0) {
672 td_verror(td, errno, "sendto udp link open");
673 return ret;
674 }
675
676 return 0;
677}
678
679static int fio_netio_open_file(struct thread_data *td, struct fio_file *f)
680{
681 int ret;
682 struct netio_options *o = td->eo;
683
684 if (o->listen)
685 ret = fio_netio_accept(td, f);
686 else
687 ret = fio_netio_connect(td, f);
688
689 if (ret) {
690 f->fd = -1;
691 return ret;
692 }
693
694 if (o->proto == FIO_TYPE_UDP) {
695 if (td_write(td))
696 ret = fio_netio_udp_send_open(td, f);
697 else {
698 int state;
699
700 state = td->runstate;
701 td_set_runstate(td, TD_SETTING_UP);
702 ret = fio_netio_udp_recv_open(td, f);
703 td_set_runstate(td, state);
704 }
705 }
706
707 if (ret)
708 fio_netio_close_file(td, f);
709
710 return ret;
711}
712
Jens Axboe0fd666b2011-10-06 20:08:53 +0200713static int fio_netio_setup_connect_inet(struct thread_data *td,
714 const char *host, unsigned short port)
Jens Axboeb5af8292007-03-08 12:43:13 +0100715{
716 struct netio_data *nd = td->io_ops->data;
717
Jens Axboe166dce42012-11-29 14:35:33 +0100718 if (!host) {
719 log_err("fio: connect with no host to connect to.\n");
720 if (td_read(td))
721 log_err("fio: did you forget to set 'listen'?\n");
722
723 td_verror(td, EINVAL, "no hostname= set");
724 return 1;
725 }
726
Jens Axboeb5af8292007-03-08 12:43:13 +0100727 nd->addr.sin_family = AF_INET;
728 nd->addr.sin_port = htons(port);
729
730 if (inet_aton(host, &nd->addr.sin_addr) != 1) {
731 struct hostent *hent;
732
733 hent = gethostbyname(host);
734 if (!hent) {
735 td_verror(td, errno, "gethostbyname");
736 return 1;
737 }
738
739 memcpy(&nd->addr.sin_addr, hent->h_addr, 4);
740 }
741
742 return 0;
743}
744
Jens Axboe0fd666b2011-10-06 20:08:53 +0200745static int fio_netio_setup_connect_unix(struct thread_data *td,
746 const char *path)
747{
748 struct netio_data *nd = td->io_ops->data;
749 struct sockaddr_un *soun = &nd->addr_un;
750
751 soun->sun_family = AF_UNIX;
752 strcpy(soun->sun_path, path);
753 return 0;
754}
755
Steven Langde890a12011-11-09 14:03:34 +0100756static int fio_netio_setup_connect(struct thread_data *td)
Jens Axboe0fd666b2011-10-06 20:08:53 +0200757{
Steven Langde890a12011-11-09 14:03:34 +0100758 struct netio_options *o = td->eo;
Jens Axboe0fd666b2011-10-06 20:08:53 +0200759
Steven Langde890a12011-11-09 14:03:34 +0100760 if (o->proto == FIO_TYPE_UDP || o->proto == FIO_TYPE_TCP)
761 return fio_netio_setup_connect_inet(td, td->o.filename,o->port);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200762 else
Steven Langde890a12011-11-09 14:03:34 +0100763 return fio_netio_setup_connect_unix(td, td->o.filename);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200764}
765
766static int fio_netio_setup_listen_unix(struct thread_data *td, const char *path)
767{
768 struct netio_data *nd = td->io_ops->data;
769 struct sockaddr_un *addr = &nd->addr_un;
770 mode_t mode;
771 int len, fd;
772
773 fd = socket(AF_UNIX, SOCK_STREAM, 0);
774 if (fd < 0) {
775 log_err("fio: socket: %s\n", strerror(errno));
776 return -1;
777 }
778
779 mode = umask(000);
780
781 memset(addr, 0, sizeof(*addr));
782 addr->sun_family = AF_UNIX;
783 strcpy(addr->sun_path, path);
784 unlink(path);
785
786 len = sizeof(addr->sun_family) + strlen(path) + 1;
787
788 if (bind(fd, (struct sockaddr *) addr, len) < 0) {
789 log_err("fio: bind: %s\n", strerror(errno));
Jens Axboeb94cba42011-10-06 21:27:10 +0200790 close(fd);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200791 return -1;
792 }
793
794 umask(mode);
795 nd->listenfd = fd;
796 return 0;
797}
798
799static int fio_netio_setup_listen_inet(struct thread_data *td, short port)
Jens Axboeb5af8292007-03-08 12:43:13 +0100800{
801 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100802 struct netio_options *o = td->eo;
Shawn Bohrerb511c9a2013-07-19 13:24:06 -0500803 struct ip_mreq mr;
804 struct sockaddr_in sin;
Jens Axboe414c2a32009-01-16 13:21:15 +0100805 int fd, opt, type;
Jens Axboeed92ac02007-02-06 14:43:52 +0100806
Shawn Bohrerb511c9a2013-07-19 13:24:06 -0500807 memset(&sin, 0, sizeof(sin));
Steven Langde890a12011-11-09 14:03:34 +0100808 if (o->proto == FIO_TYPE_TCP)
Jens Axboe414c2a32009-01-16 13:21:15 +0100809 type = SOCK_STREAM;
810 else
811 type = SOCK_DGRAM;
812
Jens Axboe0fd666b2011-10-06 20:08:53 +0200813 fd = socket(AF_INET, type, 0);
Jens Axboeed92ac02007-02-06 14:43:52 +0100814 if (fd < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100815 td_verror(td, errno, "socket");
Jens Axboeed92ac02007-02-06 14:43:52 +0100816 return 1;
817 }
818
819 opt = 1;
Jens Axboe26e594a2013-01-30 21:52:37 +0100820 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &opt, sizeof(opt)) < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100821 td_verror(td, errno, "setsockopt");
Shawn Bohrer4a93dec2013-07-19 13:24:10 -0500822 close(fd);
Jens Axboeed92ac02007-02-06 14:43:52 +0100823 return 1;
824 }
Jens Axboe6bedbfa2007-02-07 09:54:40 +0100825#ifdef SO_REUSEPORT
Jens Axboe26e594a2013-01-30 21:52:37 +0100826 if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (void *) &opt, sizeof(opt)) < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100827 td_verror(td, errno, "setsockopt");
Shawn Bohrer4a93dec2013-07-19 13:24:10 -0500828 close(fd);
Jens Axboe6bedbfa2007-02-07 09:54:40 +0100829 return 1;
830 }
831#endif
Jens Axboeed92ac02007-02-06 14:43:52 +0100832
Shawn Bohrerb511c9a2013-07-19 13:24:06 -0500833 if (td->o.filename){
834 if(o->proto != FIO_TYPE_UDP ||
835 !fio_netio_is_multicast(td->o.filename)) {
836 log_err("fio: hostname not valid for non-multicast inbound network IO\n");
837 close(fd);
838 return 1;
839 }
840
841 inet_aton(td->o.filename, &sin.sin_addr);
842
843 mr.imr_multiaddr = sin.sin_addr;
844 mr.imr_interface.s_addr = htonl(INADDR_ANY);
845 if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr)) < 0) {
846 td_verror(td, errno, "setsockopt IP_ADD_MEMBERSHIP");
847 close(fd);
848 return 1;
849 }
850 }
851
Jens Axboeb5af8292007-03-08 12:43:13 +0100852 nd->addr.sin_family = AF_INET;
Shawn Bohrerb511c9a2013-07-19 13:24:06 -0500853 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 +0100854 nd->addr.sin_port = htons(port);
Jens Axboeed92ac02007-02-06 14:43:52 +0100855
Jens Axboeb5af8292007-03-08 12:43:13 +0100856 if (bind(fd, (struct sockaddr *) &nd->addr, sizeof(nd->addr)) < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100857 td_verror(td, errno, "bind");
Jens Axboeed92ac02007-02-06 14:43:52 +0100858 return 1;
859 }
Jens Axboe0fd666b2011-10-06 20:08:53 +0200860
861 nd->listenfd = fd;
862 return 0;
863}
864
Steven Langde890a12011-11-09 14:03:34 +0100865static int fio_netio_setup_listen(struct thread_data *td)
Jens Axboe0fd666b2011-10-06 20:08:53 +0200866{
867 struct netio_data *nd = td->io_ops->data;
Steven Langde890a12011-11-09 14:03:34 +0100868 struct netio_options *o = td->eo;
Jens Axboe0fd666b2011-10-06 20:08:53 +0200869 int ret;
870
Steven Langde890a12011-11-09 14:03:34 +0100871 if (o->proto == FIO_TYPE_UDP || o->proto == FIO_TYPE_TCP)
872 ret = fio_netio_setup_listen_inet(td, o->port);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200873 else
Steven Langde890a12011-11-09 14:03:34 +0100874 ret = fio_netio_setup_listen_unix(td, td->o.filename);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200875
876 if (ret)
877 return ret;
Steven Langde890a12011-11-09 14:03:34 +0100878 if (o->proto == FIO_TYPE_UDP)
Jens Axboe0fd666b2011-10-06 20:08:53 +0200879 return 0;
880
881 if (listen(nd->listenfd, 10) < 0) {
Jens Axboee1161c32007-02-22 19:36:48 +0100882 td_verror(td, errno, "listen");
Jens Axboe0fd666b2011-10-06 20:08:53 +0200883 nd->listenfd = -1;
Jens Axboeed92ac02007-02-06 14:43:52 +0100884 return 1;
885 }
886
Jens Axboeb5af8292007-03-08 12:43:13 +0100887 return 0;
Jens Axboeed92ac02007-02-06 14:43:52 +0100888}
889
Jens Axboe9bec88e2007-03-02 08:55:48 +0100890static int fio_netio_init(struct thread_data *td)
Jens Axboeed92ac02007-02-06 14:43:52 +0100891{
Steven Langde890a12011-11-09 14:03:34 +0100892 struct netio_options *o = td->eo;
Jens Axboeaf52b342007-03-13 10:07:47 +0100893 int ret;
Jens Axboeed92ac02007-02-06 14:43:52 +0100894
Bruce Cran3f457be2012-10-10 13:37:41 +0100895#ifdef WIN32
896 WSADATA wsd;
897 WSAStartup(MAKEWORD(2,2), &wsd);
898#endif
899
Jens Axboe16d55aa2007-05-22 09:21:37 +0200900 if (td_random(td)) {
901 log_err("fio: network IO can't be random\n");
902 return 1;
903 }
Jens Axboeed92ac02007-02-06 14:43:52 +0100904
Steven Langde890a12011-11-09 14:03:34 +0100905 if (o->proto == FIO_TYPE_UNIX && o->port) {
906 log_err("fio: network IO port not valid with unix socket\n");
907 return 1;
908 } else if (o->proto != FIO_TYPE_UNIX && !o->port) {
909 log_err("fio: network IO requires port for tcp or udp\n");
910 return 1;
Jens Axboe414c2a32009-01-16 13:21:15 +0100911 }
Jens Axboe0fd666b2011-10-06 20:08:53 +0200912
Steven Langde890a12011-11-09 14:03:34 +0100913 if (o->proto != FIO_TYPE_TCP) {
914 if (o->listen) {
Jens Axboe9b986062011-12-19 08:57:18 +0100915 log_err("fio: listen only valid for TCP proto IO\n");
916 return 1;
Steven Langde890a12011-11-09 14:03:34 +0100917 }
918 if (td_rw(td)) {
Jens Axboe9b986062011-12-19 08:57:18 +0100919 log_err("fio: datagram network connections must be"
Steven Langde890a12011-11-09 14:03:34 +0100920 " read OR write\n");
Jens Axboe9b986062011-12-19 08:57:18 +0100921 return 1;
922 }
923 if (o->proto == FIO_TYPE_UNIX && !td->o.filename) {
924 log_err("fio: UNIX sockets need host/filename\n");
925 return 1;
Steven Langde890a12011-11-09 14:03:34 +0100926 }
927 o->listen = td_read(td);
928 }
929
Steven Langde890a12011-11-09 14:03:34 +0100930 if (o->listen)
931 ret = fio_netio_setup_listen(td);
Jens Axboe0fd666b2011-10-06 20:08:53 +0200932 else
Steven Langde890a12011-11-09 14:03:34 +0100933 ret = fio_netio_setup_connect(td);
Jens Axboeed92ac02007-02-06 14:43:52 +0100934
Jens Axboe7bb48f82007-03-27 15:30:28 +0200935 return ret;
Jens Axboeed92ac02007-02-06 14:43:52 +0100936}
937
Jens Axboeb5af8292007-03-08 12:43:13 +0100938static void fio_netio_cleanup(struct thread_data *td)
Jens Axboe9bec88e2007-03-02 08:55:48 +0100939{
Jens Axboeb5af8292007-03-08 12:43:13 +0100940 struct netio_data *nd = td->io_ops->data;
941
942 if (nd) {
Jens Axboe64b24cd2007-06-24 21:28:39 +0200943 if (nd->listenfd != -1)
944 close(nd->listenfd);
945 if (nd->pipes[0] != -1)
946 close(nd->pipes[0]);
947 if (nd->pipes[1] != -1)
948 close(nd->pipes[1]);
949
Jens Axboeb5af8292007-03-08 12:43:13 +0100950 free(nd);
Jens Axboeb5af8292007-03-08 12:43:13 +0100951 }
952}
953
954static int fio_netio_setup(struct thread_data *td)
955{
Jens Axboe7bb48f82007-03-27 15:30:28 +0200956 struct netio_data *nd;
Jens Axboeb5af8292007-03-08 12:43:13 +0100957
Steven Langde890a12011-11-09 14:03:34 +0100958 if (!td->files_index) {
959 add_file(td, td->o.filename ?: "net");
960 td->o.nr_files = td->o.nr_files ?: 1;
961 }
962
Jens Axboe7bb48f82007-03-27 15:30:28 +0200963 if (!td->io_ops->data) {
964 nd = malloc(sizeof(*nd));;
965
966 memset(nd, 0, sizeof(*nd));
967 nd->listenfd = -1;
Jens Axboe64b24cd2007-06-24 21:28:39 +0200968 nd->pipes[0] = nd->pipes[1] = -1;
Jens Axboe7bb48f82007-03-27 15:30:28 +0200969 td->io_ops->data = nd;
Jens Axboe7bb48f82007-03-27 15:30:28 +0200970 }
971
Jens Axboe9bec88e2007-03-02 08:55:48 +0100972 return 0;
973}
974
Jens Axboe36d80bc2012-11-30 21:46:06 +0100975static void fio_netio_terminate(struct thread_data *td)
976{
977 kill(td->pid, SIGUSR2);
978}
979
Jens Axboe67bf9822013-01-10 11:23:19 +0100980#ifdef CONFIG_LINUX_SPLICE
Jens Axboe9cce02e2007-06-22 15:42:21 +0200981static int fio_netio_setup_splice(struct thread_data *td)
982{
983 struct netio_data *nd;
984
985 fio_netio_setup(td);
986
987 nd = td->io_ops->data;
988 if (nd) {
989 if (pipe(nd->pipes) < 0)
990 return 1;
991
992 nd->use_splice = 1;
993 return 0;
994 }
995
996 return 1;
997}
998
Jens Axboe5921e802008-05-30 15:02:38 +0200999static struct ioengine_ops ioengine_splice = {
Steven Langde890a12011-11-09 14:03:34 +01001000 .name = "netsplice",
1001 .version = FIO_IOOPS_VERSION,
1002 .prep = fio_netio_prep,
1003 .queue = fio_netio_queue,
1004 .setup = fio_netio_setup_splice,
1005 .init = fio_netio_init,
1006 .cleanup = fio_netio_cleanup,
1007 .open_file = fio_netio_open_file,
Jens Axboe36d80bc2012-11-30 21:46:06 +01001008 .close_file = fio_netio_close_file,
1009 .terminate = fio_netio_terminate,
Steven Langde890a12011-11-09 14:03:34 +01001010 .options = options,
1011 .option_struct_size = sizeof(struct netio_options),
1012 .flags = FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR |
Jens Axboe36d80bc2012-11-30 21:46:06 +01001013 FIO_PIPEIO,
Jens Axboe5921e802008-05-30 15:02:38 +02001014};
1015#endif
1016
Jens Axboe9cce02e2007-06-22 15:42:21 +02001017static struct ioengine_ops ioengine_rw = {
Steven Langde890a12011-11-09 14:03:34 +01001018 .name = "net",
1019 .version = FIO_IOOPS_VERSION,
1020 .prep = fio_netio_prep,
1021 .queue = fio_netio_queue,
1022 .setup = fio_netio_setup,
1023 .init = fio_netio_init,
1024 .cleanup = fio_netio_cleanup,
1025 .open_file = fio_netio_open_file,
1026 .close_file = fio_netio_close_file,
Jens Axboe36d80bc2012-11-30 21:46:06 +01001027 .terminate = fio_netio_terminate,
Steven Langde890a12011-11-09 14:03:34 +01001028 .options = options,
1029 .option_struct_size = sizeof(struct netio_options),
1030 .flags = FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR |
Steven Noonanad705bc2013-04-08 15:05:25 -07001031 FIO_PIPEIO | FIO_BIT_BASED,
Jens Axboeed92ac02007-02-06 14:43:52 +01001032};
1033
Steven Langde890a12011-11-09 14:03:34 +01001034static int str_hostname_cb(void *data, const char *input)
1035{
1036 struct netio_options *o = data;
1037
1038 if (o->td->o.filename)
1039 free(o->td->o.filename);
1040 o->td->o.filename = strdup(input);
1041 return 0;
1042}
1043
Jens Axboeed92ac02007-02-06 14:43:52 +01001044static void fio_init fio_netio_register(void)
1045{
Jens Axboe9cce02e2007-06-22 15:42:21 +02001046 register_ioengine(&ioengine_rw);
Jens Axboe67bf9822013-01-10 11:23:19 +01001047#ifdef CONFIG_LINUX_SPLICE
Jens Axboe9cce02e2007-06-22 15:42:21 +02001048 register_ioengine(&ioengine_splice);
Jens Axboe5921e802008-05-30 15:02:38 +02001049#endif
Jens Axboeed92ac02007-02-06 14:43:52 +01001050}
1051
1052static void fio_exit fio_netio_unregister(void)
1053{
Jens Axboe9cce02e2007-06-22 15:42:21 +02001054 unregister_ioengine(&ioengine_rw);
Jens Axboe67bf9822013-01-10 11:23:19 +01001055#ifdef CONFIG_LINUX_SPLICE
Jens Axboe9cce02e2007-06-22 15:42:21 +02001056 unregister_ioengine(&ioengine_splice);
Jens Axboe5921e802008-05-30 15:02:38 +02001057#endif
Jens Axboeed92ac02007-02-06 14:43:52 +01001058}