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