Alexey Ivanov | cc01a9c | 2019-01-16 09:50:46 -0800 | [diff] [blame] | 1 | #!/usr/bin/python |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 2 | # @lint-avoid-python-3-compatibility-imports |
| 3 | # |
Brendan Gregg | 73b5401 | 2017-12-18 20:37:11 -0800 | [diff] [blame] | 4 | # tcpretrans Trace or count TCP retransmits and TLPs. |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 5 | # For Linux, uses BCC, eBPF. Embedded C. |
| 6 | # |
Hariharan Ananthakrishnan | 04893e3 | 2021-08-12 05:55:21 -0700 | [diff] [blame] | 7 | # USAGE: tcpretrans [-c] [-h] [-l] [-4 | -6] |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 8 | # |
| 9 | # This uses dynamic tracing of kernel functions, and will need to be updated |
| 10 | # to match kernel changes. |
| 11 | # |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 12 | # Copyright 2016 Netflix, Inc. |
| 13 | # Licensed under the Apache License, Version 2.0 (the "License") |
| 14 | # |
| 15 | # 14-Feb-2016 Brendan Gregg Created this. |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 16 | # 03-Nov-2017 Matthias Tafelmeier Extended this. |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 17 | |
| 18 | from __future__ import print_function |
| 19 | from bcc import BPF |
| 20 | import argparse |
| 21 | from time import strftime |
Mark Drayton | 11de298 | 2016-06-26 21:14:44 +0100 | [diff] [blame] | 22 | from socket import inet_ntop, AF_INET, AF_INET6 |
| 23 | from struct import pack |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 24 | from time import sleep |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 25 | |
| 26 | # arguments |
| 27 | examples = """examples: |
| 28 | ./tcpretrans # trace TCP retransmits |
| 29 | ./tcpretrans -l # include TLP attempts |
Hariharan Ananthakrishnan | 04893e3 | 2021-08-12 05:55:21 -0700 | [diff] [blame] | 30 | ./tcpretrans -4 # trace IPv4 family only |
| 31 | ./tcpretrans -6 # trace IPv6 family only |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 32 | """ |
| 33 | parser = argparse.ArgumentParser( |
| 34 | description="Trace TCP retransmits", |
| 35 | formatter_class=argparse.RawDescriptionHelpFormatter, |
| 36 | epilog=examples) |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 37 | parser.add_argument("-s", "--sequence", action="store_true", |
| 38 | help="display TCP sequence numbers") |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 39 | parser.add_argument("-l", "--lossprobe", action="store_true", |
| 40 | help="include tail loss probe attempts") |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 41 | parser.add_argument("-c", "--count", action="store_true", |
| 42 | help="count occurred retransmits per flow") |
Hariharan Ananthakrishnan | 04893e3 | 2021-08-12 05:55:21 -0700 | [diff] [blame] | 43 | group = parser.add_mutually_exclusive_group() |
| 44 | group.add_argument("-4", "--ipv4", action="store_true", |
| 45 | help="trace IPv4 family only") |
| 46 | group.add_argument("-6", "--ipv6", action="store_true", |
| 47 | help="trace IPv6 family only") |
Nathan Scott | cf0792f | 2018-02-02 16:56:50 +1100 | [diff] [blame] | 48 | parser.add_argument("--ebpf", action="store_true", |
| 49 | help=argparse.SUPPRESS) |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 50 | args = parser.parse_args() |
Brendan Gregg | 73b5401 | 2017-12-18 20:37:11 -0800 | [diff] [blame] | 51 | debug = 0 |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 52 | |
| 53 | # define BPF program |
| 54 | bpf_text = """ |
| 55 | #include <uapi/linux/ptrace.h> |
| 56 | #include <net/sock.h> |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 57 | #include <net/tcp.h> |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 58 | #include <bcc/proto.h> |
| 59 | |
| 60 | #define RETRANSMIT 1 |
| 61 | #define TLP 2 |
| 62 | |
| 63 | // separate data structs for ipv4 and ipv6 |
| 64 | struct ipv4_data_t { |
Joe Yin | 36ce112 | 2018-08-17 06:04:00 +0800 | [diff] [blame] | 65 | u32 pid; |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 66 | u64 ip; |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 67 | u32 seq; |
Joe Yin | 36ce112 | 2018-08-17 06:04:00 +0800 | [diff] [blame] | 68 | u32 saddr; |
| 69 | u32 daddr; |
| 70 | u16 lport; |
| 71 | u16 dport; |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 72 | u64 state; |
| 73 | u64 type; |
| 74 | }; |
| 75 | BPF_PERF_OUTPUT(ipv4_events); |
| 76 | |
| 77 | struct ipv6_data_t { |
Joe Yin | 36ce112 | 2018-08-17 06:04:00 +0800 | [diff] [blame] | 78 | u32 pid; |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 79 | u32 seq; |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 80 | u64 ip; |
Mark Drayton | 11de298 | 2016-06-26 21:14:44 +0100 | [diff] [blame] | 81 | unsigned __int128 saddr; |
| 82 | unsigned __int128 daddr; |
Joe Yin | 36ce112 | 2018-08-17 06:04:00 +0800 | [diff] [blame] | 83 | u16 lport; |
| 84 | u16 dport; |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 85 | u64 state; |
| 86 | u64 type; |
| 87 | }; |
| 88 | BPF_PERF_OUTPUT(ipv6_events); |
| 89 | |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 90 | // separate flow keys per address family |
| 91 | struct ipv4_flow_key_t { |
| 92 | u32 saddr; |
| 93 | u32 daddr; |
| 94 | u16 lport; |
| 95 | u16 dport; |
| 96 | }; |
| 97 | BPF_HASH(ipv4_count, struct ipv4_flow_key_t); |
| 98 | |
| 99 | struct ipv6_flow_key_t { |
| 100 | unsigned __int128 saddr; |
| 101 | unsigned __int128 daddr; |
| 102 | u16 lport; |
| 103 | u16 dport; |
| 104 | }; |
| 105 | BPF_HASH(ipv6_count, struct ipv6_flow_key_t); |
Xiaozhou Liu | 9cede20 | 2019-11-09 08:34:45 +0800 | [diff] [blame] | 106 | """ |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 107 | |
Xiaozhou Liu | 9cede20 | 2019-11-09 08:34:45 +0800 | [diff] [blame] | 108 | bpf_text_kprobe = """ |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 109 | static int trace_event(struct pt_regs *ctx, struct sock *skp, struct sk_buff *skb, int type) |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 110 | { |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 111 | struct tcp_skb_cb *tcb; |
| 112 | u32 seq; |
| 113 | |
Paul Chaignon | 25212ee | 2017-08-06 11:15:11 +0200 | [diff] [blame] | 114 | if (skp == NULL) |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 115 | return 0; |
Marko Myllynen | a77a254 | 2018-09-10 20:44:55 +0300 | [diff] [blame] | 116 | u32 pid = bpf_get_current_pid_tgid() >> 32; |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 117 | |
| 118 | // pull in details |
Paul Chaignon | 25212ee | 2017-08-06 11:15:11 +0200 | [diff] [blame] | 119 | u16 family = skp->__sk_common.skc_family; |
| 120 | u16 lport = skp->__sk_common.skc_num; |
| 121 | u16 dport = skp->__sk_common.skc_dport; |
| 122 | char state = skp->__sk_common.skc_state; |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 123 | |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 124 | seq = 0; |
| 125 | if (skb) { |
| 126 | /* macro TCP_SKB_CB from net/tcp.h */ |
| 127 | tcb = ((struct tcp_skb_cb *)&((skb)->cb[0])); |
| 128 | seq = tcb->seq; |
| 129 | } |
| 130 | |
Hariharan Ananthakrishnan | 04893e3 | 2021-08-12 05:55:21 -0700 | [diff] [blame] | 131 | FILTER_FAMILY |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 132 | |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 133 | if (family == AF_INET) { |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 134 | IPV4_INIT |
| 135 | IPV4_CORE |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 136 | } else if (family == AF_INET6) { |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 137 | IPV6_INIT |
| 138 | IPV6_CORE |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 139 | } |
| 140 | // else drop |
| 141 | |
| 142 | return 0; |
| 143 | } |
Xiaozhou Liu | 9cede20 | 2019-11-09 08:34:45 +0800 | [diff] [blame] | 144 | """ |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 145 | |
Xiaozhou Liu | 9cede20 | 2019-11-09 08:34:45 +0800 | [diff] [blame] | 146 | bpf_text_kprobe_retransmit = """ |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 147 | int trace_retransmit(struct pt_regs *ctx, struct sock *sk, struct sk_buff *skb) |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 148 | { |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 149 | trace_event(ctx, sk, skb, RETRANSMIT); |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 150 | return 0; |
| 151 | } |
Xiaozhou Liu | 9cede20 | 2019-11-09 08:34:45 +0800 | [diff] [blame] | 152 | """ |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 153 | |
Xiaozhou Liu | 9cede20 | 2019-11-09 08:34:45 +0800 | [diff] [blame] | 154 | bpf_text_kprobe_tlp = """ |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 155 | int trace_tlp(struct pt_regs *ctx, struct sock *sk) |
| 156 | { |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 157 | trace_event(ctx, sk, NULL, TLP); |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 158 | return 0; |
| 159 | } |
| 160 | """ |
| 161 | |
Xiaozhou Liu | 9cede20 | 2019-11-09 08:34:45 +0800 | [diff] [blame] | 162 | bpf_text_tracepoint = """ |
| 163 | TRACEPOINT_PROBE(tcp, tcp_retransmit_skb) |
| 164 | { |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 165 | struct tcp_skb_cb *tcb; |
| 166 | u32 seq; |
| 167 | |
Xiaozhou Liu | 9cede20 | 2019-11-09 08:34:45 +0800 | [diff] [blame] | 168 | u32 pid = bpf_get_current_pid_tgid() >> 32; |
| 169 | const struct sock *skp = (const struct sock *)args->skaddr; |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 170 | const struct sk_buff *skb = (const struct sk_buff *)args->skbaddr; |
Xiaozhou Liu | 9cede20 | 2019-11-09 08:34:45 +0800 | [diff] [blame] | 171 | u16 lport = args->sport; |
| 172 | u16 dport = args->dport; |
| 173 | char state = skp->__sk_common.skc_state; |
| 174 | u16 family = skp->__sk_common.skc_family; |
| 175 | |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 176 | seq = 0; |
| 177 | if (skb) { |
| 178 | /* macro TCP_SKB_CB from net/tcp.h */ |
| 179 | tcb = ((struct tcp_skb_cb *)&((skb)->cb[0])); |
| 180 | seq = tcb->seq; |
| 181 | } |
| 182 | |
| 183 | FILTER_FAMILY |
| 184 | |
Xiaozhou Liu | 9cede20 | 2019-11-09 08:34:45 +0800 | [diff] [blame] | 185 | if (family == AF_INET) { |
| 186 | IPV4_CODE |
| 187 | } else if (family == AF_INET6) { |
| 188 | IPV6_CODE |
| 189 | } |
| 190 | return 0; |
| 191 | } |
| 192 | """ |
| 193 | |
Javier Honduvilla Coto | 64bf965 | 2018-08-01 06:50:19 +0200 | [diff] [blame] | 194 | struct_init = { 'ipv4': |
| 195 | { 'count' : |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 196 | """ |
| 197 | struct ipv4_flow_key_t flow_key = {}; |
| 198 | flow_key.saddr = skp->__sk_common.skc_rcv_saddr; |
| 199 | flow_key.daddr = skp->__sk_common.skc_daddr; |
| 200 | // lport is host order |
| 201 | flow_key.lport = lport; |
| 202 | flow_key.dport = ntohs(dport);""", |
Javier Honduvilla Coto | 64bf965 | 2018-08-01 06:50:19 +0200 | [diff] [blame] | 203 | 'trace' : |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 204 | """ |
Joe Yin | 36ce112 | 2018-08-17 06:04:00 +0800 | [diff] [blame] | 205 | struct ipv4_data_t data4 = {}; |
| 206 | data4.pid = pid; |
| 207 | data4.ip = 4; |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 208 | data4.seq = seq; |
Joe Yin | 36ce112 | 2018-08-17 06:04:00 +0800 | [diff] [blame] | 209 | data4.type = type; |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 210 | data4.saddr = skp->__sk_common.skc_rcv_saddr; |
| 211 | data4.daddr = skp->__sk_common.skc_daddr; |
| 212 | // lport is host order |
| 213 | data4.lport = lport; |
| 214 | data4.dport = ntohs(dport); |
| 215 | data4.state = state; """ |
| 216 | }, |
Javier Honduvilla Coto | 64bf965 | 2018-08-01 06:50:19 +0200 | [diff] [blame] | 217 | 'ipv6': |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 218 | { 'count' : |
| 219 | """ |
| 220 | struct ipv6_flow_key_t flow_key = {}; |
Sumanth Korikkar | 7f6066d | 2020-05-20 10:49:56 -0500 | [diff] [blame] | 221 | bpf_probe_read_kernel(&flow_key.saddr, sizeof(flow_key.saddr), |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 222 | skp->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32); |
Sumanth Korikkar | 7f6066d | 2020-05-20 10:49:56 -0500 | [diff] [blame] | 223 | bpf_probe_read_kernel(&flow_key.daddr, sizeof(flow_key.daddr), |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 224 | skp->__sk_common.skc_v6_daddr.in6_u.u6_addr32); |
| 225 | // lport is host order |
| 226 | flow_key.lport = lport; |
| 227 | flow_key.dport = ntohs(dport);""", |
| 228 | 'trace' : """ |
Marko Myllynen | bfbf17e | 2018-09-11 21:49:58 +0300 | [diff] [blame] | 229 | struct ipv6_data_t data6 = {}; |
| 230 | data6.pid = pid; |
| 231 | data6.ip = 6; |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 232 | data6.seq = seq; |
Marko Myllynen | bfbf17e | 2018-09-11 21:49:58 +0300 | [diff] [blame] | 233 | data6.type = type; |
Sumanth Korikkar | 7f6066d | 2020-05-20 10:49:56 -0500 | [diff] [blame] | 234 | bpf_probe_read_kernel(&data6.saddr, sizeof(data6.saddr), |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 235 | skp->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32); |
Sumanth Korikkar | 7f6066d | 2020-05-20 10:49:56 -0500 | [diff] [blame] | 236 | bpf_probe_read_kernel(&data6.daddr, sizeof(data6.daddr), |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 237 | skp->__sk_common.skc_v6_daddr.in6_u.u6_addr32); |
| 238 | // lport is host order |
| 239 | data6.lport = lport; |
| 240 | data6.dport = ntohs(dport); |
| 241 | data6.state = state;""" |
| 242 | } |
| 243 | } |
| 244 | |
Xiaozhou Liu | 9cede20 | 2019-11-09 08:34:45 +0800 | [diff] [blame] | 245 | struct_init_tracepoint = { 'ipv4': |
| 246 | { 'count' : """ |
| 247 | struct ipv4_flow_key_t flow_key = {}; |
| 248 | __builtin_memcpy(&flow_key.saddr, args->saddr, sizeof(flow_key.saddr)); |
| 249 | __builtin_memcpy(&flow_key.daddr, args->daddr, sizeof(flow_key.daddr)); |
| 250 | flow_key.lport = lport; |
| 251 | flow_key.dport = dport; |
| 252 | ipv4_count.increment(flow_key); |
| 253 | """, |
| 254 | 'trace' : """ |
| 255 | struct ipv4_data_t data4 = {}; |
| 256 | data4.pid = pid; |
| 257 | data4.lport = lport; |
| 258 | data4.dport = dport; |
| 259 | data4.type = RETRANSMIT; |
| 260 | data4.ip = 4; |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 261 | data4.seq = seq; |
Xiaozhou Liu | 9cede20 | 2019-11-09 08:34:45 +0800 | [diff] [blame] | 262 | data4.state = state; |
| 263 | __builtin_memcpy(&data4.saddr, args->saddr, sizeof(data4.saddr)); |
| 264 | __builtin_memcpy(&data4.daddr, args->daddr, sizeof(data4.daddr)); |
| 265 | ipv4_events.perf_submit(args, &data4, sizeof(data4)); |
| 266 | """ |
| 267 | }, |
| 268 | 'ipv6': |
| 269 | { 'count' : """ |
| 270 | struct ipv6_flow_key_t flow_key = {}; |
| 271 | __builtin_memcpy(&flow_key.saddr, args->saddr_v6, sizeof(flow_key.saddr)); |
| 272 | __builtin_memcpy(&flow_key.daddr, args->daddr_v6, sizeof(flow_key.daddr)); |
| 273 | flow_key.lport = lport; |
| 274 | flow_key.dport = dport; |
| 275 | ipv6_count.increment(flow_key); |
| 276 | """, |
| 277 | 'trace' : """ |
| 278 | struct ipv6_data_t data6 = {}; |
| 279 | data6.pid = pid; |
| 280 | data6.lport = lport; |
| 281 | data6.dport = dport; |
| 282 | data6.type = RETRANSMIT; |
| 283 | data6.ip = 6; |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 284 | data6.seq = seq; |
Xiaozhou Liu | 9cede20 | 2019-11-09 08:34:45 +0800 | [diff] [blame] | 285 | data6.state = state; |
| 286 | __builtin_memcpy(&data6.saddr, args->saddr_v6, sizeof(data6.saddr)); |
| 287 | __builtin_memcpy(&data6.daddr, args->daddr_v6, sizeof(data6.daddr)); |
| 288 | ipv6_events.perf_submit(args, &data6, sizeof(data6)); |
| 289 | """ |
| 290 | } |
| 291 | } |
| 292 | |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 293 | count_core_base = """ |
Javier Honduvilla Coto | 64bf965 | 2018-08-01 06:50:19 +0200 | [diff] [blame] | 294 | COUNT_STRUCT.increment(flow_key); |
| 295 | """ |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 296 | |
Xiaozhou Liu | 9cede20 | 2019-11-09 08:34:45 +0800 | [diff] [blame] | 297 | if BPF.tracepoint_exists("tcp", "tcp_retransmit_skb"): |
| 298 | if args.count: |
| 299 | bpf_text_tracepoint = bpf_text_tracepoint.replace("IPV4_CODE", struct_init_tracepoint['ipv4']['count']) |
| 300 | bpf_text_tracepoint = bpf_text_tracepoint.replace("IPV6_CODE", struct_init_tracepoint['ipv6']['count']) |
| 301 | else: |
| 302 | bpf_text_tracepoint = bpf_text_tracepoint.replace("IPV4_CODE", struct_init_tracepoint['ipv4']['trace']) |
| 303 | bpf_text_tracepoint = bpf_text_tracepoint.replace("IPV6_CODE", struct_init_tracepoint['ipv6']['trace']) |
| 304 | bpf_text += bpf_text_tracepoint |
| 305 | |
| 306 | if args.lossprobe or not BPF.tracepoint_exists("tcp", "tcp_retransmit_skb"): |
| 307 | bpf_text += bpf_text_kprobe |
| 308 | if args.count: |
| 309 | bpf_text = bpf_text.replace("IPV4_INIT", struct_init['ipv4']['count']) |
| 310 | bpf_text = bpf_text.replace("IPV6_INIT", struct_init['ipv6']['count']) |
| 311 | bpf_text = bpf_text.replace("IPV4_CORE", count_core_base.replace("COUNT_STRUCT", 'ipv4_count')) |
| 312 | bpf_text = bpf_text.replace("IPV6_CORE", count_core_base.replace("COUNT_STRUCT", 'ipv6_count')) |
| 313 | else: |
| 314 | bpf_text = bpf_text.replace("IPV4_INIT", struct_init['ipv4']['trace']) |
| 315 | bpf_text = bpf_text.replace("IPV6_INIT", struct_init['ipv6']['trace']) |
| 316 | bpf_text = bpf_text.replace("IPV4_CORE", "ipv4_events.perf_submit(ctx, &data4, sizeof(data4));") |
| 317 | bpf_text = bpf_text.replace("IPV6_CORE", "ipv6_events.perf_submit(ctx, &data6, sizeof(data6));") |
| 318 | if args.lossprobe: |
| 319 | bpf_text += bpf_text_kprobe_tlp |
| 320 | if not BPF.tracepoint_exists("tcp", "tcp_retransmit_skb"): |
| 321 | bpf_text += bpf_text_kprobe_retransmit |
Hariharan Ananthakrishnan | 04893e3 | 2021-08-12 05:55:21 -0700 | [diff] [blame] | 322 | if args.ipv4: |
| 323 | bpf_text = bpf_text.replace('FILTER_FAMILY', |
| 324 | 'if (family != AF_INET) { return 0; }') |
| 325 | elif args.ipv6: |
| 326 | bpf_text = bpf_text.replace('FILTER_FAMILY', |
| 327 | 'if (family != AF_INET6) { return 0; }') |
| 328 | else: |
| 329 | bpf_text = bpf_text.replace('FILTER_FAMILY', '') |
Nathan Scott | cf0792f | 2018-02-02 16:56:50 +1100 | [diff] [blame] | 330 | if debug or args.ebpf: |
Brendan Gregg | 73b5401 | 2017-12-18 20:37:11 -0800 | [diff] [blame] | 331 | print(bpf_text) |
Nathan Scott | cf0792f | 2018-02-02 16:56:50 +1100 | [diff] [blame] | 332 | if args.ebpf: |
| 333 | exit() |
Brendan Gregg | 73b5401 | 2017-12-18 20:37:11 -0800 | [diff] [blame] | 334 | |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 335 | # from bpf_text: |
| 336 | type = {} |
| 337 | type[1] = 'R' |
| 338 | type[2] = 'L' |
| 339 | |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 340 | # from include/net/tcp_states.h: |
| 341 | tcpstate = {} |
| 342 | tcpstate[1] = 'ESTABLISHED' |
| 343 | tcpstate[2] = 'SYN_SENT' |
| 344 | tcpstate[3] = 'SYN_RECV' |
| 345 | tcpstate[4] = 'FIN_WAIT1' |
| 346 | tcpstate[5] = 'FIN_WAIT2' |
| 347 | tcpstate[6] = 'TIME_WAIT' |
| 348 | tcpstate[7] = 'CLOSE' |
| 349 | tcpstate[8] = 'CLOSE_WAIT' |
| 350 | tcpstate[9] = 'LAST_ACK' |
| 351 | tcpstate[10] = 'LISTEN' |
| 352 | tcpstate[11] = 'CLOSING' |
| 353 | tcpstate[12] = 'NEW_SYN_RECV' |
| 354 | |
| 355 | # process event |
| 356 | def print_ipv4_event(cpu, data, size): |
Xiaozhou Liu | 51d62d3 | 2019-02-15 13:03:05 +0800 | [diff] [blame] | 357 | event = b["ipv4_events"].event(data) |
xingfeng2510 | 03e4948 | 2022-03-17 13:07:16 +0800 | [diff] [blame] | 358 | print("%-8s %-7d %-2d %-20s %1s> %-20s" % ( |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 359 | strftime("%H:%M:%S"), event.pid, event.ip, |
Mark Drayton | 11de298 | 2016-06-26 21:14:44 +0100 | [diff] [blame] | 360 | "%s:%d" % (inet_ntop(AF_INET, pack('I', event.saddr)), event.lport), |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 361 | type[event.type], |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 362 | "%s:%s" % (inet_ntop(AF_INET, pack('I', event.daddr)), event.dport)), |
| 363 | end='') |
| 364 | if args.sequence: |
| 365 | print(" %-12s %s" % (tcpstate[event.state], event.seq)) |
| 366 | else: |
| 367 | print(" %s" % (tcpstate[event.state])) |
Mark Drayton | 11de298 | 2016-06-26 21:14:44 +0100 | [diff] [blame] | 368 | |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 369 | def print_ipv6_event(cpu, data, size): |
Xiaozhou Liu | 51d62d3 | 2019-02-15 13:03:05 +0800 | [diff] [blame] | 370 | event = b["ipv6_events"].event(data) |
xingfeng2510 | 03e4948 | 2022-03-17 13:07:16 +0800 | [diff] [blame] | 371 | print("%-8s %-7d %-2d %-20s %1s> %-20s" % ( |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 372 | strftime("%H:%M:%S"), event.pid, event.ip, |
Mark Drayton | 11de298 | 2016-06-26 21:14:44 +0100 | [diff] [blame] | 373 | "%s:%d" % (inet_ntop(AF_INET6, event.saddr), event.lport), |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 374 | type[event.type], |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 375 | "%s:%d" % (inet_ntop(AF_INET6, event.daddr), event.dport)), |
| 376 | end='') |
| 377 | if args.sequence: |
| 378 | print(" %-12s %s" % (tcpstate[event.state], event.seq)) |
| 379 | else: |
| 380 | print(" %s" % (tcpstate[event.state])) |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 381 | |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 382 | def depict_cnt(counts_tab, l3prot='ipv4'): |
| 383 | for k, v in sorted(counts_tab.items(), key=lambda counts: counts[1].value): |
| 384 | depict_key = "" |
| 385 | ep_fmt = "[%s]#%d" |
| 386 | if l3prot == 'ipv4': |
| 387 | depict_key = "%-20s <-> %-20s" % (ep_fmt % (inet_ntop(AF_INET, pack('I', k.saddr)), k.lport), |
Javier Honduvilla Coto | 64bf965 | 2018-08-01 06:50:19 +0200 | [diff] [blame] | 388 | ep_fmt % (inet_ntop(AF_INET, pack('I', k.daddr)), k.dport)) |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 389 | else: |
| 390 | depict_key = "%-20s <-> %-20s" % (ep_fmt % (inet_ntop(AF_INET6, k.saddr), k.lport), |
| 391 | ep_fmt % (inet_ntop(AF_INET6, k.daddr), k.dport)) |
| 392 | |
| 393 | print ("%s %10d" % (depict_key, v.value)) |
| 394 | |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 395 | # initialize BPF |
| 396 | b = BPF(text=bpf_text) |
Xiaozhou Liu | 9cede20 | 2019-11-09 08:34:45 +0800 | [diff] [blame] | 397 | if not BPF.tracepoint_exists("tcp", "tcp_retransmit_skb"): |
| 398 | b.attach_kprobe(event="tcp_retransmit_skb", fn_name="trace_retransmit") |
Mark Drayton | 11de298 | 2016-06-26 21:14:44 +0100 | [diff] [blame] | 399 | if args.lossprobe: |
| 400 | b.attach_kprobe(event="tcp_send_loss_probe", fn_name="trace_tlp") |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 401 | |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 402 | print("Tracing retransmits ... Hit Ctrl-C to end") |
| 403 | if args.count: |
| 404 | try: |
| 405 | while 1: |
| 406 | sleep(99999999) |
| 407 | except BaseException: |
| 408 | pass |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 409 | |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 410 | # header |
| 411 | print("\n%-25s %-25s %-10s" % ( |
| 412 | "LADDR:LPORT", "RADDR:RPORT", "RETRANSMITS")) |
Javier Honduvilla Coto | 64bf965 | 2018-08-01 06:50:19 +0200 | [diff] [blame] | 413 | depict_cnt(b.get_table("ipv4_count")) |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 414 | depict_cnt(b.get_table("ipv6_count"), l3prot='ipv6') |
Brendan Gregg | 553f2aa | 2016-02-14 18:15:24 -0800 | [diff] [blame] | 415 | # read events |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 416 | else: |
| 417 | # header |
xingfeng2510 | 03e4948 | 2022-03-17 13:07:16 +0800 | [diff] [blame] | 418 | print("%-8s %-7s %-2s %-20s %1s> %-20s" % ("TIME", "PID", "IP", |
Michael Gugino | 7abd77a | 2021-09-01 18:07:33 -0400 | [diff] [blame] | 419 | "LADDR:LPORT", "T", "RADDR:RPORT"), end='') |
| 420 | if args.sequence: |
| 421 | print(" %-12s %-10s" % ("STATE", "SEQ")) |
| 422 | else: |
| 423 | print(" %-4s" % ("STATE")) |
Matthias Tafelmeier | 1e9467f | 2017-12-13 18:50:22 +0100 | [diff] [blame] | 424 | b["ipv4_events"].open_perf_buffer(print_ipv4_event) |
| 425 | b["ipv6_events"].open_perf_buffer(print_ipv6_event) |
| 426 | while 1: |
Jerome Marchand | 5167127 | 2018-12-19 01:57:24 +0100 | [diff] [blame] | 427 | try: |
| 428 | b.perf_buffer_poll() |
| 429 | except KeyboardInterrupt: |
| 430 | exit() |