xdp1_user.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Copyright (c) 2016 PLUMgrid
  3. */
  4. #include <linux/bpf.h>
  5. #include <linux/if_link.h>
  6. #include <assert.h>
  7. #include <errno.h>
  8. #include <signal.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <unistd.h>
  13. #include <libgen.h>
  14. #include <sys/resource.h>
  15. #include <net/if.h>
  16. #include "bpf_util.h"
  17. #include <bpf/bpf.h>
  18. #include <bpf/libbpf.h>
  19. static int ifindex;
  20. static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
  21. static __u32 prog_id;
  22. static void int_exit(int sig)
  23. {
  24. __u32 curr_prog_id = 0;
  25. if (bpf_get_link_xdp_id(ifindex, &curr_prog_id, xdp_flags)) {
  26. printf("bpf_get_link_xdp_id failed\n");
  27. exit(1);
  28. }
  29. if (prog_id == curr_prog_id)
  30. bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
  31. else if (!curr_prog_id)
  32. printf("couldn't find a prog id on a given interface\n");
  33. else
  34. printf("program on interface changed, not removing\n");
  35. exit(0);
  36. }
  37. /* simple per-protocol drop counter
  38. */
  39. static void poll_stats(int map_fd, int interval)
  40. {
  41. unsigned int nr_cpus = bpf_num_possible_cpus();
  42. __u64 values[nr_cpus], prev[UINT8_MAX] = { 0 };
  43. int i;
  44. while (1) {
  45. __u32 key = UINT32_MAX;
  46. sleep(interval);
  47. while (bpf_map_get_next_key(map_fd, &key, &key) != -1) {
  48. __u64 sum = 0;
  49. assert(bpf_map_lookup_elem(map_fd, &key, values) == 0);
  50. for (i = 0; i < nr_cpus; i++)
  51. sum += values[i];
  52. if (sum > prev[key])
  53. printf("proto %u: %10llu pkt/s\n",
  54. key, (sum - prev[key]) / interval);
  55. prev[key] = sum;
  56. }
  57. }
  58. }
  59. static void usage(const char *prog)
  60. {
  61. fprintf(stderr,
  62. "usage: %s [OPTS] IFACE\n\n"
  63. "OPTS:\n"
  64. " -S use skb-mode\n"
  65. " -N enforce native mode\n"
  66. " -F force loading prog\n",
  67. prog);
  68. }
  69. int main(int argc, char **argv)
  70. {
  71. struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
  72. struct bpf_prog_load_attr prog_load_attr = {
  73. .prog_type = BPF_PROG_TYPE_XDP,
  74. };
  75. struct bpf_prog_info info = {};
  76. __u32 info_len = sizeof(info);
  77. const char *optstr = "FSN";
  78. int prog_fd, map_fd, opt;
  79. struct bpf_object *obj;
  80. struct bpf_map *map;
  81. char filename[256];
  82. int err;
  83. while ((opt = getopt(argc, argv, optstr)) != -1) {
  84. switch (opt) {
  85. case 'S':
  86. xdp_flags |= XDP_FLAGS_SKB_MODE;
  87. break;
  88. case 'N':
  89. /* default, set below */
  90. break;
  91. case 'F':
  92. xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
  93. break;
  94. default:
  95. usage(basename(argv[0]));
  96. return 1;
  97. }
  98. }
  99. if (!(xdp_flags & XDP_FLAGS_SKB_MODE))
  100. xdp_flags |= XDP_FLAGS_DRV_MODE;
  101. if (optind == argc) {
  102. usage(basename(argv[0]));
  103. return 1;
  104. }
  105. if (setrlimit(RLIMIT_MEMLOCK, &r)) {
  106. perror("setrlimit(RLIMIT_MEMLOCK)");
  107. return 1;
  108. }
  109. ifindex = if_nametoindex(argv[optind]);
  110. if (!ifindex) {
  111. perror("if_nametoindex");
  112. return 1;
  113. }
  114. snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
  115. prog_load_attr.file = filename;
  116. if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
  117. return 1;
  118. map = bpf_map__next(NULL, obj);
  119. if (!map) {
  120. printf("finding a map in obj file failed\n");
  121. return 1;
  122. }
  123. map_fd = bpf_map__fd(map);
  124. if (!prog_fd) {
  125. printf("bpf_prog_load_xattr: %s\n", strerror(errno));
  126. return 1;
  127. }
  128. signal(SIGINT, int_exit);
  129. signal(SIGTERM, int_exit);
  130. if (bpf_set_link_xdp_fd(ifindex, prog_fd, xdp_flags) < 0) {
  131. printf("link set xdp fd failed\n");
  132. return 1;
  133. }
  134. err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
  135. if (err) {
  136. printf("can't get prog info - %s\n", strerror(errno));
  137. return err;
  138. }
  139. prog_id = info.id;
  140. poll_stats(map_fd, 2);
  141. return 0;
  142. }