rperf3/config.rs
1use serde::{Deserialize, Serialize};
2use std::net::IpAddr;
3use std::time::Duration;
4
5/// Transport protocol type for network testing.
6///
7/// Specifies whether to use TCP or UDP for the performance test.
8///
9/// # Examples
10///
11/// ```
12/// use rperf3::{Config, Protocol};
13/// use std::time::Duration;
14///
15/// // TCP test
16/// let tcp_config = Config::client("127.0.0.1".to_string(), 5201)
17/// .with_protocol(Protocol::Tcp);
18///
19/// // UDP test with bandwidth limit
20/// let udp_config = Config::client("127.0.0.1".to_string(), 5201)
21/// .with_protocol(Protocol::Udp)
22/// .with_bandwidth(100_000_000); // 100 Mbps
23/// ```
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
25pub enum Protocol {
26 /// Transmission Control Protocol - provides reliable, ordered delivery
27 Tcp,
28 /// User Datagram Protocol - provides best-effort delivery with lower overhead
29 Udp,
30}
31
32impl Protocol {
33 /// Returns the protocol name as a static string.
34 ///
35 /// This avoids memory allocation when converting protocol to string,
36 /// providing a performance optimization over `format!("{:?}", protocol)`.
37 ///
38 /// # Returns
39 ///
40 /// A static string slice containing the protocol name.
41 ///
42 /// # Examples
43 ///
44 /// ```
45 /// use rperf3::Protocol;
46 ///
47 /// assert_eq!(Protocol::Tcp.as_str(), "Tcp");
48 /// assert_eq!(Protocol::Udp.as_str(), "Udp");
49 /// ```
50 pub const fn as_str(self) -> &'static str {
51 match self {
52 Protocol::Tcp => "Tcp",
53 Protocol::Udp => "Udp",
54 }
55 }
56}
57
58/// Test mode: client or server.
59///
60/// Determines whether this instance acts as a server (listening for connections)
61/// or as a client (initiating connections to a server).
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
63pub enum Mode {
64 /// Server mode - listens for incoming connections
65 Server,
66 /// Client mode - connects to a server and initiates tests
67 Client,
68}
69
70/// Configuration for rperf3 network performance tests.
71///
72/// This structure holds all configuration parameters for both client and server modes.
73/// Use the builder pattern methods to customize the configuration.
74///
75/// # Examples
76///
77/// ## Basic TCP Client
78///
79/// ```
80/// use rperf3::Config;
81/// use std::time::Duration;
82///
83/// let config = Config::client("192.168.1.100".to_string(), 5201)
84/// .with_duration(Duration::from_secs(30))
85/// .with_buffer_size(256 * 1024); // 256 KB buffer
86/// ```
87///
88/// ## UDP Client with Bandwidth Limit
89///
90/// ```
91/// use rperf3::{Config, Protocol};
92/// use std::time::Duration;
93///
94/// let config = Config::client("192.168.1.100".to_string(), 5201)
95/// .with_protocol(Protocol::Udp)
96/// .with_bandwidth(100_000_000) // 100 Mbps
97/// .with_duration(Duration::from_secs(10));
98/// ```
99///
100/// ## Server Configuration
101///
102/// ```
103/// use rperf3::Config;
104///
105/// let config = Config::server(5201);
106/// ```
107///
108/// ## Reverse Mode Test
109///
110/// ```
111/// use rperf3::Config;
112/// use std::time::Duration;
113///
114/// // Server sends data, client receives
115/// let config = Config::client("192.168.1.100".to_string(), 5201)
116/// .with_reverse(true)
117/// .with_duration(Duration::from_secs(10));
118/// ```
119#[derive(Debug, Clone, Serialize, Deserialize)]
120pub struct Config {
121 /// Server mode or client mode
122 pub mode: Mode,
123
124 /// Protocol to use (TCP or UDP)
125 pub protocol: Protocol,
126
127 /// Port number to use
128 pub port: u16,
129
130 /// Server address (for client mode)
131 pub server_addr: Option<String>,
132
133 /// Bind address (for server mode)
134 pub bind_addr: Option<IpAddr>,
135
136 /// Test duration in seconds
137 pub duration: Duration,
138
139 /// Target bandwidth in bits per second (for UDP)
140 pub bandwidth: Option<u64>,
141
142 /// Buffer size in bytes
143 pub buffer_size: usize,
144
145 /// Number of parallel streams
146 pub parallel: usize,
147
148 /// Reverse mode (server sends, client receives)
149 pub reverse: bool,
150
151 /// Output in JSON format
152 pub json: bool,
153
154 /// Interval for periodic bandwidth reports in seconds
155 pub interval: Duration,
156}
157
158impl Default for Config {
159 fn default() -> Self {
160 Self {
161 mode: Mode::Client,
162 protocol: Protocol::Tcp,
163 port: 5201,
164 server_addr: None,
165 bind_addr: None,
166 duration: Duration::from_secs(10),
167 bandwidth: None,
168 buffer_size: 128 * 1024, // 128 KB
169 parallel: 1,
170 reverse: false,
171 json: false,
172 interval: Duration::from_secs(1),
173 }
174 }
175}
176
177impl Config {
178 /// Creates a new configuration with default values.
179 ///
180 /// This is equivalent to calling `Config::default()`. The default configuration
181 /// is set up for client mode with TCP protocol.
182 ///
183 /// # Examples
184 ///
185 /// ```
186 /// use rperf3::Config;
187 ///
188 /// let config = Config::new();
189 /// assert_eq!(config.port, 5201);
190 /// ```
191 pub fn new() -> Self {
192 Self::default()
193 }
194
195 /// Creates a new server configuration.
196 ///
197 /// Sets up the configuration for server mode, which listens for incoming
198 /// connections on the specified port.
199 ///
200 /// # Arguments
201 ///
202 /// * `port` - The port number to listen on (typically 5201)
203 ///
204 /// # Examples
205 ///
206 /// ```
207 /// use rperf3::Config;
208 ///
209 /// let config = Config::server(5201);
210 /// ```
211 pub fn server(port: u16) -> Self {
212 Self {
213 mode: Mode::Server,
214 port,
215 ..Default::default()
216 }
217 }
218
219 /// Creates a new client configuration.
220 ///
221 /// Sets up the configuration for client mode, which connects to a server
222 /// at the specified address and port.
223 ///
224 /// # Arguments
225 ///
226 /// * `server_addr` - The IP address or hostname of the server
227 /// * `port` - The port number to connect to (typically 5201)
228 ///
229 /// # Examples
230 ///
231 /// ```
232 /// use rperf3::Config;
233 ///
234 /// let config = Config::client("192.168.1.100".to_string(), 5201);
235 /// ```
236 pub fn client(server_addr: String, port: u16) -> Self {
237 Self {
238 mode: Mode::Client,
239 server_addr: Some(server_addr),
240 port,
241 ..Default::default()
242 }
243 }
244
245 /// Sets the protocol to use for the test.
246 ///
247 /// # Arguments
248 ///
249 /// * `protocol` - Either `Protocol::Tcp` or `Protocol::Udp`
250 ///
251 /// # Examples
252 ///
253 /// ```
254 /// use rperf3::{Config, Protocol};
255 ///
256 /// let config = Config::client("127.0.0.1".to_string(), 5201)
257 /// .with_protocol(Protocol::Udp);
258 /// ```
259 pub fn with_protocol(mut self, protocol: Protocol) -> Self {
260 self.protocol = protocol;
261 self
262 }
263
264 /// Sets the test duration.
265 ///
266 /// # Arguments
267 ///
268 /// * `duration` - How long the test should run
269 ///
270 /// # Examples
271 ///
272 /// ```
273 /// use rperf3::Config;
274 /// use std::time::Duration;
275 ///
276 /// let config = Config::client("127.0.0.1".to_string(), 5201)
277 /// .with_duration(Duration::from_secs(30));
278 /// ```
279 pub fn with_duration(mut self, duration: Duration) -> Self {
280 self.duration = duration;
281 self
282 }
283
284 /// Sets the target bandwidth for tests.
285 ///
286 /// Controls the send rate for both TCP and UDP tests. The bandwidth limiter
287 /// uses a rate-based algorithm that checks bandwidth every 1ms and sleeps
288 /// when sending too fast.
289 ///
290 /// # Arguments
291 ///
292 /// * `bandwidth` - Target bandwidth in bits per second
293 ///
294 /// # Examples
295 ///
296 /// ```
297 /// use rperf3::{Config, Protocol};
298 ///
299 /// // UDP test at 100 Mbps
300 /// let udp_config = Config::client("127.0.0.1".to_string(), 5201)
301 /// .with_protocol(Protocol::Udp)
302 /// .with_bandwidth(100_000_000); // 100 Mbps
303 ///
304 /// // TCP test at 50 Mbps
305 /// let tcp_config = Config::client("127.0.0.1".to_string(), 5201)
306 /// .with_protocol(Protocol::Tcp)
307 /// .with_bandwidth(50_000_000); // 50 Mbps
308 /// ```
309 pub fn with_bandwidth(mut self, bandwidth: u64) -> Self {
310 self.bandwidth = Some(bandwidth);
311 self
312 }
313
314 /// Sets the buffer size for data transfer.
315 ///
316 /// Larger buffer sizes can improve throughput but use more memory.
317 ///
318 /// # Arguments
319 ///
320 /// * `size` - Buffer size in bytes (default: 128 KB)
321 ///
322 /// # Examples
323 ///
324 /// ```
325 /// use rperf3::Config;
326 ///
327 /// let config = Config::client("127.0.0.1".to_string(), 5201)
328 /// .with_buffer_size(256 * 1024); // 256 KB
329 /// ```
330 pub fn with_buffer_size(mut self, size: usize) -> Self {
331 self.buffer_size = size;
332 self
333 }
334
335 /// Sets the number of parallel streams.
336 ///
337 /// Multiple parallel streams can improve throughput by utilizing multiple
338 /// connections simultaneously. This is particularly useful for high-bandwidth
339 /// networks where a single stream might not saturate the link.
340 ///
341 /// # Arguments
342 ///
343 /// * `parallel` - Number of parallel streams (default: 1)
344 ///
345 /// # Examples
346 ///
347 /// ```
348 /// use rperf3::Config;
349 ///
350 /// let config = Config::client("127.0.0.1".to_string(), 5201)
351 /// .with_parallel(4); // Use 4 parallel streams
352 /// ```
353 pub fn with_parallel(mut self, parallel: usize) -> Self {
354 self.parallel = parallel;
355 self
356 }
357
358 /// Enables or disables reverse mode.
359 ///
360 /// In reverse mode, the server sends data and the client receives.
361 /// In normal mode, the client sends data and the server receives.
362 ///
363 /// # Arguments
364 ///
365 /// * `reverse` - `true` for reverse mode, `false` for normal mode
366 ///
367 /// # Examples
368 ///
369 /// ```
370 /// use rperf3::Config;
371 ///
372 /// let config = Config::client("127.0.0.1".to_string(), 5201)
373 /// .with_reverse(true);
374 /// ```
375 pub fn with_reverse(mut self, reverse: bool) -> Self {
376 self.reverse = reverse;
377 self
378 }
379
380 /// Enables or disables JSON output format.
381 ///
382 /// When enabled, results are output in machine-readable JSON format
383 /// similar to iperf3.
384 ///
385 /// # Arguments
386 ///
387 /// * `json` - `true` to enable JSON output, `false` for human-readable
388 ///
389 /// # Examples
390 ///
391 /// ```
392 /// use rperf3::Config;
393 ///
394 /// let config = Config::client("127.0.0.1".to_string(), 5201)
395 /// .with_json(true);
396 /// ```
397 pub fn with_json(mut self, json: bool) -> Self {
398 self.json = json;
399 self
400 }
401
402 /// Sets the interval for periodic reporting.
403 ///
404 /// Statistics will be reported at this interval during the test.
405 ///
406 /// # Arguments
407 ///
408 /// * `interval` - How often to report statistics (default: 1 second)
409 ///
410 /// # Examples
411 ///
412 /// ```
413 /// use rperf3::Config;
414 /// use std::time::Duration;
415 ///
416 /// let config = Config::client("127.0.0.1".to_string(), 5201)
417 /// .with_interval(Duration::from_secs(2));
418 /// ```
419 pub fn with_interval(mut self, interval: Duration) -> Self {
420 self.interval = interval;
421 self
422 }
423}