From 5c3c9c130e121cf89c51b95c5621f33093520f43 Mon Sep 17 00:00:00 2001 From: Timo Beckers Date: Thu, 19 May 2022 16:10:30 +0200 Subject: [PATCH] docs: add documentation Signed-off-by: Timo Beckers --- .gitignore | 7 + docs/Pipfile | 18 + docs/Pipfile.lock | 541 ++++++++++++ docs/README.md | 21 + docs/ebpf.py | 230 +++++ docs/ebpf/about.md | 9 + docs/ebpf/btf/index.md | 1 + docs/ebpf/features/index.md | 1 + docs/ebpf/getting-started/further-reading.md | 1 + docs/ebpf/getting-started/index.md | 108 +++ docs/ebpf/getting-started/rlimit.md | 1 + docs/ebpf/index.md | 8 + docs/ebpf/loading/core.md | 2 + docs/ebpf/loading/elf-sections.md | 12 + docs/ebpf/loading/index.md | 78 ++ docs/ebpf/loading/object-lifecycle.md | 95 ++ docs/ebpf/programs/attaching.md | 1 + docs/ebpf/programs/testing.md | 3 + docs/ebpf/stylesheets/extra.css | 47 + docs/ebpf/use-cases.md | 5 + docs/examples/Makefile | 4 + docs/examples/docs.c | 20 + docs/examples/docs.h | 7 + docs/examples/docs_test.go | 99 +++ docs/includes/glossary.md | 10 + docs/mkdocs.yml | 151 ++++ docs/overrides/.icons/ebee-color.svg | 15 + docs/overrides/.icons/ebee-mono.svg | 1 + docs/overrides/.icons/ebpf-go.svg | 860 +++++++++++++++++++ docs/overrides/partials/source-file.html | 12 + docs/vars.yml | 3 + netlify.toml | 4 + 32 files changed, 2375 insertions(+) create mode 100644 docs/Pipfile create mode 100644 docs/Pipfile.lock create mode 100644 docs/README.md create mode 100644 docs/ebpf.py create mode 100644 docs/ebpf/about.md create mode 100644 docs/ebpf/btf/index.md create mode 100644 docs/ebpf/features/index.md create mode 100644 docs/ebpf/getting-started/further-reading.md create mode 100644 docs/ebpf/getting-started/index.md create mode 100644 docs/ebpf/getting-started/rlimit.md create mode 100644 docs/ebpf/index.md create mode 100644 docs/ebpf/loading/core.md create mode 100644 docs/ebpf/loading/elf-sections.md create mode 100644 docs/ebpf/loading/index.md create mode 100644 docs/ebpf/loading/object-lifecycle.md create mode 100644 docs/ebpf/programs/attaching.md create mode 100644 docs/ebpf/programs/testing.md create mode 100644 docs/ebpf/stylesheets/extra.css create mode 100644 docs/ebpf/use-cases.md create mode 100644 docs/examples/Makefile create mode 100644 docs/examples/docs.c create mode 100644 docs/examples/docs.h create mode 100644 docs/examples/docs_test.go create mode 100644 docs/includes/glossary.md create mode 100644 docs/mkdocs.yml create mode 100644 docs/overrides/.icons/ebee-color.svg create mode 100644 docs/overrides/.icons/ebee-mono.svg create mode 100644 docs/overrides/.icons/ebpf-go.svg create mode 100644 docs/overrides/partials/source-file.html create mode 100644 docs/vars.yml create mode 100644 netlify.toml diff --git a/.gitignore b/.gitignore index b46162b8e..6ce7ad745 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,10 @@ # Output of the go coverage tool, specifically when used with LiteIDE *.out + +# Python +__pycache__ + +# Documentation +docs/build +docs/site diff --git a/docs/Pipfile b/docs/Pipfile new file mode 100644 index 000000000..1f30492c1 --- /dev/null +++ b/docs/Pipfile @@ -0,0 +1,18 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +mkdocs = "*" +pymdown-extensions = "*" +mkdocs-material = "*" +mkdocs-macros-plugin = "*" +mkdocs-git-revision-date-localized-plugin = "*" +mkdocs-git-authors-plugin = "*" + +[dev-packages] + +# Whatever Netlify's Ubuntu version uses. +[requires] +python_version = "3.8" diff --git a/docs/Pipfile.lock b/docs/Pipfile.lock new file mode 100644 index 000000000..9e8223694 --- /dev/null +++ b/docs/Pipfile.lock @@ -0,0 +1,541 @@ +{ + "_meta": { + "hash": { + "sha256": "7fdc85c0382ce4d85cc6b25bb2aec19714c29f6c688841be8bf66245550e5749" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.8" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "babel": { + "hashes": [ + "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610", + "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455" + ], + "markers": "python_version >= '3.7'", + "version": "==2.12.1" + }, + "certifi": { + "hashes": [ + "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3", + "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18" + ], + "markers": "python_version >= '3.6'", + "version": "==2022.12.7" + }, + "charset-normalizer": { + "hashes": [ + "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6", + "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1", + "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e", + "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373", + "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62", + "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230", + "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be", + "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c", + "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0", + "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448", + "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f", + "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649", + "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d", + "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0", + "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706", + "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a", + "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59", + "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23", + "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5", + "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb", + "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e", + "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e", + "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c", + "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28", + "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d", + "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41", + "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974", + "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce", + "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f", + "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1", + "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d", + "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8", + "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017", + "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31", + "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7", + "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8", + "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e", + "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14", + "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd", + "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d", + "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795", + "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b", + "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b", + "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b", + "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203", + "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f", + "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19", + "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1", + "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a", + "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac", + "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9", + "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0", + "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137", + "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f", + "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6", + "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5", + "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909", + "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f", + "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0", + "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324", + "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755", + "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb", + "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854", + "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c", + "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60", + "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84", + "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0", + "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b", + "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1", + "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531", + "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1", + "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11", + "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326", + "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df", + "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab" + ], + "markers": "python_full_version >= '3.7.0'", + "version": "==3.1.0" + }, + "click": { + "hashes": [ + "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e", + "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48" + ], + "markers": "python_version >= '3.7'", + "version": "==8.1.3" + }, + "colorama": { + "hashes": [ + "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", + "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", + "version": "==0.4.6" + }, + "ghp-import": { + "hashes": [ + "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619", + "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343" + ], + "version": "==2.1.0" + }, + "gitdb": { + "hashes": [ + "sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a", + "sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7" + ], + "markers": "python_version >= '3.7'", + "version": "==4.0.10" + }, + "gitpython": { + "hashes": [ + "sha256:8ce3bcf69adfdf7c7d503e78fd3b1c492af782d58893b650adb2ac8912ddd573", + "sha256:f04893614f6aa713a60cbbe1e6a97403ef633103cdd0ef5eb6efe0deb98dbe8d" + ], + "markers": "python_version >= '3.7'", + "version": "==3.1.31" + }, + "idna": { + "hashes": [ + "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", + "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" + ], + "markers": "python_version >= '3.5'", + "version": "==3.4" + }, + "importlib-metadata": { + "hashes": [ + "sha256:03ba783c3a2c69d751b109fc0c94a62c51f581b3d6acf8ed1331b6d5729321ff", + "sha256:7a8bdf1bc3a726297f5cfbc999e6e7ff6b4fa41b26bba4afc580448624460045" + ], + "markers": "python_version < '3.10'", + "version": "==6.5.0" + }, + "jinja2": { + "hashes": [ + "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852", + "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61" + ], + "markers": "python_version >= '3.7'", + "version": "==3.1.2" + }, + "markdown": { + "hashes": [ + "sha256:cbb516f16218e643d8e0a95b309f77eb118cb138d39a4f27851e6a63581db874", + "sha256:f5da449a6e1c989a4cea2631aa8ee67caa5a2ef855d551c88f9e309f4634c621" + ], + "markers": "python_version >= '3.6'", + "version": "==3.3.7" + }, + "markupsafe": { + "hashes": [ + "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed", + "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc", + "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2", + "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460", + "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7", + "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0", + "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1", + "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa", + "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03", + "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323", + "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65", + "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013", + "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036", + "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f", + "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4", + "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419", + "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2", + "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619", + "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a", + "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a", + "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd", + "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7", + "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666", + "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65", + "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859", + "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625", + "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff", + "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156", + "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd", + "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba", + "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f", + "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1", + "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094", + "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a", + "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513", + "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed", + "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d", + "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3", + "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147", + "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c", + "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603", + "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601", + "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a", + "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1", + "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d", + "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3", + "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54", + "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2", + "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6", + "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58" + ], + "markers": "python_version >= '3.7'", + "version": "==2.1.2" + }, + "mergedeep": { + "hashes": [ + "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8", + "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307" + ], + "markers": "python_version >= '3.6'", + "version": "==1.3.4" + }, + "mkdocs": { + "hashes": [ + "sha256:8947af423a6d0facf41ea1195b8e1e8c85ad94ac95ae307fe11232e0424b11c5", + "sha256:c8856a832c1e56702577023cd64cc5f84948280c1c0fcc6af4cd39006ea6aa8c" + ], + "index": "pypi", + "version": "==1.4.2" + }, + "mkdocs-git-authors-plugin": { + "hashes": [ + "sha256:087b63090ebbf6b93f20d8b8e5fbac8e8b140e2107e432ca2ac8dd1d3a1000f5", + "sha256:cc469208f98e9db08561eac08a9d8ccd0209a60ee5bd0e3e94b6840a5abc54b6" + ], + "index": "pypi", + "version": "==0.7.0" + }, + "mkdocs-git-revision-date-localized-plugin": { + "hashes": [ + "sha256:540b9c930d8d48630c090b72ac2c3900ac2ed0799b23738a33b88e31f5198fe7", + "sha256:7752edd7c4dcaa9383e9a5b6a4f729831a62d604b0c43b319331127720c6a2bf" + ], + "index": "pypi", + "version": "==1.2.0" + }, + "mkdocs-macros-plugin": { + "hashes": [ + "sha256:96bdabeb98b96139544f0048ea2f5cb80c7befde6b21e94c6d4596c22774cbcf", + "sha256:9e64e1cabcf6925359de29fe54f62d5847fb455c2528c440b87f8f1240650608" + ], + "index": "pypi", + "version": "==0.7.0" + }, + "mkdocs-material": { + "hashes": [ + "sha256:2e555152f9771646bfa62dc78a86052876183eff69ce30db03a33e85702b21fc", + "sha256:f2eb1d40db89da9922944833c1387207408f8937e1c2b46ab86e0c8f170b71e0" + ], + "index": "pypi", + "version": "==9.1.6" + }, + "mkdocs-material-extensions": { + "hashes": [ + "sha256:9c003da71e2cc2493d910237448c672e00cefc800d3d6ae93d2fc69979e3bd93", + "sha256:e41d9f38e4798b6617ad98ca8f7f1157b1e4385ac1459ca1e4ea219b556df945" + ], + "markers": "python_version >= '3.7'", + "version": "==1.1.1" + }, + "packaging": { + "hashes": [ + "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61", + "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f" + ], + "markers": "python_version >= '3.7'", + "version": "==23.1" + }, + "pygments": { + "hashes": [ + "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c", + "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1" + ], + "markers": "python_version >= '3.7'", + "version": "==2.15.1" + }, + "pymdown-extensions": { + "hashes": [ + "sha256:a499191d8d869f30339de86fcf072a787e86c42b6f16f280f5c2cf174182b7f3", + "sha256:f7e86c1d3981f23d9dc43294488ecb54abadd05b0be4bf8f0e15efc90f7853ff" + ], + "index": "pypi", + "version": "==9.11" + }, + "python-dateutil": { + "hashes": [ + "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", + "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.8.2" + }, + "pytz": { + "hashes": [ + "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588", + "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb" + ], + "version": "==2023.3" + }, + "pyyaml": { + "hashes": [ + "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf", + "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293", + "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b", + "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57", + "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b", + "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4", + "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07", + "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba", + "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9", + "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287", + "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513", + "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0", + "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782", + "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0", + "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92", + "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f", + "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2", + "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc", + "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1", + "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c", + "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86", + "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4", + "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c", + "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34", + "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b", + "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d", + "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c", + "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb", + "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7", + "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737", + "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3", + "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d", + "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358", + "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53", + "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78", + "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803", + "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a", + "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f", + "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174", + "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5" + ], + "markers": "python_version >= '3.6'", + "version": "==6.0" + }, + "pyyaml-env-tag": { + "hashes": [ + "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb", + "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069" + ], + "markers": "python_version >= '3.6'", + "version": "==0.1" + }, + "regex": { + "hashes": [ + "sha256:086afe222d58b88b62847bdbd92079b4699350b4acab892f88a935db5707c790", + "sha256:0b8eb1e3bca6b48dc721818a60ae83b8264d4089a4a41d62be6d05316ec38e15", + "sha256:11d00c31aeab9a6e0503bc77e73ed9f4527b3984279d997eb145d7c7be6268fd", + "sha256:11d1f2b7a0696dc0310de0efb51b1f4d813ad4401fe368e83c0c62f344429f98", + "sha256:1b1fc2632c01f42e06173d8dd9bb2e74ab9b0afa1d698058c867288d2c7a31f3", + "sha256:20abe0bdf03630fe92ccafc45a599bca8b3501f48d1de4f7d121153350a2f77d", + "sha256:22720024b90a6ba673a725dcc62e10fb1111b889305d7c6b887ac7466b74bedb", + "sha256:2472428efc4127374f494e570e36b30bb5e6b37d9a754f7667f7073e43b0abdd", + "sha256:25f0532fd0c53e96bad84664171969de9673b4131f2297f1db850d3918d58858", + "sha256:2848bf76673c83314068241c8d5b7fa9ad9bed866c979875a0e84039349e8fa7", + "sha256:37ae17d3be44c0b3f782c28ae9edd8b47c1f1776d4cabe87edc0b98e1f12b021", + "sha256:3cd9f5dd7b821f141d3a6ca0d5d9359b9221e4f051ca3139320adea9f1679691", + "sha256:4479f9e2abc03362df4045b1332d4a2b7885b245a30d4f4b051c4083b97d95d8", + "sha256:4c49552dc938e3588f63f8a78c86f3c9c75301e813bca0bef13bdb4b87ccf364", + "sha256:539dd010dc35af935b32f248099e38447bbffc10b59c2b542bceead2bed5c325", + "sha256:54c3fa855a3f7438149de3211738dd9b5f0c733f48b54ae05aa7fce83d48d858", + "sha256:55ae114da21b7a790b90255ea52d2aa3a0d121a646deb2d3c6a3194e722fc762", + "sha256:5ccfafd98473e007cebf7da10c1411035b7844f0f204015efd050601906dbb53", + "sha256:5fc33b27b1d800fc5b78d7f7d0f287e35079ecabe68e83d46930cf45690e1c8c", + "sha256:6560776ec19c83f3645bbc5db64a7a5816c9d8fb7ed7201c5bcd269323d88072", + "sha256:6572ff287176c0fb96568adb292674b421fa762153ed074d94b1d939ed92c253", + "sha256:6b190a339090e6af25f4a5fd9e77591f6d911cc7b96ecbb2114890b061be0ac1", + "sha256:7304863f3a652dab5e68e6fb1725d05ebab36ec0390676d1736e0571ebb713ef", + "sha256:75f288c60232a5339e0ff2fa05779a5e9c74e9fc085c81e931d4a264501e745b", + "sha256:7868b8f218bf69a2a15402fde08b08712213a1f4b85a156d90473a6fb6b12b09", + "sha256:787954f541ab95d8195d97b0b8cf1dc304424adb1e07365967e656b92b38a699", + "sha256:78ac8dd8e18800bb1f97aad0d73f68916592dddf233b99d2b5cabc562088503a", + "sha256:79e29fd62fa2f597a6754b247356bda14b866131a22444d67f907d6d341e10f3", + "sha256:845a5e2d84389c4ddada1a9b95c055320070f18bb76512608374aca00d22eca8", + "sha256:86b036f401895e854de9fefe061518e78d506d8a919cc250dc3416bca03f6f9a", + "sha256:87d9951f5a538dd1d016bdc0dcae59241d15fa94860964833a54d18197fcd134", + "sha256:8a9c63cde0eaa345795c0fdeb19dc62d22e378c50b0bc67bf4667cd5b482d98b", + "sha256:93f3f1aa608380fe294aa4cb82e2afda07a7598e828d0341e124b8fd9327c715", + "sha256:9bf4a5626f2a0ea006bf81e8963f498a57a47d58907eaa58f4b3e13be68759d8", + "sha256:9d764514d19b4edcc75fd8cb1423448ef393e8b6cbd94f38cab983ab1b75855d", + "sha256:a610e0adfcb0fc84ea25f6ea685e39e74cbcd9245a72a9a7aab85ff755a5ed27", + "sha256:a81c9ec59ca2303acd1ccd7b9ac409f1e478e40e96f8f79b943be476c5fdb8bb", + "sha256:b7006105b10b59971d3b248ad75acc3651c7e4cf54d81694df5a5130a3c3f7ea", + "sha256:c07ce8e9eee878a48ebeb32ee661b49504b85e164b05bebf25420705709fdd31", + "sha256:c125a02d22c555e68f7433bac8449992fa1cead525399f14e47c2d98f2f0e467", + "sha256:c37df2a060cb476d94c047b18572ee2b37c31f831df126c0da3cd9227b39253d", + "sha256:c869260aa62cee21c5eb171a466c0572b5e809213612ef8d495268cd2e34f20d", + "sha256:c88e8c226473b5549fe9616980ea7ca09289246cfbdf469241edf4741a620004", + "sha256:cd1671e9d5ac05ce6aa86874dd8dfa048824d1dbe73060851b310c6c1a201a96", + "sha256:cde09c4fdd070772aa2596d97e942eb775a478b32459e042e1be71b739d08b77", + "sha256:cf86b4328c204c3f315074a61bc1c06f8a75a8e102359f18ce99fbcbbf1951f0", + "sha256:d5bbe0e1511b844794a3be43d6c145001626ba9a6c1db8f84bdc724e91131d9d", + "sha256:d895b4c863059a4934d3e874b90998df774644a41b349ebb330f85f11b4ef2c0", + "sha256:db034255e72d2995cf581b14bb3fc9c00bdbe6822b49fcd4eef79e1d5f232618", + "sha256:dbb3f87e15d3dd76996d604af8678316ad2d7d20faa394e92d9394dfd621fd0c", + "sha256:dc80df325b43ffea5cdea2e3eaa97a44f3dd298262b1c7fe9dbb2a9522b956a7", + "sha256:dd7200b4c27b68cf9c9646da01647141c6db09f48cc5b51bc588deaf8e98a797", + "sha256:df45fac182ebc3c494460c644e853515cc24f5ad9da05f8ffb91da891bfee879", + "sha256:e152461e9a0aedec7d37fc66ec0fa635eca984777d3d3c3e36f53bf3d3ceb16e", + "sha256:e2396e0678167f2d0c197da942b0b3fb48fee2f0b5915a0feb84d11b6686afe6", + "sha256:e76b6fc0d8e9efa39100369a9b3379ce35e20f6c75365653cf58d282ad290f6f", + "sha256:ea3c0cb56eadbf4ab2277e7a095676370b3e46dbfc74d5c383bd87b0d6317910", + "sha256:ef3f528fe1cc3d139508fe1b22523745aa77b9d6cb5b0bf277f48788ee0b993f", + "sha256:fdf7ad455f1916b8ea5cdbc482d379f6daf93f3867b4232d14699867a5a13af7", + "sha256:fffe57312a358be6ec6baeb43d253c36e5790e436b7bf5b7a38df360363e88e9" + ], + "markers": "python_version >= '3.8'", + "version": "==2023.3.23" + }, + "requests": { + "hashes": [ + "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa", + "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf" + ], + "markers": "python_version >= '3.7' and python_version < '4'", + "version": "==2.28.2" + }, + "six": { + "hashes": [ + "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", + "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.16.0" + }, + "smmap": { + "hashes": [ + "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94", + "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936" + ], + "markers": "python_version >= '3.6'", + "version": "==5.0.0" + }, + "termcolor": { + "hashes": [ + "sha256:91ddd848e7251200eac969846cbae2dacd7d71c2871e92733289e7e3666f48e7", + "sha256:dfc8ac3f350788f23b2947b3e6cfa5a53b630b612e6cd8965a015a776020b99a" + ], + "markers": "python_version >= '3.7'", + "version": "==2.2.0" + }, + "urllib3": { + "hashes": [ + "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305", + "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==1.26.15" + }, + "watchdog": { + "hashes": [ + "sha256:0e06ab8858a76e1219e68c7573dfeba9dd1c0219476c5a44d5333b01d7e1743a", + "sha256:13bbbb462ee42ec3c5723e1205be8ced776f05b100e4737518c67c8325cf6100", + "sha256:233b5817932685d39a7896b1090353fc8efc1ef99c9c054e46c8002561252fb8", + "sha256:25f70b4aa53bd743729c7475d7ec41093a580528b100e9a8c5b5efe8899592fc", + "sha256:2b57a1e730af3156d13b7fdddfc23dea6487fceca29fc75c5a868beed29177ae", + "sha256:336adfc6f5cc4e037d52db31194f7581ff744b67382eb6021c868322e32eef41", + "sha256:3aa7f6a12e831ddfe78cdd4f8996af9cf334fd6346531b16cec61c3b3c0d8da0", + "sha256:3ed7c71a9dccfe838c2f0b6314ed0d9b22e77d268c67e015450a29036a81f60f", + "sha256:4c9956d27be0bb08fc5f30d9d0179a855436e655f046d288e2bcc11adfae893c", + "sha256:4d98a320595da7a7c5a18fc48cb633c2e73cda78f93cac2ef42d42bf609a33f9", + "sha256:4f94069eb16657d2c6faada4624c39464f65c05606af50bb7902e036e3219be3", + "sha256:5113334cf8cf0ac8cd45e1f8309a603291b614191c9add34d33075727a967709", + "sha256:51f90f73b4697bac9c9a78394c3acbbd331ccd3655c11be1a15ae6fe289a8c83", + "sha256:5d9f3a10e02d7371cd929b5d8f11e87d4bad890212ed3901f9b4d68767bee759", + "sha256:7ade88d0d778b1b222adebcc0927428f883db07017618a5e684fd03b83342bd9", + "sha256:7c5f84b5194c24dd573fa6472685b2a27cc5a17fe5f7b6fd40345378ca6812e3", + "sha256:7e447d172af52ad204d19982739aa2346245cc5ba6f579d16dac4bfec226d2e7", + "sha256:8ae9cda41fa114e28faf86cb137d751a17ffd0316d1c34ccf2235e8a84365c7f", + "sha256:8f3ceecd20d71067c7fd4c9e832d4e22584318983cabc013dbf3f70ea95de346", + "sha256:9fac43a7466eb73e64a9940ac9ed6369baa39b3bf221ae23493a9ec4d0022674", + "sha256:a70a8dcde91be523c35b2bf96196edc5730edb347e374c7de7cd20c43ed95397", + "sha256:adfdeab2da79ea2f76f87eb42a3ab1966a5313e5a69a0213a3cc06ef692b0e96", + "sha256:ba07e92756c97e3aca0912b5cbc4e5ad802f4557212788e72a72a47ff376950d", + "sha256:c07253088265c363d1ddf4b3cdb808d59a0468ecd017770ed716991620b8f77a", + "sha256:c9d8c8ec7efb887333cf71e328e39cffbf771d8f8f95d308ea4125bf5f90ba64", + "sha256:d00e6be486affb5781468457b21a6cbe848c33ef43f9ea4a73b4882e5f188a44", + "sha256:d429c2430c93b7903914e4db9a966c7f2b068dd2ebdd2fa9b9ce094c7d459f33" + ], + "markers": "python_version >= '3.7'", + "version": "==3.0.0" + }, + "zipp": { + "hashes": [ + "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b", + "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556" + ], + "markers": "python_version >= '3.7'", + "version": "==3.15.0" + } + }, + "develop": {} +} diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..95403b295 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,21 @@ +# epbf-go documentation + +The project uses Pipenv to manage its dependencies, which will automatically create a Python virtualenv when invoked +from this subdirectory. Follow your distribution's documentation for installing `pipenv`. You may also need `pyenv` +to install a different Python version if your distribution doesn't provide the version specified in the `Pipfile`. + +To create a Python venv and install dependencies: + +`$ pipenv install` + +To enter the venv and use its corresponding interpreter: + +`$ pipenv shell` + +You may now run a development copy of the documentation locally: + +`$ mkdocs serve` + +.. or build all assets and output a full copy of the website ready for hosting: + +`$ mkdocs build` diff --git a/docs/ebpf.py b/docs/ebpf.py new file mode 100644 index 000000000..5012cac04 --- /dev/null +++ b/docs/ebpf.py @@ -0,0 +1,230 @@ +"""Macro definitions for documentation.""" + +# Use built-in 'list' type when upgrading to Python 3.9. + +import glob +import os +import textwrap +from io import TextIOWrapper +from typing import List +from urllib.parse import ParseResult, urlparse + +from mkdocs_macros.plugin import MacrosPlugin + + +def define_env(env: MacrosPlugin): + """ + Define the mkdocs-macros-plugin environment. + + This function is called on setup. 'env' can be interacted with + for defining variables, macros and filters. + + - variables: the dictionary that contains the environment variables + - macro: a decorator function, to declare a macro. + - filter: a function with one or more arguments, used to perform a + transformation + """ + # Values can be overridden in mkdocs.yml:extras. + go_examples_path: str = env.variables.get( + "go_examples_path", "examples/*.go" + ) + godoc_url: ParseResult = urlparse( + env.variables.get( + "godoc_url", "https://pkg.go.dev/github.com/cilium/ebpf" + ) + ) + + c_examples_path: str = env.variables.get("c_examples_path", "examples/*.c") + + @env.macro + def godoc(sym: str, short: bool = False): + """ + Generate a godoc link based on the configured godoc_url. + + `sym` is the symbol to link to. A dot '.' separator means it's a method + on another type. Forward slashes '/' can be used to navigate to symbols + in subpackages. + + For example: + - CollectionSpec.LoadAndAssign + - link/Link + - btf/Spec.TypeByID + + `short` renders only the symbol name. + """ + if len(godoc_url) == 0: + raise ValueError("Empty godoc url") + + # Support referring to symbols in subpackages. + subpkg = os.path.dirname(sym) + # Symbol name including dots for struct methods. (e.g. Map.Get) + name = os.path.basename(sym) + + # Python's urljoin() expects the base path to have a trailing slash for + # it to correctly append subdirs. Use urlparse instead, and interact + # with the URL's components individually. + url = godoc_url._replace( + path=os.path.join(godoc_url.path, subpkg), + # Anchor token appearing after the # in the URL. + fragment=name, + ).geturl() + + text = name + if short: + text = text.split(".")[-1] + + return f"[:fontawesome-brands-golang: `{text}`]({url})" + + @env.macro + def go_example(*args, **kwargs): + """ + Include the body of a Go code example. + + See docstring of code_example() for details. + """ + return code_example( + *args, **kwargs, language="go", path=go_examples_path + ) + + @env.macro + def c_example(*args, **kwargs): + """ + Include the body of a C code example. + + See docstring of `code_example` for details. + """ + return code_example( + *args, **kwargs, language="c", path=c_examples_path + ) + + +def code_example( + symbol: str, + title: str = None, + language: str = "", + lines: bool = True, + signature: bool = False, + path: str = "", +) -> str: + """ + Include the body of a code example. + + `symbol` takes the name of the function or snippet to include. + `title` is rendered as a title at the top of the snippet. + `language` is the + `lines` controls rendering line numbers. + allowing included code snippets to be used as content tabs. + `signature` controls whether or not the function signature and brackets + are included. + `path` specifies the include path that may contain globs. + """ + opts: List[str] = [] + if lines: + opts.append("linenums='1'") + if title: + opts.append(f"title='{title}'") + + if signature: + body = full_body(path, symbol) + else: + body = inner_body(path, symbol) + + out = f"``` {language} {' '. join(opts)}\n{body}```" + + return out + + +def inner_body(path: str, sym: str) -> str: + """ + Get the inner body of sym, using default delimiters. + + First and last lines (so, function signature and closing bracket) are + stripped, the remaining body dedented. + """ + out = _search_body(path, sym) + if len(out) < 2: + raise ValueError( + f"Need at least two lines to get inner body for symbol {sym}" + ) + + return textwrap.dedent("".join(out[1:-1])) + + +def full_body(path: str, sym: str) -> str: + """Get the full body of sym, using default delimiters, dedented.""" + out = _search_body(path, sym) + + return textwrap.dedent("".join(out)) + + +def _get_body( + f: TextIOWrapper, sym: str, start: str = "{", end: str = "}" +) -> List[str]: + """ + Extract a body of text between sym and start/end delimiters. + + Tailored to finding function bodies of C-family programming languages with + curly braces. + + The starting line of the body must contain sym prefixed by a space, with + d_start appearing on the same line, for example " Foo() {". Further + occurrences of "{" and its closing counterpart "}" are tracked, and the + lines between and including the final "}" are returned. + """ + found = False + stack = 0 + lines = [] + + sym = " " + sym + + for line in f.readlines(): + if not found: + # Skip current line if we're not in a body and the current line + # doesn't contain a start delimiter. + if sym not in line: + continue + + found = True + + # Count the amount of start delimiters. + stack += line.count(start) + + if stack == 0: + # No opening delimiter found, ignore the line. + found = False + continue + + lines.append(line) + + # Count the amount of end delimiters and stop if we've escaped the + # current scope. + stack -= line.count(end) + if stack <= 0: + break + + # Rewind the file for reuse. + f.seek(0) + + if stack > 0: + raise LookupError(f"No end delimiter for {sym}") + + if len(lines) == 0: + raise LookupError(f"Symbol {sym} not found") + + return lines + + +def _search_body(path: str, sym: str) -> List[str]: + """Find the body of the given symbol in a path glob.""" + files = glob.glob(path) + if len(files) == 0: + raise LookupError(f"Path {path} did not match any files") + + for file in files: + with open(file, mode="r") as f: + try: + return _get_body(f, sym) + except LookupError: + continue + + raise LookupError(f"Symbol {sym} not found in any of {files}") diff --git a/docs/ebpf/about.md b/docs/ebpf/about.md new file mode 100644 index 000000000..f9cd870b0 --- /dev/null +++ b/docs/ebpf/about.md @@ -0,0 +1,9 @@ +# About {{ proj }} + +The project was initially created in 2017 as [`newtools/ebpf`](https://github.com/newtools/ebpf) by [Nathan +Sweet](https://github.com/nathanjsweet). It quickly gained traction within the Go community for projects that couldn't +or wouldn't build upon the CGo-based BCC bindings at the time (`gobpf`). + +Since then, it's been widely adopted by hundreds of open-source projects, by large industry players, and by startups +building their businesses on top of eBPF alike. Today, it continues to evolve thanks to its thriving community and close +collaboration with the upstream Linux project. diff --git a/docs/ebpf/btf/index.md b/docs/ebpf/btf/index.md new file mode 100644 index 000000000..9d0b443a1 --- /dev/null +++ b/docs/ebpf/btf/index.md @@ -0,0 +1 @@ +Document package btf here. diff --git a/docs/ebpf/features/index.md b/docs/ebpf/features/index.md new file mode 100644 index 000000000..ef20b5c2d --- /dev/null +++ b/docs/ebpf/features/index.md @@ -0,0 +1 @@ +Document package features here. diff --git a/docs/ebpf/getting-started/further-reading.md b/docs/ebpf/getting-started/further-reading.md new file mode 100644 index 000000000..38318952b --- /dev/null +++ b/docs/ebpf/getting-started/further-reading.md @@ -0,0 +1 @@ +Include useful links to external documentation here. diff --git a/docs/ebpf/getting-started/index.md b/docs/ebpf/getting-started/index.md new file mode 100644 index 000000000..4e4379c4e --- /dev/null +++ b/docs/ebpf/getting-started/index.md @@ -0,0 +1,108 @@ +# Getting Started with eBPF in Go + +!!! info + For a high-level understanding of what eBPF is and how it works, please + see [the eBPF introduction at ebpf.io](https://ebpf.io/what-is-ebpf). + This guide assumes familiarity with the basic concepts and terminology. + + In this guide, we'll walk you through building and shipping a new, + eBPF-powered Go application from scratch. However, we'll focus heavily on the Go + side of things, building on a relatively minimal eBPF C example. + + See the [Further Reading](further-reading) section for more in-depth resources + and reference documentation for developing eBPF C programs. Please see the + [users](/use-cases) section for existing {{ proj }}-powered projects of varying sizes + and complexities. + +## Step 1 - Writing and building eBPF C + +Let's start out with a simple eBPF program. It consists of a single call to an eBPF +helper function, which redirects all packets from one interface to another based on +the index of the incoming interface. + +!!! + +```c +#include +#include + +SEC("xdp") +int xdp_xconnect(struct xdp_md *ctx) +{ + return bpf_redirect_map(&xconnect_map, ctx->ingress_ifindex, 0); +} +``` + +In order to compile the above program, we need to provide search paths for all the included header files. The easiest way to do that is to make a copy of everything under linux/tools/lib/bpf/, however, this will include a lot of unnecessary files. So an alternative is to create a list of dependencies: + +```shell +$ clang -MD -MF xconnect.d -target bpf -I ~/linux/tools/lib/bpf -c xconnect.c +``` + +Now we can make a local copy of only a small number of files specified in xconnect.d and use the following command to compile eBPF code for the local CPU architecture: + +```shell +$ clang -target bpf -Wall -O2 -emit-llvm -g -Iinclude -c xconnect.c -o - | \ +llc -march=bpf -mcpu=probe -filetype=obj -o xconnect.o +``` + +The resulting ELF file is what we’d need to provide to our Go library in the next step. + +## Step 2 - Writing the Go code + +Compiled eBPF programs and maps can be loaded by {{ proj }} with just a few instructions. By adding a struct with ebpf tags we can automate the relocation procedure so that our program knows where to find its map. + +```go +spec, err := ebpf.LoadCollectionSpec("ebpf/xconnect.o") +if err != nil { + panic(err) +} + +var objs struct { + XCProg *ebpf.Program `ebpf:"xdp_xconnect"` + XCMap *ebpf.Map `ebpf:"xconnect_map"` +} +if err := spec.LoadAndAssign(&objs, nil); err != nil { + panic(err) +} +defer objs.XCProg.Close() +defer objs.XCMap.Close() +``` + +Type ebpf.Map has a set of methods that perform standard CRUD operations on the contents of the loaded map: + +```go +err = objs.XCMap.Put(uint32(0), uint32(10)) + +var v0 uint32 +err = objs.XCMap.Lookup(uint32(0), &v0) + +err = objs.XCMap.Delete(uint32(0)) +``` + +The only step that’s not covered by {{ proj }} is the attachment of programs to network hooks. This, however, can easily be accomplished by any existing netlink library, e.g. `vishvananda/netlink`, by associating a network link with a file descriptor of the loaded program: + +```go +link, err := netlink.LinkByName("eth0") +err = netlink.LinkSetXdpFdWithFlags(*link, c.objs.XCProg.FD(), 2) +``` + +Note that I’m using the SKB_MODE XDP flag to work around the exiting veth driver caveat. Although the native XDP mode is considerably faster than any other eBPF hook, SKB_MODE may not be as fast due to the fact that packet headers have to be pre-parsed by the network stack (see video). + +## Step 3 - Code Distribution + +At this point everything should have been ready to package and ship our application if it wasn’t for one problem - eBPF code portability. Historically, this process involved copying of the eBPF source code to the target platform, pulling in the required kernel headers and compiling it for the specific kernel version. This problem is especially pronounced for tracing/monitoring/profiling use cases which may require access to pretty much any kernel data structure, so the only solution is to introduce another layer of indirection (see CO-RE). + +Network use cases, on the other hand, rely on a relatively small and stable subset of kernel types, so they don’t suffer from the same kind of problems as their tracing and profiling counterparts. Based on what I’ve seen so far, the two most common code packaging approaches are: + +- Ship eBPF code together with the required kernel headers, assuming they match the underlying kernel (see Cilium). +- Ship eBPF code and pull in the kernel headers on the target platform. + +In both of these cases, the eBPF code is still compiled on that target platform which is an extra step that needs to be performed before the user-space application can start. However, there’s an alternative, which is to pre-compile the eBPF code and only ship the ELF files. This is exactly what can be done with bpf2go, which can embed the compiled code into a Go package. It relies on go generate to produce a new file with compiled eBPF and {{ proj }} skeleton code, the only requirement being the //go:generate instruction. Once generated though, our eBPF program can be loaded with just a few lines (note the absence of any arguments): + +``` +specs, err := newXdpSpecs() +objs, err := specs.Load(nil) +``` + +The obvious benefit of this approach is that we no longer need to compile on the target machine and can ship both eBPF and userspace Go code in a single package or Go binary. This is great because it allows us to use our application not only as a binary but also import it into any 3rd party Go applications (see usage example). diff --git a/docs/ebpf/getting-started/rlimit.md b/docs/ebpf/getting-started/rlimit.md new file mode 100644 index 000000000..c154c1f8c --- /dev/null +++ b/docs/ebpf/getting-started/rlimit.md @@ -0,0 +1 @@ +Document package rlimit here. diff --git a/docs/ebpf/index.md b/docs/ebpf/index.md new file mode 100644 index 000000000..784351a50 --- /dev/null +++ b/docs/ebpf/index.md @@ -0,0 +1,8 @@ +# Welcome! + +:ebpf-go: {{ proj }} is a Go library for working with :ebee-color: eBPF. It does not depend on C, libbpf, or any other Go +libraries other than the standard library, making it an excellent choice for writing self-contained, portable tools that +run on a variety of architectures. + +This documentation provides a central resource for learning how to build eBPF applications with the user space component +written in Go, diff --git a/docs/ebpf/loading/core.md b/docs/ebpf/loading/core.md new file mode 100644 index 000000000..350d663e3 --- /dev/null +++ b/docs/ebpf/loading/core.md @@ -0,0 +1,2 @@ +# Compile-Once, Run Everywhere + diff --git a/docs/ebpf/loading/elf-sections.md b/docs/ebpf/loading/elf-sections.md new file mode 100644 index 000000000..cd9a174bd --- /dev/null +++ b/docs/ebpf/loading/elf-sections.md @@ -0,0 +1,12 @@ +What are ELF sections and how are they used by eBPF? + +## Program Section Prefixes + +!!! incomplete + How do we keep this section up-to-date? + +Document libbpf section prefixes for programs. + +## :material-head-cog: Advanced: Map Section Prefixes + +Document section classifier in LoadCollectionSpecFromReader. diff --git a/docs/ebpf/loading/index.md b/docs/ebpf/loading/index.md new file mode 100644 index 000000000..526ac2bcf --- /dev/null +++ b/docs/ebpf/loading/index.md @@ -0,0 +1,78 @@ +# Loading Objects + +{{ proj }} ships with a fully-featured eBPF object (ELF) loader that aims to be compatible with the upstream libbpf and +iproute2 (`tc`/`ip`) projects. An ELF is usually obtained by compiling a eBPF C program using the LLVM toolchain +(`clang`). + +This page describes the journey from compiled eBPF ELF to resources in the kernel. This involves parsing the ELF into +intermediary Go (Spec) types which can be freely modified and copied before handing them off. + +```mermaid +flowchart LR; + A(BPF ELF Object\n\nCompiler output) ==LoadCollectionSpec==> B("CollectionSpec\n\nMapSpecs\nProgramSpecs\nbtf.Spec"); + B ==NewCollection==> C("Collection\n\nMaps\nPrograms"); + B ==LoadAndAssign==> D("Custom struct\n\nMaps\nPrograms"); +``` + +## {{ godoc('CollectionSpec') }} + +A CollectionSpec represents eBPF objects extracted from an ELF, and can be obtained by calling {{ +godoc('LoadCollectionSpec') }}. In the examples below, we declare a map and program in eBPF C, +then load and inspect them using Go. Use the tabs to explore the Go and C counterparts below. + +=== ":simple-go: Go" + {{ go_example('DocLoadCollectionSpec', title='Parse ELF and inspect its CollectionSpec') | indent(4) }} + + !!! warning + All of a Spec's attributes can be modified freely, and those modifications will influence the resources created + in the kernel. Be aware that doing so may invalidate any assumptions made by the compiler, resulting in maps or + programs being rejected by the kernel. Proceed at your own caution. + +=== ":ebee-color: eBPF C" + {{ c_example('DocMyMapProgram', title='Declare a minimal map and a program') | indent(4) }} + + !!! tip + See the [ELF Sections](elf-sections) page to learn about the use of the `SEC()` macro in the example above. + +## {{ godoc('Collection') }} + +After parsing the ELF into a CollectionSpec, it can be loaded into the kernel in its entirety using +{{ godoc('NewCollection') }}. + +{{ go_example('DocNewCollection') }} + +!!! info + {{ godoc('Collection.Close') }} closes all Maps and Programs in the Collection. Interacting with any resources + after `Close()` will return an error, since their underlying file descriptors will be closed. See + [Object Lifecycle](object-lifecycle) to gain a better understanding of how {{ proj }} manages its resources + and how to best handle Maps and Programs throughout the lifecycle of your application. + +## {{ godoc('CollectionSpec.LoadAndAssign', short=True) }} + +LoadAndAssign is a convenience API that can be used instead of `NewCollection`. It has two major benefits: + +- It automates away any validation logic around pulling Maps and Programs out of a Collection. No more + `#!go if m := coll.Maps["my_map"]; m == nil { return ... }`. +- **Selective loading of Maps and Programs!** Only resources of interest (and their dependencies) are loaded into the + kernel. A powerful tool for working with large CollectionSpecs that only need to be partially loaded. + +{{ go_example('DocLoadAndAssign', title='Pass a custom struct to LoadAndAssign') }} + +As can be seen from the example above, this comes with a few limitations: + +- You're responsible for calling `#!go Close()` on any resources assigned to your custom struct. (Implement your own + `#!go Close()` method!) +- Slightly less runtime flexibility. Map and Program names are baked into the custom struct at compile time, so renaming + keys in e.g. CollectionSpec.Maps will not work. This is a niche use case, however. + +## Type Information (BTF) + +If an eBPF ELF was built with `clang -g`, it will automatically contain BTF type information. This information +can be accessed programmatically through {{ godoc('CollectionSpec.Types') }}. Note that this field will be `nil` if the +ELF was built without BTF. + +{{ go_example('DocBTFTypeByName') }} + +!!! tip + Many modern eBPF features rely on eBPF ELFs to be built with BTF information, and there is little to be gained by + opting out of it. Most sections in this documentation will assume objects are built with `clang -g`. diff --git a/docs/ebpf/loading/object-lifecycle.md b/docs/ebpf/loading/object-lifecycle.md new file mode 100644 index 000000000..e42610bb9 --- /dev/null +++ b/docs/ebpf/loading/object-lifecycle.md @@ -0,0 +1,95 @@ +!!! info + This is an advanced topic and does not need to be fully understood in order to get started writing useful tools. + + If you find yourself debugging missing or detached programs, or you want to gain a deeper understanding of how + eBPF objects are managed by {{ proj }}, this document should provide some insights. + +## File Descriptors and Go + +Interacting with eBPF objects from user space is done using file descriptors. Counter-intuitively, 'file' descriptors +are used as references to many types of kernel resources in modern Linux, not just files. + +In {{ proj }}, file descriptors are modeled using the internal abstraction {{ godoc('internal/sys/FD') }}. +FD is embedded in all Go objects that represent live eBPF resources in the kernel, and allows managing the lifecycle +of the underlying file descriptor along with the lifecycle of a Go type that embeds it (e.g. a Map). + +!!! internal inline end "FD's Runtime Finalizer" + An `FD` is configured with a runtime finalizer calling `FD.Close()` when it is garbage collected. + +Go, being a garbage-collected language, automatically manages the lifecycle of Go objects. Keeping in line with the +standard library's `os.File` and friends, `FD` was designed in a way so its underlying file descriptor is closed when an +`FD` is garbage collected. This generally prevents runaway resource leaks, but is not without its drawbacks. + +This has a few subtle but significant repercussions for BPF, since this means the Go runtime can call `Close()` on +a Map's `FD` if the Map is no longer reachable by the garbage collector, e.g. if it was created by a function, but +not returned by it. One type of map, {{ godoc('ProgramArray') }}, is particularly sensitive to this; more about that in +a dedicated section below. + +## Reference Counting + +Within the **kernel**, lifetimes of eBPF objects are managed using [Reference +Counting](https://en.wikipedia.org/wiki/Reference_counting). When an object's reference count reaches 0, it is destroyed +and no longer usable. + +An object's refcount is set to 1 when it is first created and a file descriptor is issued to the calling user space +application. + +To increase an object's refcount: + +- [Attach/link it to a hook](/links) +- [Pin it to bpffs](#pinning-bpffs) +- Duplicate one of its file descriptors + +To decrease an object's refcount + +- Detach/unlink it from a hook +- Unpin it from bpffs +- Close a file descriptor + +If an object has no open file descriptors (all closed, or its creating user space application terminated), no existing +bpffs pins, and no links/attachments to any kernel hooks, the object's refcount will drop to 0. Its destructor will +be run and any associated memory will be freed. + +## Pinning (bpffs) + +One method of bumping an eBPF object's refcount is called 'pinning'. This is done through the BPF File System (or bpffs +for short), a virtual file system provided by the kernel. It allows a user space process to associate an eBPF object +with a file, similar to organizing files and directories in an ordinary file system. This way, when the user space +process exits, the bpffs pin will maintain the object's refcount, preventing it from being automatically destroyed. + +Another common use case for pinning is sharing eBPF objects between processes. For example, one could create a Map +using {{ proj }}, inspect it using `bpftool`, or interact with the map from another process or tool using {{ proj }}. + +Objects that benefit most from pinning are Maps ({{ godoc('Map.Pin') }}) and Links ({{ godoc('link/Link.Pin') }}, +more on that in the [Links](/links) section). + +To unpin an object, call e.g. {{ godoc('Map.Unpin') }} or simply remove the file from bpffs if there are no open Go +objects. + +## :warning: Program Arrays + +A {{ godoc('ProgramArray') }} is a Map type that holds references to other Programs. Before bpf2bpf calls became +possible, it was the only way of splitting up an eBPF program into separate parts/functions. + +They have a special property: they allow cyclic dependencies to be created between the Program Array and a Program (e.g. +allowing Programs to call into themselves). + +To simplify the Map's refcounting implementation in the kernel, and to avoid ending up with a set of Programs that +cannot be freed, two rules were added: + +- **Program Arrays require at least one open file descriptor or bpffs pin**. +- If no user space or bpffs references exist, **all the Map's entries are removed**. + +!!! warning + If all user space/bpffs references are gone, a Program may still retain a reference to a Program Array, but any tail + calls into the array with fail. This property, combined with {{ proj }}'s interactions with the garbage collector + described in [File Descriptors and Go](#file-descriptors-and-go), has led to a few surprises over the years. + +A few tips to handle this problem correctly: + +- Use {{ godoc('CollectionSpec.LoadAndAssign') }}. It will refuse to load the CollectionSpec if doing so would result + in a Program Array without a userspace reference. +- Always pin Program Arrays if execution of your eBPF code needs to continue if/when the user space application exits, + e.g. for upgrades or because you're building a short-lived tool. +- Make sure to retain references to the Map at all times in long-running applications. Note that `defer m.Close()` + also acts as an implicit reference, at least until the enclosing function returns. diff --git a/docs/ebpf/programs/attaching.md b/docs/ebpf/programs/attaching.md new file mode 100644 index 000000000..9ee7fb359 --- /dev/null +++ b/docs/ebpf/programs/attaching.md @@ -0,0 +1 @@ +Document package link here. diff --git a/docs/ebpf/programs/testing.md b/docs/ebpf/programs/testing.md new file mode 100644 index 000000000..fe874b6b4 --- /dev/null +++ b/docs/ebpf/programs/testing.md @@ -0,0 +1,3 @@ +# Performing eBPF Program Test Runs + +Explain BPF_PROG_TEST_RUN and the Go API here. diff --git a/docs/ebpf/stylesheets/extra.css b/docs/ebpf/stylesheets/extra.css new file mode 100644 index 000000000..a22b1657d --- /dev/null +++ b/docs/ebpf/stylesheets/extra.css @@ -0,0 +1,47 @@ +/* :fontawesome-solid-microchip: + Custom 'internal' admonition for highlighting extra/behind-the-scenes behaviour. +*/ +:root { + --md-admonition-icon--internal: url('data:image/svg+xml;charset=utf-8,') +} + +.md-typeset .admonition.internal, +.md-typeset details.internal { + border-color: rgb(140, 100, 200); +} + +.md-typeset .internal>.admonition-title, +.md-typeset .internal>summary { + background-color: rgba(140, 100, 200, 0.1); +} + +.md-typeset .internal>.admonition-title::before, +.md-typeset .internal>summary::before { + background-color: rgb(140, 100, 200); + -webkit-mask-image: var(--md-admonition-icon--internal); + mask-image: var(--md-admonition-icon--internal); +} + +/* :progress-wrench: + Custom admonition for sections that need work or maintenance. +*/ +:root { + --md-admonition-icon--incomplete: url('data:image/svg+xml;charset=utf-8,') +} + +.md-typeset .admonition.incomplete, +.md-typeset details.incomplete { + border-color: rgb(255, 204, 77); +} + +.md-typeset .incomplete>.admonition-title, +.md-typeset .incomplete>summary { + background-color: rgba(255, 204, 77, 0.1); +} + +.md-typeset .incomplete>.admonition-title::before, +.md-typeset .incomplete>summary::before { + background-color: rgb(255, 204, 77); + -webkit-mask-image: var(--md-admonition-icon--incomplete); + mask-image: var(--md-admonition-icon--incomplete); +} diff --git a/docs/ebpf/use-cases.md b/docs/ebpf/use-cases.md new file mode 100644 index 000000000..5a15dc089 --- /dev/null +++ b/docs/ebpf/use-cases.md @@ -0,0 +1,5 @@ +# Projects built with {{ proj }} + +- [conntracct](https://github.com/ti-mo/conntracct) +- [pwru](https://github.com/cilium/pwru) +- [xdp-xconnect](https://github.com/networkop/xdp-xconnect) diff --git a/docs/examples/Makefile b/docs/examples/Makefile new file mode 100644 index 000000000..dddcb0ea4 --- /dev/null +++ b/docs/examples/Makefile @@ -0,0 +1,4 @@ +examples: + clang -g -O2 -target bpf -Wall -Werror -c docs.c -o bpf_prog.o + go test . -run=xxx >/dev/null + diff --git a/docs/examples/docs.c b/docs/examples/docs.c new file mode 100644 index 000000000..b7b948a8f --- /dev/null +++ b/docs/examples/docs.c @@ -0,0 +1,20 @@ +//go:build ignore + +// DocMyMapProgram { +#include "docs.h" +#include + +// Declare a hash map called 'my_map' with a u32 key and a u64 value. +// The __uint and __type macros are from libbpf. +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, __u32); + __type(value, __u64); + __uint(max_entries, 1); +} my_map SEC(".maps"); + +// Declare a dummy socket program called 'my_prog'. +SEC("socket") int my_prog() { + return 0; +} +// } diff --git a/docs/examples/docs.h b/docs/examples/docs.h new file mode 100644 index 000000000..3bd1917b7 --- /dev/null +++ b/docs/examples/docs.h @@ -0,0 +1,7 @@ +#pragma once + +// These are macros from libbpf and are not shipped by all distributions. +#define SEC(NAME) __attribute__((section(NAME), used)) +#define __uint(name, val) int(*name)[val] +#define __type(name, val) typeof(val) *name +#define __array(name, val) typeof(val) *name[] diff --git a/docs/examples/docs_test.go b/docs/examples/docs_test.go new file mode 100644 index 000000000..9262dc536 --- /dev/null +++ b/docs/examples/docs_test.go @@ -0,0 +1,99 @@ +package examples + +import ( + "fmt" + + "github.com/cilium/ebpf" +) + +func DocLoadCollectionSpec() { + // Parse an ELF into a CollectionSpec. + // bpf_prog.o is the result of compiling BPF C code. + spec, err := ebpf.LoadCollectionSpec("bpf_prog.o") + if err != nil { + panic(err) + } + + // Look up the MapSpec and ProgramSpec in the CollectionSpec. + m := spec.Maps["my_map"] + p := spec.Programs["my_prog"] + // Note: We've omitted nil checks for brevity, take a look at + // LoadAndAssign for an automated way of checking for maps/programs. + + // Inspect the map and program type. + fmt.Println(m.Type, p.Type) + + // Print the map's key and value BTF types. + fmt.Println(m.Key, m.Value) + + // Print the program's instructions in a human-readable form, + // similar to llvm-objdump -S. + fmt.Println(p.Instructions) +} + +func DocNewCollection() { + spec, err := ebpf.LoadCollectionSpec("bpf_prog.o") + if err != nil { + panic(err) + } + + // Instantiate a Collection from a CollectionSpec. + coll, err := ebpf.NewCollection(spec) + if err != nil { + panic(err) + } + // Close the Collection before the enclosing function returns. + defer coll.Close() + + // Obtain a reference to 'my_map'. + m := coll.Maps["my_map"] + + // Set map key '1' to value '2'. + if err := m.Put(uint32(1), uint64(2)); err != nil { + panic(err) + } +} + +func DocLoadAndAssign() { + spec, err := ebpf.LoadCollectionSpec("bpf_prog.o") + if err != nil { + panic(err) + } + + // Anonymous struct that will receive pointers to a Map and a + // Program that were loaded into the kernel. This can be declared + // as a named type as well, with methods like Close(). + var obj struct { + MyMap *ebpf.Map `ebpf:"my_map"` + MyProg *ebpf.Program `ebpf:"my_prog"` + } + + // Insert only the resources specified in 'obj' into the kernel and + // assign them to their respective fields. If any declared resources + // are not found in the ELF, this will fail. Any errors encountered + // while loading Maps or Programs will be returned here. + if err := spec.LoadAndAssign(&obj, nil); err != nil { + panic(err) + } + defer obj.MyMap.Close() + defer obj.MyProg.Close() + + // Set map key '1' to value '2'. + if err := obj.MyMap.Put(uint32(1), uint64(2)); err != nil { + panic(err) + } +} + +func DocBTFTypeByName() { + spec, err := ebpf.LoadCollectionSpec("bpf_prog.o") + if err != nil { + panic(err) + } + + // Look up the __64 type declared in linux/bpf.h. + t, err := spec.Types.AnyTypeByName("__u64") + if err != nil { + panic(err) + } + fmt.Println(t) +} diff --git a/docs/includes/glossary.md b/docs/includes/glossary.md new file mode 100644 index 000000000..ea68af3e6 --- /dev/null +++ b/docs/includes/glossary.md @@ -0,0 +1,10 @@ + +*[Program]: Instructions that can be loaded and attached to one or more hooks in the Linux kernel. +*[Map]: Shared piece of memory between userspace and an eBPF program loaded into the kernel. +*[Link]: Connection between a Program and a hook/event in the kernel. +*[BTF]: BPF Type Format; a description of all data types present in the Linux kernel an eBPF object. +*[ELF]: Executable and Linkable Format, a container format used for compiled eBPF programs. +*[Spec]: Unrealized blueprint of an eBPF resource, e.g. MapSpec, ProgramSpec, btf.Spec. +*[CollectionSpec]: Bundle of ProgramSpecs, MapSpecs and a btf.Spec. Direct result of loading an eBPF ELF. +*[Collection]: Bundle of Maps and Programs that were loaded into the kernel. Direct result of instantiating (loading into the kernel) a CollectionSpec. +*[bpffs]: Birtual filesystem for 'pinning' references to eBPF resources in an familiar file hierarchy. Usually mounted at /sys/fs/bpf, but many individual instances can be mounted. diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml new file mode 100644 index 000000000..9774b262a --- /dev/null +++ b/docs/mkdocs.yml @@ -0,0 +1,151 @@ +site_name: "ebpf-go Documentation" +site_description: Pure-Go library to read, modify and load eBPF programs and attach them to various hooks in the Linux kernel. +site_author: Cilium Community + +# Rendered in header. +repo_url: https://github.com/cilium/ebpf +repo_name: cilium/ebpf +edit_uri: edit/master/docs/ebpf/ + +# Directory to look for Markdown files within docs/. +docs_dir: ebpf + +theme: + logo: ebpf-go.png + favicon: ebpf-go.png + name: material + + icon: + # GitHub link in the header. + repo: fontawesome/brands/github-alt + # Edit button at the top of each page. + edit: material/pencil-ruler + + features: + # Display sections in the navbar. + - navigation.sections + # Anchor tracking, updates the address bar with the active anchor. + - navigation.tracking + # Use XHR instead of fully reloading the page when navigating around. + - nagivation.instant + # Clipboard button in code blocks. + - content.code.copy + # Button to edit page on GitHub. + - content.action.edit + + palette: + # Palette toggle for light mode + - media: "(prefers-color-scheme: light)" + scheme: default + toggle: + icon: material/lightbulb-off + name: Switch to dark mode + + # Palette toggle for dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/lightbulb-on + name: Switch to light mode + + # Template overrides. + custom_dir: overrides + +nav: + - 'Index': index.md + - 'Getting Started': + - 'Writing your First Program': getting-started/index.md + - 'Resource Limits': getting-started/rlimit.md + - 'Further Reading': getting-started/further-reading.md + - 'Loading': + - 'Loading Objects': loading/index.md + - 'ELF Sections': loading/elf-sections.md + - 'Compile Once - Run Everywhere': loading/core.md + - 'Object Lifecycle': loading/object-lifecycle.md + - 'Programs': + - 'Attaching': programs/attaching.md + - 'Test Running': programs/testing.md + - 'BTF': + - btf/index.md + - 'Feature Detection': + - features/index.md + - 'Use Cases': use-cases.md + - 'GoDoc Reference': https://pkg.go.dev/github.com/cilium/ebpf + - 'GitHub': + - 'Repository': https://github.com/cilium/ebpf + - 'Issue Tracker': https://github.com/cilium/ebpf/issues + - 'Discussions': https://github.com/cilium/ebpf/discussions + - 'About': about.md + +extra: + social: + - icon: fontawesome/brands/github + link: https://github.com/cilium/ebpf + +extra_css: + - stylesheets/extra.css + +watch: +- examples/ +- includes/ +- overrides/ +- ebpf.py + +plugins: + - search + - macros: + # This opens ebpf.py in docs/. + module_name: ebpf + # Make the mkdocs build fail if any errors occur. + # Otherwise, any errors would be rendered to the build output. + on_error_fail: true + include_yaml: + - vars.yml + # Updated/authors displayed in footer. + # Layout is customized in overrides/partials/source-file.html. + - git-revision-date-localized: + type: timeago + - git-authors: + show_email_address: false + authorship_threshold_percent: 10 + exclude: + - index.md + +# Enable syntax highlighting in mkdocs-material. +markdown_extensions: + # Automatic tooltips for abbreviations/glossary. + - abbr + # Setting attributes on code fences (e.g. ``` go linenums='1') + - attr_list + # Special content blocks like '!!! note' + - admonition + - footnotes + # Collapsible admonitions + - pymdownx.details + # Syntax highlighting in code blocks + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.inlinehilite + # Glossary + - pymdownx.snippets: + auto_append: + - includes/glossary.md + # Superfences enables nested and tabbed code blocks and Mermaid support + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format + # Content tabs for code snippets, checklists, etc. + - pymdownx.tabbed: + alternate_style: true + # Emoji and icons like :fontawesome-brands-golang: + - pymdownx.emoji: + emoji_index: !!python/name:materialx.emoji.twemoji + emoji_generator: !!python/name:materialx.emoji.to_svg + options: + custom_icons: + - overrides/.icons + # Table of Contents + - toc: + permalink: true diff --git a/docs/overrides/.icons/ebee-color.svg b/docs/overrides/.icons/ebee-color.svg new file mode 100644 index 000000000..5391314d2 --- /dev/null +++ b/docs/overrides/.icons/ebee-color.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/overrides/.icons/ebee-mono.svg b/docs/overrides/.icons/ebee-mono.svg new file mode 100644 index 000000000..0ce920964 --- /dev/null +++ b/docs/overrides/.icons/ebee-mono.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/overrides/.icons/ebpf-go.svg b/docs/overrides/.icons/ebpf-go.svg new file mode 100644 index 000000000..2931c2f3c --- /dev/null +++ b/docs/overrides/.icons/ebpf-go.svg @@ -0,0 +1,860 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/overrides/partials/source-file.html b/docs/overrides/partials/source-file.html new file mode 100644 index 000000000..e7b016e49 --- /dev/null +++ b/docs/overrides/partials/source-file.html @@ -0,0 +1,12 @@ +
+
+ + {% if page.meta.git_revision_date_localized %} + Last updated {{ page.meta.git_revision_date_localized }} + {% endif %} +
+ {% if git_page_authors %} + Authored by {{ git_page_authors }} + {% endif %} +
+
diff --git a/docs/vars.yml b/docs/vars.yml new file mode 100644 index 000000000..a4cbde28c --- /dev/null +++ b/docs/vars.yml @@ -0,0 +1,3 @@ +# Variables accessible in documentation using e.g. '{{ godoc_file }}'. +extra: + proj: "`ebpf-go`" diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 000000000..67c83f3b3 --- /dev/null +++ b/netlify.toml @@ -0,0 +1,4 @@ +[build] + base = "docs/" + publish = "site/" + command = "mkdocs build"