xref: /DragonOS/kernel/src/driver/net/virtio_net.rs (revision 06d5e247267cb65b84a80f219853ccd0f384b16e)
113776c11Slogin use core::{
213776c11Slogin     cell::UnsafeCell,
313776c11Slogin     fmt::Debug,
413776c11Slogin     ops::{Deref, DerefMut},
513776c11Slogin };
613776c11Slogin 
713776c11Slogin use alloc::{string::String, sync::Arc};
813776c11Slogin use smoltcp::{phy, wire};
913776c11Slogin use virtio_drivers::{device::net::VirtIONet, transport::Transport};
1013776c11Slogin 
1113776c11Slogin use crate::{
12b087521eSChiichen     driver::{
13*06d5e247SLoGin         base::{
14*06d5e247SLoGin             device::{driver::DriverError, Device, DevicePrivateData, DeviceResource, IdTable},
15*06d5e247SLoGin             kobject::KObject,
16*06d5e247SLoGin         },
17b087521eSChiichen         virtio::virtio_impl::HalImpl,
18b087521eSChiichen         Driver,
19b087521eSChiichen     },
20cde5492fSlogin     kerror, kinfo,
2113776c11Slogin     libs::spinlock::SpinLock,
2213776c11Slogin     net::{generate_iface_id, NET_DRIVERS},
2313776c11Slogin     syscall::SystemError,
2413776c11Slogin     time::Instant,
2513776c11Slogin };
2613776c11Slogin 
2713776c11Slogin use super::NetDriver;
2813776c11Slogin 
2913776c11Slogin /// @brief Virtio网络设备驱动(加锁)
3013776c11Slogin pub struct VirtioNICDriver<T: Transport> {
3113776c11Slogin     pub inner: Arc<SpinLock<VirtIONet<HalImpl, T, 2>>>,
3213776c11Slogin }
3313776c11Slogin 
3413776c11Slogin impl<T: Transport> Clone for VirtioNICDriver<T> {
3513776c11Slogin     fn clone(&self) -> Self {
3613776c11Slogin         return VirtioNICDriver {
3713776c11Slogin             inner: self.inner.clone(),
3813776c11Slogin         };
3913776c11Slogin     }
4013776c11Slogin }
4113776c11Slogin 
4213776c11Slogin /// @brief 网卡驱动的包裹器,这是为了获取网卡驱动的可变引用而设计的。
4313776c11Slogin /// 由于smoltcp的设计,导致需要在poll的时候获取网卡驱动的可变引用,
4413776c11Slogin /// 同时需要在token的consume里面获取可变引用。为了避免双重加锁,所以需要这个包裹器。
4513776c11Slogin struct VirtioNICDriverWrapper<T: Transport>(UnsafeCell<VirtioNICDriver<T>>);
4613776c11Slogin unsafe impl<T: Transport> Send for VirtioNICDriverWrapper<T> {}
4713776c11Slogin unsafe impl<T: Transport> Sync for VirtioNICDriverWrapper<T> {}
4813776c11Slogin 
4913776c11Slogin impl<T: Transport> Deref for VirtioNICDriverWrapper<T> {
5013776c11Slogin     type Target = VirtioNICDriver<T>;
5113776c11Slogin     fn deref(&self) -> &Self::Target {
5213776c11Slogin         unsafe { &*self.0.get() }
5313776c11Slogin     }
5413776c11Slogin }
5513776c11Slogin impl<T: Transport> DerefMut for VirtioNICDriverWrapper<T> {
5613776c11Slogin     fn deref_mut(&mut self) -> &mut Self::Target {
5713776c11Slogin         unsafe { &mut *self.0.get() }
5813776c11Slogin     }
5913776c11Slogin }
6013776c11Slogin 
6113776c11Slogin impl<T: Transport> VirtioNICDriverWrapper<T> {
6213776c11Slogin     fn force_get_mut(&self) -> &mut VirtioNICDriver<T> {
6313776c11Slogin         unsafe { &mut *self.0.get() }
6413776c11Slogin     }
6513776c11Slogin }
6613776c11Slogin 
6713776c11Slogin impl<T: Transport> Debug for VirtioNICDriver<T> {
6813776c11Slogin     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
6913776c11Slogin         f.debug_struct("VirtioNICDriver").finish()
7013776c11Slogin     }
7113776c11Slogin }
7213776c11Slogin 
7313776c11Slogin pub struct VirtioInterface<T: Transport> {
7413776c11Slogin     driver: VirtioNICDriverWrapper<T>,
7513776c11Slogin     iface_id: usize,
7613776c11Slogin     iface: SpinLock<smoltcp::iface::Interface>,
7713776c11Slogin     name: String,
7813776c11Slogin }
7913776c11Slogin 
8013776c11Slogin impl<T: Transport> Debug for VirtioInterface<T> {
8113776c11Slogin     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8213776c11Slogin         f.debug_struct("VirtioInterface")
8313776c11Slogin             .field("driver", self.driver.deref())
8413776c11Slogin             .field("iface_id", &self.iface_id)
8513776c11Slogin             .field("iface", &"smoltcp::iface::Interface")
8613776c11Slogin             .field("name", &self.name)
8713776c11Slogin             .finish()
8813776c11Slogin     }
8913776c11Slogin }
9013776c11Slogin 
9113776c11Slogin impl<T: Transport> VirtioInterface<T> {
9213776c11Slogin     pub fn new(mut driver: VirtioNICDriver<T>) -> Arc<Self> {
9313776c11Slogin         let iface_id = generate_iface_id();
9413776c11Slogin         let mut iface_config = smoltcp::iface::Config::new();
9513776c11Slogin 
9613776c11Slogin         // todo: 随机设定这个值。
9713776c11Slogin         // 参见 https://docs.rs/smoltcp/latest/smoltcp/iface/struct.Config.html#structfield.random_seed
9813776c11Slogin         iface_config.random_seed = 12345;
9913776c11Slogin 
10013776c11Slogin         iface_config.hardware_addr = Some(wire::HardwareAddress::Ethernet(
10113776c11Slogin             smoltcp::wire::EthernetAddress(driver.inner.lock().mac_address()),
10213776c11Slogin         ));
10313776c11Slogin         let iface = smoltcp::iface::Interface::new(iface_config, &mut driver);
10413776c11Slogin 
10513776c11Slogin         let driver: VirtioNICDriverWrapper<T> = VirtioNICDriverWrapper(UnsafeCell::new(driver));
10613776c11Slogin         let result = Arc::new(VirtioInterface {
10713776c11Slogin             driver,
10813776c11Slogin             iface_id,
10913776c11Slogin             iface: SpinLock::new(iface),
11013776c11Slogin             name: format!("eth{}", iface_id),
11113776c11Slogin         });
11213776c11Slogin 
11313776c11Slogin         return result;
11413776c11Slogin     }
11513776c11Slogin }
11613776c11Slogin 
11713776c11Slogin impl<T: 'static + Transport> VirtioNICDriver<T> {
11813776c11Slogin     pub fn new(driver_net: VirtIONet<HalImpl, T, 2>) -> Self {
11913776c11Slogin         let mut iface_config = smoltcp::iface::Config::new();
12013776c11Slogin 
12113776c11Slogin         // todo: 随机设定这个值。
12213776c11Slogin         // 参见 https://docs.rs/smoltcp/latest/smoltcp/iface/struct.Config.html#structfield.random_seed
12313776c11Slogin         iface_config.random_seed = 12345;
12413776c11Slogin 
12513776c11Slogin         iface_config.hardware_addr = Some(wire::HardwareAddress::Ethernet(
12613776c11Slogin             smoltcp::wire::EthernetAddress(driver_net.mac_address()),
12713776c11Slogin         ));
12813776c11Slogin 
12913776c11Slogin         let inner: Arc<SpinLock<VirtIONet<HalImpl, T, 2>>> = Arc::new(SpinLock::new(driver_net));
13013776c11Slogin         let result = VirtioNICDriver { inner };
13113776c11Slogin         return result;
13213776c11Slogin     }
13313776c11Slogin }
13413776c11Slogin 
13513776c11Slogin pub struct VirtioNetToken<T: Transport> {
13613776c11Slogin     driver: VirtioNICDriver<T>,
13713776c11Slogin     rx_buffer: Option<virtio_drivers::device::net::RxBuffer>,
13813776c11Slogin }
13913776c11Slogin 
14013776c11Slogin impl<'a, T: Transport> VirtioNetToken<T> {
14113776c11Slogin     pub fn new(
14213776c11Slogin         driver: VirtioNICDriver<T>,
14313776c11Slogin         rx_buffer: Option<virtio_drivers::device::net::RxBuffer>,
14413776c11Slogin     ) -> Self {
14513776c11Slogin         return Self { driver, rx_buffer };
14613776c11Slogin     }
14713776c11Slogin }
14813776c11Slogin 
14913776c11Slogin impl<T: Transport> phy::Device for VirtioNICDriver<T> {
15013776c11Slogin     type RxToken<'a> = VirtioNetToken<T> where Self: 'a;
15113776c11Slogin     type TxToken<'a> = VirtioNetToken<T> where Self: 'a;
15213776c11Slogin 
15313776c11Slogin     fn receive(
15413776c11Slogin         &mut self,
15513776c11Slogin         _timestamp: smoltcp::time::Instant,
15613776c11Slogin     ) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
15713776c11Slogin         match self.inner.lock().receive() {
15813776c11Slogin             Ok(buf) => Some((
15913776c11Slogin                 VirtioNetToken::new(self.clone(), Some(buf)),
16013776c11Slogin                 VirtioNetToken::new(self.clone(), None),
16113776c11Slogin             )),
16213776c11Slogin             Err(virtio_drivers::Error::NotReady) => None,
16313776c11Slogin             Err(err) => panic!("VirtIO receive failed: {}", err),
16413776c11Slogin         }
16513776c11Slogin     }
16613776c11Slogin 
16713776c11Slogin     fn transmit(&mut self, _timestamp: smoltcp::time::Instant) -> Option<Self::TxToken<'_>> {
16813776c11Slogin         // kdebug!("VirtioNet: transmit");
16913776c11Slogin         if self.inner.lock().can_send() {
17013776c11Slogin             // kdebug!("VirtioNet: can send");
17113776c11Slogin             return Some(VirtioNetToken::new(self.clone(), None));
17213776c11Slogin         } else {
17313776c11Slogin             // kdebug!("VirtioNet: can not send");
17413776c11Slogin             return None;
17513776c11Slogin         }
17613776c11Slogin     }
17713776c11Slogin 
17813776c11Slogin     fn capabilities(&self) -> phy::DeviceCapabilities {
17913776c11Slogin         let mut caps = phy::DeviceCapabilities::default();
18013776c11Slogin         // 网卡的最大传输单元. 请与IP层的MTU进行区分。这个值应当是网卡的最大传输单元,而不是IP层的MTU。
18113776c11Slogin         caps.max_transmission_unit = 2000;
18213776c11Slogin         /*
18313776c11Slogin            Maximum burst size, in terms of MTU.
18413776c11Slogin            The network device is unable to send or receive bursts large than the value returned by this function.
18513776c11Slogin            If None, there is no fixed limit on burst size, e.g. if network buffers are dynamically allocated.
18613776c11Slogin         */
18713776c11Slogin         caps.max_burst_size = Some(1);
18813776c11Slogin         return caps;
18913776c11Slogin     }
19013776c11Slogin }
19113776c11Slogin 
19213776c11Slogin impl<T: Transport> phy::TxToken for VirtioNetToken<T> {
19313776c11Slogin     fn consume<R, F>(self, len: usize, f: F) -> R
19413776c11Slogin     where
19513776c11Slogin         F: FnOnce(&mut [u8]) -> R,
19613776c11Slogin     {
19713776c11Slogin         // // 为了线程安全,这里需要对VirtioNet进行加【写锁】,以保证对设备的互斥访问。
19813776c11Slogin 
19913776c11Slogin         let mut driver_net = self.driver.inner.lock();
20013776c11Slogin         let mut tx_buf = driver_net.new_tx_buffer(len);
20113776c11Slogin         let result = f(tx_buf.packet_mut());
20213776c11Slogin         driver_net.send(tx_buf).expect("virtio_net send failed");
20313776c11Slogin         return result;
20413776c11Slogin     }
20513776c11Slogin }
20613776c11Slogin 
20713776c11Slogin impl<T: Transport> phy::RxToken for VirtioNetToken<T> {
20813776c11Slogin     fn consume<R, F>(self, f: F) -> R
20913776c11Slogin     where
21013776c11Slogin         F: FnOnce(&mut [u8]) -> R,
21113776c11Slogin     {
21213776c11Slogin         // 为了线程安全,这里需要对VirtioNet进行加【写锁】,以保证对设备的互斥访问。
21313776c11Slogin         let mut rx_buf = self.rx_buffer.unwrap();
21413776c11Slogin         let result = f(rx_buf.packet_mut());
21513776c11Slogin         self.driver
21613776c11Slogin             .inner
21713776c11Slogin             .lock()
21813776c11Slogin             .recycle_rx_buffer(rx_buf)
21913776c11Slogin             .expect("virtio_net recv failed");
22013776c11Slogin         result
22113776c11Slogin     }
22213776c11Slogin }
22313776c11Slogin 
22413776c11Slogin /// @brief virtio-net 驱动的初始化与测试
22513776c11Slogin pub fn virtio_net<T: Transport + 'static>(transport: T) {
22613776c11Slogin     let driver_net: VirtIONet<HalImpl, T, 2> =
22713776c11Slogin         match VirtIONet::<HalImpl, T, 2>::new(transport, 4096) {
22813776c11Slogin             Ok(net) => net,
22913776c11Slogin             Err(_) => {
23013776c11Slogin                 kerror!("VirtIONet init failed");
23113776c11Slogin                 return;
23213776c11Slogin             }
23313776c11Slogin         };
23413776c11Slogin     let mac = smoltcp::wire::EthernetAddress::from_bytes(&driver_net.mac_address());
23513776c11Slogin     let driver: VirtioNICDriver<T> = VirtioNICDriver::new(driver_net);
23613776c11Slogin     let iface = VirtioInterface::new(driver);
237*06d5e247SLoGin     let name = iface.name.clone();
23813776c11Slogin     // 将网卡的接口信息注册到全局的网卡接口信息表中
23913776c11Slogin     NET_DRIVERS.write().insert(iface.nic_id(), iface.clone());
24013776c11Slogin     kinfo!(
24113776c11Slogin         "Virtio-net driver init successfully!\tNetDevID: [{}], MAC: [{}]",
242*06d5e247SLoGin         name,
24313776c11Slogin         mac
24413776c11Slogin     );
24513776c11Slogin }
24613776c11Slogin 
247*06d5e247SLoGin impl<T: Transport + 'static> Driver for VirtioInterface<T> {
248b087521eSChiichen     fn probe(&self, _data: &DevicePrivateData) -> Result<(), DriverError> {
249b087521eSChiichen         todo!()
250b087521eSChiichen     }
251b087521eSChiichen 
252b087521eSChiichen     fn load(
253b087521eSChiichen         &self,
254b087521eSChiichen         _data: DevicePrivateData,
255b087521eSChiichen         _resource: Option<DeviceResource>,
256b087521eSChiichen     ) -> Result<Arc<dyn Device>, DriverError> {
257b087521eSChiichen         todo!()
258b087521eSChiichen     }
259b087521eSChiichen 
260b087521eSChiichen     fn id_table(&self) -> IdTable {
261b087521eSChiichen         todo!()
262b087521eSChiichen     }
263b087521eSChiichen }
264b087521eSChiichen 
265*06d5e247SLoGin impl<T: Transport + 'static> NetDriver for VirtioInterface<T> {
26613776c11Slogin     fn mac(&self) -> smoltcp::wire::EthernetAddress {
26713776c11Slogin         let mac: [u8; 6] = self.driver.inner.lock().mac_address();
26813776c11Slogin         return smoltcp::wire::EthernetAddress::from_bytes(&mac);
26913776c11Slogin     }
27013776c11Slogin 
27113776c11Slogin     #[inline]
27213776c11Slogin     fn nic_id(&self) -> usize {
27313776c11Slogin         return self.iface_id;
27413776c11Slogin     }
27513776c11Slogin 
27613776c11Slogin     #[inline]
27713776c11Slogin     fn name(&self) -> String {
27813776c11Slogin         return self.name.clone();
27913776c11Slogin     }
28013776c11Slogin 
28113776c11Slogin     fn update_ip_addrs(&self, ip_addrs: &[wire::IpCidr]) -> Result<(), SystemError> {
28213776c11Slogin         if ip_addrs.len() != 1 {
28313776c11Slogin             return Err(SystemError::EINVAL);
28413776c11Slogin         }
28513776c11Slogin 
28613776c11Slogin         self.iface.lock().update_ip_addrs(|addrs| {
28713776c11Slogin             let dest = addrs.iter_mut().next();
28813776c11Slogin             if let None = dest {
28913776c11Slogin                 addrs.push(ip_addrs[0]).expect("Push ipCidr failed: full");
29013776c11Slogin             } else {
29113776c11Slogin                 let dest = dest.unwrap();
29213776c11Slogin                 *dest = ip_addrs[0];
29313776c11Slogin             }
29413776c11Slogin         });
29513776c11Slogin         return Ok(());
29613776c11Slogin     }
29713776c11Slogin 
29813776c11Slogin     fn poll(
29913776c11Slogin         &self,
30013776c11Slogin         sockets: &mut smoltcp::iface::SocketSet,
30113776c11Slogin     ) -> Result<(), crate::syscall::SystemError> {
30213776c11Slogin         let timestamp: smoltcp::time::Instant = Instant::now().into();
30313776c11Slogin         let mut guard = self.iface.lock();
30413776c11Slogin         let poll_res = guard.poll(timestamp, self.driver.force_get_mut(), sockets);
30513776c11Slogin         // todo: notify!!!
30613776c11Slogin         // kdebug!("Virtio Interface poll:{poll_res}");
30713776c11Slogin         if poll_res {
30813776c11Slogin             return Ok(());
30913776c11Slogin         }
31079a452ceShoumkh         return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
31113776c11Slogin     }
31213776c11Slogin 
31313776c11Slogin     #[inline(always)]
31413776c11Slogin     fn inner_iface(&self) -> &SpinLock<smoltcp::iface::Interface> {
31513776c11Slogin         return &self.iface;
31613776c11Slogin     }
31713776c11Slogin     // fn as_any_ref(&'static self) -> &'static dyn core::any::Any {
31813776c11Slogin     //     return self;
31913776c11Slogin     // }
32013776c11Slogin }
32113776c11Slogin 
322*06d5e247SLoGin impl<T: Transport + 'static> KObject for VirtioInterface<T> {
323*06d5e247SLoGin     fn as_any_ref(&self) -> &dyn core::any::Any {
324*06d5e247SLoGin         self
325*06d5e247SLoGin     }
326*06d5e247SLoGin 
327*06d5e247SLoGin     fn set_inode(&self, _inode: Option<Arc<crate::filesystem::kernfs::KernFSInode>>) {
328*06d5e247SLoGin         todo!()
329*06d5e247SLoGin     }
330*06d5e247SLoGin 
331*06d5e247SLoGin     fn inode(&self) -> Option<Arc<crate::filesystem::kernfs::KernFSInode>> {
332*06d5e247SLoGin         todo!()
333*06d5e247SLoGin     }
334*06d5e247SLoGin 
335*06d5e247SLoGin     fn parent(&self) -> Option<alloc::sync::Weak<dyn KObject>> {
336*06d5e247SLoGin         todo!()
337*06d5e247SLoGin     }
338*06d5e247SLoGin 
339*06d5e247SLoGin     fn set_parent(&self, _parent: Option<alloc::sync::Weak<dyn KObject>>) {
340*06d5e247SLoGin         todo!()
341*06d5e247SLoGin     }
342*06d5e247SLoGin 
343*06d5e247SLoGin     fn kset(&self) -> Option<Arc<crate::driver::base::kset::KSet>> {
344*06d5e247SLoGin         todo!()
345*06d5e247SLoGin     }
346*06d5e247SLoGin 
347*06d5e247SLoGin     fn set_kset(&self, _kset: Option<Arc<crate::driver::base::kset::KSet>>) {
348*06d5e247SLoGin         todo!()
349*06d5e247SLoGin     }
350*06d5e247SLoGin 
351*06d5e247SLoGin     fn kobj_type(&self) -> Option<&'static dyn crate::driver::base::kobject::KObjType> {
352*06d5e247SLoGin         todo!()
353*06d5e247SLoGin     }
354*06d5e247SLoGin 
355*06d5e247SLoGin     fn name(&self) -> String {
356*06d5e247SLoGin         self.name.clone()
357*06d5e247SLoGin     }
358*06d5e247SLoGin 
359*06d5e247SLoGin     fn set_name(&self, _name: String) {
360*06d5e247SLoGin         todo!()
361*06d5e247SLoGin     }
362*06d5e247SLoGin 
363*06d5e247SLoGin     fn kobj_state(
364*06d5e247SLoGin         &self,
365*06d5e247SLoGin     ) -> crate::libs::rwlock::RwLockReadGuard<crate::driver::base::kobject::KObjectState> {
366*06d5e247SLoGin         todo!()
367*06d5e247SLoGin     }
368*06d5e247SLoGin 
369*06d5e247SLoGin     fn kobj_state_mut(
370*06d5e247SLoGin         &self,
371*06d5e247SLoGin     ) -> crate::libs::rwlock::RwLockWriteGuard<crate::driver::base::kobject::KObjectState> {
372*06d5e247SLoGin         todo!()
373*06d5e247SLoGin     }
374*06d5e247SLoGin 
375*06d5e247SLoGin     fn set_kobj_state(&self, _state: crate::driver::base::kobject::KObjectState) {
376*06d5e247SLoGin         todo!()
377*06d5e247SLoGin     }
378*06d5e247SLoGin }
379*06d5e247SLoGin 
38013776c11Slogin // 向编译器保证,VirtioNICDriver在线程之间是安全的.
38113776c11Slogin // 由于smoltcp只会在token内真正操作网卡设备,并且在VirtioNetToken的consume
38213776c11Slogin // 方法内,会对VirtioNet进行加【写锁】,因此,能够保证对设备操作的的互斥访问,
38313776c11Slogin // 因此VirtioNICDriver在线程之间是安全的。
38413776c11Slogin // unsafe impl<T: Transport> Sync for VirtioNICDriver<T> {}
38513776c11Slogin // unsafe impl<T: Transport> Send for VirtioNICDriver<T> {}
386