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}