1 use core::{ 2 cell::UnsafeCell, 3 fmt::Debug, 4 ops::{Deref, DerefMut}, 5 }; 6 7 use alloc::{string::String, sync::Arc}; 8 use smoltcp::{phy, wire}; 9 use virtio_drivers::{device::net::VirtIONet, transport::Transport}; 10 11 use super::NetDriver; 12 use crate::{ 13 driver::{ 14 base::{ 15 device::{bus::Bus, driver::Driver, Device, IdTable}, 16 kobject::{KObjType, KObject, KObjectState}, 17 }, 18 virtio::virtio_impl::HalImpl, 19 }, 20 kerror, kinfo, 21 libs::spinlock::SpinLock, 22 net::{generate_iface_id, NET_DRIVERS}, 23 time::Instant, 24 }; 25 use system_error::SystemError; 26 27 /// @brief Virtio网络设备驱动(加锁) 28 pub struct VirtioNICDriver<T: Transport> { 29 pub inner: Arc<SpinLock<VirtIONet<HalImpl, T, 2>>>, 30 } 31 32 impl<T: Transport> Clone for VirtioNICDriver<T> { 33 fn clone(&self) -> Self { 34 return VirtioNICDriver { 35 inner: self.inner.clone(), 36 }; 37 } 38 } 39 40 /// @brief 网卡驱动的包裹器,这是为了获取网卡驱动的可变引用而设计的。 41 /// 由于smoltcp的设计,导致需要在poll的时候获取网卡驱动的可变引用, 42 /// 同时需要在token的consume里面获取可变引用。为了避免双重加锁,所以需要这个包裹器。 43 struct VirtioNICDriverWrapper<T: Transport>(UnsafeCell<VirtioNICDriver<T>>); 44 unsafe impl<T: Transport> Send for VirtioNICDriverWrapper<T> {} 45 unsafe impl<T: Transport> Sync for VirtioNICDriverWrapper<T> {} 46 47 impl<T: Transport> Deref for VirtioNICDriverWrapper<T> { 48 type Target = VirtioNICDriver<T>; 49 fn deref(&self) -> &Self::Target { 50 unsafe { &*self.0.get() } 51 } 52 } 53 impl<T: Transport> DerefMut for VirtioNICDriverWrapper<T> { 54 fn deref_mut(&mut self) -> &mut Self::Target { 55 unsafe { &mut *self.0.get() } 56 } 57 } 58 59 impl<T: Transport> VirtioNICDriverWrapper<T> { 60 fn force_get_mut(&self) -> &mut VirtioNICDriver<T> { 61 unsafe { &mut *self.0.get() } 62 } 63 } 64 65 impl<T: Transport> Debug for VirtioNICDriver<T> { 66 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 67 f.debug_struct("VirtioNICDriver").finish() 68 } 69 } 70 71 pub struct VirtioInterface<T: Transport> { 72 driver: VirtioNICDriverWrapper<T>, 73 iface_id: usize, 74 iface: SpinLock<smoltcp::iface::Interface>, 75 name: String, 76 } 77 78 impl<T: Transport> Debug for VirtioInterface<T> { 79 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 80 f.debug_struct("VirtioInterface") 81 .field("driver", self.driver.deref()) 82 .field("iface_id", &self.iface_id) 83 .field("iface", &"smoltcp::iface::Interface") 84 .field("name", &self.name) 85 .finish() 86 } 87 } 88 89 impl<T: Transport> VirtioInterface<T> { 90 pub fn new(mut driver: VirtioNICDriver<T>) -> Arc<Self> { 91 let iface_id = generate_iface_id(); 92 let mut iface_config = smoltcp::iface::Config::new(); 93 94 // todo: 随机设定这个值。 95 // 参见 https://docs.rs/smoltcp/latest/smoltcp/iface/struct.Config.html#structfield.random_seed 96 iface_config.random_seed = 12345; 97 98 iface_config.hardware_addr = Some(wire::HardwareAddress::Ethernet( 99 smoltcp::wire::EthernetAddress(driver.inner.lock().mac_address()), 100 )); 101 let iface = smoltcp::iface::Interface::new(iface_config, &mut driver); 102 103 let driver: VirtioNICDriverWrapper<T> = VirtioNICDriverWrapper(UnsafeCell::new(driver)); 104 let result = Arc::new(VirtioInterface { 105 driver, 106 iface_id, 107 iface: SpinLock::new(iface), 108 name: format!("eth{}", iface_id), 109 }); 110 111 return result; 112 } 113 } 114 115 impl<T: 'static + Transport> VirtioNICDriver<T> { 116 pub fn new(driver_net: VirtIONet<HalImpl, T, 2>) -> Self { 117 let mut iface_config = smoltcp::iface::Config::new(); 118 119 // todo: 随机设定这个值。 120 // 参见 https://docs.rs/smoltcp/latest/smoltcp/iface/struct.Config.html#structfield.random_seed 121 iface_config.random_seed = 12345; 122 123 iface_config.hardware_addr = Some(wire::HardwareAddress::Ethernet( 124 smoltcp::wire::EthernetAddress(driver_net.mac_address()), 125 )); 126 127 let inner: Arc<SpinLock<VirtIONet<HalImpl, T, 2>>> = Arc::new(SpinLock::new(driver_net)); 128 let result = VirtioNICDriver { inner }; 129 return result; 130 } 131 } 132 133 pub struct VirtioNetToken<T: Transport> { 134 driver: VirtioNICDriver<T>, 135 rx_buffer: Option<virtio_drivers::device::net::RxBuffer>, 136 } 137 138 impl<'a, T: Transport> VirtioNetToken<T> { 139 pub fn new( 140 driver: VirtioNICDriver<T>, 141 rx_buffer: Option<virtio_drivers::device::net::RxBuffer>, 142 ) -> Self { 143 return Self { driver, rx_buffer }; 144 } 145 } 146 147 impl<T: Transport> phy::Device for VirtioNICDriver<T> { 148 type RxToken<'a> = VirtioNetToken<T> where Self: 'a; 149 type TxToken<'a> = VirtioNetToken<T> where Self: 'a; 150 151 fn receive( 152 &mut self, 153 _timestamp: smoltcp::time::Instant, 154 ) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { 155 match self.inner.lock().receive() { 156 Ok(buf) => Some(( 157 VirtioNetToken::new(self.clone(), Some(buf)), 158 VirtioNetToken::new(self.clone(), None), 159 )), 160 Err(virtio_drivers::Error::NotReady) => None, 161 Err(err) => panic!("VirtIO receive failed: {}", err), 162 } 163 } 164 165 fn transmit(&mut self, _timestamp: smoltcp::time::Instant) -> Option<Self::TxToken<'_>> { 166 // kdebug!("VirtioNet: transmit"); 167 if self.inner.lock_irqsave().can_send() { 168 // kdebug!("VirtioNet: can send"); 169 return Some(VirtioNetToken::new(self.clone(), None)); 170 } else { 171 // kdebug!("VirtioNet: can not send"); 172 return None; 173 } 174 } 175 176 fn capabilities(&self) -> phy::DeviceCapabilities { 177 let mut caps = phy::DeviceCapabilities::default(); 178 // 网卡的最大传输单元. 请与IP层的MTU进行区分。这个值应当是网卡的最大传输单元,而不是IP层的MTU。 179 caps.max_transmission_unit = 2000; 180 /* 181 Maximum burst size, in terms of MTU. 182 The network device is unable to send or receive bursts large than the value returned by this function. 183 If None, there is no fixed limit on burst size, e.g. if network buffers are dynamically allocated. 184 */ 185 caps.max_burst_size = Some(1); 186 return caps; 187 } 188 } 189 190 impl<T: Transport> phy::TxToken for VirtioNetToken<T> { 191 fn consume<R, F>(self, len: usize, f: F) -> R 192 where 193 F: FnOnce(&mut [u8]) -> R, 194 { 195 // // 为了线程安全,这里需要对VirtioNet进行加【写锁】,以保证对设备的互斥访问。 196 197 let mut driver_net = self.driver.inner.lock(); 198 let mut tx_buf = driver_net.new_tx_buffer(len); 199 let result = f(tx_buf.packet_mut()); 200 driver_net.send(tx_buf).expect("virtio_net send failed"); 201 return result; 202 } 203 } 204 205 impl<T: Transport> phy::RxToken for VirtioNetToken<T> { 206 fn consume<R, F>(self, f: F) -> R 207 where 208 F: FnOnce(&mut [u8]) -> R, 209 { 210 // 为了线程安全,这里需要对VirtioNet进行加【写锁】,以保证对设备的互斥访问。 211 let mut rx_buf = self.rx_buffer.unwrap(); 212 let result = f(rx_buf.packet_mut()); 213 self.driver 214 .inner 215 .lock() 216 .recycle_rx_buffer(rx_buf) 217 .expect("virtio_net recv failed"); 218 result 219 } 220 } 221 222 /// @brief virtio-net 驱动的初始化与测试 223 pub fn virtio_net<T: Transport + 'static>(transport: T) { 224 let driver_net: VirtIONet<HalImpl, T, 2> = 225 match VirtIONet::<HalImpl, T, 2>::new(transport, 4096) { 226 Ok(net) => net, 227 Err(_) => { 228 kerror!("VirtIONet init failed"); 229 return; 230 } 231 }; 232 let mac = smoltcp::wire::EthernetAddress::from_bytes(&driver_net.mac_address()); 233 let driver: VirtioNICDriver<T> = VirtioNICDriver::new(driver_net); 234 let iface = VirtioInterface::new(driver); 235 let name = iface.name.clone(); 236 // 将网卡的接口信息注册到全局的网卡接口信息表中 237 NET_DRIVERS.write().insert(iface.nic_id(), iface.clone()); 238 kinfo!( 239 "Virtio-net driver init successfully!\tNetDevID: [{}], MAC: [{}]", 240 name, 241 mac 242 ); 243 } 244 245 impl<T: Transport + 'static> Driver for VirtioInterface<T> { 246 fn id_table(&self) -> Option<IdTable> { 247 todo!() 248 } 249 250 fn add_device(&self, _device: Arc<dyn Device>) { 251 todo!() 252 } 253 254 fn delete_device(&self, _device: &Arc<dyn Device>) { 255 todo!() 256 } 257 258 fn devices(&self) -> alloc::vec::Vec<Arc<dyn Device>> { 259 todo!() 260 } 261 262 fn bus(&self) -> Option<Arc<dyn Bus>> { 263 todo!() 264 } 265 266 fn set_bus(&self, _bus: Option<Arc<dyn Bus>>) { 267 todo!() 268 } 269 } 270 271 impl<T: Transport + 'static> NetDriver for VirtioInterface<T> { 272 fn mac(&self) -> smoltcp::wire::EthernetAddress { 273 let mac: [u8; 6] = self.driver.inner.lock().mac_address(); 274 return smoltcp::wire::EthernetAddress::from_bytes(&mac); 275 } 276 277 #[inline] 278 fn nic_id(&self) -> usize { 279 return self.iface_id; 280 } 281 282 #[inline] 283 fn name(&self) -> String { 284 return self.name.clone(); 285 } 286 287 fn update_ip_addrs(&self, ip_addrs: &[wire::IpCidr]) -> Result<(), SystemError> { 288 if ip_addrs.len() != 1 { 289 return Err(SystemError::EINVAL); 290 } 291 292 self.iface.lock().update_ip_addrs(|addrs| { 293 let dest = addrs.iter_mut().next(); 294 if let None = dest { 295 addrs.push(ip_addrs[0]).expect("Push ipCidr failed: full"); 296 } else { 297 let dest = dest.unwrap(); 298 *dest = ip_addrs[0]; 299 } 300 }); 301 return Ok(()); 302 } 303 304 fn poll(&self, sockets: &mut smoltcp::iface::SocketSet) -> Result<(), SystemError> { 305 let timestamp: smoltcp::time::Instant = Instant::now().into(); 306 let mut guard = self.iface.lock(); 307 let poll_res = guard.poll(timestamp, self.driver.force_get_mut(), sockets); 308 // todo: notify!!! 309 // kdebug!("Virtio Interface poll:{poll_res}"); 310 if poll_res { 311 return Ok(()); 312 } 313 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 314 } 315 316 #[inline(always)] 317 fn inner_iface(&self) -> &SpinLock<smoltcp::iface::Interface> { 318 return &self.iface; 319 } 320 // fn as_any_ref(&'static self) -> &'static dyn core::any::Any { 321 // return self; 322 // } 323 } 324 325 impl<T: Transport + 'static> KObject for VirtioInterface<T> { 326 fn as_any_ref(&self) -> &dyn core::any::Any { 327 self 328 } 329 330 fn set_inode(&self, _inode: Option<Arc<crate::filesystem::kernfs::KernFSInode>>) { 331 todo!() 332 } 333 334 fn inode(&self) -> Option<Arc<crate::filesystem::kernfs::KernFSInode>> { 335 todo!() 336 } 337 338 fn parent(&self) -> Option<alloc::sync::Weak<dyn KObject>> { 339 todo!() 340 } 341 342 fn set_parent(&self, _parent: Option<alloc::sync::Weak<dyn KObject>>) { 343 todo!() 344 } 345 346 fn kset(&self) -> Option<Arc<crate::driver::base::kset::KSet>> { 347 todo!() 348 } 349 350 fn set_kset(&self, _kset: Option<Arc<crate::driver::base::kset::KSet>>) { 351 todo!() 352 } 353 354 fn kobj_type(&self) -> Option<&'static dyn crate::driver::base::kobject::KObjType> { 355 todo!() 356 } 357 358 fn name(&self) -> String { 359 self.name.clone() 360 } 361 362 fn set_name(&self, _name: String) { 363 todo!() 364 } 365 366 fn kobj_state( 367 &self, 368 ) -> crate::libs::rwlock::RwLockReadGuard<crate::driver::base::kobject::KObjectState> { 369 todo!() 370 } 371 372 fn kobj_state_mut( 373 &self, 374 ) -> crate::libs::rwlock::RwLockWriteGuard<crate::driver::base::kobject::KObjectState> { 375 todo!() 376 } 377 378 fn set_kobj_state(&self, _state: KObjectState) { 379 todo!() 380 } 381 382 fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) { 383 todo!() 384 } 385 } 386 387 // 向编译器保证,VirtioNICDriver在线程之间是安全的. 388 // 由于smoltcp只会在token内真正操作网卡设备,并且在VirtioNetToken的consume 389 // 方法内,会对VirtioNet进行加【写锁】,因此,能够保证对设备操作的的互斥访问, 390 // 因此VirtioNICDriver在线程之间是安全的。 391 // unsafe impl<T: Transport> Sync for VirtioNICDriver<T> {} 392 // unsafe impl<T: Transport> Send for VirtioNICDriver<T> {} 393