test_overhead_user.c 4.5 KB

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