[netperf-dev] netperf4 commit notice r207 - trunk/src
burger at netperf.org
burger at netperf.org
Fri Mar 9 11:00:07 PST 2007
Author: burger
Date: 2007-03-09 11:00:05 -0800 (Fri, 09 Mar 2007)
New Revision: 207
Modified:
trunk/src/netlib.c
trunk/src/netperf.c
trunk/src/netserver.c
trunk/src/nettest_bsd.c
trunk/src/nettest_bsd.h
Log:
Added send_tcp_crr and recv_tcp_crr tests to nettest_bsd.c.
Changed errno to GET_ERRNO so netperf4 would work correctly on windows.
Added debug code to resolve_depency in netperf.c
Fixed timing window caused by missing call to g_timeout_add to
accept_connection in netserver.c
Stephen Burger
Modified: trunk/src/netlib.c
===================================================================
--- trunk/src/netlib.c 2007-03-09 18:38:34 UTC (rev 206)
+++ trunk/src/netlib.c 2007-03-09 19:00:05 UTC (rev 207)
@@ -2033,7 +2033,9 @@
} else {
/* the connect call failed */
if (debug) {
- fprintf(where, "establish_control: connect failed, errno %d\n",errno);
+ fprintf(where,
+ "establish_control: connect failed, errno %d\n",
+ GET_ERRNO);
fprintf(where, " trying next address combination\n");
fflush(where);
}
@@ -2652,8 +2654,9 @@
&timeout)) != 1) {
if (debug) {
fprintf(where,
- "recv_control_message: select error or timeout. errno %d counter %d\n",
- errno,
+ "%s: select error or timeout. errno %d counter %d\n",
+ __func__,
+ GET_ERRNO,
counter);
fflush(where);
}
@@ -2666,9 +2669,10 @@
0);
if (bytes_recvd < 0) {
fprintf(where,
- "Unexpected byte count on control message of %d errno %d\n",
+ "%s: Unexpected byte count on control message of %d errno %d\n",
+ __func__,
bytes_recvd,
- errno);
+ GET_ERRNO);
fflush(where);
return(NPE_NEG_MSG_BYTES);
}
@@ -2728,8 +2732,9 @@
&timeout)) != 1) {
if (debug) {
fprintf(where,
- "recv_control_message: select error or timeout on message body. errno %d counter %d\n",
- errno,
+ "%s: select error or timeout on message body. errno %d counter %d\n",
+ __func__,
+ GET_ERRNO,
counter);
fflush(where);
}
@@ -2742,9 +2747,10 @@
if (bytes_recvd < 0) {
if (debug) {
fprintf(where,
- "Unexpected byte count on control message of %d errno %d\n",
+ "%s: Unexpected byte count on control message of %d errno %d\n",
+ __func__,
bytes_recvd,
- errno);
+ GET_ERRNO);
fflush(where);
}
return(NPE_NEG_MSG_BYTES);
Modified: trunk/src/netperf.c
===================================================================
--- trunk/src/netperf.c 2007-03-09 18:38:34 UTC (rev 206)
+++ trunk/src/netperf.c 2007-03-09 19:00:05 UTC (rev 207)
@@ -897,6 +897,7 @@
static int
resolve_dependency(xmlChar *id, xmlNodePtr *data)
{
+ int loop_count;
int rc = NPE_DEPENDENCY_NOT_PRESENT;
int hash_value;
test_t *test;
@@ -937,13 +938,16 @@
} /* end of test initilization */
#endif
/* wait for test to initialize */
+ loop_count = 0;
while (test->state == TEST_PREINIT) {
NETPERF_MUTEX_UNLOCK(h->hash_lock);
- if (debug > 1) {
+ if ((debug) && (loop_count == 0)) {
fprintf(where,
- "resolve_dependency: waiting on test %s\n",
+ "%s: waiting on test %s\n",
+ (char *)__func__,
(char *)id);
fflush(where);
+ loop_count++;
}
NETPERF_MUTEX_LOCK(h->hash_lock);
@@ -952,6 +956,13 @@
g_time_val_add(&abstime,1000);
g_cond_timed_wait(h->condition, h->hash_lock, &abstime);
} /* end wait */
+ if ((debug) && (loop_count > 0)) {
+ fprintf(where,
+ "%s: nolonger waiting on test %s\n",
+ (char *)__func__,
+ (char *)id);
+ fflush(where);
+ }
/* test has reached at least the TEST_INIT state */
if (test->state != TEST_ERROR) {
Modified: trunk/src/netserver.c
===================================================================
--- trunk/src/netserver.c 2007-03-09 18:38:34 UTC (rev 206)
+++ trunk/src/netserver.c 2007-03-09 19:00:05 UTC (rev 207)
@@ -714,8 +714,8 @@
g_fprintf(where,
"%s: accept failed errno %d %s\n",
__func__,
- errno,
- strerror(errno));
+ GET_ERRNO,
+ strerror(GET_ERRNO));
fflush(where);
exit(-1);
}
@@ -768,6 +768,9 @@
read_from_control_connection,
data);
g_fprintf(where,"added watch id %d\n",watch_id);
+ g_timeout_add(1000,
+ (GSourceFunc)check_test_state_callback,
+ data);
}
return(TRUE);
Modified: trunk/src/nettest_bsd.c
===================================================================
--- trunk/src/nettest_bsd.c 2007-03-09 18:38:34 UTC (rev 206)
+++ trunk/src/nettest_bsd.c 2007-03-09 19:00:05 UTC (rev 207)
@@ -139,10 +139,14 @@
#define CHECK_FOR_INVALID_SOCKET (temp_socket == INVALID_SOCKET)
#define CHECK_FOR_RECV_ERROR(len) (len == SOCKET_ERROR)
#define GET_ERRNO WSAGetLastError()
+#define CHECK_FOR_EADDRINUSE (GET_ERRNO == WSAEADDRINUSE)
+#define CHECK_FOR_EADDRNOTAVAIL (GET_ERRNO == WSAEADDRNOTAVAIL)
#else
#define CHECK_FOR_INVALID_SOCKET (temp_socket < 0)
#define CHECK_FOR_RECV_ERROR(len) (len < 0)
#define GET_ERRNO errno
+#define CHECK_FOR_EADDRINUSE (GET_ERRNO == EADDRINUSE)
+#define CHECK_FOR_EADDRNOTAVAIL (GET_ERRNO == EADDRNOTAVAIL)
#endif
@@ -198,7 +202,33 @@
}
#endif
+#if !defined(WANT_SET_QUEUE)
+ #define SET_QUEUE /* multiqueue binding goes here */
+#else
+ #define SET_QUEUE \
+ if (test) { \
+ /* code to establish HPUX multiqueue binding */ \
+ int len; \
+ bsd_data_t *my_data; \
+ my_data = GET_TEST_DATA(test); \
+ if (my_data->multi_queue) { \
+ if ((len=send(my_data->s_data, \
+ my_data->recv_ring->buffer_ptr, \
+ 1, \
+ 0)) != 1) { \
+ /* this macro hides windows differences */ \
+ if (CHECK_FOR_SEND_ERROR(len)) { \
+ report_test_failure(test, \
+ (char *)__func__, \
+ BSDE_DATA_SEND_ERROR, \
+ "data send_error"); \
+ } \
+ } \
+ } \
+ }
+#endif
+
static void
report_test_failure(test_t *test, const char *function, int err_code, const char * err_string) {
if (test->debug) {
@@ -344,6 +374,58 @@
}
+static int
+get_port_number(struct addrinfo *res)
+{
+ int port;
+ switch(res->ai_family) {
+ case AF_INET: {
+ struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr;
+ port = ntohs(foo->sin_port);
+ break;
+ }
+#if defined(AF_INET6)
+ case AF_INET6: {
+ struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr;
+ port = ntohs(foo->sin6_port);
+ break;
+ }
+#endif
+ default:
+ port = -1;
+ break;
+ }
+ return (port);
+}
+
+/* this routine will set the port number of the sockaddr in the
+ addrinfo to the specified value, based on the address family */
+void
+set_port_number(test_t *test, 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(test->where,
+ "%s: Unexpected Address Family of %u\n",
+ __func__,
+ res->ai_family);
+ fflush(test->where);
+ }
+}
+
+
#ifdef notdef
static int
strtofam(xmlChar *familystr)
@@ -366,6 +448,7 @@
}
#endif
+
static void
get_dependency_data(test_t *test, int type, int protocol)
{
@@ -721,7 +804,7 @@
fprintf(test->where,
"%s: %s: getsockopt SO_SNDBUF: errno %d\n",
__FILE__,
- __func__, errno);
+ __func__, GET_ERRNO);
fflush(test->where);
lss_size = -1;
}
@@ -733,7 +816,7 @@
fprintf(test->where,
"%s: %s: getsockopt SO_RCVBUF: errno %d\n",
__FILE__,
- __func__, errno);
+ __func__, GET_ERRNO);
fflush(test->where);
lsr_size = -1;
}
@@ -817,7 +900,7 @@
fprintf(test->where,
"%s: %s: nodelay: errno %d\n",
__FILE__,
- __func__, errno);
+ __func__, GET_ERRNO);
fflush(test->where);
}
@@ -924,6 +1007,14 @@
else {
new_data->port_max = -1;
}
+
+ string = xmlGetProp(args,(const xmlChar *)"multi_queue");
+ if (string) {
+ new_data->multi_queue = atoi((char *)string);
+ }
+ else {
+ new_data->multi_queue = 0;
+ }
string = xmlGetProp(args,(const xmlChar *)"send_width");
new_data->send_width = atoi((char *)string);
@@ -1200,7 +1291,7 @@
if (test->debug) {
fprintf(test->where,
"%s:bind returned %d errno=%d\n",
- __func__, rc, errno);
+ __func__, rc, GET_ERRNO);
fflush(test->where);
}
if (rc == -1) {
@@ -1694,6 +1785,9 @@
if (new_state == TEST_IDLE) {
g_usleep(1000000);
}
+ if (new_state == TEST_LOADED) {
+ SET_QUEUE;
+ }
break;
case TEST_MEASURE:
new_state = recv_tcp_stream_meas(test);
@@ -1795,7 +1889,7 @@
if (test->debug) {
fprintf(test->where,
"%s:bind returned %d errno=%d\n",
- __func__, rc, errno);
+ __func__, rc, GET_ERRNO);
fflush(test->where);
}
if (rc == -1) {
@@ -2471,8 +2565,845 @@
} /* end of while */
wait_to_die(test);
} /* end of send_tcp_rr */
+
+#define BSD_TCP_CRR_TESTS
+#ifdef BSD_TCP_CRR_TESTS
+static void
+recv_tcp_crr_preinit(test_t *test)
+{
+ int rc;
+ SOCKET s_listen;
+ bsd_data_t *my_data;
+ struct sockaddr myaddr;
+ netperf_socklen_t mylen;
+
+ my_data = GET_TEST_DATA(test);
+
+ mylen = sizeof(myaddr);
+
+ my_data->recv_ring = allocate_buffer_ring(my_data->recv_width,
+ my_data->req_size,
+ my_data->recv_align,
+ my_data->recv_offset,
+ my_data->fill_source);
+ my_data->send_ring = allocate_buffer_ring(my_data->send_width,
+ my_data->rsp_size,
+ my_data->send_align,
+ my_data->send_offset,
+ my_data->fill_source);
+ s_listen = create_data_socket(test);
+ my_data->s_listen = s_listen;
+ if (test->debug) {
+ dump_addrinfo(test->where, my_data->locaddr,
+ (xmlChar *)NULL, (xmlChar *)NULL, -1);
+ fprintf(test->where,
+ "%s:create_data_socket returned %d\n",
+ __func__, s_listen);
+ fflush(test->where);
+ }
+ rc = bind(s_listen, my_data->locaddr->ai_addr, my_data->locaddr->ai_addrlen);
+ if (test->debug) {
+ fprintf(test->where,
+ "%s:bind returned %d errno=%d\n",
+ __func__, rc, GET_ERRNO);
+ fflush(test->where);
+ }
+ if (rc == -1) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_BIND_FAILED,
+ "data socket bind failed");
+ }
+ else if (listen(s_listen,5) == -1) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_LISTEN_FAILED,
+ "data socket listen failed");
+ }
+ else if (getsockname(s_listen,&myaddr,&mylen) == -1) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_GETSOCKNAME_FAILED,
+ "getting the listen socket name failed");
+ }
+ else {
+ memcpy(my_data->locaddr->ai_addr,&myaddr,mylen);
+ my_data->locaddr->ai_addrlen = mylen;
+ set_dependent_data(test);
+ }
+}
+
+static uint32_t
+recv_tcp_crr_init(test_t *test)
+{
+ SOCKET s_data;
+ bsd_data_t *my_data;
+ struct sockaddr peeraddr;
+ netperf_socklen_t peerlen;
+
+ my_data = GET_TEST_DATA(test);
+
+ peerlen = sizeof(peeraddr);
+
+ if (test->debug) {
+ fprintf(test->where, "%s:waiting in accept\n", __func__);
+ fflush(test->where);
+ }
+ if ((s_data = accept(my_data->s_listen,
+ &peeraddr,
+ &peerlen)) == -1) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_ACCEPT_FAILED,
+ "listen socket accept failed");
+ }
+ else {
+ if (test->debug) {
+ fprintf(test->where,
+ "%s:accept returned successfully %d\n",
+ __func__, s_data);
+ fflush(test->where);
+ }
+ my_data->s_data = s_data;
+ }
+ return(TEST_IDLE);
+}
+
+
+static uint32_t
+recv_tcp_crr_meas(test_t *test)
+{
+ SOCKET s_data;
+ int len = -1;
+ int bytes_left;
+ char *req_ptr;
+ uint32_t new_state;
+ bsd_data_t *my_data;
+ struct sockaddr peeraddr;
+ netperf_socklen_t peerlen;
+
+
+ HISTOGRAM_VARS;
+ my_data = GET_TEST_DATA(test);
+
+
+ while (NO_STATE_CHANGE(test)) {
+ /* accept a connection from the remote */
+ if ((s_data = accept(my_data->s_listen,
+ &peeraddr,
+ &peerlen)) == -1) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_ACCEPT_FAILED,
+ "listen socket accept failed");
+ continue;
+ }
+ else {
+ if (test->debug) {
+ fprintf(test->where,
+ "%s:accept returned successfully %d\n",
+ __func__, s_data);
+ fflush(test->where);
+ }
+ my_data->s_data = s_data;
+ }
+ /* receive the request from the other side */
+ /* code to timestamp enabled by WANT_HISTOGRAM */
+ HIST_TIMESTAMP(&time_one);
+ /* recv the request for the test */
+ req_ptr = my_data->recv_ring->buffer_ptr;
+ bytes_left = my_data->req_size;
+ while (bytes_left > 0) {
+ len=recv(s_data,
+ req_ptr,
+ bytes_left,
+ 0);
+ if (len > 0) {
+ req_ptr += len;
+ bytes_left -= len;
+ continue;
+ }
+ else {
+ break;
+ }
+ }
+ /* this macro hides windows differences */
+ if (CHECK_FOR_RECV_ERROR(len)) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_DATA_RECV_ERROR,
+ "data_recv_error");
+ continue;
+ }
+ if (len == 0) {
+ /* just got a data connection close break out of while loop */
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_DATA_CONNECTION_CLOSED_ERROR,
+ "data_connection_closed_early");
+ continue;
+ }
+ /* Now, send the response to the remote */
+ if ((len=send(s_data,
+ my_data->send_ring->buffer_ptr,
+ my_data->rsp_size,
+ 0)) != my_data->rsp_size) {
+ /* this macro hides windows differences */
+ if (CHECK_FOR_SEND_ERROR(len)) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_DATA_SEND_ERROR,
+ "data_send_error");
+ continue;
+ }
+ }
+ /* code to timestamp enabled by WANT_HISTOGRAM */
+ HIST_TIMESTAMP(&time_two);
+ HIST_ADD(my_data->time_hist,&time_one,&time_two);
+ my_data->stats.named.trans_received++;
+ my_data->recv_ring = my_data->recv_ring->next;
+ my_data->send_ring = my_data->send_ring->next;
+ /* close the connection. the server will likely do a graceful */
+ /* close of the connection, insuring that all data has arrived at */
+ /* the client. for this it will call shutdown(), and then recv() and */
+ /* then close(). I'm reasonably confident that this is the */
+ /* appropriate sequence of calls - I would like to hear of */
+ /* examples in web servers to the contrary. raj 10/95*/
+#ifdef TCP_CRR_SHUTDOWN
+ shutdown(s_data, SHUT_WR);
+ recv(s_data,
+ recv_message_ptr,
+ 1,
+ 0);
+ close(s_data);
+#else
+ close(s_data);
+#endif /* TCP_CRR_SHUTDOWN */
+ }
+ new_state = CHECK_REQ_STATE;
+ if (new_state == TEST_LOADED) {
+ /* transitioning to loaded state from measure state
+ set current timestamp and update elapsed time */
+ gettimeofday(&(my_data->curr_time), NULL);
+ update_elapsed_time(my_data);
+ my_data->s_data = -1;
+ }
+ return(new_state);
+}
+
+static uint32_t
+recv_tcp_crr_load(test_t *test)
+{
+ SOCKET s_data;
+ int len=-1;
+ int bytes_left;
+ char *req_ptr;
+ uint32_t new_state;
+ bsd_data_t *my_data;
+ struct sockaddr peeraddr;
+ netperf_socklen_t peerlen;
+ int ready;
+ fd_set readfds;
+ struct timeval timeout;
+
+
+ my_data = GET_TEST_DATA(test);
+
+ FD_ZERO(&readfds);
+ FD_SET(my_data->s_listen, &readfds);
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+
+ s_data = my_data->s_data;
+ while (NO_STATE_CHANGE(test)) {
+ if (s_data == -1) {
+ /* do a select call to ensure that the accept will not block */
+ /* if the accept blocks the test may hang on state transitions */
+ ready = select(my_data->s_listen+1, &readfds, NULL, NULL, &timeout);
+ if (ready == 0) {
+ FD_SET(my_data->s_listen, &readfds);
+ continue;
+ }
+ /* accept a connection from the remote */
+ if ((s_data = accept(my_data->s_listen,
+ &peeraddr,
+ &peerlen)) == -1) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_ACCEPT_FAILED,
+ "listen socket accept failed");
+ continue;
+ }
+ else {
+ if (test->debug) {
+ fprintf(test->where,
+ "%s:accept returned successfully %d\n",
+ __func__, s_data);
+ fflush(test->where);
+ }
+ }
+ }
+ /* receive the request from the other side */
+ req_ptr = my_data->recv_ring->buffer_ptr;
+ bytes_left = my_data->req_size;
+ while (bytes_left > 0) {
+ len=recv(s_data,
+ req_ptr,
+ bytes_left,
+ 0);
+ if (len > 0) {
+ req_ptr += len;
+ bytes_left -= len;
+ continue;
+ }
+ else {
+ break;
+ }
+ }
+ /* this macro hides windows differences */
+ if (CHECK_FOR_RECV_ERROR(len)) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_DATA_RECV_ERROR,
+ "data_recv_error");
+ continue;
+ }
+ if (len == 0) {
+ /* just got a data connection close break out of while loop */
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_DATA_CONNECTION_CLOSED_ERROR,
+ "data_connection_closed_early");
+ continue;
+ }
+ /* Now, send the response to the remote */
+ if ((len=send(s_data,
+ my_data->send_ring->buffer_ptr,
+ my_data->rsp_size,
+ 0)) != my_data->rsp_size) {
+ /* this macro hides windows differences */
+ if (CHECK_FOR_SEND_ERROR(len)) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_DATA_SEND_ERROR,
+ "data_send_error");
+ continue;
+ }
+ }
+ my_data->recv_ring = my_data->recv_ring->next;
+ my_data->send_ring = my_data->send_ring->next;
+ /* close the connection. the server will likely do a graceful */
+ /* close of the connection, insuring that all data has arrived at */
+ /* the client. for this it will call shutdown(), and then recv() and */
+ /* then close(). I'm reasonably confident that this is the */
+ /* appropriate sequence of calls - I would like to hear of */
+ /* examples in web servers to the contrary. raj 10/95*/
+#ifdef TCP_CRR_SHUTDOWN
+ shutdown(s_data, SHUT_WR);
+ recv(s_data,
+ recv_message_ptr,
+ 1,
+ 0);
+ close(s_data);
+#else
+ close(s_data);
+#endif /* TCP_CRR_SHUTDOWN */
+ s_data = -1;
+ }
+ /* check for state transition */
+ new_state = CHECK_REQ_STATE;
+ if (new_state == TEST_MEASURE) {
+ /* transitioning to measure state from loaded state
+ set previous timestamp */
+ gettimeofday(&(my_data->prev_time), NULL);
+ }
+ return(new_state);
+}
+
+
+static void
+send_tcp_crr_preinit(test_t *test)
+{
+ bsd_data_t *my_data;
+
+ my_data = GET_TEST_DATA(test);
+
+ if (my_data->port_min == -1) {
+ my_data->port_min = 5000;
+ }
+
+ if (my_data->port_max == -1) {
+ my_data->port_max = 65535;
+ }
+
+ my_data->recv_ring = allocate_buffer_ring(my_data->recv_width,
+ my_data->rsp_size,
+ my_data->recv_align,
+ my_data->recv_offset,
+ my_data->fill_source);
+ my_data->send_ring = allocate_buffer_ring(my_data->send_width,
+ my_data->req_size,
+ my_data->send_align,
+ my_data->send_offset,
+ my_data->fill_source);
+
+ get_dependency_data(test, SOCK_STREAM, IPPROTO_TCP);
+ my_data->s_data = create_data_socket(test);
+}
+
+static uint32_t
+send_tcp_crr_init(test_t *test)
+{
+ bsd_data_t *my_data;
+ int myport;
+ int rc;
+
+ my_data = GET_TEST_DATA(test);
+
+ if (test->debug) {
+ fprintf(test->where,"%s: in INIT state making connect call\n",__func__);
+ fflush(test->where);
+ }
+
+ myport = my_data->port_min;
+ srand(getpid());
+ if (my_data->port_max - my_data->port_min) {
+ myport = my_data->port_min +
+ (rand() % (my_data->port_max - my_data->port_min));
+ }
+ for (;;) {
+ my_data->s_data = create_data_socket(test);
+ myport++;
+ if (myport >= my_data->port_max) {
+ myport = my_data->port_min;
+ }
+ set_port_number(test, my_data->locaddr, myport);
+ rc = bind(my_data->s_data,
+ my_data->locaddr->ai_addr,
+ my_data->locaddr->ai_addrlen);
+ if (rc < 0) {
+ if (!(CHECK_FOR_EADDRINUSE || CHECK_FOR_EADDRNOTAVAIL)) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_BIND_FAILED,
+ "data socket bind failed");
+
+ break;
+ }
+ close(my_data->s_data);
+ my_data->s_data = -1;
+ continue;
+ }
+ else {
+ rc = connect(my_data->s_data,
+ my_data->remaddr->ai_addr,
+ my_data->remaddr->ai_addrlen);
+ if (rc < 0) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_CONNECT_FAILED,
+ "data socket connect failed");
+ close(my_data->s_data);
+ my_data->s_data = -1;
+ }
+ else if (test->debug) {
+ fprintf(test->where,"%s: connected and moving to IDLE\n",__func__);
+ fflush(test->where);
+ }
+ break;
+ }
+ }
+ return(TEST_IDLE);
+}
+
+
+static uint32_t
+send_tcp_crr_meas(test_t *test)
+{
+ uint32_t new_state;
+ int bytes_left;
+ int len;
+ int myport;
+ int rc;
+ char *rsp_ptr;
+ bsd_data_t *my_data;
+
+ my_data = GET_TEST_DATA(test);
+
+ myport = get_port_number(my_data->locaddr);
+
+ while (NO_STATE_CHANGE(test)) {
+ HISTOGRAM_VARS;
+ /* code to make data dirty macro enabled by DIRTY */
+ MAKE_DIRTY(my_data,my_data->send_ring);
+ /* code to timestamp enabled by WANT_HISTOGRAM */
+ /* change the port number and get a new socket */
+ my_data->s_data = create_data_socket(test);
+ myport++;
+ if (myport >= my_data->port_max) {
+ myport = my_data->port_min;
+ }
+ set_port_number(test, my_data->locaddr, myport);
+ rc = bind(my_data->s_data,
+ my_data->locaddr->ai_addr,
+ my_data->locaddr->ai_addrlen);
+ if (rc < 0) {
+ if (!(CHECK_FOR_EADDRINUSE || CHECK_FOR_EADDRNOTAVAIL)) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_BIND_FAILED,
+ "data socket bind failed");
+ }
+ continue;
+ }
+ HIST_TIMESTAMP(&time_one);
+ if (connect(my_data->s_data,
+ my_data->remaddr->ai_addr,
+ my_data->remaddr->ai_addrlen) < 0) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_CONNECT_FAILED,
+ "data socket connect failed");
+ continue;
+ }
+ /* send data for the test */
+ if((len=send(my_data->s_data,
+ my_data->send_ring->buffer_ptr,
+ my_data->req_size,
+ 0)) != my_data->req_size) {
+ /* this macro hides windows differences */
+ if (CHECK_FOR_SEND_ERROR(len)) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_DATA_SEND_ERROR,
+ "data send error");
+ continue;
+ }
+ }
+ /* recv the request for the test */
+ rsp_ptr = my_data->recv_ring->buffer_ptr;
+ bytes_left = my_data->rsp_size;
+ while (bytes_left > 0) {
+ len = recv(my_data->s_data,
+ rsp_ptr,
+ bytes_left,
+ 0);
+ if (len > 0) {
+ rsp_ptr += len;
+ bytes_left -= len;
+ continue;
+ }
+ else {
+ break;
+ }
+ }
+ /* this macro hides windows differences */
+ if (CHECK_FOR_RECV_ERROR(len)) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_DATA_RECV_ERROR,
+ "data_recv_error");
+ continue;
+ }
+ if (len == 0) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_DATA_CONNECTION_CLOSED_ERROR,
+ "data_connection_closed_early");
+ continue;
+ }
+ len = recv(my_data->s_data,
+ rsp_ptr,
+ 1,
+ 0);
+ if (CHECK_FOR_RECV_ERROR(len)) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_DATA_RECV_ERROR,
+ "data_recv_error");
+ continue;
+ }
+ /* code to timestamp enabled by WANT_HISTOGRAM */
+ HIST_TIMESTAMP(&time_two);
+ HIST_ADD(my_data->time_hist,&time_one,&time_two);
+ my_data->stats.named.trans_sent++;
+ my_data->recv_ring = my_data->recv_ring->next;
+ my_data->send_ring = my_data->send_ring->next;
+ CLOSE_SOCKET(my_data->s_data);
+ my_data->s_data = -1;
+ }
+ new_state = CHECK_REQ_STATE;
+ if (new_state == TEST_LOADED) {
+ /* transitioning to loaded state from measure state
+ set current timestamp and update elapsed time */
+ gettimeofday(&(my_data->curr_time), NULL);
+ update_elapsed_time(my_data);
+ }
+ return(new_state);
+}
+
+
+static uint32_t
+send_tcp_crr_load(test_t *test)
+{
+ uint32_t new_state;
+ int bytes_left;
+ int len;
+ int myport;
+ int rc;
+ char *rsp_ptr;
+ bsd_data_t *my_data;
+
+ my_data = GET_TEST_DATA(test);
+
+ myport = get_port_number(my_data->locaddr);
+
+ while (NO_STATE_CHANGE(test)) {
+ /* code to make data dirty macro enabled by DIRTY */
+ MAKE_DIRTY(my_data,my_data->send_ring);
+ /* code to timestamp enabled by WANT_HISTOGRAM */
+ /* change the port number and get a new socket */
+ if (my_data->s_data == -1) {
+ my_data->s_data = create_data_socket(test);
+ myport++;
+ if (myport >= my_data->port_max) {
+ myport = my_data->port_min;
+ }
+ set_port_number(test, my_data->locaddr, myport);
+ rc = bind(my_data->s_data,
+ my_data->locaddr->ai_addr,
+ my_data->locaddr->ai_addrlen);
+ if (rc < 0) {
+ if (!(CHECK_FOR_EADDRINUSE || CHECK_FOR_EADDRNOTAVAIL)) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_BIND_FAILED,
+ "data socket bind failed");
+ }
+ close(my_data->s_data);
+ my_data->s_data = -1;
+ continue;
+ }
+ if (connect(my_data->s_data,
+ my_data->remaddr->ai_addr,
+ my_data->remaddr->ai_addrlen) < 0) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_CONNECT_FAILED,
+ "data socket connect failed");
+ close(my_data->s_data);
+ my_data->s_data = -1;
+ continue;
+ }
+ }
+ /* send data for the test */
+ if((len=send(my_data->s_data,
+ my_data->send_ring->buffer_ptr,
+ my_data->req_size,
+ 0)) != my_data->req_size) {
+ /* this macro hides windows differences */
+ if (CHECK_FOR_SEND_ERROR(len)) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_DATA_SEND_ERROR,
+ "data send error");
+ continue;
+ }
+ }
+ /* recv the request for the test */
+ rsp_ptr = my_data->recv_ring->buffer_ptr;
+ bytes_left = my_data->rsp_size;
+ while (bytes_left > 0) {
+ len = recv(my_data->s_data,
+ rsp_ptr,
+ bytes_left,
+ 0);
+ if (len > 0) {
+ rsp_ptr += len;
+ bytes_left -= len;
+ continue;
+ }
+ else {
+ break;
+ }
+ }
+ /* this macro hides windows differences */
+ if (CHECK_FOR_RECV_ERROR(len)) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_DATA_RECV_ERROR,
+ "data_recv_error");
+ continue;
+ }
+ if (len == 0) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_DATA_CONNECTION_CLOSED_ERROR,
+ "data_connection_closed_early");
+ continue;
+ }
+ len = recv(my_data->s_data,
+ rsp_ptr,
+ 1,
+ 0);
+ if (CHECK_FOR_RECV_ERROR(len)) {
+ report_test_failure(test,
+ (char *)__func__,
+ BSDE_DATA_RECV_ERROR,
+ "data_recv_error");
+ continue;
+ }
+ my_data->recv_ring = my_data->recv_ring->next;
+ my_data->send_ring = my_data->send_ring->next;
+ CLOSE_SOCKET(my_data->s_data);
+ my_data->s_data = -1;
+ }
+ new_state = CHECK_REQ_STATE;
+ if (new_state == TEST_MEASURE) {
+ /* transitioning to measure state from loaded state
+ set previous timestamp */
+ gettimeofday(&(my_data->prev_time), NULL);
+ }
+ return(new_state);
+}
+
+int
+recv_tcp_crr_clear_stats(test_t *test)
+{
+ return(bsd_test_clear_stats(GET_TEST_DATA(test)));
+}
+
+
+xmlNodePtr
+recv_tcp_crr_get_stats(test_t *test)
+{
+ return( bsd_test_get_stats(test));
+}
+
+void
+recv_tcp_crr_decode_stats(xmlNodePtr stats,test_t *test)
+{
+ bsd_test_decode_stats(stats,test);
+}
+
+
+int
+send_tcp_crr_clear_stats(test_t *test)
+{
+ return(bsd_test_clear_stats(GET_TEST_DATA(test)));
+}
+
+xmlNodePtr
+send_tcp_crr_get_stats(test_t *test)
+{
+ return( bsd_test_get_stats(test));
+}
+
+void
+send_tcp_crr_decode_stats(xmlNodePtr stats,test_t *test)
+{
+ bsd_test_decode_stats(stats,test);
+}
+
+
+/* This routine implements the server-side of the TCP request/response */
+/* test (a.k.a. rr) for the sockets interface. It receives its */
+/* parameters via the xml node contained in the test structure. */
+/* results are collected by the procedure recv_tcp_crr_get_stats */
+
+void
+recv_tcp_crr(test_t *test)
+{
+ uint32_t state, new_state;
+ bsd_test_init(test, SOCK_STREAM, IPPROTO_TCP);
+ state = GET_TEST_STATE;
+ while ((state != TEST_ERROR) &&
+ (state != TEST_DEAD )) {
+ switch(state) {
+ case TEST_PREINIT:
+ recv_tcp_crr_preinit(test);
+ new_state = TEST_INIT;
+ break;
+ case TEST_INIT:
+ new_state = CHECK_REQ_STATE;
+ if (new_state == TEST_IDLE) {
+ new_state = recv_tcp_crr_init(test);
+ }
+ break;
+ case TEST_IDLE:
+ new_state = CHECK_REQ_STATE;
+ if (new_state == TEST_IDLE) {
+ g_usleep(1000000);
+ }
+ break;
+ case TEST_MEASURE:
+ new_state = recv_tcp_crr_meas(test);
+ break;
+ case TEST_LOADED:
+ new_state = recv_tcp_crr_load(test);
+ break;
+ default:
+ break;
+ } /* end of switch */
+ set_test_state(test, new_state);
+ state = GET_TEST_STATE;
+ } /* end of while */
+ wait_to_die(test);
+} /* end of recv_tcp_crr */
+
+
+/* This routine implements the TCP request/response test */
+/* (a.k.a. rr) for the sockets interface. It receives its */
+/* parameters via the xml node contained in the test structure */
+/* output to the standard output. */
+/* results are collected by the procedure send_tcp_crr_get_stats */
+
+void
+send_tcp_crr(test_t *test)
+{
+ uint32_t state, new_state;
+ bsd_test_init(test, SOCK_STREAM, IPPROTO_TCP);
+ state = GET_TEST_STATE;
+ while ((state != TEST_ERROR) &&
+ (state != TEST_DEAD )) {
+ switch(state) {
+ case TEST_PREINIT:
+ send_tcp_crr_preinit(test);
+ new_state = TEST_INIT;
+ break;
+ case TEST_INIT:
+ new_state = CHECK_REQ_STATE;
+ if (new_state == TEST_IDLE) {
+ new_state = send_tcp_crr_init(test);
+ }
+ break;
+ case TEST_IDLE:
+ new_state = CHECK_REQ_STATE;
+ if (new_state == TEST_IDLE) {
+ g_usleep(1000000);
+ }
+ break;
+ case TEST_MEASURE:
+ new_state = send_tcp_crr_meas(test);
+ break;
+ case TEST_LOADED:
+ new_state = send_tcp_crr_load(test);
+ break;
+ default:
+ break;
+ } /* end of switch */
+ set_test_state(test, new_state);
+ state = GET_TEST_STATE;
+ } /* end of while */
+ wait_to_die(test);
+} /* end of send_tcp_crr */
+
+#endif
+/* end of BSD_TCP_CRR_TESTS */
+
+
#define BSD_UDP_STREAM_TESTS
#define BSD_UDP_RR_TESTS
#ifdef BSD_UDP_STREAM_TESTS
@@ -2508,7 +3439,7 @@
if (test->debug) {
fprintf(test->where,
"%s:bind returned %d errno=%d\n",
- __func__, rc, errno);
+ __func__, rc, GET_ERRNO);
fflush(test->where);
}
if (rc == -1) {
@@ -2708,7 +3639,7 @@
if (test->debug) {
fprintf(test->where,
"%s:bind returned %d errno=%d\n",
- __func__, rc, errno);
+ __func__, rc, GET_ERRNO);
fflush(test->where);
}
if (rc == -1) {
@@ -2979,7 +3910,7 @@
if (test->debug) {
fprintf(test->where,
"%s:bind returned %d errno=%d\n",
- __func__, rc, errno);
+ __func__, rc, GET_ERRNO);
fflush(test->where);
}
if (rc == -1) {
@@ -3219,7 +4150,7 @@
if (test->debug) {
fprintf(test->where,
"%s:bind returned %d errno=%d\n",
- __func__, rc, errno);
+ __func__, rc, GET_ERRNO);
fflush(test->where);
}
if (rc == -1) {
Modified: trunk/src/nettest_bsd.h
===================================================================
--- trunk/src/nettest_bsd.h 2007-03-09 18:38:34 UTC (rev 206)
+++ trunk/src/nettest_bsd.h 2007-03-09 19:00:05 UTC (rev 207)
@@ -102,6 +102,7 @@
int recv_width;
int req_size;
int rsp_size;
+ int multi_queue;
/* data structures for UDP RR packet loss detection and retransmission. */
int retry_index;
More information about the netperf-dev
mailing list