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