nettest_bsd.c
Upload User: kvgkvg
Upload Date: 2015-05-07
Package Size: 1129k
Code Size: 385k
Development Platform:

C/C++

  1. #ifndef lint
  2. char nettest_id[]="
  3. @(#)nettest_bsd.c (c) Copyright 1993-2004 Hewlett-Packard Co. Version 2.4.3";
  4. #endif /* lint */
  5. /****************************************************************/
  6. /* */
  7. /* nettest_bsd.c */
  8. /* */
  9. /*      the BSD sockets parsing routine...                      */
  10. /*       ...with the addition of Windows NT, this is now also   */
  11. /*          a Winsock test... sigh :)                           */
  12. /*                                                              */
  13. /*      scan_sockets_args()                                     */
  14. /*                                                              */
  15. /* the actual test routines... */
  16. /* */
  17. /* send_tcp_stream() perform a tcp stream test */
  18. /* recv_tcp_stream() */
  19. /*      send_tcp_maerts()       perform a tcp stream test       */
  20. /*      recv_tcp_maerts()       in the other direction          */
  21. /* send_tcp_rr() perform a tcp request/response */
  22. /* recv_tcp_rr() */
  23. /*      send_tcp_conn_rr()      an RR test including connect    */
  24. /*      recv_tcp_conn_rr()                                      */
  25. /*      send_tcp_cc()           a connect/disconnect test with  */
  26. /*      recv_tcp_cc()           no RR                           */
  27. /* send_udp_stream() perform a udp stream test */
  28. /* recv_udp_stream() */
  29. /* send_udp_rr() perform a udp request/response */
  30. /* recv_udp_rr() */
  31. /* loc_cpu_rate() determine the local cpu maxrate */
  32. /* rem_cpu_rate() find the remote cpu maxrate */
  33. /* */
  34. /****************************************************************/
  35. #ifdef HAVE_CONFIG_H
  36. #include <config.h>
  37. #endif
  38. #include <stdio.h>
  39. #if HAVE_SYS_TYPES_H
  40. # include <sys/types.h>
  41. #endif
  42. #if HAVE_SYS_STAT_H
  43. # include <sys/stat.h>
  44. #endif
  45. #if STDC_HEADERS
  46. # include <stdlib.h>
  47. # include <stddef.h>
  48. #else
  49. # if HAVE_STDLIB_H
  50. #  include <stdlib.h>
  51. # endif
  52. #endif
  53. #if HAVE_STRING_H
  54. # if !STDC_HEADERS && HAVE_MEMORY_H
  55. #  include <memory.h>
  56. # endif
  57. # include <string.h>
  58. #endif
  59. #if HAVE_STRINGS_H
  60. # include <strings.h>
  61. #endif
  62. #if HAVE_INTTYPES_H
  63. # include <inttypes.h>
  64. #else
  65. # if HAVE_STDINT_H
  66. #  include <stdint.h>
  67. # endif
  68. #endif
  69. #if HAVE_UNISTD_H
  70. # include <unistd.h>
  71. #endif
  72. #include <fcntl.h>
  73. #ifndef WIN32
  74. #include <errno.h>
  75. #include <signal.h>
  76. #endif
  77. #if TIME_WITH_SYS_TIME
  78. # include <sys/time.h>
  79. # include <time.h>
  80. #else
  81. # if HAVE_SYS_TIME_H
  82. #  include <sys/time.h>
  83. # else
  84. #  include <time.h>
  85. # endif
  86. #endif
  87. #ifdef NOSTDLIBH
  88. #include <malloc.h>
  89. #endif /* NOSTDLIBH */
  90. #ifndef WIN32
  91. #if !defined(__VMS)
  92. #include <sys/ipc.h>
  93. #endif /* !defined(__VMS) */
  94. #include <sys/socket.h>
  95. #include <netinet/in.h>
  96. #include <netinet/tcp.h>
  97. #include <arpa/inet.h>
  98. #include <netdb.h>
  99. #else /* WIN32 */
  100. #include <process.h>
  101. #define netperf_socklen_t socklen_t
  102. #include <winsock2.h>
  103. /* while it is unlikely that anyone running Windows 2000 or NT 4 is
  104.    going to be trying to compile this, if they are they will want to
  105.    define DONT_IPV6 in the sources file */
  106. #ifndef DONT_IPV6
  107. #include <ws2tcpip.h>
  108. #endif
  109. #include <windows.h>
  110. #define sleep(x) Sleep((x)*1000)
  111. #define __func__ __FUNCTION__
  112. #endif /* WIN32 */
  113. /* We don't want to use bare constants in the shutdown() call.  In the
  114.    extremely unlikely event that SHUT_WR isn't defined, we will define
  115.    it to the value we used to be passing to shutdown() anyway.  raj
  116.    2007-02-08 */
  117. #if !defined(SHUT_WR)
  118. #define SHUT_WR 1
  119. #endif
  120. #if !defined(HAVE_GETADDRINFO) || !defined(HAVE_GETNAMEINFO)
  121. # include "missing/getaddrinfo.h"
  122. #endif
  123. #include "netlib.h"
  124. #include "netsh.h"
  125. #include "nettest_bsd.h"
  126. #if defined(WANT_HISTOGRAM) || defined(WANT_DEMO) 
  127. #include "hist.h"
  128. #endif /* WANT_HISTOGRAM */
  129. /* make first_burst_size unconditional so we can use it easily enough
  130.    when calculating transaction latency for the TCP_RR test. raj
  131.    2007-06-08 */
  132. int first_burst_size=0;
  133. #if defined(HAVE_SENDFILE) && (defined(__linux) || defined(__sun__))
  134. #include <sys/sendfile.h>
  135. #endif /* HAVE_SENDFILE && (__linux || __sun__) */
  136. /* these variables are specific to the BSD sockets tests, but can
  137.  * be used elsewhere if needed.  They are externed through nettest_bsd.h
  138.  */
  139. int
  140.   rss_size_req = -1, /* requested remote socket send buffer size */
  141.   rsr_size_req = -1, /* requested remote socket recv buffer size */
  142.   rss_size, /* remote socket send buffer size */
  143.   rsr_size, /* remote socket recv buffer size */
  144.   lss_size_req = -1, /* requested local socket send buffer size */
  145.   lsr_size_req = -1, /* requested local socket recv buffer size */
  146.   lss_size, /* local  socket send buffer size  */
  147.   lsr_size, /* local  socket recv buffer size  */
  148.   req_size = 1, /* request size                    */
  149.   rsp_size = 1, /* response size */
  150.   send_size, /* how big are individual sends */
  151.   recv_size; /* how big are individual receives */
  152. static  int confidence_iteration;
  153. static  char  local_cpu_method;
  154. static  char  remote_cpu_method;
  155. /* these will control the width of port numbers we try to use in the */
  156. /* TCP_CRR and/or TCP_TRR tests. raj 3/95 */
  157. static int client_port_min = 5000;
  158. static int client_port_max = 65535;
  159.  /* different options for the sockets */
  160. int
  161.   loc_nodelay, /* don't/do use NODELAY locally */
  162.   rem_nodelay, /* don't/do use NODELAY remotely */
  163. #ifdef TCP_CORK
  164.   loc_tcpcork=0,        /* don't/do use TCP_CORK locally        */
  165.   rem_tcpcork=0,        /* don't/do use TCP_CORK remotely       */
  166. #endif /* TCP_CORK */
  167.   loc_sndavoid, /* avoid send copies locally */
  168.   loc_rcvavoid, /* avoid recv copies locally */
  169.   rem_sndavoid, /* avoid send copies remotely */
  170.   rem_rcvavoid,  /* avoid recv_copies remotely */
  171.   local_connected = 0,  /* local socket type, connected/non-connected */
  172.   remote_connected = 0; /* remote socket type, connected/non-connected */
  173. #ifdef WANT_HISTOGRAM
  174. #ifdef HAVE_GETHRTIME
  175. static hrtime_t time_one;
  176. static hrtime_t time_two;
  177. #elif HAVE_GET_HRT
  178. #include "hrt.h"
  179. static hrt_t time_one;
  180. static hrt_t time_two;
  181. #elif defined(WIN32)
  182. static LARGE_INTEGER time_one;
  183. static LARGE_INTEGER time_two;
  184. #else
  185. static struct timeval time_one;
  186. static struct timeval time_two;
  187. #endif /* HAVE_GETHRTIME */
  188. static HIST time_hist;
  189. #endif /* WANT_HISTOGRAM */
  190. #ifdef WANT_INTERVALS
  191. int interval_count;
  192. #ifndef WANT_SPIN
  193. sigset_t signal_set;
  194. #define INTERVALS_INIT() 
  195.     if (interval_burst) { 
  196.       /* zero means that we never pause, so we never should need the 
  197.          interval timer. we used to use it for demo mode, but we deal 
  198.  with that with a variant on watching the clock rather than 
  199.  waiting for a timer. raj 2006-02-06 */ 
  200.       start_itimer(interval_wate); 
  201.     } 
  202.     interval_count = interval_burst; 
  203.     /* get the signal set for the call to sigsuspend */ 
  204.     if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) { 
  205.       fprintf(where, 
  206.       "%s: unable to get sigmask errno %dn", 
  207.       __func__, 
  208.       errno); 
  209.       fflush(where); 
  210.       exit(1); 
  211.     }
  212. #define INTERVALS_WAIT() 
  213.       /* in this case, the interval count is the count-down couter 
  214.  to decide to sleep for a little bit */ 
  215.       if ((interval_burst) && (--interval_count == 0)) { 
  216. /* call sigsuspend and wait for the interval timer to get us 
  217.    out */ 
  218. if (debug > 1) { 
  219.   fprintf(where,"about to suspendn"); 
  220.   fflush(where); 
  221. if (sigsuspend(&signal_set) == EFAULT) { 
  222.   fprintf(where, 
  223.   "%s: fault with sigsuspend.n", 
  224.                   __func__); 
  225.   fflush(where); 
  226.   exit(1); 
  227. interval_count = interval_burst; 
  228.       }
  229. #else
  230. /* first out timestamp */
  231. #ifdef HAVE_GETHRTIME
  232. static hrtime_t intvl_one;
  233. static hrtime_t intvl_two;
  234. static hrtime_t *intvl_one_ptr = &intvl_one;
  235. static hrtime_t *intvl_two_ptr = &intvl_two;
  236. static hrtime_t *temp_intvl_ptr = &intvl_one;
  237. #elif defined(WIN32)
  238. static LARGE_INTEGER intvl_one;
  239. static LARGE_INTEGER intvl_two;
  240. static LARGE_INTEGER *intvl_one_ptr = &intvl_one;
  241. static LARGE_INTEGER *intvl_two_ptr = &intvl_two;
  242. static LARGE_INTEGER *temp_intvl_ptr = &intvl_one;
  243. #else
  244. static struct timeval intvl_one;
  245. static struct timeval intvl_two;
  246. static struct timeval *intvl_one_ptr = &intvl_one;
  247. static struct timeval *intvl_two_ptr = &intvl_two;
  248. static struct timeval *temp_intvl_ptr = &intvl_one;
  249. #endif
  250. #define INTERVALS_INIT() 
  251.       if (interval_burst) { 
  252. HIST_timestamp(intvl_one_ptr); 
  253.       } 
  254.       interval_count = interval_burst; 
  255. #define INTERVALS_WAIT() 
  256.       /* in this case, the interval count is the count-down couter 
  257.  to decide to sleep for a little bit */ 
  258.       if ((interval_burst) && (--interval_count == 0)) { 
  259. /* call sigsuspend and wait for the interval timer to get us 
  260.    out */ 
  261. if (debug > 1) { 
  262.   fprintf(where,"about to spin suspendn"); 
  263.   fflush(where); 
  264.         HIST_timestamp(intvl_two_ptr); 
  265.         while(delta_micro(intvl_one_ptr,intvl_two_ptr) < interval_usecs) { 
  266.   HIST_timestamp(intvl_two_ptr); 
  267. temp_intvl_ptr = intvl_one_ptr; 
  268. intvl_one_ptr = intvl_two_ptr; 
  269. intvl_two_ptr = temp_intvl_ptr; 
  270. interval_count = interval_burst; 
  271.       }
  272. #endif
  273. #endif
  274. #ifdef WANT_DEMO
  275. #ifdef HAVE_GETHRTIME
  276. static hrtime_t demo_one;
  277. static hrtime_t demo_two;
  278. static hrtime_t *demo_one_ptr = &demo_one;
  279. static hrtime_t *demo_two_ptr = &demo_two;
  280. static hrtime_t *temp_demo_ptr = &demo_one;
  281. #elif defined(WIN32)
  282. static LARGE_INTEGER demo_one;
  283. static LARGE_INTEGER demo_two;
  284. static LARGE_INTEGER *demo_one_ptr = &demo_one;
  285. static LARGE_INTEGER *demo_two_ptr = &demo_two;
  286. static LARGE_INTEGER *temp_demo_ptr = &demo_one;
  287. #else
  288. static struct timeval demo_one;
  289. static struct timeval demo_two;
  290. static struct timeval *demo_one_ptr = &demo_one;
  291. static struct timeval *demo_two_ptr = &demo_two;
  292. static struct timeval *temp_demo_ptr = &demo_one;
  293. #endif 
  294. /* for a _STREAM test, "a" should be lss_size and "b" should be
  295.    rsr_size. for a _MAERTS test, "a" should be lsr_size and "b" should
  296.    be rss_size. raj 2005-04-06 */
  297. #define DEMO_STREAM_SETUP(a,b) 
  298.     if ((demo_mode) && (demo_units == 0)) { 
  299.       /* take our default value of demo_units to be the larger of 
  300.  twice the remote's SO_RCVBUF or twice our SO_SNDBUF */ 
  301.       if (a > b) { 
  302. demo_units = 2*a; 
  303.       } 
  304.       else { 
  305. demo_units = 2*b; 
  306.       } 
  307.     }
  308. #define DEMO_STREAM_INTERVAL(units) 
  309.       if (demo_mode) { 
  310. double actual_interval; 
  311. units_this_tick += units; 
  312. if (units_this_tick >= demo_units) { 
  313.   /* time to possibly update demo_units and maybe output an 
  314.      interim result */ 
  315.   HIST_timestamp(demo_two_ptr); 
  316.   actual_interval = delta_micro(demo_one_ptr,demo_two_ptr); 
  317.   /* we always want to fine-tune demo_units here whether we 
  318.      emit an interim result or not.  if we are short, this 
  319.      will lengthen demo_units.  if we are long, this will 
  320.      shorten it */ 
  321.   demo_units = demo_units * (demo_interval / actual_interval); 
  322.   if (actual_interval >= demo_interval) { 
  323.     /* time to emit an interim result */ 
  324.     fprintf(where, 
  325.     "Interim result: %7.2f %s/s over %.2f secondsn", 
  326.     calc_thruput_interval(units_this_tick, 
  327.   actual_interval/1000000.0), 
  328.     format_units(), 
  329.     actual_interval/1000000.0); 
  330.             fflush(where); 
  331.     units_this_tick = 0.0; 
  332.     /* now get a new starting timestamp.  we could be clever 
  333.        and swap pointers - the math we do probably does not 
  334.        take all that long, but for now this will suffice */ 
  335.     temp_demo_ptr = demo_one_ptr; 
  336.     demo_one_ptr = demo_two_ptr; 
  337.     demo_two_ptr = temp_demo_ptr; 
  338.   } 
  339.       }
  340. #define DEMO_RR_SETUP(a) 
  341.     if ((demo_mode) && (demo_units == 0)) { 
  342.       /* take whatever we are given */ 
  343. demo_units = a; 
  344.     }
  345. #define DEMO_RR_INTERVAL(units) 
  346.       if (demo_mode) { 
  347. double actual_interval; 
  348. units_this_tick += units; 
  349. if (units_this_tick >= demo_units) { 
  350.   /* time to possibly update demo_units and maybe output an 
  351.      interim result */ 
  352.   HIST_timestamp(demo_two_ptr); 
  353.   actual_interval = delta_micro(demo_one_ptr,demo_two_ptr); 
  354.   /* we always want to fine-tune demo_units here whether we 
  355.      emit an interim result or not.  if we are short, this 
  356.      will lengthen demo_units.  if we are long, this will 
  357.      shorten it */ 
  358.   demo_units = demo_units * (demo_interval / actual_interval); 
  359.   if (actual_interval >= demo_interval) { 
  360.     /* time to emit an interim result */ 
  361.     fprintf(where, 
  362.     "Interim result: %.2f %s/s over %.2f secondsn", 
  363.                     units_this_tick / (actual_interval/1000000.0), 
  364.     "Trans", 
  365.     actual_interval/1000000.0); 
  366.     units_this_tick = 0.0; 
  367.     /* now get a new starting timestamp.  we could be clever 
  368.        and swap pointers - the math we do probably does not 
  369.        take all that long, but for now this will suffice */ 
  370.     temp_demo_ptr = demo_one_ptr; 
  371.     demo_one_ptr = demo_two_ptr; 
  372.     demo_two_ptr = temp_demo_ptr; 
  373.   } 
  374.       }
  375. #endif 
  376. char sockets_usage[] = "n
  377. Usage: netperf [global options] -- [test options] n
  378. n
  379. TCP/UDP BSD Sockets Test Options:n
  380.     -b number         Send number requests at start of _RR testsn
  381.     -C                Set TCP_CORK when availablen
  382.     -D [L][,R]        Set TCP_NODELAY locally and/or remotely (TCP_*)n
  383.     -h                Display this textn
  384.     -H name,fam       Use name (or IP) and family as target of data connectionn
  385.     -L name,fam       Use name (or IP) and family as source of data connectionn
  386.     -m bytes          Set the send size (TCP_STREAM, UDP_STREAM)n
  387.     -M bytes          Set the recv size (TCP_STREAM, UDP_STREAM)n
  388.     -n                Use the connected socket for UDP locallyn
  389.     -N                Use the connected socket for UDP remotelyn
  390.     -p min[,max]      Set the min/max port numbers for TCP_CRR, TCP_TRRn
  391.     -P local[,remote] Set the local/remote port for the data socketn
  392.     -r req,[rsp]      Set request/response sizes (TCP_RR, UDP_RR)n
  393.     -s send[,recv]    Set local socket send/recv buffer sizesn
  394.     -S send[,recv]    Set remote socket send/recv buffer sizesn
  395.     -4                Use AF_INET (eg IPv4) on both ends of the data connn
  396.     -6                Use AF_INET6 (eg IPv6) on both ends of the data connn
  397. n
  398. For those options taking two parms, at least one must be specified;n
  399. specifying one value without a comma will set both parms to thatn
  400. value, specifying a value with a leading comma will set just the secondn
  401. parm, a value with a trailing comma will set just the first. To setn
  402. each parm to unique values, specify both and separate them with an
  403. comma.n"; 
  404. /* these routines convert between the AF address space and the NF
  405.    address space since the numeric values of AF_mumble are not the
  406.    same across the platforms. raj 2005-02-08 */
  407. int
  408. nf_to_af(int nf) {
  409.   switch(nf) {
  410.   case NF_INET:
  411.     return AF_INET;
  412.     break;
  413.   case NF_UNSPEC:
  414.     return AF_UNSPEC;
  415.     break;
  416.   case NF_INET6:
  417. #if defined(AF_INET6)
  418.     return AF_INET6;
  419. #else
  420.     return AF_UNSPEC;
  421. #endif
  422.     break;
  423.   default:
  424.     return AF_UNSPEC;
  425.     break;
  426.   }
  427. }
  428. int
  429. af_to_nf(int af) {
  430.   switch(af) {
  431.   case AF_INET:
  432.     return NF_INET;
  433.     break;
  434.   case AF_UNSPEC:
  435.     return NF_UNSPEC;
  436.     break;
  437. #if defined(AF_INET6)
  438.   case AF_INET6:
  439.     return NF_INET6;
  440.     break;
  441. #endif
  442.   default:
  443.     return NF_UNSPEC;
  444.     break;
  445.   }
  446. }     
  447.  /* This routine is intended to retrieve interesting aspects of tcp */
  448.  /* for the data connection. at first, it attempts to retrieve the */
  449.  /* maximum segment size. later, it might be modified to retrieve */
  450.  /* other information, but it must be information that can be */
  451.  /* retrieved quickly as it is called during the timing of the test. */
  452.  /* for that reason, a second routine may be created that can be */
  453.  /* called outside of the timing loop */
  454. static
  455. void
  456. get_tcp_info(SOCKET socket, int *mss)
  457. {
  458. #ifdef TCP_MAXSEG
  459.   netperf_socklen_t sock_opt_len;
  460.   sock_opt_len = sizeof(netperf_socklen_t);
  461.   if (getsockopt(socket,
  462.  getprotobyname("tcp")->p_proto,
  463.  TCP_MAXSEG,
  464.  (char *)mss,
  465.  &sock_opt_len) == SOCKET_ERROR) {
  466.     fprintf(where,
  467.     "netperf: get_tcp_info: getsockopt TCP_MAXSEG: errno %dn",
  468.     errno);
  469.     fflush(where);
  470.     *mss = -1;
  471.   }
  472. #else
  473.   *mss = -1;
  474. #endif /* TCP_MAXSEG */
  475. }
  476. /* return a pointer to a completed addrinfo chain - prefer
  477.    data_address to controlhost and utilize the specified address
  478.    family */
  479. struct addrinfo *
  480. complete_addrinfo(char *controlhost, char *data_address, char *port, int family, int type, int protocol, int flags) 
  481. {
  482.   struct addrinfo hints;
  483.   struct addrinfo *res;
  484.   struct addrinfo *temp_res;
  485. #define CHANGED_SOCK_TYPE  0x1
  486. #define CHANGED_PROTOCOL   0x2
  487. #define CHANGED_SCTP       0x4
  488.   int    change_info = 0;
  489.   static int change_warning_displayed = 0;
  490.   int count = 0;
  491.   int error = 0;
  492.   char *hostname;
  493.   /* take data-address over controlhost */
  494.   if (data_address)
  495.     hostname = data_address;
  496.   else
  497.     hostname = controlhost;
  498.   if (debug) {
  499.     fprintf(where,
  500.     "complete_addrinfo using hostname %s port %s family %s type %s prot %s flags 0x%xn",
  501.     hostname,
  502.     port,
  503.     inet_ftos(family),
  504.     inet_ttos(type),
  505.     inet_ptos(protocol),
  506.     flags);
  507.     fflush(where);
  508.   }
  509.   memset(&hints, 0, sizeof(hints));
  510.   hints.ai_family = family;
  511.   hints.ai_socktype = type;
  512.   hints.ai_protocol = protocol;
  513.   hints.ai_flags = flags|AI_CANONNAME;
  514.   count = 0;
  515.   do {
  516.     error = getaddrinfo((char *)hostname,
  517.                         (char *)port,
  518.                         &hints,
  519.                         &res);
  520.     count += 1;
  521.     if (error == EAI_AGAIN) {
  522.       if (debug) {
  523.         fprintf(where,"Sleeping on getaddrinfo EAI_AGAINn");
  524.         fflush(where);
  525.       }
  526.       sleep(1);
  527.     }
  528.     /* while you see this kludge first, it is actually the second, the
  529.        first being the one for Solaris below. The need for this kludge
  530.        came after implementing the Solaris broken getaddrinfo kludge -
  531.        now we see a kludge in Linux getaddrinfo where if it is given
  532.        SOCK_STREAM and IPPROTO_SCTP it barfs with a -7
  533.        EAI_SOCKTYPE. so, we check if the error was EAI_SOCKTYPE and if
  534.        we were asking for IPPROTO_SCTP and if so, kludge, again... raj
  535.        2008-10-13 */
  536. #ifdef WANT_SCTP
  537.     if (EAI_SOCKTYPE == error
  538. #ifdef EAI_BADHINTS
  539.         || EAI_BADHINTS == error
  540. #endif
  541.         ) {
  542.       /* we ass-u-me this is the Linux getaddrinfo bug, clear the
  543.  hints.ai_protocol field, and set some state "remembering"
  544.  that we did this so the code for the Solaris kludge can do
  545.  the fix-up for us.  also flip error over to EAI_AGAIN and
  546.  make sure we don't "count" this time around the loop. */
  547.       hints.ai_protocol = 0;
  548.       error = EAI_AGAIN;
  549.       count -= 1;
  550.       change_info |= CHANGED_SCTP;
  551.     }
  552. #endif
  553.   } while ((error == EAI_AGAIN) && (count <= 5));
  554.   if (error) {
  555.     fprintf(where,
  556.     "complete_addrinfo: could not resolve '%s' port '%s' af %d",
  557.     hostname,
  558.     port,
  559.     family);
  560.     fprintf(where,
  561.     "ntgetaddrinfo returned %d %sn",
  562.     error,
  563.     gai_strerror(error));
  564.     fflush(where);
  565.     exit(-1);
  566.   }
  567.   /* there exists at least one platform - Solaris 10 - that does not
  568.      seem to completely honor the ai_protocol and/or ai_socktype one
  569.      sets in the hints parm to the getaddrinfo call.  so, we need to
  570.      walk the list of entries returned and if either of those do not
  571.      match what we asked for, we need to go ahead and set them
  572.      "correctly" this is based in part on some earlier SCTP-only code
  573.      from previous revisions.  raj 2006-10-09 */
  574.   temp_res = res;
  575.   while (temp_res) {
  576.     if ((type)  &&
  577. (temp_res->ai_socktype != type)) {
  578.       change_info |= CHANGED_SOCK_TYPE;
  579.       if (debug) {
  580. fprintf(where,
  581. "WARNING! Changed bogus getaddrinfo socket type %d to %dn",
  582. temp_res->ai_socktype,
  583. type);
  584. fflush(where);
  585.       }
  586.       temp_res->ai_socktype = type;
  587.     }
  588.     if ((protocol) &&
  589. (temp_res->ai_protocol != protocol)) {
  590.       change_info |= CHANGED_PROTOCOL;
  591.       if (debug) {
  592. fprintf(where,
  593. "WARNING! Changed bogus getaddrinfo protocol %d to %dn",
  594. temp_res->ai_protocol,
  595. protocol);
  596. fflush(where);
  597.       }
  598.       temp_res->ai_protocol = protocol;
  599.     }
  600.     temp_res = temp_res->ai_next;
  601.   }
  602.   if ((change_info & CHANGED_SOCK_TYPE) &&
  603.       !(change_warning_displayed & CHANGED_SOCK_TYPE)) {
  604.     change_warning_displayed |= CHANGED_SOCK_TYPE;
  605.     fprintf(where,
  606.     "WARNING! getaddrinfo returned a socket type which did notn");
  607.     fprintf(where,
  608.     "match the requested type.  Please contact your vendor forn");
  609.     fprintf(where,
  610.     "a fix to this bug in getaddrinfo()n");
  611.     fflush(where);
  612.   }
  613.   /* if we dropped the protocol hint, it would be for a protocol that
  614.      getaddrinfo() wasn't supporting yet, not for the bug that it took
  615.      our hint and still returned zero. raj 2006-10-16 */
  616.   if ((change_info & CHANGED_PROTOCOL) &&
  617.       !(change_warning_displayed & CHANGED_PROTOCOL) &&
  618.       (hints.ai_protocol != 0)) {
  619.     change_warning_displayed |= CHANGED_PROTOCOL;
  620.     fprintf(where,
  621.     "WARNING! getaddrinfo returned a protocol other than then");
  622.     fprintf(where,
  623.     "requested protocol.  Please contact your vendor forn");
  624.     fprintf(where,
  625.     "a fix to this bug in getaddrinfo()n");
  626.     fflush(where);
  627.   }
  628.   if ((change_info & CHANGED_SCTP) &&
  629.       !(change_warning_displayed & CHANGED_SCTP)) {
  630.     change_warning_displayed |= CHANGED_SCTP;
  631.     fprintf(where,
  632.     "WARNING! getaddrinfo on this platform does not accept IPPROTO_SCTP!n");
  633.     fprintf(where,
  634.     "Please contact your vendor for a fix to this bug in getaddrinfo().n");
  635.     fflush(where);
  636.   }
  637.   if (debug) {
  638.     dump_addrinfo(where, res, hostname, port, family);
  639.   }
  640.   return(res);
  641. }
  642. void
  643. complete_addrinfos(struct addrinfo **remote,struct addrinfo **local, char remote_host[], int type, int protocol, int flags) {
  644.   *remote = complete_addrinfo(remote_host,
  645.       remote_data_address,
  646.       remote_data_port,
  647.       remote_data_family,
  648.       type,
  649.       protocol,
  650.       flags);
  651.   /* OK, if the user has not specified a local data endpoint address
  652.      (test-specific -L), pick the local data endpoint address based on
  653.      the remote data family info (test-specific -H or -4 or -6
  654.      option).  if the user has not specified remote data addressing
  655.      info (test-specific -H, -4 -6) pick something based on the local
  656.      control connection address (ie the global -L option). */
  657.   if (NULL == local_data_address) {
  658.     local_data_address = malloc(HOSTNAMESIZE);
  659.     if (NULL == remote_data_address) {
  660.       if (debug) {
  661. fprintf(where,
  662. "local_data_address not set, using local_host_name of '%s'n",
  663. local_host_name);
  664. fflush(where);
  665.       }
  666.       strcpy(local_data_address,local_host_name);
  667.     }
  668.     else {
  669.       if (debug) {
  670. fprintf(where,
  671. "local_data_address not set, using address family infon");
  672. fflush(where);
  673.       }
  674.       /* by default, use 0.0.0.0 - assume IPv4 */
  675.       strcpy(local_data_address,"0.0.0.0");
  676. #if defined(AF_INET6)
  677.       if ((AF_INET6 == local_data_family) ||
  678.   ((AF_UNSPEC == local_data_family) &&
  679.    (AF_INET6 == remote_data_family)) ||
  680.   ((AF_UNSPEC == local_data_family) && 
  681.    (AF_INET6 == (*remote)->ai_family))) {
  682. strcpy(local_data_address,"::0");
  683.       }
  684. #endif
  685.     }
  686.   }
  687.   *local = complete_addrinfo("what to put here?",
  688.      local_data_address,
  689.      local_data_port,
  690.      local_data_family,
  691.      type,
  692.      protocol,
  693.      flags|AI_PASSIVE);
  694. }
  695. void
  696. set_hostname_and_port(char *hostname, char *portstr, int family, int port)
  697. {
  698.   strcpy(hostname,"0.0.0.0");
  699. #if defined AF_INET6
  700.   if (AF_INET6 == family) {
  701.     strcpy(hostname,"::0");
  702.   }
  703. #endif
  704.     
  705.   sprintf(portstr, "%u", port);
  706. }
  707. static unsigned short
  708. get_port_number(struct addrinfo *res) 
  709. {
  710.  switch(res->ai_family) {
  711.   case AF_INET: {
  712.     struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr;
  713.     return(ntohs(foo->sin_port));
  714.     break;
  715.   }
  716. #if defined(AF_INET6)
  717.   case AF_INET6: {
  718.     struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr;
  719.     return(ntohs(foo->sin6_port));
  720.     break;
  721.   }
  722. #endif
  723.   default:
  724.     fprintf(where,
  725.     "Unexpected Address Family of %un",res->ai_family);
  726.     fflush(where);
  727.     exit(-1);
  728.   }
  729. }
  730. /* this routine will set the port number of the sockaddr in the
  731.    addrinfo to the specified value, based on the address family */
  732. void
  733. set_port_number(struct addrinfo *res, unsigned short port)
  734. {
  735.   switch(res->ai_family) {
  736.   case AF_INET: {
  737.     struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr;
  738.     foo->sin_port = htons(port);
  739.     break;
  740.   }
  741. #if defined(AF_INET6)
  742.   case AF_INET6: {
  743.     struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr;
  744.     foo->sin6_port = htons(port);
  745.     break;
  746.   }
  747. #endif
  748.   default:
  749.     fprintf(where,
  750.     "Unexpected Address Family of %un",res->ai_family);
  751.     fflush(where);
  752.     exit(-1);
  753.   }
  754. }
  755.  /* This routine will create a data (listen) socket with the
  756.   apropriate options set and return it to the caller. this replaces
  757.   all the duplicate code in each of the test routines and should help
  758.   make things a little easier to understand. since this routine can be
  759.   called by either the netperf or netserver programs, all output
  760.   should be directed towards "where." family is generally AF_INET and
  761.   type will be either SOCK_STREAM or SOCK_DGRAM.  This routine will
  762.   also be used by the "SCTP" tests, hence the slightly strange-looking
  763.   SCTP stuff in the classic bsd sockets test file... vlad/raj
  764.   2005-03-15 */
  765. SOCKET
  766. create_data_socket(struct addrinfo *res)
  767. {
  768.   SOCKET temp_socket;
  769.   int one;
  770.   int    on  = 1;
  771.   
  772.   /*set up the data socket                        */
  773.   temp_socket = socket(res->ai_family,
  774.        res->ai_socktype,
  775.        res->ai_protocol);
  776.   
  777.   if (temp_socket == INVALID_SOCKET){
  778.     fprintf(where,
  779.     "netperf: create_data_socket: socket: errno %d fam %s type %s prot %s errmsg %sn",
  780.     errno,
  781.     inet_ftos(res->ai_family),
  782.     inet_ttos(res->ai_socktype),
  783.     inet_ptos(res->ai_protocol),
  784.     strerror(errno));
  785.     fflush(where);
  786.     exit(1);
  787.   }
  788.   
  789.   if (debug) {
  790.     fprintf(where,"create_data_socket: socket %d obtained...n",temp_socket);
  791.     fflush(where);
  792.   }
  793.   
  794.   /* Modify the local socket size. The reason we alter the send buffer
  795.    size here rather than when the connection is made is to take care
  796.    of decreases in buffer size. Decreasing the window size after
  797.    connection establishment is a TCP no-no. Also, by setting the
  798.    buffer (window) size before the connection is established, we can
  799.    control the TCP MSS (segment size). The MSS is never (well, should
  800.    never be) more that 1/2 the minimum receive buffer size at each
  801.    half of the connection.  This is why we are altering the receive
  802.    buffer size on the sending size of a unidirectional transfer. If
  803.    the user has not requested that the socket buffers be altered, we
  804.    will try to find-out what their values are. If we cannot touch the
  805.    socket buffer in any way, we will set the values to -1 to indicate
  806.    that.  */
  807.   
  808.   /* all the oogy nitty gritty stuff moved from here into the routine
  809.      being called below, per patches from davidm to workaround the bug
  810.      in Linux getsockopt().  raj 2004-06-15 */
  811.   set_sock_buffer (temp_socket, SEND_BUFFER, lss_size_req, &lss_size);
  812.   set_sock_buffer (temp_socket, RECV_BUFFER, lsr_size_req, &lsr_size);
  813.   /* now, we may wish to enable the copy avoidance features on the */
  814.   /* local system. of course, this may not be possible... */
  815.   
  816. #ifdef SO_RCV_COPYAVOID
  817.   if (loc_rcvavoid) {
  818.     if (setsockopt(temp_socket,
  819.    SOL_SOCKET,
  820.    SO_RCV_COPYAVOID,
  821.    (const char *)&loc_rcvavoid,
  822.    sizeof(int)) == SOCKET_ERROR) {
  823.       fprintf(where,
  824.       "netperf: create_data_socket: Could not enable receive copy avoidance");
  825.       fflush(where);
  826.       loc_rcvavoid = 0;
  827.     }
  828.   }
  829. #else
  830.   /* it wasn't compiled in... */
  831.   loc_rcvavoid = 0;
  832. #endif /* SO_RCV_COPYAVOID */
  833. #ifdef SO_SND_COPYAVOID
  834.   if (loc_sndavoid) {
  835.     if (setsockopt(temp_socket,
  836.    SOL_SOCKET,
  837.    SO_SND_COPYAVOID,
  838.    (const char *)&loc_sndavoid,
  839.    sizeof(int)) == SOCKET_ERROR) {
  840.       fprintf(where,
  841.       "netperf: create_data_socket: Could not enable send copy avoidance");
  842.       fflush(where);
  843.       loc_sndavoid = 0;
  844.     }
  845.   }
  846. #else
  847.   /* it was not compiled in... */
  848.   loc_sndavoid = 0;
  849. #endif
  850.   
  851.   /* Now, we will see about setting the TCP_NODELAY flag on the local */
  852.   /* socket. We will only do this for those systems that actually */
  853.   /* support the option. If it fails, note the fact, but keep going. */
  854.   /* If the user tries to enable TCP_NODELAY on a UDP socket, this */
  855.   /* will cause an error to be displayed */
  856.   /* well..... long ago and far away that would have happened, in
  857.      particular because we would always use IPPROTO_TCP here.
  858.      however, now we are using res->ai_protocol, which will be
  859.      IPPROT_UDP, and while HP-UX, and I suspect no-one else on the
  860.      planet has a UDP_mumble option that overlaps with TCP_NODELAY,
  861.      sure as knuth made little green programs, linux has a UDP_CORK
  862.      option that is defined as a value of 1, which is the same a
  863.      TCP_NODELAY under Linux.  So, when asking for -D and
  864.      "TCP_NODELAY" under Linux, we are actually setting UDP_CORK
  865.      instead of getting an error like every other OS on the
  866.      planet. joy and rupture. this stops a UDP_RR test cold sooo we
  867.      have to make sure that res->ai_protocol actually makes sense for
  868.      a _NODELAY setsockopt() or a UDP_RR test on Linux where someone
  869.      mistakenly sets -D will hang.  raj 2005-04-21 */
  870.   
  871. #if defined(TCP_NODELAY) || defined(SCTP_NODELAY)
  872.   if ((loc_nodelay) && (res->ai_protocol != IPPROTO_UDP)) {
  873.     /* strictly speaking, since the if defined above is an OR, we
  874.        should probably check against TCP_NODELAY being defined here.
  875.        however, the likelihood of SCTP_NODELAY being defined and
  876.        TCP_NODELAY _NOT_ being defined is, probably :), epsilon.  raj
  877.        2005-03-15 */
  878.     int option = TCP_NODELAY;
  879.     /* I suspect that WANT_SCTP would suffice here since that is the
  880.        only time we would have called getaddrinfo with a hints asking
  881.        for SCTP, but just in case there is an SCTP implementation out
  882.        there _without_ SCTP_NODELAY... raj 2005-03-15 */ 
  883. #if defined(WANT_SCTP) && defined(SCTP_NODELAY)
  884.     if (IPPROTO_SCTP == res->ai_protocol) {
  885.       option = SCTP_NODELAY;
  886.     }
  887. #endif
  888.     one = 1;
  889.     if(setsockopt(temp_socket,
  890.   res->ai_protocol,
  891.   option,
  892.   (char *)&one,
  893.   sizeof(one)) == SOCKET_ERROR) {
  894.       fprintf(where,
  895.       "netperf: create_data_socket: nodelay: errno %dn",
  896.       errno);
  897.       fflush(where);
  898.     }
  899.     
  900.     if (debug > 1) {
  901.       fprintf(where,
  902.       "netperf: create_data_socket: [TCP|SCTP]_NODELAY requested...n");
  903.       fflush(where);
  904.     }
  905.   }
  906. #else /* TCP_NODELAY */
  907.   
  908.   loc_nodelay = 0;
  909.   
  910. #endif /* TCP_NODELAY */
  911. #if defined(TCP_CORK)
  912.     
  913.     if (loc_tcpcork != 0) {
  914.       /* the user wishes for us to set TCP_CORK on the socket */
  915.       int one = 1;
  916.       if (setsockopt(temp_socket,
  917.      getprotobyname("tcp")->p_proto,
  918.      TCP_CORK,
  919.      (char *)&one,
  920.      sizeof(one)) == SOCKET_ERROR) {
  921. perror("netperf: sendfile_tcp_stream: tcp_cork");
  922. exit(1);
  923.       }
  924.       if (debug) {
  925. fprintf(where,"sendfile_tcp_stream: tcp_cork...n");
  926.       }
  927.     }
  928.     
  929. #endif /* TCP_CORK */    
  930.   /* since some of the UDP tests do not do anything to cause an
  931.      implicit bind() call, we need to be rather explicit about our
  932.      bind() call here. even if the address and/or the port are zero
  933.      (INADDR_ANY etc). raj 2004-07-20 */
  934.   if (setsockopt(temp_socket,
  935.  SOL_SOCKET,
  936.  SO_REUSEADDR,
  937.  (const char *)&on,
  938.  sizeof(on)) < 0) {
  939.     fprintf(where,
  940.     "netperf: create_data_socket: SO_REUSEADDR failed %dn",
  941.     errno);
  942.     fflush(where);
  943.   }
  944.   
  945.   if (bind(temp_socket,
  946.    res->ai_addr,
  947.    res->ai_addrlen) < 0) {
  948.     if (debug) {
  949.       fprintf(where,
  950.       "netperf: create_data_socket: data socket bind failed errno %dn",
  951.       errno);
  952.       fprintf(where," port: %dn",get_port_number(res));
  953.       fflush(where);
  954.     }
  955.   }
  956.   
  957.   return(temp_socket);
  958. }
  959. #ifdef KLUDGE_SOCKET_OPTIONS
  960.  /* This routine is for those BROKEN systems which do not correctly */
  961.  /* pass socket attributes through calls such as accept(). It should */
  962.  /* only be called for those broken systems. I *really* don't want to */
  963.  /* have this, but even broken systems must be measured. raj 11/95 */
  964. void
  965. kludge_socket_options(int temp_socket)
  966. {
  967.   set_sock_buffer(temp_socket, SEND_BUFFER, lss_size_req, &lss_size);
  968.   set_sock_buffer(temp_socket, RECV_BUFFER, lsr_size_req, &lsr_size);
  969.   /* now, we may wish to enable the copy avoidance features on the */
  970.   /* local system. of course, this may not be possible... */
  971.   /* those calls were only valid for HP-UX, and I know that HP-UX is */
  972.   /* written correctly, and so we do not need to include those calls */
  973.   /* in this kludgy routine. raj 11/95 */
  974.   
  975.   /* Now, we will see about setting the TCP_NODELAY flag on the local */
  976.   /* socket. We will only do this for those systems that actually */
  977.   /* support the option. If it fails, note the fact, but keep going. */
  978.   /* If the user tries to enable TCP_NODELAY on a UDP socket, this */
  979.   /* will cause an error to be displayed */
  980.   
  981. #ifdef TCP_NODELAY
  982.   if (loc_nodelay) {
  983.     one = 1;
  984.     if(setsockopt(temp_socket,
  985.   getprotobyname("tcp")->p_proto,
  986.   TCP_NODELAY,
  987.   (char *)&one,
  988.   sizeof(one)) == SOCKET_ERROR) {
  989.       fprintf(where,"netperf: kludge_socket_options: nodelay: errno %dn",
  990.       errno);
  991.       fflush(where);
  992.     }
  993.     
  994.     if (debug > 1) {
  995.       fprintf(where,
  996.       "netperf: kludge_socket_options: TCP_NODELAY requested...n");
  997.       fflush(where);
  998.     }
  999.   }
  1000. #else /* TCP_NODELAY */
  1001.   
  1002.   loc_nodelay = 0;
  1003.   
  1004. #endif /* TCP_NODELAY */
  1005.   }
  1006. #endif /* KLUDGE_SOCKET_OPTIONS */
  1007. static void *
  1008. get_address_address(struct addrinfo *info) 
  1009. {
  1010.   struct sockaddr_in *sin;
  1011. #if defined(AF_INET6)
  1012.   struct sockaddr_in6 *sin6;
  1013. #endif
  1014.   switch(info->ai_family) {
  1015.   case AF_INET:
  1016.     sin = (struct sockaddr_in *)info->ai_addr;
  1017.     return(&(sin->sin_addr));
  1018.     break;
  1019. #if defined(AF_INET6)
  1020.   case AF_INET6:
  1021.     sin6 = (struct sockaddr_in6 *)info->ai_addr;
  1022.     return(&(sin6->sin6_addr));
  1023.     break;
  1024. #endif
  1025.   default:
  1026.     fprintf(stderr,"we never expected to get here in get_address_addressn");
  1027.     fflush(stderr);
  1028.     exit(-1);
  1029.   }
  1030. }
  1031. #if defined(WIN32) 
  1032. /* +*+ Why isn't this in the winsock headers yet? */
  1033. const char *
  1034. inet_ntop(int af, const void *src, char *dst, size_t size);
  1035. #endif
  1036. /* This routine is a generic test header printer for the topmost header */
  1037. void
  1038. print_top_test_header(char test_name[], struct addrinfo *source, struct addrinfo *destination)
  1039. {
  1040. #if defined(AF_INET6)
  1041.   char address_buf[INET6_ADDRSTRLEN];
  1042. #else
  1043.   char address_buf[16]; /* magic constant */
  1044. #endif
  1045.   /* we want to have some additional, interesting information in */
  1046.   /* the headers. we know some of it here, but not all, so we will */
  1047.   /* only print the test title here and will print the results */
  1048.   /* titles after the test is finished */
  1049.   fprintf(where,test_name);
  1050.   address_buf[0] = '';
  1051.   inet_ntop(source->ai_family,get_address_address(source),address_buf,sizeof(address_buf));
  1052.   fprintf(where,
  1053.   " from %s (%s) port %u %s",
  1054.   source->ai_canonname,
  1055.   address_buf,
  1056.   get_port_number(source),
  1057.   inet_ftos(source->ai_family));
  1058.   address_buf[0] = '';
  1059.   inet_ntop(destination->ai_family,get_address_address(destination),address_buf,sizeof(address_buf));
  1060.   fprintf(where,
  1061.   " to %s (%s) port %u %s",
  1062.   destination->ai_canonname,
  1063.   address_buf,
  1064.   get_port_number(destination),
  1065.   inet_ftos(destination->ai_family));
  1066.   if (iteration_max > 1) {
  1067.     fprintf(where,
  1068.     " : +/-%3.1f%% @ %2d%% conf. %s",
  1069.     interval/0.02,
  1070.     confidence_level,
  1071.     result_confidence_only ? " on result only" : "");
  1072.   }
  1073.   if ((loc_nodelay > 0) || (rem_nodelay > 0)) {
  1074.     fprintf(where," : nodelay");
  1075.   }
  1076.   if ((loc_sndavoid > 0) || 
  1077.       (loc_rcvavoid > 0) ||
  1078.       (rem_sndavoid > 0) ||
  1079.       (rem_rcvavoid > 0)) {
  1080.     fprintf(where," : copy avoidance");
  1081.   }
  1082.   if (no_control) {
  1083.     fprintf(where," : no control");
  1084.   }
  1085. #ifdef WANT_HISTOGRAM
  1086.   fprintf(where," : histogram");
  1087. #endif /* WANT_HISTOGRAM */
  1088. #ifdef WANT_INTERVALS
  1089. #ifndef WANT_SPIN
  1090.   fprintf(where," : interval");
  1091. #else
  1092.   fprintf(where," : spin interval");
  1093. #endif
  1094. #endif /* WANT_INTERVALS */
  1095. #ifdef DIRTY 
  1096.   fprintf(where," : dirty data");
  1097. #endif /* DIRTY */
  1098. #ifdef WANT_DEMO
  1099.   fprintf(where," : demo");
  1100. #endif
  1101. #ifdef WANT_FIRST_BURST
  1102.   /* a little hokey perhaps, but we really only want this to be
  1103.      emitted for tests where it actually is used, which means a
  1104.      "REQUEST/RESPONSE" test. raj 2005-11-10 */
  1105.   if (strstr(test_name,"REQUEST/RESPONSE")) {
  1106.     fprintf(where," : first burst %d",first_burst_size);
  1107.   }
  1108. #endif
  1109.   if (cpu_binding_requested) {
  1110.     fprintf(where," : cpu bind");
  1111.   }
  1112.   fprintf(where,"n");
  1113.   
  1114. }
  1115. /* This routine implements the TCP unidirectional data transfer test */
  1116. /* (a.k.a. stream) for the sockets interface. It receives its */
  1117. /* parameters via global variables from the shell and writes its */
  1118. /* output to the standard output. */
  1119. void 
  1120. send_tcp_stream(char remote_host[])
  1121. {
  1122.   
  1123.   char *tput_title = "
  1124. Recv   Send    Send                          n
  1125. Socket Socket  Message  Elapsed              n
  1126. Size   Size    Size     Time     Throughput  n
  1127. bytes  bytes   bytes    secs.    %s/sec  nn";
  1128.   
  1129.   char *tput_fmt_0 =
  1130.     "%7.2f %sn";
  1131.   
  1132.   char *tput_fmt_1 =
  1133.     "%6d %6d %6d    %-6.2f   %7.2f   %sn";
  1134.   
  1135.   char *cpu_title = "
  1136. Recv   Send    Send                          Utilization       Service Demandn
  1137. Socket Socket  Message  Elapsed              Send     Recv     Send    Recvn
  1138. Size   Size    Size     Time     Throughput  local    remote   local   remoten
  1139. bytes  bytes   bytes    secs.    %-8.8s/s  %% %c      %% %c      us/KB   us/KBnn";
  1140.   
  1141.   char *cpu_fmt_0 =
  1142.     "%6.3f %c %sn";
  1143.   char *cpu_fmt_1 =
  1144.     "%6d %6d %6d    %-6.2f     %7.2f   %-6.2f   %-6.2f   %-6.3f  %-6.3f %sn";
  1145.   
  1146.   char *ksink_fmt = "n
  1147. Alignment      Offset         %-8.8s %-8.8s    Sends   %-8.8s Recvsn
  1148. Local  Remote  Local  Remote  Xfered   Per                 Pern
  1149. Send   Recv    Send   Recv             Send (avg)          Recv (avg)n
  1150. %5d   %5d  %5d   %5d %6.4g  %6.2f    %6d   %6.2f %6dn";
  1151.   char *ksink_fmt2 = "n
  1152. Maximumn
  1153. Segmentn
  1154. Size (bytes)n
  1155. %6dn";
  1156.   
  1157.   
  1158.   float elapsed_time;
  1159.   
  1160.   /* what we want is to have a buffer space that is at least one */
  1161.   /* send-size greater than our send window. this will insure that we */
  1162.   /* are never trying to re-use a buffer that may still be in the hands */
  1163.   /* of the transport. This buffer will be malloc'd after we have found */
  1164.   /* the size of the local senc socket buffer. We will want to deal */
  1165.   /* with alignment and offset concerns as well. */
  1166.   
  1167.   struct ring_elt *send_ring;
  1168.   
  1169.   int len;
  1170.   unsigned int nummessages = 0;
  1171.   SOCKET send_socket;
  1172.   int bytes_remaining;
  1173.   int tcp_mss = -1;  /* possibly uninitialized on printf far below */
  1174.   /* with links like fddi, one can send > 32 bits worth of bytes */
  1175.   /* during a test... ;-) at some point, this should probably become a */
  1176.   /* 64bit integral type, but those are not entirely common yet */
  1177.   unsigned long long local_bytes_sent = 0;
  1178.   double bytes_sent = 0.0;
  1179.   
  1180.   float local_cpu_utilization;
  1181.   float local_service_demand;
  1182.   float remote_cpu_utilization;
  1183.   float remote_service_demand;
  1184.   double thruput;
  1185.   
  1186.   struct addrinfo *remote_res;
  1187.   struct addrinfo *local_res;
  1188.   
  1189.   struct tcp_stream_request_struct *tcp_stream_request;
  1190.   struct tcp_stream_response_struct *tcp_stream_response;
  1191.   struct tcp_stream_results_struct *tcp_stream_result;
  1192.   
  1193.   tcp_stream_request  = 
  1194.     (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
  1195.   tcp_stream_response =
  1196.     (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
  1197.   tcp_stream_result   = 
  1198.     (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
  1199.   
  1200. #ifdef WANT_HISTOGRAM
  1201.   if (verbosity > 1) {
  1202.     time_hist = HIST_new();
  1203.   }
  1204. #endif /* WANT_HISTOGRAM */
  1205.   /* since we are now disconnected from the code that established the */
  1206.   /* control socket, and since we want to be able to use different */
  1207.   /* protocols and such, we are passed the name of the remote host and */
  1208.   /* must turn that into the test specific addressing information. */
  1209.   
  1210.   /* complete_addrinfos will either succede or exit the process */
  1211.   complete_addrinfos(&remote_res,
  1212.      &local_res,
  1213.      remote_host,
  1214.      SOCK_STREAM,
  1215.      IPPROTO_TCP,
  1216.      0);
  1217.   
  1218.   if ( print_headers ) {
  1219.     print_top_test_header("TCP STREAM TEST",local_res,remote_res);
  1220.   }
  1221.   send_ring = NULL;
  1222.   confidence_iteration = 1;
  1223.   init_stat();
  1224.   /* we have a great-big while loop which controls the number of times */
  1225.   /* we run a particular test. this is for the calculation of a */
  1226.   /* confidence interval (I really should have stayed awake during */
  1227.   /* probstats :). If the user did not request confidence measurement */
  1228.   /* (no confidence is the default) then we will only go though the */
  1229.   /* loop once. the confidence stuff originates from the folks at IBM */
  1230.   while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
  1231.  (confidence_iteration <= iteration_min)) {
  1232.     /* initialize a few counters. we have to remember that we might be */
  1233.     /* going through the loop more than once. */
  1234.     
  1235.     nummessages    = 0;
  1236.     bytes_sent     = 0.0;
  1237.     times_up       =  0;
  1238.     
  1239.     /*set up the data socket                        */
  1240.     send_socket = create_data_socket(local_res);
  1241.     
  1242.     if (send_socket == INVALID_SOCKET){
  1243.       perror("netperf: send_tcp_stream: tcp stream data socket");
  1244.       exit(1);
  1245.     }
  1246.     
  1247.     if (debug) {
  1248.       fprintf(where,"send_tcp_stream: send_socket obtained...n");
  1249.     }
  1250.     
  1251.     /* at this point, we have either retrieved the socket buffer sizes, */
  1252.     /* or have tried to set them, so now, we may want to set the send */
  1253.     /* size based on that (because the user either did not use a -m */
  1254.     /* option, or used one with an argument of 0). If the socket buffer */
  1255.     /* size is not available, we will set the send size to 4KB - no */
  1256.     /* particular reason, just arbitrary... */
  1257.     if (send_size == 0) {
  1258.       if (lss_size > 0) {
  1259. send_size = lss_size;
  1260.       }
  1261.       else {
  1262. send_size = 4096;
  1263.       }
  1264.     }
  1265.     
  1266.     /* set-up the data buffer ring with the requested alignment and offset. */
  1267.     /* note also that we have allocated a quantity */
  1268.     /* of memory that is at least one send-size greater than our socket */
  1269.     /* buffer size. We want to be sure that there are at least two */
  1270.     /* buffers allocated - this can be a bit of a problem when the */
  1271.     /* send_size is bigger than the socket size, so we must check... the */
  1272.     /* user may have wanted to explicitly set the "width" of our send */
  1273.     /* buffers, we should respect that wish... */
  1274.     if (send_width == 0) {
  1275.       send_width = (lss_size/send_size) + 1;
  1276.       if (send_width == 1) send_width++;
  1277.     }
  1278.     
  1279.     if (send_ring == NULL) {
  1280.       /* only allocate the send ring once. this is a networking test, */
  1281.       /* not a memory allocation test. this way, we do not need a */
  1282.       /* deallocate_buffer_ring() routine, and I don't feel like */
  1283.       /* writing one anyway :) raj 11/94 */
  1284.       send_ring = allocate_buffer_ring(send_width,
  1285.        send_size,
  1286.        local_send_align,
  1287.        local_send_offset);
  1288.     }
  1289.     /* If the user has requested cpu utilization measurements, we must */
  1290.     /* calibrate the cpu(s). We will perform this task within the tests */
  1291.     /* themselves. If the user has specified the cpu rate, then */
  1292.     /* calibrate_local_cpu will return rather quickly as it will have */
  1293.     /* nothing to do. If local_cpu_rate is zero, then we will go through */
  1294.     /* all the "normal" calibration stuff and return the rate back. */
  1295.     
  1296.     if (local_cpu_usage) {
  1297.       local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
  1298.     }
  1299.     
  1300.     if (!no_control) {
  1301.       /* Tell the remote end to do a listen. The server alters the
  1302.  socket paramters on the other side at this point, hence the
  1303.  reason for all the values being passed in the setup
  1304.  message. If the user did not specify any of the parameters,
  1305.  they will be passed as 0, which will indicate to the remote
  1306.  that no changes beyond the system's default should be
  1307.  used. Alignment is the exception, it will default to 1, which
  1308.  will be no alignment alterations. */
  1309.     
  1310.       netperf_request.content.request_type = DO_TCP_STREAM;
  1311.       tcp_stream_request->send_buf_size = rss_size_req;
  1312.       tcp_stream_request->recv_buf_size = rsr_size_req;
  1313.       tcp_stream_request->receive_size = recv_size;
  1314.       tcp_stream_request->no_delay = rem_nodelay;
  1315.       tcp_stream_request->recv_alignment = remote_recv_align;
  1316.       tcp_stream_request->recv_offset = remote_recv_offset;
  1317.       tcp_stream_request->measure_cpu = remote_cpu_usage;
  1318.       tcp_stream_request->cpu_rate = remote_cpu_rate;
  1319.       if (test_time) {
  1320. tcp_stream_request->test_length = test_time;
  1321.       }
  1322.       else {
  1323. tcp_stream_request->test_length = test_bytes;
  1324.       }
  1325.       tcp_stream_request->so_rcvavoid = rem_rcvavoid;
  1326.       tcp_stream_request->so_sndavoid = rem_sndavoid;
  1327. #ifdef DIRTY
  1328.       tcp_stream_request->dirty_count     =       rem_dirty_count;
  1329.       tcp_stream_request->clean_count     =       rem_clean_count;
  1330. #endif /* DIRTY */
  1331.       tcp_stream_request->port            =    atoi(remote_data_port);
  1332.       tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
  1333.       if (debug > 1) {
  1334. fprintf(where,
  1335. "netperf: send_tcp_stream: requesting TCP stream testn");
  1336.       }
  1337.       
  1338.       send_request();
  1339.       
  1340.       /* The response from the remote will contain all of the relevant
  1341.          socket parameters for this test type. We will put them back
  1342.          into the variables here so they can be displayed if desired.
  1343.          The remote will have calibrated CPU if necessary, and will
  1344.          have done all the needed set-up we will have calibrated the
  1345.          cpu locally before sending the request, and will grab the
  1346.          counter value right after the connect returns. The remote
  1347.          will grab the counter right after the accept call. This saves
  1348.          the hassle of extra messages being sent for the TCP
  1349.          tests.  */
  1350.     
  1351.       recv_response();
  1352.     
  1353.       if (!netperf_response.content.serv_errno) {
  1354. if (debug)
  1355.   fprintf(where,"remote listen done.n");
  1356. rsr_size       = tcp_stream_response->recv_buf_size;
  1357. rss_size       = tcp_stream_response->send_buf_size;
  1358. rem_nodelay     = tcp_stream_response->no_delay;
  1359. remote_cpu_usage= tcp_stream_response->measure_cpu;
  1360. remote_cpu_rate = tcp_stream_response->cpu_rate;
  1361. /* we have to make sure that the server port number is in
  1362.    network order */
  1363. set_port_number(remote_res,
  1364. (short)tcp_stream_response->data_port_number);
  1365. rem_rcvavoid = tcp_stream_response->so_rcvavoid;
  1366. rem_sndavoid = tcp_stream_response->so_sndavoid;
  1367.       }
  1368.       else {
  1369. Set_errno(netperf_response.content.serv_errno);
  1370. fprintf(where,
  1371. "netperf: remote error %d",
  1372. netperf_response.content.serv_errno);
  1373. perror("");
  1374. fflush(where);
  1375. exit(1);
  1376.       }
  1377.     }
  1378. #ifdef WANT_DEMO
  1379.     DEMO_STREAM_SETUP(lss_size,rsr_size)
  1380. #endif
  1381.     /*Connect up to the remote port on the data socket  */
  1382.     if (connect(send_socket, 
  1383. remote_res->ai_addr,
  1384. remote_res->ai_addrlen) == INVALID_SOCKET){
  1385.       perror("netperf: send_tcp_stream: data socket connect failed");
  1386.       exit(1);
  1387.     }
  1388.     /* Data Socket set-up is finished. If there were problems, either */
  1389.     /* the connect would have failed, or the previous response would */
  1390.     /* have indicated a problem. I failed to see the value of the */
  1391.     /* extra  message after the accept on the remote. If it failed, */
  1392.     /* we'll see it here. If it didn't, we might as well start pumping */
  1393.     /* data. */ 
  1394.     
  1395.     /* Set-up the test end conditions. For a stream test, they can be */
  1396.     /* either time or byte-count based. */
  1397.     
  1398.     if (test_time) {
  1399.       /* The user wanted to end the test after a period of time. */
  1400.       times_up = 0;
  1401.       bytes_remaining = 0;
  1402.       /* in previous revisions, we had the same code repeated throught */
  1403.       /* all the test suites. this was unnecessary, and meant more */
  1404.       /* work for me when I wanted to switch to POSIX signals, so I */
  1405.       /* have abstracted this out into a routine in netlib.c. if you */
  1406.       /* are experiencing signal problems, you might want to look */
  1407.       /* there. raj 11/94 */
  1408.       start_timer(test_time);
  1409.     }
  1410.     else {
  1411.       /* The tester wanted to send a number of bytes. */
  1412.       bytes_remaining = test_bytes;
  1413.       times_up = 1;
  1414.     }
  1415.     
  1416.     /* The cpu_start routine will grab the current time and possibly */
  1417.     /* value of the idle counter for later use in measuring cpu */
  1418.     /* utilization and/or service demand and thruput. */
  1419.     
  1420.     cpu_start(local_cpu_usage);
  1421.     /* we only start the interval timer if we are using the
  1422.        timer-timed intervals rather than the sit and spin ones. raj
  1423.        2006-02-06 */    
  1424. #if defined(WANT_INTERVALS)
  1425.     INTERVALS_INIT();
  1426. #endif /* WANT_INTERVALS */
  1427.     /* before we start, initialize a few variables */
  1428. #ifdef WANT_DEMO
  1429.       if (demo_mode) {
  1430. HIST_timestamp(demo_one_ptr);
  1431.       }
  1432. #endif
  1433.       
  1434.     /* We use an "OR" to control test execution. When the test is */
  1435.     /* controlled by time, the byte count check will always return false. */
  1436.     /* When the test is controlled by byte count, the time test will */
  1437.     /* always return false. When the test is finished, the whole */
  1438.     /* expression will go false and we will stop sending data. */
  1439.     
  1440.     while ((!times_up) || (bytes_remaining > 0)) {
  1441.       
  1442. #ifdef DIRTY
  1443.       access_buffer(send_ring->buffer_ptr,
  1444.     send_size,
  1445.     loc_dirty_count,
  1446.     loc_clean_count);
  1447. #endif /* DIRTY */
  1448.       
  1449. #ifdef WANT_HISTOGRAM
  1450.       if (verbosity > 1) {
  1451. /* timestamp just before we go into send and then again just
  1452.  after we come out raj 8/94 */
  1453. /* but lets only do this if there is going to be a histogram
  1454.    displayed */
  1455. HIST_timestamp(&time_one);
  1456.       }
  1457. #endif /* WANT_HISTOGRAM */
  1458.       if((len=send(send_socket,
  1459.    send_ring->buffer_ptr,
  1460.    send_size,
  1461.    0)) != send_size) {
  1462.       if ((len >=0) || SOCKET_EINTR(len)) {
  1463.     /* the test was interrupted, must be the end of test */
  1464.     break;
  1465.   }
  1466. perror("netperf: data send error");
  1467. printf("len was %dn",len);
  1468. exit(1);
  1469.       }
  1470.       local_bytes_sent += send_size;
  1471. #ifdef WANT_HISTOGRAM
  1472.       if (verbosity > 1) {
  1473. /* timestamp the exit from the send call and update the histogram */
  1474. HIST_timestamp(&time_two);
  1475. HIST_add(time_hist,delta_micro(&time_one,&time_two));
  1476.       }
  1477. #endif /* WANT_HISTOGRAM */      
  1478. #ifdef WANT_DEMO
  1479.       DEMO_STREAM_INTERVAL(send_size)
  1480. #endif 
  1481. #if defined(WANT_INTERVALS)
  1482.       INTERVALS_WAIT();
  1483. #endif /* WANT_INTERVALS */
  1484.       
  1485.       /* now we want to move our pointer to the next position in the */
  1486.       /* data buffer...we may also want to wrap back to the "beginning" */
  1487.       /* of the bufferspace, so we will mod the number of messages sent */
  1488.       /* by the send width, and use that to calculate the offset to add */
  1489.       /* to the base pointer. */
  1490.       nummessages++;          
  1491.       send_ring = send_ring->next;
  1492.       if (bytes_remaining) {
  1493. bytes_remaining -= send_size;
  1494.       }
  1495.     }
  1496.     /* The test is over. Flush the buffers to the remote end. We do a */
  1497.     /* graceful release to insure that all data has been taken by the */
  1498.     /* remote. */ 
  1499.     /* but first, if the verbosity is greater than 1, find-out what */
  1500.     /* the TCP maximum segment_size was (if possible) */
  1501.     if (verbosity > 1) {
  1502.       tcp_mss = -1;
  1503.       get_tcp_info(send_socket,&tcp_mss);
  1504.     }
  1505.     
  1506.     if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR) {
  1507.       perror("netperf: cannot shutdown tcp stream socket");
  1508.       exit(1);
  1509.     }
  1510.     
  1511.     /* hang a recv() off the socket to block until the remote has */
  1512.     /* brought all the data up into the application. it will do a */
  1513.     /* shutdown to cause a FIN to be sent our way. We will assume that */
  1514.     /* any exit from the recv() call is good... raj 4/93 */
  1515.     
  1516.     recv(send_socket, send_ring->buffer_ptr, send_size, 0);
  1517.     
  1518.     /* this call will always give us the elapsed time for the test, and */
  1519.     /* will also store-away the necessaries for cpu utilization */
  1520.     
  1521.     cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
  1522. /* measured and how */
  1523. /* long did we really */
  1524. /* run? */
  1525.     
  1526.     /* we are finished with the socket, so close it to prevent hitting */
  1527.     /* the limit on maximum open files. */
  1528.     close(send_socket);
  1529.     if (!no_control) {
  1530.       /* Get the statistics from the remote end. The remote will have
  1531.  calculated service demand and all those interesting
  1532.  things. If it wasn't supposed to care, it will return obvious
  1533.  values. */
  1534.     
  1535.       recv_response();
  1536.       if (!netperf_response.content.serv_errno) {
  1537. if (debug)
  1538.   fprintf(where,"remote results obtainedn");
  1539.       }
  1540.       else {
  1541. Set_errno(netperf_response.content.serv_errno);
  1542. fprintf(where,
  1543. "netperf: remote error %d",
  1544. netperf_response.content.serv_errno);
  1545. perror("");
  1546. fflush(where);
  1547. exit(1);
  1548.       }
  1549.     
  1550.       /* We now calculate what our thruput was for the test. In the
  1551.  future, we may want to include a calculation of the thruput
  1552.  measured by the remote, but it should be the case that for a
  1553.  TCP stream test, that the two numbers should be *very*
  1554.  close... We calculate bytes_sent regardless of the way the
  1555.  test length was controlled.  If it was time, we needed to,
  1556.  and if it was by bytes, the user may have specified a number
  1557.  of bytes that wasn't a multiple of the send_size, so we
  1558.  really didn't send what he asked for ;-) */
  1559.     
  1560.       bytes_sent = ntohd(tcp_stream_result->bytes_received);
  1561.     }
  1562.     else {
  1563.       bytes_sent = (double)local_bytes_sent;
  1564.     }
  1565.     thruput = calc_thruput(bytes_sent);
  1566.     
  1567.     if (local_cpu_usage || remote_cpu_usage) {
  1568.       /* We must now do a little math for service demand and cpu */
  1569.       /* utilization for the system(s) */
  1570.       /* Of course, some of the information might be bogus because */
  1571.       /* there was no idle counter in the kernel(s). We need to make */
  1572.       /* a note of this for the user's benefit...*/
  1573.       if (local_cpu_usage) {
  1574. local_cpu_utilization = calc_cpu_util(0.0);
  1575. local_service_demand = calc_service_demand(bytes_sent,
  1576.       0.0,
  1577.       0.0,
  1578.       0);
  1579.       }
  1580.       else {
  1581. local_cpu_utilization = (float) -1.0;
  1582. local_service_demand = (float) -1.0;
  1583.       }
  1584.       
  1585.       if (remote_cpu_usage) {
  1586. remote_cpu_utilization = tcp_stream_result->cpu_util;
  1587. remote_service_demand = calc_service_demand(bytes_sent,
  1588.       0.0,
  1589.       remote_cpu_utilization,
  1590.       tcp_stream_result->num_cpus);
  1591.       }
  1592.       else {
  1593. remote_cpu_utilization = (float) -1.0;
  1594. remote_service_demand  = (float) -1.0;
  1595.       }
  1596.     }    
  1597.     else {
  1598.       /* we were not measuring cpu, for the confidence stuff, we */
  1599.       /* should make it -1.0 */
  1600.       local_cpu_utilization = (float) -1.0;
  1601.       local_service_demand = (float) -1.0;
  1602.       remote_cpu_utilization = (float) -1.0;
  1603.       remote_service_demand  = (float) -1.0;
  1604.     }
  1605.     /* at this point, we want to calculate the confidence information. */
  1606.     /* if debugging is on, calculate_confidence will print-out the */
  1607.     /* parameters we pass it */
  1608.     
  1609.     calculate_confidence(confidence_iteration,
  1610.  elapsed_time,
  1611.  thruput,
  1612.  local_cpu_utilization,
  1613.  remote_cpu_utilization,
  1614.  local_service_demand,
  1615.  remote_service_demand);
  1616.     
  1617.     
  1618.     confidence_iteration++;
  1619.   }
  1620.   /* at this point, we have finished making all the runs that we */
  1621.   /* will be making. so, we should extract what the calcuated values */
  1622.   /* are for all the confidence stuff. we could make the values */
  1623.   /* global, but that seemed a little messy, and it did not seem worth */
  1624.   /* all the mucking with header files. so, we create a routine much */
  1625.   /* like calcualte_confidence, which just returns the mean values. */
  1626.   /* raj 11/94 */
  1627.   retrieve_confident_values(&elapsed_time,
  1628.     &thruput,
  1629.     &local_cpu_utilization,
  1630.     &remote_cpu_utilization,
  1631.     &local_service_demand,
  1632.     &remote_service_demand);
  1633.   /* We are now ready to print all the information. If the user */
  1634.   /* has specified zero-level verbosity, we will just print the */
  1635.   /* local service demand, or the remote service demand. If the */
  1636.   /* user has requested verbosity level 1, he will get the basic */
  1637.   /* "streamperf" numbers. If the user has specified a verbosity */
  1638.   /* of greater than 1, we will display a veritable plethora of */
  1639.   /* background information from outside of this block as it it */
  1640.   /* not cpu_measurement specific...  */
  1641.   if (confidence < 0) {
  1642.     /* we did not hit confidence, but were we asked to look for it? */
  1643.     if (iteration_max > 1) {
  1644.       display_confidence();
  1645.     }
  1646.   }
  1647.   if (local_cpu_usage || remote_cpu_usage) {
  1648.     local_cpu_method = format_cpu_method(cpu_method);
  1649.     remote_cpu_method = format_cpu_method(tcp_stream_result->cpu_method);
  1650.     
  1651.     switch (verbosity) {
  1652.     case 0:
  1653.       if (local_cpu_usage) {
  1654. fprintf(where,
  1655. cpu_fmt_0,
  1656. local_service_demand,
  1657. local_cpu_method,
  1658. ((print_headers) || 
  1659.  (result_brand == NULL)) ? "" : result_brand);
  1660.       }
  1661.       else {
  1662. fprintf(where,
  1663. cpu_fmt_0,
  1664. remote_service_demand,
  1665. remote_cpu_method,
  1666. ((print_headers) || 
  1667.  (result_brand == NULL)) ? "" : result_brand);
  1668.       }
  1669.       break;
  1670.     case 1:
  1671.     case 2:
  1672.       if (print_headers) {
  1673. fprintf(where,
  1674. cpu_title,
  1675. format_units(),
  1676. local_cpu_method,
  1677. remote_cpu_method);
  1678.       }
  1679.     
  1680.       fprintf(where,
  1681.       cpu_fmt_1, /* the format string */
  1682.       rsr_size,         /* remote recvbuf size */
  1683.       lss_size,         /* local sendbuf size */
  1684.       send_size, /* how large were the sends */
  1685.       elapsed_time, /* how long was the test */
  1686.       thruput,          /* what was the xfer rate */
  1687.       local_cpu_utilization, /* local cpu */
  1688.       remote_cpu_utilization, /* remote cpu */
  1689.       local_service_demand, /* local service demand */
  1690.       remote_service_demand, /* remote service demand */
  1691.       ((print_headers) || 
  1692.        (result_brand == NULL)) ? "" : result_brand);
  1693.       break;
  1694.     }
  1695.   }
  1696.   else {
  1697.     /* The tester did not wish to measure service demand. */
  1698.     
  1699.     switch (verbosity) {
  1700.     case 0:
  1701.       fprintf(where,
  1702.       tput_fmt_0,
  1703.       thruput,
  1704.       ((print_headers) || 
  1705.        (result_brand == NULL)) ? "" : result_brand);
  1706.       break;
  1707.     case 1:
  1708.     case 2:
  1709.       if (print_headers) {
  1710. fprintf(where,tput_title,format_units());
  1711.       }
  1712.       fprintf(where,
  1713.       tput_fmt_1, /* the format string */
  1714.       rsr_size,  /* remote recvbuf size */
  1715.       lss_size,  /* local sendbuf size */
  1716.       send_size, /* how large were the sends */
  1717.       elapsed_time,  /* how long did it take */
  1718.       thruput,                  /* how fast did it go */
  1719.       ((print_headers) || 
  1720.        (result_brand == NULL)) ? "" : result_brand);
  1721.       break;
  1722.     }
  1723.   }
  1724.   
  1725.   /* it would be a good thing to include information about some of the */
  1726.   /* other parameters that may have been set for this test, but at the */
  1727.   /* moment, I do not wish to figure-out all the  formatting, so I will */
  1728.   /* just put this comment here to help remind me that it is something */
  1729.   /* that should be done at a later time. */
  1730.   
  1731.   if (verbosity > 1) {
  1732.     /* The user wanted to know it all, so we will give it to him. */
  1733.     /* This information will include as much as we can find about */
  1734.     /* TCP statistics, the alignments of the sends and receives */
  1735.     /* and all that sort of rot... */
  1736.    
  1737.     /* this stuff needs to be worked-out in the presence of confidence */
  1738.     /* intervals and multiple iterations of the test... raj 11/94 */
  1739.  
  1740.     fprintf(where,
  1741.     ksink_fmt,
  1742.     "Bytes",
  1743.     "Bytes",
  1744.     "Bytes",
  1745.     local_send_align,
  1746.     remote_recv_align,
  1747.     local_send_offset,
  1748.     remote_recv_offset,
  1749.     bytes_sent,
  1750.     bytes_sent / (double)nummessages,
  1751.     nummessages,
  1752.     bytes_sent / (double)tcp_stream_result->recv_calls,
  1753.     tcp_stream_result->recv_calls);
  1754.     fprintf(where,
  1755.     ksink_fmt2,
  1756.     tcp_mss);
  1757.     fflush(where);
  1758. #ifdef WANT_HISTOGRAM
  1759.     fprintf(where,"nnHistogram of time spent in send() call.n");
  1760.     fflush(where);
  1761.     HIST_report(time_hist);
  1762. #endif /* WANT_HISTOGRAM */
  1763.   }
  1764.   
  1765. }
  1766. /* This routine implements the netperf-side TCP unidirectional data
  1767.    transfer test (a.k.a. stream) for the sockets interface where the
  1768.    data flow is from the netserver to the netperf.  It receives its
  1769.    parameters via global variables from the shell and writes its
  1770.    output to the standard output. */
  1771. void 
  1772. send_tcp_maerts(char remote_host[])
  1773. {
  1774.   
  1775.   char *tput_title = "
  1776. Recv   Send    Send                          n
  1777. Socket Socket  Message  Elapsed              n
  1778. Size   Size    Size     Time     Throughput  n
  1779. bytes  bytes   bytes    secs.    %s/sec  nn";
  1780.   
  1781.   char *tput_fmt_0 =
  1782.     "%7.2f %sn";
  1783.   
  1784.   char *tput_fmt_1 =
  1785.     "%6d %6d %6d    %-6.2f   %7.2f    %s n";
  1786.   
  1787.   char *cpu_title = "
  1788. Recv   Send    Send                          Utilization       Service Demandn
  1789. Socket Socket  Message  Elapsed              Send     Recv     Send    Recvn
  1790. Size   Size    Size     Time     Throughput  local    remote   local   remoten
  1791. bytes  bytes   bytes    secs.    %-8.8s/s  %% %c      %% %c      us/KB   us/KBnn";
  1792.   
  1793.   char *cpu_fmt_0 =
  1794.     "%6.3f %c %sn";
  1795.   char *cpu_fmt_1 =
  1796.     "%6d %6d %6d    %-6.2f     %7.2f   %-6.2f   %-6.2f   %-6.3f  %-6.3f %sn";
  1797.   
  1798.   char *ksink_fmt = "n
  1799. Alignment      Offset         %-8.8s %-8.8s    Recvs   %-8.8s Sendsn
  1800. Local  Remote  Local  Remote  Xfered   Per                 Pern
  1801. Recv   Send    Recv   Send             Recv (avg)          Send (avg)n
  1802. %5d   %5d  %5d   %5d %6.4g  %6.2f    %6d   %6.2f %6dn";
  1803.   char *ksink_fmt2 = "n
  1804. Maximumn
  1805. Segmentn
  1806. Size (bytes)n
  1807. %6dn";
  1808.   
  1809.   
  1810.   float elapsed_time;
  1811.   
  1812.   /* what we want is to have a buffer space that is at least one */
  1813.   /* recv-size greater than our recv window. this will insure that we */
  1814.   /* are never trying to re-use a buffer that may still be in the hands */
  1815.   /* of the transport. This buffer will be malloc'd after we have found */
  1816.   /* the size of the local senc socket buffer. We will want to deal */
  1817.   /* with alignment and offset concerns as well. */
  1818.   
  1819.   struct ring_elt *recv_ring;
  1820.   
  1821.   int len;
  1822.   unsigned int nummessages = 0;
  1823.   SOCKET recv_socket;
  1824.   int bytes_remaining;
  1825.   int tcp_mss = -1;  /* possibly uninitialized on printf far below */
  1826.   /* with links like fddi, one can recv > 32 bits worth of bytes */
  1827.   /* during a test... ;-) at some point, this should probably become a */
  1828.   /* 64bit integral type, but those are not entirely common yet */
  1829.   double bytes_sent = 0.0;
  1830.   unsigned long long local_bytes_recvd = 0;
  1831.   float local_cpu_utilization;
  1832.   float local_service_demand;
  1833.   float remote_cpu_utilization;
  1834.   float remote_service_demand;
  1835.   double thruput;
  1836.   
  1837.   struct addrinfo *remote_res;
  1838.   struct addrinfo *local_res;
  1839.   
  1840.   struct tcp_maerts_request_struct *tcp_maerts_request;
  1841.   struct tcp_maerts_response_struct *tcp_maerts_response;
  1842.   struct tcp_maerts_results_struct *tcp_maerts_result;
  1843.   
  1844.   tcp_maerts_request  = 
  1845.     (struct tcp_maerts_request_struct *)netperf_request.content.test_specific_data;
  1846.   tcp_maerts_response =
  1847.     (struct tcp_maerts_response_struct *)netperf_response.content.test_specific_data;
  1848.   tcp_maerts_result   = 
  1849.     (struct tcp_maerts_results_struct *)netperf_response.content.test_specific_data;
  1850.   
  1851. #ifdef WANT_HISTOGRAM
  1852.   if (verbosity > 1) {
  1853.     time_hist = HIST_new();
  1854.   }
  1855. #endif /* WANT_HISTOGRAM */
  1856.   /* since we are now disconnected from the code that established the */
  1857.   /* control socket, and since we want to be able to use different */
  1858.   /* protocols and such, we are passed the name of the remote host and */
  1859.   /* must turn that into the test specific addressing information. */
  1860.   
  1861.   complete_addrinfos(&remote_res,
  1862.      &local_res,
  1863.      remote_host,
  1864.      SOCK_STREAM,
  1865.      IPPROTO_TCP,
  1866.      0);
  1867.   
  1868.   if ( print_headers ) {
  1869.     print_top_test_header("TCP MAERTS TEST",local_res,remote_res);
  1870.   }
  1871.   recv_ring = NULL;
  1872.   confidence_iteration = 1;
  1873.   init_stat();
  1874.   /* we have a great-big while loop which controls the number of times */
  1875.   /* we run a particular test. this is for the calculation of a */
  1876.   /* confidence interval (I really should have stayed awake during */
  1877.   /* probstats :). If the user did not request confidence measurement */
  1878.   /* (no confidence is the default) then we will only go though the */
  1879.   /* loop once. the confidence stuff originates from the folks at IBM */
  1880.   while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
  1881.  (confidence_iteration <= iteration_min)) {
  1882.     /* initialize a few counters. we have to remember that we might be */
  1883.     /* going through the loop more than once. */
  1884.     
  1885.     nummessages    = 0;
  1886.     bytes_sent     = 0.0;
  1887.     times_up       =  0;
  1888.     
  1889.     /*set up the data socket                        */
  1890.     recv_socket = create_data_socket(local_res);
  1891.     
  1892.     if (recv_socket == INVALID_SOCKET){
  1893.       perror("netperf: send_tcp_maerts: tcp stream data socket");
  1894.       exit(1);
  1895.     }
  1896.     
  1897.     if (debug) {
  1898.       fprintf(where,"send_tcp_maerts: recv_socket obtained...n");
  1899.     }
  1900.     /* at this point, we have either retrieved the socket buffer sizes, */
  1901.     /* or have tried to set them, so now, we may want to set the recv */
  1902.     /* size based on that (because the user either did not use a -m */
  1903.     /* option, or used one with an argument of 0). If the socket buffer */
  1904.     /* size is not available, we will set the recv size to 4KB - no */
  1905.     /* particular reason, just arbitrary... */
  1906.     if (recv_size == 0) {
  1907.       if (lsr_size > 0) {
  1908. recv_size = lsr_size;
  1909.       }
  1910.       else {
  1911. recv_size = 4096;
  1912.       }
  1913.     }
  1914.     /* set-up the data buffer ring with the requested alignment and offset. */
  1915.     /* note also that we have allocated a quantity */
  1916.     /* of memory that is at least one recv-size greater than our socket */
  1917.     /* buffer size. We want to be sure that there are at least two */
  1918.     /* buffers allocated - this can be a bit of a problem when the */
  1919.     /* recv_size is bigger than the socket size, so we must check... the */
  1920.     /* user may have wanted to explicitly set the "width" of our recv */
  1921.     /* buffers, we should respect that wish... */
  1922.     if (recv_width == 0) {
  1923.       recv_width = (lsr_size/recv_size) + 1;
  1924.       if (recv_width == 1) recv_width++;
  1925.     }
  1926.     
  1927.     if (recv_ring == NULL) {
  1928.       /* only allocate the recv ring once. this is a networking test, */
  1929.       /* not a memory allocation test. this way, we do not need a */
  1930.       /* deallocate_buffer_ring() routine, and I don't feel like */
  1931.       /* writing one anyway :) raj 11/94 */
  1932.       recv_ring = allocate_buffer_ring(recv_width,
  1933.        recv_size,
  1934.        local_recv_align,
  1935.        local_recv_offset);
  1936.     }
  1937.     /* If the user has requested cpu utilization measurements, we must */
  1938.     /* calibrate the cpu(s). We will perform this task within the tests */
  1939.     /* themselves. If the user has specified the cpu rate, then */
  1940.     /* calibrate_local_cpu will return rather quickly as it will have */
  1941.     /* nothing to do. If local_cpu_rate is zero, then we will go through */
  1942.     /* all the "normal" calibration stuff and return the rate back. */
  1943.     
  1944.     if (local_cpu_usage) {
  1945.       local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
  1946.     }
  1947.     
  1948.     if (!no_control) {
  1949.       /* Tell the remote end to do a listen. The server alters the
  1950.  socket paramters on the other side at this point, hence the
  1951.  reason for all the values being passed in the setup
  1952.  message. If the user did not specify any of the parameters,
  1953.  they will be passed as 0, which will indicate to the remote
  1954.  that no changes beyond the system's default should be
  1955.  used. Alignment is the exception, it will default to 1, which
  1956.  will be no alignment alterations. */
  1957.       netperf_request.content.request_type = DO_TCP_MAERTS;
  1958.       tcp_maerts_request->send_buf_size = rss_size_req;
  1959.       tcp_maerts_request->recv_buf_size = rsr_size_req;
  1960.       tcp_maerts_request->send_size = send_size;
  1961.       tcp_maerts_request->no_delay = rem_nodelay;
  1962.       tcp_maerts_request->send_alignment = remote_send_align;
  1963.       tcp_maerts_request->send_offset = remote_send_offset;
  1964.       tcp_maerts_request->measure_cpu = remote_cpu_usage;
  1965.       tcp_maerts_request->cpu_rate = remote_cpu_rate;
  1966.       if (test_time) {
  1967. tcp_maerts_request->test_length = test_time;
  1968.       }
  1969.       else {
  1970. tcp_maerts_request->test_length = test_bytes;
  1971.       }
  1972.       tcp_maerts_request->so_rcvavoid = rem_rcvavoid;
  1973.       tcp_maerts_request->so_sndavoid = rem_sndavoid;
  1974. #ifdef DIRTY
  1975.       tcp_maerts_request->dirty_count       =       rem_dirty_count;
  1976.       tcp_maerts_request->clean_count       =       rem_clean_count;
  1977. #endif /* DIRTY */
  1978.       tcp_maerts_request->port            = atoi(remote_data_port);
  1979.       tcp_maerts_request->ipfamily        = af_to_nf(remote_res->ai_family);
  1980.       if (debug > 1) {
  1981. fprintf(where,
  1982. "netperf: send_tcp_maerts: requesting TCP maerts testn");
  1983.       }
  1984.       
  1985.       send_request();
  1986.       
  1987.       /* The response from the remote will contain all of the relevant
  1988.  socket parameters for this test type. We will put them back
  1989.  into the variables here so they can be displayed if desired.
  1990.  The remote will have calibrated CPU if necessary, and will
  1991.  have done all the needed set-up we will have calibrated the
  1992.  cpu locally before sending the request, and will grab the
  1993.  counter value right after the connect returns. The remote
  1994.  will grab the counter right after the accept call. This saves
  1995.  the hassle of extra messages being sent for the TCP
  1996.  tests.  */
  1997.       
  1998.       recv_response();
  1999.     
  2000.       if (!netperf_response.content.serv_errno) {
  2001. if (debug)
  2002.   fprintf(where,"remote listen done.n");
  2003. rsr_size = tcp_maerts_response->recv_buf_size;
  2004. rss_size = tcp_maerts_response->send_buf_size;
  2005. rem_nodelay     = tcp_maerts_response->no_delay;
  2006. remote_cpu_usage= tcp_maerts_response->measure_cpu;
  2007. remote_cpu_rate = tcp_maerts_response->cpu_rate;
  2008. send_size       = tcp_maerts_response->send_size;
  2009. /* we have to make sure that the server port number is in
  2010.  network order */
  2011.       set_port_number(remote_res,
  2012.       (short)tcp_maerts_response->data_port_number);
  2013.       rem_rcvavoid = tcp_maerts_response->so_rcvavoid;
  2014.       rem_sndavoid = tcp_maerts_response->so_sndavoid;
  2015.       }
  2016.       else {
  2017. Set_errno(netperf_response.content.serv_errno);
  2018. fprintf(where,
  2019. "netperf: remote error %d",
  2020. netperf_response.content.serv_errno);
  2021. perror("");
  2022. fflush(where);
  2023. exit(1);
  2024.       }
  2025.     }
  2026. #ifdef WANT_DEMO
  2027.     DEMO_STREAM_SETUP(lsr_size,rss_size)
  2028. #endif
  2029.     /*Connect up to the remote port on the data socket  */
  2030.     if (connect(recv_socket, 
  2031. remote_res->ai_addr,
  2032. remote_res->ai_addrlen) == INVALID_SOCKET){
  2033.       perror("netperf: send_tcp_maerts: data socket connect failed");
  2034.       exit(1);
  2035.     }
  2036.     /* Data Socket set-up is finished. If there were problems, either */
  2037.     /* the connect would have failed, or the previous response would */
  2038.     /* have indicated a problem. I failed to see the value of the */
  2039.     /* extra  message after the accept on the remote. If it failed, */
  2040.     /* we'll see it here. If it didn't, we might as well start pumping */
  2041.     /* data. */ 
  2042.     
  2043.     /* Set-up the test end conditions. For a maerts test, they can be */
  2044.     /* either time or byte-count based. */
  2045.     
  2046.     if (test_time) {
  2047.       /* The user wanted to end the test after a period of time. */
  2048.       times_up = 0;
  2049.       bytes_remaining = 0;
  2050.       /* in previous revisions, we had the same code repeated throught */
  2051.       /* all the test suites. this was unnecessary, and meant more */
  2052.       /* work for me when I wanted to switch to POSIX signals, so I */
  2053.       /* have abstracted this out into a routine in netlib.c. if you */
  2054.       /* are experiencing signal problems, you might want to look */
  2055.       /* there. raj 11/94 */
  2056.       if (!no_control) {
  2057. /* this is a netperf to netserver test, netserver will close
  2058.    to tell us the test is over, so use PAD_TIME to avoid
  2059.    causing the netserver fits. */
  2060. start_timer(test_time + PAD_TIME);
  2061.       }
  2062.       else {
  2063. /* this is a netperf to data source test, no PAD_TIME */
  2064. start_timer(test_time);
  2065.       }
  2066.     }
  2067.     else {
  2068.       /* The tester wanted to recv a number of bytes. we don't do that 
  2069.  in a TCP_MAERTS test. sorry. raj 2002-06-21 */
  2070.       printf("netperf: send_tcp_maerts: test must be timedn");
  2071.       exit(1);
  2072.     }
  2073.     
  2074.     /* The cpu_start routine will grab the current time and possibly */
  2075.     /* value of the idle counter for later use in measuring cpu */
  2076.     /* utilization and/or service demand and thruput. */
  2077.     
  2078.     cpu_start(local_cpu_usage);
  2079.     
  2080. #ifdef WANT_INTERVALS
  2081.     INTERVALS_INIT();
  2082. #endif /* WANT_INTERVALS */
  2083.     /* before we start, initialize a few variables */
  2084. #ifdef WANT_DEMO
  2085.     if (demo_mode) {
  2086.       HIST_timestamp(demo_one_ptr);
  2087.     }
  2088. #endif
  2089.     /* the test will continue until we either get a zero-byte recv()
  2090.        on the socket or our failsafe timer expires. most of the time
  2091.        we trust that we get a zero-byte recieve from the socket. raj
  2092.        2002-06-21 */
  2093. #ifdef WANT_HISTOGRAM
  2094.     if (verbosity > 1) {
  2095.       /* timestamp just before we go into recv and then again just
  2096.  after we come out raj 8/94 */
  2097.       /* but only if we are actually going to display a histogram. raj
  2098.  2006-02-07 */
  2099.       HIST_timestamp(&time_one);
  2100.     }
  2101. #endif /* WANT_HISTOGRAM */
  2102.     
  2103.     while ((!times_up) && (len=recv(recv_socket,
  2104.     recv_ring->buffer_ptr,
  2105.     recv_size,
  2106.     0)) > 0 ) {
  2107. #ifdef WANT_HISTOGRAM
  2108.       if (verbosity > 1) {
  2109. /* timestamp the exit from the recv call and update the histogram */
  2110. HIST_timestamp(&time_two);
  2111. HIST_add(time_hist,delta_micro(&time_one,&time_two));
  2112.       }
  2113. #endif /* WANT_HISTOGRAM */      
  2114. #ifdef DIRTY
  2115.       access_buffer(recv_ring->buffer_ptr,
  2116.     recv_size,
  2117.     loc_dirty_count,
  2118.     loc_clean_count);
  2119. #endif /* DIRTY */
  2120. #ifdef WANT_DEMO
  2121.       DEMO_STREAM_INTERVAL(len);
  2122. #endif
  2123. #ifdef WANT_INTERVALS      
  2124.       INTERVALS_WAIT();
  2125. #endif /* WANT_INTERVALS */
  2126.       
  2127.       /* now we want to move our pointer to the next position in the */
  2128.       /* data buffer...we may also want to wrap back to the "beginning" */
  2129.       /* of the bufferspace, so we will mod the number of messages sent */
  2130.       /* by the recv width, and use that to calculate the offset to add */
  2131.       /* to the base pointer. */
  2132.       nummessages++;          
  2133.       recv_ring = recv_ring->next;
  2134.       if (bytes_remaining) {
  2135. bytes_remaining -= len;
  2136.       }
  2137.       local_bytes_recvd += len;
  2138. #ifdef WANT_HISTOGRAM
  2139.       if (verbosity > 1) {
  2140. /* make sure we timestamp just before we go into recv  */
  2141. /* raj 2004-06-15 */
  2142. HIST_timestamp(&time_one);
  2143.       }
  2144. #endif /* WANT_HISTOGRAM */
  2145.     
  2146.     }
  2147.     /* an EINTR is to be expected when this is a no_control test */
  2148.     if (((len < 0) || SOCKET_EINTR(len)) && (!no_control)) {
  2149.       perror("send_tcp_maerts: data recv error");
  2150.       printf("len was %dn",len);
  2151.       exit(1);
  2152.     }
  2153.     
  2154.     /* if we get here, it must mean we had a recv return of 0 before
  2155.        the watchdog timer expired, or the watchdog timer expired and
  2156.        this was a no_control test */
  2157.     /* The test is over. Flush the buffers to the remote end. We do a
  2158.        graceful release to tell the  remote we have all the data. */  
  2159.     /* but first, if the verbosity is greater than 1, find-out what */
  2160.     /* the TCP maximum segment_size was (if possible) */
  2161.     if (verbosity > 1) {
  2162.       tcp_mss = -1;
  2163.       get_tcp_info(recv_socket,&tcp_mss);
  2164.     }
  2165.     
  2166.     if (shutdown(recv_socket,SHUT_WR) == SOCKET_ERROR) {
  2167.       perror("netperf: cannot shutdown tcp maerts socket");
  2168.       exit(1);
  2169.     }
  2170.     stop_timer();
  2171.     
  2172.     /* this call will always give us the local elapsed time for the
  2173.        test, and will also store-away the necessaries for cpu
  2174.        utilization */ 
  2175.     
  2176.     cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
  2177. /* measured and how */
  2178. /* long did we really */
  2179. /* run? */
  2180.     
  2181.     /* we are finished with the socket, so close it to prevent hitting */
  2182.     /* the limit on maximum open files. */
  2183.     close(recv_socket);
  2184.     if (!no_control) {
  2185.       /* Get the statistics from the remote end. The remote will have
  2186.          calculated service demand and all those interesting
  2187.          things. If it wasn't supposed to care, it will return obvious
  2188.          values. */
  2189.     
  2190.       recv_response();
  2191.       if (!netperf_response.content.serv_errno) {
  2192. if (debug)
  2193.   fprintf(where,"remote results obtainedn");
  2194.       }
  2195.       else {
  2196. Set_errno(netperf_response.content.serv_errno);
  2197. fprintf(where,
  2198. "netperf: remote error %d",
  2199. netperf_response.content.serv_errno);
  2200. perror("");
  2201. fflush(where);
  2202. exit(1);
  2203.       }
  2204.       
  2205.       /* We now calculate what our thruput was for the test. In the
  2206.  future, we may want to include a calculation of the thruput
  2207.  measured by the remote, but it should be the case that for a
  2208.  TCP maerts test, that the two numbers should be *very*
  2209.  close... We calculate bytes_sent regardless of the way the
  2210.  test length was controlled.  If it was time, we needed to,
  2211.  and if it was by bytes, the user may have specified a number
  2212.  of bytes that wasn't a multiple of the recv_size, so we
  2213.  really didn't recv what he asked for ;-) */
  2214.     
  2215.       bytes_sent = ntohd(tcp_maerts_result->bytes_sent);
  2216.     }
  2217.     else {
  2218.       bytes_sent = (double)local_bytes_recvd;
  2219.     }
  2220.     thruput = calc_thruput(bytes_sent);
  2221.     if (local_cpu_usage || remote_cpu_usage) {
  2222.       /* We must now do a little math for service demand and cpu */
  2223.       /* utilization for the system(s) */
  2224.       /* Of course, some of the information might be bogus because */
  2225.       /* there was no idle counter in the kernel(s). We need to make */
  2226.       /* a note of this for the user's benefit...*/
  2227.       if (local_cpu_usage) {
  2228. local_cpu_utilization = calc_cpu_util(0.0);
  2229. local_service_demand = calc_service_demand(bytes_sent,
  2230.       0.0,
  2231.       0.0,
  2232.       0);
  2233.       }
  2234.       else {
  2235. local_cpu_utilization = (float) -1.0;
  2236. local_service_demand = (float) -1.0;
  2237.       }
  2238.       
  2239.       if (remote_cpu_usage) {
  2240. remote_cpu_utilization = tcp_maerts_result->cpu_util;
  2241. remote_service_demand = calc_service_demand(bytes_sent,
  2242.       0.0,
  2243.       remote_cpu_utilization,
  2244.       tcp_maerts_result->num_cpus);
  2245.       }
  2246.       else {
  2247. remote_cpu_utilization = (float) -1.0;
  2248. remote_service_demand  = (float) -1.0;
  2249.       }
  2250.     }    
  2251.     else {
  2252.       /* we were not measuring cpu, for the confidence stuff, we */
  2253.       /* should make it -1.0 */
  2254.       local_cpu_utilization = (float) -1.0;
  2255.       local_service_demand = (float) -1.0;
  2256.       remote_cpu_utilization = (float) -1.0;
  2257.       remote_service_demand  = (float) -1.0;
  2258.     }
  2259.     /* at this point, we want to calculate the confidence information. */
  2260.     /* if debugging is on, calculate_confidence will print-out the */
  2261.     /* parameters we pass it */
  2262.     calculate_confidence(confidence_iteration,
  2263.  elapsed_time,
  2264.  thruput,
  2265.  local_cpu_utilization,
  2266.  remote_cpu_utilization,
  2267.  local_service_demand,
  2268.  remote_service_demand);
  2269.     
  2270.     
  2271.     confidence_iteration++;
  2272.   }
  2273.   /* at this point, we have finished making all the runs that we */
  2274.   /* will be making. so, we should extract what the calcuated values */
  2275.   /* are for all the confidence stuff. we could make the values */
  2276.   /* global, but that seemed a little messy, and it did not seem worth */
  2277.   /* all the mucking with header files. so, we create a routine much */
  2278.   /* like calcualte_confidence, which just returns the mean values. */
  2279.   /* raj 11/94 */
  2280.   retrieve_confident_values(&elapsed_time,
  2281.     &thruput,
  2282.     &local_cpu_utilization,
  2283.     &remote_cpu_utilization,
  2284.     &local_service_demand,
  2285.     &remote_service_demand);
  2286.   /* We are now ready to print all the information. If the user */
  2287.   /* has specified zero-level verbosity, we will just print the */
  2288.   /* local service demand, or the remote service demand. If the */
  2289.   /* user has requested verbosity level 1, he will get the basic */
  2290.   /* "streamperf" numbers. If the user has specified a verbosity */
  2291.   /* of greater than 1, we will display a veritable plethora of */
  2292.   /* background information from outside of this block as it it */
  2293.   /* not cpu_measurement specific...  */
  2294.   if (confidence < 0) {
  2295.     /* we did not hit confidence, but were we asked to look for it? */
  2296.     if (iteration_max > 1) {
  2297.       display_confidence();
  2298.     }
  2299.   }
  2300.   if (local_cpu_usage || remote_cpu_usage) {
  2301.     local_cpu_method = format_cpu_method(cpu_method);
  2302.     remote_cpu_method = format_cpu_method(tcp_maerts_result->cpu_method);
  2303.     
  2304.     switch (verbosity) {
  2305.     case 0:
  2306.       if (local_cpu_usage) {
  2307. fprintf(where,
  2308. cpu_fmt_0,
  2309. local_service_demand,
  2310. local_cpu_method,
  2311. ((print_headers) || 
  2312.  (result_brand == NULL)) ? "" : result_brand);
  2313.       }
  2314.       else {
  2315. fprintf(where,
  2316. cpu_fmt_0,
  2317. remote_service_demand,
  2318. remote_cpu_method,
  2319. ((print_headers) || 
  2320.  (result_brand == NULL)) ? "" : result_brand);
  2321.       }
  2322.       break;
  2323.     case 1:
  2324.     case 2:
  2325.       if (print_headers) {
  2326. fprintf(where,
  2327. cpu_title,
  2328. format_units(),
  2329. local_cpu_method,
  2330. remote_cpu_method);
  2331.       }
  2332.     
  2333.       fprintf(where,
  2334.       cpu_fmt_1, /* the format string */
  2335.       rsr_size,         /* remote recvbuf size */
  2336.       lss_size,         /* local sendbuf size */
  2337.       send_size, /* how large were the recvs */
  2338.       elapsed_time, /* how long was the test */
  2339.       thruput,          /* what was the xfer rate */
  2340.       local_cpu_utilization, /* local cpu */
  2341.       remote_cpu_utilization, /* remote cpu */
  2342.       local_service_demand, /* local service demand */
  2343.       remote_service_demand, /* remote service demand */
  2344.       ((print_headers) || 
  2345.        (result_brand == NULL)) ? "" : result_brand);
  2346.       break;
  2347.     }
  2348.   }
  2349.   else {
  2350.     /* The tester did not wish to measure service demand. */
  2351.     
  2352.     switch (verbosity) {
  2353.     case 0:
  2354.       fprintf(where,
  2355.       tput_fmt_0,
  2356.       thruput,
  2357.       ((print_headers) || 
  2358.        (result_brand == NULL)) ? "" : result_brand);
  2359.       break;
  2360.     case 1:
  2361.     case 2:
  2362.       if (print_headers) {
  2363. fprintf(where,tput_title,format_units());
  2364.       }
  2365.       fprintf(where,
  2366.       tput_fmt_1, /* the format string */
  2367.       lsr_size,  /* local recvbuf size */
  2368.       rss_size,  /* remot sendbuf size */
  2369.       send_size, /* how large were the recvs */
  2370.       elapsed_time,  /* how long did it take */
  2371.       thruput,                  /* how fast did it go */
  2372.       ((print_headers) || 
  2373.        (result_brand == NULL)) ? "" : result_brand);
  2374.       break;
  2375.     }
  2376.   }
  2377.   
  2378.   /* it would be a good thing to include information about some of the */
  2379.   /* other parameters that may have been set for this test, but at the */
  2380.   /* moment, I do not wish to figure-out all the  formatting, so I will */
  2381.   /* just put this comment here to help remind me that it is something */
  2382.   /* that should be done at a later time. */
  2383.   
  2384.   if (verbosity > 1) {
  2385.     /* The user wanted to know it all, so we will give it to him. */
  2386.     /* This information will include as much as we can find about */
  2387.     /* TCP statistics, the alignments of the sends and receives */
  2388.     /* and all that sort of rot... */
  2389.    
  2390.     /* this stuff needs to be worked-out in the presence of confidence */
  2391.     /* intervals and multiple iterations of the test... raj 11/94 */
  2392.  
  2393.     fprintf(where,
  2394.     ksink_fmt,
  2395.     "Bytes",
  2396.     "Bytes",
  2397.     "Bytes",
  2398.     local_recv_align,
  2399.     remote_recv_align,
  2400.     local_recv_offset,
  2401.     remote_recv_offset,
  2402.     bytes_sent,
  2403.     bytes_sent / (double)nummessages,
  2404.     nummessages,
  2405.     bytes_sent / (double)tcp_maerts_result->send_calls,
  2406.     tcp_maerts_result->send_calls);
  2407.     fprintf(where,
  2408.     ksink_fmt2,
  2409.     tcp_mss);
  2410.     fflush(where);
  2411. #ifdef WANT_HISTOGRAM
  2412.     fprintf(where,"nnHistogram of time spent in recv() call.n");
  2413.     fflush(where);
  2414.     HIST_report(time_hist);
  2415. #endif /* WANT_HISTOGRAM */
  2416.   }
  2417.   
  2418. }
  2419. #ifdef HAVE_ICSC_EXS
  2420. #include <sys/exs.h>
  2421. /* This routine implements the TCP unidirectional data transfer test */
  2422. /* (a.k.a. stream) for the sockets interface. It receives its */
  2423. /* parameters via global variables from the shell and writes its */
  2424. /* output to the standard output. */
  2425. void
  2426. send_exs_tcp_stream(char remote_host[])
  2427. {
  2428.     char *tput_title = "
  2429. Recv   Send    Send                          n
  2430. Socket Socket  Message  Elapsed              n
  2431. Size   Size    Size     Time     Throughput  n
  2432. bytes  bytes   bytes    secs.    %s/sec  nn";
  2433.     char *tput_fmt_0 =
  2434.         "%7.2fn";
  2435.     char *tput_fmt_1 =
  2436.         "%6d %6d %6d    %-6.2f   %7.2f   n";
  2437.     char *cpu_title = "
  2438. Recv   Send    Send                          Utilization       Service Demandn
  2439. Socket Socket  Message  Elapsed              Send     Recv     Send    Recvn
  2440. Size   Size    Size     Time     Throughput  local    remote   local   remoten
  2441. bytes  bytes   bytes    secs.    %-8.8s/s  %% %c      %% %c      us/KB   us/KBnn";
  2442.     char *cpu_fmt_0 =
  2443.         "%6.3f %cn";
  2444.     char *cpu_fmt_1 =
  2445.         "%6d %6d %6d    %-6.2f     %7.2f   %-6.2f   %-6.2f   %-6.3f  %-6.3fn";
  2446.     char *ksink_fmt = "n
  2447. Alignment      Offset         %-8.8s %-8.8s    Sends   %-8.8s Recvsn
  2448. Local  Remote  Local  Remote  Xfered   Per                 Pern
  2449. Send   Recv    Send   Recv             Send (avg)          Recv (avg)n
  2450. %5d   %5d  %5d   %5d %6.4g  %6.2f    %6d   %6.2f %6dn";
  2451.     char *ksink_fmt2 = "n
  2452. Maximumn
  2453. Segmentn
  2454. Size (bytes)n
  2455. %6dn";
  2456.     float         elapsed_time;
  2457.     /* what we want is to have a buffer space that is at least one */
  2458.     /* send-size greater than our send window. this will insure that we */
  2459.     /* are never trying to re-use a buffer that may still be in the hands */
  2460.     /* of the transport. This buffer will be malloc'd after we have found */
  2461.     /* the size of the local senc socket buffer. We will want to deal */
  2462.     /* with alignment and offset concerns as well. */
  2463.     struct ring_elt *send_ring;
  2464.     int len;
  2465.     unsigned int nummessages = 0;
  2466.     SOCKET send_socket;
  2467.     int bytes_remaining;
  2468.     int tcp_mss = -1;  /* possibly uninitialized on printf far below */
  2469.     exs_mhandle_t exs_mhandle;
  2470.     exs_qhandle_t exs_qhandle;
  2471. #define NETPERF_EXS_PENDING  16
  2472.     int exs_aio_pending;
  2473.     int exs_aio_eagain;
  2474.     int exs_aio_dequeued;
  2475.     int exs_aio_dequeuecnt;
  2476.     int exs_evtcnt;
  2477. #define NETPERF_EXS_QSIZE    128
  2478.     exs_event_t exs_evtvec[NETPERF_EXS_QSIZE];
  2479.     /* with links like fddi, one can send > 32 bits worth of bytes */
  2480.     /* during a test... ;-) at some point, this should probably become a */
  2481.     /* 64bit integral type, but those are not entirely common yet */
  2482.     double   bytes_sent = 0.0;
  2483.     float   local_cpu_utilization;
  2484.     float   local_service_demand;
  2485.     float   remote_cpu_utilization;
  2486.     float   remote_service_demand;
  2487.     double   thruput;
  2488.     struct addrinfo *remote_res;
  2489.     struct addrinfo *local_res;
  2490.     struct   tcp_stream_request_struct   *tcp_stream_request;
  2491.     struct   tcp_stream_response_struct   *tcp_stream_response;
  2492.     struct   tcp_stream_results_struct   *tcp_stream_result;
  2493.     tcp_stream_request  =
  2494.         (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
  2495.     tcp_stream_response =
  2496.         (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
  2497.     tcp_stream_result   =
  2498.         (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
  2499. #if 0 /* def WANT_HISTOGRAM */
  2500.     time_hist = HIST_new();
  2501. #endif /* WANT_HISTOGRAM */
  2502.     /* since we are now disconnected from the code that established the */
  2503.     /* control socket, and since we want to be able to use different */
  2504.     /* protocols and such, we are passed the name of the remote host and */
  2505.     /* must turn that into the test specific addressing information. */
  2506.     /* complete_addrinfos will either succede or exit the process */
  2507.     complete_addrinfos(&remote_res,
  2508.                        &local_res,
  2509.                        remote_host,
  2510.                        SOCK_STREAM,
  2511.                        IPPROTO_TCP,
  2512.                        0);
  2513.     if ( print_headers ) {
  2514.         print_top_test_header("EXS TCP STREAM TEST",local_res,remote_res);
  2515.     }
  2516.     send_ring = NULL;
  2517.     confidence_iteration = 1;
  2518.     init_stat();
  2519.     /* initialize EXS API and create event queue */
  2520.     if (exs_init (EXS_VERSION) == -1) {
  2521.         perror ("netperf: send_exs_tcp_stream: exs_init failed");
  2522.         exit (1);
  2523.     }
  2524.     if ((exs_qhandle = exs_qcreate (NETPERF_EXS_QSIZE)) == EXS_QHANDLE_INVALID) {
  2525.         perror ("netperf: send_exs_tcp_stream: exs_qcreate failed");
  2526.         exit (1);
  2527.     }
  2528.     if (debug) {
  2529.         fprintf (where, "send_exs_tcp_stream: qhandle=%dn", exs_qhandle);
  2530.     }
  2531.     /* we have a great-big while loop which controls the number of times */
  2532.     /* we run a particular test. this is for the calculation of a */
  2533.     /* confidence interval (I really should have stayed awake during */
  2534.     /* probstats :). If the user did not request confidence measurement */
  2535.     /* (no confidence is the default) then we will only go though the */
  2536.     /* loop once. the confidence stuff originates from the folks at IBM */
  2537.     while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
  2538.            (confidence_iteration <= iteration_min)) {
  2539.         /* initialize a few counters. we have to remember that we might be */
  2540.         /* going through the loop more than once. */
  2541.         nummessages    =   0;
  2542.         bytes_sent     =   0.0;
  2543.         times_up       =    0;
  2544.         /*set up the data socket                        */
  2545.         send_socket = create_data_socket(local_res);
  2546.         if (send_socket == INVALID_SOCKET){
  2547.             perror("netperf: send_tcp_stream: tcp stream data socket");
  2548.             exit(1);
  2549.         }
  2550.         if (debug) {
  2551.             fprintf(where,"send_tcp_stream: send_socket obtained...n");
  2552.         }
  2553.         /* at this point, we have either retrieved the socket buffer sizes, */
  2554.         /* or have tried to set them, so now, we may want to set the send */
  2555.         /* size based on that (because the user either did not use a -m */
  2556.         /* option, or used one with an argument of 0). If the socket buffer */
  2557.         /* size is not available, we will set the send size to 4KB - no */
  2558.         /* particular reason, just arbitrary... */
  2559.         if (send_size == 0) {
  2560.             if (lss_size > 0) {
  2561.                 send_size = lss_size;
  2562.             }
  2563.             else {
  2564.                 send_size = 4096;
  2565.             }
  2566.         }
  2567.         /* set-up the data buffer ring with the requested alignment and offset. */
  2568.         /* note also that we have allocated a quantity */
  2569.         /* of memory that is at least one send-size greater than our socket */
  2570.         /* buffer size. We want to be sure that there are at least two */
  2571.         /* buffers allocated - this can be a bit of a problem when the */
  2572.         /* send_size is bigger than the socket size, so we must check... the */
  2573.         /* user may have wanted to explicitly set the "width" of our send */
  2574.         /* buffers, we should respect that wish... */
  2575.         if (send_width == 0) {
  2576.             send_width = (lss_size/send_size) + 1;
  2577.             if (send_width == 1) send_width++;
  2578.         }
  2579.         if (send_ring == NULL) {
  2580.             /* only allocate the send ring once. this is a networking test, */
  2581.             /* not a memory allocation test. this way, we do not need a */
  2582.             /* deallocate_buffer_ring() routine, and I don't feel like */
  2583.             /* writing one anyway :) raj 11/94 */
  2584.             send_ring = allocate_exs_buffer_ring(send_width,
  2585.                                                  send_size,
  2586.                                                  local_send_align,
  2587.                                                  local_send_offset,
  2588.                                                  &exs_mhandle);
  2589.         }
  2590.         /* If the user has requested cpu utilization measurements, we must */
  2591.         /* calibrate the cpu(s). We will perform this task within the tests */
  2592.         /* themselves. If the user has specified the cpu rate, then */
  2593.         /* calibrate_local_cpu will return rather quickly as it will have */
  2594.         /* nothing to do. If local_cpu_rate is zero, then we will go through */
  2595.         /* all the "normal" calibration stuff and return the rate back. */
  2596.         if (local_cpu_usage) {
  2597.             local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
  2598.         }
  2599.         /* Tell the remote end to do a listen. The server alters the socket */
  2600.         /* paramters on the other side at this point, hence the reason for */
  2601.         /* all the values being passed in the setup message. If the user did */
  2602.         /* not specify any of the parameters, they will be passed as 0, which */
  2603.         /* will indicate to the remote that no changes beyond the system's */
  2604.         /* default should be used. Alignment is the exception, it will */
  2605.         /* default to 1, which will be no alignment alterations. */
  2606.         netperf_request.content.request_type =   DO_TCP_STREAM;
  2607.         tcp_stream_request->send_buf_size   =   rss_size_req;
  2608.         tcp_stream_request->recv_buf_size   =   rsr_size_req;
  2609.         tcp_stream_request->receive_size   =   recv_size;
  2610.         tcp_stream_request->no_delay   =   rem_nodelay;
  2611.         tcp_stream_request->recv_alignment   =   remote_recv_align;
  2612.         tcp_stream_request->recv_offset   =   remote_recv_offset;
  2613.         tcp_stream_request->measure_cpu   =   remote_cpu_usage;
  2614.         tcp_stream_request->cpu_rate   =   remote_cpu_rate;
  2615.         if (test_time) {
  2616.             tcp_stream_request->test_length   =   test_time;
  2617.         }
  2618.         else {
  2619.             tcp_stream_request->test_length   =   test_bytes;
  2620.         }
  2621.         tcp_stream_request->so_rcvavoid   =   rem_rcvavoid;
  2622.         tcp_stream_request->so_sndavoid   =   rem_sndavoid;
  2623. #ifdef DIRTY
  2624.         tcp_stream_request->dirty_count     =       rem_dirty_count;
  2625.         tcp_stream_request->clean_count     =       rem_clean_count;
  2626. #endif /* DIRTY */
  2627.         tcp_stream_request->port            =    atoi(remote_data_port);
  2628.         tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
  2629.         if (debug > 1) {
  2630.             fprintf(where,
  2631.                     "netperf: send_tcp_stream: requesting TCP stream testn");
  2632.         }
  2633.         send_request();
  2634.         /* The response from the remote will contain all of the relevant    */
  2635.         /* socket parameters for this test type. We will put them back into */
  2636.         /* the variables here so they can be displayed if desired.  The   */
  2637.         /* remote will have calibrated CPU if necessary, and will have done   */
  2638.         /* all the needed set-up we will have calibrated the cpu locally   */
  2639.         /* before sending the request, and will grab the counter value right*/
  2640.         /* after the connect returns. The remote will grab the counter right*/
  2641.         /* after the accept call. This saves the hassle of extra messages   */
  2642.         /* being sent for the TCP tests.               */
  2643.         recv_response();
  2644.         if (!netperf_response.content.serv_errno) {
  2645.             if (debug)
  2646.                 fprintf(where,"remote listen done.n");
  2647.             rsr_size         =   tcp_stream_response->recv_buf_size;
  2648.             rss_size         =   tcp_stream_response->send_buf_size;
  2649.             rem_nodelay     =   tcp_stream_response->no_delay;
  2650.             remote_cpu_usage=   tcp_stream_response->measure_cpu;
  2651.             remote_cpu_rate = tcp_stream_response->cpu_rate;
  2652.             /* we have to make sure that the server port number is in */
  2653.             /* network order */
  2654.             set_port_number(remote_res,(short)tcp_stream_response->data_port_number);
  2655.             rem_rcvavoid   = tcp_stream_response->so_rcvavoid;
  2656.             rem_sndavoid   = tcp_stream_response->so_sndavoid;
  2657.         }
  2658.         else {
  2659.             Set_errno(netperf_response.content.serv_errno);
  2660.             fprintf(where,
  2661.                     "netperf: remote error %d",
  2662.                     netperf_response.content.serv_errno);
  2663.             perror("");
  2664.             fflush(where);
  2665.             exit(1);
  2666.         }
  2667. #if 0 /* def WANT_DEMO */
  2668.         DEMO_STREAM_SETUP(lss_size,rsr_size)
  2669. #endif
  2670.             /*Connect up to the remote port on the data socket  */
  2671.             if (connect(send_socket,
  2672.                         remote_res->ai_addr,
  2673.                         remote_res->ai_addrlen) == INVALID_SOCKET){
  2674.                 perror("netperf: send_tcp_stream: data socket connect failed");
  2675.                 exit(1);
  2676.             }
  2677.         /* Data Socket set-up is finished. If there were problems, either */
  2678.         /* the connect would have failed, or the previous response would */
  2679.         /* have indicated a problem. I failed to see the value of the */
  2680.         /* extra  message after the accept on the remote. If it failed, */
  2681.         /* we'll see it here. If it didn't, we might as well start pumping */
  2682.         /* data. */
  2683.         /* Set-up the test end conditions. For a stream test, they can be */
  2684.         /* either time or byte-count based. */
  2685.         if (test_time) {
  2686.             /* The user wanted to end the test after a period of time. */
  2687.             times_up = 0;
  2688.             bytes_remaining = 0;
  2689.             /* in previous revisions, we had the same code repeated throught */
  2690.             /* all the test suites. this was unnecessary, and meant more */
  2691.             /* work for me when I wanted to switch to POSIX signals, so I */
  2692.             /* have abstracted this out into a routine in netlib.c. if you */
  2693.             /* are experiencing signal problems, you might want to look */
  2694.             /* there. raj 11/94 */
  2695.             start_timer(test_time);
  2696.         }
  2697.         else {
  2698.             /* The tester wanted to send a number of bytes. */
  2699.             bytes_remaining = test_bytes;
  2700.             times_up = 1;
  2701.         }
  2702.         /* The cpu_start routine will grab the current time and possibly */
  2703.         /* value of the idle counter for later use in measuring cpu */
  2704.         /* utilization and/or service demand and thruput. */
  2705.         cpu_start(local_cpu_usage);
  2706. #if 0 /* def WANT_INTERVALS */
  2707. INTERVALS_INIT();
  2708. #endif /* WANT_INTERVALS */
  2709.         /* before we start, initialize a few variables */
  2710. #if 0 /* def WANT_DEMO */
  2711.         if (demo_mode) {
  2712.             HIST_timestamp(demo_one_ptr);
  2713.         }
  2714. #endif
  2715.         /* We use an "OR" to control test execution. When the test is */
  2716.         /* controlled by time, the byte count check will always return false. */
  2717.         /* When the test is controlled by byte count, the time test will */
  2718.         /* always return false. When the test is finished, the whole */
  2719.         /* expression will go false and we will stop sending data. */
  2720.         exs_aio_pending = 0;
  2721.         exs_aio_eagain = 0;
  2722.         exs_aio_dequeuecnt = 0;
  2723.         while ((!times_up) || (bytes_remaining > 0)) {
  2724. #ifdef DIRTY
  2725.   access_buffer(send_ring->buffer_ptr,
  2726. send_size,
  2727. loc_dirty_count,
  2728. loc_clean_count);
  2729. #endif /* DIRTY */
  2730. #if 0 /* def WANT_HISTOGRAM */
  2731.             /* timestamp just before we go into send and then again just after */
  2732.             /* we come out raj 8/94 */
  2733.             HIST_timestamp(&time_one);
  2734. #endif /* WANT_HISTOGRAM */
  2735.             /* post up to NETPERF_EXS_PENDING I/Os  */
  2736.             while ((exs_aio_pending < NETPERF_EXS_PENDING) &&
  2737.                    (exs_send (send_socket, send_ring->buffer_ptr, send_size,
  2738.                               0, exs_qhandle, (exs_ahandle_t)-1, exs_mhandle) == 0)) {
  2739.                 exs_aio_pending++;
  2740.                 /* now we want to move our pointer to the next
  2741.    position in the data buffer...we may also want to
  2742.    wrap back to the "beginning" of the bufferspace, so
  2743.    we will mod the number of messages sent by the send
  2744.    width, and use that to calculate the offset to add
  2745.    to the base pointer. */
  2746.                 nummessages++;
  2747.                 send_ring = send_ring->next;
  2748.                 if (bytes_remaining) {
  2749.                     bytes_remaining -= send_size;
  2750.                 }
  2751.             }
  2752.             /* check exs_send result */
  2753.             if (exs_aio_pending < NETPERF_EXS_PENDING) {
  2754.                /* standard flow control case */
  2755.                 if (errno == EAGAIN)
  2756.                     exs_aio_eagain++;
  2757.                 /* case of times_up */
  2758.                 else if (errno == EINTR)
  2759.                     break;
  2760.                 /* strange, let's stop */
  2761.                 else {
  2762.                     perror ("netperf: exs_send error");
  2763.                     exit (1);
  2764.                 }
  2765.             }
  2766.             /* dequeue events with "threshold" on 1/2 posted */
  2767.             exs_aio_dequeued =
  2768.                 exs_qdequeue (exs_qhandle, exs_evtvec,
  2769.                               -(exs_aio_pending>>1), NULL);
  2770.             exs_aio_dequeuecnt++;
  2771.             /* check exs_dequeue result */
  2772.             if (exs_aio_dequeued < 0) {
  2773.                 /* case of times_up */
  2774.                 if (errno == EINTR)
  2775.                     break;
  2776.                 /* strange, let's stop */
  2777.                 else {
  2778.                     perror ("netperf: exs_send error");
  2779.                     exit (1);
  2780.                 }
  2781.             }
  2782.             /* update number of pending I/Os */
  2783.             else {
  2784.                 exs_aio_pending -= exs_aio_dequeued;
  2785.             }
  2786. #if 0 /* def WANT_HISTOGRAM */