125763b3cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2e3edfdecSAlexei Starovoitov /* Copyright (c) 2016 Facebook
3e3edfdecSAlexei Starovoitov */
4e3edfdecSAlexei Starovoitov #define _GNU_SOURCE
5e3edfdecSAlexei Starovoitov #include <sched.h>
602a2f000STaeung Song #include <errno.h>
7e3edfdecSAlexei Starovoitov #include <stdio.h>
8e3edfdecSAlexei Starovoitov #include <sys/types.h>
9e3edfdecSAlexei Starovoitov #include <asm/unistd.h>
10e3edfdecSAlexei Starovoitov #include <fcntl.h>
11e3edfdecSAlexei Starovoitov #include <unistd.h>
12e3edfdecSAlexei Starovoitov #include <assert.h>
13e3edfdecSAlexei Starovoitov #include <sys/wait.h>
1458e975d0SDaniel T. Lee #include <sys/socket.h>
1558e975d0SDaniel T. Lee #include <arpa/inet.h>
16e3edfdecSAlexei Starovoitov #include <stdlib.h>
17e3edfdecSAlexei Starovoitov #include <signal.h>
18e3edfdecSAlexei Starovoitov #include <linux/bpf.h>
19e3edfdecSAlexei Starovoitov #include <string.h>
20e3edfdecSAlexei Starovoitov #include <time.h>
212bf3e2efSJakub Kicinski #include <bpf/bpf.h>
22c6497df0SDaniel T. Lee #include <bpf/libbpf.h>
23e3edfdecSAlexei Starovoitov
24e3edfdecSAlexei Starovoitov #define MAX_CNT 1000000
2558e975d0SDaniel T. Lee #define DUMMY_IP "127.0.0.1"
2658e975d0SDaniel T. Lee #define DUMMY_PORT 80
27e3edfdecSAlexei Starovoitov
28c6497df0SDaniel T. Lee static struct bpf_link *links[2];
29c6497df0SDaniel T. Lee static struct bpf_object *obj;
30c6497df0SDaniel T. Lee static int cnt;
31c6497df0SDaniel T. Lee
time_get_ns(void)32e3edfdecSAlexei Starovoitov static __u64 time_get_ns(void)
33e3edfdecSAlexei Starovoitov {
34e3edfdecSAlexei Starovoitov struct timespec ts;
35e3edfdecSAlexei Starovoitov
36e3edfdecSAlexei Starovoitov clock_gettime(CLOCK_MONOTONIC, &ts);
37e3edfdecSAlexei Starovoitov return ts.tv_sec * 1000000000ull + ts.tv_nsec;
38e3edfdecSAlexei Starovoitov }
39e3edfdecSAlexei Starovoitov
test_task_rename(int cpu)40e3edfdecSAlexei Starovoitov static void test_task_rename(int cpu)
41e3edfdecSAlexei Starovoitov {
42e3edfdecSAlexei Starovoitov char buf[] = "test\n";
4358e975d0SDaniel T. Lee __u64 start_time;
44e3edfdecSAlexei Starovoitov int i, fd;
45e3edfdecSAlexei Starovoitov
46e3edfdecSAlexei Starovoitov fd = open("/proc/self/comm", O_WRONLY|O_TRUNC);
47e3edfdecSAlexei Starovoitov if (fd < 0) {
48e3edfdecSAlexei Starovoitov printf("couldn't open /proc\n");
49e3edfdecSAlexei Starovoitov exit(1);
50e3edfdecSAlexei Starovoitov }
51e3edfdecSAlexei Starovoitov start_time = time_get_ns();
5202a2f000STaeung Song for (i = 0; i < MAX_CNT; i++) {
5302a2f000STaeung Song if (write(fd, buf, sizeof(buf)) < 0) {
5402a2f000STaeung Song printf("task rename failed: %s\n", strerror(errno));
5502a2f000STaeung Song close(fd);
5602a2f000STaeung Song return;
5702a2f000STaeung Song }
5802a2f000STaeung Song }
59e3edfdecSAlexei Starovoitov printf("task_rename:%d: %lld events per sec\n",
60e3edfdecSAlexei Starovoitov cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
61e3edfdecSAlexei Starovoitov close(fd);
62e3edfdecSAlexei Starovoitov }
63e3edfdecSAlexei Starovoitov
test_fib_table_lookup(int cpu)6458e975d0SDaniel T. Lee static void test_fib_table_lookup(int cpu)
65e3edfdecSAlexei Starovoitov {
6658e975d0SDaniel T. Lee struct sockaddr_in addr;
6758e975d0SDaniel T. Lee char buf[] = "test\n";
68e3edfdecSAlexei Starovoitov __u64 start_time;
69e3edfdecSAlexei Starovoitov int i, fd;
70e3edfdecSAlexei Starovoitov
7158e975d0SDaniel T. Lee fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
72e3edfdecSAlexei Starovoitov if (fd < 0) {
7358e975d0SDaniel T. Lee printf("couldn't open socket\n");
74e3edfdecSAlexei Starovoitov exit(1);
75e3edfdecSAlexei Starovoitov }
7658e975d0SDaniel T. Lee memset((char *)&addr, 0, sizeof(addr));
7758e975d0SDaniel T. Lee addr.sin_addr.s_addr = inet_addr(DUMMY_IP);
7858e975d0SDaniel T. Lee addr.sin_port = htons(DUMMY_PORT);
7958e975d0SDaniel T. Lee addr.sin_family = AF_INET;
80e3edfdecSAlexei Starovoitov start_time = time_get_ns();
8102a2f000STaeung Song for (i = 0; i < MAX_CNT; i++) {
8258e975d0SDaniel T. Lee if (sendto(fd, buf, strlen(buf), 0,
8358e975d0SDaniel T. Lee (struct sockaddr *)&addr, sizeof(addr)) < 0) {
8458e975d0SDaniel T. Lee printf("failed to start ping: %s\n", strerror(errno));
8502a2f000STaeung Song close(fd);
8602a2f000STaeung Song return;
8702a2f000STaeung Song }
8802a2f000STaeung Song }
8958e975d0SDaniel T. Lee printf("fib_table_lookup:%d: %lld events per sec\n",
90e3edfdecSAlexei Starovoitov cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
91e3edfdecSAlexei Starovoitov close(fd);
92e3edfdecSAlexei Starovoitov }
93e3edfdecSAlexei Starovoitov
loop(int cpu,int flags)94e3edfdecSAlexei Starovoitov static void loop(int cpu, int flags)
95e3edfdecSAlexei Starovoitov {
96e3edfdecSAlexei Starovoitov cpu_set_t cpuset;
97e3edfdecSAlexei Starovoitov
98e3edfdecSAlexei Starovoitov CPU_ZERO(&cpuset);
99e3edfdecSAlexei Starovoitov CPU_SET(cpu, &cpuset);
100e3edfdecSAlexei Starovoitov sched_setaffinity(0, sizeof(cpuset), &cpuset);
101e3edfdecSAlexei Starovoitov
102e3edfdecSAlexei Starovoitov if (flags & 1)
103e3edfdecSAlexei Starovoitov test_task_rename(cpu);
104e3edfdecSAlexei Starovoitov if (flags & 2)
10558e975d0SDaniel T. Lee test_fib_table_lookup(cpu);
106e3edfdecSAlexei Starovoitov }
107e3edfdecSAlexei Starovoitov
run_perf_test(int tasks,int flags)108e3edfdecSAlexei Starovoitov static void run_perf_test(int tasks, int flags)
109e3edfdecSAlexei Starovoitov {
110e3edfdecSAlexei Starovoitov pid_t pid[tasks];
111e3edfdecSAlexei Starovoitov int i;
112e3edfdecSAlexei Starovoitov
113e3edfdecSAlexei Starovoitov for (i = 0; i < tasks; i++) {
114e3edfdecSAlexei Starovoitov pid[i] = fork();
115e3edfdecSAlexei Starovoitov if (pid[i] == 0) {
116e3edfdecSAlexei Starovoitov loop(i, flags);
117e3edfdecSAlexei Starovoitov exit(0);
118e3edfdecSAlexei Starovoitov } else if (pid[i] == -1) {
119e3edfdecSAlexei Starovoitov printf("couldn't spawn #%d process\n", i);
120e3edfdecSAlexei Starovoitov exit(1);
121e3edfdecSAlexei Starovoitov }
122e3edfdecSAlexei Starovoitov }
123e3edfdecSAlexei Starovoitov for (i = 0; i < tasks; i++) {
124e3edfdecSAlexei Starovoitov int status;
125e3edfdecSAlexei Starovoitov
126e3edfdecSAlexei Starovoitov assert(waitpid(pid[i], &status, 0) == pid[i]);
127e3edfdecSAlexei Starovoitov assert(status == 0);
128e3edfdecSAlexei Starovoitov }
129e3edfdecSAlexei Starovoitov }
130e3edfdecSAlexei Starovoitov
load_progs(char * filename)131c6497df0SDaniel T. Lee static int load_progs(char *filename)
132c6497df0SDaniel T. Lee {
133c6497df0SDaniel T. Lee struct bpf_program *prog;
134c6497df0SDaniel T. Lee int err = 0;
135c6497df0SDaniel T. Lee
136c6497df0SDaniel T. Lee obj = bpf_object__open_file(filename, NULL);
137c6497df0SDaniel T. Lee err = libbpf_get_error(obj);
138c6497df0SDaniel T. Lee if (err < 0) {
139c6497df0SDaniel T. Lee fprintf(stderr, "ERROR: opening BPF object file failed\n");
140c6497df0SDaniel T. Lee return err;
141c6497df0SDaniel T. Lee }
142c6497df0SDaniel T. Lee
143c6497df0SDaniel T. Lee /* load BPF program */
144c6497df0SDaniel T. Lee err = bpf_object__load(obj);
145c6497df0SDaniel T. Lee if (err < 0) {
146c6497df0SDaniel T. Lee fprintf(stderr, "ERROR: loading BPF object file failed\n");
147c6497df0SDaniel T. Lee return err;
148c6497df0SDaniel T. Lee }
149c6497df0SDaniel T. Lee
150c6497df0SDaniel T. Lee bpf_object__for_each_program(prog, obj) {
151c6497df0SDaniel T. Lee links[cnt] = bpf_program__attach(prog);
152c6497df0SDaniel T. Lee err = libbpf_get_error(links[cnt]);
153c6497df0SDaniel T. Lee if (err < 0) {
154c6497df0SDaniel T. Lee fprintf(stderr, "ERROR: bpf_program__attach failed\n");
155c6497df0SDaniel T. Lee links[cnt] = NULL;
156c6497df0SDaniel T. Lee return err;
157c6497df0SDaniel T. Lee }
158c6497df0SDaniel T. Lee cnt++;
159c6497df0SDaniel T. Lee }
160c6497df0SDaniel T. Lee
161c6497df0SDaniel T. Lee return err;
162c6497df0SDaniel T. Lee }
163c6497df0SDaniel T. Lee
unload_progs(void)164e3edfdecSAlexei Starovoitov static void unload_progs(void)
165e3edfdecSAlexei Starovoitov {
166c6497df0SDaniel T. Lee while (cnt)
167c6497df0SDaniel T. Lee bpf_link__destroy(links[--cnt]);
168c6497df0SDaniel T. Lee
169c6497df0SDaniel T. Lee bpf_object__close(obj);
170e3edfdecSAlexei Starovoitov }
171e3edfdecSAlexei Starovoitov
main(int argc,char ** argv)172e3edfdecSAlexei Starovoitov int main(int argc, char **argv)
173e3edfdecSAlexei Starovoitov {
174c6497df0SDaniel T. Lee int num_cpu = sysconf(_SC_NPROCESSORS_ONLN);
175e3edfdecSAlexei Starovoitov int test_flags = ~0;
176c6497df0SDaniel T. Lee char filename[256];
177c6497df0SDaniel T. Lee int err = 0;
178e3edfdecSAlexei Starovoitov
179e3edfdecSAlexei Starovoitov
180e3edfdecSAlexei Starovoitov if (argc > 1)
181e3edfdecSAlexei Starovoitov test_flags = atoi(argv[1]) ? : test_flags;
182e3edfdecSAlexei Starovoitov if (argc > 2)
183e3edfdecSAlexei Starovoitov num_cpu = atoi(argv[2]) ? : num_cpu;
184e3edfdecSAlexei Starovoitov
185e3edfdecSAlexei Starovoitov if (test_flags & 0x3) {
186e3edfdecSAlexei Starovoitov printf("BASE\n");
187e3edfdecSAlexei Starovoitov run_perf_test(num_cpu, test_flags);
188e3edfdecSAlexei Starovoitov }
189e3edfdecSAlexei Starovoitov
190e3edfdecSAlexei Starovoitov if (test_flags & 0xC) {
191e3edfdecSAlexei Starovoitov snprintf(filename, sizeof(filename),
192*e04946f5SDaniel T. Lee "%s_kprobe.bpf.o", argv[0]);
193c6497df0SDaniel T. Lee
194e3edfdecSAlexei Starovoitov printf("w/KPROBE\n");
195c6497df0SDaniel T. Lee err = load_progs(filename);
196c6497df0SDaniel T. Lee if (!err)
197e3edfdecSAlexei Starovoitov run_perf_test(num_cpu, test_flags >> 2);
198c6497df0SDaniel T. Lee
199e3edfdecSAlexei Starovoitov unload_progs();
200e3edfdecSAlexei Starovoitov }
201e3edfdecSAlexei Starovoitov
202e3edfdecSAlexei Starovoitov if (test_flags & 0x30) {
203e3edfdecSAlexei Starovoitov snprintf(filename, sizeof(filename),
204*e04946f5SDaniel T. Lee "%s_tp.bpf.o", argv[0]);
205e3edfdecSAlexei Starovoitov printf("w/TRACEPOINT\n");
206c6497df0SDaniel T. Lee err = load_progs(filename);
207c6497df0SDaniel T. Lee if (!err)
208e3edfdecSAlexei Starovoitov run_perf_test(num_cpu, test_flags >> 4);
209c6497df0SDaniel T. Lee
210e3edfdecSAlexei Starovoitov unload_progs();
211e3edfdecSAlexei Starovoitov }
212e3edfdecSAlexei Starovoitov
2134662a4e5SAlexei Starovoitov if (test_flags & 0xC0) {
2144662a4e5SAlexei Starovoitov snprintf(filename, sizeof(filename),
215*e04946f5SDaniel T. Lee "%s_raw_tp.bpf.o", argv[0]);
2164662a4e5SAlexei Starovoitov printf("w/RAW_TRACEPOINT\n");
217c6497df0SDaniel T. Lee err = load_progs(filename);
218c6497df0SDaniel T. Lee if (!err)
2194662a4e5SAlexei Starovoitov run_perf_test(num_cpu, test_flags >> 6);
220c6497df0SDaniel T. Lee
2214662a4e5SAlexei Starovoitov unload_progs();
2224662a4e5SAlexei Starovoitov }
2234662a4e5SAlexei Starovoitov
224c6497df0SDaniel T. Lee return err;
225e3edfdecSAlexei Starovoitov }
226