ebpf_shm.c 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287
  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. "Calls to syscall <code>shmget(2)</code>.",
  270. EBPF_COMMON_DIMENSION_CALL,
  271. NETDATA_APPS_IPC_SHM_GROUP,
  272. NETDATA_EBPF_CHART_TYPE_STACKED,
  273. NULL,
  274. 20191,
  275. em->update_every);
  276. ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
  277. NETDATA_SHMAT_CHART,
  278. "Calls to syscall <code>shmat(2)</code>.",
  279. EBPF_COMMON_DIMENSION_CALL,
  280. NETDATA_APPS_IPC_SHM_GROUP,
  281. NETDATA_EBPF_CHART_TYPE_STACKED,
  282. NULL,
  283. 20192,
  284. em->update_every);
  285. ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
  286. NETDATA_SHMDT_CHART,
  287. "Calls to syscall <code>shmdt(2)</code>.",
  288. EBPF_COMMON_DIMENSION_CALL,
  289. NETDATA_APPS_IPC_SHM_GROUP,
  290. NETDATA_EBPF_CHART_TYPE_STACKED,
  291. NULL,
  292. 20193,
  293. em->update_every);
  294. ebpf_write_chart_obsolete(NETDATA_SERVICE_FAMILY,
  295. NETDATA_SHMCTL_CHART,
  296. "Calls to syscall <code>shmctl(2)</code>.",
  297. EBPF_COMMON_DIMENSION_CALL,
  298. NETDATA_APPS_IPC_SHM_GROUP,
  299. NETDATA_EBPF_CHART_TYPE_STACKED,
  300. NULL,
  301. 20193,
  302. em->update_every);
  303. }
  304. /**
  305. * Obsolete cgroup chart
  306. *
  307. * Send obsolete for all charts created before to close.
  308. *
  309. * @param em a pointer to `struct ebpf_module`
  310. */
  311. static inline void ebpf_obsolete_shm_cgroup_charts(ebpf_module_t *em) {
  312. pthread_mutex_lock(&mutex_cgroup_shm);
  313. ebpf_obsolete_shm_services(em);
  314. ebpf_cgroup_target_t *ect;
  315. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  316. if (ect->systemd)
  317. continue;
  318. ebpf_obsolete_specific_shm_charts(ect->name, em->update_every);
  319. }
  320. pthread_mutex_unlock(&mutex_cgroup_shm);
  321. }
  322. /**
  323. * Obsolette apps charts
  324. *
  325. * Obsolete apps charts.
  326. *
  327. * @param em a pointer to the structure with the default values.
  328. */
  329. void ebpf_obsolete_shm_apps_charts(struct ebpf_module *em)
  330. {
  331. ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
  332. NETDATA_SHMGET_CHART,
  333. "Calls to syscall <code>shmget(2)</code>.",
  334. EBPF_COMMON_DIMENSION_CALL,
  335. NETDATA_APPS_IPC_SHM_GROUP,
  336. NETDATA_EBPF_CHART_TYPE_STACKED,
  337. NULL,
  338. 20191,
  339. em->update_every);
  340. ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
  341. NETDATA_SHMAT_CHART,
  342. "Calls to syscall <code>shmat(2)</code>.",
  343. EBPF_COMMON_DIMENSION_CALL,
  344. NETDATA_APPS_IPC_SHM_GROUP,
  345. NETDATA_EBPF_CHART_TYPE_STACKED,
  346. NULL,
  347. 20192,
  348. em->update_every);
  349. ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
  350. NETDATA_SHMDT_CHART,
  351. "Calls to syscall <code>shmdt(2)</code>.",
  352. EBPF_COMMON_DIMENSION_CALL,
  353. NETDATA_APPS_IPC_SHM_GROUP,
  354. NETDATA_EBPF_CHART_TYPE_STACKED,
  355. NULL,
  356. 20193,
  357. em->update_every);
  358. ebpf_write_chart_obsolete(NETDATA_APPS_FAMILY,
  359. NETDATA_SHMCTL_CHART,
  360. "Calls to syscall <code>shmctl(2)</code>.",
  361. EBPF_COMMON_DIMENSION_CALL,
  362. NETDATA_APPS_IPC_SHM_GROUP,
  363. NETDATA_EBPF_CHART_TYPE_STACKED,
  364. NULL,
  365. 20194,
  366. em->update_every);
  367. }
  368. /**
  369. * Obsolete global
  370. *
  371. * Obsolete global charts created by thread.
  372. *
  373. * @param em a pointer to `struct ebpf_module`
  374. */
  375. static void ebpf_obsolete_shm_global(ebpf_module_t *em)
  376. {
  377. ebpf_write_chart_obsolete(NETDATA_EBPF_SYSTEM_GROUP,
  378. NETDATA_SHM_GLOBAL_CHART,
  379. "Calls to shared memory system calls",
  380. EBPF_COMMON_DIMENSION_CALL,
  381. NETDATA_SYSTEM_IPC_SHM_SUBMENU,
  382. NETDATA_EBPF_CHART_TYPE_LINE,
  383. NULL,
  384. NETDATA_CHART_PRIO_SYSTEM_IPC_SHARED_MEM_CALLS,
  385. em->update_every);
  386. }
  387. /**
  388. * SHM Exit
  389. *
  390. * Cancel child thread.
  391. *
  392. * @param ptr thread data.
  393. */
  394. static void ebpf_shm_exit(void *ptr)
  395. {
  396. ebpf_module_t *em = (ebpf_module_t *)ptr;
  397. if (em->enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
  398. pthread_mutex_lock(&lock);
  399. if (em->cgroup_charts) {
  400. ebpf_obsolete_shm_cgroup_charts(em);
  401. fflush(stdout);
  402. }
  403. if (em->apps_charts & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
  404. ebpf_obsolete_shm_apps_charts(em);
  405. }
  406. ebpf_obsolete_shm_global(em);
  407. #ifdef NETDATA_DEV_MODE
  408. if (ebpf_aral_shm_pid)
  409. ebpf_statistic_obsolete_aral_chart(em, shm_disable_priority);
  410. #endif
  411. fflush(stdout);
  412. pthread_mutex_unlock(&lock);
  413. }
  414. ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_REMOVE);
  415. #ifdef LIBBPF_MAJOR_VERSION
  416. if (shm_bpf_obj) {
  417. shm_bpf__destroy(shm_bpf_obj);
  418. shm_bpf_obj = NULL;
  419. }
  420. #endif
  421. if (em->objects) {
  422. ebpf_unload_legacy_code(em->objects, em->probe_links);
  423. em->objects = NULL;
  424. em->probe_links = NULL;
  425. }
  426. pthread_mutex_lock(&ebpf_exit_cleanup);
  427. em->enabled = NETDATA_THREAD_EBPF_STOPPED;
  428. ebpf_update_stats(&plugin_statistics, em);
  429. pthread_mutex_unlock(&ebpf_exit_cleanup);
  430. }
  431. /*****************************************************************
  432. * COLLECTOR THREAD
  433. *****************************************************************/
  434. /**
  435. * Apps Accumulator
  436. *
  437. * Sum all values read from kernel and store in the first address.
  438. *
  439. * @param out the vector with read values.
  440. * @param maps_per_core do I need to read all cores?
  441. */
  442. static void shm_apps_accumulator(netdata_publish_shm_t *out, int maps_per_core)
  443. {
  444. int i, end = (maps_per_core) ? ebpf_nprocs : 1;
  445. netdata_publish_shm_t *total = &out[0];
  446. for (i = 1; i < end; i++) {
  447. netdata_publish_shm_t *w = &out[i];
  448. total->get += w->get;
  449. total->at += w->at;
  450. total->dt += w->dt;
  451. total->ctl += w->ctl;
  452. }
  453. }
  454. /**
  455. * Fill PID
  456. *
  457. * Fill PID structures
  458. *
  459. * @param current_pid pid that we are collecting data
  460. * @param out values read from hash tables;
  461. */
  462. static void shm_fill_pid(uint32_t current_pid, netdata_publish_shm_t *publish)
  463. {
  464. netdata_publish_shm_t *curr = shm_pid[current_pid];
  465. if (!curr) {
  466. curr = ebpf_shm_stat_get( );
  467. shm_pid[current_pid] = curr;
  468. }
  469. memcpy(curr, publish, sizeof(netdata_publish_shm_t));
  470. }
  471. /**
  472. * Update cgroup
  473. *
  474. * Update cgroup data based in
  475. *
  476. * @param maps_per_core do I need to read all cores?
  477. */
  478. static void ebpf_update_shm_cgroup(int maps_per_core)
  479. {
  480. netdata_publish_shm_t *cv = shm_vector;
  481. int fd = shm_maps[NETDATA_PID_SHM_TABLE].map_fd;
  482. size_t length = sizeof(netdata_publish_shm_t);
  483. if (maps_per_core)
  484. length *= ebpf_nprocs;
  485. ebpf_cgroup_target_t *ect;
  486. memset(cv, 0, length);
  487. pthread_mutex_lock(&mutex_cgroup_shm);
  488. for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
  489. struct pid_on_target2 *pids;
  490. for (pids = ect->pids; pids; pids = pids->next) {
  491. int pid = pids->pid;
  492. netdata_publish_shm_t *out = &pids->shm;
  493. if (likely(shm_pid) && shm_pid[pid]) {
  494. netdata_publish_shm_t *in = shm_pid[pid];
  495. memcpy(out, in, sizeof(netdata_publish_shm_t));
  496. } else {
  497. if (!bpf_map_lookup_elem(fd, &pid, cv)) {
  498. shm_apps_accumulator(cv, maps_per_core);
  499. memcpy(out, cv, sizeof(netdata_publish_shm_t));
  500. // now that we've consumed the value, zero it out in the map.
  501. memset(cv, 0, length);
  502. bpf_map_update_elem(fd, &pid, cv, BPF_EXIST);
  503. }
  504. }
  505. }
  506. }
  507. pthread_mutex_unlock(&mutex_cgroup_shm);
  508. }
  509. /**
  510. * Read APPS table
  511. *
  512. * Read the apps table and store data inside the structure.
  513. *
  514. * @param maps_per_core do I need to read all cores?
  515. */
  516. static void read_shm_apps_table(int maps_per_core)
  517. {
  518. netdata_publish_shm_t *cv = shm_vector;
  519. uint32_t key;
  520. struct ebpf_pid_stat *pids = ebpf_root_of_pids;
  521. int fd = shm_maps[NETDATA_PID_SHM_TABLE].map_fd;
  522. size_t length = sizeof(netdata_publish_shm_t);
  523. if (maps_per_core)
  524. length *= ebpf_nprocs;
  525. while (pids) {
  526. key = pids->pid;
  527. if (bpf_map_lookup_elem(fd, &key, cv)) {
  528. pids = pids->next;
  529. continue;
  530. }
  531. shm_apps_accumulator(cv, maps_per_core);
  532. shm_fill_pid(key, cv);
  533. // now that we've consumed the value, zero it out in the map.
  534. memset(cv, 0, length);
  535. bpf_map_update_elem(fd, &key, cv, BPF_EXIST);
  536. pids = pids->next;
  537. }
  538. }
  539. /**
  540. * Send global charts to netdata agent.
  541. */
  542. static void shm_send_global()
  543. {
  544. write_begin_chart(NETDATA_EBPF_SYSTEM_GROUP, NETDATA_SHM_GLOBAL_CHART);
  545. write_chart_dimension(
  546. shm_publish_aggregated[NETDATA_KEY_SHMGET_CALL].dimension,
  547. (long long) shm_hash_values[NETDATA_KEY_SHMGET_CALL]
  548. );
  549. write_chart_dimension(
  550. shm_publish_aggregated[NETDATA_KEY_SHMAT_CALL].dimension,
  551. (long long) shm_hash_values[NETDATA_KEY_SHMAT_CALL]
  552. );
  553. write_chart_dimension(
  554. shm_publish_aggregated[NETDATA_KEY_SHMDT_CALL].dimension,
  555. (long long) shm_hash_values[NETDATA_KEY_SHMDT_CALL]
  556. );
  557. write_chart_dimension(
  558. shm_publish_aggregated[NETDATA_KEY_SHMCTL_CALL].dimension,
  559. (long long) shm_hash_values[NETDATA_KEY_SHMCTL_CALL]
  560. );
  561. write_end_chart();
  562. }
  563. /**
  564. * Read global counter
  565. *
  566. * Read the table with number of calls for all functions
  567. *
  568. * @param stats vector used to read data from control table.
  569. * @param maps_per_core do I need to read all cores?
  570. */
  571. static void ebpf_shm_read_global_table(netdata_idx_t *stats, int maps_per_core)
  572. {
  573. ebpf_read_global_table_stats(shm_hash_values,
  574. shm_values,
  575. shm_maps[NETDATA_SHM_GLOBAL_TABLE].map_fd,
  576. maps_per_core,
  577. NETDATA_KEY_SHMGET_CALL,
  578. NETDATA_SHM_END);
  579. ebpf_read_global_table_stats(stats,
  580. shm_values,
  581. shm_maps[NETDATA_SHM_CONTROLLER].map_fd,
  582. maps_per_core,
  583. NETDATA_CONTROLLER_PID_TABLE_ADD,
  584. NETDATA_CONTROLLER_END);
  585. }
  586. /**
  587. * Sum values for all targets.
  588. */
  589. static void ebpf_shm_sum_pids(netdata_publish_shm_t *shm, struct ebpf_pid_on_target *root)
  590. {
  591. while (root) {
  592. int32_t pid = root->pid;
  593. netdata_publish_shm_t *w = shm_pid[pid];
  594. if (w) {
  595. shm->get += w->get;
  596. shm->at += w->at;
  597. shm->dt += w->dt;
  598. shm->ctl += w->ctl;
  599. // reset for next collection.
  600. w->get = 0;
  601. w->at = 0;
  602. w->dt = 0;
  603. w->ctl = 0;
  604. }
  605. root = root->next;
  606. }
  607. }
  608. /**
  609. * Send data to Netdata calling auxiliary functions.
  610. *
  611. * @param root the target list.
  612. */
  613. void ebpf_shm_send_apps_data(struct ebpf_target *root)
  614. {
  615. struct ebpf_target *w;
  616. for (w = root; w; w = w->next) {
  617. if (unlikely(w->exposed && w->processes)) {
  618. ebpf_shm_sum_pids(&w->shm, w->root_pid);
  619. }
  620. }
  621. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SHMGET_CHART);
  622. for (w = root; w; w = w->next) {
  623. if (unlikely(w->exposed && w->processes)) {
  624. write_chart_dimension(w->name, (long long) w->shm.get);
  625. }
  626. }
  627. write_end_chart();
  628. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SHMAT_CHART);
  629. for (w = root; w; w = w->next) {
  630. if (unlikely(w->exposed && w->processes)) {
  631. write_chart_dimension(w->name, (long long) w->shm.at);
  632. }
  633. }
  634. write_end_chart();
  635. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SHMDT_CHART);
  636. for (w = root; w; w = w->next) {
  637. if (unlikely(w->exposed && w->processes)) {
  638. write_chart_dimension(w->name, (long long) w->shm.dt);
  639. }
  640. }
  641. write_end_chart();
  642. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SHMCTL_CHART);
  643. for (w = root; w; w = w->next) {
  644. if (unlikely(w->exposed && w->processes)) {
  645. write_chart_dimension(w->name, (long long) w->shm.ctl);
  646. }
  647. }
  648. write_end_chart();
  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 <code>shmget(2)</code>.",
  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 <code>shmat(2)</code>.",
  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 <code>shmdt(2)</code>.",
  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 <code>shmctl(2)</code>.",
  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. "Calls to syscall <code>shmget(2)</code>.",
  738. EBPF_COMMON_DIMENSION_CALL,
  739. NETDATA_APPS_IPC_SHM_GROUP,
  740. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_SHM_GET_CONTEXT,
  741. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5800, update_every);
  742. ebpf_write_chart_obsolete(type, NETDATA_SHMAT_CHART,
  743. "Calls to syscall <code>shmat(2)</code>.",
  744. EBPF_COMMON_DIMENSION_CALL,
  745. NETDATA_APPS_IPC_SHM_GROUP,
  746. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_SHM_AT_CONTEXT,
  747. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5801, update_every);
  748. ebpf_write_chart_obsolete(type, NETDATA_SHMDT_CHART,
  749. "Calls to syscall <code>shmdt(2)</code>.",
  750. EBPF_COMMON_DIMENSION_CALL,
  751. NETDATA_APPS_IPC_SHM_GROUP,
  752. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_SHM_DT_CONTEXT,
  753. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5802, update_every);
  754. ebpf_write_chart_obsolete(type, NETDATA_SHMCTL_CHART,
  755. "Calls to syscall <code>shmctl(2)</code>.",
  756. EBPF_COMMON_DIMENSION_CALL,
  757. NETDATA_APPS_IPC_SHM_GROUP,
  758. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_SHM_CTL_CONTEXT,
  759. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5803, update_every);
  760. }
  761. /**
  762. * Create Systemd Swap Charts
  763. *
  764. * Create charts when systemd is enabled
  765. *
  766. * @param update_every value to overwrite the update frequency set by the server.
  767. **/
  768. static void ebpf_create_systemd_shm_charts(int update_every)
  769. {
  770. ebpf_create_charts_on_systemd(NETDATA_SHMGET_CHART,
  771. "Calls to syscall <code>shmget(2)</code>.",
  772. EBPF_COMMON_DIMENSION_CALL,
  773. NETDATA_APPS_IPC_SHM_GROUP,
  774. NETDATA_EBPF_CHART_TYPE_STACKED,
  775. 20191,
  776. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  777. NETDATA_SYSTEMD_SHM_GET_CONTEXT, NETDATA_EBPF_MODULE_NAME_SHM, update_every);
  778. ebpf_create_charts_on_systemd(NETDATA_SHMAT_CHART,
  779. "Calls to syscall <code>shmat(2)</code>.",
  780. EBPF_COMMON_DIMENSION_CALL,
  781. NETDATA_APPS_IPC_SHM_GROUP,
  782. NETDATA_EBPF_CHART_TYPE_STACKED,
  783. 20192,
  784. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  785. NETDATA_SYSTEMD_SHM_AT_CONTEXT, NETDATA_EBPF_MODULE_NAME_SHM, update_every);
  786. ebpf_create_charts_on_systemd(NETDATA_SHMDT_CHART,
  787. "Calls to syscall <code>shmdt(2)</code>.",
  788. EBPF_COMMON_DIMENSION_CALL,
  789. NETDATA_APPS_IPC_SHM_GROUP,
  790. NETDATA_EBPF_CHART_TYPE_STACKED,
  791. 20193,
  792. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  793. NETDATA_SYSTEMD_SHM_DT_CONTEXT, NETDATA_EBPF_MODULE_NAME_SHM, update_every);
  794. ebpf_create_charts_on_systemd(NETDATA_SHMCTL_CHART,
  795. "Calls to syscall <code>shmctl(2)</code>.",
  796. EBPF_COMMON_DIMENSION_CALL,
  797. NETDATA_APPS_IPC_SHM_GROUP,
  798. NETDATA_EBPF_CHART_TYPE_STACKED,
  799. 20193,
  800. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  801. NETDATA_SYSTEMD_SHM_CTL_CONTEXT, NETDATA_EBPF_MODULE_NAME_SHM, update_every);
  802. }
  803. /**
  804. * Send Systemd charts
  805. *
  806. * Send collected data to Netdata.
  807. */
  808. static void ebpf_send_systemd_shm_charts()
  809. {
  810. ebpf_cgroup_target_t *ect;
  811. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SHMGET_CHART);
  812. for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
  813. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  814. write_chart_dimension(ect->name, (long long)ect->publish_shm.get);
  815. }
  816. }
  817. write_end_chart();
  818. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SHMAT_CHART);
  819. for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
  820. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  821. write_chart_dimension(ect->name, (long long)ect->publish_shm.at);
  822. }
  823. }
  824. write_end_chart();
  825. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SHMDT_CHART);
  826. for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
  827. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  828. write_chart_dimension(ect->name, (long long)ect->publish_shm.dt);
  829. }
  830. }
  831. write_end_chart();
  832. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SHMCTL_CHART);
  833. for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
  834. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  835. write_chart_dimension(ect->name, (long long)ect->publish_shm.ctl);
  836. }
  837. }
  838. write_end_chart();
  839. }
  840. /*
  841. * Send Specific Shared memory data
  842. *
  843. * Send data for specific cgroup/apps.
  844. *
  845. * @param type chart type
  846. * @param values structure with values that will be sent to netdata
  847. */
  848. static void ebpf_send_specific_shm_data(char *type, netdata_publish_shm_t *values)
  849. {
  850. write_begin_chart(type, NETDATA_SHMGET_CHART);
  851. write_chart_dimension(shm_publish_aggregated[NETDATA_KEY_SHMGET_CALL].name, (long long)values->get);
  852. write_end_chart();
  853. write_begin_chart(type, NETDATA_SHMAT_CHART);
  854. write_chart_dimension(shm_publish_aggregated[NETDATA_KEY_SHMAT_CALL].name, (long long)values->at);
  855. write_end_chart();
  856. write_begin_chart(type, NETDATA_SHMDT_CHART);
  857. write_chart_dimension(shm_publish_aggregated[NETDATA_KEY_SHMDT_CALL].name, (long long)values->dt);
  858. write_end_chart();
  859. write_begin_chart(type, NETDATA_SHMCTL_CHART);
  860. write_chart_dimension(shm_publish_aggregated[NETDATA_KEY_SHMCTL_CALL].name, (long long)values->ctl);
  861. write_end_chart();
  862. }
  863. /**
  864. * Send data to Netdata calling auxiliary functions.
  865. *
  866. * @param update_every value to overwrite the update frequency set by the server.
  867. */
  868. void ebpf_shm_send_cgroup_data(int update_every)
  869. {
  870. if (!ebpf_cgroup_pids)
  871. return;
  872. pthread_mutex_lock(&mutex_cgroup_shm);
  873. ebpf_cgroup_target_t *ect;
  874. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  875. ebpf_shm_sum_cgroup_pids(&ect->publish_shm, ect->pids);
  876. }
  877. int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
  878. if (has_systemd) {
  879. if (send_cgroup_chart) {
  880. ebpf_create_systemd_shm_charts(update_every);
  881. }
  882. ebpf_send_systemd_shm_charts();
  883. }
  884. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  885. if (ect->systemd)
  886. continue;
  887. if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_SHM_CHART) && ect->updated) {
  888. ebpf_create_specific_shm_charts(ect->name, update_every);
  889. ect->flags |= NETDATA_EBPF_CGROUP_HAS_SHM_CHART;
  890. }
  891. if (ect->flags & NETDATA_EBPF_CGROUP_HAS_SHM_CHART) {
  892. if (ect->updated) {
  893. ebpf_send_specific_shm_data(ect->name, &ect->publish_shm);
  894. } else {
  895. ebpf_obsolete_specific_shm_charts(ect->name, update_every);
  896. ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_SWAP_CHART;
  897. }
  898. }
  899. }
  900. pthread_mutex_unlock(&mutex_cgroup_shm);
  901. }
  902. /**
  903. * Main loop for this collector.
  904. */
  905. static void shm_collector(ebpf_module_t *em)
  906. {
  907. int cgroups = em->cgroup_charts;
  908. int update_every = em->update_every;
  909. heartbeat_t hb;
  910. heartbeat_init(&hb);
  911. int counter = update_every - 1;
  912. int maps_per_core = em->maps_per_core;
  913. uint32_t running_time = 0;
  914. uint32_t lifetime = em->lifetime;
  915. netdata_idx_t *stats = em->hash_table_stats;
  916. memset(stats, 0, sizeof(em->hash_table_stats));
  917. while (!ebpf_plugin_exit && running_time < lifetime) {
  918. (void)heartbeat_next(&hb, USEC_PER_SEC);
  919. if (ebpf_plugin_exit || ++counter != update_every)
  920. continue;
  921. counter = 0;
  922. netdata_apps_integration_flags_t apps = em->apps_charts;
  923. ebpf_shm_read_global_table(stats, maps_per_core);
  924. pthread_mutex_lock(&collect_data_mutex);
  925. if (apps) {
  926. read_shm_apps_table(maps_per_core);
  927. }
  928. if (cgroups) {
  929. ebpf_update_shm_cgroup(maps_per_core);
  930. }
  931. pthread_mutex_lock(&lock);
  932. shm_send_global();
  933. if (apps & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
  934. ebpf_shm_send_apps_data(apps_groups_root_target);
  935. }
  936. #ifdef NETDATA_DEV_MODE
  937. if (ebpf_aral_shm_pid)
  938. ebpf_send_data_aral_chart(ebpf_aral_shm_pid, em);
  939. #endif
  940. if (cgroups) {
  941. ebpf_shm_send_cgroup_data(update_every);
  942. }
  943. pthread_mutex_unlock(&lock);
  944. pthread_mutex_unlock(&collect_data_mutex);
  945. pthread_mutex_lock(&ebpf_exit_cleanup);
  946. if (running_time && !em->running_time)
  947. running_time = update_every;
  948. else
  949. running_time += update_every;
  950. em->running_time = running_time;
  951. pthread_mutex_unlock(&ebpf_exit_cleanup);
  952. }
  953. }
  954. /*****************************************************************
  955. * INITIALIZE THREAD
  956. *****************************************************************/
  957. /**
  958. * Create apps charts
  959. *
  960. * Call ebpf_create_chart to create the charts on apps submenu.
  961. *
  962. * @param em a pointer to the structure with the default values.
  963. */
  964. void ebpf_shm_create_apps_charts(struct ebpf_module *em, void *ptr)
  965. {
  966. struct ebpf_target *root = ptr;
  967. ebpf_create_charts_on_apps(NETDATA_SHMGET_CHART,
  968. "Calls to syscall <code>shmget(2)</code>.",
  969. EBPF_COMMON_DIMENSION_CALL,
  970. NETDATA_APPS_IPC_SHM_GROUP,
  971. NETDATA_EBPF_CHART_TYPE_STACKED,
  972. 20191,
  973. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  974. root, em->update_every, NETDATA_EBPF_MODULE_NAME_SHM);
  975. ebpf_create_charts_on_apps(NETDATA_SHMAT_CHART,
  976. "Calls to syscall <code>shmat(2)</code>.",
  977. EBPF_COMMON_DIMENSION_CALL,
  978. NETDATA_APPS_IPC_SHM_GROUP,
  979. NETDATA_EBPF_CHART_TYPE_STACKED,
  980. 20192,
  981. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  982. root, em->update_every, NETDATA_EBPF_MODULE_NAME_SHM);
  983. ebpf_create_charts_on_apps(NETDATA_SHMDT_CHART,
  984. "Calls to syscall <code>shmdt(2)</code>.",
  985. EBPF_COMMON_DIMENSION_CALL,
  986. NETDATA_APPS_IPC_SHM_GROUP,
  987. NETDATA_EBPF_CHART_TYPE_STACKED,
  988. 20193,
  989. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  990. root, em->update_every, NETDATA_EBPF_MODULE_NAME_SHM);
  991. ebpf_create_charts_on_apps(NETDATA_SHMCTL_CHART,
  992. "Calls to syscall <code>shmctl(2)</code>.",
  993. EBPF_COMMON_DIMENSION_CALL,
  994. NETDATA_APPS_IPC_SHM_GROUP,
  995. NETDATA_EBPF_CHART_TYPE_STACKED,
  996. 20194,
  997. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  998. root, em->update_every, NETDATA_EBPF_MODULE_NAME_SHM);
  999. em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
  1000. }
  1001. /**
  1002. * Allocate vectors used with this thread.
  1003. *
  1004. * We are not testing the return, because callocz does this and shutdown the software
  1005. * case it was not possible to allocate.
  1006. *
  1007. * @param apps is apps enabled?
  1008. */
  1009. static void ebpf_shm_allocate_global_vectors(int apps)
  1010. {
  1011. if (apps) {
  1012. ebpf_shm_aral_init();
  1013. shm_pid = callocz((size_t)pid_max, sizeof(netdata_publish_shm_t *));
  1014. shm_vector = callocz((size_t)ebpf_nprocs, sizeof(netdata_publish_shm_t));
  1015. }
  1016. shm_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t));
  1017. memset(shm_hash_values, 0, sizeof(shm_hash_values));
  1018. }
  1019. /*****************************************************************
  1020. * MAIN THREAD
  1021. *****************************************************************/
  1022. /**
  1023. * Create global charts
  1024. *
  1025. * Call ebpf_create_chart to create the charts for the collector.
  1026. *
  1027. * @param update_every value to overwrite the update frequency set by the server.
  1028. */
  1029. static void ebpf_create_shm_charts(int update_every)
  1030. {
  1031. ebpf_create_chart(
  1032. NETDATA_EBPF_SYSTEM_GROUP,
  1033. NETDATA_SHM_GLOBAL_CHART,
  1034. "Calls to shared memory system calls",
  1035. EBPF_COMMON_DIMENSION_CALL,
  1036. NETDATA_SYSTEM_IPC_SHM_SUBMENU,
  1037. NULL,
  1038. NETDATA_EBPF_CHART_TYPE_LINE,
  1039. NETDATA_CHART_PRIO_SYSTEM_IPC_SHARED_MEM_CALLS,
  1040. ebpf_create_global_dimension,
  1041. shm_publish_aggregated,
  1042. NETDATA_SHM_END,
  1043. update_every, NETDATA_EBPF_MODULE_NAME_SHM
  1044. );
  1045. fflush(stdout);
  1046. }
  1047. /*
  1048. * Load BPF
  1049. *
  1050. * Load BPF files.
  1051. *
  1052. * @param em the structure with configuration
  1053. */
  1054. static int ebpf_shm_load_bpf(ebpf_module_t *em)
  1055. {
  1056. #ifdef LIBBPF_MAJOR_VERSION
  1057. ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel);
  1058. #endif
  1059. int ret = 0;
  1060. ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_KEY_SHMGET_CALL].mode);
  1061. if (em->load & EBPF_LOAD_LEGACY) {
  1062. em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
  1063. if (!em->probe_links) {
  1064. ret = -1;
  1065. }
  1066. }
  1067. #ifdef LIBBPF_MAJOR_VERSION
  1068. else {
  1069. shm_bpf_obj = shm_bpf__open();
  1070. if (!shm_bpf_obj)
  1071. ret = -1;
  1072. else
  1073. ret = ebpf_shm_load_and_attach(shm_bpf_obj, em);
  1074. }
  1075. #endif
  1076. if (ret)
  1077. netdata_log_error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->info.thread_name);
  1078. return ret;
  1079. }
  1080. /**
  1081. * Shared memory thread.
  1082. *
  1083. * @param ptr a pointer to `struct ebpf_module`
  1084. * @return It always return NULL
  1085. */
  1086. void *ebpf_shm_thread(void *ptr)
  1087. {
  1088. netdata_thread_cleanup_push(ebpf_shm_exit, ptr);
  1089. ebpf_module_t *em = (ebpf_module_t *)ptr;
  1090. em->maps = shm_maps;
  1091. ebpf_update_pid_table(&shm_maps[NETDATA_PID_SHM_TABLE], em);
  1092. #ifdef LIBBPF_MAJOR_VERSION
  1093. ebpf_adjust_thread_load(em, default_btf);
  1094. #endif
  1095. if (ebpf_shm_load_bpf(em)) {
  1096. goto endshm;
  1097. }
  1098. ebpf_shm_allocate_global_vectors(em->apps_charts);
  1099. int algorithms[NETDATA_SHM_END] = {
  1100. NETDATA_EBPF_INCREMENTAL_IDX,
  1101. NETDATA_EBPF_INCREMENTAL_IDX,
  1102. NETDATA_EBPF_INCREMENTAL_IDX,
  1103. NETDATA_EBPF_INCREMENTAL_IDX
  1104. };
  1105. ebpf_global_labels(
  1106. shm_aggregated_data,
  1107. shm_publish_aggregated,
  1108. shm_dimension_name,
  1109. shm_dimension_name,
  1110. algorithms,
  1111. NETDATA_SHM_END
  1112. );
  1113. pthread_mutex_lock(&lock);
  1114. ebpf_create_shm_charts(em->update_every);
  1115. ebpf_update_stats(&plugin_statistics, em);
  1116. ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_ADD);
  1117. #ifdef NETDATA_DEV_MODE
  1118. if (ebpf_aral_shm_pid)
  1119. shm_disable_priority = ebpf_statistic_create_aral_chart(NETDATA_EBPF_SHM_ARAL_NAME, em);
  1120. #endif
  1121. pthread_mutex_unlock(&lock);
  1122. shm_collector(em);
  1123. endshm:
  1124. ebpf_update_disabled_plugin_stats(em);
  1125. netdata_thread_cleanup_pop(1);
  1126. return NULL;
  1127. }