226 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Copyright (c) 2016 Facebook3 */4#define _GNU_SOURCE5#include <sched.h>6#include <errno.h>7#include <stdio.h>8#include <sys/types.h>9#include <asm/unistd.h>10#include <fcntl.h>11#include <unistd.h>12#include <assert.h>13#include <sys/wait.h>14#include <sys/socket.h>15#include <arpa/inet.h>16#include <stdlib.h>17#include <signal.h>18#include <linux/bpf.h>19#include <string.h>20#include <time.h>21#include <bpf/bpf.h>22#include <bpf/libbpf.h>23 24#define MAX_CNT 100000025#define DUMMY_IP "127.0.0.1"26#define DUMMY_PORT 8027 28static struct bpf_link *links[2];29static struct bpf_object *obj;30static int cnt;31 32static __u64 time_get_ns(void)33{34 struct timespec ts;35 36 clock_gettime(CLOCK_MONOTONIC, &ts);37 return ts.tv_sec * 1000000000ull + ts.tv_nsec;38}39 40static void test_task_rename(int cpu)41{42 char buf[] = "test\n";43 __u64 start_time;44 int i, fd;45 46 fd = open("/proc/self/comm", O_WRONLY|O_TRUNC);47 if (fd < 0) {48 printf("couldn't open /proc\n");49 exit(1);50 }51 start_time = time_get_ns();52 for (i = 0; i < MAX_CNT; i++) {53 if (write(fd, buf, sizeof(buf)) < 0) {54 printf("task rename failed: %s\n", strerror(errno));55 close(fd);56 return;57 }58 }59 printf("task_rename:%d: %lld events per sec\n",60 cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));61 close(fd);62}63 64static void test_fib_table_lookup(int cpu)65{66 struct sockaddr_in addr;67 char buf[] = "test\n";68 __u64 start_time;69 int i, fd;70 71 fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);72 if (fd < 0) {73 printf("couldn't open socket\n");74 exit(1);75 }76 memset((char *)&addr, 0, sizeof(addr));77 addr.sin_addr.s_addr = inet_addr(DUMMY_IP);78 addr.sin_port = htons(DUMMY_PORT);79 addr.sin_family = AF_INET;80 start_time = time_get_ns();81 for (i = 0; i < MAX_CNT; i++) {82 if (sendto(fd, buf, strlen(buf), 0,83 (struct sockaddr *)&addr, sizeof(addr)) < 0) {84 printf("failed to start ping: %s\n", strerror(errno));85 close(fd);86 return;87 }88 }89 printf("fib_table_lookup:%d: %lld events per sec\n",90 cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));91 close(fd);92}93 94static void loop(int cpu, int flags)95{96 cpu_set_t cpuset;97 98 CPU_ZERO(&cpuset);99 CPU_SET(cpu, &cpuset);100 sched_setaffinity(0, sizeof(cpuset), &cpuset);101 102 if (flags & 1)103 test_task_rename(cpu);104 if (flags & 2)105 test_fib_table_lookup(cpu);106}107 108static void run_perf_test(int tasks, int flags)109{110 pid_t pid[tasks];111 int i;112 113 for (i = 0; i < tasks; i++) {114 pid[i] = fork();115 if (pid[i] == 0) {116 loop(i, flags);117 exit(0);118 } else if (pid[i] == -1) {119 printf("couldn't spawn #%d process\n", i);120 exit(1);121 }122 }123 for (i = 0; i < tasks; i++) {124 int status;125 126 assert(waitpid(pid[i], &status, 0) == pid[i]);127 assert(status == 0);128 }129}130 131static int load_progs(char *filename)132{133 struct bpf_program *prog;134 int err = 0;135 136 obj = bpf_object__open_file(filename, NULL);137 err = libbpf_get_error(obj);138 if (err < 0) {139 fprintf(stderr, "ERROR: opening BPF object file failed\n");140 return err;141 }142 143 /* load BPF program */144 err = bpf_object__load(obj);145 if (err < 0) {146 fprintf(stderr, "ERROR: loading BPF object file failed\n");147 return err;148 }149 150 bpf_object__for_each_program(prog, obj) {151 links[cnt] = bpf_program__attach(prog);152 err = libbpf_get_error(links[cnt]);153 if (err < 0) {154 fprintf(stderr, "ERROR: bpf_program__attach failed\n");155 links[cnt] = NULL;156 return err;157 }158 cnt++;159 }160 161 return err;162}163 164static void unload_progs(void)165{166 while (cnt)167 bpf_link__destroy(links[--cnt]);168 169 bpf_object__close(obj);170}171 172int main(int argc, char **argv)173{174 int num_cpu = sysconf(_SC_NPROCESSORS_ONLN);175 int test_flags = ~0;176 char filename[256];177 int err = 0;178 179 180 if (argc > 1)181 test_flags = atoi(argv[1]) ? : test_flags;182 if (argc > 2)183 num_cpu = atoi(argv[2]) ? : num_cpu;184 185 if (test_flags & 0x3) {186 printf("BASE\n");187 run_perf_test(num_cpu, test_flags);188 }189 190 if (test_flags & 0xC) {191 snprintf(filename, sizeof(filename),192 "%s_kprobe.bpf.o", argv[0]);193 194 printf("w/KPROBE\n");195 err = load_progs(filename);196 if (!err)197 run_perf_test(num_cpu, test_flags >> 2);198 199 unload_progs();200 }201 202 if (test_flags & 0x30) {203 snprintf(filename, sizeof(filename),204 "%s_tp.bpf.o", argv[0]);205 printf("w/TRACEPOINT\n");206 err = load_progs(filename);207 if (!err)208 run_perf_test(num_cpu, test_flags >> 4);209 210 unload_progs();211 }212 213 if (test_flags & 0xC0) {214 snprintf(filename, sizeof(filename),215 "%s_raw_tp.bpf.o", argv[0]);216 printf("w/RAW_TRACEPOINT\n");217 err = load_progs(filename);218 if (!err)219 run_perf_test(num_cpu, test_flags >> 6);220 221 unload_progs();222 }223 224 return err;225}226