Add tcp_info.snd_wnd to JSON output.
tcp_info.snd_wnd is available on FreeBSD and NetBSD since TCP_INFO was added. It was added to Linux 5.4 in late 2019 and becomes available in Ubuntu 20.04 and Debian 11. Tested on: * Debian 11 running on x86-64 with this field. * Debian 10 armv7 running on Raspberry Pi 2 without this field. * NetBSD 9.2 armv7 running on Raspberry Pi 3 with this field. * FreeBSD 13 aarch64 running on Raspberry Pi 4 with this field.
Этот коммит содержится в:
родитель
2ec43d1261
Коммит
47985d7fc4
90
configure
поставляемый
90
configure
поставляемый
@ -1881,6 +1881,63 @@ fi
|
||||
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||
|
||||
} # ac_fn_c_check_header_mongrel
|
||||
|
||||
# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
|
||||
# ----------------------------------------------------
|
||||
# Tries to find if the field MEMBER exists in type AGGR, after including
|
||||
# INCLUDES, setting cache variable VAR accordingly.
|
||||
ac_fn_c_check_member ()
|
||||
{
|
||||
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
|
||||
$as_echo_n "checking for $2.$3... " >&6; }
|
||||
if eval \${$4+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$5
|
||||
int
|
||||
main ()
|
||||
{
|
||||
static $2 ac_aggr;
|
||||
if (ac_aggr.$3)
|
||||
return 0;
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
eval "$4=yes"
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$5
|
||||
int
|
||||
main ()
|
||||
{
|
||||
static $2 ac_aggr;
|
||||
if (sizeof ac_aggr.$3)
|
||||
return 0;
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
eval "$4=yes"
|
||||
else
|
||||
eval "$4=no"
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
eval ac_res=\$$4
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
||||
$as_echo "$ac_res" >&6; }
|
||||
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||
|
||||
} # ac_fn_c_check_member
|
||||
cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
@ -13383,6 +13440,19 @@ else
|
||||
fi
|
||||
|
||||
|
||||
for ac_header in linux/tcp.h
|
||||
do :
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "linux/tcp.h" "ac_cv_header_linux_tcp_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_linux_tcp_h" = xyes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_LINUX_TCP_H 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
|
||||
# Check for SCTP support
|
||||
if $try_sctp; then
|
||||
for ac_header in sys/socket.h
|
||||
@ -14020,6 +14090,26 @@ $as_echo "#define HAVE_DONT_FRAGMENT 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
ac_fn_c_check_member "$LINENO" "struct tcp_info" "tcpi_snd_wnd" "ac_cv_member_struct_tcp_info_tcpi_snd_wnd" "#ifdef HAVE_LINUX_TCP_H
|
||||
#include <linux/tcp.h>
|
||||
#else
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
|
||||
"
|
||||
if test "x$ac_cv_member_struct_tcp_info_tcpi_snd_wnd" = xyes; then :
|
||||
iperf3_cv_header_tcp_info_snd_wnd=yes
|
||||
else
|
||||
iperf3_cv_header_tcp_info_snd_wnd=no
|
||||
fi
|
||||
|
||||
|
||||
if test "x$iperf3_cv_header_tcp_info_snd_wnd" = "xyes"; then
|
||||
|
||||
$as_echo "#define HAVE_TCP_INFO_SND_WND 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
# Check if we need -lrt for clock_gettime
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5
|
||||
$as_echo_n "checking for library containing clock_gettime... " >&6; }
|
||||
|
15
configure.ac
15
configure.ac
@ -113,6 +113,8 @@ AC_ARG_WITH([sctp],
|
||||
]
|
||||
)
|
||||
|
||||
AC_CHECK_HEADERS([linux/tcp.h])
|
||||
|
||||
# Check for SCTP support
|
||||
if $try_sctp; then
|
||||
AC_CHECK_HEADERS([sys/socket.h])
|
||||
@ -258,6 +260,19 @@ if test "x$iperf3_cv_header_dontfragment" = "xyes"; then
|
||||
AC_DEFINE([HAVE_DONT_FRAGMENT], [1], [Have IP_MTU_DISCOVER/IP_DONTFRAG sockopt.])
|
||||
fi
|
||||
|
||||
AC_CHECK_MEMBER([struct tcp_info.tcpi_snd_wnd],
|
||||
[iperf3_cv_header_tcp_info_snd_wnd=yes], [iperf3_cv_header_tcp_info_snd_wnd=no],
|
||||
[#ifdef HAVE_LINUX_TCP_H
|
||||
#include <linux/tcp.h>
|
||||
#else
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
])
|
||||
|
||||
if test "x$iperf3_cv_header_tcp_info_snd_wnd" = "xyes"; then
|
||||
AC_DEFINE([HAVE_TCP_INFO_SND_WND], [1], [Have tcpi_snd_wnd field in tcp_info.])
|
||||
fi
|
||||
|
||||
# Check if we need -lrt for clock_gettime
|
||||
AC_SEARCH_LIBS(clock_gettime, [rt posix4])
|
||||
# Check for clock_gettime support
|
||||
|
@ -39,7 +39,11 @@
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_TCP_H
|
||||
#include <linux/tcp.h>
|
||||
#else
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
#include <net/if.h> // for IFNAMSIZ
|
||||
|
||||
#if defined(HAVE_CPUSET_SETAFFINITY)
|
||||
@ -100,6 +104,7 @@ struct iperf_interval_results
|
||||
int interval_retrans;
|
||||
int interval_sacks;
|
||||
int snd_cwnd;
|
||||
int snd_wnd;
|
||||
TAILQ_ENTRY(iperf_interval_results) irlistentries;
|
||||
void *custom_data;
|
||||
int rtt;
|
||||
@ -123,6 +128,7 @@ struct iperf_stream_result
|
||||
int stream_sum_rtt;
|
||||
int stream_count_rtt;
|
||||
int stream_max_snd_cwnd;
|
||||
int stream_max_snd_wnd;
|
||||
struct iperf_time start_time;
|
||||
struct iperf_time end_time;
|
||||
struct iperf_time start_time_fixed;
|
||||
|
@ -49,7 +49,6 @@
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/mman.h>
|
||||
@ -3070,6 +3069,11 @@ iperf_stats_callback(struct iperf_test *test)
|
||||
rp->stream_max_snd_cwnd = temp.snd_cwnd;
|
||||
}
|
||||
|
||||
temp.snd_wnd = get_snd_wnd(&temp);
|
||||
if (temp.snd_wnd > rp->stream_max_snd_wnd) {
|
||||
rp->stream_max_snd_wnd = temp.snd_wnd;
|
||||
}
|
||||
|
||||
temp.rtt = get_rtt(&temp);
|
||||
if (temp.rtt > rp->stream_max_rtt) {
|
||||
rp->stream_max_rtt = temp.rtt;
|
||||
@ -3501,7 +3505,7 @@ iperf_print_results(struct iperf_test *test)
|
||||
if (test->sender_has_retransmits) {
|
||||
/* Sender summary, TCP and SCTP with retransmits. */
|
||||
if (test->json_output)
|
||||
cJSON_AddItemToObject(json_summary_stream, "sender", iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d max_snd_cwnd: %d max_rtt: %d min_rtt: %d mean_rtt: %d sender: %b", (int64_t) sp->socket, (double) start_time, (double) sender_time, (double) sender_time, (int64_t) bytes_sent, bandwidth * 8, (int64_t) sp->result->stream_retrans, (int64_t) sp->result->stream_max_snd_cwnd, (int64_t) sp->result->stream_max_rtt, (int64_t) sp->result->stream_min_rtt, (int64_t) ((sp->result->stream_count_rtt == 0) ? 0 : sp->result->stream_sum_rtt / sp->result->stream_count_rtt), stream_must_be_sender));
|
||||
cJSON_AddItemToObject(json_summary_stream, "sender", iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d max_snd_cwnd: %d max_snd_wnd: %d max_rtt: %d min_rtt: %d mean_rtt: %d sender: %b", (int64_t) sp->socket, (double) start_time, (double) sender_time, (double) sender_time, (int64_t) bytes_sent, bandwidth * 8, (int64_t) sp->result->stream_retrans, (int64_t) sp->result->stream_max_snd_cwnd, (int64_t) sp->result->stream_max_snd_wnd, (int64_t) sp->result->stream_max_rtt, (int64_t) sp->result->stream_min_rtt, (int64_t) ((sp->result->stream_count_rtt == 0) ? 0 : sp->result->stream_sum_rtt / sp->result->stream_count_rtt), stream_must_be_sender));
|
||||
else
|
||||
if (test->role == 's' && !sp->sender) {
|
||||
if (test->verbose)
|
||||
@ -3915,7 +3919,7 @@ print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *
|
||||
if (test->sender_has_retransmits == 1 && sp->sender) {
|
||||
/* Interval, TCP with retransmits. */
|
||||
if (test->json_output)
|
||||
cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d snd_cwnd: %d rtt: %d rttvar: %d pmtu: %d omitted: %b sender: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (int64_t) irp->interval_retrans, (int64_t) irp->snd_cwnd, (int64_t) irp->rtt, (int64_t) irp->rttvar, (int64_t) irp->pmtu, irp->omitted, sp->sender));
|
||||
cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d snd_cwnd: %d snd_wnd: %d rtt: %d rttvar: %d pmtu: %d omitted: %b sender: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (int64_t) irp->interval_retrans, (int64_t) irp->snd_cwnd, (int64_t) irp->snd_wnd, (int64_t) irp->rtt, (int64_t) irp->rttvar, (int64_t) irp->pmtu, irp->omitted, sp->sender));
|
||||
else {
|
||||
unit_snprintf(cbuf, UNIT_LEN, irp->snd_cwnd, 'A');
|
||||
iperf_printf(test, report_bw_retrans_cwnd_format, sp->socket, mbuf, st, et, ubuf, nbuf, irp->interval_retrans, cbuf, irp->omitted?report_omitted:"");
|
||||
|
@ -277,6 +277,7 @@ int has_tcpinfo_retransmits(void);
|
||||
void save_tcpinfo(struct iperf_stream *sp, struct iperf_interval_results *irp);
|
||||
long get_total_retransmits(struct iperf_interval_results *irp);
|
||||
long get_snd_cwnd(struct iperf_interval_results *irp);
|
||||
long get_snd_wnd(struct iperf_interval_results *irp);
|
||||
long get_rtt(struct iperf_interval_results *irp);
|
||||
long get_rttvar(struct iperf_interval_results *irp);
|
||||
long get_pmtu(struct iperf_interval_results *irp);
|
||||
|
@ -30,6 +30,9 @@
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the <linux/tcp.h> header file. */
|
||||
#undef HAVE_LINUX_TCP_H
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
@ -90,6 +93,9 @@
|
||||
/* Have TCP_CONGESTION sockopt. */
|
||||
#undef HAVE_TCP_CONGESTION
|
||||
|
||||
/* Have tcpi_snd_wnd field in tcp_info. */
|
||||
#undef HAVE_TCP_INFO_SND_WND
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
|
@ -143,6 +143,26 @@ get_snd_cwnd(struct iperf_interval_results *irp)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************/
|
||||
/*
|
||||
* 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 irp->tcpInfo.tcpi_snd_wnd * irp->tcpInfo.tcpi_snd_mss;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************/
|
||||
/*
|
||||
* Return rtt in usec.
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user