{"id":26293484,"url":"https://github.com/bra1l0r/xdp-loader","last_synced_at":"2026-04-12T16:06:05.002Z","repository":{"id":282479643,"uuid":"943770200","full_name":"BRA1L0R/xdp-loader","owner":"BRA1L0R","description":"Configurable XDP loader in Rust. Supports jump table dispatching and program pinning. ","archived":false,"fork":false,"pushed_at":"2025-03-14T22:01:59.000Z","size":26,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-14T22:28:25.785Z","etag":null,"topics":["ebpf","rust","xdp"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BRA1L0R.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-06T08:36:49.000Z","updated_at":"2025-03-14T22:02:02.000Z","dependencies_parsed_at":"2025-03-15T05:15:50.609Z","dependency_job_id":null,"html_url":"https://github.com/BRA1L0R/xdp-loader","commit_stats":null,"previous_names":["bra1l0r/xdp-loader"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/BRA1L0R/xdp-loader","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BRA1L0R%2Fxdp-loader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BRA1L0R%2Fxdp-loader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BRA1L0R%2Fxdp-loader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BRA1L0R%2Fxdp-loader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BRA1L0R","download_url":"https://codeload.github.com/BRA1L0R/xdp-loader/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BRA1L0R%2Fxdp-loader/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270585946,"owners_count":24611312,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-15T02:00:12.559Z","response_time":110,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ebpf","rust","xdp"],"created_at":"2025-03-15T02:18:44.723Z","updated_at":"2026-04-12T16:06:04.994Z","avatar_url":"https://github.com/BRA1L0R.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# xdp-loader\n[![Get binaries](https://img.shields.io/badge/Download_Binary-grey?logo=hackthebox\u0026logoColor=white)](https://github.com/BRA1L0R/xdp-loader/releases)\n[![GitHub Release](https://img.shields.io/github/v/release/BRA1L0R/xdp-loader?logo=rust)](https://github.com/BRA1L0R/xdp-loader)\n\n\n### Key concepts and features\n- Configuration file\n  - Heavily inspired by **docker compose**, the base of every loadable project is a `Config.toml`\n  - Pin location and jump tables can be configured through configuration files\n  - You can load **many programs** on many **different interfaces** at once abd share maps and jump tables between them\n- Folder structures\n  - Maps and program sections will be saved in their corresponding folder with the same name as the section\n  - Links will be saved with the following naming scheme: `{if name}_{program name}`\n- Jump tables\n  - A jump table is a `BPF_MAP_TYPE_PROG_ARRAY` that is filled with fds of neighbouring programs as\nspecified by configuration.\n  - Each program can then reference other programs by calling `bpf_tail_call` with the correct index.\n\n\n\n## Cli\n\n```sh\nUsage: xdp-loader [OPTIONS] \u003cCOMMAND\u003e\n\nCommands:\n  attach\n  detach\n  help    Print this message or the help of the given subcommand(s)\n\nOptions:\n  -p, --purge-maps       creates maps from scratch, scrapping previously pinned maps and their contents\n  -v, --verbose          verbose debug output (Info)\n      --vv               very verbose debug output (Debug)\n  -s, --silent           limit console output to only hard errors\n  -c, --config \u003cCONFIG\u003e  specifies a config file [default: ./Config.toml]\n  -h, --help             Print help\n```\n\nEach command has options of its own. Run `xdp-loader \u003cCOMMAND\u003e --help` to learn more.\n\n## Writing programs\n### Section and section names\n\nXDP programs export names under sections specified by the `SEC(...)` directive.\n\nWhat `xdp-loader` is interested in is the **name of the function** exported by\nthe compiled program, not the name of the section it is exported in.\n\n| Object | Section | Directive |\n|---|---|---|\n| Programs | xdp | `SEC(\"xdp\")` |\n| Map | .maps | `SEC(\".maps\")` |\n\n### Map pinning\n\n\u003e [!TIP]\n\u003e It is better to **NOT** pin a jump table to a folder.\n\u003e\n\u003e Pinning a jump table would create an ambiguos situation where one unloaded program could reference\n\u003e new loaded programs that have been put into the jump table instead of the original ones.\n\nThis loader uses the LIBBPF pinning convention for map pinning. To have a map pinned by the aforementioned convention you must specify the `LIBBPF_PIN_BY_MAME` flag.\n\nExample map definition:\n```c\nstruct\n{\n   __uint(type, BPF_MAP_TYPE_ARRAY);\n   __uint(max_entries, 1000);\n   __type(key, __u32);\n   __type(value, __u32);\n   __uint(pinning, LIBBPF_PIN_BY_NAME);\n} my_pinned_map SEC(\".maps\");\n```\n\n\n\n## Configuration\n\n\u003e [!CAUTION]\n\u003e Never change a configuration file's folders before detaching the\nprogram, or else the loader won't know where to unload the programs / maps from.\nThis isn't dangerous as-is, but those resources could stay leaked forever!\n\n\n\u003e [!TIP]\n\u003e Remember to specify the `attach_mode` under `[[attach]]` to ensure maximum performance of your xdp program.\n\u003e\n\u003e Possible values for `attach_mode` are:\n\u003e - `skb`: emulated mode (default)\n\u003e - `driver`: driver mode, only available with supported NIC drivers\n\u003e - `hardware`: run BPF directly on supported NIC hardware\n\n\u003cdetails open\u003e\n\u003csummary\u003eExample configuration\u003c/summary\u003e\n\n```toml\n[directories]\nbase = \"/sys/fs/bpf/my_program\"\n\n[directories.overrides]\n#\n# You can specify overrides for the folders if your existing tooling needs it\n#\n# maps = \"{base}/maps\"\n# programs = \"{base}/programs\"\n# links = \"{base}/links\"\n\n[[attach]]\nprogram = \"xdp_entry\"\nattach_mode = \"driver\"\nifaces = [\"eno1\"]\n\n# You can specify additional programs to load on different interfaces\n#\n# [[attach]]\n# program = \"xdp_entry_2\"\n# ifaces = [\"eno2\", \"eno3\"]\n\n[[tables.JUMP_TABLE]]\nprogram = \"xdp_tcp_program\"\nindex = 1\n\n[[tables.JUMP_TABLE]]\nprogram = \"xdp_udp_program\"\nindex = 2\n```\n\n\u003c/details\u003e\n\nThis config file will fill the `JUMP_TABLE` program array in the following way:\n\n| Index | Program |\n|---|----|\n| 0 | None |\n| 1 | `xdp_tcp_program` |\n| 2 | `xdp_udp_program` |\n\nOfcourse you're not required to setup a jump table if you don't need one.\n\n\u003cdetails open\u003e\n\u003csummary\u003eMinimal configuration example\u003c/summary\u003e\n  \n```toml\n[directories]\nbase = \"/sys/fs/bpf/my_program\"\n\n[[attach]]\nprogram = \"xdp_entry\"\nifaces = [\"if1, if2, if3\"]\n```\n\n\u003c/details\u003e\n\n### Example Program\n\n```c\n// imports are excluded for the sake of brevity\n\nstruct\n{\n   __uint(type, BPF_MAP_TYPE_PROG_ARRAY);\n   __uint(max_entries, 1000);\n   __type(key, __u32);\n   __type(value, __u32);\n} JUMP_TABLE SEC(\".maps\");\n\nSEC(\"xdp\")\nint xdp_entry(struct xdp_md *ctx)\n{\n    void *data_end = (void *)(long)ctx-\u003edata_end;\n    void *data = (void *)(long)ctx-\u003edata;\n    struct ethhdr *eth = data;\n    __u64 eth_off = sizeof(*eth);\n    struct iphdr *iph = data + eth_off;\n\n    // standard bound checking formalities\n    if (eth + 1 \u003e data_end)\n        return XDP_DROP;\n    if (eth-\u003eh_proto != bpf_htons(ETH_P_IP))\n        return XDP_PASS;\n\n    if (iph + 1 \u003e data_end)\n        return XDP_DROP;\n\n    if (iph-\u003eprotocol == IPPROTO_TCP)\n        bpf_tail_call(ctx, \u0026JUMP_TABLE, 1);\n    else if (iph-\u003eprotocol == IPPROTO_UDP)\n        bpf_tail_call(ctx, \u0026JUMP_TABLE, 2);\n\n   return XDP_PASS;\n}\n\nSEC(\"xdp\")\nint xdp_tcp_program(struct xdp_md *ctx) {\n    return XDP_DROP;\n}\n\nSEC(\"xdp\")\nint xdp_udp_program(struct xdp_md *ctx) {\n    return XDP_DROP;\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbra1l0r%2Fxdp-loader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbra1l0r%2Fxdp-loader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbra1l0r%2Fxdp-loader/lists"}