[netperf-dev] netperf4 commit notice r27 - trunk/src
raj at netperf.org
raj at netperf.org
Tue Nov 29 17:00:38 PST 2005
Author: raj
Date: 2005-11-29 17:00:36 -0800 (Tue, 29 Nov 2005)
New Revision: 27
Modified:
trunk/src/dns_config.xml
trunk/src/netlib.c
trunk/src/netperf.h
trunk/src/netperf_docs.dtd
trunk/src/nettest_bsd.c
trunk/src/nettest_dns.c
trunk/src/nettest_dns.h
trunk/src/nettest_vst.c
Log:
start to add proper platform-agnostic timestamp support, fix delta_macro to
be delta_micro, create a dns_args for the DTD, and start getting things ready
to have more than one DNS request outstanding at a time
Modified: trunk/src/dns_config.xml
===================================================================
--- trunk/src/dns_config.xml 2005-11-29 23:33:26 UTC (rev 26)
+++ trunk/src/dns_config.xml 2005-11-30 01:00:36 UTC (rev 27)
@@ -18,6 +18,10 @@
fill_file = "/tmp/dns_requests"
send_buffer_size = "128"
recv_buffer_size = "128" />
+ <dns_args
+ max_outstanding = "1"
+ timeout = "5000"
+ use_tcp = "false" />
</test>
</netserver>
</netperf>
Modified: trunk/src/netlib.c
===================================================================
--- trunk/src/netlib.c 2005-11-29 23:33:26 UTC (rev 26)
+++ trunk/src/netlib.c 2005-11-30 01:00:36 UTC (rev 27)
@@ -92,6 +92,54 @@
#include "nettest_bsd.h"
+#ifdef HAVE_GETHRTIME
+
+void
+netperf_timestamp(hrtime_t *timestamp)
+{
+ *timestamp = gethrtime();
+}
+
+int
+delta_micro(hrtime_t *begin, hrtime_t *end)
+{
+ long nsecs;
+ nsecs = (*end) - (*begin);
+ return(nsecs/1000);
+}
+
+#else
+
+void
+netperf_timestamp(struct timeval *timestamp)
+{
+ gettimeofday(timestamp,NULL);
+}
+
+ /* return the difference (in micro seconds) between two timeval */
+ /* timestamps */
+int
+delta_micro(struct timeval *begin,struct timeval *end)
+
+{
+
+ int usecs, secs;
+
+ if (end->tv_usec < begin->tv_usec) {
+ /* borrow a second from the tv_sec */
+ end->tv_usec += 1000000;
+ end->tv_sec--;
+ }
+ usecs = end->tv_usec - begin->tv_usec;
+ secs = end->tv_sec - begin->tv_sec;
+
+ usecs += (secs * 1000000);
+
+ return(usecs);
+
+}
+#endif /* HAVE_GETHRTIME */
+
/* This routine will return the two arguments to the calling routine. */
/* If the second argument is not specified, and there is no comma, */
/* then the value of the second argument will be the same as the */
Modified: trunk/src/netperf.h
===================================================================
--- trunk/src/netperf.h 2005-11-29 23:33:26 UTC (rev 26)
+++ trunk/src/netperf.h 2005-11-30 01:00:36 UTC (rev 27)
@@ -45,6 +45,12 @@
#define NETPERF_PATH_SEP "\\"
#endif
+#ifdef HAVE_GETHRTIME
+#define NETPERF_TIMESTAMP_T hrtime_t
+#else
+#define NETPERF_TIMESTAMP_T struct timeval
+#endif
+
/* a set of server_t's will exist in the netperf process and will
describe everything that netperf needs to know about a server
instance (ie remote netserver). */
Modified: trunk/src/netperf_docs.dtd
===================================================================
--- trunk/src/netperf_docs.dtd 2005-11-29 23:33:26 UTC (rev 26)
+++ trunk/src/netperf_docs.dtd 2005-11-30 01:00:36 UTC (rev 27)
@@ -162,7 +162,8 @@
port CDATA #REQUIRED
>
-<!ELEMENT test ((dependson | dependency_data)?, (socket_args | unknown )?) >
+<!ELEMENT test ((dependson | dependency_data)?, (socket_args | unknown )?,
+ (dns_args)? ) >
<!ATTLIST test
xmlns CDATA #FIXED "http://www.netperf.org/ns/netperf"
tid ID #REQUIRED
@@ -450,6 +451,11 @@
recv_offset CDATA %default.offset;
>
+<!ELEMENT dns_args EMPTY >
+<!ATTLIST dns_args
+ max_outstanding CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+>
<!-- Element definitions for variable sized data tests -->
Modified: trunk/src/nettest_bsd.c
===================================================================
--- trunk/src/nettest_bsd.c 2005-11-29 23:33:26 UTC (rev 26)
+++ trunk/src/nettest_bsd.c 2005-11-30 01:00:36 UTC (rev 27)
@@ -1276,7 +1276,7 @@
}
/* code to timestamp enabled by HISTOGRAM */
HIST_TIMESTAMP(&time_two);
- HIST_ADD(my_data->time_hist,delta_macro(&time_one,&time_two));
+ HIST_ADD(my_data->time_hist,delta_micro(&time_one,&time_two));
new_state = CHECK_REQ_STATE;
if (new_state == TEST_LOADED) {
/* transitioning to loaded state from measure state
@@ -1463,7 +1463,7 @@
my_data->send_ring = my_data->send_ring->next;
/* code to timestamp enabled by HISTOGRAM */
HIST_TIMESTAMP(&time_two);
- HIST_ADD(my_data->time_hist,delta_macro(&time_one,&time_two));
+ HIST_ADD(my_data->time_hist,delta_micro(&time_one,&time_two));
new_state = CHECK_REQ_STATE;
if (new_state == TEST_LOADED) {
/* transitioning to loaded state from measure state
@@ -1879,7 +1879,7 @@
}
/* code to timestamp enabled by HISTOGRAM */
HIST_TIMESTAMP(&time_two);
- HIST_ADD(my_data->time_hist,delta_macro(&time_one,&time_two));
+ HIST_ADD(my_data->time_hist,delta_micro(&time_one,&time_two));
my_data->recv_ring = my_data->recv_ring->next;
my_data->send_ring = my_data->send_ring->next;
new_state = CHECK_REQ_STATE;
@@ -2130,7 +2130,7 @@
}
/* code to timestamp enabled by HISTOGRAM */
HIST_TIMESTAMP(&time_two);
- HIST_ADD(my_data->time_hist,delta_macro(&time_one,&time_two));
+ HIST_ADD(my_data->time_hist,delta_micro(&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;
Modified: trunk/src/nettest_dns.c
===================================================================
--- trunk/src/nettest_dns.c 2005-11-29 23:33:26 UTC (rev 26)
+++ trunk/src/nettest_dns.c 2005-11-30 01:00:36 UTC (rev 27)
@@ -757,6 +757,7 @@
{
dns_data_t *new_data;
xmlNodePtr args;
+ xmlNodePtr dns_args = NULL;
xmlChar *string;
xmlChar *units;
xmlChar *localhost;
@@ -777,6 +778,9 @@
if (!xmlStrcmp(args->name,(const xmlChar *)"dependency_data")) {
test->dependency_data = args;
}
+ if (!xmlStrcmp(args->name,(const xmlChar *)"dns_args")) {
+ dns_args = args;
+ }
if (xmlStrcmp(args->name,(const xmlChar *)"socket_args")) {
args = args->next;
continue;
@@ -815,12 +819,6 @@
we should use TCP, set TCP_NODELAY, keep the TCP connection
open... */
- /* we also neeed to add code to get stuff such as the name of the
- remote DNS server, the port number and what address family to
- use. this should be in this message rather than some dependent
- data bit since there will really be no corresponding "recv_"
- test. raj 2005-11-17 */
-
/* now get and initialize the local addressing info */
string = xmlGetProp(args,(const xmlChar *)"family");
localfam = strtofam(string);
@@ -857,7 +855,8 @@
than assign here so we can do a freeaddrinfo()? raj
2005-11-17 */
new_data->locaddr = local_ai;
- } else {
+ }
+ else {
if (test->debug) {
fprintf(test->where,
"%s: getaddrinfo returned %d %s\n",
@@ -871,7 +870,30 @@
DNSE_GETADDRINFO_ERROR,
gai_strerror(error));
}
- } else {
+ if (dns_args) {
+ string = xmlGetProp(args,(const xmlChar *)"max_outstanding");
+ if (string) {
+ new_data->max_outstanding = atoi(string);
+ }
+ else {
+ new_data->max_outstanding = 1;
+ }
+ string = xmlGetProp(args,(const xmlChar *)"timeout");
+ if (string) {
+ new_data->timeout = atoi(string);
+ }
+ else {
+ new_data->timeout = 5000;
+ }
+ }
+ else {
+ /* there was no dns_args element in the test element, so use the
+ program defaults. raj 2005-11-29 */
+ new_data->max_outstanding = 1;
+ new_data->timeout = 5000;
+ }
+ }
+ else {
report_test_failure(test,
(char *) __func__,
DNSE_NO_SOCKET_ARGS,
@@ -1123,10 +1145,12 @@
uint16_t *rsp_ptr;
uint16_t message_id;
uint16_t response_id;
+ int num_to_check;
dns_data_t *my_data;
dns_request_status_t *status_entry;
struct pollfd fds;
int keep_going=1;
+ NETPERF_TIMESTAMP_T now;
/* this aught to be enough to hold it - modulo stuff like large
requests on TCP connections... and we make it of type uint16_t so
@@ -1143,55 +1167,59 @@
while (NO_STATE_CHANGE(test) &&
keep_going) {
- /* go through and build the next request to send */
- req_size = get_next_dns_request(test,
- (char *)request_buffer,
- sizeof(request_buffer));
-
- /* set the ID as apropriate since it is a uint16_t, we'll not worry
- about "overflow" as it will just be dealt with "naturally. we use
- the magic number of "0" based on "knowing" that the ID is the
- first thing in the message, and it seems there is no commonly
- defined structure for a DNS reqeust header? raj 2005-11-18 */
-
- message_id = request_buffer[0] = my_data->request_id++;
-
- /* now stash some state away so we can deal with the response */
- status_entry = &(my_data->outstanding_requests[message_id]);
- if (status_entry->active) {
- /* this could be bad? or is it just an expired entry? */
- printf("Hey dummy, this entry %d is already active!\n",message_id);
- }
- else {
- status_entry->active = 1;
- status_entry->success = 1;
- NETPERF_TIME_STAMP(status_entry->sent_time);
- }
- /* send data for the test. we can use send() rather than sendto()
- because in _init we will have called connect() on the socket.
- now, if we are using UDP and the server happens to reply from a
- source IP address other than the one to which we have
- connected... well... raj 2005-11-18 */
-
- /* if we are ever going to pace these things, we need logic to
- decide if it is time to send another request or not */
-
- if((len=send(my_data->query_socket,
- request_buffer,
- req_size,
- 0)) != req_size) {
- /* this macro hides windows differences */
- if (CHECK_FOR_SEND_ERROR(len)) {
- keep_going = 0;
- report_test_failure(test,
- __func__,
- DNSE_DATA_SEND_ERROR,
- "data send error");
+ while (my_data->num_outstanding < my_data->max_outstanding ) {
+ /* go through and build the next request to send */
+ req_size = get_next_dns_request(test,
+ (char *)request_buffer,
+ sizeof(request_buffer));
+
+ /* set the ID as apropriate since it is a uint16_t, we'll not
+ worry about "overflow" as it will just be dealt with
+ "naturally. we use the magic number of "0" based on "knowing"
+ that the ID is the first thing in the message, and it seems
+ there is no commonly defined structure for a DNS reqeust
+ header? raj 2005-11-18 */
+
+ message_id = request_buffer[0] = my_data->request_id++;
+
+ /* now stash some state away so we can deal with the response */
+ status_entry = &(my_data->outstanding_requests[message_id]);
+ if (status_entry->active) {
+ /* this could be bad? or is it just an expired entry? */
+ printf("Hey dummy, this entry %d is already active!\n",message_id);
}
+ else {
+ status_entry->active = 1;
+ status_entry->success = 1;
+ netperf_timestamp(&(status_entry->sent_time));
+ }
+ /* send data for the test. we can use send() rather than
+ sendto() because in _init we will have called connect() on
+ the socket. now, if we are using UDP and the server happens
+ to reply from a source IP address other than the one to which
+ we have connected... well... raj 2005-11-18 */
+
+ /* if we are ever going to _really_ pace these things, we need
+ logic to decide if it is time to send another request or
+ not */
+
+ if((len=send(my_data->query_socket,
+ request_buffer,
+ req_size,
+ 0)) != req_size) {
+ /* this macro hides windows differences */
+ if (CHECK_FOR_SEND_ERROR(len)) {
+ keep_going = 0;
+ report_test_failure(test,
+ __func__,
+ DNSE_DATA_SEND_ERROR,
+ "data send error");
+ }
+ }
+ /* my_data->stats.named.queries_sent++; */
+ /* my_data->stats.named.query_bytes_sent += len; */
+ my_data->num_outstanding++;
}
- /* my_data->stats.named.queries_sent++; */
- /* my_data->stats.named.query_bytes_sent += len; */
-
/* recv the request for the test, but first we really need some sort
of timeout on a poll call or whatnot... */
@@ -1199,9 +1227,7 @@
fds.events = POLLIN;
fds.revents = 0;
- ret = poll(&fds,1,5000); /* magic constant alert - that is something
- that should come from the config
- file... */
+ ret = poll(&fds,1,my_data->timeout);
switch (ret) {
case -1:
@@ -1214,10 +1240,27 @@
break;
case 0:
- /* we had a timeout. invalidate the existing request so we will
- ignore it if it was simply delayed. status_entry should still
- be valid*/
- memset(status_entry,0,sizeof(status_entry));
+ /* we had a timeout. invalidate the existing request(s) as
+ apropriate so we will ignore it if it was simply
+ delayed. status_entry should still be valid. we only need to
+ go back at most num_outstanding requests */
+ num_to_check = my_data->num_outstanding;
+ netperf_timestamp(&now);
+ message_id = my_data->request_id;
+ message_id--; /* my_data->request_id is actually one more than
+ we sent */
+ while (num_to_check) {
+ status_entry = &(my_data->outstanding_requests[message_id]);
+ if ((status_entry->active) &&
+ (delta_micro(&(status_entry->sent_time),&now) >=
+ my_data->timeout * 1000)) {
+ my_data->num_outstanding--;
+ memset(status_entry,0,sizeof(status_entry));
+ }
+ message_id--; /* wrap-around is handled automagically since
+ this is a uint16_t */
+ num_to_check--;
+ }
break;
case 1:
@@ -1263,10 +1306,11 @@
/* code to timestamp enabled by HISTOGRAM */
HIST_TIMESTAMP(&time_two);
HIST_ADD(my_data->time_hist,
- delta_macro(&(status_entry->sent_time),&time_two));
+ delta_micro(&(status_entry->sent_time),&time_two));
/* my_data->stats.named.responses_received++; */
/* so we can continue to "leverage" the nettest_bsd reporter for
now. raj 2005-11-18 */
+ my_data->num_outstanding--;
my_data->stats.named.trans_sent++;
my_data->stats.named.trans_received++;
/* my_data->stats.named.response_bytes_received += response_len; */
@@ -1353,9 +1397,7 @@
fds.events = POLLIN;
fds.revents = 0;
- ret = poll(&fds,1,5000); /* magic constant alert - that is something
- that should come from the config
- file... */
+ ret = poll(&fds,1,my_data->timeout);
switch (ret) {
case -1:
Modified: trunk/src/nettest_dns.h
===================================================================
--- trunk/src/nettest_dns.h 2005-11-29 23:33:26 UTC (rev 26)
+++ trunk/src/nettest_dns.h 2005-11-30 01:00:36 UTC (rev 27)
@@ -54,11 +54,6 @@
sufficient or if we need to also check against stuff like the type
and the class? raj 2005-11-17 */
- /* until we get the gethrtime() stuff done, this will be a struct
- timeval and... this should probably really be in netperf.h... */
-#define NETPERF_TIMESTAMP_T struct timeval
-#define NETPERF_TIME_STAMP(s) gettimeofday(&(s),NULL);
-
typedef struct dns_request_status {
unsigned short active; /* was there a query sent with this id for
which we are awaiting a response */
@@ -85,7 +80,9 @@
int send_buf_size; /* send socket buffer size */
int rbuf_size_ret; /* receive socket buffer size returned on creation */
int recv_buf_size; /* receive socket buffer size */
-
+ int max_outstanding; /* max number of outstanding requests */
+ int num_outstanding; /* present number of requests outstanding */
+ int timeout; /* request timeout in milliseconds */
uint16_t request_id; /* this is used to match requests with
responses and serves as the index into the
outstanding queries array */
Modified: trunk/src/nettest_vst.c
===================================================================
--- trunk/src/nettest_vst.c 2005-11-29 23:33:26 UTC (rev 26)
+++ trunk/src/nettest_vst.c 2005-11-30 01:00:36 UTC (rev 27)
@@ -1570,7 +1570,7 @@
}
/* code to timestamp enabled by HISTOGRAM */
HIST_TIMESTAMP(&time_two);
- HIST_ADD(my_data->time_hist,delta_macro(&time_one,&time_two));
+ HIST_ADD(my_data->time_hist,delta_micro(&time_one,&time_two));
get_next_vst_transaction(test);
new_state = CHECK_REQ_STATE;
if (new_state == TEST_LOADED) {
@@ -1826,7 +1826,7 @@
}
/* code to timestamp enabled by HISTOGRAM */
HIST_TIMESTAMP(&time_two);
- HIST_ADD(my_data->time_hist,delta_macro(&time_one,&time_two));
+ HIST_ADD(my_data->time_hist,delta_micro(&time_one,&time_two));
my_data->stats.named.trans_sent++;
get_next_vst_transaction(test);
if (len == 0) {
More information about the netperf-dev
mailing list