Skip to content

Commit dbcdad2

Browse files
committed
upgrade to clap 4.4.x
1 parent 6fbd736 commit dbcdad2

File tree

6 files changed

+215
-299
lines changed

6 files changed

+215
-299
lines changed

Cargo.toml

+8-8
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,17 @@ readme = "README.md"
1212

1313
[dependencies]
1414
chrono = "0.4"
15-
clap = "~2.33.3"
16-
core_affinity = "0.5"
17-
ctrlc = "3.1"
18-
env_logger = "0.8"
19-
log = {version = "0.4", features = ["std"]}
15+
clap = { version = "4.4", features = ["derive", "wrap_help"] }
16+
core_affinity = "0.8"
17+
ctrlc2 = "3.5"
18+
env_logger = "0.10"
19+
log = { version = "0.4", features = ["std"] }
2020
mio = "0.6"
2121
nix = "0.20"
22-
serde = {version = "1.0", features = ["derive"]}
22+
serde = { version = "1.0", features = ["derive"] }
2323
serde_json = "1.0"
24-
simple-error = "0.2"
25-
uuid = {version = "0.8", features = ["v4"]}
24+
simple-error = "0.3"
25+
uuid = { version = "1.6", features = ["v4"] }
2626

2727
#configuration for cargo-deb
2828
#install with "cargo install cargo-deb"

src/args.rs

+147
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/// rperf, validates network throughput capacity and reliability,
2+
/// https://github.com/opensource-3d-p/rperf
3+
#[derive(clap::Parser, Debug, Clone)]
4+
#[command(author, version, about, long_about = None)]
5+
pub struct Args {
6+
/// the port used for client-server interactions
7+
#[arg(short, long, value_name = "number", default_value_t = 5199)]
8+
pub port: u16,
9+
10+
/// specify logical CPUs, delimited by commas, across which to round-robin affinity;
11+
/// not supported on all systems
12+
#[arg(short = 'A', long, value_name = "number", default_value = "1")]
13+
pub affinity: String,
14+
15+
/// bind to the interface associated with the address <host>
16+
#[arg(
17+
short = 'B',
18+
long,
19+
conflicts_with = "client",
20+
default_value_if("version6", "true", Some("::")),
21+
default_value = "0.0.0.0",
22+
value_name = "host"
23+
)]
24+
pub bind: std::net::IpAddr,
25+
26+
/// emit debug-level logging on stderr; default is info and above
27+
#[arg(short, long)]
28+
pub debug: bool,
29+
30+
/// run in server mode
31+
#[arg(short, long, conflicts_with = "client")]
32+
pub server: bool,
33+
34+
/// enable IPv6 on the server (on most hosts, this will allow both IPv4 and IPv6,
35+
/// but it might limit to just IPv6 on some)
36+
#[arg(short = '6', long)]
37+
pub version6: bool,
38+
39+
/// limit the number of concurrent clients that can be processed by a server;
40+
/// any over this count will be immediately disconnected
41+
#[arg(long, value_name = "number", default_value = "0")]
42+
pub client_limit: usize,
43+
44+
/// run in client mode; value is the server's address
45+
#[arg(short, long, value_name = "host", conflicts_with = "server")]
46+
pub client: Option<std::net::IpAddr>,
47+
48+
/// run in reverse-mode (server sends, client receives)
49+
#[arg(short = 'R', long)]
50+
pub reverse: bool,
51+
52+
/// the format in which to deplay information (json, megabit/sec, megabyte/sec)
53+
#[arg(
54+
short,
55+
long,
56+
value_enum,
57+
value_name = "format",
58+
default_value = "megabit"
59+
)]
60+
pub format: Format,
61+
62+
/// use UDP rather than TCP
63+
#[arg(short, long)]
64+
pub udp: bool,
65+
66+
/// target bandwidth in bytes/sec; this value is applied to each stream,
67+
/// with a default target of 1 megabit/second for all protocols (note: megabit, not mebibit);
68+
/// the suffixes kKmMgG can also be used for xbit and xbyte, respectively
69+
#[arg(short, long, default_value = "125000", value_name = "bytes/sec")]
70+
pub bandwidth: String,
71+
72+
/// the time in seconds for which to transmit
73+
#[arg(short, long, default_value = "10.0", value_name = "seconds")]
74+
pub time: f64,
75+
76+
/// the interval at which to send batches of data, in seconds, between [0.0 and 1.0);
77+
/// this is used to evenly spread packets out over time
78+
#[arg(long, default_value = "0.05", value_name = "seconds")]
79+
pub send_interval: f64,
80+
81+
/// length of the buffer to exchange; for TCP, this defaults to 32 kibibytes; for UDP, it's 1024 bytes
82+
#[arg(short, long, default_value = "32768", value_name = "bytes")]
83+
pub length: usize,
84+
85+
/// send buffer, in bytes (only supported on some platforms;
86+
/// if set too small, a 'resource unavailable' error may occur;
87+
/// affects TCP window-size)
88+
#[arg(long, default_value = "0", value_name = "bytes")]
89+
pub send_buffer: usize,
90+
91+
/// receive buffer, in bytes (only supported on some platforms;
92+
/// if set too small, a 'resource unavailable' error may occur; affects TCP window-size)
93+
#[arg(long, default_value = "0", value_name = "bytes")]
94+
pub receive_buffer: usize,
95+
96+
/// the number of parallel data-streams to use
97+
#[arg(short = 'P', long, value_name = "number", default_value = "1")]
98+
pub parallel: usize,
99+
100+
/// omit a number of seconds from the start of calculations,
101+
/// primarily to avoid including TCP ramp-up in averages;
102+
/// using this option may result in disagreement between bytes sent and received,
103+
/// since data can be in-flight across time-boundaries
104+
#[arg(short, long, default_value = "0", value_name = "seconds")]
105+
pub omit: usize,
106+
107+
/// use no-delay mode for TCP tests, disabling Nagle's Algorithm
108+
#[arg(short = 'N', long)]
109+
pub no_delay: bool,
110+
111+
/// an optional pool of IPv4 TCP ports over which data will be accepted;
112+
/// if omitted, any OS-assignable port is used; format: 1-10,19,21
113+
#[arg(long, value_name = "ports", default_value = "")]
114+
pub tcp_port_pool: String,
115+
116+
/// an optional pool of IPv6 TCP ports over which data will be accepted;
117+
/// if omitted, any OS-assignable port is used; format: 1-10,19,21
118+
#[arg(long, value_name = "ports", default_value = "")]
119+
pub tcp6_port_pool: String,
120+
121+
/// an optional pool of IPv4 UDP ports over which data will be accepted;
122+
/// if omitted, any OS-assignable port is used; format: 1-10,19,21
123+
#[arg(long, value_name = "ports", default_value = "")]
124+
pub udp_port_pool: String,
125+
126+
/// an optional pool of IPv6 UDP ports over which data will be accepted;
127+
/// if omitted, any OS-assignable port is used; format: 1-10,19,21
128+
#[arg(long, value_name = "ports", default_value = "")]
129+
pub udp6_port_pool: String,
130+
}
131+
132+
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, clap::ValueEnum)]
133+
pub enum Format {
134+
Json,
135+
Megabit,
136+
Megabyte,
137+
}
138+
139+
impl std::fmt::Display for Format {
140+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
141+
match self {
142+
Format::Json => write!(f, "json"),
143+
Format::Megabit => write!(f, "megabit/sec"),
144+
Format::Megabyte => write!(f, "megabyte/sec"),
145+
}
146+
}
147+
}

src/client.rs

+18-27
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,9 @@ use std::sync::{Arc, Mutex};
2525
use std::thread;
2626
use std::time::{Duration, SystemTime, UNIX_EPOCH};
2727

28-
use clap::ArgMatches;
29-
3028
use mio::net::TcpStream;
3129

30+
use crate::args;
3231
use crate::protocol::communication::{receive, send, KEEPALIVE_DURATION};
3332

3433
use crate::protocol::messaging::{
@@ -115,56 +114,48 @@ fn prepare_test_results(is_udp: bool, stream_count: u8) -> Mutex<Box<dyn TestRes
115114
}
116115
}
117116

118-
pub fn execute(args: ArgMatches) -> BoxResult<()> {
117+
pub fn execute(args: &args::Args) -> BoxResult<()> {
119118
let mut complete = false;
120119

121120
//config-parsing and pre-connection setup
122121
let mut tcp_port_pool = tcp::receiver::TcpPortPool::new(
123-
args.value_of("tcp_port_pool").unwrap().to_string(),
124-
args.value_of("tcp6_port_pool").unwrap().to_string(),
122+
args.tcp_port_pool.to_string(),
123+
args.tcp6_port_pool.to_string(),
125124
);
126125
let mut udp_port_pool = udp::receiver::UdpPortPool::new(
127-
args.value_of("udp_port_pool").unwrap().to_string(),
128-
args.value_of("udp6_port_pool").unwrap().to_string(),
126+
args.udp_port_pool.to_string(),
127+
args.udp6_port_pool.to_string(),
129128
);
130129

131130
let cpu_affinity_manager = Arc::new(Mutex::new(
132-
crate::utils::cpu_affinity::CpuAffinityManager::new(args.value_of("affinity").unwrap())?,
131+
crate::utils::cpu_affinity::CpuAffinityManager::new(&args.affinity)?,
133132
));
134133

135134
let display_json: bool;
136135
let display_bit: bool;
137-
match args.value_of("format").unwrap() {
138-
"json" => {
136+
match args.format {
137+
args::Format::Json => {
139138
display_json = true;
140139
display_bit = false;
141140
}
142-
"megabit" => {
141+
args::Format::Megabit => {
143142
display_json = false;
144143
display_bit = true;
145144
}
146-
"megabyte" => {
145+
args::Format::Megabyte => {
147146
display_json = false;
148147
display_bit = false;
149148
}
150-
_ => {
151-
log::error!("unsupported display-mode; defaulting to JSON");
152-
display_json = true;
153-
display_bit = false;
154-
}
155149
}
156150

157-
let is_udp = args.is_present("udp");
151+
let is_udp = args.udp;
158152

159153
let test_id = uuid::Uuid::new_v4();
160-
let mut upload_config = prepare_upload_configuration(&args, test_id.as_bytes())?;
161-
let mut download_config = prepare_download_configuration(&args, test_id.as_bytes())?;
154+
let mut upload_config = prepare_upload_configuration(args, test_id.as_bytes())?;
155+
let mut download_config = prepare_download_configuration(args, test_id.as_bytes())?;
162156

163157
//connect to the server
164-
let mut stream = connect_to_server(
165-
args.value_of("client").unwrap(),
166-
&(args.value_of("port").unwrap().parse()?),
167-
)?;
158+
let mut stream = connect_to_server(&args.client.unwrap().to_string(), &args.port)?;
168159
let server_addr = stream.peer_addr()?;
169160

170161
//scaffolding to track and relay the streams and stream-results associated with this test
@@ -224,7 +215,7 @@ pub fn execute(args: ArgMatches) -> BoxResult<()> {
224215
};
225216

226217
//depending on whether this is a forward- or reverse-test, the order of configuring test-streams will differ
227-
if args.is_present("reverse") {
218+
if args.reverse {
228219
log::debug!("running in reverse-mode: server will be uploading data");
229220

230221
//when we're receiving data, we're also responsible for letting the server know where to send it
@@ -559,7 +550,7 @@ pub fn execute(args: ArgMatches) -> BoxResult<()> {
559550
}
560551

561552
log::debug!("displaying test results");
562-
let omit_seconds: usize = args.value_of("omit").unwrap().parse()?;
553+
let omit_seconds: usize = args.omit;
563554
{
564555
let tr = test_results.lock().unwrap();
565556
if display_json {
@@ -576,7 +567,7 @@ pub fn execute(args: ArgMatches) -> BoxResult<()> {
576567
IpAddr::V4(_) => 4,
577568
IpAddr::V6(_) => 6,
578569
},
579-
"reverse": args.is_present("reverse"),
570+
"reverse": args.reverse,
580571
})
581572
)
582573
);

0 commit comments

Comments
 (0)