xref: /DragonOS/kernel/src/driver/net/virtio_net.rs (revision 406099704eb939ae23b18f0cfb3ed36c534c1c84)
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::{
1306d5e247SLoGin         base::{
14a03c4f9dSLoGin             device::{bus::Bus, driver::Driver, Device, IdTable},
15a03c4f9dSLoGin             kobject::{KObjType, KObject, KObjectState},
1606d5e247SLoGin         },
17b087521eSChiichen         virtio::virtio_impl::HalImpl,
18d470019bSLoGin     },
19d470019bSLoGin     kerror, kinfo,
2013776c11Slogin     libs::spinlock::SpinLock,
2113776c11Slogin     net::{generate_iface_id, NET_DRIVERS},
2213776c11Slogin     syscall::SystemError,
2313776c11Slogin     time::Instant,
2413776c11Slogin };
2513776c11Slogin 
2613776c11Slogin use super::NetDriver;
2713776c11Slogin 
2813776c11Slogin /// @brief Virtio网络设备驱动(加锁)
2913776c11Slogin pub struct VirtioNICDriver<T: Transport> {
3013776c11Slogin     pub inner: Arc<SpinLock<VirtIONet<HalImpl, T, 2>>>,
3113776c11Slogin }
3213776c11Slogin 
3313776c11Slogin impl<T: Transport> Clone for VirtioNICDriver<T> {
3413776c11Slogin     fn clone(&self) -> Self {
3513776c11Slogin         return VirtioNICDriver {
3613776c11Slogin             inner: self.inner.clone(),
3713776c11Slogin         };
3813776c11Slogin     }
3913776c11Slogin }
4013776c11Slogin 
4113776c11Slogin /// @brief 网卡驱动的包裹器,这是为了获取网卡驱动的可变引用而设计的。
4213776c11Slogin /// 由于smoltcp的设计,导致需要在poll的时候获取网卡驱动的可变引用,
4313776c11Slogin /// 同时需要在token的consume里面获取可变引用。为了避免双重加锁,所以需要这个包裹器。
4413776c11Slogin struct VirtioNICDriverWrapper<T: Transport>(UnsafeCell<VirtioNICDriver<T>>);
4513776c11Slogin unsafe impl<T: Transport> Send for VirtioNICDriverWrapper<T> {}
4613776c11Slogin unsafe impl<T: Transport> Sync for VirtioNICDriverWrapper<T> {}
4713776c11Slogin 
4813776c11Slogin impl<T: Transport> Deref for VirtioNICDriverWrapper<T> {
4913776c11Slogin     type Target = VirtioNICDriver<T>;
5013776c11Slogin     fn deref(&self) -> &Self::Target {
5113776c11Slogin         unsafe { &*self.0.get() }
5213776c11Slogin     }
5313776c11Slogin }
5413776c11Slogin impl<T: Transport> DerefMut for VirtioNICDriverWrapper<T> {
5513776c11Slogin     fn deref_mut(&mut self) -> &mut Self::Target {
5613776c11Slogin         unsafe { &mut *self.0.get() }
5713776c11Slogin     }
5813776c11Slogin }
5913776c11Slogin 
6013776c11Slogin impl<T: Transport> VirtioNICDriverWrapper<T> {
6113776c11Slogin     fn force_get_mut(&self) -> &mut VirtioNICDriver<T> {
6213776c11Slogin         unsafe { &mut *self.0.get() }
6313776c11Slogin     }
6413776c11Slogin }
6513776c11Slogin 
6613776c11Slogin impl<T: Transport> Debug for VirtioNICDriver<T> {
6713776c11Slogin     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
6813776c11Slogin         f.debug_struct("VirtioNICDriver").finish()
6913776c11Slogin     }
7013776c11Slogin }
7113776c11Slogin 
7213776c11Slogin pub struct VirtioInterface<T: Transport> {
7313776c11Slogin     driver: VirtioNICDriverWrapper<T>,
7413776c11Slogin     iface_id: usize,
7513776c11Slogin     iface: SpinLock<smoltcp::iface::Interface>,
7613776c11Slogin     name: String,
7713776c11Slogin }
7813776c11Slogin 
7913776c11Slogin impl<T: Transport> Debug for VirtioInterface<T> {
8013776c11Slogin     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8113776c11Slogin         f.debug_struct("VirtioInterface")
8213776c11Slogin             .field("driver", self.driver.deref())
8313776c11Slogin             .field("iface_id", &self.iface_id)
8413776c11Slogin             .field("iface", &"smoltcp::iface::Interface")
8513776c11Slogin             .field("name", &self.name)
8613776c11Slogin             .finish()
8713776c11Slogin     }
8813776c11Slogin }
8913776c11Slogin 
9013776c11Slogin impl<T: Transport> VirtioInterface<T> {
9113776c11Slogin     pub fn new(mut driver: VirtioNICDriver<T>) -> Arc<Self> {
9213776c11Slogin         let iface_id = generate_iface_id();
9313776c11Slogin         let mut iface_config = smoltcp::iface::Config::new();
9413776c11Slogin 
9513776c11Slogin         // todo: 随机设定这个值。
9613776c11Slogin         // 参见 https://docs.rs/smoltcp/latest/smoltcp/iface/struct.Config.html#structfield.random_seed
9713776c11Slogin         iface_config.random_seed = 12345;
9813776c11Slogin 
9913776c11Slogin         iface_config.hardware_addr = Some(wire::HardwareAddress::Ethernet(
10013776c11Slogin             smoltcp::wire::EthernetAddress(driver.inner.lock().mac_address()),
10113776c11Slogin         ));
10213776c11Slogin         let iface = smoltcp::iface::Interface::new(iface_config, &mut driver);
10313776c11Slogin 
10413776c11Slogin         let driver: VirtioNICDriverWrapper<T> = VirtioNICDriverWrapper(UnsafeCell::new(driver));
10513776c11Slogin         let result = Arc::new(VirtioInterface {
10613776c11Slogin             driver,
10713776c11Slogin             iface_id,
10813776c11Slogin             iface: SpinLock::new(iface),
10913776c11Slogin             name: format!("eth{}", iface_id),
11013776c11Slogin         });
11113776c11Slogin 
11213776c11Slogin         return result;
11313776c11Slogin     }
11413776c11Slogin }
11513776c11Slogin 
11613776c11Slogin impl<T: 'static + Transport> VirtioNICDriver<T> {
11713776c11Slogin     pub fn new(driver_net: VirtIONet<HalImpl, T, 2>) -> Self {
11813776c11Slogin         let mut iface_config = smoltcp::iface::Config::new();
11913776c11Slogin 
12013776c11Slogin         // todo: 随机设定这个值。
12113776c11Slogin         // 参见 https://docs.rs/smoltcp/latest/smoltcp/iface/struct.Config.html#structfield.random_seed
12213776c11Slogin         iface_config.random_seed = 12345;
12313776c11Slogin 
12413776c11Slogin         iface_config.hardware_addr = Some(wire::HardwareAddress::Ethernet(
12513776c11Slogin             smoltcp::wire::EthernetAddress(driver_net.mac_address()),
12613776c11Slogin         ));
12713776c11Slogin 
12813776c11Slogin         let inner: Arc<SpinLock<VirtIONet<HalImpl, T, 2>>> = Arc::new(SpinLock::new(driver_net));
12913776c11Slogin         let result = VirtioNICDriver { inner };
13013776c11Slogin         return result;
13113776c11Slogin     }
13213776c11Slogin }
13313776c11Slogin 
13413776c11Slogin pub struct VirtioNetToken<T: Transport> {
13513776c11Slogin     driver: VirtioNICDriver<T>,
13613776c11Slogin     rx_buffer: Option<virtio_drivers::device::net::RxBuffer>,
13713776c11Slogin }
13813776c11Slogin 
13913776c11Slogin impl<'a, T: Transport> VirtioNetToken<T> {
14013776c11Slogin     pub fn new(
14113776c11Slogin         driver: VirtioNICDriver<T>,
14213776c11Slogin         rx_buffer: Option<virtio_drivers::device::net::RxBuffer>,
14313776c11Slogin     ) -> Self {
14413776c11Slogin         return Self { driver, rx_buffer };
14513776c11Slogin     }
14613776c11Slogin }
14713776c11Slogin 
14813776c11Slogin impl<T: Transport> phy::Device for VirtioNICDriver<T> {
14913776c11Slogin     type RxToken<'a> = VirtioNetToken<T> where Self: 'a;
15013776c11Slogin     type TxToken<'a> = VirtioNetToken<T> where Self: 'a;
15113776c11Slogin 
15213776c11Slogin     fn receive(
15313776c11Slogin         &mut self,
15413776c11Slogin         _timestamp: smoltcp::time::Instant,
15513776c11Slogin     ) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
15613776c11Slogin         match self.inner.lock().receive() {
15713776c11Slogin             Ok(buf) => Some((
15813776c11Slogin                 VirtioNetToken::new(self.clone(), Some(buf)),
15913776c11Slogin                 VirtioNetToken::new(self.clone(), None),
16013776c11Slogin             )),
16113776c11Slogin             Err(virtio_drivers::Error::NotReady) => None,
16213776c11Slogin             Err(err) => panic!("VirtIO receive failed: {}", err),
16313776c11Slogin         }
16413776c11Slogin     }
16513776c11Slogin 
16613776c11Slogin     fn transmit(&mut self, _timestamp: smoltcp::time::Instant) -> Option<Self::TxToken<'_>> {
16713776c11Slogin         // kdebug!("VirtioNet: transmit");
168*40609970SGnoCiYeH         if self.inner.lock_irqsave().can_send() {
16913776c11Slogin             // kdebug!("VirtioNet: can send");
17013776c11Slogin             return Some(VirtioNetToken::new(self.clone(), None));
17113776c11Slogin         } else {
17213776c11Slogin             // kdebug!("VirtioNet: can not send");
17313776c11Slogin             return None;
17413776c11Slogin         }
17513776c11Slogin     }
17613776c11Slogin 
17713776c11Slogin     fn capabilities(&self) -> phy::DeviceCapabilities {
17813776c11Slogin         let mut caps = phy::DeviceCapabilities::default();
17913776c11Slogin         // 网卡的最大传输单元. 请与IP层的MTU进行区分。这个值应当是网卡的最大传输单元,而不是IP层的MTU。
18013776c11Slogin         caps.max_transmission_unit = 2000;
18113776c11Slogin         /*
18213776c11Slogin            Maximum burst size, in terms of MTU.
18313776c11Slogin            The network device is unable to send or receive bursts large than the value returned by this function.
18413776c11Slogin            If None, there is no fixed limit on burst size, e.g. if network buffers are dynamically allocated.
18513776c11Slogin         */
18613776c11Slogin         caps.max_burst_size = Some(1);
18713776c11Slogin         return caps;
18813776c11Slogin     }
18913776c11Slogin }
19013776c11Slogin 
19113776c11Slogin impl<T: Transport> phy::TxToken for VirtioNetToken<T> {
19213776c11Slogin     fn consume<R, F>(self, len: usize, f: F) -> R
19313776c11Slogin     where
19413776c11Slogin         F: FnOnce(&mut [u8]) -> R,
19513776c11Slogin     {
19613776c11Slogin         // // 为了线程安全,这里需要对VirtioNet进行加【写锁】,以保证对设备的互斥访问。
19713776c11Slogin 
19813776c11Slogin         let mut driver_net = self.driver.inner.lock();
19913776c11Slogin         let mut tx_buf = driver_net.new_tx_buffer(len);
20013776c11Slogin         let result = f(tx_buf.packet_mut());
20113776c11Slogin         driver_net.send(tx_buf).expect("virtio_net send failed");
20213776c11Slogin         return result;
20313776c11Slogin     }
20413776c11Slogin }
20513776c11Slogin 
20613776c11Slogin impl<T: Transport> phy::RxToken for VirtioNetToken<T> {
20713776c11Slogin     fn consume<R, F>(self, f: F) -> R
20813776c11Slogin     where
20913776c11Slogin         F: FnOnce(&mut [u8]) -> R,
21013776c11Slogin     {
21113776c11Slogin         // 为了线程安全,这里需要对VirtioNet进行加【写锁】,以保证对设备的互斥访问。
21213776c11Slogin         let mut rx_buf = self.rx_buffer.unwrap();
21313776c11Slogin         let result = f(rx_buf.packet_mut());
21413776c11Slogin         self.driver
21513776c11Slogin             .inner
21613776c11Slogin             .lock()
21713776c11Slogin             .recycle_rx_buffer(rx_buf)
21813776c11Slogin             .expect("virtio_net recv failed");
21913776c11Slogin         result
22013776c11Slogin     }
22113776c11Slogin }
22213776c11Slogin 
22313776c11Slogin /// @brief virtio-net 驱动的初始化与测试
22413776c11Slogin pub fn virtio_net<T: Transport + 'static>(transport: T) {
22513776c11Slogin     let driver_net: VirtIONet<HalImpl, T, 2> =
22613776c11Slogin         match VirtIONet::<HalImpl, T, 2>::new(transport, 4096) {
22713776c11Slogin             Ok(net) => net,
22813776c11Slogin             Err(_) => {
22913776c11Slogin                 kerror!("VirtIONet init failed");
23013776c11Slogin                 return;
23113776c11Slogin             }
23213776c11Slogin         };
23313776c11Slogin     let mac = smoltcp::wire::EthernetAddress::from_bytes(&driver_net.mac_address());
23413776c11Slogin     let driver: VirtioNICDriver<T> = VirtioNICDriver::new(driver_net);
23513776c11Slogin     let iface = VirtioInterface::new(driver);
23606d5e247SLoGin     let name = iface.name.clone();
23713776c11Slogin     // 将网卡的接口信息注册到全局的网卡接口信息表中
23813776c11Slogin     NET_DRIVERS.write().insert(iface.nic_id(), iface.clone());
23913776c11Slogin     kinfo!(
24013776c11Slogin         "Virtio-net driver init successfully!\tNetDevID: [{}], MAC: [{}]",
24106d5e247SLoGin         name,
24213776c11Slogin         mac
24313776c11Slogin     );
24413776c11Slogin }
24513776c11Slogin 
24606d5e247SLoGin impl<T: Transport + 'static> Driver for VirtioInterface<T> {
247a03c4f9dSLoGin     fn id_table(&self) -> Option<IdTable> {
248b087521eSChiichen         todo!()
249b087521eSChiichen     }
250b087521eSChiichen 
251a03c4f9dSLoGin     fn add_device(&self, _device: Arc<dyn Device>) {
252b087521eSChiichen         todo!()
253b087521eSChiichen     }
254b087521eSChiichen 
255a03c4f9dSLoGin     fn delete_device(&self, _device: &Arc<dyn Device>) {
256a03c4f9dSLoGin         todo!()
257a03c4f9dSLoGin     }
258a03c4f9dSLoGin 
259a03c4f9dSLoGin     fn devices(&self) -> alloc::vec::Vec<Arc<dyn Device>> {
260a03c4f9dSLoGin         todo!()
261a03c4f9dSLoGin     }
262a03c4f9dSLoGin 
263a03c4f9dSLoGin     fn bus(&self) -> Option<Arc<dyn Bus>> {
264a03c4f9dSLoGin         todo!()
265a03c4f9dSLoGin     }
266a03c4f9dSLoGin 
267a03c4f9dSLoGin     fn set_bus(&self, _bus: Option<Arc<dyn Bus>>) {
268b087521eSChiichen         todo!()
269b087521eSChiichen     }
270b087521eSChiichen }
271b087521eSChiichen 
27206d5e247SLoGin impl<T: Transport + 'static> NetDriver for VirtioInterface<T> {
27313776c11Slogin     fn mac(&self) -> smoltcp::wire::EthernetAddress {
27413776c11Slogin         let mac: [u8; 6] = self.driver.inner.lock().mac_address();
27513776c11Slogin         return smoltcp::wire::EthernetAddress::from_bytes(&mac);
27613776c11Slogin     }
27713776c11Slogin 
27813776c11Slogin     #[inline]
27913776c11Slogin     fn nic_id(&self) -> usize {
28013776c11Slogin         return self.iface_id;
28113776c11Slogin     }
28213776c11Slogin 
28313776c11Slogin     #[inline]
28413776c11Slogin     fn name(&self) -> String {
28513776c11Slogin         return self.name.clone();
28613776c11Slogin     }
28713776c11Slogin 
28813776c11Slogin     fn update_ip_addrs(&self, ip_addrs: &[wire::IpCidr]) -> Result<(), SystemError> {
28913776c11Slogin         if ip_addrs.len() != 1 {
29013776c11Slogin             return Err(SystemError::EINVAL);
29113776c11Slogin         }
29213776c11Slogin 
29313776c11Slogin         self.iface.lock().update_ip_addrs(|addrs| {
29413776c11Slogin             let dest = addrs.iter_mut().next();
29513776c11Slogin             if let None = dest {
29613776c11Slogin                 addrs.push(ip_addrs[0]).expect("Push ipCidr failed: full");
29713776c11Slogin             } else {
29813776c11Slogin                 let dest = dest.unwrap();
29913776c11Slogin                 *dest = ip_addrs[0];
30013776c11Slogin             }
30113776c11Slogin         });
30213776c11Slogin         return Ok(());
30313776c11Slogin     }
30413776c11Slogin 
30513776c11Slogin     fn poll(
30613776c11Slogin         &self,
30713776c11Slogin         sockets: &mut smoltcp::iface::SocketSet,
30813776c11Slogin     ) -> Result<(), crate::syscall::SystemError> {
30913776c11Slogin         let timestamp: smoltcp::time::Instant = Instant::now().into();
31013776c11Slogin         let mut guard = self.iface.lock();
31113776c11Slogin         let poll_res = guard.poll(timestamp, self.driver.force_get_mut(), sockets);
31213776c11Slogin         // todo: notify!!!
313971462beSGnoCiYeH         // kdebug!("Virtio Interface poll:{poll_res}");
31413776c11Slogin         if poll_res {
31513776c11Slogin             return Ok(());
31613776c11Slogin         }
31779a452ceShoumkh         return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
31813776c11Slogin     }
31913776c11Slogin 
32013776c11Slogin     #[inline(always)]
32113776c11Slogin     fn inner_iface(&self) -> &SpinLock<smoltcp::iface::Interface> {
32213776c11Slogin         return &self.iface;
32313776c11Slogin     }
32413776c11Slogin     // fn as_any_ref(&'static self) -> &'static dyn core::any::Any {
32513776c11Slogin     //     return self;
32613776c11Slogin     // }
32713776c11Slogin }
32813776c11Slogin 
32906d5e247SLoGin impl<T: Transport + 'static> KObject for VirtioInterface<T> {
33006d5e247SLoGin     fn as_any_ref(&self) -> &dyn core::any::Any {
33106d5e247SLoGin         self
33206d5e247SLoGin     }
33306d5e247SLoGin 
33406d5e247SLoGin     fn set_inode(&self, _inode: Option<Arc<crate::filesystem::kernfs::KernFSInode>>) {
33506d5e247SLoGin         todo!()
33606d5e247SLoGin     }
33706d5e247SLoGin 
33806d5e247SLoGin     fn inode(&self) -> Option<Arc<crate::filesystem::kernfs::KernFSInode>> {
33906d5e247SLoGin         todo!()
34006d5e247SLoGin     }
34106d5e247SLoGin 
34206d5e247SLoGin     fn parent(&self) -> Option<alloc::sync::Weak<dyn KObject>> {
34306d5e247SLoGin         todo!()
34406d5e247SLoGin     }
34506d5e247SLoGin 
34606d5e247SLoGin     fn set_parent(&self, _parent: Option<alloc::sync::Weak<dyn KObject>>) {
34706d5e247SLoGin         todo!()
34806d5e247SLoGin     }
34906d5e247SLoGin 
35006d5e247SLoGin     fn kset(&self) -> Option<Arc<crate::driver::base::kset::KSet>> {
35106d5e247SLoGin         todo!()
35206d5e247SLoGin     }
35306d5e247SLoGin 
35406d5e247SLoGin     fn set_kset(&self, _kset: Option<Arc<crate::driver::base::kset::KSet>>) {
35506d5e247SLoGin         todo!()
35606d5e247SLoGin     }
35706d5e247SLoGin 
35806d5e247SLoGin     fn kobj_type(&self) -> Option<&'static dyn crate::driver::base::kobject::KObjType> {
35906d5e247SLoGin         todo!()
36006d5e247SLoGin     }
36106d5e247SLoGin 
36206d5e247SLoGin     fn name(&self) -> String {
36306d5e247SLoGin         self.name.clone()
36406d5e247SLoGin     }
36506d5e247SLoGin 
36606d5e247SLoGin     fn set_name(&self, _name: String) {
36706d5e247SLoGin         todo!()
36806d5e247SLoGin     }
36906d5e247SLoGin 
37006d5e247SLoGin     fn kobj_state(
37106d5e247SLoGin         &self,
37206d5e247SLoGin     ) -> crate::libs::rwlock::RwLockReadGuard<crate::driver::base::kobject::KObjectState> {
37306d5e247SLoGin         todo!()
37406d5e247SLoGin     }
37506d5e247SLoGin 
37606d5e247SLoGin     fn kobj_state_mut(
37706d5e247SLoGin         &self,
37806d5e247SLoGin     ) -> crate::libs::rwlock::RwLockWriteGuard<crate::driver::base::kobject::KObjectState> {
37906d5e247SLoGin         todo!()
38006d5e247SLoGin     }
38106d5e247SLoGin 
382a03c4f9dSLoGin     fn set_kobj_state(&self, _state: KObjectState) {
383a03c4f9dSLoGin         todo!()
384a03c4f9dSLoGin     }
385a03c4f9dSLoGin 
386a03c4f9dSLoGin     fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
38706d5e247SLoGin         todo!()
38806d5e247SLoGin     }
38906d5e247SLoGin }
39006d5e247SLoGin 
39113776c11Slogin // 向编译器保证,VirtioNICDriver在线程之间是安全的.
39213776c11Slogin // 由于smoltcp只会在token内真正操作网卡设备,并且在VirtioNetToken的consume
39313776c11Slogin // 方法内,会对VirtioNet进行加【写锁】,因此,能够保证对设备操作的的互斥访问,
39413776c11Slogin // 因此VirtioNICDriver在线程之间是安全的。
39513776c11Slogin // unsafe impl<T: Transport> Sync for VirtioNICDriver<T> {}
39613776c11Slogin // unsafe impl<T: Transport> Send for VirtioNICDriver<T> {}
397