Fio 2.0.14
[fio.git] / engines / net.c
1 /*
2  * net engine
3  *
4  * IO engine that reads/writes to/from sockets.
5  *
6  */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <signal.h>
11 #include <errno.h>
12 #include <assert.h>
13 #include <netinet/in.h>
14 #include <netinet/tcp.h>
15 #include <arpa/inet.h>
16 #include <netdb.h>
17 #include <sys/poll.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <sys/socket.h>
21 #include <sys/un.h>
22
23 #include "../fio.h"
24
25 struct netio_data {
26         int listenfd;
27         int use_splice;
28         int pipes[2];
29         struct sockaddr_in addr;
30         struct sockaddr_un addr_un;
31 };
32
33 struct netio_options {
34         struct thread_data *td;
35         unsigned int port;
36         unsigned int proto;
37         unsigned int listen;
38         unsigned int pingpong;
39         unsigned int nodelay;
40 };
41
42 struct udp_close_msg {
43         uint32_t magic;
44         uint32_t cmd;
45 };
46
47 enum {
48         FIO_LINK_CLOSE = 0x89,
49         FIO_LINK_OPEN_CLOSE_MAGIC = 0x6c696e6b,
50         FIO_LINK_OPEN = 0x98,
51
52         FIO_TYPE_TCP    = 1,
53         FIO_TYPE_UDP    = 2,
54         FIO_TYPE_UNIX   = 3,
55 };
56
57 static int str_hostname_cb(void *data, const char *input);
58 static 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",
64         },
65         {
66                 .name   = "port",
67                 .type   = FIO_OPT_INT,
68                 .off1   = offsetof(struct netio_options, port),
69                 .minval = 1,
70                 .maxval = 65535,
71                 .help   = "Port to use for TCP or UDP net connections",
72         },
73         {
74                 .name   = "protocol",
75                 .alias  = "proto",
76                 .type   = FIO_OPT_STR,
77                 .off1   = offsetof(struct netio_options, proto),
78                 .help   = "Network protocol to use",
79                 .def    = "tcp",
80                 .posval = {
81                           { .ival = "tcp",
82                             .oval = FIO_TYPE_TCP,
83                             .help = "Transmission Control Protocol",
84                           },
85                           { .ival = "udp",
86                             .oval = FIO_TYPE_UDP,
87                             .help = "User Datagram Protocol",
88                           },
89                           { .ival = "unix",
90                             .oval = FIO_TYPE_UNIX,
91                             .help = "UNIX domain socket",
92                           },
93                 },
94         },
95 #ifdef CONFIG_TCP_NODELAY
96         {
97                 .name   = "nodelay",
98                 .type   = FIO_OPT_BOOL,
99                 .off1   = offsetof(struct netio_options, nodelay),
100                 .help   = "Use TCP_NODELAY on TCP connections",
101         },
102 #endif
103         {
104                 .name   = "listen",
105                 .type   = FIO_OPT_STR_SET,
106                 .off1   = offsetof(struct netio_options, listen),
107                 .help   = "Listen for incoming TCP connections",
108         },
109         {
110                 .name   = "pingpong",
111                 .type   = FIO_OPT_STR_SET,
112                 .off1   = offsetof(struct netio_options, pingpong),
113                 .help   = "Ping-pong IO requests",
114         },
115         {
116                 .name   = NULL,
117         },
118 };
119
120 /*
121  * Return -1 for error and 'nr events' for a positive number
122  * of events
123  */
124 static int poll_wait(struct thread_data *td, int fd, short events)
125 {
126         struct pollfd pfd;
127         int ret;
128
129         while (!td->terminate) {
130                 pfd.fd = fd;
131                 pfd.events = events;
132                 ret = poll(&pfd, 1, -1);
133                 if (ret < 0) {
134                         if (errno == EINTR)
135                                 break;
136
137                         td_verror(td, errno, "poll");
138                         return -1;
139                 } else if (!ret)
140                         continue;
141
142                 break;
143         }
144
145         if (pfd.revents & events)
146                 return 1;
147
148         return -1;
149 }
150
151 static int fio_netio_prep(struct thread_data *td, struct io_u *io_u)
152 {
153         struct netio_options *o = td->eo;
154
155         /*
156          * Make sure we don't see spurious reads to a receiver, and vice versa
157          */
158         if (o->proto == FIO_TYPE_TCP)
159                 return 0;
160
161         if ((o->listen && io_u->ddir == DDIR_WRITE) ||
162             (!o->listen && io_u->ddir == DDIR_READ)) {
163                 td_verror(td, EINVAL, "bad direction");
164                 return 1;
165         }
166
167         return 0;
168 }
169
170 #ifdef CONFIG_LINUX_SPLICE
171 static int splice_io_u(int fdin, int fdout, unsigned int len)
172 {
173         int bytes = 0;
174
175         while (len) {
176                 int ret = splice(fdin, NULL, fdout, NULL, len, 0);
177
178                 if (ret < 0) {
179                         if (!bytes)
180                                 bytes = ret;
181
182                         break;
183                 } else if (!ret)
184                         break;
185
186                 bytes += ret;
187                 len -= ret;
188         }
189
190         return bytes;
191 }
192
193 /*
194  * Receive bytes from a socket and fill them into the internal pipe
195  */
196 static int splice_in(struct thread_data *td, struct io_u *io_u)
197 {
198         struct netio_data *nd = td->io_ops->data;
199
200         return splice_io_u(io_u->file->fd, nd->pipes[1], io_u->xfer_buflen);
201 }
202
203 /*
204  * Transmit 'len' bytes from the internal pipe
205  */
206 static int splice_out(struct thread_data *td, struct io_u *io_u,
207                       unsigned int len)
208 {
209         struct netio_data *nd = td->io_ops->data;
210
211         return splice_io_u(nd->pipes[0], io_u->file->fd, len);
212 }
213
214 static int vmsplice_io_u(struct io_u *io_u, int fd, unsigned int len)
215 {
216         struct iovec iov = {
217                 .iov_base = io_u->xfer_buf,
218                 .iov_len = len,
219         };
220         int bytes = 0;
221
222         while (iov.iov_len) {
223                 int ret = vmsplice(fd, &iov, 1, SPLICE_F_MOVE);
224
225                 if (ret < 0) {
226                         if (!bytes)
227                                 bytes = ret;
228                         break;
229                 } else if (!ret)
230                         break;
231
232                 iov.iov_len -= ret;
233                 iov.iov_base += ret;
234                 bytes += ret;
235         }
236
237         return bytes;
238
239 }
240
241 /*
242  * vmsplice() pipe to io_u buffer
243  */
244 static int vmsplice_io_u_out(struct thread_data *td, struct io_u *io_u,
245                              unsigned int len)
246 {
247         struct netio_data *nd = td->io_ops->data;
248
249         return vmsplice_io_u(io_u, nd->pipes[0], len);
250 }
251
252 /*
253  * vmsplice() io_u to pipe
254  */
255 static int vmsplice_io_u_in(struct thread_data *td, struct io_u *io_u)
256 {
257         struct netio_data *nd = td->io_ops->data;
258
259         return vmsplice_io_u(io_u, nd->pipes[1], io_u->xfer_buflen);
260 }
261
262 /*
263  * splice receive - transfer socket data into a pipe using splice, then map
264  * that pipe data into the io_u using vmsplice.
265  */
266 static int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
267 {
268         int ret;
269
270         ret = splice_in(td, io_u);
271         if (ret > 0)
272                 return vmsplice_io_u_out(td, io_u, ret);
273
274         return ret;
275 }
276
277 /*
278  * splice transmit - map data from the io_u into a pipe by using vmsplice,
279  * then transfer that pipe to a socket using splice.
280  */
281 static int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
282 {
283         int ret;
284
285         ret = vmsplice_io_u_in(td, io_u);
286         if (ret > 0)
287                 return splice_out(td, io_u, ret);
288
289         return ret;
290 }
291 #else
292 static int fio_netio_splice_in(struct thread_data *td, struct io_u *io_u)
293 {
294         errno = EOPNOTSUPP;
295         return -1;
296 }
297
298 static int fio_netio_splice_out(struct thread_data *td, struct io_u *io_u)
299 {
300         errno = EOPNOTSUPP;
301         return -1;
302 }
303 #endif
304
305 static int fio_netio_send(struct thread_data *td, struct io_u *io_u)
306 {
307         struct netio_data *nd = td->io_ops->data;
308         struct netio_options *o = td->eo;
309         int ret, flags = 0;
310
311         do {
312                 if (o->proto == FIO_TYPE_UDP) {
313                         struct sockaddr *to = (struct sockaddr *) &nd->addr;
314
315                         ret = sendto(io_u->file->fd, io_u->xfer_buf,
316                                         io_u->xfer_buflen, flags, to,
317                                         sizeof(*to));
318                 } else {
319                         /*
320                          * if we are going to write more, set MSG_MORE
321                          */
322 #ifdef MSG_MORE
323                         if ((td->this_io_bytes[DDIR_WRITE] + io_u->xfer_buflen <
324                             td->o.size) && !o->pingpong)
325                                 flags |= MSG_MORE;
326 #endif
327                         ret = send(io_u->file->fd, io_u->xfer_buf,
328                                         io_u->xfer_buflen, flags);
329                 }
330                 if (ret > 0)
331                         break;
332
333                 ret = poll_wait(td, io_u->file->fd, POLLOUT);
334                 if (ret <= 0)
335                         break;
336         } while (1);
337
338         return ret;
339 }
340
341 static int is_udp_close(struct io_u *io_u, int len)
342 {
343         struct udp_close_msg *msg;
344
345         if (len != sizeof(struct udp_close_msg))
346                 return 0;
347
348         msg = io_u->xfer_buf;
349         if (ntohl(msg->magic) != FIO_LINK_OPEN_CLOSE_MAGIC)
350                 return 0;
351         if (ntohl(msg->cmd) != FIO_LINK_CLOSE)
352                 return 0;
353
354         return 1;
355 }
356
357 static int fio_netio_recv(struct thread_data *td, struct io_u *io_u)
358 {
359         struct netio_data *nd = td->io_ops->data;
360         struct netio_options *o = td->eo;
361         int ret, flags = 0;
362
363         do {
364                 if (o->proto == FIO_TYPE_UDP) {
365                         socklen_t len = sizeof(nd->addr);
366                         struct sockaddr *from = (struct sockaddr *) &nd->addr;
367
368                         ret = recvfrom(io_u->file->fd, io_u->xfer_buf,
369                                         io_u->xfer_buflen, flags, from, &len);
370                         if (is_udp_close(io_u, ret)) {
371                                 td->done = 1;
372                                 return 0;
373                         }
374                 } else {
375                         ret = recv(io_u->file->fd, io_u->xfer_buf,
376                                         io_u->xfer_buflen, flags);
377                 }
378                 if (ret > 0)
379                         break;
380                 else if (!ret && (flags & MSG_WAITALL))
381                         break;
382
383                 ret = poll_wait(td, io_u->file->fd, POLLIN);
384                 if (ret <= 0)
385                         break;
386                 flags |= MSG_WAITALL;
387         } while (1);
388
389         return ret;
390 }
391
392 static int __fio_netio_queue(struct thread_data *td, struct io_u *io_u,
393                              enum fio_ddir ddir)
394 {
395         struct netio_data *nd = td->io_ops->data;
396         struct netio_options *o = td->eo;
397         int ret;
398
399         if (ddir == DDIR_WRITE) {
400                 if (!nd->use_splice || o->proto == FIO_TYPE_UDP ||
401                     o->proto == FIO_TYPE_UNIX)
402                         ret = fio_netio_send(td, io_u);
403                 else
404                         ret = fio_netio_splice_out(td, io_u);
405         } else if (ddir == DDIR_READ) {
406                 if (!nd->use_splice || o->proto == FIO_TYPE_UDP ||
407                     o->proto == FIO_TYPE_UNIX)
408                         ret = fio_netio_recv(td, io_u);
409                 else
410                         ret = fio_netio_splice_in(td, io_u);
411         } else
412                 ret = 0;        /* must be a SYNC */
413
414         if (ret != (int) io_u->xfer_buflen) {
415                 if (ret >= 0) {
416                         io_u->resid = io_u->xfer_buflen - ret;
417                         io_u->error = 0;
418                         return FIO_Q_COMPLETED;
419                 } else {
420                         int err = errno;
421
422                         if (ddir == DDIR_WRITE && err == EMSGSIZE)
423                                 return FIO_Q_BUSY;
424
425                         io_u->error = err;
426                 }
427         }
428
429         if (io_u->error)
430                 td_verror(td, io_u->error, "xfer");
431
432         return FIO_Q_COMPLETED;
433 }
434
435 static int fio_netio_queue(struct thread_data *td, struct io_u *io_u)
436 {
437         struct netio_options *o = td->eo;
438         int ret;
439
440         fio_ro_check(td, io_u);
441
442         ret = __fio_netio_queue(td, io_u, io_u->ddir);
443         if (!o->pingpong || ret != FIO_Q_COMPLETED)
444                 return ret;
445
446         /*
447          * For ping-pong mode, receive or send reply as needed
448          */
449         if (td_read(td) && io_u->ddir == DDIR_READ)
450                 ret = __fio_netio_queue(td, io_u, DDIR_WRITE);
451         else if (td_write(td) && io_u->ddir == DDIR_WRITE)
452                 ret = __fio_netio_queue(td, io_u, DDIR_READ);
453
454         return ret;
455 }
456
457 static int fio_netio_connect(struct thread_data *td, struct fio_file *f)
458 {
459         struct netio_data *nd = td->io_ops->data;
460         struct netio_options *o = td->eo;
461         int type, domain, optval;
462
463         if (o->proto == FIO_TYPE_TCP) {
464                 domain = AF_INET;
465                 type = SOCK_STREAM;
466         } else if (o->proto == FIO_TYPE_UDP) {
467                 domain = AF_INET;
468                 type = SOCK_DGRAM;
469         } else if (o->proto == FIO_TYPE_UNIX) {
470                 domain = AF_UNIX;
471                 type = SOCK_STREAM;
472         } else {
473                 log_err("fio: bad network type %d\n", o->proto);
474                 f->fd = -1;
475                 return 1;
476         }
477
478         f->fd = socket(domain, type, 0);
479         if (f->fd < 0) {
480                 td_verror(td, errno, "socket");
481                 return 1;
482         }
483
484 #ifdef CONFIG_TCP_NODELAY
485         if (o->nodelay && o->proto == FIO_TYPE_TCP) {
486                 optval = 1;
487                 if (setsockopt(f->fd, IPPROTO_TCP, TCP_NODELAY, (void *) &optval, sizeof(int)) < 0) {
488                         log_err("fio: cannot set TCP_NODELAY option on socket (%s), disable with 'nodelay=0'\n", strerror(errno));
489                         return 1;
490                 }
491         }
492 #endif
493
494         if (o->proto == FIO_TYPE_UDP)
495                 return 0;
496         else if (o->proto == FIO_TYPE_TCP) {
497                 socklen_t len = sizeof(nd->addr);
498
499                 if (connect(f->fd, (struct sockaddr *) &nd->addr, len) < 0) {
500                         td_verror(td, errno, "connect");
501                         close(f->fd);
502                         return 1;
503                 }
504         } else {
505                 struct sockaddr_un *addr = &nd->addr_un;
506                 socklen_t len;
507
508                 len = sizeof(addr->sun_family) + strlen(addr->sun_path) + 1;
509
510                 if (connect(f->fd, (struct sockaddr *) addr, len) < 0) {
511                         td_verror(td, errno, "connect");
512                         close(f->fd);
513                         return 1;
514                 }
515         }
516
517         return 0;
518 }
519
520 static int fio_netio_accept(struct thread_data *td, struct fio_file *f)
521 {
522         struct netio_data *nd = td->io_ops->data;
523         struct netio_options *o = td->eo;
524         socklen_t socklen = sizeof(nd->addr);
525         int state, optval;
526
527         if (o->proto == FIO_TYPE_UDP) {
528                 f->fd = nd->listenfd;
529                 return 0;
530         }
531
532         state = td->runstate;
533         td_set_runstate(td, TD_SETTING_UP);
534
535         log_info("fio: waiting for connection\n");
536
537         if (poll_wait(td, nd->listenfd, POLLIN) < 0)
538                 goto err;
539
540         f->fd = accept(nd->listenfd, (struct sockaddr *) &nd->addr, &socklen);
541         if (f->fd < 0) {
542                 td_verror(td, errno, "accept");
543                 goto err;
544         }
545
546 #ifdef CONFIG_TCP_NODELAY
547         if (o->nodelay && o->proto == FIO_TYPE_TCP) {
548                 optval = 1;
549                 if (setsockopt(f->fd, IPPROTO_TCP, TCP_NODELAY, (void *) &optval, sizeof(int)) < 0) {
550                         log_err("fio: cannot set TCP_NODELAY option on socket (%s), disable with 'nodelay=0'\n", strerror(errno));
551                         return 1;
552                 }
553         }
554 #endif
555
556         reset_all_stats(td);
557         td_set_runstate(td, state);
558         return 0;
559 err:
560         td_set_runstate(td, state);
561         return 1;
562 }
563
564 static void fio_netio_udp_close(struct thread_data *td, struct fio_file *f)
565 {
566         struct netio_data *nd = td->io_ops->data;
567         struct udp_close_msg msg;
568         struct sockaddr *to = (struct sockaddr *) &nd->addr;
569         int ret;
570
571         msg.magic = htonl(FIO_LINK_OPEN_CLOSE_MAGIC);
572         msg.cmd = htonl(FIO_LINK_CLOSE);
573
574         ret = sendto(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to,
575                         sizeof(nd->addr));
576         if (ret < 0)
577                 td_verror(td, errno, "sendto udp link close");
578 }
579
580 static int fio_netio_close_file(struct thread_data *td, struct fio_file *f)
581 {
582         struct netio_options *o = td->eo;
583
584         /*
585          * If this is an UDP connection, notify the receiver that we are
586          * closing down the link
587          */
588         if (o->proto == FIO_TYPE_UDP)
589                 fio_netio_udp_close(td, f);
590
591         return generic_close_file(td, f);
592 }
593
594 static int fio_netio_udp_recv_open(struct thread_data *td, struct fio_file *f)
595 {
596         struct netio_data *nd = td->io_ops->data;
597         struct udp_close_msg msg;
598         struct sockaddr *to = (struct sockaddr *) &nd->addr;
599         socklen_t len = sizeof(nd->addr);
600         int ret;
601
602         ret = recvfrom(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to, &len);
603         if (ret < 0) {
604                 td_verror(td, errno, "sendto udp link open");
605                 return ret;
606         }
607
608         if (ntohl(msg.magic) != FIO_LINK_OPEN_CLOSE_MAGIC ||
609             ntohl(msg.cmd) != FIO_LINK_OPEN) {
610                 log_err("fio: bad udp open magic %x/%x\n", ntohl(msg.magic),
611                                                                 ntohl(msg.cmd));
612                 return -1;
613         }
614
615         return 0;
616 }
617
618 static int fio_netio_udp_send_open(struct thread_data *td, struct fio_file *f)
619 {
620         struct netio_data *nd = td->io_ops->data;
621         struct udp_close_msg msg;
622         struct sockaddr *to = (struct sockaddr *) &nd->addr;
623         int ret;
624
625         msg.magic = htonl(FIO_LINK_OPEN_CLOSE_MAGIC);
626         msg.cmd = htonl(FIO_LINK_OPEN);
627
628         ret = sendto(f->fd, (void *) &msg, sizeof(msg), MSG_WAITALL, to,
629                         sizeof(nd->addr));
630         if (ret < 0) {
631                 td_verror(td, errno, "sendto udp link open");
632                 return ret;
633         }
634
635         return 0;
636 }
637
638 static int fio_netio_open_file(struct thread_data *td, struct fio_file *f)
639 {
640         int ret;
641         struct netio_options *o = td->eo;
642
643         if (o->listen)
644                 ret = fio_netio_accept(td, f);
645         else
646                 ret = fio_netio_connect(td, f);
647
648         if (ret) {
649                 f->fd = -1;
650                 return ret;
651         }
652
653         if (o->proto == FIO_TYPE_UDP) {
654                 if (td_write(td))
655                         ret = fio_netio_udp_send_open(td, f);
656                 else {
657                         int state;
658
659                         state = td->runstate;
660                         td_set_runstate(td, TD_SETTING_UP);
661                         ret = fio_netio_udp_recv_open(td, f);
662                         td_set_runstate(td, state);
663                 }
664         }
665
666         if (ret)
667                 fio_netio_close_file(td, f);
668
669         return ret;
670 }
671
672 static int fio_netio_setup_connect_inet(struct thread_data *td,
673                                         const char *host, unsigned short port)
674 {
675         struct netio_data *nd = td->io_ops->data;
676
677         if (!host) {
678                 log_err("fio: connect with no host to connect to.\n");
679                 if (td_read(td))
680                         log_err("fio: did you forget to set 'listen'?\n");
681
682                 td_verror(td, EINVAL, "no hostname= set");
683                 return 1;
684         }
685
686         nd->addr.sin_family = AF_INET;
687         nd->addr.sin_port = htons(port);
688
689         if (inet_aton(host, &nd->addr.sin_addr) != 1) {
690                 struct hostent *hent;
691
692                 hent = gethostbyname(host);
693                 if (!hent) {
694                         td_verror(td, errno, "gethostbyname");
695                         return 1;
696                 }
697
698                 memcpy(&nd->addr.sin_addr, hent->h_addr, 4);
699         }
700
701         return 0;
702 }
703
704 static int fio_netio_setup_connect_unix(struct thread_data *td,
705                                         const char *path)
706 {
707         struct netio_data *nd = td->io_ops->data;
708         struct sockaddr_un *soun = &nd->addr_un;
709
710         soun->sun_family = AF_UNIX;
711         strcpy(soun->sun_path, path);
712         return 0;
713 }
714
715 static int fio_netio_setup_connect(struct thread_data *td)
716 {
717         struct netio_options *o = td->eo;
718
719         if (o->proto == FIO_TYPE_UDP || o->proto == FIO_TYPE_TCP)
720                 return fio_netio_setup_connect_inet(td, td->o.filename,o->port);
721         else
722                 return fio_netio_setup_connect_unix(td, td->o.filename);
723 }
724
725 static int fio_netio_setup_listen_unix(struct thread_data *td, const char *path)
726 {
727         struct netio_data *nd = td->io_ops->data;
728         struct sockaddr_un *addr = &nd->addr_un;
729         mode_t mode;
730         int len, fd;
731
732         fd = socket(AF_UNIX, SOCK_STREAM, 0);
733         if (fd < 0) {
734                 log_err("fio: socket: %s\n", strerror(errno));
735                 return -1;
736         }
737
738         mode = umask(000);
739
740         memset(addr, 0, sizeof(*addr));
741         addr->sun_family = AF_UNIX;
742         strcpy(addr->sun_path, path);
743         unlink(path);
744
745         len = sizeof(addr->sun_family) + strlen(path) + 1;
746
747         if (bind(fd, (struct sockaddr *) addr, len) < 0) {
748                 log_err("fio: bind: %s\n", strerror(errno));
749                 close(fd);
750                 return -1;
751         }
752
753         umask(mode);
754         nd->listenfd = fd;
755         return 0;
756 }
757
758 static int fio_netio_setup_listen_inet(struct thread_data *td, short port)
759 {
760         struct netio_data *nd = td->io_ops->data;
761         struct netio_options *o = td->eo;
762         int fd, opt, type;
763
764         if (o->proto == FIO_TYPE_TCP)
765                 type = SOCK_STREAM;
766         else
767                 type = SOCK_DGRAM;
768
769         fd = socket(AF_INET, type, 0);
770         if (fd < 0) {
771                 td_verror(td, errno, "socket");
772                 return 1;
773         }
774
775         opt = 1;
776         if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &opt, sizeof(opt)) < 0) {
777                 td_verror(td, errno, "setsockopt");
778                 return 1;
779         }
780 #ifdef SO_REUSEPORT
781         if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (void *) &opt, sizeof(opt)) < 0) {
782                 td_verror(td, errno, "setsockopt");
783                 return 1;
784         }
785 #endif
786
787         nd->addr.sin_family = AF_INET;
788         nd->addr.sin_addr.s_addr = htonl(INADDR_ANY);
789         nd->addr.sin_port = htons(port);
790
791         if (bind(fd, (struct sockaddr *) &nd->addr, sizeof(nd->addr)) < 0) {
792                 td_verror(td, errno, "bind");
793                 return 1;
794         }
795
796         nd->listenfd = fd;
797         return 0;
798 }
799
800 static int fio_netio_setup_listen(struct thread_data *td)
801 {
802         struct netio_data *nd = td->io_ops->data;
803         struct netio_options *o = td->eo;
804         int ret;
805
806         if (o->proto == FIO_TYPE_UDP || o->proto == FIO_TYPE_TCP)
807                 ret = fio_netio_setup_listen_inet(td, o->port);
808         else
809                 ret = fio_netio_setup_listen_unix(td, td->o.filename);
810
811         if (ret)
812                 return ret;
813         if (o->proto == FIO_TYPE_UDP)
814                 return 0;
815
816         if (listen(nd->listenfd, 10) < 0) {
817                 td_verror(td, errno, "listen");
818                 nd->listenfd = -1;
819                 return 1;
820         }
821
822         return 0;
823 }
824
825 static int fio_netio_init(struct thread_data *td)
826 {
827         struct netio_options *o = td->eo;
828         int ret;
829
830 #ifdef WIN32
831         WSADATA wsd;
832         WSAStartup(MAKEWORD(2,2), &wsd);
833 #endif
834
835         if (td_random(td)) {
836                 log_err("fio: network IO can't be random\n");
837                 return 1;
838         }
839
840         if (o->proto == FIO_TYPE_UNIX && o->port) {
841                 log_err("fio: network IO port not valid with unix socket\n");
842                 return 1;
843         } else if (o->proto != FIO_TYPE_UNIX && !o->port) {
844                 log_err("fio: network IO requires port for tcp or udp\n");
845                 return 1;
846         }
847
848         if (o->proto != FIO_TYPE_TCP) {
849                 if (o->listen) {
850                         log_err("fio: listen only valid for TCP proto IO\n");
851                         return 1;
852                 }
853                 if (td_rw(td)) {
854                         log_err("fio: datagram network connections must be"
855                                    " read OR write\n");
856                         return 1;
857                 }
858                 if (o->proto == FIO_TYPE_UNIX && !td->o.filename) {
859                         log_err("fio: UNIX sockets need host/filename\n");
860                         return 1;
861                 }
862                 o->listen = td_read(td);
863         }
864
865         if (o->proto != FIO_TYPE_UNIX && o->listen && td->o.filename) {
866                 log_err("fio: hostname not valid for inbound network IO\n");
867                 return 1;
868         }
869
870         if (o->listen)
871                 ret = fio_netio_setup_listen(td);
872         else
873                 ret = fio_netio_setup_connect(td);
874
875         return ret;
876 }
877
878 static void fio_netio_cleanup(struct thread_data *td)
879 {
880         struct netio_data *nd = td->io_ops->data;
881
882         if (nd) {
883                 if (nd->listenfd != -1)
884                         close(nd->listenfd);
885                 if (nd->pipes[0] != -1)
886                         close(nd->pipes[0]);
887                 if (nd->pipes[1] != -1)
888                         close(nd->pipes[1]);
889
890                 free(nd);
891         }
892 }
893
894 static int fio_netio_setup(struct thread_data *td)
895 {
896         struct netio_data *nd;
897
898         if (!td->files_index) {
899                 add_file(td, td->o.filename ?: "net");
900                 td->o.nr_files = td->o.nr_files ?: 1;
901         }
902
903         if (!td->io_ops->data) {
904                 nd = malloc(sizeof(*nd));;
905
906                 memset(nd, 0, sizeof(*nd));
907                 nd->listenfd = -1;
908                 nd->pipes[0] = nd->pipes[1] = -1;
909                 td->io_ops->data = nd;
910         }
911
912         return 0;
913 }
914
915 static void fio_netio_terminate(struct thread_data *td)
916 {
917         kill(td->pid, SIGUSR2);
918 }
919
920 #ifdef CONFIG_LINUX_SPLICE
921 static int fio_netio_setup_splice(struct thread_data *td)
922 {
923         struct netio_data *nd;
924
925         fio_netio_setup(td);
926
927         nd = td->io_ops->data;
928         if (nd) {
929                 if (pipe(nd->pipes) < 0)
930                         return 1;
931
932                 nd->use_splice = 1;
933                 return 0;
934         }
935
936         return 1;
937 }
938
939 static struct ioengine_ops ioengine_splice = {
940         .name                   = "netsplice",
941         .version                = FIO_IOOPS_VERSION,
942         .prep                   = fio_netio_prep,
943         .queue                  = fio_netio_queue,
944         .setup                  = fio_netio_setup_splice,
945         .init                   = fio_netio_init,
946         .cleanup                = fio_netio_cleanup,
947         .open_file              = fio_netio_open_file,
948         .close_file             = fio_netio_close_file,
949         .terminate              = fio_netio_terminate,
950         .options                = options,
951         .option_struct_size     = sizeof(struct netio_options),
952         .flags                  = FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR |
953                                   FIO_PIPEIO,
954 };
955 #endif
956
957 static struct ioengine_ops ioengine_rw = {
958         .name                   = "net",
959         .version                = FIO_IOOPS_VERSION,
960         .prep                   = fio_netio_prep,
961         .queue                  = fio_netio_queue,
962         .setup                  = fio_netio_setup,
963         .init                   = fio_netio_init,
964         .cleanup                = fio_netio_cleanup,
965         .open_file              = fio_netio_open_file,
966         .close_file             = fio_netio_close_file,
967         .terminate              = fio_netio_terminate,
968         .options                = options,
969         .option_struct_size     = sizeof(struct netio_options),
970         .flags                  = FIO_SYNCIO | FIO_DISKLESSIO | FIO_UNIDIR |
971                                   FIO_PIPEIO,
972 };
973
974 static int str_hostname_cb(void *data, const char *input)
975 {
976         struct netio_options *o = data;
977
978         if (o->td->o.filename)
979                 free(o->td->o.filename);
980         o->td->o.filename = strdup(input);
981         return 0;
982 }
983
984 static void fio_init fio_netio_register(void)
985 {
986         register_ioengine(&ioengine_rw);
987 #ifdef CONFIG_LINUX_SPLICE
988         register_ioengine(&ioengine_splice);
989 #endif
990 }
991
992 static void fio_exit fio_netio_unregister(void)
993 {
994         unregister_ioengine(&ioengine_rw);
995 #ifdef CONFIG_LINUX_SPLICE
996         unregister_ioengine(&ioengine_splice);
997 #endif
998 }