1*387f9dfdSAndroid Build Coastguard Worker // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2*387f9dfdSAndroid Build Coastguard Worker // Copyright (c) 2021 Wenbo Zhang
3*387f9dfdSAndroid Build Coastguard Worker //
4*387f9dfdSAndroid Build Coastguard Worker // Based on tcprtt(8) from BCC by zhenwei pi.
5*387f9dfdSAndroid Build Coastguard Worker // 06-Aug-2021 Wenbo Zhang Created this.
6*387f9dfdSAndroid Build Coastguard Worker #define _DEFAULT_SOURCE
7*387f9dfdSAndroid Build Coastguard Worker #include <arpa/inet.h>
8*387f9dfdSAndroid Build Coastguard Worker #include <argp.h>
9*387f9dfdSAndroid Build Coastguard Worker #include <stdio.h>
10*387f9dfdSAndroid Build Coastguard Worker #include <signal.h>
11*387f9dfdSAndroid Build Coastguard Worker #include <unistd.h>
12*387f9dfdSAndroid Build Coastguard Worker #include <time.h>
13*387f9dfdSAndroid Build Coastguard Worker #include <bpf/libbpf.h>
14*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf.h>
15*387f9dfdSAndroid Build Coastguard Worker #include "tcprtt.h"
16*387f9dfdSAndroid Build Coastguard Worker #include "tcprtt.skel.h"
17*387f9dfdSAndroid Build Coastguard Worker #include "trace_helpers.h"
18*387f9dfdSAndroid Build Coastguard Worker
19*387f9dfdSAndroid Build Coastguard Worker static struct env {
20*387f9dfdSAndroid Build Coastguard Worker __u16 lport;
21*387f9dfdSAndroid Build Coastguard Worker __u16 rport;
22*387f9dfdSAndroid Build Coastguard Worker __u32 laddr;
23*387f9dfdSAndroid Build Coastguard Worker __u32 raddr;
24*387f9dfdSAndroid Build Coastguard Worker __u8 laddr_v6[IPV6_LEN];
25*387f9dfdSAndroid Build Coastguard Worker __u8 raddr_v6[IPV6_LEN];
26*387f9dfdSAndroid Build Coastguard Worker bool milliseconds;
27*387f9dfdSAndroid Build Coastguard Worker time_t duration;
28*387f9dfdSAndroid Build Coastguard Worker time_t interval;
29*387f9dfdSAndroid Build Coastguard Worker bool timestamp;
30*387f9dfdSAndroid Build Coastguard Worker bool laddr_hist;
31*387f9dfdSAndroid Build Coastguard Worker bool raddr_hist;
32*387f9dfdSAndroid Build Coastguard Worker bool extended;
33*387f9dfdSAndroid Build Coastguard Worker bool verbose;
34*387f9dfdSAndroid Build Coastguard Worker } env = {
35*387f9dfdSAndroid Build Coastguard Worker .interval = 99999999,
36*387f9dfdSAndroid Build Coastguard Worker };
37*387f9dfdSAndroid Build Coastguard Worker
38*387f9dfdSAndroid Build Coastguard Worker static volatile bool exiting;
39*387f9dfdSAndroid Build Coastguard Worker
40*387f9dfdSAndroid Build Coastguard Worker const char *argp_program_version = "tcprtt 0.1";
41*387f9dfdSAndroid Build Coastguard Worker const char *argp_program_bug_address =
42*387f9dfdSAndroid Build Coastguard Worker "https://github.com/iovisor/bcc/tree/master/libbpf-tools";
43*387f9dfdSAndroid Build Coastguard Worker const char argp_program_doc[] =
44*387f9dfdSAndroid Build Coastguard Worker "Summarize TCP RTT as a histogram.\n"
45*387f9dfdSAndroid Build Coastguard Worker "\n"
46*387f9dfdSAndroid Build Coastguard Worker "USAGE: \n"
47*387f9dfdSAndroid Build Coastguard Worker "\n"
48*387f9dfdSAndroid Build Coastguard Worker "EXAMPLES:\n"
49*387f9dfdSAndroid Build Coastguard Worker " tcprtt # summarize TCP RTT\n"
50*387f9dfdSAndroid Build Coastguard Worker " tcprtt -i 1 -d 10 # print 1 second summaries, 10 times\n"
51*387f9dfdSAndroid Build Coastguard Worker " tcprtt -m -T # summarize in millisecond, and timestamps\n"
52*387f9dfdSAndroid Build Coastguard Worker " tcprtt -p # filter for local port\n"
53*387f9dfdSAndroid Build Coastguard Worker " tcprtt -P # filter for remote port\n"
54*387f9dfdSAndroid Build Coastguard Worker " tcprtt -a # filter for local address\n"
55*387f9dfdSAndroid Build Coastguard Worker " tcprtt -A # filter for remote address\n"
56*387f9dfdSAndroid Build Coastguard Worker " tcprtt -b # show sockets histogram by local address\n"
57*387f9dfdSAndroid Build Coastguard Worker " tcprtt -B # show sockets histogram by remote address\n"
58*387f9dfdSAndroid Build Coastguard Worker " tcprtt -e # show extension summary(average)\n";
59*387f9dfdSAndroid Build Coastguard Worker
60*387f9dfdSAndroid Build Coastguard Worker static const struct argp_option opts[] = {
61*387f9dfdSAndroid Build Coastguard Worker { "interval", 'i', "INTERVAL", 0, "summary interval, seconds" },
62*387f9dfdSAndroid Build Coastguard Worker { "duration", 'd', "DURATION", 0, "total duration of trace, seconds" },
63*387f9dfdSAndroid Build Coastguard Worker { "timestamp", 'T', NULL, 0, "include timestamp on output" },
64*387f9dfdSAndroid Build Coastguard Worker { "millisecond", 'm', NULL, 0, "millisecond histogram" },
65*387f9dfdSAndroid Build Coastguard Worker { "lport", 'p', "LPORT", 0, "filter for local port" },
66*387f9dfdSAndroid Build Coastguard Worker { "rport", 'P', "RPORT", 0, "filter for remote port" },
67*387f9dfdSAndroid Build Coastguard Worker { "laddr", 'a', "LADDR", 0, "filter for local address" },
68*387f9dfdSAndroid Build Coastguard Worker { "raddr", 'A', "RADDR", 0, "filter for remote address" },
69*387f9dfdSAndroid Build Coastguard Worker { "byladdr", 'b', NULL, 0,
70*387f9dfdSAndroid Build Coastguard Worker "show sockets histogram by local address" },
71*387f9dfdSAndroid Build Coastguard Worker { "byraddr", 'B', NULL, 0,
72*387f9dfdSAndroid Build Coastguard Worker "show sockets histogram by remote address" },
73*387f9dfdSAndroid Build Coastguard Worker { "extension", 'e', NULL, 0, "show extension summary(average)" },
74*387f9dfdSAndroid Build Coastguard Worker { "verbose", 'v', NULL, 0, "Verbose debug output" },
75*387f9dfdSAndroid Build Coastguard Worker { NULL, 'h', NULL, OPTION_HIDDEN, "Show the full help" },
76*387f9dfdSAndroid Build Coastguard Worker {},
77*387f9dfdSAndroid Build Coastguard Worker };
78*387f9dfdSAndroid Build Coastguard Worker
parse_arg(int key,char * arg,struct argp_state * state)79*387f9dfdSAndroid Build Coastguard Worker static error_t parse_arg(int key, char *arg, struct argp_state *state)
80*387f9dfdSAndroid Build Coastguard Worker {
81*387f9dfdSAndroid Build Coastguard Worker struct in_addr addr;
82*387f9dfdSAndroid Build Coastguard Worker struct in6_addr addr_v6;
83*387f9dfdSAndroid Build Coastguard Worker
84*387f9dfdSAndroid Build Coastguard Worker switch (key) {
85*387f9dfdSAndroid Build Coastguard Worker case 'h':
86*387f9dfdSAndroid Build Coastguard Worker argp_state_help(state, stderr, ARGP_HELP_STD_HELP);
87*387f9dfdSAndroid Build Coastguard Worker break;
88*387f9dfdSAndroid Build Coastguard Worker case 'v':
89*387f9dfdSAndroid Build Coastguard Worker env.verbose = true;
90*387f9dfdSAndroid Build Coastguard Worker break;
91*387f9dfdSAndroid Build Coastguard Worker case 'i':
92*387f9dfdSAndroid Build Coastguard Worker errno = 0;
93*387f9dfdSAndroid Build Coastguard Worker env.interval = strtol(arg, NULL, 10);
94*387f9dfdSAndroid Build Coastguard Worker if (errno || env.interval <= 0) {
95*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "invalid interval: %s\n", arg);
96*387f9dfdSAndroid Build Coastguard Worker argp_usage(state);
97*387f9dfdSAndroid Build Coastguard Worker }
98*387f9dfdSAndroid Build Coastguard Worker break;
99*387f9dfdSAndroid Build Coastguard Worker case 'd':
100*387f9dfdSAndroid Build Coastguard Worker errno = 0;
101*387f9dfdSAndroid Build Coastguard Worker env.duration = strtol(arg, NULL, 10);
102*387f9dfdSAndroid Build Coastguard Worker if (errno || env.duration <= 0) {
103*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "invalid duration: %s\n", arg);
104*387f9dfdSAndroid Build Coastguard Worker argp_usage(state);
105*387f9dfdSAndroid Build Coastguard Worker }
106*387f9dfdSAndroid Build Coastguard Worker break;
107*387f9dfdSAndroid Build Coastguard Worker case 'T':
108*387f9dfdSAndroid Build Coastguard Worker env.timestamp = true;
109*387f9dfdSAndroid Build Coastguard Worker break;
110*387f9dfdSAndroid Build Coastguard Worker case 'm':
111*387f9dfdSAndroid Build Coastguard Worker env.milliseconds = true;
112*387f9dfdSAndroid Build Coastguard Worker break;
113*387f9dfdSAndroid Build Coastguard Worker case 'p':
114*387f9dfdSAndroid Build Coastguard Worker errno = 0;
115*387f9dfdSAndroid Build Coastguard Worker env.lport = strtoul(arg, NULL, 10);
116*387f9dfdSAndroid Build Coastguard Worker if (errno) {
117*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "invalid lport: %s\n", arg);
118*387f9dfdSAndroid Build Coastguard Worker argp_usage(state);
119*387f9dfdSAndroid Build Coastguard Worker }
120*387f9dfdSAndroid Build Coastguard Worker env.lport = htons(env.lport);
121*387f9dfdSAndroid Build Coastguard Worker break;
122*387f9dfdSAndroid Build Coastguard Worker case 'P':
123*387f9dfdSAndroid Build Coastguard Worker errno = 0;
124*387f9dfdSAndroid Build Coastguard Worker env.rport = strtoul(arg, NULL, 10);
125*387f9dfdSAndroid Build Coastguard Worker if (errno) {
126*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "invalid rport: %s\n", arg);
127*387f9dfdSAndroid Build Coastguard Worker argp_usage(state);
128*387f9dfdSAndroid Build Coastguard Worker }
129*387f9dfdSAndroid Build Coastguard Worker env.rport = htons(env.rport);
130*387f9dfdSAndroid Build Coastguard Worker break;
131*387f9dfdSAndroid Build Coastguard Worker case 'a':
132*387f9dfdSAndroid Build Coastguard Worker if (strchr(arg, ':')) {
133*387f9dfdSAndroid Build Coastguard Worker if (inet_pton(AF_INET6, arg, &addr_v6) < 1) {
134*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "invalid local IPv6 address: %s\n", arg);
135*387f9dfdSAndroid Build Coastguard Worker argp_usage(state);
136*387f9dfdSAndroid Build Coastguard Worker }
137*387f9dfdSAndroid Build Coastguard Worker memcpy(env.laddr_v6, &addr_v6, sizeof(env.laddr_v6));
138*387f9dfdSAndroid Build Coastguard Worker } else {
139*387f9dfdSAndroid Build Coastguard Worker if (inet_pton(AF_INET, arg, &addr) < 0) {
140*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "invalid local address: %s\n", arg);
141*387f9dfdSAndroid Build Coastguard Worker argp_usage(state);
142*387f9dfdSAndroid Build Coastguard Worker }
143*387f9dfdSAndroid Build Coastguard Worker env.laddr = addr.s_addr;
144*387f9dfdSAndroid Build Coastguard Worker }
145*387f9dfdSAndroid Build Coastguard Worker break;
146*387f9dfdSAndroid Build Coastguard Worker case 'A':
147*387f9dfdSAndroid Build Coastguard Worker if (strchr(arg, ':')) {
148*387f9dfdSAndroid Build Coastguard Worker if (inet_pton(AF_INET6, arg, &addr_v6) < 1) {
149*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "invalid remote address: %s\n", arg);
150*387f9dfdSAndroid Build Coastguard Worker argp_usage(state);
151*387f9dfdSAndroid Build Coastguard Worker }
152*387f9dfdSAndroid Build Coastguard Worker memcpy(env.raddr_v6, &addr_v6, sizeof(env.raddr_v6));
153*387f9dfdSAndroid Build Coastguard Worker } else {
154*387f9dfdSAndroid Build Coastguard Worker if (inet_pton(AF_INET, arg, &addr) < 0) {
155*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "invalid remote address: %s\n", arg);
156*387f9dfdSAndroid Build Coastguard Worker argp_usage(state);
157*387f9dfdSAndroid Build Coastguard Worker }
158*387f9dfdSAndroid Build Coastguard Worker env.raddr = addr.s_addr;
159*387f9dfdSAndroid Build Coastguard Worker }
160*387f9dfdSAndroid Build Coastguard Worker break;
161*387f9dfdSAndroid Build Coastguard Worker case 'b':
162*387f9dfdSAndroid Build Coastguard Worker env.laddr_hist = true;
163*387f9dfdSAndroid Build Coastguard Worker break;
164*387f9dfdSAndroid Build Coastguard Worker case 'B':
165*387f9dfdSAndroid Build Coastguard Worker env.raddr_hist = true;
166*387f9dfdSAndroid Build Coastguard Worker break;
167*387f9dfdSAndroid Build Coastguard Worker case 'e':
168*387f9dfdSAndroid Build Coastguard Worker env.extended = true;
169*387f9dfdSAndroid Build Coastguard Worker break;
170*387f9dfdSAndroid Build Coastguard Worker default:
171*387f9dfdSAndroid Build Coastguard Worker return ARGP_ERR_UNKNOWN;
172*387f9dfdSAndroid Build Coastguard Worker }
173*387f9dfdSAndroid Build Coastguard Worker return 0;
174*387f9dfdSAndroid Build Coastguard Worker }
175*387f9dfdSAndroid Build Coastguard Worker
libbpf_print_fn(enum libbpf_print_level level,const char * format,va_list args)176*387f9dfdSAndroid Build Coastguard Worker static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
177*387f9dfdSAndroid Build Coastguard Worker {
178*387f9dfdSAndroid Build Coastguard Worker if (level == LIBBPF_DEBUG && !env.verbose)
179*387f9dfdSAndroid Build Coastguard Worker return 0;
180*387f9dfdSAndroid Build Coastguard Worker return vfprintf(stderr, format, args);
181*387f9dfdSAndroid Build Coastguard Worker }
182*387f9dfdSAndroid Build Coastguard Worker
sig_handler(int sig)183*387f9dfdSAndroid Build Coastguard Worker static void sig_handler(int sig)
184*387f9dfdSAndroid Build Coastguard Worker {
185*387f9dfdSAndroid Build Coastguard Worker exiting = true;
186*387f9dfdSAndroid Build Coastguard Worker }
187*387f9dfdSAndroid Build Coastguard Worker
print_map(struct bpf_map * map)188*387f9dfdSAndroid Build Coastguard Worker static int print_map(struct bpf_map *map)
189*387f9dfdSAndroid Build Coastguard Worker {
190*387f9dfdSAndroid Build Coastguard Worker const char *units = env.milliseconds ? "msecs" : "usecs";
191*387f9dfdSAndroid Build Coastguard Worker struct hist_key *lookup_key = NULL, next_key;
192*387f9dfdSAndroid Build Coastguard Worker int err, fd = bpf_map__fd(map);
193*387f9dfdSAndroid Build Coastguard Worker struct hist hist;
194*387f9dfdSAndroid Build Coastguard Worker
195*387f9dfdSAndroid Build Coastguard Worker while (!bpf_map_get_next_key(fd, lookup_key, &next_key)) {
196*387f9dfdSAndroid Build Coastguard Worker err = bpf_map_lookup_elem(fd, &next_key, &hist);
197*387f9dfdSAndroid Build Coastguard Worker if (err < 0) {
198*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "failed to lookup infos: %d\n", err);
199*387f9dfdSAndroid Build Coastguard Worker return -1;
200*387f9dfdSAndroid Build Coastguard Worker }
201*387f9dfdSAndroid Build Coastguard Worker
202*387f9dfdSAndroid Build Coastguard Worker
203*387f9dfdSAndroid Build Coastguard Worker if (env.laddr_hist)
204*387f9dfdSAndroid Build Coastguard Worker printf("Local Address = ");
205*387f9dfdSAndroid Build Coastguard Worker else if (env.raddr_hist)
206*387f9dfdSAndroid Build Coastguard Worker printf("Remote Address = ");
207*387f9dfdSAndroid Build Coastguard Worker else
208*387f9dfdSAndroid Build Coastguard Worker printf("All Addresses = ****** ");
209*387f9dfdSAndroid Build Coastguard Worker
210*387f9dfdSAndroid Build Coastguard Worker if (env.laddr_hist || env.raddr_hist) {
211*387f9dfdSAndroid Build Coastguard Worker __u16 family = next_key.family;
212*387f9dfdSAndroid Build Coastguard Worker char str[INET6_ADDRSTRLEN];
213*387f9dfdSAndroid Build Coastguard Worker
214*387f9dfdSAndroid Build Coastguard Worker if (!inet_ntop(family, next_key.addr, str, sizeof(str))) {
215*387f9dfdSAndroid Build Coastguard Worker perror("converting IP to string:");
216*387f9dfdSAndroid Build Coastguard Worker return -1;
217*387f9dfdSAndroid Build Coastguard Worker }
218*387f9dfdSAndroid Build Coastguard Worker
219*387f9dfdSAndroid Build Coastguard Worker printf("%s ", str);
220*387f9dfdSAndroid Build Coastguard Worker }
221*387f9dfdSAndroid Build Coastguard Worker
222*387f9dfdSAndroid Build Coastguard Worker if (env.extended)
223*387f9dfdSAndroid Build Coastguard Worker printf("[AVG %llu]", hist.latency / hist.cnt);
224*387f9dfdSAndroid Build Coastguard Worker printf("\n");
225*387f9dfdSAndroid Build Coastguard Worker print_log2_hist(hist.slots, MAX_SLOTS, units);
226*387f9dfdSAndroid Build Coastguard Worker lookup_key = &next_key;
227*387f9dfdSAndroid Build Coastguard Worker }
228*387f9dfdSAndroid Build Coastguard Worker
229*387f9dfdSAndroid Build Coastguard Worker lookup_key = NULL;
230*387f9dfdSAndroid Build Coastguard Worker while (!bpf_map_get_next_key(fd, lookup_key, &next_key)) {
231*387f9dfdSAndroid Build Coastguard Worker err = bpf_map_delete_elem(fd, &next_key);
232*387f9dfdSAndroid Build Coastguard Worker if (err < 0) {
233*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "failed to cleanup infos: %d\n", err);
234*387f9dfdSAndroid Build Coastguard Worker return -1;
235*387f9dfdSAndroid Build Coastguard Worker }
236*387f9dfdSAndroid Build Coastguard Worker lookup_key = &next_key;
237*387f9dfdSAndroid Build Coastguard Worker }
238*387f9dfdSAndroid Build Coastguard Worker
239*387f9dfdSAndroid Build Coastguard Worker return 0;
240*387f9dfdSAndroid Build Coastguard Worker }
241*387f9dfdSAndroid Build Coastguard Worker
main(int argc,char ** argv)242*387f9dfdSAndroid Build Coastguard Worker int main(int argc, char **argv)
243*387f9dfdSAndroid Build Coastguard Worker {
244*387f9dfdSAndroid Build Coastguard Worker static const struct argp argp = {
245*387f9dfdSAndroid Build Coastguard Worker .options = opts,
246*387f9dfdSAndroid Build Coastguard Worker .parser = parse_arg,
247*387f9dfdSAndroid Build Coastguard Worker .doc = argp_program_doc,
248*387f9dfdSAndroid Build Coastguard Worker };
249*387f9dfdSAndroid Build Coastguard Worker __u8 zero_addr_v6[IPV6_LEN] = {};
250*387f9dfdSAndroid Build Coastguard Worker struct tcprtt_bpf *obj;
251*387f9dfdSAndroid Build Coastguard Worker __u64 time_end = 0;
252*387f9dfdSAndroid Build Coastguard Worker struct tm *tm;
253*387f9dfdSAndroid Build Coastguard Worker char ts[32];
254*387f9dfdSAndroid Build Coastguard Worker time_t t;
255*387f9dfdSAndroid Build Coastguard Worker int err;
256*387f9dfdSAndroid Build Coastguard Worker
257*387f9dfdSAndroid Build Coastguard Worker err = argp_parse(&argp, argc, argv, 0, NULL, NULL);
258*387f9dfdSAndroid Build Coastguard Worker if (err)
259*387f9dfdSAndroid Build Coastguard Worker return err;
260*387f9dfdSAndroid Build Coastguard Worker
261*387f9dfdSAndroid Build Coastguard Worker if ((env.laddr || env.raddr)
262*387f9dfdSAndroid Build Coastguard Worker && (memcmp(env.laddr_v6, zero_addr_v6, sizeof(env.laddr_v6)) || memcmp(env.raddr_v6, zero_addr_v6, sizeof(env.raddr_v6)))) {
263*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "It is not permitted to filter by both IPv4 and IPv6\n");
264*387f9dfdSAndroid Build Coastguard Worker return 1;
265*387f9dfdSAndroid Build Coastguard Worker }
266*387f9dfdSAndroid Build Coastguard Worker
267*387f9dfdSAndroid Build Coastguard Worker libbpf_set_print(libbpf_print_fn);
268*387f9dfdSAndroid Build Coastguard Worker
269*387f9dfdSAndroid Build Coastguard Worker obj = tcprtt_bpf__open();
270*387f9dfdSAndroid Build Coastguard Worker if (!obj) {
271*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "failed to open BPF object\n");
272*387f9dfdSAndroid Build Coastguard Worker return 1;
273*387f9dfdSAndroid Build Coastguard Worker }
274*387f9dfdSAndroid Build Coastguard Worker
275*387f9dfdSAndroid Build Coastguard Worker obj->rodata->targ_laddr_hist = env.laddr_hist;
276*387f9dfdSAndroid Build Coastguard Worker obj->rodata->targ_raddr_hist = env.raddr_hist;
277*387f9dfdSAndroid Build Coastguard Worker obj->rodata->targ_show_ext = env.extended;
278*387f9dfdSAndroid Build Coastguard Worker obj->rodata->targ_sport = env.lport;
279*387f9dfdSAndroid Build Coastguard Worker obj->rodata->targ_dport = env.rport;
280*387f9dfdSAndroid Build Coastguard Worker obj->rodata->targ_saddr = env.laddr;
281*387f9dfdSAndroid Build Coastguard Worker obj->rodata->targ_daddr = env.raddr;
282*387f9dfdSAndroid Build Coastguard Worker memcpy(obj->rodata->targ_saddr_v6, env.laddr_v6, sizeof(obj->rodata->targ_saddr_v6));
283*387f9dfdSAndroid Build Coastguard Worker memcpy(obj->rodata->targ_daddr_v6, env.raddr_v6, sizeof(obj->rodata->targ_daddr_v6));
284*387f9dfdSAndroid Build Coastguard Worker obj->rodata->targ_ms = env.milliseconds;
285*387f9dfdSAndroid Build Coastguard Worker
286*387f9dfdSAndroid Build Coastguard Worker if (fentry_can_attach("tcp_rcv_established", NULL))
287*387f9dfdSAndroid Build Coastguard Worker bpf_program__set_autoload(obj->progs.tcp_rcv_kprobe, false);
288*387f9dfdSAndroid Build Coastguard Worker else
289*387f9dfdSAndroid Build Coastguard Worker bpf_program__set_autoload(obj->progs.tcp_rcv, false);
290*387f9dfdSAndroid Build Coastguard Worker
291*387f9dfdSAndroid Build Coastguard Worker err = tcprtt_bpf__load(obj);
292*387f9dfdSAndroid Build Coastguard Worker if (err) {
293*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "failed to load BPF object: %d\n", err);
294*387f9dfdSAndroid Build Coastguard Worker goto cleanup;
295*387f9dfdSAndroid Build Coastguard Worker }
296*387f9dfdSAndroid Build Coastguard Worker
297*387f9dfdSAndroid Build Coastguard Worker err = tcprtt_bpf__attach(obj);
298*387f9dfdSAndroid Build Coastguard Worker if (err) {
299*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "failed to attach BPF programs: %d\n", err);
300*387f9dfdSAndroid Build Coastguard Worker goto cleanup;
301*387f9dfdSAndroid Build Coastguard Worker }
302*387f9dfdSAndroid Build Coastguard Worker
303*387f9dfdSAndroid Build Coastguard Worker signal(SIGINT, sig_handler);
304*387f9dfdSAndroid Build Coastguard Worker
305*387f9dfdSAndroid Build Coastguard Worker printf("Tracing TCP RTT");
306*387f9dfdSAndroid Build Coastguard Worker if (env.duration)
307*387f9dfdSAndroid Build Coastguard Worker printf(" for %ld secs.\n", env.duration);
308*387f9dfdSAndroid Build Coastguard Worker else
309*387f9dfdSAndroid Build Coastguard Worker printf("... Hit Ctrl-C to end.\n");
310*387f9dfdSAndroid Build Coastguard Worker
311*387f9dfdSAndroid Build Coastguard Worker /* setup duration */
312*387f9dfdSAndroid Build Coastguard Worker if (env.duration)
313*387f9dfdSAndroid Build Coastguard Worker time_end = get_ktime_ns() + env.duration * NSEC_PER_SEC;
314*387f9dfdSAndroid Build Coastguard Worker
315*387f9dfdSAndroid Build Coastguard Worker /* main: poll */
316*387f9dfdSAndroid Build Coastguard Worker while (1) {
317*387f9dfdSAndroid Build Coastguard Worker sleep(env.interval);
318*387f9dfdSAndroid Build Coastguard Worker printf("\n");
319*387f9dfdSAndroid Build Coastguard Worker
320*387f9dfdSAndroid Build Coastguard Worker if (env.timestamp) {
321*387f9dfdSAndroid Build Coastguard Worker time(&t);
322*387f9dfdSAndroid Build Coastguard Worker tm = localtime(&t);
323*387f9dfdSAndroid Build Coastguard Worker strftime(ts, sizeof(ts), "%H:%M:%S", tm);
324*387f9dfdSAndroid Build Coastguard Worker printf("%-8s\n", ts);
325*387f9dfdSAndroid Build Coastguard Worker }
326*387f9dfdSAndroid Build Coastguard Worker
327*387f9dfdSAndroid Build Coastguard Worker err = print_map(obj->maps.hists);
328*387f9dfdSAndroid Build Coastguard Worker if (err)
329*387f9dfdSAndroid Build Coastguard Worker break;
330*387f9dfdSAndroid Build Coastguard Worker
331*387f9dfdSAndroid Build Coastguard Worker if (env.duration && get_ktime_ns() > time_end)
332*387f9dfdSAndroid Build Coastguard Worker goto cleanup;
333*387f9dfdSAndroid Build Coastguard Worker
334*387f9dfdSAndroid Build Coastguard Worker if (exiting)
335*387f9dfdSAndroid Build Coastguard Worker break;
336*387f9dfdSAndroid Build Coastguard Worker }
337*387f9dfdSAndroid Build Coastguard Worker
338*387f9dfdSAndroid Build Coastguard Worker cleanup:
339*387f9dfdSAndroid Build Coastguard Worker tcprtt_bpf__destroy(obj);
340*387f9dfdSAndroid Build Coastguard Worker return err != 0;
341*387f9dfdSAndroid Build Coastguard Worker }
342