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 Resolution Performance Testing Tool
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ***
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt *** Version $Id: resperf.c 263304 2015-12-15 01:14:10Z bwelling $
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ***/
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <errno.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <stdio.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <stdlib.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <string.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <unistd.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include <sys/time.h>
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/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/result.h>
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include "datafile.h"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include "dns.h"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include "log.h"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include "net.h"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include "opt.h"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include "util.h"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#include "version.h"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Global stuff
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
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_SOCKET_BUFFER 32
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#define DEFAULT_TIMEOUT 45
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#define DEFAULT_MAX_OUTSTANDING (64 * 1024)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#define MAX_INPUT_DATA (4 * 1024)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstruct query_info;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunttypedef ISC_LIST(struct query_info) query_list;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunttypedef struct query_info {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t sent_timestamp;
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 /*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * The list this query is on.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt query_list *list;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt} query_info;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic query_list outstanding_list;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic query_list instanding_list;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic query_info *queries;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_mem_t *mctx;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_sockaddr_t server_addr;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_sockaddr_t local_addr;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic unsigned int nsocks;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic int *socks;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_uint64_t query_timeout;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_boolean_t edns;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_boolean_t dnssec;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic perf_datafile_t *input;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/* The target traffic level at the end of the ramp-up */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntdouble max_qps = 100000.0;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/* The time period over which we ramp up traffic */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#define DEFAULT_RAMP_TIME 60
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_uint64_t ramp_time;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/* How long to send constant traffic after the initial ramp-up */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#define DEFAULT_SUSTAIN_TIME 0
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_uint64_t sustain_time;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/* How long to wait for responses after sending traffic */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_uint64_t wait_time = 40 * MILLION;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/* Total duration of the traffic-sending part of the test */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_uint64_t traffic_time;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/* Total duration of the test */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_uint64_t end_time;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/* Interval between plot data points, in microseconds */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt#define DEFAULT_BUCKET_INTERVAL 0.5
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_uint64_t bucket_interval;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/* The number of plot data points */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic int n_buckets;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/* The plot data file */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic const char *plotfile = "resperf.gnuplot";
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/* The largest acceptable query loss when reporting max throughput */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic double max_loss_percent = 100.0;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/* The maximum number of outstanding queries */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic unsigned int max_outstanding;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_uint64_t num_queries_sent;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_uint64_t num_queries_outstanding;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_uint64_t num_responses_received;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_uint64_t num_queries_timed_out;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_uint64_t rcodecounts[16];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_uint64_t time_now;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_uint64_t time_of_program_start;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_uint64_t time_of_end_of_run;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * The last plot data point containing actual data; this can
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * be less than than (n_buckets - 1) if the traffic sending
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * phase is cut short
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic int last_bucket_used;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * The statistics for queries sent during one bucket_interval
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * of the traffic sending phase.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunttypedef struct {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int queries;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int responses;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int failures;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt double latency_sum;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt} ramp_bucket;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/* Pointer to array of n_buckets ramp_bucket structures */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic ramp_bucket *buckets;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntenum phase {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * The ramp-up phase: we are steadily increasing traffic.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt PHASE_RAMP,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * The sustain phase: we are sending traffic at a constant
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * rate.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt PHASE_SUSTAIN,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * The wait phase: we have stopped sending queries and are
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * just waiting for any remaining responses.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt PHASE_WAIT
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt};
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic enum phase phase = PHASE_RAMP;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/* The time when the sustain/wait phase began */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_uint64_t sustain_phase_began, wait_phase_began;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic perf_dnstsigkey_t *tsigkey;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic char *
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstringify(double value, int precision)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt static char buf[20];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt snprintf(buf, sizeof(buf), "%.*f", precision, value);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return buf;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntsetup(int argc, char **argv)
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_str = NULL;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int sock_family;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int bufsize;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int i;
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 sock_family = AF_UNSPEC;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt server_port = DEFAULT_SERVER_PORT;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt local_port = DEFAULT_LOCAL_PORT;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt bufsize = DEFAULT_SOCKET_BUFFER;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt query_timeout = DEFAULT_TIMEOUT * MILLION;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ramp_time = DEFAULT_RAMP_TIME * MILLION;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt sustain_time = DEFAULT_SUSTAIN_TIME * MILLION;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt bucket_interval = DEFAULT_BUCKET_INTERVAL * MILLION;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt max_outstanding = DEFAULT_MAX_OUTSTANDING;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt nsocks = 1;
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, 0), &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, 0), &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('t', perf_opt_timeval, "timeout",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the timeout for query completion in seconds",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stringify(DEFAULT_TIMEOUT, 0), &query_timeout);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('b', perf_opt_uint, "buffer_size",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "socket send/receive buffer size in kilobytes", NULL,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &bufsize);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('e', perf_opt_boolean, NULL,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "enable EDNS 0", NULL, &edns);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('D', perf_opt_boolean, NULL,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "set the DNSSEC OK bit (implies EDNS)", NULL, &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_str);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('i', perf_opt_timeval, "plot_interval",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the time interval between plot data points, in seconds",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stringify(DEFAULT_BUCKET_INTERVAL, 1), &bucket_interval);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('m', perf_opt_double, "max_qps",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the maximum number of queries per second",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stringify(max_qps, 0), &max_qps);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('P', perf_opt_string, "plotfile",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the name of the plot data file", plotfile, &plotfile);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('r', perf_opt_timeval, "ramp_time",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the ramp-up time in seconds",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stringify(DEFAULT_RAMP_TIME, 0), &ramp_time);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('c', perf_opt_timeval, "constant_traffic_time",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "how long to send constant traffic, in seconds",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stringify(DEFAULT_SUSTAIN_TIME, 0), &sustain_time);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('L', perf_opt_double, "max_query_loss",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the maximum acceptable query loss, in percent",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stringify(max_loss_percent, 0), &max_loss_percent);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('C', perf_opt_uint, "clients",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the number of clients to act as", NULL,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &nsocks);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_add('q', perf_opt_uint, "num_outstanding",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "the maximum number of queries outstanding",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt stringify(DEFAULT_MAX_OUTSTANDING, 0), &max_outstanding);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_opt_parse(argc, argv);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (max_outstanding > nsocks * DEFAULT_MAX_OUTSTANDING)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("number of outstanding packets (%u) must not "
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "be more than 64K per client", max_outstanding);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (ramp_time + sustain_time == 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("rampup_time and constant_traffic_time must not "
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "both be 0");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LIST_INIT(outstanding_list);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LIST_INIT(instanding_list);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt queries = isc_mem_get(mctx, max_outstanding * sizeof(query_info));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (queries == NULL)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("out of memory");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < max_outstanding; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LINK_INIT(&queries[i], link);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LIST_APPEND(instanding_list, &queries[i], link);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt queries[i].list = &instanding_list;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (family != NULL)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt sock_family = perf_net_parsefamily(family);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_net_parseserver(sock_family, server_name, server_port,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &server_addr);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_net_parselocal(isc_sockaddr_pf(&server_addr),
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt local_name, local_port, &local_addr);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt input = perf_datafile_open(mctx, filename);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (dnssec)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt edns = ISC_TRUE;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (tsigkey_str != NULL)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt tsigkey = perf_dns_parsetsigkey(tsigkey_str, mctx);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt socks = isc_mem_get(mctx, nsocks * sizeof(int));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (socks == NULL)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("out of memory");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < nsocks; i++)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt socks[i] = perf_net_opensocket(&server_addr, &local_addr, i,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt bufsize);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntcleanup(void)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int i;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_datafile_close(&input);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < nsocks; i++)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (void) close(socks[i]);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_mem_put(mctx, socks, nsocks * sizeof(int));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_mem_put(mctx, queries, max_outstanding * sizeof(query_info));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_mem_put(mctx, buckets, n_buckets * sizeof(ramp_bucket));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/* Find the ramp_bucket for queries sent at time "when" */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic ramp_bucket *
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntfind_bucket(isc_uint64_t when) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t sent_at = when - time_of_program_start;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int i = (int) ((n_buckets * sent_at) / traffic_time);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Guard against array bounds violations due to roundoff
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * errors or scheduling jitter
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (i < 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt i = 0;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (i > n_buckets - 1)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt i = n_buckets - 1;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return &buckets[i];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * print_statistics:
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Print out statistics based on the results of the test
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntprint_statistics(void) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int i;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt double max_throughput;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt double loss_at_max_throughput;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_boolean_t first_rcode;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t run_time = time_of_end_of_run - time_of_program_start;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("\nStatistics:\n\n");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" Queries sent: %" ISC_PRINT_QUADFORMAT "u\n",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt num_queries_sent);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" Queries completed: %" ISC_PRINT_QUADFORMAT "u\n",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt num_responses_received);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" Queries lost: %" ISC_PRINT_QUADFORMAT "u\n",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt num_queries_sent - num_responses_received);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" Response codes: ");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt first_rcode = ISC_TRUE;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < 16; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (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], rcodecounts[i],
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (rcodecounts[i] * 100.0) / num_responses_received);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("\n");
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
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /* Find the maximum throughput, subject to the -L option */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt max_throughput = 0.0;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt loss_at_max_throughput = 0.0;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i <= last_bucket_used; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ramp_bucket *b = &buckets[i];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt double responses_per_sec =
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt b->responses / (bucket_interval / (double) MILLION);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt double loss = b->queries ?
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (b->queries - b->responses) / (double) b->queries : 0.0;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt double loss_percent = loss * 100.0;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (loss_percent > max_loss_percent)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt break;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (responses_per_sec > max_throughput) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt max_throughput = responses_per_sec;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt loss_at_max_throughput = loss_percent;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" Maximum throughput: %.6lf qps\n", max_throughput);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" Lost at that point: %.2f%%\n", loss_at_max_throughput);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic ramp_bucket *
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntinit_buckets(int n) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ramp_bucket *p;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int i;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt p = isc_mem_get(mctx, n * sizeof(*p));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (p == NULL)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("out of memory");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i < n; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt p[i].queries = p[i].responses = p[i].failures = 0;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt p[i].latency_sum = 0.0;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return p;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Send a query based on a line of input.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Return ISC_R_NOMORE if we ran out of query IDs.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic isc_result_t
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntdo_one_line(isc_buffer_t *lines, isc_buffer_t *msg) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt query_info *q;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int qid;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int sock;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_region_t used;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned char *base;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int length;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_result_t result;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_buffer_clear(lines);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt result = perf_datafile_next(input, lines, ISC_FALSE);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (result != ISC_R_SUCCESS)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("ran out of query data");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_buffer_usedregion(lines, &used);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q = ISC_LIST_HEAD(instanding_list);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (! q)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return (ISC_R_NOMORE);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt qid = (q - queries) / nsocks;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt sock = (q - queries) % nsocks;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_buffer_clear(msg);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt result = perf_dns_buildrequest(NULL, (isc_textregion_t *) &used,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt qid, edns, dnssec, tsigkey, msg);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (result != ISC_R_SUCCESS)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return (result);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q->sent_timestamp = time_now;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt base = isc_buffer_base(msg);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt length = isc_buffer_usedlength(msg);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (sendto(socks[sock], base, length, 0,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt &server_addr.type.sa,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt server_addr.length) < 1)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_warning("failed to send packet: %s",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt strerror(errno));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return (ISC_R_FAILURE);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LIST_UNLINK(instanding_list, q, link);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LIST_PREPEND(outstanding_list, q, link);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q->list = &outstanding_list;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt num_queries_sent++;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt num_queries_outstanding++;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return ISC_R_SUCCESS;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntenter_sustain_phase(void) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt phase = PHASE_SUSTAIN;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (sustain_time != 0.0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("[Status] Ramp-up done, sending constant traffic\n");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt sustain_phase_began = time_now;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntenter_wait_phase(void) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt phase = PHASE_WAIT;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("[Status] Waiting for more responses\n");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt wait_phase_began = time_now;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt/*
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * try_process_response:
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt *
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Receive from the given socket & process an individual response packet.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * Remove it from the list of open queries (status[]) and decrement the
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt * number of outstanding queries if it matches an open query.
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunttry_process_response(unsigned int sockindex) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned char packet_buffer[MAX_EDNS_PACKET];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint16_t *packet_header;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint16_t qid, rcode;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt query_info *q;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt double latency;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ramp_bucket *b;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int n;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt packet_header = (isc_uint16_t *) packet_buffer;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt n = recvfrom(socks[sockindex], packet_buffer, sizeof(packet_buffer),
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt 0, NULL, NULL);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (n < 0) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (errno == EAGAIN || errno == EINTR) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt } else {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("failed to receive packet: %s",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt strerror(errno));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt } else if (n < 4) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_warning("received short response");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt qid = ntohs(packet_header[0]);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt rcode = ntohs(packet_header[1]) & 0xF;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q = &queries[qid * nsocks + sockindex];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (q->list != &outstanding_list) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_warning("received a response with an "
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "unexpected id: %u", qid);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LIST_UNLINK(outstanding_list, q, link);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LIST_APPEND(instanding_list, q, link);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q->list = &instanding_list;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt num_queries_outstanding--;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt latency = (time_now - q->sent_timestamp) / (double)MILLION;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt b = find_bucket(q->sent_timestamp);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt b->responses++;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (!(rcode == dns_rcode_noerror || rcode == dns_rcode_nxdomain))
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt b->failures++;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt b->latency_sum += latency;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt num_responses_received++;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt rcodecounts[rcode]++;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic void
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntretire_old_queries(void)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt query_info *q;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt while (ISC_TRUE) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q = ISC_LIST_TAIL(outstanding_list);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (q == NULL ||
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (time_now - q->sent_timestamp) < query_timeout)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt break;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LIST_UNLINK(outstanding_list, q, link);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LIST_APPEND(instanding_list, q, link);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt q->list = &instanding_list;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt num_queries_outstanding--;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt num_queries_timed_out++;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntstatic inline int
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntnum_scheduled(isc_uint64_t time_since_start)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt{
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (phase == PHASE_RAMP) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return 0.5 * max_qps *
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (double)time_since_start * time_since_start /
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (ramp_time * MILLION);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt } else { /* PHASE_SUSTAIN */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return 0.5 * max_qps * (ramp_time / (double)MILLION) +
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt max_qps *
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (time_since_start - ramp_time) / (double)MILLION;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntint
f3ad877eb05befbc862b0233d985758c0caef29aEvan Huntmain(int argc, char **argv) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int i;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt FILE *plotf;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_buffer_t lines, msg;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt char input_data[MAX_INPUT_DATA];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned char outpacket_buffer[MAX_EDNS_PACKET];
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int max_packet_size;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt unsigned int current_sock;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_result_t result;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("DNS Resolution Performance Testing Tool\n"
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "Nominum Version " VERSION "\n\n");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt setup(argc, argv);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_buffer_init(&lines, input_data, sizeof(input_data));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt max_packet_size = edns ? MAX_EDNS_PACKET : MAX_UDP_PACKET;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_buffer_init(&msg, outpacket_buffer, max_packet_size);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt traffic_time = ramp_time + sustain_time;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt end_time = traffic_time + wait_time;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt n_buckets = (traffic_time + bucket_interval - 1) / bucket_interval;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt buckets = init_buckets(n_buckets);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt time_now = get_time();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt time_of_program_start = time_now;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("[Status] Command line: %s", isc_file_basename(argv[0]));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 1; i < argc; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf(" %s", argv[i]);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("\n");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("[Status] Sending\n");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt current_sock = 0;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (;;) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt int should_send;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt isc_uint64_t time_since_start = time_now -
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt time_of_program_start;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt switch (phase) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt case PHASE_RAMP:
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (time_since_start >= ramp_time)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt enter_sustain_phase();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt break;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt case PHASE_SUSTAIN:
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (time_since_start >= traffic_time)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt enter_wait_phase();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt break;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt case PHASE_WAIT:
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (time_since_start >= end_time ||
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ISC_LIST_EMPTY(outstanding_list))
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt goto end_loop;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt break;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (phase != PHASE_WAIT) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt should_send = num_scheduled(time_since_start) -
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt num_queries_sent;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (should_send >= 1000) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("[Status] Fell behind by %d queries, "
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "ending test at %.0f qps\n",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt should_send,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (max_qps * time_since_start) /
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt ramp_time);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt enter_wait_phase();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (should_send > 0) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt result = do_one_line(&lines, &msg);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (result == ISC_R_SUCCESS)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt find_bucket(time_now)->queries++;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (result == ISC_R_NOMORE) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("[Status] Reached %u outstanding queries\n",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt max_outstanding);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt enter_wait_phase();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt try_process_response(current_sock++);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt current_sock = current_sock % nsocks;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt retire_old_queries();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt time_now = get_time();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt end_loop:
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt time_now = get_time();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt time_of_end_of_run = time_now;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt printf("[Status] Testing complete\n");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt plotf = fopen(plotfile, "w");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (! plotf) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt perf_log_fatal("could not open %s: %s", plotfile,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt strerror(errno));
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /* Print column headers */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt fprintf(plotf, "# time target_qps actual_qps "
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "responses_per_sec failures_per_sec "
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt "avg_latency\n");
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /* Don't print unused buckets */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt last_bucket_used = find_bucket(wait_phase_began) - buckets;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt /* Don't print a partial bucket at the end */
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt if (last_bucket_used > 0)
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt --last_bucket_used;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt for (i = 0; i <= last_bucket_used; i++) {
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt double t = (i + 0.5) * traffic_time /
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt (n_buckets * (double)MILLION);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt double ramp_dtime = ramp_time / (double)MILLION;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt double target_qps =
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt t <= ramp_dtime ? (t / ramp_dtime) * max_qps : max_qps;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt double latency = buckets[i].responses ?
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt buckets[i].latency_sum / buckets[i].responses : 0;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt double interval = bucket_interval / (double) MILLION;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt fprintf(plotf, "%7.3f %8.2f %8.2f %8.2f %8.2f %8.6f\n",
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt t,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt target_qps,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt buckets[i].queries / interval,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt buckets[i].responses / interval,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt buckets[i].failures / interval,
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt latency);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt }
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt fclose(plotf);
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt print_statistics();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt cleanup();
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt return 0;
f3ad877eb05befbc862b0233d985758c0caef29aEvan Hunt}