Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code formating and refine #4

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Rust

on:
[push, pull_request]

env:
CARGO_TERM_COLOR: always

jobs:
build:
strategy:
matrix:
host_os:
- ubuntu-latest
- macos-latest
- windows-latest

runs-on: ${{ matrix.host_os }}

steps:
- uses: actions/checkout@v3
- name: check
run: cargo check
- name: rustfmt
run: |
rustc --version
cargo fmt --all -- --check
- name: clippy
run: cargo clippy -- -D warnings
- name: Build
run: cargo build --verbose --all-features --tests --examples
- name: Run tests
run: cargo test --verbose
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.vscode/
.VSCodeCounter/
build/
tmp/
Cargo.lock
target/
20 changes: 10 additions & 10 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"]}
mio = "0.6"
nix = "0.20"
serde = {version = "1.0", features = ["derive"]}
clap = { version = "4.4", features = ["derive", "wrap_help"] }
core_affinity = "0.8"
ctrlc2 = { version = "3.5", features = ["termination"] }
env_logger = "0.10"
log = { version = "0.4", features = ["std"] }
mio = { version = "0.8", features = ["log", "os-poll", "net"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
simple-error = "0.2"
uuid = {version = "0.8", features = ["v4"]}
simple-error = "0.3"
socket2 = { version = "0.5", features = ["all"] }
uuid = { version = "1.6", features = ["v4"] }

#configuration for cargo-deb
#install with "cargo install cargo-deb"
Expand Down
1 change: 1 addition & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
max_width = 140
184 changes: 184 additions & 0 deletions src/args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/// 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 = "numbers", default_value = "")]
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, conflicts_with = "client")]
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", conflicts_with = "client")]
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<String>,

/// run in reverse-mode (server sends, client receives)
#[arg(short = 'R', long, conflicts_with = "server")]
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",
conflicts_with = "server"
)]
pub format: Format,

/// use UDP rather than TCP
#[arg(short, long, conflicts_with = "server")]
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", conflicts_with = "server")]
pub bandwidth: String,

/// the time in seconds for which to transmit
#[arg(short, long, default_value = "10.0", value_name = "seconds", conflicts_with = "server")]
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", conflicts_with = "server")]
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,
conflicts_with = "server",
default_value = "32768",
default_value_if("udp", "true", Some("1024")),
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 UDP and TCP window-size)
#[arg(long, default_value = "0", value_name = "bytes", conflicts_with = "server")]
pub send_buffer: usize,

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

/// the number of parallel data-streams to use
#[arg(short = 'P', long, value_name = "number", default_value = "1", conflicts_with = "server")]
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 = 'O', long, default_value = "0", value_name = "seconds", conflicts_with = "server")]
pub omit: usize,

/// use no-delay mode for TCP tests, disabling Nagle's Algorithm
#[arg(short = 'N', long, conflicts_with = "server")]
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,

/// Verbosity level
#[arg(short, long, value_name = "level", value_enum, default_value = "info")]
pub verbosity: ArgVerbosity,
}

#[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"),
}
}
}

#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, clap::ValueEnum)]
pub enum ArgVerbosity {
Off,
Error,
Warn,
#[default]
Info,
Debug,
Trace,
}

impl std::fmt::Display for ArgVerbosity {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ArgVerbosity::Off => write!(f, "off"),
ArgVerbosity::Error => write!(f, "error"),
ArgVerbosity::Warn => write!(f, "warn"),
ArgVerbosity::Info => write!(f, "info"),
ArgVerbosity::Debug => write!(f, "debug"),
ArgVerbosity::Trace => write!(f, "trace"),
}
}
}
Loading