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 |