libp2p-test-plans/hole-punch-interop
Piotr Galar e5e32c7c0a
chore: parameterise s3 build cache setup (#465)
* chore: parameterise s3 build cache setup

* Apply suggestions from code review

Co-authored-by: Alex Potsides <alex@achingbrain.net>

* fix: cache load/push

* chore: pass creds when reading cache

* fix: interact with aws only using the CLI

* Update transport-interop.yml

---------

Co-authored-by: Alex Potsides <alex@achingbrain.net>
2024-09-11 10:01:42 +02:00
..
compose-spec feat(hole-punch): add hole-punch interoperability test suite (#304) 2023-10-17 10:07:25 +11:00
helpers chore: parameterise s3 build cache setup (#465) 2024-09-11 10:01:42 +02:00
impl/rust feat(hole-punch/rust): use `v0.53` release (#327) 2023-11-16 15:56:41 +01:00
router feat(hole-punch): add hole-punch interoperability test suite (#304) 2023-10-17 10:07:25 +11:00
rust-relay fix(hole-punch): Add support for arm64 architecture (#311) 2023-10-26 16:28:40 +11:00
src Fix flaky QUIC hole-punching tests (#314) 2023-10-25 13:23:34 +11:00
.gitignore feat(hole-punch): add hole-punch interoperability test suite (#304) 2023-10-17 10:07:25 +11:00
Makefile feat(hole-punch): add hole-punch interoperability test suite (#304) 2023-10-17 10:07:25 +11:00
README.md feat(hole-punch): add hole-punch interoperability test suite (#304) 2023-10-17 10:07:25 +11:00
dockerBuildWrapper.sh feat(hole-punch): add hole-punch interoperability test suite (#304) 2023-10-17 10:07:25 +11:00
package-lock.json feat(hole-punch): add hole-punch interoperability test suite (#304) 2023-10-17 10:07:25 +11:00
package.json feat(hole-punch): add hole-punch interoperability test suite (#304) 2023-10-17 10:07:25 +11:00
renderResults.ts feat(hole-punch): add hole-punch interoperability test suite (#304) 2023-10-17 10:07:25 +11:00
testplans.ts feat(hole-punch): add hole-punch interoperability test suite (#304) 2023-10-17 10:07:25 +11:00
tsconfig.json feat(hole-punch): add hole-punch interoperability test suite (#304) 2023-10-17 10:07:25 +11:00
versions.ts feat(hole-punch/rust): use `v0.53` release (#327) 2023-11-16 15:56:41 +01:00

README.md

Hole punch tests

How to run locally

  1. npm install
  2. make
  3. npm run test

Client configuration

env variable possible values
MODE listen | dial
TRANSPORT tcp | quic
  • For TCP, the client MUST use noise + yamux to upgrade the connection.
  • The relayed connection MUST use noise + yamux.

Test flow

  1. The relay starts and pushes its address to the following redis keys:
    • RELAY_TCP_ADDRESS for the TCP test
    • RELAY_QUIC_ADDRESS for the QUIC test
  2. Upon start-up, clients connect to a redis server at redis:6379 and block until this redis key comes available. They then dial the relay on the provided address.
  3. The relay supports identify. Implementations SHOULD use that to figure out their external address next.
  4. Once connected to the relay, a client in MODE=listen should listen on the relay and make a reservation. Once the reservation is made, it pushes its PeerId to the redis key LISTEN_CLIENT_PEER_ID.
  5. A client in MODE=dial blocks on the availability of LISTEN_CLIENT_PEER_ID. Once available, it dials <relay_addr>/p2p-circuit/<listen-client-peer-id>.
  6. Upon a successful hole-punch, the peer in MODE=dial measures the RTT across the newly established connection.
  7. The RTT MUST be printed to stdout in the following format:
    { "rtt_to_holepunched_peer_millis": 12 }
    
  8. Once printed, the dialer MUST exit with 0.

Requirements for implementations

  • Docker containers MUST have a binary called hole-punch-client in their $PATH
  • MUST have dig, curl, jq and tcpdump installed
  • Listener MUST NOT early-exit but wait to be killed by test runner
  • Logs MUST go to stderr, RTT json MUST go to stdout
  • Dialer and lister both MUST use 0RTT negotiation for protocols
  • Implementations SHOULD disable timeouts on the redis client, i.e. use 0
  • Implementations SHOULD exit early with a non-zero exit code if anything goes wrong
  • Implementations MUST set TCP_NODELAY for the TCP transport
  • Implements MUST make sure connections are being kept alive

Design notes

The design of this test runner is heavily influenced by multidim-interop but differs in several ways.

All files related to test runs will be written to the ./runs directory. This includes the docker-compose.yml files of each individual run as well as logs and tcpdump's for the dialer and listener.

The docker-compose file uses 6 containers in total:

  • 1 redis container for orchestrating the test
  • 1 relay
  • 1 hole-punch client in MODE=dial
  • 1 hole-punch client in MODE=listen
  • 2 routers: 1 per client

The networks are allocated by docker-compose. We dynamically fetch the IPs and subnets as part of a startup script to set the correct IP routes.

In total, we have three networks:

  1. lan_dialer
  2. lan_listener
  3. internet

The two LANs host a router and a client each whereas the relay is connected (without a router) to the internet network. On startup of the clients, we add an ip route that redirects all traffic to the corresponding router container. The router container masquerades all traffic upon forwarding, see the README for details.

Running a single test

  1. Build all containers using make
  2. Generate all test definitions using npm run test -- --no-run
  3. Pick the desired test from the runs directory
  4. Execute it using docker compose up