.SH NAME
tcpaccept \- Trace TCP passive connections (accept()). Uses Linux eBPF/bcc.
.SH SYNOPSIS
-.B tcpaccept [\-h] [\-T] [\-t] [\-p PID] [\-P PORTS] [\-\-cgroupmap MAPPATH] [\-\-mntnsmap MAPPATH]
+.B tcpaccept [\-h] [\-T] [\-t] [\-p PID] [\-P PORTS] [\-4 | \-6] [\-\-cgroupmap MAPPATH] [\-\-mntnsmap MAPPATH]
.SH DESCRIPTION
This tool traces passive TCP connections (eg, via an accept() syscall;
connect() are active connections). This can be useful for general
\-P PORTS
Comma-separated list of local ports to trace (filtered in-kernel).
.TP
+\-4
+Trace IPv4 family only.
+.TP
+\-6
+Trace IPv6 family only.
+.TP
\-\-cgroupmap MAPPATH
Trace cgroups in this BPF map only (filtered in-kernel).
.TP
#
.B tcpaccept \-p 181
.TP
+Trace IPv4 family only:
+#
+.B tcpaccept \-4
+.TP
+Trace IPv6 family only:
+#
+.B tcpaccept \-6
+.TP
Trace a set of cgroups only (see special_filtering.md from bcc sources for more details):
#
.B tcpaccept \-\-cgroupmap /sys/fs/bpf/test01
.SH NAME
tcpconnect \- Trace TCP active connections (connect()). Uses Linux eBPF/bcc.
.SH SYNOPSIS
-.B tcpconnect [\-h] [\-c] [\-t] [\-p PID] [-P PORT] [\-L] [-u UID] [-U] [\-\-cgroupmap MAPPATH] [\-\-mntnsmap MAPPATH] [\-d]
+.B tcpconnect [\-h] [\-c] [\-t] [\-p PID] [-P PORT] [\-4 | \-6] [\-L] [-u UID] [-U] [\-\-cgroupmap MAPPATH] [\-\-mntnsmap MAPPATH] [\-d]
.SH DESCRIPTION
This tool traces active TCP connections (eg, via a connect() syscall;
accept() are passive connections). This can be useful for general
\-P PORT
Comma-separated list of destination ports to trace (filtered in-kernel).
.TP
+\-4
+Trace IPv4 family only.
+.TP
+\-6
+Trace IPv6 family only.
+.TP
\-L
Include a LPORT column.
.TP
#
.B tcpconnect \-P 80,81
.TP
+Trace IPv4 family only:
+#
+.B tcpconnect -4
+.TP
+Trace IPv6 family only:
+#
+.B tcpconnect -6
+.TP
Trace all TCP connects, and include LPORT:
#
.B tcpconnect \-L
.SH NAME
tcpconnlat \- Trace TCP active connection latency. Uses Linux eBPF/bcc.
.SH SYNOPSIS
-.B tcpconnlat [\-h] [\-t] [\-p PID] [\-L] [-v] [min_ms]
+.B tcpconnlat [\-h] [\-t] [\-p PID] [\-L] [\-4 | \-6] [-v] [min_ms]
.SH DESCRIPTION
This tool traces active TCP connections
(eg, via a connect() syscall), and shows the latency (time) for the connection
\-L
Include a LPORT column.
.TP
+\-4
+Trace IPv4 family only.
+.TP
+\-6
+Trace IPv6 family only.
+.TP
\-v
Print the resulting BPF program, for debugging purposes.
.TP
#
.B tcpconnlat \-L
.TP
+Trace IPv4 family only:
+#
+.B tcpconnlat \-4
+.TP
+Trace IPv6 family only:
+#
+.B tcpconnlat \-6
+.TP
Trace connects with latency longer than 10 ms:
#
.B tcpconnlat 10
.SH NAME
tcpdrop \- Trace kernel-based TCP packet drops with details. Uses Linux eBPF/bcc.
.SH SYNOPSIS
-.B tcpdrop [\-h]
+.B tcpdrop [\-4 | \-6] [\-h]
.SH DESCRIPTION
This tool traces TCP packets or segments that were dropped by the kernel, and
shows details from the IP and TCP headers, the socket state, and the
CONFIG_BPF and bcc.
.SH OPTIONS
.TP
+\-4
+Trace IPv4 family only.
+.TP
+\-6
+Trace IPv6 family only.
+.TP
\-h
Print usage message.
+.SH EXAMPLES
+.TP
+Trace kernel-based TCP packet drops with details:
+#
.B tcpdrop
+.TP
+Trace IPv4 family only:
+#
+.B tcpdrop \-4
+.TP
+Trace IPv6 family only:
+#
+.B tcpdrop \-6
.SH FIELDS
.TP
TIME
.SH NAME
tcplife \- Trace TCP sessions and summarize lifespan. Uses Linux eBPF/bcc.
.SH SYNOPSIS
-.B tcplife [\-h] [\-T] [\-t] [\-w] [\-s] [\-p PID] [\-D PORTS] [\-L PORTS]
+.B tcplife [\-h] [\-T] [\-t] [\-w] [\-s] [\-p PID] [\-D PORTS] [\-L PORTS] [\-4 | \-6]
.SH DESCRIPTION
This tool traces TCP sessions that open and close while tracing, and prints
a line of output to summarize each one. This includes the IP addresses, ports,
.TP
\-D PORTS
Comma-separated list of destination ports to trace (filtered in-kernel).
+.TP
+\-4
+Trace IPv4 family only.
+.TP
+\-6
+Trace IPv6 family only.
.SH EXAMPLES
.TP
Trace all TCP sessions, and summarize lifespan and throughput:
Trace connections to remote port 80 only:
#
.B tcplife \-D 80
+.TP
+Trace IPv4 family only:
+#
+.B tcplife \-4
+.TP
+Trace IPv6 family only:
+#
+.B tcplife \-6
.SH FIELDS
.TP
TIME
.SH NAME
tcpretrans \- Trace or count TCP retransmits and TLPs. Uses Linux eBPF/bcc.
.SH SYNOPSIS
-.B tcpretrans [\-h] [\-l] [\-c]
+.B tcpretrans [\-h] [\-l] [\-c] [\-4 | \-6]
.SH DESCRIPTION
This traces TCP retransmits, showing address, port, and TCP state information,
and sometimes the PID (although usually not, since retransmits are usually
complete the TLP send).
.TP
\-c
-Count occurring retransmits per flow.
+Count occurring retransmits per flow.
+.TP
+\-4
+Trace IPv4 family only.
+.TP
+\-6
+Trace IPv6 family only.
.SH EXAMPLES
.TP
Trace TCP retransmits:
Trace TCP retransmits and TLP attempts:
#
.B tcpretrans \-l
+.TP
+Trace IPv4 family only:
+#
+.B tcpretrans \-4
+.TP
+Trace IPv6 family only:
+#
+.B tcpretrans \-6
.SH FIELDS
.TP
TIME
.SH NAME
tcprtt \- Trace TCP RTT of established connections. Uses Linux eBPF/bcc.
.SH SYNOPSIS
-.B tcprtt [\-h] [\-T] [\-D] [\-m] [\-i INTERVAL] [\-d DURATION] [\-b] [\-B] [\-e]
+.B tcprtt [\-h] [\-T] [\-D] [\-m] [\-i INTERVAL] [\-d DURATION] [\-b] [\-B] [\-e] [\-4 | \-6]
.SH DESCRIPTION
This tool traces established connections RTT(round-trip time) to analyze the
quality of network. This can be useful for general troubleshooting to
.TP
\-e
Show extension summary(average).
+.TP
+\-4
+Trace IPv4 family only.
+.TP
+\-6
+Trace IPv6 family only.
.SH EXAMPLES
.TP
Trace TCP RTT and print 1 second summaries, 10 times:
Trace local port and show a breakdown of remote hosts RTT:
#
.B tcprtt \-i 3 --lport 80 --byraddr
+.TP
+Trace IPv4 family only:
+#
+.B tcprtt \-4
+.TP
+Trace IPv6 family only:
+#
+.B tcprtt \-6
.SH OVERHEAD
This traces the kernel tcp_rcv_established function and collects TCP RTT. The
rate of this depends on your server application. If it is a web or proxy server
.SH NAME
tcpstates \- Trace TCP session state changes with durations. Uses Linux eBPF/bcc.
.SH SYNOPSIS
-.B tcpstates [\-h] [\-T] [\-t] [\-w] [\-s] [\-D PORTS] [\-L PORTS] [\-Y]
+.B tcpstates [\-h] [\-T] [\-t] [\-w] [\-s] [\-D PORTS] [\-L PORTS] [\-Y] [\-4 | \-6]
.SH DESCRIPTION
This tool traces TCP session state changes while tracing, and prints details
including the duration in each state. This can help explain the latency of
.TP
\-Y
Log session state changes to the systemd journal.
+.TP
+\-4
+Trace IPv4 family only.
+.TP
+\-6
+Trace IPv6 family only.
.SH EXAMPLES
.TP
Trace all TCP sessions, and show all state changes:
Trace connections to remote port 80 only:
#
.B tcpstates \-D 80
+.TP
+Trace IPv4 family only:
+#
+.B tcpstates -4
+.TP
+Trace IPv6 family only:
+#
+.B tcpstates -6
.SH FIELDS
.TP
TIME
.SH NAME
tcpsynbl \- Show the TCP SYN backlog as a histogram. Uses BCC/eBPF.
.SH SYNOPSIS
-.B tcpsynbl
+.B tcpsynbl [\-4 | \-6]
.SH DESCRIPTION
This tool shows the TCP SYN backlog size during SYN arrival as a histogram.
This lets you see how close your applications are to hitting the backlog limit
Since this uses BPF, only the root user can use this tool.
.SH REQUIREMENTS
CONFIG_BPF and BCC.
+.SH OPTIONS
+.TP
+\-h
+Print usage message.
+.TP
+\-4
+Trace IPv4 family only.
+.TP
+\-6
+Trace IPv6 family only.
.SH EXAMPLES
.TP
Show the TCP SYN backlog as a histogram.
#
.B tcpsynbl
+.TP
+Trace IPv4 family only:
+#
+.B tcpsynbl -4
+.TP
+Trace IPv6 family only:
+#
+.B tcpsynbl -6
.SH FIELDS
.TP
backlog
tcptop \- Summarize TCP send/recv throughput by host. Top for TCP.
.SH SYNOPSIS
.B tcptop [\-h] [\-C] [\-S] [\-p PID] [\-\-cgroupmap MAPPATH]
- [--mntnsmap MAPPATH] [interval] [count]
+ [--mntnsmap MAPPATH] [interval] [count] [\-4 | \-6]
.SH DESCRIPTION
This is top for TCP sessions.
.TP
count
Number of interval summaries (default is many).
+.TP
+\-4
+Trace IPv4 family only.
+.TP
+\-6
+Trace IPv6 family only.
.SH EXAMPLES
.TP
Summarize TCP throughput by active sessions, 1 second refresh:
Trace a set of cgroups only (see special_filtering.md from bcc sources for more details):
#
.B tcptop \-\-cgroupmap /sys/fs/bpf/test01
+.TP
+Trace IPv4 family only:
+#
+.B tcptop \-4
+.TP
+Trace IPv6 family only:
+#
+.B tcptop \-6
.SH FIELDS
.TP
loadavg:
.SH NAME
tcptracer \- Trace TCP established connections. Uses Linux eBPF/bcc.
.SH SYNOPSIS
-.B tcptracer [\-h] [\-v] [\-p PID] [\-N NETNS] [\-\-cgroupmap MAPPATH] [--mntnsmap MAPPATH]
+.B tcptracer [\-h] [\-v] [\-p PID] [\-N NETNS] [\-\-cgroupmap MAPPATH] [--mntnsmap MAPPATH] [\-4 | \-6]
.SH DESCRIPTION
This tool traces established TCP connections that open and close while tracing,
and prints a line of output per connect, accept and close events. This includes
.TP
\-\-mntnsmap MAPPATH
Trace mount namespaces in the map (filtered in-kernel).
+.TP
+\-4
+Trace IPv4 family only.
+.TP
+\-6
+Trace IPv6 family only.
.SH EXAMPLES
.TP
Trace all TCP established connections:
Trace a set of cgroups only (see special_filtering.md from bcc sources for more details):
#
.B tcptracer \-\-cgroupmap /sys/fs/bpf/test01
+.TP
+Trace IPv4 family only:
+#
+.B tcptracer -4
+.TP
+Trace IPv6 family only:
+#
+.B tcptracer -6
.SH FIELDS
.TP
TYPE
# tcpaccept Trace TCP accept()s.
# For Linux, uses BCC, eBPF. Embedded C.
#
-# USAGE: tcpaccept [-h] [-T] [-t] [-p PID] [-P PORTS]
+# USAGE: tcpaccept [-h] [-T] [-t] [-p PID] [-P PORTS] [-4 | -6]
#
# This uses dynamic tracing of the kernel inet_csk_accept() socket function
# (from tcp_prot.accept), and will need to be modified to match kernel changes.
./tcpaccept -p 181 # only trace PID 181
./tcpaccept --cgroupmap mappath # only trace cgroups in this BPF map
./tcpaccept --mntnsmap mappath # only trace mount namespaces in the map
+ ./tcpaccept -4 # trace IPv4 family
+ ./tcpaccept -6 # trace IPv6 family
"""
parser = argparse.ArgumentParser(
description="Trace TCP accepts",
help="trace this PID only")
parser.add_argument("-P", "--port",
help="comma-separated list of local ports to trace")
+group = parser.add_mutually_exclusive_group()
+group.add_argument("-4", "--ipv4", action="store_true",
+ help="trace IPv4 family only")
+group.add_argument("-6", "--ipv6", action="store_true",
+ help="trace IPv6 family only")
parser.add_argument("--cgroupmap",
help="trace cgroups in this BPF map only")
parser.add_argument("--mntnsmap",
dport = newsk->__sk_common.skc_dport;
dport = ntohs(dport);
+ ##FILTER_FAMILY##
+
##FILTER_PORT##
if (family == AF_INET) {
lports_if = ' && '.join(['lport != %d' % lport for lport in lports])
bpf_text = bpf_text.replace('##FILTER_PORT##',
'if (%s) { return 0; }' % lports_if)
+if args.ipv4:
+ bpf_text = bpf_text.replace('##FILTER_FAMILY##',
+ 'if (family != AF_INET) { return 0; }')
+elif args.ipv6:
+ bpf_text = bpf_text.replace('##FILTER_FAMILY##',
+ 'if (family != AF_INET6) { return 0; }')
+
bpf_text = filter_by_containers(args) + bpf_text
if debug or args.ebpf:
print(bpf_text)
exit()
bpf_text = bpf_text.replace('##FILTER_PORT##', '')
+bpf_text = bpf_text.replace('##FILTER_FAMILY##', '')
# process event
def print_ipv4_event(cpu, data, size):
USAGE message:
# ./tcpaccept -h
-usage: tcpaccept.py [-h] [-T] [-t] [-p PID] [-P PORT] [--cgroupmap CGROUPMAP]
+usage: tcpaccept.py [-h] [-T] [-t] [-p PID] [-P PORT] [-4 | -6] [--cgroupmap CGROUPMAP]
Trace TCP accepts
-t, --timestamp include timestamp on output
-p PID, --pid PID trace this PID only
-P PORT, --port PORT comma-separated list of local ports to trace
+ -4, --ipv4 trace IPv4 family only
+ -6, --ipv6 trace IPv6 family only
--cgroupmap CGROUPMAP
trace cgroups in this BPF map only
./tcpaccept -P 80,81 # only trace port 80 and 81
./tcpaccept -p 181 # only trace PID 181
./tcpaccept --cgroupmap mappath # only trace cgroups in this BPF map
- ./tcpaccept --mntnsmap mappath # only trace mount namespaces in the map
\ No newline at end of file
+ ./tcpaccept --mntnsmap mappath # only trace mount namespaces in the map
+ ./tcpaccept -4 # trace IPv4 family only
+ ./tcpaccept -6 # trace IPv6 family only
\ No newline at end of file
# tcpconnect Trace TCP connect()s.
# For Linux, uses BCC, eBPF. Embedded C.
#
-# USAGE: tcpconnect [-h] [-c] [-t] [-p PID] [-P PORT [PORT ...]]
+# USAGE: tcpconnect [-h] [-c] [-t] [-p PID] [-P PORT [PORT ...]] [-4 | -6]
#
# All connection attempts are traced, even if they ultimately fail.
#
./tcpconnect -p 181 # only trace PID 181
./tcpconnect -P 80 # only trace port 80
./tcpconnect -P 80,81 # only trace port 80 and 81
+ ./tcpconnect -4 # only trace IPv4 family
+ ./tcpconnect -6 # only trace IPv6 family
./tcpconnect -U # include UID
./tcpconnect -u 1000 # only trace UID 1000
./tcpconnect -c # count connects per src ip and dest ip/port
help="trace this PID only")
parser.add_argument("-P", "--port",
help="comma-separated list of destination ports to trace.")
+group = parser.add_mutually_exclusive_group()
+group.add_argument("-4", "--ipv4", action="store_true",
+ help="trace IPv4 family only")
+group.add_argument("-6", "--ipv6", action="store_true",
+ help="trace IPv6 family only")
parser.add_argument("-L", "--lport", action="store_true",
help="include LPORT on output")
parser.add_argument("-U", "--print-uid", action="store_true",
u16 dport = skp->__sk_common.skc_dport;
FILTER_PORT
+
+ FILTER_FAMILY
if (ipver == 4) {
IPV4_CODE
dports_if = ' && '.join(['dport != %d' % ntohs(dport) for dport in dports])
bpf_text = bpf_text.replace('FILTER_PORT',
'if (%s) { currsock.delete(&tid); return 0; }' % dports_if)
+if args.ipv4:
+ bpf_text = bpf_text.replace('FILTER_FAMILY',
+ 'if (ipver != 4) { return 0; }')
+elif args.ipv6:
+ bpf_text = bpf_text.replace('FILTER_FAMILY',
+ 'if (ipver != 6) { return 0; }')
if args.uid:
bpf_text = bpf_text.replace('FILTER_UID',
'if (uid != %s) { return 0; }' % args.uid)
bpf_text = bpf_text.replace('FILTER_PID', '')
bpf_text = bpf_text.replace('FILTER_PORT', '')
+bpf_text = bpf_text.replace('FILTER_FAMILY', '')
bpf_text = bpf_text.replace('FILTER_UID', '')
if args.dns:
# ./tcpconnect -h
-usage: tcpconnect.py [-h] [-t] [-p PID] [-P PORT] [-L] [-U] [-u UID] [-c]
- [--cgroupmap CGROUPMAP] [--mntnsmap MNTNSMAP] [-d]
+usage: tcpconnect.py [-h] [-t] [-p PID] [-P PORT] [-4 | -6] [-L] [-U] [-u UID]
+ [-c] [--cgroupmap CGROUPMAP] [--mntnsmap MNTNSMAP] [-d]
Trace TCP connects
-t, --timestamp include timestamp on output
-p PID, --pid PID trace this PID only
-P PORT, --port PORT comma-separated list of destination ports to trace.
+ -4, --ipv4 trace IPv4 family only
+ -6, --ipv6 trace IPv6 family only
-L, --lport include LPORT on output
-U, --print-uid include UID on output
-u UID, --uid UID trace this UID only
./tcpconnect -p 181 # only trace PID 181
./tcpconnect -P 80 # only trace port 80
./tcpconnect -P 80,81 # only trace port 80 and 81
+ ./tcpconnect -4 # only trace IPv4 family
+ ./tcpconnect -6 # only trace IPv6 family
./tcpconnect -U # include UID
./tcpconnect -u 1000 # only trace UID 1000
./tcpconnect -c # count connects per src ip and dest ip/port
# tcpconnlat Trace TCP active connection latency (connect).
# For Linux, uses BCC, eBPF. Embedded C.
#
-# USAGE: tcpconnlat [-h] [-t] [-p PID]
+# USAGE: tcpconnlat [-h] [-t] [-p PID] [-4 | -6]
#
# This uses dynamic tracing of kernel functions, and will need to be updated
# to match kernel changes.
./tcpconnlat -t # include timestamps
./tcpconnlat -p 181 # only trace PID 181
./tcpconnlat -L # include LPORT while printing outputs
+ ./tcpconnlat -4 # trace IPv4 family only
+ ./tcpconnlat -6 # trace IPv6 family only
"""
parser = argparse.ArgumentParser(
description="Trace TCP connects and show connection latency",
help="trace this PID only")
parser.add_argument("-L", "--lport", action="store_true",
help="include LPORT on output")
+group = parser.add_mutually_exclusive_group()
+group.add_argument("-4", "--ipv4", action="store_true",
+ help="trace IPv4 family only")
+group.add_argument("-6", "--ipv6", action="store_true",
+ help="trace IPv6 family only")
parser.add_argument("duration_ms", nargs="?", default=0,
type=positive_float,
help="minimum duration to trace (ms)")
# initialize BPF
b = BPF(text=bpf_text)
-b.attach_kprobe(event="tcp_v4_connect", fn_name="trace_connect")
-b.attach_kprobe(event="tcp_v6_connect", fn_name="trace_connect")
+if args.ipv4:
+ b.attach_kprobe(event="tcp_v4_connect", fn_name="trace_connect")
+elif args.ipv6:
+ b.attach_kprobe(event="tcp_v6_connect", fn_name="trace_connect")
+else:
+ b.attach_kprobe(event="tcp_v4_connect", fn_name="trace_connect")
+ b.attach_kprobe(event="tcp_v6_connect", fn_name="trace_connect")
+
b.attach_kprobe(event="tcp_rcv_state_process",
fn_name="trace_tcp_rcv_state_process")
"SADDR", "DADDR", "DPORT", "LAT(ms)"))
# read events
-b["ipv4_events"].open_perf_buffer(print_ipv4_event)
-b["ipv6_events"].open_perf_buffer(print_ipv6_event)
+if args.ipv4:
+ b["ipv4_events"].open_perf_buffer(print_ipv4_event)
+elif args.ipv6:
+ b["ipv6_events"].open_perf_buffer(print_ipv6_event)
+else:
+ b["ipv4_events"].open_perf_buffer(print_ipv4_event)
+ b["ipv6_events"].open_perf_buffer(print_ipv6_event)
+
while 1:
try:
b.perf_buffer_poll()
USAGE message:
# ./tcpconnlat -h
-usage: tcpconnlat [-h] [-t] [-p PID] [-L] [-v] [duration_ms]
+usage: tcpconnlat [-h] [-t] [-p PID] [-L] [-4 | -6] [-v] [duration_ms]
Trace TCP connects and show connection latency
-t, --timestamp include timestamp on output
-p PID, --pid PID trace this PID only
-L, --lport include LPORT on output
+ -4, --ipv4 trace IPv4 family only
+ -6 --ipv6 trace IPv6 family only
-v, --verbose print the BPF program for debugging purposes
examples:
./tcpconnlat -t # include timestamps
./tcpconnlat -p 181 # only trace PID 181
./tcpconnlat -L # include LPORT while printing outputs
+ ./tcpconnlat -4 # trace IPv4 family only
+ ./tcpconnlat -6 # trace IPv6 family only
# This provides information such as packet details, socket state, and kernel
# stack trace for packets/segments that were dropped via tcp_drop().
#
-# USAGE: tcpdrop [-h]
+# USAGE: tcpdrop [-4 | -6] [-h]
#
# This uses dynamic tracing of kernel functions, and will need to be updated
# to match kernel changes.
# arguments
examples = """examples:
./tcpdrop # trace kernel TCP drops
+ ./tcpdrop -4 # trace IPv4 family only
+ ./tcpdrop -6 # trace IPv6 family only
"""
parser = argparse.ArgumentParser(
description="Trace TCP drops by the kernel",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=examples)
+group = parser.add_mutually_exclusive_group()
+group.add_argument("-4", "--ipv4", action="store_true",
+ help="trace IPv4 family only")
+group.add_argument("-6", "--ipv6", action="store_true",
+ help="trace IPv6 family only")
parser.add_argument("--ebpf", action="store_true",
help=argparse.SUPPRESS)
args = parser.parse_args()
sport = ntohs(sport);
dport = ntohs(dport);
+ FILTER_FAMILY
+
if (family == AF_INET) {
struct ipv4_data_t data4 = {};
data4.pid = pid;
print(bpf_text)
if args.ebpf:
exit()
+if args.ipv4:
+ bpf_text = bpf_text.replace('FILTER_FAMILY',
+ 'if (family != AF_INET) { return 0; }')
+elif args.ipv6:
+ bpf_text = bpf_text.replace('FILTER_FAMILY',
+ 'if (family != AF_INET6) { return 0; }')
+else:
+ bpf_text = bpf_text.replace('FILTER_FAMILY', '')
# process event
def print_ipv4_event(cpu, data, size):
USAGE:
# ./tcpdrop.py -h
-usage: tcpdrop.py [-h]
+usage: tcpdrop.py [4 | -6] [-h]
Trace TCP drops by the kernel
optional arguments:
+ -4, --ipv4 trace IPv4 family only
+ -6, --ipv6 trace IPv6 family only
-h, --help show this help message and exit
examples:
./tcpdrop # trace kernel TCP drops
+ ./tcpdrop -4 # trace IPv4 family only
+ ./tcpdrop -6 # trace IPv6 family only
# tcplife Trace the lifespan of TCP sessions and summarize.
# For Linux, uses BCC, BPF. Embedded C.
#
-# USAGE: tcplife [-h] [-C] [-S] [-p PID] [interval [count]]
+# USAGE: tcplife [-h] [-C] [-S] [-p PID] [-4 | -6] [interval [count]]
#
# This uses the sock:inet_sock_set_state tracepoint if it exists (added to
# Linux 4.16, and replacing the earlier tcp:tcp_set_state), else it uses
./tcplife -L 80 # only trace local port 80
./tcplife -L 80,81 # only trace local ports 80 and 81
./tcplife -D 80 # only trace remote port 80
+ ./tcplife -4 # only trace IPv4 family
+ ./tcplife -6 # only trace IPv6 family
"""
parser = argparse.ArgumentParser(
description="Trace the lifespan of TCP sessions and summarize",
help="comma-separated list of local ports to trace.")
parser.add_argument("-D", "--remoteport",
help="comma-separated list of remote ports to trace.")
+group = parser.add_mutually_exclusive_group()
+group.add_argument("-4", "--ipv4", action="store_true",
+ help="trace IPv4 family only")
+group.add_argument("-6", "--ipv6", action="store_true",
+ help="trace IPv6 family only")
parser.add_argument("--ebpf", action="store_true",
help=argparse.SUPPRESS)
args = parser.parse_args()
tx_b = tp->bytes_acked;
u16 family = sk->__sk_common.skc_family;
+
+ FILTER_FAMILY
if (family == AF_INET) {
struct ipv4_data_t data4 = {};
if (mep != 0)
pid = mep->pid;
FILTER_PID
+
+ u16 family = args->family;
+ FILTER_FAMILY
// get throughput stats. see tcp_get_info().
u64 rx_b = 0, tx_b = 0, sport = 0;
lports_if = ' && '.join(['lport != %d' % lport for lport in lports])
bpf_text = bpf_text.replace('FILTER_LPORT',
'if (%s) { birth.delete(&sk); return 0; }' % lports_if)
+if args.ipv4:
+ bpf_text = bpf_text.replace('FILTER_FAMILY',
+ 'if (family != AF_INET) { return 0; }')
+elif args.ipv6:
+ bpf_text = bpf_text.replace('FILTER_FAMILY',
+ 'if (family != AF_INET6) { return 0; }')
bpf_text = bpf_text.replace('FILTER_PID', '')
bpf_text = bpf_text.replace('FILTER_DPORT', '')
bpf_text = bpf_text.replace('FILTER_LPORT', '')
+bpf_text = bpf_text.replace('FILTER_FAMILY', '')
if debug or args.ebpf:
print(bpf_text)
# ./tcplife.py -h
usage: tcplife.py [-h] [-T] [-t] [-w] [-s] [-p PID] [-L LOCALPORT]
- [-D REMOTEPORT]
+ [-D REMOTEPORT] [-4 | -6]
Trace the lifespan of TCP sessions and summarize
comma-separated list of local ports to trace.
-D REMOTEPORT, --remoteport REMOTEPORT
comma-separated list of remote ports to trace.
+ -4, --ipv4 trace IPv4 family only
+ -6, --ipv6 trace IPv6 family only
examples:
./tcplife # trace all TCP connect()s
./tcplife -L 80 # only trace local port 80
./tcplife -L 80,81 # only trace local ports 80 and 81
./tcplife -D 80 # only trace remote port 80
+ ./tcplife -4 # only trace IPv4 family
+ ./tcplife -6 # only trace IPv6 family
# tcpretrans Trace or count TCP retransmits and TLPs.
# For Linux, uses BCC, eBPF. Embedded C.
#
-# USAGE: tcpretrans [-c] [-h] [-l]
+# USAGE: tcpretrans [-c] [-h] [-l] [-4 | -6]
#
# This uses dynamic tracing of kernel functions, and will need to be updated
# to match kernel changes.
examples = """examples:
./tcpretrans # trace TCP retransmits
./tcpretrans -l # include TLP attempts
+ ./tcpretrans -4 # trace IPv4 family only
+ ./tcpretrans -6 # trace IPv6 family only
"""
parser = argparse.ArgumentParser(
description="Trace TCP retransmits",
help="include tail loss probe attempts")
parser.add_argument("-c", "--count", action="store_true",
help="count occurred retransmits per flow")
+group = parser.add_mutually_exclusive_group()
+group.add_argument("-4", "--ipv4", action="store_true",
+ help="trace IPv4 family only")
+group.add_argument("-6", "--ipv6", action="store_true",
+ help="trace IPv6 family only")
parser.add_argument("--ebpf", action="store_true",
help=argparse.SUPPRESS)
args = parser.parse_args()
u16 dport = skp->__sk_common.skc_dport;
char state = skp->__sk_common.skc_state;
+ FILTER_FAMILY
+
if (family == AF_INET) {
IPV4_INIT
IPV4_CORE
char state = skp->__sk_common.skc_state;
u16 family = skp->__sk_common.skc_family;
+ FILTER_FAMILY
+
if (family == AF_INET) {
IPV4_CODE
} else if (family == AF_INET6) {
bpf_text += bpf_text_kprobe_tlp
if not BPF.tracepoint_exists("tcp", "tcp_retransmit_skb"):
bpf_text += bpf_text_kprobe_retransmit
-
+if args.ipv4:
+ bpf_text = bpf_text.replace('FILTER_FAMILY',
+ 'if (family != AF_INET) { return 0; }')
+elif args.ipv6:
+ bpf_text = bpf_text.replace('FILTER_FAMILY',
+ 'if (family != AF_INET6) { return 0; }')
+else:
+ bpf_text = bpf_text.replace('FILTER_FAMILY', '')
if debug or args.ebpf:
print(bpf_text)
if args.ebpf:
USAGE message:
# ./tcpretrans -h
-usage: tcpretrans [-h] [-l]
+usage: tcpretrans [-h] [-l] [-4 | -6]
Trace TCP retransmits
-h, --help show this help message and exit
-l, --lossprobe include tail loss probe attempts
-c, --count count occurred retransmits per flow
+ -4, --ipv4 trace IPv4 family only
+ -6, --ipv6 trace IPv6 family only
examples:
./tcpretrans # trace TCP retransmits
./tcpretrans -l # include TLP attempts
+ ./tcpretrans -4 # trace IPv4 family only
+ ./tcpretrans -6 # trace IPv6 family only
#
# USAGE: tcprtt [-h] [-T] [-D] [-m] [-i INTERVAL] [-d DURATION]
# [-p LPORT] [-P RPORT] [-a LADDR] [-A RADDR] [-b] [-B] [-e]
+# [-4 | -6]
#
# Copyright (c) 2020 zhenwei pi
# Licensed under the Apache License, Version 2.0 (the "License")
./tcprtt -B # show sockets histogram by remote address
./tcprtt -D # show debug bpf text
./tcprtt -e # show extension summary(average)
+ ./tcprtt -4 # trace only IPv4 family
+ ./tcprtt -6 # trace only IPv6 family
"""
parser = argparse.ArgumentParser(
description="Summarize TCP RTT as a histogram",
help="show extension summary(average)")
parser.add_argument("-D", "--debug", action="store_true",
help="print BPF program before starting (for debugging purposes)")
+group = parser.add_mutually_exclusive_group()
+group.add_argument("-4", "--ipv4", action="store_true",
+ help="trace IPv4 family only")
+group.add_argument("-6", "--ipv6", action="store_true",
+ help="trace IPv6 family only")
parser.add_argument("--ebpf", action="store_true",
help=argparse.SUPPRESS)
args = parser.parse_args()
u16 dport = 0;
u32 saddr = 0;
u32 daddr = 0;
+ u16 family = 0;
/* for histogram */
sock_key_t key;
bpf_probe_read_kernel(&dport, sizeof(dport), (void *)&inet->inet_dport);
bpf_probe_read_kernel(&saddr, sizeof(saddr), (void *)&inet->inet_saddr);
bpf_probe_read_kernel(&daddr, sizeof(daddr), (void *)&inet->inet_daddr);
+ bpf_probe_read_kernel(&family, sizeof(family), (void *)&sk->__sk_common.skc_family);
LPORTFILTER
RPORTFILTER
LADDRFILTER
RADDRFILTER
+ FAMILYFILTER
FACTOR
return 0;""" % struct.unpack("=I", socket.inet_aton(args.raddr))[0])
else:
bpf_text = bpf_text.replace('RADDRFILTER', '')
-
+if args.ipv4:
+ bpf_text = bpf_text.replace('FAMILYFILTER',
+ 'if (family != AF_INET) { return 0; }')
+elif args.ipv6:
+ bpf_text = bpf_text.replace('FAMILYFILTER',
+ 'if (family != AF_INET6) { return 0; }')
+else:
+ bpf_text = bpf_text.replace('FAMILYFILTER', '')
# show msecs or usecs[default]
if args.milliseconds:
bpf_text = bpf_text.replace('FACTOR', 'srtt /= 1000;')
# ./tcprtt -h
usage: tcprtt [-h] [-i INTERVAL] [-d DURATION] [-T] [-m] [-p LPORT]
[-P RPORT] [-a LADDR] [-A RADDR] [-b] [-B] [-e] [-D]
+ [-4 | -6]
Summarize TCP RTT as a histogram
-e, --extension show extension summary(average)
-D, --debug print BPF program before starting (for debugging
purposes)
+ -4, --ipv4 trace IPv4 family only
+ -6, --ipv6 trace IPv6 family only
examples:
./tcprtt # summarize TCP RTT
./tcprtt -B # show sockets histogram by remote address
./tcprtt -D # show debug bpf text
./tcprtt -e # show extension summary(average)
+ ./tcprtt -4 # trace IPv4 family only
+ ./tcprtt -6 # trace IPv6 family only
# tcpstates Trace the TCP session state changes with durations.
# For Linux, uses BCC, BPF. Embedded C.
#
-# USAGE: tcpstates [-h] [-C] [-S] [interval [count]]
+# USAGE: tcpstates [-h] [-C] [-S] [interval [count]] [-4 | -6]
#
# This uses the sock:inet_sock_set_state tracepoint, added to Linux 4.16.
# Linux 4.16 also adds more state transitions so that they can be traced.
./tcpstates -L 80 # only trace local port 80
./tcpstates -L 80,81 # only trace local ports 80 and 81
./tcpstates -D 80 # only trace remote port 80
+ ./tcpstates -4 # trace IPv4 family only
+ ./tcpstates -6 # trace IPv6 family only
"""
parser = argparse.ArgumentParser(
description="Trace TCP session state changes and durations",
help=argparse.SUPPRESS)
parser.add_argument("-Y", "--journal", action="store_true",
help="log session state changes to the systemd journal")
+group = parser.add_mutually_exclusive_group()
+group.add_argument("-4", "--ipv4", action="store_true",
+ help="trace IPv4 family only")
+group.add_argument("-6", "--ipv6", action="store_true",
+ help="trace IPv6 family only")
args = parser.parse_args()
debug = 0
delta_us = 0;
else
delta_us = (bpf_ktime_get_ns() - *tsp) / 1000;
-
+ u16 family = args->family;
+ FILTER_FAMILY
+
if (args->family == AF_INET) {
struct ipv4_data_t data4 = {
.span_us = delta_us,
delta_us = (bpf_ktime_get_ns() - *tsp) / 1000;
u16 family = sk->__sk_common.skc_family;
-
+ FILTER_FAMILY
+
if (family == AF_INET) {
struct ipv4_data_t data4 = {
.span_us = delta_us,
lports_if = ' && '.join(['lport != %d' % lport for lport in lports])
bpf_text = bpf_text.replace('FILTER_LPORT',
'if (%s) { last.delete(&sk); return 0; }' % lports_if)
+if args.ipv4:
+ bpf_text = bpf_text.replace('FILTER_FAMILY',
+ 'if (family != AF_INET) { return 0; }')
+elif args.ipv6:
+ bpf_text = bpf_text.replace('FILTER_FAMILY',
+ 'if (family != AF_INET6) { return 0; }')
+bpf_text = bpf_text.replace('FILTER_FAMILY', '')
bpf_text = bpf_text.replace('FILTER_DPORT', '')
bpf_text = bpf_text.replace('FILTER_LPORT', '')
# tcpstates -h
usage: tcpstates.py [-h] [-T] [-t] [-w] [-s] [-L LOCALPORT] [-D REMOTEPORT]
- [-Y]
+ [-Y] [-4 | -6]
Trace TCP session state changes and durations
-D REMOTEPORT, --remoteport REMOTEPORT
comma-separated list of remote ports to trace.
-Y, --journal log session state changes to the systemd journal
+ -4, --ipv4 trace IPv4 family only
+ -6, --ipv6 trace IPv6 family only
examples:
./tcpstates # trace all TCP state changes
./tcpstates -L 80 # only trace local port 80
./tcpstates -L 80,81 # only trace local ports 80 and 81
./tcpstates -D 80 # only trace remote port 80
+ ./tcpstates -4 # trace IPv4 family only
+ ./tcpstates -6 # trace IPv6 family only
# tcpsynbl Show TCP SYN backlog.
# For Linux, uses BCC, eBPF. Embedded C.
#
+# USAGE: tcpsynbl [-4 | -6] [-h]
+#
# Copyright (c) 2019 Brendan Gregg.
# Licensed under the Apache License, Version 2.0 (the "License").
# This was originally created for the BPF Performance Tools book
# 03-Jul-2019 Brendan Gregg Ported from bpftrace to BCC.
from __future__ import print_function
+import argparse
from bcc import BPF
from time import sleep
# load BPF program
-b = BPF(text="""
+bpf_text = """
#include <net/sock.h>
typedef struct backlog_key {
int do_entry(struct pt_regs *ctx) {
struct sock *sk = (struct sock *)PT_REGS_PARM1(ctx);
-
+
backlog_key_t key = {};
key.backlog = sk->sk_max_ack_backlog;
key.slot = bpf_log2l(sk->sk_ack_backlog);
return 0;
};
-""")
-b.attach_kprobe(event="tcp_v4_syn_recv_sock", fn_name="do_entry")
-b.attach_kprobe(event="tcp_v6_syn_recv_sock", fn_name="do_entry")
+"""
+examples = """examples:
+ ./tcpsynbl # trace syn backlog
+ ./tcpsynbl -4 # trace IPv4 family only
+ ./tcpsynbl -6 # trace IPv6 family only
+"""
+parser = argparse.ArgumentParser(
+ description="Show TCP SYN backlog.",
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ epilog=examples)
+group = parser.add_mutually_exclusive_group()
+group.add_argument("-4", "--ipv4", action="store_true",
+ help="trace IPv4 family only")
+group.add_argument("-6", "--ipv6", action="store_true",
+ help="trace IPv6 family only")
+args = parser.parse_args()
+
+b = BPF(text=bpf_text)
+
+if args.ipv4:
+ b.attach_kprobe(event="tcp_v4_syn_recv_sock", fn_name="do_entry")
+elif args.ipv6:
+ b.attach_kprobe(event="tcp_v6_syn_recv_sock", fn_name="do_entry")
+else:
+ b.attach_kprobe(event="tcp_v4_syn_recv_sock", fn_name="do_entry")
+ b.attach_kprobe(event="tcp_v6_syn_recv_sock", fn_name="do_entry")
print("Tracing SYN backlog size. Ctrl-C to end.");
This output shows that for the backlog limit of 500, there were 961 SYN
arrival where the backlog was zero or one, and one accept where the backlog was
two or three. This indicates that we are nowhere near this limit.
+
+USAGE:
+
+# ./tcpsynbl -h
+usage: tcpsynbl.py [-h] [-4 | -6]
+
+Show TCP SYN backlog.
+
+optional arguments:
+ -h, --help show this help message and exit
+ -4, --ipv4 trace IPv4 family only
+ -6, --ipv6 trace IPv6 family only
+
+examples:
+ ./tcpsynbl # trace syn backlog
+ ./tcpsynbl -4 # trace IPv4 family only
+ ./tcpsynbl -6 # trace IPv6 family only
\ No newline at end of file
# tcptop Summarize TCP send/recv throughput by host.
# For Linux, uses BCC, eBPF. Embedded C.
#
-# USAGE: tcptop [-h] [-C] [-S] [-p PID] [interval [count]]
+# USAGE: tcptop [-h] [-C] [-S] [-p PID] [interval [count]] [-4 | -6]
#
# This uses dynamic tracing of kernel functions, and will need to be updated
# to match kernel changes.
./tcptop -p 181 # only trace PID 181
./tcptop --cgroupmap mappath # only trace cgroups in this BPF map
./tcptop --mntnsmap mappath # only trace mount namespaces in the map
+ ./tcptop -4 # trace IPv4 family only
+ ./tcptop -6 # trace IPv6 family only
"""
parser = argparse.ArgumentParser(
description="Summarize TCP send/recv throughput by host",
help="trace cgroups in this BPF map only")
parser.add_argument("--mntnsmap",
help="trace mount namespaces in this BPF map only")
+group = parser.add_mutually_exclusive_group()
+group.add_argument("-4", "--ipv4", action="store_true",
+ help="trace IPv4 family only")
+group.add_argument("-6", "--ipv6", action="store_true",
+ help="trace IPv6 family only")
parser.add_argument("--ebpf", action="store_true",
help=argparse.SUPPRESS)
args = parser.parse_args()
u16 dport = 0, family = sk->__sk_common.skc_family;
+ FILTER_FAMILY
+
if (family == AF_INET) {
struct ipv4_key_t ipv4_key = {.pid = pid};
ipv4_key.saddr = sk->__sk_common.skc_rcv_saddr;
if (copied <= 0)
return 0;
+ FILTER_FAMILY
+
if (family == AF_INET) {
struct ipv4_key_t ipv4_key = {.pid = pid};
ipv4_key.saddr = sk->__sk_common.skc_rcv_saddr;
'if (pid != %s) { return 0; }' % args.pid)
else:
bpf_text = bpf_text.replace('FILTER_PID', '')
+if args.ipv4:
+ bpf_text = bpf_text.replace('FILTER_FAMILY',
+ 'if (family != AF_INET) { return 0; }')
+elif args.ipv6:
+ bpf_text = bpf_text.replace('FILTER_FAMILY',
+ 'if (family != AF_INET6) { return 0; }')
+bpf_text = bpf_text.replace('FILTER_FAMILY', '')
bpf_text = filter_by_containers(args) + bpf_text
if debug or args.ebpf:
print(bpf_text)
# tcptop -h
usage: tcptop.py [-h] [-C] [-S] [-p PID] [--cgroupmap CGROUPMAP]
[--mntnsmap MNTNSMAP]
- [interval] [count]
+ [interval] [count] [-4 | -6]
Summarize TCP send/recv throughput by host
-p PID, --pid PID trace this PID only
--cgroupmap CGROUPMAP
trace cgroups in this BPF map only
+ -4, --ipv4 trace IPv4 family only
+ -6, --ipv6 trace IPv6 family only
examples:
./tcptop # trace TCP send/recv by host
./tcptop -p 181 # only trace PID 181
./tcptop --cgroupmap ./mappath # only trace cgroups in this BPF map
./tcptop --mntnsmap mappath # only trace mount namespaces in the map
+ ./tcptop -4 # trace IPv4 family only
+ ./tcptop -6 # trace IPv6 family only
# tcpv4tracer Trace TCP connections.
# For Linux, uses BCC, eBPF. Embedded C.
#
-# USAGE: tcpv4tracer [-h] [-v] [-p PID] [-N NETNS]
+# USAGE: tcpv4tracer [-h] [-v] [-p PID] [-N NETNS] [-4 | -6]
#
# You should generally try to avoid writing long scripts that measure multiple
# functions and walk multiple kernel structures, as they will be a burden to
help="trace cgroups in this BPF map only")
parser.add_argument("--mntnsmap",
help="trace mount namespaces in this BPF map only")
+group = parser.add_mutually_exclusive_group()
+group.add_argument("-4", "--ipv4", action="store_true",
+ help="trace IPv4 family only")
+group.add_argument("-6", "--ipv6", action="store_true",
+ help="trace IPv6 family only")
parser.add_argument("-v", "--verbose", action="store_true",
help="include Network Namespace in the output")
parser.add_argument("--ebpf", action="store_true",
u64 pid = bpf_get_current_pid_tgid();
##FILTER_PID##
+
+ u16 family = sk->__sk_common.skc_family;
+ ##FILTER_FAMILY##
+
// stash the sock ptr for lookup on return
connectsock.update(&pid, &sk);
u64 pid = bpf_get_current_pid_tgid();
##FILTER_PID##
+ u16 family = sk->__sk_common.skc_family;
+ ##FILTER_FAMILY##
// stash the sock ptr for lookup on return
connectsock.update(&pid, &sk);
return 0;
}
+ u16 family = skp->__sk_common.skc_family;
+ ##FILTER_FAMILY##
+
u8 ipver = 0;
if (check_family(skp, AF_INET)) {
ipver = 4;
u64 pid = bpf_get_current_pid_tgid();
##FILTER_PID##
+
+ u16 family = skp->__sk_common.skc_family;
+ ##FILTER_FAMILY##
u8 oldstate = skp->sk_state;
// Don't generate close events for connections that were never
#endif
##FILTER_NETNS##
+
+ u16 family = newsk->__sk_common.skc_family;
+ ##FILTER_FAMILY##
if (check_family(newsk, AF_INET)) {
ipver = 4;
pid_filter = 'if (pid >> 32 != %d) { return 0; }' % args.pid
if args.netns:
netns_filter = 'if (net_ns_inum != %d) { return 0; }' % args.netns
-
+if args.ipv4:
+ bpf_text = bpf_text.replace('##FILTER_FAMILY##',
+ 'if (family != AF_INET) { return 0; }')
+elif args.ipv6:
+ bpf_text = bpf_text.replace('##FILTER_FAMILY##',
+ 'if (family != AF_INET6) { return 0; }')
+bpf_text = bpf_text.replace('##FILTER_FAMILY##', '')
bpf_text = bpf_text.replace('##FILTER_PID##', pid_filter)
bpf_text = bpf_text.replace('##FILTER_NETNS##', netns_filter)
bpf_text = filter_by_containers(args) + bpf_text
# initialize BPF
b = BPF(text=bpf_text)
-b.attach_kprobe(event="tcp_v4_connect", fn_name="trace_connect_v4_entry")
-b.attach_kretprobe(event="tcp_v4_connect", fn_name="trace_connect_v4_return")
-b.attach_kprobe(event="tcp_v6_connect", fn_name="trace_connect_v6_entry")
-b.attach_kretprobe(event="tcp_v6_connect", fn_name="trace_connect_v6_return")
+if args.ipv4:
+ b.attach_kprobe(event="tcp_v4_connect", fn_name="trace_connect_v4_entry")
+ b.attach_kretprobe(event="tcp_v4_connect", fn_name="trace_connect_v4_return")
+elif args.ipv6:
+ b.attach_kprobe(event="tcp_v6_connect", fn_name="trace_connect_v6_entry")
+ b.attach_kretprobe(event="tcp_v6_connect", fn_name="trace_connect_v6_return")
+else:
+ b.attach_kprobe(event="tcp_v4_connect", fn_name="trace_connect_v4_entry")
+ b.attach_kretprobe(event="tcp_v4_connect", fn_name="trace_connect_v4_return")
+ b.attach_kprobe(event="tcp_v6_connect", fn_name="trace_connect_v6_entry")
+ b.attach_kretprobe(event="tcp_v6_connect", fn_name="trace_connect_v6_return")
b.attach_kprobe(event="tcp_set_state", fn_name="trace_tcp_set_state_entry")
b.attach_kprobe(event="tcp_close", fn_name="trace_close_entry")
b.attach_kretprobe(event="inet_csk_accept", fn_name="trace_accept_return")