Skip to content

Commit aab5c72

Browse files
Merge commit '3194714f6fa1c78108b2a6353bd3e2af95ce1152' into multipath-quinn-0.11.x-b2b930a-merges
2 parents c72f5ea + 3194714 commit aab5c72

File tree

14 files changed

+537
-252
lines changed

14 files changed

+537
-252
lines changed

.github/workflows/codecov.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
# | paste -sd ',' -
2828
run: |
2929
cargo llvm-cov \
30-
--features="arbitrary,async-io,async-std,aws-lc-rs,bloom,direct-log,fast-apple-datapath,futures-io,json-output,lock_tracking,log,platform-verifier,__qlog,ring,runtime-async-std,runtime-smol,runtime-tokio,rustls,rustls-aws-lc-rs,rustls-log,rustls-ring,serde,serde_json,smol,tracing" \
30+
--features="arbitrary,async-io,async-std,aws-lc-rs,bloom,direct-log,fast-apple-datapath,futures-io,json-output,lock_tracking,log,platform-verifier,qlog,ring,runtime-async-std,runtime-smol,runtime-tokio,rustls,rustls-aws-lc-rs,rustls-log,rustls-ring,serde,serde_json,smol,tracing" \
3131
--workspace --lcov --output-path lcov.info
3232
- name: Upload coverage to Codecov
3333
uses: codecov/codecov-action@v5

.github/workflows/rust.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ on:
245245
uses: actions/checkout@v5
246246

247247
- name: Install JDK
248-
uses: actions/setup-java@v4
248+
uses: actions/setup-java@v5
249249
with:
250250
distribution: 'zulu'
251251
java-version: '21'

Cargo.lock

Lines changed: 11 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bench/src/lib.rs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -177,14 +177,14 @@ pub struct Opt {
177177
pub max_streams: usize,
178178
/// Number of bytes to transmit from server to client
179179
///
180-
/// This can use SI prefixes for sizes. E.g. 1M will transfer 1MiB, 10G
181-
/// will transfer 10GiB.
180+
/// This can use SI suffixes for sizes. For example, 1M will transfer
181+
/// 1MiB, 10G will transfer 10GiB.
182182
#[clap(long, default_value = "1G", value_parser = parse_byte_size)]
183183
pub download_size: u64,
184184
/// Number of bytes to transmit from client to server
185185
///
186-
/// This can use SI prefixes for sizes. E.g. 1M will transfer 1MiB, 10G
187-
/// will transfer 10GiB.
186+
/// This can use SI suffixes for sizes. For example, 1M will transfer
187+
/// 1MiB, 10G will transfer 10GiB.
188188
#[clap(long, default_value = "0", value_parser = parse_byte_size)]
189189
pub upload_size: u64,
190190
/// Show connection stats the at the end of the benchmark
@@ -214,15 +214,12 @@ fn parse_byte_size(s: &str) -> Result<u64, ParseIntError> {
214214
_ => 1,
215215
};
216216

217-
let s = if multiplier != 1 {
218-
&s[..s.len() - 1]
219-
} else {
220-
s
217+
let s = match multiplier {
218+
1 => s,
219+
_ => &s[..s.len() - 1],
221220
};
222221

223-
let base: u64 = u64::from_str(s)?;
224-
225-
Ok(base * multiplier)
222+
Ok(u64::from_str(s)? * multiplier)
226223
}
227224

228225
#[derive(Debug, PartialEq, Eq, Clone, Copy)]

perf/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ edition = "2021"
55
license = "MIT OR Apache-2.0"
66
publish = false
77

8+
[[bin]]
9+
name = "quinn-perf"
10+
path = "src/bin/perf.rs"
11+
812
[features]
913
# NOTE: Please keep this in sync with the feature list in `.github/workflows/codecov.yml`, see
1014
# comment in that file for more information.

perf/src/bin/perf.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use clap::{Parser, Subcommand};
2+
use tracing::error;
3+
use tracing_subscriber::{EnvFilter, fmt, layer::SubscriberExt, util::SubscriberInitExt};
4+
5+
use perf::{client, server};
6+
7+
#[derive(Parser)]
8+
#[clap(long_about = None)]
9+
struct Cli {
10+
#[command(subcommand)]
11+
command: Commands,
12+
}
13+
14+
#[derive(Subcommand)]
15+
enum Commands {
16+
/// Run as a perf server
17+
Server(server::Opt),
18+
/// Run as a perf client
19+
Client(client::Opt),
20+
}
21+
22+
#[tokio::main(flavor = "current_thread")]
23+
async fn main() {
24+
let opt = Cli::parse();
25+
26+
tracing_subscriber::registry()
27+
.with(
28+
EnvFilter::try_from_default_env()
29+
.or_else(|_| EnvFilter::try_new("warn"))
30+
.unwrap(),
31+
)
32+
.with(fmt::layer())
33+
.init();
34+
35+
let r = match opt.command {
36+
Commands::Server(opt) => server::run(opt).await,
37+
Commands::Client(opt) => client::run(opt).await,
38+
};
39+
if let Err(e) = r {
40+
error!("{:#}", e);
41+
}
42+
}

perf/src/bin/perf_client.rs renamed to perf/src/client.rs

Lines changed: 33 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#[cfg(feature = "json-output")]
2-
use std::{fs::File, path::PathBuf};
2+
use std::path::PathBuf;
33
use std::{
44
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
55
sync::Arc,
@@ -14,92 +14,60 @@ use rustls::pki_types::{CertificateDer, ServerName, UnixTime};
1414
use tokio::sync::Semaphore;
1515
use tracing::{debug, error, info};
1616

17-
use perf::{
18-
CongestionAlgorithm, bind_socket,
17+
use crate::{
18+
CommonOpt, PERF_CIPHER_SUITES,
1919
noprotection::NoProtectionClientConfig,
20+
parse_byte_size,
2021
stats::{OpenStreamStats, Stats},
2122
};
2223

2324
/// Connects to a QUIC perf server and maintains a specified pattern of requests until interrupted
2425
#[derive(Parser)]
2526
#[clap(name = "client")]
26-
struct Opt {
27+
pub struct Opt {
2728
/// Host to connect to
2829
#[clap(default_value = "localhost:4433")]
2930
host: String,
3031
/// Override DNS resolution for host
3132
#[clap(long)]
3233
ip: Option<IpAddr>,
34+
/// Specify the local socket address
35+
#[clap(long)]
36+
local_addr: Option<SocketAddr>,
3337
/// Number of unidirectional requests to maintain concurrently
3438
#[clap(long, default_value = "0")]
3539
uni_requests: u64,
3640
/// Number of bidirectional requests to maintain concurrently
3741
#[clap(long, default_value = "1")]
3842
bi_requests: u64,
3943
/// Number of bytes to request
40-
#[clap(long, default_value = "1048576")]
44+
///
45+
/// This can use SI suffixes for sizes. For example, 1M will transfer
46+
/// 1MiB, 10G will transfer 10GiB.
47+
#[clap(long, default_value = "1M", value_parser = parse_byte_size)]
4148
download_size: u64,
4249
/// Number of bytes to transmit, in addition to the request header
43-
#[clap(long, default_value = "1048576")]
50+
///
51+
/// This can use SI suffixes for sizes. For example, 1M will transfer
52+
/// 1MiB, 10G will transfer 10GiB.
53+
#[clap(long, default_value = "1M", value_parser = parse_byte_size)]
4454
upload_size: u64,
4555
/// The time to run in seconds
4656
#[clap(long, default_value = "60")]
4757
duration: u64,
4858
/// The interval in seconds at which stats are reported
4959
#[clap(long, default_value = "1")]
5060
interval: u64,
51-
/// Send buffer size in bytes
52-
#[clap(long, default_value = "2097152")]
53-
send_buffer_size: usize,
54-
/// Receive buffer size in bytes
55-
#[clap(long, default_value = "2097152")]
56-
recv_buffer_size: usize,
57-
/// Specify the local socket address
58-
#[clap(long)]
59-
local_addr: Option<SocketAddr>,
60-
/// Whether to print connection statistics
61-
#[clap(long)]
62-
conn_stats: bool,
6361
/// File path to output JSON statistics to. If the file is '-', stdout will be used
6462
#[cfg(feature = "json-output")]
6563
#[clap(long)]
6664
json: Option<PathBuf>,
67-
/// Perform NSS-compatible TLS key logging to the file specified in `SSLKEYLOGFILE`.
68-
#[clap(long = "keylog")]
69-
keylog: bool,
70-
/// UDP payload size that the network must be capable of carrying
71-
#[clap(long, default_value = "1200")]
72-
initial_mtu: u16,
73-
/// Disable packet encryption/decryption (for debugging purpose)
74-
#[clap(long = "no-protection")]
75-
no_protection: bool,
76-
/// The initial round-trip-time (in msecs)
77-
#[clap(long)]
78-
initial_rtt: Option<u64>,
79-
/// Ack Frequency mode
80-
#[clap(long = "ack-frequency")]
81-
ack_frequency: bool,
82-
/// Congestion algorithm to use
83-
#[clap(long = "congestion")]
84-
cong_alg: Option<CongestionAlgorithm>,
85-
/// qlog output file
86-
#[cfg(feature = "qlog")]
87-
#[clap(long = "qlog")]
88-
qlog_file: Option<PathBuf>,
89-
}
90-
91-
#[tokio::main(flavor = "current_thread")]
92-
async fn main() {
93-
let opt = Opt::parse();
94-
95-
tracing_subscriber::fmt::init();
96-
97-
if let Err(e) = run(opt).await {
98-
error!("{:#}", e);
99-
}
65+
/// Common options
66+
#[command(flatten)]
67+
common: CommonOpt,
10068
}
10169

102-
async fn run(opt: Opt) -> Result<()> {
70+
pub async fn run(opt: Opt) -> Result<()> {
10371
let mut host_parts = opt.host.split(':');
10472
let host_name = host_parts.next().unwrap();
10573
let host_port = host_parts
@@ -128,13 +96,16 @@ async fn run(opt: Opt) -> Result<()> {
12896

12997
info!("local addr {:?}", bind_addr);
13098

131-
let socket = bind_socket(bind_addr, opt.send_buffer_size, opt.recv_buffer_size)?;
99+
let socket = opt.common.bind_socket(bind_addr)?;
100+
101+
let mut endpoint_cfg = quinn::EndpointConfig::default();
102+
endpoint_cfg.max_udp_payload_size(opt.common.max_udp_payload_size)?;
132103

133-
let endpoint = quinn::Endpoint::new(Default::default(), None, socket, Arc::new(TokioRuntime))?;
104+
let endpoint = quinn::Endpoint::new(endpoint_cfg, None, socket, Arc::new(TokioRuntime))?;
134105

135106
let default_provider = rustls::crypto::ring::default_provider();
136107
let provider = Arc::new(rustls::crypto::CryptoProvider {
137-
cipher_suites: perf::PERF_CIPHER_SUITES.into(),
108+
cipher_suites: PERF_CIPHER_SUITES.into(),
138109
..default_provider
139110
});
140111

@@ -146,35 +117,17 @@ async fn run(opt: Opt) -> Result<()> {
146117
.with_no_client_auth();
147118
crypto.alpn_protocols = vec![b"perf".to_vec()];
148119

149-
if opt.keylog {
120+
if opt.common.keylog {
150121
crypto.key_log = Arc::new(rustls::KeyLogFile::new());
151122
}
152123

153-
let mut transport = quinn::TransportConfig::default();
154-
transport.initial_mtu(opt.initial_mtu);
155-
156-
if let Some(initial_rtt) = opt.initial_rtt {
157-
transport.initial_rtt(Duration::from_millis(initial_rtt));
158-
}
159-
160-
if opt.ack_frequency {
161-
transport.ack_frequency_config(Some(quinn::AckFrequencyConfig::default()));
162-
}
163-
164-
if let Some(cong_alg) = opt.cong_alg {
165-
transport.congestion_controller_factory(cong_alg.build());
166-
}
167-
168-
#[cfg(feature = "qlog")]
169-
if let Some(qlog_file) = &opt.qlog_file {
170-
let mut qlog = quinn::QlogConfig::default();
171-
qlog.writer(Box::new(File::create(qlog_file)?))
172-
.title(Some("perf-client".into()));
173-
transport.qlog_stream(qlog.into_stream());
174-
}
124+
let transport = opt.common.build_transport_config(
125+
#[cfg(feature = "qlog")]
126+
"perf-client",
127+
)?;
175128

176129
let crypto = Arc::new(QuicClientConfig::try_from(crypto)?);
177-
let mut config = quinn::ClientConfig::new(match opt.no_protection {
130+
let mut config = quinn::ClientConfig::new(match opt.common.no_protection {
178131
true => Arc::new(NoProtectionClientConfig::new(crypto)),
179132
false => crypto,
180133
});
@@ -220,7 +173,7 @@ async fn run(opt: Opt) -> Result<()> {
220173
stats.on_interval(start, &stream_stats);
221174

222175
stats.print();
223-
if opt.conn_stats {
176+
if opt.common.conn_stats {
224177
println!("{:?}\n", connection.stats());
225178
}
226179
}

0 commit comments

Comments
 (0)