/* * routines related to collection TCP_INFO using getsockopt() * * Brian Tierney, ESnet (bltierney@es.net) * * Note that this is only really useful on Linux. # * FreeBSD has a limitted implementation that only includes the following: * 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 * fixed before v8.1 at the earliest. * * OSX has no support. * * I think MS Windows does support TCP_INFO, but iperf3 does not currently support Windows. */ #include #include #include #include #include #include #include #include #include "stdint.h" #include "iperf_api.h" #include "locale.h" /*************************************************************/ void get_tcpinfo(struct iperf_test *test, struct iperf_interval_results *rp) { #if defined(linux) || defined(__FreeBSD__) socklen_t tcp_info_length; struct iperf_stream *sp = test->streams; tcp_info_length = sizeof(struct tcp_info); //printf("getting TCP_INFO for socket %d \n", sp->socket); if (getsockopt(sp->socket, IPPROTO_TCP, TCP_INFO, (void *)&rp->tcpInfo, &tcp_info_length) < 0) { perror("getsockopt"); } /* for debugging */ //printf(" got TCP_INFO: %d, %d, %d, %d\n", rp->tcpInfo.tcpi_snd_cwnd, // rp->tcpInfo.tcpi_snd_ssthresh, rp->tcpInfo.tcpi_rcv_space, rp->tcpInfo.tcpi_rtt); return; #else return; #endif } /*************************************************************/ void print_tcpinfo(struct iperf_interval_results *r) { #if defined(linux) printf(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_lost, r->tcpInfo.tcpi_retrans, r->tcpInfo.tcpi_fackets, r->tcpInfo.tcpi_rtt, r->tcpInfo.tcpi_reordering); #endif #if defined(__FreeBSD__) printf(report_tcpInfo, r->tcpInfo.tcpi_snd_cwnd, r->tcpInfo.tcpi_rcv_space, r->tcpInfo.tcpi_snd_ssthresh, r->tcpInfo.tcpi_rtt); #endif } /*************************************************************/ void build_tcpinfo_message(struct iperf_interval_results *r, char *message) { #if defined(linux) 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_lost, r->tcpInfo.tcpi_retrans, r->tcpInfo.tcpi_fackets, r->tcpInfo.tcpi_rtt, r->tcpInfo.tcpi_reordering); #endif #if defined(__FreeBSD__) sprintf(message, report_tcpInfo, r->tcpInfo.tcpi_snd_cwnd, r->tcpInfo.tcpi_rcv_space, r->tcpInfo.tcpi_snd_ssthresh, r->tcpInfo.tcpi_rtt); #endif }