/* * testcode/perf.c - debug program to estimate name server performance. * * Copyright (c) 2008, NLnet Labs. All rights reserved. * * This software is open source. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the NLNET LABS nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /** * \file * * This program estimates DNS name server performance. */ #include "config.h" #include "util/log.h" #include "util/locks.h" #include "util/netevent.h" /** usage information for perf */ static void usage(char* argv[]) { printf("usage: %s [options] server\n", argv[0]); printf("server: ip address of server, IP4 or IP6.\n"); printf(" If not on port %d add @port.\n", UNBOUND_DNS_PORT); exit(1); } struct perfinfo; struct perfio; /** Global info for perf */ struct perfinfo { /** communication base */ struct comm_base* base; /** timer to send out new queries */ struct comm_timer* sendout_timer; /** all purpose buffer */ ldns_buffer* udpbuffer; /** destination */ struct sockaddr_storage dest; /** length of dest socket addr */ socklen_t destlen; /** number of seconds elapsed in total */ struct timeval time_cumul; /** number of queries received in that time */ size_t numrecv; /** number of queries sent out in that time */ size_t numsent; /** numbers by rcode */ size_t by_rcode[32]; /** number of I/O ports */ size_t io_num; /** I/O ports array */ struct perfio* io; /** size of querylist */ size_t qlist_size; /** list of query packets (data) */ uint8_t** qlist_data; /** list of query packets (length of a packet) */ size_t** qlist_len; /** index into querylist, for walking the list */ size_t qlist_idx; }; /** I/O port for perf */ struct perfio { /** id number */ int id; /** file descriptor of socket */ int fd; /** ptr back to perfinfo */ struct perfinfo* info; }; /** setup perf test environment */ static void perfsetup(struct perfinfo* info, struct sockaddr_storage* dest, socklen_t destlen) { info->base = comm_base_create(); if(!info->base) fatal_exit("out of memory"); info->sendout_timer = comm_timer_create(...); if(!info->sendout_timer) fatal_exit("out of memory"); info->udpbuffer = ldns_buffer_new(65553); if(!info->udpbuffer) fatal_exit("out of memory"); } /** cleanup perf test environment */ static void perffree(struct perfinfo* info) { comm_timer_delete(info->sendout_timer); comm_base_free(info->base); ldns_buffer_free(info->udpbuffer); } /** perform the performance test */ static void perfmain(struct perfinfo* info) { perfsetup(info, dest, destlen); comm_base_dispatch(info->base); perffree(info); } /** getopt global, in case header files fail to declare it. */ extern int optind; /** getopt global, in case header files fail to declare it. */ extern char* optarg; /** main program for perf */ int main(int argc, char* argv[]) { int c; struct perfinfo info; /* defaults */ memset(&info, 0, sizeof(info)); info.io_num = 16; log_init(NULL, 0, NULL); checklock_start(); /* parse the options */ while( (c=getopt(argc, argv, "h")) != -1) { switch(c) { case '?': case 'h': default: usage(); } } argc -= optind; argv += optind; if(argc != 1) usage(); if(!extstrtoaddr(argv[0], &info->dest, &info->destlen)) { printf("Could not parse ip: %s\n", argv[0]); return 1; } /* do the performance test */ perf_main(&dest, destlen); checklock_stop(); return 0; }