xref: /aosp_15_r20/external/iperf3/src/tcp_info.c (revision 7ab6e6ace082586527a400463bc693a412a40341)
1*7ab6e6acSAndroid Build Coastguard Worker /*
2*7ab6e6acSAndroid Build Coastguard Worker  * iperf, Copyright (c) 2014, 2017, The Regents of the University of
3*7ab6e6acSAndroid Build Coastguard Worker  * California, through Lawrence Berkeley National Laboratory (subject
4*7ab6e6acSAndroid Build Coastguard Worker  * to receipt of any required approvals from the U.S. Dept. of
5*7ab6e6acSAndroid Build Coastguard Worker  * Energy).  All rights reserved.
6*7ab6e6acSAndroid Build Coastguard Worker  *
7*7ab6e6acSAndroid Build Coastguard Worker  * If you have questions about your rights to use or distribute this
8*7ab6e6acSAndroid Build Coastguard Worker  * software, please contact Berkeley Lab's Technology Transfer
9*7ab6e6acSAndroid Build Coastguard Worker  * Department at [email protected].
10*7ab6e6acSAndroid Build Coastguard Worker  *
11*7ab6e6acSAndroid Build Coastguard Worker  * NOTICE.  This software is owned by the U.S. Department of Energy.
12*7ab6e6acSAndroid Build Coastguard Worker  * As such, the U.S. Government has been granted for itself and others
13*7ab6e6acSAndroid Build Coastguard Worker  * acting on its behalf a paid-up, nonexclusive, irrevocable,
14*7ab6e6acSAndroid Build Coastguard Worker  * worldwide license in the Software to reproduce, prepare derivative
15*7ab6e6acSAndroid Build Coastguard Worker  * works, and perform publicly and display publicly.  Beginning five
16*7ab6e6acSAndroid Build Coastguard Worker  * (5) years after the date permission to assert copyright is obtained
17*7ab6e6acSAndroid Build Coastguard Worker  * from the U.S. Department of Energy, and subject to any subsequent
18*7ab6e6acSAndroid Build Coastguard Worker  * five (5) year renewals, the U.S. Government is granted for itself
19*7ab6e6acSAndroid Build Coastguard Worker  * and others acting on its behalf a paid-up, nonexclusive,
20*7ab6e6acSAndroid Build Coastguard Worker  * irrevocable, worldwide license in the Software to reproduce,
21*7ab6e6acSAndroid Build Coastguard Worker  * prepare derivative works, distribute copies to the public, perform
22*7ab6e6acSAndroid Build Coastguard Worker  * publicly and display publicly, and to permit others to do so.
23*7ab6e6acSAndroid Build Coastguard Worker  *
24*7ab6e6acSAndroid Build Coastguard Worker  * This code is distributed under a BSD style license, see the LICENSE
25*7ab6e6acSAndroid Build Coastguard Worker  * file for complete information.
26*7ab6e6acSAndroid Build Coastguard Worker  */
27*7ab6e6acSAndroid Build Coastguard Worker 
28*7ab6e6acSAndroid Build Coastguard Worker /*
29*7ab6e6acSAndroid Build Coastguard Worker  * routines related to collection TCP_INFO using getsockopt()
30*7ab6e6acSAndroid Build Coastguard Worker  *
31*7ab6e6acSAndroid Build Coastguard Worker  * Brian Tierney, ESnet  ([email protected])
32*7ab6e6acSAndroid Build Coastguard Worker  *
33*7ab6e6acSAndroid Build Coastguard Worker  * Note that this is only really useful on Linux.
34*7ab6e6acSAndroid Build Coastguard Worker  * XXX: only standard on linux versions 2.4 and later
35*7ab6e6acSAndroid Build Coastguard Worker  #
36*7ab6e6acSAndroid Build Coastguard Worker  * FreeBSD has a limitted implementation that only includes the following:
37*7ab6e6acSAndroid Build Coastguard Worker  *   tcpi_snd_ssthresh, tcpi_snd_cwnd, tcpi_rcv_space, tcpi_rtt
38*7ab6e6acSAndroid Build Coastguard Worker  * Based on information on http://wiki.freebsd.org/8.0TODO, I dont think this will be
39*7ab6e6acSAndroid Build Coastguard Worker  * fixed before v8.1 at the earliest.
40*7ab6e6acSAndroid Build Coastguard Worker  *
41*7ab6e6acSAndroid Build Coastguard Worker  * OSX has no support.
42*7ab6e6acSAndroid Build Coastguard Worker  *
43*7ab6e6acSAndroid Build Coastguard Worker  * I think MS Windows does support TCP_INFO, but iperf3 does not currently support Windows.
44*7ab6e6acSAndroid Build Coastguard Worker  */
45*7ab6e6acSAndroid Build Coastguard Worker 
46*7ab6e6acSAndroid Build Coastguard Worker #include <stdio.h>
47*7ab6e6acSAndroid Build Coastguard Worker #include <stdlib.h>
48*7ab6e6acSAndroid Build Coastguard Worker #include <sys/param.h>
49*7ab6e6acSAndroid Build Coastguard Worker #include <sys/types.h>
50*7ab6e6acSAndroid Build Coastguard Worker #include <sys/socket.h>
51*7ab6e6acSAndroid Build Coastguard Worker #include <string.h>
52*7ab6e6acSAndroid Build Coastguard Worker #include <netinet/in.h>
53*7ab6e6acSAndroid Build Coastguard Worker #include <errno.h>
54*7ab6e6acSAndroid Build Coastguard Worker 
55*7ab6e6acSAndroid Build Coastguard Worker #include "iperf.h"
56*7ab6e6acSAndroid Build Coastguard Worker #include "iperf_api.h"
57*7ab6e6acSAndroid Build Coastguard Worker #include "iperf_locale.h"
58*7ab6e6acSAndroid Build Coastguard Worker 
59*7ab6e6acSAndroid Build Coastguard Worker /*************************************************************/
60*7ab6e6acSAndroid Build Coastguard Worker int
has_tcpinfo(void)61*7ab6e6acSAndroid Build Coastguard Worker has_tcpinfo(void)
62*7ab6e6acSAndroid Build Coastguard Worker {
63*7ab6e6acSAndroid Build Coastguard Worker #if (defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)) \
64*7ab6e6acSAndroid Build Coastguard Worker 	&& defined(TCP_INFO)
65*7ab6e6acSAndroid Build Coastguard Worker     return 1;
66*7ab6e6acSAndroid Build Coastguard Worker #else
67*7ab6e6acSAndroid Build Coastguard Worker     return 0;
68*7ab6e6acSAndroid Build Coastguard Worker #endif
69*7ab6e6acSAndroid Build Coastguard Worker }
70*7ab6e6acSAndroid Build Coastguard Worker 
71*7ab6e6acSAndroid Build Coastguard Worker /*************************************************************/
72*7ab6e6acSAndroid Build Coastguard Worker int
has_tcpinfo_retransmits(void)73*7ab6e6acSAndroid Build Coastguard Worker has_tcpinfo_retransmits(void)
74*7ab6e6acSAndroid Build Coastguard Worker {
75*7ab6e6acSAndroid Build Coastguard Worker #if defined(linux) && defined(TCP_MD5SIG)
76*7ab6e6acSAndroid Build Coastguard Worker     /* TCP_MD5SIG doesn't actually have anything to do with TCP
77*7ab6e6acSAndroid Build Coastguard Worker     ** retransmits, it just showed up in the same rev of the header
78*7ab6e6acSAndroid Build Coastguard Worker     ** file.  If it's present then struct tcp_info has the
79*7ab6e6acSAndroid Build Coastguard Worker     ** tcpi_total_retrans field that we need; if not, not.
80*7ab6e6acSAndroid Build Coastguard Worker     */
81*7ab6e6acSAndroid Build Coastguard Worker     return 1;
82*7ab6e6acSAndroid Build Coastguard Worker #else
83*7ab6e6acSAndroid Build Coastguard Worker #if defined(__FreeBSD__) && __FreeBSD_version >= 600000
84*7ab6e6acSAndroid Build Coastguard Worker     return 1; /* Should work now */
85*7ab6e6acSAndroid Build Coastguard Worker #elif defined(__NetBSD__) && defined(TCP_INFO)
86*7ab6e6acSAndroid Build Coastguard Worker     return 1;
87*7ab6e6acSAndroid Build Coastguard Worker #else
88*7ab6e6acSAndroid Build Coastguard Worker     return 0;
89*7ab6e6acSAndroid Build Coastguard Worker #endif
90*7ab6e6acSAndroid Build Coastguard Worker #endif
91*7ab6e6acSAndroid Build Coastguard Worker }
92*7ab6e6acSAndroid Build Coastguard Worker 
93*7ab6e6acSAndroid Build Coastguard Worker /*************************************************************/
94*7ab6e6acSAndroid Build Coastguard Worker void
save_tcpinfo(struct iperf_stream * sp,struct iperf_interval_results * irp)95*7ab6e6acSAndroid Build Coastguard Worker save_tcpinfo(struct iperf_stream *sp, struct iperf_interval_results *irp)
96*7ab6e6acSAndroid Build Coastguard Worker {
97*7ab6e6acSAndroid Build Coastguard Worker #if (defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)) && \
98*7ab6e6acSAndroid Build Coastguard Worker 	defined(TCP_INFO)
99*7ab6e6acSAndroid Build Coastguard Worker     socklen_t tcp_info_length = sizeof(struct tcp_info);
100*7ab6e6acSAndroid Build Coastguard Worker 
101*7ab6e6acSAndroid Build Coastguard Worker     if (getsockopt(sp->socket, IPPROTO_TCP, TCP_INFO, (void *)&irp->tcpInfo, &tcp_info_length) < 0)
102*7ab6e6acSAndroid Build Coastguard Worker 	iperf_err(sp->test, "getsockopt - %s", strerror(errno));
103*7ab6e6acSAndroid Build Coastguard Worker 
104*7ab6e6acSAndroid Build Coastguard Worker     if (sp->test->debug) {
105*7ab6e6acSAndroid Build Coastguard Worker 	printf("tcpi_snd_cwnd %u tcpi_snd_mss %u tcpi_rtt %u\n",
106*7ab6e6acSAndroid Build Coastguard Worker 	       irp->tcpInfo.tcpi_snd_cwnd, irp->tcpInfo.tcpi_snd_mss,
107*7ab6e6acSAndroid Build Coastguard Worker 	       irp->tcpInfo.tcpi_rtt);
108*7ab6e6acSAndroid Build Coastguard Worker     }
109*7ab6e6acSAndroid Build Coastguard Worker 
110*7ab6e6acSAndroid Build Coastguard Worker #endif
111*7ab6e6acSAndroid Build Coastguard Worker }
112*7ab6e6acSAndroid Build Coastguard Worker 
113*7ab6e6acSAndroid Build Coastguard Worker /*************************************************************/
114*7ab6e6acSAndroid Build Coastguard Worker long
get_total_retransmits(struct iperf_interval_results * irp)115*7ab6e6acSAndroid Build Coastguard Worker get_total_retransmits(struct iperf_interval_results *irp)
116*7ab6e6acSAndroid Build Coastguard Worker {
117*7ab6e6acSAndroid Build Coastguard Worker #if defined(linux) && defined(TCP_MD5SIG)
118*7ab6e6acSAndroid Build Coastguard Worker     return irp->tcpInfo.tcpi_total_retrans;
119*7ab6e6acSAndroid Build Coastguard Worker #elif defined(__FreeBSD__) && __FreeBSD_version >= 600000
120*7ab6e6acSAndroid Build Coastguard Worker     return irp->tcpInfo.tcpi_snd_rexmitpack;
121*7ab6e6acSAndroid Build Coastguard Worker #elif defined(__NetBSD__) && defined(TCP_INFO)
122*7ab6e6acSAndroid Build Coastguard Worker     return irp->tcpInfo.tcpi_snd_rexmitpack;
123*7ab6e6acSAndroid Build Coastguard Worker #else
124*7ab6e6acSAndroid Build Coastguard Worker     return -1;
125*7ab6e6acSAndroid Build Coastguard Worker #endif
126*7ab6e6acSAndroid Build Coastguard Worker }
127*7ab6e6acSAndroid Build Coastguard Worker 
128*7ab6e6acSAndroid Build Coastguard Worker /*************************************************************/
129*7ab6e6acSAndroid Build Coastguard Worker /*
130*7ab6e6acSAndroid Build Coastguard Worker  * Return snd_cwnd in octets.
131*7ab6e6acSAndroid Build Coastguard Worker  */
132*7ab6e6acSAndroid Build Coastguard Worker long
get_snd_cwnd(struct iperf_interval_results * irp)133*7ab6e6acSAndroid Build Coastguard Worker get_snd_cwnd(struct iperf_interval_results *irp)
134*7ab6e6acSAndroid Build Coastguard Worker {
135*7ab6e6acSAndroid Build Coastguard Worker #if defined(linux) && defined(TCP_MD5SIG)
136*7ab6e6acSAndroid Build Coastguard Worker     return irp->tcpInfo.tcpi_snd_cwnd * irp->tcpInfo.tcpi_snd_mss;
137*7ab6e6acSAndroid Build Coastguard Worker #elif defined(__FreeBSD__) && __FreeBSD_version >= 600000
138*7ab6e6acSAndroid Build Coastguard Worker     return irp->tcpInfo.tcpi_snd_cwnd;
139*7ab6e6acSAndroid Build Coastguard Worker #elif defined(__NetBSD__) && defined(TCP_INFO)
140*7ab6e6acSAndroid Build Coastguard Worker     return irp->tcpInfo.tcpi_snd_cwnd * irp->tcpInfo.tcpi_snd_mss;
141*7ab6e6acSAndroid Build Coastguard Worker #else
142*7ab6e6acSAndroid Build Coastguard Worker     return -1;
143*7ab6e6acSAndroid Build Coastguard Worker #endif
144*7ab6e6acSAndroid Build Coastguard Worker }
145*7ab6e6acSAndroid Build Coastguard Worker 
146*7ab6e6acSAndroid Build Coastguard Worker /*************************************************************/
147*7ab6e6acSAndroid Build Coastguard Worker /*
148*7ab6e6acSAndroid Build Coastguard Worker  * Return rtt in usec.
149*7ab6e6acSAndroid Build Coastguard Worker  */
150*7ab6e6acSAndroid Build Coastguard Worker long
get_rtt(struct iperf_interval_results * irp)151*7ab6e6acSAndroid Build Coastguard Worker get_rtt(struct iperf_interval_results *irp)
152*7ab6e6acSAndroid Build Coastguard Worker {
153*7ab6e6acSAndroid Build Coastguard Worker #if defined(linux) && defined(TCP_MD5SIG)
154*7ab6e6acSAndroid Build Coastguard Worker     return irp->tcpInfo.tcpi_rtt;
155*7ab6e6acSAndroid Build Coastguard Worker #elif defined(__FreeBSD__) && __FreeBSD_version >= 600000
156*7ab6e6acSAndroid Build Coastguard Worker     return irp->tcpInfo.tcpi_rtt;
157*7ab6e6acSAndroid Build Coastguard Worker #elif defined(__NetBSD__) && defined(TCP_INFO)
158*7ab6e6acSAndroid Build Coastguard Worker     return irp->tcpInfo.tcpi_rtt;
159*7ab6e6acSAndroid Build Coastguard Worker #else
160*7ab6e6acSAndroid Build Coastguard Worker     return -1;
161*7ab6e6acSAndroid Build Coastguard Worker #endif
162*7ab6e6acSAndroid Build Coastguard Worker }
163*7ab6e6acSAndroid Build Coastguard Worker 
164*7ab6e6acSAndroid Build Coastguard Worker /*************************************************************/
165*7ab6e6acSAndroid Build Coastguard Worker /*
166*7ab6e6acSAndroid Build Coastguard Worker  * Return rttvar in usec.
167*7ab6e6acSAndroid Build Coastguard Worker  */
168*7ab6e6acSAndroid Build Coastguard Worker long
get_rttvar(struct iperf_interval_results * irp)169*7ab6e6acSAndroid Build Coastguard Worker get_rttvar(struct iperf_interval_results *irp)
170*7ab6e6acSAndroid Build Coastguard Worker {
171*7ab6e6acSAndroid Build Coastguard Worker #if defined(linux) && defined(TCP_MD5SIG)
172*7ab6e6acSAndroid Build Coastguard Worker     return irp->tcpInfo.tcpi_rttvar;
173*7ab6e6acSAndroid Build Coastguard Worker #elif defined(__FreeBSD__) && __FreeBSD_version >= 600000
174*7ab6e6acSAndroid Build Coastguard Worker     return irp->tcpInfo.tcpi_rttvar;
175*7ab6e6acSAndroid Build Coastguard Worker #elif defined(__NetBSD__) && defined(TCP_INFO)
176*7ab6e6acSAndroid Build Coastguard Worker     return irp->tcpInfo.tcpi_rttvar;
177*7ab6e6acSAndroid Build Coastguard Worker #else
178*7ab6e6acSAndroid Build Coastguard Worker     return -1;
179*7ab6e6acSAndroid Build Coastguard Worker #endif
180*7ab6e6acSAndroid Build Coastguard Worker }
181*7ab6e6acSAndroid Build Coastguard Worker 
182*7ab6e6acSAndroid Build Coastguard Worker /*************************************************************/
183*7ab6e6acSAndroid Build Coastguard Worker /*
184*7ab6e6acSAndroid Build Coastguard Worker  * Return PMTU in bytes.
185*7ab6e6acSAndroid Build Coastguard Worker  */
186*7ab6e6acSAndroid Build Coastguard Worker long
get_pmtu(struct iperf_interval_results * irp)187*7ab6e6acSAndroid Build Coastguard Worker get_pmtu(struct iperf_interval_results *irp)
188*7ab6e6acSAndroid Build Coastguard Worker {
189*7ab6e6acSAndroid Build Coastguard Worker #if defined(linux) && defined(TCP_MD5SIG)
190*7ab6e6acSAndroid Build Coastguard Worker     return irp->tcpInfo.tcpi_pmtu;
191*7ab6e6acSAndroid Build Coastguard Worker #else
192*7ab6e6acSAndroid Build Coastguard Worker     return -1;
193*7ab6e6acSAndroid Build Coastguard Worker #endif
194*7ab6e6acSAndroid Build Coastguard Worker }
195*7ab6e6acSAndroid Build Coastguard Worker 
196*7ab6e6acSAndroid Build Coastguard Worker /*************************************************************/
197*7ab6e6acSAndroid Build Coastguard Worker void
build_tcpinfo_message(struct iperf_interval_results * r,char * message)198*7ab6e6acSAndroid Build Coastguard Worker build_tcpinfo_message(struct iperf_interval_results *r, char *message)
199*7ab6e6acSAndroid Build Coastguard Worker {
200*7ab6e6acSAndroid Build Coastguard Worker #if defined(linux) && defined(TCP_INFO)
201*7ab6e6acSAndroid Build Coastguard Worker     sprintf(message, report_tcpInfo, r->tcpInfo.tcpi_snd_cwnd, r->tcpInfo.tcpi_snd_ssthresh,
202*7ab6e6acSAndroid Build Coastguard Worker 	    r->tcpInfo.tcpi_rcv_ssthresh, r->tcpInfo.tcpi_unacked, r->tcpInfo.tcpi_sacked,
203*7ab6e6acSAndroid Build Coastguard Worker 	    r->tcpInfo.tcpi_lost, r->tcpInfo.tcpi_retrans, r->tcpInfo.tcpi_fackets,
204*7ab6e6acSAndroid Build Coastguard Worker 	    r->tcpInfo.tcpi_rtt, r->tcpInfo.tcpi_reordering);
205*7ab6e6acSAndroid Build Coastguard Worker #endif
206*7ab6e6acSAndroid Build Coastguard Worker #if defined(__FreeBSD__) && defined(TCP_INFO)
207*7ab6e6acSAndroid Build Coastguard Worker     sprintf(message, report_tcpInfo, r->tcpInfo.tcpi_snd_cwnd,
208*7ab6e6acSAndroid Build Coastguard Worker 	    r->tcpInfo.tcpi_rcv_space, r->tcpInfo.tcpi_snd_ssthresh, r->tcpInfo.tcpi_rtt);
209*7ab6e6acSAndroid Build Coastguard Worker #endif
210*7ab6e6acSAndroid Build Coastguard Worker #if defined(__NetBSD__) && defined(TCP_INFO)
211*7ab6e6acSAndroid Build Coastguard Worker     sprintf(message, report_tcpInfo, r->tcpInfo.tcpi_snd_cwnd,
212*7ab6e6acSAndroid Build Coastguard Worker 	    r->tcpInfo.tcpi_rcv_space, r->tcpInfo.tcpi_snd_ssthresh, r->tcpInfo.tcpi_rtt);
213*7ab6e6acSAndroid Build Coastguard Worker #endif
214*7ab6e6acSAndroid Build Coastguard Worker }
215