ebpf_shm.c 46 KB

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