r5408: - added testing for the behaviour of the special 0x1c name
[Samba/gebeck_regimport.git] / source4 / torture / nbt / winsbench.c
blobf6a6283dd245cc89bdc2b350b6f906d0518d0770
1 /*
2 Unix SMB/CIFS implementation.
4 WINS benchmark test
6 Copyright (C) Andrew Tridgell 2005
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 2 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
24 #include "lib/events/events.h"
25 #include "libcli/nbt/libnbt.h"
26 #include "librpc/gen_ndr/ndr_nbt.h"
27 #include "lib/socket/socket.h"
29 struct wins_state {
30 int num_names;
31 BOOL *registered;
32 int pass_count;
33 int fail_count;
34 const char *wins_server;
35 const char *my_ip;
36 uint32_t ttl;
39 struct idx_state {
40 int idx;
41 struct wins_state *state;
44 struct nbt_name generate_name(TALLOC_CTX *mem_ctx, int idx)
46 struct nbt_name name;
47 name.name = talloc_asprintf(mem_ctx, "WINSBench%6u", idx);
48 name.type = 0x4;
49 name.scope = NULL;
50 return name;
53 static void register_handler(struct nbt_name_request *req)
55 struct idx_state *istate = talloc_get_type(req->async.private, struct idx_state);
56 struct wins_state *state = istate->state;
57 struct nbt_name_register io;
58 NTSTATUS status;
60 status = nbt_name_register_recv(req, istate, &io);
61 if (!NT_STATUS_IS_OK(status) || io.out.rcode != NBT_RCODE_OK) {
62 state->fail_count++;
63 } else {
64 state->pass_count++;
65 state->registered[istate->idx] = True;
67 talloc_free(istate);
71 generate a registration
73 static void generate_register(struct nbt_name_socket *nbtsock, struct wins_state *state, int idx)
75 struct nbt_name_register io;
76 TALLOC_CTX *tmp_ctx = talloc_new(state);
77 struct nbt_name_request *req;
78 struct idx_state *istate;
80 istate = talloc(nbtsock, struct idx_state);
81 istate->idx = idx;
82 istate->state = state;
84 io.in.name = generate_name(tmp_ctx, idx);
85 io.in.dest_addr = state->wins_server;
86 io.in.address = state->my_ip;
87 io.in.nb_flags = NBT_NODE_H;
88 io.in.register_demand = False;
89 io.in.broadcast = False;
90 io.in.multi_homed = False;
91 io.in.ttl = state->ttl;
92 io.in.timeout = 2;
93 io.in.retries = 1;
95 req = nbt_name_register_send(nbtsock, &io);
97 req->async.fn = register_handler;
98 req->async.private = istate;
100 talloc_free(tmp_ctx);
104 static void release_handler(struct nbt_name_request *req)
106 struct idx_state *istate = talloc_get_type(req->async.private, struct idx_state);
107 struct wins_state *state = istate->state;
108 struct nbt_name_release io;
109 NTSTATUS status;
111 status = nbt_name_release_recv(req, istate, &io);
112 if (state->registered[istate->idx] &&
113 (!NT_STATUS_IS_OK(status) || io.out.rcode != NBT_RCODE_OK)) {
114 state->fail_count++;
115 } else {
116 state->pass_count++;
117 state->registered[istate->idx] = False;
119 talloc_free(istate);
123 generate a name release
125 static void generate_release(struct nbt_name_socket *nbtsock, struct wins_state *state, int idx)
127 struct nbt_name_release io;
128 TALLOC_CTX *tmp_ctx = talloc_new(state);
129 struct nbt_name_request *req;
130 struct idx_state *istate;
132 istate = talloc(nbtsock, struct idx_state);
133 istate->idx = idx;
134 istate->state = state;
136 io.in.name = generate_name(tmp_ctx, idx);
137 io.in.dest_addr = state->wins_server;
138 io.in.address = state->my_ip;
139 io.in.nb_flags = NBT_NODE_H;
140 io.in.broadcast = False;
141 io.in.timeout = 2;
142 io.in.retries = 1;
144 req = nbt_name_release_send(nbtsock, &io);
146 req->async.fn = release_handler;
147 req->async.private = istate;
149 talloc_free(tmp_ctx);
153 static void query_handler(struct nbt_name_request *req)
155 struct idx_state *istate = talloc_get_type(req->async.private, struct idx_state);
156 struct wins_state *state = istate->state;
157 struct nbt_name_query io;
158 NTSTATUS status;
160 status = nbt_name_query_recv(req, istate, &io);
161 if (!NT_STATUS_IS_OK(status) && state->registered[istate->idx]) {
162 state->fail_count++;
163 } else {
164 state->pass_count++;
166 talloc_free(istate);
170 generate a name query
172 static void generate_query(struct nbt_name_socket *nbtsock, struct wins_state *state, int idx)
174 struct nbt_name_query io;
175 TALLOC_CTX *tmp_ctx = talloc_new(state);
176 struct nbt_name_request *req;
177 struct idx_state *istate;
179 istate = talloc(nbtsock, struct idx_state);
180 istate->idx = idx;
181 istate->state = state;
183 io.in.name = generate_name(tmp_ctx, idx);
184 io.in.dest_addr = state->wins_server;
185 io.in.broadcast = False;
186 io.in.wins_lookup = True;
187 io.in.timeout = 2;
188 io.in.retries = 1;
190 req = nbt_name_query_send(nbtsock, &io);
192 req->async.fn = query_handler;
193 req->async.private = istate;
195 talloc_free(tmp_ctx);
199 generate one WINS request
201 static void generate_request(struct nbt_name_socket *nbtsock, struct wins_state *state, int idx)
203 if (random() % 5 == 0) {
204 generate_register(nbtsock, state, idx);
205 return;
208 if (random() % 20 == 0) {
209 generate_release(nbtsock, state, idx);
210 return;
213 generate_query(nbtsock, state, idx);
217 benchmark simple name queries
219 static BOOL bench_wins(TALLOC_CTX *mem_ctx, struct nbt_name *name, const char *address)
221 struct nbt_name_socket *nbtsock = nbt_name_socket_init(mem_ctx, NULL);
222 int num_sent=0;
223 struct timeval tv = timeval_current();
224 BOOL ret = True;
225 int timelimit = lp_parm_int(-1, "torture", "timelimit", 10);
226 struct wins_state *state;
227 extern int torture_entries;
229 state = talloc_zero(nbtsock, struct wins_state);
231 state->num_names = torture_entries;
232 state->registered = talloc_zero_array(state, BOOL, state->num_names);
233 state->wins_server = address;
234 state->my_ip = talloc_strdup(mem_ctx, iface_n_ip(0));
235 state->ttl = timelimit;
237 socket_listen(nbtsock->sock, state->my_ip, 0, 0, 0);
239 printf("Running for %d seconds\n", timelimit);
240 while (timeval_elapsed(&tv) < timelimit) {
241 while (num_sent - (state->pass_count+state->fail_count) < 10) {
242 generate_request(nbtsock, state, num_sent % state->num_names);
243 num_sent++;
244 if (num_sent % 50 == 0) {
245 printf("%.1f queries per second (%d failures) \r",
246 state->pass_count / timeval_elapsed(&tv),
247 state->fail_count);
251 event_loop_once(nbtsock->event_ctx);
254 while (num_sent != (state->pass_count + state->fail_count)) {
255 event_loop_once(nbtsock->event_ctx);
258 printf("%.1f queries per second (%d failures) \n",
259 state->pass_count / timeval_elapsed(&tv),
260 state->fail_count);
262 talloc_free(nbtsock);
263 return ret;
268 benchmark how fast a WINS server can respond to a mixture of
269 registration/refresh/release and name query requests
271 BOOL torture_bench_wins(void)
273 const char *address;
274 struct nbt_name name;
275 TALLOC_CTX *mem_ctx = talloc_new(NULL);
276 NTSTATUS status;
277 BOOL ret = True;
279 name.name = lp_parm_string(-1, "torture", "host");
280 name.type = NBT_NAME_SERVER;
281 name.scope = NULL;
283 /* do an initial name resolution to find its IP */
284 status = resolve_name(&name, mem_ctx, &address);
285 if (!NT_STATUS_IS_OK(status)) {
286 printf("Failed to resolve %s - %s\n",
287 name.name, nt_errstr(status));
288 talloc_free(mem_ctx);
289 return False;
292 ret &= bench_wins(mem_ctx, &name, address);
294 talloc_free(mem_ctx);
296 return ret;