bpf.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
  4. */
  5. #define _GNU_SOURCE
  6. #include <sys/types.h>
  7. #include <sys/socket.h>
  8. #include <sys/resource.h>
  9. #include <netinet/if_ether.h>
  10. #include <netlink/msg.h>
  11. #include <netlink/attr.h>
  12. #include <netlink/socket.h>
  13. #include <linux/rtnetlink.h>
  14. #include <linux/pkt_cls.h>
  15. #include <bpf/bpf.h>
  16. #include <bpf/libbpf.h>
  17. #include "unetd.h"
  18. static int unetd_bpf_pr(enum libbpf_print_level level, const char *format,
  19. va_list args)
  20. {
  21. return vfprintf(stderr, format, args);
  22. }
  23. static void unetd_init_env(void)
  24. {
  25. struct rlimit limit = {
  26. .rlim_cur = RLIM_INFINITY,
  27. .rlim_max = RLIM_INFINITY,
  28. };
  29. setrlimit(RLIMIT_MEMLOCK, &limit);
  30. }
  31. static void
  32. unetd_set_prog_mtu(struct bpf_object *obj, uint32_t mtu)
  33. {
  34. struct bpf_map *map = NULL;
  35. while ((map = bpf_object__next_map(obj, map)) != NULL) {
  36. if (!strstr(bpf_map__name(map), ".rodata"))
  37. continue;
  38. bpf_map__set_initial_value(map, &mtu, sizeof(mtu));
  39. }
  40. }
  41. static int
  42. unetd_attach_bpf_prog(int ifindex, int fd, bool egress)
  43. {
  44. DECLARE_LIBBPF_OPTS(bpf_tc_hook, hook,
  45. .attach_point = egress ? BPF_TC_EGRESS : BPF_TC_INGRESS,
  46. .ifindex = ifindex);
  47. DECLARE_LIBBPF_OPTS(bpf_tc_opts, attach_tc,
  48. .flags = BPF_TC_F_REPLACE,
  49. .handle = 1,
  50. .prog_fd = fd,
  51. .priority = UNETD_MSS_PRIO_BASE);
  52. bpf_tc_hook_create(&hook);
  53. return bpf_tc_attach(&hook, &attach_tc);
  54. }
  55. int unetd_attach_mssfix(int ifindex, int mtu)
  56. {
  57. struct bpf_program *prog;
  58. struct bpf_object *obj;
  59. int prog_fd;
  60. int ret = -1;
  61. if (rtnl_init())
  62. return -1;
  63. unetd_init_env();
  64. libbpf_set_print(unetd_bpf_pr);
  65. obj = bpf_object__open_file(mssfix_path, NULL);
  66. if (libbpf_get_error(obj)) {
  67. perror("bpf_object__open_file");
  68. goto out;
  69. }
  70. prog = bpf_object__find_program_by_name(obj, "mssfix");
  71. if (!prog) {
  72. perror("bpf_object__find_program_by_name");
  73. goto out;
  74. }
  75. bpf_program__set_type(prog, BPF_PROG_TYPE_SCHED_CLS);
  76. unetd_set_prog_mtu(obj, mtu);
  77. if (bpf_object__load(obj)) {
  78. perror("bpf_object__load");
  79. goto out;
  80. }
  81. prog_fd = bpf_program__fd(prog);
  82. unetd_attach_bpf_prog(ifindex, prog_fd, true);
  83. unetd_attach_bpf_prog(ifindex, prog_fd, false);
  84. ret = 0;
  85. out:
  86. bpf_object__close(obj);
  87. return ret;
  88. }