Skip to main content

iris_core/runtime/
mod.rs

1//! Iris runtime.
2//!
3//! The runtime initializes the DPDK environment abstraction layer, creates memory pools, launches
4//! the packet processing cores, and manages logging and display output.
5
6mod offline;
7mod online;
8use self::offline::*;
9use self::online::*;
10
11use crate::config::*;
12use crate::dpdk;
13use crate::filter::FilterFactory;
14use crate::lcore::SocketId;
15use crate::memory::mempool::Mempool;
16use crate::subscription::*;
17
18use std::collections::BTreeMap;
19use std::ffi::CString;
20use std::sync::Arc;
21
22use anyhow::{bail, Result};
23
24/// The Iris runtime.
25///
26/// The runtime initializes the DPDK environment abstraction layer, creates memory pools, launches
27/// the packet processing cores, and manages logging and display output.
28pub struct Runtime<S>
29where
30    S: Subscribable,
31{
32    #[allow(dead_code)]
33    mempools: BTreeMap<SocketId, Mempool>,
34    online: Option<OnlineRuntime<S>>,
35    pub(crate) offline: Option<OfflineRuntime<S>>, // Public for testing only
36    #[cfg(feature = "timing")]
37    subscription: Arc<Subscription<S>>,
38}
39
40impl<S> Runtime<S>
41where
42    S: Subscribable,
43{
44    /// Creates a new runtime from the `config` settings, filter, and callback.
45    ///
46    /// # Remarks
47    ///
48    /// The `factory` parameter is a macro-generated function pointer based on the user-defined
49    /// filter string, and must take the value "`filter`". `cb` is the name of the user-defined
50    /// callback function.
51    ///
52    /// # Example
53    ///
54    /// let mut runtime = Runtime::new(config, filter, callback)?;
55    pub fn new(config: RuntimeConfig, factory: fn() -> FilterFactory<S::Tracked>) -> Result<Self> {
56        let factory = factory();
57        let filter_str = factory.hw_filter_str.clone();
58        let subscription = Arc::new(Subscription::new(factory));
59
60        println!("Initializing Iris runtime...");
61        log::info!("Initializing EAL...");
62        dpdk::load_drivers();
63        {
64            let eal_params = config.get_eal_params();
65            let eal_params_len = eal_params.len() as i32;
66
67            let args: Vec<CString> = eal_params
68                .into_iter()
69                .map(|arg| CString::new(arg).unwrap())
70                .collect();
71            let ptrs: Vec<*mut u8> = args.iter().map(|s| s.as_ptr() as *mut u8).collect();
72
73            let ret = unsafe { dpdk::rte_eal_init(eal_params_len, ptrs.as_ptr() as *mut _) };
74            if ret < 0 {
75                bail!("Failure initializing EAL");
76            }
77        }
78
79        log::info!("Initializing Mempools...");
80        let mut mempools = BTreeMap::new();
81        let socket_ids = config.get_all_socket_ids();
82        let mtu = if let Some(online) = &config.online {
83            online.mtu
84        } else if let Some(offline) = &config.offline {
85            offline.mtu
86        } else {
87            Mempool::default_mtu()
88        };
89        for socket_id in socket_ids {
90            log::debug!("Socket ID: {}", socket_id);
91            let mempool = Mempool::new(&config.mempool, socket_id, mtu)?;
92            mempools.insert(socket_id, mempool);
93        }
94
95        let online = config.online.as_ref().map(|cfg| {
96            log::info!("Initializing Online Runtime...");
97            let online_opts = OnlineOptions {
98                online: cfg.clone(),
99                conntrack: config.conntrack.clone(),
100            };
101            OnlineRuntime::new(
102                &config,
103                online_opts,
104                &mut mempools,
105                filter_str.clone(),
106                Arc::clone(&subscription),
107            )
108        });
109
110        let offline = config.offline.as_ref().map(|cfg| {
111            log::info!("Initializing Offline Analysis...");
112            let offline_opts = OfflineOptions {
113                offline: cfg.clone(),
114                conntrack: config.conntrack.clone(),
115            };
116            OfflineRuntime::new(offline_opts, &mempools, Arc::clone(&subscription))
117        });
118
119        log::info!("Runtime ready.");
120        Ok(Runtime {
121            mempools,
122            online,
123            offline,
124            #[cfg(feature = "timing")]
125            subscription,
126        })
127    }
128
129    /// Run Iris for the duration specified in the configuration or until `ctrl-c` to terminate.
130    ///
131    /// # Example
132    ///
133    /// runtime.run();
134    pub fn run(&mut self) {
135        if let Some(online) = &mut self.online {
136            online.run();
137        } else if let Some(offline) = &self.offline {
138            offline.run();
139        } else {
140            log::error!("No runtime");
141        }
142        #[cfg(feature = "timing")]
143        {
144            self.subscription.timers.display_stats();
145            self.subscription.timers.dump_stats();
146        }
147        log::info!("Done.");
148    }
149}