1 // Copyright (C) 2019 Alibaba Cloud Computing. All rights reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 use std::fs::File; 5 6 use crate::message::*; 7 use crate::Error; 8 use crate::Protocol; 9 use crate::Result; 10 use crate::VhostUserSlaveReqHandlerMut; 11 12 pub const MAX_QUEUE_NUM: usize = 2; 13 pub const MAX_VRING_NUM: usize = 256; 14 pub const MAX_MEM_SLOTS: usize = 32; 15 pub const VIRTIO_FEATURES: u64 = 0x40000003; 16 17 #[derive(Default)] 18 pub struct DummySlaveReqHandler { 19 pub owned: bool, 20 pub features_acked: bool, 21 pub acked_features: u64, 22 pub acked_protocol_features: u64, 23 pub queue_num: usize, 24 pub vring_num: [u32; MAX_QUEUE_NUM], 25 pub vring_base: [u32; MAX_QUEUE_NUM], 26 pub call_fd: [Option<File>; MAX_QUEUE_NUM], 27 pub kick_fd: [Option<File>; MAX_QUEUE_NUM], 28 pub err_fd: [Option<File>; MAX_QUEUE_NUM], 29 pub vring_started: [bool; MAX_QUEUE_NUM], 30 pub vring_enabled: [bool; MAX_QUEUE_NUM], 31 pub inflight_file: Option<File>, 32 } 33 34 impl DummySlaveReqHandler { new() -> Self35 pub fn new() -> Self { 36 DummySlaveReqHandler { 37 queue_num: MAX_QUEUE_NUM, 38 ..Default::default() 39 } 40 } 41 } 42 43 impl VhostUserSlaveReqHandlerMut for DummySlaveReqHandler { protocol(&self) -> Protocol44 fn protocol(&self) -> Protocol { 45 Protocol::Regular 46 } 47 set_owner(&mut self) -> Result<()>48 fn set_owner(&mut self) -> Result<()> { 49 if self.owned { 50 return Err(Error::InvalidOperation); 51 } 52 self.owned = true; 53 Ok(()) 54 } 55 reset_owner(&mut self) -> Result<()>56 fn reset_owner(&mut self) -> Result<()> { 57 self.owned = false; 58 self.features_acked = false; 59 self.acked_features = 0; 60 self.acked_protocol_features = 0; 61 Ok(()) 62 } 63 get_features(&mut self) -> Result<u64>64 fn get_features(&mut self) -> Result<u64> { 65 Ok(VIRTIO_FEATURES) 66 } 67 set_features(&mut self, features: u64) -> Result<()>68 fn set_features(&mut self, features: u64) -> Result<()> { 69 if !self.owned || self.features_acked { 70 return Err(Error::InvalidOperation); 71 } else if (features & !VIRTIO_FEATURES) != 0 { 72 return Err(Error::InvalidParam); 73 } 74 75 self.acked_features = features; 76 self.features_acked = true; 77 78 // If VHOST_USER_F_PROTOCOL_FEATURES has not been negotiated, 79 // the ring is initialized in an enabled state. 80 // If VHOST_USER_F_PROTOCOL_FEATURES has been negotiated, 81 // the ring is initialized in a disabled state. Client must not 82 // pass data to/from the backend until ring is enabled by 83 // VHOST_USER_SET_VRING_ENABLE with parameter 1, or after it has 84 // been disabled by VHOST_USER_SET_VRING_ENABLE with parameter 0. 85 let vring_enabled = 86 self.acked_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits() == 0; 87 for enabled in &mut self.vring_enabled { 88 *enabled = vring_enabled; 89 } 90 91 Ok(()) 92 } 93 set_mem_table(&mut self, _ctx: &[VhostUserMemoryRegion], _files: Vec<File>) -> Result<()>94 fn set_mem_table(&mut self, _ctx: &[VhostUserMemoryRegion], _files: Vec<File>) -> Result<()> { 95 Ok(()) 96 } 97 set_vring_num(&mut self, index: u32, num: u32) -> Result<()>98 fn set_vring_num(&mut self, index: u32, num: u32) -> Result<()> { 99 if index as usize >= self.queue_num || num == 0 || num as usize > MAX_VRING_NUM { 100 return Err(Error::InvalidParam); 101 } 102 self.vring_num[index as usize] = num; 103 Ok(()) 104 } 105 set_vring_addr( &mut self, index: u32, _flags: VhostUserVringAddrFlags, _descriptor: u64, _used: u64, _available: u64, _log: u64, ) -> Result<()>106 fn set_vring_addr( 107 &mut self, 108 index: u32, 109 _flags: VhostUserVringAddrFlags, 110 _descriptor: u64, 111 _used: u64, 112 _available: u64, 113 _log: u64, 114 ) -> Result<()> { 115 if index as usize >= self.queue_num { 116 return Err(Error::InvalidParam); 117 } 118 Ok(()) 119 } 120 set_vring_base(&mut self, index: u32, base: u32) -> Result<()>121 fn set_vring_base(&mut self, index: u32, base: u32) -> Result<()> { 122 if index as usize >= self.queue_num || base as usize >= MAX_VRING_NUM { 123 return Err(Error::InvalidParam); 124 } 125 self.vring_base[index as usize] = base; 126 Ok(()) 127 } 128 get_vring_base(&mut self, index: u32) -> Result<VhostUserVringState>129 fn get_vring_base(&mut self, index: u32) -> Result<VhostUserVringState> { 130 if index as usize >= self.queue_num { 131 return Err(Error::InvalidParam); 132 } 133 // Quotation from vhost-user spec: 134 // Client must start ring upon receiving a kick (that is, detecting 135 // that file descriptor is readable) on the descriptor specified by 136 // VHOST_USER_SET_VRING_KICK, and stop ring upon receiving 137 // VHOST_USER_GET_VRING_BASE. 138 self.vring_started[index as usize] = false; 139 Ok(VhostUserVringState::new( 140 index, 141 self.vring_base[index as usize], 142 )) 143 } 144 set_vring_kick(&mut self, index: u8, fd: Option<File>) -> Result<()>145 fn set_vring_kick(&mut self, index: u8, fd: Option<File>) -> Result<()> { 146 if index as usize >= self.queue_num || index as usize > self.queue_num { 147 return Err(Error::InvalidParam); 148 } 149 self.kick_fd[index as usize] = fd; 150 151 // Quotation from vhost-user spec: 152 // Client must start ring upon receiving a kick (that is, detecting 153 // that file descriptor is readable) on the descriptor specified by 154 // VHOST_USER_SET_VRING_KICK, and stop ring upon receiving 155 // VHOST_USER_GET_VRING_BASE. 156 // 157 // So we should add fd to event monitor(select, poll, epoll) here. 158 self.vring_started[index as usize] = true; 159 Ok(()) 160 } 161 set_vring_call(&mut self, index: u8, fd: Option<File>) -> Result<()>162 fn set_vring_call(&mut self, index: u8, fd: Option<File>) -> Result<()> { 163 if index as usize >= self.queue_num || index as usize > self.queue_num { 164 return Err(Error::InvalidParam); 165 } 166 self.call_fd[index as usize] = fd; 167 Ok(()) 168 } 169 set_vring_err(&mut self, index: u8, fd: Option<File>) -> Result<()>170 fn set_vring_err(&mut self, index: u8, fd: Option<File>) -> Result<()> { 171 if index as usize >= self.queue_num || index as usize > self.queue_num { 172 return Err(Error::InvalidParam); 173 } 174 self.err_fd[index as usize] = fd; 175 Ok(()) 176 } 177 get_protocol_features(&mut self) -> Result<VhostUserProtocolFeatures>178 fn get_protocol_features(&mut self) -> Result<VhostUserProtocolFeatures> { 179 Ok(VhostUserProtocolFeatures::all()) 180 } 181 set_protocol_features(&mut self, features: u64) -> Result<()>182 fn set_protocol_features(&mut self, features: u64) -> Result<()> { 183 // Note: slave that reported VHOST_USER_F_PROTOCOL_FEATURES must 184 // support this message even before VHOST_USER_SET_FEATURES was 185 // called. 186 // What happens if the master calls set_features() with 187 // VHOST_USER_F_PROTOCOL_FEATURES cleared after calling this 188 // interface? 189 self.acked_protocol_features = features; 190 Ok(()) 191 } 192 get_queue_num(&mut self) -> Result<u64>193 fn get_queue_num(&mut self) -> Result<u64> { 194 Ok(MAX_QUEUE_NUM as u64) 195 } 196 set_vring_enable(&mut self, index: u32, enable: bool) -> Result<()>197 fn set_vring_enable(&mut self, index: u32, enable: bool) -> Result<()> { 198 // This request should be handled only when VHOST_USER_F_PROTOCOL_FEATURES 199 // has been negotiated. 200 if self.acked_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits() == 0 { 201 return Err(Error::InvalidOperation); 202 } else if index as usize >= self.queue_num || index as usize > self.queue_num { 203 return Err(Error::InvalidParam); 204 } 205 206 // Slave must not pass data to/from the backend until ring is 207 // enabled by VHOST_USER_SET_VRING_ENABLE with parameter 1, 208 // or after it has been disabled by VHOST_USER_SET_VRING_ENABLE 209 // with parameter 0. 210 self.vring_enabled[index as usize] = enable; 211 Ok(()) 212 } 213 get_config( &mut self, offset: u32, size: u32, _flags: VhostUserConfigFlags, ) -> Result<Vec<u8>>214 fn get_config( 215 &mut self, 216 offset: u32, 217 size: u32, 218 _flags: VhostUserConfigFlags, 219 ) -> Result<Vec<u8>> { 220 if self.acked_protocol_features & VhostUserProtocolFeatures::CONFIG.bits() == 0 { 221 return Err(Error::InvalidOperation); 222 } else if !(VHOST_USER_CONFIG_OFFSET..VHOST_USER_CONFIG_SIZE).contains(&offset) 223 || size > VHOST_USER_CONFIG_SIZE - VHOST_USER_CONFIG_OFFSET 224 || size + offset > VHOST_USER_CONFIG_SIZE 225 { 226 return Err(Error::InvalidParam); 227 } 228 Ok(vec![0xa5; size as usize]) 229 } 230 set_config(&mut self, offset: u32, buf: &[u8], _flags: VhostUserConfigFlags) -> Result<()>231 fn set_config(&mut self, offset: u32, buf: &[u8], _flags: VhostUserConfigFlags) -> Result<()> { 232 let size = buf.len() as u32; 233 if self.acked_protocol_features & VhostUserProtocolFeatures::CONFIG.bits() == 0 { 234 return Err(Error::InvalidOperation); 235 } else if !(VHOST_USER_CONFIG_OFFSET..VHOST_USER_CONFIG_SIZE).contains(&offset) 236 || size > VHOST_USER_CONFIG_SIZE - VHOST_USER_CONFIG_OFFSET 237 || size + offset > VHOST_USER_CONFIG_SIZE 238 { 239 return Err(Error::InvalidParam); 240 } 241 Ok(()) 242 } 243 get_inflight_fd( &mut self, inflight: &VhostUserInflight, ) -> Result<(VhostUserInflight, File)>244 fn get_inflight_fd( 245 &mut self, 246 inflight: &VhostUserInflight, 247 ) -> Result<(VhostUserInflight, File)> { 248 let file = tempfile::tempfile().unwrap(); 249 self.inflight_file = Some(file.try_clone().unwrap()); 250 Ok(( 251 VhostUserInflight { 252 mmap_size: 0x1000, 253 mmap_offset: 0, 254 num_queues: inflight.num_queues, 255 queue_size: inflight.queue_size, 256 }, 257 file, 258 )) 259 } 260 set_inflight_fd(&mut self, _inflight: &VhostUserInflight, _file: File) -> Result<()>261 fn set_inflight_fd(&mut self, _inflight: &VhostUserInflight, _file: File) -> Result<()> { 262 Ok(()) 263 } 264 get_max_mem_slots(&mut self) -> Result<u64>265 fn get_max_mem_slots(&mut self) -> Result<u64> { 266 Ok(MAX_MEM_SLOTS as u64) 267 } 268 add_mem_region(&mut self, _region: &VhostUserSingleMemoryRegion, _fd: File) -> Result<()>269 fn add_mem_region(&mut self, _region: &VhostUserSingleMemoryRegion, _fd: File) -> Result<()> { 270 Ok(()) 271 } 272 remove_mem_region(&mut self, _region: &VhostUserSingleMemoryRegion) -> Result<()>273 fn remove_mem_region(&mut self, _region: &VhostUserSingleMemoryRegion) -> Result<()> { 274 Ok(()) 275 } 276 get_shared_memory_regions(&mut self) -> Result<Vec<VhostSharedMemoryRegion>>277 fn get_shared_memory_regions(&mut self) -> Result<Vec<VhostSharedMemoryRegion>> { 278 Ok(Vec::new()) 279 } 280 } 281