|
7 | 7 | #include "tracing_multi.skel.h" |
8 | 8 | #include "tracing_multi_intersect.skel.h" |
9 | 9 | #include "tracing_multi_session.skel.h" |
| 10 | +#include "tracing_multi_bench.skel.h" |
10 | 11 | #include "trace_helpers.h" |
11 | 12 |
|
12 | 13 | static __u64 bpf_fentry_test_cookies[] = { |
@@ -315,6 +316,186 @@ static void test_session(void) |
315 | 316 | tracing_multi_session__destroy(skel); |
316 | 317 | } |
317 | 318 |
|
| 319 | +static bool skip_entry(char *name) |
| 320 | +{ |
| 321 | + if (!strcmp(name, "arch_cpu_idle")) |
| 322 | + return true; |
| 323 | + if (!strcmp(name, "default_idle")) |
| 324 | + return true; |
| 325 | + if (!strncmp(name, "rcu_", 4)) |
| 326 | + return true; |
| 327 | + if (!strcmp(name, "bpf_dispatcher_xdp_func")) |
| 328 | + return true; |
| 329 | + if (!strncmp(name, "__ftrace_invalid_address__", sizeof("__ftrace_invalid_address__") - 1)) |
| 330 | + return true; |
| 331 | + if (strstr(name, "rcu")) |
| 332 | + return true; |
| 333 | + if (strstr(name, "trace")) |
| 334 | + return true; |
| 335 | + if (strstr(name, "irq")) |
| 336 | + return true; |
| 337 | + if (strstr(name, "bpf_lsm_")) |
| 338 | + return true; |
| 339 | + if (!strcmp(name, "migrate_enable")) |
| 340 | + return true; |
| 341 | + if (!strcmp(name, "migrate_disable")) |
| 342 | + return true; |
| 343 | + if (!strcmp(name, "__bpf_prog_enter_recur")) |
| 344 | + return true; |
| 345 | + if (!strcmp(name, "__bpf_prog_exit_recur")) |
| 346 | + return true; |
| 347 | + if (!strcmp(name, "preempt_count_sub")) |
| 348 | + return true; |
| 349 | + if (!strcmp(name, "preempt_count_add")) |
| 350 | + return true; |
| 351 | + return false; |
| 352 | +} |
| 353 | + |
| 354 | +#define MAX_BPF_FUNC_ARGS 12 |
| 355 | + |
| 356 | +static bool btf_type_is_modifier(const struct btf_type *t) |
| 357 | +{ |
| 358 | + switch (BTF_INFO_KIND(t->info)) { |
| 359 | + case BTF_KIND_TYPEDEF: |
| 360 | + case BTF_KIND_VOLATILE: |
| 361 | + case BTF_KIND_CONST: |
| 362 | + case BTF_KIND_RESTRICT: |
| 363 | + case BTF_KIND_TYPE_TAG: |
| 364 | + return true; |
| 365 | + } |
| 366 | + return false; |
| 367 | +} |
| 368 | + |
| 369 | +static bool is_allowed_func(const struct btf *btf, const struct btf_type *t) |
| 370 | +{ |
| 371 | + const struct btf_type *proto; |
| 372 | + const struct btf_param *args; |
| 373 | + __u32 i, nargs; |
| 374 | + __s64 ret; |
| 375 | + |
| 376 | + proto = btf_type_by_id(btf, t->type); |
| 377 | + if (BTF_INFO_KIND(proto->info) != BTF_KIND_FUNC_PROTO) |
| 378 | + return false; |
| 379 | + |
| 380 | + args = (const struct btf_param *)(proto + 1); |
| 381 | + nargs = btf_vlen(proto); |
| 382 | + if (nargs > MAX_BPF_FUNC_ARGS) |
| 383 | + return false; |
| 384 | + |
| 385 | + t = btf__type_by_id(btf, proto->type); |
| 386 | + while (t && btf_type_is_modifier(t)) |
| 387 | + t = btf__type_by_id(btf, t->type); |
| 388 | + |
| 389 | + if (btf_is_struct(t) || btf_is_union(t)) |
| 390 | + return false; |
| 391 | + |
| 392 | + for (i = 0; i < nargs; i++) { |
| 393 | + /* No support for variable args */ |
| 394 | + if (i == nargs - 1 && args[i].type == 0) |
| 395 | + return false; |
| 396 | + |
| 397 | + /* No support of struct argument size greater than 16 bytes */ |
| 398 | + ret = btf__resolve_size(btf, args[i].type); |
| 399 | + if (ret < 0 || ret > 16) |
| 400 | + return false; |
| 401 | + } |
| 402 | + |
| 403 | + return true; |
| 404 | +} |
| 405 | + |
| 406 | +void serial_test_bench_attach(void) |
| 407 | +{ |
| 408 | + struct tracing_multi_bench *skel = NULL; |
| 409 | + long attach_start_ns, attach_end_ns; |
| 410 | + long detach_start_ns, detach_end_ns; |
| 411 | + double attach_delta, detach_delta; |
| 412 | + struct bpf_link *link = NULL; |
| 413 | + size_t i, syms_cnt; |
| 414 | + char **syms; |
| 415 | + void *root = NULL; |
| 416 | + __u32 nr, type_id; |
| 417 | + struct btf *btf; |
| 418 | + __u32 *ids = NULL; |
| 419 | + size_t cap = 0, cnt = 0; |
| 420 | + int err; |
| 421 | + LIBBPF_OPTS(bpf_tracing_multi_opts, opts); |
| 422 | + |
| 423 | +#ifndef __x86_64__ |
| 424 | + test__skip(); |
| 425 | + return; |
| 426 | +#endif |
| 427 | + |
| 428 | + btf = btf__load_vmlinux_btf(); |
| 429 | + if (!ASSERT_OK_PTR(btf, "btf__load_vmlinux_btf")) |
| 430 | + return; |
| 431 | + |
| 432 | + skel = tracing_multi_bench__open_and_load(); |
| 433 | + if (!ASSERT_OK_PTR(skel, "tracing_multi_bench__open_and_load")) |
| 434 | + goto cleanup; |
| 435 | + |
| 436 | + if (!ASSERT_OK(bpf_get_ksyms(&syms, &syms_cnt, true), "get_syms")) |
| 437 | + goto cleanup; |
| 438 | + |
| 439 | + for (i = 0; i < syms_cnt; i++) { |
| 440 | + if (skip_entry(syms[i])) |
| 441 | + continue; |
| 442 | + tsearch(&syms[i], &root, compare); |
| 443 | + } |
| 444 | + |
| 445 | + nr = btf__type_cnt(btf); |
| 446 | + for (type_id = 1; type_id < nr; type_id++) { |
| 447 | + const struct btf_type *type; |
| 448 | + const char *str; |
| 449 | + |
| 450 | + type = btf__type_by_id(btf, type_id); |
| 451 | + if (!type) |
| 452 | + break; |
| 453 | + |
| 454 | + if (BTF_INFO_KIND(type->info) != BTF_KIND_FUNC) |
| 455 | + continue; |
| 456 | + |
| 457 | + str = btf__name_by_offset(btf, type->name_off); |
| 458 | + if (!str) |
| 459 | + break; |
| 460 | + |
| 461 | + if (!tfind(&str, &root, compare)) |
| 462 | + continue; |
| 463 | + |
| 464 | + if (!is_allowed_func(btf, type)) |
| 465 | + continue; |
| 466 | + |
| 467 | + err = libbpf_ensure_mem((void **) &ids, &cap, sizeof(*ids), cnt + 1); |
| 468 | + if (err) |
| 469 | + break; |
| 470 | + |
| 471 | + ids[cnt++] = type_id; |
| 472 | + } |
| 473 | + |
| 474 | + opts.ids = ids; |
| 475 | + opts.cnt = cnt; |
| 476 | + |
| 477 | + attach_start_ns = get_time_ns(); |
| 478 | + link = bpf_program__attach_tracing_multi(skel->progs.bench, NULL, &opts); |
| 479 | + attach_end_ns = get_time_ns(); |
| 480 | + |
| 481 | + if (!ASSERT_OK_PTR(link, "bpf_program__attach_tracing_multi")) |
| 482 | + goto cleanup; |
| 483 | + |
| 484 | + detach_start_ns = get_time_ns(); |
| 485 | + bpf_link__destroy(link); |
| 486 | + detach_end_ns = get_time_ns(); |
| 487 | + |
| 488 | + attach_delta = (attach_end_ns - attach_start_ns) / 1000000000.0; |
| 489 | + detach_delta = (detach_end_ns - detach_start_ns) / 1000000000.0; |
| 490 | + |
| 491 | + printf("%s: found %lu functions\n", __func__, cnt); |
| 492 | + printf("%s: attached in %7.3lfs\n", __func__, attach_delta); |
| 493 | + printf("%s: detached in %7.3lfs\n", __func__, detach_delta); |
| 494 | + |
| 495 | +cleanup: |
| 496 | + tracing_multi_bench__destroy(skel); |
| 497 | +} |
| 498 | + |
318 | 499 | void test_tracing_multi_test(void) |
319 | 500 | { |
320 | 501 | #ifndef __x86_64__ |
|
0 commit comments