libbpf.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /* eBPF mini library */
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <linux/unistd.h>
  5. #include <unistd.h>
  6. #include <string.h>
  7. #include <linux/netlink.h>
  8. #include <linux/bpf.h>
  9. #include <errno.h>
  10. #include <net/ethernet.h>
  11. #include <net/if.h>
  12. #include <linux/if_packet.h>
  13. #include <arpa/inet.h>
  14. #include "libbpf.h"
  15. static __u64 ptr_to_u64(void *ptr)
  16. {
  17. return (__u64) (unsigned long) ptr;
  18. }
  19. int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
  20. int max_entries, int map_flags)
  21. {
  22. union bpf_attr attr = {
  23. .map_type = map_type,
  24. .key_size = key_size,
  25. .value_size = value_size,
  26. .max_entries = max_entries,
  27. .map_flags = map_flags,
  28. };
  29. return syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
  30. }
  31. int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags)
  32. {
  33. union bpf_attr attr = {
  34. .map_fd = fd,
  35. .key = ptr_to_u64(key),
  36. .value = ptr_to_u64(value),
  37. .flags = flags,
  38. };
  39. return syscall(__NR_bpf, BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
  40. }
  41. int bpf_lookup_elem(int fd, void *key, void *value)
  42. {
  43. union bpf_attr attr = {
  44. .map_fd = fd,
  45. .key = ptr_to_u64(key),
  46. .value = ptr_to_u64(value),
  47. };
  48. return syscall(__NR_bpf, BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
  49. }
  50. int bpf_delete_elem(int fd, void *key)
  51. {
  52. union bpf_attr attr = {
  53. .map_fd = fd,
  54. .key = ptr_to_u64(key),
  55. };
  56. return syscall(__NR_bpf, BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
  57. }
  58. int bpf_get_next_key(int fd, void *key, void *next_key)
  59. {
  60. union bpf_attr attr = {
  61. .map_fd = fd,
  62. .key = ptr_to_u64(key),
  63. .next_key = ptr_to_u64(next_key),
  64. };
  65. return syscall(__NR_bpf, BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
  66. }
  67. #define ROUND_UP(x, n) (((x) + (n) - 1u) & ~((n) - 1u))
  68. char bpf_log_buf[LOG_BUF_SIZE];
  69. int bpf_prog_load(enum bpf_prog_type prog_type,
  70. const struct bpf_insn *insns, int prog_len,
  71. const char *license, int kern_version)
  72. {
  73. union bpf_attr attr = {
  74. .prog_type = prog_type,
  75. .insns = ptr_to_u64((void *) insns),
  76. .insn_cnt = prog_len / sizeof(struct bpf_insn),
  77. .license = ptr_to_u64((void *) license),
  78. .log_buf = ptr_to_u64(bpf_log_buf),
  79. .log_size = LOG_BUF_SIZE,
  80. .log_level = 1,
  81. };
  82. /* assign one field outside of struct init to make sure any
  83. * padding is zero initialized
  84. */
  85. attr.kern_version = kern_version;
  86. bpf_log_buf[0] = 0;
  87. return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
  88. }
  89. int bpf_obj_pin(int fd, const char *pathname)
  90. {
  91. union bpf_attr attr = {
  92. .pathname = ptr_to_u64((void *)pathname),
  93. .bpf_fd = fd,
  94. };
  95. return syscall(__NR_bpf, BPF_OBJ_PIN, &attr, sizeof(attr));
  96. }
  97. int bpf_obj_get(const char *pathname)
  98. {
  99. union bpf_attr attr = {
  100. .pathname = ptr_to_u64((void *)pathname),
  101. };
  102. return syscall(__NR_bpf, BPF_OBJ_GET, &attr, sizeof(attr));
  103. }
  104. int open_raw_sock(const char *name)
  105. {
  106. struct sockaddr_ll sll;
  107. int sock;
  108. sock = socket(PF_PACKET, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, htons(ETH_P_ALL));
  109. if (sock < 0) {
  110. printf("cannot create raw socket\n");
  111. return -1;
  112. }
  113. memset(&sll, 0, sizeof(sll));
  114. sll.sll_family = AF_PACKET;
  115. sll.sll_ifindex = if_nametoindex(name);
  116. sll.sll_protocol = htons(ETH_P_ALL);
  117. if (bind(sock, (struct sockaddr *)&sll, sizeof(sll)) < 0) {
  118. printf("bind to %s: %s\n", name, strerror(errno));
  119. close(sock);
  120. return -1;
  121. }
  122. return sock;
  123. }
  124. int perf_event_open(struct perf_event_attr *attr, int pid, int cpu,
  125. int group_fd, unsigned long flags)
  126. {
  127. return syscall(__NR_perf_event_open, attr, pid, cpu,
  128. group_fd, flags);
  129. }