#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
/*内部宏声明*/
#define HOSTNAMESIZE 255
#define PORTBUFSIZE 10
#define TESTNAMESIZE 15
#define MAXSPECDATA 62
#define DO_TCP_STREAM 22
#define TCP_STREAM_ECHO 21
#define NO_CPU_MEASURE 0
#define NO_CPU_RATE 0
#define NO_DELAY 0
#define NO_RCVAVOID 0
#define NO_SNDAVOID 0
#define SIGALRM 14
/*定义变量类型*/
typedef unsigned char u8;
typedef unsigned short int u16;
typedef unsigned long int u32;
/*for socket create*/
#define DEBUG_INFO
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define SOCKET int
#ifndef AF_NORMAL
#define AF_NORMAL AF_INET
#endif
SOCKET control_sock = INVALID_SOCKET;
SOCKET server_sock = INVALID_SOCKET;
/*error type*/
#define NOR_ERROR -1
#define SOCK_ERROR -1
/*define send and recv*/
#define SEND_SIZE 1
#define RECV_SIZE 0
/*内部全局变量声明*/
char rem_host_name[HOSTNAMESIZE];
char local_host_name[HOSTNAMESIZE];
char test_name[TESTNAMESIZE];
char rem_port[PORTBUFSIZE];
char local_port[PORTBUFSIZE];
int rem_addr_family;
int local_addr_family;
unsigned int test_time;
unsigned int test_len_ticks;
unsigned int test_size;
char *client_name = NULL;
FILE *where = stdout;
union netbench_request_struct netbench_request;
union netbench_response_struct netbench_response;
char local_data_port[PORTBUFSIZE];
char rem_data_port[PORTBUFSIZE];
int
local_recv_align, /* alignment for local receives */
local_send_align, /* alignment for local sends */
local_send_offset = 0,
local_recv_offset = 0,
remote_recv_align, /* alignment for remote receives */
remote_send_align, /* alignment for remote sends */
remote_send_offset = 0,
remote_recv_offset = 0;
/*define dirty varibles*/
#ifdef DIRTY
int loc_dirty_count;
int loc_clean_count;
int rem_dirty_count;
int rem_clean_count;
#endif
u16 iteration_min;
u16 iteration_max;
u16 confidence_iteration;
double confidence;
u16 times_up;
/*define send and recv size vairables*/
static int ls_size_req,
lr_size_req,
ls_size,
lr_size,
rs_size_req,
rr_size_req,
rs_size,
rr_size;
struct timeval time_begin, time_stop;
float lib_elapsed;
char libfmt = 'm';
/*内部结构体声明*/
/*struct addrinfo*/
struct addrinfo {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
socklen_t ai_addrlen;
struct sockaddr *ai_addr;
};
struct tcp_stream_request_struct {
int send_buf_size;
int recv_buf_size; /* how big does the client want it - the */
/* receive socket buffer that is */
int receive_size; /* how many bytes do we want to receive at one */
/* time? */
int recv_alignment; /* what is the alignment of the receive */
/* buffer? */
int recv_offset; /* and at what offset from that alignment? */
int no_delay; /* do we disable the nagle algorithm for send */
/* coalescing? */
int measure_cpu; /* does the client want server cpu utilization */
/* measured? */
float cpu_rate; /* do we know how fast the cpu is already? */
int test_length; /* how long is the test? */
int so_rcvavoid; /* do we want the remote to avoid copies on */
/* receives? */
int so_sndavoid; /* do we want the remote to avoid send copies? */
int dirty_count; /* how many integers in the receive buffer */
/* should be made dirty before calling recv? */
int clean_count; /* how many integers should be read from the */
/* recv buffer before calling recv? */
int port; /* the port to which the recv side should bind
to allow netperf to run through those evil
firewall things */
int ipfamily; /* the address family of ipaddress */
};
struct tcp_stream_response_struct {
int recv_buf_size; /* how big does the client want it */
int receive_size;
int no_delay;
int measure_cpu; /* does the client want server cpu */
int test_length; /* how long is the test? */
int send_buf_size;
int data_port_number; /* connect to me here */
float cpu_rate; /* could we measure */
int so_rcvavoid; /* could the remote avoid receive copies? */
int so_sndavoid; /* could the remote avoid send copies? */
};
struct tcp_stream_results_struct {
double bytes_received;
unsigned int recv_calls;
float elapsed_time; /* how long the test ran */
float cpu_util; /* -1 if not measured */
float serv_dem; /* -1 if not measured */
int cpu_method; /* how was cpu util measured? */
int num_cpus; /* how many CPUs had the remote? */
};
union netbench_request_struct {
struct {
int request_type;
int dummy;
int test_specific_data[MAXSPECDATA];
} content;
double dummy;
};
union netbench_response_struct {
struct {
int response_type;
int serv_errno;
int test_specific_data[MAXSPECDATA];
} content;
double dummy;
};
struct ring_elt {
struct ring_elt *next; /* next element in the ring */
char *buffer_base; /* in case we have to free it at somepoint */
char *buffer_ptr; /* the aligned and offset pointer */
};
/*内部函数声明*/
void set_opt_defaults();
void set_user_opt(int argc, char **argv);
int getopt(int argc, char **argv);
unsigned int convert(char *string);
void usage();
void enter_control_sock(char *RemHname, char *RemPort, int RemAf, char * LocHname, char *LocPort, int LocAf);
int create_control_sock(char *RemHname, char *RemPort, int RemAf, char * LocHname, char *LocPort, int LocAf);
void send_tcp_stream(char *remote_name);
int main(int argc, char **argv)
{
client_name = *argv[0];
set_opt_defaults();
set_user_opt(argc, argv);
enter_control_sock(rem_host_name,
rem_port,
rem_addr_family,
local_host_name,
local_port,
local_addr_family);
if(0 == strcasecmp(test_name, "TCP_STREAM"))
{
send_tcp_stream(rem_host_name);
}
else if()
{
return (0);
}
return (0);
}
/*******************************************************
函数功能:设置默认状态下的全局变量
输入参数:无
输出参数:无
作者:
时间:2009/07/31
描述:新生成函数
*********************************************************/
void set_opt_defaults()
{
strcpy(rem_host_name,"");
strcpy(local_host_name,"");
strcpy(test_name,"TCP_STREAM");
strncpy(rem_port,"12856",PORTBUFSIZE);
strncpy(local_port,"0",PORTBUFSIZE);
strncpy(local_data_port, "5000", PORTBUFSIZE);
strncpy(rem_data_port, "5001", PORTBUFSIZE);
rem_addr_family = AF_NORMAL;
local_addr_family = AF_NORMAL;
test_time = 10;
test_size = 1024;
/*set align vairables*/
local_recv_align = 8;
local_send_align = 8;
remote_recv_align = 8;
remote_send_align = 8;
/*set dirty vairables*/
#ifdef DIRTY
loc_dirty_count = 0;
loc_clean_count = 0;
rem_dirty_count = 0;
rem_clean_count = 0;
#endif
/* set some of the vairables for confidence intervals*/
iteration_min = 1;
iteration_max = 1;
/*set send and recv size*/
ls_size_req = 3*test_size;
lr_size_req = 3*test_size;
rs_size_req = 3*test_size;
rr_size_req = 3*test_size;
}
/*******************************************************
函数功能:设置用户传入的全局变量
输入参数:无
输出参数:无
作者:
时间:2009/07/31
描述:新生成函数
*********************************************************/
void set_user_opt(int argc, char **argv)
{
int c ;
argc--;
argv++;
while((c= getopt(argc, argv)) != EOF)
{
switch (c) {
case '?':
usage();
exit(0);
case 'h':
case 'H':
argc--;
argv++;
strcpy(rem_host_name,*argv[]);
break;
case 'p':
case 'P':
argc--;
argv++;
strncpy(local_port,*argv[],PORTBUFSIZE);
break;
case 'n':
case 'N':
argc--;
argv++;
strcpy(test_name,*argv[]);
break;
case 't':
case 'T':
argc--;
argv++;
test_time = convert(*argv[]);
break;
case 's':
case 'S':
argc--;
argv++;
test_size = convert(*argv[]);
break;
default:
argc--;
argv++;
break;
}
}
}
/*******************************************************
函数功能:将一字符串转换为整数
输入参数:无
输出参数:无
作者:
时间:2009/07/31
描述:新生成函数
*********************************************************/
unsigned int convert(char *string)
{
unsigned int base;
base = atoi(string);
if (strstr(string,"K")) {
base *= 1024;
}
if (strstr(string,"M")) {
base *= (1024 * 1024);
}
if (strstr(string,"G")) {
base *= (1024 * 1024 * 1024);
}
if (strstr(string,"k")) {
base *= (1000);
}
if (strstr(string,"m")) {
base *= (1000 * 1000);
}
if (strstr(string,"g")) {
base *= (1000 * 1000 * 1000);
}
return(base);
}
/*******************************************************
函数功能:打印使用方法
输入参数:无
输出参数:无
作者:
时间:2009/07/31
描述:新生成函数
*********************************************************/
void usage()
{
fprintf(where,"./%s -H ip_addr -P port_num -n TCP_STREAM -t elapsed_time -s test_size/n",client_name);
fprintf(where,"each parameter as follows:/n");
fprintf(where,">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>/n");
fprintf(where,"H:local host ip address/n");
fprintf(where,"P:local host port number/n");
fprintf(where,"n:test type/n");
fprintf(where,"t:elapsed time/n");
fprintf(where,"s:each time send size/n");
fprintf(where,">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>/n");
fflush(where);
}
/*******************************************************
函数功能:扫描用户输入的参数
输入参数:无
输出参数:无
作者:
时间:2009/07/31
描述:新生成函数
*********************************************************/
int getopt(int argc, char **argv)
{
char *PtrArg = *argv[];
if('-' == *PtrArg)
{
return (*(++PtrArg));
}
else
{
return 0;
}
}
/*******************************************************
函数功能:调用创建控制端口套接字的入口函数
输入参数:无
输出参数:无
作者:
时间:2009/07/31
描述:新生成函数
*********************************************************/
void enter_control_sock(char *RemHname,
char *RemPort,
int RemAf,
char * LocHname,
char *LocPort,
int LocAf)
{
control_sock = create_control_sock(RemHname,
RemPort,
RemAf,
LocHname,
LocPort,
LocAf);
if(control_sock < 0)
{
fprintf(where,
"create_control could not establish the control connection from %s port %s address family %s to %s port %s address family %s/n",
LocHname,LocPort,inet_ftos(LocAf),
RemHname,RemPort,inet_ftos(RemAf));
fflush(where);
exit(-1);
}
}
/*******************************************************
函数功能:get address family
输入参数:无
输出参数:address family
作者:
时间:2009/07/31
描述:新生成函数
*********************************************************/
char* inet_ftos(int family)
{
switch(family) {
case AF_INET:
return("AF_INET");
break;
#if defined(AF_INET6)
case AF_INET6:
return("AF_INET6");
break;
#endif
default:
return("AF_NORMAL");
}
}
/*******************************************************
函数功能:创建控制套接字
输入参数:无
输出参数:无
作者:
时间:2009/07/31
描述:新生成函数
*********************************************************/
int create_control_sock(char *RemHname,
char *RemPort,
int RemAf,
char * LocHname,
char *LocPort,
int LocAf);
{
int control_sock;
int ret;
struct addrinfo local_info;
struct addrinfo remote_info;
#ifdef DEBUG_INFO
fprintf(where,
"establish_control called with host '%s' port '%s' remfam %s/n",
RemHname,
RemPort,
inet_ftos(RemAf));
fprintf(where,
"/t/tlocal '%s' port '%s' locfam %s/n",
LocHname,
LocPort,
inet_ftos(LocAf));
fflush(where);
#endif
/*do the remote info struct*/
memset(&remote_info, 0, sizeof(addrinfo));
remote_info.ai_family = RemAf;
remote_info.ai_socktype = SOCK_STREAM;
remote_info.ai_protocol = IPPROTO_TCP;
remote_info.ai_flags = 0;
/*get addr info*/
ret = get_addr_info((char *)RemHname,
(char *)RemPort,
&remote_info);
if(ret < 0)
{
fprintf(where,"get_addr_info(Remote) failed/n");
fflush(where);
return SOCKET_ERROR;
}
/*do the local info struct*/
memset(&local_info, 0, sizeof(addrinfo));
local_info.ai_family = RemAf;
local_info.ai_socktype = SOCK_STREAM;
local_info.ai_protocol = IPPROTO_TCP;
local_info.ai_flags = 0;
/*get addr info*/
ret = get_addr_info((char *)LocHname,
(char *)LocPort,
&local_info);
if(ret < 0)
{
fprintf(where,"get_addr_info(Local) failed/n");
fflush(where);
return SOCKET_ERROR;
}
/*ok,start to create control sock*/
control_sock = socket(local_info.ai_family, SOCK_STREAM, 0);
if(control_sock < 0)
{
fprintf(where,"control_sock socket failed/n");
fflush(where);
return SOCKET_ERROR;
}
/*bind control_sock to local address*/
if(bind(control_sock,
local_info.ai_addr,
local_info.ai_addrlen) == 0)
{
/*successed*/
#ifdef DEBUG_INFO
fprintf(where,
"bound control socket to %s and %s/n",
LocHname,
LocPort);
fflush(where);
#endif
}
else
{
/*failed*/
fprintf(where,
"bound control socket to %s and %s failed/n",
LocHname,
LocPort);
fflush(where);
return SOCKET_ERROR;
}
/*connect remote host*/
if(connect(control_sock,
remote_info.ai_addr,
remote_info.ai_addrlen) == 0)
{
/*successed*/
#ifdef DEBUG_INFO
fprintf(where,
"connect control socket to %s and %s/n",
RemHname,
RemPort);
fflush(where);
#endif
}
else
{
/*failed*/
fprintf(where,
"connect control socket to %s and %s failed/n",
RemHname,
RemPort);
fflush(where);
return SOCKET_ERROR;
}
return (control_sock);
}
/********************************************************************************
函数功能:填充addrinfo结构体,各个结构体的定义及关系如下
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
struct addrinfo {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
socklen_t ai_addrlen;
struct sockaddr *ai_addr;
};
info->ai_addrlen = sizeof(struct sockaddr_in) = sizeof(sockaddr)
_
| sin_family <-- AF_INET _
info->ai_addr <-- sockaddr_in test <-- | sin_port <-- HostPort |
|--------------struct in_addr test |s_addr <-- HostName
|char sin_zero[8] |_
|_
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
输入参数:无
输出参数:无
作者:
时间:2009/08/1
描述:新生成函数
**********************************************************************************/
int get_addr_info(char *HostName,
char *HostPort,
struct addrinfo *info)
{
u16 port;
struct in_addr temp_addr;
struct sockaddr_in* temp_sock = NULL;
/*get port number and ip address*/
if(HostPort != NULL)
{
if(is_integer(HostPort))
{
port = htons(atoi(HostPort));
}
else{
port = htons(0);
}
}
else
{
port = htons(0);
}
if(HostName != NULL)
{
if(is_address(HostName))
{
temp_addr.s_addr = inet_addr(nodename);
}
else
{
temp_addr.s_addr = htonl(INADDR_ANY);
}
}
else
{
temp_addr.s_addr = htonl(INADDR_ANY);
}
/*fill the info->ai_addr and info->ai_addrlen*/
info->ai_addrlen = sizeof(struct sockaddr_in);
info->ai_addr = (struct sockaddr*)malloc(sizeof(sockaddr_in));
if(info->ai_addr == NULL){
fprintf(where,"ai_addr malloc failed/n");
fflush(where);
free(info->ai_addr);
return SOCKET_ERROR;
}
temp_sock = (struct sockaddr_in*)info->ai_addr;
temp_sock->sin_family = AF_NORMAL;
temp_sock->sin_port = port;
memcpy(&temp_sock->sin_addr, &temp_addr, sizeof(struct in_addr));
return (0);
}
/*******************************************************
函数功能:判断输入的参数是否是整数
输入参数:无
输出参数:无
作者:
时间:2009/08/1
描述:新生成函数
*********************************************************/
static int
is_integer(s)
const char *s;
{
if (*s == '-' || *s == '+')
s++;
if (*s < '0' || '9' < *s)
return 0;
s++;
while ('0' <= *s && *s <= '9')
s++;
return (*s == '/0');
}
/*******************************************************
函数功能:判断输入的参数是否是IP地址
输入参数:无
输出参数:无
作者:
时间:2009/08/1
描述:新生成函数
*********************************************************/
static int
is_address(s)
const char *s;
{
const static char delimiters[] = {'.', '.', '.', '/0'};
int i, j;
int octet;
for (i = 0; i < 4; i++) {
if (*s == '0' && *(s + 1) != delimiters[i])
return 0;
for (j = 0, octet = 0; '0' <= *s && *s <= '9' && j < 3; s++, j++)
octet = octet * 10 + (*s - '0');
if (j == 0 || octet > 255 || *s != delimiters[i])
return 0;
s++;
}
return 1;
}
/*******************************************************
函数功能:发送TCP_STREAM报文
输入参数:无
输出参数:无
作者:
时间:2009/08/1
描述:新生成函数
*********************************************************/
void send_tcp_stream(char *remote_host)
{
float elapsed_time;
double thruput;
unsigned int nummesg = 0;
double bytes_send = 0.0;
unsigned int send_width = 0;
int len;
#ifdef DIRTY
int *mes_ptr;
int i;
#endif
SOCKET data_sock;
struct addrinfo *remote_res;
struct addrinfo *local_res;
struct ring_elt *send_ring;
struct tcp_stream_request_struct *tcp_stream_request;
struct tcp_stream_response_struct *tcp_stream_response;
struct tcp_stream_results_struct *tcp_stream_result;
tcp_stream_request = (struct tcp_stream_request_struct*)netbench_request.content.test_specific_data;
tcp_stream_response = (struct tcp_stream_response_struct*)netbench_response.content.test_specific_data;
tcp_stream_result = (struct tcp_stream_results_struct*)netbench_response.content.test_specific_data;
/*complete remote addrinfo and local addrinfo*/
complete_addrinfos(remote_res,
local_res,
remote_host,
AF_NORMAL,
SOCK_STREAM,
IPPROTO_TCP,
0);
send_ring = NULL;
times_up = 0;
init_stat();
/*set up data socket*/
data_sock = create_data_sock(local_res);
if(data_sock == INVALID_SOCKET)
{
printf(where,"send_tcp_stream:data_sock error/n");
exit(1);
}
#ifdef DEBUG_INFO
printf(where,"data_sock is OK.../n");
#endif
/*it is time to malloc send buff*/
test_size = (test_size > ls_size)?ls_size : test_size;
if(send_width == 0){
send_width = (ls_size/test_size) + 1;
if(send_width == 1) send_width++;
}
if(send_ring == NULL){
send_ring = alloc_ring_buff(send_width,
test_size,
local_send_align,
local_send_offset);
}
/*fill request info*/
netbench_request.content.request_type = DO_TCP_STREAM;
tcp_stream_request->send_buf_size = rs_size_req;
tcp_stream_request->recv_buf_size = rr_size_req;
tcp_stream_request->receive_size = test_size;
tcp_stream_request->no_delay = NO_DELAY;
tcp_stream_request->recv_alignment = remote_recv_align;
tcp_stream_request->recv_offset = remote_recv_offset;
tcp_stream_request->measure_cpu = NO_CPU_MEASURE;
tcp_stream_request->cpu_rate = NO_CPU_RATE;
tcp_stream_request->test_length = test_time;
tcp_stream_request->so_rcvavoid = NO_RCVAVOID;
tcp_stream_request->so_sndavoid = NO_SNDAVOID;
#ifdef DIRTY
tcp_stream_request->dirty_count = rem_dirty_count;
tcp_stream_request->clean_count = rem_clean_count;
#endif
tcp_stream_request->port = atoi(rem_data_port);
tcp_stream_request->ipfamily = remote_res->ai_family;
/*ok,send request*/
//send_request();
if(send(control_sock,
(char *)&netbench_request,
sizeof(netbench_request),
&netbench_request) != sizeof(netbench_request)){
fprintf(where,"request send failure/n");
fflush(where);
exit(1);
}
/*next step,recv request*/
//recv_response();
/**/
if(!netbench_response.content.serv_errno){
#ifdef DEBUG_INFO
fprintf(where,"remote listen done./n");
fflush(where);
#endif
rr_size = tcp_stream_response->recv_buf_size;
rs_size = tcp_stream_response->send_buf_size;
set_port_num(remote_res,(unsigned short)tcp_stream_response->data_port_number);
}
else{
fprintf(where,
"netbench: remote error %d",
netbench_response.content.serv_errno);
fflush(where);
exit(1);
}
/*connect remote*/
if(connect(data_sock,
remote_res->ai_addr,
remote_res->ai_addrlen) == INVALID_SOCKET){
fprintf(where,"netbench: send_tcp_stream:connect failed/n");
fflush(where);
exit(1);
}
/*start timer*/
start_timer(test_time);
cpu_start();
#ifdef DIRTY
/*initialize the random number*/
srand((int)getpid());
#endif
/*ok, we will start the test*/
while(!times_up)
{
#ifdef DIRTY
mes_ptr = (int *)(send_ring->buffer_ptr);
for(i = 0; i < loc_dirty_count; i++){
*mes_ptr = rand();
mes_ptr++;
}
for(i = 0; i < loc_clean_count; i++){
loc_dirty_count = *mes_ptr;
mes_ptr++;
}
#endif
if((len = send(data_sock,
send_ring->buffer_ptr,
test_size,
0)) != test_size){
/*the test send is bad,must be end of test*/
printf(where,"netbench:data send error!/n");
fflush(where);
exit(1);
}
send_ring = send_ring->next;
}
/*shut down socket*/
/**********************************************
int shutdown( int sockfd, int howto) ;
howto选项:
SHUT_RD 关闭连接的读一半(0)
SHUT_WR 关闭连接的写这一半(1)
SHUT_RDWR 关闭连接读读和写(2)
************************************************/
if(shutdowm(data_sock, 1) == SOCKET_ERROR){
printf(where,"netbench: cannot shutdown tcp stream socket/n");
fflush(where);
exit(1);
}
recv(data_sock, send_ring->buffer_ptr, test_size, 0);
cpu_stop(&elapsed_time);
/*close the socket*/
close(data_sock);
/*recv remote results*/
recv_response();
if(!netbench_response.content.serv_errno){
#ifdef DEBUG_INFO
fprintf(where,"remote results obtained/n");
fflush(where);
#endif
}
else{
fprintf(where,"netbench: remote error %d/n",
netbench_response.content.serv_errno);
fflush(where);
exit(1);
}
/*calculate the thruput*/
bytes_send = ntohd(tcp_stream_result->bytes_received);
thruput = calc_thruput(bytes_send);
return;
}
/*******************************************************
函数功能:字节转换
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
double ntohd(double net_double)
{
/* we rely on things being nicely packed */
union {
double whole_thing;
unsigned int words[2];
unsigned char bytes[8];
} conv_rec;
unsigned char scratch;
int i;
/* on those systems where ntohl is a no-op, we want to return the */
/* original value, unchanged */
if (ntohl(1L) == 1L) {
return(net_double);
}
conv_rec.whole_thing = net_double;
/* we know that in the message passing routines that ntohl will have */
/* been called on the 32 bit quantities. we need to put those back */
/* the way they belong before we swap */
conv_rec.words[0] = htonl(conv_rec.words[0]);
conv_rec.words[1] = htonl(conv_rec.words[1]);
/* now swap */
for (i=0; i<= 3; i++) {
scratch = conv_rec.bytes[i];
conv_rec.bytes[i] = conv_rec.bytes[7-i];
conv_rec.bytes[7-i] = scratch;
}
return(conv_rec.whole_thing);
}
/*******************************************************
函数功能:进入吞吐量的测试函数
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
double calc_thruput(double rec_bytes)
{
return(calc_thruput_interval(rec_bytes,lib_elapsed));
}
/*******************************************************
函数功能:吞吐量计算函数
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
double calc_thruput_interval(double rcv_bytes,double elapsed)
{
double divisor;
/* We will calculate the thruput in libfmt units/second */
switch (libfmt) {
case 'K':
divisor = 1024.0;
break;
case 'M':
divisor = 1024.0 * 1024.0;
break;
case 'G':
divisor = 1024.0 * 1024.0 * 1024.0;
break;
case 'k':
divisor = 1000.0 / 8.0;
break;
case 'm':
divisor = 1000.0 * 1000.0 / 8.0;
break;
case 'g':
divisor = 1000.0 * 1000.0 * 1000.0 / 8.0;
break;
default:
divisor = 1024.0;
}
return (rcv_bytes / divisor / elapsed);
}
/*******************************************************
函数功能:发送请求函数
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
void send_request()
{
return;
}
/*******************************************************
函数功能:接收相应函数
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
void recv_response()
{
int tot_bytes_recvd,
bytes_recvd = 0,
bytes_left;
char *buf = (char *)&netbench_response;
int buflen = sizeof(netbench_response);
int counter;
fd_set readfds;
struct timeval timeout;
tot_bytes_recvd = 0;
bytes_left = buflen;
/*在一个进程的多端口收发中,需要设置收发套接字集合*/
FD_ZERO(&readfds);
FD_SET(control_sock, &readfds);
timeout.tv_sec = 120;
timeout.tv_usec = 0;
if(counter = select(FD_SETSIZE,
&readfds,
0,
0,
&timeout)) !=1) {
fprintf(where,"netbench:recv_response: no response received.counter %d",counter);
fflush(where);
exit(1);
}
while ((tot_bytes_recvd != buflen) &&
((bytes_recvd = recv(control_sock, buf, bytes_left,0)) > 0 )) {
tot_bytes_recvd += bytes_recvd;
buf += bytes_recvd;
bytes_left -= bytes_recvd;
}
#ifdef DEBUG_INFO
fprintf(where,"recv_response: received a %d byte response/n",
tot_bytes_recvd);
fflush(where);
#endif
if(tot_bytes_recvd < buflen){
fprintf(stderr,
"recv_response: partial response received: %d bytes/n",
tot_bytes_recvd);
fflush(stderr);
exit(1);
}
}
/*******************************************************
函数功能:记录测试的开始时间
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
void cpu_start()
{
gettimeofday(&time_begin, NULL);
}
/*******************************************************
函数功能:记录测试的结束时间
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
void cpu_stop(float *elapsed)
{
int sec;
int usec;
gettimeofday(&time_stop, NULL);
if (time_stop.tv_usec < time_begin.tv_usec) {
time_stop.tv_usec += 1000000;
time_stop.tv_sec -= 1;
}
sec = time_stop.tv_sec - time_begin.tv_sec;
usec = time_stop.tv_usec - time_begin.tv_usec;
lib_elapsed = (float)sec + ((float)usec/(float)1000000.0);
*elapsed = lib_elapsed;
}
/*******************************************************
函数功能:启动定时器
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
void start_timer(unsigned int time)
{
struct sigaction action;
#ifdef DEBUG_INFO
fprintf(where,"About to start a timer for %d seconds./n",time);
#endif
action.sa_handler = timer;
sigemptyset(&(action.sa_mask));
sigaddset(&(action.sa_mask), SIGALRM);
action.sa_flags = 0;
if(sigaction(SIGALRM, &action, NULL) < 0){
fprintf(where,"start timer: error installing alarm handler/n");
fflush(where);
exit(1);
}
/*start the alarm time*/
if(alarm(time) != 0){
fprintf(where,"error starting alarm timer/n");
fflush(where);
}
test_len_ticks = 1;
}
/*******************************************************
函数功能:定时启动函数
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
void timer(int sig)
{
switch(sig) {
case SIGINT:
fprintf(where,"netbench: caught SIGINT/n");
fflush(where);
exit(1);
break;
case SIGALRM:
if (--test_len_ticks == 0) {
/* the test is over */
if (times_up != 0) {
fprintf(where,"timer: timer popped with times_up != 0/n");
fflush(where);
}
times_up = 1;
}
break;
}
return;
}
/*******************************************************
函数功能:分配缓冲区
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
struct ring_elt *alloc_ring_buff(unsigned int width, unsigned int size, int align, int offset)
{
struct ring_elt *first_link = NULL;
struct ring_elt *temp_link = NULL;
struct ring_elt *prev_link;
int i;
int malloc_size;
malloc_size = size + align + offset;
assert(width >= 1);
prev_link = NULL;
for(i = 1; i <= width; i++){
temp_link = (struct ring_elt *)malloc(sizeof(struct ring_elt));
if(temp_link == NULL){
printf("malloc(%u) failed!/n", sizeof(struct ring_elt));
free(temp_link);
exit(1);
}
if(i == 1){
first_link = temp_link;
prev_link = temp_link;
}
temp_link->buffer_base = (char *)malloc(malloc_size);
if(temp_link->buffer_base == NULL){
printf("malloc(%d) failed!/n",malloc_size);
free(temp_link->buffer_base);
exit(1);
}
temp_link->buffer_ptr += offset;
//temp_link->next = NULL;
prev_link->next = temp_link;
if(i == width){
temp_link->next = first_link;
}
prev_link = temp_link;
}
return (first_link);
}
/*******************************************************
函数功能:初始化状态参数
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
void init_stat()
{
confidence_iteration = 1;
confidence = -10.0;
}
/*******************************************************
函数功能:创建传输数据套接字
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
int create_data_sock(struct addrinfo *res)
{
SOCKET temp_sock;
int on = 1;
temp_sock = socket(res->ai_family,
res->ai_socktype,
res->ai_protocol);
if(temp_sock == INVALID_SOCKET){
fprintf(where,
"netbench: create_data_socket: socket: errno %d fam %s type %s prot %s errmsg %s/n",
inet_ftos(res->ai_family),
inet_ttos(res->ai_socktype),
inet_ptos(res->ai_protocol));
fflush(where);
exit(1);
}
#ifdef DEBUG_INFO
fprintf(where,"create_data_socket: socket %d obtained.../n", temp_sock);
fflush(where);
#endif
/*set socket buffer size,send and recv*/
set_sock_buffer(temp_sock, SEND_SIZE, ls_size_req, &ls_size);
set_sock_buffer(temp_sock, RECV_SIZE, lr_size_req, &lr_size);
/*set reuse address property*/
if(setsockopt(temp_sock,
SOL_SOCKET.
SO_REUSEADDR,
&on,
sizeof(on)) < 0){
fprintf(where, "netbench:create_data_sock:SO_REUSEADDR failled/n");
fflush(where);
}
/*bind the sock*/
if (bind(temp_sock,
res->ai_addr,
res->ai_addrlen) < 0) {
fprintf(where,
"netbench: create_data_socket: data socket bind failed errno %d/n");
fprintf(where," port: %d/n",get_port_number(res));
fflush(where);
}
return(temp_sock);
}
/**********************************************************
函数功能:获得addrinfo结构体中存储的端口号
输入参数:无
输出参数:无
作者:
时间:2009/08/1
描述:新生成函数
***********************************************************/
static unsigned short get_port_number(struct addrinfo *port_res)
{
switch(port_res->ai_family){
case AF_INET:{
struct sockaddr_in *foo = (struct sockaddr_in *)port_res->ai_addr;
return (ntohs(foo->sin_port));
break;
}
#if defined(AF_INET6)
case AF_INET6: {
struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr;
return(ntohs(foo->sin6_port));
break;
}
#endif
default:
fprintf(where,"Unexpected Address Family of %u/n",port_res->ai_family);
fflush(where);
exit(-1);
}
}
/*******************************************************
函数功能:设置端口号
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
void set_port_num(struct addrinfo * res, unsigned short port)
{
switch(res->ai_family) {
case AF_INET: {
struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr;
foo->sin_port = htons(port);
break;
}
#if defined(AF_INET6)
case AF_INET6: {
struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr;
foo->sin6_port = htons(port);
break;
}
#endif
default:
fprintf(where,
"Unexpected Address Family of %u/n",res->ai_family);
fflush(where);
exit(-1);
}
}
/*******************************************************
函数功能:设置套接字缓冲区大小
输入参数:无
输出参数:无
作者:
时间:2009/08/1
描述:新生成函数
*********************************************************/
void set_sock_buffer(SOCKET sock_fd, int flag, int req_size, int *rea_size)
{
int opt_name = (flag == SEND_SIZE)? SO_SNDBUF : SO_RCVBUF;
socklen_t sock_opt_len;
if(req_size > 0)
{
if(setsockopt(sock_fd, SOL_SOCKET, opt_name,
(char *)&req_size, sizeof(int)) < 0){
fprintf(where, "netbench: set_sock_buffer: %s option:/n",
(flag == SEND_SIZE) ? "SO_SNDBUF" : "SO_RCVBUF");
fflush(where);
exit(1);
}
#ifdef DEBUG_INFO
fprintf(where, "netbench: set_sock_buffer: %s option:/n",
(flag == SEND_SIZE) ? "SO_SNDBUF" : "SO_RCVBUF");
fflush(where);
#endif
}
/*get real size*/
sock_opt_len = sizeof(socklen_t);
if(getsockopt(sock_fd, SOL_SOCKET, opt_name,
(char *)rea_size, &sock_opt_len) < 0){
fprintf(where, "netbench: set_sock_buffer: %s option:/n",
(flag == SEND_SIZE) ? "SO_SNDBUF" : "SO_RCVBUF");
fflush(where);
*rea_size = -1;
}
#ifdef DEBUG_INFO
fprintf(where, "netbench: set_sock_buffer: %s option:/n",
(flag == SEND_SIZE) ? "SO_SNDBUF" : "SO_RCVBUF");
fflush(where);
#endif
}
/*******************************************************
函数功能:进入填充本地和远端主机信息
输入参数:无
输出参数:无
作者:
时间:2009/08/1
描述:新生成函数
*********************************************************/
void complete_addrinfos(struct addrinfo*remote_res,
struct addrinfo*local_res,
char *remote_name,
int family,
int type,
int protocol,
int flag)
{
/*first,we do remote addrinfo*/
complete_addrinfo(remote_res, remote_name, family, rem_data_port, type, protocol, flag);
/*do local addrinfo*/
complete_addrinfo(local_res, "", family, local_data_port, type, protocol, flag);
}
/*******************************************************
函数功能:填充本地和远端主机信息
输入参数:无
输出参数:无
作者:
时间:2009/08/1
描述:新生成函数
*********************************************************/
void complete_addrinfo(struct addrinfo*res,
char *remote_name,
int family,
char *port,
int type,
int protocol,
int flag)
{
res->ai_family = family;
res->ai_socktype = type;
res->ai_protocol = protocol;
res->ai_flags = flag;
get_addr_info(remote_name, port, res);
}