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