Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
bcc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
bcc
Commits
3083c85c
Commit
3083c85c
authored
Jan 14, 2016
by
Brenden Blanco
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #312 from iovisor/ast_dev
fix pep8 lint errors in the rest of the tools
parents
a0aa7f28
bdf0773f
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
669 additions
and
661 deletions
+669
-661
tools/biolatency_example.txt
tools/biolatency_example.txt
+1
-1
tools/funccount
tools/funccount
+47
-46
tools/funclatency
tools/funclatency
+87
-86
tools/hardirqs
tools/hardirqs
+80
-79
tools/hardirqs_example.txt
tools/hardirqs_example.txt
+1
-1
tools/killsnoop
tools/killsnoop
+44
-43
tools/killsnoop_example.txt
tools/killsnoop_example.txt
+1
-1
tools/opensnoop
tools/opensnoop
+51
-48
tools/opensnoop_example.txt
tools/opensnoop_example.txt
+45
-51
tools/pidpersec
tools/pidpersec
+13
-13
tools/softirqs
tools/softirqs
+71
-70
tools/softirqs_example.txt
tools/softirqs_example.txt
+1
-1
tools/syncsnoop
tools/syncsnoop
+8
-7
tools/syncsnoop_example.txt
tools/syncsnoop_example.txt
+1
-1
tools/tcpaccept
tools/tcpaccept
+72
-71
tools/tcpaccept_example.txt
tools/tcpaccept_example.txt
+5
-5
tools/tcpconnect
tools/tcpconnect
+83
-82
tools/tcpconnect_example.txt
tools/tcpconnect_example.txt
+5
-5
tools/vfscount
tools/vfscount
+8
-7
tools/vfscount_example.txt
tools/vfscount_example.txt
+1
-1
tools/vfsstat
tools/vfsstat
+43
-41
tools/vfsstat_example.txt
tools/vfsstat_example.txt
+1
-1
No files found.
tools/biolatency_example.txt
View file @
3083c85c
...
...
@@ -5,7 +5,7 @@ biolatency traces block device I/O (disk I/O), and records the distribution
of I/O latency (time), printing this as a histogram when Ctrl-C is hit.
For example:
# ./biolatency
# ./biolatency
Tracing block device I/O... Hit Ctrl-C to end.
^C
usecs : count distribution
...
...
tools/funccount
View file @
3083c85c
#!/usr/bin/python
# @lint-avoid-python-3-compatibility-imports
#
# funccount
Count kernel function calls.
#
For Linux, uses BCC, eBPF. See .c file.
# funccount
Count kernel function calls.
#
For Linux, uses BCC, eBPF. See .c file.
#
# USAGE: funccount [-h] [-p PID] [-i INTERVAL] [-T] [-r] pattern
#
...
...
@@ -11,7 +12,7 @@
# Copyright (c) 2015 Brendan Gregg.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 09-Sep-2015
Brendan Gregg
Created this.
# 09-Sep-2015
Brendan Gregg
Created this.
from
__future__
import
print_function
from
bcc
import
BPF
...
...
@@ -28,63 +29,63 @@ examples = """examples:
./funccount -p 185 'vfs_*' # count vfs calls for PID 181 only
"""
parser
=
argparse
.
ArgumentParser
(
description
=
"Count kernel function calls"
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
epilog
=
examples
)
description
=
"Count kernel function calls"
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
epilog
=
examples
)
parser
.
add_argument
(
"-p"
,
"--pid"
,
help
=
"trace this PID only"
)
help
=
"trace this PID only"
)
parser
.
add_argument
(
"-i"
,
"--interval"
,
default
=
99999999
,
help
=
"summary interval, seconds"
)
help
=
"summary interval, seconds"
)
parser
.
add_argument
(
"-T"
,
"--timestamp"
,
action
=
"store_true"
,
help
=
"include timestamp on output"
)
help
=
"include timestamp on output"
)
parser
.
add_argument
(
"-r"
,
"--regexp"
,
action
=
"store_true"
,
help
=
"use regular expressions. Default is
\
"
*
\
"
wildcards only."
)
help
=
"use regular expressions. Default is
\
"
*
\
"
wildcards only."
)
parser
.
add_argument
(
"pattern"
,
help
=
"search expression for kernel functions"
)
help
=
"search expression for kernel functions"
)
args
=
parser
.
parse_args
()
pattern
=
args
.
pattern
if
not
args
.
regexp
:
pattern
=
pattern
.
replace
(
'*'
,
'.*'
)
pattern
=
'^'
+
pattern
+
'$'
pattern
=
pattern
.
replace
(
'*'
,
'.*'
)
pattern
=
'^'
+
pattern
+
'$'
debug
=
0
# signal handler
def
signal_ignore
(
signal
,
frame
):
print
()
print
()
# load BPF program
bpf_text
=
"""
#include <uapi/linux/ptrace.h>
struct key_t {
u64 ip;
u64 ip;
};
BPF_HASH(counts, struct key_t);
int trace_count(struct pt_regs *ctx) {
FILTER
struct key_t key = {};
u64 zero = 0, *val;
key.ip = ctx->ip;
val = counts.lookup_or_init(&key, &zero);
(*val)++;
return 0;
FILTER
struct key_t key = {};
u64 zero = 0, *val;
key.ip = ctx->ip;
val = counts.lookup_or_init(&key, &zero);
(*val)++;
return 0;
}
"""
if
args
.
pid
:
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
(
'u32 pid; pid = bpf_get_current_pid_tgid(); '
+
'if (pid != %s) { return 0; }'
)
%
(
args
.
pid
))
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
(
'u32 pid; pid = bpf_get_current_pid_tgid(); '
+
'if (pid != %s) { return 0; }'
)
%
(
args
.
pid
))
else
:
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
''
)
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
''
)
if
debug
:
print
(
bpf_text
)
print
(
bpf_text
)
b
=
BPF
(
text
=
bpf_text
)
b
.
attach_kprobe
(
event_re
=
pattern
,
fn_name
=
"trace_count"
)
matched
=
b
.
num_open_kprobes
()
if
matched
==
0
:
print
(
"0 functions matched by
\
"
%s
\
"
. Exiting."
%
args
.
pattern
)
exit
()
print
(
"0 functions matched by
\
"
%s
\
"
. Exiting."
%
args
.
pattern
)
exit
()
# header
print
(
"Tracing %d functions for
\
"
%s
\
"
... Hit Ctrl-C to end."
%
...
...
@@ -93,23 +94,23 @@ print("Tracing %d functions for \"%s\"... Hit Ctrl-C to end." %
# output
exiting
=
0
if
args
.
interval
else
1
while
(
1
):
try
:
sleep
(
int
(
args
.
interval
))
except
KeyboardInterrupt
:
exiting
=
1
# as cleanup can take many seconds, trap Ctrl-C:
signal
.
signal
(
signal
.
SIGINT
,
signal_ignore
)
try
:
sleep
(
int
(
args
.
interval
))
except
KeyboardInterrupt
:
exiting
=
1
# as cleanup can take many seconds, trap Ctrl-C:
signal
.
signal
(
signal
.
SIGINT
,
signal_ignore
)
print
()
if
args
.
timestamp
:
print
(
"%-8s
\
n
"
%
strftime
(
"%H:%M:%S"
),
end
=
""
)
print
()
if
args
.
timestamp
:
print
(
"%-8s
\
n
"
%
strftime
(
"%H:%M:%S"
),
end
=
""
)
print
(
"%-16s %-26s %8s"
%
(
"ADDR"
,
"FUNC"
,
"COUNT"
))
counts
=
b
.
get_table
(
"counts"
)
for
k
,
v
in
sorted
(
counts
.
items
(),
key
=
lambda
counts
:
counts
[
1
].
value
):
print
(
"%-16x %-26s %8d"
%
(
k
.
ip
,
b
.
ksym
(
k
.
ip
),
v
.
value
))
counts
.
clear
()
print
(
"%-16s %-26s %8s"
%
(
"ADDR"
,
"FUNC"
,
"COUNT"
))
counts
=
b
.
get_table
(
"counts"
)
for
k
,
v
in
sorted
(
counts
.
items
(),
key
=
lambda
counts
:
counts
[
1
].
value
):
print
(
"%-16x %-26s %8d"
%
(
k
.
ip
,
b
.
ksym
(
k
.
ip
),
v
.
value
))
counts
.
clear
()
if
exiting
:
print
(
"Detaching..."
)
exit
()
if
exiting
:
print
(
"Detaching..."
)
exit
()
tools/funclatency
View file @
3083c85c
#!/usr/bin/python
# @lint-avoid-python-3-compatibility-imports
#
# funclatency
Time kernel funcitons and print latency as a histogram.
#
For Linux, uses BCC, eBPF.
# funclatency
Time kernel funcitons and print latency as a histogram.
#
For Linux, uses BCC, eBPF.
#
# USAGE: funclatency [-h] [-p PID] [-i INTERVAL] [-T] [-u] [-m] [-r] pattern
#
...
...
@@ -20,7 +21,7 @@
# Copyright (c) 2015 Brendan Gregg.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 20-Sep-2015
Brendan Gregg
Created this.
# 20-Sep-2015
Brendan Gregg
Created this.
from
__future__
import
print_function
from
bcc
import
BPF
...
...
@@ -39,30 +40,30 @@ examples = """examples:
./funclatency -F 'vfs_r*' # show one histogram per matched function
"""
parser
=
argparse
.
ArgumentParser
(
description
=
"Time kernel funcitons and print latency as a histogram"
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
epilog
=
examples
)
description
=
"Time kernel funcitons and print latency as a histogram"
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
epilog
=
examples
)
parser
.
add_argument
(
"-p"
,
"--pid"
,
help
=
"trace this PID only"
)
help
=
"trace this PID only"
)
parser
.
add_argument
(
"-i"
,
"--interval"
,
default
=
99999999
,
help
=
"summary interval, seconds"
)
help
=
"summary interval, seconds"
)
parser
.
add_argument
(
"-T"
,
"--timestamp"
,
action
=
"store_true"
,
help
=
"include timestamp on output"
)
help
=
"include timestamp on output"
)
parser
.
add_argument
(
"-u"
,
"--microseconds"
,
action
=
"store_true"
,
help
=
"microsecond histogram"
)
help
=
"microsecond histogram"
)
parser
.
add_argument
(
"-m"
,
"--milliseconds"
,
action
=
"store_true"
,
help
=
"millisecond histogram"
)
help
=
"millisecond histogram"
)
parser
.
add_argument
(
"-F"
,
"--function"
,
action
=
"store_true"
,
help
=
"show a separate histogram per function"
)
help
=
"show a separate histogram per function"
)
parser
.
add_argument
(
"-r"
,
"--regexp"
,
action
=
"store_true"
,
help
=
"use regular expressions. Default is
\
"
*
\
"
wildcards only."
)
help
=
"use regular expressions. Default is
\
"
*
\
"
wildcards only."
)
parser
.
add_argument
(
"pattern"
,
help
=
"search expression for kernel functions"
)
help
=
"search expression for kernel functions"
)
args
=
parser
.
parse_args
()
pattern
=
args
.
pattern
if
not
args
.
regexp
:
pattern
=
pattern
.
replace
(
'*'
,
'.*'
)
pattern
=
'^'
+
pattern
+
'$'
pattern
=
pattern
.
replace
(
'*'
,
'.*'
)
pattern
=
'^'
+
pattern
+
'$'
debug
=
0
# define BPF program
...
...
@@ -71,8 +72,8 @@ bpf_text = """
#include <linux/blkdev.h>
typedef struct ip_key {
u64 ip;
u64 slot;
u64 ip;
u64 slot;
} ip_key_t;
BPF_HASH(start, u32);
...
...
@@ -80,73 +81,73 @@ STORAGE
int trace_func_entry(struct pt_regs *ctx)
{
u32 pid = bpf_get_current_pid_tgid();
u64 ts = bpf_ktime_get_ns();
u32 pid = bpf_get_current_pid_tgid();
u64 ts = bpf_ktime_get_ns();
FILTER
ENTRYSTORE
start.update(&pid, &ts);
FILTER
ENTRYSTORE
start.update(&pid, &ts);
return 0;
return 0;
}
int trace_func_return(struct pt_regs *ctx)
{
u64 *tsp, delta;
u32 pid = bpf_get_current_pid_tgid();
// calculate delta time
tsp = start.lookup(&pid);
if (tsp == 0) {
return 0;
// missed start
}
delta = bpf_ktime_get_ns() - *tsp;
start.delete(&pid);
FACTOR
// store as histogram
STORE
return 0;
u64 *tsp, delta;
u32 pid = bpf_get_current_pid_tgid();
// calculate delta time
tsp = start.lookup(&pid);
if (tsp == 0) {
return 0;
// missed start
}
delta = bpf_ktime_get_ns() - *tsp;
start.delete(&pid);
FACTOR
// store as histogram
STORE
return 0;
}
"""
# code substitutions
if
args
.
pid
:
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
'if (pid != %s) { return 0; }'
%
args
.
pid
)
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
'if (pid != %s) { return 0; }'
%
args
.
pid
)
else
:
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
''
)
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
''
)
if
args
.
milliseconds
:
bpf_text
=
bpf_text
.
replace
(
'FACTOR'
,
'delta /= 1000000;'
)
label
=
"msecs"
bpf_text
=
bpf_text
.
replace
(
'FACTOR'
,
'delta /= 1000000;'
)
label
=
"msecs"
elif
args
.
microseconds
:
bpf_text
=
bpf_text
.
replace
(
'FACTOR'
,
'delta /= 1000;'
)
label
=
"usecs"
bpf_text
=
bpf_text
.
replace
(
'FACTOR'
,
'delta /= 1000;'
)
label
=
"usecs"
else
:
bpf_text
=
bpf_text
.
replace
(
'FACTOR'
,
''
)
label
=
"nsecs"
bpf_text
=
bpf_text
.
replace
(
'FACTOR'
,
''
)
label
=
"nsecs"
if
args
.
function
:
bpf_text
=
bpf_text
.
replace
(
'STORAGE'
,
'BPF_HASH(ipaddr, u32);
\
n
'
+
'BPF_HISTOGRAM(dist, ip_key_t);'
)
# stash the IP on entry, as on return it's kretprobe_trampoline:
bpf_text
=
bpf_text
.
replace
(
'ENTRYSTORE'
,
'u64 ip = ctx->ip; ipaddr.update(&pid, &ip);'
)
bpf_text
=
bpf_text
.
replace
(
'STORE'
,
'u64 ip, *ipp = ipaddr.lookup(&pid); if (ipp) { ip = *ipp; '
+
'dist.increment((ip_key_t){ip, bpf_log2l(delta)}); '
+
'ipaddr.delete(&pid); }'
)
bpf_text
=
bpf_text
.
replace
(
'STORAGE'
,
'BPF_HASH(ipaddr, u32);
\
n
'
+
'BPF_HISTOGRAM(dist, ip_key_t);'
)
# stash the IP on entry, as on return it's kretprobe_trampoline:
bpf_text
=
bpf_text
.
replace
(
'ENTRYSTORE'
,
'u64 ip = ctx->ip; ipaddr.update(&pid, &ip);'
)
bpf_text
=
bpf_text
.
replace
(
'STORE'
,
'u64 ip, *ipp = ipaddr.lookup(&pid); if (ipp) { ip = *ipp; '
+
'dist.increment((ip_key_t){ip, bpf_log2l(delta)}); '
+
'ipaddr.delete(&pid); }'
)
else
:
bpf_text
=
bpf_text
.
replace
(
'STORAGE'
,
'BPF_HISTOGRAM(dist);'
)
bpf_text
=
bpf_text
.
replace
(
'ENTRYSTORE'
,
''
)
bpf_text
=
bpf_text
.
replace
(
'STORE'
,
'dist.increment(bpf_log2l(delta));'
)
bpf_text
=
bpf_text
.
replace
(
'STORAGE'
,
'BPF_HISTOGRAM(dist);'
)
bpf_text
=
bpf_text
.
replace
(
'ENTRYSTORE'
,
''
)
bpf_text
=
bpf_text
.
replace
(
'STORE'
,
'dist.increment(bpf_log2l(delta));'
)
if
debug
:
print
(
bpf_text
)
print
(
bpf_text
)
# signal handler
def
signal_ignore
(
signal
,
frame
):
print
()
print
()
# load BPF program
b
=
BPF
(
text
=
bpf_text
)
...
...
@@ -154,8 +155,8 @@ b.attach_kprobe(event_re=pattern, fn_name="trace_func_entry")
b
.
attach_kretprobe
(
event_re
=
pattern
,
fn_name
=
"trace_func_return"
)
matched
=
b
.
num_open_kprobes
()
if
matched
==
0
:
print
(
"0 functions matched by
\
"
%s
\
"
. Exiting."
%
args
.
pattern
)
exit
()
print
(
"0 functions matched by
\
"
%s
\
"
. Exiting."
%
args
.
pattern
)
exit
()
# header
print
(
"Tracing %d functions for
\
"
%s
\
"
... Hit Ctrl-C to end."
%
...
...
@@ -165,23 +166,23 @@ print("Tracing %d functions for \"%s\"... Hit Ctrl-C to end." %
exiting
=
0
if
args
.
interval
else
1
dist
=
b
.
get_table
(
"dist"
)
while
(
1
):
try
:
sleep
(
int
(
args
.
interval
))
except
KeyboardInterrupt
:
exiting
=
1
# as cleanup can take many seconds, trap Ctrl-C:
signal
.
signal
(
signal
.
SIGINT
,
signal_ignore
)
print
()
if
args
.
timestamp
:
print
(
"%-8s
\
n
"
%
strftime
(
"%H:%M:%S"
),
end
=
""
)
if
args
.
function
:
dist
.
print_log2_hist
(
label
,
"Function"
,
BPF
.
ksym
)
else
:
dist
.
print_log2_hist
(
label
)
dist
.
clear
()
if
exiting
:
print
(
"Detaching..."
)
exit
()
try
:
sleep
(
int
(
args
.
interval
))
except
KeyboardInterrupt
:
exiting
=
1
# as cleanup can take many seconds, trap Ctrl-C:
signal
.
signal
(
signal
.
SIGINT
,
signal_ignore
)
print
()
if
args
.
timestamp
:
print
(
"%-8s
\
n
"
%
strftime
(
"%H:%M:%S"
),
end
=
""
)
if
args
.
function
:
dist
.
print_log2_hist
(
label
,
"Function"
,
BPF
.
ksym
)
else
:
dist
.
print_log2_hist
(
label
)
dist
.
clear
()
if
exiting
:
print
(
"Detaching..."
)
exit
()
tools/hardirqs
View file @
3083c85c
#!/usr/bin/python
# @lint-avoid-python-3-compatibility-imports
#
# hardirqs
Summarize hard IRQ (interrupt) event time.
#
For Linux, uses BCC, eBPF.
# hardirqs
Summarize hard IRQ (interrupt) event time.
#
For Linux, uses BCC, eBPF.
#
# USAGE: hardirqs [-h] [-T] [-Q] [-m] [-D] [interval] [count]
#
...
...
@@ -10,7 +11,7 @@
# Copyright (c) 2015 Brendan Gregg.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 19-Oct-2015
Brendan Gregg
Created this.
# 19-Oct-2015
Brendan Gregg
Created this.
from
__future__
import
print_function
from
bcc
import
BPF
...
...
@@ -25,27 +26,27 @@ examples = """examples:
./hardirqs -NT 1 # 1s summaries, nanoseconds, and timestamps
"""
parser
=
argparse
.
ArgumentParser
(
description
=
"Summarize hard irq event time as histograms"
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
epilog
=
examples
)
description
=
"Summarize hard irq event time as histograms"
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
epilog
=
examples
)
parser
.
add_argument
(
"-T"
,
"--timestamp"
,
action
=
"store_true"
,
help
=
"include timestamp on output"
)
help
=
"include timestamp on output"
)
parser
.
add_argument
(
"-N"
,
"--nanoseconds"
,
action
=
"store_true"
,
help
=
"output in nanoseconds"
)
help
=
"output in nanoseconds"
)
parser
.
add_argument
(
"-d"
,
"--dist"
,
action
=
"store_true"
,
help
=
"show distributions as histograms"
)
help
=
"show distributions as histograms"
)
parser
.
add_argument
(
"interval"
,
nargs
=
"?"
,
default
=
99999999
,
help
=
"output interval, in seconds"
)
help
=
"output interval, in seconds"
)
parser
.
add_argument
(
"count"
,
nargs
=
"?"
,
default
=
99999999
,
help
=
"number of outputs"
)
help
=
"number of outputs"
)
args
=
parser
.
parse_args
()
countdown
=
int
(
args
.
count
)
if
args
.
nanoseconds
:
factor
=
1
label
=
"nsecs"
factor
=
1
label
=
"nsecs"
else
:
factor
=
1000
label
=
"usecs"
factor
=
1000
label
=
"usecs"
debug
=
0
### define BPF program
...
...
@@ -56,8 +57,8 @@ bpf_text = """
#include <linux/interrupt.h>
typedef struct irq_key {
char name[32];
u64 slot;
char name[32];
u64 slot;
} irq_key_t;
BPF_HASH(start, u32);
BPF_HASH(irqdesc, u32, struct irq_desc *);
...
...
@@ -66,59 +67,59 @@ BPF_HISTOGRAM(dist, irq_key_t);
// time IRQ
int trace_start(struct pt_regs *ctx, struct irq_desc *desc)
{
u32 pid = bpf_get_current_pid_tgid();
u64 ts = bpf_ktime_get_ns();
start.update(&pid, &ts);
irqdesc.update(&pid, &desc);
return 0;
u32 pid = bpf_get_current_pid_tgid();
u64 ts = bpf_ktime_get_ns();
start.update(&pid, &ts);
irqdesc.update(&pid, &desc);
return 0;
}
int trace_completion(struct pt_regs *ctx)
{
u64 *tsp, delta;
struct irq_desc **descp;
u32 pid = bpf_get_current_pid_tgid();
// fetch timestamp and calculate delta
tsp = start.lookup(&pid);
descp = irqdesc.lookup(&pid);
if (tsp == 0 || descp == 0) {
return 0;
// missed start
}
// Note: descp is a value from map, so '&' can be done without
// probe_read, but the next level irqaction * needs a probe read.
// Do these steps first after reading the map, otherwise some of these
// pointers may get pushed onto the stack and verifier will fail.
struct irqaction *action = 0;
bpf_probe_read(&action, sizeof(action), &(*descp)->action);
const char **namep = &action->name;
char *name = 0;
bpf_probe_read(&name, sizeof(name), namep);
delta = bpf_ktime_get_ns() - *tsp;
// store as sum or histogram
STORE
start.delete(&pid);
irqdesc.delete(&pid);
return 0;
u64 *tsp, delta;
struct irq_desc **descp;
u32 pid = bpf_get_current_pid_tgid();
// fetch timestamp and calculate delta
tsp = start.lookup(&pid);
descp = irqdesc.lookup(&pid);
if (tsp == 0 || descp == 0) {
return 0;
// missed start
}
// Note: descp is a value from map, so '&' can be done without
// probe_read, but the next level irqaction * needs a probe read.
// Do these steps first after reading the map, otherwise some of these
// pointers may get pushed onto the stack and verifier will fail.
struct irqaction *action = 0;
bpf_probe_read(&action, sizeof(action), &(*descp)->action);
const char **namep = &action->name;
char *name = 0;
bpf_probe_read(&name, sizeof(name), namep);
delta = bpf_ktime_get_ns() - *tsp;
// store as sum or histogram
STORE
start.delete(&pid);
irqdesc.delete(&pid);
return 0;
}
"""
### code substitutions
if
args
.
dist
:
bpf_text
=
bpf_text
.
replace
(
'STORE'
,
'irq_key_t key = {.slot = bpf_log2l(delta)};'
+
'bpf_probe_read(&key.name, sizeof(key.name), name);'
+
'dist.increment(key);'
)
bpf_text
=
bpf_text
.
replace
(
'STORE'
,
'irq_key_t key = {.slot = bpf_log2l(delta)};'
+
'bpf_probe_read(&key.name, sizeof(key.name), name);'
+
'dist.increment(key);'
)
else
:
bpf_text
=
bpf_text
.
replace
(
'STORE'
,
'irq_key_t key = {.slot = 0 /* ignore */};'
+
'bpf_probe_read(&key.name, sizeof(key.name), name);'
+
'u64 zero = 0, *vp = dist.lookup_or_init(&key, &zero);'
+
'(*vp) += delta;'
)
bpf_text
=
bpf_text
.
replace
(
'STORE'
,
'irq_key_t key = {.slot = 0 /* ignore */};'
+
'bpf_probe_read(&key.name, sizeof(key.name), name);'
+
'u64 zero = 0, *vp = dist.lookup_or_init(&key, &zero);'
+
'(*vp) += delta;'
)
if
debug
:
print
(
bpf_text
)
print
(
bpf_text
)
### load BPF program
b
=
BPF
(
text
=
bpf_text
)
...
...
@@ -133,23 +134,23 @@ print("Tracing hard irq event time... Hit Ctrl-C to end.")
exiting
=
0
if
args
.
interval
else
1
dist
=
b
.
get_table
(
"dist"
)
while
(
1
):
try
:
sleep
(
int
(
args
.
interval
))
except
KeyboardInterrupt
:
exiting
=
1
print
()
if
args
.
timestamp
:
print
(
"%-8s
\
n
"
%
strftime
(
"%H:%M:%S"
),
end
=
""
)
if
args
.
dist
:
dist
.
print_log2_hist
(
label
,
"hardirq"
)
else
:
print
(
"%-26s %11s"
%
(
"HARDIRQ"
,
"TOTAL_"
+
label
))
for
k
,
v
in
sorted
(
dist
.
items
(),
key
=
lambda
dist
:
dist
[
1
].
value
):
print
(
"%-26s %11d"
%
(
k
.
name
,
v
.
value
/
factor
))
dist
.
clear
()
countdown
-=
1
if
exiting
or
countdown
==
0
:
exit
()
try
:
sleep
(
int
(
args
.
interval
))
except
KeyboardInterrupt
:
exiting
=
1
print
()
if
args
.
timestamp
:
print
(
"%-8s
\
n
"
%
strftime
(
"%H:%M:%S"
),
end
=
""
)
if
args
.
dist
:
dist
.
print_log2_hist
(
label
,
"hardirq"
)
else
:
print
(
"%-26s %11s"
%
(
"HARDIRQ"
,
"TOTAL_"
+
label
))
for
k
,
v
in
sorted
(
dist
.
items
(),
key
=
lambda
dist
:
dist
[
1
].
value
):
print
(
"%-26s %11d"
%
(
k
.
name
,
v
.
value
/
factor
))
dist
.
clear
()
countdown
-=
1
if
exiting
or
countdown
==
0
:
exit
()
tools/hardirqs_example.txt
View file @
3083c85c
...
...
@@ -4,7 +4,7 @@ Demonstrations of hardirqs, the Linux eBPF/bcc version.
This program traces hard interrupts (irqs), and stores timing statistics
in-kernel for efficiency. For example:
# ./hardirqs
# ./hardirqs
Tracing hard irq event time... Hit Ctrl-C to end.
^C
HARDIRQ TOTAL_usecs
...
...
tools/killsnoop
View file @
3083c85c
#!/usr/bin/python
# @lint-avoid-python-3-compatibility-imports
#
# killsnoop
Trace signals issued by the kill() syscall.
#
For Linux, uses BCC, eBPF. Embedded C.
# killsnoop
Trace signals issued by the kill() syscall.
#
For Linux, uses BCC, eBPF. Embedded C.
#
# USAGE: killsnoop [-h] [-t] [-x] [-p PID]
#
# Copyright (c) 2015 Brendan Gregg.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 20-Sep-2015
Brendan Gregg
Created this.
# 20-Sep-2015
Brendan Gregg
Created this.
from
__future__
import
print_function
from
bcc
import
BPF
...
...
@@ -22,15 +23,15 @@ examples = """examples:
./killsnoop -p 181 # only trace PID 181
"""
parser
=
argparse
.
ArgumentParser
(
description
=
"Trace signals issued by the kill() syscall"
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
epilog
=
examples
)
description
=
"Trace signals issued by the kill() syscall"
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
epilog
=
examples
)
parser
.
add_argument
(
"-t"
,
"--timestamp"
,
action
=
"store_true"
,
help
=
"include timestamp on output"
)
help
=
"include timestamp on output"
)
parser
.
add_argument
(
"-x"
,
"--failed"
,
action
=
"store_true"
,
help
=
"only show failed opens"
)
help
=
"only show failed opens"
)
parser
.
add_argument
(
"-p"
,
"--pid"
,
help
=
"trace this PID only"
)
help
=
"trace this PID only"
)
args
=
parser
.
parse_args
()
debug
=
0
...
...
@@ -43,63 +44,63 @@ BPF_HASH(args_sig, u32, int);
int kprobe__sys_kill(struct pt_regs *ctx, int tpid, int sig)
{
u32 pid = bpf_get_current_pid_tgid();
u32 pid = bpf_get_current_pid_tgid();
FILTER
args_pid.update(&pid, &tpid);
args_sig.update(&pid, &sig);
FILTER
args_pid.update(&pid, &tpid);
args_sig.update(&pid, &sig);
return 0;
return 0;
};
int kretprobe__sys_kill(struct pt_regs *ctx)
{
int *tpidp, *sigp, ret = ctx->ax;
u32 pid = bpf_get_current_pid_tgid();
int *tpidp, *sigp, ret = ctx->ax;
u32 pid = bpf_get_current_pid_tgid();
tpidp = args_pid.lookup(&pid);
sigp = args_sig.lookup(&pid);
if (tpidp == 0 || sigp == 0) {
return 0;
// missed entry
}
tpidp = args_pid.lookup(&pid);
sigp = args_sig.lookup(&pid);
if (tpidp == 0 || sigp == 0) {
return 0;
// missed entry
}
bpf_trace_printk("%d %d %d
\
\
n", *tpidp, *sigp, ret);
args_pid.delete(&pid);
args_sig.delete(&pid);
bpf_trace_printk("%d %d %d
\
\
n", *tpidp, *sigp, ret);
args_pid.delete(&pid);
args_sig.delete(&pid);
return 0;
return 0;
}
"""
if
args
.
pid
:
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
'if (pid != %s) { return 0; }'
%
args
.
pid
)
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
'if (pid != %s) { return 0; }'
%
args
.
pid
)
else
:
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
''
)
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
''
)
if
debug
:
print
(
bpf_text
)
print
(
bpf_text
)
# initialize BPF
b
=
BPF
(
text
=
bpf_text
)
# header
if
args
.
timestamp
:
print
(
"%-14s"
%
(
"TIME(s)"
),
end
=
""
)
print
(
"%-14s"
%
(
"TIME(s)"
),
end
=
""
)
print
(
"%-6s %-16s %-4s %-6s %s"
%
(
"PID"
,
"COMM"
,
"SIG"
,
"TPID"
,
"RESULT"
))
start_ts
=
0
# format output
while
1
:
(
task
,
pid
,
cpu
,
flags
,
ts
,
msg
)
=
b
.
trace_fields
()
(
tpid_s
,
sig_s
,
ret_s
)
=
msg
.
split
(
" "
)
ret
=
int
(
ret_s
)
if
(
args
.
failed
and
(
ret
>=
0
)):
continue
# print columns
if
args
.
timestamp
:
if
start_ts
==
0
:
start_ts
=
ts
print
(
"%-14.9f"
%
(
ts
-
start_ts
),
end
=
""
)
print
(
"%-6d %-16s %-4s %-6s %s"
%
(
pid
,
task
,
sig_s
,
tpid_s
,
ret_s
))
(
task
,
pid
,
cpu
,
flags
,
ts
,
msg
)
=
b
.
trace_fields
()
(
tpid_s
,
sig_s
,
ret_s
)
=
msg
.
split
(
" "
)
ret
=
int
(
ret_s
)
if
(
args
.
failed
and
(
ret
>=
0
)):
continue
# print columns
if
args
.
timestamp
:
if
start_ts
==
0
:
start_ts
=
ts
print
(
"%-14.9f"
%
(
ts
-
start_ts
),
end
=
""
)
print
(
"%-6d %-16s %-4s %-6s %s"
%
(
pid
,
task
,
sig_s
,
tpid_s
,
ret_s
))
tools/killsnoop_example.txt
View file @
3083c85c
...
...
@@ -3,7 +3,7 @@ Demonstrations of killsnoop, the Linux eBPF/bcc version.
This traces signals sent via the kill() syscall. For example:
# ./killsnoop
# ./killsnoop
PID COMM SIG TPID RESULT
17064 bash 9 27682 0
17064 bash 9 27682 -3
...
...
tools/opensnoop
View file @
3083c85c
#!/usr/bin/python
# @lint-avoid-python-3-compatibility-imports
#
# opensnoop
Trace open() syscalls.
#
For Linux, uses BCC, eBPF. Embedded C.
# opensnoop
Trace open() syscalls.
#
For Linux, uses BCC, eBPF. Embedded C.
#
# USAGE: opensnoop [-h] [-t] [-x] [-p PID]
#
# Copyright (c) 2015 Brendan Gregg.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 17-Sep-2015
Brendan Gregg
Created this.
# 17-Sep-2015
Brendan Gregg
Created this.
from
__future__
import
print_function
from
bcc
import
BPF
...
...
@@ -22,15 +23,15 @@ examples = """examples:
./opensnoop -p 181 # only trace PID 181
"""
parser
=
argparse
.
ArgumentParser
(
description
=
"Trace open() syscalls"
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
epilog
=
examples
)
description
=
"Trace open() syscalls"
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
epilog
=
examples
)
parser
.
add_argument
(
"-t"
,
"--timestamp"
,
action
=
"store_true"
,
help
=
"include timestamp on output"
)
help
=
"include timestamp on output"
)
parser
.
add_argument
(
"-x"
,
"--failed"
,
action
=
"store_true"
,
help
=
"only show failed opens"
)
help
=
"only show failed opens"
)
parser
.
add_argument
(
"-p"
,
"--pid"
,
help
=
"trace this PID only"
)
help
=
"trace this PID only"
)
args
=
parser
.
parse_args
()
debug
=
0
...
...
@@ -42,68 +43,70 @@ BPF_HASH(args_filename, u32, const char *);
int kprobe__sys_open(struct pt_regs *ctx, const char __user *filename)
{
u32 pid = bpf_get_current_pid_tgid();
u32 pid = bpf_get_current_pid_tgid();
FILTER
args_filename.update(&pid, &filename);
FILTER
args_filename.update(&pid, &filename);
return 0;
return 0;
};
int kretprobe__sys_open(struct pt_regs *ctx)
{
const char **filenamep;
int ret = ctx->ax;
u32 pid = bpf_get_current_pid_tgid();
const char **filenamep;
int ret = ctx->ax;
u32 pid = bpf_get_current_pid_tgid();
filenamep = args_filename.lookup(&pid);
if (filenamep == 0) {
// missed entry
return 0;
}
filenamep = args_filename.lookup(&pid);
if (filenamep == 0) {
// missed entry
return 0;
}
bpf_trace_printk("%s %d
\
\
n", *filenamep, ret);
args_filename.delete(&pid);
bpf_trace_printk("%s %d
\
\
n", *filenamep, ret);
args_filename.delete(&pid);
return 0;
return 0;
}
"""
if
args
.
pid
:
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
'if (pid != %s) { return 0; }'
%
args
.
pid
)
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
'if (pid != %s) { return 0; }'
%
args
.
pid
)
else
:
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
''
)
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
''
)
if
debug
:
print
(
bpf_text
)
print
(
bpf_text
)
# initialize BPF
b
=
BPF
(
text
=
bpf_text
)
# header
if
args
.
timestamp
:
print
(
"%-14s"
%
(
"TIME(s)"
),
end
=
""
)
print
(
"%-14s"
%
(
"TIME(s)"
),
end
=
""
)
print
(
"%-6s %-16s %4s %3s %s"
%
(
"PID"
,
"COMM"
,
"FD"
,
"ERR"
,
"PATH"
))
start_ts
=
0
# format output
while
1
:
(
task
,
pid
,
cpu
,
flags
,
ts
,
msg
)
=
b
.
trace_fields
()
(
filename
,
ret_s
)
=
msg
.
split
(
" "
)
ret
=
int
(
ret_s
)
if
(
args
.
failed
and
(
ret
>=
0
)):
continue
# split return value into FD and errno columns
if
ret
>=
0
:
fd_s
=
ret
;
err
=
0
else
:
fd_s
=
"-1"
;
err
=
-
ret
# print columns
if
args
.
timestamp
:
if
start_ts
==
0
:
start_ts
=
ts
print
(
"%-14.9f"
%
(
ts
-
start_ts
),
end
=
""
)
print
(
"%-6d %-16s %4s %3s %s"
%
(
pid
,
task
,
fd_s
,
err
,
filename
))
(
task
,
pid
,
cpu
,
flags
,
ts
,
msg
)
=
b
.
trace_fields
()
(
filename
,
ret_s
)
=
msg
.
split
(
" "
)
ret
=
int
(
ret_s
)
if
(
args
.
failed
and
(
ret
>=
0
)):
continue
# split return value into FD and errno columns
if
ret
>=
0
:
fd_s
=
ret
err
=
0
else
:
fd_s
=
"-1"
err
=
-
ret
# print columns
if
args
.
timestamp
:
if
start_ts
==
0
:
start_ts
=
ts
print
(
"%-14.9f"
%
(
ts
-
start_ts
),
end
=
""
)
print
(
"%-6d %-16s %4s %3s %s"
%
(
pid
,
task
,
fd_s
,
err
,
filename
))
tools/opensnoop_example.txt
View file @
3083c85c
...
...
@@ -5,38 +5,38 @@ opensnoop traces the open() syscall system-wide, and prints various details.
Example output:
# ./opensnoop
PID COMM
FD ERR PATH
17326 <...>
7 0 /sys/kernel/debug/tracing/trace_pipe
1576 snmpd
9 0 /proc/net/dev
1576 snmpd
11 0 /proc/net/if_inet6
1576 snmpd
11 0 /proc/sys/net/ipv4/neigh/eth0/retrans_time_ms
1576 snmpd
11 0 /proc/sys/net/ipv6/neigh/eth0/retrans_time_ms
1576 snmpd
11 0 /proc/sys/net/ipv6/conf/eth0/forwarding
1576 snmpd
11 0 /proc/sys/net/ipv6/neigh/eth0/base_reachable_time_ms
1576 snmpd
11 0 /proc/sys/net/ipv4/neigh/lo/retrans_time_ms
1576 snmpd
11 0 /proc/sys/net/ipv6/neigh/lo/retrans_time_ms
1576 snmpd
11 0 /proc/sys/net/ipv6/conf/lo/forwarding
1576 snmpd
11 0 /proc/sys/net/ipv6/neigh/lo/base_reachable_time_ms
1576 snmpd
9 0 /proc/diskstats
1576 snmpd
9 0 /proc/stat
1576 snmpd
9 0 /proc/vmstat
1956 supervise
9 0 supervise/status.new
1956 supervise
9 0 supervise/status.new
17358 run
3 0 /etc/ld.so.cache
17358 run
3 0 /lib/x86_64-linux-gnu/libtinfo.so.5
17358 run
3 0 /lib/x86_64-linux-gnu/libdl.so.2
17358 run
3 0 /lib/x86_64-linux-gnu/libc.so.6
17358 run
-1 6 /dev/tty
17358 run
3 0 /proc/meminfo
17358 run
3 0 /etc/nsswitch.conf
17358 run
3 0 /etc/ld.so.cache
17358 run
3 0 /lib/x86_64-linux-gnu/libnss_compat.so.2
17358 run
3 0 /lib/x86_64-linux-gnu/libnsl.so.1
17358 run
3 0 /etc/ld.so.cache
17358 run
3 0 /lib/x86_64-linux-gnu/libnss_nis.so.2
17358 run
3 0 /lib/x86_64-linux-gnu/libnss_files.so.2
17358 run
3 0 /etc/passwd
17358 run
3 0 ./run
PID COMM FD ERR PATH
17326 <...> 7 0 /sys/kernel/debug/tracing/trace_pipe
1576 snmpd 9 0 /proc/net/dev
1576 snmpd 11 0 /proc/net/if_inet6
1576 snmpd 11 0 /proc/sys/net/ipv4/neigh/eth0/retrans_time_ms
1576 snmpd 11 0 /proc/sys/net/ipv6/neigh/eth0/retrans_time_ms
1576 snmpd 11 0 /proc/sys/net/ipv6/conf/eth0/forwarding
1576 snmpd 11 0 /proc/sys/net/ipv6/neigh/eth0/base_reachable_time_ms
1576 snmpd 11 0 /proc/sys/net/ipv4/neigh/lo/retrans_time_ms
1576 snmpd 11 0 /proc/sys/net/ipv6/neigh/lo/retrans_time_ms
1576 snmpd 11 0 /proc/sys/net/ipv6/conf/lo/forwarding
1576 snmpd 11 0 /proc/sys/net/ipv6/neigh/lo/base_reachable_time_ms
1576 snmpd 9 0 /proc/diskstats
1576 snmpd 9 0 /proc/stat
1576 snmpd 9 0 /proc/vmstat
1956 supervise 9 0 supervise/status.new
1956 supervise 9 0 supervise/status.new
17358 run 3 0 /etc/ld.so.cache
17358 run 3 0 /lib/x86_64-linux-gnu/libtinfo.so.5
17358 run 3 0 /lib/x86_64-linux-gnu/libdl.so.2
17358 run 3 0 /lib/x86_64-linux-gnu/libc.so.6
17358 run -1 6 /dev/tty
17358 run 3 0 /proc/meminfo
17358 run 3 0 /etc/nsswitch.conf
17358 run 3 0 /etc/ld.so.cache
17358 run 3 0 /lib/x86_64-linux-gnu/libnss_compat.so.2
17358 run 3 0 /lib/x86_64-linux-gnu/libnsl.so.1
17358 run 3 0 /etc/ld.so.cache
17358 run 3 0 /lib/x86_64-linux-gnu/libnss_nis.so.2
17358 run 3 0 /lib/x86_64-linux-gnu/libnss_files.so.2
17358 run 3 0 /etc/passwd
17358 run 3 0 ./run
^C
While tracing, the snmpd process opened various /proc files (reading metrics),
...
...
@@ -68,25 +68,19 @@ second.
The -x option only prints failed opens:
# ./opensnoop -x
PID COMM FD ERR PATH
18372 run -1 6 /dev/tty
18373 run -1 6 /dev/tty
18373 multilog -1 13 lock
18372 multilog -1 13 lock
18384 df -1 2 /usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo
18384 df -1 2 /usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo
18384 df -1 2 /usr/share/locale/en_US/LC_MESSAGES/coreutils.mo
18384 df -1 2 /usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo
18384 df -1 2 /usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo
18384 df -1 2 /usr/share/locale/en/LC_MESSAGES/coreutils.mo
18384 df -1 2 /usr/share/locale-langpack/en_US.UTF-8/LC_MESSAGES/coreutils.mo
18384 df -1 2 /usr/share/locale-langpack/en_US.utf8/LC_MESSAGES/coreutils.mo
18384 df -1 2 /usr/share/locale-langpack/en_US/LC_MESSAGES/coreutils.mo
18384 df -1 2 /usr/share/locale-langpack/en.UTF-8/LC_MESSAGES/coreutils.mo
18384 df -1 2 /usr/share/locale-langpack/en.utf8/LC_MESSAGES/coreutils.mo
18384 df -1 2 /usr/share/locale-langpack/en/LC_MESSAGES/coreutils.mo
18385 run -1 6 /dev/tty
18386 run -1 6 /dev/tty
PID COMM FD ERR PATH
18372 run -1 6 /dev/tty
18373 run -1 6 /dev/tty
18373 multilog -1 13 lock
18372 multilog -1 13 lock
18384 df -1 2 /usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo
18384 df -1 2 /usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo
18384 df -1 2 /usr/share/locale/en_US/LC_MESSAGES/coreutils.mo
18384 df -1 2 /usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo
18384 df -1 2 /usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo
18384 df -1 2 /usr/share/locale/en/LC_MESSAGES/coreutils.mo
18385 run -1 6 /dev/tty
18386 run -1 6 /dev/tty
This caught a df command failing to open a coreutils.mo file, and trying from
different directories.
...
...
tools/pidpersec
View file @
3083c85c
#!/usr/bin/python
#
vim: ts=8 noet sw=8
#
@lint-avoid-python-3-compatibility-imports
#
# pidpersec
Count new processes (via fork).
#
For Linux, uses BCC, eBPF. See .c file.
# pidpersec
Count new processes (via fork).
#
For Linux, uses BCC, eBPF. See .c file.
#
# USAGE: pidpersec
#
...
...
@@ -11,14 +11,14 @@
# Copyright (c) 2015 Brendan Gregg.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 11-Aug-2015
Brendan Gregg
Created this.
# 11-Aug-2015
Brendan Gregg
Created this.
from
bcc
import
BPF
from
ctypes
import
c_
ushort
,
c_int
,
c_ulonglong
from
ctypes
import
c_
int
from
time
import
sleep
,
strftime
# load BPF program
b
=
BPF
(
src_file
=
"pidpersec.c"
)
b
=
BPF
(
src_file
=
"pidpersec.c"
)
b
.
attach_kprobe
(
event
=
"sched_fork"
,
fn_name
=
"do_count"
)
# stat indexes
...
...
@@ -29,11 +29,11 @@ print("Tracing... Ctrl-C to end.")
# output
while
(
1
):
try
:
sleep
(
1
)
except
KeyboardInterrupt
:
exit
()
try
:
sleep
(
1
)
except
KeyboardInterrupt
:
exit
()
print
(
"%s: PIDs/sec: %d"
%
(
strftime
(
"%H:%M:%S"
),
b
[
"stats"
][
S_COUNT
].
value
))
b
[
"stats"
].
clear
()
print
(
"%s: PIDs/sec: %d"
%
(
strftime
(
"%H:%M:%S"
),
b
[
"stats"
][
S_COUNT
].
value
))
b
[
"stats"
].
clear
()
tools/softirqs
View file @
3083c85c
#!/usr/bin/python
# @lint-avoid-python-3-compatibility-imports
#
# softirqs
Summarize soft IRQ (interrupt) event time.
#
For Linux, uses BCC, eBPF.
# softirqs
Summarize soft IRQ (interrupt) event time.
#
For Linux, uses BCC, eBPF.
#
# USAGE: softirqs [-h] [-T] [-N] [-d] [interval] [count]
#
# Copyright (c) 2015 Brendan Gregg.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 20-Oct-2015
Brendan Gregg
Created this.
# 20-Oct-2015
Brendan Gregg
Created this.
from
__future__
import
print_function
from
bcc
import
BPF
...
...
@@ -23,27 +24,27 @@ examples = """examples:
./softirqs -NT 1 # 1s summaries, nanoseconds, and timestamps
"""
parser
=
argparse
.
ArgumentParser
(
description
=
"Summarize soft irq event time as histograms"
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
epilog
=
examples
)
description
=
"Summarize soft irq event time as histograms"
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
epilog
=
examples
)
parser
.
add_argument
(
"-T"
,
"--timestamp"
,
action
=
"store_true"
,
help
=
"include timestamp on output"
)
help
=
"include timestamp on output"
)
parser
.
add_argument
(
"-N"
,
"--nanoseconds"
,
action
=
"store_true"
,
help
=
"output in nanoseconds"
)
help
=
"output in nanoseconds"
)
parser
.
add_argument
(
"-d"
,
"--dist"
,
action
=
"store_true"
,
help
=
"show distributions as histograms"
)
help
=
"show distributions as histograms"
)
parser
.
add_argument
(
"interval"
,
nargs
=
"?"
,
default
=
99999999
,
help
=
"output interval, in seconds"
)
help
=
"output interval, in seconds"
)
parser
.
add_argument
(
"count"
,
nargs
=
"?"
,
default
=
99999999
,
help
=
"number of outputs"
)
help
=
"number of outputs"
)
args
=
parser
.
parse_args
()
countdown
=
int
(
args
.
count
)
if
args
.
nanoseconds
:
factor
=
1
label
=
"nsecs"
factor
=
1
label
=
"nsecs"
else
:
factor
=
1000
label
=
"usecs"
factor
=
1000
label
=
"usecs"
debug
=
0
### define BPF program
...
...
@@ -51,8 +52,8 @@ bpf_text = """
#include <uapi/linux/ptrace.h>
typedef struct irq_key {
u64 ip;
u64 slot;
u64 ip;
u64 slot;
} irq_key_t;
BPF_HASH(start, u32);
BPF_HASH(iptr, u32);
...
...
@@ -61,48 +62,48 @@ BPF_HISTOGRAM(dist, irq_key_t);
// time IRQ
int trace_start(struct pt_regs *ctx)
{
u32 pid = bpf_get_current_pid_tgid();
u64 ip = ctx->ip, ts = bpf_ktime_get_ns();
start.update(&pid, &ts);
iptr.update(&pid, &ip);
return 0;
u32 pid = bpf_get_current_pid_tgid();
u64 ip = ctx->ip, ts = bpf_ktime_get_ns();
start.update(&pid, &ts);
iptr.update(&pid, &ip);
return 0;
}
int trace_completion(struct pt_regs *ctx)
{
u64 *tsp, delta, ip, *ipp;
u32 pid = bpf_get_current_pid_tgid();
// fetch timestamp and calculate delta
tsp = start.lookup(&pid);
ipp = iptr.lookup(&pid);
if (tsp == 0 || ipp == 0) {
return 0;
// missed start
}
delta = bpf_ktime_get_ns() - *tsp;
ip = *ipp;
// store as sum or histogram
STORE
start.delete(&pid);
iptr.delete(&pid);
return 0;
u64 *tsp, delta, ip, *ipp;
u32 pid = bpf_get_current_pid_tgid();
// fetch timestamp and calculate delta
tsp = start.lookup(&pid);
ipp = iptr.lookup(&pid);
if (tsp == 0 || ipp == 0) {
return 0;
// missed start
}
delta = bpf_ktime_get_ns() - *tsp;
ip = *ipp;
// store as sum or histogram
STORE
start.delete(&pid);
iptr.delete(&pid);
return 0;
}
"""
### code substitutions
if
args
.
dist
:
bpf_text
=
bpf_text
.
replace
(
'STORE'
,
'irq_key_t key = {.ip = ip, .slot = bpf_log2l(delta)};'
+
'dist.increment(key);'
)
bpf_text
=
bpf_text
.
replace
(
'STORE'
,
'irq_key_t key = {.ip = ip, .slot = bpf_log2l(delta)};'
+
'dist.increment(key);'
)
else
:
bpf_text
=
bpf_text
.
replace
(
'STORE'
,
'irq_key_t key = {.ip = ip, .slot = 0 /* ignore */};'
+
'u64 zero = 0, *vp = dist.lookup_or_init(&key, &zero);'
+
'(*vp) += delta;'
)
bpf_text
=
bpf_text
.
replace
(
'STORE'
,
'irq_key_t key = {.ip = ip, .slot = 0 /* ignore */};'
+
'u64 zero = 0, *vp = dist.lookup_or_init(&key, &zero);'
+
'(*vp) += delta;'
)
if
debug
:
print
(
bpf_text
)
print
(
bpf_text
)
### load BPF program
b
=
BPF
(
text
=
bpf_text
)
...
...
@@ -114,8 +115,8 @@ for softirqfunc in ("blk_iopoll_softirq", "blk_done_softirq",
"rcu_process_callbacks"
,
"run_rebalance_domains"
,
"tasklet_action"
,
"tasklet_hi_action"
,
"run_timer_softirq"
,
"net_tx_action"
,
"net_rx_action"
):
b
.
attach_kprobe
(
event
=
softirqfunc
,
fn_name
=
"trace_start"
)
b
.
attach_kretprobe
(
event
=
softirqfunc
,
fn_name
=
"trace_completion"
)
b
.
attach_kprobe
(
event
=
softirqfunc
,
fn_name
=
"trace_start"
)
b
.
attach_kretprobe
(
event
=
softirqfunc
,
fn_name
=
"trace_completion"
)
print
(
"Tracing soft irq event time... Hit Ctrl-C to end."
)
...
...
@@ -123,23 +124,23 @@ print("Tracing soft irq event time... Hit Ctrl-C to end.")
exiting
=
0
if
args
.
interval
else
1
dist
=
b
.
get_table
(
"dist"
)
while
(
1
):
try
:
sleep
(
int
(
args
.
interval
))
except
KeyboardInterrupt
:
exiting
=
1
print
()
if
args
.
timestamp
:
print
(
"%-8s
\
n
"
%
strftime
(
"%H:%M:%S"
),
end
=
""
)
if
args
.
dist
:
dist
.
print_log2_hist
(
label
,
"softirq"
,
section_print_fn
=
b
.
ksym
)
else
:
print
(
"%-26s %11s"
%
(
"SOFTIRQ"
,
"TOTAL_"
+
label
))
for
k
,
v
in
sorted
(
dist
.
items
(),
key
=
lambda
dist
:
dist
[
1
].
value
):
print
(
"%-26s %11d"
%
(
b
.
ksym
(
k
.
ip
),
v
.
value
/
factor
))
dist
.
clear
()
countdown
-=
1
if
exiting
or
countdown
==
0
:
exit
()
try
:
sleep
(
int
(
args
.
interval
))
except
KeyboardInterrupt
:
exiting
=
1
print
()
if
args
.
timestamp
:
print
(
"%-8s
\
n
"
%
strftime
(
"%H:%M:%S"
),
end
=
""
)
if
args
.
dist
:
dist
.
print_log2_hist
(
label
,
"softirq"
,
section_print_fn
=
b
.
ksym
)
else
:
print
(
"%-26s %11s"
%
(
"SOFTIRQ"
,
"TOTAL_"
+
label
))
for
k
,
v
in
sorted
(
dist
.
items
(),
key
=
lambda
dist
:
dist
[
1
].
value
):
print
(
"%-26s %11d"
%
(
b
.
ksym
(
k
.
ip
),
v
.
value
/
factor
))
dist
.
clear
()
countdown
-=
1
if
exiting
or
countdown
==
0
:
exit
()
tools/softirqs_example.txt
View file @
3083c85c
...
...
@@ -4,7 +4,7 @@ Demonstrations of softirqs, the Linux eBPF/bcc version.
This program traces soft interrupts (irqs), and stores timing statistics
in-kernel for efficiency. For example:
# ./softirqs
# ./softirqs
Tracing soft irq event time... Hit Ctrl-C to end.
^C
SOFTIRQ TOTAL_usecs
...
...
tools/syncsnoop
View file @
3083c85c
#!/usr/bin/python
# @lint-avoid-python-3-compatibility-imports
#
# syncsnoop
Trace sync() syscall.
#
For Linux, uses BCC, eBPF. Embedded C.
# syncsnoop
Trace sync() syscall.
#
For Linux, uses BCC, eBPF. Embedded C.
#
# Written as a basic example of BCC trace & reformat. See
# examples/hello_world.py for a BCC trace with default output example.
...
...
@@ -9,15 +10,15 @@
# Copyright (c) 2015 Brendan Gregg.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 13-Aug-2015
Brendan Gregg
Created this.
# 13-Aug-2015
Brendan Gregg
Created this.
from
__future__
import
print_function
from
bcc
import
BPF
# load BPF program
b
=
BPF
(
text
=
"""
b
=
BPF
(
text
=
"""
void kprobe__sys_sync(void *ctx) {
bpf_trace_printk("sync()
\
\
n");
bpf_trace_printk("sync()
\
\
n");
};
"""
)
...
...
@@ -26,5 +27,5 @@ print("%-18s %s" % ("TIME(s)", "CALL"))
# format output
while
1
:
(
task
,
pid
,
cpu
,
flags
,
ts
,
msg
)
=
b
.
trace_fields
()
print
(
"%-18.9f %s"
%
(
ts
,
msg
))
(
task
,
pid
,
cpu
,
flags
,
ts
,
msg
)
=
b
.
trace_fields
()
print
(
"%-18.9f %s"
%
(
ts
,
msg
))
tools/syncsnoop_example.txt
View file @
3083c85c
...
...
@@ -3,7 +3,7 @@ Demonstrations of syncsnoop, the Linux eBPF/bcc version.
This program traces calls to the kernel sync() routine, with basic timestamps:
# ./syncsnoop
# ./syncsnoop
TIME(s) CALL
16458148.611952 sync()
16458151.533709 sync()
...
...
tools/tcpaccept
View file @
3083c85c
#!/usr/bin/python
# @lint-avoid-python-3-compatibility-imports
#
# tcpaccept
Trace TCP accept()s.
#
For Linux, uses BCC, eBPF. Embedded C.
# tcpaccept
Trace TCP accept()s.
#
For Linux, uses BCC, eBPF. Embedded C.
#
# USAGE: tcpaccept [-h] [-t] [-p PID]
#
...
...
@@ -15,7 +16,7 @@
# Copyright (c) 2015 Brendan Gregg.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 13-Oct-2015
Brendan Gregg
Created this.
# 13-Oct-2015
Brendan Gregg
Created this.
from
__future__
import
print_function
from
bcc
import
BPF
...
...
@@ -28,13 +29,13 @@ examples = """examples:
./tcpaccept -p 181 # only trace PID 181
"""
parser
=
argparse
.
ArgumentParser
(
description
=
"Trace TCP accepts"
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
epilog
=
examples
)
description
=
"Trace TCP accepts"
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
epilog
=
examples
)
parser
.
add_argument
(
"-t"
,
"--timestamp"
,
action
=
"store_true"
,
help
=
"include timestamp on output"
)
help
=
"include timestamp on output"
)
parser
.
add_argument
(
"-p"
,
"--pid"
,
help
=
"trace this PID only"
)
help
=
"trace this PID only"
)
args
=
parser
.
parse_args
()
debug
=
0
...
...
@@ -46,88 +47,88 @@ bpf_text = """
int kretprobe__inet_csk_accept(struct pt_regs *ctx)
{
struct sock *newsk = (struct sock *)ctx->ax;
u32 pid = bpf_get_current_pid_tgid();
if (newsk == NULL)
return 0;
// check this is TCP
u8 protocol = 0;
// workaround for reading the sk_protocol bitfield:
bpf_probe_read(&protocol, 1, (void *)((long)&newsk->sk_wmem_queued) - 3);
if (protocol != IPPROTO_TCP)
return 0;
// pull in details
u16 family = 0, lport = 0;
u32 saddr = 0, daddr = 0;
bpf_probe_read(&family, sizeof(family), &newsk->__sk_common.skc_family);
bpf_probe_read(&lport, sizeof(lport), &newsk->__sk_common.skc_num);
if (family == AF_INET) {
bpf_probe_read(&saddr, sizeof(saddr),
&newsk->__sk_common.skc_rcv_saddr);
bpf_probe_read(&daddr, sizeof(daddr),
&newsk->__sk_common.skc_daddr);
// output
bpf_trace_printk("4 %x %x %d
\
\
n", daddr, saddr, lport);
} else if (family == AF_INET6) {
// just grab the last 4 bytes for now
bpf_probe_read(&saddr, sizeof(saddr),
&newsk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32[3]);
bpf_probe_read(&daddr, sizeof(daddr),
&newsk->__sk_common.skc_v6_daddr.in6_u.u6_addr32[3]);
// output and flip byte order of addresses
bpf_trace_printk("6 %x %x %d
\
\
n", bpf_ntohl(daddr),
bpf_ntohl(saddr), lport);
}
// else drop
return 0;
struct sock *newsk = (struct sock *)ctx->ax;
u32 pid = bpf_get_current_pid_tgid();
if (newsk == NULL)
return 0;
// check this is TCP
u8 protocol = 0;
// workaround for reading the sk_protocol bitfield:
bpf_probe_read(&protocol, 1, (void *)((long)&newsk->sk_wmem_queued) - 3);
if (protocol != IPPROTO_TCP)
return 0;
// pull in details
u16 family = 0, lport = 0;
u32 saddr = 0, daddr = 0;
bpf_probe_read(&family, sizeof(family), &newsk->__sk_common.skc_family);
bpf_probe_read(&lport, sizeof(lport), &newsk->__sk_common.skc_num);
if (family == AF_INET) {
bpf_probe_read(&saddr, sizeof(saddr),
&newsk->__sk_common.skc_rcv_saddr);
bpf_probe_read(&daddr, sizeof(daddr),
&newsk->__sk_common.skc_daddr);
// output
bpf_trace_printk("4 %x %x %d
\
\
n", daddr, saddr, lport);
} else if (family == AF_INET6) {
// just grab the last 4 bytes for now
bpf_probe_read(&saddr, sizeof(saddr),
&newsk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32[3]);
bpf_probe_read(&daddr, sizeof(daddr),
&newsk->__sk_common.skc_v6_daddr.in6_u.u6_addr32[3]);
// output and flip byte order of addresses
bpf_trace_printk("6 %x %x %d
\
\
n", bpf_ntohl(daddr),
bpf_ntohl(saddr), lport);
}
// else drop
return 0;
}
"""
# code substitutions
if
args
.
pid
:
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
'if (pid != %s) { return 0; }'
%
args
.
pid
)
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
'if (pid != %s) { return 0; }'
%
args
.
pid
)
else
:
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
''
)
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
''
)
if
debug
:
print
(
bpf_text
)
print
(
bpf_text
)
# initialize BPF
b
=
BPF
(
text
=
bpf_text
)
# header
if
args
.
timestamp
:
print
(
"%-9s"
%
(
"TIME(s)"
),
end
=
""
)
print
(
"%-9s"
%
(
"TIME(s)"
),
end
=
""
)
print
(
"%-6s %-12s %-2s %-16s %-16s %-4s"
%
(
"PID"
,
"COMM"
,
"IP"
,
"RADDR"
,
"LADDR"
,
"LPORT"
))
start_ts
=
0
def
inet_ntoa
(
addr
):
dq
=
''
for
i
in
range
(
0
,
4
):
dq
=
dq
+
str
(
addr
&
0xff
)
if
(
i
!=
3
):
dq
=
dq
+
'.'
addr
=
addr
>>
8
return
dq
dq
=
''
for
i
in
range
(
0
,
4
):
dq
=
dq
+
str
(
addr
&
0xff
)
if
(
i
!=
3
):
dq
=
dq
+
'.'
addr
=
addr
>>
8
return
dq
# format output
while
1
:
(
task
,
pid
,
cpu
,
flags
,
ts
,
msg
)
=
b
.
trace_fields
()
(
ip_s
,
raddr_hs
,
laddr_hs
,
lport_s
)
=
msg
.
split
(
" "
)
if
args
.
timestamp
:
if
start_ts
==
0
:
start_ts
=
ts
print
(
"%-9.3f"
%
(
ts
-
start_ts
),
end
=
""
)
print
(
"%-6d %-12.12s %-2s %-16s %-16s %-4s"
%
(
pid
,
task
,
ip_s
,
inet_ntoa
(
int
(
raddr_hs
,
16
))
if
ip_s
==
"4"
else
"..."
+
raddr_hs
,
inet_ntoa
(
int
(
laddr_hs
,
16
))
if
ip_s
==
"4"
else
"..."
+
laddr_hs
,
lport_s
))
(
task
,
pid
,
cpu
,
flags
,
ts
,
msg
)
=
b
.
trace_fields
()
(
ip_s
,
raddr_hs
,
laddr_hs
,
lport_s
)
=
msg
.
split
(
" "
)
if
args
.
timestamp
:
if
start_ts
==
0
:
start_ts
=
ts
print
(
"%-9.3f"
%
(
ts
-
start_ts
),
end
=
""
)
print
(
"%-6d %-12.12s %-2s %-16s %-16s %-4s"
%
(
pid
,
task
,
ip_s
,
inet_ntoa
(
int
(
raddr_hs
,
16
))
if
ip_s
==
"4"
else
"..."
+
raddr_hs
,
inet_ntoa
(
int
(
laddr_hs
,
16
))
if
ip_s
==
"4"
else
"..."
+
laddr_hs
,
lport_s
))
tools/tcpaccept_example.txt
View file @
3083c85c
...
...
@@ -7,8 +7,8 @@ addresses changed to protect the innocent):
# ./tcpaccept
PID COMM IP RADDR LADDR LPORT
907 sshd 4 192.168.56.1 192.168.56.102 22
907 sshd 4 127.0.0.1 127.0.0.1 22
907 sshd 4 192.168.56.1 192.168.56.102 22
907 sshd 4 127.0.0.1 127.0.0.1 22
5389 perl 6 ...fec0ae21 ...fec0ae21 7001
This output shows three connections, two to PID 907, an "sshd" process listening
...
...
@@ -30,9 +30,9 @@ The -t option prints a timestamp column:
# ./tcpaccept -t
TIME(s) PID COMM IP RADDR LADDR LPORT
0.000 907 sshd 4 127.0.0.1 127.0.0.1 22
0.992 907 sshd 4 127.0.0.1 127.0.0.1 22
1.984 907 sshd 4 127.0.0.1 127.0.0.1 22
0.000 907 sshd 4 127.0.0.1 127.0.0.1 22
0.992 907 sshd 4 127.0.0.1 127.0.0.1 22
1.984 907 sshd 4 127.0.0.1 127.0.0.1 22
USAGE message:
...
...
tools/tcpconnect
View file @
3083c85c
#!/usr/bin/python
# @lint-avoid-python-3-compatibility-imports
#
# tcpconnect
Trace TCP connect()s.
#
For Linux, uses BCC, eBPF. Embedded C.
# tcpconnect
Trace TCP connect()s.
#
For Linux, uses BCC, eBPF. Embedded C.
#
# USAGE: tcpconnect [-h] [-t] [-p PID]
#
...
...
@@ -10,7 +11,7 @@
# Copyright (c) 2015 Brendan Gregg.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 25-Sep-2015
Brendan Gregg
Created this.
# 25-Sep-2015
Brendan Gregg
Created this.
from
__future__
import
print_function
from
bcc
import
BPF
...
...
@@ -23,13 +24,13 @@ examples = """examples:
./tcpconnect -p 181 # only trace PID 181
"""
parser
=
argparse
.
ArgumentParser
(
description
=
"Trace TCP connects"
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
epilog
=
examples
)
description
=
"Trace TCP connects"
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
,
epilog
=
examples
)
parser
.
add_argument
(
"-t"
,
"--timestamp"
,
action
=
"store_true"
,
help
=
"include timestamp on output"
)
help
=
"include timestamp on output"
)
parser
.
add_argument
(
"-p"
,
"--pid"
,
help
=
"trace this PID only"
)
help
=
"trace this PID only"
)
args
=
parser
.
parse_args
()
debug
=
0
...
...
@@ -43,82 +44,82 @@ BPF_HASH(currsock, u32, struct sock *);
int trace_connect_entry(struct pt_regs *ctx, struct sock *sk)
{
u32 pid = bpf_get_current_pid_tgid();
FILTER
u32 pid = bpf_get_current_pid_tgid();
FILTER
// stash the sock ptr for lookup on return
currsock.update(&pid, &sk);
// stash the sock ptr for lookup on return
currsock.update(&pid, &sk);
return 0;
return 0;
};
static int trace_connect_return(struct pt_regs *ctx, short ipver)
{
int ret = ctx->ax;
u32 pid = bpf_get_current_pid_tgid();
struct sock **skpp;
skpp = currsock.lookup(&pid);
if (skpp == 0) {
return 0;
// missed entry
}
if (ret != 0) {
// failed to send SYNC packet, may not have populated
// socket __sk_common.{skc_rcv_saddr, ...}
currsock.delete(&pid);
return 0;
}
// pull in details
struct sock *skp = *skpp;
u32 saddr = 0, daddr = 0;
u16 dport = 0;
bpf_probe_read(&dport, sizeof(dport), &skp->__sk_common.skc_dport);
if (ipver == 4) {
bpf_probe_read(&saddr, sizeof(saddr),
&skp->__sk_common.skc_rcv_saddr);
bpf_probe_read(&daddr, sizeof(daddr),
&skp->__sk_common.skc_daddr);
// output
bpf_trace_printk("4 %x %x %d
\
\
n", saddr, daddr, ntohs(dport));
} else /* 6 */ {
// just grab the last 4 bytes for now
bpf_probe_read(&saddr, sizeof(saddr),
&skp->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32[3]);
bpf_probe_read(&daddr, sizeof(daddr),
&skp->__sk_common.skc_v6_daddr.in6_u.u6_addr32[3]);
// output and flip byte order of addresses
bpf_trace_printk("6 %x %x %d
\
\
n", bpf_ntohl(saddr),
bpf_ntohl(daddr), ntohs(dport));
}
currsock.delete(&pid);
return 0;
int ret = ctx->ax;
u32 pid = bpf_get_current_pid_tgid();
struct sock **skpp;
skpp = currsock.lookup(&pid);
if (skpp == 0) {
return 0;
// missed entry
}
if (ret != 0) {
// failed to send SYNC packet, may not have populated
// socket __sk_common.{skc_rcv_saddr, ...}
currsock.delete(&pid);
return 0;
}
// pull in details
struct sock *skp = *skpp;
u32 saddr = 0, daddr = 0;
u16 dport = 0;
bpf_probe_read(&dport, sizeof(dport), &skp->__sk_common.skc_dport);
if (ipver == 4) {
bpf_probe_read(&saddr, sizeof(saddr),
&skp->__sk_common.skc_rcv_saddr);
bpf_probe_read(&daddr, sizeof(daddr),
&skp->__sk_common.skc_daddr);
// output
bpf_trace_printk("4 %x %x %d
\
\
n", saddr, daddr, ntohs(dport));
} else /* 6 */ {
// just grab the last 4 bytes for now
bpf_probe_read(&saddr, sizeof(saddr),
&skp->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32[3]);
bpf_probe_read(&daddr, sizeof(daddr),
&skp->__sk_common.skc_v6_daddr.in6_u.u6_addr32[3]);
// output and flip byte order of addresses
bpf_trace_printk("6 %x %x %d
\
\
n", bpf_ntohl(saddr),
bpf_ntohl(daddr), ntohs(dport));
}
currsock.delete(&pid);
return 0;
}
int trace_connect_v4_return(struct pt_regs *ctx)
{
return trace_connect_return(ctx, 4);
return trace_connect_return(ctx, 4);
}
int trace_connect_v6_return(struct pt_regs *ctx)
{
return trace_connect_return(ctx, 6);
return trace_connect_return(ctx, 6);
}
"""
# code substitutions
if
args
.
pid
:
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
'if (pid != %s) { return 0; }'
%
args
.
pid
)
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
'if (pid != %s) { return 0; }'
%
args
.
pid
)
else
:
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
''
)
bpf_text
=
bpf_text
.
replace
(
'FILTER'
,
''
)
if
debug
:
print
(
bpf_text
)
print
(
bpf_text
)
# initialize BPF
b
=
BPF
(
text
=
bpf_text
)
...
...
@@ -129,31 +130,31 @@ b.attach_kretprobe(event="tcp_v6_connect", fn_name="trace_connect_v6_return")
# header
if
args
.
timestamp
:
print
(
"%-9s"
%
(
"TIME(s)"
),
end
=
""
)
print
(
"%-9s"
%
(
"TIME(s)"
),
end
=
""
)
print
(
"%-6s %-12s %-2s %-16s %-16s %-4s"
%
(
"PID"
,
"COMM"
,
"IP"
,
"SADDR"
,
"DADDR"
,
"DPORT"
))
start_ts
=
0
def
inet_ntoa
(
addr
):
dq
=
''
for
i
in
range
(
0
,
4
):
dq
=
dq
+
str
(
addr
&
0xff
)
if
(
i
!=
3
):
dq
=
dq
+
'.'
addr
=
addr
>>
8
return
dq
dq
=
''
for
i
in
range
(
0
,
4
):
dq
=
dq
+
str
(
addr
&
0xff
)
if
(
i
!=
3
):
dq
=
dq
+
'.'
addr
=
addr
>>
8
return
dq
# format output
while
1
:
(
task
,
pid
,
cpu
,
flags
,
ts
,
msg
)
=
b
.
trace_fields
()
(
ip_s
,
saddr_hs
,
daddr_hs
,
dport_s
)
=
msg
.
split
(
" "
)
if
args
.
timestamp
:
if
start_ts
==
0
:
start_ts
=
ts
print
(
"%-9.3f"
%
(
ts
-
start_ts
),
end
=
""
)
print
(
"%-6d %-12.12s %-2s %-16s %-16s %-4s"
%
(
pid
,
task
,
ip_s
,
inet_ntoa
(
int
(
saddr_hs
,
16
))
if
ip_s
==
"4"
else
"..."
+
saddr_hs
,
inet_ntoa
(
int
(
daddr_hs
,
16
))
if
ip_s
==
"4"
else
"..."
+
daddr_hs
,
dport_s
))
(
task
,
pid
,
cpu
,
flags
,
ts
,
msg
)
=
b
.
trace_fields
()
(
ip_s
,
saddr_hs
,
daddr_hs
,
dport_s
)
=
msg
.
split
(
" "
)
if
args
.
timestamp
:
if
start_ts
==
0
:
start_ts
=
ts
print
(
"%-9.3f"
%
(
ts
-
start_ts
),
end
=
""
)
print
(
"%-6d %-12.12s %-2s %-16s %-16s %-4s"
%
(
pid
,
task
,
ip_s
,
inet_ntoa
(
int
(
saddr_hs
,
16
))
if
ip_s
==
"4"
else
"..."
+
saddr_hs
,
inet_ntoa
(
int
(
daddr_hs
,
16
))
if
ip_s
==
"4"
else
"..."
+
daddr_hs
,
dport_s
))
tools/tcpconnect_example.txt
View file @
3083c85c
...
...
@@ -5,12 +5,12 @@ This tool traces the kernel function performing active TCP connections
(eg, via a connect() syscall; accept() are passive connections). Some example
output (IP addresses changed to protect the innocent):
# ./tcpconnect
# ./tcpconnect
PID COMM IP SADDR DADDR DPORT
1479 telnet 4 127.0.0.1 127.0.0.1 23
1469 curl 4 10.201.219.236 54.245.105.25 80
1469 curl 4 10.201.219.236 54.67.101.145 80
11072 ssh 6 ...fe8203ac ...fe82abcd 22
1479 telnet 4 127.0.0.1 127.0.0.1 23
1469 curl 4 10.201.219.236 54.245.105.25 80
1469 curl 4 10.201.219.236 54.67.101.145 80
11072 ssh 6 ...fe8203ac ...fe82abcd 22
This output shows four connections, one from a "telnet" process, two from
"curl", and one from "ssh". The output details shows the IP version, source
...
...
tools/vfscount
View file @
3083c85c
#!/usr/bin/python
# @lint-avoid-python-3-compatibility-imports
#
# vfscount
Count VFS calls ("vfs_*").
#
For Linux, uses BCC, eBPF. See .c file.
# vfscount
Count VFS calls ("vfs_*").
#
For Linux, uses BCC, eBPF. See .c file.
#
# Written as a basic example of counting functions.
#
# Copyright (c) 2015 Brendan Gregg.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 14-Aug-2015
Brendan Gregg
Created this.
# 14-Aug-2015
Brendan Gregg
Created this.
from
__future__
import
print_function
from
bcc
import
BPF
from
time
import
sleep
# load BPF program
b
=
BPF
(
src_file
=
"vfscount.c"
)
b
=
BPF
(
src_file
=
"vfscount.c"
)
b
.
attach_kprobe
(
event_re
=
"^vfs_.*"
,
fn_name
=
"do_count"
)
# header
...
...
@@ -23,11 +24,11 @@ print("Tracing... Ctrl-C to end.")
# output
try
:
sleep
(
99999999
)
sleep
(
99999999
)
except
KeyboardInterrupt
:
pass
pass
print
(
"
\
n
%-16s %-26s %8s"
%
(
"ADDR"
,
"FUNC"
,
"COUNT"
))
counts
=
b
.
get_table
(
"counts"
)
for
k
,
v
in
sorted
(
counts
.
items
(),
key
=
lambda
counts
:
counts
[
1
].
value
):
print
(
"%-16x %-26s %8d"
%
(
k
.
ip
,
b
.
ksym
(
k
.
ip
),
v
.
value
))
print
(
"%-16x %-26s %8d"
%
(
k
.
ip
,
b
.
ksym
(
k
.
ip
),
v
.
value
))
tools/vfscount_example.txt
View file @
3083c85c
...
...
@@ -3,7 +3,7 @@ Demonstrations of vfscount, the Linux eBPF/bcc version.
This counts VFS calls, by tracing all kernel functions beginning with "vfs_":
# ./vfscount
# ./vfscount
Tracing... Ctrl-C to end.
^C
ADDR FUNC COUNT
...
...
tools/vfsstat
View file @
3083c85c
#!/usr/bin/python
# @lint-avoid-python-3-compatibility-imports
#
# vfsstat
Count some VFS calls.
#
For Linux, uses BCC, eBPF. See .c file.
# vfsstat
Count some VFS calls.
#
For Linux, uses BCC, eBPF. See .c file.
#
# Written as a basic example of counting multiple events as a stat tool.
#
...
...
@@ -10,33 +11,33 @@
# Copyright (c) 2015 Brendan Gregg.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 14-Aug-2015
Brendan Gregg
Created this.
# 14-Aug-2015
Brendan Gregg
Created this.
from
__future__
import
print_function
from
bcc
import
BPF
from
ctypes
import
c_
ushort
,
c_int
,
c_ulonglong
from
ctypes
import
c_
int
from
time
import
sleep
,
strftime
from
sys
import
argv
def
usage
():
print
(
"USAGE: %s [interval [count]]"
%
argv
[
0
])
exit
()
print
(
"USAGE: %s [interval [count]]"
%
argv
[
0
])
exit
()
# arguments
interval
=
1
count
=
-
1
if
len
(
argv
)
>
1
:
try
:
interval
=
int
(
argv
[
1
])
if
interval
==
0
:
raise
if
len
(
argv
)
>
2
:
count
=
int
(
argv
[
2
])
except
:
# also catches -h, --help
usage
()
try
:
interval
=
int
(
argv
[
1
])
if
interval
==
0
:
raise
if
len
(
argv
)
>
2
:
count
=
int
(
argv
[
2
])
except
:
# also catches -h, --help
usage
()
# load BPF program
b
=
BPF
(
src_file
=
"vfsstat.c"
)
b
=
BPF
(
src_file
=
"vfsstat.c"
)
b
.
attach_kprobe
(
event
=
"vfs_read"
,
fn_name
=
"do_read"
)
b
.
attach_kprobe
(
event
=
"vfs_write"
,
fn_name
=
"do_write"
)
b
.
attach_kprobe
(
event
=
"vfs_fsync"
,
fn_name
=
"do_fsync"
)
...
...
@@ -45,40 +46,41 @@ b.attach_kprobe(event="vfs_create", fn_name="do_create")
# stat column labels and indexes
stat_types
=
{
"READ"
:
1
,
"WRITE"
:
2
,
"FSYNC"
:
3
,
"OPEN"
:
4
,
"CREATE"
:
5
"READ"
:
1
,
"WRITE"
:
2
,
"FSYNC"
:
3
,
"OPEN"
:
4
,
"CREATE"
:
5
}
# header
print
(
"%-8s "
%
"TIME"
,
end
=
""
)
for
stype
in
stat_types
.
keys
():
print
(
" %8s"
%
(
stype
+
"/s"
),
end
=
""
)
idx
=
stat_types
[
stype
]
print
(
" %8s"
%
(
stype
+
"/s"
),
end
=
""
)
idx
=
stat_types
[
stype
]
print
(
""
)
# output
i
=
0
while
(
1
):
if
count
>
0
:
i
+=
1
if
i
>
count
:
exit
()
try
:
sleep
(
interval
)
except
KeyboardInterrupt
:
pass
;
exit
()
if
count
>
0
:
i
+=
1
if
i
>
count
:
exit
()
try
:
sleep
(
interval
)
except
KeyboardInterrupt
:
pass
exit
()
print
(
"%-8s: "
%
strftime
(
"%H:%M:%S"
),
end
=
""
)
# print each statistic as a column
for
stype
in
stat_types
.
keys
():
idx
=
stat_types
[
stype
]
try
:
val
=
b
[
"stats"
][
c_int
(
idx
)].
value
/
interval
print
(
" %8d"
%
val
,
end
=
""
)
except
:
print
(
" %8d"
%
0
,
end
=
""
)
b
[
"stats"
].
clear
()
print
(
""
)
print
(
"%-8s: "
%
strftime
(
"%H:%M:%S"
),
end
=
""
)
# print each statistic as a column
for
stype
in
stat_types
.
keys
():
idx
=
stat_types
[
stype
]
try
:
val
=
b
[
"stats"
][
c_int
(
idx
)].
value
/
interval
print
(
" %8d"
%
val
,
end
=
""
)
except
:
print
(
" %8d"
%
0
,
end
=
""
)
b
[
"stats"
].
clear
()
print
(
""
)
tools/vfsstat_example.txt
View file @
3083c85c
...
...
@@ -4,7 +4,7 @@ Demonstrations of vfsstat, the Linux eBPF/bcc version.
This traces some common VFS calls and prints per-second summaries. By default,
the output interval is one second:
# ./vfsstat
# ./vfsstat
TIME READ/s WRITE/s CREATE/s OPEN/s FSYNC/s
18:35:32: 231 12 4 98 0
18:35:33: 274 13 4 106 0
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment