Skip to content

Commit

Permalink
Merge pull request #247 from Tencent/release/v0.10.0
Browse files Browse the repository at this point in the history
Release/v0.10.0
  • Loading branch information
iyangsj committed Apr 26, 2024
2 parents 1d631c8 + fad614f commit ede1c92
Show file tree
Hide file tree
Showing 28 changed files with 1,818 additions and 238 deletions.
65 changes: 65 additions & 0 deletions .github/workflows/plot-fct.py
@@ -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", "gquiche", "lsquic", "picoquic", "quiche"]

# Different modes
MODES = ["1rtt", "0rtt"]

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

# Running count for each test
COUNT = 30


# Read a measurement file generated by fct testing
def read_data(data_dir, impl, cc, mode, loss):
dirname = "fct%s-%s-%s" % (mode, cc, impl)
filename = "fct%s-%s-%s-%s.json" % (mode, 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
# modes and packet loss rates.
def plot(data_dir, cc):
fig, axs = plt.subplots(len(MODES), len(RATES), figsize=(15,10))
x = np.linspace(0, COUNT, COUNT)
for i in range(len(MODES)):
for j in range(len(RATES)):
for impl in IMPLS:
data = read_data(data_dir, impl, cc, MODES[i], RATES[j])
if data is None or len(data) != COUNT:
continue
axs[i, j].plot(x, data, label=impl, marker=".")
axs[i, j].set_xlabel("Run #")
axs[i, j].set_ylabel("FCT")
axs[i, j].set_title("%s loss rate %s%%" % (MODES[i], RATES[j]))
axs[i, j].legend()
plt.suptitle(cc.upper())
plt.tight_layout()
plt.savefig("fct-%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")

4 changes: 2 additions & 2 deletions .github/workflows/plot-goodput.py
Expand Up @@ -8,7 +8,7 @@
import numpy as np

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

# Different file sizes
SIZES = ["10m", "1m", "100k"]
Expand Down Expand Up @@ -44,7 +44,7 @@ def plot(data_dir, cc):
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].plot(x, data, label=impl, marker=".")
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]))
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Expand Up @@ -136,7 +136,7 @@ jobs:
- name: Generate code coverage
run: cargo llvm-cov --lcov --output-path lcov.info
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: lcov.info
Expand Down
90 changes: 90 additions & 0 deletions .github/workflows/tquic-fct.yml
@@ -0,0 +1,90 @@
name: FCT

on:
schedule:
- cron: '30 1 * * *'
workflow_dispatch:

env:
CARGO_TERM_COLOR: always
QUIC_IMAGES: gquiche=tquicgroup/qirgq,lsquic=tquicgroup/qirls,picoquic=tquicgroup/qirpq,quiche=tquicgroup/qircq

jobs:
measure:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
impl: [tquic,gquiche,lsquic,picoquic]
case: [fct1rtt,fct0rtt]
cc: [cubic, bbr]

# The scheduled workflow only runs for the main repository.
# 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/iyangsj/quic-interop-runner.git
cd quic-interop-runner
pip3 install -r requirements.txt
- name: Install dependences
run: |
sudo modprobe ip6table_filter
sudo add-apt-repository -y ppa:wireshark-dev/stable
sudo apt install -y tshark
- name: Run the interop tests
run: |
cd quic-interop-runner
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.case }}-${{ matrix.cc }}-${{ matrix.impl }}
path: quic-interop-runner/fct*.json

result:
runs-on: ubuntu-latest
needs: measure
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 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-fct.py .

- name: Store all measurement results
uses: actions/upload-artifact@v4
with:
name: fct-all-result
path: fct*
4 changes: 2 additions & 2 deletions .github/workflows/tquic-goodput.yml
Expand Up @@ -7,15 +7,15 @@ on:

env:
CARGO_TERM_COLOR: always
QUIC_IMAGES: lsquic=tquicgroup/qirls,picoquic=tquicgroup/qirpq,quiche=tquicgroup/qircq
QUIC_IMAGES: gquiche=tquicgroup/qirgq,lsquic=tquicgroup/qirls,picoquic=tquicgroup/qirpq,quiche=tquicgroup/qircq

jobs:
measure:
runs-on: ubuntu-latest

strategy:
matrix:
impl: [tquic,lsquic,picoquic,quiche]
impl: [tquic,gquiche,lsquic,picoquic,quiche]
case: [goodput100k,goodput1m,goodput10m]
cc: [cubic, bbr]

Expand Down
38 changes: 38 additions & 0 deletions CHANGELOG.md
Expand Up @@ -10,6 +10,43 @@ All notable changes to this project will be documented in this file.
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.10.0] - 2024-04-26

### Added
- Add support for responding to key updates
- Add datagram packetization layer PMTU discovery
- Improve API for stream creation
- Limit configuration value of type varint
- Add pacing_rate to PathStats
- tquic_server: output stats when server connection is closed
- Add workflow and plot tools for fct testing

### Fixed
- Fix the issue where bbr3 cannot exit slow start due to high packet loss rate

### Security
- Limit memory consuption for tracking closed stream ids


## [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.9.0] - 2024-04-10

Expand Down Expand Up @@ -182,6 +219,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Provide example clients and servers.


[v0.10.0]: https://github.com/tencent/tquic/compare/v0.9.0...v0.10.0
[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
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "tquic"
version = "0.9.0"
version = "0.10.0"
edition = "2021"
rust-version = "1.70.0"
license = "Apache-2.0"
Expand Down
36 changes: 31 additions & 5 deletions include/tquic.h
Expand Up @@ -318,12 +318,17 @@ void quic_config_set_max_handshake_timeout(struct quic_config_t *config, uint64_
*/
void quic_config_set_recv_udp_payload_size(struct quic_config_t *config, uint16_t v);

/*
* Enable the Datagram Packetization Layer Path MTU Discovery
* default value is true.
*/
void enable_dplpmtud(struct quic_config_t *config, bool v);

/**
* Set the initial maximum outgoing UDP payload size.
* The default and minimum value is `1200`.
* Set the maximum outgoing UDP payload size in bytes.
* It corresponds to the maximum datagram size that DPLPMTUD tries to discovery.
*
* The configuration should be changed with caution. The connection may
* not work properly if an inappropriate value is set.
* The default value is `1200` which means let DPLPMTUD choose a value.
*/
void quic_config_set_send_udp_payload_size(struct quic_config_t *config, uintptr_t v);

Expand Down Expand Up @@ -891,13 +896,34 @@ ssize_t quic_stream_write(struct quic_conn_t *conn,
bool fin);

/**
* Create a new quic transport stream with the given id and priority.
* Create a new quic stream with the given id and priority.
* This is a low-level API for stream creation. It is recommended to use
* `quic_stream_bidi_new` for bidirectional streams or `quic_stream_uni_new`
* for unidrectional streams.
*/
int quic_stream_new(struct quic_conn_t *conn,
uint64_t stream_id,
uint8_t urgency,
bool incremental);

/**
* Create a new quic bidiectional stream with the given priority.
* If success, the output parameter `stream_id` carrys the id of the created stream.
*/
int quic_stream_bidi_new(struct quic_conn_t *conn,
uint8_t urgency,
bool incremental,
uint64_t *stream_id);

/**
* Create a new quic uniectional stream with the given priority.
* If success, the output parameter `stream_id` carrys the id of the created stream.
*/
int quic_stream_uni_new(struct quic_conn_t *conn,
uint8_t urgency,
bool incremental,
uint64_t *stream_id);

/**
* Shutdown stream reading or writing.
*/
Expand Down
6 changes: 0 additions & 6 deletions interop/run_endpoint.sh
Expand Up @@ -80,9 +80,6 @@ if [ "$ROLE" == "client" ]; then
zerortt)
CLIENT_ARGS="$CLIENT_ARGS --session-file=session.bin --enable-early-data"
;;
transfer)
CLIENT_ARGS="$CLIENT_ARGS --send-udp-payload-size 1400"
;;
http3)
CLIENT_ALPN="--alpn h3"
;;
Expand Down Expand Up @@ -112,9 +109,6 @@ elif [ "$ROLE" == "server" ]; then
retry)
SERVER_ARGS="$SERVER_ARGS --enable-retry"
;;
transfer)
SERVER_ARGS="$SERVER_ARGS --send-udp-payload-size 1400"
;;
*)
;;
esac
Expand Down
4 changes: 4 additions & 0 deletions src/codec.rs
Expand Up @@ -21,6 +21,10 @@ use bytes::BufMut;
use crate::error::Error;
use crate::Result;

/// The maximum value for QUIC variable-length integer encoding
/// See RFC 9000 Section 16
pub const VINT_MAX: u64 = 4_611_686_018_427_387_903;

/// Encoder for QUIC wire data
pub trait Encoder {
/// Write an unsigned 8 bit integer to self.
Expand Down
3 changes: 2 additions & 1 deletion src/congestion_control/bbr3.rs
Expand Up @@ -1463,7 +1463,8 @@ impl Bbr3 {
//
// See <https://www.ietf.org/archive/id/draft-cardwell-iccrg-bbr-congestion-control-02.html#name-probing-for-bandwidth-in-pr>.
fn handle_lost_packet(&mut self, now: Instant, packet: &SentPacket) {
if !self.bw_probe_samples {
// In startup phase we need to update stats upon every ack reception
if !self.bw_probe_samples && !self.in_slow_start() {
// not a packet sent while probing bandwidth.
return;
}
Expand Down

0 comments on commit ede1c92

Please sign in to comment.