loader.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2021 Felix Fietkau <nbd@nbd.name>
  4. */
  5. #include <sys/resource.h>
  6. #include <sys/stat.h>
  7. #include <arpa/inet.h>
  8. #include <glob.h>
  9. #include <unistd.h>
  10. #include "qosify.h"
  11. static struct {
  12. const char *suffix;
  13. uint32_t flags;
  14. int fd;
  15. } bpf_progs[] = {
  16. { "egress_eth", 0 },
  17. { "egress_ip", QOSIFY_IP_ONLY },
  18. { "ingress_eth", QOSIFY_INGRESS },
  19. { "ingress_ip", QOSIFY_INGRESS | QOSIFY_IP_ONLY },
  20. };
  21. static int qosify_bpf_pr(enum libbpf_print_level level, const char *format,
  22. va_list args)
  23. {
  24. return vfprintf(stderr, format, args);
  25. }
  26. static void qosify_init_env(void)
  27. {
  28. struct rlimit limit = {
  29. .rlim_cur = RLIM_INFINITY,
  30. .rlim_max = RLIM_INFINITY,
  31. };
  32. setrlimit(RLIMIT_MEMLOCK, &limit);
  33. }
  34. static void qosify_fill_rodata(struct bpf_object *obj, uint32_t flags)
  35. {
  36. struct bpf_map *map = NULL;
  37. while ((map = bpf_object__next_map(obj, map)) != NULL) {
  38. if (!strstr(bpf_map__name(map), ".rodata"))
  39. continue;
  40. bpf_map__set_initial_value(map, &flags, sizeof(flags));
  41. }
  42. }
  43. const char *qosify_get_program(uint32_t flags, int *fd)
  44. {
  45. int i;
  46. for (i = 0; i < ARRAY_SIZE(bpf_progs); i++) {
  47. if (bpf_progs[i].flags != flags)
  48. continue;
  49. *fd = bpf_progs[i].fd;
  50. return bpf_progs[i].suffix;
  51. }
  52. return NULL;
  53. }
  54. static int
  55. qosify_create_program(int idx)
  56. {
  57. DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts,
  58. .pin_root_path = CLASSIFY_DATA_PATH,
  59. );
  60. struct bpf_program *prog;
  61. struct bpf_object *obj;
  62. char path[256];
  63. int err;
  64. snprintf(path, sizeof(path), CLASSIFY_PIN_PATH "_" "%s", bpf_progs[idx].suffix);
  65. obj = bpf_object__open_file(CLASSIFY_PROG_PATH, &opts);
  66. err = libbpf_get_error(obj);
  67. if (err) {
  68. perror("bpf_object__open_file");
  69. return -1;
  70. }
  71. prog = bpf_object__find_program_by_name(obj, "classify");
  72. if (!prog) {
  73. fprintf(stderr, "Can't find classifier prog\n");
  74. return -1;
  75. }
  76. bpf_program__set_type(prog, BPF_PROG_TYPE_SCHED_CLS);
  77. qosify_fill_rodata(obj, bpf_progs[idx].flags);
  78. err = bpf_object__load(obj);
  79. if (err) {
  80. perror("bpf_object__load");
  81. return -1;
  82. }
  83. libbpf_set_print(NULL);
  84. unlink(path);
  85. err = bpf_program__pin(prog, path);
  86. if (err) {
  87. fprintf(stderr, "Failed to pin program to %s: %s\n",
  88. path, strerror(-err));
  89. return -1;
  90. }
  91. bpf_object__close(obj);
  92. err = bpf_obj_get(path);
  93. if (err < 0) {
  94. fprintf(stderr, "Failed to load pinned program %s: %s\n",
  95. path, strerror(errno));
  96. }
  97. bpf_progs[idx].fd = err;
  98. return 0;
  99. }
  100. int qosify_loader_init(void)
  101. {
  102. glob_t g;
  103. int i;
  104. if (glob(CLASSIFY_DATA_PATH "/*", 0, NULL, &g) == 0) {
  105. for (i = 0; i < g.gl_pathc; i++)
  106. unlink(g.gl_pathv[i]);
  107. }
  108. libbpf_set_print(qosify_bpf_pr);
  109. qosify_init_env();
  110. for (i = 0; i < ARRAY_SIZE(bpf_progs); i++) {
  111. if (qosify_create_program(i))
  112. return -1;
  113. }
  114. return 0;
  115. }