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