Recent changes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The following changes since commit cf00f975d506d20ad5f02ee9dd8fec17af74bb2f:

  Fix io_u->buf calculation overflow (2011-10-22 18:49:06 +0200)

are available in the git repository at:
  git://git.kernel.dk/fio.git master

Jens Axboe (2):
      client/server: IPv6 support
      server: document fio_server_parse_string()

 README   |   20 +++++++-----
 client.c |   37 ++++++++++++++++-----
 fio.1    |   20 +++++++-----
 server.c |  105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
 server.h |    3 +-
 5 files changed, 146 insertions(+), 39 deletions(-)

---

Diff of recent changes:

diff --git a/README b/README
index d41fc66..b2fdd0b 100644
--- a/README
+++ b/README
@@ -331,28 +331,32 @@ To start the server, you would do:
 fio --server=args
 
 on that machine, where args defines what fio listens to. The arguments
-are of the form 'type:hostname or IP:port'. 'type' is either 'ip' for
-TCP/IP, or 'sock' for a local unix domain socket. 'hostname' is either
-a hostname or IP address, and 'port' is the port to listen to (only valid
-for TCP/IP, not a local socket). Some examples:
+are of the form 'type,hostname or IP,port'. 'type' is either 'ip' (or ip4)
+for TCP/IP v4, 'ip6' for TCP/IP v6, or 'sock' for a local unix domain socket.
+'hostname' is either a hostname or IP address, and 'port' is the port to
+listen to (only valid for TCP/IP, not a local socket). Some examples:
 
 1) fio --server
 
    Start a fio server, listening on all interfaces on the default port (8765).
 
-2) fio --server=ip:hostname:4444
+2) fio --server=ip:hostname,4444
 
    Start a fio server, listening on IP belonging to hostname and on port 4444.
 
-3) fio --server=:4444
+3) fio --server=ip6:::1,4444
+
+   Start a fio server, listening on IPv6 localhost ::1 and on port 4444.
+
+4) fio --server=,4444
 
    Start a fio server, listening on all interfaces on port 4444.
 
-4) fio --server=1.2.3.4
+5) fio --server=1.2.3.4
 
    Start a fio server, listening on IP 1.2.3.4 on the default port.
 
-5) fio --server=sock:/tmp/fio.sock
+6) fio --server=sock:/tmp/fio.sock
 
    Start a fio server, listening on the local socket /tmp/fio.sock.
 
diff --git a/client.c b/client.c
index fda16b8..a61bc80 100644
--- a/client.c
+++ b/client.c
@@ -29,8 +29,11 @@ struct fio_client {
 	struct flist_head list;
 	struct flist_head hash_list;
 	struct flist_head arg_list;
-	struct sockaddr_in addr;
-	struct sockaddr_un addr_un;
+	union {
+		struct sockaddr_in addr;
+		struct sockaddr_in6 addr6;
+		struct sockaddr_un addr_un;
+	};
 	char *hostname;
 	int port;
 	int fd;
@@ -44,6 +47,7 @@ struct fio_client {
 	int disk_stats_shown;
 	unsigned int jobs;
 	int error;
+	int ipv6;
 
 	struct flist_head eta_list;
 	struct client_eta *eta_in_flight;
@@ -204,7 +208,9 @@ int fio_client_add(const char *hostname, void **cookie)
 
 	if (fio_server_parse_string(hostname, &client->hostname,
 					&client->is_sock, &client->port,
-					&client->addr.sin_addr))
+					&client->addr.sin_addr,
+					&client->addr6.sin6_addr,
+					&client->ipv6))
 		return -1;
 
 	client->fd = -1;
@@ -220,18 +226,31 @@ int fio_client_add(const char *hostname, void **cookie)
 
 static int fio_client_connect_ip(struct fio_client *client)
 {
-	int fd;
-
-	client->addr.sin_family = AF_INET;
-	client->addr.sin_port = htons(client->port);
+	struct sockaddr *addr;
+	fio_socklen_t socklen;
+	int fd, domain;
+
+	if (client->ipv6) {
+		client->addr6.sin6_family = AF_INET6;
+		client->addr6.sin6_port = htons(client->port);
+		domain = AF_INET6;
+		addr = (struct sockaddr *) &client->addr6;
+		socklen = sizeof(client->addr6);
+	} else {
+		client->addr.sin_family = AF_INET;
+		client->addr.sin_port = htons(client->port);
+		domain = AF_INET;
+		addr = (struct sockaddr *) &client->addr;
+		socklen = sizeof(client->addr);
+	}
 
-	fd = socket(AF_INET, SOCK_STREAM, 0);
+	fd = socket(domain, SOCK_STREAM, 0);
 	if (fd < 0) {
 		log_err("fio: socket: %s\n", strerror(errno));
 		return -1;
 	}
 
-	if (connect(fd, (struct sockaddr *) &client->addr, sizeof(client->addr)) < 0) {
+	if (connect(fd, addr, socklen) < 0) {
 		log_err("fio: connect: %s\n", strerror(errno));
 		log_err("fio: failed to connect to %s:%u\n", client->hostname,
 								client->port);
diff --git a/fio.1 b/fio.1
index d63d1f2..3b11122 100644
--- a/fio.1
+++ b/fio.1
@@ -1221,28 +1221,32 @@ To start the server, you would do:
 \fBfio \-\-server=args\fR
 
 on that machine, where args defines what fio listens to. The arguments
-are of the form 'type:hostname or IP:port'. 'type' is either 'ip' for
-TCP/IP, or 'sock' for a local unix domain socket. 'hostname' is either
-a hostname or IP address, and 'port' is the port to listen to (only valid
-for TCP/IP, not a local socket). Some examples:
+are of the form 'type:hostname or IP:port'. 'type' is either 'ip' (or ip4)
+for TCP/IP v4, 'ip6' for TCP/IP v6, or 'sock' for a local unix domain socket.
+'hostname' is either a hostname or IP address, and 'port' is the port to
+listen to (only valid for TCP/IP, not a local socket). Some examples:
 
 1) fio --server
 
    Start a fio server, listening on all interfaces on the default port (8765).
 
-2) fio --server=ip:hostname:4444
+2) fio --server=ip:hostname,4444
 
    Start a fio server, listening on IP belonging to hostname and on port 4444.
 
-3) fio --server=:4444
+3) fio --server=ip6:::1,4444
+
+   Start a fio server, listening on IPv6 localhost ::1 and on port 4444.
+
+4) fio --server=,4444
 
    Start a fio server, listening on all interfaces on port 4444.
 
-4) fio --server=1.2.3.4
+5) fio --server=1.2.3.4
 
    Start a fio server, listening on IP 1.2.3.4 on the default port.
 
-5) fio --server=sock:/tmp/fio.sock
+6) fio --server=sock:/tmp/fio.sock
 
    Start a fio server, listening on the local socket /tmp/fio.sock.
 
diff --git a/server.c b/server.c
index 4da8bf0..81ec6b0 100644
--- a/server.c
+++ b/server.c
@@ -32,7 +32,9 @@ static int server_fd = -1;
 static char *fio_server_arg;
 static char *bind_sock;
 static struct sockaddr_in saddr_in;
+static struct sockaddr_in6 saddr_in6;
 static int first_cmd_check;
+static int use_ipv6;
 
 static const char *fio_server_ops[FIO_NET_CMD_NR] = {
 	"",
@@ -814,9 +816,15 @@ int fio_server_log(const char *format, ...)
 
 static int fio_init_server_ip(void)
 {
+	struct sockaddr *addr;
+	fio_socklen_t socklen;
 	int sk, opt;
 
-	sk = socket(AF_INET, SOCK_STREAM, 0);
+	if (use_ipv6)
+		sk = socket(AF_INET6, SOCK_STREAM, 0);
+	else
+		sk = socket(AF_INET, SOCK_STREAM, 0);
+
 	if (sk < 0) {
 		log_err("fio: socket: %s\n", strerror(errno));
 		return -1;
@@ -836,9 +844,17 @@ static int fio_init_server_ip(void)
 	}
 #endif
 
-	saddr_in.sin_family = AF_INET;
+	if (use_ipv6) {
+		addr = (struct sockaddr *) &saddr_in6;
+		socklen = sizeof(saddr_in6);
+		saddr_in6.sin6_family = AF_INET6;
+	} else {
+		addr = (struct sockaddr *) &saddr_in;
+		socklen = sizeof(saddr_in);
+		saddr_in.sin_family = AF_INET;
+	}
 
-	if (bind(sk, (struct sockaddr *) &saddr_in, sizeof(saddr_in)) < 0) {
+	if (bind(sk, addr, socklen) < 0) {
 		log_err("fio: bind: %s\n", strerror(errno));
 		close(sk);
 		return -1;
@@ -894,9 +910,27 @@ static int fio_init_server_connection(void)
 	if (sk < 0)
 		return sk;
 
-	if (!bind_sock)
-		sprintf(bind_str, "%s:%u", inet_ntoa(saddr_in.sin_addr), fio_net_port);
-	else
+	if (!bind_sock) {
+		char *p, port[16];
+		const void *src;
+		int af;
+
+		if (use_ipv6) {
+			af = AF_INET6;
+			src = &saddr_in6.sin6_addr;
+		} else {
+			af = AF_INET;
+			src = &saddr_in.sin_addr;
+		}
+
+		p = (char *) inet_ntop(af, src, bind_str, sizeof(bind_str));
+
+		sprintf(port, ",%u", fio_net_port);
+		if (p)
+			strcat(p, port);
+		else
+			strcpy(bind_str, port);
+	} else
 		strcpy(bind_str, bind_sock);
 
 	log_info("fio: server listening on %s\n", bind_str);
@@ -909,12 +943,26 @@ static int fio_init_server_connection(void)
 	return sk;
 }
 
+/*
+ * Parse a host/ip/port string. Reads from 'str'.
+ *
+ * Outputs:
+ *
+ * For IPv4:
+ *	*ptr is the host, *port is the port, inp is the destination.
+ * For IPv6:
+ *	*ptr is the host, *port is the port, inp6 is the dest, and *ipv6 is 1.
+ * For local domain sockets:
+ *	*ptr is the filename, *is_sock is 1.
+ */
 int fio_server_parse_string(const char *str, char **ptr, int *is_sock,
-			    int *port, struct in_addr *inp)
+			    int *port, struct in_addr *inp,
+			    struct in6_addr *inp6, int *ipv6)
 {
 	*ptr = NULL;
 	*is_sock = 0;
 	*port = fio_net_port;
+	*ipv6 = 0;
 
 	if (!strncmp(str, "sock:", 5)) {
 		*ptr = strdup(str + 5);
@@ -922,14 +970,19 @@ int fio_server_parse_string(const char *str, char **ptr, int *is_sock,
 	} else {
 		const char *host = str;
 		char *portp;
-		int lport = 0;
+		int ret, lport = 0;
 
 		/*
 		 * Is it ip:<ip or host>:port
 		 */
 		if (!strncmp(host, "ip:", 3))
 			host += 3;
-		else if (host[0] == ':') {
+		else if (!strncmp(host, "ip4:", 4))
+			host += 4;
+		else if (!strncmp(host, "ip6:", 4)) {
+			host += 4;
+			*ipv6 = 1;
+		} else if (host[0] == ':') {
 			/* String is :port */
 			host++;
 			lport = atoi(host);
@@ -946,7 +999,7 @@ int fio_server_parse_string(const char *str, char **ptr, int *is_sock,
 		 * If no port seen yet, check if there's a last ':' at the end
 		 */
 		if (!lport) {
-			portp = strchr(host, ':');
+			portp = strchr(host, ',');
 			if (portp) {
 				*portp = '\0';
 				portp++;
@@ -961,22 +1014,46 @@ int fio_server_parse_string(const char *str, char **ptr, int *is_sock,
 		if (lport)
 			*port = lport;
 
+		if (!strlen(host))
+			goto done;
+
 		*ptr = strdup(host);
 
-		if (inet_aton(host, inp) != 1) {
+		if (*ipv6)
+			ret = inet_pton(AF_INET6, host, inp6);
+		else
+			ret = inet_pton(AF_INET, host, inp);
+
+		if (ret != 1) {
 			struct hostent *hent;
 
 			hent = gethostbyname(host);
 			if (!hent) {
+				log_err("fio: failed to resolve <%s>\n", host);
+err:
 				free(*ptr);
 				*ptr = NULL;
 				return 1;
 			}
 
-			memcpy(inp, hent->h_addr, 4);
+			if (*ipv6) {
+				if (hent->h_addrtype != AF_INET6) {
+					log_info("fio: falling back to IPv4\n");
+					*ipv6 = 0;
+				} else
+					memcpy(inp6, hent->h_addr_list[0], 16);
+			}
+			if (!*ipv6) {
+				if (hent->h_addrtype != AF_INET) {
+					log_err("fio: lookup type mismatch\n");
+					goto err;
+				}
+				memcpy(inp, hent->h_addr_list[0], 4);
+			}
 		}
 	}
 
+done:
 	if (*port == 0)
 		*port = fio_net_port;
 
@@ -1006,7 +1083,8 @@ static int fio_handle_server_arg(void)
 		goto out;
 
 	ret = fio_server_parse_string(fio_server_arg, &bind_sock, &is_sock,
-					&port, &saddr_in.sin_addr);
+					&port, &saddr_in.sin_addr,
+					&saddr_in6.sin6_addr, &use_ipv6);
 
 	if (!is_sock && bind_sock) {
 		free(bind_sock);
@@ -1016,6 +1094,7 @@ static int fio_handle_server_arg(void)
 out:
 	fio_net_port = port;
 	saddr_in.sin_port = htons(port);
+	saddr_in6.sin6_port = htons(port);
 	return ret;
 }
 
diff --git a/server.h b/server.h
index 99689d4..27da94f 100644
--- a/server.h
+++ b/server.h
@@ -4,6 +4,7 @@
 #include <inttypes.h>
 #include <string.h>
 #include <sys/time.h>
+#include <netinet/in.h>
 
 #include "stat.h"
 #include "os/os.h"
@@ -109,7 +110,7 @@ extern int fio_server_log(const char *format, ...);
 extern int fio_net_send_cmd(int, uint16_t, const void *, off_t, uint64_t);
 extern int fio_net_send_simple_cmd(int, uint16_t, uint64_t, struct flist_head *);
 extern void fio_server_set_arg(const char *);
-extern int fio_server_parse_string(const char *, char **, int *, int *, struct in_addr *);
+extern int fio_server_parse_string(const char *, char **, int *, int *, struct in_addr *, struct in6_addr *, int *);
 extern const char *fio_server_op(unsigned int);
 extern void fio_server_got_signal(int);
 
--
To unsubscribe from this list: send the line "unsubscribe fio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel]     [Linux SCSI]     [Linux IDE]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux