{"id":21678308,"url":"https://github.com/asiffer/carnx","last_synced_at":"2026-04-18T09:36:34.403Z","repository":{"id":88407241,"uuid":"269317397","full_name":"asiffer/carnx","owner":"asiffer","description":"XDP-based network statistics digger","archived":false,"fork":false,"pushed_at":"2020-06-15T20:13:54.000Z","size":117,"stargazers_count":2,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-30T07:01:42.550Z","etag":null,"topics":["bpf","ebpf","xdp","xdp-hooks"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/asiffer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2020-06-04T09:33:37.000Z","updated_at":"2023-08-10T17:12:04.000Z","dependencies_parsed_at":null,"dependency_job_id":"0df532a0-2d11-4a9b-8bfc-76170714549c","html_url":"https://github.com/asiffer/carnx","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/asiffer/carnx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asiffer%2Fcarnx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asiffer%2Fcarnx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asiffer%2Fcarnx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asiffer%2Fcarnx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/asiffer","download_url":"https://codeload.github.com/asiffer/carnx/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asiffer%2Fcarnx/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31964333,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T00:39:45.007Z","status":"online","status_checked_at":"2026-04-18T02:00:07.018Z","response_time":103,"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":["bpf","ebpf","xdp","xdp-hooks"],"created_at":"2024-11-25T14:28:03.487Z","updated_at":"2026-04-18T09:36:34.359Z","avatar_url":"https://github.com/asiffer.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Carnx\n\nXDP-based network statistics digger.\n\n## What is XDP ?\n\n**XDP** (for eXpress Data Path) is a Linux Kernel feature (`\u003e=4.8`) providing an early hook in the incoming packets queue (RX).\n\nThe hook is placed in the network interface controller (NIC) driver just after the interrupt processing, and before any memory allocation needed by the network stack itself ([Wikipedia][1]). The following diagram ([source][8]) details the position of XDP in the incoming packet data flow.\n\n![kernel](assets/kernel-diagram.svg)\n\nThe main assets of XDP are the following:\n- XDP does not require memory allocation\n- XDP hook code is run in the kernel cutting down its CPU usage\n\nDue to this design, XDP is then rather competitive with kernel-bypass methods (like [DPDK][6] or [PF_RING][7]) but easier to integrate. In comparison with userspace methods, it can process roughly 5x more packets than classical tools (like `iptables`). \nYou can have a look to the benchmarks in this [repository][5]. See the [original paper][2] and the corresponding [presentation][8] for a deeper description of XDP.\n\n\n## Architecture of carnx\n\nThe design of XDP constraints its use. In particular carnx is divided into several components to manage both the kernel hook and the incoming requests of the server.\n\n\u003cimg style=\"width:100%;\" src=\"assets/archi.svg\" alt=\"Architecture\"\u003e\n\n### Kernel hook\n\nThe program processing the incoming packets is `carnx.bpf`. Its sources are written in `C` and are then compiled to `eBPF` with `clang` (XDP hooks are run by the eBPF virtual machine).\nThis code is very critical as it runs in kernel mode, therefore it is verified by the kernel when we want to load it. There are many constraints to pass the *verifier*: limited program size, no loop, buffer bounds must be checked before accesses... \nThis program is implemented so as to update some counters from incoming packets.\n\nAs an example, if you have [built the program](#build), you can fetch the list of the counters through:\n\n```console\n# grpcurl -plaintext -emit-defaults -unix /run/carnx.sock api.Carnx/GetCounterNames\n{\n  \"counters\": [\n    \"PKT\",\n    \"IP\",\n    \"IP6\",\n    \"TCP\",\n    \"UDP\",\n    \"ICMP\",\n    \"ICMP6\",\n    \"ARP\",\n    \"ACK\",\n    \"SYN\"\n  ]\n}\n```\n\n### BPF Map\n\nThe kernel hook increments some counters but naturally we want to fetch these values to a user-space application (our server). For this purpose XDP can use all the BPF ecosystem (recall that XDP is merely a BPF program) which notably provides *maps* to share memory between the kernel and the user-space.\n\nSeveral map types exist. Carnx use currently a single map (`XDP_CARNX_MAP`) storing counter values: counters are referenced by an index `i` and their value is merely `XDP_CARNX_MAP[i]`. So, our map behaves like an array. \n\nActually, there is not a single map but one for each CPU core. Why? In a Linux system, you have not a single RX queue but one for every core. Packets are well dispatched to the cores and are then processed in parallel (see [this post][10] for a more detailed view of the linux networking stack receiving data).\n\n### User-space interface\n\nWhile the hook updates the map, the counter values are fetched from the kernel\nby the user-space library `libcarnx.so`. This library mainly uses `libbpf.so` to interact with the kernel objects. So it can read `XDP_CARNX_MAP` but it is also responsible of loading `carnx.bpf` into the kernel (and attaching the program to the desired network interface).\n\nIn addition, the library maintains a context (defined below) to track\nthe load/attach operations.\n```c\nstruct context\n{\n    struct bpf_object *obj;\n    int prog_fd;\n    int map_fd;\n    struct bpf_map *map;\n    char iface[IFACE_LENGTH];\n    unsigned int xdp_flags;\n    bool is_loaded;\n    bool is_attached;\n};\n```\n\n### Server\n\nFinally a server written in `Go` (`carnxd`) exposes a gRPC API to manage load/attach operations and provide counter values. It basically wraps around `libcarnx.so`.\nBy default `carnxd` listens to a unix socket to avoid polluting a network interface with API calls (recall that the XDP hook monitors a network interface).\n\n\n## Build\n\nCurrently you can only get carnx from sources. First you have to compile `libbpf.so` and then you can build both `libcarnx.so` and `carnxd`.\n\n```console\n$ make libbpf\n$ make\n```\n\nThen you can test carnx (as root) through\n\n```console\n# tests/unix-test.sh \n```\n\nIn particular it check the API. If there is a problem, you will see it :)\n\n\n## Install \n\nAfter the build, you can install everything with the following command. You should naturally check the `Makefile` to ensure it is not harmful :)\n```console\n# make install\n```\n\nIn details it does the following:\n- The BPF library files (`libbpf.so` and `libbpf.so.0`) are installed to `/usr/lib`\n- The carnx library (`libcarnx.so`) too\n- The carnx server (`carnxd`) is installed to `/usr/bin`\n- The `systemd` files (`carnx.socket` and `carnx.service`) are installed to `/lib/systemd/system/` \n\n\nYou can remove the installed files by calling\n```console\n# make uninstall\n```\n\n## Get started\n\nAfter installing carnx, you can start the server by defining the path to the BPF program and the network interface to monitor:\n```console\n# carnxd --interface lo --load /var/lib/carnx/carnx.bpf\n```\n\nThe program cannot be put into background (daemonize). For this purpose, you should use the `systemd` service. By default it will listen to the localhost interface `lo`. Currently you must modify it by editing `/lib/systemd/system/carnx.service`.\n\nTo test the server, you can install [grpcurl][9] and request a snapshot from the server (the current values of the counters).\n```console\n# grpcurl -plaintext -emit-defaults -unix /run/carnx.sock api.Carnx/Snapshot\n```\n\n\n## API\n\nThe gRPC API is detailed in the [api](api/) sub-directory.\n\n## What's next?\n\nMany things can be done. I don't know precisely what I tend to do:\n- Improve carnx (config file, non-root rights to the socket...)\n- Build something upon carnx\n- Package carnx\n- Improve the doc\n\n\n\n[1]: https://en.wikipedia.org/wiki/Express_Data_Path\n[2]: https://github.com/xdp-project/xdp-paper/blob/master/xdp-the-express-data-path.pdf\n[3]: http://vger.kernel.org/lpc_net2018_talks/lpc18_paper_af_xdp_perf-v2.pdf\n[4]: https://www.linuxplumbersconf.org/event/2/contributions/71/attachments/17/9/presentation-lpc2018-xdp-tutorial.pdf\n[5]: https://github.com/xdp-project/xdp-paper/tree/master/benchmarks\n[6]: https://www.dpdk.org/\n[7]: https://www.ntop.org/products/packet-capture/pf_ring/\n[8]: https://github.com/xdp-project/xdp-paper/blob/master/xdp-presentation.pdf\n[9]: https://github.com/fullstorydev/grpcurl\n[10]: https://blog.packagecloud.io/eng/2016/06/22/monitoring-tuning-linux-networking-stack-receiving-data/","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasiffer%2Fcarnx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fasiffer%2Fcarnx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasiffer%2Fcarnx/lists"}