Skip to content

Commit

Permalink
Merge pull request #257 from Tencent/release/v0.11.0
Browse files Browse the repository at this point in the history
Release/v0.11.0
  • Loading branch information
iyangsj committed May 8, 2024
2 parents ede1c92 + 32b5608 commit 5f9289c
Show file tree
Hide file tree
Showing 19 changed files with 462 additions and 184 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/plot-interop.py
Expand Up @@ -18,8 +18,8 @@
"go-x-net", "quic-go", "mvfst"]

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


Expand Down Expand Up @@ -84,7 +84,7 @@ def plot(data_dir, is_tquic_server):
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]),
text = ax.text(i, j, convert_text(interop_result[j, i]),
ha="center", va="center", color="w")
ax.set_title("TQUIC %s interop results" % (name))
fig.tight_layout()
Expand Down
26 changes: 26 additions & 0 deletions .github/workflows/tquic-integration.yml
@@ -0,0 +1,26 @@
name: Integration

on:
push:
branches: [ "develop" ]
pull_request:
branches: [ "develop" ]
workflow_dispatch:

env:
CARGO_TERM_COLOR: always

jobs:
extra:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: 'recursive'
- name: Build
run: cargo build --release --all
- name: Run integration tests for multipath
run: |
cd tools/tests/
bash ./tquic_tools_test.sh -b ../../target/release/ -t multipath_redundant,multipath_minrtt,multipath_roundrobin -f 1000M -p 5
2 changes: 1 addition & 1 deletion .github/workflows/tquic-interop-all.yml
Expand Up @@ -104,7 +104,7 @@ jobs:
- name: Run the interop tests
run: |
cd quic-interop-runner
python3 run.py -s ${{ matrix.server }} -c ${{ matrix.client }} -t handshake,handshakeloss,handshakecorruption,retry,resumption,zerortt,amplificationlimit,http3,ipv6,transfer,multiplexing,longrtt,blackhole,transferloss,transfercorruption,goodput,crosstraffic -d -r tquic=tquic_interop:v1 -l ${{ matrix.server }}-${{ matrix.client }}-logs -j ${{ matrix.server }}-${{ matrix.client }}-logs/interop.json
python3 run.py -s ${{ matrix.server }} -c ${{ matrix.client }} -t handshake,handshakeloss,handshakecorruption,retry,resumption,zerortt,amplificationlimit,http3,ipv6,chacha20,keyupdate,transfer,multiplexing,longrtt,blackhole,transferloss,transfercorruption,goodput,crosstraffic -d -r tquic=tquic_interop:v1 -l ${{ matrix.server }}-${{ matrix.client }}-logs -j ${{ matrix.server }}-${{ matrix.client }}-logs/interop.json
- name: Dump the interop result
if: ${{ always() }}
Expand Down
39 changes: 19 additions & 20 deletions CHANGELOG.md
Expand Up @@ -10,6 +10,24 @@ 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.11.0] - 2024-05-08

### Added
- tquic_tools: group different options by category and prioritize commonly used options
- Add the header file of BoringSSL library in tquic.h
- Resolve new issues found by cargo clippy
- Add integration testing for multipath
- Update run_endpoint.sh to enable keyupdate/chacha20 testcase for server

### Changed
- tquic_tools: rename `max_requests_per_thread` to `total_requests_per_thread`

### Fixed
- Fix RangeSet::filter() used by Redundant multipath scheduler
- Fix injected stream frames for Redundant multipath scheduler


## [v0.10.0] - 2024-04-26

### Added
Expand Down Expand Up @@ -48,26 +66,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- limit the number of queued RETIRE_CONNECTION_ID frames


## [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
Expand Down Expand Up @@ -219,6 +217,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Provide example clients and servers.


[v0.11.0]: https://github.com/tencent/tquic/compare/v0.10.0...v0.11.0
[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
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "tquic"
version = "0.10.0"
version = "0.11.0"
edition = "2021"
rust-version = "1.70.0"
license = "Apache-2.0"
Expand Down
1 change: 1 addition & 0 deletions cbindgen.toml
Expand Up @@ -16,6 +16,7 @@ documentation = true

# A list of headers to #include (with quotes)
sys_includes = ["sys/socket.h", "sys/types.h"]
includes = ["openssl/ssl.h"]

[export]
exclude = ["MAX_CID_LEN", "MIN_CLIENT_INITIAL_LEN"]
Expand Down
1 change: 1 addition & 0 deletions include/tquic.h
Expand Up @@ -9,6 +9,7 @@
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "openssl/ssl.h"

/**
* The current QUIC wire version.
Expand Down
4 changes: 2 additions & 2 deletions interop/run_endpoint.sh
Expand Up @@ -23,12 +23,12 @@ set -x
case "$TESTCASE" in
handshake|http3|multiconnect|resumption|retry|transfer|zerortt)
;;
chacha20)
chacha20|keyupdate)
if [ "$ROLE" == "client" ]; then
exit 127
fi
;;
keyupdate|ecn|v2)
ecn|v2)
exit 127
;;
*)
Expand Down
18 changes: 7 additions & 11 deletions src/connection/connection.rs
Expand Up @@ -1079,7 +1079,7 @@ impl Connection {
return Err(Error::Done);
}

self.token = pkt_hdr.token.clone();
self.token.clone_from(&pkt_hdr.token);
self.flags.insert(DidRetry);
self.flags.remove(GotPeerCid);

Expand Down Expand Up @@ -1161,7 +1161,7 @@ impl Connection {
self.multipath_scheduler = Some(build_multipath_scheduler(&self.multipath_conf));
self.paths.enable_multipath();
self.flags.insert(EnableMultipath);
trace!("{} enable multipath", &self.trace_id);
debug!("{} enable multipath", &self.trace_id);
}

// Prepare for sending NEW_CONNECTION_ID/NEW_TOKEN frames.
Expand Down Expand Up @@ -2528,12 +2528,14 @@ impl Connection {

// Processing the following subrange.
if r.start + (data_len as u64) < offset + length as u64 {
let tail_len =
(offset + length as u64 - r.start - data_len as u64) as usize;
let frame = Frame::Stream {
stream_id,
offset: r.start + data_len as u64,
length: length - data_len,
length: tail_len,
fin,
data: data.slice(data_len..),
data: data.slice(length - tail_len..),
};
space.buffered.push_front(frame, buffer_type);
}
Expand Down Expand Up @@ -4045,13 +4047,7 @@ impl CryptoStreams {
/// stream data. QUIC relies on the implementation to avoid excessive
/// buffering of data
fn new_stream() -> Stream {
Stream::new(
true,
true,
std::u64::MAX,
std::u64::MAX,
stream::MAX_STREAM_WINDOW,
)
Stream::new(true, true, u64::MAX, u64::MAX, stream::MAX_STREAM_WINDOW)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/connection/recovery.rs
Expand Up @@ -212,7 +212,7 @@ impl Recovery {

// Update the largest packet number acknowledged in the space
let largest_acked_pkt = ranges.max().unwrap();
if space.largest_acked_pkt == std::u64::MAX {
if space.largest_acked_pkt == u64::MAX {
space.largest_acked_pkt = largest_acked_pkt;
} else {
space.largest_acked_pkt = cmp::max(space.largest_acked_pkt, largest_acked_pkt);
Expand Down
4 changes: 2 additions & 2 deletions src/connection/space.rs
Expand Up @@ -141,7 +141,7 @@ impl PacketNumSpace {
id,
next_pkt_num: 0,
consecutive_non_ack_eliciting_sent: 0,
lowest_1rtt_pkt_num: std::u64::MAX,
lowest_1rtt_pkt_num: u64::MAX,
largest_rx_pkt_num: 0,
first_pkt_num_recv: None,
first_pkt_num_sent: None,
Expand All @@ -156,7 +156,7 @@ impl PacketNumSpace {
buffered: BufferQueue::default(),
time_of_last_sent_ack_eliciting_pkt: None,
loss_time: None,
largest_acked_pkt: std::u64::MAX,
largest_acked_pkt: u64::MAX,
loss_probes: 0,
bytes_in_flight: 0,
ack_eliciting_in_flight: 0,
Expand Down
4 changes: 2 additions & 2 deletions src/connection/stream.rs
Expand Up @@ -1619,7 +1619,7 @@ impl StreamMap {
/// RESET_STREAM frame was lost, if the stream is still open, add the stream
/// to the reset set to ensure a RESET_STREAM frame will be retransmitted.
pub fn on_reset_stream_frame_lost(&mut self, stream_id: u64, error_code: u64, final_size: u64) {
if self.streams.get(&stream_id).is_some() {
if self.streams.contains_key(&stream_id) {
self.mark_reset(stream_id, true, error_code, final_size);
}
}
Expand All @@ -1641,7 +1641,7 @@ impl StreamMap {
/// MAX_STREAM_DATA frame was lost, add the stream to the almost full set
/// to ensure a MAX_STREAM_DATA frame will be sent.
pub fn on_max_stream_data_frame_lost(&mut self, stream_id: u64) {
if self.streams.get(&stream_id).is_some() {
if self.streams.contains_key(&stream_id) {
self.mark_almost_full(stream_id, true);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/endpoint.rs
Expand Up @@ -621,7 +621,7 @@ impl Endpoint {

/// Check whether the given connection exists.
pub(crate) fn conn_exist(&self, cid: ConnectionId) -> bool {
self.routes.cid_table.get(&cid).is_some()
self.routes.cid_table.contains_key(&cid)
}

/// Get the connection by index
Expand Down
1 change: 1 addition & 0 deletions src/packet.rs
Expand Up @@ -472,6 +472,7 @@ fn encrypt_header(
/// The `paylaod_offset` is the offset of packet payload in `pkt_buf`.
/// The `payload_len` is the length of pacekt payload (other than the value of Length field).
/// The `pkt_num` is the decrypted and decoded packet number.
#[allow(unexpected_cfgs)]
pub(crate) fn decrypt_payload(
pkt_buf: &mut [u8],
payload_offset: usize,
Expand Down
55 changes: 51 additions & 4 deletions src/ranges.rs
Expand Up @@ -16,6 +16,7 @@ use std::ops::Range;

use std::collections::btree_map;
use std::collections::BTreeMap;
use std::collections::Bound::Excluded;
use std::collections::Bound::Included;
use std::collections::Bound::Unbounded;

Expand Down Expand Up @@ -170,7 +171,7 @@ impl RangeSet {
}
}

if let Some(r) = self.next_to(range.start) {
if let Some(r) = self.next_after(range.start) {
if r.start < range.end {
new_end = r.start
}
Expand Down Expand Up @@ -216,22 +217,30 @@ impl RangeSet {
}
}

/// Find the closest range to `elem` that begins at or before it.
/// Find the closest range to `elem` that begins *at* or before it.
fn prev_to(&self, elem: u64) -> Option<Range<u64>> {
self.set
.range((Unbounded, Included(elem)))
.map(|(&s, &e)| (s..e))
.next_back()
}

/// Find the closest range to `elem` that begins after it.
/// Find the closest range to `elem` that begins *at* or after it.
fn next_to(&self, elem: u64) -> Option<Range<u64>> {
self.set
.range((Included(elem), Unbounded))
.map(|(&s, &e)| (s..e))
.next()
}

/// Find the closest range to `elem` that begins after it.
fn next_after(&self, elem: u64) -> Option<Range<u64>> {
self.set
.range((Excluded(elem), Unbounded))
.map(|(&s, &e)| (s..e))
.next()
}

/// Check if the element exists or not
pub fn contains(&self, elem: u64) -> bool {
if let Some(prev) = self.prev_to(elem) {
Expand Down Expand Up @@ -263,7 +272,7 @@ impl RangeSet {

impl Default for RangeSet {
fn default() -> Self {
Self::new(std::usize::MAX)
Self::new(usize::MAX)
}
}

Expand Down Expand Up @@ -810,17 +819,29 @@ mod tests {

#[test]
fn filter() {
// simple cases
let cases = [
(vec![2..4, 6..8], 0..2, Some(0..2)),
(vec![2..4, 6..8], 4..6, Some(4..6)),
(vec![2..4, 6..8], 8..9, Some(8..9)),
(vec![], 8..9, Some(8..9)),
(vec![2..4, 6..8], 2..4, None),
(vec![2..4, 6..8], 6..8, None),
(vec![2..4, 6..8], 2..3, None),
(vec![2..4, 6..8], 3..4, None),
(vec![2..4, 6..8], 6..7, None),
(vec![2..4, 6..8], 7..8, None),
(vec![2..4, 6..8], 0..4, Some(0..2)),
(vec![2..4, 6..8], 2..5, Some(4..5)),
(vec![2..4, 6..8], 5..8, Some(5..6)),
(vec![2..4, 6..8], 6..9, Some(8..9)),
(vec![2..4, 6..8], 3..5, Some(4..5)),
(vec![2..4, 6..8], 7..9, Some(8..9)),
(vec![2..4, 6..8], 0..3, Some(0..2)),
(vec![2..4, 6..8], 5..7, Some(5..6)),
(vec![2..4, 6..8], 0..5, Some(0..2)),
(vec![2..4, 6..8], 5..9, Some(5..6)),
(vec![2..4, 6..8], 3..7, Some(4..6)),
(vec![2..4, 6..8], 3..9, Some(4..6)),
(vec![2..4, 6..8], 0..7, Some(0..2)),
(vec![2..4, 6..8], 0..9, Some(0..2)),
Expand All @@ -832,6 +853,32 @@ mod tests {
}
assert_eq!(rs.filter(case.1), case.2);
}

// all cases
let mut rs = RangeSet::default();
for r in vec![2..4, 6..8] {
rs.insert(r);
}
for i in 0..10 {
for j in i + 1..11 {
let res = rs.filter(i..j);
if (i < 2 && j <= 2) || (i >= 4 && j <= 6) || i >= 8 {
assert_eq!(res, Some(i..j), "{:?} want {:?}, got {:?}", i..j, i..j, res)
} else if i < 2 && j > 2 {
assert_eq!(res, Some(i..2), "{:?} want {:?}, got {:?}", i..j, i..2, res)
} else if i >= 2 && i <= 4 && j > 4 && j <= 6 {
assert_eq!(res, Some(4..j), "{:?} want {:?}, got {:?}", i..j, 4..j, res)
} else if i >= 2 && i <= 4 && j > 4 && j > 6 {
assert_eq!(res, Some(4..6), "{:?} want {:?}, got {:?}", i..j, 4..6, res)
} else if i >= 4 && i < 6 && j >= 6 {
assert_eq!(res, Some(i..6), "{:?} want {:?}, got {:?}", i..j, i..6, res)
} else if i >= 6 && i < 8 && j > 8 {
assert_eq!(res, Some(8..j), "{:?} want {:?}, got {:?}", i..j, 8..j, res)
} else {
assert_eq!(res, None, "{:?} want None, got {:?}", i..j, res)
}
}
}
}

#[test]
Expand Down

0 comments on commit 5f9289c

Please sign in to comment.