├── artifacts └── .gitkeep ├── headers └── .gitkeep ├── kernel-patches ├── 4.14.291 │ └── .gitkeep ├── 4.16.18 │ ├── .gitkeep │ ├── gcc-9.diff.gz │ └── fix-classmap-PF_MAX.diff.gz ├── 4.18.0 │ └── .gitkeep ├── 5.10.139 │ └── .gitkeep ├── 5.11.19 │ └── .gitkeep ├── 5.15.63 │ └── .gitkeep ├── 5.16.18 │ └── .gitkeep ├── 5.4.17 │ ├── .gitkeep │ └── pgtable.h.diff.gz ├── 5.4.210 │ └── .gitkeep ├── 6.16.2 │ └── .gitkeep ├── 6.8.2 │ └── .gitkeep ├── 4.18.0-372.32.1.el8_6 │ └── .gitkeep ├── 5.14.0-70.30.1.el9_0 │ └── .gitkeep └── README.md ├── .gitattributes ├── .github ├── CODEOWNERS ├── dependabot.yml ├── workflows │ ├── build.yml │ ├── release.yml │ └── review.yml └── PULL_REQUEST_TEMPLATE.md ├── .gitmodules ├── CentOS7 ├── pnetdata_ebpf_dc.3.10.rhf.o ├── pnetdata_ebpf_fd.3.10.rhf.o ├── rnetdata_ebpf_dc.3.10.rhf.o ├── rnetdata_ebpf_fd.3.10.rhf.o ├── pnetdata_ebpf_btrfs.3.10.rhf.o ├── pnetdata_ebpf_disk.3.10.rhf.o ├── pnetdata_ebpf_ext4.3.10.rhf.o ├── pnetdata_ebpf_fsync.3.10.rhf.o ├── pnetdata_ebpf_hardirq.3.10.rhf.o ├── pnetdata_ebpf_mdflush.3.10.rhf.o ├── pnetdata_ebpf_mount.3.10.rhf.o ├── pnetdata_ebpf_msync.3.10.rhf.o ├── pnetdata_ebpf_nfs.3.10.rhf.o ├── pnetdata_ebpf_oomkill.3.10.rhf.o ├── pnetdata_ebpf_process.3.10.rhf.o ├── pnetdata_ebpf_shm.3.10.rhf.o ├── pnetdata_ebpf_socket.3.10.rhf.o ├── pnetdata_ebpf_softirq.3.10.rhf.o ├── pnetdata_ebpf_swap.3.10.rhf.o ├── pnetdata_ebpf_sync.3.10.rhf.o ├── pnetdata_ebpf_syncfs.3.10.rhf.o ├── pnetdata_ebpf_vfs.3.10.rhf.o ├── pnetdata_ebpf_xfs.3.10.rhf.o ├── pnetdata_ebpf_zfs.3.10.rhf.o ├── rnetdata_ebpf_btrfs.3.10.rhf.o ├── rnetdata_ebpf_disk.3.10.rhf.o ├── rnetdata_ebpf_ext4.3.10.rhf.o ├── rnetdata_ebpf_fsync.3.10.rhf.o ├── rnetdata_ebpf_hardirq.3.10.rhf.o ├── rnetdata_ebpf_mdflush.3.10.rhf.o ├── rnetdata_ebpf_mount.3.10.rhf.o ├── rnetdata_ebpf_msync.3.10.rhf.o ├── rnetdata_ebpf_nfs.3.10.rhf.o ├── rnetdata_ebpf_oomkill.3.10.rhf.o ├── rnetdata_ebpf_process.3.10.rhf.o ├── rnetdata_ebpf_shm.3.10.rhf.o ├── rnetdata_ebpf_socket.3.10.rhf.o ├── rnetdata_ebpf_softirq.3.10.rhf.o ├── rnetdata_ebpf_swap.3.10.rhf.o ├── rnetdata_ebpf_sync.3.10.rhf.o ├── rnetdata_ebpf_syncfs.3.10.rhf.o ├── rnetdata_ebpf_vfs.3.10.rhf.o ├── rnetdata_ebpf_xfs.3.10.rhf.o ├── rnetdata_ebpf_zfs.3.10.rhf.o ├── pnetdata_ebpf_cachestat.3.10.rhf.o ├── pnetdata_ebpf_fdatasync.3.10.rhf.o ├── rnetdata_ebpf_cachestat.3.10.rhf.o ├── rnetdata_ebpf_fdatasync.3.10.rhf.o ├── pnetdata_ebpf_network_viewer.3.10.rhf.o ├── pnetdata_ebpf_sync_file_range.3.10.rhf.o ├── rnetdata_ebpf_network_viewer.3.10.rhf.o └── rnetdata_ebpf_sync_file_range.3.10.rhf.o ├── .gitignore ├── includes ├── netdata_mdflush.h ├── netdata_sync.h ├── netdata_mount.h ├── netdata_oomkill.h ├── netdata_asm_goto.h ├── netdata_swap.h ├── netdata_shm.h ├── netdata_cache.h ├── netdata_dc.h ├── netdata_ebpf.h ├── netdata_defs.h ├── netdata_fd.h ├── netdata_fs.h ├── netdata_softirq.h ├── netdata_vfs.h ├── netdata_disk.h ├── netdata_process.h ├── netdata_hardirq.h ├── netdata_socket.h ├── netdata_tests.h └── netdata_common.h ├── .dockerfiles ├── patch_kernel.sh ├── change_libbpf.sh └── build.sh ├── .chglog ├── CHANGELOG.tpl.md └── config.yml ├── .yamllint.yml ├── tools ├── README.md ├── complement.sh ├── build-ebpf-kernel.sh └── check-kernel-config.sh ├── docs ├── centos.md ├── compiling.md └── kernel-vsn.md ├── Dockerfile.musl.generic ├── Dockerfile.static.generic ├── Dockerfile.glibc.generic ├── Dockerfile.musl.centos8 ├── Dockerfile.musl.centos9 ├── Dockerfile.static.centos8 ├── Dockerfile.static.centos9 ├── Dockerfile.musl.oracle8 ├── Dockerfile.static.oracle8 ├── kernel ├── oomkill_kern.c ├── README.md ├── sync_kern.c ├── fsync_kern.c ├── msync_kern.c ├── fdatasync_kern.c ├── sync_file_range_kern.c ├── mdflush_kern.c ├── syncfs_kern.c ├── rename_binaries.sh ├── softirq_kern.c ├── mount_kern.c ├── DEVELOPER.md ├── disk_kern.c ├── swap_kern.c ├── dc_kern.c ├── tester_user.h ├── Makefile ├── shm_kern.c ├── fd_kern.c ├── zfs_kern.c ├── xfs_kern.c ├── ext4_kern.c ├── nfs_kern.c └── cachestat_kern.c ├── Makefile ├── Dockerfile.glibc.centos8 ├── Dockerfile.glibc.centos9 ├── Dockerfile.glibc.oracle8 └── README.md /artifacts/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /headers/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kernel-patches/4.14.291/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kernel-patches/4.16.18/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kernel-patches/4.18.0/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kernel-patches/5.10.139/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kernel-patches/5.11.19/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kernel-patches/5.15.63/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kernel-patches/5.16.18/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kernel-patches/5.4.17/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kernel-patches/5.4.210/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kernel-patches/6.16.2/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kernel-patches/6.8.2/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kernel-patches/4.18.0-372.32.1.el8_6/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kernel-patches/5.14.0-70.30.1.el9_0/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.3.10.rhf.o filter=lfs diff=lfs merge=lfs -text 2 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # By Default the team working on this owns/reviews everything 2 | * @thiagoftsm @Ferroin @tkatsoulas 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libbpf"] 2 | path = libbpf 3 | url = https://github.com/netdata/libbpf 4 | ignore = dirty 5 | -------------------------------------------------------------------------------- /kernel-patches/4.16.18/gcc-9.diff.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netdata/kernel-collector/HEAD/kernel-patches/4.16.18/gcc-9.diff.gz -------------------------------------------------------------------------------- /kernel-patches/5.4.17/pgtable.h.diff.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netdata/kernel-collector/HEAD/kernel-patches/5.4.17/pgtable.h.diff.gz -------------------------------------------------------------------------------- /kernel-patches/4.16.18/fix-classmap-PF_MAX.diff.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netdata/kernel-collector/HEAD/kernel-patches/4.16.18/fix-classmap-PF_MAX.diff.gz -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_dc.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e75d4e5019e72c3cfcf56f96d441c9961adf9b929ede71c934048cce58a0244f 3 | size 103680 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_fd.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ce860ce005b416a70cf5004e4ff148942662e7d6b71656ac1fba283aa26d280c 3 | size 99944 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_dc.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e75d4e5019e72c3cfcf56f96d441c9961adf9b929ede71c934048cce58a0244f 3 | size 103680 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_fd.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:07037c58755dad3c5856b9ba93692587ef4fc260b29517598de008a6a5b29f20 3 | size 102240 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_btrfs.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7ef1df0b133ef1d4f01cb023089a2241084ccf12f1c65fb25729a3cb43b83c37 3 | size 195968 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_disk.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:14741b00c8bb526f7d0847a187cc3cc7506f730ec0ea4c877a76c5e56846bccb 3 | size 168408 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_ext4.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:495dd04563e6a3c5d0a431f4dc1ccb7eec7f74423348893fe71c9191b2a685fa 3 | size 192096 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_fsync.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:19f1bc176ba469dd1d9e7014c2bcc56324795d5b3ed6127c77b69ad4a36c58b6 3 | size 80808 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_hardirq.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:34dbc433bd0a1ae5d264501cbd04156005cb95d7ba571faaf2e84e0a6ae390aa 3 | size 167120 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_mdflush.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:06c6ea7c0c6f1500f49b6b31f88e0bf8920120e608da955a6d8a173fe5edc669 3 | size 211432 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_mount.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0016089fffe498e3d4664465c2e3089fc7d95c27aed17f68df7c3361043c3724 3 | size 82992 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_msync.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f0e2212eefe4602fbebb6e4e6039568810cbf04b94372d2b66c5312bdd3168db 3 | size 80808 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_nfs.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:78c32709e5627ff8a2c9f2d2d7dd1b457474e0c536f6c2e125f36cd1bc042e03 3 | size 199936 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_oomkill.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1b242015fa4ae88aad6a8cf3786e58d5a415bff25aa8c0a34df0ab0e6b75c8df 3 | size 133416 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_process.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:adcdd4dd8f92daf3b5d0953f19125042ab1d4c637bea416ed8d0e64713a6385b 3 | size 171680 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_shm.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4e2c0b6aef1a5e5960b43fddc108f2e0606c9808ec9c991c3ec118868f862169 3 | size 115072 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_socket.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0aa506aec153ca31cdf4ac13f22c9ec27b65bd7c4f5b789b1724b28b089e5b47 3 | size 450048 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_softirq.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:caa418cfd25a1b9836d9487707f1846d3432226f68917f115e81e5be86823ed4 3 | size 136376 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_swap.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5c349beda4075b8e7fe6a25b45e8b0756b50e7c6efc1af09191a92daa04cf2ea 3 | size 99632 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_sync.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9598734c78dc27dc3cff5980c226d186c61bad0b6ea0f47cb1ce51477f631969 3 | size 80792 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_syncfs.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3bcc96642cb0881d5271a09fa35616801a940a046aff5f10e5ff70bbffe21a70 3 | size 81016 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_vfs.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c1c7e7eb82722b2f1e1a643fcf8806bdcd4731f15c30e20cb12afb6b367cf33e 3 | size 219616 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_xfs.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:dfc139b94e244faf5ce2d8311c36e95cc8b57fb655a7d27e34ce918a090419f2 3 | size 198880 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_zfs.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0f0e2de062593d1646d2cea4de2dd7b99e3843cd33957b28dbcae102a4a01a90 3 | size 191880 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_btrfs.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7ef1df0b133ef1d4f01cb023089a2241084ccf12f1c65fb25729a3cb43b83c37 3 | size 195968 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_disk.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:14741b00c8bb526f7d0847a187cc3cc7506f730ec0ea4c877a76c5e56846bccb 3 | size 168408 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_ext4.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:495dd04563e6a3c5d0a431f4dc1ccb7eec7f74423348893fe71c9191b2a685fa 3 | size 192096 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_fsync.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:19f1bc176ba469dd1d9e7014c2bcc56324795d5b3ed6127c77b69ad4a36c58b6 3 | size 80808 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_hardirq.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:34dbc433bd0a1ae5d264501cbd04156005cb95d7ba571faaf2e84e0a6ae390aa 3 | size 167120 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_mdflush.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:06c6ea7c0c6f1500f49b6b31f88e0bf8920120e608da955a6d8a173fe5edc669 3 | size 211432 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_mount.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9e09080ab6a071619042333f79eaf88a54ade712da0357083bbf432207c6566c 3 | size 84696 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_msync.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f0e2212eefe4602fbebb6e4e6039568810cbf04b94372d2b66c5312bdd3168db 3 | size 80808 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_nfs.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:78c32709e5627ff8a2c9f2d2d7dd1b457474e0c536f6c2e125f36cd1bc042e03 3 | size 199936 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_oomkill.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1b242015fa4ae88aad6a8cf3786e58d5a415bff25aa8c0a34df0ab0e6b75c8df 3 | size 133416 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_process.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e2ea9c6047cae3f89623bae2feada1cbbbc24c67aec5ef0b7221c5843b35bd97 3 | size 172520 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_shm.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4e2c0b6aef1a5e5960b43fddc108f2e0606c9808ec9c991c3ec118868f862169 3 | size 115072 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_socket.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:36e5c9673f6e2122cbd047ff286ec0f7eb9998de33a94da08fc2d44cc3fe3316 3 | size 455560 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_softirq.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:caa418cfd25a1b9836d9487707f1846d3432226f68917f115e81e5be86823ed4 3 | size 136376 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_swap.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5c349beda4075b8e7fe6a25b45e8b0756b50e7c6efc1af09191a92daa04cf2ea 3 | size 99632 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_sync.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9598734c78dc27dc3cff5980c226d186c61bad0b6ea0f47cb1ce51477f631969 3 | size 80792 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_syncfs.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3bcc96642cb0881d5271a09fa35616801a940a046aff5f10e5ff70bbffe21a70 3 | size 81016 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_vfs.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:41743c2ffbb44d169fd1016da181348e9e5fa66316cd65c8e4c5bad268b662bb 3 | size 228728 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_xfs.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:dfc139b94e244faf5ce2d8311c36e95cc8b57fb655a7d27e34ce918a090419f2 3 | size 198880 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_zfs.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0f0e2de062593d1646d2cea4de2dd7b99e3843cd33957b28dbcae102a4a01a90 3 | size 191880 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_cachestat.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:233aede81c588ba9ee616957067514247cbcf210068885a8751dcf1fcf599573 3 | size 116464 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_fdatasync.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:933b830fcd7b8a368640e1f51a7731e341b7441acbb3dea102cee4a7034e52af 3 | size 80824 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_cachestat.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:233aede81c588ba9ee616957067514247cbcf210068885a8751dcf1fcf599573 3 | size 116464 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_fdatasync.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:933b830fcd7b8a368640e1f51a7731e341b7441acbb3dea102cee4a7034e52af 3 | size 80824 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_network_viewer.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:02eb5d5de0292e857f8bc56ce26ee4b88cc6287c119fd59ace2ad707b399aa1b 3 | size 530952 4 | -------------------------------------------------------------------------------- /CentOS7/pnetdata_ebpf_sync_file_range.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:081a503dc2540aa7c27e7248c7b551fb44291ddc151b6cd8e882a4739bfc5041 3 | size 80832 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_network_viewer.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:02eb5d5de0292e857f8bc56ce26ee4b88cc6287c119fd59ace2ad707b399aa1b 3 | size 530952 4 | -------------------------------------------------------------------------------- /CentOS7/rnetdata_ebpf_sync_file_range.3.10.rhf.o: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:081a503dc2540aa7c27e7248c7b551fb44291ddc151b6cd8e882a4739bfc5041 3 | size 80832 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.bak 3 | *.log 4 | 5 | *.tar.* 6 | *.tar 7 | 8 | *.ll 9 | *.o* 10 | !CentOS7/*.o* 11 | 12 | *.skel.h 13 | *.a 14 | 15 | kernel/legacy_test 16 | .local_libbpf/bpf 17 | .local_libbpf/pkgconfig 18 | 19 | -------------------------------------------------------------------------------- /includes/netdata_mdflush.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_MDFLUSH_H_ 4 | #define _NETDATA_MDFLUSH_H_ 1 5 | 6 | typedef dev_t mdflush_key_t; 7 | typedef u64 mdflush_val_t; 8 | 9 | #endif /* _NETDATA_MDFLUSH_H_ */ 10 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 2 3 | updates: 4 | - package-ecosystem: github-actions 5 | directory: / 6 | schedule: 7 | interval: weekly 8 | 9 | - package-ecosystem: docker 10 | directory: / 11 | schedule: 12 | interval: weekly 13 | -------------------------------------------------------------------------------- /includes/netdata_sync.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_SYNC_H_ 4 | #define _NETDATA_SYNC_H_ 1 5 | 6 | enum sync_counters { 7 | NETDATA_KEY_SYNC_CALL, 8 | 9 | // Keep this as last and don't skip numbers as it is used as element counter 10 | NETDATA_SYNC_END 11 | }; 12 | 13 | #endif /* _NETDATA_SYNC_H_ */ 14 | -------------------------------------------------------------------------------- /includes/netdata_mount.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_MOUNT_H_ 4 | #define _NETDATA_MOUNT_H_ 1 5 | 6 | enum mount_counters { 7 | NETDATA_KEY_MOUNT_CALL, 8 | NETDATA_KEY_UMOUNT_CALL, 9 | NETDATA_KEY_MOUNT_ERROR, 10 | NETDATA_KEY_UMOUNT_ERROR, 11 | 12 | NETDATA_MOUNT_END 13 | }; 14 | 15 | #endif /* _NETDATA_MOUNT_H_ */ 16 | 17 | -------------------------------------------------------------------------------- /kernel-patches/README.md: -------------------------------------------------------------------------------- 1 | # Kernel Patches 2 | 3 | For some Linux kernels that are not LTS and are used on distributions like 4 | Ubuntu, eBPF programs cannot be compiled cleanly. It is necessary to apply some 5 | patches on these kernels in order to use them. 6 | 7 | The structure of our Dockerfile forces us to have a directory for every kernel 8 | that we are compiling for, even if a patch is not needed. If you'd like to add 9 | a new kernel version, please make the directory here as well and insert an 10 | empty `.gitkeep` file. 11 | -------------------------------------------------------------------------------- /.dockerfiles/patch_kernel.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | srcdir="${1:-/usr/src/linux}" 6 | 7 | cd "${srcdir}" || exit 8 | 9 | if [ ! -d /usr/src/linux-"${KERNEL_VERSION}"-patches ]; then 10 | echo >&2 " No patches found for ${KERNEL_VERSION}" 11 | exit 0 12 | fi 13 | 14 | for patch in /usr/src/linux-"${KERNEL_VERSION}"-patches/*.diff.gz; do 15 | printf >&2 " Patching linux-%s with %s ... " "${KERNEL_VERSION}" "${patch}" 16 | if zcat < "${patch}" | patch -p 1; then 17 | echo >&2 " OK" 18 | else 19 | echo >&2 " ERR" 20 | fi 21 | done 22 | -------------------------------------------------------------------------------- /.chglog/CHANGELOG.tpl.md: -------------------------------------------------------------------------------- 1 | {{ range .Versions }} 2 | 3 | ## {{ if .Tag.Previous }}[{{ .Tag.Name }}]({{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}){{ else }}{{ .Tag.Name }}{{ end }} ({{ datetime "2006-01-02" .Tag.Date }}) 4 | 5 | {{ range .CommitGroups -}} 6 | ### {{ .Title }} 7 | 8 | {{ range .Commits -}} 9 | * {{ .Subject }} 10 | {{ end }} 11 | {{ end -}} 12 | 13 | {{- if .NoteGroups -}} 14 | {{ range .NoteGroups -}} 15 | ### {{ .Title }} 16 | 17 | {{ range .Notes }} 18 | {{ .Body }} 19 | {{ end }} 20 | {{ end -}} 21 | {{ end -}} 22 | {{ end -}} -------------------------------------------------------------------------------- /includes/netdata_oomkill.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_OOMKILL_H_ 4 | #define _NETDATA_OOMKILL_H_ 1 5 | 6 | // to try and only use 4096 bytes in the map and no more given 4 byte keys & 1 7 | // byte values, we choose a very small number. 8 | #define NETDATA_OOMKILL_MAX_ENTRIES 64 9 | 10 | // /sys/kernel/debug/tracing/events/oom/mark_victim/ 11 | struct netdata_oom_mark_victim_entry { 12 | u64 pad; // This is not used with eBPF 13 | int pid; // offset:8; size:4; signed:1; 14 | }; 15 | 16 | #endif /* _NETDATA_OOMKILL_H_ */ 17 | -------------------------------------------------------------------------------- /includes/netdata_asm_goto.h: -------------------------------------------------------------------------------- 1 | #ifndef _NETDATA_ASM_GOTO_H_ 2 | # define _NETDATA_ASM_GOTO_H_ 1 3 | 4 | /* 5 | This header allows us to compile our code on RH 7.x family. 6 | */ 7 | 8 | # include 9 | # include 10 | 11 | # ifndef RHEL_RELEASE_VERSION 12 | # define RHEL_RELEASE_VERSION(x,y) ((x << 8) + (y)) 13 | # endif 14 | 15 | # if RHEL_RELEASE_CODE && \ 16 | RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,0) 17 | # ifdef asm_volatile_goto 18 | # undef asm_volatile_goto 19 | # define asm_volatile_goto(x...) asm volatile("invalid use of asm_volatile_goto") 20 | # endif 21 | # endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /includes/netdata_swap.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_SWAP_H_ 4 | #define _NETDATA_SWAP_H_ 1 5 | 6 | typedef struct netdata_swap_access { 7 | __u64 ct; 8 | __u32 tgid; 9 | __u32 uid; 10 | __u32 gid; 11 | char name[TASK_COMM_LEN]; 12 | 13 | __u32 read; 14 | __u32 write; 15 | } netdata_swap_access_t; 16 | 17 | enum swap_counters { 18 | NETDATA_KEY_SWAP_READPAGE_CALL, 19 | NETDATA_KEY_SWAP_WRITEPAGE_CALL, 20 | 21 | // Keep this as last and don't skip numbers as it is used as element counter 22 | NETDATA_SWAP_END 23 | }; 24 | 25 | #endif /* _NETDATA_SWAP_H_ */ 26 | -------------------------------------------------------------------------------- /.chglog/config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | style: github 3 | template: CHANGELOG.tpl.md 4 | info: 5 | title: CHANGELOG 6 | repository_url: https://github.com/netdata/kernel-collector 7 | options: 8 | commits: 9 | filters: 10 | Type: 11 | - Add 12 | - Fix 13 | - Document 14 | - Refactor 15 | commit_groups: 16 | title_maps: 17 | Add: Features 18 | Fix: Bug Fixes 19 | Document: Documentation 20 | refactor: Code Refactoring 21 | header: 22 | pattern: "^((\\w+)\\s.*)$" 23 | pattern_maps: 24 | - Subject 25 | - Type 26 | notes: 27 | keywords: 28 | - BREAKING CHANGE 29 | -------------------------------------------------------------------------------- /.yamllint.yml: -------------------------------------------------------------------------------- 1 | --- 2 | yaml-files: 3 | - '*.yaml' 4 | - '*.yml' 5 | - '.yamllint' 6 | 7 | rules: 8 | braces: enable 9 | brackets: enable 10 | colons: enable 11 | commas: enable 12 | comments: disable 13 | comments-indentation: disable 14 | document-end: disable 15 | document-start: 16 | level: warning 17 | empty-lines: enable 18 | empty-values: disable 19 | hyphens: enable 20 | indentation: enable 21 | key-duplicates: enable 22 | key-ordering: disable 23 | line-length: disable 24 | new-line-at-end-of-file: enable 25 | new-lines: enable 26 | octal-values: enable 27 | quoted-strings: disable 28 | trailing-spaces: enable 29 | truthy: disable 30 | -------------------------------------------------------------------------------- /includes/netdata_shm.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_SHM_H_ 4 | #define _NETDATA_SHM_H_ 1 5 | 6 | typedef struct netdata_shm { 7 | __u64 ct; 8 | __u32 tgid; 9 | __u32 uid; 10 | __u32 gid; 11 | char name[TASK_COMM_LEN]; 12 | 13 | __u32 get; 14 | __u32 at; 15 | __u32 dt; 16 | __u32 ctl; 17 | } netdata_shm_t; 18 | 19 | enum shm_counters { 20 | NETDATA_KEY_SHMGET_CALL, 21 | NETDATA_KEY_SHMAT_CALL, 22 | NETDATA_KEY_SHMDT_CALL, 23 | NETDATA_KEY_SHMCTL_CALL, 24 | 25 | // Keep this as last and don't skip numbers as it is used as element counter 26 | NETDATA_SHM_END 27 | }; 28 | 29 | #endif /* _NETDATA_SHM_H_ */ 30 | -------------------------------------------------------------------------------- /tools/README.md: -------------------------------------------------------------------------------- 1 | # Tools 2 | 3 | This directory contains scripts used to check if the kernel is valid for the 4 | purpose of compiling our eBPF programs, and also for compiling a kernel which 5 | is compatible. 6 | 7 | ## check-kernel-config.sh 8 | 9 | This script is necessary for use to check whether your kernel's configuration 10 | is correct for running eBPF programs. 11 | 12 | ## check-kernel-core.sh 13 | 14 | This script is necessary for use to check whether your kernel's configuration 15 | is correct for running eBPF programs using CO-RE technology. 16 | 17 | ## build-ebpf-kernel.sh 18 | 19 | This script attempts to build a kernel image that has its configuration setup 20 | to run our eBPF programs. 21 | -------------------------------------------------------------------------------- /.dockerfiles/change_libbpf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | KMAJOR= 4 | KMINOR= 5 | 6 | if [ -z "$1" ] || [ -z "$2" ]; then 7 | VER=$(uname -r) 8 | KMAJOR=$(echo "${VER}" | cut -d. -f1) 9 | KMINOR=$(echo "${VER}" | cut -d. -f2) 10 | echo "Kernel parameters not given, we will use dist values ${KMAJOR}.${KMINOR}" 11 | else 12 | KMAJOR="${1}" 13 | KMINOR="${2}" 14 | fi 15 | 16 | parse_kernel_version() { 17 | R="${1}.${2}" 18 | 19 | read -r -a P <<< "$(echo "${R}" | tr '.' ' ')" 20 | 21 | printf "%03d%03d" "${P[0]}" "${P[1]}" 22 | } 23 | 24 | KVER=$(parse_kernel_version "${KMAJOR}" "${KMINOR}") 25 | 26 | VER3_10_0="003010" 27 | 28 | if [ "${KVER}" -eq "${VER3_10_0}" ]; then 29 | git checkout netdata-patch 30 | fi 31 | -------------------------------------------------------------------------------- /docs/centos.md: -------------------------------------------------------------------------------- 1 | # CentOS 2 | 3 | Our eBPF programs are designed to support down to CentOS 7. 4 | 5 | Note that CentOS 7 uses Linux 3.10, and supports eBPF via backporting the code 6 | for it to their distribution's kernel fork. 7 | 8 | This introduces some complexities in dealing with the eBPF verifier, as it may 9 | behave very differently than on the latest kernels for some code, and reject 10 | it. 11 | 12 | For this reason it is strongly advised to create a VM for CentOS 7 and test 13 | whether the verifier will accept your programs on that platform. 14 | 15 | ## Setting up CentOS 7 16 | 17 | Setting up the environment inside the VM is nearly exactly the same as that 18 | used in the `Dockerfile.glibc.centos7`. 19 | 20 | When you run any compilation commands with `make`, you must ensure `make` uses 21 | the correct LLVM toolset as well. 22 | -------------------------------------------------------------------------------- /includes/netdata_cache.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_CACHE_H_ 4 | #define _NETDATA_CACHE_H_ 1 5 | 6 | typedef struct netdata_cachestat { 7 | __u64 ct; 8 | __u32 tgid; 9 | __u32 uid; 10 | __u32 gid; 11 | char name[TASK_COMM_LEN]; 12 | 13 | __u32 add_to_page_cache_lru; 14 | __u32 mark_page_accessed; 15 | __u32 account_page_dirtied; 16 | __u32 mark_buffer_dirty; 17 | } netdata_cachestat_t; 18 | 19 | enum cachestat_counters { 20 | NETDATA_KEY_CALLS_ADD_TO_PAGE_CACHE_LRU, 21 | NETDATA_KEY_CALLS_MARK_PAGE_ACCESSED, 22 | NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED, 23 | NETDATA_KEY_CALLS_MARK_BUFFER_DIRTY, 24 | 25 | // Keep this as last and don't skip numbers as it is used as element counter 26 | NETDATA_CACHESTAT_END 27 | }; 28 | 29 | #endif /* _NETDATA_CACHE_H_ */ 30 | -------------------------------------------------------------------------------- /includes/netdata_dc.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_DIRECTORY_CACHE_H_ 4 | #define _NETDATA_DIRECTORY_CACHE_H_ 1 5 | 6 | typedef struct netdata_dc_stat { 7 | __u64 ct; 8 | __u32 tgid; 9 | __u32 uid; 10 | __u32 gid; 11 | char name[TASK_COMM_LEN]; 12 | 13 | __u32 references; 14 | __u32 slow; 15 | __u32 missed; 16 | } netdata_dc_stat_t; 17 | 18 | enum directory_cache_counters { 19 | NETDATA_KEY_DC_REFERENCE, 20 | NETDATA_KEY_DC_SLOW, 21 | NETDATA_KEY_DC_MISS, 22 | 23 | // Keep this as last and don't skip numbers as it is used as element counter 24 | NETDATA_DIRECTORY_CACHE_END 25 | }; 26 | 27 | enum directory_cachec_functions { 28 | NETDATA_LOOKUP_FAST, 29 | NETDATA_D_LOOKUP, 30 | 31 | NETDATA_DC_COUNTER 32 | }; 33 | 34 | #endif /* _NETDATA_DIRECTORY_CACHE_H_ */ 35 | 36 | -------------------------------------------------------------------------------- /includes/netdata_ebpf.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_EBPF_ 4 | #define _NETDATA_EBPF_ 1 5 | 6 | /* 7 | The main header. 8 | 9 | This header has the common definitions for all `.c` files. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "netdata_common.h" 17 | #include "netdata_cache.h" 18 | #include "netdata_dc.h" 19 | #include "netdata_disk.h" 20 | #include "netdata_fd.h" 21 | #include "netdata_fs.h" 22 | #include "netdata_hardirq.h" 23 | #include "netdata_mdflush.h" 24 | #include "netdata_mount.h" 25 | #include "netdata_oomkill.h" 26 | #include "netdata_process.h" 27 | #include "netdata_shm.h" 28 | #include "netdata_socket.h" 29 | #include "netdata_softirq.h" 30 | #include "netdata_sync.h" 31 | #include "netdata_swap.h" 32 | #include "netdata_vfs.h" 33 | 34 | #endif /* _NETDATA_EBPF_ */ 35 | 36 | -------------------------------------------------------------------------------- /docs/compiling.md: -------------------------------------------------------------------------------- 1 | # Compiling 2 | 3 | ## 1. Package Installs 4 | 5 | Before compiling this repository, you have to install necessary packages 6 | available on your Linux distribution. The complete list of packages can be 7 | found inside the Docker files in this repository. 8 | 9 | ## 2. Linux Source Code Directory 10 | 11 | Also, if your distribution does not create the symlink `/usr/src/linux`, 12 | pointing to the latest Linux source code of your current live kernel, you 13 | should make one now. 14 | 15 | ## 3. Disabling Inline Assembly 16 | 17 | In case you are trying to compile on a kernel newer than `5.0`, it will be 18 | necessary to disable the `assembly inline` option; this can be done by editing 19 | the file `/usr/src/linux/include/generated/autoconf.h` and commenting the line 20 | `//#define CONFIG_CC_HAS_ASM_INLINE 1`. 21 | 22 | ## 4. Compile 23 | 24 | Now you can simply run `make`: 25 | 26 | ```bash 27 | $ make -j`nproc` 28 | ``` 29 | -------------------------------------------------------------------------------- /includes/netdata_defs.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_DEFS_ 4 | #define _NETDATA_DEFS_ 1 5 | 6 | enum netdata_controller { 7 | NETDATA_CONTROLLER_APPS_ENABLED, 8 | NETDATA_CONTROLLER_APPS_LEVEL, 9 | 10 | // These index show the number of elements 11 | // stored inside hash tables. 12 | // 13 | // We have indexes to count increase and 14 | // decrease events, because __sync_fetch_and_sub 15 | // generates compilatoion errors. 16 | NETDATA_CONTROLLER_PID_TABLE_ADD, 17 | NETDATA_CONTROLLER_PID_TABLE_DEL, 18 | NETDATA_CONTROLLER_TEMP_TABLE_ADD, 19 | NETDATA_CONTROLLER_TEMP_TABLE_DEL, 20 | 21 | NETDATA_CONTROLLER_END 22 | }; 23 | 24 | enum netdata_apps_level { 25 | NETDATA_APPS_LEVEL_REAL_PARENT, 26 | NETDATA_APPS_LEVEL_PARENT, 27 | NETDATA_APPS_LEVEL_ALL, 28 | NETDATA_APPS_LEVEL_IGNORE, 29 | 30 | NETDATA_APPS_LEVEL_END 31 | }; 32 | 33 | #endif 34 | 35 | -------------------------------------------------------------------------------- /includes/netdata_fd.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_EBPF_FD_H_ 4 | #define _NETDATA_EBPF_FD_H_ 1 5 | 6 | struct netdata_fd_stat_t { 7 | __u64 ct; 8 | __u32 tgid; 9 | __u32 uid; 10 | __u32 gid; 11 | char name[TASK_COMM_LEN]; 12 | 13 | //Counter 14 | __u32 open_call; //open syscalls (open and openat) 15 | __u32 close_call; //Close syscall (close) 16 | 17 | //Counter 18 | __u32 open_err; 19 | __u32 close_err; 20 | }; 21 | 22 | enum fd_counters { 23 | NETDATA_KEY_CALLS_DO_SYS_OPEN, 24 | NETDATA_KEY_ERROR_DO_SYS_OPEN, 25 | 26 | NETDATA_KEY_CALLS_CLOSE_FD, 27 | NETDATA_KEY_ERROR_CLOSE_FD, 28 | 29 | // Keep this as last and don't skip numbers as it is used as element counter 30 | NETDATA_FD_COUNTER 31 | }; 32 | 33 | enum fd_actions { 34 | NETDATA_FD_OPEN, 35 | NETDATA_FD_CLOSE, 36 | 37 | NETDATA_FD_ACTIONS 38 | }; 39 | 40 | #endif /* _NETDATA_EBPF_FD_H_ */ 41 | 42 | -------------------------------------------------------------------------------- /Dockerfile.musl.generic: -------------------------------------------------------------------------------- 1 | FROM alpine:3.22 AS build 2 | 3 | ARG ARCH=x86 4 | ENV ARCH=$ARCH 5 | 6 | ARG KERNEL_VERSION=5.4.20 7 | ENV KERNEL_VERSION=$KERNEL_VERSION 8 | 9 | ENV _LIBC=musl 10 | 11 | # hadolint ignore=DL3018 12 | RUN apk add --no-cache -U build-base autoconf automake coreutils pkgconfig \ 13 | bc elfutils-dev openssl-dev clang clang-dev llvm \ 14 | rsync bison flex tar xz bash linux-headers 15 | 16 | # hadolint ignore=DL3003,SC3009 17 | RUN mkdir -p /usr/src && \ 18 | cd /usr/src && \ 19 | wget -q https://cdn.kernel.org/pub/linux/kernel/v$(echo "$KERNEL_VERSION" | cut -f 1 -d '.').x/linux-${KERNEL_VERSION}.tar.xz && \ 20 | tar -xf linux-${KERNEL_VERSION}.tar.xz && \ 21 | ln -s linux-${KERNEL_VERSION} linux && \ 22 | ln -s /usr/lib/gcc/x86_64-alpine-linux-musl/14.2.0/include/stdarg.h /usr/src/linux/include/ 23 | 24 | WORKDIR /kernel-collector 25 | 26 | COPY .dockerfiles/build.sh /build.sh 27 | COPY . . 28 | 29 | CMD ["/build.sh"] 30 | -------------------------------------------------------------------------------- /Dockerfile.static.generic: -------------------------------------------------------------------------------- 1 | FROM alpine:3.22 AS build 2 | 3 | ARG ARCH=x86 4 | ENV ARCH=$ARCH 5 | 6 | ARG KERNEL_VERSION=5.4.20 7 | ENV KERNEL_VERSION=$KERNEL_VERSION 8 | 9 | ENV _LIBC=static 10 | 11 | # hadolint ignore=DL3018 12 | RUN apk add --no-cache -U build-base autoconf automake coreutils pkgconfig \ 13 | bc elfutils-dev openssl-dev clang clang-dev llvm \ 14 | rsync bison flex tar xz bash linux-headers 15 | 16 | # hadolint ignore=DL3003,SC3009 17 | RUN mkdir -p /usr/src && \ 18 | cd /usr/src && \ 19 | wget -q https://cdn.kernel.org/pub/linux/kernel/v$(echo "$KERNEL_VERSION" | cut -f 1 -d '.').x/linux-${KERNEL_VERSION}.tar.xz && \ 20 | tar -xf linux-${KERNEL_VERSION}.tar.xz && \ 21 | ln -s linux-${KERNEL_VERSION} linux && \ 22 | ln -s /usr/lib/gcc/x86_64-alpine-linux-musl/14.2.0/include/stdarg.h /usr/src/linux/include/ 23 | 24 | WORKDIR /kernel-collector 25 | 26 | COPY .dockerfiles/build.sh /build.sh 27 | COPY . . 28 | 29 | CMD ["/build.sh"] 30 | -------------------------------------------------------------------------------- /includes/netdata_fs.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_FS_H_ 4 | #define _NETDATA_FS_H_ 1 5 | 6 | enum fs_counters { 7 | NETDATA_KEY_CALLS_READ, 8 | NETDATA_KEY_CALLS_WRITE, 9 | NETDATA_KEY_CALLS_OPEN, 10 | NETDATA_KEY_CALLS_SYNC, 11 | 12 | NETDATA_FS_END 13 | }; 14 | 15 | enum fs_btf_counters { 16 | NETDATA_KEY_BTF_READ, 17 | NETDATA_KEY_BTF_WRITE, 18 | NETDATA_KEY_BTF_OPEN, 19 | NETDATA_KEY_BTF_SYNC_ATTR, 20 | NETDATA_KEY_BTF_OPEN2, 21 | 22 | NETDATA_FS_BTF_END 23 | }; 24 | 25 | // We are using 24 as hard limit to avoid intervals bigger than 26 | // 8 seconds and to keep memory aligment. 27 | #define NETDATA_FS_MAX_BINS 24UL 28 | #define NETDATA_FS_MAX_TABLES 4UL 29 | #define NETDATA_FS_MAX_ELEMENTS (NETDATA_FS_MAX_BINS * NETDATA_FS_MAX_TABLES) 30 | #define NETDATA_FS_MAX_BINS_POS (NETDATA_FS_MAX_BINS - 1) 31 | #define NETDATA_FS_HISTOGRAM_LENGTH (NETDATA_FS_MAX_BINS * NETDATA_FS_MAX_BINS) 32 | 33 | 34 | #endif /* _NETDATA_FS_H_ */ 35 | 36 | -------------------------------------------------------------------------------- /includes/netdata_softirq.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_SOFTIRQ_H_ 4 | #define _NETDATA_SOFTIRQ_H_ 1 5 | 6 | #define NETDATA_SOFTIRQ_MAX_IRQS 10 7 | 8 | // /sys/kernel/debug/tracing/events/irq/softirq_entry 9 | struct netdata_softirq_entry { 10 | u64 pad; // This is not used with eBPF 11 | u32 vec; // offset:8; size:4; signed:0; 12 | }; 13 | 14 | // /sys/kernel/debug/tracing/events/irq/softirq_exit 15 | struct netdata_softirq_exit { 16 | u64 pad; // This is not used with eBPF 17 | u32 vec; // offset:8; size:4; signed:0; 18 | }; 19 | 20 | typedef struct softirq_val { 21 | // incremental counter storing the total latency so far. 22 | u64 latency; 23 | 24 | // temporary timestamp stored at the entry handler, to be diff'd with a 25 | // timestamp at the exit handler, to get the latency to add to the 26 | // `latency` field. 27 | u64 ts; 28 | } softirq_val_t; 29 | 30 | #endif /* _NETDATA_SOFTIRQ_H_ */ 31 | -------------------------------------------------------------------------------- /tools/complement.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | parse_kernel_version() { 4 | r="${1}" 5 | 6 | read -r -a p <<< "$(echo "${r}" | tr '.' ' ')" 7 | 8 | printf "%03d%03d%03d" "${p[0]}" "${p[1]}" "${p[2]}" 9 | } 10 | 11 | first_kernel() { 12 | kver=$(parse_kernel_version "${1}") 13 | 14 | ver5_10_0="005010000" 15 | ver5_11_0="005011000" 16 | ver4_18_0="004018000" 17 | ver4_17_0="004017000" 18 | ver4_15_0="004015000" 19 | ver4_11_0="004011000" 20 | ver3_10_0="003010000" 21 | 22 | if [ "${kver}" -eq "${ver3_10_0}" ]; then 23 | kpkg="3.10"; 24 | elif [ "${kver}" -eq "${ver4_18_0}" ]; then 25 | kpkg="4.18"; 26 | elif [ "${kver}" -ge "${ver5_11_0}" ]; then 27 | kpkg="5.11"; 28 | elif [ "${kver}" -ge "${ver5_10_0}" ]; then 29 | kpkg="5.10"; 30 | elif [ "${kver}" -ge "${ver4_17_0}" ]; then 31 | kpkg="4.17"; 32 | elif [ "${kver}" -ge "${ver4_15_0}" ]; then 33 | kpkg="4.15"; 34 | elif [ "${kver}" -ge "${ver4_11_0}" ]; then 35 | kpkg="4.11"; 36 | fi 37 | 38 | echo "${kpkg}" 39 | } 40 | 41 | first_kernel "${1}" 42 | -------------------------------------------------------------------------------- /Dockerfile.glibc.generic: -------------------------------------------------------------------------------- 1 | FROM ubuntu:24.04 AS build 2 | 3 | ARG ARCH=x86 4 | ENV ARCH=$ARCH 5 | 6 | ARG KERNEL_VERSION=5.4.20 7 | ENV KERNEL_VERSION=$KERNEL_VERSION 8 | 9 | ENV _LIBC=glibc 10 | 11 | ENV DEBIAN_FRONTEND=noninteractive 12 | RUN apt-get update && \ 13 | apt-get install -y build-essential autoconf automake coreutils pkg-config \ 14 | bc libelf-dev libssl-dev clang-tools-18 libclang-18-dev \ 15 | clang-18 llvm-18 rsync bison flex tar xz-utils wget 16 | 17 | RUN mkdir -p /usr/src && \ 18 | cd /usr/src && \ 19 | wget -q https://cdn.kernel.org/pub/linux/kernel/v$(echo "$KERNEL_VERSION" | cut -f 1 -d '.').x/linux-${KERNEL_VERSION}.tar.xz && \ 20 | tar -xf linux-${KERNEL_VERSION}.tar.xz && \ 21 | ln -s linux-${KERNEL_VERSION} linux 22 | 23 | COPY kernel-patches/${KERNEL_VERSION} /usr/src/linux-${KERNEL_VERSION}-patches 24 | COPY .dockerfiles/patch_kernel.sh /patch_kernel.sh 25 | RUN /patch_kernel.sh 26 | 27 | ENV PATH=/usr/lib/llvm-18/bin:$PATH 28 | 29 | WORKDIR /kernel-collector 30 | 31 | COPY .dockerfiles/build.sh /build.sh 32 | COPY . . 33 | 34 | CMD ["/build.sh"] 35 | -------------------------------------------------------------------------------- /.dockerfiles/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | build() { 6 | echo "[XXX]: Preparing kernel headers for ${KERNEL_VERSION}..." 7 | ( 8 | if [ "${KERNEL_VERSION}" != "3.10.0-1160.108.1.el7" ]; then 9 | make defconfig -C /usr/src/linux 10 | else 11 | make silentoldconfig -C /usr/src/linux 12 | fi 13 | make scripts -C /usr/src/linux 14 | make prepare -C /usr/src/linux 15 | make headers_install -C /usr/src/linux 16 | ) || return 1 17 | echo "[XXX]: Building against Kernel ${KERNEL_VERSION} for libc ${_LIBC} ..." 18 | ( 19 | if [ "${DEBUG:-0}" -eq 1 ]; then 20 | echo "[XXX]: Building with debug symbols ..." 21 | make CFLAGS='-fno-stack-protector -I /usr/src/linux/usr/include' EXTRA_CFLAGS='-g -fno-stack-protector' 22 | else 23 | make CFLAGS='-fno-stack-protector -I /usr/src/linux/usr/include' 24 | fi 25 | ) || return 1 26 | } 27 | 28 | _main() { 29 | if ! build; then 30 | echo "ERROR: Build failed ..." 31 | if [ -t 1 ]; then 32 | echo "Dropping into a shell ..." 33 | exec /bin/sh 34 | else 35 | exit 1 36 | fi 37 | fi 38 | } 39 | 40 | if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then 41 | _main "$@" 42 | fi 43 | -------------------------------------------------------------------------------- /Dockerfile.musl.centos8: -------------------------------------------------------------------------------- 1 | FROM alpine:3.22 AS build 2 | 3 | ARG ARCH=x86 4 | ENV ARCH=$ARCH 5 | 6 | ARG LOCAL_KERNEL_VERSION=4.18.0-372.16.1.el8_6 7 | 8 | ENV _LIBC=static 9 | 10 | # hadolint ignore=DL3018 11 | RUN apk add --no-cache -U build-base autoconf automake coreutils pkgconfig \ 12 | bc elfutils-dev openssl-dev clang clang-dev llvm \ 13 | rsync bison flex tar xz bash rpm ssl_client linux-headers 14 | 15 | # hadolint ignore=DL3003,SC3009 16 | RUN mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} && \ 17 | echo "%_topdir %(echo $HOME)/rpmbuild" > ~/.rpmmacros && \ 18 | wget -q https://repo.almalinux.org/vault/8.6/BaseOS/Source/Packages/kernel-${LOCAL_KERNEL_VERSION}.src.rpm && \ 19 | rpm -i kernel-${LOCAL_KERNEL_VERSION}.src.rpm && \ 20 | cd ~/rpmbuild/SOURCES && \ 21 | tar -xf linux-${LOCAL_KERNEL_VERSION}.tar.xz && \ 22 | mkdir -p /usr/src/kernels && \ 23 | cd /usr/src && \ 24 | ln -s ~/rpmbuild/SOURCES/linux-${LOCAL_KERNEL_VERSION} linux && \ 25 | ln -s /usr/lib/gcc/x86_64-alpine-linux-musl/14.2.0/include/stdarg.h /usr/src/linux/include/ 26 | 27 | WORKDIR /kernel-collector 28 | 29 | COPY .dockerfiles/build.sh /build.sh 30 | COPY . . 31 | 32 | CMD ["/build.sh"] 33 | -------------------------------------------------------------------------------- /Dockerfile.musl.centos9: -------------------------------------------------------------------------------- 1 | FROM alpine:3.22 AS build 2 | 3 | ARG ARCH=x86 4 | ENV ARCH=$ARCH 5 | 6 | ARG LOCAL_KERNEL_VERSION=5.14.0-70.17.1.el9_0 7 | 8 | ENV _LIBC=static 9 | 10 | # hadolint ignore=DL3018 11 | RUN apk add --no-cache -U build-base autoconf automake coreutils pkgconfig \ 12 | bc elfutils-dev openssl-dev clang clang-dev llvm \ 13 | rsync bison flex tar xz bash rpm ssl_client linux-headers 14 | 15 | # hadolint ignore=DL3003,SC3009 16 | RUN mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} && \ 17 | echo "%_topdir %(echo $HOME)/rpmbuild" > ~/.rpmmacros && \ 18 | wget -q https://repo.almalinux.org/vault/9.0/BaseOS/Source/Packages/kernel-${LOCAL_KERNEL_VERSION}.src.rpm && \ 19 | rpm -i kernel-${LOCAL_KERNEL_VERSION}.src.rpm && \ 20 | cd ~/rpmbuild/SOURCES && \ 21 | tar -xf linux-${LOCAL_KERNEL_VERSION}.tar.xz && \ 22 | mkdir -p /usr/src/kernels && \ 23 | cd /usr/src && \ 24 | ln -s ~/rpmbuild/SOURCES/linux-${LOCAL_KERNEL_VERSION} linux && \ 25 | ln -s /usr/lib/gcc/x86_64-alpine-linux-musl/14.2.0/include/stdarg.h /usr/src/linux/include/ 26 | 27 | WORKDIR /kernel-collector 28 | 29 | COPY .dockerfiles/build.sh /build.sh 30 | COPY . . 31 | 32 | CMD ["/build.sh"] 33 | -------------------------------------------------------------------------------- /Dockerfile.static.centos8: -------------------------------------------------------------------------------- 1 | FROM alpine:3.22 AS build 2 | 3 | ARG ARCH=x86 4 | ENV ARCH=$ARCH 5 | 6 | ARG LOCAL_KERNEL_VERSION=4.18.0-372.16.1.el8_6 7 | 8 | ENV _LIBC=static 9 | 10 | # hadolint ignore=DL3018 11 | RUN apk add --no-cache -U build-base autoconf automake coreutils pkgconfig \ 12 | bc elfutils-dev openssl-dev clang clang-dev llvm \ 13 | rsync bison flex tar xz bash rpm ssl_client linux-headers 14 | 15 | # hadolint ignore=DL3003,SC3009 16 | RUN mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} && \ 17 | echo "%_topdir %(echo $HOME)/rpmbuild" > ~/.rpmmacros && \ 18 | wget -q https://repo.almalinux.org/vault/8.6/BaseOS/Source/Packages/kernel-${LOCAL_KERNEL_VERSION}.src.rpm && \ 19 | rpm -i kernel-${LOCAL_KERNEL_VERSION}.src.rpm && \ 20 | cd ~/rpmbuild/SOURCES && \ 21 | tar -xf linux-${LOCAL_KERNEL_VERSION}.tar.xz && \ 22 | mkdir -p /usr/src/kernels && \ 23 | cd /usr/src && \ 24 | ln -s ~/rpmbuild/SOURCES/linux-${LOCAL_KERNEL_VERSION} linux && \ 25 | ln -s /usr/lib/gcc/x86_64-alpine-linux-musl/14.2.0/include/stdarg.h /usr/src/linux/include/ 26 | 27 | WORKDIR /kernel-collector 28 | 29 | COPY .dockerfiles/build.sh /build.sh 30 | COPY . . 31 | 32 | CMD ["/build.sh"] 33 | -------------------------------------------------------------------------------- /Dockerfile.static.centos9: -------------------------------------------------------------------------------- 1 | FROM alpine:3.22 AS build 2 | 3 | ARG ARCH=x86 4 | ENV ARCH=$ARCH 5 | 6 | ARG LOCAL_KERNEL_VERSION=5.14.0-70.17.1.el9_0 7 | 8 | ENV _LIBC=static 9 | 10 | # hadolint ignore=DL3018 11 | RUN apk add --no-cache -U build-base autoconf automake coreutils pkgconfig \ 12 | bc elfutils-dev openssl-dev clang clang-dev llvm \ 13 | rsync bison flex tar xz bash rpm ssl_client linux-headers 14 | 15 | # hadolint ignore=DL3003,SC3009 16 | RUN mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} && \ 17 | echo "%_topdir %(echo $HOME)/rpmbuild" > ~/.rpmmacros && \ 18 | wget -q https://repo.almalinux.org/vault/9.0/BaseOS/Source/Packages/kernel-${LOCAL_KERNEL_VERSION}.src.rpm && \ 19 | rpm -i kernel-${LOCAL_KERNEL_VERSION}.src.rpm && \ 20 | cd ~/rpmbuild/SOURCES && \ 21 | tar -xf linux-${LOCAL_KERNEL_VERSION}.tar.xz && \ 22 | mkdir -p /usr/src/kernels && \ 23 | cd /usr/src && \ 24 | ln -s ~/rpmbuild/SOURCES/linux-${LOCAL_KERNEL_VERSION} linux && \ 25 | ln -s /usr/lib/gcc/x86_64-alpine-linux-musl/14.2.0/include/stdarg.h /usr/src/linux/include/ 26 | 27 | WORKDIR /kernel-collector 28 | 29 | COPY .dockerfiles/build.sh /build.sh 30 | COPY . . 31 | 32 | CMD ["/build.sh"] 33 | -------------------------------------------------------------------------------- /Dockerfile.musl.oracle8: -------------------------------------------------------------------------------- 1 | FROM alpine:3.22 AS build 2 | 3 | ARG ARCH=x86 4 | ENV ARCH=$ARCH 5 | 6 | ARG LOCAL_KERNEL_VERSION=5.4.17 7 | 8 | ENV _LIBC=static 9 | 10 | # hadolint ignore=DL3018 11 | RUN apk add --no-cache -U build-base autoconf automake coreutils pkgconfig \ 12 | bc elfutils-dev openssl-dev clang clang-dev llvm \ 13 | rsync bison flex tar xz bash rpm ssl_client linux-headers 14 | 15 | # hadolint ignore=DL3003,SC3009 16 | RUN mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} && \ 17 | echo "%_topdir %(echo $HOME)/rpmbuild" > ~/.rpmmacros && \ 18 | wget -q https://oss.oracle.com/ol8/SRPMS-updates/kernel-uek-${LOCAL_KERNEL_VERSION}-2136.316.7.el8uek.src.rpm && \ 19 | rpm -i kernel-uek-${LOCAL_KERNEL_VERSION}-2136.316.7.el8uek.src.rpm && \ 20 | cd ~/rpmbuild/SOURCES && \ 21 | tar -xf linux-${LOCAL_KERNEL_VERSION}.tar.bz2 && \ 22 | mkdir -p /usr/src/kernels && \ 23 | cd /usr/src && \ 24 | ln -s ~/rpmbuild/SOURCES/linux-${LOCAL_KERNEL_VERSION} linux && \ 25 | ln -s /usr/lib/gcc/x86_64-alpine-linux-musl/14.2.0/include/stdarg.h /usr/src/linux/include/ 26 | 27 | WORKDIR /kernel-collector 28 | 29 | COPY .dockerfiles/build.sh /build.sh 30 | COPY . . 31 | 32 | CMD ["/build.sh"] 33 | -------------------------------------------------------------------------------- /Dockerfile.static.oracle8: -------------------------------------------------------------------------------- 1 | FROM alpine:3.22 AS build 2 | 3 | ARG ARCH=x86 4 | ENV ARCH=$ARCH 5 | 6 | ARG LOCAL_KERNEL_VERSION=5.4.17 7 | 8 | ENV _LIBC=static 9 | 10 | # hadolint ignore=DL3018 11 | RUN apk add --no-cache -U build-base autoconf automake coreutils pkgconfig \ 12 | bc elfutils-dev openssl-dev clang clang-dev llvm \ 13 | rsync bison flex tar xz bash rpm ssl_client linux-headers 14 | 15 | # hadolint ignore=DL3003,SC3009 16 | RUN mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} && \ 17 | echo "%_topdir %(echo $HOME)/rpmbuild" > ~/.rpmmacros && \ 18 | wget -q https://oss.oracle.com/ol8/SRPMS-updates/kernel-uek-${LOCAL_KERNEL_VERSION}-2136.316.7.el8uek.src.rpm && \ 19 | rpm -i kernel-uek-${LOCAL_KERNEL_VERSION}-2136.316.7.el8uek.src.rpm && \ 20 | cd ~/rpmbuild/SOURCES && \ 21 | tar -xf linux-${LOCAL_KERNEL_VERSION}.tar.bz2 && \ 22 | mkdir -p /usr/src/kernels && \ 23 | cd /usr/src && \ 24 | ln -s ~/rpmbuild/SOURCES/linux-${LOCAL_KERNEL_VERSION} linux && \ 25 | ln -s /usr/lib/gcc/x86_64-alpine-linux-musl/14.2.0/include/stdarg.h /usr/src/linux/include/ 26 | 27 | WORKDIR /kernel-collector 28 | 29 | COPY .dockerfiles/build.sh /build.sh 30 | COPY . . 31 | 32 | CMD ["/build.sh"] 33 | -------------------------------------------------------------------------------- /kernel/oomkill_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "oomkill_netdata" 2 | #include 3 | #include 4 | #include 5 | 6 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 7 | #include 8 | #else 9 | #include 10 | #endif 11 | #include "bpf_tracing.h" 12 | #include "bpf_helpers.h" 13 | #include "netdata_ebpf.h" 14 | 15 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 16 | struct { 17 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) 18 | __uint(type, BPF_MAP_TYPE_HASH); 19 | #else 20 | __uint(type, BPF_MAP_TYPE_PERCPU_HASH); 21 | #endif 22 | __type(key, int); 23 | __type(value, __u8); 24 | __uint(max_entries, NETDATA_OOMKILL_MAX_ENTRIES); 25 | } tbl_oomkill SEC(".maps"); 26 | #else 27 | struct bpf_map_def SEC("maps") tbl_oomkill = { 28 | .type = BPF_MAP_TYPE_HASH, 29 | .key_size = sizeof(int), 30 | .value_size = sizeof(__u8), 31 | .max_entries = NETDATA_OOMKILL_MAX_ENTRIES 32 | }; 33 | #endif 34 | 35 | SEC("tracepoint/oom/mark_victim") 36 | int netdata_oom_mark_victim(struct netdata_oom_mark_victim_entry *ptr) { 37 | int key = ptr->pid; 38 | u8 val = 0; 39 | bpf_map_update_elem(&tbl_oomkill, &key, &val, BPF_ANY); 40 | return 0; 41 | } 42 | 43 | char _license[] SEC("license") = "GPL"; 44 | -------------------------------------------------------------------------------- /tools/build-ebpf-kernel.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | log() { 4 | printf "%s\n" "${1}" 5 | } 6 | 7 | error() { 8 | log "ERROR: ${1}" 9 | } 10 | 11 | fail() { 12 | log "FATAL: ${1}" 13 | exit 1 14 | } 15 | 16 | debug() { 17 | log "Dropping into a shell for debugging ..." 18 | exec /bin/sh 19 | } 20 | 21 | config() { 22 | if grep "CONFIG_$2" .config; then 23 | sed -i "s|.*CONFIG_$2.*|CONFIG_$2=$1|" .config 24 | else 25 | echo "CONFIG_$2=$1" >> .config 26 | fi 27 | } 28 | 29 | if [ "$#" -eq 0 ]; then 30 | log "Usage: $(basename "$0") " 31 | exit 1 32 | fi 33 | 34 | REQUIRED_KERNEL_CONFIG="KPROBES KPROBES_ON_FTRACE HAVE_KPROBES HAVE_KPROBES_ON_FTRACE KPROBE_EVENTS PERF_EVENT HAVE_PERF_EVENT FTRACE BPF_SYSCALL" 35 | 36 | KERNEL_VERSION="${1}" 37 | shift 38 | 39 | test -d /usr/src || mkdir -p /usr/src 40 | cd /usr/src || exit 1 41 | if [ ! -f linux-"${KERNEL_VERSION}".tar.xz ]; then 42 | wget -q https://cdn.kernel.org/pub/linux/kernel/v"$(echo "$KERNEL_VERSION" | cut -f 1 -d '.')".x/linux-"${KERNEL_VERSION}".tar.xz 43 | fi 44 | if [ ! -d linux-"${KERNEL_VERSION}" ]; then 45 | tar -xf linux-"${KERNEL_VERSION}".tar.xz 46 | fi 47 | rm linux 48 | ln -s linux-"${KERNEL_VERSION}" linux 49 | 50 | cd /usr/src/linux || exit 1 51 | zcat /proc/config.gz > .config 52 | 53 | for required_kernel_config in ${REQUIRED_KERNEL_CONFIG}; do 54 | config y "${required_kernel_config}" 55 | done 56 | 57 | yes "" | make oldconfig 58 | 59 | make 60 | make modules_install 61 | 62 | cp arch/x86/boot/bzImage /boot/vmlinuz 63 | cp System.map /boot/System.map 64 | lilo 65 | -------------------------------------------------------------------------------- /kernel/README.md: -------------------------------------------------------------------------------- 1 | # eBPF Programs 2 | 3 | All of the legacy (i.e. non-CO-RE) eBPF programs belong in this directory. 4 | 5 | The following provides a short description for each of the `eBPF` programs we 6 | have: 7 | 8 | - `cachestat_kern.c`: provides Linux page cache monitoring. 9 | - `dc_kern.c`: provides Linux directory cache monitoring. 10 | - `disk_kern.c`: provides disk latency monitoring. 11 | - `ext4_kern.c`: provides ext4 monitoring. 12 | - `fdatasync_kern.c`: monitor calls for syscall `fdatasync`. 13 | - `fsync_kern.c`: monitor calls for syscall `fsync`. 14 | - `hardirq_kern.c`: provides hard interrupt (hard IRQ) latency monitoring. 15 | - `mdflush_kern.c`: monitor flushes at the md driver level. 16 | - `mount_kern.c`: monitor calls for syscalls `mount` and `umount`. 17 | - `msync_kern.c`: monitor calls for syscall `msync`. 18 | - `nfs_kern.c`: provides nfs monitoring. 19 | - `oomkill_kern.c`: provides info on which processes got OOM killed. 20 | - `process_kern.c`: provides process, file and VFS stats. 21 | - `shm_kern.c`: monitor calls for syscalls `shmget`, `shmat`, `shmdt` and `shmctl`. 22 | - `socket_kern.c`: provides network stats; 23 | - `softirq_kern.c`: provides software interrupt (soft IRQ) latency monitoring. 24 | - `swap_kern.c`: provides swap stats; 25 | - `sync_file_range_kern.c`: monitor calls for syscall `sync_file_range`. 26 | - `sync_kern.c`: monitor calls for syscall `sync`. 27 | - `syncfs_kern.c`: monitor calls for syscall `syncfs`. 28 | - `vfs_kern.c`: monitor Virtual Filesystem functions. 29 | - `xfs_kern.c`: provides XFS monitoring. 30 | - `zfs_kern.c`: provides ZFS monitoring. 31 | -------------------------------------------------------------------------------- /docs/kernel-vsn.md: -------------------------------------------------------------------------------- 1 | # Kernel version and eBPF program 2 | 3 | In the first versions of the `bpf()` syscall, the Linux kernel verified whether 4 | the eBPF programs that had `kprobe` were matching the kernel version, but when 5 | the kernel `5.0` was released they removed this check with the argument that it 6 | was [useless](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/kernel/bpf/syscall.c?h=v5.0&id=6c4fc209fcf9d27efbaa48368773e4d2bfbd59aa): 7 | 8 | > bpf: remove useless version check for prog load 9 | > Existing libraries and tracing frameworks work around this kernel 10 | > version check by automatically deriving the kernel version from 11 | > uname(3) or similar such that the user does not need to do it 12 | > manually; these workarounds also make the version check useless 13 | > at the same time. 14 | > 15 | > Moreover, most other BPF tracing types enabling `bpf_probe_read()`-like 16 | > functionality have /not/ adapted this check, and in general these 17 | > days it is well understood anyway that all the tracing programs are 18 | > not stable with regards to future kernels as kernel internal data 19 | > structures are subject to change from release to release. 20 | > 21 | > Back at last netconf we discussed [0] and agreed to remove this 22 | > check from `bpf_prog_load()` and instead document it here in the uapi 23 | > header that there is no such guarantee for stable API for these 24 | > programs. 25 | > 26 | > [0] http://vger.kernel.org/netconf2018_files/DanielBorkmann_netconf2018.pdf 27 | 28 | At Netdata we therefore took the decision to always give the current kernel 29 | version of the kernel when any of our `kprobe`-based eBPF programs are loaded. 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | 3 | KERNEL_DIR = kernel/ 4 | KERNEL_PROGRAM = $(KERNEL_DIR)process_kern.o 5 | 6 | KERNEL_VERSION="$(shell if [ -f /usr/src/linux/include/config/kernel.release ]; then cat /usr/src/linux/include/config/kernel.release; else cat /proc/sys/kernel/osrelease; fi)" 7 | FIRST_KERNEL_VERSION=$(shell tools/complement.sh "$(KERNEL_VERSION)") 8 | RHF=$(shell if [ -f /etc/redhat-release ]; then printf ".rhf"; else printf ''; fi) 9 | 10 | NETDATA_KERNEL_VERSION=$(shell echo $(KERNEL_VERSION) | tr -s "." "_") 11 | 12 | VER_MAJOR=$(shell echo $(KERNEL_VERSION) | cut -d. -f1) 13 | VER_MINOR=$(shell echo $(KERNEL_VERSION) | cut -d. -f2) 14 | #VER_PATCH=$(shell echo $(KERNEL_VERSION) | cut -d. -f3) 15 | 16 | _LIBC ?= glibc 17 | 18 | EXTRA_CFLAGS += -fno-stack-protector 19 | 20 | all: $(KERNEL_PROGRAM) 21 | tar -cf artifacts/netdata_ebpf-$(FIRST_KERNEL_VERSION)_$(VER_MAJOR).$(VER_MINOR)$(RHF)-$(_LIBC).tar [pr]netdata_ebpf_*.o 22 | if [ "$${DEBUG:-0}" -eq 1 ]; then tar -uvf artifacts/netdata_ebpf-$(FIRST_KERNEL_VERSION)_$(VER_MAJOR).$(VER_MINOR)$(RHF)-$(_LIBC).tar tools/check-kernel-config.sh; fi 23 | #gzip artifacts/netdata_ebpf-$(FIRST_KERNEL_VERSION)_$(VER_MAJOR).$(VER_MINOR)$(RHF)-$(_LIBC).tar 24 | ( cd artifacts; sha256sum netdata_ebpf-$(FIRST_KERNEL_VERSION)_$(VER_MAJOR).$(VER_MINOR)$(RHF)-$(_LIBC).tar > netdata_ebpf-$(FIRST_KERNEL_VERSION)_$(VER_MAJOR).$(VER_MINOR)$(RHF)-$(_LIBC).tar.gz.sha256sum ) 25 | 26 | dev: 27 | cd $(KERNEL_DIR) && $(MAKE) dev; 28 | 29 | $(KERNEL_PROGRAM): 30 | cd $(KERNEL_DIR) && $(MAKE) all; 31 | 32 | tester: 33 | cd $(KERNEL_DIR) && $(MAKE) tester 34 | 35 | clean: 36 | rm -f *.o; 37 | cd $(KERNEL_DIR) && $(MAKE) clean; 38 | rm -f artifacts/* 39 | rm -rf .local_libbpf 40 | 41 | install: 42 | cp *netdata_ebpf_process.$(VER_MAJOR).$(VER_MINOR).o /usr/libexec/netdata/plugins.d/ 43 | -------------------------------------------------------------------------------- /kernel/sync_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "sync_netdata" 2 | 3 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 4 | #include 5 | #else 6 | #include 7 | #endif 8 | #include "bpf_tracing.h" 9 | #include "bpf_helpers.h" 10 | #include "netdata_ebpf.h" 11 | 12 | /************************************************************************************ 13 | * 14 | * MAPS 15 | * 16 | ***********************************************************************************/ 17 | 18 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 19 | struct { 20 | __uint(type, BPF_MAP_TYPE_ARRAY); 21 | __type(key, __u32); 22 | __type(value, __u64); 23 | __uint(max_entries, NETDATA_SYNC_END); 24 | } tbl_sync SEC(".maps"); 25 | #else 26 | struct bpf_map_def SEC("maps") tbl_sync = { 27 | .type = BPF_MAP_TYPE_ARRAY, 28 | .key_size = sizeof(__u32), 29 | .value_size = sizeof(__u64), 30 | .max_entries = NETDATA_SYNC_END 31 | }; 32 | #endif 33 | 34 | /************************************************************************************ 35 | * 36 | * SYNC SECTION 37 | * 38 | ***********************************************************************************/ 39 | 40 | #if defined(LIBBPF_MAJOR_VERSION) && (LIBBPF_MAJOR_VERSION >= 1) 41 | SEC("ksyscall/sync") 42 | #else 43 | SEC("kprobe/" NETDATA_SYSCALL(sync)) 44 | #endif 45 | int netdata_syscall_sync(struct pt_regs* ctx) 46 | { 47 | libnetdata_update_global(&tbl_sync, NETDATA_KEY_SYNC_CALL, 1); 48 | 49 | return 0; 50 | } 51 | 52 | /************************************************************************************ 53 | * 54 | * END SYNC SECTION 55 | * 56 | ***********************************************************************************/ 57 | 58 | -------------------------------------------------------------------------------- /kernel/fsync_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "fsync_netdata" 2 | 3 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 4 | #include 5 | #else 6 | #include 7 | #endif 8 | #include "bpf_tracing.h" 9 | #include "bpf_helpers.h" 10 | #include "netdata_ebpf.h" 11 | 12 | /************************************************************************************ 13 | * 14 | * MAPS 15 | * 16 | ***********************************************************************************/ 17 | 18 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 19 | struct { 20 | __uint(type, BPF_MAP_TYPE_ARRAY); 21 | __type(key, __u32); 22 | __type(value, __u64); 23 | __uint(max_entries, NETDATA_SYNC_END); 24 | } tbl_fsync SEC(".maps"); 25 | #else 26 | struct bpf_map_def SEC("maps") tbl_fsync = { 27 | .type = BPF_MAP_TYPE_ARRAY, 28 | .key_size = sizeof(__u32), 29 | .value_size = sizeof(__u64), 30 | .max_entries = NETDATA_SYNC_END 31 | }; 32 | #endif 33 | 34 | /************************************************************************************ 35 | * 36 | * FSYNC SECTION 37 | * 38 | ***********************************************************************************/ 39 | 40 | #if defined(LIBBPF_MAJOR_VERSION) && (LIBBPF_MAJOR_VERSION >= 1) 41 | SEC("ksyscall/fsync") 42 | #else 43 | SEC("kprobe/" NETDATA_SYSCALL(fsync)) 44 | #endif 45 | int netdata_syscall_sync(struct pt_regs* ctx) 46 | { 47 | libnetdata_update_global(&tbl_fsync, NETDATA_KEY_SYNC_CALL, 1); 48 | 49 | return 0; 50 | } 51 | 52 | /************************************************************************************ 53 | * 54 | * END FSYNC SECTION 55 | * 56 | ***********************************************************************************/ 57 | 58 | -------------------------------------------------------------------------------- /kernel/msync_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "msync_netdata" 2 | 3 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 4 | #include 5 | #else 6 | #include 7 | #endif 8 | #include "bpf_tracing.h" 9 | #include "bpf_helpers.h" 10 | #include "netdata_ebpf.h" 11 | 12 | /************************************************************************************ 13 | * 14 | * MAPS 15 | * 16 | ***********************************************************************************/ 17 | 18 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 19 | struct { 20 | __uint(type, BPF_MAP_TYPE_ARRAY); 21 | __type(key, __u32); 22 | __type(value, __u64); 23 | __uint(max_entries, NETDATA_SYNC_END); 24 | } tbl_msync SEC(".maps"); 25 | 26 | #else 27 | 28 | struct bpf_map_def SEC("maps") tbl_msync = { 29 | .type = BPF_MAP_TYPE_ARRAY, 30 | .key_size = sizeof(__u32), 31 | .value_size = sizeof(__u64), 32 | .max_entries = NETDATA_SYNC_END 33 | }; 34 | 35 | #endif 36 | 37 | /************************************************************************************ 38 | * 39 | * MSYNC SECTION 40 | * 41 | ***********************************************************************************/ 42 | 43 | #if defined(LIBBPF_MAJOR_VERSION) && (LIBBPF_MAJOR_VERSION >= 1) 44 | SEC("ksyscall/msync") 45 | #else 46 | SEC("kprobe/" NETDATA_SYSCALL(msync)) 47 | #endif 48 | int netdata_syscall_sync(struct pt_regs* ctx) 49 | { 50 | libnetdata_update_global(&tbl_msync, NETDATA_KEY_SYNC_CALL, 1); 51 | 52 | return 0; 53 | } 54 | 55 | /************************************************************************************ 56 | * 57 | * END MSYNC SECTION 58 | * 59 | ***********************************************************************************/ 60 | 61 | -------------------------------------------------------------------------------- /kernel/fdatasync_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "fdatasync_netdata" 2 | 3 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 4 | #include 5 | #else 6 | #include 7 | #endif 8 | #include "bpf_tracing.h" 9 | #include "bpf_helpers.h" 10 | #include "netdata_ebpf.h" 11 | 12 | /************************************************************************************ 13 | * 14 | * MAPS 15 | * 16 | ***********************************************************************************/ 17 | 18 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 19 | struct { 20 | __uint(type, BPF_MAP_TYPE_ARRAY); 21 | __type(key, __u32); 22 | __type(value, __u64); 23 | __uint(max_entries, NETDATA_SYNC_END); 24 | } tbl_fdatasync SEC(".maps"); 25 | #else 26 | struct bpf_map_def SEC("maps") tbl_fdatasync = { 27 | .type = BPF_MAP_TYPE_ARRAY, 28 | .key_size = sizeof(__u32), 29 | .value_size = sizeof(__u64), 30 | .max_entries = NETDATA_SYNC_END 31 | }; 32 | #endif 33 | 34 | /************************************************************************************ 35 | * 36 | * FDATASYNC SECTION 37 | * 38 | ***********************************************************************************/ 39 | 40 | #if defined(LIBBPF_MAJOR_VERSION) && (LIBBPF_MAJOR_VERSION >= 1) 41 | SEC("ksyscall/fdatasync") 42 | #else 43 | SEC("kprobe/" NETDATA_SYSCALL(fdatasync)) 44 | #endif 45 | int netdata_syscall_sync(struct pt_regs* ctx) 46 | { 47 | libnetdata_update_global(&tbl_fdatasync, NETDATA_KEY_SYNC_CALL, 1); 48 | 49 | return 0; 50 | } 51 | 52 | /************************************************************************************ 53 | * 54 | * END FDATASYNC SECTION 55 | * 56 | ***********************************************************************************/ 57 | 58 | -------------------------------------------------------------------------------- /kernel/sync_file_range_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "sfrange_netdata" 2 | 3 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 4 | #include 5 | #else 6 | #include 7 | #endif 8 | #include "bpf_tracing.h" 9 | #include "bpf_helpers.h" 10 | #include "netdata_ebpf.h" 11 | 12 | /************************************************************************************ 13 | * 14 | * MAPS 15 | * 16 | ***********************************************************************************/ 17 | 18 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 19 | struct { 20 | __uint(type, BPF_MAP_TYPE_ARRAY); 21 | __type(key, __u32); 22 | __type(value, __u64); 23 | __uint(max_entries, NETDATA_SYNC_END); 24 | } tbl_syncfr SEC(".maps"); 25 | #else 26 | struct bpf_map_def SEC("maps") tbl_syncfr = { 27 | .type = BPF_MAP_TYPE_ARRAY, 28 | .key_size = sizeof(__u32), 29 | .value_size = sizeof(__u64), 30 | .max_entries = NETDATA_SYNC_END 31 | }; 32 | #endif 33 | 34 | /************************************************************************************ 35 | * 36 | * SYNC_FILE_RANGE SECTION 37 | * 38 | ***********************************************************************************/ 39 | 40 | #if defined(LIBBPF_MAJOR_VERSION) && (LIBBPF_MAJOR_VERSION >= 1) 41 | SEC("ksyscall/sync_file_range") 42 | #else 43 | SEC("kprobe/" NETDATA_SYSCALL(sync_file_range)) 44 | #endif 45 | int netdata_syscall_sync(struct pt_regs* ctx) 46 | { 47 | libnetdata_update_global(&tbl_syncfr, NETDATA_KEY_SYNC_CALL, 1); 48 | 49 | return 0; 50 | } 51 | 52 | /************************************************************************************ 53 | * 54 | * END SYNC_FILE_RANGE SECTION 55 | * 56 | ***********************************************************************************/ 57 | 58 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: CI 3 | on: 4 | pull_request: 5 | concurrency: 6 | group: ci-${{ github.ref }} 7 | cancel-in-progress: true 8 | jobs: 9 | build-artifacts: 10 | name: Build Artifacts 11 | strategy: 12 | fail-fast: false 13 | matrix: 14 | kernel_version: 15 | - '6.16.2' 16 | - '6.8.2' 17 | - '5.16.18' 18 | - '5.15.63' 19 | - '5.14.0' 20 | - '5.11.19' 21 | - '5.10.139' 22 | - '5.4.210' 23 | - '5.4.17' 24 | - '4.16.18' 25 | - '4.18.0' 26 | - '4.14.291' 27 | libc: 28 | - static 29 | - glibc 30 | - musl 31 | exclude: 32 | - kernel_version: 5.4.17 33 | libc: static 34 | - kernel_version: 5.4.17 35 | libc: musl 36 | runs-on: ubuntu-latest 37 | steps: 38 | - name: Checkout 39 | uses: actions/checkout@v6 40 | with: 41 | submodules: true 42 | fetch-depth: 0 43 | - name: Run build.sh 44 | run: | 45 | if [ ${{ matrix.kernel_version }} = "5.14.0" ]; then 46 | os=centos9 47 | elif [ ${{ matrix.kernel_version }} = "5.4.17" ]; then 48 | os=oracle8 49 | elif [ ${{ matrix.kernel_version }} = "4.18.0" ]; then 50 | os=centos8 51 | else 52 | os=generic 53 | fi 54 | ./build.sh ${{ matrix.kernel_version }} ${{ matrix.libc }} "${os}" 55 | - name: List Artifacts 56 | run: | 57 | ls -lah artifacts 58 | test -f artifacts/netdata_ebpf-*.tar 59 | - name: Upload Artifacts 60 | uses: actions/upload-artifact@v6 61 | if: success() 62 | with: 63 | name: artifacts-${{ matrix.kernel_version }}-${{ matrix.libc }} 64 | path: artifacts 65 | -------------------------------------------------------------------------------- /kernel/mdflush_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "mdflush_netdata" 2 | #include 3 | #include 4 | #include 5 | 6 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 7 | #include 8 | #else 9 | #include 10 | #endif 11 | #include "bpf_tracing.h" 12 | #include "bpf_helpers.h" 13 | #include "netdata_ebpf.h" 14 | 15 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 16 | struct { 17 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) 18 | __uint(type, BPF_MAP_TYPE_HASH); 19 | #else 20 | __uint(type, BPF_MAP_TYPE_PERCPU_HASH); 21 | #endif 22 | __type(key, mdflush_key_t); 23 | __type(value, mdflush_val_t); 24 | __uint(max_entries, 1024); 25 | } tbl_mdflush SEC(".maps"); 26 | 27 | #else 28 | 29 | struct bpf_map_def SEC("maps") tbl_mdflush = { 30 | .type = BPF_MAP_TYPE_HASH, 31 | .key_size = sizeof(mdflush_key_t), 32 | .value_size = sizeof(mdflush_val_t), 33 | .max_entries = 1024 34 | }; 35 | #endif 36 | 37 | SEC("kprobe/md_flush_request") 38 | int netdata_md_flush_request(struct pt_regs *ctx) 39 | { 40 | mdflush_key_t key = 0; 41 | mdflush_val_t *valp, val; 42 | struct mddev *mddev = (struct mddev *)PT_REGS_PARM1(ctx); 43 | 44 | // get correct key. 45 | // this essentially does the logic here: 46 | // https://elixir.bootlin.com/linux/v4.14/source/drivers/md/md.c#L5256 47 | bpf_probe_read(&key, sizeof(key), &mddev->unit); 48 | int partitioned = (MAJOR(key) != MD_MAJOR); 49 | int shift = partitioned ? MdpMinorShift : 0; 50 | key = MINOR(key) >> shift; 51 | 52 | valp = bpf_map_lookup_elem(&tbl_mdflush, &key); 53 | if (valp) { 54 | *valp += 1; 55 | } else { 56 | val = 1; 57 | bpf_map_update_elem(&tbl_mdflush, &key, &val, BPF_ANY); 58 | } 59 | 60 | return 0; 61 | } 62 | 63 | char _license[] SEC("license") = "GPL"; 64 | -------------------------------------------------------------------------------- /kernel/syncfs_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "syncfs_netdata" 2 | 3 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 4 | #include 5 | #else 6 | #include 7 | #endif 8 | #include "bpf_tracing.h" 9 | #include "bpf_helpers.h" 10 | #include "netdata_ebpf.h" 11 | 12 | /************************************************************************************ 13 | * 14 | * MAPS 15 | * 16 | ***********************************************************************************/ 17 | 18 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 19 | struct { 20 | __uint(type, BPF_MAP_TYPE_ARRAY); 21 | __type(key, __u32); 22 | __type(value, __u64); 23 | __uint(max_entries, NETDATA_SYNC_END); 24 | } tbl_syncfs SEC(".maps"); 25 | #else 26 | struct bpf_map_def SEC("maps") tbl_syncfs = { 27 | .type = BPF_MAP_TYPE_ARRAY, 28 | .key_size = sizeof(__u32), 29 | .value_size = sizeof(__u64), 30 | .max_entries = NETDATA_SYNC_END 31 | }; 32 | #endif 33 | 34 | /************************************************************************************ 35 | * 36 | * SYNCFS SECTION 37 | * 38 | ***********************************************************************************/ 39 | 40 | #if defined(LIBBPF_MAJOR_VERSION) && (LIBBPF_MAJOR_VERSION >= 1) 41 | SEC("ksyscall/syncfs") 42 | #else 43 | SEC("kprobe/" NETDATA_SYSCALL(syncfs)) 44 | #endif 45 | int netdata_syscall_sync(struct pt_regs* ctx) 46 | { 47 | libnetdata_update_global(&tbl_syncfs, NETDATA_KEY_SYNC_CALL, 1); 48 | 49 | return 0; 50 | } 51 | 52 | /************************************************************************************ 53 | * 54 | * END SYNCFS SECTION 55 | * 56 | ***********************************************************************************/ 57 | 58 | char _license[] SEC("license") = "GPL"; 59 | 60 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 12 | 13 | ##### Summary 14 | 15 | ##### Test Plan 16 | 1. Get binaries according to your C library from [this](ADD ACTIONS LINK HERE) link and extract them inside a directory, for example: `../artifacts`. 17 | You can also get everything for `glibc` [here](UPLOAD FILE WITH ALL BINARIES TO SIMPLIFY REVIEWERS). 18 | 19 | 2. Extract them running: 20 | ```sh 21 | $ for i in `ls *.zip`; do unzip $i; rm .gitkeep ; rm $i; done 22 | $ for i in `ls *.xz`; do tar -xf $i; rm $i* ; done 23 | ``` 24 | 25 | 3. Compile branch an run the following tests: 26 | 27 | ```sh 28 | # make clean; make tester 29 | # for i in `seq 0 3`; do ./kernel/legacy_test --netdata-path ../artifacts --content --iteration 1 --pid $i --log-path file_pid$i.txt; done 30 | ``` 31 | 32 | 4. Every test should ends with `Success`, unless you do not have a specific target (function) available. 33 | 34 | ##### Additional information 35 | 36 | This PR was tested on: 37 | 38 | | Linux Distribution | Environment |Kernel Version | Real Parent | Parent | All PIDs | Without PIDs | 39 | |--------------------|----------------|---------------|-------------|--------|-----------|--------------| 40 | | LINUX DISTRIBUION | Bare metal/VM | uname -r | | | | | 41 | -------------------------------------------------------------------------------- /Dockerfile.glibc.centos8: -------------------------------------------------------------------------------- 1 | FROM almalinux:9 AS build 2 | 3 | ARG ARCH=x86 4 | ENV ARCH=$ARCH 5 | 6 | ENV KERNEL_VERSION=4.18.0-372.32.1.el8_6 7 | 8 | ENV _LIBC=glibc 9 | 10 | # We use "Development tools" to install: 11 | # gcc c/c++ compiler, redhat-rpm-config, strace, rpm-build, make, pkgconfig, gettext, automake, strace64, gdb, bison, 12 | # libtool, autoconf, gcc-c++ compiler, binutils and all dependencies 13 | 14 | # hadolint ignore=DL3040,DL3041 15 | RUN dnf update -y && \ 16 | dnf install -y gcc make gcc-c++ libtool rpm-build-libs bison && \ 17 | dnf install -y asciidoc audit-libs-devel bash bc binutils binutils-devel \ 18 | diffutils elfutils elfutils-devel \ 19 | elfutils-libelf-devel findutils gawk \ 20 | gzip hmaccalc hostname java-devel m4 \ 21 | module-init-tools ncurses-devel net-tools newt-devel \ 22 | numactl-devel openssl openssl-devel patch pciutils-devel \ 23 | perl perl-ExtUtils-Embed pesign \ 24 | rpm-build tar xmlto xz zlib-devel clang llvm 25 | 26 | RUN mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} && \ 27 | echo '%_topdir %(echo $HOME)/rpmbuild' > ~/.rpmmacros && \ 28 | rpm -i https://repo.almalinux.org/vault/8.6/BaseOS/Source/Packages/kernel-${KERNEL_VERSION}.src.rpm 2>&1 29 | 30 | RUN cd ~/rpmbuild/SOURCES && \ 31 | tar -xf linux-${KERNEL_VERSION}.tar.xz && \ 32 | mkdir -p /usr/src/kernels 33 | 34 | RUN cd /usr/src && \ 35 | ln -s ~/rpmbuild/SOURCES/linux-${KERNEL_VERSION} linux && \ 36 | ln -s /usr/lib/gcc/x86_64-redhat-linux/11/include/stdarg.h /usr/src/linux/include/ 37 | 38 | COPY kernel-patches/${KERNEL_VERSION} /usr/src/linux-${KERNEL_VERSION}-patches 39 | COPY .dockerfiles/patch_kernel.sh /patch_kernel.sh 40 | RUN /patch_kernel.sh 41 | 42 | WORKDIR /kernel-collector 43 | 44 | COPY .dockerfiles/build.sh /build.sh 45 | COPY . . 46 | 47 | CMD ["/build.sh"] 48 | -------------------------------------------------------------------------------- /Dockerfile.glibc.centos9: -------------------------------------------------------------------------------- 1 | FROM almalinux:9.5 AS build 2 | 3 | ARG ARCH=x86 4 | ENV ARCH=$ARCH 5 | 6 | ENV KERNEL_VERSION=5.14.0-70.30.1.el9_0 7 | 8 | ENV _LIBC=glibc 9 | 10 | # We use "Development tools" to install: 11 | # gcc c/c++ compiler, redhat-rpm-config, strace, rpm-build, make, pkgconfig, gettext, automake, strace64, gdb, bison, 12 | # libtool, autoconf, gcc-c++ compiler, binutils and all dependencies 13 | 14 | # hadolint ignore=DL3040,DL3041 15 | RUN dnf update -y && \ 16 | dnf install -y gcc make gcc-c++ libtool rpm-build-libs bison && \ 17 | dnf install -y asciidoc audit-libs-devel bash bc binutils binutils-devel \ 18 | diffutils elfutils elfutils-devel \ 19 | elfutils-libelf-devel findutils gawk \ 20 | gzip hmaccalc hostname java-devel m4 \ 21 | module-init-tools ncurses-devel net-tools newt-devel \ 22 | numactl-devel openssl openssl-devel patch pciutils-devel \ 23 | perl perl-ExtUtils-Embed pesign \ 24 | rpm-build rsync tar xmlto xz zlib-devel clang llvm 25 | 26 | RUN mkdir -p /root/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} && \ 27 | echo '%_topdir %(echo $HOME)/rpmbuild' > /root/.rpmmacros && \ 28 | rpm -i https://repo.almalinux.org/vault/9.0/BaseOS/Source/Packages/kernel-${KERNEL_VERSION}.src.rpm 2>&1 29 | 30 | RUN tar -xf /root/rpmbuild/SOURCES/linux-${KERNEL_VERSION}.tar.xz -C /root/rpmbuild/SOURCES && \ 31 | mkdir -p /usr/src/kernels 32 | 33 | RUN ln -s /root/rpmbuild/SOURCES/linux-${KERNEL_VERSION} /usr/src/linux && \ 34 | ln -s /usr/lib/gcc/x86_64-redhat-linux/11/include/stdarg.h /usr/src/linux/include/ 35 | 36 | COPY kernel-patches/${KERNEL_VERSION} /usr/src/linux-${KERNEL_VERSION}-patches 37 | COPY .dockerfiles/patch_kernel.sh /patch_kernel.sh 38 | RUN /patch_kernel.sh 39 | 40 | WORKDIR /kernel-collector 41 | 42 | COPY .dockerfiles/build.sh /build.sh 43 | COPY . . 44 | 45 | CMD ["/build.sh"] 46 | -------------------------------------------------------------------------------- /Dockerfile.glibc.oracle8: -------------------------------------------------------------------------------- 1 | FROM almalinux:9 AS build 2 | 3 | ARG ARCH=x86 4 | ENV ARCH=$ARCH 5 | 6 | ENV KERNEL_VERSION=5.4.17 7 | 8 | ENV _LIBC=glibc 9 | 10 | # We use "Development tools" to install: 11 | # gcc c/c++ compiler, redhat-rpm-config, strace, rpm-build, make, pkgconfig, gettext, automake, strace64, gdb, bison, 12 | # libtool, autoconf, gcc-c++ compiler, binutils and all dependencies 13 | 14 | # hadolint ignore=DL3040,DL3041 15 | RUN dnf update -y && \ 16 | dnf install -y gcc make gcc-c++ libtool rpm-build-libs bison && \ 17 | dnf install -y asciidoc audit-libs-devel bash bc binutils binutils-devel \ 18 | diffutils elfutils elfutils-devel \ 19 | elfutils-libelf-devel findutils gawk \ 20 | gzip hmaccalc hostname java-devel m4 \ 21 | module-init-tools ncurses-devel net-tools newt-devel \ 22 | numactl-devel openssl openssl-devel patch pciutils-devel \ 23 | perl perl-ExtUtils-Embed pesign \ 24 | rpm-build tar xmlto xz zlib-devel clang llvm rsync 25 | 26 | # hadolint ignore=SC2016 27 | RUN mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} && \ 28 | echo '%_topdir %(echo $HOME)/rpmbuild' > ~/.rpmmacros && \ 29 | rpm -i https://oss.oracle.com/ol8/SRPMS-updates/kernel-uek-${KERNEL_VERSION}-2136.328.3.el8uek.src.rpm 2>&1 30 | 31 | # hadolint ignore=DL3003 32 | RUN cd ~/rpmbuild/SOURCES && \ 33 | tar -xf linux-${KERNEL_VERSION}.tar.bz2 && \ 34 | mkdir -p /usr/src/kernels 35 | 36 | # hadolint ignore=DL3003 37 | RUN cd /usr/src && \ 38 | ln -s ~/rpmbuild/SOURCES/linux-${KERNEL_VERSION} linux && \ 39 | ln -s /usr/lib/gcc/x86_64-redhat-linux/11/include/stdarg.h /usr/src/linux/include/ 40 | 41 | COPY kernel-patches/${KERNEL_VERSION} /usr/src/linux-${KERNEL_VERSION}-patches 42 | COPY .dockerfiles/patch_kernel.sh /patch_kernel.sh 43 | RUN /patch_kernel.sh 44 | 45 | WORKDIR /kernel-collector 46 | 47 | COPY .dockerfiles/build.sh /build.sh 48 | COPY . . 49 | 50 | CMD ["/build.sh"] 51 | -------------------------------------------------------------------------------- /kernel/rename_binaries.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then 4 | echo "Give kernel as parameter: kernel major version, kernel minor version, and function name" 5 | exit 1 6 | fi 7 | 8 | parse_kernel_version() { 9 | R="${1}.${2}" 10 | 11 | read -r -a P <<< "$(echo "${R}" | tr '.' ' ')" 12 | 13 | printf "%03d%03d" "${P[0]}" "${P[1]}" 14 | } 15 | 16 | select_kernel_version() { 17 | KVER=$(parse_kernel_version "${1}" "${2}") 18 | 19 | VER6_12_0="006012" 20 | VER6_8_0="006008" 21 | VER5_16_0="005016" 22 | VER5_15_0="005015" 23 | VER5_14_0="005014" 24 | VER5_11_0="005011" 25 | VER5_10_0="005010" 26 | VER4_18_0="004018" 27 | VER4_17_0="004017" 28 | VER4_15_0="004015" 29 | VER4_11_0="004011" 30 | VER3_10_0="003010" 31 | ISRH="" 32 | 33 | if [ "${KVER}" -eq "${VER3_10_0}" ]; then 34 | KSELECTED="3.10"; 35 | elif [ "${KVER}" -eq "${VER4_18_0}" ]; then 36 | KSELECTED="4.18"; 37 | elif [ "${KVER}" -ge "${VER6_12_0}" ]; then 38 | KSELECTED="6.12"; 39 | elif [ "${KVER}" -ge "${VER6_8_0}" ]; then 40 | KSELECTED="6.8"; 41 | elif [ "${KVER}" -ge "${VER5_16_0}" ]; then 42 | KSELECTED="5.16"; 43 | elif [ "${KVER}" -ge "${VER5_15_0}" ]; then 44 | KSELECTED="5.15"; 45 | elif [ "${KVER}" -ge "${VER5_14_0}" ]; then 46 | KSELECTED="5.14"; 47 | elif [ "${KVER}" -ge "${VER5_11_0}" ]; then 48 | KSELECTED="5.11"; 49 | elif [ "${KVER}" -ge "${VER5_10_0}" ]; then 50 | KSELECTED="5.10"; 51 | elif [ "${KVER}" -ge "${VER4_17_0}" ]; then 52 | KSELECTED="5.4"; 53 | elif [ "${KVER}" -ge "${VER4_15_0}" ]; then 54 | KSELECTED="4.16"; 55 | elif [ "${KVER}" -ge "${VER4_11_0}" ]; then 56 | KSELECTED="4.14"; 57 | fi 58 | 59 | if [ -f /etc/redhat-release ]; then 60 | ISRH=".rhf" 61 | fi 62 | 63 | echo "${KSELECTED}${ISRH}" 64 | } 65 | 66 | OBJECTNAME="$3" 67 | NAME=${OBJECTNAME%_*} 68 | 69 | KNAME=$(select_kernel_version "${1}" "${2}") 70 | 71 | cp "r${NAME}_kern.o" "../rnetdata_ebpf_${NAME}.${KNAME}.o" 72 | cp "p${NAME}_kern.o" "../pnetdata_ebpf_${NAME}.${KNAME}.o" 73 | 74 | -------------------------------------------------------------------------------- /includes/netdata_vfs.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_VFS_H_ 4 | #define _NETDATA_VFS_H_ 1 5 | 6 | struct netdata_vfs_stat_t { 7 | __u64 ct; 8 | __u32 tgid; 9 | __u32 uid; 10 | __u32 gid; 11 | char name[TASK_COMM_LEN]; 12 | 13 | //Counter 14 | __u32 write_call; 15 | __u32 writev_call; 16 | __u32 read_call; 17 | __u32 readv_call; 18 | __u32 unlink_call; 19 | __u32 fsync_call; 20 | __u32 open_call; 21 | __u32 create_call; 22 | 23 | //Accumulator 24 | __u64 write_bytes; 25 | __u64 writev_bytes; 26 | __u64 readv_bytes; 27 | __u64 read_bytes; 28 | 29 | //Counter 30 | __u32 write_err; 31 | __u32 writev_err; 32 | __u32 read_err; 33 | __u32 readv_err; 34 | __u32 unlink_err; 35 | __u32 fsync_err; 36 | __u32 open_err; 37 | __u32 create_err; 38 | }; 39 | 40 | enum vfs_counters { 41 | NETDATA_KEY_CALLS_VFS_WRITE, 42 | NETDATA_KEY_ERROR_VFS_WRITE, 43 | NETDATA_KEY_BYTES_VFS_WRITE, 44 | 45 | NETDATA_KEY_CALLS_VFS_WRITEV, 46 | NETDATA_KEY_ERROR_VFS_WRITEV, 47 | NETDATA_KEY_BYTES_VFS_WRITEV, 48 | 49 | NETDATA_KEY_CALLS_VFS_READ, 50 | NETDATA_KEY_ERROR_VFS_READ, 51 | NETDATA_KEY_BYTES_VFS_READ, 52 | 53 | NETDATA_KEY_CALLS_VFS_READV, 54 | NETDATA_KEY_ERROR_VFS_READV, 55 | NETDATA_KEY_BYTES_VFS_READV, 56 | 57 | NETDATA_KEY_CALLS_VFS_UNLINK, 58 | NETDATA_KEY_ERROR_VFS_UNLINK, 59 | 60 | NETDATA_KEY_CALLS_VFS_FSYNC, 61 | NETDATA_KEY_ERROR_VFS_FSYNC, 62 | 63 | NETDATA_KEY_CALLS_VFS_OPEN, 64 | NETDATA_KEY_ERROR_VFS_OPEN, 65 | 66 | NETDATA_KEY_CALLS_VFS_CREATE, 67 | NETDATA_KEY_ERROR_VFS_CREATE, 68 | 69 | // Keep this as last and don't skip numbers as it is used as element counter 70 | NETDATA_VFS_COUNTER 71 | }; 72 | 73 | enum netdata_vfs_calls_name { 74 | NETDATA_VFS_WRITE, 75 | NETDATA_VFS_WRITEV, 76 | NETDATA_VFS_READ, 77 | NETDATA_VFS_READV, 78 | NETDATA_VFS_UNLINK, 79 | NETDATA_VFS_FSYNC, 80 | NETDATA_VFS_OPEN, 81 | NETDATA_VFS_CREATE, 82 | 83 | NETDATA_VFS_END_LIST 84 | }; 85 | 86 | #endif /* _NETDATA_VFS_H_ */ 87 | 88 | -------------------------------------------------------------------------------- /tools/check-kernel-config.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function get_kernel_version() { 4 | r="$(uname -r | cut -f 1 -d '-')" 5 | 6 | read -r -a p <<< "$(echo "${r}" | tr '.' ' ')" 7 | 8 | printf "%03d%03d%03d" "${p[0]}" "${p[1]}" "${p[2]}" 9 | } 10 | 11 | function get_rh_version() { 12 | if [ ! -f /etc/redhat-release ] ; then 13 | printf "000000000" 14 | return 15 | fi 16 | 17 | r="$(cut -f 4 -d ' ' < /etc/redhat-release)" 18 | 19 | read -r -a p <<< "$(echo "${r}" | tr '.' ' ')" 20 | 21 | printf "%03d%03d%03d" "${p[0]}" "${p[1]}" "${p[2]}" 22 | } 23 | 24 | if [ "$(uname -s)" != "Linux" ]; then 25 | echo >&2 "This does not appear to be a Linux system." 26 | exit 1 27 | fi 28 | 29 | KERNEL_VERSION="$(uname -r)" 30 | 31 | if [ "$(get_kernel_version)" -lt 004014000 ] && [ "$(get_rh_version)" -lt 0070061810 ] ; then 32 | echo >&2 "WARNING: Your kernel appears to be older than 4.11 or you are using RH version older than 7.6.1810. This may still work in some cases, but probably won't." 33 | fi 34 | 35 | CONFIG_PATH="" 36 | MODULE_LOADED="" 37 | 38 | if modprobe configs 2> /dev/null; then 39 | MODULE_LOADED=1 40 | fi 41 | 42 | if [ -r /proc/config.gz ]; then 43 | CONFIG_PATH="/proc/config.gz" 44 | elif [ -r "/lib/modules/${KERNEL_VERSION}/source/.config" ]; then 45 | CONFIG_PATH="/lib/modules/${KERNEL_VERSION}/source/.config" 46 | elif [ -r "/lib/modules/${KERNEL_VERSION}.x86_64/source/.config" ]; then 47 | CONFIG_PATH="/lib/modules/${KERNEL_VERSION}.x86_64/source/.config" 48 | elif [ -n "$(find /boot -name "config-${KERNEL_VERSION}*")" ]; then 49 | CONFIG_PATH="$(find /boot -name "config-${KERNEL_VERSION}*" | head -n 1)" 50 | fi 51 | 52 | if [ -n "${CONFIG_PATH}" ]; then 53 | GREP='grep' 54 | 55 | if echo "${CONFIG_PATH}" | grep -q '.gz'; then 56 | GREP='zgrep' 57 | fi 58 | 59 | REQUIRED_CONFIG="KPROBES KPROBES_ON_FTRACE HAVE_KPROBES BPF BPF_SYSCALL BPF_JIT DYNAMIC_FTRACE" 60 | 61 | for required_config in ${REQUIRED_CONFIG}; do 62 | if ! "${GREP}" -q "CONFIG_${required_config}=y" "${CONFIG_PATH}"; then 63 | echo >&2 " Missing Kernel Config: ${required_config}" 64 | exit 1 65 | fi 66 | done 67 | fi 68 | 69 | if [ -n "${MODULE_LOADED}" ]; then 70 | modprobe -r configs 2> /dev/null || true # Ignore failures from CONFIGS being builtin 71 | fi 72 | 73 | exit 0 74 | -------------------------------------------------------------------------------- /kernel/softirq_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "softirq_netdata" 2 | #include 3 | 4 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 5 | #include 6 | #else 7 | #include 8 | #endif 9 | #include "bpf_tracing.h" 10 | #include "bpf_helpers.h" 11 | #include "netdata_ebpf.h" 12 | 13 | /************************************************************************************ 14 | * MAPS 15 | ***********************************************************************************/ 16 | 17 | // maps from irq index to latency. 18 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 19 | struct { 20 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 21 | __type(key, __u32); 22 | __type(value, softirq_val_t); 23 | __uint(max_entries, NETDATA_SOFTIRQ_MAX_IRQS); 24 | } tbl_softirq SEC(".maps"); 25 | #else 26 | struct bpf_map_def SEC("maps") tbl_softirq = { 27 | .type = BPF_MAP_TYPE_PERCPU_ARRAY, 28 | .key_size = sizeof(__u32), 29 | .value_size = sizeof(softirq_val_t), 30 | .max_entries = NETDATA_SOFTIRQ_MAX_IRQS 31 | }; 32 | #endif 33 | 34 | /************************************************************************************ 35 | * SOFTIRQ SECTION 36 | ***********************************************************************************/ 37 | 38 | SEC("tracepoint/irq/softirq_entry") 39 | int netdata_softirq_entry(struct netdata_softirq_entry *ptr) 40 | { 41 | softirq_val_t *valp, val = {}; 42 | u32 vec = ptr->vec; 43 | 44 | // out-of-range index. 45 | if (vec > NETDATA_SOFTIRQ_MAX_IRQS-1) { 46 | return 0; 47 | } 48 | 49 | valp = bpf_map_lookup_elem(&tbl_softirq, &vec); 50 | if (valp) { 51 | valp->ts = bpf_ktime_get_ns(); 52 | } else { 53 | val.latency = 0; 54 | val.ts = bpf_ktime_get_ns(); 55 | bpf_map_update_elem(&tbl_softirq, &vec, &val, BPF_ANY); 56 | } 57 | 58 | return 0; 59 | } 60 | 61 | SEC("tracepoint/irq/softirq_exit") 62 | int netdata_softirq_exit(struct netdata_softirq_exit *ptr) 63 | { 64 | softirq_val_t *valp; 65 | u32 vec = ptr->vec; 66 | 67 | // out-of-range index. 68 | if (vec > NETDATA_SOFTIRQ_MAX_IRQS-1) { 69 | return 0; 70 | } 71 | 72 | valp = bpf_map_lookup_elem(&tbl_softirq, &vec); 73 | if (!valp) { 74 | return 0; 75 | } 76 | 77 | // get time diff and convert to microseconds. 78 | u64 latency = (bpf_ktime_get_ns() - valp->ts) / 1000; 79 | libnetdata_update_u64(&valp->latency, latency); 80 | 81 | return 0; 82 | } 83 | 84 | char _license[] SEC("license") = "GPL"; 85 | -------------------------------------------------------------------------------- /includes/netdata_disk.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_DISK_H_ 4 | #define _NETDATA_DISK_H_ 1 5 | 6 | #include "netdata_fs.h" 7 | 8 | #define NETDATA_DISK_MAX_HD 256L 9 | #define NETDATA_DISK_HISTOGRAM_LENGTH (NETDATA_FS_MAX_BINS * NETDATA_DISK_MAX_HD) 10 | 11 | // Decode function extracted from: https://elixir.bootlin.com/linux/v5.10.8/source/include/linux/kdev_t.h#L7 12 | #define NETDATA_MINORBITS 20 13 | #define NETDATA_MINORMASK ((1U << NETDATA_MINORBITS) - 1) 14 | 15 | #define NETDATA_MAJOR(dev) ((unsigned int) ((dev) >> NETDATA_MINORBITS)) 16 | #define NETDATA_MINOR(dev) ((unsigned int) ((dev) & NETDATA_MINORMASK)) 17 | #define NETDATA_MKDEV(ma,mi) (((ma) << MINORBITS) | (mi)) 18 | 19 | static __always_inline u32 netdata_new_encode_dev(dev_t dev) 20 | { 21 | unsigned major = NETDATA_MAJOR(dev); 22 | unsigned minor = NETDATA_MINOR(dev); 23 | return (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12); 24 | } 25 | 26 | // /sys/kernel/debug/tracing/events/block/block_rq_issue/ 27 | struct netdata_block_rq_issue { 28 | u64 pad; // This is not used with eBPF 29 | dev_t dev; // offset:8; size:4; signed:0; 30 | sector_t sector; // offset:16; size:8; signed:0; 31 | unsigned int nr_sector; // offset:24; size:4; signed:0; 32 | unsigned int bytes; // offset:28; size:4; signed:0; 33 | char rwbs[8]; // offset:32; size:8; signed:1; 34 | char comm[16]; // offset:40; size:16; signed:1; 35 | int data_loc_name; // offset:56; size:4; signed:1; (https://github.com/iovisor/bpftrace/issues/385) 36 | }; 37 | 38 | // /sys/kernel/debug/tracing/events/block/block_rq_complete 39 | // https://elixir.bootlin.com/linux/latest/source/include/trace/events/block.h 40 | struct netdata_block_rq_complete { 41 | u64 pad; // This is not used with eBPF 42 | dev_t dev; // offset:8; size:4; signed:0; 43 | sector_t sector; // offset:16; size:8; signed:0; 44 | unsigned int nr_sector; // offset:24; size:4; signed:0; 45 | int error; // offset:28; size:4; signed:1; 46 | char rwbs[8]; // offset:32; size:8; signed:1; 47 | int data_loc_name; // offset:40; size:4; signed:1; 48 | //(https://lists.linuxfoundation.org/pipermail/iovisor-dev/2017-February/000627.html) 49 | }; 50 | 51 | typedef struct netdata_disk_key { 52 | dev_t dev; 53 | sector_t sector; 54 | } netdata_disk_key_t; 55 | 56 | typedef struct block_key { 57 | __u32 bin; 58 | u32 dev; 59 | } block_key_t; 60 | 61 | #endif /* _NETDATA_DISK_H_ */ 62 | 63 | -------------------------------------------------------------------------------- /includes/netdata_process.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_EBPF_PROCESS_H_ 4 | #define _NETDATA_EBPF_PROCESS_H_ 1 5 | 6 | // /sys/kernel/tracing/events/sched/sched_process_exit/format 7 | typedef struct netdata_sched_process_exit { 8 | __u64 pad; // This is not used with eBPF 9 | char comm[16] ; // offset:8; size:16; signed:1; 10 | int pid; // offset:24; size:4; signed:1; 11 | int prio; // offset:28; size:4; signed:1; 12 | } netdata_sched_process_exit_t; 13 | 14 | // /sys/kernel/tracing/events/sched/sched_process_fork/format 15 | typedef struct netdata_sched_process_fork { 16 | __u64 pad; // This is not used with eBPF 17 | char parent_comm[16]; // offset:8; size:16; signed:1; 18 | int parent_pid; // offset:24; size:4; signed:1; 19 | char child_comm[16]; // offset:28; size:16; signed:1; 20 | int child_pid; // offset:44; size:4; signed:1; 21 | } netdata_sched_process_fork_t; 22 | 23 | typedef struct netdata_sched_process_fork_v2 { 24 | __u64 pad; // This is not used with eBPF 25 | char parent_comm[4]; // offset:8; size:4; signed:1; 26 | int parent_pid; // offset:12; size:4; signed:1; 27 | char child_comm[4]; // offset:16; size:4; signed:1; 28 | int child_pid; // offset:20; size:4; signed:1; 29 | } netdata_sched_process_fork_v2_t; 30 | 31 | // /sys/kernel/tracing/events/sched/sched_process_exec/format 32 | typedef struct netdata_sched_process_exec { 33 | __u64 pad; // This is not used with eBPF 34 | int filename; // offset:8; size:4; signed:1; 35 | int pid; // offset:12; size:4; signed:1; 36 | int old_pid; // offset:16; size:4; signed:1; 37 | } netdata_sched_process_exec_t; 38 | 39 | struct netdata_pid_stat_t { 40 | __u64 ct; 41 | __u32 uid; 42 | __u32 gid; 43 | char name[TASK_COMM_LEN]; 44 | 45 | __u32 tgid; //Task id 46 | __u32 pid; //Process id 47 | 48 | //Counter 49 | __u32 exit_call; //Exit syscalls (exit for exit_group) 50 | __u32 release_call; //Exit syscalls (exit and exit_group) 51 | __u32 create_process; //Start syscall (fork, clone, forkv) 52 | __u32 create_thread; //Start syscall (fork, clone, forkv) 53 | 54 | __u32 task_err; 55 | }; 56 | 57 | enum process_counters { 58 | NETDATA_KEY_CALLS_DO_EXIT, 59 | 60 | NETDATA_KEY_CALLS_RELEASE_TASK, 61 | 62 | NETDATA_KEY_CALLS_PROCESS, 63 | NETDATA_KEY_ERROR_PROCESS, 64 | 65 | NETDATA_KEY_CALLS_THREAD, 66 | NETDATA_KEY_ERROR_THREAD, 67 | 68 | // Keep this as last and don't skip numbers as it is used as element counter 69 | NETDATA_GLOBAL_COUNTER 70 | }; 71 | 72 | #endif /* _NETDATA_EBPF_PROCESS_H_ */ 73 | 74 | -------------------------------------------------------------------------------- /kernel/mount_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "mount_netdata" 2 | 3 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 4 | #include 5 | #else 6 | #include 7 | #endif 8 | #include "bpf_tracing.h" 9 | #include "bpf_helpers.h" 10 | #include "netdata_ebpf.h" 11 | 12 | /************************************************************************************ 13 | * 14 | * MAPS 15 | * 16 | ***********************************************************************************/ 17 | 18 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 19 | struct { 20 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 21 | __type(key, __u32); 22 | __type(value, __u64); 23 | __uint(max_entries, NETDATA_MOUNT_END); 24 | } tbl_mount SEC(".maps"); 25 | #else 26 | struct bpf_map_def SEC("maps") tbl_mount = { 27 | .type = BPF_MAP_TYPE_PERCPU_ARRAY, 28 | .key_size = sizeof(__u32), 29 | .value_size = sizeof(__u64), 30 | .max_entries = NETDATA_MOUNT_END 31 | }; 32 | #endif 33 | 34 | /************************************************************************************ 35 | * 36 | * MOUNT SECTION 37 | * 38 | ***********************************************************************************/ 39 | 40 | #if defined(LIBBPF_MAJOR_VERSION) && (LIBBPF_MAJOR_VERSION >= 1) 41 | #if NETDATASEL < 2 42 | SEC("kretsyscall/mount") 43 | #else 44 | SEC("ksyscall/mount") 45 | #endif /* NETDATASEL < 2 */ 46 | #else 47 | #if NETDATASEL < 2 48 | SEC("kretprobe/" NETDATA_SYSCALL(mount)) 49 | #else 50 | SEC("kprobe/" NETDATA_SYSCALL(mount)) 51 | #endif /* NETDATASEL < 2 */ 52 | #endif 53 | int netdata_syscall_mount(struct pt_regs* ctx) 54 | { 55 | libnetdata_update_global(&tbl_mount, NETDATA_KEY_MOUNT_CALL, 1); 56 | #if NETDATASEL < 2 57 | int ret = (int)PT_REGS_RC(ctx); 58 | if (ret < 0) 59 | libnetdata_update_global(&tbl_mount, NETDATA_KEY_MOUNT_ERROR, 1); 60 | #endif 61 | 62 | return 0; 63 | } 64 | 65 | #if defined(LIBBPF_MAJOR_VERSION) && (LIBBPF_MAJOR_VERSION >= 1) 66 | #if NETDATASEL < 2 67 | SEC("kretsyscall/umount") 68 | #else 69 | SEC("ksyscall/umount") 70 | #endif /* NETDATASEL < 2 */ 71 | #else 72 | #if NETDATASEL < 2 73 | SEC("kretprobe/" NETDATA_SYSCALL(umount)) 74 | #else 75 | SEC("kprobe/" NETDATA_SYSCALL(umount)) 76 | #endif /* NETDATASEL < 2 */ 77 | #endif 78 | int netdata_syscall_umount(struct pt_regs* ctx) 79 | { 80 | libnetdata_update_global(&tbl_mount, NETDATA_KEY_UMOUNT_CALL, 1); 81 | #if NETDATASEL < 2 82 | int ret = (int)PT_REGS_RC(ctx); 83 | if (ret < 0) 84 | libnetdata_update_global(&tbl_mount, NETDATA_KEY_UMOUNT_ERROR, 1); 85 | #endif 86 | 87 | return 0; 88 | } 89 | 90 | /************************************************************************************ 91 | * 92 | * END MOUNT SECTION 93 | * 94 | ***********************************************************************************/ 95 | 96 | char _license[] SEC("license") = "GPL"; 97 | 98 | -------------------------------------------------------------------------------- /includes/netdata_hardirq.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_HARDIRQ_H_ 4 | #define _NETDATA_HARDIRQ_H_ 1 5 | 6 | #define NETDATA_HARDIRQ_MAX_IRQS 1024L 7 | #define NETDATA_HARDIRQ_NAME_LEN 32 8 | 9 | // /sys/kernel/debug/tracing/events/irq/irq_handler_entry/ 10 | struct netdata_irq_handler_entry { 11 | u64 pad; // This is not used with eBPF 12 | int irq; // offset:8; size:4; signed:1; 13 | int data_loc_name; // offset:12; size:4; signed:1; (https://github.com/iovisor/bpftrace/issues/385) 14 | // (https://lists.linuxfoundation.org/pipermail/iovisor-dev/2017-February/000627.html) 15 | }; 16 | 17 | // /sys/kernel/debug/tracing/events/irq/irq_handler_exit/ 18 | struct netdata_irq_handler_exit { 19 | u64 pad; // This is not used with eBPF 20 | int irq; // offset:8; size:4; signed:1; 21 | int ret; // offset:12; size:4; signed:1; 22 | }; 23 | 24 | typedef struct hardirq_key { 25 | int irq; 26 | } hardirq_key_t; 27 | 28 | /* 29 | typedef struct hardirq_val { 30 | // incremental counter storing the total latency so far. 31 | u64 latency; 32 | 33 | // temporary timestamp stored at the IRQ entry handler, to be diff'd with a 34 | // timestamp at the IRQ exit handler, to get the latency to add to the 35 | // `latency` field. 36 | u64 ts; 37 | 38 | // identifies the IRQ with a human-readable string. 39 | // We are reading it direct from /proc avoiding in some kernels: 40 | // #0 0x000055f9729eb725 in libbpf_err_errno () 41 | // #1 0x000055f9729ec8a0 in bpf_map_lookup_elem () 42 | // #2 0x000055f97298be21 in hardirq_read_latency_map (mapfd=69) at collectors/ebpf.plugin/ebpf_hardirq.c:259 43 | // char name[NETDATA_HARDIRQ_NAME_LEN]; 44 | } hardirq_val_t; 45 | */ 46 | 47 | /************************************************************************************ 48 | * HARDIRQ STATIC 49 | ***********************************************************************************/ 50 | 51 | // all of the `irq_vectors` events, except `vector_*`, have the same format. 52 | // cat /sys/kernel/debug/tracing/available_events | grep 'irq_vectors' | grep -v ':vector_' 53 | struct netdata_irq_vectors_entry { 54 | u64 pad; // This is not used with eBPF 55 | int vector; // offset:8; size:4; signed:1; 56 | }; 57 | struct netdata_irq_vectors_exit { 58 | u64 pad; // This is not used with eBPF 59 | int vector; // offset:8; size:4; signed:1; 60 | }; 61 | 62 | // these represent static IRQs that aren't given an IRQ ID like the ones above. 63 | // they each require separate entry/exit tracepoints to track. 64 | enum netdata_hardirq_static { 65 | NETDATA_HARDIRQ_STATIC_APIC_THERMAL, 66 | NETDATA_HARDIRQ_STATIC_APIC_THRESHOLD, 67 | NETDATA_HARDIRQ_STATIC_APIC_ERROR, 68 | NETDATA_HARDIRQ_STATIC_APIC_DEFERRED_ERROR, 69 | NETDATA_HARDIRQ_STATIC_APIC_SPURIOUS, 70 | NETDATA_HARDIRQ_STATIC_FUNC_CALL, 71 | NETDATA_HARDIRQ_STATIC_FUNC_CALL_SINGLE, 72 | NETDATA_HARDIRQ_STATIC_RESCHEDULE, 73 | NETDATA_HARDIRQ_STATIC_LOCAL_TIMER, 74 | NETDATA_HARDIRQ_STATIC_IRQ_WORK, 75 | NETDATA_HARDIRQ_STATIC_X86_PLATFORM_IPI, 76 | 77 | // must be last; used as counter. 78 | NETDATA_HARDIRQ_STATIC_END 79 | }; 80 | 81 | typedef struct hardirq_val { 82 | // incremental counter storing the total latency so far. 83 | u64 latency; 84 | 85 | // temporary timestamp stored at the IRQ entry handler, to be diff'd with a 86 | // timestamp at the IRQ exit handler, to get the latency to add to the 87 | // `latency` field. 88 | u64 ts; 89 | } hardirq_val_t; 90 | 91 | #endif /* _NETDATA_HARDIRQ_H_ */ 92 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Builds and Releases packages for eBPF to be consumed by Netdata Agent 3 | name: CD 4 | on: 5 | push: 6 | tags: 7 | - 'v*' 8 | concurrency: 9 | group: cd-${{ github.ref }} 10 | cancel-in-progress: true 11 | jobs: 12 | build-artifacts: 13 | name: Build Artifacts 14 | strategy: 15 | matrix: 16 | kernel_version: 17 | - '6.16.2' 18 | - '6.8.2' 19 | - '5.16.18' 20 | - '5.15.63' 21 | - '5.14.0' 22 | - '5.11.19' 23 | - '5.10.139' 24 | - '5.4.210' 25 | - '5.4.17' 26 | - '4.16.18' 27 | - '4.18.0' 28 | - '4.14.291' 29 | libc: 30 | - static 31 | - glibc 32 | - musl 33 | exclude: 34 | - kernel_version: 5.4.17 35 | libc: static 36 | - kernel_version: 5.4.17 37 | libc: musl 38 | runs-on: ubuntu-latest 39 | steps: 40 | - name: Checkout 41 | uses: actions/checkout@v6 42 | with: 43 | submodules: true 44 | fetch-depth: 0 45 | lfs: true 46 | - name: Checkout LFS objects 47 | run: git lfs checkout 48 | - name: Run build.sh 49 | run: | 50 | if [ ${{ matrix.kernel_version }} = "5.14.0" ]; then 51 | os=centos9 52 | elif [ ${{ matrix.kernel_version }} = "5.4.17" ]; then 53 | os=oracle8 54 | elif [ ${{ matrix.kernel_version }} = "4.18.0" ]; then 55 | os=centos8 56 | else 57 | os=generic 58 | fi 59 | ./build.sh ${{ matrix.kernel_version }} ${{ matrix.libc }} "${os}" 60 | - name: List Artifacts 61 | run: | 62 | ls -lah artifacts 63 | test -f artifacts/netdata_ebpf-*.tar 64 | - name: Upload Artifacts 65 | uses: actions/upload-artifact@v6 66 | if: success() 67 | with: 68 | name: artifacts-${{ matrix.kernel_version }}-${{ matrix.libc }} 69 | path: artifacts 70 | 71 | create-release: 72 | name: Create Release 73 | needs: build-artifacts 74 | runs-on: ubuntu-latest 75 | steps: 76 | - name: Checkout 77 | uses: actions/checkout@v6 78 | with: 79 | submodules: true 80 | fetch-depth: 0 81 | lfs: true 82 | - name: Checkout LFS objects 83 | run: git lfs checkout 84 | - name: Download all Artifacts 85 | uses: actions/download-artifact@v7 86 | with: 87 | pattern: artifacts-* 88 | path: artifacts 89 | merge-multiple: true 90 | - name: Set release_tag 91 | run: | 92 | echo "RELEASE_TAG=${GITHUB_REF##*/}" >> $GITHUB_ENV 93 | - name: Consolidate Artifacts 94 | run: | 95 | mkdir -p final-artifacts 96 | for libc in static glibc musl; do 97 | for pkg in artifacts/netdata_ebpf-*_*-${libc}.tar; do 98 | mkdir -p "packages/netdata-kernel-collector-${libc}-${RELEASE_TAG}" 99 | tar -C "packages/netdata-kernel-collector-${libc}-${RELEASE_TAG}" -xvf "${pkg}" 100 | done 101 | if [ "${libc}" == "glibc" ]; then cp -R CentOS7/* "packages/netdata-kernel-collector-${libc}-${RELEASE_TAG}"; fi 102 | tar -C "packages/netdata-kernel-collector-${libc}-${RELEASE_TAG}" -Jcvf "final-artifacts/netdata-kernel-collector-${libc}-${RELEASE_TAG}.tar.xz" ./ 103 | done 104 | cd final-artifacts && sha256sum ./*.tar.xz > sha256sums.txt 105 | - name: Create Release 106 | uses: ncipollo/release-action@v1 107 | with: 108 | allowUpdates: false 109 | artifactErrorsFailBuild: true 110 | artifacts: 'final-artifacts/*' 111 | draft: true 112 | token: ${{ secrets.NETDATABOT_GITHUB_TOKEN }} 113 | -------------------------------------------------------------------------------- /kernel/DEVELOPER.md: -------------------------------------------------------------------------------- 1 | # Developers 2 | 3 | This MD file was added to help developers starting with eBPF development. 4 | 5 | In this repo we are using the same [pattern](https://elixir.bootlin.com/linux/v4.20.17/source/samples/bpf) that was used before 6 | [BTF](https://docs.kernel.org/bpf/btf.html) was released. All source files ending with `_kern.c` are eBPF codes 7 | loaded inside `kernel ring`. We do no have a `_user.c` for each one of `_kern.c` files, because we have a common loader for 8 | all (`tester_user.c`). 9 | 10 | ## Libbpf 11 | 12 | This repo is currently using two libbpf versions. We are using the [latest](https://github.com/netdata/libbpf) for kernels newer 13 | than `4.11`, and we still use version `0.0.9` to support `CentOS 7.9`. The transition between versions is done during compilation 14 | time using a [script](https://github.com/netdata/kernel-collector/blob/master/.dockerfiles/change_libbpf.sh). 15 | 16 | ## Internal Code division 17 | 18 | All eBPF sources are split in three sections: 19 | 20 | - Headers 21 | - Tables 22 | - Tracers 23 | 24 | 25 | ### Headers 26 | 27 | Netdata headers are defined inside directory `includes/`. 28 | 29 | All other headers used in `_kern.c` files are inside kernel source and you can generate them with commands: 30 | 31 | ```sh 32 | KERNEL_VERSION=`uname -r` 33 | if [ "${KERNEL_VERSION}" != "3.10.0-1160.76.1.el7" ]; then 34 | make defconfig -C /usr/src/linux 35 | else 36 | make silentoldconfig -C /usr/src/linux 37 | fi 38 | make scripts -C /usr/src/linux 39 | make prepare -C /usr/src/linux 40 | make headers_install -C /usr/src/linux 41 | ``` 42 | 43 | You can take a look in our [docker image](https://github.com/netdata/kernel-collector/blob/master/Dockerfile.glibc.generic) how 44 | to get specific kernels from [kernel.org](https://kernel.org/). 45 | 46 | Our headers always start with prefix `netdata_` and we append the associated `eBPF` code after `_`, the exceptions for this rule 47 | are: 48 | 49 | - `netdata_common.h`: that has common functions used inside all eBPF programs; 50 | - `netdata_defs.h`: Constants used inside hash tables 51 | - `netdata_asm_goto.h`: Used to compile old RH kernels. 52 | 53 | ### Tables 54 | 55 | Tables are defined according `LIBBPF` version, but we are defining their declarations according kernel version to avoid 56 | unnecessary headers inside eBPF codes. Thanks this every time you see the preprocessor like this 57 | 58 | ```sh 59 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 60 | ``` 61 | 62 | means that we are using codes that will be compiled with latest `libbpf` version. 63 | 64 | 65 | For all hash tables we are defining: 66 | 67 | - Type: We are working with [HASH](https://docs.kernel.org/bpf/map_hash.html) and [ARRAY](https://docs.kernel.org/bpf/map_array.html) 68 | - Key size: the size in bytes of the key. 69 | - Value size: the size in bytes of the value. 70 | - Max entries: Number of entries expected in the table. 71 | 72 | ### Tracers 73 | 74 | In this repo we use the following tracers: 75 | 76 | - probes: They can be `kprobe` or `kretprobe`. The first is added when we wish to monitor calls for the function, while the second 77 | monitors not only the calls, but also returns from functions. 78 | - tracepoints: provides a [hook](https://docs.kernel.org/trace/tracepoints.html) to call functions. 79 | 80 | There are other tracers like `uprobe` that we are not working right now, and `trampolines` that we have a specific 81 | [repo](https://github.com/netdata/ebpf-co-re) for them. 82 | 83 | ## Binaries 84 | 85 | Binaries are compiled in accordance to kernel version, the list of binaries are defined in our 86 | [Makefile](https://github.com/netdata/kernel-collector/blob/84e70d0ae83cc91fee59053459eff84f9077d2c5/kernel/Makefile#L66-L88). 87 | 88 | When needed to compile everything during development, we can run the command: 89 | 90 | ```sh 91 | make dev 92 | ``` 93 | 94 | ## Tests 95 | 96 | The tester is not compiled by default. To compile it and run all common tests run: 97 | 98 | ```sh 99 | make dev 100 | for j in `seq 0 2`; do for i in `ls *.o`; do ./kernel/legacy_test --content --pid $j --load-binary $i --log-path $i_pid$i.txt; 2>> err >> out; done; done 101 | ``` 102 | 103 | You can take a look in all options available for tests running: 104 | 105 | ```sh 106 | ./kernel/legacy_test --help 107 | ``` 108 | 109 | -------------------------------------------------------------------------------- /.github/workflows/review.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Runs various ReviewDog based checks against PR with suggested changes to improve quality 3 | name: Review 4 | on: 5 | pull_request: 6 | env: 7 | DO_NOT_TRACK: 1 8 | concurrency: 9 | group: review-${{ github.ref }} 10 | cancel-in-progress: true 11 | jobs: 12 | prep-review: 13 | name: Prepare Review Jobs 14 | runs-on: ubuntu-latest 15 | outputs: 16 | actionlint: ${{ steps.actionlint.outputs.run }} 17 | hadolint: ${{ steps.hadolint.outputs.run }} 18 | shellcheck: ${{ steps.shellcheck.outputs.run }} 19 | yamllint: ${{ steps.yamllint.outputs.run }} 20 | steps: 21 | - name: Clone repository 22 | uses: actions/checkout@v6 23 | with: 24 | submodules: recursive 25 | fetch-depth: 0 26 | - name: Check files for actionlint 27 | id: actionlint 28 | run: | 29 | if git diff --name-only origin/${{ github.base_ref }} HEAD | grep -Eq '\.github/workflows/.*' ; then 30 | echo "run=true" >> $GITHUB_OUTPUT 31 | echo 'GitHub Actions workflows have changed, need to run actionlint.' 32 | else 33 | echo "run=false" >> $GITHUB_OUTPUT 34 | fi 35 | - name: Check files for hadolint 36 | id: hadolint 37 | run: | 38 | if git diff --name-only origin/${{ github.base_ref }} HEAD | grep -Eq '.*Dockerfile.*' ; then 39 | echo "run=true" >> $GITHUB_OUTPUT 40 | echo 'Dockerfiles have changed, need to run Hadolint.' 41 | else 42 | echo "run=false" >> $GITHUB_OUTPUT 43 | fi 44 | - name: Check files for shellcheck 45 | id: shellcheck 46 | run: | 47 | if git diff --name-only origin/${{ github.base_ref }} HEAD | grep -Eq '.*\.sh.*' ; then 48 | echo "run=true" >> $GITHUB_OUTPUT 49 | echo 'Shell scripts have changed, need to run shellcheck.' 50 | else 51 | echo "run=false" >> $GITHUB_OUTPUT 52 | fi 53 | - name: Check files for yamllint 54 | id: yamllint 55 | run: | 56 | if git diff --name-only origin/${{ github.base_ref }} HEAD | grep -Eq '.*\.ya?ml' ; then 57 | echo "run=true" >> $GITHUB_OUTPUT 58 | echo 'YAML files have changed, need to run yamllint.' 59 | else 60 | echo "run=false" >> $GITHUB_OUTPUT 61 | fi 62 | 63 | actionlint: 64 | name: actionlint 65 | needs: prep-review 66 | if: needs.prep-review.outputs.actionlint == 'true' 67 | runs-on: ubuntu-latest 68 | steps: 69 | - name: Git clone repository 70 | uses: actions/checkout@v6 71 | with: 72 | submodules: recursive 73 | fetch-depth: 0 74 | - name: Run actionlint 75 | uses: reviewdog/action-actionlint@v1 76 | with: 77 | github_token: ${{ secrets.GITHUB_TOKEN }} 78 | reporter: github-pr-check 79 | 80 | hadolint: 81 | name: hadolint 82 | needs: prep-review 83 | if: needs.prep-review.outputs.hadolint == 'true' 84 | runs-on: ubuntu-latest 85 | steps: 86 | - name: Git clone repository 87 | uses: actions/checkout@v6 88 | with: 89 | fetch-depth: 0 90 | - name: Run hadolint 91 | uses: reviewdog/action-hadolint@v1 92 | with: 93 | github_token: ${{ secrets.GITHUB_TOKEN }} 94 | reporter: github-pr-check 95 | 96 | shellcheck: 97 | name: shellcheck 98 | needs: prep-review 99 | if: needs.prep-review.outputs.shellcheck == 'true' 100 | runs-on: ubuntu-latest 101 | steps: 102 | - name: Git clone repository 103 | uses: actions/checkout@v6 104 | with: 105 | submodules: recursive 106 | fetch-depth: 0 107 | - name: Run shellcheck 108 | uses: reviewdog/action-shellcheck@v1 109 | with: 110 | github_token: ${{ secrets.GITHUB_TOKEN }} 111 | reporter: github-pr-check 112 | path: "." 113 | pattern: "*.sh*" 114 | exclude: "./.git/*" 115 | 116 | yamllint: 117 | name: yamllint 118 | needs: prep-review 119 | if: needs.prep-review.outputs.yamllint == 'true' 120 | runs-on: ubuntu-latest 121 | steps: 122 | - name: Git clone repository 123 | uses: actions/checkout@v6 124 | with: 125 | submodules: recursive 126 | fetch-depth: 0 127 | - name: Run yamllint 128 | uses: reviewdog/action-yamllint@v1 129 | with: 130 | github_token: ${{ secrets.GITHUB_TOKEN }} 131 | reporter: github-pr-check 132 | -------------------------------------------------------------------------------- /kernel/disk_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "disk_netdata" 2 | #include 3 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)) 4 | #include 5 | #endif 6 | 7 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(6,0,0)) 8 | #include 9 | #endif 10 | 11 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 12 | #include 13 | #else 14 | #include 15 | #endif 16 | #include "bpf_tracing.h" 17 | #include "bpf_helpers.h" 18 | #include "netdata_ebpf.h" 19 | 20 | /************************************************************************************ 21 | * 22 | * MAPS 23 | * 24 | ***********************************************************************************/ 25 | 26 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 27 | //Hardware 28 | struct { 29 | __uint(type, BPF_MAP_TYPE_PERCPU_HASH); 30 | __type(key, block_key_t); 31 | __type(value, __u64); 32 | __uint(max_entries, NETDATA_DISK_HISTOGRAM_LENGTH); 33 | } tbl_disk_iocall SEC(".maps"); 34 | 35 | // Temporary use only 36 | struct { 37 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) 38 | __uint(type, BPF_MAP_TYPE_HASH); 39 | #else 40 | __uint(type, BPF_MAP_TYPE_PERCPU_HASH); 41 | #endif 42 | __type(key, netdata_disk_key_t); 43 | __type(value, __u64); 44 | __uint(max_entries, 8192); 45 | } tmp_disk_tp_stat SEC(".maps"); 46 | 47 | struct { 48 | __uint(type, BPF_MAP_TYPE_ARRAY); 49 | __type(key, __u32); 50 | __type(value, __u64); 51 | __uint(max_entries, NETDATA_CONTROLLER_END); 52 | } disk_ctrl SEC(".maps"); 53 | 54 | #else 55 | 56 | //Hardware 57 | struct bpf_map_def SEC("maps") tbl_disk_iocall = { 58 | .type = BPF_MAP_TYPE_HASH, 59 | .key_size = sizeof(block_key_t), 60 | .value_size = sizeof(__u64), 61 | .max_entries = NETDATA_DISK_HISTOGRAM_LENGTH 62 | }; 63 | 64 | // Temporary use only 65 | struct bpf_map_def SEC("maps") tmp_disk_tp_stat = { 66 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) 67 | .type = BPF_MAP_TYPE_HASH, 68 | #else 69 | .type = BPF_MAP_TYPE_PERCPU_HASH, 70 | #endif 71 | .key_size = sizeof(netdata_disk_key_t), 72 | .value_size = sizeof(__u64), 73 | .max_entries = 8192 74 | }; 75 | 76 | struct bpf_map_def SEC("maps") disk_ctrl = { 77 | .type = BPF_MAP_TYPE_ARRAY, 78 | .key_size = sizeof(__u32), 79 | .value_size = sizeof(__u64), 80 | .max_entries = NETDATA_CONTROLLER_END 81 | }; 82 | 83 | #endif 84 | 85 | /************************************************************************************ 86 | * 87 | * DISK SECTION 88 | * 89 | ***********************************************************************************/ 90 | 91 | // Probably it is available after 4.13 only 92 | 93 | SEC("tracepoint/block/block_rq_issue") 94 | int netdata_block_rq_issue(struct netdata_block_rq_issue *ptr) 95 | { 96 | // blkid generates these and we're not interested in them 97 | if (!ptr->dev) 98 | return 0; 99 | 100 | netdata_disk_key_t key = {}; 101 | key.dev = ptr->dev; 102 | key.sector = ptr->sector; 103 | 104 | if (key.sector < 0) 105 | key.sector = 0; 106 | 107 | __u64 value = bpf_ktime_get_ns(); 108 | 109 | bpf_map_update_elem(&tmp_disk_tp_stat, &key, &value, BPF_ANY); 110 | 111 | libnetdata_update_global(&disk_ctrl, NETDATA_CONTROLLER_PID_TABLE_ADD, 1); 112 | 113 | return 0; 114 | } 115 | 116 | SEC("tracepoint/block/block_rq_complete") 117 | int netdata_block_rq_complete(struct netdata_block_rq_complete *ptr) 118 | { 119 | __u64 *fill; 120 | netdata_disk_key_t key = {}; 121 | block_key_t blk = {}; 122 | key.dev = ptr->dev; 123 | key.sector = ptr->sector; 124 | 125 | if (key.sector < 0) 126 | key.sector = 0; 127 | 128 | fill = bpf_map_lookup_elem(&tmp_disk_tp_stat ,&key); 129 | if (!fill) 130 | return 0; 131 | 132 | // calculate and convert to microsecond 133 | u64 curr = bpf_ktime_get_ns(); 134 | __u64 data, *update; 135 | curr -= *fill; 136 | curr /= 1000; 137 | 138 | blk.bin = libnetdata_select_idx(curr, NETDATA_FS_MAX_BINS_POS); 139 | blk.dev = new_encode_dev(ptr->dev); 140 | 141 | // Update IOPS 142 | update = bpf_map_lookup_elem(&tbl_disk_iocall ,&blk); 143 | if (update) { 144 | libnetdata_update_u64(update, 1); 145 | } else { 146 | data = 1; 147 | bpf_map_update_elem(&tbl_disk_iocall, &blk, &data, BPF_ANY); 148 | } 149 | 150 | bpf_map_delete_elem(&tmp_disk_tp_stat, &key); 151 | 152 | libnetdata_update_global(&disk_ctrl, NETDATA_CONTROLLER_PID_TABLE_DEL, 1); 153 | 154 | return 0; 155 | } 156 | 157 | char _license[] SEC("license") = "GPL"; 158 | 159 | -------------------------------------------------------------------------------- /kernel/swap_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "swap_netdata" 2 | 3 | #include 4 | 5 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 6 | #include 7 | #else 8 | #include 9 | #endif 10 | #include "bpf_tracing.h" 11 | #include "bpf_helpers.h" 12 | #include "netdata_ebpf.h" 13 | 14 | /************************************************************************************ 15 | * 16 | * MAPS 17 | * 18 | ***********************************************************************************/ 19 | 20 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 21 | struct { 22 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 23 | __type(key, __u32); 24 | __type(value, __u64); 25 | __uint(max_entries, NETDATA_SWAP_END); 26 | } tbl_swap SEC(".maps"); 27 | 28 | struct { 29 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) 30 | __uint(type, BPF_MAP_TYPE_HASH); 31 | #else 32 | __uint(type, BPF_MAP_TYPE_PERCPU_HASH); 33 | #endif 34 | __type(key, __u32); 35 | __type(value, netdata_swap_access_t); 36 | __uint(max_entries, PID_MAX_DEFAULT); 37 | } tbl_pid_swap SEC(".maps"); 38 | 39 | struct { 40 | __uint(type, BPF_MAP_TYPE_ARRAY); 41 | __type(key, __u32); 42 | __type(value, __u64); 43 | __uint(max_entries, NETDATA_CONTROLLER_END); 44 | } swap_ctrl SEC(".maps"); 45 | #else 46 | struct bpf_map_def SEC("maps") tbl_swap = { 47 | .type = BPF_MAP_TYPE_PERCPU_ARRAY, 48 | .key_size = sizeof(__u32), 49 | .value_size = sizeof(__u64), 50 | .max_entries = NETDATA_SWAP_END 51 | }; 52 | 53 | struct bpf_map_def SEC("maps") tbl_pid_swap = { 54 | .type = BPF_MAP_TYPE_HASH, 55 | .key_size = sizeof(__u32), 56 | .value_size = sizeof(netdata_swap_access_t), 57 | .max_entries = PID_MAX_DEFAULT 58 | }; 59 | 60 | struct bpf_map_def SEC("maps") swap_ctrl = { 61 | .type = BPF_MAP_TYPE_ARRAY, 62 | .key_size = sizeof(__u32), 63 | .value_size = sizeof(__u64), 64 | .max_entries = NETDATA_CONTROLLER_END 65 | }; 66 | #endif 67 | 68 | /************************************************************************************ 69 | * 70 | * SWAP SECTION 71 | * 72 | ***********************************************************************************/ 73 | 74 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(6,7,255)) 75 | SEC("kprobe/swap_read_folio") 76 | #else 77 | SEC("kprobe/swap_readpage") 78 | #endif 79 | int netdata_swap_readpage(struct pt_regs* ctx) 80 | { 81 | netdata_swap_access_t data = {}; 82 | 83 | libnetdata_update_global(&tbl_swap, NETDATA_KEY_SWAP_READPAGE_CALL, 1); 84 | 85 | __u32 key = 0; 86 | __u32 tgid = 0; 87 | if (!monitor_apps(&swap_ctrl)) 88 | return 0; 89 | 90 | netdata_swap_access_t *fill = netdata_get_pid_structure(&key, &tgid, &swap_ctrl, &tbl_pid_swap); 91 | if (fill) { 92 | libnetdata_update_u32(&fill->read, 1); 93 | } else { 94 | data.ct = bpf_ktime_get_ns(); 95 | libnetdata_update_uid_gid(&data.uid, &data.gid); 96 | data.tgid = tgid; 97 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 98 | bpf_get_current_comm(&data.name, TASK_COMM_LEN); 99 | #else 100 | data.name[0] = '\0'; 101 | #endif 102 | 103 | data.read = 1; 104 | bpf_map_update_elem(&tbl_pid_swap, &key, &data, BPF_ANY); 105 | 106 | libnetdata_update_global(&swap_ctrl, NETDATA_CONTROLLER_PID_TABLE_ADD, 1); 107 | } 108 | 109 | return 0; 110 | } 111 | 112 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,16,0)) 113 | SEC("kprobe/__swap_writepage") 114 | #else 115 | SEC("kprobe/swap_writepage") 116 | #endif 117 | int netdata_swap_writepage(struct pt_regs* ctx) 118 | { 119 | netdata_swap_access_t data = {}; 120 | 121 | libnetdata_update_global(&tbl_swap, NETDATA_KEY_SWAP_WRITEPAGE_CALL, 1); 122 | 123 | __u32 key = 0; 124 | __u32 tgid = 0; 125 | if (!monitor_apps(&swap_ctrl)) 126 | return 0; 127 | 128 | netdata_swap_access_t *fill = netdata_get_pid_structure(&key, &tgid, &swap_ctrl, &tbl_pid_swap); 129 | if (fill) { 130 | libnetdata_update_u32(&fill->write, 1); 131 | } else { 132 | data.ct = bpf_ktime_get_ns(); 133 | libnetdata_update_uid_gid(&data.uid, &data.gid); 134 | data.tgid = tgid; 135 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 136 | bpf_get_current_comm(&data.name, TASK_COMM_LEN); 137 | #else 138 | data.name[0] = '\0'; 139 | #endif 140 | 141 | data.write = 1; 142 | bpf_map_update_elem(&tbl_pid_swap, &key, &data, BPF_ANY); 143 | 144 | libnetdata_update_global(&swap_ctrl, NETDATA_CONTROLLER_PID_TABLE_ADD, 1); 145 | } 146 | 147 | return 0; 148 | } 149 | 150 | char _license[] SEC("license") = "GPL"; 151 | 152 | -------------------------------------------------------------------------------- /kernel/dc_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "dc_kern" 2 | 3 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 4 | #include 5 | #else 6 | #include 7 | #endif 8 | #include "bpf_tracing.h" 9 | #include "bpf_helpers.h" 10 | #include "netdata_ebpf.h" 11 | 12 | /************************************************************************************ 13 | * 14 | * Maps Section 15 | * 16 | ***********************************************************************************/ 17 | 18 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 19 | struct { 20 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 21 | __type(key, __u32); 22 | __type(value, __u64); 23 | __uint(max_entries, NETDATA_DIRECTORY_CACHE_END); 24 | } dcstat_global SEC(".maps"); 25 | 26 | struct { 27 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) 28 | __uint(type, BPF_MAP_TYPE_HASH); 29 | #else 30 | __uint(type, BPF_MAP_TYPE_PERCPU_HASH); 31 | #endif 32 | __type(key, __u32); 33 | __type(value, netdata_dc_stat_t); 34 | __uint(max_entries, PID_MAX_DEFAULT); 35 | } dcstat_pid SEC(".maps"); 36 | 37 | struct { 38 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 39 | __type(key, __u32); 40 | __type(value, __u64); 41 | __uint(max_entries, NETDATA_CONTROLLER_END); 42 | } dcstat_ctrl SEC(".maps"); 43 | 44 | #else 45 | 46 | struct bpf_map_def SEC("maps") dcstat_global = { 47 | .type = BPF_MAP_TYPE_PERCPU_ARRAY, 48 | .key_size = sizeof(__u32), 49 | .value_size = sizeof(__u64), 50 | .max_entries = NETDATA_DIRECTORY_CACHE_END 51 | }; 52 | 53 | struct bpf_map_def SEC("maps") dcstat_pid = { 54 | .type = BPF_MAP_TYPE_HASH, 55 | .key_size = sizeof(__u32), 56 | .value_size = sizeof(netdata_dc_stat_t), 57 | .max_entries = PID_MAX_DEFAULT 58 | }; 59 | 60 | struct bpf_map_def SEC("maps") dcstat_ctrl = { 61 | .type = BPF_MAP_TYPE_ARRAY, 62 | .key_size = sizeof(__u32), 63 | .value_size = sizeof(__u64), 64 | .max_entries = NETDATA_CONTROLLER_END 65 | }; 66 | 67 | #endif 68 | 69 | /************************************************************************************ 70 | * 71 | * Probe Section 72 | * 73 | ***********************************************************************************/ 74 | 75 | SEC("kprobe/lookup_fast") 76 | int netdata_lookup_fast(struct pt_regs* ctx) 77 | { 78 | netdata_dc_stat_t *fill, data = {}; 79 | libnetdata_update_global(&dcstat_global, NETDATA_KEY_DC_REFERENCE, 1); 80 | 81 | __u32 key = 0; 82 | __u32 tgid = 0; 83 | if (!monitor_apps(&dcstat_ctrl)) 84 | return 0; 85 | 86 | fill = netdata_get_pid_structure(&key, &tgid, &dcstat_ctrl, &dcstat_pid); 87 | if (fill) { 88 | libnetdata_update_u32(&fill->references, 1); 89 | } else { 90 | data.ct = bpf_ktime_get_ns(); 91 | libnetdata_update_uid_gid(&data.uid, &data.gid); 92 | data.tgid = tgid; 93 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 94 | bpf_get_current_comm(&data.name, TASK_COMM_LEN); 95 | #else 96 | data.name[0] = '\0'; 97 | #endif 98 | 99 | data.references = 1; 100 | bpf_map_update_elem(&dcstat_pid, &key, &data, BPF_ANY); 101 | 102 | libnetdata_update_global(&dcstat_ctrl, NETDATA_CONTROLLER_PID_TABLE_ADD, 1); 103 | } 104 | 105 | return 0; 106 | } 107 | 108 | SEC("kretprobe/d_lookup") 109 | int netdata_d_lookup(struct pt_regs* ctx) 110 | { 111 | netdata_dc_stat_t *fill, data = {}; 112 | libnetdata_update_global(&dcstat_global, NETDATA_KEY_DC_SLOW, 1); 113 | 114 | int ret = PT_REGS_RC(ctx); 115 | 116 | __u32 key = 0; 117 | __u32 tgid = 0; 118 | if (!monitor_apps(&dcstat_ctrl)) 119 | return 0; 120 | 121 | fill = netdata_get_pid_structure(&key, &tgid, &dcstat_ctrl, &dcstat_pid); 122 | if (fill) { 123 | libnetdata_update_u32(&fill->slow, 1); 124 | } else { 125 | data.ct = bpf_ktime_get_ns(); 126 | libnetdata_update_uid_gid(&data.uid, &data.gid); 127 | data.tgid = tgid; 128 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 129 | bpf_get_current_comm(&data.name, TASK_COMM_LEN); 130 | #else 131 | data.name[0] = '\0'; 132 | #endif 133 | 134 | data.slow = 1; 135 | bpf_map_update_elem(&dcstat_pid, &key, &data, BPF_ANY); 136 | 137 | libnetdata_update_global(&dcstat_ctrl, NETDATA_CONTROLLER_PID_TABLE_ADD, 1); 138 | } 139 | 140 | // file not found 141 | if (ret == 0) { 142 | libnetdata_update_global(&dcstat_global, NETDATA_KEY_DC_MISS, 1); 143 | fill = netdata_get_pid_structure(&key, &tgid, &dcstat_ctrl, &dcstat_pid); 144 | if (fill) { 145 | libnetdata_update_u32(&fill->missed, 1); 146 | } 147 | } 148 | 149 | return 0; 150 | } 151 | 152 | char _license[] SEC("license") = "GPL"; 153 | 154 | -------------------------------------------------------------------------------- /includes/netdata_socket.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_NETWORK_H_ 4 | #define _NETDATA_NETWORK_H_ 1 5 | 6 | // Conflict with CO-RE code 7 | // #include 8 | 9 | /** 10 | * SOCKET 11 | */ 12 | 13 | /** 14 | * Union used to store ip addresses 15 | */ 16 | union netdata_ip { 17 | __u8 addr8[16]; 18 | __u16 addr16[8]; 19 | __u32 addr32[4]; 20 | __u64 addr64[2]; 21 | }; 22 | 23 | typedef struct netdata_socket { 24 | char name[TASK_COMM_LEN]; 25 | 26 | // Timestamp 27 | __u64 first; // First timestamp 28 | __u64 ct; // Current timestamp 29 | // Socket additional info 30 | __u16 protocol; 31 | __u16 family; 32 | __u32 external_origin; // We are using only lower bits, so if it is 33 | // necessary to store more info, this shoud be 34 | // split in two __u16. 35 | // Stats 36 | // Number of bytes 37 | struct { 38 | __u32 call_tcp_sent; 39 | __u32 call_tcp_received; 40 | __u64 tcp_bytes_sent; 41 | __u64 tcp_bytes_received; 42 | __u32 close; //It is never used with UDP 43 | __u32 retransmit; //It is never used with UDP 44 | __u32 ipv4_connect; // Use to count new connections 45 | __u32 ipv6_connect; // Use to count new connections 46 | __u32 state; //Current socket state 47 | } tcp; 48 | // Number of calls 49 | struct { 50 | __u32 call_udp_sent; // Use to count new connections 51 | __u32 call_udp_received; 52 | __u64 udp_bytes_sent; 53 | __u64 udp_bytes_received; 54 | } udp; 55 | } netdata_socket_t; 56 | 57 | typedef struct netdata_bandwidth { 58 | __u64 first; 59 | __u64 ct; 60 | __u64 bytes_sent; 61 | __u64 bytes_received; 62 | __u64 call_tcp_sent; 63 | __u64 call_tcp_received; 64 | __u64 retransmit; 65 | __u64 call_udp_sent; 66 | __u64 call_udp_received; 67 | __u64 close; 68 | __u32 ipv4_connect; 69 | __u32 ipv6_connect; 70 | } netdata_bandwidth_t; 71 | 72 | // Index used together previous structure 73 | typedef struct netdata_socket_idx { 74 | union netdata_ip saddr; 75 | //__u16 sport; 76 | union netdata_ip daddr; 77 | __u16 dport; 78 | __u32 pid; 79 | } netdata_socket_idx_t; 80 | 81 | typedef struct netdata_passive_connection { 82 | __u32 tgid; 83 | __u32 pid; 84 | __u64 counter; 85 | } netdata_passive_connection_t; 86 | 87 | typedef struct netdata_passive_connection_idx { 88 | __u16 protocol; 89 | __u16 port; 90 | } netdata_passive_connection_idx_t; 91 | 92 | enum socket_counters { 93 | NETDATA_KEY_CALLS_TCP_SENDMSG, 94 | NETDATA_KEY_ERROR_TCP_SENDMSG, 95 | NETDATA_KEY_BYTES_TCP_SENDMSG, 96 | 97 | NETDATA_KEY_CALLS_TCP_CLEANUP_RBUF, 98 | NETDATA_KEY_ERROR_TCP_CLEANUP_RBUF, 99 | NETDATA_KEY_BYTES_TCP_CLEANUP_RBUF, 100 | 101 | NETDATA_KEY_CALLS_TCP_CLOSE, 102 | 103 | NETDATA_KEY_CALLS_UDP_RECVMSG, 104 | NETDATA_KEY_ERROR_UDP_RECVMSG, 105 | NETDATA_KEY_BYTES_UDP_RECVMSG, 106 | 107 | NETDATA_KEY_CALLS_UDP_SENDMSG, 108 | NETDATA_KEY_ERROR_UDP_SENDMSG, 109 | NETDATA_KEY_BYTES_UDP_SENDMSG, 110 | 111 | NETDATA_KEY_TCP_RETRANSMIT, 112 | 113 | NETDATA_KEY_CALLS_TCP_CONNECT_IPV4, 114 | NETDATA_KEY_ERROR_TCP_CONNECT_IPV4, 115 | 116 | NETDATA_KEY_CALLS_TCP_CONNECT_IPV6, 117 | NETDATA_KEY_ERROR_TCP_CONNECT_IPV6, 118 | 119 | NETDATA_KEY_CALLS_TCP_SET_STATE, 120 | 121 | // Keep this as last and don't skip numbers as it is used as element counter 122 | NETDATA_SOCKET_COUNTER 123 | }; 124 | 125 | enum socket_functions { 126 | NETDATA_FCNT_INET_CSK_ACCEPT, 127 | NETDATA_FCNT_TCP_RETRANSMIT, 128 | NETDATA_FCNT_CLEANUP_RBUF, 129 | NETDATA_FCNT_TCP_CLOSE, 130 | NETDATA_FCNT_UDP_RECEVMSG, 131 | NETDATA_FCNT_TCP_SENDMSG, 132 | NETDATA_FCNT_UDP_SENDMSG, 133 | NETDATA_FCNT_TCP_V4_CONNECT, 134 | NETDATA_FCNT_TCP_V6_CONNECT, 135 | NETDATA_FCNT_TCP_SET_STATE, 136 | 137 | NETDATA_SOCKET_FCNT_END 138 | }; 139 | 140 | /** 141 | * NETWORK VIEWER 142 | */ 143 | 144 | typedef enum __attribute__((packed)) { 145 | NETDATA_SOCKET_DIRECTION_NONE = 0, 146 | NETDATA_SOCKET_DIRECTION_LISTEN = (1 << 0), // a listening socket 147 | NETDATA_SOCKET_DIRECTION_INBOUND = (1 << 1), // an inbound socket connecting a remote system to a local listening socket 148 | NETDATA_SOCKET_DIRECTION_OUTBOUND = (1 << 2), // a socket initiated by this system, connecting to another system 149 | NETDATA_SOCKET_DIRECTION_LOCAL_INBOUND = (1 << 3), // the socket connecting 2 localhost applications 150 | NETDATA_SOCKET_DIRECTION_LOCAL_OUTBOUND = (1 << 4), // the socket connecting 2 localhost applications 151 | } NETDATA_SOCKET_DIRECTION; 152 | 153 | // simplified version from https://elixir.bootlin.com/linux/v3.19.8/source/include/uapi/linux/in6.h 154 | struct netdata_in6_addr { 155 | union { 156 | __u8 u6_addr8[16]; 157 | } in6_u; 158 | }; 159 | 160 | union ipv46 { 161 | uint32_t ipv4; 162 | struct netdata_in6_addr ipv6; 163 | }; 164 | 165 | typedef struct netdata_nv_idx { 166 | union ipv46 saddr; 167 | union ipv46 daddr; 168 | __u16 sport; 169 | __u16 dport; 170 | } netdata_nv_idx_t; 171 | 172 | typedef struct netdata_nv_data { 173 | int state; 174 | 175 | __u32 pid; 176 | __u32 tgid; 177 | __u32 uid; 178 | __u64 ts; 179 | 180 | __u8 timer; 181 | __u8 retransmits; 182 | __u16 closed; 183 | __u32 expires; 184 | __u32 rqueue; 185 | __u32 wqueue; 186 | 187 | char name[TASK_COMM_LEN]; 188 | 189 | NETDATA_SOCKET_DIRECTION direction; 190 | 191 | __u16 family; 192 | __u16 protocol; 193 | } netdata_nv_data_t; 194 | 195 | 196 | #endif /* _NETDATA_NETWORK_H_ */ 197 | -------------------------------------------------------------------------------- /kernel/tester_user.h: -------------------------------------------------------------------------------- 1 | #ifndef NETDATA_LEGACY_TESTER 2 | #define NETDATA_LEGACY_TESTER 1 3 | 4 | #include 5 | #include 6 | 7 | #include "../includes/netdata_defs.h" 8 | 9 | #define VERSION_STRING_LEN 256 10 | #define NETDATA_EBPF_PROGRAM_LEN VERSION_STRING_LEN 11 | 12 | 13 | /** 14 | * The RedHat magic number was got doing: 15 | * 16 | * 1797 = 7*256 + 5 17 | * 18 | * For more details, please, read /usr/include/linux/version.h 19 | * in any Red Hat installation. 20 | */ 21 | #define NETDATA_MINIMUM_RH_VERSION 1797 22 | 23 | /** 24 | * 2048 = 8*256 + 0 25 | */ 26 | #define NETDATA_RH_8 2048 27 | 28 | /** 29 | * Kernel Version 30 | * 31 | * Kernel versions are calculated using the following formula: 32 | * 33 | * VERSION = LINUX_VERSION_MAJOR*65536 + LINUX_VERSION_PATCHLEVEL*256 + LINUX_VERSION_SUBLEVEL 34 | * 35 | * Where LINUX_VERSION_MAJOR, LINUX_VERSION_PATCHLEVEL, and LINUX_VERSION_SUBLEVEL are extracted 36 | * from /usr/include/linux/version.h. 37 | * 38 | * LINUX_VERSION_SUBLEVEL has the maximum value 255, but linux can have more SUBLEVELS. 39 | * 40 | */ 41 | enum netdata_ebpf_kernel_versions { 42 | NETDATA_EBPF_KERNEL_4_11 = 264960, // 264960 = 4 * 65536 + 15 * 256 43 | NETDATA_EBPF_KERNEL_4_14 = 265728, // 264960 = 4 * 65536 + 14 * 256 44 | NETDATA_EBPF_KERNEL_4_15 = 265984, // 265984 = 4 * 65536 + 15 * 256 45 | NETDATA_EBPF_KERNEL_4_17 = 266496, // 266496 = 4 * 65536 + 17 * 256 46 | NETDATA_EBPF_KERNEL_5_0 = 327680, // 327680 = 5 * 65536 + 0 * 256 47 | NETDATA_EBPF_KERNEL_5_2 = 328192, // 327680 = 5 * 65536 + 2 * 256 48 | NETDATA_EBPF_KERNEL_5_4 = 328704, // 327680 = 5 * 65536 + 4 * 256 49 | NETDATA_EBPF_KERNEL_5_10 = 330240, // 330240 = 5 * 65536 + 10 * 256 50 | NETDATA_EBPF_KERNEL_5_11 = 330496, // 330240 = 5 * 65536 + 11 * 256 51 | NETDATA_EBPF_KERNEL_5_14 = 331264, // 331264 = 5 * 65536 + 14 * 256 52 | NETDATA_EBPF_KERNEL_5_15 = 331520, // 331520 = 5 * 65536 + 15 * 256 53 | NETDATA_EBPF_KERNEL_5_16 = 331776, // 331776 = 5 * 65536 + 16 * 256 54 | NETDATA_EBPF_KERNEL_6_8 = 395264 // 395264 = 5 * 65536 + 8 * 256 55 | }; 56 | 57 | /** 58 | * Minimum value has relationship with libbpf support. 59 | */ 60 | #define NETDATA_MINIMUM_EBPF_KERNEL NETDATA_EBPF_KERNEL_4_11 61 | 62 | 63 | enum netdata_kernel_flag { 64 | NETDATA_V3_10 = 1 << 0, 65 | NETDATA_V4_14 = 1 << 1, 66 | NETDATA_V4_16 = 1 << 2, 67 | NETDATA_V4_18 = 1 << 3, 68 | NETDATA_V5_4 = 1 << 4, 69 | NETDATA_V5_10 = 1 << 5, 70 | NETDATA_V5_11 = 1 << 6, 71 | NETDATA_V5_14 = 1 << 7, 72 | NETDATA_V5_15 = 1 << 8, 73 | NETDATA_V5_16 = 1 << 9, 74 | NETDATA_V6_8 = 1 << 10 75 | }; 76 | 77 | enum netdata_kernel_counter { 78 | NETDATA_3_10, 79 | NETDATA_4_14, 80 | NETDATA_4_16, 81 | NETDATA_4_18, 82 | NETDATA_5_4, 83 | NETDATA_5_10, 84 | NETDATA_5_11, 85 | NETDATA_5_14, 86 | NETDATA_5_15, 87 | NETDATA_5_16, 88 | NETDATA_6_8, 89 | 90 | NETDATA_VERSION_END 91 | }; 92 | 93 | enum netdata_thread_flag { 94 | NETDATA_FLAG_BTRFS = 1 << 0, 95 | NETDATA_FLAG_CACHESTAT = 1 << 1, 96 | NETDATA_FLAG_DC = 1 << 2, 97 | NETDATA_FLAG_DISK = 1 << 3, 98 | NETDATA_FLAG_EXT4 = 1 << 4, 99 | NETDATA_FLAG_FD = 1 << 5, 100 | NETDATA_FLAG_SYNC = 1 << 6, 101 | NETDATA_FLAG_HARDIRQ = 1 << 7, 102 | NETDATA_FLAG_MDFLUSH = 1 << 8, 103 | NETDATA_FLAG_MOUNT = 1 << 9, 104 | NETDATA_FLAG_NETWORK_VIEWER = 1 << 10, 105 | NETDATA_FLAG_OOMKILL = 1 << 11, 106 | NETDATA_FLAG_PROCESS = 1 << 12, 107 | NETDATA_FLAG_SHM = 1 << 13, 108 | NETDATA_FLAG_SOCKET = 1 << 14, 109 | NETDATA_FLAG_SOFTIRQ = 1 << 15, 110 | NETDATA_FLAG_SWAP = 1 << 16, 111 | NETDATA_FLAG_VFS = 1 << 17, 112 | NETDATA_FLAG_NFS = 1 << 18, 113 | NETDATA_FLAG_XFS = 1 << 19, 114 | NETDATA_FLAG_ZFS = 1 << 20, 115 | NETDATA_FLAG_LOAD_BINARY = 1 << 21, 116 | NETDATA_FLAG_CONTENT = 1 << 22, 117 | 118 | NETDATA_FLAG_FS = (uint64_t)(NETDATA_FLAG_BTRFS | NETDATA_FLAG_EXT4 | NETDATA_FLAG_VFS | NETDATA_FLAG_NFS | NETDATA_FLAG_XFS | NETDATA_FLAG_ZFS), 119 | NETDATA_FLAG_ALL = 0XFFFFFFFFFFFFFFFF 120 | }; 121 | 122 | enum netdata_thread_OPT { 123 | NETDATA_OPT_BTRFS, 124 | NETDATA_OPT_CACHESTAT, 125 | NETDATA_OPT_DC, 126 | NETDATA_OPT_DISK, 127 | NETDATA_OPT_EXT4, 128 | NETDATA_OPT_FD, 129 | NETDATA_OPT_SYNC, 130 | NETDATA_OPT_HARDIRQ, 131 | NETDATA_OPT_MDFLUSH, 132 | NETDATA_OPT_MOUNT, 133 | NETDATA_OPT_NETWORK_VIEWER, 134 | NETDATA_OPT_OOMKILL, 135 | NETDATA_OPT_PROCESS, 136 | NETDATA_OPT_SHM, 137 | NETDATA_OPT_SOCKET, 138 | NETDATA_OPT_SOFTIRQ, 139 | NETDATA_OPT_SWAP, 140 | NETDATA_OPT_VFS, 141 | NETDATA_OPT_NFS, 142 | NETDATA_OPT_XFS, 143 | NETDATA_OPT_ZFS, 144 | 145 | NETDATA_OPT_HELP, 146 | NETDATA_OPT_ALL, 147 | NETDATA_OPT_COMMON, 148 | NETDATA_OPT_LOAD_BINARY, 149 | NETDATA_OPT_NETDATA_PATH, 150 | NETDATA_OPT_LOG_PATH, 151 | NETDATA_OPT_CONTENT, 152 | NETDATA_OPT_ITERATION, 153 | NETDATA_OPT_PID 154 | }; 155 | 156 | typedef struct ebpf_specify_name { 157 | char *program_name; 158 | char *function_to_attach; 159 | char *optional; 160 | bool retprobe; 161 | } ebpf_specify_name_t; 162 | 163 | typedef struct ebpf_module { 164 | uint32_t kernels; 165 | uint64_t flags; 166 | char *name; 167 | ebpf_specify_name_t *update_names; 168 | char *ctrl_table; 169 | } ebpf_module_t ; 170 | 171 | typedef struct ebpf_attach { 172 | struct bpf_link **links; 173 | size_t success; 174 | size_t fail; 175 | } ebpf_attach_t; 176 | 177 | typedef struct ebpf_table_data { 178 | void *key; 179 | void *next_key; 180 | void *value; 181 | void *def_value; 182 | 183 | long key_length; 184 | long value_length; 185 | 186 | size_t filled; 187 | size_t zero; 188 | } ebpf_table_data_t; 189 | 190 | #endif /* NETDATA_LEGACY_TESTER */ 191 | 192 | -------------------------------------------------------------------------------- /includes/netdata_tests.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_TESTS_H_ 4 | #define _NETDATA_TESTS_H_ 1 5 | 6 | #define NETDATA_BTF_FILE "/sys/kernel/btf/vmlinux" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #define NETDATA_CORE_DEFAULT_ERROR "It was not possible to attach JIT code for your kernel, try another\n" \ 21 | "method or use eBPF programs from ../kernel directory.\n " 22 | #define NETDATA_KALLSYMS "/proc/kallsyms" 23 | 24 | // Use __always_inline instead inline to keep compatiblity with old kernels 25 | 26 | static inline int netdata_ebf_memlock_limit(void) 27 | { 28 | struct rlimit r = { RLIM_INFINITY, RLIM_INFINITY }; 29 | if (setrlimit(RLIMIT_MEMLOCK, &r)) { 30 | return -1; 31 | } 32 | 33 | return 0; 34 | } 35 | 36 | static inline struct btf *netdata_parse_btf_file(const char *filename) 37 | { 38 | struct btf *bf = btf__parse(filename, NULL); 39 | if (libbpf_get_error(bf)) { 40 | fprintf(stderr, "Cannot parse btf file"); 41 | btf__free(bf); 42 | } 43 | 44 | return bf; 45 | } 46 | 47 | static inline const struct btf_type *netdata_find_bpf_attach_type(struct btf *bf) 48 | { 49 | int id = btf__find_by_name_kind(bf, "bpf_attach_type", BTF_KIND_ENUM); 50 | if (id < 0) { 51 | fprintf(stderr, "Cannot find 'bpf_attach_type'"); 52 | 53 | return NULL; 54 | } 55 | 56 | return btf__type_by_id(bf, id); 57 | } 58 | 59 | enum netdata_modes { 60 | NETDATA_MODE_TRAMPOLINE, 61 | NETDATA_MODE_PROBE, 62 | NETDATA_MODE_TRACEPOINT 63 | }; 64 | 65 | static inline void ebpf_tracepoint_help(char *name) { 66 | fprintf(stdout, "%s tests if it is possible to use tracepoints on host\n\n" 67 | "--help (-h): Prints this help.\n", name); 68 | } 69 | 70 | 71 | static inline int ebpf_find_function_id(struct btf *bf, char *name) 72 | { 73 | const struct btf_type *type = netdata_find_bpf_attach_type(bf); 74 | if (!type) 75 | return -1; 76 | 77 | const struct btf_enum *e = btf_enum(type); 78 | int i, id; 79 | for (id = -1, i = 0; i < btf_vlen(type); i++, e++) { 80 | if (!strcmp(btf__name_by_offset(bf, e->name_off), "BPF_TRACE_FENTRY")) { 81 | id = btf__find_by_name_kind(bf, name, BTF_KIND_FUNC); 82 | break; 83 | } 84 | } 85 | 86 | return id; 87 | } 88 | 89 | static inline char *ebpf_select_type(int selector) 90 | { 91 | switch(selector) 92 | { 93 | case 0: { 94 | return "trampoline"; 95 | } 96 | case 1: { 97 | return "probe"; 98 | } 99 | case 2: { 100 | return "tracepoint"; 101 | } 102 | } 103 | 104 | return NULL; 105 | } 106 | 107 | static inline void update_controller_table(int fd) 108 | { 109 | uint32_t key = NETDATA_CONTROLLER_APPS_ENABLED; 110 | uint32_t value = 1; 111 | int ret = bpf_map_update_elem(fd, &key, &value, 0); 112 | if (ret) 113 | fprintf(stderr, "Cannot insert value to control table."); 114 | } 115 | 116 | static inline int ebpf_find_functions(struct btf *bf, int selector, char *syscalls[], uint32_t end) 117 | { 118 | if (!bf) 119 | return selector; 120 | 121 | uint32_t i; 122 | for (i = 0; i < end; i++) { 123 | if (ebpf_find_function_id(bf, syscalls[i]) < 0 ) { 124 | fprintf(stderr, "Cannot find function %s\n", syscalls[i]); 125 | selector = NETDATA_MODE_PROBE; 126 | break; 127 | } 128 | } 129 | 130 | return selector; 131 | } 132 | 133 | static inline int ebpf_read_global_array(int fd, int ebpf_nprocs, uint32_t end) 134 | { 135 | uint64_t *stored = calloc((size_t)ebpf_nprocs, sizeof(uint64_t)); 136 | if (!stored) 137 | return 2; 138 | 139 | size_t length = (size_t)ebpf_nprocs * sizeof(uint64_t); 140 | uint32_t idx; 141 | uint64_t counter = 0; 142 | for (idx = 0; idx < end; idx++) { 143 | if (!bpf_map_lookup_elem(fd, &idx, stored)) { 144 | int j; 145 | for (j = 0; j < ebpf_nprocs; j++) { 146 | counter += stored[j]; 147 | } 148 | } 149 | 150 | memset(stored, 0, length); 151 | } 152 | 153 | free(stored); 154 | 155 | // Some testers store only one value, so for every value different of zero 156 | // the result will be successful 157 | if (counter) { 158 | fprintf(stdout, "Global data stored with success\n"); 159 | return 0; 160 | } 161 | 162 | return 2; 163 | } 164 | 165 | static inline pid_t ebpf_fill_global(int fd) 166 | { 167 | pid_t pid = getpid(); 168 | uint32_t idx = 0; 169 | uint64_t value = 1; 170 | 171 | int ret = bpf_map_update_elem(fd, &idx, &value, 0); 172 | if (ret) 173 | fprintf(stderr, "Cannot insert value to global table."); 174 | 175 | return pid; 176 | } 177 | 178 | static inline char *netdata_update_name(char *search) 179 | { 180 | char filename[FILENAME_MAX + 1]; 181 | char data[128]; 182 | char *ret = NULL; 183 | snprintf(filename, FILENAME_MAX, "%s", NETDATA_KALLSYMS); 184 | FILE *fp = fopen(filename, "r"); 185 | if (!fp) 186 | return NULL; 187 | 188 | char *parse; 189 | size_t length = strlen(search); 190 | while ( (parse = fgets(data, 127, fp)) ) { 191 | parse += 19; 192 | if (!strncmp(search, parse, length) ) { 193 | char *end; 194 | for (end = parse; isalnum(*end) || *end == '_' || *end == '.'; end++); 195 | if (end) { 196 | *end = '\0'; 197 | ret = strdup(parse); 198 | } 199 | 200 | break; 201 | } 202 | } 203 | 204 | fclose(fp); 205 | 206 | return ret; 207 | } 208 | 209 | #endif /* _NETDATA_TESTS_H_ */ 210 | 211 | -------------------------------------------------------------------------------- /kernel/Makefile: -------------------------------------------------------------------------------- 1 | CLANG = clang 2 | LLC = llc 3 | KERNELSOURCE = /usr/src/linux 4 | LIBBPF = ../libbpf 5 | LIBBPF_HEADERS = ../.local_libbpf 6 | ARCH := $(shell uname -m | sed 's/x86_64/x86/') 7 | 8 | EXTRA_CFLAGS += -fno-stack-protector 9 | 10 | LINUXINCLUDE += -I$(KERNELSOURCE)/arch/$(ARCH)/include/generated 11 | LINUXINCLUDE += -I$(KERNELSOURCE)/arch/$(ARCH)/include/generated/uapi 12 | LINUXINCLUDE += -I$(KERNELSOURCE)/include/generated/uapi 13 | LINUXINCLUDE += -I$(KERNELSOURCE)/arch/$(ARCH)/include 14 | LINUXINCLUDE += -I$(KERNELSOURCE)/arch/$(ARCH)/include/uapi 15 | LINUXINCLUDE += -I$(KERNELSOURCE)/include 16 | LINUXINCLUDE += -I$(KERNELSOURCE)/include/linux 17 | LINUXINCLUDE += -I$(KERNELSOURCE)/include/uapi 18 | LINUXINCLUDE += -I$(KERNELSOURCE) 19 | 20 | LINUXINCLUDE += -I$(LIBBPF)/src 21 | LINUXINCLUDE += -I$(LIBBPF)/include 22 | LINUXINCLUDE += -I$(LIBBPF_HEADERS)/ 23 | LINUXINCLUDE += -include $(KERNELSOURCE)/include/linux/kconfig.h 24 | LINUXINCLUDE += -I../includes 25 | 26 | CLANG_VERSION := $(shell clang --version | grep -o -E 'clang version [0-9]+\.[0-9]+\.[0-9]' | cut -f 3 -d ' ') 27 | CLANG_MAJOR_VERSION := $(shell echo $(CLANG_VERSION) | cut -d. -f1 ) 28 | LLVM_INCLUDES = $(shell [ -d /usr/lib/clang ] && echo "-I/usr/lib/clang/$(CLANG_VERSION)/include" || echo "-I/usr/lib64/clang/$(CLANG_VERSION)/include") 29 | LLVM_INCLUDES += -I/opt/rh/llvm-toolset-7.0/root/usr/lib64/clang/$(CLANG_VERSION)/include 30 | 31 | #KERNEL_VERSION="$(shell basename $(realpath $(KERNELSOURCE)) | cut -f 2 -d '-')" 32 | KERNEL_VERSION="$(shell cat $(KERNELSOURCE)/include/config/kernel.release)" 33 | 34 | VER_MAJOR=$(shell echo $(KERNEL_VERSION) | cut -d. -f1) 35 | VER_MINOR=$(shell echo $(KERNEL_VERSION) | cut -d. -f2) 36 | VER_PATCH=$(shell echo $(KERNEL_VERSION) | cut -d. -f3) 37 | 38 | CURRENT_KERNEL=$(shell echo $(VER_MAJOR)\*65536 + $(VER_MINOR)\*256 + $(VER_PATCH) |bc) 39 | 40 | NETDATA_ALL_APPS= btrfs \ 41 | cachestat \ 42 | dc \ 43 | disk \ 44 | ext4 \ 45 | fd \ 46 | fdatasync \ 47 | fsync \ 48 | hardirq \ 49 | mdflush \ 50 | mount \ 51 | msync \ 52 | network_viewer \ 53 | nfs \ 54 | oomkill \ 55 | process \ 56 | shm \ 57 | socket \ 58 | softirq \ 59 | sync \ 60 | syncfs \ 61 | sync_file_range \ 62 | swap \ 63 | vfs \ 64 | xfs \ 65 | zfs \ 66 | # 67 | 68 | # Kernel newer than 6.16.0 ( 397312 = 6 * 65536 + 16 * 256) 69 | ifeq ($(shell test $(CURRENT_KERNEL) -ge 397312 ; echo $$?),0) 70 | NETDATA_APPS= swap \ 71 | process \ 72 | # 73 | 74 | # Kernel newer than 6.8.0 ( 395264 = 6 * 65536 + 8 * 256) 75 | else ifeq ($(shell test $(CURRENT_KERNEL) -ge 395264 ; echo $$?),0) 76 | NETDATA_APPS= swap \ 77 | # 78 | # Kernel newer than 5.15.256 ( 331776 = 5 * 65536 + 16 * 256) 79 | else ifeq ($(shell test $(CURRENT_KERNEL) -ge 331776 ; echo $$?),0) 80 | NETDATA_APPS= cachestat \ 81 | # 82 | # Kernel newer than 5.14.256 ( 331520 = 5 * 65536 + 14 * 256) 83 | else ifeq ($(shell test $(CURRENT_KERNEL) -ge 331520 ; echo $$?),0) 84 | NETDATA_APPS= cachestat \ 85 | # 86 | # Kernel newer than 5.13.256 ( 331264 = 5 * 65536 + 13 * 256) and smaller than 5.14.256 87 | else ifeq ($(shell test $(CURRENT_KERNEL) -ge 331264 -a $(CURRENT_KERNEL) -lt 331520 ; echo $$?),0) 88 | NETDATA_APPS= ${NETDATA_ALL_APPS} 89 | # Kernel newer than 5.10.256 ( 330496 = 5 * 65536 + 11 * 256) 90 | else ifeq ($(shell test $(CURRENT_KERNEL) -ge 330496 ; echo $$?),0) 91 | NETDATA_APPS= fd \ 92 | # 93 | # Kernel newer than 5.9.256 ( 330240 = 5 * 65536 + 10 * 256) 94 | else ifeq ($(shell test $(CURRENT_KERNEL) -ge 330240 ; echo $$?),0) 95 | NETDATA_APPS= btrfs \ 96 | process \ 97 | # 98 | else 99 | NETDATA_APPS= ${NETDATA_ALL_APPS} 100 | endif 101 | 102 | ifeq ($(shell test $(CLANG_MAJOR_VERSION) -ge 8 ; echo $$?),0) 103 | CC_LIBBPF = clang 104 | else 105 | CC_LIBBPF = gcc 106 | endif 107 | 108 | all: $(NETDATA_APPS) 109 | 110 | dev: ${NETDATA_ALL_APPS} 111 | 112 | libbpf: 113 | # -fPIE added to be compatible with olders clang/gcc 114 | cd $(LIBBPF)/src && /bin/bash ../../.dockerfiles/change_libbpf.sh $(VER_MAJOR) $(VER_MINOR) && $(MAKE) CC=$(CC_LIBBPF) CFLAGS="-fPIE" BUILD_STATIC_ONLY=1 DESTDIR=../../.local_libbpf INCLUDEDIR= LIBDIR= UAPIDIR= install \ 115 | 116 | %_kern.o: %_kern.c libbpf 117 | if [ -w $(KERNELSOURCE)/include/generated/autoconf.h ]; then if [ "$(CURRENT_KERNEL)" -ge 328448 ]; then sed -i -e 's/\(#define CONFIG_CC_HAS_ASM_INLINE 1\)/\/\/\1/' $(KERNELSOURCE)/include/generated/autoconf.h; fi ; fi 118 | $(CLANG) $(EXTRA_CFLAGS) -S -nostdinc $(LINUXINCLUDE) $(LLVM_INCLUDES) \ 119 | -D__KERNEL__ -D__ASM_SYSREG_H -Wno-unused-value -Wno-pointer-sign \ 120 | -Wno-compare-distinct-pointer-types \ 121 | -Wno-gnu-variable-sized-type-not-at-end \ 122 | -Wno-tautological-compare \ 123 | -fno-asynchronous-unwind-tables \ 124 | -DNETDATASEL=0 \ 125 | -D__BPF_TRACING__ \ 126 | -D__TARGET_ARCH_$(ARCH) \ 127 | -include ../includes/netdata_asm_goto.h \ 128 | -O2 -g -emit-llvm -c $< 129 | $(LLC) -march=bpf -filetype=obj -o r$@ $(<:.c=.ll) 130 | $(CLANG) $(EXTRA_CFLAGS) -S -nostdinc $(LINUXINCLUDE) $(LLVM_INCLUDES) \ 131 | -D__KERNEL__ -D__ASM_SYSREG_H -Wno-unused-value -Wno-pointer-sign \ 132 | -Wno-compare-distinct-pointer-types \ 133 | -Wno-gnu-variable-sized-type-not-at-end \ 134 | -Wno-tautological-compare \ 135 | -fno-asynchronous-unwind-tables \ 136 | -DNETDATASEL=2 \ 137 | -D__BPF_TRACING__ \ 138 | -D__TARGET_ARCH_$(ARCH) \ 139 | -include ../includes/netdata_asm_goto.h \ 140 | -O2 -g -emit-llvm -c $< 141 | $(LLC) -march=bpf -filetype=obj -o p$@ $(<:.c=.ll) 142 | /bin/bash rename_binaries.sh "$(VER_MAJOR)" "$(VER_MINOR)" "$@" 143 | 144 | $(NETDATA_APPS): %: %_kern.o 145 | 146 | ${NETDATA_ALL_APPS}: %: %_kern.o 147 | 148 | tester: libbpf 149 | $(CC) -I../.local_libbpf -I$(LIBBPF)/src -I$(LIBBPF)/include -I$(LIBBPF)/include/uapi -L../.local_libbpf -o legacy_test tester_user.c -lbpf -lz -lelf 150 | 151 | clean: 152 | cd $(LIBBPF)/src && make clean 153 | rm -f *.o *.ll 154 | if [ -f legacy_test ] ; then rm legacy_test; fi 155 | -------------------------------------------------------------------------------- /kernel/shm_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "shm_netdata" 2 | 3 | #include 4 | 5 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 6 | #include 7 | #else 8 | #include 9 | #endif 10 | #include "bpf_tracing.h" 11 | #include "bpf_helpers.h" 12 | #include "netdata_ebpf.h" 13 | 14 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 15 | struct { 16 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 17 | __type(key, __u32); 18 | __type(value, __u64); 19 | __uint(max_entries, NETDATA_SHM_END); 20 | } tbl_shm SEC(".maps"); 21 | 22 | struct { 23 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) 24 | __uint(type, BPF_MAP_TYPE_HASH); 25 | #else 26 | __uint(type, BPF_MAP_TYPE_PERCPU_HASH); 27 | #endif 28 | __type(key, __u32); 29 | __type(value, netdata_shm_t); 30 | __uint(max_entries, PID_MAX_DEFAULT); 31 | } tbl_pid_shm SEC(".maps"); 32 | 33 | struct { 34 | __uint(type, BPF_MAP_TYPE_ARRAY); 35 | __type(key, __u32); 36 | __type(value, __u64); 37 | __uint(max_entries, NETDATA_CONTROLLER_END); 38 | } shm_ctrl SEC(".maps"); 39 | #else 40 | struct bpf_map_def SEC("maps") tbl_shm = { 41 | .type = BPF_MAP_TYPE_PERCPU_ARRAY, 42 | .key_size = sizeof(__u32), 43 | .value_size = sizeof(__u64), 44 | .max_entries = NETDATA_SHM_END 45 | }; 46 | 47 | struct bpf_map_def SEC("maps") tbl_pid_shm = { 48 | .type = BPF_MAP_TYPE_HASH, 49 | .key_size = sizeof(__u32), 50 | .value_size = sizeof(netdata_shm_t), 51 | .max_entries = PID_MAX_DEFAULT 52 | }; 53 | 54 | struct bpf_map_def SEC("maps") shm_ctrl = { 55 | .type = BPF_MAP_TYPE_ARRAY, 56 | .key_size = sizeof(__u32), 57 | .value_size = sizeof(__u64), 58 | .max_entries = NETDATA_CONTROLLER_END 59 | }; 60 | #endif 61 | 62 | #if defined(LIBBPF_MAJOR_VERSION) && (LIBBPF_MAJOR_VERSION >= 1) 63 | SEC("ksyscall/shmget") 64 | #else 65 | SEC("kprobe/" NETDATA_SYSCALL(shmget)) 66 | #endif 67 | int netdata_syscall_shmget(struct pt_regs *ctx) 68 | { 69 | netdata_shm_t data = {}; 70 | 71 | libnetdata_update_global(&tbl_shm, NETDATA_KEY_SHMGET_CALL, 1); 72 | 73 | // check if apps is enabled; if not, don't record apps data. 74 | __u32 key = 0; 75 | __u32 tgid = 0; 76 | if (!monitor_apps(&shm_ctrl)) 77 | return 0; 78 | 79 | netdata_shm_t *fill = netdata_get_pid_structure(&key, &tgid, &shm_ctrl, &tbl_pid_shm); 80 | if (fill) { 81 | libnetdata_update_u32(&fill->get, 1); 82 | } else { 83 | data.ct = bpf_ktime_get_ns(); 84 | libnetdata_update_uid_gid(&data.uid, &data.gid); 85 | data.tgid = tgid; 86 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 87 | bpf_get_current_comm(&data.name, TASK_COMM_LEN); 88 | #else 89 | data.name[0] = '\0'; 90 | #endif 91 | 92 | data.get = 1; 93 | bpf_map_update_elem(&tbl_pid_shm, &key, &data, BPF_ANY); 94 | 95 | libnetdata_update_global(&shm_ctrl, NETDATA_CONTROLLER_PID_TABLE_ADD, 1); 96 | } 97 | 98 | return 0; 99 | } 100 | 101 | #if defined(LIBBPF_MAJOR_VERSION) && (LIBBPF_MAJOR_VERSION >= 1) 102 | SEC("ksyscall/shmat") 103 | #else 104 | SEC("kprobe/" NETDATA_SYSCALL(shmat)) 105 | #endif 106 | int netdata_syscall_shmat(struct pt_regs *ctx) 107 | { 108 | netdata_shm_t data = {}; 109 | 110 | libnetdata_update_global(&tbl_shm, NETDATA_KEY_SHMAT_CALL, 1); 111 | 112 | // check if apps is enabled; if not, don't record apps data. 113 | __u32 key = 0; 114 | __u32 tgid = 0; 115 | if (!monitor_apps(&shm_ctrl)) 116 | return 0; 117 | 118 | netdata_shm_t *fill = netdata_get_pid_structure(&key, &tgid, &shm_ctrl, &tbl_pid_shm); 119 | if (fill) { 120 | libnetdata_update_u32(&fill->at, 1); 121 | } else { 122 | data.ct = bpf_ktime_get_ns(); 123 | libnetdata_update_uid_gid(&data.uid, &data.gid); 124 | data.tgid = tgid; 125 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 126 | bpf_get_current_comm(&data.name, TASK_COMM_LEN); 127 | #else 128 | data.name[0] = '\0'; 129 | #endif 130 | 131 | data.at = 1; 132 | bpf_map_update_elem(&tbl_pid_shm, &key, &data, BPF_ANY); 133 | 134 | libnetdata_update_global(&shm_ctrl, NETDATA_CONTROLLER_PID_TABLE_ADD, 1); 135 | } 136 | 137 | return 0; 138 | } 139 | 140 | #if defined(LIBBPF_MAJOR_VERSION) && (LIBBPF_MAJOR_VERSION >= 1) 141 | SEC("ksyscall/shmdt") 142 | #else 143 | SEC("kprobe/" NETDATA_SYSCALL(shmdt)) 144 | #endif 145 | int netdata_syscall_shmdt(struct pt_regs *ctx) 146 | { 147 | netdata_shm_t data = {}; 148 | 149 | libnetdata_update_global(&tbl_shm, NETDATA_KEY_SHMDT_CALL, 1); 150 | 151 | // check if apps is enabled; if not, don't record apps data. 152 | __u32 key = 0; 153 | __u32 tgid = 0; 154 | if (!monitor_apps(&shm_ctrl)) 155 | return 0; 156 | 157 | netdata_shm_t *fill = netdata_get_pid_structure(&key, &tgid, &shm_ctrl, &tbl_pid_shm); 158 | if (fill) { 159 | libnetdata_update_u32(&fill->dt, 1); 160 | } else { 161 | data.ct = bpf_ktime_get_ns(); 162 | libnetdata_update_uid_gid(&data.uid, &data.gid); 163 | data.tgid = tgid; 164 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 165 | bpf_get_current_comm(&data.name, TASK_COMM_LEN); 166 | #else 167 | data.name[0] = '\0'; 168 | #endif 169 | 170 | data.dt = 1; 171 | bpf_map_update_elem(&tbl_pid_shm, &key, &data, BPF_ANY); 172 | 173 | libnetdata_update_global(&shm_ctrl, NETDATA_CONTROLLER_PID_TABLE_ADD, 1); 174 | } 175 | 176 | return 0; 177 | } 178 | 179 | #if defined(LIBBPF_MAJOR_VERSION) && (LIBBPF_MAJOR_VERSION >= 1) 180 | SEC("ksyscall/shmctl") 181 | #else 182 | SEC("kprobe/" NETDATA_SYSCALL(shmctl)) 183 | #endif 184 | int netdata_syscall_shmctl(struct pt_regs *ctx) 185 | { 186 | netdata_shm_t data = {}; 187 | 188 | libnetdata_update_global(&tbl_shm, NETDATA_KEY_SHMCTL_CALL, 1); 189 | 190 | // check if apps is enabled; if not, don't record apps data. 191 | __u32 key = 0; 192 | __u32 tgid = 0; 193 | if (!monitor_apps(&shm_ctrl)) 194 | return 0; 195 | 196 | netdata_shm_t *fill = netdata_get_pid_structure(&key, &tgid, &shm_ctrl, &tbl_pid_shm); 197 | if (fill) { 198 | libnetdata_update_u32(&fill->ctl, 1); 199 | } else { 200 | data.ct = bpf_ktime_get_ns(); 201 | libnetdata_update_uid_gid(&data.uid, &data.gid); 202 | data.tgid = tgid; 203 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 204 | bpf_get_current_comm(&data.name, TASK_COMM_LEN); 205 | #else 206 | data.name[0] = '\0'; 207 | #endif 208 | 209 | data.ctl = 1; 210 | bpf_map_update_elem(&tbl_pid_shm, &key, &data, BPF_ANY); 211 | 212 | libnetdata_update_global(&shm_ctrl, NETDATA_CONTROLLER_PID_TABLE_ADD, 1); 213 | } 214 | 215 | return 0; 216 | } 217 | 218 | char _license[] SEC("license") = "GPL"; 219 | 220 | -------------------------------------------------------------------------------- /kernel/fd_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "fd_kern" 2 | #include 3 | #include 4 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,10,17)) 5 | # include 6 | #endif 7 | 8 | #include 9 | #include 10 | 11 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 12 | #include 13 | #else 14 | #include 15 | #endif 16 | #include "bpf_tracing.h" 17 | #include "bpf_helpers.h" 18 | #include "netdata_ebpf.h" 19 | 20 | /************************************************************************************ 21 | * 22 | * MAPS Section 23 | * 24 | ***********************************************************************************/ 25 | 26 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 27 | struct { 28 | __uint(type, BPF_MAP_TYPE_HASH); 29 | __type(key, __u32); 30 | __type(value, struct netdata_fd_stat_t); 31 | __uint(max_entries, PID_MAX_DEFAULT); 32 | } tbl_fd_pid SEC(".maps"); 33 | 34 | struct { 35 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 36 | __type(key, __u32); 37 | __type(value, __u64); 38 | __uint(max_entries, NETDATA_FD_COUNTER); 39 | } tbl_fd_global SEC(".maps"); 40 | 41 | struct { 42 | __uint(type, BPF_MAP_TYPE_ARRAY); 43 | __type(key, __u32); 44 | __type(value, __u64); 45 | __uint(max_entries, NETDATA_CONTROLLER_END); 46 | } fd_ctrl SEC(".maps"); 47 | 48 | #else 49 | 50 | struct bpf_map_def SEC("maps") tbl_fd_pid = { 51 | .type = BPF_MAP_TYPE_HASH, 52 | .key_size = sizeof(__u32), 53 | .value_size = sizeof(struct netdata_fd_stat_t), 54 | .max_entries = PID_MAX_DEFAULT 55 | }; 56 | 57 | struct bpf_map_def SEC("maps") tbl_fd_global = { 58 | .type = BPF_MAP_TYPE_PERCPU_ARRAY, 59 | .key_size = sizeof(__u32), 60 | .value_size = sizeof(__u64), 61 | .max_entries = NETDATA_FD_COUNTER 62 | }; 63 | 64 | struct bpf_map_def SEC("maps") fd_ctrl = { 65 | .type = BPF_MAP_TYPE_ARRAY, 66 | .key_size = sizeof(__u32), 67 | .value_size = sizeof(__u64), 68 | .max_entries = NETDATA_CONTROLLER_END 69 | }; 70 | 71 | #endif 72 | 73 | /************************************************************************************ 74 | * 75 | * Probe Section 76 | * 77 | ***********************************************************************************/ 78 | 79 | #if (LINUX_VERSION_CODE <= KERNEL_VERSION(5,5,19)) 80 | #if NETDATASEL < 2 81 | SEC("kretprobe/do_sys_open") 82 | #else 83 | SEC("kprobe/do_sys_open") 84 | #endif 85 | #else 86 | #if NETDATASEL < 2 87 | SEC("kretprobe/do_sys_openat2") 88 | #else 89 | SEC("kprobe/do_sys_openat2") 90 | #endif // Endif NETDATASEL 91 | #endif //ENDIF KERNEL VERSION 92 | int netdata_sys_open(struct pt_regs* ctx) 93 | { 94 | #if NETDATASEL < 2 95 | int ret = (ssize_t)PT_REGS_RC(ctx); 96 | #endif 97 | struct netdata_fd_stat_t *fill; 98 | struct netdata_fd_stat_t data = { }; 99 | 100 | libnetdata_update_global(&tbl_fd_global, NETDATA_KEY_CALLS_DO_SYS_OPEN, 1); 101 | #if NETDATASEL < 2 102 | if (ret < 0) { 103 | libnetdata_update_global(&tbl_fd_global, NETDATA_KEY_ERROR_DO_SYS_OPEN, 1); 104 | } 105 | #endif 106 | 107 | __u32 key = 0; 108 | __u32 tgid = 0; 109 | if (!monitor_apps(&fd_ctrl)) 110 | return 0; 111 | 112 | fill = netdata_get_pid_structure(&key, &tgid, &fd_ctrl, &tbl_fd_pid); 113 | if (fill) { 114 | libnetdata_update_u32(&fill->open_call, 1) ; 115 | 116 | #if NETDATASEL < 2 117 | if (ret < 0) { 118 | libnetdata_update_u32(&fill->open_err, 1) ; 119 | } 120 | #endif 121 | } else { 122 | data.ct = bpf_ktime_get_ns(); 123 | libnetdata_update_uid_gid(&data.uid, &data.gid); 124 | data.tgid = tgid; 125 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 126 | bpf_get_current_comm(&data.name, TASK_COMM_LEN); 127 | #else 128 | data.name[0] = '\0'; 129 | #endif 130 | 131 | #if NETDATASEL < 2 132 | if (ret < 0) { 133 | data.open_err = 1; 134 | } else { 135 | #endif 136 | data.open_err = 0; 137 | #if NETDATASEL < 2 138 | } 139 | #endif 140 | data.open_call = 1; 141 | 142 | bpf_map_update_elem(&tbl_fd_pid, &key, &data, BPF_ANY); 143 | 144 | libnetdata_update_global(&fd_ctrl, NETDATA_CONTROLLER_PID_TABLE_ADD, 1); 145 | } 146 | 147 | return 0; 148 | } 149 | 150 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,11,0)) 151 | # if NETDATASEL < 2 152 | SEC("kretprobe/close_fd") 153 | # else 154 | SEC("kprobe/close_fd") 155 | # endif /* NETDATASEL < 2 */ 156 | #else /* KERNEL > 5.11 */ 157 | # if NETDATASEL < 2 158 | # if defined(RHEL_MAJOR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)) && (LINUX_VERSION_CODE <= KERNEL_VERSION(4,19,0)) 159 | SEC("kretprobe/close_fd") 160 | # else /* RHEL_MAJOR */ 161 | SEC("kretprobe/__close_fd") 162 | # endif /* RHEL_MAJOR */ 163 | # else /* NETDATASEL < 2 */ 164 | # if defined(RHEL_MAJOR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)) && (LINUX_VERSION_CODE <= KERNEL_VERSION(4,19,0)) 165 | SEC("kprobe/close_fd") 166 | # else /* RHEL_MAJOR */ 167 | SEC("kprobe/__close_fd") 168 | # endif /* RHEL_MAJOR */ 169 | # endif /* NETDATASEL < 2 */ 170 | #endif /* KERNEL > 5.11 */ 171 | int netdata_close(struct pt_regs* ctx) 172 | { 173 | #if NETDATASEL < 2 174 | int ret = (int)PT_REGS_RC(ctx); 175 | #endif 176 | struct netdata_fd_stat_t data = { }; 177 | struct netdata_fd_stat_t *fill; 178 | 179 | libnetdata_update_global(&tbl_fd_global, NETDATA_KEY_CALLS_CLOSE_FD, 1); 180 | #if NETDATASEL < 2 181 | if (ret < 0) { 182 | libnetdata_update_global(&tbl_fd_global, NETDATA_KEY_ERROR_CLOSE_FD, 1); 183 | } 184 | #endif 185 | 186 | __u32 key = 0; 187 | __u32 tgid = 0; 188 | if (!monitor_apps(&fd_ctrl)) 189 | return 0; 190 | 191 | fill = netdata_get_pid_structure(&key, &tgid, &fd_ctrl, &tbl_fd_pid); 192 | if (fill) { 193 | libnetdata_update_u32(&fill->close_call, 1) ; 194 | 195 | #if NETDATASEL < 2 196 | if (ret < 0) { 197 | libnetdata_update_u32(&fill->close_err, 1) ; 198 | } 199 | #endif 200 | } else { 201 | data.ct = bpf_ktime_get_ns(); 202 | libnetdata_update_uid_gid(&data.uid, &data.gid); 203 | data.tgid = tgid; 204 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 205 | bpf_get_current_comm(&data.name, TASK_COMM_LEN); 206 | #else 207 | data.name[0] = '\0'; 208 | #endif 209 | 210 | data.close_call = 1; 211 | #if NETDATASEL < 2 212 | if (ret < 0) { 213 | data.close_err = 1; 214 | } 215 | #endif 216 | 217 | bpf_map_update_elem(&tbl_fd_pid, &key, &data, BPF_ANY); 218 | 219 | libnetdata_update_global(&fd_ctrl, NETDATA_CONTROLLER_PID_TABLE_ADD, 1); 220 | } 221 | 222 | return 0; 223 | } 224 | 225 | char _license[] SEC("license") = "GPL"; 226 | 227 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kernel-collector 2 | 3 | ![CI](https://github.com/netdata/kernel-collector/workflows/CI/badge.svg) 4 | ![CD](https://github.com/netdata/kernel-collector/workflows/CD/badge.svg) 5 | 6 | Linux Kernel eBPF Collectors 7 | 8 | ## Directory structure 9 | 10 | The respository has the following directory structure: 11 | 12 | - `artifacts`: directory that will have the eBPF programs when the compilation 13 | process ends. 14 | - `co-re`: contains all eBPF programs that utilize eBPF CO-RE (Compile Once - 15 | Run Everywhere) technology. 16 | - `tests`: contains test cases for our eBPF CO-RE programs. 17 | - `docs`: contains an assortment of documentation related to this repository. 18 | - `includes`: headers used throughout the project. 19 | - `kernel`: contains all eBPF programs that don't utilize eBPF CO-RE 20 | technology; these may be considered legacy more and more as time progresses 21 | and we shift fully to CO-RE. 22 | - `kernel-patches`: contains patches needed to properly compile our legacy 23 | `kernel/` eBPF programs on some kernel versions. 24 | - `libbpf`: this is a submodule'd fork of 25 | [netdata/libbpf](https://github.com/netdata/libbpf) which is itself a fork of 26 | the official `libbpf` package, the user-space side of eBPF system calls. 27 | - `tools`: scripts used to verify system status before installing eBPF code. 28 | 29 | ## Requirements 30 | 31 | #### Packages 32 | 33 | To compile the eBPF programs, it will be necessary to have the following 34 | packages: 35 | 36 | - libelf headers 37 | - LLVM/Clang; this is because GCC prior to 10.0 cannot compile eBPF code. 38 | - Kernel headers 39 | 40 | #### Initializing Submodules 41 | 42 | `libbpf` directory is included as a git submodule and it is necessary to fetch contents with the git command below: 43 | ```bash 44 | git submodule update --init --recursive 45 | ``` 46 | #### Generating Headers 47 | 48 | Kernel headers can be extracted directly from the kernel source doing the 49 | following steps (assumes your kernel source is accessible at `/usr/src/linux`): 50 | 51 | ```bash 52 | cd /usr/src/linux 53 | make defconfig 54 | make scripts 55 | make prepare 56 | make headers_install 57 | ``` 58 | 59 | #### Misc 60 | 61 | In case you are using the kernel `5.4` or newer, please comment out the 62 | following line inside the file `generated/autoconf.h`: 63 | 64 | ```c 65 | #define CONFIG_CC_HAS_ASM_INLINE 1 66 | ``` 67 | 68 | #### Makefiles 69 | 70 | It's also possible that you'll need to change the `Makefile`s in this 71 | repository according your environment. The original files were adjusted to 72 | compile on Slackware Linux Current. 73 | 74 | Inside `kernel/Makefile`, you may need to change the following variables: 75 | 76 | - `KERNELSOURCE`: Where is your kernel-source? This variable was set initially 77 | to work on Slackware, Fedora and Ubuntu. 78 | - `LINUXINCLUDE`: Depending on the Linux distribution, it may be necessary to 79 | add or remove directories from this variable. 80 | - `LLVM_INCLUDES`: Depending on the kernel version, it may be necessary to 81 | change this path. 82 | 83 | ## Building with Docker 84 | 85 | There are two build environments that produce different variants of libc and 86 | the Linux Kernel. 87 | 88 | The build environments are: 89 | 90 | - `musl` => `Dockerfile.musl` (_based on Alpine 3.11_) 91 | - `glibc` => `Dockerfile.glibc.generic` (_based on Ubuntu 20.04_) 92 | 93 | ### glibc 94 | 95 | ```sh 96 | $ docker build -f Dockerfile.glibc.generic -t kernel-collector:glibc ./ 97 | $ docker run --rm -v $PWD:/kernel-collector kernel-collector:glibc 98 | ``` 99 | 100 | ### musl 101 | 102 | ```sh 103 | $ docker build -f Dockerfile.musl -t kernel-collector:musl ./ 104 | $ docker run --rm -v $PWD:/kernel-collector kernel-collector:musl 105 | ``` 106 | 107 | ### Different Kernel 108 | 109 | To build for a different Kernel version rather than the default just pass the 110 | `--build-arg KERNEL_VERSION=` argument to the `docker build`. 111 | 112 | For example: 113 | 114 | ```sh 115 | $ docker build -f Dockerfile.musl -t kernel-collector:musl_5_4 --build--arg KERNEL_VERSION=5.4.18 ./ 116 | $ docker run --rm -v $PWD:/kernel-collector kernel-collector:musl_5_4 117 | ``` 118 | 119 | ### Building with Debug Symbols 120 | 121 | To build with debug symbols enabled, set the environment variable `DEBUG` to `1` 122 | when running the build image. 123 | 124 | For example: 125 | 126 | ```sh 127 | $ docker build -f Dockerfile.musl -t kernel-collector:musl ./ 128 | $ docker run --rm -e DEBUG=1 -v $PWD:/kernel-collector kernel-collector:musl 129 | ``` 130 | 131 | This sets `EXTRA_CFLAGS=-g` before building. 132 | 133 | ## Manual Compilation 134 | 135 | After you've got your `kernel/Makefille` properly setup, you can run the 136 | following command to compile all the eBPF programs: 137 | 138 | ```bash 139 | # build in parallel jobs equal to `nproc` (number of processors) 140 | $ make -j`nproc` 141 | ``` 142 | 143 | When compilation finishes, you will have a file inside the `artifacts` 144 | directory with contents like the following: 145 | 146 | ``` 147 | pnetdata_ebpf_process..o 148 | pnetdata_ebpf_socket..o 149 | rnetdata_ebpf_process..o 150 | rnetdata_ebpf_socket..o 151 | ... 152 | ``` 153 | 154 | `p*.o`: eBPF programs used with entry mode, this is the default mode. 155 | `r*.o`: eBPF programs used with return mode. 156 | 157 | These files have to be copied to your plugins directory, which is usually at 158 | `/usr/libexec/netdata/plugins.d/`, for the collector to be able to access them. 159 | After this you can start the new collector `ebpf_program.plugin`. 160 | 161 | ## Releasing 162 | 163 | To release a new version and create a Github Release: 164 | 165 | 1. Create a Git tag like so: 166 | 167 | ```sh 168 | $ TAG="v0.0.1"; git tag -a -s -m "Release ${TAG}" "${TAG}" && git push origin "${TAG}" 169 | ``` 170 | 171 | Replace `v0.0.1` with the next desired tag. SemVer is not strictly being 172 | followed here at this time so the specific tagged versions is not so 173 | important. 174 | 175 | This will kick off a Github Action Workflow that will Rebuild the Netdata 176 | eBPF Kernel Collector for all Kernel and LIBC variants, create a Github 177 | Release and upload all assets to the release to be consumed by anyone or the 178 | Netdata Installer. 179 | 180 | 2. Wait for the CD pipeline to finish in the Github Actions UI. 181 | 3. Review the Release, Updates Release Notes, etc in the Github Releases UI. 182 | 4. Push the "Publish Release" button in the Github Releases UI. 183 | 184 | ## Contribution 185 | 186 | Netdata is open-source software and we are always open for contributions that 187 | you can give us. 188 | 189 | If you want to contribute an eBPF program, then please be sure that your 190 | program matches the following patterns: 191 | 192 | - Your program must run on all kernels since at least kernel `4.11`. 193 | - Write some code that's responsible to measure the latency of your program. 194 | - We have the variable NETDATASEL, that selects where the functions will be 195 | attached. Be sure that inside your code `0` is associated `kretprobe`, and `2` is assoacited 196 | with `kprobe`. 197 | -------------------------------------------------------------------------------- /kernel/zfs_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "zfs_netdata" 2 | #include 3 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)) 4 | #include 5 | #endif 6 | 7 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 8 | #include 9 | #else 10 | #include 11 | #endif 12 | #include "bpf_tracing.h" 13 | #include "bpf_helpers.h" 14 | #include "netdata_ebpf.h" 15 | 16 | /************************************************************************************ 17 | * 18 | * MAP Section 19 | * 20 | ***********************************************************************************/ 21 | 22 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 23 | struct { 24 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 25 | __type(key, __u32); 26 | __type(value, __u64); 27 | __uint(max_entries, NETDATA_FS_MAX_ELEMENTS); 28 | } tbl_zfs SEC(".maps"); 29 | 30 | struct { 31 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) 32 | __uint(type, BPF_MAP_TYPE_HASH); 33 | #else 34 | __uint(type, BPF_MAP_TYPE_PERCPU_HASH); 35 | #endif 36 | __type(key, __u32); 37 | __type(value, __u64); 38 | __uint(max_entries, 4192); 39 | } tmp_zfs SEC(".maps"); 40 | 41 | struct { 42 | __uint(type, BPF_MAP_TYPE_ARRAY); 43 | __type(key, __u32); 44 | __type(value, __u64); 45 | __uint(max_entries, NETDATA_CONTROLLER_END); 46 | } zfs_ctrl SEC(".maps"); 47 | 48 | #else 49 | struct bpf_map_def SEC("maps") tbl_zfs = { 50 | .type = BPF_MAP_TYPE_PERCPU_ARRAY, 51 | .key_size = sizeof(__u32), 52 | .value_size = sizeof(__u64), 53 | .max_entries = NETDATA_FS_MAX_ELEMENTS 54 | }; 55 | 56 | struct bpf_map_def SEC("maps") tmp_zfs = { 57 | .type = BPF_MAP_TYPE_HASH, 58 | .key_size = sizeof(__u32), 59 | .value_size = sizeof(__u64), 60 | .max_entries = 4192 61 | }; 62 | 63 | struct bpf_map_def SEC("maps") zfs_ctrl = { 64 | .type = BPF_MAP_TYPE_ARRAY, 65 | .key_size = sizeof(__u32), 66 | .value_size = sizeof(__u64), 67 | .max_entries = NETDATA_CONTROLLER_END 68 | }; 69 | #endif 70 | 71 | /************************************************************************************ 72 | * 73 | * ENTRY Section 74 | * 75 | ***********************************************************************************/ 76 | 77 | static __always_inline int netdata_zfs_entry() 78 | { 79 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 80 | __u32 pid = (__u32)(pid_tgid >> 32); 81 | __u64 ts = bpf_ktime_get_ns(); 82 | 83 | bpf_map_update_elem(&tmp_zfs, &pid, &ts, BPF_ANY); 84 | 85 | libnetdata_update_global(&zfs_ctrl, NETDATA_CONTROLLER_TEMP_TABLE_ADD, 1); 86 | 87 | return 0; 88 | } 89 | 90 | SEC("kprobe/zpl_iter_read") 91 | int netdata_zpl_iter_read(struct pt_regs *ctx) 92 | { 93 | return netdata_zfs_entry(); 94 | } 95 | 96 | SEC("kprobe/zpl_iter_write") 97 | int netdata_zpl_iter_write(struct pt_regs *ctx) 98 | { 99 | return netdata_zfs_entry(); 100 | } 101 | 102 | SEC("kprobe/zpl_open") 103 | int netdata_zpl_open(struct pt_regs *ctx) 104 | { 105 | return netdata_zfs_entry(); 106 | } 107 | 108 | SEC("kprobe/zpl_fsync") 109 | int netdata_zpl_fsync(struct pt_regs *ctx) 110 | { 111 | return netdata_zfs_entry(); 112 | } 113 | 114 | /************************************************************************************ 115 | * 116 | * END Section 117 | * 118 | ***********************************************************************************/ 119 | 120 | static void netdata_zfs_store_bin(__u32 bin, __u32 selection) 121 | { 122 | __u64 *fill, data; 123 | __u32 idx = selection * NETDATA_FS_MAX_BINS + bin; 124 | if (idx >= NETDATA_FS_MAX_ELEMENTS) 125 | return; 126 | 127 | fill = bpf_map_lookup_elem(&tbl_zfs, &idx); 128 | if (fill) { 129 | libnetdata_update_u64(fill, 1); 130 | return; 131 | } 132 | 133 | data = 1; 134 | bpf_map_update_elem(&tbl_zfs, &idx, &data, BPF_ANY); 135 | 136 | libnetdata_update_global(&zfs_ctrl, NETDATA_CONTROLLER_TEMP_TABLE_DEL, 1); 137 | } 138 | 139 | SEC("kretprobe/zpl_iter_read") 140 | int netdata_ret_zpl_iter_read(struct pt_regs *ctx) 141 | { 142 | __u64 *fill, data; 143 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 144 | __u32 bin, pid = (__u32)(pid_tgid >> 32); 145 | 146 | fill = bpf_map_lookup_elem(&tmp_zfs, &pid); 147 | if (!fill) 148 | return 0; 149 | 150 | data = bpf_ktime_get_ns() - *fill; 151 | bpf_map_delete_elem(&tmp_zfs, &pid); 152 | 153 | // Skip entries with backward time 154 | if ( (s64)data < 0) 155 | return 0; 156 | 157 | // convert to microseconds 158 | data /= 1000; 159 | bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); 160 | netdata_zfs_store_bin(bin, NETDATA_KEY_CALLS_READ); 161 | 162 | return 0; 163 | } 164 | 165 | SEC("kretprobe/zpl_iter_write") 166 | int netdata_ret_zpl_iter_write(struct pt_regs *ctx) 167 | { 168 | __u64 *fill, data; 169 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 170 | __u32 bin, pid = (__u32)(pid_tgid >> 32); 171 | 172 | fill = bpf_map_lookup_elem(&tmp_zfs, &pid); 173 | if (!fill) 174 | return 0; 175 | 176 | data = bpf_ktime_get_ns() - *fill; 177 | bpf_map_delete_elem(&tmp_zfs, &pid); 178 | 179 | // Skip entries with backward time 180 | if ( (s64)data < 0) 181 | return 0; 182 | 183 | // convert to microseconds 184 | data /= 1000; 185 | bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); 186 | netdata_zfs_store_bin(bin, NETDATA_KEY_CALLS_WRITE); 187 | 188 | return 0; 189 | } 190 | 191 | SEC("kretprobe/zpl_open") 192 | int netdata_ret_zpl_open(struct pt_regs *ctx) 193 | { 194 | __u64 *fill, data; 195 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 196 | __u32 bin, pid = (__u32)(pid_tgid >> 32); 197 | 198 | fill = bpf_map_lookup_elem(&tmp_zfs, &pid); 199 | if (!fill) 200 | return 0; 201 | 202 | data = bpf_ktime_get_ns() - *fill; 203 | bpf_map_delete_elem(&tmp_zfs, &pid); 204 | 205 | // Skip entries with backward time 206 | if ( (s64)data < 0) 207 | return 0; 208 | 209 | // convert to microseconds 210 | data /= 1000; 211 | bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); 212 | netdata_zfs_store_bin(bin, NETDATA_KEY_CALLS_OPEN); 213 | 214 | return 0; 215 | } 216 | 217 | SEC("kretprobe/zpl_fsync") 218 | int netdata_ret_zpl_fsync(struct pt_regs *ctx) 219 | { 220 | __u64 *fill, data; 221 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 222 | __u32 bin, pid = (__u32)(pid_tgid >> 32); 223 | 224 | fill = bpf_map_lookup_elem(&tmp_zfs, &pid); 225 | if (!fill) 226 | return 0; 227 | 228 | data = bpf_ktime_get_ns() - *fill; 229 | bpf_map_delete_elem(&tmp_zfs, &pid); 230 | 231 | // Skip entries with backward time 232 | if ( (s64)data < 0) 233 | return 0; 234 | 235 | // convert to microseconds 236 | data /= 1000; 237 | bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); 238 | netdata_zfs_store_bin(bin, NETDATA_KEY_CALLS_SYNC); 239 | 240 | return 0; 241 | } 242 | 243 | char _license[] SEC("license") = "GPL"; 244 | 245 | -------------------------------------------------------------------------------- /kernel/xfs_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "xfs_netdata" 2 | #include 3 | #include 4 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)) 5 | #include 6 | #endif 7 | 8 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 9 | #include 10 | #else 11 | #include 12 | #endif 13 | #include "bpf_tracing.h" 14 | #include "bpf_helpers.h" 15 | #include "netdata_ebpf.h" 16 | 17 | /************************************************************************************ 18 | * 19 | * MAP Section 20 | * 21 | ***********************************************************************************/ 22 | 23 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 24 | struct { 25 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 26 | __type(key, __u32); 27 | __type(value, __u64); 28 | __uint(max_entries, NETDATA_FS_MAX_ELEMENTS); 29 | } tbl_xfs SEC(".maps"); 30 | 31 | struct { 32 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) 33 | __uint(type, BPF_MAP_TYPE_HASH); 34 | #else 35 | __uint(type, BPF_MAP_TYPE_PERCPU_HASH); 36 | #endif 37 | __type(key, __u32); 38 | __type(value, __u64); 39 | __uint(max_entries, 4192); 40 | } tmp_xfs SEC(".maps"); 41 | 42 | struct { 43 | __uint(type, BPF_MAP_TYPE_ARRAY); 44 | __type(key, __u32); 45 | __type(value, __u64); 46 | __uint(max_entries, NETDATA_CONTROLLER_END); 47 | } xfs_ctrl SEC(".maps"); 48 | 49 | #else 50 | struct bpf_map_def SEC("maps") tbl_xfs = { 51 | .type = BPF_MAP_TYPE_PERCPU_ARRAY, 52 | .key_size = sizeof(__u32), 53 | .value_size = sizeof(__u64), 54 | .max_entries = NETDATA_FS_MAX_ELEMENTS 55 | }; 56 | 57 | struct bpf_map_def SEC("maps") tmp_xfs = { 58 | .type = BPF_MAP_TYPE_HASH, 59 | .key_size = sizeof(__u32), 60 | .value_size = sizeof(__u64), 61 | .max_entries = 4192 62 | }; 63 | 64 | struct bpf_map_def SEC("maps") xfs_ctrl = { 65 | .type = BPF_MAP_TYPE_ARRAY, 66 | .key_size = sizeof(__u32), 67 | .value_size = sizeof(__u64), 68 | .max_entries = NETDATA_CONTROLLER_END 69 | }; 70 | #endif 71 | 72 | /************************************************************************************ 73 | * 74 | * ENTRY Section 75 | * 76 | ***********************************************************************************/ 77 | 78 | static __always_inline int netdata_xfs_entry() 79 | { 80 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 81 | __u32 pid = (__u32)(pid_tgid >> 32); 82 | __u64 ts = bpf_ktime_get_ns(); 83 | 84 | bpf_map_update_elem(&tmp_xfs, &pid, &ts, BPF_ANY); 85 | 86 | libnetdata_update_global(&xfs_ctrl, NETDATA_CONTROLLER_TEMP_TABLE_ADD, 1); 87 | 88 | return 0; 89 | } 90 | 91 | SEC("kprobe/xfs_file_read_iter") 92 | int netdata_xfs_file_read_iter(struct pt_regs *ctx) 93 | { 94 | return netdata_xfs_entry(); 95 | } 96 | 97 | SEC("kprobe/xfs_file_write_iter") 98 | int netdata_xfs_file_write_iter(struct pt_regs *ctx) 99 | { 100 | return netdata_xfs_entry(); 101 | } 102 | 103 | SEC("kprobe/xfs_file_open") 104 | int netdata_xfs_file_open(struct pt_regs *ctx) 105 | { 106 | return netdata_xfs_entry(); 107 | } 108 | 109 | SEC("kprobe/xfs_file_fsync") 110 | int netdata_xfs_file_fsync(struct pt_regs *ctx) 111 | { 112 | return netdata_xfs_entry(); 113 | } 114 | 115 | /************************************************************************************ 116 | * 117 | * END Section 118 | * 119 | ***********************************************************************************/ 120 | 121 | static void netdata_xfs_store_bin(__u32 bin, __u32 selection) 122 | { 123 | __u64 *fill, data; 124 | __u32 idx = selection * NETDATA_FS_MAX_BINS + bin; 125 | if (idx >= NETDATA_FS_MAX_ELEMENTS) 126 | return; 127 | 128 | fill = bpf_map_lookup_elem(&tbl_xfs, &idx); 129 | if (fill) { 130 | libnetdata_update_u64(fill, 1); 131 | return; 132 | } 133 | 134 | data = 1; 135 | bpf_map_update_elem(&tbl_xfs, &idx, &data, BPF_ANY); 136 | 137 | libnetdata_update_global(&xfs_ctrl, NETDATA_CONTROLLER_TEMP_TABLE_DEL, 1); 138 | } 139 | 140 | SEC("kretprobe/xfs_file_read_iter") 141 | int netdata_ret_xfs_file_read_iter(struct pt_regs *ctx) 142 | { 143 | __u64 *fill, data; 144 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 145 | __u32 bin, pid = (__u32)(pid_tgid >> 32); 146 | 147 | fill = bpf_map_lookup_elem(&tmp_xfs, &pid); 148 | if (!fill) 149 | return 0; 150 | 151 | data = bpf_ktime_get_ns() - *fill; 152 | bpf_map_delete_elem(&tmp_xfs, &pid); 153 | 154 | // Skip entries with backward time 155 | if ( (s64)data < 0) 156 | return 0; 157 | 158 | // convert to microseconds 159 | data /= 1000; 160 | bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); 161 | netdata_xfs_store_bin(bin, NETDATA_KEY_CALLS_READ); 162 | 163 | return 0; 164 | } 165 | 166 | SEC("kretprobe/xfs_file_write_iter") 167 | int netdata_ret_xfs_file_write_iter(struct pt_regs *ctx) 168 | { 169 | __u64 *fill, data; 170 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 171 | __u32 bin, pid = (__u32)(pid_tgid >> 32); 172 | 173 | fill = bpf_map_lookup_elem(&tmp_xfs, &pid); 174 | if (!fill) 175 | return 0; 176 | 177 | data = bpf_ktime_get_ns() - *fill; 178 | bpf_map_delete_elem(&tmp_xfs, &pid); 179 | 180 | // Skip entries with backward time 181 | if ( (s64)data < 0) 182 | return 0; 183 | 184 | // convert to microseconds 185 | data /= 1000; 186 | bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); 187 | netdata_xfs_store_bin(bin, NETDATA_KEY_CALLS_WRITE); 188 | 189 | return 0; 190 | } 191 | 192 | SEC("kretprobe/xfs_file_open") 193 | int netdata_ret_xfs_file_open(struct pt_regs *ctx) 194 | { 195 | __u64 *fill, data; 196 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 197 | __u32 bin, pid = (__u32)(pid_tgid >> 32); 198 | 199 | fill = bpf_map_lookup_elem(&tmp_xfs, &pid); 200 | if (!fill) 201 | return 0; 202 | 203 | data = bpf_ktime_get_ns() - *fill; 204 | bpf_map_delete_elem(&tmp_xfs, &pid); 205 | 206 | // Skip entries with backward time 207 | if ( (s64)data < 0) 208 | return 0; 209 | 210 | // convert to microseconds 211 | data /= 1000; 212 | bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); 213 | netdata_xfs_store_bin(bin, NETDATA_KEY_CALLS_OPEN); 214 | 215 | return 0; 216 | } 217 | 218 | SEC("kretprobe/xfs_file_fsync") 219 | int netdata_ret_xfs_file_fsync(struct pt_regs *ctx) 220 | { 221 | __u64 *fill, data; 222 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 223 | __u32 bin, pid = (__u32)(pid_tgid >> 32); 224 | 225 | fill = bpf_map_lookup_elem(&tmp_xfs, &pid); 226 | if (!fill) 227 | return 0; 228 | 229 | data = bpf_ktime_get_ns() - *fill; 230 | bpf_map_delete_elem(&tmp_xfs, &pid); 231 | 232 | // Skip entries with backward time 233 | if ( (s64)data < 0) 234 | return 0; 235 | 236 | // convert to microseconds 237 | data /= 1000; 238 | bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); 239 | netdata_xfs_store_bin(bin, NETDATA_KEY_CALLS_SYNC); 240 | 241 | return 0; 242 | } 243 | 244 | char _license[] SEC("license") = "GPL"; 245 | 246 | -------------------------------------------------------------------------------- /kernel/ext4_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "ext4_netdata" 2 | #include 3 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)) 4 | #include 5 | #endif 6 | 7 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 8 | #include 9 | #else 10 | #include 11 | #endif 12 | #include "bpf_tracing.h" 13 | #include "bpf_helpers.h" 14 | #include "netdata_ebpf.h" 15 | 16 | /************************************************************************************ 17 | * 18 | * MAP Section 19 | * 20 | ***********************************************************************************/ 21 | 22 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 23 | struct { 24 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 25 | __type(key, __u32); 26 | __type(value, __u64); 27 | __uint(max_entries, NETDATA_FS_MAX_ELEMENTS); 28 | } tbl_ext4 SEC(".maps"); 29 | 30 | struct { 31 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) 32 | __uint(type, BPF_MAP_TYPE_HASH); 33 | #else 34 | __uint(type, BPF_MAP_TYPE_PERCPU_HASH); 35 | #endif 36 | __type(key, __u32); 37 | __type(value, __u64); 38 | __uint(max_entries, 4192); 39 | } tmp_ext4 SEC(".maps"); 40 | 41 | struct { 42 | __uint(type, BPF_MAP_TYPE_ARRAY); 43 | __type(key, __u32); 44 | __type(value, __u64); 45 | __uint(max_entries, NETDATA_CONTROLLER_END); 46 | } ext4_ctrl SEC(".maps"); 47 | 48 | #else 49 | 50 | struct bpf_map_def SEC("maps") tbl_ext4 = { 51 | .type = BPF_MAP_TYPE_PERCPU_ARRAY, 52 | .key_size = sizeof(__u32), 53 | .value_size = sizeof(__u64), 54 | .max_entries = NETDATA_FS_MAX_ELEMENTS 55 | }; 56 | 57 | struct bpf_map_def SEC("maps") tmp_ext4 = { 58 | .type = BPF_MAP_TYPE_HASH, 59 | .key_size = sizeof(__u32), 60 | .value_size = sizeof(__u64), 61 | .max_entries = 4192 62 | }; 63 | 64 | struct bpf_map_def SEC("maps") ext4_ctrl = { 65 | .type = BPF_MAP_TYPE_ARRAY, 66 | .key_size = sizeof(__u32), 67 | .value_size = sizeof(__u64), 68 | .max_entries = NETDATA_CONTROLLER_END 69 | }; 70 | 71 | #endif 72 | 73 | /************************************************************************************ 74 | * 75 | * ENTRY Section 76 | * 77 | ***********************************************************************************/ 78 | 79 | static __always_inline int netdata_ext4_entry() 80 | { 81 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 82 | __u32 pid = (__u32)(pid_tgid >> 32); 83 | __u64 ts = bpf_ktime_get_ns(); 84 | 85 | bpf_map_update_elem(&tmp_ext4, &pid, &ts, BPF_ANY); 86 | 87 | libnetdata_update_global(&ext4_ctrl, NETDATA_CONTROLLER_TEMP_TABLE_ADD, 1); 88 | 89 | return 0; 90 | } 91 | 92 | SEC("kprobe/ext4_file_read_iter") 93 | int netdata_ext4_file_read_iter(struct pt_regs *ctx) 94 | { 95 | return netdata_ext4_entry(); 96 | } 97 | 98 | SEC("kprobe/ext4_file_write_iter") 99 | int netdata_ext4_file_write_iter(struct pt_regs *ctx) 100 | { 101 | return netdata_ext4_entry(); 102 | } 103 | 104 | SEC("kprobe/ext4_file_open") 105 | int netdata_ext4_file_open(struct pt_regs *ctx) 106 | { 107 | return netdata_ext4_entry(); 108 | } 109 | 110 | SEC("kprobe/ext4_sync_file") 111 | int netdata_ext4_sync_file(struct pt_regs *ctx) 112 | { 113 | return netdata_ext4_entry(); 114 | } 115 | 116 | /************************************************************************************ 117 | * 118 | * END Section 119 | * 120 | ***********************************************************************************/ 121 | 122 | static void netdata_ext4_store_bin(__u32 bin, __u32 selection) 123 | { 124 | __u64 *fill, data; 125 | __u32 idx = selection * NETDATA_FS_MAX_BINS + bin; 126 | if (idx >= NETDATA_FS_MAX_ELEMENTS) 127 | return; 128 | 129 | fill = bpf_map_lookup_elem(&tbl_ext4, &idx); 130 | if (fill) { 131 | libnetdata_update_u64(fill, 1); 132 | return; 133 | } 134 | 135 | data = 1; 136 | bpf_map_update_elem(&tbl_ext4, &idx, &data, BPF_ANY); 137 | 138 | libnetdata_update_global(&ext4_ctrl, NETDATA_CONTROLLER_TEMP_TABLE_DEL, 1); 139 | } 140 | 141 | SEC("kretprobe/ext4_file_read_iter") 142 | int netdata_ret_ext4_ext4_file_read_iter(struct pt_regs *ctx) 143 | { 144 | __u64 *fill, data; 145 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 146 | __u32 bin, pid = (__u32)(pid_tgid >> 32); 147 | 148 | fill = bpf_map_lookup_elem(&tmp_ext4, &pid); 149 | if (!fill) 150 | return 0; 151 | 152 | data = bpf_ktime_get_ns() - *fill; 153 | bpf_map_delete_elem(&tmp_ext4, &pid); 154 | 155 | // Skip entries with backward time 156 | if ( (s64)data < 0) 157 | return 0; 158 | 159 | // convert to microseconds 160 | data /= 1000; 161 | bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); 162 | netdata_ext4_store_bin(bin, NETDATA_KEY_CALLS_READ); 163 | 164 | return 0; 165 | } 166 | 167 | SEC("kretprobe/ext4_file_write_iter") 168 | int netdata_ret_ext4_file_write_iter(struct pt_regs *ctx) 169 | { 170 | __u64 *fill, data; 171 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 172 | __u32 bin, pid = (__u32)(pid_tgid >> 32); 173 | 174 | fill = bpf_map_lookup_elem(&tmp_ext4, &pid); 175 | if (!fill) 176 | return 0; 177 | 178 | data = bpf_ktime_get_ns() - *fill; 179 | bpf_map_delete_elem(&tmp_ext4, &pid); 180 | 181 | // Skip entries with backward time 182 | if ( (s64)data < 0) 183 | return 0; 184 | 185 | // convert to microseconds 186 | data /= 1000; 187 | bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); 188 | netdata_ext4_store_bin(bin, NETDATA_KEY_CALLS_WRITE); 189 | 190 | return 0; 191 | } 192 | 193 | SEC("kretprobe/ext4_file_open") 194 | int netdata_ret_ext4_file_open(struct pt_regs *ctx) 195 | { 196 | __u64 *fill, data; 197 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 198 | __u32 bin, pid = (__u32)(pid_tgid >> 32); 199 | 200 | fill = bpf_map_lookup_elem(&tmp_ext4, &pid); 201 | if (!fill) 202 | return 0; 203 | 204 | data = bpf_ktime_get_ns() - *fill; 205 | bpf_map_delete_elem(&tmp_ext4, &pid); 206 | 207 | // Skip entries with backward time 208 | if ( (s64)data < 0) 209 | return 0; 210 | 211 | // convert to microseconds 212 | data /= 1000; 213 | bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); 214 | netdata_ext4_store_bin(bin, NETDATA_KEY_CALLS_OPEN); 215 | 216 | return 0; 217 | } 218 | 219 | SEC("kretprobe/ext4_sync_file") 220 | int netdata_ret_ext4_sync_file(struct pt_regs *ctx) 221 | { 222 | __u64 *fill, data; 223 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 224 | __u32 bin, pid = (__u32)(pid_tgid >> 32); 225 | 226 | fill = bpf_map_lookup_elem(&tmp_ext4, &pid); 227 | if (!fill) 228 | return 0; 229 | 230 | data = bpf_ktime_get_ns() - *fill; 231 | bpf_map_delete_elem(&tmp_ext4, &pid); 232 | 233 | // Skip entries with backward time 234 | if ( (s64)data < 0) 235 | return 0; 236 | 237 | // convert to microseconds 238 | data /= 1000; 239 | bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); 240 | netdata_ext4_store_bin(bin, NETDATA_KEY_CALLS_SYNC); 241 | 242 | return 0; 243 | } 244 | 245 | char _license[] SEC("license") = "GPL"; 246 | 247 | -------------------------------------------------------------------------------- /includes/netdata_common.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #ifndef _NETDATA_COMMON_ 4 | #define _NETDATA_COMMON_ 1 5 | 6 | #include "netdata_defs.h" 7 | 8 | struct netdata_error_report_t { 9 | char comm[TASK_COMM_LEN]; 10 | __u32 pid; 11 | 12 | int type; 13 | int err; 14 | }; 15 | 16 | static __always_inline void libnetdata_update_u64(__u64 *res, __u64 value) 17 | { 18 | __sync_fetch_and_add(res, value); 19 | if ( (0xFFFFFFFFFFFFFFFF - *res) <= value) { 20 | *res = value; 21 | } 22 | } 23 | 24 | static __always_inline void libnetdata_update_s64(__s64 *res, __s64 value) 25 | { 26 | __sync_fetch_and_add(res, value); 27 | } 28 | 29 | static __always_inline void libnetdata_update_global(void *tbl, __u32 key, __u64 value) 30 | { 31 | __u64 *res; 32 | res = bpf_map_lookup_elem(tbl, &key); 33 | if (res) 34 | libnetdata_update_u64(res, value) ; 35 | else 36 | bpf_map_update_elem(tbl, &key, &value, BPF_EXIST); 37 | } 38 | 39 | static __always_inline void libnetdata_update_sglobal(void *tbl, __u32 key, __s64 value) 40 | { 41 | __s64 *res; 42 | res = bpf_map_lookup_elem(tbl, &key); 43 | if (res) 44 | libnetdata_update_s64(res, value) ; 45 | else 46 | bpf_map_update_elem(tbl, &key, &value, BPF_EXIST); 47 | } 48 | 49 | static __always_inline void libnetdata_update_uid_gid(__u32 *uid, __u32 *gid) 50 | { 51 | __u64 uid_gid = bpf_get_current_uid_gid(); 52 | *uid = (__u32)uid_gid; 53 | *gid = (__u32)(uid_gid>>32); 54 | } 55 | 56 | /** 57 | * The motive we are using log2 to plot instead the raw value is well explained 58 | * inside this paper https://www.fsl.cs.stonybrook.edu/docs/osprof-osdi2006/osprof.pdf 59 | */ 60 | static __always_inline unsigned int libnetdata_log2(unsigned int v) 61 | { 62 | unsigned int r; 63 | unsigned int shift; 64 | 65 | r = (v > 0xFFFF) << 4; v >>= r; 66 | shift = (v > 0xFF) << 3; v >>= shift; r |= shift; 67 | shift = (v > 0xF) << 2; v >>= shift; r |= shift; 68 | shift = (v > 0x3) << 1; v >>= shift; r |= shift; 69 | r |= (v >> 1); 70 | 71 | return r; 72 | } 73 | 74 | static __always_inline unsigned int libnetdata_log2l(__u64 v) 75 | { 76 | unsigned int hi = v >> 32; 77 | if (hi) 78 | return libnetdata_log2(hi) + 32; 79 | else 80 | return libnetdata_log2(v); 81 | } 82 | 83 | static __always_inline void libnetdata_update_u32(u32 *res, u32 value) 84 | { 85 | if (!value) 86 | return; 87 | 88 | __sync_fetch_and_add(res, value); 89 | if ( (0xFFFFFFFF - *res) <= value) { 90 | *res = value; 91 | } 92 | } 93 | 94 | static __always_inline __u32 libnetdata_select_idx(__u64 val, __u32 end) 95 | { 96 | __u32 rlog; 97 | 98 | rlog = libnetdata_log2l(val); 99 | 100 | if (rlog > end) 101 | rlog = end; 102 | 103 | return rlog; 104 | } 105 | 106 | // Copied from linux/samples/bpf/tracex1_kern.c 107 | #define _(P) \ 108 | ({ \ 109 | typeof(P) val = 0; \ 110 | bpf_probe_read(&val, sizeof(val), &(P)); \ 111 | val; \ 112 | }) 113 | 114 | // Copied from linux/samples/bpf/trace_common.h 115 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0)) 116 | 117 | #ifdef __x86_64__ 118 | #define NETDATA_SYSCALL(SYS) "__x64_sys_" __stringify(SYS) 119 | #elif defined(__s390x__) 120 | #define NETDATA_SYSCALL(SYS) "__s390x_" __stringify(SYS) 121 | #else 122 | #define NETDATA_SYSCALL(SYS) "sys_" __stringify(SYS) 123 | #endif 124 | 125 | #else 126 | #define NETDATA_SYSCALL(SYS) "sys_" __stringify(SYS) 127 | #endif 128 | 129 | /* 130 | the TP_DATA_LOC_READ_* macros are used for reading from a field that's pointed 131 | to by a __data_loc variable. 132 | 133 | FYI, a __data_loc variable is really an int that contains within it the data 134 | needed to get the location of the actual value. these macros do the 135 | transformation needed to get that final location and then read from it. 136 | 137 | this code is from iovisor/bcc file src/cc/exports/helpers.h and modified by 138 | Netdata's Agent team for inclusion in Netdata. 139 | */ 140 | #define TP_DATA_LOC_READ_CONST(_dst, _arg, _data_loc, _length) do { \ 141 | unsigned short __offset = _data_loc & 0xFFFF; \ 142 | bpf_probe_read((void *)_dst, _length, (char *)_arg + __offset); \ 143 | } while (0) 144 | #define TP_DATA_LOC_READ(_dst, _arg, _data_loc) do { \ 145 | unsigned short __offset = _data_loc & 0xFFFF; \ 146 | unsigned short __length = _data_loc >> 16; \ 147 | bpf_probe_read((void *)_dst, __length, (char *)_arg + __offset); \ 148 | } while (0) 149 | 150 | // Get real parent PID 151 | static __always_inline __u32 netdata_get_real_parent_pid() 152 | { 153 | __u32 ppid; 154 | struct task_struct *task, *real_parent; 155 | 156 | task = (struct task_struct *)bpf_get_current_task(); 157 | real_parent = _(task->real_parent); 158 | bpf_probe_read(&ppid, sizeof(__u32), &real_parent->tgid); 159 | 160 | return ppid; 161 | } 162 | 163 | static __always_inline __u32 netdata_get_parent_pid() 164 | { 165 | __u32 ppid; 166 | struct task_struct *task, *parent; 167 | 168 | task = (struct task_struct *)bpf_get_current_task(); 169 | parent = _(task->parent); 170 | bpf_probe_read(&ppid, sizeof(__u32), &parent->tgid); 171 | 172 | return ppid; 173 | } 174 | 175 | static __always_inline __u32 netdata_get_current_pid(__u32 *tgid) 176 | { 177 | __u32 pid; 178 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 179 | pid = (__u32)pid_tgid; 180 | *tgid = (__u32)(pid_tgid>>32); 181 | 182 | return pid; 183 | } 184 | 185 | static __always_inline __u32 netdata_get_pid(void *ctrl_tbl, __u32 *tgid) 186 | { 187 | __u32 key = NETDATA_CONTROLLER_APPS_LEVEL; 188 | 189 | __u64 *level = bpf_map_lookup_elem(ctrl_tbl ,&key); 190 | if (level) { 191 | if (*level == NETDATA_APPS_LEVEL_REAL_PARENT) { 192 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 193 | *tgid = (__u32)(pid_tgid>>32); 194 | return netdata_get_real_parent_pid(); 195 | } else if (*level == NETDATA_APPS_LEVEL_PARENT) { 196 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 197 | *tgid = (__u32)(pid_tgid>>32); 198 | return netdata_get_parent_pid(); 199 | } else if (*level == NETDATA_APPS_LEVEL_ALL) 200 | return netdata_get_current_pid(tgid); 201 | else if (*level == NETDATA_APPS_LEVEL_IGNORE) // Ignore PID 202 | return 0; 203 | } 204 | 205 | return netdata_get_real_parent_pid(); 206 | } 207 | 208 | static __always_inline void *netdata_get_pid_structure(__u32 *store_pid, __u32 *store_tgid, void *ctrl_tbl, void *pid_tbl) 209 | { 210 | __u32 pid = netdata_get_pid(ctrl_tbl, store_tgid); 211 | 212 | *store_pid = pid; 213 | 214 | return bpf_map_lookup_elem(pid_tbl, store_pid); 215 | } 216 | 217 | static __always_inline __u32 monitor_apps(void *ctrl_tbl) 218 | { 219 | __u32 apps_key = NETDATA_CONTROLLER_APPS_ENABLED; 220 | __u64 *apps = bpf_map_lookup_elem(ctrl_tbl ,&apps_key); 221 | if (!apps || (apps && *apps == 0)) 222 | return 0; 223 | 224 | return 1; 225 | } 226 | 227 | #endif /* _NETDATA_COMMON_ */ 228 | 229 | -------------------------------------------------------------------------------- /kernel/nfs_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "nfs_netdata" 2 | #include 3 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)) 4 | #include 5 | #endif 6 | 7 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 8 | #include 9 | #else 10 | #include 11 | #endif 12 | #include "bpf_tracing.h" 13 | #include "bpf_helpers.h" 14 | #include "netdata_ebpf.h" 15 | 16 | /************************************************************************************ 17 | * 18 | * MAP Section 19 | * 20 | ***********************************************************************************/ 21 | 22 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 23 | struct { 24 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 25 | __type(key, __u32); 26 | __type(value, __u64); 27 | __uint(max_entries, NETDATA_FS_MAX_ELEMENTS); 28 | } tbl_nfs SEC(".maps"); 29 | 30 | struct { 31 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) 32 | __uint(type, BPF_MAP_TYPE_HASH); 33 | #else 34 | __uint(type, BPF_MAP_TYPE_PERCPU_HASH); 35 | #endif 36 | __type(key, __u32); 37 | __type(value, __u64); 38 | __uint(max_entries, 4192); 39 | } tmp_nfs SEC(".maps"); 40 | 41 | struct { 42 | __uint(type, BPF_MAP_TYPE_ARRAY); 43 | __type(key, __u32); 44 | __type(value, __u64); 45 | __uint(max_entries, NETDATA_CONTROLLER_END); 46 | } nfs_ctrl SEC(".maps"); 47 | 48 | #else 49 | 50 | struct bpf_map_def SEC("maps") tbl_nfs = { 51 | .type = BPF_MAP_TYPE_PERCPU_ARRAY, 52 | .key_size = sizeof(__u32), 53 | .value_size = sizeof(__u64), 54 | .max_entries = NETDATA_FS_MAX_ELEMENTS 55 | }; 56 | 57 | struct bpf_map_def SEC("maps") tmp_nfs = { 58 | .type = BPF_MAP_TYPE_HASH, 59 | .key_size = sizeof(__u32), 60 | .value_size = sizeof(__u64), 61 | .max_entries = 4192 62 | }; 63 | 64 | struct bpf_map_def SEC("maps") nfs_ctrl = { 65 | .type = BPF_MAP_TYPE_ARRAY, 66 | .key_size = sizeof(__u32), 67 | .value_size = sizeof(__u64), 68 | .max_entries = NETDATA_CONTROLLER_END 69 | }; 70 | 71 | #endif 72 | 73 | /************************************************************************************ 74 | * 75 | * ENTRY Section 76 | * 77 | ***********************************************************************************/ 78 | 79 | static __always_inline int netdata_nfs_entry() 80 | { 81 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 82 | __u32 pid = (__u32)(pid_tgid >> 32); 83 | __u64 ts = bpf_ktime_get_ns(); 84 | 85 | bpf_map_update_elem(&tmp_nfs, &pid, &ts, BPF_ANY); 86 | 87 | libnetdata_update_global(&nfs_ctrl, NETDATA_CONTROLLER_TEMP_TABLE_ADD, 1); 88 | 89 | return 0; 90 | } 91 | 92 | SEC("kprobe/nfs_file_read") 93 | int netdata_nfs_file_read(struct pt_regs *ctx) 94 | { 95 | return netdata_nfs_entry(); 96 | } 97 | 98 | SEC("kprobe/nfs_file_write") 99 | int netdata_nfs_file_write(struct pt_regs *ctx) 100 | { 101 | return netdata_nfs_entry(); 102 | } 103 | 104 | SEC("kprobe/nfs_file_open") 105 | int netdata_nfs_file_open(struct pt_regs *ctx) 106 | { 107 | return netdata_nfs_entry(); 108 | } 109 | 110 | SEC("kprobe/nfs4_file_open") 111 | int netdata_nfs4_file_open(struct pt_regs *ctx) 112 | { 113 | return netdata_nfs_entry(); 114 | } 115 | 116 | SEC("kprobe/nfs_getattr") 117 | int netdata_nfs_getattr(struct pt_regs *ctx) 118 | { 119 | return netdata_nfs_entry(); 120 | } 121 | 122 | /************************************************************************************ 123 | * 124 | * END Section 125 | * 126 | ***********************************************************************************/ 127 | 128 | static void netdata_nfs_store_bin(__u32 bin, __u32 selection) 129 | { 130 | __u64 *fill, data; 131 | __u32 idx = selection * NETDATA_FS_MAX_BINS + bin; 132 | if (idx >= NETDATA_FS_MAX_ELEMENTS) 133 | return; 134 | 135 | fill = bpf_map_lookup_elem(&tbl_nfs, &idx); 136 | if (fill) { 137 | libnetdata_update_u64(fill, 1); 138 | return; 139 | } 140 | 141 | data = 1; 142 | bpf_map_update_elem(&tbl_nfs, &idx, &data, BPF_ANY); 143 | 144 | libnetdata_update_global(&nfs_ctrl, NETDATA_CONTROLLER_TEMP_TABLE_DEL, 1); 145 | } 146 | 147 | SEC("kretprobe/nfs_file_read") 148 | int netdata_ret_nfs_file_read(struct pt_regs *ctx) 149 | { 150 | __u64 *fill, data; 151 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 152 | __u32 bin, pid = (__u32)(pid_tgid >> 32); 153 | 154 | fill = bpf_map_lookup_elem(&tmp_nfs, &pid); 155 | if (!fill) 156 | return 0; 157 | 158 | data = bpf_ktime_get_ns() - *fill; 159 | bpf_map_delete_elem(&tmp_nfs, &pid); 160 | 161 | // Skip entries with backward time 162 | if ( (s64)data < 0) 163 | return 0; 164 | 165 | // convert to microseconds 166 | data /= 1000; 167 | bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); 168 | netdata_nfs_store_bin(bin, NETDATA_KEY_CALLS_READ); 169 | 170 | return 0; 171 | } 172 | 173 | SEC("kretprobe/nfs_file_write") 174 | int netdata_ret_nfs_file_write(struct pt_regs *ctx) 175 | { 176 | __u64 *fill, data; 177 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 178 | __u32 bin, pid = (__u32)(pid_tgid >> 32); 179 | 180 | fill = bpf_map_lookup_elem(&tmp_nfs, &pid); 181 | if (!fill) 182 | return 0; 183 | 184 | data = bpf_ktime_get_ns() - *fill; 185 | bpf_map_delete_elem(&tmp_nfs, &pid); 186 | 187 | // Skip entries with backward time 188 | if ( (s64)data < 0) 189 | return 0; 190 | 191 | // convert to microseconds 192 | data /= 1000; 193 | bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); 194 | netdata_nfs_store_bin(bin, NETDATA_KEY_CALLS_WRITE); 195 | 196 | return 0; 197 | } 198 | 199 | SEC("kretprobe/nfs_file_open") 200 | int netdata_ret_nfs_file_open(struct pt_regs *ctx) 201 | { 202 | __u64 *fill, data; 203 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 204 | __u32 bin, pid = (__u32)(pid_tgid >> 32); 205 | 206 | fill = bpf_map_lookup_elem(&tmp_nfs, &pid); 207 | if (!fill) 208 | return 0; 209 | 210 | data = bpf_ktime_get_ns() - *fill; 211 | bpf_map_delete_elem(&tmp_nfs, &pid); 212 | 213 | // Skip entries with backward time 214 | if ( (s64)data < 0) 215 | return 0; 216 | 217 | // convert to microseconds 218 | data /= 1000; 219 | bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); 220 | netdata_nfs_store_bin(bin, NETDATA_KEY_CALLS_OPEN); 221 | 222 | return 0; 223 | } 224 | 225 | SEC("kretprobe/nfs4_file_open") 226 | int netdata_ret_nfs4_file_open(struct pt_regs *ctx) 227 | { 228 | __u64 *fill, data; 229 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 230 | __u32 bin, pid = (__u32)(pid_tgid >> 32); 231 | 232 | fill = bpf_map_lookup_elem(&tmp_nfs, &pid); 233 | if (!fill) 234 | return 0; 235 | 236 | data = bpf_ktime_get_ns() - *fill; 237 | bpf_map_delete_elem(&tmp_nfs, &pid); 238 | 239 | // Skip entries with backward time 240 | if ( (s64)data < 0) 241 | return 0; 242 | 243 | // convert to microseconds 244 | data /= 1000; 245 | bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); 246 | netdata_nfs_store_bin(bin, NETDATA_KEY_CALLS_OPEN); 247 | 248 | return 0; 249 | } 250 | 251 | SEC("kretprobe/nfs_getattr") 252 | int netdata_ret_nfs_getattr(struct pt_regs *ctx) 253 | { 254 | __u64 *fill, data; 255 | __u64 pid_tgid = bpf_get_current_pid_tgid(); 256 | __u32 bin, pid = (__u32)(pid_tgid >> 32); 257 | 258 | fill = bpf_map_lookup_elem(&tmp_nfs, &pid); 259 | if (!fill) 260 | return 0; 261 | 262 | data = bpf_ktime_get_ns() - *fill; 263 | bpf_map_delete_elem(&tmp_nfs, &pid); 264 | 265 | // Skip entries with backward time 266 | if ( (s64)data < 0) 267 | return 0; 268 | 269 | // convert to microseconds 270 | data /= 1000; 271 | bin = libnetdata_select_idx(data, NETDATA_FS_MAX_BINS_POS); 272 | netdata_nfs_store_bin(bin, NETDATA_KEY_CALLS_SYNC); 273 | 274 | return 0; 275 | } 276 | 277 | char _license[] SEC("license") = "GPL"; 278 | 279 | -------------------------------------------------------------------------------- /kernel/cachestat_kern.c: -------------------------------------------------------------------------------- 1 | #define KBUILD_MODNAME "cachestat_kern" 2 | #include 3 | #include 4 | #include 5 | 6 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 7 | #include 8 | #else 9 | #include 10 | #endif 11 | #include "bpf_tracing.h" 12 | #include "bpf_helpers.h" 13 | #include 14 | #include "netdata_ebpf.h" 15 | 16 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 17 | struct { 18 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 19 | __type(key, __u32); 20 | __type(value, __u64); 21 | __uint(max_entries, NETDATA_CACHESTAT_END); 22 | } cstat_global SEC(".maps"); 23 | 24 | struct { 25 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) 26 | __uint(type, BPF_MAP_TYPE_HASH); 27 | #else 28 | __uint(type, BPF_MAP_TYPE_PERCPU_HASH); 29 | #endif 30 | __type(key, __u32); 31 | __type(value, netdata_cachestat_t); 32 | __uint(max_entries, PID_MAX_DEFAULT); 33 | } cstat_pid SEC(".maps"); 34 | 35 | struct { 36 | __uint(type, BPF_MAP_TYPE_ARRAY); 37 | __type(key, __u32); 38 | __type(value, __u64); 39 | __uint(max_entries, NETDATA_CONTROLLER_END); 40 | } cstat_ctrl SEC(".maps"); 41 | 42 | #else 43 | 44 | struct bpf_map_def SEC("maps") cstat_global = { 45 | .type = BPF_MAP_TYPE_PERCPU_ARRAY, 46 | .key_size = sizeof(__u32), 47 | .value_size = sizeof(__u64), 48 | .max_entries = NETDATA_CACHESTAT_END 49 | }; 50 | 51 | struct bpf_map_def SEC("maps") cstat_pid = { 52 | .type = BPF_MAP_TYPE_HASH, 53 | .key_size = sizeof(__u32), 54 | .value_size = sizeof(netdata_cachestat_t), 55 | .max_entries = PID_MAX_DEFAULT 56 | }; 57 | 58 | struct bpf_map_def SEC("maps") cstat_ctrl = { 59 | .type = BPF_MAP_TYPE_ARRAY, 60 | .key_size = sizeof(__u32), 61 | .value_size = sizeof(__u64), 62 | .max_entries = NETDATA_CONTROLLER_END 63 | }; 64 | 65 | #endif 66 | 67 | /************************************************************************************ 68 | * 69 | * Probe Section 70 | * 71 | ***********************************************************************************/ 72 | 73 | SEC("kprobe/add_to_page_cache_lru") 74 | int netdata_add_to_page_cache_lru(struct pt_regs* ctx) 75 | { 76 | netdata_cachestat_t *fill, data = {}; 77 | libnetdata_update_global(&cstat_global, NETDATA_KEY_CALLS_ADD_TO_PAGE_CACHE_LRU, 1); 78 | 79 | __u32 key = 0; 80 | __u32 tgid = 0; 81 | if (!monitor_apps(&cstat_ctrl)) 82 | return 0; 83 | 84 | fill = netdata_get_pid_structure(&key, &tgid, &cstat_ctrl, &cstat_pid); 85 | if (fill) { 86 | libnetdata_update_u32(&fill->add_to_page_cache_lru, 1); 87 | } else { 88 | data.ct = bpf_ktime_get_ns(); 89 | libnetdata_update_uid_gid(&data.uid, &data.gid); 90 | data.tgid = tgid; 91 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 92 | bpf_get_current_comm(&data.name, TASK_COMM_LEN); 93 | #else 94 | data.name[0] = '\0'; 95 | #endif 96 | 97 | data.add_to_page_cache_lru = 1; 98 | bpf_map_update_elem(&cstat_pid, &key, &data, BPF_ANY); 99 | 100 | libnetdata_update_global(&cstat_ctrl, NETDATA_CONTROLLER_PID_TABLE_ADD, 1); 101 | } 102 | 103 | return 0; 104 | } 105 | 106 | SEC("kprobe/mark_page_accessed") 107 | int netdata_mark_page_accessed(struct pt_regs* ctx) 108 | { 109 | netdata_cachestat_t *fill, data = {}; 110 | libnetdata_update_global(&cstat_global, NETDATA_KEY_CALLS_MARK_PAGE_ACCESSED, 1); 111 | 112 | __u32 key = 0; 113 | __u32 tgid = 0; 114 | if (!monitor_apps(&cstat_ctrl)) 115 | return 0; 116 | 117 | fill = netdata_get_pid_structure(&key, &tgid, &cstat_ctrl, &cstat_pid); 118 | if (fill) { 119 | libnetdata_update_u32(&fill->mark_page_accessed, 1); 120 | } else { 121 | data.ct = bpf_ktime_get_ns(); 122 | libnetdata_update_uid_gid(&data.uid, &data.gid); 123 | data.tgid = tgid; 124 | 125 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 126 | bpf_get_current_comm(&data.name, TASK_COMM_LEN); 127 | #else 128 | data.name[0] = '\0'; 129 | #endif 130 | 131 | data.mark_page_accessed = 1; 132 | bpf_map_update_elem(&cstat_pid, &key, &data, BPF_ANY); 133 | 134 | libnetdata_update_global(&cstat_ctrl, NETDATA_CONTROLLER_PID_TABLE_ADD, 1); 135 | } 136 | 137 | return 0; 138 | } 139 | 140 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0)) 141 | 142 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,16,0)) 143 | // When kernel 5.16.0 was released, __set_page_dirty became a static inline function, 144 | // so we are callging directly the __folio_mark_dirty. 145 | SEC("kprobe/__folio_mark_dirty") 146 | #else 147 | // When kernel 5.15.0 was released the function account_page_dirtied became static 148 | // https://elixir.bootlin.com/linux/v5.15/source/mm/page-writeback.c#L2441 149 | // as consequence of this, we are monitoring the function from caller. 150 | SEC("kprobe/__set_page_dirty") 151 | #endif 152 | int netdata_set_page_dirty(struct pt_regs* ctx) 153 | { 154 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(5,16,0)) 155 | struct page *page = (struct page *)PT_REGS_PARM1(ctx) ; 156 | struct address_space *mapping = _(page->mapping); 157 | 158 | if (!mapping) 159 | return 0; 160 | #endif 161 | 162 | netdata_cachestat_t *fill, data = {}; 163 | libnetdata_update_global(&cstat_global, NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED, 1); 164 | 165 | __u32 key = 0; 166 | __u32 tgid = 0; 167 | if (!monitor_apps(&cstat_ctrl)) 168 | return 0; 169 | 170 | fill = netdata_get_pid_structure(&key, &tgid, &cstat_ctrl, &cstat_pid); 171 | if (fill) { 172 | libnetdata_update_u32(&fill->account_page_dirtied, 1); 173 | } else { 174 | data.ct = bpf_ktime_get_ns(); 175 | libnetdata_update_uid_gid(&data.uid, &data.gid); 176 | data.tgid = tgid; 177 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 178 | bpf_get_current_comm(&data.name, TASK_COMM_LEN); 179 | #else 180 | data.name[0] = '\0'; 181 | #endif 182 | 183 | data.account_page_dirtied = 1; 184 | bpf_map_update_elem(&cstat_pid, &key, &data, BPF_ANY); 185 | 186 | libnetdata_update_global(&cstat_ctrl, NETDATA_CONTROLLER_PID_TABLE_ADD, 1); 187 | } 188 | 189 | return 0; 190 | } 191 | #else 192 | #if defined(RHEL_MAJOR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(5,14,0)) 193 | SEC("kprobe/__folio_mark_dirty") 194 | #else 195 | SEC("kprobe/account_page_dirtied") 196 | #endif 197 | int netdata_account_page_dirtied(struct pt_regs* ctx) 198 | { 199 | netdata_cachestat_t *fill, data = {}; 200 | libnetdata_update_global(&cstat_global, NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED, 1); 201 | 202 | __u32 key = 0; 203 | __u32 tgid = 0; 204 | if (!monitor_apps(&cstat_ctrl)) 205 | return 0; 206 | 207 | fill = netdata_get_pid_structure(&key, &tgid, &cstat_ctrl, &cstat_pid); 208 | if (fill) { 209 | libnetdata_update_u32(&fill->account_page_dirtied, 1); 210 | } else { 211 | data.ct = bpf_ktime_get_ns(); 212 | libnetdata_update_uid_gid(&data.uid, &data.gid); 213 | data.tgid = tgid; 214 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 215 | bpf_get_current_comm(&data.name, TASK_COMM_LEN); 216 | #else 217 | data.name[0] = '\0'; 218 | #endif 219 | 220 | data.account_page_dirtied = 1; 221 | bpf_map_update_elem(&cstat_pid, &key, &data, BPF_ANY); 222 | 223 | libnetdata_update_global(&cstat_ctrl, NETDATA_CONTROLLER_PID_TABLE_ADD, 1); 224 | } 225 | 226 | return 0; 227 | } 228 | #endif 229 | 230 | SEC("kprobe/mark_buffer_dirty") 231 | int netdata_mark_buffer_dirty(struct pt_regs* ctx) 232 | { 233 | netdata_cachestat_t *fill, data = {}; 234 | libnetdata_update_global(&cstat_global, NETDATA_KEY_CALLS_MARK_BUFFER_DIRTY, 1); 235 | 236 | __u32 key = 0; 237 | __u32 tgid = 0; 238 | if (!monitor_apps(&cstat_ctrl)) 239 | return 0; 240 | 241 | fill = netdata_get_pid_structure(&key, &tgid, &cstat_ctrl, &cstat_pid); 242 | if (fill) { 243 | libnetdata_update_u32(&fill->mark_buffer_dirty, 1); 244 | } else { 245 | data.ct = bpf_ktime_get_ns(); 246 | libnetdata_update_uid_gid(&data.uid, &data.gid); 247 | data.tgid = tgid; 248 | #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) 249 | bpf_get_current_comm(&data.name, TASK_COMM_LEN); 250 | #else 251 | data.name[0] = '\0'; 252 | #endif 253 | 254 | data.mark_buffer_dirty = 1; 255 | bpf_map_update_elem(&cstat_pid, &key, &data, BPF_ANY); 256 | 257 | libnetdata_update_global(&cstat_ctrl, NETDATA_CONTROLLER_PID_TABLE_ADD, 1); 258 | } 259 | 260 | return 0; 261 | } 262 | 263 | char _license[] SEC("license") = "GPL"; 264 | 265 | --------------------------------------------------------------------------------