diff --git a/.gitignore b/.gitignore index 20e2395ea..b8d4ae736 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ Cargo.lock .idea .DS_Store .vscode + +perf/docker/work/ diff --git a/perf/docker/Dockerfile b/perf/docker/Dockerfile new file mode 100644 index 000000000..abdd64f18 --- /dev/null +++ b/perf/docker/Dockerfile @@ -0,0 +1,15 @@ +# https://hub.docker.com/_/debian +FROM debian:bookworm-slim + +RUN apt-get update && apt-get install -y procps iputils-ping iproute2 ethtool tcpdump + +WORKDIR /root + +RUN mkdir -p .local/share/quinn + +COPY ./entrypoint.sh . + +COPY ./target/perf_client . +COPY ./target/perf_server . + +ENTRYPOINT [ "/root/entrypoint.sh" ] diff --git a/perf/docker/build.sh b/perf/docker/build.sh new file mode 100755 index 000000000..cac2a3817 --- /dev/null +++ b/perf/docker/build.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env -S bash -eu + +CURDIR=$(pwd) + +mkdir -p ./target + +cd ../.. +cargo build -p perf --release +cp -au ./target/release/perf_server ./target/release/perf_client ${CURDIR}/target + +cd ${CURDIR} +docker compose build diff --git a/perf/docker/docker-compose.yml b/perf/docker/docker-compose.yml new file mode 100644 index 000000000..2bd44d5bf --- /dev/null +++ b/perf/docker/docker-compose.yml @@ -0,0 +1,33 @@ +version: '3' + +networks: + quinn-perf: + ipam: + config: + - subnet: 172.42.0.0/16 + +services: + server: + build: . + image: quinn_perf + networks: + quinn-perf: + ipv4_address: 172.42.0.2 + volumes: + - ./work:/root/.local/share/quinn + cap_add: + - NET_ADMIN + environment: + - SSLKEYLOGFILE=/root/.local/share/quinn/server.key + + client: + image: quinn_perf + networks: + quinn-perf: + ipv4_address: 172.42.0.3 + volumes: + - ./work:/root/.local/share/quinn + cap_add: + - NET_ADMIN + environment: + - SSLKEYLOGFILE=/root/.local/share/quinn/client.key diff --git a/perf/docker/entrypoint.sh b/perf/docker/entrypoint.sh new file mode 100755 index 000000000..423c24e5e --- /dev/null +++ b/perf/docker/entrypoint.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +while :; do sleep 10; done diff --git a/perf/docker/run-client.sh b/perf/docker/run-client.sh new file mode 100755 index 000000000..530a7f091 --- /dev/null +++ b/perf/docker/run-client.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env -S bash -eu + +SERVICE=client +PERF_CLIENT_ARGS="--keylog --duration 5 172.42.0.2:4433" + +LATENCY=0 +GSO=0 +CAPTURE=0 +OPEN=0 + +function usage() { + echo "usage: $0 [-cgho] [-l number]" + echo " -c enable packet capture" + echo " -g enable GSO (default: disabled)" + echo " -h display help" + echo " -l number specify simulated latency in ms (default: ${LATENCY}ms)" + echo " -o open packet capture" + exit 1 +} + +while getopts "cghl:o" opt; do + case $opt in + c) CAPTURE=1;; + g) GSO=1;; + l) LATENCY=$OPTARG;; + o) OPEN=1;; + h) usage;; + *) usage;; + esac +done + +mkdir -p ./work + +echo "Launching docker ${SERVICE}" +docker compose up -d --force-recreate ${SERVICE} +if [ ${LATENCY} -ne 0 ]; then + echo "Enforcing a latency of ${LATENCY}ms" + docker compose exec -it ${SERVICE} tc qdisc add dev eth0 root netem delay ${LATENCY}ms +fi + +if [ ${GSO} -eq 0 ]; then + # FIXME disable GSO due to this issue + # https://gitlab.com/wireshark/wireshark/-/issues/19109 + docker compose exec -it ${SERVICE} ethtool -K eth0 tx-udp-segmentation off +fi + +if [ ${CAPTURE} -eq 1 ]; then + echo "Starting capture within docker" + docker compose exec -d ${SERVICE} tcpdump -ni eth0 -s0 -w /root/.local/share/quinn/${SERVICE}.pcap udp and port 4433 +fi + +echo "Launching quinn perf client" +docker compose exec -it ${SERVICE} /root/perf_client ${PERF_CLIENT_ARGS} + +if [ ${CAPTURE} -eq 1 ]; then + echo "Stopping capture within docker" + docker compose exec -it ${SERVICE} killall -STOP tcpdump +fi + +if [ ${LATENCY} -ne 0 ]; then + echo "Dumping QOS stats" + docker compose exec -it ${SERVICE} tc -s qdisc ls dev eth0 +fi + +if [ ${CAPTURE} -eq 1 ] && [ ${OPEN} -eq 1 ]; then + wireshark -o tls.keylog_file:./work/${SERVICE}.key ./work/${SERVICE}.pcap +fi diff --git a/perf/docker/run-server.sh b/perf/docker/run-server.sh new file mode 100755 index 000000000..e4330df5e --- /dev/null +++ b/perf/docker/run-server.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env -S bash -eu + +SERVICE=server +PERF_SERVER_ARGS="--keylog --listen 172.42.0.2:4433" + +LATENCY=0 +GSO=0 +CAPTURE=0 +OPEN=0 + +function usage() { + echo "usage: $0 [-cgho] [-l number]" + echo " -c enable packet capture" + echo " -g enable GSO (default: disabled)" + echo " -h display help" + echo " -l number specify simulated latency in ms (default: ${LATENCY}ms)" + echo " -o open packet capture" + exit 1 +} + +while getopts "cghl:o" opt; do + case $opt in + c) CAPTURE=1;; + g) GSO=1;; + l) LATENCY=$OPTARG;; + o) OPEN=1;; + h) usage;; + *) usage;; + esac +done + +mkdir -p ./work + +echo "Launching docker ${SERVICE}" +docker compose up -d --force-recreate ${SERVICE} +if [ ${LATENCY} -ne 0 ]; then + echo "Enforcing a latency of ${LATENCY}ms" + docker compose exec -it ${SERVICE} tc qdisc add dev eth0 root netem delay ${LATENCY}ms +fi + +if [ ${GSO} -eq 0 ]; then + # FIXME disable GSO due to this issue + # https://gitlab.com/wireshark/wireshark/-/issues/19109 + docker compose exec -it ${SERVICE} ethtool -K eth0 tx-udp-segmentation off +fi + +if [ ${CAPTURE} -eq 1 ]; then + echo "Starting capture within docker" + docker compose exec -d ${SERVICE} tcpdump -ni eth0 -s0 -w /root/.local/share/quinn/${SERVICE}.pcap udp port 4433 +fi + +echo "Launching quinn perf server" +docker compose exec -d ${SERVICE} /root/perf_server ${PERF_SERVER_ARGS} + +echo "Press Ctrl-C to stop server" +( trap exit SIGINT ; read -r -d '' _