Skip to content

Commit

Permalink
libbpf-tools/softirqs: Add -c/--cpu option to filter cpu
Browse files Browse the repository at this point in the history
tools/softirqs.py supports `-c/--cpu` otption to filter cpu,
It's reasonable to support a same otption for libbpf-tools/softirqs.

Reported-by: Tang Yizhou <[email protected]>
Signed-off-by: Dantezy <[email protected]>
  • Loading branch information
ZhangYet committed Sep 13, 2024
1 parent 9f3d0df commit 7466f69
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 73 deletions.
76 changes: 45 additions & 31 deletions libbpf-tools/softirqs.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

const volatile bool targ_dist = false;
const volatile bool targ_ns = false;
const volatile int targ_cpu = -1;

struct {
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
Expand All @@ -21,44 +22,57 @@ __u64 counts[NR_SOFTIRQS] = {};
__u64 time[NR_SOFTIRQS] = {};
struct hist hists[NR_SOFTIRQS] = {};

static bool is_target_cpu() {
if (targ_cpu < 0)
return true;

return bpf_get_smp_processor_id() == (u32)targ_cpu;
}

static int handle_entry(unsigned int vec_nr)
{
u64 ts = bpf_ktime_get_ns();
u32 key = 0;
if (!is_target_cpu())
return 0;

bpf_map_update_elem(&start, &key, &ts, BPF_ANY);
return 0;
u64 ts = bpf_ktime_get_ns();
u32 key = 0;

bpf_map_update_elem(&start, &key, &ts, BPF_ANY);
return 0;
}

static int handle_exit(unsigned int vec_nr)
{
u64 delta, *tsp;
u32 key = 0;

if (vec_nr >= NR_SOFTIRQS)
return 0;
tsp = bpf_map_lookup_elem(&start, &key);
if (!tsp)
return 0;
delta = bpf_ktime_get_ns() - *tsp;
if (!targ_ns)
delta /= 1000U;

if (!targ_dist) {
__sync_fetch_and_add(&counts[vec_nr], 1);
__sync_fetch_and_add(&time[vec_nr], delta);
} else {
struct hist *hist;
u64 slot;

hist = &hists[vec_nr];
slot = log2(delta);
if (slot >= MAX_SLOTS)
slot = MAX_SLOTS - 1;
__sync_fetch_and_add(&hist->slots[slot], 1);
}

return 0;
if (!is_target_cpu()) {
return 0;
}

u64 delta, *tsp;
u32 key = 0;

vec_nr &= 0xf; // to avoid compiler opti make verifier error

tsp = bpf_map_lookup_elem(&start, &key);
if (!tsp)
return 0;
delta = bpf_ktime_get_ns() - *tsp;
if (!targ_ns)
delta /= 1000U;

if (!targ_dist) {
__sync_fetch_and_add(&counts[vec_nr], 1);
__sync_fetch_and_add(&time[vec_nr], delta);
} else {
struct hist *hist;
u64 slot;

hist = &hists[vec_nr];
slot = log2(delta);
if (slot >= MAX_SLOTS)
slot = MAX_SLOTS - 1;
__sync_fetch_and_add(&hist->slots[slot], 1);
}
return 0;
}

SEC("tp_btf/softirq_entry")
Expand Down
97 changes: 55 additions & 42 deletions libbpf-tools/softirqs.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ struct env {
int times;
bool timestamp;
bool verbose;
int targ_cpu;
} env = {
.interval = 99999999,
.times = 99999999,
.count = false,
.interval = 99999999,
.times = 99999999,
.count = false,
.targ_cpu = -1,
};

static volatile bool exiting;
Expand All @@ -36,24 +38,26 @@ const char *argp_program_version = "softirqs 0.1";
const char *argp_program_bug_address =
"https://github.com/iovisor/bcc/tree/master/libbpf-tools";
const char argp_program_doc[] =
"Summarize soft irq event time as histograms.\n"
"\n"
"USAGE: softirqs [--help] [-T] [-N] [-d] [interval] [count]\n"
"\n"
"EXAMPLES:\n"
" softirqs # sum soft irq event time\n"
" softirqs -d # show soft irq event time as histograms\n"
" softirqs 1 10 # print 1 second summaries, 10 times\n"
" softirqs -NT 1 # 1s summaries, nanoseconds, and timestamps\n";
"Summarize soft irq event time as histograms.\n"
"\n"
"USAGE: softirqs [--help] [-T] [-N] [-d] [interval] [count]\n"
"\n"
"EXAMPLES:\n"
" softirqs # sum soft irq event time\n"
" softirqs -d # show soft irq event time as histograms\n"
" softirqs -c 1 # show soft irq event time on cpu 1\n"
" softirqs 1 10 # print 1 second summaries, 10 times\n"
" softirqs -NT 1 # 1s summaries, nanoseconds, and timestamps\n";

static const struct argp_option opts[] = {
{ "distributed", 'd', NULL, 0, "Show distributions as histograms", 0 },
{ "timestamp", 'T', NULL, 0, "Include timestamp on output", 0 },
{ "nanoseconds", 'N', NULL, 0, "Output in nanoseconds", 0 },
{ "count", 'C', NULL, 0, "Show event counts with timing", 0 },
{ "verbose", 'v', NULL, 0, "Verbose debug output", 0 },
{ NULL, 'h', NULL, OPTION_HIDDEN, "Show the full help", 0 },
{},
{"distributed", 'd', NULL, 0, "Show distributions as histograms", 0},
{"timestamp", 'T', NULL, 0, "Include timestamp on output", 0},
{"nanoseconds", 'N', NULL, 0, "Output in nanoseconds", 0},
{"count", 'C', NULL, 0, "Show event counts with timing", 0},
{"verbose", 'v', NULL, 0, "Verbose debug output", 0},
{"cpu", 'c', "CPU", 0, "Trace this cpu only", 0},
{NULL, 'h', NULL, OPTION_HIDDEN, "Show the full help", 0},
{},
};

static error_t parse_arg(int key, char *arg, struct argp_state *state)
Expand All @@ -79,27 +83,35 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
case 'C':
env.count = true;
break;
case ARGP_KEY_ARG:
errno = 0;
if (pos_args == 0) {
env.interval = strtol(arg, NULL, 10);
if (errno) {
fprintf(stderr, "invalid internal\n");
argp_usage(state);
}
} else if (pos_args == 1) {
env.times = strtol(arg, NULL, 10);
if (errno) {
fprintf(stderr, "invalid times\n");
argp_usage(state);
}
} else {
fprintf(stderr,
"unrecognized positional argument: %s\n", arg);
argp_usage(state);
}
pos_args++;
break;
case 'c':
errno = 0;
long c = strtol(arg, NULL, 10);
if (errno || c < 0) {
fprintf(stderr, "invalid cpu: %s\n", arg);
argp_usage(state);
}
env.targ_cpu = (int)c;
break;
case ARGP_KEY_ARG:
errno = 0;
if (pos_args == 0) {
env.interval = strtol(arg, NULL, 10);
if (errno) {
fprintf(stderr, "invalid internal\n");
argp_usage(state);
}
} else if (pos_args == 1) {
env.times = strtol(arg, NULL, 10);
if (errno) {
fprintf(stderr, "invalid times\n");
argp_usage(state);
}
} else {
fprintf(stderr, "unrecognized positional argument: %s\n", arg);
argp_usage(state);
}
pos_args++;
break;
default:
return ARGP_ERR_UNKNOWN;
}
Expand Down Expand Up @@ -228,9 +240,10 @@ int main(int argc, char **argv)
/* initialize global data (filtering options) */
obj->rodata->targ_dist = env.distributed;
obj->rodata->targ_ns = env.nanoseconds;
obj->rodata->targ_cpu = env.targ_cpu;

err = softirqs_bpf__load(obj);
if (err) {
err = softirqs_bpf__load(obj);
if (err) {
fprintf(stderr, "failed to load BPF object: %d\n", err);
goto cleanup;
}
Expand Down

0 comments on commit 7466f69

Please sign in to comment.