Line data Source code
1 : /* 2 : Unix SMB/CIFS implementation. 3 : 4 : NBT name query testing 5 : 6 : Copyright (C) Andrew Tridgell 2005 7 : 8 : This program is free software; you can redistribute it and/or modify 9 : it under the terms of the GNU General Public License as published by 10 : the Free Software Foundation; either version 3 of the License, or 11 : (at your option) any later version. 12 : 13 : This program is distributed in the hope that it will be useful, 14 : but WITHOUT ANY WARRANTY; without even the implied warranty of 15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 : GNU General Public License for more details. 17 : 18 : You should have received a copy of the GNU General Public License 19 : along with this program. If not, see <http://www.gnu.org/licenses/>. 20 : */ 21 : 22 : #include "includes.h" 23 : #include "lib/events/events.h" 24 : #include "libcli/resolve/resolve.h" 25 : #include "torture/torture.h" 26 : #include "torture/nbt/proto.h" 27 : #include "param/param.h" 28 : 29 : struct result_struct { 30 : int num_pass; 31 : int num_fail; 32 : }; 33 : 34 0 : static void increment_handler(struct nbt_name_request *req) 35 : { 36 0 : struct result_struct *v = talloc_get_type(req->async.private_data, struct result_struct); 37 0 : if (req->state != NBT_REQUEST_DONE) { 38 0 : v->num_fail++; 39 : } else { 40 0 : v->num_pass++; 41 : } 42 0 : talloc_free(req); 43 0 : } 44 : 45 : /* 46 : benchmark simple name queries 47 : */ 48 0 : static bool bench_namequery(struct torture_context *tctx) 49 : { 50 0 : struct nbt_name_socket *nbtsock = torture_init_nbt_socket(tctx); 51 0 : int num_sent=0; 52 0 : struct result_struct *result; 53 0 : struct nbt_name_query io; 54 0 : struct timeval tv = timeval_current(); 55 0 : int timelimit = torture_setting_int(tctx, "timelimit", 5); 56 : 57 0 : const char *address; 58 0 : struct nbt_name name; 59 : 60 0 : if (!torture_nbt_get_name(tctx, &name, &address)) 61 0 : return false; 62 : 63 0 : io.in.name = name; 64 0 : io.in.dest_addr = address; 65 0 : io.in.dest_port = lpcfg_nbt_port(tctx->lp_ctx); 66 0 : io.in.broadcast = false; 67 0 : io.in.wins_lookup = false; 68 0 : io.in.timeout = 1; 69 : 70 0 : result = talloc_zero(tctx, struct result_struct); 71 : 72 0 : torture_comment(tctx, "Running for %d seconds\n", timelimit); 73 0 : while (timeval_elapsed(&tv) < timelimit) { 74 0 : while (num_sent - (result->num_pass+result->num_fail) < 10) { 75 0 : struct nbt_name_request *req; 76 0 : req = nbt_name_query_send(nbtsock, &io); 77 0 : torture_assert(tctx, req != NULL, "Failed to setup request!"); 78 0 : req->async.fn = increment_handler; 79 0 : req->async.private_data = result; 80 0 : num_sent++; 81 0 : if (num_sent % 1000 == 0) { 82 0 : if (torture_setting_bool(tctx, "progress", true)) { 83 0 : torture_comment(tctx, "%.1f queries per second (%d failures) \r", 84 0 : result->num_pass / timeval_elapsed(&tv), 85 : result->num_fail); 86 0 : fflush(stdout); 87 : } 88 : } 89 : } 90 : 91 0 : tevent_loop_once(nbtsock->event_ctx); 92 : } 93 : 94 0 : while (num_sent != (result->num_pass + result->num_fail)) { 95 0 : tevent_loop_once(nbtsock->event_ctx); 96 : } 97 : 98 0 : torture_comment(tctx, "%.1f queries per second (%d failures) \n", 99 0 : result->num_pass / timeval_elapsed(&tv), 100 : result->num_fail); 101 : 102 0 : return true; 103 : } 104 : 105 : 106 : /* 107 : benchmark how fast a server can respond to name queries 108 : */ 109 2354 : struct torture_suite *torture_bench_nbt(TALLOC_CTX *mem_ctx) 110 : { 111 2354 : struct torture_suite *suite = torture_suite_create(mem_ctx, "bench"); 112 2354 : torture_suite_add_simple_test(suite, "namequery", bench_namequery); 113 : 114 2354 : return suite; 115 : }