{"id":24756833,"url":"https://github.com/robinohs/phantomlink","last_synced_at":"2026-05-02T01:31:59.659Z","repository":{"id":297859341,"uuid":"923075695","full_name":"robinohs/phantomlink","owner":"robinohs","description":"phantomlink looks like a multi-hop Internet path, but emulates a virtual end-to-end link","archived":false,"fork":false,"pushed_at":"2026-04-20T13:11:08.000Z","size":696,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-04-20T15:20:04.480Z","etag":null,"topics":["linux","network-benchmark","network-emulation","network-emulator","rust","rust-lang","virtual-interface","virtual-link"],"latest_commit_sha":null,"homepage":"https://dl.acm.org/doi/10.1145/3744200.3744758","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robinohs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE-APACHE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-01-27T15:51:12.000Z","updated_at":"2026-04-20T13:11:12.000Z","dependencies_parsed_at":"2025-06-07T23:57:43.078Z","dependency_job_id":"6c02af8d-404b-4776-bb79-add4ae3dc843","html_url":"https://github.com/robinohs/phantomlink","commit_stats":null,"previous_names":["robinohs/phantomlink"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/robinohs/phantomlink","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robinohs%2Fphantomlink","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robinohs%2Fphantomlink/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robinohs%2Fphantomlink/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robinohs%2Fphantomlink/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robinohs","download_url":"https://codeload.github.com/robinohs/phantomlink/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robinohs%2Fphantomlink/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32520156,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-02T01:12:54.858Z","status":"ssl_error","status_checked_at":"2026-05-02T01:12:54.261Z","response_time":64,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["linux","network-benchmark","network-emulation","network-emulator","rust","rust-lang","virtual-interface","virtual-link"],"created_at":"2025-01-28T14:20:53.056Z","updated_at":"2026-05-02T01:31:59.648Z","avatar_url":"https://github.com/robinohs.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./docs/images/phantomlink.png\" alt=\"phantomlink Logo\" width=\"500px\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\u003ccode\u003ephantomlink\u003c/code\u003e looks like a multi-hop Internet path but emulates a virtual end-to-end link\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://rustup.rs\"\u003e\u003cimg alt=\"MSRV\" src=\"https://img.shields.io/badge/Rust-1.88.0%2B-orange.svg\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://depend.cs.uni-saarland.de/\"\u003e\u003cimg alt=\"Dependable Systems and Software\" src=\"https://img.shields.io/badge/Dependable%20Systems%20and%20Software-8A2BE2\"\u003e\u003c/a\u003e\n    \u003ca href=\"#contributors\"\u003e\u003cimg alt=\"Contributors\" src=\"https://img.shields.io/github/all-contributors/robinohs/phantomlink?color=ee8449\u0026style=flat-square\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/robinohs/phantomlink/actions/workflows/build.yml\"\u003e\u003cimg alt=\"Build Status\" src=\"https://github.com/robinohs/phantomlink/actions/workflows/build.yml/badge.svg\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://api.reuse.software/info/github.com/robinohs/phantomlink\"\u003e\u003cimg alt=\"MSRV\" src=\"https://api.reuse.software/badge/github.com/robinohs/phantomlink\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n```phantomlink``` is a tool for studying the impact of a dynamic network environment on the performance of internet protocols and applications. Written in safe Rust, the tool makes use of Linux network namespaces and virtual Ethernet devices to simulate a realistic end-to-end link. Using simple `.csv` scenario files, it is possible to define the time-evolving virtual link parameters, including delay, data rate over time, and route changes.\nSince the tool just opens two connected vEth in different namespaces, it is possible to combine ```phantomlink``` with any application, such as the well-known tools like netcat or iperf but also your own custom application.\nWith the ability to reorder, delay, pace, and drop packets, ```phantomlink``` can be used to test network behavior under various scenarios.\n\n## 🔥 Features\n\n- **connect** two Linux network namespaces over a **dynamic virtual link**\n- specify **bottleneck data rate**, **link delay**, and **packet reordering**\n- set the virtual link behavior with a **simple input file format**\n- **support** for **all protocols** using ethernet frames ➡️ just route the traffic to ```phantomlink```\n\n## 🚀 Use ```phantomlink```\n\n\u003e [!WARNING]\n\u003e Phantomlink currently only runs on Linux or the Windows Subsystem for Linux (WSL)\n\n### Installation\n\n#### Debian/Ubuntu\n\n  1. Download the ```phantomlink``` debian package.\n  2. Install the package using (replace [version] with the downloaded version):\n  ```sh\n  sudo apt install ~/downloads/phantomlink_[version].deb \n  ```\n\n#### Cargo\n\nTo get started you have to do the following:\n\n  1. Install ```phantomlink``` from crates.io:\n```bash\ncargo install phantomlink\n```\n\n#### Other Distros\n\nTo get started you have to do the following:\n\n  1. Download the ```phantomlink``` binary.\n  2. Make the binary executable using:\n  ```bash\n  chmod +x phantomlink_[version]\n  ```\n  3. Move the binary to `/bin`.\n\n#### Build from source\n\nIt is also possible to build the `phantomlink` binary from source.\n\n##### Prerequisites\n- Git installed on your system.\n- Rust and Cargo installed (for building the binary).\n\n##### Option 1: Manual Build\n1. Clone the `phantomlink` repository from GitHub:\n```bash\ngit clone https://github.com/robinohs/phantomlink\n```\n2. Navigate to the cloned repository and build the binary using Cargo:\n```bash\ncargo build --release\n```\n3. Move the binary to a directory that is in your system's PATH:\n```bash\nsudo mv target/release/phantomlink /bin/\n```\n\n##### Option 2: Use the Install Script\n1. Clone the ```phantomlink``` repository from GitHub:\n```bash\ngit clone https://github.com/robinohs/phantomlink\n```\n2. Navigate to the repository and execute the provided `install.sh` script:\n```bash\ncd phantomlink\n./install.sh\n```\n\n### Notes\nVerify ```phantomlink``` is correctly installed by running:\n```bash\nphantomlink --version\n```\n\n### Shell completions\n\n```phantomlink``` provides shell completion support for multiple shells, including **bash**, **elvish**, **fish**, **PowerShell**, **zsh**, and **nushell**. It automatically detects your default shell from the environment, so you don’t need to specify it unless you want to.\nTo generate completions for a specific shell, use the command below. ```phantomlink``` will output the auto-completion code to stdout, allowing you to pipe it into the auto-completion file appropriate for your shell.\n\n```bash\nphantomlink generate \u003cshell\u003e\n```\n\n### Quick-start\n\n  1. Download the [input.csv](examples/input.csv) file from examples.\n  2. Setup the network environment:\n  ```bash\n  phantomlink setup\n  ```\n  3. Start the main virtual link (assuming the input file is in ~/Downloads):\n  ```bash\n  phantomlink start ~/Downloads/input.csv\n  ```\n  4. Start an application in the server network namespace:\n  ```bash\n  phantomlink exec server iperf3 -s --port 5000\n  ```\n  5. Start an application in the client network namespace:\n  ```bash\n  phantomlink exec client iperf3 -c 192.168.66.2 --port 5000\n  ```\n  6. To get informations about the client or server network namespace you can use:\n  ```bash\n  phantomlink exec \u003cclient/server\u003e ifconfig\n  ```\n  7. After the experiment has finished, you can teardown the network environment:\n  ```bash\n  phantomlink teardown\n  ```\n\n## 🔍 Structure of ```phantomlink```\n\n### Input Format\n\n```phantomlink``` runs on scenario files—simple `.csv` files that contain the (time-evolving) parameters of the virtual end-to-end link. This format is motivated by the actual physical variability that an end-to-end connection can be exposed to.\nScenario files define the behavior of the virtual link over time, with parameters such as delay and data rate evolving throughout the experiment.\nThe `RouteID` column indicates whether there is an actual route change or only updated parameters for the current route.\n```phantomlink``` is agnostic of how the scenario file was created and whether the values are realistic. Users can create hand-crafted, synthetic scenarios or use output from any (orbital) dynamics simulator to perform systematic.\nParameters are updated at specified times, creating a step function of changes. For example given the following table:\n\n| Time [ms] | RouteID | Delay [ms] | Btldr [Mbps] |\n| --------- | ------- | ---------- | ------------ |\n| 0         | 0       | 41.0       | 80.0         |\n| 11 000    | 0       | 41.2       | 80.2         |\n| 23 000    | 1       | 37.0       | 100.0        |\n| 40 000    | 1       | 36.7       | 101.5        |\n| 60 000    | 1       | 37.0       | 100.1        |\n\n- From `t = 0 ms`, a route with a one-way delay of `41.0 ms` and a data rate of `80.0 Mbit/s` is used.\n- At `t = 11 s`, values are updated to `41.2 ms` and `80.2 Mbit/s`.\n- At `t = 23 s`, the route changes, as indicated by a new `RouteID`.\n\n### Architecture\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./docs/images/overview.png\" alt=\"Tool overview\" width=\"1000px\"\u003e\n\u003c/p\u003e\n\nAt its core, the ```phantomlink``` toolchain has a binary that operates in conjunction with Linux network namespaces and virtual Ethernet devices.\nThe toolchain architecture consists of three network namespaces created with `netns`:\n- Client Application Namespace\n- PhantomLink Binary Namespace\n- Server Application Namespace\n\nThe client and server namespaces are interconnected with the PhantomLink namespace using two virtual Ethernet devices, resulting in four virtual interfaces. For each virtual Ethernet device:\n- One side is moved to the PhantomLink namespace (`sim-veth`)\n- The other side is moved to the client or server namespace (`veth`)\n\nAfter moving the interfaces, MAC and IP addresses are assigned. For each namespace except for the PhantomLink namespace:\n- A loopback device is added\n- `veth` is configured as the default route to enable traffic flow towards ```phantomlink```\n\nTo allow traffic to flow from the client to the server namespace and vice-versa, the ```phantomlink``` binary forwards packets between the two (`sim-veth`) interfaces. This enables applications in the client or server namespace to send and receive traffic over the emulated virtual end-to-end link that evolves according to the scenario file.\n\n### Core Binary\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./docs/images/binary.png\" alt=\"Binary structure\" width=\"1000px\"\u003e\n\u003c/p\u003e\n\nThe ```phantomlink``` binary is implemented in safe Rust to benefit from Rust’s performance and memory safety. The internal binary structure is depicted in the picture above.\n\n1. **Namespace and Raw Sockets**:\n   - ```phantomlink``` is started in the PhantomLink namespace.\n   - It binds a raw sockets to the interfaces `sim-veth1` and `sim-veth2` each.\n\n2. **libpnet crate**:\n   - Using the Rust crate `libpnet`, ```phantomlink``` creates a `pnet::datalink::Channel` for each interface.\n   - This allows ```phantomlink``` to send and receive at the data link layer.\n\n3. **OnewayVirtualLink**:\n   - All incoming traffic from the client is processed by a `OnewayVirtualLink` and forwarded to the server.\n   - Similarly, a second `OnewayVirtualLink` instance handles all traffic from the server to the client.\n\nThe functionality and role of each individual component is explained in the paper.\n\n## � FAQ\n\n### I need help\n\nDon't hesitate to file an issue or contact one of the authors!\n\n### How can I help?\n\nPlease have a look at the issues or open one if you feel that something is needed.\n\nAny contributions are very welcome!\n\n## 🏛 License\n\n`Phantomlink` is dual-licensed under [Apache License, Version 2.0](https://github.com/robinohs/phantomlink/blob/main/LICENSE-APACHE) or [MIT License](https://github.com/robinohs/phantomlink/blob/main/LICENSE-MIT).\n\n## 🙏 Acknowledgement\n\nThis project has received funding from the European Union’s Horizon 2020 research and innovation programme under the Marie Skłodowska-Curie grant agreement No [101008233](https://doi.org/10.3030/101008233) (MISSION).\n\n## 🤼 Contributing\n\nWe look forward to any kind of contributions!\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual-licensed as above, without any additional terms or conditions.\n\n### Contributors\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"http://robinohs.dev/\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/49798174?v=4?s=100\" width=\"100px;\" alt=\"Robin Ohs\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eRobin Ohs\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/robinohs/phantomlink/commits?author=robinohs\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/robinohs/phantomlink/commits?author=robinohs\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"#ideas-robinohs\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e \u003ca href=\"#maintenance-robinohs\" title=\"Maintenance\"\u003e🚧\u003c/a\u003e \u003ca href=\"#research-robinohs\" title=\"Research\"\u003e🔬\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/GrSto\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/10924479?v=4?s=100\" width=\"100px;\" alt=\"Gregory\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eGregory\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/robinohs/phantomlink/commits?author=GrSto\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/robinohs/phantomlink/commits?author=GrSto\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"#ideas-GrSto\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e \u003ca href=\"#research-GrSto\" title=\"Research\"\u003e🔬\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"http://netzdoktor.eu/\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/974093?v=4?s=100\" width=\"100px;\" alt=\"Andreas Schmidt\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAndreas Schmidt\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/robinohs/phantomlink/commits?author=netzdoktor\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"#design-netzdoktor\" title=\"Design\"\u003e🎨\u003c/a\u003e \u003ca href=\"https://github.com/robinohs/phantomlink/commits?author=netzdoktor\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"#ideas-netzdoktor\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e \u003ca href=\"#research-netzdoktor\" title=\"Research\"\u003e🔬\u003c/a\u003e \u003ca href=\"#mentoring-netzdoktor\" title=\"Mentoring\"\u003e🧑‍🏫\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\nThis project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind are welcome 😎.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobinohs%2Fphantomlink","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobinohs%2Fphantomlink","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobinohs%2Fphantomlink/lists"}