ibumad_user.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
  2. /*
  3. * ibumad BPF sample user side
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of version 2 of the GNU General Public
  7. * License as published by the Free Software Foundation.
  8. *
  9. * Copyright(c) 2018 Ira Weiny, Intel Corporation
  10. */
  11. #include <linux/bpf.h>
  12. #include <signal.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <unistd.h>
  17. #include <sys/types.h>
  18. #include <limits.h>
  19. #include <getopt.h>
  20. #include <net/if.h>
  21. #include <bpf/bpf.h>
  22. #include "bpf_util.h"
  23. #include <bpf/libbpf.h>
  24. static struct bpf_link *tp_links[3];
  25. static struct bpf_object *obj;
  26. static int map_fd[2];
  27. static int tp_cnt;
  28. static void dump_counts(int fd)
  29. {
  30. __u32 key;
  31. __u64 value;
  32. for (key = 0; key < 256; key++) {
  33. if (bpf_map_lookup_elem(fd, &key, &value)) {
  34. printf("failed to read key %u\n", key);
  35. continue;
  36. }
  37. if (value)
  38. printf("0x%02x : %llu\n", key, value);
  39. }
  40. }
  41. static void dump_all_counts(void)
  42. {
  43. printf("Read 'Class : count'\n");
  44. dump_counts(map_fd[0]);
  45. printf("Write 'Class : count'\n");
  46. dump_counts(map_fd[1]);
  47. }
  48. static void dump_exit(int sig)
  49. {
  50. dump_all_counts();
  51. /* Detach tracepoints */
  52. while (tp_cnt)
  53. bpf_link__destroy(tp_links[--tp_cnt]);
  54. bpf_object__close(obj);
  55. exit(0);
  56. }
  57. static const struct option long_options[] = {
  58. {"help", no_argument, NULL, 'h'},
  59. {"delay", required_argument, NULL, 'd'},
  60. };
  61. static void usage(char *cmd)
  62. {
  63. printf("eBPF test program to count packets from various IP addresses\n"
  64. "Usage: %s <options>\n"
  65. " --help, -h this menu\n"
  66. " --delay, -d <delay> wait <delay> sec between prints [1 - 1000000]\n"
  67. , cmd
  68. );
  69. }
  70. int main(int argc, char **argv)
  71. {
  72. struct bpf_program *prog;
  73. unsigned long delay = 5;
  74. char filename[256];
  75. int longindex = 0;
  76. int opt, err = -1;
  77. while ((opt = getopt_long(argc, argv, "hd:rSw",
  78. long_options, &longindex)) != -1) {
  79. switch (opt) {
  80. case 'd':
  81. delay = strtoul(optarg, NULL, 0);
  82. if (delay == ULONG_MAX || delay < 0 ||
  83. delay > 1000000) {
  84. fprintf(stderr, "ERROR: invalid delay : %s\n",
  85. optarg);
  86. usage(argv[0]);
  87. return 1;
  88. }
  89. break;
  90. default:
  91. case 'h':
  92. usage(argv[0]);
  93. return 1;
  94. }
  95. }
  96. /* Do one final dump when exiting */
  97. signal(SIGINT, dump_exit);
  98. signal(SIGTERM, dump_exit);
  99. snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
  100. obj = bpf_object__open_file(filename, NULL);
  101. if (libbpf_get_error(obj)) {
  102. fprintf(stderr, "ERROR: opening BPF object file failed\n");
  103. return err;
  104. }
  105. /* load BPF program */
  106. if (bpf_object__load(obj)) {
  107. fprintf(stderr, "ERROR: loading BPF object file failed\n");
  108. goto cleanup;
  109. }
  110. map_fd[0] = bpf_object__find_map_fd_by_name(obj, "read_count");
  111. map_fd[1] = bpf_object__find_map_fd_by_name(obj, "write_count");
  112. if (map_fd[0] < 0 || map_fd[1] < 0) {
  113. fprintf(stderr, "ERROR: finding a map in obj file failed\n");
  114. goto cleanup;
  115. }
  116. bpf_object__for_each_program(prog, obj) {
  117. tp_links[tp_cnt] = bpf_program__attach(prog);
  118. if (libbpf_get_error(tp_links[tp_cnt])) {
  119. fprintf(stderr, "ERROR: bpf_program__attach failed\n");
  120. tp_links[tp_cnt] = NULL;
  121. goto cleanup;
  122. }
  123. tp_cnt++;
  124. }
  125. while (1) {
  126. sleep(delay);
  127. dump_all_counts();
  128. }
  129. err = 0;
  130. cleanup:
  131. /* Detach tracepoints */
  132. while (tp_cnt)
  133. bpf_link__destroy(tp_links[--tp_cnt]);
  134. bpf_object__close(obj);
  135. return err;
  136. }