Skip to content

Commit

Permalink
tools: add option to include 'LPORT' in tcpconnlat, update man pages
Browse files Browse the repository at this point in the history
  • Loading branch information
suresh2514 authored and yonghong-song committed Mar 17, 2021
1 parent d80afb2 commit 456cb95
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 18 deletions.
12 changes: 11 additions & 1 deletion man/man8/tcpconnlat.8
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
.SH NAME
tcpconnlat \- Trace TCP active connection latency. Uses Linux eBPF/bcc.
.SH SYNOPSIS
.B tcpconnlat [\-h] [\-t] [\-p PID] [-v] [min_ms]
.B tcpconnlat [\-h] [\-t] [\-p PID] [\-L] [-v] [min_ms]
.SH DESCRIPTION
This tool traces active TCP connections
(eg, via a connect() syscall), and shows the latency (time) for the connection
Expand Down Expand Up @@ -31,6 +31,9 @@ Include a timestamp column.
\-p PID
Trace this process ID only (filtered in-kernel).
.TP
\-L
Include a LPORT column.
.TP
\-v
Print the resulting BPF program, for debugging purposes.
.TP
Expand All @@ -50,6 +53,10 @@ Trace PID 181 only:
#
.B tcpconnlat \-p 181
.TP
Trace connects, and include LPORT:
#
.B tcpconnlat \-L
.TP
Trace connects with latency longer than 10 ms:
#
.B tcpconnlat 10
Expand Down Expand Up @@ -77,6 +84,9 @@ Source IP address.
DADDR
Destination IP address.
.TP
LPORT
Source port
.TP
DPORT
Destination port
.TP
Expand Down
51 changes: 39 additions & 12 deletions tools/tcpconnlat.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 19-Feb-2016 Brendan Gregg Created this.
# 15-Mar-2021 Suresh Kumar Added LPORT option

from __future__ import print_function
from bcc import BPF
Expand All @@ -38,6 +39,7 @@ def positive_float(val):
./tcpconnlat 0.1 # trace connection latency slower than 100 us
./tcpconnlat -t # include timestamps
./tcpconnlat -p 181 # only trace PID 181
./tcpconnlat -L # include LPORT while printing outputs
"""
parser = argparse.ArgumentParser(
description="Trace TCP connects and show connection latency",
Expand All @@ -47,6 +49,8 @@ def positive_float(val):
help="include timestamp on output")
parser.add_argument("-p", "--pid",
help="trace this PID only")
parser.add_argument("-L", "--lport", action="store_true",
help="include LPORT on output")
parser.add_argument("duration_ms", nargs="?", default=0,
type=positive_float,
help="minimum duration to trace (ms)")
Expand Down Expand Up @@ -85,6 +89,7 @@ def positive_float(val):
u32 saddr;
u32 daddr;
u64 ip;
u16 lport;
u16 dport;
u64 delta_us;
char task[TASK_COMM_LEN];
Expand All @@ -97,6 +102,7 @@ def positive_float(val):
unsigned __int128 saddr;
unsigned __int128 daddr;
u64 ip;
u16 lport;
u16 dport;
u64 delta_us;
char task[TASK_COMM_LEN];
Expand Down Expand Up @@ -142,8 +148,9 @@ def positive_float(val):
#endif
// pull in details
u16 family = 0, dport = 0;
u16 family = 0, lport = 0, dport = 0;
family = skp->__sk_common.skc_family;
lport = skp->__sk_common.skc_num;
dport = skp->__sk_common.skc_dport;
// emit to appropriate data path
Expand All @@ -152,6 +159,7 @@ def positive_float(val):
data4.ts_us = now / 1000;
data4.saddr = skp->__sk_common.skc_rcv_saddr;
data4.daddr = skp->__sk_common.skc_daddr;
data4.lport = lport;
data4.dport = ntohs(dport);
data4.delta_us = delta_us;
__builtin_memcpy(&data4.task, infop->task, sizeof(data4.task));
Expand All @@ -164,6 +172,7 @@ def positive_float(val):
skp->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
bpf_probe_read_kernel(&data6.daddr, sizeof(data6.daddr),
skp->__sk_common.skc_v6_daddr.in6_u.u6_addr32);
data6.lport = lport;
data6.dport = ntohs(dport);
data6.delta_us = delta_us;
__builtin_memcpy(&data6.task, infop->task, sizeof(data6.task));
Expand Down Expand Up @@ -208,11 +217,18 @@ def print_ipv4_event(cpu, data, size):
if start_ts == 0:
start_ts = event.ts_us
print("%-9.3f" % ((float(event.ts_us) - start_ts) / 1000000), end="")
print("%-6d %-12.12s %-2d %-16s %-16s %-5d %.2f" % (event.pid,
event.task.decode('utf-8', 'replace'), event.ip,
inet_ntop(AF_INET, pack("I", event.saddr)),
inet_ntop(AF_INET, pack("I", event.daddr)), event.dport,
float(event.delta_us) / 1000))
if args.lport:
print("%-6d %-12.12s %-2d %-16s %-6d %-16s %-5d %.2f" % (event.pid,
event.task.decode('utf-8', 'replace'), event.ip,
inet_ntop(AF_INET, pack("I", event.saddr)), event.lport,
inet_ntop(AF_INET, pack("I", event.daddr)), event.dport,
float(event.delta_us) / 1000))
else:
print("%-6d %-12.12s %-2d %-16s %-16s %-5d %.2f" % (event.pid,
event.task.decode('utf-8', 'replace'), event.ip,
inet_ntop(AF_INET, pack("I", event.saddr)),
inet_ntop(AF_INET, pack("I", event.daddr)), event.dport,
float(event.delta_us) / 1000))

def print_ipv6_event(cpu, data, size):
event = b["ipv6_events"].event(data)
Expand All @@ -221,16 +237,27 @@ def print_ipv6_event(cpu, data, size):
if start_ts == 0:
start_ts = event.ts_us
print("%-9.3f" % ((float(event.ts_us) - start_ts) / 1000000), end="")
print("%-6d %-12.12s %-2d %-16s %-16s %-5d %.2f" % (event.pid,
event.task.decode('utf-8', 'replace'), event.ip,
inet_ntop(AF_INET6, event.saddr), inet_ntop(AF_INET6, event.daddr),
event.dport, float(event.delta_us) / 1000))
if args.lport:
print("%-6d %-12.12s %-2d %-16s %-6d %-16s %-5d %.2f" % (event.pid,
event.task.decode('utf-8', 'replace'), event.ip,
inet_ntop(AF_INET6, event.saddr), event.lport,
inet_ntop(AF_INET6, event.daddr),
event.dport, float(event.delta_us) / 1000))
else:
print("%-6d %-12.12s %-2d %-16s %-16s %-5d %.2f" % (event.pid,
event.task.decode('utf-8', 'replace'), event.ip,
inet_ntop(AF_INET6, event.saddr), inet_ntop(AF_INET6, event.daddr),
event.dport, float(event.delta_us) / 1000))

# header
if args.timestamp:
print("%-9s" % ("TIME(s)"), end="")
print("%-6s %-12s %-2s %-16s %-16s %-5s %s" % ("PID", "COMM", "IP", "SADDR",
"DADDR", "DPORT", "LAT(ms)"))
if args.lport:
print("%-6s %-12s %-2s %-16s %-6s %-16s %-5s %s" % ("PID", "COMM",
"IP", "SADDR", "LPORT", "DADDR", "DPORT", "LAT(ms)"))
else:
print("%-6s %-12s %-2s %-16s %-16s %-5s %s" % ("PID", "COMM", "IP",
"SADDR", "DADDR", "DPORT", "LAT(ms)"))

# read events
b["ipv4_events"].open_perf_buffer(print_ipv4_event)
Expand Down
12 changes: 7 additions & 5 deletions tools/tcpconnlat_example.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,24 @@ if the response is a RST (port closed).
USAGE message:

# ./tcpconnlat -h
usage: tcpconnlat [-h] [-t] [-p PID] [min_ms]
usage: tcpconnlat [-h] [-t] [-p PID] [-L] [-v] [duration_ms]

Trace TCP connects and show connection latency

positional arguments:
min_ms minimum duration to trace, in ms (default 0)
duration_ms minimum duration to trace (ms)

optional arguments:
-h, --help show this help message and exit
-t, --timestamp include timestamp on output
-p PID, --pid PID trace this PID only
-L, --lport include LPORT on output
-v, --verbose print the BPF program for debugging purposes

examples:
./tcpconnlat # trace all TCP connect()s
./tcpconnlat 1 # trace connection latency slower than 1 ms
./tcpconnlat 0.1 # trace connection latency slower than 100 us
./tcpconnlat -t # include timestamps
./tcpconnlat -p 181 # only trace PID 181
./tcpconnlat 1 # only show connects longer than 1 ms
./tcpconnlat 0.1 # only show connects longer than 100 us
./tcpconnlat -v # Show the BPF program
./tcpconnlat -L # include LPORT while printing outputs

0 comments on commit 456cb95

Please sign in to comment.