ebpf_shm.c 37 KB

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