├── 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 | 
4 | 
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 |
--------------------------------------------------------------------------------