[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