f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Copyright (C) 2000, 2001 Nominum, Inc.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt *
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 *
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 */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Copyright (C) 2004 - 2015 Nominum, Inc.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt *
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 *
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 */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/***
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt *** DNS Performance Testing Tool
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ***
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt *** Version $Id: dnsperf.c 263303 2015-12-15 01:09:36Z bwelling $
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ***/
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <errno.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <math.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <pthread.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <signal.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <stdio.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <stdlib.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <string.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <time.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <unistd.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <sys/time.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#define ISC_BUFFER_USEINLINE
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <isc/buffer.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <isc/file.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <isc/list.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <isc/mem.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <isc/netaddr.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <isc/print.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <isc/region.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <isc/result.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <isc/sockaddr.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <isc/types.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <dns/rcode.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <dns/result.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include "net.h"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include "datafile.h"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include "dns.h"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include "log.h"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include "opt.h"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include "os.h"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include "util.h"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include "version.h"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#define DEFAULT_SERVER_NAME "127.0.0.1"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#define DEFAULT_SERVER_PORT 53
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#define DEFAULT_LOCAL_PORT 0
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#define DEFAULT_MAX_OUTSTANDING 100
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#define DEFAULT_TIMEOUT 5
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#define TIMEOUT_CHECK_TIME 100000
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#define MAX_INPUT_DATA (64 * 1024)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#define MAX_SOCKETS 256
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#define RECV_BATCH_SIZE 16
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunttypedef struct {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int argc;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt char **argv;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int family;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint32_t clients;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint32_t threads;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint32_t maxruns;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t timelimit;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_sockaddr_t server_addr;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_sockaddr_t local_addr;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t timeout;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint32_t bufsize;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_boolean_t edns;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_boolean_t dnssec;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_dnstsigkey_t *tsigkey;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint32_t max_outstanding;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint32_t max_qps;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t stats_interval;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_boolean_t updates;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_boolean_t verbose;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt} config_t;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunttypedef struct {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t start_time;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t end_time;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t stop_time;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt struct timespec stop_time_ns;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt} times_t;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunttypedef struct {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t rcodecounts[16];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t num_sent;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t num_interrupted;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t num_timedout;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t num_completed;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t total_request_size;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t total_response_size;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t latency_sum;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t latency_sum_squares;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t latency_min;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t latency_max;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt} stats_t;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunttypedef ISC_LIST(struct query_info) query_list;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunttypedef struct query_info {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t timestamp;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt query_list *list;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt char *desc;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int sock;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * This link links the query into the list of outstanding
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * queries or the list of available query IDs.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LINK(struct query_info) link;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt} query_info;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#define NQIDS 65536
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunttypedef struct {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt query_info queries[NQIDS];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt query_list outstanding_queries;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt query_list unused_queries;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt pthread_t sender;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt pthread_t receiver;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt pthread_mutex_t lock;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt pthread_cond_t cond;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int nsocks;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int current_sock;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int *socks;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_dnsctx_t *dnsctx;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_boolean_t done_sending;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t done_send_time;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt const config_t *config;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt const times_t *times;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats_t stats;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint32_t max_outstanding;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint32_t max_qps;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t last_recv;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt} threadinfo_t;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic threadinfo_t *threads;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic pthread_mutex_t start_lock = PTHREAD_MUTEX_INITIALIZER;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic pthread_cond_t start_cond = PTHREAD_COND_INITIALIZER;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_boolean_t started;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_boolean_t interrupted = ISC_FALSE;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic int threadpipe[2];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic int mainpipe[2];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic int intrpipe[2];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_mem_t *mctx;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic perf_datafile_t *input;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunthandle_sigint(int sig)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (void)sig;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt write(intrpipe[1], "", 1);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntprint_initial_status(const config_t *config)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt time_t now;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_netaddr_t addr;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt char buf[ISC_NETADDR_FORMATSIZE];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int i;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("[Status] Command line: %s",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_file_basename(config->argv[0]));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 1; i < config->argc; i++)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" %s", config->argv[i]);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("\n");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_netaddr_fromsockaddr(&addr, &config->server_addr);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_netaddr_format(&addr, buf, sizeof(buf));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("[Status] Sending %s (to %s)\n",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->updates ? "updates" : "queries", buf);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt now = time(NULL);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("[Status] Started at: %s", ctime(&now));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("[Status] Stopping after ");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (config->timelimit)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("%u.%06u seconds",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (unsigned int)(config->timelimit / MILLION),
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (unsigned int)(config->timelimit % MILLION));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (config->timelimit && config->maxruns)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" or ");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (config->maxruns)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("%u run%s through file", config->maxruns,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->maxruns == 1 ? "" : "s");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("\n");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntprint_final_status(const config_t *config)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt const char *reason;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (interrupted)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt reason = "interruption";
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt else if (config->maxruns > 0 &&
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_datafile_nruns(input) == config->maxruns)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt reason = "end of file";
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt else
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt reason = "time limit";
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("[Status] Testing complete (%s)\n", reason);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("\n");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic double
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstddev(isc_uint64_t sum_of_squares, isc_uint64_t sum, isc_uint64_t total)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt double squared;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt squared = (double)sum * (double)sum;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return sqrt((sum_of_squares - (squared / total)) / (total - 1));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntprint_statistics(const config_t *config, const times_t *times, stats_t *stats)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt const char *units;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t run_time;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_boolean_t first_rcode;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t latency_avg;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int i;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt units = config->updates ? "Updates" : "Queries";
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt run_time = times->end_time - times->start_time;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("Statistics:\n\n");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" %s sent: %" ISC_PRINT_QUADFORMAT "u\n",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt units, stats->num_sent);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" %s completed: %" ISC_PRINT_QUADFORMAT "u (%.2lf%%)\n",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt units, stats->num_completed,
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 units, stats->num_timedout,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt SAFE_DIV(100.0 * stats->num_timedout, stats->num_sent));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (stats->num_interrupted > 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" %s interrupted: %" ISC_PRINT_QUADFORMAT "u "
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "(%.2lf%%)\n",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt units, stats->num_interrupted,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt SAFE_DIV(100.0 * stats->num_interrupted,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats->num_sent));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("\n");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" Response codes: ");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt first_rcode = ISC_TRUE;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < 16; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (stats->rcodecounts[i] == 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt continue;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (first_rcode)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt first_rcode = ISC_FALSE;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt else
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(", ");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("%s %" ISC_PRINT_QUADFORMAT "u (%.2lf%%)",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_dns_rcode_strings[i], stats->rcodecounts[i],
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (stats->rcodecounts[i] * 100.0) / stats->num_completed);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("\n");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" Average packet size: request %u, response %u\n",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (unsigned int)SAFE_DIV(stats->total_request_size,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats->num_sent),
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (unsigned int)SAFE_DIV(stats->total_response_size,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats->num_completed));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" Run time (s): %u.%06u\n",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (unsigned int)(run_time / MILLION),
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (unsigned int)(run_time % MILLION));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" %s per second: %.6lf\n", units,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt SAFE_DIV(stats->num_completed, (((double)run_time) / MILLION)));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("\n");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
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 (unsigned int)(latency_avg / MILLION),
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (unsigned int)(latency_avg % MILLION),
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (unsigned int)(stats->latency_min / MILLION),
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (unsigned int)(stats->latency_min % MILLION),
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (unsigned int)(stats->latency_max / MILLION),
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (unsigned int)(stats->latency_max % MILLION));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (stats->num_completed > 1) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" Latency StdDev (s): %f\n",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stddev(stats->latency_sum_squares, stats->latency_sum,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats->num_completed) / MILLION);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("\n");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntsum_stats(const config_t *config, stats_t *total)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int i, j;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt memset(total, 0, sizeof(*total));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < config->threads; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats_t *stats = &threads[i].stats;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (j = 0; j < 16; j++)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt total->rcodecounts[j] += stats->rcodecounts[j];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt total->num_sent += stats->num_sent;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt total->num_interrupted += stats->num_interrupted;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt total->num_timedout += stats->num_timedout;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt total->num_completed += stats->num_completed;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt total->total_request_size += stats->total_request_size;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt total->total_response_size += stats->total_response_size;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt total->latency_sum += stats->latency_sum;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt total->latency_sum_squares += stats->latency_sum_squares;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt total->latency_min += stats->latency_min;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt total->latency_max += stats->latency_max;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic char *
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstringify(unsigned int value)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt static char buf[20];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt snprintf(buf, sizeof(buf), "%u", value);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return buf;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntsetup(int argc, char **argv, config_t *config)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt const char *family = NULL;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt const char *server_name = DEFAULT_SERVER_NAME;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt in_port_t server_port = DEFAULT_SERVER_PORT;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt const char *local_name = NULL;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt in_port_t local_port = DEFAULT_LOCAL_PORT;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt const char *filename = NULL;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt const char *tsigkey = NULL;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_result_t result;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt result = isc_mem_create(0, 0, &mctx);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (result != ISC_R_SUCCESS)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("creating memory context: %s",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_result_totext(result));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt dns_result_register();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt memset(config, 0, sizeof(*config));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->argc = argc;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->argv = argv;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->family = AF_UNSPEC;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->clients = 1;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->threads = 1;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->timeout = DEFAULT_TIMEOUT * MILLION;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->max_outstanding = DEFAULT_MAX_OUTSTANDING;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('f', perf_opt_string, "family",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "address family of DNS transport, inet or inet6", "any",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &family);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('s', perf_opt_string, "server_addr",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the server to query", DEFAULT_SERVER_NAME, &server_name);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('p', perf_opt_port, "port",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the port on which to query the server",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stringify(DEFAULT_SERVER_PORT), &server_port);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('a', perf_opt_string, "local_addr",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the local address from which to send queries", NULL,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &local_name);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('x', perf_opt_port, "local_port",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the local port from which to send queries",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stringify(DEFAULT_LOCAL_PORT), &local_port);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('d', perf_opt_string, "datafile",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the input data file", "stdin", &filename);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('c', perf_opt_uint, "clients",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the number of clients to act as", NULL,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &config->clients);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('T', perf_opt_uint, "threads",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the number of threads to run", NULL,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &config->threads);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('n', perf_opt_uint, "maxruns",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "run through input at most N times", NULL,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &config->maxruns);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('l', perf_opt_timeval, "timelimit",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "run for at most this many seconds", NULL,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &config->timelimit);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('b', perf_opt_uint, "buffer_size",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "socket send/receive buffer size in kilobytes", NULL,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &config->bufsize);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('t', perf_opt_timeval, "timeout",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the timeout for query completion in seconds",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stringify(DEFAULT_TIMEOUT), &config->timeout);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('e', perf_opt_boolean, NULL,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "enable EDNS 0", NULL, &config->edns);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('D', perf_opt_boolean, NULL,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "set the DNSSEC OK bit (implies EDNS)", NULL,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &config->dnssec);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('y', perf_opt_string, "[alg:]name:secret",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the TSIG algorithm, name and secret", NULL,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &tsigkey);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('q', perf_opt_uint, "num_queries",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the maximum number of queries outstanding",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stringify(DEFAULT_MAX_OUTSTANDING),
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &config->max_outstanding);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('Q', perf_opt_uint, "max_qps",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "limit the number of queries per second", NULL,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &config->max_qps);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('S', perf_opt_timeval, "stats_interval",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "print qps statistics every N seconds",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt NULL, &config->stats_interval);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('u', perf_opt_boolean, NULL,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "send dynamic updates instead of queries",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt NULL, &config->updates);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('v', perf_opt_boolean, NULL,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "verbose: report each query to stdout",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt NULL, &config->verbose);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_parse(argc, argv);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (family != NULL)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->family = perf_net_parsefamily(family);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_net_parseserver(config->family, server_name, server_port,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &config->server_addr);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_net_parselocal(isc_sockaddr_pf(&config->server_addr),
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt local_name, local_port, &config->local_addr);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt input = perf_datafile_open(mctx, filename);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (config->maxruns == 0 && config->timelimit == 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->maxruns = 1;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_datafile_setmaxruns(input, config->maxruns);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (config->dnssec)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->edns = ISC_TRUE;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (tsigkey != NULL)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->tsigkey = perf_dns_parsetsigkey(tsigkey, mctx);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /*
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 */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (config->max_qps > 0 && config->threads > config->max_qps)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->threads = config->max_qps;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * We also can't run more threads than clients.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (config->threads > config->clients)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->threads = config->clients;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntcleanup(config_t *config)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int i;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_datafile_close(&input);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < 2; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt close(threadpipe[i]);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt close(mainpipe[i]);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt close(intrpipe[i]);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (config->tsigkey != NULL)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_dns_destroytsigkey(&config->tsigkey);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_mem_destroy(&mctx);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunttypedef enum {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt prepend_unused,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt append_unused,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt prepend_outstanding,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt} query_move_op;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic inline void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntquery_move(threadinfo_t *tinfo, query_info *q, query_move_op op)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LIST_UNLINK(*q->list, q, link);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt switch (op) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt case prepend_unused:
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q->list = &tinfo->unused_queries;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LIST_PREPEND(tinfo->unused_queries, q, link);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt break;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt case append_unused:
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q->list = &tinfo->unused_queries;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LIST_APPEND(tinfo->unused_queries, q, link);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt break;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt case prepend_outstanding:
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q->list = &tinfo->outstanding_queries;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LIST_PREPEND(tinfo->outstanding_queries, q, link);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt break;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic inline isc_uint64_t
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntnum_outstanding(const stats_t *stats)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return stats->num_sent - stats->num_completed - stats->num_timedout;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntwait_for_start(void)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt LOCK(&start_lock);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt while (!started)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt WAIT(&start_cond, &start_lock);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt UNLOCK(&start_lock);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void *
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntdo_send(void *arg)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt threadinfo_t *tinfo;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt const config_t *config;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt const times_t *times;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats_t *stats;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int max_packet_size;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_buffer_t msg;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t now, run_time, req_time;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt char input_data[MAX_INPUT_DATA];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_buffer_t lines;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_region_t used;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt query_info *q;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int qid;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned char packet_buffer[MAX_EDNS_PACKET];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned char *base;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int length;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int n;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_result_t result;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo = (threadinfo_t *) arg;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config = tinfo->config;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt times = tinfo->times;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats = &tinfo->stats;
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
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt wait_for_start();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt now = get_time();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt while (!interrupted && now < times->stop_time) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /* Avoid flooding the network too quickly. */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (stats->num_sent < tinfo->max_outstanding &&
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats->num_sent % 2 == 1)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (stats->num_completed == 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt usleep(1000);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt else
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt sleep(0);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt now = get_time();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /* Rate limiting */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (tinfo->max_qps > 0) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt run_time = now - times->start_time;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt req_time = (MILLION * stats->num_sent) /
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->max_qps;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (req_time > run_time) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt usleep(req_time - run_time);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt now = get_time();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt continue;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt LOCK(&tinfo->lock);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /* Limit in-flight queries */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (num_outstanding(stats) >= tinfo->max_outstanding) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt TIMEDWAIT(&tinfo->cond, &tinfo->lock,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &times->stop_time_ns, NULL);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt UNLOCK(&tinfo->lock);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt now = get_time();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt continue;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q = ISC_LIST_HEAD(tinfo->unused_queries);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt query_move(tinfo, q, prepend_outstanding);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q->timestamp = ISC_UINT64_MAX;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q->sock = tinfo->socks[tinfo->current_sock++ % tinfo->nsocks];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt UNLOCK(&tinfo->lock);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_buffer_clear(&lines);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt result = perf_datafile_next(input, &lines, config->updates);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (result != ISC_R_SUCCESS) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (result == ISC_R_INVALIDFILE)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("input file contains no data");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt break;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt qid = q - tinfo->queries;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_buffer_usedregion(&lines, &used);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_buffer_clear(&msg);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt result = perf_dns_buildrequest(tinfo->dnsctx,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (isc_textregion_t *) &used,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt qid, config->edns,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->dnssec, config->tsigkey,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &msg);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (result != ISC_R_SUCCESS) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt LOCK(&tinfo->lock);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt query_move(tinfo, q, prepend_unused);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt UNLOCK(&tinfo->lock);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt now = get_time();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt continue;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt base = isc_buffer_base(&msg);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt length = isc_buffer_usedlength(&msg);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt now = get_time();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (config->verbose) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q->desc = strdup(lines.base);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (q->desc == NULL)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("out of memory");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q->timestamp = now;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats->num_sent++;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt n = sendto(q->sock, base, length, 0,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &config->server_addr.type.sa,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->server_addr.length);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (n < 0 || (unsigned int) n != length) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_warning("failed to send packet: %s",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt strerror(errno));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt LOCK(&tinfo->lock);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt query_move(tinfo, q, prepend_unused);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt UNLOCK(&tinfo->lock);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats->num_sent--;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt continue;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats->total_request_size += length;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->done_send_time = get_time();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->done_sending = ISC_TRUE;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt write(mainpipe[1], "", 1);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return NULL;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntprocess_timeouts(threadinfo_t *tinfo, isc_uint64_t now)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt struct query_info *q;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt const config_t *config;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config = tinfo->config;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /* Avoid locking unless we need to. */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q = ISC_LIST_TAIL(tinfo->outstanding_queries);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (q == NULL || q->timestamp > now ||
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt now - q->timestamp < config->timeout)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt LOCK(&tinfo->lock);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt do {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt query_move(tinfo, q, append_unused);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->stats.num_timedout++;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (q->desc != NULL) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_printf("> T %s", q->desc);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt } else {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_printf("[Timeout] %s timed out: msg id %u",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->updates ? "Update" : "Query",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (unsigned int)(q - tinfo->queries));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q = ISC_LIST_TAIL(tinfo->outstanding_queries);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt } while (q != NULL && q->timestamp < now &&
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt now - q->timestamp >= config->timeout);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt UNLOCK(&tinfo->lock);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunttypedef struct {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int sock;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint16_t qid;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint16_t rcode;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int size;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t when;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t sent;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_boolean_t unexpected;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_boolean_t short_response;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt char *desc;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt} received_query_t;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_boolean_t
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntrecv_one(threadinfo_t *tinfo, int which_sock,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned char *packet_buffer, unsigned int packet_size,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt received_query_t *recvd, int *saved_errnop)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint16_t *packet_header;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int s;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t now;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int n;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt packet_header = (isc_uint16_t *) packet_buffer;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt s = tinfo->socks[which_sock];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt n = recv(s, packet_buffer, packet_size, 0);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt now = get_time();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (n < 0) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt *saved_errnop = errno;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return ISC_FALSE;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt recvd->sock = s;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt recvd->qid = ntohs(packet_header[0]);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt recvd->rcode = ntohs(packet_header[1]) & 0xF;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt recvd->size = n;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt recvd->when = now;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt recvd->sent = 0;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt recvd->unexpected = ISC_FALSE;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt recvd->short_response = ISC_TF(n < 4);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt recvd->desc = NULL;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return ISC_TRUE;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic inline void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntbit_set(unsigned char *bits, unsigned int bit)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int shift, mask;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt shift = 7 - (bit % 8);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt mask = 1 << shift;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt bits[bit / 8] |= mask;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic inline isc_boolean_t
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntbit_check(unsigned char *bits, unsigned int bit)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int shift;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt shift = 7 - (bit % 8);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if ((bits[bit / 8] >> shift) & 0x01)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return ISC_TRUE;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return ISC_FALSE;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void *
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntdo_recv(void *arg)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt threadinfo_t *tinfo;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats_t *stats;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned char packet_buffer[MAX_EDNS_PACKET];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt received_query_t recvd[RECV_BATCH_SIZE];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int nrecvd;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int saved_errno;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned char socketbits[MAX_SOCKETS / 8];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t now, latency;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt query_info *q;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int current_socket, last_socket;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int i, j;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo = (threadinfo_t *) arg;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats = &tinfo->stats;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt wait_for_start();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt now = get_time();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt last_socket = 0;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt while (!interrupted) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt process_timeouts(tinfo, now);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * If we're done sending and either all responses have been
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * received, stop.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (tinfo->done_sending && num_outstanding(stats) == 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt break;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Try to receive a few packets, so that we can process them
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * atomically.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt saved_errno = 0;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt memset(socketbits, 0, sizeof(socketbits));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < RECV_BATCH_SIZE; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (j = 0; j < tinfo->nsocks; j++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt current_socket = (j + last_socket) %
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->nsocks;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (bit_check(socketbits, current_socket))
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt continue;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (recv_one(tinfo, current_socket,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt packet_buffer,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt sizeof(packet_buffer),
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &recvd[i], &saved_errno))
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt last_socket = (current_socket + 1);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt break;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt bit_set(socketbits, current_socket);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (saved_errno != EAGAIN)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt break;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (j == tinfo->nsocks)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt break;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt nrecvd = i;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /* Do all of the processing that requires the lock */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt LOCK(&tinfo->lock);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < nrecvd; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (recvd[i].short_response)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt continue;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q = &tinfo->queries[recvd[i].qid];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (q->list != &tinfo->outstanding_queries ||
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q->timestamp == ISC_UINT64_MAX ||
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q->sock != recvd[i].sock)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt recvd[i].unexpected = ISC_TRUE;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt continue;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt query_move(tinfo, q, append_unused);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt recvd[i].sent = q->timestamp;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt recvd[i].desc = q->desc;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q->desc = NULL;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt SIGNAL(&tinfo->cond);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt UNLOCK(&tinfo->lock);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /* Now do the rest of the processing unlocked */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < nrecvd; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (recvd[i].short_response) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_warning("received short response");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt continue;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (recvd[i].unexpected) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_warning("received a response with an "
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "unexpected (maybe timed out) "
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "id: %u", recvd[i].qid);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt continue;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt latency = recvd[i].when - recvd[i].sent;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (recvd[i].desc != NULL) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_printf(
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "> %s %s %u.%06u",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_dns_rcode_strings[recvd[i].rcode],
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt recvd[i].desc,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (unsigned int)(latency / MILLION),
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (unsigned int)(latency % MILLION));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt free(recvd[i].desc);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats->num_completed++;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats->total_response_size += recvd[i].size;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats->rcodecounts[recvd[i].rcode]++;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats->latency_sum += latency;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats->latency_sum_squares += (latency * latency);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (latency < stats->latency_min ||
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats->num_completed == 1)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats->latency_min = latency;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (latency > stats->latency_max)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats->latency_max = latency;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (nrecvd > 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->last_recv = recvd[nrecvd - 1].when;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * If there was an error, handle it (by either ignoring it,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * blocking, or exiting).
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (nrecvd < RECV_BATCH_SIZE) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (saved_errno == EINTR) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt continue;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt } else if (saved_errno == EAGAIN) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_os_waituntilanyreadable(
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->socks,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->nsocks,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt threadpipe[0],
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt TIMEOUT_CHECK_TIME);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt now = get_time();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt continue;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt } else {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("failed to receive packet: %s",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt strerror(saved_errno));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return NULL;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void *
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntdo_interval_stats(void *arg)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt threadinfo_t *tinfo;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats_t total;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t now;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t last_interval_time;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t last_completed;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t interval_time;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t num_completed;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt double qps;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo = arg;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt last_interval_time = tinfo->times->start_time;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt last_completed = 0;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt wait_for_start();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt while (perf_os_waituntilreadable(threadpipe[0], threadpipe[0],
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->config->stats_interval) ==
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_R_TIMEDOUT)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt now = get_time();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt sum_stats(tinfo->config, &total);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt interval_time = now - last_interval_time;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt num_completed = total.num_completed - last_completed;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt qps = num_completed / (((double)interval_time) / MILLION);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_printf("%u.%06u: %.6lf",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (unsigned int)(now / MILLION),
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (unsigned int)(now % MILLION), qps);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt last_interval_time = now;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt last_completed = total.num_completed;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return NULL;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntcancel_queries(threadinfo_t *tinfo)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt struct query_info *q;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt while (ISC_TRUE) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q = ISC_LIST_TAIL(tinfo->outstanding_queries);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (q == NULL)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt break;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt query_move(tinfo, q, append_unused);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (q->timestamp == ISC_UINT64_MAX)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt continue;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->stats.num_interrupted++;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (q->desc != NULL) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_printf("> I %s", q->desc);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt free(q->desc);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q->desc = NULL;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_uint32_t
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntper_thread(isc_uint32_t total, isc_uint32_t nthreads, unsigned int offset)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint32_t value;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt value = total / nthreads;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (value % nthreads > offset)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt value++;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return value;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntthreadinfo_init(threadinfo_t *tinfo, const config_t *config,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt const times_t *times)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int offset, socket_offset, i;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt memset(tinfo, 0, sizeof(*tinfo));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt MUTEX_INIT(&tinfo->lock);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt COND_INIT(&tinfo->cond);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LIST_INIT(tinfo->outstanding_queries);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LIST_INIT(tinfo->unused_queries);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < NQIDS; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LINK_INIT(&tinfo->queries[i], link);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LIST_APPEND(tinfo->unused_queries,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &tinfo->queries[i], link);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->queries[i].list = &tinfo->unused_queries;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt offset = tinfo - threads;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->dnsctx = perf_dns_createctx(config->updates);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->config = config;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->times = times;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Compute per-thread limits based on global values.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->max_outstanding = per_thread(config->max_outstanding,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->threads, offset);
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
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * We can't have more than 64k outstanding queries per thread.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (tinfo->max_outstanding > NQIDS)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->max_outstanding = NQIDS;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (tinfo->nsocks > MAX_SOCKETS)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->nsocks = MAX_SOCKETS;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->socks = isc_mem_get(mctx, tinfo->nsocks * sizeof(int));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (tinfo->socks == NULL)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("out of memory");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt socket_offset = 0;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < offset; i++)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt socket_offset += threads[i].nsocks;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < tinfo->nsocks; i++)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->socks[i] = perf_net_opensocket(&config->server_addr,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &config->local_addr,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt socket_offset++,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config->bufsize);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tinfo->current_sock = 0;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt THREAD(&tinfo->receiver, do_recv, tinfo);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt THREAD(&tinfo->sender, do_send, tinfo);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntthreadinfo_stop(threadinfo_t *tinfo)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt SIGNAL(&tinfo->cond);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt JOIN(tinfo->sender, NULL);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt JOIN(tinfo->receiver, NULL);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntthreadinfo_cleanup(threadinfo_t *tinfo, times_t *times)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int i;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (interrupted)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt cancel_queries(tinfo);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < tinfo->nsocks; i++)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt close(tinfo->socks[i]);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_mem_put(mctx, tinfo->socks, tinfo->nsocks * sizeof(int));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_dns_destroyctx(&tinfo->dnsctx);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (tinfo->last_recv > times->end_time)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt times->end_time = tinfo->last_recv;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntint
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntmain(int argc, char **argv)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt config_t config;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt times_t times;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats_t total_stats;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt threadinfo_t stats_thread;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int i;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_result_t result;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("DNS Performance Testing Tool\n"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "Nominum Version " VERSION "\n\n");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt setup(argc, argv, &config);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (pipe(threadpipe) < 0 || pipe(mainpipe) < 0 ||
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt pipe(intrpipe) < 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("creating pipe");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_datafile_setpipefd(input, threadpipe[0]);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_os_blocksignal(SIGINT, ISC_TRUE);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt print_initial_status(&config);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt threads = isc_mem_get(mctx, config.threads * sizeof(threadinfo_t));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (threads == NULL)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("out of memory");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < config.threads; i++)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt threadinfo_init(&threads[i], &config, &times);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (config.stats_interval > 0) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats_thread.config = &config;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stats_thread.times = &times;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt THREAD(&stats_thread.sender, do_interval_stats, &stats_thread);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt times.start_time = get_time();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (config.timelimit > 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt times.stop_time = times.start_time + config.timelimit;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt else
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt times.stop_time = ISC_UINT64_MAX;
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
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt LOCK(&start_lock);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt started = ISC_TRUE;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt BROADCAST(&start_cond);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt UNLOCK(&start_lock);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_os_handlesignal(SIGINT, handle_sigint);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_os_blocksignal(SIGINT, ISC_FALSE);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt result = perf_os_waituntilreadable(mainpipe[0], intrpipe[0],
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt times.stop_time - times.start_time);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (result == ISC_R_CANCELED)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt interrupted = ISC_TRUE;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt times.end_time = get_time();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt write(threadpipe[1], "", 1);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < config.threads; i++)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt threadinfo_stop(&threads[i]);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (config.stats_interval > 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt JOIN(stats_thread.sender, NULL);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < config.threads; i++)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt threadinfo_cleanup(&threads[i], &times);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt print_final_status(&config);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt sum_stats(&config, &total_stats);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt print_statistics(&config, &times, &total_stats);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_mem_put(mctx, threads, config.threads * sizeof(threadinfo_t));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt cleanup(&config);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return (0);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}