#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <errno.h>
#include "iperf.h"
#include "iperf_api.h"
#include "iperf_locale.h"
int
has_tcpinfo(void)
{
#if (defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)) \
&& defined(TCP_INFO)
return 1;
#elif (defined(__APPLE__) && defined(__MACH__)) && defined(TCP_CONNECTION_INFO)
return 1;
#else
return 0;
#endif
}
int
has_tcpinfo_retransmits(void)
{
#if defined(linux) && defined(TCP_MD5SIG)
return 1;
#else
#if defined(__FreeBSD__) && __FreeBSD_version >= 600000
return 1;
#elif (defined(__NetBSD__) || defined(__OpenBSD__)) && defined(TCP_INFO)
return 1;
#elif (defined(__APPLE__) && defined(__MACH__)) && defined(TCP_CONNECTION_INFO)
return 1;
#else
return 0;
#endif
#endif
}
void
save_tcpinfo(struct iperf_stream *sp, struct iperf_interval_results *irp)
{
#if (defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)) && \
defined(TCP_INFO)
socklen_t tcp_info_length = sizeof(struct tcp_info);
if (getsockopt(sp->socket, IPPROTO_TCP, TCP_INFO, (void *)&irp->tcpInfo, &tcp_info_length) < 0)
iperf_err(sp->test, "getsockopt - %s", strerror(errno));
if (sp->test->debug) {
printf("tcpi_snd_cwnd %u tcpi_snd_mss %u tcpi_rtt %u\n",
irp->tcpInfo.tcpi_snd_cwnd, irp->tcpInfo.tcpi_snd_mss,
irp->tcpInfo.tcpi_rtt);
}
#elif (defined(__APPLE__) && defined(__MACH__)) && defined(TCP_CONNECTION_INFO)
struct tcp_connection_info conn_info;
socklen_t tcp_info_length = sizeof(conn_info );
if (getsockopt(sp->socket, IPPROTO_TCP, TCP_CONNECTION_INFO, (void *)&irp->tcpConnInfo, &tcp_info_length) < 0)
iperf_err(sp->test, "getsockopt - %s", strerror(errno));
if (sp->test->debug) {
printf("tcpi_snd_cwnd %u tcpi_snd_cwnd %u tcpi_srtt %u\n",
irp->tcpConnInfo.tcpi_snd_cwnd, irp->tcpConnInfo.tcpi_snd_cwnd,
irp->tcpConnInfo.tcpi_srtt);
}
#endif
}
long
get_total_retransmits(struct iperf_interval_results *irp)
{
#if defined(linux) && defined(TCP_MD5SIG)
return irp->tcpInfo.tcpi_total_retrans;
#elif defined(__FreeBSD__) && __FreeBSD_version >= 600000
return irp->tcpInfo.tcpi_snd_rexmitpack;
#elif (defined(__NetBSD__) || defined(__OpenBSD__)) && defined(TCP_INFO)
return irp->tcpInfo.tcpi_snd_rexmitpack;
#elif (defined(__APPLE__) && defined(__MACH__)) && defined(TCP_CONNECTION_INFO)
return irp->tcpConnInfo.tcpi_txretransmitpackets;
#else
return -1;
#endif
}
long
get_snd_cwnd(struct iperf_interval_results *irp)
{
#if defined(linux) && defined(TCP_MD5SIG)
return (long)irp->tcpInfo.tcpi_snd_cwnd * irp->tcpInfo.tcpi_snd_mss;
#elif defined(__FreeBSD__) && __FreeBSD_version >= 600000
return irp->tcpInfo.tcpi_snd_cwnd;
#elif defined(__NetBSD__) && defined(TCP_INFO)
return (long)irp->tcpInfo.tcpi_snd_cwnd * irp->tcpInfo.tcpi_snd_mss;
#elif defined(__OpenBSD__) && defined(TCP_INFO)
return irp->tcpInfo.tcpi_snd_cwnd;
#elif (defined(__APPLE__) && defined(__MACH__)) && defined(TCP_CONNECTION_INFO)
return irp->tcpConnInfo.tcpi_snd_cwnd;
#else
return -1;
#endif
}
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;
#elif (defined(__APPLE__) && defined(__MACH__)) && defined(TCP_CONNECTION_INFO)
return irp->tcpConnInfo.tcpi_snd_wnd;
#else
return -1;
#endif
}
long
get_rtt(struct iperf_interval_results *irp)
{
#if defined(linux) && defined(TCP_MD5SIG)
return irp->tcpInfo.tcpi_rtt;
#elif defined(__FreeBSD__) && __FreeBSD_version >= 600000
return irp->tcpInfo.tcpi_rtt;
#elif (defined(__NetBSD__) || defined(__OpenBSD__)) && defined(TCP_INFO)
return irp->tcpInfo.tcpi_rtt;
#elif (defined(__APPLE__) && defined(__MACH__)) && defined(TCP_CONNECTION_INFO)
return irp->tcpConnInfo.tcpi_srtt;
#else
return -1;
#endif
}
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;
#elif (defined(__APPLE__) && defined(__MACH__)) && defined(TCP_CONNECTION_INFO)
return irp->tcpConnInfo.tcpi_rttvar;
#else
return -1;
#endif
}
long
get_pmtu(struct iperf_interval_results *irp)
{
#if defined(linux) && defined(TCP_MD5SIG)
return irp->tcpInfo.tcpi_pmtu;
#else
return -1;
#endif
}
long
get_reorder(struct iperf_interval_results *irp)
{
#if defined(linux) && defined(TCP_REPAIR_ON)
return irp->tcpInfo.tcpi_reord_seen;
#else
return -1;
#endif
}