safer_ring/advanced/config.rs
1//! Advanced configuration for io_uring operations.
2
3/// Advanced features configuration for io_uring operations.
4///
5/// Enables configuration of advanced io_uring features that may not be
6/// available on all kernel versions. Features are disabled by default
7/// to ensure compatibility. Use the provided constructors and methods
8/// to create configurations suitable for your use case.
9///
10/// # Examples
11///
12/// ```rust
13/// use safer_ring::advanced::AdvancedConfig;
14///
15/// // Create a conservative configuration (all features disabled)
16/// let conservative = AdvancedConfig::default();
17///
18/// // Create a configuration with basic stable features
19/// let basic = AdvancedConfig::stable();
20///
21/// // Create a performance-optimized configuration
22/// let performance = AdvancedConfig::performance();
23///
24/// // Enable specific features
25/// let custom = AdvancedConfig::default()
26/// .with_buffer_selection(true)
27/// .with_multi_shot(true)
28/// .with_fast_poll(true);
29/// ```
30///
31/// # Feature Categories
32///
33/// Features are grouped by kernel version:
34/// - **Legacy** (5.1-5.19): Basic io_uring features
35/// - **6.1+**: Advanced task management
36/// - **6.2+**: Zero-copy optimizations and batching
37/// - **6.3-6.5**: Enhanced resource management
38/// - **6.6+**: Performance and cancellation improvements
39/// - **6.11-6.12**: Latest optimizations
40///
41/// # Safety and Compatibility
42///
43/// Some features may have stability or performance implications:
44/// - `sq_poll`: High CPU usage, use with caution
45/// - `defer_async_work`: Requires careful application integration
46/// - `user_allocated_ring_memory`: Requires custom memory management
47///
48/// Use `validate()` to check feature compatibility before use.
49#[derive(Debug, Clone, Default)]
50pub struct AdvancedConfig {
51 /// Enable buffer selection for read operations
52 pub buffer_selection: bool,
53 /// Enable multi-shot operations where supported
54 pub multi_shot: bool,
55 /// Enable provided buffers for zero-copy operations
56 pub provided_buffers: bool,
57 /// Enable fast poll for network operations
58 pub fast_poll: bool,
59 /// Enable submission queue polling
60 pub sq_poll: bool,
61 /// Enable io_uring kernel thread affinity
62 pub sq_thread_cpu: Option<u32>,
63 /// Enable cooperative task running
64 pub coop_taskrun: bool,
65 /// Enable task work defer
66 pub defer_taskrun: bool,
67
68 // Kernel 6.1+ features
69 /// Enable advanced task work management (6.1+)
70 pub advanced_task_work: bool,
71 /// Enable deferred async work until GETEVENTS (6.1+)
72 pub defer_async_work: bool,
73
74 // Kernel 6.2+ features
75 /// Enable zero-copy send reporting (6.2+)
76 pub send_zc_reporting: bool,
77 /// Enable completion batching for multishot operations (6.2+)
78 pub multishot_completion_batching: bool,
79 /// Enable EPOLL_URING_WAKE support (6.2+)
80 pub epoll_uring_wake: bool,
81
82 // Kernel 6.3+ features
83 /// Enable io_uring_register() with registered ring fd (6.3+)
84 pub registered_ring_fd: bool,
85
86 // Kernel 6.4+ features
87 /// Enable multishot timeout operations (6.4+)
88 pub multishot_timeouts: bool,
89
90 // Kernel 6.5+ features
91 /// Enable user-allocated ring memory (6.5+)
92 pub user_allocated_ring_memory: bool,
93
94 // Kernel 6.6+ features
95 /// Enable async operation cancellation (6.6+)
96 pub async_cancel_op: bool,
97 /// Enable socket command support (6.6+)
98 pub socket_command_support: bool,
99 /// Enable Direct I/O performance optimizations (6.6+)
100 pub direct_io_optimizations: bool,
101
102 // Kernel 6.11+ features
103 /// Enable MSG_RING performance improvements (6.11+)
104 pub msg_ring_speedup: bool,
105 /// Enable native bind/listen operations (6.11+)
106 pub native_bind_listen: bool,
107
108 // Kernel 6.12+ features
109 /// Enable improved huge page handling (6.12+)
110 pub improved_huge_pages: bool,
111 /// Enable async discard operations (6.12+)
112 pub async_discard: bool,
113 /// Enable minimum timeout waits (6.12+)
114 pub minimum_timeout_waits: bool,
115 /// Enable absolute timeouts with multiple clock sources (6.12+)
116 pub absolute_timeouts: bool,
117 /// Enable incremental buffer consumption (6.12+)
118 pub incremental_buffer_consumption: bool,
119 /// Enable registered buffer cloning (6.12+)
120 pub registered_buffer_cloning: bool,
121}
122
123impl AdvancedConfig {
124 /// Create a new AdvancedConfig with all features disabled.
125 ///
126 /// This is equivalent to `AdvancedConfig::default()` but more explicit.
127 /// Provides maximum compatibility across all kernel versions.
128 ///
129 /// # Examples
130 ///
131 /// ```rust
132 /// use safer_ring::advanced::AdvancedConfig;
133 ///
134 /// let config = AdvancedConfig::new();
135 /// assert!(!config.buffer_selection);
136 /// assert!(!config.multi_shot);
137 /// ```
138 pub fn new() -> Self {
139 Self::default()
140 }
141
142 /// Create a configuration with stable, well-tested features enabled.
143 ///
144 /// Enables features that are considered stable and have minimal
145 /// compatibility or performance risks. Suitable for production use
146 /// on kernels 5.13+.
147 ///
148 /// # Examples
149 ///
150 /// ```rust
151 /// use safer_ring::advanced::AdvancedConfig;
152 ///
153 /// let config = AdvancedConfig::stable();
154 /// assert!(config.buffer_selection);
155 /// assert!(config.fast_poll);
156 /// assert!(!config.sq_poll); // Disabled due to CPU usage concerns
157 /// ```
158 pub fn stable() -> Self {
159 Self {
160 // Core stable features (5.13+)
161 buffer_selection: true,
162 fast_poll: true,
163 provided_buffers: true,
164
165 // Task management features (6.0+)
166 coop_taskrun: true,
167 defer_taskrun: true,
168
169 // Keep potentially problematic features disabled
170 sq_poll: false,
171 defer_async_work: false,
172 user_allocated_ring_memory: false,
173
174 ..Self::default()
175 }
176 }
177
178 /// Create a performance-optimized configuration.
179 ///
180 /// Enables features that can improve performance, including some
181 /// that may have higher resource usage. Suitable for high-performance
182 /// applications on modern kernels (6.2+).
183 ///
184 /// # Examples
185 ///
186 /// ```rust
187 /// use safer_ring::advanced::AdvancedConfig;
188 ///
189 /// let config = AdvancedConfig::performance();
190 /// assert!(config.multi_shot);
191 /// assert!(config.advanced_task_work);
192 /// assert!(config.multishot_completion_batching);
193 /// ```
194 pub fn performance() -> Self {
195 Self {
196 // All stable features
197 ..Self::stable()
198 }
199 .with_multi_shot(true)
200 .with_advanced_task_work(true)
201 .with_send_zc_reporting(true)
202 .with_multishot_completion_batching(true)
203 .with_async_cancel_op(true)
204 .with_direct_io_optimizations(true)
205 }
206
207 /// Create a development-friendly configuration.
208 ///
209 /// Enables features that are helpful for development and testing,
210 /// prioritizing debuggability over maximum performance.
211 ///
212 /// # Examples
213 ///
214 /// ```rust
215 /// use safer_ring::advanced::AdvancedConfig;
216 ///
217 /// let config = AdvancedConfig::development();
218 /// assert!(config.buffer_selection);
219 /// assert!(!config.sq_poll); // Disabled for easier debugging
220 /// ```
221 pub fn development() -> Self {
222 Self {
223 // Enable features useful for development
224 buffer_selection: true,
225 multi_shot: true,
226 provided_buffers: true,
227 fast_poll: true,
228 coop_taskrun: true,
229 defer_taskrun: true,
230
231 // Disable features that complicate debugging
232 sq_poll: false,
233 defer_async_work: false,
234
235 ..Self::default()
236 }
237 }
238
239 /// Enable buffer selection feature.
240 ///
241 /// Buffer selection allows the kernel to choose buffers for read operations,
242 /// improving efficiency for workloads with varying buffer sizes.
243 ///
244 /// # Examples
245 ///
246 /// ```rust
247 /// use safer_ring::advanced::AdvancedConfig;
248 ///
249 /// let config = AdvancedConfig::new().with_buffer_selection(true);
250 /// assert!(config.buffer_selection);
251 /// ```
252 pub fn with_buffer_selection(mut self, enabled: bool) -> Self {
253 self.buffer_selection = enabled;
254 self
255 }
256
257 /// Enable multi-shot operations.
258 ///
259 /// Multi-shot operations can handle multiple completions from a single
260 /// submission, reducing system call overhead for operations like accept().
261 pub fn with_multi_shot(mut self, enabled: bool) -> Self {
262 self.multi_shot = enabled;
263 self
264 }
265
266 /// Enable provided buffers for zero-copy operations.
267 pub fn with_provided_buffers(mut self, enabled: bool) -> Self {
268 self.provided_buffers = enabled;
269 self
270 }
271
272 /// Enable fast poll for network operations.
273 pub fn with_fast_poll(mut self, enabled: bool) -> Self {
274 self.fast_poll = enabled;
275 self
276 }
277
278 /// Enable submission queue polling with optional CPU affinity.
279 ///
280 /// **Warning**: SQ polling uses dedicated CPU resources and should be
281 /// used carefully in production environments.
282 pub fn with_sq_poll(mut self, enabled: bool, cpu: Option<u32>) -> Self {
283 self.sq_poll = enabled;
284 self.sq_thread_cpu = if enabled { cpu } else { None };
285 self
286 }
287
288 /// Enable cooperative task running.
289 pub fn with_coop_taskrun(mut self, enabled: bool) -> Self {
290 self.coop_taskrun = enabled;
291 self
292 }
293
294 /// Enable task work defer.
295 pub fn with_defer_taskrun(mut self, enabled: bool) -> Self {
296 self.defer_taskrun = enabled;
297 self
298 }
299
300 /// Enable advanced task work management (6.1+).
301 pub fn with_advanced_task_work(mut self, enabled: bool) -> Self {
302 self.advanced_task_work = enabled;
303 self
304 }
305
306 /// Enable zero-copy send reporting (6.2+).
307 pub fn with_send_zc_reporting(mut self, enabled: bool) -> Self {
308 self.send_zc_reporting = enabled;
309 self
310 }
311
312 /// Enable completion batching for multishot operations (6.2+).
313 pub fn with_multishot_completion_batching(mut self, enabled: bool) -> Self {
314 self.multishot_completion_batching = enabled;
315 self
316 }
317
318 /// Enable async operation cancellation (6.6+).
319 pub fn with_async_cancel_op(mut self, enabled: bool) -> Self {
320 self.async_cancel_op = enabled;
321 self
322 }
323
324 /// Enable Direct I/O performance optimizations (6.6+).
325 pub fn with_direct_io_optimizations(mut self, enabled: bool) -> Self {
326 self.direct_io_optimizations = enabled;
327 self
328 }
329
330 /// Get a list of all enabled features.
331 ///
332 /// Returns a vector of feature names that are currently enabled.
333 /// Useful for logging, debugging, or feature validation.
334 ///
335 /// # Examples
336 ///
337 /// ```rust
338 /// use safer_ring::advanced::AdvancedConfig;
339 ///
340 /// let config = AdvancedConfig::stable();
341 /// let enabled = config.enabled_features();
342 /// println!("Enabled features: {:?}", enabled);
343 /// ```
344 pub fn enabled_features(&self) -> Vec<&'static str> {
345 let mut features = Vec::new();
346
347 // Legacy features
348 if self.buffer_selection {
349 features.push("buffer_selection");
350 }
351 if self.multi_shot {
352 features.push("multi_shot");
353 }
354 if self.provided_buffers {
355 features.push("provided_buffers");
356 }
357 if self.fast_poll {
358 features.push("fast_poll");
359 }
360 if self.sq_poll {
361 features.push("sq_poll");
362 }
363 if self.coop_taskrun {
364 features.push("coop_taskrun");
365 }
366 if self.defer_taskrun {
367 features.push("defer_taskrun");
368 }
369
370 // 6.1+ features
371 if self.advanced_task_work {
372 features.push("advanced_task_work");
373 }
374 if self.defer_async_work {
375 features.push("defer_async_work");
376 }
377
378 // 6.2+ features
379 if self.send_zc_reporting {
380 features.push("send_zc_reporting");
381 }
382 if self.multishot_completion_batching {
383 features.push("multishot_completion_batching");
384 }
385 if self.epoll_uring_wake {
386 features.push("epoll_uring_wake");
387 }
388
389 // 6.3+ features
390 if self.registered_ring_fd {
391 features.push("registered_ring_fd");
392 }
393
394 // 6.4+ features
395 if self.multishot_timeouts {
396 features.push("multishot_timeouts");
397 }
398
399 // 6.5+ features
400 if self.user_allocated_ring_memory {
401 features.push("user_allocated_ring_memory");
402 }
403
404 // 6.6+ features
405 if self.async_cancel_op {
406 features.push("async_cancel_op");
407 }
408 if self.socket_command_support {
409 features.push("socket_command_support");
410 }
411 if self.direct_io_optimizations {
412 features.push("direct_io_optimizations");
413 }
414
415 // 6.11+ features
416 if self.msg_ring_speedup {
417 features.push("msg_ring_speedup");
418 }
419 if self.native_bind_listen {
420 features.push("native_bind_listen");
421 }
422
423 // 6.12+ features
424 if self.improved_huge_pages {
425 features.push("improved_huge_pages");
426 }
427 if self.async_discard {
428 features.push("async_discard");
429 }
430 if self.minimum_timeout_waits {
431 features.push("minimum_timeout_waits");
432 }
433 if self.absolute_timeouts {
434 features.push("absolute_timeouts");
435 }
436 if self.incremental_buffer_consumption {
437 features.push("incremental_buffer_consumption");
438 }
439 if self.registered_buffer_cloning {
440 features.push("registered_buffer_cloning");
441 }
442
443 features
444 }
445
446 /// Count the number of enabled features.
447 ///
448 /// # Examples
449 ///
450 /// ```rust
451 /// use safer_ring::advanced::AdvancedConfig;
452 ///
453 /// let config = AdvancedConfig::stable();
454 /// let count = config.feature_count();
455 /// println!("Enabled {} features", count);
456 /// ```
457 pub fn feature_count(&self) -> usize {
458 self.enabled_features().len()
459 }
460
461 /// Validate the configuration for internal consistency.
462 ///
463 /// Checks for feature combinations that are known to be problematic
464 /// or mutually exclusive. Returns a list of warnings about the current
465 /// configuration.
466 ///
467 /// # Examples
468 ///
469 /// ```rust
470 /// use safer_ring::advanced::AdvancedConfig;
471 ///
472 /// let config = AdvancedConfig::performance();
473 /// let warnings = config.validate();
474 /// if !warnings.is_empty() {
475 /// println!("Configuration warnings: {:?}", warnings);
476 /// }
477 /// ```
478 pub fn validate(&self) -> Vec<String> {
479 let mut warnings = Vec::new();
480
481 // Check for problematic feature combinations
482 if self.sq_poll && self.defer_taskrun {
483 warnings.push("sq_poll and defer_taskrun may conflict on some kernels".to_string());
484 }
485
486 if self.defer_async_work && !self.advanced_task_work {
487 warnings.push("defer_async_work requires advanced_task_work for stability".to_string());
488 }
489
490 if self.user_allocated_ring_memory {
491 warnings
492 .push("user_allocated_ring_memory requires custom memory management".to_string());
493 }
494
495 if self.sq_poll && self.sq_thread_cpu.is_none() {
496 warnings.push("sq_poll without CPU affinity may cause performance issues".to_string());
497 }
498
499 // Check for resource-intensive combinations
500 let intensive_features = [
501 self.sq_poll,
502 self.defer_async_work,
503 self.user_allocated_ring_memory,
504 ];
505 if intensive_features.iter().filter(|&&x| x).count() > 1 {
506 warnings.push("Multiple resource-intensive features enabled".to_string());
507 }
508
509 warnings
510 }
511}
512
513#[cfg(test)]
514mod tests {
515 use super::*;
516
517 #[test]
518 fn test_default_config() {
519 let config = AdvancedConfig::default();
520
521 // Legacy features
522 assert!(!config.buffer_selection);
523 assert!(!config.multi_shot);
524 assert!(!config.provided_buffers);
525 assert!(!config.fast_poll);
526 assert!(!config.sq_poll);
527 assert!(config.sq_thread_cpu.is_none());
528 assert!(!config.coop_taskrun);
529 assert!(!config.defer_taskrun);
530
531 // Kernel 6.1+ features
532 assert!(!config.advanced_task_work);
533 assert!(!config.defer_async_work);
534
535 // Kernel 6.2+ features
536 assert!(!config.send_zc_reporting);
537 assert!(!config.multishot_completion_batching);
538 assert!(!config.epoll_uring_wake);
539
540 // Kernel 6.3+ features
541 assert!(!config.registered_ring_fd);
542
543 // Kernel 6.4+ features
544 assert!(!config.multishot_timeouts);
545
546 // Kernel 6.5+ features
547 assert!(!config.user_allocated_ring_memory);
548
549 // Kernel 6.6+ features
550 assert!(!config.async_cancel_op);
551 assert!(!config.socket_command_support);
552 assert!(!config.direct_io_optimizations);
553
554 // Kernel 6.11+ features
555 assert!(!config.msg_ring_speedup);
556 assert!(!config.native_bind_listen);
557
558 // Kernel 6.12+ features
559 assert!(!config.improved_huge_pages);
560 assert!(!config.async_discard);
561 assert!(!config.minimum_timeout_waits);
562 assert!(!config.absolute_timeouts);
563 assert!(!config.incremental_buffer_consumption);
564 assert!(!config.registered_buffer_cloning);
565 }
566
567 #[test]
568 fn test_new_config() {
569 let config = AdvancedConfig::new();
570 // Should be identical to default
571 assert_eq!(
572 format!("{config:?}"),
573 format!("{:?}", AdvancedConfig::default())
574 );
575 }
576
577 #[test]
578 fn test_stable_config() {
579 let config = AdvancedConfig::stable();
580
581 // Should enable stable features
582 assert!(config.buffer_selection);
583 assert!(config.fast_poll);
584 assert!(config.provided_buffers);
585 assert!(config.coop_taskrun);
586 assert!(config.defer_taskrun);
587
588 // Should keep problematic features disabled
589 assert!(!config.sq_poll);
590 assert!(!config.defer_async_work);
591 assert!(!config.user_allocated_ring_memory);
592 }
593
594 #[test]
595 fn test_performance_config() {
596 let config = AdvancedConfig::performance();
597
598 // Should have stable features
599 assert!(config.buffer_selection);
600 assert!(config.fast_poll);
601
602 // Should have performance features
603 assert!(config.multi_shot);
604 assert!(config.advanced_task_work);
605 assert!(config.send_zc_reporting);
606 assert!(config.multishot_completion_batching);
607 }
608
609 #[test]
610 fn test_development_config() {
611 let config = AdvancedConfig::development();
612
613 // Should enable useful development features
614 assert!(config.buffer_selection);
615 assert!(config.multi_shot);
616 assert!(config.provided_buffers);
617
618 // Should disable debugging-unfriendly features
619 assert!(!config.sq_poll);
620 assert!(!config.defer_async_work);
621 }
622
623 #[test]
624 fn test_builder_pattern() {
625 let config = AdvancedConfig::new()
626 .with_buffer_selection(true)
627 .with_multi_shot(true)
628 .with_fast_poll(true);
629
630 assert!(config.buffer_selection);
631 assert!(config.multi_shot);
632 assert!(config.fast_poll);
633 assert!(!config.provided_buffers); // Should remain false
634 }
635
636 #[test]
637 fn test_sq_poll_configuration() {
638 let config = AdvancedConfig::new().with_sq_poll(true, Some(2));
639 assert!(config.sq_poll);
640 assert_eq!(config.sq_thread_cpu, Some(2));
641
642 let config = AdvancedConfig::new().with_sq_poll(false, Some(2));
643 assert!(!config.sq_poll);
644 assert_eq!(config.sq_thread_cpu, None); // Should be reset when disabled
645 }
646
647 #[test]
648 fn test_enabled_features() {
649 let config = AdvancedConfig::stable();
650 let features = config.enabled_features();
651
652 assert!(features.contains(&"buffer_selection"));
653 assert!(features.contains(&"fast_poll"));
654 assert!(!features.is_empty());
655
656 let default_config = AdvancedConfig::default();
657 assert!(default_config.enabled_features().is_empty());
658 }
659
660 #[test]
661 fn test_feature_count() {
662 let default_config = AdvancedConfig::default();
663 assert_eq!(default_config.feature_count(), 0);
664
665 let stable_config = AdvancedConfig::stable();
666 assert!(stable_config.feature_count() > 0);
667
668 let performance_config = AdvancedConfig::performance();
669 assert!(performance_config.feature_count() >= stable_config.feature_count());
670 }
671
672 #[test]
673 fn test_validation() {
674 let good_config = AdvancedConfig::stable();
675 let warnings = good_config.validate();
676 // Stable config should have minimal warnings
677 assert!(warnings.len() <= 1);
678
679 let problematic_config = AdvancedConfig::new()
680 .with_sq_poll(true, None)
681 .with_defer_taskrun(true);
682 let warnings = problematic_config.validate();
683 assert!(!warnings.is_empty());
684 }
685
686 #[test]
687 fn test_resource_intensive_validation() {
688 let intensive_config = AdvancedConfig {
689 sq_poll: true,
690 defer_async_work: true,
691 user_allocated_ring_memory: true,
692 sq_thread_cpu: Some(0),
693 advanced_task_work: true, // Required for defer_async_work
694 ..AdvancedConfig::default()
695 };
696
697 let warnings = intensive_config.validate();
698 assert!(warnings.iter().any(|w| w.contains("resource-intensive")));
699 }
700}