f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Copyright (C) 2000, 2001 Nominum, Inc.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Permission to use, copy, modify, and distribute this software for any
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * purpose with or without fee is hereby granted, provided that the above
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * copyright notice and this permission notice appear in all copies.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Copyright (C) 2004 - 2015 Nominum, Inc.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Permission to use, copy, modify, and distribute this software and its
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * documentation for any purpose with or without fee is hereby granted,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * provided that the above copyright notice and this permission notice
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * appear in all copies.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt *** DNS Performance Testing Tool
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt *** Version $Id: dnsperf.c 263303 2015-12-15 01:09:36Z bwelling $
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunttypedef struct {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunttypedef struct {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunttypedef struct {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * This link links the query into the list of outstanding
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * queries or the list of available query IDs.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunttypedef struct {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic pthread_mutex_t start_lock = PTHREAD_MUTEX_INITIALIZER;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic pthread_cond_t start_cond = PTHREAD_COND_INITIALIZER;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_netaddr_fromsockaddr(&addr, &config->server_addr);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("[Status] Testing complete (%s)\n", reason);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic double
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstddev(isc_uint64_t sum_of_squares, isc_uint64_t sum, isc_uint64_t total)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return sqrt((sum_of_squares - (squared / total)) / (total - 1));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntprint_statistics(const config_t *config, const times_t *times, stats_t *stats)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int i;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" %s completed: %" ISC_PRINT_QUADFORMAT "u (%.2lf%%)\n",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt SAFE_DIV(100.0 * stats->num_completed, stats->num_sent));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" %s lost: %" ISC_PRINT_QUADFORMAT "u (%.2lf%%)\n",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt SAFE_DIV(100.0 * stats->num_timedout, stats->num_sent));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" %s interrupted: %" ISC_PRINT_QUADFORMAT "u "
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "(%.2lf%%)\n",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < 16; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (stats->rcodecounts[i] * 100.0) / stats->num_completed);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" Average packet size: request %u, response %u\n",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (unsigned int)SAFE_DIV(stats->total_response_size,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt SAFE_DIV(stats->num_completed, (((double)run_time) / MILLION)));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt latency_avg = SAFE_DIV(stats->latency_sum, stats->num_completed);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" Average Latency (s): %u.%06u (min %u.%06u, max %u.%06u)\n",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stddev(stats->latency_sum_squares, stats->latency_sum,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int i, j;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (j = 0; j < 16; j++)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt total->total_request_size += stats->total_request_size;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt total->total_response_size += stats->total_response_size;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt total->latency_sum_squares += stats->latency_sum_squares;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic char *
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->max_outstanding = DEFAULT_MAX_OUTSTANDING;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "address family of DNS transport, inet or inet6", "any",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the server to query", DEFAULT_SERVER_NAME, &server_name);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the port on which to query the server",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the local address from which to send queries", NULL,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the local port from which to send queries",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "socket send/receive buffer size in kilobytes", NULL,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the timeout for query completion in seconds",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('y', perf_opt_string, "[alg:]name:secret",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the maximum number of queries outstanding",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('S', perf_opt_timeval, "stats_interval",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "print qps statistics every N seconds",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "send dynamic updates instead of queries",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "verbose: report each query to stdout",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_net_parseserver(config->family, server_name, server_port,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_net_parselocal(isc_sockaddr_pf(&config->server_addr),
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (config->maxruns == 0 && config->timelimit == 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->tsigkey = perf_dns_parsetsigkey(tsigkey, mctx);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * If we run more threads than max-qps, some threads will have
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * ->max_qps set to 0, and be unlimited.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (config->max_qps > 0 && config->threads > config->max_qps)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * We also can't run more threads than clients.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int i;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < 2; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunttypedef enum {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic inline void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntquery_move(threadinfo_t *tinfo, query_info *q, query_move_op op)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LIST_PREPEND(tinfo->outstanding_queries, q, link);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return stats->num_sent - stats->num_completed - stats->num_timedout;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void *
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt max_packet_size = config->edns ? MAX_EDNS_PACKET : MAX_UDP_PACKET;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_buffer_init(&msg, packet_buffer, max_packet_size);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_buffer_init(&lines, input_data, sizeof(input_data));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /* Avoid flooding the network too quickly. */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /* Rate limiting */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /* Limit in-flight queries */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (num_outstanding(stats) >= tinfo->max_outstanding) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q->sock = tinfo->socks[tinfo->current_sock++ % tinfo->nsocks];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt result = perf_datafile_next(input, &lines, config->updates);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (n < 0 || (unsigned int) n != length) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntprocess_timeouts(threadinfo_t *tinfo, isc_uint64_t now)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /* Avoid locking unless we need to. */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_printf("[Timeout] %s timed out: msg id %u",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunttypedef struct {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned char *packet_buffer, unsigned int packet_size,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (n < 0) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic inline void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void *
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int i, j;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * If we're done sending and either all responses have been
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * received, stop.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (tinfo->done_sending && num_outstanding(stats) == 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Try to receive a few packets, so that we can process them
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * atomically.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < RECV_BATCH_SIZE; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /* Do all of the processing that requires the lock */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < nrecvd; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /* Now do the rest of the processing unlocked */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < nrecvd; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "unexpected (maybe timed out) "
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "> %s %s %u.%06u",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats->latency_sum_squares += (latency * latency);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * If there was an error, handle it (by either ignoring it,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * blocking, or exiting).
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void *
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt while (perf_os_waituntilreadable(threadpipe[0], threadpipe[0],
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt num_completed = total.num_completed - last_completed;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt qps = num_completed / (((double)interval_time) / MILLION);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntper_thread(isc_uint32_t total, isc_uint32_t nthreads, unsigned int offset)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntthreadinfo_init(threadinfo_t *tinfo, const config_t *config,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < NQIDS; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->dnsctx = perf_dns_createctx(config->updates);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Compute per-thread limits based on global values.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->max_outstanding = per_thread(config->max_outstanding,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->max_qps = per_thread(config->max_qps, config->threads, offset);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->nsocks = per_thread(config->clients, config->threads, offset);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * We can't have more than 64k outstanding queries per thread.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->socks = isc_mem_get(mctx, tinfo->nsocks * sizeof(int));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < offset; i++)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->socks[i] = perf_net_opensocket(&config->server_addr,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntthreadinfo_cleanup(threadinfo_t *tinfo, times_t *times)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int i;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_mem_put(mctx, tinfo->socks, tinfo->nsocks * sizeof(int));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int i;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt threads = isc_mem_get(mctx, config.threads * sizeof(threadinfo_t));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt THREAD(&stats_thread.sender, do_interval_stats, &stats_thread);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt times.stop_time = times.start_time + config.timelimit;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt times.stop_time_ns.tv_sec = times.stop_time / MILLION;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt times.stop_time_ns.tv_nsec = (times.stop_time % MILLION) * 1000;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt result = perf_os_waituntilreadable(mainpipe[0], intrpipe[0],