Skip to content

Commit

Permalink
upgrade to clap 4.4.x
Browse files Browse the repository at this point in the history
  • Loading branch information
ssrlive committed Dec 17, 2023
1 parent 6fbd736 commit 75bcfbb
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 299 deletions.
16 changes: 8 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ readme = "README.md"

[dependencies]
chrono = "0.4"
clap = "~2.33.3"
core_affinity = "0.5"
ctrlc = "3.1"
env_logger = "0.8"
log = {version = "0.4", features = ["std"]}
clap = { version = "4.4", features = ["derive", "wrap_help"] }
core_affinity = "0.8"
ctrlc2 = "3.5"
env_logger = "0.10"
log = { version = "0.4", features = ["std"] }
mio = "0.6"
nix = "0.20"
serde = {version = "1.0", features = ["derive"]}
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
simple-error = "0.2"
uuid = {version = "0.8", features = ["v4"]}
simple-error = "0.3"
uuid = { version = "1.6", features = ["v4"] }

#configuration for cargo-deb
#install with "cargo install cargo-deb"
Expand Down
148 changes: 148 additions & 0 deletions src/args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/// rperf, validates network throughput capacity and reliability,
/// https://github.com/opensource-3d-p/rperf
#[derive(clap::Parser, Debug, Clone)]
#[command(author, version, about, long_about = None)]
pub struct Args {
/// the port used for client-server interactions
#[arg(short, long, value_name = "number", default_value_t = 5199)]
pub port: u16,

/// specify logical CPUs, delimited by commas, across which to round-robin affinity;
/// not supported on all systems
#[arg(short = 'A', long, value_name = "number", default_value = "1")]
pub affinity: String,

/// bind to the interface associated with the address <host>
#[arg(
short = 'B',
long,
conflicts_with = "client",
default_value_if("version6", "true", Some("::")),
default_value = "0.0.0.0",
value_name = "host"
)]
pub bind: std::net::IpAddr,

/// emit debug-level logging on stderr; default is info and above
#[arg(short, long)]
pub debug: bool,

/// run in server mode
#[arg(short, long, conflicts_with = "client")]
pub server: bool,

/// enable IPv6 on the server (on most hosts, this will allow both IPv4 and IPv6,
/// but it might limit to just IPv6 on some)
#[arg(short = '6', long)]
pub version6: bool,

/// limit the number of concurrent clients that can be processed by a server;
/// any over this count will be immediately disconnected
#[arg(long, value_name = "number", default_value = "0")]
pub client_limit: usize,

/// run in client mode; value is the server's address
#[arg(short, long, value_name = "host", conflicts_with = "server")]
pub client: Option<std::net::IpAddr>,

/// run in reverse-mode (server sends, client receives)
#[arg(short = 'R', long)]
pub reverse: bool,

/// the format in which to deplay information (json, megabit/sec, megabyte/sec)
#[arg(
short,
long,
value_enum,
value_name = "format",
default_value = "megabit"
)]
pub format: Format,

/// use UDP rather than TCP
#[arg(short, long)]
pub udp: bool,

/// target bandwidth in bytes/sec; this value is applied to each stream,
/// with a default target of 1 megabit/second for all protocols (note: megabit, not mebibit);
/// the suffixes kKmMgG can also be used for xbit and xbyte, respectively
#[arg(short, long, default_value = "125000", value_name = "bytes/sec")]
pub bandwidth: String,

/// the time in seconds for which to transmit
#[arg(short, long, default_value = "10.0", value_name = "seconds")]
pub time: f64,

/// the interval at which to send batches of data, in seconds, between [0.0 and 1.0);
/// this is used to evenly spread packets out over time
#[arg(long, default_value = "0.05", value_name = "seconds")]
pub send_interval: f64,

/// length of the buffer to exchange; for TCP, this defaults to 32 kibibytes; for UDP, it's 1024 bytes
#[arg(short, long, default_value = "32768", value_name = "bytes")]
pub length: usize,

/// send buffer, in bytes (only supported on some platforms;
/// if set too small, a 'resource unavailable' error may occur;
/// affects TCP window-size)
#[arg(long, default_value = "0", value_name = "bytes")]
pub send_buffer: usize,

/// receive buffer, in bytes (only supported on some platforms;
/// if set too small, a 'resource unavailable' error may occur; affects TCP window-size)
#[arg(long, default_value = "0", value_name = "bytes")]
pub receive_buffer: usize,

/// the number of parallel data-streams to use
#[arg(short = 'P', long, value_name = "number", default_value = "1")]
pub parallel: usize,

/// omit a number of seconds from the start of calculations,
/// primarily to avoid including TCP ramp-up in averages;
/// using this option may result in disagreement between bytes sent and received,
/// since data can be in-flight across time-boundaries
#[arg(short, long, default_value = "0", value_name = "seconds")]
pub omit: usize,

/// use no-delay mode for TCP tests, disabling Nagle's Algorithm
#[arg(short = 'N', long)]
pub no_delay: bool,

/// an optional pool of IPv4 TCP ports over which data will be accepted;
/// if omitted, any OS-assignable port is used; format: 1-10,19,21
#[arg(long, value_name = "ports", default_value = "")]
pub tcp_port_pool: String,

/// an optional pool of IPv6 TCP ports over which data will be accepted;
/// if omitted, any OS-assignable port is used; format: 1-10,19,21
#[arg(long, value_name = "ports", default_value = "")]
pub tcp6_port_pool: String,

/// an optional pool of IPv4 UDP ports over which data will be accepted;
/// if omitted, any OS-assignable port is used; format: 1-10,19,21
#[arg(long, value_name = "ports", default_value = "")]
pub udp_port_pool: String,

/// an optional pool of IPv6 UDP ports over which data will be accepted;
/// if omitted, any OS-assignable port is used; format: 1-10,19,21
#[arg(long, value_name = "ports", default_value = "")]
pub udp6_port_pool: String,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, clap::ValueEnum, Default)]
pub enum Format {
#[default]
Json,
Megabit,
Megabyte,
}

impl std::fmt::Display for Format {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Format::Json => write!(f, "json"),
Format::Megabit => write!(f, "megabit/sec"),
Format::Megabyte => write!(f, "megabyte/sec"),
}
}
}
45 changes: 18 additions & 27 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,9 @@ use std::sync::{Arc, Mutex};
use std::thread;
use std::time::{Duration, SystemTime, UNIX_EPOCH};

use clap::ArgMatches;

use mio::net::TcpStream;

use crate::args;
use crate::protocol::communication::{receive, send, KEEPALIVE_DURATION};

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

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

//config-parsing and pre-connection setup
let mut tcp_port_pool = tcp::receiver::TcpPortPool::new(
args.value_of("tcp_port_pool").unwrap().to_string(),
args.value_of("tcp6_port_pool").unwrap().to_string(),
args.tcp_port_pool.to_string(),
args.tcp6_port_pool.to_string(),
);
let mut udp_port_pool = udp::receiver::UdpPortPool::new(
args.value_of("udp_port_pool").unwrap().to_string(),
args.value_of("udp6_port_pool").unwrap().to_string(),
args.udp_port_pool.to_string(),
args.udp6_port_pool.to_string(),
);

let cpu_affinity_manager = Arc::new(Mutex::new(
crate::utils::cpu_affinity::CpuAffinityManager::new(args.value_of("affinity").unwrap())?,
crate::utils::cpu_affinity::CpuAffinityManager::new(&args.affinity)?,
));

let display_json: bool;
let display_bit: bool;
match args.value_of("format").unwrap() {
"json" => {
match args.format {
args::Format::Json => {
display_json = true;
display_bit = false;
}
"megabit" => {
args::Format::Megabit => {
display_json = false;
display_bit = true;
}
"megabyte" => {
args::Format::Megabyte => {
display_json = false;
display_bit = false;
}
_ => {
log::error!("unsupported display-mode; defaulting to JSON");
display_json = true;
display_bit = false;
}
}

let is_udp = args.is_present("udp");
let is_udp = args.udp;

let test_id = uuid::Uuid::new_v4();
let mut upload_config = prepare_upload_configuration(&args, test_id.as_bytes())?;
let mut download_config = prepare_download_configuration(&args, test_id.as_bytes())?;
let mut upload_config = prepare_upload_configuration(args, test_id.as_bytes())?;
let mut download_config = prepare_download_configuration(args, test_id.as_bytes())?;

//connect to the server
let mut stream = connect_to_server(
args.value_of("client").unwrap(),
&(args.value_of("port").unwrap().parse()?),
)?;
let mut stream = connect_to_server(&args.client.unwrap().to_string(), &args.port)?;
let server_addr = stream.peer_addr()?;

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

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

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

log::debug!("displaying test results");
let omit_seconds: usize = args.value_of("omit").unwrap().parse()?;
let omit_seconds: usize = args.omit;
{
let tr = test_results.lock().unwrap();
if display_json {
Expand All @@ -576,7 +567,7 @@ pub fn execute(args: ArgMatches) -> BoxResult<()> {
IpAddr::V4(_) => 4,
IpAddr::V6(_) => 6,
},
"reverse": args.is_present("reverse"),
"reverse": args.reverse,
})
)
);
Expand Down
Loading

0 comments on commit 75bcfbb

Please sign in to comment.