|
| 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 | +} |
0 commit comments