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