164e01684SSebastien Boeuf // Copyright © 2020 Intel Corporation 264e01684SSebastien Boeuf // 364e01684SSebastien Boeuf // SPDX-License-Identifier: Apache-2.0 464e01684SSebastien Boeuf 564e01684SSebastien Boeuf use std::collections::HashMap; 664e01684SSebastien Boeuf use std::sync::{Arc, Mutex}; 788a9f799SRob Bradford 888a9f799SRob Bradford use pci::PciBdf; 988a9f799SRob Bradford use serde::{Deserialize, Serialize}; 1064e01684SSebastien Boeuf use vm_device::Resource; 1164e01684SSebastien Boeuf use vm_migration::Migratable; 1264e01684SSebastien Boeuf 1388a9f799SRob Bradford use crate::device_manager::PciDeviceHandle; 1488a9f799SRob Bradford 1564e01684SSebastien Boeuf #[derive(Clone, Serialize, Deserialize)] 1664e01684SSebastien Boeuf pub struct DeviceNode { 1764e01684SSebastien Boeuf pub id: String, 1864e01684SSebastien Boeuf pub resources: Vec<Resource>, 1964e01684SSebastien Boeuf pub parent: Option<String>, 2064e01684SSebastien Boeuf pub children: Vec<String>, 2164e01684SSebastien Boeuf #[serde(skip)] 2264e01684SSebastien Boeuf pub migratable: Option<Arc<Mutex<dyn Migratable>>>, 2342b5d4a2SSebastien Boeuf pub pci_bdf: Option<PciBdf>, 24b06fd80fSSebastien Boeuf #[serde(skip)] 25b06fd80fSSebastien Boeuf pub pci_device_handle: Option<PciDeviceHandle>, 2664e01684SSebastien Boeuf } 2764e01684SSebastien Boeuf 2864e01684SSebastien Boeuf impl DeviceNode { new(id: String, migratable: Option<Arc<Mutex<dyn Migratable>>>) -> Self2964e01684SSebastien Boeuf pub fn new(id: String, migratable: Option<Arc<Mutex<dyn Migratable>>>) -> Self { 3064e01684SSebastien Boeuf DeviceNode { 3164e01684SSebastien Boeuf id, 3264e01684SSebastien Boeuf resources: Vec::new(), 3364e01684SSebastien Boeuf parent: None, 3464e01684SSebastien Boeuf children: Vec::new(), 3564e01684SSebastien Boeuf migratable, 3698dac352SSebastien Boeuf pci_bdf: None, 37b06fd80fSSebastien Boeuf pci_device_handle: None, 3864e01684SSebastien Boeuf } 3964e01684SSebastien Boeuf } 4064e01684SSebastien Boeuf } 4164e01684SSebastien Boeuf 4264e01684SSebastien Boeuf #[macro_export] 4364e01684SSebastien Boeuf macro_rules! device_node { 4464e01684SSebastien Boeuf ($id:ident) => { 4564e01684SSebastien Boeuf DeviceNode::new($id.clone(), None) 4664e01684SSebastien Boeuf }; 4764e01684SSebastien Boeuf ($id:ident, $device:ident) => { 4864e01684SSebastien Boeuf DeviceNode::new( 4964e01684SSebastien Boeuf $id.clone(), 5064e01684SSebastien Boeuf Some(Arc::clone(&$device) as Arc<Mutex<dyn Migratable>>), 5164e01684SSebastien Boeuf ) 5264e01684SSebastien Boeuf }; 5364e01684SSebastien Boeuf } 5464e01684SSebastien Boeuf 5564e01684SSebastien Boeuf #[derive(Clone, Default, Serialize, Deserialize)] 5664e01684SSebastien Boeuf pub struct DeviceTree(HashMap<String, DeviceNode>); 5764e01684SSebastien Boeuf 5864e01684SSebastien Boeuf impl DeviceTree { new() -> Self5964e01684SSebastien Boeuf pub fn new() -> Self { 6064e01684SSebastien Boeuf DeviceTree(HashMap::new()) 6164e01684SSebastien Boeuf } contains_key(&self, k: &str) -> bool6262aacceeSSebastien Boeuf pub fn contains_key(&self, k: &str) -> bool { 6362aacceeSSebastien Boeuf self.0.contains_key(k) 6462aacceeSSebastien Boeuf } get(&self, k: &str) -> Option<&DeviceNode>6564e01684SSebastien Boeuf pub fn get(&self, k: &str) -> Option<&DeviceNode> { 6664e01684SSebastien Boeuf self.0.get(k) 6764e01684SSebastien Boeuf } get_mut(&mut self, k: &str) -> Option<&mut DeviceNode>6864e01684SSebastien Boeuf pub fn get_mut(&mut self, k: &str) -> Option<&mut DeviceNode> { 6964e01684SSebastien Boeuf self.0.get_mut(k) 7064e01684SSebastien Boeuf } insert(&mut self, k: String, v: DeviceNode) -> Option<DeviceNode>7164e01684SSebastien Boeuf pub fn insert(&mut self, k: String, v: DeviceNode) -> Option<DeviceNode> { 7264e01684SSebastien Boeuf self.0.insert(k, v) 7364e01684SSebastien Boeuf } remove(&mut self, k: &str) -> Option<DeviceNode>7464e01684SSebastien Boeuf pub fn remove(&mut self, k: &str) -> Option<DeviceNode> { 7564e01684SSebastien Boeuf self.0.remove(k) 7664e01684SSebastien Boeuf } iter(&self) -> std::collections::hash_map::Iter<'_, String, DeviceNode>77*2bc8d51aSJinank Jain pub fn iter(&self) -> std::collections::hash_map::Iter<'_, String, DeviceNode> { 7864e01684SSebastien Boeuf self.0.iter() 7964e01684SSebastien Boeuf } breadth_first_traversal(&self) -> BftIter<'_>80*2bc8d51aSJinank Jain pub fn breadth_first_traversal(&self) -> BftIter<'_> { 8164e01684SSebastien Boeuf BftIter::new(&self.0) 8264e01684SSebastien Boeuf } pci_devices(&self) -> Vec<&DeviceNode>83b06fd80fSSebastien Boeuf pub fn pci_devices(&self) -> Vec<&DeviceNode> { 84b06fd80fSSebastien Boeuf self.0 85b06fd80fSSebastien Boeuf .values() 861a5a8950SRob Bradford .filter(|v| v.pci_bdf.is_some() && v.pci_device_handle.is_some()) 87b06fd80fSSebastien Boeuf .collect() 88b06fd80fSSebastien Boeuf } 89d33d2549SRob Bradford remove_node_by_pci_bdf(&mut self, pci_bdf: PciBdf) -> Option<DeviceNode>9042b5d4a2SSebastien Boeuf pub fn remove_node_by_pci_bdf(&mut self, pci_bdf: PciBdf) -> Option<DeviceNode> { 91b06fd80fSSebastien Boeuf let mut id = None; 92b06fd80fSSebastien Boeuf for (k, v) in self.0.iter() { 931a5a8950SRob Bradford if v.pci_bdf == Some(pci_bdf) { 94b06fd80fSSebastien Boeuf id = Some(k.clone()); 95b06fd80fSSebastien Boeuf break; 96b06fd80fSSebastien Boeuf } 97b06fd80fSSebastien Boeuf } 98b06fd80fSSebastien Boeuf 99b06fd80fSSebastien Boeuf if let Some(id) = &id { 100b06fd80fSSebastien Boeuf self.0.remove(id) 101b06fd80fSSebastien Boeuf } else { 102b06fd80fSSebastien Boeuf None 103b06fd80fSSebastien Boeuf } 104b06fd80fSSebastien Boeuf } 10564e01684SSebastien Boeuf } 10664e01684SSebastien Boeuf 10764e01684SSebastien Boeuf // Breadth first traversal iterator. 10864e01684SSebastien Boeuf pub struct BftIter<'a> { 10964e01684SSebastien Boeuf nodes: Vec<&'a DeviceNode>, 11064e01684SSebastien Boeuf } 11164e01684SSebastien Boeuf 11264e01684SSebastien Boeuf impl<'a> BftIter<'a> { new(hash_map: &'a HashMap<String, DeviceNode>) -> Self11364e01684SSebastien Boeuf fn new(hash_map: &'a HashMap<String, DeviceNode>) -> Self { 114c56a3ce5SHao Xu let mut nodes = Vec::with_capacity(hash_map.len()); 115c56a3ce5SHao Xu let mut i = 0; 11664e01684SSebastien Boeuf 11764e01684SSebastien Boeuf for (_, node) in hash_map.iter() { 11864e01684SSebastien Boeuf if node.parent.is_none() { 11964e01684SSebastien Boeuf nodes.push(node); 12064e01684SSebastien Boeuf } 12164e01684SSebastien Boeuf } 12264e01684SSebastien Boeuf 123c56a3ce5SHao Xu while i < nodes.len() { 124c56a3ce5SHao Xu for child_node_id in nodes[i].children.iter() { 12564e01684SSebastien Boeuf if let Some(child_node) = hash_map.get(child_node_id) { 126c56a3ce5SHao Xu nodes.push(child_node); 12764e01684SSebastien Boeuf } 12864e01684SSebastien Boeuf } 129c56a3ce5SHao Xu i += 1; 13064e01684SSebastien Boeuf } 13164e01684SSebastien Boeuf 13264e01684SSebastien Boeuf BftIter { nodes } 13364e01684SSebastien Boeuf } 13464e01684SSebastien Boeuf } 13564e01684SSebastien Boeuf 13664e01684SSebastien Boeuf impl<'a> Iterator for BftIter<'a> { 13764e01684SSebastien Boeuf type Item = &'a DeviceNode; 13864e01684SSebastien Boeuf next(&mut self) -> Option<Self::Item>13964e01684SSebastien Boeuf fn next(&mut self) -> Option<Self::Item> { 14064e01684SSebastien Boeuf if self.nodes.is_empty() { 14164e01684SSebastien Boeuf None 14264e01684SSebastien Boeuf } else { 14364e01684SSebastien Boeuf Some(self.nodes.remove(0)) 14464e01684SSebastien Boeuf } 14564e01684SSebastien Boeuf } 14664e01684SSebastien Boeuf } 14764e01684SSebastien Boeuf 1480aab960bSRuoqing He impl DoubleEndedIterator for BftIter<'_> { next_back(&mut self) -> Option<Self::Item>14964e01684SSebastien Boeuf fn next_back(&mut self) -> Option<Self::Item> { 15064e01684SSebastien Boeuf self.nodes.pop() 15164e01684SSebastien Boeuf } 15264e01684SSebastien Boeuf } 153f6a71becSSebastien Boeuf 154f6a71becSSebastien Boeuf #[cfg(test)] 155f6a71becSSebastien Boeuf mod tests { 156f6a71becSSebastien Boeuf use super::{DeviceNode, DeviceTree}; 157f6a71becSSebastien Boeuf 158f6a71becSSebastien Boeuf #[test] test_device_tree()159f6a71becSSebastien Boeuf fn test_device_tree() { 160f6a71becSSebastien Boeuf // Check new() 161f6a71becSSebastien Boeuf let mut device_tree = DeviceTree::new(); 162e4763b47SRob Bradford assert_eq!(device_tree.0.len(), 0); 163f6a71becSSebastien Boeuf 164f6a71becSSebastien Boeuf // Check insert() 165f6a71becSSebastien Boeuf let id = String::from("id1"); 166f6a71becSSebastien Boeuf device_tree.insert(id.clone(), DeviceNode::new(id.clone(), None)); 167e4763b47SRob Bradford assert_eq!(device_tree.0.len(), 1); 168f6a71becSSebastien Boeuf let node = device_tree.0.get(&id); 169e4763b47SRob Bradford assert!(node.is_some()); 170f6a71becSSebastien Boeuf let node = node.unwrap(); 171e4763b47SRob Bradford assert_eq!(node.id, id); 172f6a71becSSebastien Boeuf 173f6a71becSSebastien Boeuf // Check get() 174f6a71becSSebastien Boeuf let id2 = String::from("id2"); 175e4763b47SRob Bradford assert!(device_tree.get(&id).is_some()); 176e4763b47SRob Bradford assert!(device_tree.get(&id2).is_none()); 177f6a71becSSebastien Boeuf 178f6a71becSSebastien Boeuf // Check get_mut() 179f6a71becSSebastien Boeuf let node = device_tree.get_mut(&id).unwrap(); 180521a0d1aSRob Bradford node.id.clone_from(&id2); 181f6a71becSSebastien Boeuf let node = device_tree.0.get(&id).unwrap(); 182e4763b47SRob Bradford assert_eq!(node.id, id2); 183f6a71becSSebastien Boeuf 184f6a71becSSebastien Boeuf // Check remove() 185f6a71becSSebastien Boeuf let node = device_tree.remove(&id).unwrap(); 186e4763b47SRob Bradford assert_eq!(node.id, id2); 187e4763b47SRob Bradford assert_eq!(device_tree.0.len(), 0); 188f6a71becSSebastien Boeuf 189f6a71becSSebastien Boeuf // Check iter() 190f6a71becSSebastien Boeuf let disk_id = String::from("disk0"); 191f6a71becSSebastien Boeuf let net_id = String::from("net0"); 192f6a71becSSebastien Boeuf let rng_id = String::from("rng0"); 193f6a71becSSebastien Boeuf let device_list = vec![ 194f6a71becSSebastien Boeuf (disk_id.clone(), device_node!(disk_id)), 195f6a71becSSebastien Boeuf (net_id.clone(), device_node!(net_id)), 196f6a71becSSebastien Boeuf (rng_id.clone(), device_node!(rng_id)), 197f6a71becSSebastien Boeuf ]; 198f6a71becSSebastien Boeuf device_tree.0.extend(device_list); 199f6a71becSSebastien Boeuf for (id, node) in device_tree.iter() { 200f6a71becSSebastien Boeuf if id == &disk_id { 201e4763b47SRob Bradford assert_eq!(node.id, disk_id); 202f6a71becSSebastien Boeuf } else if id == &net_id { 203e4763b47SRob Bradford assert_eq!(node.id, net_id); 204f6a71becSSebastien Boeuf } else if id == &rng_id { 205e4763b47SRob Bradford assert_eq!(node.id, rng_id); 206f6a71becSSebastien Boeuf } else { 207e4763b47SRob Bradford unreachable!() 208f6a71becSSebastien Boeuf } 209f6a71becSSebastien Boeuf } 210f6a71becSSebastien Boeuf 211f6a71becSSebastien Boeuf // Check breadth_first_traversal() based on the following hierarchy 212f6a71becSSebastien Boeuf // 213f6a71becSSebastien Boeuf // 0 214f6a71becSSebastien Boeuf // | \ 215f6a71becSSebastien Boeuf // 1 2 216f6a71becSSebastien Boeuf // | | \ 217f6a71becSSebastien Boeuf // 3 4 5 218f6a71becSSebastien Boeuf // 219f6a71becSSebastien Boeuf let mut device_tree = DeviceTree::new(); 220f6a71becSSebastien Boeuf let child_1_id = String::from("child1"); 221f6a71becSSebastien Boeuf let child_2_id = String::from("child2"); 222f6a71becSSebastien Boeuf let child_3_id = String::from("child3"); 223f6a71becSSebastien Boeuf let parent_1_id = String::from("parent1"); 224f6a71becSSebastien Boeuf let parent_2_id = String::from("parent2"); 225f6a71becSSebastien Boeuf let root_id = String::from("root"); 226f6a71becSSebastien Boeuf let mut child_1_node = device_node!(child_1_id); 227f6a71becSSebastien Boeuf let mut child_2_node = device_node!(child_2_id); 228f6a71becSSebastien Boeuf let mut child_3_node = device_node!(child_3_id); 229f6a71becSSebastien Boeuf let mut parent_1_node = device_node!(parent_1_id); 230f6a71becSSebastien Boeuf let mut parent_2_node = device_node!(parent_2_id); 231f6a71becSSebastien Boeuf let mut root_node = device_node!(root_id); 232f6a71becSSebastien Boeuf child_1_node.parent = Some(parent_1_id.clone()); 233f6a71becSSebastien Boeuf child_2_node.parent = Some(parent_2_id.clone()); 234f6a71becSSebastien Boeuf child_3_node.parent = Some(parent_2_id.clone()); 235f6a71becSSebastien Boeuf parent_1_node.children = vec![child_1_id.clone()]; 236f6a71becSSebastien Boeuf parent_1_node.parent = Some(root_id.clone()); 237f6a71becSSebastien Boeuf parent_2_node.children = vec![child_2_id.clone(), child_3_id.clone()]; 238f6a71becSSebastien Boeuf parent_2_node.parent = Some(root_id.clone()); 239f6a71becSSebastien Boeuf root_node.children = vec![parent_1_id.clone(), parent_2_id.clone()]; 240f6a71becSSebastien Boeuf let device_list = vec![ 241f6a71becSSebastien Boeuf (child_1_id.clone(), child_1_node), 242f6a71becSSebastien Boeuf (child_2_id.clone(), child_2_node), 243f6a71becSSebastien Boeuf (child_3_id.clone(), child_3_node), 244f6a71becSSebastien Boeuf (parent_1_id.clone(), parent_1_node), 245f6a71becSSebastien Boeuf (parent_2_id.clone(), parent_2_node), 246f6a71becSSebastien Boeuf (root_id.clone(), root_node), 247f6a71becSSebastien Boeuf ]; 248f6a71becSSebastien Boeuf device_tree.0.extend(device_list); 249f6a71becSSebastien Boeuf 250f6a71becSSebastien Boeuf let iter_vec = device_tree 251f6a71becSSebastien Boeuf .breadth_first_traversal() 252f6a71becSSebastien Boeuf .collect::<Vec<&DeviceNode>>(); 253e4763b47SRob Bradford assert_eq!(iter_vec.len(), 6); 254e4763b47SRob Bradford assert_eq!(iter_vec[0].id, root_id); 255e4763b47SRob Bradford assert_eq!(iter_vec[1].id, parent_1_id); 256e4763b47SRob Bradford assert_eq!(iter_vec[2].id, parent_2_id); 257e4763b47SRob Bradford assert_eq!(iter_vec[3].id, child_1_id); 258e4763b47SRob Bradford assert_eq!(iter_vec[4].id, child_2_id); 259e4763b47SRob Bradford assert_eq!(iter_vec[5].id, child_3_id); 260f6a71becSSebastien Boeuf 261f6a71becSSebastien Boeuf let iter_vec = device_tree 262f6a71becSSebastien Boeuf .breadth_first_traversal() 263f6a71becSSebastien Boeuf .rev() 264f6a71becSSebastien Boeuf .collect::<Vec<&DeviceNode>>(); 265e4763b47SRob Bradford assert_eq!(iter_vec.len(), 6); 266e4763b47SRob Bradford assert_eq!(iter_vec[5].id, root_id); 267e4763b47SRob Bradford assert_eq!(iter_vec[4].id, parent_1_id); 268e4763b47SRob Bradford assert_eq!(iter_vec[3].id, parent_2_id); 269e4763b47SRob Bradford assert_eq!(iter_vec[2].id, child_1_id); 270e4763b47SRob Bradford assert_eq!(iter_vec[1].id, child_2_id); 271e4763b47SRob Bradford assert_eq!(iter_vec[0].id, child_3_id); 272f6a71becSSebastien Boeuf } 273f6a71becSSebastien Boeuf } 274