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