Skip to content

Commit

Permalink
Merge pull request #219 from Tencent/release/v0.9.0
Browse files Browse the repository at this point in the history
Release/v0.9.0
  • Loading branch information
iyangsj authored Apr 10, 2024
2 parents cc948f5 + a872a61 commit 1d631c8
Show file tree
Hide file tree
Showing 18 changed files with 777 additions and 89 deletions.
65 changes: 65 additions & 0 deletions .github/workflows/plot-goodput.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env python3

import os
import sys

import json
import matplotlib.pyplot as plt
import numpy as np

# QUIC implementes
IMPLS = ["tquic", "lsquic", "picoquic", "quiche"]

# Different file sizes
SIZES = ["10m", "1m", "100k"]

# Different loss rates
RATES = [0, 1, 3, 5]

# Running count for each test
COUNT = 10


# Read a measurement file generated by goodput testing
def read_data(data_dir, impl, cc, size, loss):
dirname = "goodput%s-%s-%s" % (size, cc, impl)
filename = "goodput%s-%s-%s-%s.json" % (size, loss, cc, impl)
path = os.path.join(data_dir, dirname, filename)
try:
with open(path) as f:
data = json.load(f)
return data["measurements"][0][0]["data"]
except:
return None


# Plot the throughput graph for the specified CC algorithm under different file
# sizes and packet loss rates.
def plot(data_dir, cc):
fig, axs = plt.subplots(len(SIZES), len(RATES), figsize=(15,10))
x = np.linspace(0, COUNT, COUNT)
for i in range(len(SIZES)):
for j in range(len(RATES)):
for impl in IMPLS:
data = read_data(data_dir, impl, cc, SIZES[i], RATES[j])
if data is None or len(data) != COUNT:
continue
axs[i, j].plot(x, data, label=impl, marker="o")
axs[i, j].set_xlabel("Run #")
axs[i, j].set_ylabel("Goodput")
axs[i, j].set_title("%s loss rate %s%%" % (SIZES[i], RATES[j]))
axs[i, j].legend()
plt.suptitle(cc.upper())
plt.tight_layout()
plt.savefig("goodput-%s.png" % (cc), dpi=300)


if __name__ == '__main__':
if len(sys.argv) < 2:
print("Usage: %s [data_dir]" % (sys.argv[0]))
exit(1)

data_dir= sys.argv[1]
plot(data_dir, "bbr")
plot(data_dir, "cubic")

104 changes: 104 additions & 0 deletions .github/workflows/plot-interop.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#!/usr/bin/env python3

import os
import sys

import json
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import ListedColormap

# QUIC implementes
CLIENT_IMPLS = ["tquic", "lsquic", "quiche", "picoquic", "ngtcp2", "msquic",
"s2n-quic", "quinn", "neqo", "kwik", "aioquic", "chrome",
"go-x-net", "quic-go", "mvfst"]

SERVER_IMPLS = ["lsquic", "quiche", "picoquic", "ngtcp2", "msquic", "s2n-quic",
"quinn", "neqo", "kwik", "aioquic", "nginx", "haproxy",
"go-x-net", "quic-go", "mvfst"]

# Interop test cases
INTEROP_TESTS = ["handshake", "retry", "resumption", "zerortt", "amplificationlimit",
"http3", "ipv6", "transfer", "multiplexing", "longrtt", "blackhole",
"handshakeloss", "handshakecorruption", "transferloss","transfercorruption"]


# Read a interop file generated by interop testing
def read_data(data_dir, server, client):
dirname = "%s-%s/%s-%s-logs" % (server, client, server, client)
path = os.path.join(data_dir, dirname, "interop.json")
try:
with open(path) as f:
data = json.load(f)
return convert_data(data["results"][0])
except:
return [0] * len(INTEROP_TESTS)


# Convert interop results to a vector
def convert_data(result):
data = [0] * len(INTEROP_TESTS)
for i, name in enumerate(INTEROP_TESTS):
for item in result:
if item["name"] != name:
continue
if item["result"] == "succeeded":
data[i] = 3
elif item["result"] == "unsupported":
data[i] = 2
else:
data[i] = 1
break
return data


# Convert test result to a letter
def convert_text(value):
if value == 3:
return "Y" # success
elif value == 2:
return "U" # unsupported
elif value == 1:
return "N" # failure
else:
return "-" # unknown


# Plot the interop graph
def plot(data_dir, is_tquic_server):
impls = CLIENT_IMPLS if is_tquic_server else SERVER_IMPLS
name = "server" if is_tquic_server else "client"
if is_tquic_server:
data = [read_data(data_dir, "tquic", impl) for impl in impls]
else:
data = [read_data(data_dir, impl, "tquic") for impl in impls]
interop_result = np.array(data)
print(interop_result)

fig, ax = plt.subplots()
im = ax.imshow(interop_result, cmap=ListedColormap(['gray', 'red', 'blue', 'green']),
interpolation='nearest')
ax.set_xticks(np.arange(len(INTEROP_TESTS)), labels=INTEROP_TESTS)
ax.set_yticks(np.arange(len(impls)), labels=impls)
plt.setp(ax.get_xticklabels(), rotation=45, ha="right",
rotation_mode="anchor")
for i in range(len(INTEROP_TESTS)):
for j in range(len(impls)):
text = ax.text(j, i, convert_text(interop_result[i, j]),
ha="center", va="center", color="w")
ax.set_title("TQUIC %s interop results" % (name))
fig.tight_layout()

filename = "interop-tquic-%s.png" % (name)
plt.savefig(filename, dpi=300)


if __name__ == '__main__':
if len(sys.argv) < 2:
print("Usage: %s [data_dir]" % (sys.argv[0]))
exit(1)

data_dir= sys.argv[1]
plot(data_dir, True)
plot(data_dir, False)

34 changes: 29 additions & 5 deletions .github/workflows/tquic-goodput.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ jobs:
# You can manually trigger it if necessary.
if: ${{ ( github.event_name == 'schedule' && github.repository == 'tencent/tquic' ) || github.event_name == 'workflow_dispatch' }}
steps:
- uses: actions/checkout@v4
with:
submodules: 'recursive'

- name: Build docker image
run: docker build -t tquic_interop:v1 -f interop/Dockerfile .

- name: Install quic-interop-runner
run: |
git clone https://github.com/tquic-group/quic-interop-runner.git
Expand All @@ -38,15 +45,15 @@ jobs:
- name: Run the interop tests
run: |
cd quic-interop-runner
python3 run.py -r $QUIC_IMAGES -s ${{ matrix.impl }} -c ${{ matrix.impl }} -t ${{ matrix.case }} -a ${{ matrix.cc }} -d -n "drop-rate --delay=15ms --bandwidth=10Mbps --queue=25 --rate_to_server=0 --rate_to_client=0" -j ${{ matrix.case }}-0-${{ matrix.cc }}-${{ matrix.impl }}.json
python3 run.py -r $QUIC_IMAGES -s ${{ matrix.impl }} -c ${{ matrix.impl }} -t ${{ matrix.case }} -a ${{ matrix.cc }} -d -n "drop-rate --delay=15ms --bandwidth=10Mbps --queue=25 --rate_to_server=1 --rate_to_client=1" -j ${{ matrix.case }}-1-${{ matrix.cc }}-${{ matrix.impl }}.json
python3 run.py -r $QUIC_IMAGES -s ${{ matrix.impl }} -c ${{ matrix.impl }} -t ${{ matrix.case }} -a ${{ matrix.cc }} -d -n "drop-rate --delay=15ms --bandwidth=10Mbps --queue=25 --rate_to_server=3 --rate_to_client=3" -j ${{ matrix.case }}-3-${{ matrix.cc }}-${{ matrix.impl }}.json
python3 run.py -r $QUIC_IMAGES -s ${{ matrix.impl }} -c ${{ matrix.impl }} -t ${{ matrix.case }} -a ${{ matrix.cc }} -d -n "drop-rate --delay=15ms --bandwidth=10Mbps --queue=25 --rate_to_server=5 --rate_to_client=5" -j ${{ matrix.case }}-5-${{ matrix.cc }}-${{ matrix.impl }}.json
python3 run.py -r "$QUIC_IMAGES,tquic=tquic_interop:v1" -s ${{ matrix.impl }} -c ${{ matrix.impl }} -t ${{ matrix.case }} -a ${{ matrix.cc }} -d -n "drop-rate --delay=15ms --bandwidth=10Mbps --queue=25 --rate_to_server=0 --rate_to_client=0" -j ${{ matrix.case }}-0-${{ matrix.cc }}-${{ matrix.impl }}.json
python3 run.py -r "$QUIC_IMAGES,tquic=tquic_interop:v1" -s ${{ matrix.impl }} -c ${{ matrix.impl }} -t ${{ matrix.case }} -a ${{ matrix.cc }} -d -n "drop-rate --delay=15ms --bandwidth=10Mbps --queue=25 --rate_to_server=1 --rate_to_client=1" -j ${{ matrix.case }}-1-${{ matrix.cc }}-${{ matrix.impl }}.json
python3 run.py -r "$QUIC_IMAGES,tquic=tquic_interop:v1" -s ${{ matrix.impl }} -c ${{ matrix.impl }} -t ${{ matrix.case }} -a ${{ matrix.cc }} -d -n "drop-rate --delay=15ms --bandwidth=10Mbps --queue=25 --rate_to_server=3 --rate_to_client=3" -j ${{ matrix.case }}-3-${{ matrix.cc }}-${{ matrix.impl }}.json
python3 run.py -r "$QUIC_IMAGES,tquic=tquic_interop:v1" -s ${{ matrix.impl }} -c ${{ matrix.impl }} -t ${{ matrix.case }} -a ${{ matrix.cc }} -d -n "drop-rate --delay=15ms --bandwidth=10Mbps --queue=25 --rate_to_server=5 --rate_to_client=5" -j ${{ matrix.case }}-5-${{ matrix.cc }}-${{ matrix.impl }}.json
- name: Store measurement results
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.impl }}-${{ matrix.case }}-${{ matrix.cc }}
name: ${{ matrix.case }}-${{ matrix.cc }}-${{ matrix.impl }}
path: quic-interop-runner/goodput*.json

result:
Expand All @@ -55,8 +62,25 @@ jobs:
steps:
- name: Download all workflow run artifacts
uses: actions/download-artifact@v4

- name: Display structure of downloaded files
run: ls -R

- name: Display all measurement details
run: grep "details.*" . -Ro

- name: Download plot tools
uses: actions/checkout@v4
with:
path: tools

- name: Install dependences
run: |
sudo apt install python3-matplotlib
- name: Plot all measurement results
run: python3 tools/.github/workflows/plot-goodput.py .

- name: Store all measurement results
uses: actions/upload-artifact@v4
with:
Expand Down
37 changes: 36 additions & 1 deletion .github/workflows/tquic-interop-all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,46 @@ jobs:
python3 -m json.tool ${{ matrix.server }}-${{ matrix.client }}-logs/interop.json
- name: Store interop logs
if: ${{ failure() }}
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.server }}-${{ matrix.client }}
path: |
quic-interop-runner/*logs/*
!quic-interop-runner/*logs/**/crosstraffic/
!quic-interop-runner/*logs/**/goodput/
result:
runs-on: ubuntu-latest
needs: tquic_interop_testing
if: ${{ (( github.event_name == 'schedule' && github.repository == 'tencent/tquic' ) || github.event_name == 'workflow_dispatch') && !cancelled() }}
steps:
- name: Download all workflow run artifacts
uses: actions/download-artifact@v4

- name: Display structure of downloaded files
run: ls -R

- name: Display failed interop tests
run: grep -Ho "{[^{]*failed" */*/*.json

- name: Download plot tools
uses: actions/checkout@v4
with:
path: tools

- name: Install dependences
run: |
sudo apt install python3-matplotlib
- name: Plot all interop results
run: python3 tools/.github/workflows/plot-interop.py ./

- name: Store all interop results
uses: actions/upload-artifact@v4
with:
name: tquic-interop-all-result
path: |
interop*.png
*/*logs/*
!*/*logs/**/**/sim/
2 changes: 0 additions & 2 deletions .github/workflows/tquic-interop-main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ jobs:
client: tquic
- server: tquic
client: ngtcp2
- server: ngtcp2
client: tquic

steps:
- uses: actions/checkout@v4
Expand Down
25 changes: 22 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,35 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).


## [v0.9.0] - 2024-04-10

### Added
- Improve FFI for quic_tls_config_t
- Update the handling of probe timeout to conform with RFC 9002
- Update limit of the output buffer for Connection::send()
- Add plot tools for goodput and interop testing

### Changed
- Change `quic_config_set_tls_config()` in FFI
- Change `quic_tls_config_select_methods_t` in FFI

### Fixed
- Fix NewToken frame in qlog
- Fix the unit test case `conn_write_qlog` that fails with low probability

### Security
- limit the number of queued RETIRE_CONNECTION_ID frames


## [v0.8.1] - 2024-03-18

### Removed

- Remove the sfv feature flag from h3 (to resolve a build issue at docs.rs)


## [v0.8.0] - 2024-03-15

### Added

- Support anti-amplification limit for server
- Support customized config when initiating a connection
- Add callback based FFI for writing the keylog and qlog
Expand Down Expand Up @@ -88,7 +106,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- tquic_client: output the stats first and then exit when it receives an SIGINT signal.

### Changed
- Simplify FFI quic_set_logger() to avoid from return unnessary errors
- Simplify FFI quic_set_logger() to avoid from return unnecessary errors
- Rename set_multipath() in Config to enable_multipath()
- Rename set_multipath_algor() in Config to set_multipath_algorithm()
- Change default congestion control algorithm to BBR
Expand Down Expand Up @@ -164,6 +182,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Provide example clients and servers.


[v0.9.0]: https://github.com/tencent/tquic/compare/v0.8.1...v0.9.0
[v0.8.1]: https://github.com/tencent/tquic/compare/v0.8.0...v0.8.1
[v0.8.0]: https://github.com/tencent/tquic/compare/v0.7.0...v0.8.0
[v0.7.0]: https://github.com/tencent/tquic/compare/v0.6.0...v0.7.0
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "tquic"
version = "0.8.1"
version = "0.9.0"
edition = "2021"
rust-version = "1.70.0"
license = "Apache-2.0"
Expand Down
Loading

0 comments on commit 1d631c8

Please sign in to comment.