| 
version 1.1, 2016/10/18 13:28:18
 | 
version 1.1.1.3, 2023/09/27 11:14:54
 | 
| 
 Line 1
 | 
 Line 1
 | 
 |  /* | 
  /* | 
|  * iperf, Copyright (c) 2014, The Regents of the University of |  * iperf, Copyright (c) 2014, 2017, The Regents of the University of | 
 |   * California, through Lawrence Berkeley National Laboratory (subject | 
   * California, through Lawrence Berkeley National Laboratory (subject | 
 |   * to receipt of any required approvals from the U.S. Dept. of | 
   * to receipt of any required approvals from the U.S. Dept. of | 
 |   * Energy).  All rights reserved. | 
   * Energy).  All rights reserved. | 
| 
 Line 27
 | 
 Line 27
 | 
 |   | 
   | 
 |  /* | 
  /* | 
 |   * routines related to collection TCP_INFO using getsockopt() | 
   * routines related to collection TCP_INFO using getsockopt() | 
|  *  |  * | 
 |   * Brian Tierney, ESnet  (bltierney@es.net) | 
   * Brian Tierney, ESnet  (bltierney@es.net) | 
|  *  |  * | 
 |   * Note that this is only really useful on Linux. | 
   * Note that this is only really useful on Linux. | 
 |   * XXX: only standard on linux versions 2.4 and later | 
   * XXX: only standard on linux versions 2.4 and later | 
 |   # | 
   # | 
|  * FreeBSD has a limitted implementation that only includes the following: |  * FreeBSD has a limited implementation that only includes the following: | 
 |   *   tcpi_snd_ssthresh, tcpi_snd_cwnd, tcpi_rcv_space, tcpi_rtt | 
   *   tcpi_snd_ssthresh, tcpi_snd_cwnd, tcpi_rcv_space, tcpi_rtt | 
 |   * Based on information on http://wiki.freebsd.org/8.0TODO, I dont think this will be | 
   * Based on information on http://wiki.freebsd.org/8.0TODO, I dont think this will be | 
 |   * fixed before v8.1 at the earliest. | 
   * fixed before v8.1 at the earliest. | 
| 
 Line 48
 | 
 Line 48
 | 
 |  #include <sys/param.h> | 
  #include <sys/param.h> | 
 |  #include <sys/types.h> | 
  #include <sys/types.h> | 
 |  #include <sys/socket.h> | 
  #include <sys/socket.h> | 
 |  #include <netinet/tcp.h> | 
   | 
 |  #include <string.h> | 
  #include <string.h> | 
 |  #include <netinet/in.h> | 
  #include <netinet/in.h> | 
 |  #include <errno.h> | 
  #include <errno.h> | 
| 
 Line 61
 | 
 Line 60
 | 
 |  int | 
  int | 
 |  has_tcpinfo(void) | 
  has_tcpinfo(void) | 
 |  { | 
  { | 
| #if (defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)) \ | #if (defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)) \ | 
 |          && defined(TCP_INFO) | 
          && defined(TCP_INFO) | 
 |      return 1; | 
      return 1; | 
 |  #else | 
  #else | 
| 
 Line 76  has_tcpinfo_retransmits(void)
 | 
 Line 75  has_tcpinfo_retransmits(void)
 | 
 |  #if defined(linux) && defined(TCP_MD5SIG) | 
  #if defined(linux) && defined(TCP_MD5SIG) | 
 |      /* TCP_MD5SIG doesn't actually have anything to do with TCP | 
      /* TCP_MD5SIG doesn't actually have anything to do with TCP | 
 |      ** retransmits, it just showed up in the same rev of the header | 
      ** retransmits, it just showed up in the same rev of the header | 
|     ** file.  If it's present then struct tcp_info has the  |     ** file.  If it's present then struct tcp_info has the | 
 |      ** tcpi_total_retrans field that we need; if not, not. | 
      ** tcpi_total_retrans field that we need; if not, not. | 
 |      */ | 
      */ | 
 |      return 1; | 
      return 1; | 
 |  #else | 
  #else | 
 |  #if defined(__FreeBSD__) && __FreeBSD_version >= 600000 | 
  #if defined(__FreeBSD__) && __FreeBSD_version >= 600000 | 
 |      return 1; /* Should work now */ | 
      return 1; /* Should work now */ | 
| #elif defined(__NetBSD__) && defined(TCP_INFO) | #elif (defined(__NetBSD__) || defined(__OpenBSD__)) && defined(TCP_INFO) | 
 |      return 1; | 
      return 1; | 
 |  #else | 
  #else | 
 |      return 0; | 
      return 0; | 
| 
 Line 95  has_tcpinfo_retransmits(void)
 | 
 Line 94  has_tcpinfo_retransmits(void)
 | 
 |  void | 
  void | 
 |  save_tcpinfo(struct iperf_stream *sp, struct iperf_interval_results *irp) | 
  save_tcpinfo(struct iperf_stream *sp, struct iperf_interval_results *irp) | 
 |  { | 
  { | 
| #if (defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)) && \ | #if (defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)) && \ | 
 |          defined(TCP_INFO) | 
          defined(TCP_INFO) | 
 |      socklen_t tcp_info_length = sizeof(struct tcp_info); | 
      socklen_t tcp_info_length = sizeof(struct tcp_info); | 
 |   | 
   | 
| 
 Line 119  get_total_retransmits(struct iperf_interval_results *i
 | 
 Line 118  get_total_retransmits(struct iperf_interval_results *i
 | 
 |      return irp->tcpInfo.tcpi_total_retrans; | 
      return irp->tcpInfo.tcpi_total_retrans; | 
 |  #elif defined(__FreeBSD__) && __FreeBSD_version >= 600000 | 
  #elif defined(__FreeBSD__) && __FreeBSD_version >= 600000 | 
 |      return irp->tcpInfo.tcpi_snd_rexmitpack; | 
      return irp->tcpInfo.tcpi_snd_rexmitpack; | 
| #elif defined(__NetBSD__) && defined(TCP_INFO) | #elif (defined(__NetBSD__) || defined(__OpenBSD__)) && defined(TCP_INFO) | 
 |      return irp->tcpInfo.tcpi_snd_rexmitpack; | 
      return irp->tcpInfo.tcpi_snd_rexmitpack; | 
 |  #else | 
  #else | 
 |      return -1; | 
      return -1; | 
| 
 Line 134  long
 | 
 Line 133  long
 | 
 |  get_snd_cwnd(struct iperf_interval_results *irp) | 
  get_snd_cwnd(struct iperf_interval_results *irp) | 
 |  { | 
  { | 
 |  #if defined(linux) && defined(TCP_MD5SIG) | 
  #if defined(linux) && defined(TCP_MD5SIG) | 
|     return irp->tcpInfo.tcpi_snd_cwnd * irp->tcpInfo.tcpi_snd_mss; |     return (long)irp->tcpInfo.tcpi_snd_cwnd * irp->tcpInfo.tcpi_snd_mss; | 
 |  #elif defined(__FreeBSD__) && __FreeBSD_version >= 600000 | 
  #elif defined(__FreeBSD__) && __FreeBSD_version >= 600000 | 
|     return irp->tcpInfo.tcpi_snd_cwnd * irp->tcpInfo.tcpi_snd_mss; |     return irp->tcpInfo.tcpi_snd_cwnd; | 
 |  #elif defined(__NetBSD__) && defined(TCP_INFO) | 
  #elif defined(__NetBSD__) && defined(TCP_INFO) | 
|     return irp->tcpInfo.tcpi_snd_cwnd * irp->tcpInfo.tcpi_snd_mss; |     return (long)irp->tcpInfo.tcpi_snd_cwnd * irp->tcpInfo.tcpi_snd_mss; | 
|   | #elif defined(__OpenBSD__) && defined(TCP_INFO) | 
|   |     return irp->tcpInfo.tcpi_snd_cwnd; | 
 |  #else | 
  #else | 
 |      return -1; | 
      return -1; | 
 |  #endif | 
  #endif | 
| 
 Line 146  get_snd_cwnd(struct iperf_interval_results *irp)
 | 
 Line 147  get_snd_cwnd(struct iperf_interval_results *irp)
 | 
 |   | 
   | 
 |  /*************************************************************/ | 
  /*************************************************************/ | 
 |  /* | 
  /* | 
 |   | 
   * Return snd_wnd in octets. | 
 |   | 
   */ | 
 |   | 
  long | 
 |   | 
  get_snd_wnd(struct iperf_interval_results *irp) | 
 |   | 
  { | 
 |   | 
  #if !defined(HAVE_TCP_INFO_SND_WND) | 
 |   | 
      return -1; | 
 |   | 
  #elif defined(linux) && defined(TCP_MD5SIG) | 
 |   | 
      return irp->tcpInfo.tcpi_snd_wnd; | 
 |   | 
  #elif defined(__FreeBSD__) && __FreeBSD_version >= 600000 | 
 |   | 
      return irp->tcpInfo.tcpi_snd_wnd; | 
 |   | 
  #elif defined(__NetBSD__) && defined(TCP_INFO) | 
 |   | 
      return (long)irp->tcpInfo.tcpi_snd_wnd * irp->tcpInfo.tcpi_snd_mss; | 
 |   | 
  #elif defined(__OpenBSD__) && defined(TCP_INFO) | 
 |   | 
      return irp->tcpInfo.tcpi_snd_wnd; | 
 |   | 
  #else | 
 |   | 
      return -1; | 
 |   | 
  #endif | 
 |   | 
  } | 
 |   | 
   | 
 |   | 
  /*************************************************************/ | 
 |   | 
  /* | 
 |   * Return rtt in usec. | 
   * Return rtt in usec. | 
 |   */ | 
   */ | 
 |  long | 
  long | 
| 
 Line 155  get_rtt(struct iperf_interval_results *irp)
 | 
 Line 178  get_rtt(struct iperf_interval_results *irp)
 | 
 |      return irp->tcpInfo.tcpi_rtt; | 
      return irp->tcpInfo.tcpi_rtt; | 
 |  #elif defined(__FreeBSD__) && __FreeBSD_version >= 600000 | 
  #elif defined(__FreeBSD__) && __FreeBSD_version >= 600000 | 
 |      return irp->tcpInfo.tcpi_rtt; | 
      return irp->tcpInfo.tcpi_rtt; | 
| #elif defined(__NetBSD__) && defined(TCP_INFO) | #elif (defined(__NetBSD__) || defined(__OpenBSD__)) && defined(TCP_INFO) | 
 |      return irp->tcpInfo.tcpi_rtt; | 
      return irp->tcpInfo.tcpi_rtt; | 
 |  #else | 
  #else | 
 |      return -1; | 
      return -1; | 
| 
 Line 163  get_rtt(struct iperf_interval_results *irp)
 | 
 Line 186  get_rtt(struct iperf_interval_results *irp)
 | 
 |  } | 
  } | 
 |   | 
   | 
 |  /*************************************************************/ | 
  /*************************************************************/ | 
 |   | 
  /* | 
 |   | 
   * Return rttvar in usec. | 
 |   | 
   */ | 
 |   | 
  long | 
 |   | 
  get_rttvar(struct iperf_interval_results *irp) | 
 |   | 
  { | 
 |   | 
  #if defined(linux) && defined(TCP_MD5SIG) | 
 |   | 
      return irp->tcpInfo.tcpi_rttvar; | 
 |   | 
  #elif defined(__FreeBSD__) && __FreeBSD_version >= 600000 | 
 |   | 
      return irp->tcpInfo.tcpi_rttvar; | 
 |   | 
  #elif (defined(__NetBSD__) || defined(__OpenBSD__)) && defined(TCP_INFO) | 
 |   | 
      return irp->tcpInfo.tcpi_rttvar; | 
 |   | 
  #else | 
 |   | 
      return -1; | 
 |   | 
  #endif | 
 |   | 
  } | 
 |   | 
   | 
 |   | 
  /*************************************************************/ | 
 |   | 
  /* | 
 |   | 
   * Return PMTU in bytes. | 
 |   | 
   */ | 
 |   | 
  long | 
 |   | 
  get_pmtu(struct iperf_interval_results *irp) | 
 |   | 
  { | 
 |   | 
  #if defined(linux) && defined(TCP_MD5SIG) | 
 |   | 
      return irp->tcpInfo.tcpi_pmtu; | 
 |   | 
  #else | 
 |   | 
      return -1; | 
 |   | 
  #endif | 
 |   | 
  } | 
 |   | 
   | 
 |   | 
  /*************************************************************/ | 
 |  void | 
  void | 
 |  build_tcpinfo_message(struct iperf_interval_results *r, char *message) | 
  build_tcpinfo_message(struct iperf_interval_results *r, char *message) | 
 |  { | 
  { | 
| #if defined(linux) | #if defined(linux) && defined(TCP_INFO) | 
 |      sprintf(message, report_tcpInfo, r->tcpInfo.tcpi_snd_cwnd, r->tcpInfo.tcpi_snd_ssthresh, | 
      sprintf(message, report_tcpInfo, r->tcpInfo.tcpi_snd_cwnd, r->tcpInfo.tcpi_snd_ssthresh, | 
 |              r->tcpInfo.tcpi_rcv_ssthresh, r->tcpInfo.tcpi_unacked, r->tcpInfo.tcpi_sacked, | 
              r->tcpInfo.tcpi_rcv_ssthresh, r->tcpInfo.tcpi_unacked, r->tcpInfo.tcpi_sacked, | 
|             r->tcpInfo.tcpi_lost, r->tcpInfo.tcpi_retrans, r->tcpInfo.tcpi_fackets,  |             r->tcpInfo.tcpi_lost, r->tcpInfo.tcpi_retrans, r->tcpInfo.tcpi_fackets, | 
 |              r->tcpInfo.tcpi_rtt, r->tcpInfo.tcpi_reordering); | 
              r->tcpInfo.tcpi_rtt, r->tcpInfo.tcpi_reordering); | 
 |  #endif | 
  #endif | 
| #if defined(__FreeBSD__) | #if (defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)) && defined(TCP_INFO) | 
|     sprintf(message, report_tcpInfo, r->tcpInfo.tcpi_snd_cwnd, |   | 
|             r->tcpInfo.tcpi_rcv_space, r->tcpInfo.tcpi_snd_ssthresh, r->tcpInfo.tcpi_rtt); |   | 
| #endif |   | 
| #if defined(__NetBSD__) && defined(TCP_INFO) |   | 
 |      sprintf(message, report_tcpInfo, r->tcpInfo.tcpi_snd_cwnd, | 
      sprintf(message, report_tcpInfo, r->tcpInfo.tcpi_snd_cwnd, | 
 |              r->tcpInfo.tcpi_rcv_space, r->tcpInfo.tcpi_snd_ssthresh, r->tcpInfo.tcpi_rtt); | 
              r->tcpInfo.tcpi_rcv_space, r->tcpInfo.tcpi_snd_ssthresh, r->tcpInfo.tcpi_rtt); | 
 |  #endif | 
  #endif |