ebpf_shm.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "ebpf.h"
  3. #include "ebpf_shm.h"
  4. static char *shm_dimension_name[NETDATA_SHM_END] = { "get", "at", "dt", "ctl" };
  5. static netdata_syscall_stat_t shm_aggregated_data[NETDATA_SHM_END];
  6. static netdata_publish_syscall_t shm_publish_aggregated[NETDATA_SHM_END];
  7. netdata_publish_shm_t *shm_vector = NULL;
  8. static netdata_idx_t shm_hash_values[NETDATA_SHM_END];
  9. static netdata_idx_t *shm_values = NULL;
  10. netdata_publish_shm_t **shm_pid = NULL;
  11. struct config shm_config = { .first_section = NULL,
  12. .last_section = NULL,
  13. .mutex = NETDATA_MUTEX_INITIALIZER,
  14. .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
  15. .rwlock = AVL_LOCK_INITIALIZER } };
  16. static ebpf_local_maps_t shm_maps[] = {{.name = "tbl_pid_shm", .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
  17. .user_input = 0,
  18. .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
  19. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
  20. {.name = "shm_ctrl", .internal_input = NETDATA_CONTROLLER_END,
  21. .user_input = 0,
  22. .type = NETDATA_EBPF_MAP_CONTROLLER,
  23. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
  24. {.name = "tbl_shm", .internal_input = NETDATA_SHM_END,
  25. .user_input = 0,
  26. .type = NETDATA_EBPF_MAP_STATIC,
  27. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
  28. {.name = NULL, .internal_input = 0, .user_input = 0}};
  29. struct netdata_static_thread shm_threads = {
  30. .name = "SHM KERNEL",
  31. .config_section = NULL,
  32. .config_name = NULL,
  33. .env_name = NULL,
  34. .enabled = 1,
  35. .thread = NULL,
  36. .init_routine = NULL,
  37. .start_routine = NULL
  38. };
  39. netdata_ebpf_targets_t shm_targets[] = { {.name = "shmget", .mode = EBPF_LOAD_TRAMPOLINE},
  40. {.name = "shmat", .mode = EBPF_LOAD_TRAMPOLINE},
  41. {.name = "shmdt", .mode = EBPF_LOAD_TRAMPOLINE},
  42. {.name = "shmctl", .mode = EBPF_LOAD_TRAMPOLINE},
  43. {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
  44. #ifdef LIBBPF_MAJOR_VERSION
  45. #include "includes/shm.skel.h"
  46. static struct shm_bpf *bpf_obj = NULL;
  47. /*****************************************************************
  48. *
  49. * BTF FUNCTIONS
  50. *
  51. *****************************************************************/
  52. /*
  53. * Disable tracepoint
  54. *
  55. * Disable all tracepoints to use exclusively another method.
  56. *
  57. * @param obj is the main structure for bpf objects.
  58. */
  59. static void ebpf_shm_disable_tracepoint(struct shm_bpf *obj)
  60. {
  61. bpf_program__set_autoload(obj->progs.netdata_syscall_shmget, false);
  62. bpf_program__set_autoload(obj->progs.netdata_syscall_shmat, false);
  63. bpf_program__set_autoload(obj->progs.netdata_syscall_shmdt, false);
  64. bpf_program__set_autoload(obj->progs.netdata_syscall_shmctl, false);
  65. }
  66. /*
  67. * Disable probe
  68. *
  69. * Disable all probes to use exclusively another method.
  70. *
  71. * @param obj is the main structure for bpf objects.
  72. */
  73. static void ebpf_disable_probe(struct shm_bpf *obj)
  74. {
  75. bpf_program__set_autoload(obj->progs.netdata_shmget_probe, false);
  76. bpf_program__set_autoload(obj->progs.netdata_shmat_probe, false);
  77. bpf_program__set_autoload(obj->progs.netdata_shmdt_probe, false);
  78. bpf_program__set_autoload(obj->progs.netdata_shmctl_probe, false);
  79. bpf_program__set_autoload(obj->progs.netdata_shm_release_task_probe, false);
  80. }
  81. /*
  82. * Disable trampoline
  83. *
  84. * Disable all trampoline to use exclusively another method.
  85. *
  86. * @param obj is the main structure for bpf objects.
  87. */
  88. static void ebpf_disable_trampoline(struct shm_bpf *obj)
  89. {
  90. bpf_program__set_autoload(obj->progs.netdata_shmget_fentry, false);
  91. bpf_program__set_autoload(obj->progs.netdata_shmat_fentry, false);
  92. bpf_program__set_autoload(obj->progs.netdata_shmdt_fentry, false);
  93. bpf_program__set_autoload(obj->progs.netdata_shmctl_fentry, false);
  94. bpf_program__set_autoload(obj->progs.netdata_shm_release_task_fentry, false);
  95. }
  96. /**
  97. * Set trampoline target
  98. *
  99. * Set the targets we will monitor.
  100. *
  101. * @param obj is the main structure for bpf objects.
  102. */
  103. static void ebpf_set_trampoline_target(struct shm_bpf *obj)
  104. {
  105. char syscall[NETDATA_EBPF_MAX_SYSCALL_LENGTH + 1];
  106. ebpf_select_host_prefix(syscall, NETDATA_EBPF_MAX_SYSCALL_LENGTH,
  107. shm_targets[NETDATA_KEY_SHMGET_CALL].name, running_on_kernel);
  108. bpf_program__set_attach_target(obj->progs.netdata_shmget_fentry, 0,
  109. syscall);
  110. ebpf_select_host_prefix(syscall, NETDATA_EBPF_MAX_SYSCALL_LENGTH,
  111. shm_targets[NETDATA_KEY_SHMAT_CALL].name, running_on_kernel);
  112. bpf_program__set_attach_target(obj->progs.netdata_shmat_fentry, 0,
  113. syscall);
  114. ebpf_select_host_prefix(syscall, NETDATA_EBPF_MAX_SYSCALL_LENGTH,
  115. shm_targets[NETDATA_KEY_SHMDT_CALL].name, running_on_kernel);
  116. bpf_program__set_attach_target(obj->progs.netdata_shmdt_fentry, 0,
  117. syscall);
  118. ebpf_select_host_prefix(syscall, NETDATA_EBPF_MAX_SYSCALL_LENGTH,
  119. shm_targets[NETDATA_KEY_SHMCTL_CALL].name, running_on_kernel);
  120. bpf_program__set_attach_target(obj->progs.netdata_shmctl_fentry, 0,
  121. syscall);
  122. bpf_program__set_attach_target(obj->progs.netdata_shm_release_task_fentry, 0,
  123. EBPF_COMMON_FNCT_CLEAN_UP);
  124. }
  125. /**
  126. * SHM Attach Probe
  127. *
  128. * Attach probes to target
  129. *
  130. * @param obj is the main structure for bpf objects.
  131. *
  132. * @return It returns 0 on success and -1 otherwise.
  133. */
  134. static int ebpf_shm_attach_probe(struct shm_bpf *obj)
  135. {
  136. char syscall[NETDATA_EBPF_MAX_SYSCALL_LENGTH + 1];
  137. ebpf_select_host_prefix(syscall, NETDATA_EBPF_MAX_SYSCALL_LENGTH,
  138. shm_targets[NETDATA_KEY_SHMGET_CALL].name, running_on_kernel);
  139. obj->links.netdata_shmget_probe = bpf_program__attach_kprobe(obj->progs.netdata_shmget_probe,
  140. false, syscall);
  141. int ret = (int)libbpf_get_error(obj->links.netdata_shmget_probe);
  142. if (ret)
  143. return -1;
  144. ebpf_select_host_prefix(syscall, NETDATA_EBPF_MAX_SYSCALL_LENGTH,
  145. shm_targets[NETDATA_KEY_SHMAT_CALL].name, running_on_kernel);
  146. obj->links.netdata_shmat_probe = bpf_program__attach_kprobe(obj->progs.netdata_shmat_probe,
  147. false, syscall);
  148. ret = (int)libbpf_get_error(obj->links.netdata_shmat_probe);
  149. if (ret)
  150. return -1;
  151. ebpf_select_host_prefix(syscall, NETDATA_EBPF_MAX_SYSCALL_LENGTH,
  152. shm_targets[NETDATA_KEY_SHMDT_CALL].name, running_on_kernel);
  153. obj->links.netdata_shmdt_probe = bpf_program__attach_kprobe(obj->progs.netdata_shmdt_probe,
  154. false, syscall);
  155. ret = (int)libbpf_get_error(obj->links.netdata_shmdt_probe);
  156. if (ret)
  157. return -1;
  158. ebpf_select_host_prefix(syscall, NETDATA_EBPF_MAX_SYSCALL_LENGTH,
  159. shm_targets[NETDATA_KEY_SHMCTL_CALL].name, running_on_kernel);
  160. obj->links.netdata_shmctl_probe = bpf_program__attach_kprobe(obj->progs.netdata_shmctl_probe,
  161. false, syscall);
  162. ret = (int)libbpf_get_error(obj->links.netdata_shmctl_probe);
  163. if (ret)
  164. return -1;
  165. obj->links.netdata_shm_release_task_probe = bpf_program__attach_kprobe(obj->progs.netdata_shm_release_task_probe,
  166. false, EBPF_COMMON_FNCT_CLEAN_UP);
  167. ret = (int)libbpf_get_error(obj->links.netdata_shm_release_task_probe);
  168. if (ret)
  169. return -1;
  170. return 0;
  171. }
  172. /**
  173. * Set hash tables
  174. *
  175. * Set the values for maps according the value given by kernel.
  176. */
  177. static void ebpf_shm_set_hash_tables(struct shm_bpf *obj)
  178. {
  179. shm_maps[NETDATA_PID_SHM_TABLE].map_fd = bpf_map__fd(obj->maps.tbl_pid_shm);
  180. shm_maps[NETDATA_SHM_CONTROLLER].map_fd = bpf_map__fd(obj->maps.shm_ctrl);
  181. shm_maps[NETDATA_SHM_GLOBAL_TABLE].map_fd = bpf_map__fd(obj->maps.tbl_shm);
  182. }
  183. /**
  184. * Disable Release Task
  185. *
  186. * Disable release task when apps is not enabled.
  187. *
  188. * @param obj is the main structure for bpf objects.
  189. */
  190. static void ebpf_shm_disable_release_task(struct shm_bpf *obj)
  191. {
  192. bpf_program__set_autoload(obj->progs.netdata_shm_release_task_probe, false);
  193. bpf_program__set_autoload(obj->progs.netdata_shm_release_task_fentry, false);
  194. }
  195. /**
  196. * Adjust Map Size
  197. *
  198. * Resize maps according input from users.
  199. *
  200. * @param obj is the main structure for bpf objects.
  201. * @param em structure with configuration
  202. */
  203. static void ebpf_shm_adjust_map_size(struct shm_bpf *obj, ebpf_module_t *em)
  204. {
  205. ebpf_update_map_size(obj->maps.tbl_pid_shm, &shm_maps[NETDATA_PID_SHM_TABLE],
  206. em, bpf_map__name(obj->maps.tbl_pid_shm));
  207. }
  208. /**
  209. * Load and attach
  210. *
  211. * Load and attach the eBPF code in kernel.
  212. *
  213. * @param obj is the main structure for bpf objects.
  214. * @param em structure with configuration
  215. *
  216. * @return it returns 0 on success and -1 otherwise
  217. */
  218. static inline int ebpf_shm_load_and_attach(struct shm_bpf *obj, ebpf_module_t *em)
  219. {
  220. netdata_ebpf_targets_t *shmt = em->targets;
  221. netdata_ebpf_program_loaded_t test = shmt[NETDATA_KEY_SHMGET_CALL].mode;
  222. // We are testing only one, because all will have the same behavior
  223. if (test == EBPF_LOAD_TRAMPOLINE ) {
  224. ebpf_shm_disable_tracepoint(obj);
  225. ebpf_disable_probe(obj);
  226. ebpf_set_trampoline_target(obj);
  227. } else if (test == EBPF_LOAD_PROBE || test == EBPF_LOAD_RETPROBE ) {
  228. ebpf_shm_disable_tracepoint(obj);
  229. ebpf_disable_trampoline(obj);
  230. } else {
  231. ebpf_disable_probe(obj);
  232. ebpf_disable_trampoline(obj);
  233. }
  234. ebpf_shm_adjust_map_size(obj, em);
  235. if (!em->apps_charts && !em->cgroup_charts)
  236. ebpf_shm_disable_release_task(obj);
  237. int ret = shm_bpf__load(obj);
  238. if (!ret) {
  239. if (test != EBPF_LOAD_PROBE && test != EBPF_LOAD_RETPROBE)
  240. shm_bpf__attach(obj);
  241. else
  242. ret = ebpf_shm_attach_probe(obj);
  243. if (!ret)
  244. ebpf_shm_set_hash_tables(obj);
  245. }
  246. return ret;
  247. }
  248. #endif
  249. /*****************************************************************
  250. * FUNCTIONS TO CLOSE THE THREAD
  251. *****************************************************************/
  252. /**
  253. * SHM Free
  254. *
  255. * Cleanup variables after child threads to stop
  256. *
  257. * @param ptr thread data.
  258. */
  259. static void ebpf_shm_free(ebpf_module_t *em)
  260. {
  261. pthread_mutex_lock(&ebpf_exit_cleanup);
  262. if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
  263. em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
  264. pthread_mutex_unlock(&ebpf_exit_cleanup);
  265. return;
  266. }
  267. pthread_mutex_unlock(&ebpf_exit_cleanup);
  268. ebpf_cleanup_publish_syscall(shm_publish_aggregated);
  269. freez(shm_vector);
  270. freez(shm_values);
  271. #ifdef LIBBPF_MAJOR_VERSION
  272. if (bpf_obj)
  273. shm_bpf__destroy(bpf_obj);
  274. #endif
  275. em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
  276. }
  277. /**
  278. * SHM Exit
  279. *
  280. * Cancel child thread.
  281. *
  282. * @param ptr thread data.
  283. */
  284. static void ebpf_shm_exit(void *ptr)
  285. {
  286. ebpf_module_t *em = (ebpf_module_t *)ptr;
  287. if (shm_threads.thread)
  288. netdata_thread_cancel(*shm_threads.thread);
  289. ebpf_shm_free(em);
  290. }
  291. /**
  292. * SHM Cleanup
  293. *
  294. * Clean up allocated memory.
  295. *
  296. * @param ptr thread data.
  297. */
  298. static void ebpf_shm_cleanup(void *ptr)
  299. {
  300. ebpf_module_t *em = (ebpf_module_t *)ptr;
  301. ebpf_shm_free(em);
  302. }
  303. /*****************************************************************
  304. * COLLECTOR THREAD
  305. *****************************************************************/
  306. /**
  307. * Apps Accumulator
  308. *
  309. * Sum all values read from kernel and store in the first address.
  310. *
  311. * @param out the vector with read values.
  312. */
  313. static void shm_apps_accumulator(netdata_publish_shm_t *out)
  314. {
  315. int i, end = (running_on_kernel >= NETDATA_KERNEL_V4_15) ? ebpf_nprocs : 1;
  316. netdata_publish_shm_t *total = &out[0];
  317. for (i = 1; i < end; i++) {
  318. netdata_publish_shm_t *w = &out[i];
  319. total->get += w->get;
  320. total->at += w->at;
  321. total->dt += w->dt;
  322. total->ctl += w->ctl;
  323. }
  324. }
  325. /**
  326. * Fill PID
  327. *
  328. * Fill PID structures
  329. *
  330. * @param current_pid pid that we are collecting data
  331. * @param out values read from hash tables;
  332. */
  333. static void shm_fill_pid(uint32_t current_pid, netdata_publish_shm_t *publish)
  334. {
  335. netdata_publish_shm_t *curr = shm_pid[current_pid];
  336. if (!curr) {
  337. curr = callocz(1, sizeof(netdata_publish_shm_t));
  338. shm_pid[current_pid] = curr;
  339. }
  340. memcpy(curr, publish, sizeof(netdata_publish_shm_t));
  341. }
  342. /**
  343. * Update cgroup
  344. *
  345. * Update cgroup data based in
  346. */
  347. static void ebpf_update_shm_cgroup()
  348. {
  349. netdata_publish_shm_t *cv = shm_vector;
  350. int fd = shm_maps[NETDATA_PID_SHM_TABLE].map_fd;
  351. size_t length = sizeof(netdata_publish_shm_t) * ebpf_nprocs;
  352. ebpf_cgroup_target_t *ect;
  353. memset(cv, 0, length);
  354. pthread_mutex_lock(&mutex_cgroup_shm);
  355. for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
  356. struct pid_on_target2 *pids;
  357. for (pids = ect->pids; pids; pids = pids->next) {
  358. int pid = pids->pid;
  359. netdata_publish_shm_t *out = &pids->shm;
  360. if (likely(shm_pid) && shm_pid[pid]) {
  361. netdata_publish_shm_t *in = shm_pid[pid];
  362. memcpy(out, in, sizeof(netdata_publish_shm_t));
  363. } else {
  364. if (!bpf_map_lookup_elem(fd, &pid, cv)) {
  365. shm_apps_accumulator(cv);
  366. memcpy(out, cv, sizeof(netdata_publish_shm_t));
  367. // now that we've consumed the value, zero it out in the map.
  368. memset(cv, 0, length);
  369. bpf_map_update_elem(fd, &pid, cv, BPF_EXIST);
  370. }
  371. }
  372. }
  373. }
  374. pthread_mutex_unlock(&mutex_cgroup_shm);
  375. }
  376. /**
  377. * Read APPS table
  378. *
  379. * Read the apps table and store data inside the structure.
  380. */
  381. static void read_apps_table()
  382. {
  383. netdata_publish_shm_t *cv = shm_vector;
  384. uint32_t key;
  385. struct pid_stat *pids = root_of_pids;
  386. int fd = shm_maps[NETDATA_PID_SHM_TABLE].map_fd;
  387. size_t length = sizeof(netdata_publish_shm_t)*ebpf_nprocs;
  388. while (pids) {
  389. key = pids->pid;
  390. if (bpf_map_lookup_elem(fd, &key, cv)) {
  391. pids = pids->next;
  392. continue;
  393. }
  394. shm_apps_accumulator(cv);
  395. shm_fill_pid(key, cv);
  396. // now that we've consumed the value, zero it out in the map.
  397. memset(cv, 0, length);
  398. bpf_map_update_elem(fd, &key, cv, BPF_EXIST);
  399. pids = pids->next;
  400. }
  401. }
  402. /**
  403. * Send global charts to netdata agent.
  404. */
  405. static void shm_send_global()
  406. {
  407. write_begin_chart(NETDATA_EBPF_SYSTEM_GROUP, NETDATA_SHM_GLOBAL_CHART);
  408. write_chart_dimension(
  409. shm_publish_aggregated[NETDATA_KEY_SHMGET_CALL].dimension,
  410. (long long) shm_hash_values[NETDATA_KEY_SHMGET_CALL]
  411. );
  412. write_chart_dimension(
  413. shm_publish_aggregated[NETDATA_KEY_SHMAT_CALL].dimension,
  414. (long long) shm_hash_values[NETDATA_KEY_SHMAT_CALL]
  415. );
  416. write_chart_dimension(
  417. shm_publish_aggregated[NETDATA_KEY_SHMDT_CALL].dimension,
  418. (long long) shm_hash_values[NETDATA_KEY_SHMDT_CALL]
  419. );
  420. write_chart_dimension(
  421. shm_publish_aggregated[NETDATA_KEY_SHMCTL_CALL].dimension,
  422. (long long) shm_hash_values[NETDATA_KEY_SHMCTL_CALL]
  423. );
  424. write_end_chart();
  425. }
  426. /**
  427. * Read global counter
  428. *
  429. * Read the table with number of calls for all functions
  430. */
  431. static void read_global_table()
  432. {
  433. netdata_idx_t *stored = shm_values;
  434. netdata_idx_t *val = shm_hash_values;
  435. int fd = shm_maps[NETDATA_SHM_GLOBAL_TABLE].map_fd;
  436. uint32_t i, end = NETDATA_SHM_END;
  437. for (i = NETDATA_KEY_SHMGET_CALL; i < end; i++) {
  438. if (!bpf_map_lookup_elem(fd, &i, stored)) {
  439. int j;
  440. int last = ebpf_nprocs;
  441. netdata_idx_t total = 0;
  442. for (j = 0; j < last; j++)
  443. total += stored[j];
  444. val[i] = total;
  445. }
  446. }
  447. }
  448. /**
  449. * Shared memory reader thread.
  450. *
  451. * @param ptr It is a NULL value for this thread.
  452. * @return It always returns NULL.
  453. */
  454. void *ebpf_shm_read_hash(void *ptr)
  455. {
  456. netdata_thread_cleanup_push(ebpf_shm_cleanup, ptr);
  457. heartbeat_t hb;
  458. heartbeat_init(&hb);
  459. ebpf_module_t *em = (ebpf_module_t *)ptr;
  460. usec_t step = NETDATA_SHM_SLEEP_MS * em->update_every;
  461. while (!ebpf_exit_plugin) {
  462. (void)heartbeat_next(&hb, step);
  463. read_global_table();
  464. }
  465. netdata_thread_cleanup_pop(1);
  466. return NULL;
  467. }
  468. /**
  469. * Sum values for all targets.
  470. */
  471. static void ebpf_shm_sum_pids(netdata_publish_shm_t *shm, struct pid_on_target *root)
  472. {
  473. while (root) {
  474. int32_t pid = root->pid;
  475. netdata_publish_shm_t *w = shm_pid[pid];
  476. if (w) {
  477. shm->get += w->get;
  478. shm->at += w->at;
  479. shm->dt += w->dt;
  480. shm->ctl += w->ctl;
  481. // reset for next collection.
  482. w->get = 0;
  483. w->at = 0;
  484. w->dt = 0;
  485. w->ctl = 0;
  486. }
  487. root = root->next;
  488. }
  489. }
  490. /**
  491. * Send data to Netdata calling auxiliary functions.
  492. *
  493. * @param root the target list.
  494. */
  495. void ebpf_shm_send_apps_data(struct target *root)
  496. {
  497. struct target *w;
  498. for (w = root; w; w = w->next) {
  499. if (unlikely(w->exposed && w->processes)) {
  500. ebpf_shm_sum_pids(&w->shm, w->root_pid);
  501. }
  502. }
  503. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SHMGET_CHART);
  504. for (w = root; w; w = w->next) {
  505. if (unlikely(w->exposed && w->processes)) {
  506. write_chart_dimension(w->name, (long long) w->shm.get);
  507. }
  508. }
  509. write_end_chart();
  510. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SHMAT_CHART);
  511. for (w = root; w; w = w->next) {
  512. if (unlikely(w->exposed && w->processes)) {
  513. write_chart_dimension(w->name, (long long) w->shm.at);
  514. }
  515. }
  516. write_end_chart();
  517. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SHMDT_CHART);
  518. for (w = root; w; w = w->next) {
  519. if (unlikely(w->exposed && w->processes)) {
  520. write_chart_dimension(w->name, (long long) w->shm.dt);
  521. }
  522. }
  523. write_end_chart();
  524. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SHMCTL_CHART);
  525. for (w = root; w; w = w->next) {
  526. if (unlikely(w->exposed && w->processes)) {
  527. write_chart_dimension(w->name, (long long) w->shm.ctl);
  528. }
  529. }
  530. write_end_chart();
  531. }
  532. /**
  533. * Sum values for all targets.
  534. */
  535. static void ebpf_shm_sum_cgroup_pids(netdata_publish_shm_t *shm, struct pid_on_target2 *root)
  536. {
  537. netdata_publish_shm_t shmv;
  538. memset(&shmv, 0, sizeof(shmv));
  539. while (root) {
  540. netdata_publish_shm_t *w = &root->shm;
  541. shmv.get += w->get;
  542. shmv.at += w->at;
  543. shmv.dt += w->dt;
  544. shmv.ctl += w->ctl;
  545. root = root->next;
  546. }
  547. memcpy(shm, &shmv, sizeof(shmv));
  548. }
  549. /**
  550. * Create specific shared memory charts
  551. *
  552. * Create charts for cgroup/application.
  553. *
  554. * @param type the chart type.
  555. * @param update_every value to overwrite the update frequency set by the server.
  556. */
  557. static void ebpf_create_specific_shm_charts(char *type, int update_every)
  558. {
  559. ebpf_create_chart(type, NETDATA_SHMGET_CHART,
  560. "Calls to syscall <code>shmget(2)</code>.",
  561. EBPF_COMMON_DIMENSION_CALL,
  562. NETDATA_APPS_IPC_SHM_GROUP,
  563. NETDATA_CGROUP_SHM_GET_CONTEXT,
  564. NETDATA_EBPF_CHART_TYPE_LINE,
  565. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5800,
  566. ebpf_create_global_dimension,
  567. &shm_publish_aggregated[NETDATA_KEY_SHMGET_CALL],
  568. 1,
  569. update_every,
  570. NETDATA_EBPF_MODULE_NAME_SHM);
  571. ebpf_create_chart(type, NETDATA_SHMAT_CHART,
  572. "Calls to syscall <code>shmat(2)</code>.",
  573. EBPF_COMMON_DIMENSION_CALL,
  574. NETDATA_APPS_IPC_SHM_GROUP,
  575. NETDATA_CGROUP_SHM_AT_CONTEXT,
  576. NETDATA_EBPF_CHART_TYPE_LINE,
  577. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5801,
  578. ebpf_create_global_dimension,
  579. &shm_publish_aggregated[NETDATA_KEY_SHMAT_CALL],
  580. 1,
  581. update_every,
  582. NETDATA_EBPF_MODULE_NAME_SHM);
  583. ebpf_create_chart(type, NETDATA_SHMDT_CHART,
  584. "Calls to syscall <code>shmdt(2)</code>.",
  585. EBPF_COMMON_DIMENSION_CALL,
  586. NETDATA_APPS_IPC_SHM_GROUP,
  587. NETDATA_CGROUP_SHM_DT_CONTEXT,
  588. NETDATA_EBPF_CHART_TYPE_LINE,
  589. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5802,
  590. ebpf_create_global_dimension,
  591. &shm_publish_aggregated[NETDATA_KEY_SHMDT_CALL],
  592. 1,
  593. update_every,
  594. NETDATA_EBPF_MODULE_NAME_SHM);
  595. ebpf_create_chart(type, NETDATA_SHMCTL_CHART,
  596. "Calls to syscall <code>shmctl(2)</code>.",
  597. EBPF_COMMON_DIMENSION_CALL,
  598. NETDATA_APPS_IPC_SHM_GROUP,
  599. NETDATA_CGROUP_SHM_CTL_CONTEXT,
  600. NETDATA_EBPF_CHART_TYPE_LINE,
  601. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5803,
  602. ebpf_create_global_dimension,
  603. &shm_publish_aggregated[NETDATA_KEY_SHMCTL_CALL],
  604. 1,
  605. update_every,
  606. NETDATA_EBPF_MODULE_NAME_SHM);
  607. }
  608. /**
  609. * Obsolete specific shared memory charts
  610. *
  611. * Obsolete charts for cgroup/application.
  612. *
  613. * @param type the chart type.
  614. * @param update_every value to overwrite the update frequency set by the server.
  615. */
  616. static void ebpf_obsolete_specific_shm_charts(char *type, int update_every)
  617. {
  618. ebpf_write_chart_obsolete(type, NETDATA_SHMGET_CHART,
  619. "Calls to syscall <code>shmget(2)</code>.",
  620. EBPF_COMMON_DIMENSION_CALL,
  621. NETDATA_APPS_IPC_SHM_GROUP,
  622. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_SHM_GET_CONTEXT,
  623. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5800, update_every);
  624. ebpf_write_chart_obsolete(type, NETDATA_SHMAT_CHART,
  625. "Calls to syscall <code>shmat(2)</code>.",
  626. EBPF_COMMON_DIMENSION_CALL,
  627. NETDATA_APPS_IPC_SHM_GROUP,
  628. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_SHM_AT_CONTEXT,
  629. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5801, update_every);
  630. ebpf_write_chart_obsolete(type, NETDATA_SHMDT_CHART,
  631. "Calls to syscall <code>shmdt(2)</code>.",
  632. EBPF_COMMON_DIMENSION_CALL,
  633. NETDATA_APPS_IPC_SHM_GROUP,
  634. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_SHM_DT_CONTEXT,
  635. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5802, update_every);
  636. ebpf_write_chart_obsolete(type, NETDATA_SHMCTL_CHART,
  637. "Calls to syscall <code>shmctl(2)</code>.",
  638. EBPF_COMMON_DIMENSION_CALL,
  639. NETDATA_APPS_IPC_SHM_GROUP,
  640. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_SHM_CTL_CONTEXT,
  641. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5803, update_every);
  642. }
  643. /**
  644. * Create Systemd Swap Charts
  645. *
  646. * Create charts when systemd is enabled
  647. *
  648. * @param update_every value to overwrite the update frequency set by the server.
  649. **/
  650. static void ebpf_create_systemd_shm_charts(int update_every)
  651. {
  652. ebpf_create_charts_on_systemd(NETDATA_SHMGET_CHART,
  653. "Calls to syscall <code>shmget(2)</code>.",
  654. EBPF_COMMON_DIMENSION_CALL,
  655. NETDATA_APPS_IPC_SHM_GROUP,
  656. NETDATA_EBPF_CHART_TYPE_STACKED,
  657. 20191,
  658. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  659. NETDATA_SYSTEMD_SHM_GET_CONTEXT, NETDATA_EBPF_MODULE_NAME_SHM, update_every);
  660. ebpf_create_charts_on_systemd(NETDATA_SHMAT_CHART,
  661. "Calls to syscall <code>shmat(2)</code>.",
  662. EBPF_COMMON_DIMENSION_CALL,
  663. NETDATA_APPS_IPC_SHM_GROUP,
  664. NETDATA_EBPF_CHART_TYPE_STACKED,
  665. 20192,
  666. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  667. NETDATA_SYSTEMD_SHM_AT_CONTEXT, NETDATA_EBPF_MODULE_NAME_SHM, update_every);
  668. ebpf_create_charts_on_systemd(NETDATA_SHMDT_CHART,
  669. "Calls to syscall <code>shmdt(2)</code>.",
  670. EBPF_COMMON_DIMENSION_CALL,
  671. NETDATA_APPS_IPC_SHM_GROUP,
  672. NETDATA_EBPF_CHART_TYPE_STACKED,
  673. 20193,
  674. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  675. NETDATA_SYSTEMD_SHM_DT_CONTEXT, NETDATA_EBPF_MODULE_NAME_SHM, update_every);
  676. ebpf_create_charts_on_systemd(NETDATA_SHMCTL_CHART,
  677. "Calls to syscall <code>shmctl(2)</code>.",
  678. EBPF_COMMON_DIMENSION_CALL,
  679. NETDATA_APPS_IPC_SHM_GROUP,
  680. NETDATA_EBPF_CHART_TYPE_STACKED,
  681. 20193,
  682. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  683. NETDATA_SYSTEMD_SHM_CTL_CONTEXT, NETDATA_EBPF_MODULE_NAME_SHM, update_every);
  684. }
  685. /**
  686. * Send Systemd charts
  687. *
  688. * Send collected data to Netdata.
  689. */
  690. static void ebpf_send_systemd_shm_charts()
  691. {
  692. ebpf_cgroup_target_t *ect;
  693. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SHMGET_CHART);
  694. for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
  695. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  696. write_chart_dimension(ect->name, (long long)ect->publish_shm.get);
  697. }
  698. }
  699. write_end_chart();
  700. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SHMAT_CHART);
  701. for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
  702. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  703. write_chart_dimension(ect->name, (long long)ect->publish_shm.at);
  704. }
  705. }
  706. write_end_chart();
  707. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SHMDT_CHART);
  708. for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
  709. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  710. write_chart_dimension(ect->name, (long long)ect->publish_shm.dt);
  711. }
  712. }
  713. write_end_chart();
  714. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SHMCTL_CHART);
  715. for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
  716. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  717. write_chart_dimension(ect->name, (long long)ect->publish_shm.ctl);
  718. }
  719. }
  720. write_end_chart();
  721. }
  722. /*
  723. * Send Specific Shared memory data
  724. *
  725. * Send data for specific cgroup/apps.
  726. *
  727. * @param type chart type
  728. * @param values structure with values that will be sent to netdata
  729. */
  730. static void ebpf_send_specific_shm_data(char *type, netdata_publish_shm_t *values)
  731. {
  732. write_begin_chart(type, NETDATA_SHMGET_CHART);
  733. write_chart_dimension(shm_publish_aggregated[NETDATA_KEY_SHMGET_CALL].name, (long long)values->get);
  734. write_end_chart();
  735. write_begin_chart(type, NETDATA_SHMAT_CHART);
  736. write_chart_dimension(shm_publish_aggregated[NETDATA_KEY_SHMAT_CALL].name, (long long)values->at);
  737. write_end_chart();
  738. write_begin_chart(type, NETDATA_SHMDT_CHART);
  739. write_chart_dimension(shm_publish_aggregated[NETDATA_KEY_SHMDT_CALL].name, (long long)values->dt);
  740. write_end_chart();
  741. write_begin_chart(type, NETDATA_SHMCTL_CHART);
  742. write_chart_dimension(shm_publish_aggregated[NETDATA_KEY_SHMCTL_CALL].name, (long long)values->ctl);
  743. write_end_chart();
  744. }
  745. /**
  746. * Send data to Netdata calling auxiliary functions.
  747. *
  748. * @param update_every value to overwrite the update frequency set by the server.
  749. */
  750. void ebpf_shm_send_cgroup_data(int update_every)
  751. {
  752. if (!ebpf_cgroup_pids)
  753. return;
  754. pthread_mutex_lock(&mutex_cgroup_shm);
  755. ebpf_cgroup_target_t *ect;
  756. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  757. ebpf_shm_sum_cgroup_pids(&ect->publish_shm, ect->pids);
  758. }
  759. int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
  760. if (has_systemd) {
  761. if (send_cgroup_chart) {
  762. ebpf_create_systemd_shm_charts(update_every);
  763. }
  764. ebpf_send_systemd_shm_charts();
  765. }
  766. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  767. if (ect->systemd)
  768. continue;
  769. if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_SHM_CHART) && ect->updated) {
  770. ebpf_create_specific_shm_charts(ect->name, update_every);
  771. ect->flags |= NETDATA_EBPF_CGROUP_HAS_SHM_CHART;
  772. }
  773. if (ect->flags & NETDATA_EBPF_CGROUP_HAS_SHM_CHART) {
  774. if (ect->updated) {
  775. ebpf_send_specific_shm_data(ect->name, &ect->publish_shm);
  776. } else {
  777. ebpf_obsolete_specific_shm_charts(ect->name, update_every);
  778. ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_SWAP_CHART;
  779. }
  780. }
  781. }
  782. pthread_mutex_unlock(&mutex_cgroup_shm);
  783. }
  784. /**
  785. * Main loop for this collector.
  786. */
  787. static void shm_collector(ebpf_module_t *em)
  788. {
  789. shm_threads.thread = mallocz(sizeof(netdata_thread_t));
  790. shm_threads.start_routine = ebpf_shm_read_hash;
  791. netdata_thread_create(
  792. shm_threads.thread,
  793. shm_threads.name,
  794. NETDATA_THREAD_OPTION_DEFAULT,
  795. ebpf_shm_read_hash,
  796. em
  797. );
  798. int cgroups = em->cgroup_charts;
  799. int update_every = em->update_every;
  800. heartbeat_t hb;
  801. heartbeat_init(&hb);
  802. usec_t step = update_every * USEC_PER_SEC;
  803. while (!ebpf_exit_plugin) {
  804. (void)heartbeat_next(&hb, step);
  805. if (ebpf_exit_plugin)
  806. break;
  807. netdata_apps_integration_flags_t apps = em->apps_charts;
  808. pthread_mutex_lock(&collect_data_mutex);
  809. if (apps) {
  810. read_apps_table();
  811. }
  812. if (cgroups) {
  813. ebpf_update_shm_cgroup();
  814. }
  815. pthread_mutex_lock(&lock);
  816. shm_send_global();
  817. if (apps & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
  818. ebpf_shm_send_apps_data(apps_groups_root_target);
  819. }
  820. if (cgroups) {
  821. ebpf_shm_send_cgroup_data(update_every);
  822. }
  823. pthread_mutex_unlock(&lock);
  824. pthread_mutex_unlock(&collect_data_mutex);
  825. }
  826. }
  827. /*****************************************************************
  828. * INITIALIZE THREAD
  829. *****************************************************************/
  830. /**
  831. * Create apps charts
  832. *
  833. * Call ebpf_create_chart to create the charts on apps submenu.
  834. *
  835. * @param em a pointer to the structure with the default values.
  836. */
  837. void ebpf_shm_create_apps_charts(struct ebpf_module *em, void *ptr)
  838. {
  839. struct target *root = ptr;
  840. ebpf_create_charts_on_apps(NETDATA_SHMGET_CHART,
  841. "Calls to syscall <code>shmget(2)</code>.",
  842. EBPF_COMMON_DIMENSION_CALL,
  843. NETDATA_APPS_IPC_SHM_GROUP,
  844. NETDATA_EBPF_CHART_TYPE_STACKED,
  845. 20191,
  846. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  847. root, em->update_every, NETDATA_EBPF_MODULE_NAME_SHM);
  848. ebpf_create_charts_on_apps(NETDATA_SHMAT_CHART,
  849. "Calls to syscall <code>shmat(2)</code>.",
  850. EBPF_COMMON_DIMENSION_CALL,
  851. NETDATA_APPS_IPC_SHM_GROUP,
  852. NETDATA_EBPF_CHART_TYPE_STACKED,
  853. 20192,
  854. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  855. root, em->update_every, NETDATA_EBPF_MODULE_NAME_SHM);
  856. ebpf_create_charts_on_apps(NETDATA_SHMDT_CHART,
  857. "Calls to syscall <code>shmdt(2)</code>.",
  858. EBPF_COMMON_DIMENSION_CALL,
  859. NETDATA_APPS_IPC_SHM_GROUP,
  860. NETDATA_EBPF_CHART_TYPE_STACKED,
  861. 20193,
  862. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  863. root, em->update_every, NETDATA_EBPF_MODULE_NAME_SHM);
  864. ebpf_create_charts_on_apps(NETDATA_SHMCTL_CHART,
  865. "Calls to syscall <code>shmctl(2)</code>.",
  866. EBPF_COMMON_DIMENSION_CALL,
  867. NETDATA_APPS_IPC_SHM_GROUP,
  868. NETDATA_EBPF_CHART_TYPE_STACKED,
  869. 20194,
  870. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  871. root, em->update_every, NETDATA_EBPF_MODULE_NAME_SHM);
  872. em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
  873. }
  874. /**
  875. * Allocate vectors used with this thread.
  876. *
  877. * We are not testing the return, because callocz does this and shutdown the software
  878. * case it was not possible to allocate.
  879. *
  880. * @param apps is apps enabled?
  881. */
  882. static void ebpf_shm_allocate_global_vectors(int apps)
  883. {
  884. if (apps)
  885. shm_pid = callocz((size_t)pid_max, sizeof(netdata_publish_shm_t *));
  886. shm_vector = callocz((size_t)ebpf_nprocs, sizeof(netdata_publish_shm_t));
  887. shm_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t));
  888. memset(shm_hash_values, 0, sizeof(shm_hash_values));
  889. }
  890. /*****************************************************************
  891. * MAIN THREAD
  892. *****************************************************************/
  893. /**
  894. * Create global charts
  895. *
  896. * Call ebpf_create_chart to create the charts for the collector.
  897. *
  898. * @param update_every value to overwrite the update frequency set by the server.
  899. */
  900. static void ebpf_create_shm_charts(int update_every)
  901. {
  902. ebpf_create_chart(
  903. NETDATA_EBPF_SYSTEM_GROUP,
  904. NETDATA_SHM_GLOBAL_CHART,
  905. "Calls to shared memory system calls",
  906. EBPF_COMMON_DIMENSION_CALL,
  907. NETDATA_SYSTEM_IPC_SHM_SUBMENU,
  908. NULL,
  909. NETDATA_EBPF_CHART_TYPE_LINE,
  910. NETDATA_CHART_PRIO_SYSTEM_IPC_SHARED_MEM_CALLS,
  911. ebpf_create_global_dimension,
  912. shm_publish_aggregated,
  913. NETDATA_SHM_END,
  914. update_every, NETDATA_EBPF_MODULE_NAME_SHM
  915. );
  916. fflush(stdout);
  917. }
  918. /*
  919. * Load BPF
  920. *
  921. * Load BPF files.
  922. *
  923. * @param em the structure with configuration
  924. */
  925. static int ebpf_shm_load_bpf(ebpf_module_t *em)
  926. {
  927. int ret = 0;
  928. ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_KEY_SHMGET_CALL].mode);
  929. if (em->load & EBPF_LOAD_LEGACY) {
  930. em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
  931. if (!em->probe_links) {
  932. em->enabled = CONFIG_BOOLEAN_NO;
  933. ret = -1;
  934. }
  935. }
  936. #ifdef LIBBPF_MAJOR_VERSION
  937. else {
  938. bpf_obj = shm_bpf__open();
  939. if (!bpf_obj)
  940. ret = -1;
  941. else
  942. ret = ebpf_shm_load_and_attach(bpf_obj, em);
  943. }
  944. #endif
  945. if (ret)
  946. error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->thread_name);
  947. return ret;
  948. }
  949. /**
  950. * Shared memory thread.
  951. *
  952. * @param ptr a pointer to `struct ebpf_module`
  953. * @return It always return NULL
  954. */
  955. void *ebpf_shm_thread(void *ptr)
  956. {
  957. netdata_thread_cleanup_push(ebpf_shm_exit, ptr);
  958. ebpf_module_t *em = (ebpf_module_t *)ptr;
  959. em->maps = shm_maps;
  960. ebpf_update_pid_table(&shm_maps[NETDATA_PID_SHM_TABLE], em);
  961. #ifdef LIBBPF_MAJOR_VERSION
  962. ebpf_adjust_thread_load(em, default_btf);
  963. #endif
  964. if (ebpf_shm_load_bpf(em)) {
  965. em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
  966. goto endshm;
  967. }
  968. ebpf_shm_allocate_global_vectors(em->apps_charts);
  969. int algorithms[NETDATA_SHM_END] = {
  970. NETDATA_EBPF_INCREMENTAL_IDX,
  971. NETDATA_EBPF_INCREMENTAL_IDX,
  972. NETDATA_EBPF_INCREMENTAL_IDX,
  973. NETDATA_EBPF_INCREMENTAL_IDX
  974. };
  975. ebpf_global_labels(
  976. shm_aggregated_data,
  977. shm_publish_aggregated,
  978. shm_dimension_name,
  979. shm_dimension_name,
  980. algorithms,
  981. NETDATA_SHM_END
  982. );
  983. pthread_mutex_lock(&lock);
  984. ebpf_create_shm_charts(em->update_every);
  985. ebpf_update_stats(&plugin_statistics, em);
  986. pthread_mutex_unlock(&lock);
  987. shm_collector(em);
  988. endshm:
  989. ebpf_update_disabled_plugin_stats(em);
  990. netdata_thread_cleanup_pop(1);
  991. return NULL;
  992. }