ebpf_shm.c 45 KB

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