18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci#include <stdio.h>
38c2ecf20Sopenharmony_ci#include <fcntl.h>
48c2ecf20Sopenharmony_ci#include <poll.h>
58c2ecf20Sopenharmony_ci#include <time.h>
68c2ecf20Sopenharmony_ci#include <signal.h>
78c2ecf20Sopenharmony_ci#include <bpf/libbpf.h>
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_cistatic __u64 time_get_ns(void)
108c2ecf20Sopenharmony_ci{
118c2ecf20Sopenharmony_ci	struct timespec ts;
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci	clock_gettime(CLOCK_MONOTONIC, &ts);
148c2ecf20Sopenharmony_ci	return ts.tv_sec * 1000000000ull + ts.tv_nsec;
158c2ecf20Sopenharmony_ci}
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_cistatic __u64 start_time;
188c2ecf20Sopenharmony_cistatic __u64 cnt;
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#define MAX_CNT 100000ll
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic void print_bpf_output(void *ctx, int cpu, void *data, __u32 size)
238c2ecf20Sopenharmony_ci{
248c2ecf20Sopenharmony_ci	struct {
258c2ecf20Sopenharmony_ci		__u64 pid;
268c2ecf20Sopenharmony_ci		__u64 cookie;
278c2ecf20Sopenharmony_ci	} *e = data;
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	if (e->cookie != 0x12345678) {
308c2ecf20Sopenharmony_ci		printf("BUG pid %llx cookie %llx sized %d\n",
318c2ecf20Sopenharmony_ci		       e->pid, e->cookie, size);
328c2ecf20Sopenharmony_ci		return;
338c2ecf20Sopenharmony_ci	}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	cnt++;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	if (cnt == MAX_CNT) {
388c2ecf20Sopenharmony_ci		printf("recv %lld events per sec\n",
398c2ecf20Sopenharmony_ci		       MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
408c2ecf20Sopenharmony_ci		return;
418c2ecf20Sopenharmony_ci	}
428c2ecf20Sopenharmony_ci}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ciint main(int argc, char **argv)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	struct perf_buffer_opts pb_opts = {};
478c2ecf20Sopenharmony_ci	struct bpf_link *link = NULL;
488c2ecf20Sopenharmony_ci	struct bpf_program *prog;
498c2ecf20Sopenharmony_ci	struct perf_buffer *pb;
508c2ecf20Sopenharmony_ci	struct bpf_object *obj;
518c2ecf20Sopenharmony_ci	int map_fd, ret = 0;
528c2ecf20Sopenharmony_ci	char filename[256];
538c2ecf20Sopenharmony_ci	FILE *f;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
568c2ecf20Sopenharmony_ci	obj = bpf_object__open_file(filename, NULL);
578c2ecf20Sopenharmony_ci	if (libbpf_get_error(obj)) {
588c2ecf20Sopenharmony_ci		fprintf(stderr, "ERROR: opening BPF object file failed\n");
598c2ecf20Sopenharmony_ci		return 0;
608c2ecf20Sopenharmony_ci	}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	/* load BPF program */
638c2ecf20Sopenharmony_ci	if (bpf_object__load(obj)) {
648c2ecf20Sopenharmony_ci		fprintf(stderr, "ERROR: loading BPF object file failed\n");
658c2ecf20Sopenharmony_ci		goto cleanup;
668c2ecf20Sopenharmony_ci	}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	map_fd = bpf_object__find_map_fd_by_name(obj, "my_map");
698c2ecf20Sopenharmony_ci	if (map_fd < 0) {
708c2ecf20Sopenharmony_ci		fprintf(stderr, "ERROR: finding a map in obj file failed\n");
718c2ecf20Sopenharmony_ci		goto cleanup;
728c2ecf20Sopenharmony_ci	}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	prog = bpf_object__find_program_by_name(obj, "bpf_prog1");
758c2ecf20Sopenharmony_ci	if (libbpf_get_error(prog)) {
768c2ecf20Sopenharmony_ci		fprintf(stderr, "ERROR: finding a prog in obj file failed\n");
778c2ecf20Sopenharmony_ci		goto cleanup;
788c2ecf20Sopenharmony_ci	}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	link = bpf_program__attach(prog);
818c2ecf20Sopenharmony_ci	if (libbpf_get_error(link)) {
828c2ecf20Sopenharmony_ci		fprintf(stderr, "ERROR: bpf_program__attach failed\n");
838c2ecf20Sopenharmony_ci		link = NULL;
848c2ecf20Sopenharmony_ci		goto cleanup;
858c2ecf20Sopenharmony_ci	}
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	pb_opts.sample_cb = print_bpf_output;
888c2ecf20Sopenharmony_ci	pb = perf_buffer__new(map_fd, 8, &pb_opts);
898c2ecf20Sopenharmony_ci	ret = libbpf_get_error(pb);
908c2ecf20Sopenharmony_ci	if (ret) {
918c2ecf20Sopenharmony_ci		printf("failed to setup perf_buffer: %d\n", ret);
928c2ecf20Sopenharmony_ci		return 1;
938c2ecf20Sopenharmony_ci	}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	f = popen("taskset 1 dd if=/dev/zero of=/dev/null", "r");
968c2ecf20Sopenharmony_ci	(void) f;
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	start_time = time_get_ns();
998c2ecf20Sopenharmony_ci	while ((ret = perf_buffer__poll(pb, 1000)) >= 0 && cnt < MAX_CNT) {
1008c2ecf20Sopenharmony_ci	}
1018c2ecf20Sopenharmony_ci	kill(0, SIGINT);
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cicleanup:
1048c2ecf20Sopenharmony_ci	bpf_link__destroy(link);
1058c2ecf20Sopenharmony_ci	bpf_object__close(obj);
1068c2ecf20Sopenharmony_ci	return ret;
1078c2ecf20Sopenharmony_ci}
108