flow_dissector_load.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <error.h>
  3. #include <errno.h>
  4. #include <getopt.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <sys/stat.h>
  9. #include <fcntl.h>
  10. #include <unistd.h>
  11. #include <bpf/bpf.h>
  12. #include <bpf/libbpf.h>
  13. #include "bpf_rlimit.h"
  14. const char *cfg_pin_path = "/sys/fs/bpf/flow_dissector";
  15. const char *cfg_map_name = "jmp_table";
  16. bool cfg_attach = true;
  17. char *cfg_section_name;
  18. char *cfg_path_name;
  19. static void load_and_attach_program(void)
  20. {
  21. struct bpf_program *prog, *main_prog;
  22. struct bpf_map *prog_array;
  23. int i, fd, prog_fd, ret;
  24. struct bpf_object *obj;
  25. int prog_array_fd;
  26. ret = bpf_prog_load(cfg_path_name, BPF_PROG_TYPE_FLOW_DISSECTOR, &obj,
  27. &prog_fd);
  28. if (ret)
  29. error(1, 0, "bpf_prog_load %s", cfg_path_name);
  30. main_prog = bpf_object__find_program_by_title(obj, cfg_section_name);
  31. if (!main_prog)
  32. error(1, 0, "bpf_object__find_program_by_title %s",
  33. cfg_section_name);
  34. prog_fd = bpf_program__fd(main_prog);
  35. if (prog_fd < 0)
  36. error(1, 0, "bpf_program__fd");
  37. prog_array = bpf_object__find_map_by_name(obj, cfg_map_name);
  38. if (!prog_array)
  39. error(1, 0, "bpf_object__find_map_by_name %s", cfg_map_name);
  40. prog_array_fd = bpf_map__fd(prog_array);
  41. if (prog_array_fd < 0)
  42. error(1, 0, "bpf_map__fd %s", cfg_map_name);
  43. i = 0;
  44. bpf_object__for_each_program(prog, obj) {
  45. fd = bpf_program__fd(prog);
  46. if (fd < 0)
  47. error(1, 0, "bpf_program__fd");
  48. if (fd != prog_fd) {
  49. printf("%d: %s\n", i, bpf_program__title(prog, false));
  50. bpf_map_update_elem(prog_array_fd, &i, &fd, BPF_ANY);
  51. ++i;
  52. }
  53. }
  54. ret = bpf_prog_attach(prog_fd, 0 /* Ignore */, BPF_FLOW_DISSECTOR, 0);
  55. if (ret)
  56. error(1, 0, "bpf_prog_attach %s", cfg_path_name);
  57. ret = bpf_object__pin(obj, cfg_pin_path);
  58. if (ret)
  59. error(1, 0, "bpf_object__pin %s", cfg_pin_path);
  60. }
  61. static void detach_program(void)
  62. {
  63. char command[64];
  64. int ret;
  65. ret = bpf_prog_detach(0, BPF_FLOW_DISSECTOR);
  66. if (ret)
  67. error(1, 0, "bpf_prog_detach");
  68. /* To unpin, it is necessary and sufficient to just remove this dir */
  69. sprintf(command, "rm -r %s", cfg_pin_path);
  70. ret = system(command);
  71. if (ret)
  72. error(1, errno, command);
  73. }
  74. static void parse_opts(int argc, char **argv)
  75. {
  76. bool attach = false;
  77. bool detach = false;
  78. int c;
  79. while ((c = getopt(argc, argv, "adp:s:")) != -1) {
  80. switch (c) {
  81. case 'a':
  82. if (detach)
  83. error(1, 0, "attach/detach are exclusive");
  84. attach = true;
  85. break;
  86. case 'd':
  87. if (attach)
  88. error(1, 0, "attach/detach are exclusive");
  89. detach = true;
  90. break;
  91. case 'p':
  92. if (cfg_path_name)
  93. error(1, 0, "only one prog name can be given");
  94. cfg_path_name = optarg;
  95. break;
  96. case 's':
  97. if (cfg_section_name)
  98. error(1, 0, "only one section can be given");
  99. cfg_section_name = optarg;
  100. break;
  101. }
  102. }
  103. if (detach)
  104. cfg_attach = false;
  105. if (cfg_attach && !cfg_path_name)
  106. error(1, 0, "must provide a path to the BPF program");
  107. if (cfg_attach && !cfg_section_name)
  108. error(1, 0, "must provide a section name");
  109. }
  110. int main(int argc, char **argv)
  111. {
  112. parse_opts(argc, argv);
  113. if (cfg_attach)
  114. load_and_attach_program();
  115. else
  116. detach_program();
  117. return 0;
  118. }