2005-02-15 04:55:56 +00:00
/*
Unix SMB / CIFS implementation .
WINS benchmark test
Copyright ( C ) Andrew Tridgell 2005
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2005-02-15 04:55:56 +00:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 02:07:03 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-02-15 04:55:56 +00:00
*/
# include "includes.h"
# include "lib/events/events.h"
# include "lib/socket/socket.h"
2006-03-07 11:07:23 +00:00
# include "libcli/resolve/resolve.h"
# include "system/network.h"
2006-08-17 13:37:04 +00:00
# include "lib/socket/netif.h"
2006-03-25 16:01:28 +00:00
# include "torture/torture.h"
2006-10-16 13:06:41 +00:00
# include "torture/nbt/proto.h"
2007-12-06 16:26:56 +01:00
# include "param/param.h"
2005-02-15 04:55:56 +00:00
struct wins_state {
int num_names ;
2006-10-16 13:06:41 +00:00
bool * registered ;
2005-02-15 04:55:56 +00:00
int pass_count ;
int fail_count ;
const char * wins_server ;
2007-12-07 03:01:41 +01:00
uint16_t wins_port ;
2005-02-15 04:55:56 +00:00
const char * my_ip ;
uint32_t ttl ;
} ;
struct idx_state {
int idx ;
struct wins_state * state ;
} ;
2007-07-10 11:37:30 +00:00
static struct nbt_name generate_name ( TALLOC_CTX * tctx , int idx )
2005-02-15 04:55:56 +00:00
{
struct nbt_name name ;
2006-10-16 13:06:41 +00:00
name . name = talloc_asprintf ( tctx , " WINSBench%6u " , idx ) ;
2005-02-15 04:55:56 +00:00
name . type = 0x4 ;
name . scope = NULL ;
return name ;
}
static void register_handler ( struct nbt_name_request * req )
{
2008-09-23 09:02:16 +02:00
struct idx_state * istate = talloc_get_type ( req - > async . private_data , struct idx_state ) ;
2005-02-15 04:55:56 +00:00
struct wins_state * state = istate - > state ;
struct nbt_name_register io ;
NTSTATUS status ;
status = nbt_name_register_recv ( req , istate , & io ) ;
if ( ! NT_STATUS_IS_OK ( status ) | | io . out . rcode ! = NBT_RCODE_OK ) {
state - > fail_count + + ;
} else {
state - > pass_count + + ;
2006-10-16 13:06:41 +00:00
state - > registered [ istate - > idx ] = true ;
2005-02-15 04:55:56 +00:00
}
talloc_free ( istate ) ;
}
/*
generate a registration
*/
static void generate_register ( struct nbt_name_socket * nbtsock , struct wins_state * state , int idx )
{
struct nbt_name_register io ;
TALLOC_CTX * tmp_ctx = talloc_new ( state ) ;
struct nbt_name_request * req ;
struct idx_state * istate ;
istate = talloc ( nbtsock , struct idx_state ) ;
istate - > idx = idx ;
istate - > state = state ;
io . in . name = generate_name ( tmp_ctx , idx ) ;
io . in . dest_addr = state - > wins_server ;
2007-12-12 02:15:20 +01:00
io . in . dest_port = state - > wins_port ;
2005-02-15 04:55:56 +00:00
io . in . address = state - > my_ip ;
io . in . nb_flags = NBT_NODE_H ;
2006-10-16 13:06:41 +00:00
io . in . register_demand = false ;
io . in . broadcast = false ;
io . in . multi_homed = false ;
2005-02-15 04:55:56 +00:00
io . in . ttl = state - > ttl ;
io . in . timeout = 2 ;
io . in . retries = 1 ;
req = nbt_name_register_send ( nbtsock , & io ) ;
req - > async . fn = register_handler ;
2008-09-23 09:02:16 +02:00
req - > async . private_data = istate ;
2005-02-15 04:55:56 +00:00
talloc_free ( tmp_ctx ) ;
}
static void release_handler ( struct nbt_name_request * req )
{
2008-09-23 09:02:16 +02:00
struct idx_state * istate = talloc_get_type ( req - > async . private_data , struct idx_state ) ;
2005-02-15 04:55:56 +00:00
struct wins_state * state = istate - > state ;
struct nbt_name_release io ;
NTSTATUS status ;
status = nbt_name_release_recv ( req , istate , & io ) ;
if ( state - > registered [ istate - > idx ] & &
( ! NT_STATUS_IS_OK ( status ) | | io . out . rcode ! = NBT_RCODE_OK ) ) {
state - > fail_count + + ;
} else {
state - > pass_count + + ;
2006-10-16 13:06:41 +00:00
state - > registered [ istate - > idx ] = false ;
2005-02-15 04:55:56 +00:00
}
talloc_free ( istate ) ;
}
/*
2005-02-15 11:14:04 +00:00
generate a name release
2005-02-15 04:55:56 +00:00
*/
static void generate_release ( struct nbt_name_socket * nbtsock , struct wins_state * state , int idx )
{
struct nbt_name_release io ;
TALLOC_CTX * tmp_ctx = talloc_new ( state ) ;
struct nbt_name_request * req ;
struct idx_state * istate ;
istate = talloc ( nbtsock , struct idx_state ) ;
istate - > idx = idx ;
istate - > state = state ;
io . in . name = generate_name ( tmp_ctx , idx ) ;
2007-12-13 11:41:47 +01:00
io . in . dest_port = state - > wins_port ;
2005-02-15 04:55:56 +00:00
io . in . dest_addr = state - > wins_server ;
io . in . address = state - > my_ip ;
io . in . nb_flags = NBT_NODE_H ;
2006-10-16 13:06:41 +00:00
io . in . broadcast = false ;
2005-02-15 04:55:56 +00:00
io . in . timeout = 2 ;
io . in . retries = 1 ;
req = nbt_name_release_send ( nbtsock , & io ) ;
req - > async . fn = release_handler ;
2008-09-23 09:02:16 +02:00
req - > async . private_data = istate ;
2005-02-15 04:55:56 +00:00
talloc_free ( tmp_ctx ) ;
}
static void query_handler ( struct nbt_name_request * req )
{
2008-09-23 09:02:16 +02:00
struct idx_state * istate = talloc_get_type ( req - > async . private_data , struct idx_state ) ;
2005-02-15 04:55:56 +00:00
struct wins_state * state = istate - > state ;
struct nbt_name_query io ;
NTSTATUS status ;
status = nbt_name_query_recv ( req , istate , & io ) ;
if ( ! NT_STATUS_IS_OK ( status ) & & state - > registered [ istate - > idx ] ) {
state - > fail_count + + ;
} else {
state - > pass_count + + ;
}
talloc_free ( istate ) ;
}
/*
generate a name query
*/
static void generate_query ( struct nbt_name_socket * nbtsock , struct wins_state * state , int idx )
{
struct nbt_name_query io ;
TALLOC_CTX * tmp_ctx = talloc_new ( state ) ;
struct nbt_name_request * req ;
struct idx_state * istate ;
istate = talloc ( nbtsock , struct idx_state ) ;
istate - > idx = idx ;
istate - > state = state ;
io . in . name = generate_name ( tmp_ctx , idx ) ;
io . in . dest_addr = state - > wins_server ;
2007-12-07 03:01:41 +01:00
io . in . dest_port = state - > wins_port ;
2006-10-16 13:06:41 +00:00
io . in . broadcast = false ;
io . in . wins_lookup = true ;
2005-02-15 04:55:56 +00:00
io . in . timeout = 2 ;
io . in . retries = 1 ;
req = nbt_name_query_send ( nbtsock , & io ) ;
req - > async . fn = query_handler ;
2008-09-23 09:02:16 +02:00
req - > async . private_data = istate ;
2005-02-15 04:55:56 +00:00
talloc_free ( tmp_ctx ) ;
}
/*
generate one WINS request
*/
static void generate_request ( struct nbt_name_socket * nbtsock , struct wins_state * state , int idx )
{
if ( random ( ) % 5 = = 0 ) {
generate_register ( nbtsock , state , idx ) ;
return ;
}
if ( random ( ) % 20 = = 0 ) {
generate_release ( nbtsock , state , idx ) ;
return ;
}
generate_query ( nbtsock , state , idx ) ;
}
/*
benchmark simple name queries
*/
2006-10-16 13:06:41 +00:00
static bool bench_wins ( struct torture_context * tctx )
2005-02-15 04:55:56 +00:00
{
2010-05-09 17:20:01 +02:00
struct nbt_name_socket * nbtsock = nbt_name_socket_init ( tctx , tctx - > ev ) ;
2005-02-15 04:55:56 +00:00
int num_sent = 0 ;
struct timeval tv = timeval_current ( ) ;
2006-10-16 13:06:41 +00:00
bool ret = true ;
2007-04-17 22:35:01 +00:00
int timelimit = torture_setting_int ( tctx , " timelimit " , 5 ) ;
2005-02-15 04:55:56 +00:00
struct wins_state * state ;
extern int torture_entries ;
2006-01-09 22:12:53 +00:00
struct socket_address * my_ip ;
2006-10-16 13:06:41 +00:00
struct nbt_name name ;
const char * address ;
2007-12-11 22:23:14 +01:00
struct interface * ifaces ;
2006-10-16 13:06:41 +00:00
if ( ! torture_nbt_get_name ( tctx , & name , & address ) )
return false ;
2005-02-15 04:55:56 +00:00
state = talloc_zero ( nbtsock , struct wins_state ) ;
state - > num_names = torture_entries ;
2006-10-16 13:06:41 +00:00
state - > registered = talloc_zero_array ( state , bool , state - > num_names ) ;
2005-02-15 04:55:56 +00:00
state - > wins_server = address ;
2010-07-16 14:32:42 +10:00
state - > wins_port = lpcfg_nbt_port ( tctx - > lp_ctx ) ;
load_interfaces ( tctx , lpcfg_interfaces ( tctx - > lp_ctx ) , & ifaces ) ;
2007-12-11 22:23:14 +01:00
state - > my_ip = talloc_strdup ( tctx , iface_best_ip ( ifaces , address ) ) ;
2005-02-15 04:55:56 +00:00
state - > ttl = timelimit ;
2006-01-09 22:12:53 +00:00
my_ip = socket_address_from_strings ( nbtsock , nbtsock - > sock - > backend_name ,
state - > my_ip , 0 ) ;
socket_listen ( nbtsock - > sock , my_ip , 0 , 0 ) ;
2005-02-15 04:55:56 +00:00
2006-10-16 13:06:41 +00:00
torture_comment ( tctx , " Running for %d seconds \n " , timelimit ) ;
2005-02-15 04:55:56 +00:00
while ( timeval_elapsed ( & tv ) < timelimit ) {
while ( num_sent - ( state - > pass_count + state - > fail_count ) < 10 ) {
generate_request ( nbtsock , state , num_sent % state - > num_names ) ;
num_sent + + ;
if ( num_sent % 50 = = 0 ) {
2007-04-29 21:37:29 +00:00
if ( torture_setting_bool ( tctx , " progress " , true ) ) {
torture_comment ( tctx , " %.1f queries per second (%d failures) \r " ,
state - > pass_count / timeval_elapsed ( & tv ) ,
state - > fail_count ) ;
fflush ( stdout ) ;
}
2005-02-15 04:55:56 +00:00
}
}
event_loop_once ( nbtsock - > event_ctx ) ;
}
while ( num_sent ! = ( state - > pass_count + state - > fail_count ) ) {
event_loop_once ( nbtsock - > event_ctx ) ;
}
2006-10-16 13:06:41 +00:00
torture_comment ( tctx , " %.1f queries per second (%d failures) \n " ,
2005-02-15 04:55:56 +00:00
state - > pass_count / timeval_elapsed ( & tv ) ,
state - > fail_count ) ;
talloc_free ( nbtsock ) ;
return ret ;
}
/*
benchmark how fast a WINS server can respond to a mixture of
registration / refresh / release and name query requests
*/
2007-09-07 16:27:57 +00:00
struct torture_suite * torture_bench_wins ( TALLOC_CTX * mem_ctx )
2005-02-15 04:55:56 +00:00
{
2007-09-07 16:27:57 +00:00
struct torture_suite * suite = torture_suite_create ( mem_ctx ,
" BENCH-WINS " ) ;
2005-02-15 04:55:56 +00:00
2006-10-16 13:06:41 +00:00
torture_suite_add_simple_test ( suite , " wins " , bench_wins ) ;
2005-02-15 04:55:56 +00:00
2006-10-16 13:06:41 +00:00
return suite ;
2005-02-15 04:55:56 +00:00
}