ebpf_fd.c 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "ebpf.h"
  3. #include "ebpf_fd.h"
  4. static char *fd_dimension_names[NETDATA_FD_SYSCALL_END] = { "open", "close" };
  5. static char *fd_id_names[NETDATA_FD_SYSCALL_END] = { "do_sys_open", "__close_fd" };
  6. static char *close_targets[NETDATA_EBPF_MAX_FD_TARGETS] = {"close_fd", "__close_fd"};
  7. static char *open_targets[NETDATA_EBPF_MAX_FD_TARGETS] = {"do_sys_openat2", "do_sys_open"};
  8. static netdata_syscall_stat_t fd_aggregated_data[NETDATA_FD_SYSCALL_END];
  9. static netdata_publish_syscall_t fd_publish_aggregated[NETDATA_FD_SYSCALL_END];
  10. static ebpf_local_maps_t fd_maps[] = {{.name = "tbl_fd_pid", .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
  11. .user_input = 0,
  12. .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
  13. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
  14. {.name = "tbl_fd_global", .internal_input = NETDATA_KEY_END_VECTOR,
  15. .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
  16. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
  17. {.name = "fd_ctrl", .internal_input = NETDATA_CONTROLLER_END,
  18. .user_input = 0,
  19. .type = NETDATA_EBPF_MAP_CONTROLLER,
  20. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
  21. {.name = NULL, .internal_input = 0, .user_input = 0,
  22. .type = NETDATA_EBPF_MAP_CONTROLLER,
  23. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}};
  24. struct config fd_config = { .first_section = NULL, .last_section = NULL, .mutex = NETDATA_MUTEX_INITIALIZER,
  25. .index = {.avl_tree = { .root = NULL, .compar = appconfig_section_compare },
  26. .rwlock = AVL_LOCK_INITIALIZER } };
  27. static netdata_idx_t fd_hash_values[NETDATA_FD_COUNTER];
  28. static netdata_idx_t *fd_values = NULL;
  29. netdata_fd_stat_t *fd_vector = NULL;
  30. netdata_ebpf_targets_t fd_targets[] = { {.name = "open", .mode = EBPF_LOAD_TRAMPOLINE},
  31. {.name = "close", .mode = EBPF_LOAD_TRAMPOLINE},
  32. {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
  33. #ifdef LIBBPF_MAJOR_VERSION
  34. /**
  35. * Disable probe
  36. *
  37. * Disable all probes to use exclusively another method.
  38. *
  39. * @param obj is the main structure for bpf objects
  40. */
  41. static inline void ebpf_fd_disable_probes(struct fd_bpf *obj)
  42. {
  43. bpf_program__set_autoload(obj->progs.netdata_sys_open_kprobe, false);
  44. bpf_program__set_autoload(obj->progs.netdata_sys_open_kretprobe, false);
  45. bpf_program__set_autoload(obj->progs.netdata_release_task_fd_kprobe, false);
  46. if (!strcmp(fd_targets[NETDATA_FD_SYSCALL_CLOSE].name, close_targets[NETDATA_FD_CLOSE_FD])) {
  47. bpf_program__set_autoload(obj->progs.netdata___close_fd_kretprobe, false);
  48. bpf_program__set_autoload(obj->progs.netdata___close_fd_kprobe, false);
  49. bpf_program__set_autoload(obj->progs.netdata_close_fd_kprobe, false);
  50. } else {
  51. bpf_program__set_autoload(obj->progs.netdata___close_fd_kprobe, false);
  52. bpf_program__set_autoload(obj->progs.netdata_close_fd_kretprobe, false);
  53. bpf_program__set_autoload(obj->progs.netdata_close_fd_kprobe, false);
  54. }
  55. }
  56. /*
  57. * Disable specific probe
  58. *
  59. * Disable probes according the kernel version
  60. *
  61. * @param obj is the main structure for bpf objects
  62. */
  63. static inline void ebpf_disable_specific_probes(struct fd_bpf *obj)
  64. {
  65. if (!strcmp(fd_targets[NETDATA_FD_SYSCALL_CLOSE].name, close_targets[NETDATA_FD_CLOSE_FD])) {
  66. bpf_program__set_autoload(obj->progs.netdata___close_fd_kretprobe, false);
  67. bpf_program__set_autoload(obj->progs.netdata___close_fd_kprobe, false);
  68. } else {
  69. bpf_program__set_autoload(obj->progs.netdata_close_fd_kretprobe, false);
  70. bpf_program__set_autoload(obj->progs.netdata_close_fd_kprobe, false);
  71. }
  72. }
  73. /*
  74. * Disable trampoline
  75. *
  76. * Disable all trampoline to use exclusively another method.
  77. *
  78. * @param obj is the main structure for bpf objects.
  79. */
  80. static inline void ebpf_disable_trampoline(struct fd_bpf *obj)
  81. {
  82. bpf_program__set_autoload(obj->progs.netdata_sys_open_fentry, false);
  83. bpf_program__set_autoload(obj->progs.netdata_sys_open_fexit, false);
  84. bpf_program__set_autoload(obj->progs.netdata_close_fd_fentry, false);
  85. bpf_program__set_autoload(obj->progs.netdata_close_fd_fexit, false);
  86. bpf_program__set_autoload(obj->progs.netdata___close_fd_fentry, false);
  87. bpf_program__set_autoload(obj->progs.netdata___close_fd_fexit, false);
  88. bpf_program__set_autoload(obj->progs.netdata_release_task_fd_fentry, false);
  89. }
  90. /*
  91. * Disable specific trampoline
  92. *
  93. * Disable trampoline according to kernel version.
  94. *
  95. * @param obj is the main structure for bpf objects.
  96. */
  97. static inline void ebpf_disable_specific_trampoline(struct fd_bpf *obj)
  98. {
  99. if (!strcmp(fd_targets[NETDATA_FD_SYSCALL_CLOSE].name, close_targets[NETDATA_FD_CLOSE_FD])) {
  100. bpf_program__set_autoload(obj->progs.netdata___close_fd_fentry, false);
  101. bpf_program__set_autoload(obj->progs.netdata___close_fd_fexit, false);
  102. } else {
  103. bpf_program__set_autoload(obj->progs.netdata_close_fd_fentry, false);
  104. bpf_program__set_autoload(obj->progs.netdata_close_fd_fexit, false);
  105. }
  106. }
  107. /**
  108. * Set trampoline target
  109. *
  110. * Set the targets we will monitor.
  111. *
  112. * @param obj is the main structure for bpf objects.
  113. */
  114. static void ebpf_set_trampoline_target(struct fd_bpf *obj)
  115. {
  116. bpf_program__set_attach_target(obj->progs.netdata_sys_open_fentry, 0, fd_targets[NETDATA_FD_SYSCALL_OPEN].name);
  117. bpf_program__set_attach_target(obj->progs.netdata_sys_open_fexit, 0, fd_targets[NETDATA_FD_SYSCALL_OPEN].name);
  118. bpf_program__set_attach_target(obj->progs.netdata_release_task_fd_fentry, 0, EBPF_COMMON_FNCT_CLEAN_UP);
  119. if (!strcmp(fd_targets[NETDATA_FD_SYSCALL_CLOSE].name, close_targets[NETDATA_FD_CLOSE_FD])) {
  120. bpf_program__set_attach_target(
  121. obj->progs.netdata_close_fd_fentry, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
  122. bpf_program__set_attach_target(obj->progs.netdata_close_fd_fexit, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
  123. } else {
  124. bpf_program__set_attach_target(
  125. obj->progs.netdata___close_fd_fentry, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
  126. bpf_program__set_attach_target(
  127. obj->progs.netdata___close_fd_fexit, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
  128. }
  129. }
  130. /**
  131. * Mount Attach Probe
  132. *
  133. * Attach probes to target
  134. *
  135. * @param obj is the main structure for bpf objects.
  136. *
  137. * @return It returns 0 on success and -1 otherwise.
  138. */
  139. static int ebpf_fd_attach_probe(struct fd_bpf *obj)
  140. {
  141. obj->links.netdata_sys_open_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_sys_open_kprobe, false,
  142. fd_targets[NETDATA_FD_SYSCALL_OPEN].name);
  143. int ret = libbpf_get_error(obj->links.netdata_sys_open_kprobe);
  144. if (ret)
  145. return -1;
  146. obj->links.netdata_sys_open_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_sys_open_kretprobe, true,
  147. fd_targets[NETDATA_FD_SYSCALL_OPEN].name);
  148. ret = libbpf_get_error(obj->links.netdata_sys_open_kretprobe);
  149. if (ret)
  150. return -1;
  151. obj->links.netdata_release_task_fd_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_release_task_fd_kprobe,
  152. false,
  153. EBPF_COMMON_FNCT_CLEAN_UP);
  154. ret = libbpf_get_error(obj->links.netdata_release_task_fd_kprobe);
  155. if (ret)
  156. return -1;
  157. if (!strcmp(fd_targets[NETDATA_FD_SYSCALL_CLOSE].name, close_targets[NETDATA_FD_CLOSE_FD])) {
  158. obj->links.netdata_close_fd_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_close_fd_kretprobe, true,
  159. fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
  160. ret = libbpf_get_error(obj->links.netdata_close_fd_kretprobe);
  161. if (ret)
  162. return -1;
  163. obj->links.netdata_close_fd_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_close_fd_kprobe, false,
  164. fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
  165. ret = libbpf_get_error(obj->links.netdata_close_fd_kprobe);
  166. if (ret)
  167. return -1;
  168. } else {
  169. obj->links.netdata___close_fd_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata___close_fd_kretprobe,
  170. true,
  171. fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
  172. ret = libbpf_get_error(obj->links.netdata___close_fd_kretprobe);
  173. if (ret)
  174. return -1;
  175. obj->links.netdata___close_fd_kprobe = bpf_program__attach_kprobe(obj->progs.netdata___close_fd_kprobe,
  176. false,
  177. fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
  178. ret = libbpf_get_error(obj->links.netdata___close_fd_kprobe);
  179. if (ret)
  180. return -1;
  181. }
  182. return 0;
  183. }
  184. /**
  185. * FD Fill Address
  186. *
  187. * Fill address value used to load probes/trampoline.
  188. */
  189. static inline void ebpf_fd_fill_address(ebpf_addresses_t *address, char **targets)
  190. {
  191. int i;
  192. for (i = 0; i < NETDATA_EBPF_MAX_FD_TARGETS; i++) {
  193. address->function = targets[i];
  194. ebpf_load_addresses(address, -1);
  195. if (address->addr)
  196. break;
  197. }
  198. }
  199. /**
  200. * Set target values
  201. *
  202. * Set pointers used to load data.
  203. *
  204. * @return It returns 0 on success and -1 otherwise.
  205. */
  206. static int ebpf_fd_set_target_values()
  207. {
  208. ebpf_addresses_t address = {.function = NULL, .hash = 0, .addr = 0};
  209. ebpf_fd_fill_address(&address, close_targets);
  210. if (!address.addr)
  211. return -1;
  212. fd_targets[NETDATA_FD_SYSCALL_CLOSE].name = address.function;
  213. address.addr = 0;
  214. ebpf_fd_fill_address(&address, open_targets);
  215. if (!address.addr)
  216. return -1;
  217. fd_targets[NETDATA_FD_SYSCALL_OPEN].name = address.function;
  218. return 0;
  219. }
  220. /**
  221. * Set hash tables
  222. *
  223. * Set the values for maps according the value given by kernel.
  224. *
  225. * @param obj is the main structure for bpf objects.
  226. */
  227. static void ebpf_fd_set_hash_tables(struct fd_bpf *obj)
  228. {
  229. fd_maps[NETDATA_FD_GLOBAL_STATS].map_fd = bpf_map__fd(obj->maps.tbl_fd_global);
  230. fd_maps[NETDATA_FD_PID_STATS].map_fd = bpf_map__fd(obj->maps.tbl_fd_pid);
  231. fd_maps[NETDATA_FD_CONTROLLER].map_fd = bpf_map__fd(obj->maps.fd_ctrl);
  232. }
  233. /**
  234. * Adjust Map Size
  235. *
  236. * Resize maps according input from users.
  237. *
  238. * @param obj is the main structure for bpf objects.
  239. * @param em structure with configuration
  240. */
  241. static void ebpf_fd_adjust_map_size(struct fd_bpf *obj, ebpf_module_t *em)
  242. {
  243. ebpf_update_map_size(obj->maps.tbl_fd_pid, &fd_maps[NETDATA_FD_PID_STATS],
  244. em, bpf_map__name(obj->maps.tbl_fd_pid));
  245. }
  246. /**
  247. * Disable Release Task
  248. *
  249. * Disable release task when apps is not enabled.
  250. *
  251. * @param obj is the main structure for bpf objects.
  252. */
  253. static void ebpf_fd_disable_release_task(struct fd_bpf *obj)
  254. {
  255. bpf_program__set_autoload(obj->progs.netdata_release_task_fd_kprobe, false);
  256. bpf_program__set_autoload(obj->progs.netdata_release_task_fd_fentry, false);
  257. }
  258. /**
  259. * Load and attach
  260. *
  261. * Load and attach the eBPF code in kernel.
  262. *
  263. * @param obj is the main structure for bpf objects.
  264. * @param em structure with configuration
  265. *
  266. * @return it returns 0 on success and -1 otherwise
  267. */
  268. static inline int ebpf_fd_load_and_attach(struct fd_bpf *obj, ebpf_module_t *em)
  269. {
  270. netdata_ebpf_targets_t *mt = em->targets;
  271. netdata_ebpf_program_loaded_t test = mt[NETDATA_FD_SYSCALL_OPEN].mode;
  272. if (ebpf_fd_set_target_values()) {
  273. error("%s file descriptor.", NETDATA_EBPF_DEFAULT_FNT_NOT_FOUND);
  274. return -1;
  275. }
  276. if (test == EBPF_LOAD_TRAMPOLINE) {
  277. ebpf_fd_disable_probes(obj);
  278. ebpf_disable_specific_trampoline(obj);
  279. ebpf_set_trampoline_target(obj);
  280. // TODO: Remove this in next PR, because this specific trampoline has an error.
  281. bpf_program__set_autoload(obj->progs.netdata_release_task_fd_fentry, false);
  282. } else {
  283. ebpf_disable_trampoline(obj);
  284. ebpf_disable_specific_probes(obj);
  285. }
  286. ebpf_fd_adjust_map_size(obj, em);
  287. if (!em->apps_charts && !em->cgroup_charts)
  288. ebpf_fd_disable_release_task(obj);
  289. int ret = fd_bpf__load(obj);
  290. if (ret) {
  291. return ret;
  292. }
  293. ret = (test == EBPF_LOAD_TRAMPOLINE) ? fd_bpf__attach(obj) : ebpf_fd_attach_probe(obj);
  294. if (!ret) {
  295. ebpf_fd_set_hash_tables(obj);
  296. ebpf_update_controller(fd_maps[NETDATA_CACHESTAT_CTRL].map_fd, em);
  297. }
  298. return ret;
  299. }
  300. #endif
  301. /*****************************************************************
  302. *
  303. * FUNCTIONS TO CLOSE THE THREAD
  304. *
  305. *****************************************************************/
  306. /**
  307. * FD Free
  308. *
  309. * Cleanup variables after child threads to stop
  310. *
  311. * @param ptr thread data.
  312. */
  313. static void ebpf_fd_free(ebpf_module_t *em)
  314. {
  315. pthread_mutex_lock(&ebpf_exit_cleanup);
  316. em->enabled = NETDATA_THREAD_EBPF_STOPPING;
  317. pthread_mutex_unlock(&ebpf_exit_cleanup);
  318. freez(fd_values);
  319. freez(fd_vector);
  320. pthread_mutex_lock(&ebpf_exit_cleanup);
  321. em->enabled = NETDATA_THREAD_EBPF_STOPPED;
  322. pthread_mutex_unlock(&ebpf_exit_cleanup);
  323. }
  324. /**
  325. * FD Exit
  326. *
  327. * Cancel child thread and exit.
  328. *
  329. * @param ptr thread data.
  330. */
  331. static void ebpf_fd_exit(void *ptr)
  332. {
  333. ebpf_module_t *em = (ebpf_module_t *)ptr;
  334. ebpf_fd_free(em);
  335. }
  336. /*****************************************************************
  337. *
  338. * MAIN LOOP
  339. *
  340. *****************************************************************/
  341. /**
  342. * Send data to Netdata calling auxiliary functions.
  343. *
  344. * @param em the structure with thread information
  345. */
  346. static void ebpf_fd_send_data(ebpf_module_t *em)
  347. {
  348. fd_publish_aggregated[NETDATA_FD_SYSCALL_OPEN].ncall = fd_hash_values[NETDATA_KEY_CALLS_DO_SYS_OPEN];
  349. fd_publish_aggregated[NETDATA_FD_SYSCALL_OPEN].nerr = fd_hash_values[NETDATA_KEY_ERROR_DO_SYS_OPEN];
  350. fd_publish_aggregated[NETDATA_FD_SYSCALL_CLOSE].ncall = fd_hash_values[NETDATA_KEY_CALLS_CLOSE_FD];
  351. fd_publish_aggregated[NETDATA_FD_SYSCALL_CLOSE].nerr = fd_hash_values[NETDATA_KEY_ERROR_CLOSE_FD];
  352. write_count_chart(NETDATA_FILE_OPEN_CLOSE_COUNT, NETDATA_FILESYSTEM_FAMILY, fd_publish_aggregated,
  353. NETDATA_FD_SYSCALL_END);
  354. if (em->mode < MODE_ENTRY) {
  355. write_err_chart(NETDATA_FILE_OPEN_ERR_COUNT, NETDATA_FILESYSTEM_FAMILY,
  356. fd_publish_aggregated, NETDATA_FD_SYSCALL_END);
  357. }
  358. }
  359. /**
  360. * Read global counter
  361. *
  362. * Read the table with number of calls for all functions
  363. */
  364. static void ebpf_fd_read_global_table()
  365. {
  366. uint32_t idx;
  367. netdata_idx_t *val = fd_hash_values;
  368. netdata_idx_t *stored = fd_values;
  369. int fd = fd_maps[NETDATA_FD_GLOBAL_STATS].map_fd;
  370. for (idx = NETDATA_KEY_CALLS_DO_SYS_OPEN; idx < NETDATA_FD_COUNTER; idx++) {
  371. if (!bpf_map_lookup_elem(fd, &idx, stored)) {
  372. int i;
  373. int end = ebpf_nprocs;
  374. netdata_idx_t total = 0;
  375. for (i = 0; i < end; i++)
  376. total += stored[i];
  377. val[idx] = total;
  378. }
  379. }
  380. }
  381. /**
  382. * Apps Accumulator
  383. *
  384. * Sum all values read from kernel and store in the first address.
  385. *
  386. * @param out the vector with read values.
  387. */
  388. static void fd_apps_accumulator(netdata_fd_stat_t *out)
  389. {
  390. int i, end = (running_on_kernel >= NETDATA_KERNEL_V4_15) ? ebpf_nprocs : 1;
  391. netdata_fd_stat_t *total = &out[0];
  392. for (i = 1; i < end; i++) {
  393. netdata_fd_stat_t *w = &out[i];
  394. total->open_call += w->open_call;
  395. total->close_call += w->close_call;
  396. total->open_err += w->open_err;
  397. total->close_err += w->close_err;
  398. }
  399. }
  400. /**
  401. * Fill PID
  402. *
  403. * Fill PID structures
  404. *
  405. * @param current_pid pid that we are collecting data
  406. * @param out values read from hash tables;
  407. */
  408. static void fd_fill_pid(uint32_t current_pid, netdata_fd_stat_t *publish)
  409. {
  410. netdata_fd_stat_t *curr = fd_pid[current_pid];
  411. if (!curr) {
  412. curr = ebpf_fd_stat_get();
  413. fd_pid[current_pid] = curr;
  414. }
  415. memcpy(curr, &publish[0], sizeof(netdata_fd_stat_t));
  416. }
  417. /**
  418. * Read APPS table
  419. *
  420. * Read the apps table and store data inside the structure.
  421. */
  422. static void read_apps_table()
  423. {
  424. netdata_fd_stat_t *fv = fd_vector;
  425. uint32_t key;
  426. struct ebpf_pid_stat *pids = ebpf_root_of_pids;
  427. int fd = fd_maps[NETDATA_FD_PID_STATS].map_fd;
  428. size_t length = sizeof(netdata_fd_stat_t) * ebpf_nprocs;
  429. while (pids) {
  430. key = pids->pid;
  431. if (bpf_map_lookup_elem(fd, &key, fv)) {
  432. pids = pids->next;
  433. continue;
  434. }
  435. fd_apps_accumulator(fv);
  436. fd_fill_pid(key, fv);
  437. // We are cleaning to avoid passing data read from one process to other.
  438. memset(fv, 0, length);
  439. pids = pids->next;
  440. }
  441. }
  442. /**
  443. * Update cgroup
  444. *
  445. * Update cgroup data based in
  446. */
  447. static void ebpf_update_fd_cgroup()
  448. {
  449. ebpf_cgroup_target_t *ect ;
  450. netdata_fd_stat_t *fv = fd_vector;
  451. int fd = fd_maps[NETDATA_FD_PID_STATS].map_fd;
  452. size_t length = sizeof(netdata_fd_stat_t) * ebpf_nprocs;
  453. pthread_mutex_lock(&mutex_cgroup_shm);
  454. for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
  455. struct pid_on_target2 *pids;
  456. for (pids = ect->pids; pids; pids = pids->next) {
  457. int pid = pids->pid;
  458. netdata_fd_stat_t *out = &pids->fd;
  459. if (likely(fd_pid) && fd_pid[pid]) {
  460. netdata_fd_stat_t *in = fd_pid[pid];
  461. memcpy(out, in, sizeof(netdata_fd_stat_t));
  462. } else {
  463. memset(fv, 0, length);
  464. if (!bpf_map_lookup_elem(fd, &pid, fv)) {
  465. fd_apps_accumulator(fv);
  466. memcpy(out, fv, sizeof(netdata_fd_stat_t));
  467. }
  468. }
  469. }
  470. }
  471. pthread_mutex_unlock(&mutex_cgroup_shm);
  472. }
  473. /**
  474. * Sum PIDs
  475. *
  476. * Sum values for all targets.
  477. *
  478. * @param fd the output
  479. * @param root list of pids
  480. */
  481. static void ebpf_fd_sum_pids(netdata_fd_stat_t *fd, struct ebpf_pid_on_target *root)
  482. {
  483. uint32_t open_call = 0;
  484. uint32_t close_call = 0;
  485. uint32_t open_err = 0;
  486. uint32_t close_err = 0;
  487. while (root) {
  488. int32_t pid = root->pid;
  489. netdata_fd_stat_t *w = fd_pid[pid];
  490. if (w) {
  491. open_call += w->open_call;
  492. close_call += w->close_call;
  493. open_err += w->open_err;
  494. close_err += w->close_err;
  495. }
  496. root = root->next;
  497. }
  498. // These conditions were added, because we are using incremental algorithm
  499. fd->open_call = (open_call >= fd->open_call) ? open_call : fd->open_call;
  500. fd->close_call = (close_call >= fd->close_call) ? close_call : fd->close_call;
  501. fd->open_err = (open_err >= fd->open_err) ? open_err : fd->open_err;
  502. fd->close_err = (close_err >= fd->close_err) ? close_err : fd->close_err;
  503. }
  504. /**
  505. * Send data to Netdata calling auxiliary functions.
  506. *
  507. * @param em the structure with thread information
  508. * @param root the target list.
  509. */
  510. void ebpf_fd_send_apps_data(ebpf_module_t *em, struct ebpf_target *root)
  511. {
  512. struct ebpf_target *w;
  513. for (w = root; w; w = w->next) {
  514. if (unlikely(w->exposed && w->processes)) {
  515. ebpf_fd_sum_pids(&w->fd, w->root_pid);
  516. }
  517. }
  518. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_FILE_OPEN);
  519. for (w = root; w; w = w->next) {
  520. if (unlikely(w->exposed && w->processes)) {
  521. write_chart_dimension(w->name, w->fd.open_call);
  522. }
  523. }
  524. write_end_chart();
  525. if (em->mode < MODE_ENTRY) {
  526. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR);
  527. for (w = root; w; w = w->next) {
  528. if (unlikely(w->exposed && w->processes)) {
  529. write_chart_dimension(w->name, w->fd.open_err);
  530. }
  531. }
  532. write_end_chart();
  533. }
  534. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_FILE_CLOSED);
  535. for (w = root; w; w = w->next) {
  536. if (unlikely(w->exposed && w->processes)) {
  537. write_chart_dimension(w->name, w->fd.close_call);
  538. }
  539. }
  540. write_end_chart();
  541. if (em->mode < MODE_ENTRY) {
  542. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR);
  543. for (w = root; w; w = w->next) {
  544. if (unlikely(w->exposed && w->processes)) {
  545. write_chart_dimension(w->name, w->fd.close_err);
  546. }
  547. }
  548. write_end_chart();
  549. }
  550. }
  551. /**
  552. * Sum PIDs
  553. *
  554. * Sum values for all targets.
  555. *
  556. * @param fd structure used to store data
  557. * @param pids input data
  558. */
  559. static void ebpf_fd_sum_cgroup_pids(netdata_fd_stat_t *fd, struct pid_on_target2 *pids)
  560. {
  561. netdata_fd_stat_t accumulator;
  562. memset(&accumulator, 0, sizeof(accumulator));
  563. while (pids) {
  564. netdata_fd_stat_t *w = &pids->fd;
  565. accumulator.open_err += w->open_err;
  566. accumulator.open_call += w->open_call;
  567. accumulator.close_call += w->close_call;
  568. accumulator.close_err += w->close_err;
  569. pids = pids->next;
  570. }
  571. fd->open_call = (accumulator.open_call >= fd->open_call) ? accumulator.open_call : fd->open_call;
  572. fd->open_err = (accumulator.open_err >= fd->open_err) ? accumulator.open_err : fd->open_err;
  573. fd->close_call = (accumulator.close_call >= fd->close_call) ? accumulator.close_call : fd->close_call;
  574. fd->close_err = (accumulator.close_err >= fd->close_err) ? accumulator.close_err : fd->close_err;
  575. }
  576. /**
  577. * Create specific file descriptor charts
  578. *
  579. * Create charts for cgroup/application.
  580. *
  581. * @param type the chart type.
  582. * @param em the main thread structure.
  583. */
  584. static void ebpf_create_specific_fd_charts(char *type, ebpf_module_t *em)
  585. {
  586. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_FILE_OPEN, "Number of open files",
  587. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
  588. NETDATA_CGROUP_FD_OPEN_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  589. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5400,
  590. ebpf_create_global_dimension,
  591. &fd_publish_aggregated[NETDATA_FD_SYSCALL_OPEN],
  592. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_FD);
  593. if (em->mode < MODE_ENTRY) {
  594. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR, "Fails to open files",
  595. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
  596. NETDATA_CGROUP_FD_OPEN_ERR_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  597. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5401,
  598. ebpf_create_global_dimension,
  599. &fd_publish_aggregated[NETDATA_FD_SYSCALL_OPEN],
  600. 1, em->update_every,
  601. NETDATA_EBPF_MODULE_NAME_FD);
  602. }
  603. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_FILE_CLOSED, "Files closed",
  604. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
  605. NETDATA_CGROUP_FD_CLOSE_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  606. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5402,
  607. ebpf_create_global_dimension,
  608. &fd_publish_aggregated[NETDATA_FD_SYSCALL_CLOSE],
  609. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_FD);
  610. if (em->mode < MODE_ENTRY) {
  611. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR, "Fails to close files",
  612. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
  613. NETDATA_CGROUP_FD_CLOSE_ERR_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  614. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5403,
  615. ebpf_create_global_dimension,
  616. &fd_publish_aggregated[NETDATA_FD_SYSCALL_CLOSE],
  617. 1, em->update_every,
  618. NETDATA_EBPF_MODULE_NAME_FD);
  619. }
  620. }
  621. /**
  622. * Obsolete specific file descriptor charts
  623. *
  624. * Obsolete charts for cgroup/application.
  625. *
  626. * @param type the chart type.
  627. * @param em the main thread structure.
  628. */
  629. static void ebpf_obsolete_specific_fd_charts(char *type, ebpf_module_t *em)
  630. {
  631. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_FILE_OPEN, "Number of open files",
  632. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_GROUP,
  633. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_FD_OPEN_CONTEXT,
  634. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5400, em->update_every);
  635. if (em->mode < MODE_ENTRY) {
  636. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR, "Fails to open files",
  637. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_GROUP,
  638. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_FD_OPEN_ERR_CONTEXT,
  639. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5401, em->update_every);
  640. }
  641. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_FILE_CLOSED, "Files closed",
  642. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_GROUP,
  643. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_FD_CLOSE_CONTEXT,
  644. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5402, em->update_every);
  645. if (em->mode < MODE_ENTRY) {
  646. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR, "Fails to close files",
  647. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_GROUP,
  648. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_FD_CLOSE_ERR_CONTEXT,
  649. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5403, em->update_every);
  650. }
  651. }
  652. /*
  653. * Send specific file descriptor data
  654. *
  655. * Send data for specific cgroup/apps.
  656. *
  657. * @param type chart type
  658. * @param values structure with values that will be sent to netdata
  659. */
  660. static void ebpf_send_specific_fd_data(char *type, netdata_fd_stat_t *values, ebpf_module_t *em)
  661. {
  662. write_begin_chart(type, NETDATA_SYSCALL_APPS_FILE_OPEN);
  663. write_chart_dimension(fd_publish_aggregated[NETDATA_FD_SYSCALL_OPEN].name, (long long)values->open_call);
  664. write_end_chart();
  665. if (em->mode < MODE_ENTRY) {
  666. write_begin_chart(type, NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR);
  667. write_chart_dimension(fd_publish_aggregated[NETDATA_FD_SYSCALL_OPEN].name, (long long)values->open_err);
  668. write_end_chart();
  669. }
  670. write_begin_chart(type, NETDATA_SYSCALL_APPS_FILE_CLOSED);
  671. write_chart_dimension(fd_publish_aggregated[NETDATA_FD_SYSCALL_CLOSE].name, (long long)values->close_call);
  672. write_end_chart();
  673. if (em->mode < MODE_ENTRY) {
  674. write_begin_chart(type, NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR);
  675. write_chart_dimension(fd_publish_aggregated[NETDATA_FD_SYSCALL_CLOSE].name, (long long)values->close_err);
  676. write_end_chart();
  677. }
  678. }
  679. /**
  680. * Create systemd file descriptor charts
  681. *
  682. * Create charts when systemd is enabled
  683. *
  684. * @param em the main collector structure
  685. **/
  686. static void ebpf_create_systemd_fd_charts(ebpf_module_t *em)
  687. {
  688. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_FILE_OPEN, "Number of open files",
  689. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
  690. NETDATA_EBPF_CHART_TYPE_STACKED, 20061,
  691. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_FD_OPEN_CONTEXT,
  692. NETDATA_EBPF_MODULE_NAME_FD, em->update_every);
  693. if (em->mode < MODE_ENTRY) {
  694. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR, "Fails to open files",
  695. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
  696. NETDATA_EBPF_CHART_TYPE_STACKED, 20062,
  697. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_FD_OPEN_ERR_CONTEXT,
  698. NETDATA_EBPF_MODULE_NAME_FD, em->update_every);
  699. }
  700. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_FILE_CLOSED, "Files closed",
  701. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
  702. NETDATA_EBPF_CHART_TYPE_STACKED, 20063,
  703. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_FD_CLOSE_CONTEXT,
  704. NETDATA_EBPF_MODULE_NAME_FD, em->update_every);
  705. if (em->mode < MODE_ENTRY) {
  706. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR, "Fails to close files",
  707. EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_FILE_CGROUP_GROUP,
  708. NETDATA_EBPF_CHART_TYPE_STACKED, 20064,
  709. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_FD_CLOSE_ERR_CONTEXT,
  710. NETDATA_EBPF_MODULE_NAME_FD, em->update_every);
  711. }
  712. }
  713. /**
  714. * Send Systemd charts
  715. *
  716. * Send collected data to Netdata.
  717. *
  718. * @param em the main collector structure
  719. */
  720. static void ebpf_send_systemd_fd_charts(ebpf_module_t *em)
  721. {
  722. ebpf_cgroup_target_t *ect;
  723. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_FILE_OPEN);
  724. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  725. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  726. write_chart_dimension(ect->name, ect->publish_systemd_fd.open_call);
  727. }
  728. }
  729. write_end_chart();
  730. if (em->mode < MODE_ENTRY) {
  731. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR);
  732. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  733. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  734. write_chart_dimension(ect->name, ect->publish_systemd_fd.open_err);
  735. }
  736. }
  737. write_end_chart();
  738. }
  739. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_FILE_CLOSED);
  740. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  741. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  742. write_chart_dimension(ect->name, ect->publish_systemd_fd.close_call);
  743. }
  744. }
  745. write_end_chart();
  746. if (em->mode < MODE_ENTRY) {
  747. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR);
  748. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  749. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  750. write_chart_dimension(ect->name, ect->publish_systemd_fd.close_err);
  751. }
  752. }
  753. write_end_chart();
  754. }
  755. }
  756. /**
  757. * Send data to Netdata calling auxiliary functions.
  758. *
  759. * @param em the main collector structure
  760. */
  761. static void ebpf_fd_send_cgroup_data(ebpf_module_t *em)
  762. {
  763. if (!ebpf_cgroup_pids)
  764. return;
  765. pthread_mutex_lock(&mutex_cgroup_shm);
  766. ebpf_cgroup_target_t *ect;
  767. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  768. ebpf_fd_sum_cgroup_pids(&ect->publish_systemd_fd, ect->pids);
  769. }
  770. int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
  771. if (has_systemd) {
  772. if (send_cgroup_chart) {
  773. ebpf_create_systemd_fd_charts(em);
  774. }
  775. ebpf_send_systemd_fd_charts(em);
  776. }
  777. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  778. if (ect->systemd)
  779. continue;
  780. if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_FD_CHART) && ect->updated) {
  781. ebpf_create_specific_fd_charts(ect->name, em);
  782. ect->flags |= NETDATA_EBPF_CGROUP_HAS_FD_CHART;
  783. }
  784. if (ect->flags & NETDATA_EBPF_CGROUP_HAS_FD_CHART ) {
  785. if (ect->updated) {
  786. ebpf_send_specific_fd_data(ect->name, &ect->publish_systemd_fd, em);
  787. } else {
  788. ebpf_obsolete_specific_fd_charts(ect->name, em);
  789. ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_FD_CHART;
  790. }
  791. }
  792. }
  793. pthread_mutex_unlock(&mutex_cgroup_shm);
  794. }
  795. /**
  796. * Main loop for this collector.
  797. */
  798. static void fd_collector(ebpf_module_t *em)
  799. {
  800. int cgroups = em->cgroup_charts;
  801. heartbeat_t hb;
  802. heartbeat_init(&hb);
  803. int update_every = em->update_every;
  804. int counter = update_every - 1;
  805. while (!ebpf_exit_plugin) {
  806. (void)heartbeat_next(&hb, USEC_PER_SEC);
  807. if (ebpf_exit_plugin || ++counter != update_every)
  808. continue;
  809. counter = 0;
  810. netdata_apps_integration_flags_t apps = em->apps_charts;
  811. ebpf_fd_read_global_table();
  812. pthread_mutex_lock(&collect_data_mutex);
  813. if (apps)
  814. read_apps_table();
  815. #ifdef NETDATA_DEV_MODE
  816. if (ebpf_aral_fd_pid)
  817. ebpf_send_data_aral_chart(ebpf_aral_fd_pid, em);
  818. #endif
  819. if (cgroups)
  820. ebpf_update_fd_cgroup();
  821. pthread_mutex_lock(&lock);
  822. ebpf_fd_send_data(em);
  823. if (apps & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
  824. ebpf_fd_send_apps_data(em, apps_groups_root_target);
  825. if (cgroups)
  826. ebpf_fd_send_cgroup_data(em);
  827. pthread_mutex_unlock(&lock);
  828. pthread_mutex_unlock(&collect_data_mutex);
  829. }
  830. }
  831. /*****************************************************************
  832. *
  833. * CREATE CHARTS
  834. *
  835. *****************************************************************/
  836. /**
  837. * Create apps charts
  838. *
  839. * Call ebpf_create_chart to create the charts on apps submenu.
  840. *
  841. * @param em a pointer to the structure with the default values.
  842. */
  843. void ebpf_fd_create_apps_charts(struct ebpf_module *em, void *ptr)
  844. {
  845. struct ebpf_target *root = ptr;
  846. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_OPEN,
  847. "Number of open files",
  848. EBPF_COMMON_DIMENSION_CALL,
  849. NETDATA_APPS_FILE_GROUP,
  850. NETDATA_EBPF_CHART_TYPE_STACKED,
  851. 20061,
  852. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  853. root, em->update_every, NETDATA_EBPF_MODULE_NAME_FD);
  854. if (em->mode < MODE_ENTRY) {
  855. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR,
  856. "Fails to open files",
  857. EBPF_COMMON_DIMENSION_CALL,
  858. NETDATA_APPS_FILE_GROUP,
  859. NETDATA_EBPF_CHART_TYPE_STACKED,
  860. 20062,
  861. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  862. root, em->update_every, NETDATA_EBPF_MODULE_NAME_FD);
  863. }
  864. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_CLOSED,
  865. "Files closed",
  866. EBPF_COMMON_DIMENSION_CALL,
  867. NETDATA_APPS_FILE_GROUP,
  868. NETDATA_EBPF_CHART_TYPE_STACKED,
  869. 20063,
  870. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  871. root, em->update_every, NETDATA_EBPF_MODULE_NAME_FD);
  872. if (em->mode < MODE_ENTRY) {
  873. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR,
  874. "Fails to close files",
  875. EBPF_COMMON_DIMENSION_CALL,
  876. NETDATA_APPS_FILE_GROUP,
  877. NETDATA_EBPF_CHART_TYPE_STACKED,
  878. 20064,
  879. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  880. root, em->update_every, NETDATA_EBPF_MODULE_NAME_FD);
  881. }
  882. em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
  883. }
  884. /**
  885. * Create global charts
  886. *
  887. * Call ebpf_create_chart to create the charts for the collector.
  888. *
  889. * @param em a pointer to the structure with the default values.
  890. */
  891. static void ebpf_create_fd_global_charts(ebpf_module_t *em)
  892. {
  893. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  894. NETDATA_FILE_OPEN_CLOSE_COUNT,
  895. "Open and close calls",
  896. EBPF_COMMON_DIMENSION_CALL,
  897. NETDATA_FILE_GROUP,
  898. NULL,
  899. NETDATA_EBPF_CHART_TYPE_LINE,
  900. NETDATA_CHART_PRIO_EBPF_FD_CHARTS,
  901. ebpf_create_global_dimension,
  902. fd_publish_aggregated,
  903. NETDATA_FD_SYSCALL_END,
  904. em->update_every, NETDATA_EBPF_MODULE_NAME_FD);
  905. if (em->mode < MODE_ENTRY) {
  906. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  907. NETDATA_FILE_OPEN_ERR_COUNT,
  908. "Open fails",
  909. EBPF_COMMON_DIMENSION_CALL,
  910. NETDATA_FILE_GROUP,
  911. NULL,
  912. NETDATA_EBPF_CHART_TYPE_LINE,
  913. NETDATA_CHART_PRIO_EBPF_FD_CHARTS + 1,
  914. ebpf_create_global_dimension,
  915. fd_publish_aggregated,
  916. NETDATA_FD_SYSCALL_END,
  917. em->update_every, NETDATA_EBPF_MODULE_NAME_FD);
  918. }
  919. }
  920. /*****************************************************************
  921. *
  922. * MAIN THREAD
  923. *
  924. *****************************************************************/
  925. /**
  926. * Allocate vectors used with this thread.
  927. *
  928. * We are not testing the return, because callocz does this and shutdown the software
  929. * case it was not possible to allocate.
  930. *
  931. * @param apps is apps enabled?
  932. */
  933. static void ebpf_fd_allocate_global_vectors(int apps)
  934. {
  935. if (apps) {
  936. ebpf_fd_aral_init();
  937. fd_pid = callocz((size_t)pid_max, sizeof(netdata_fd_stat_t *));
  938. fd_vector = callocz((size_t)ebpf_nprocs, sizeof(netdata_fd_stat_t));
  939. }
  940. fd_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t));
  941. }
  942. /*
  943. * Load BPF
  944. *
  945. * Load BPF files.
  946. *
  947. * @param em the structure with configuration
  948. */
  949. static int ebpf_fd_load_bpf(ebpf_module_t *em)
  950. {
  951. int ret = 0;
  952. ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_FD_SYSCALL_OPEN].mode);
  953. if (em->load & EBPF_LOAD_LEGACY) {
  954. em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
  955. if (!em->probe_links) {
  956. ret = -1;
  957. }
  958. }
  959. #ifdef LIBBPF_MAJOR_VERSION
  960. else {
  961. fd_bpf_obj = fd_bpf__open();
  962. if (!fd_bpf_obj)
  963. ret = -1;
  964. else
  965. ret = ebpf_fd_load_and_attach(fd_bpf_obj, em);
  966. }
  967. #endif
  968. if (ret)
  969. error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->thread_name);
  970. return ret;
  971. }
  972. /**
  973. * Directory Cache thread
  974. *
  975. * Thread used to make dcstat thread
  976. *
  977. * @param ptr a pointer to `struct ebpf_module`
  978. *
  979. * @return It always returns NULL
  980. */
  981. void *ebpf_fd_thread(void *ptr)
  982. {
  983. netdata_thread_cleanup_push(ebpf_fd_exit, ptr);
  984. ebpf_module_t *em = (ebpf_module_t *)ptr;
  985. em->maps = fd_maps;
  986. #ifdef LIBBPF_MAJOR_VERSION
  987. ebpf_adjust_thread_load(em, default_btf);
  988. #endif
  989. if (ebpf_fd_load_bpf(em)) {
  990. goto endfd;
  991. }
  992. ebpf_fd_allocate_global_vectors(em->apps_charts);
  993. int algorithms[NETDATA_FD_SYSCALL_END] = {
  994. NETDATA_EBPF_INCREMENTAL_IDX, NETDATA_EBPF_INCREMENTAL_IDX
  995. };
  996. ebpf_global_labels(fd_aggregated_data, fd_publish_aggregated, fd_dimension_names, fd_id_names,
  997. algorithms, NETDATA_FD_SYSCALL_END);
  998. pthread_mutex_lock(&lock);
  999. ebpf_create_fd_global_charts(em);
  1000. ebpf_update_stats(&plugin_statistics, em);
  1001. ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps);
  1002. #ifdef NETDATA_DEV_MODE
  1003. if (ebpf_aral_fd_pid)
  1004. ebpf_statistic_create_aral_chart(NETDATA_EBPF_FD_ARAL_NAME, em);
  1005. #endif
  1006. pthread_mutex_unlock(&lock);
  1007. fd_collector(em);
  1008. endfd:
  1009. ebpf_update_disabled_plugin_stats(em);
  1010. netdata_thread_cleanup_pop(1);
  1011. return NULL;
  1012. }