diff --git a/client.cpp b/client.cpp index 82045ed0..979dcdd9 100755 --- a/client.cpp +++ b/client.cpp @@ -178,9 +178,14 @@ int client::connect(void) } // Just in case we got domain name and not ip, we convert it - struct sockaddr_in *ipv4 = (struct sockaddr_in *)addr.ci_addr; - char address[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &(ipv4->sin_addr), address, INET_ADDRSTRLEN); + char address[INET6_ADDRSTRLEN]; + if (addr.ci_family == PF_INET) { + struct sockaddr_in *ipv4 = (struct sockaddr_in *)addr.ci_addr; + inet_ntop(AF_INET, &(ipv4->sin_addr), address, INET_ADDRSTRLEN); + } else { + struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)addr.ci_addr; + inet_ntop(AF_INET6, &(ipv6->sin6_addr), address, INET6_ADDRSTRLEN); + } char port_str[20]; snprintf(port_str, sizeof(port_str)-1, "%u", m_config->port); diff --git a/cluster_client.cpp b/cluster_client.cpp index 215feac9..1333167b 100644 --- a/cluster_client.cpp +++ b/cluster_client.cpp @@ -194,7 +194,7 @@ bool cluster_client::connect_shard_connection(shard_connection* sc, char* addres memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; - hints.ai_family = AF_INET; + hints.ai_family = AF_UNSPEC; int res = getaddrinfo(address, port, &hints, &addr_info); if (res != 0) { diff --git a/config_types.cpp b/config_types.cpp index 2be0a9d2..3e9f9285 100644 --- a/config_types.cpp +++ b/config_types.cpp @@ -225,8 +225,8 @@ const char* config_weight_list::print(char *buf, int buf_len) } -server_addr::server_addr(const char *hostname, int port) : - m_hostname(hostname), m_port(port), m_server_addr(NULL), m_used_addr(NULL), m_last_error(0) +server_addr::server_addr(const char *hostname, int port, int resolution) : + m_hostname(hostname), m_port(port), m_server_addr(NULL), m_used_addr(NULL), m_resolution(resolution), m_last_error(0) { int error = resolve(); @@ -254,7 +254,7 @@ int server_addr::resolve(void) memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; - hints.ai_family = PF_UNSPEC; + hints.ai_family = m_resolution; snprintf(port_str, sizeof(port_str)-1, "%u", m_port); m_last_error = getaddrinfo(m_hostname.c_str(), port_str, &hints, &m_server_addr); diff --git a/config_types.h b/config_types.h index 14ff1eb4..787e0428 100644 --- a/config_types.h +++ b/config_types.h @@ -86,7 +86,7 @@ struct connect_info { }; struct server_addr { - server_addr(const char *hostname, int port); + server_addr(const char *hostname, int port, int resolution); virtual ~server_addr(); int get_connect_info(struct connect_info *ci); @@ -99,6 +99,7 @@ struct server_addr { int m_port; struct addrinfo *m_server_addr; struct addrinfo *m_used_addr; + int m_resolution; int m_last_error; }; diff --git a/memtier_benchmark.cpp b/memtier_benchmark.cpp index 7648ee25..c0b09430 100755 --- a/memtier_benchmark.cpp +++ b/memtier_benchmark.cpp @@ -99,6 +99,7 @@ static void config_print(FILE *file, struct benchmark_config *cfg) "server = %s\n" "port = %u\n" "unix socket = %s\n" + "address family = %s\n" "protocol = %s\n" #ifdef USE_TLS "tls = %s\n" @@ -147,6 +148,7 @@ static void config_print(FILE *file, struct benchmark_config *cfg) cfg->server, cfg->port, cfg->unix_socket, + cfg->resolution == AF_UNSPEC ? "Unspecified" : cfg->resolution == AF_INET ? "AF_INET" : "AF_INET6", get_protocol_name(cfg->protocol), #ifdef USE_TLS cfg->tls ? "yes" : "no", @@ -203,6 +205,7 @@ static void config_print_to_json(json_handler * jsonhandler, struct benchmark_co jsonhandler->write_obj("server" ,"\"%s\"", cfg->server); jsonhandler->write_obj("port" ,"%u", cfg->port); jsonhandler->write_obj("unix socket" ,"\"%s\"", cfg->unix_socket); + jsonhandler->write_obj("address family" ,"\"%s\"", cfg->resolution == AF_UNSPEC ? "Unspecified" : cfg->resolution == AF_INET ? "AF_INET" : "AF_INET6"); jsonhandler->write_obj("protocol" ,"\"%s\"", get_protocol_name(cfg->protocol)); jsonhandler->write_obj("out_file" ,"\"%s\"", cfg->out_file); #ifdef USE_TLS @@ -257,6 +260,8 @@ static void config_init_defaults(struct benchmark_config *cfg) cfg->server = "localhost"; if (!cfg->port && !cfg->unix_socket) cfg->port = 6379; + if (!cfg->resolution) + cfg->resolution = AF_UNSPEC; if (!cfg->run_count) cfg->run_count = 1; if (!cfg->clients) @@ -409,6 +414,8 @@ static int config_parse_args(int argc, char *argv[], struct benchmark_config *cf { "server", 1, 0, 's' }, { "port", 1, 0, 'p' }, { "unix-socket", 1, 0, 'S' }, + { "ipv4", 0, 0, '4' }, + { "ipv6", 0, 0, '6' }, { "protocol", 1, 0, 'P' }, #ifdef USE_TLS { "tls", 0, 0, o_tls }, @@ -473,7 +480,7 @@ static int config_parse_args(int argc, char *argv[], struct benchmark_config *cf int c; char *endptr; while ((c = getopt_long(argc, argv, - "vs:S:p:P:o:x:DRn:c:t:d:a:h", long_options, &option_index)) != -1) + "vs:S:p:P:o:x:DRn:c:t:d:a:h:46", long_options, &option_index)) != -1) { switch (c) { case 'h': @@ -500,6 +507,12 @@ static int config_parse_args(int argc, char *argv[], struct benchmark_config *cf return -1; } break; + case '4': + cfg->resolution = AF_INET; + break; + case '6': + cfg->resolution = AF_INET6; + break; case 'P': if (strcmp(optarg, "redis") == 0) { cfg->protocol = PROTOCOL_REDIS_DEFAULT; @@ -873,6 +886,8 @@ void usage() { " -s, --server=ADDR Server address (default: localhost)\n" " -p, --port=PORT Server port (default: 6379)\n" " -S, --unix-socket=SOCKET UNIX Domain socket name (default: none)\n" + " -4, --ipv4 Force IPv4 address resolution.\n" + " -6 --ipv6 Force IPv6 address resolution.\n" " -P, --protocol=PROTOCOL Protocol to use (default: redis).\n" " other supported protocols are resp2, resp3, memcache_text and memcache_binary.\n" " when using one of resp2 or resp3 the redis protocol version will be set via HELLO command.\n" @@ -1340,7 +1355,7 @@ int main(int argc, char *argv[]) if (cfg.server != NULL && cfg.port > 0) { try { - cfg.server_addr = new server_addr(cfg.server, cfg.port); + cfg.server_addr = new server_addr(cfg.server, cfg.port, cfg.resolution); } catch (std::runtime_error& e) { benchmark_error_log("%s:%u: error: %s\n", cfg.server, cfg.port, e.what()); diff --git a/memtier_benchmark.h b/memtier_benchmark.h index c180e2c5..c2f83f44 100644 --- a/memtier_benchmark.h +++ b/memtier_benchmark.h @@ -54,6 +54,7 @@ struct benchmark_config { unsigned short port; struct server_addr *server_addr; const char *unix_socket; + int resolution; enum PROTOCOL_TYPE protocol; const char *out_file; const char *client_stats;