xref: /DragonOS/kernel/src/driver/net/virtio_net.rs (revision 91e9d4ab55ef960f57a1b6287bc523ca4341f67a)
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.write().insert(iface.nic_id(), iface.clone());
238     kinfo!(
239         "Virtio-net driver init successfully!\tNetDevID: [{}], MAC: [{}]",
240         name,
241         mac
242     );
243 }
244 
245 impl<T: Transport + 'static> Driver for VirtioInterface<T> {
246     fn id_table(&self) -> Option<IdTable> {
247         todo!()
248     }
249 
250     fn add_device(&self, _device: Arc<dyn Device>) {
251         todo!()
252     }
253 
254     fn delete_device(&self, _device: &Arc<dyn Device>) {
255         todo!()
256     }
257 
258     fn devices(&self) -> alloc::vec::Vec<Arc<dyn Device>> {
259         todo!()
260     }
261 
262     fn bus(&self) -> Option<Arc<dyn Bus>> {
263         todo!()
264     }
265 
266     fn set_bus(&self, _bus: Option<Arc<dyn Bus>>) {
267         todo!()
268     }
269 }
270 
271 impl<T: Transport + 'static> NetDriver for VirtioInterface<T> {
272     fn mac(&self) -> smoltcp::wire::EthernetAddress {
273         let mac: [u8; 6] = self.driver.inner.lock().mac_address();
274         return smoltcp::wire::EthernetAddress::from_bytes(&mac);
275     }
276 
277     #[inline]
278     fn nic_id(&self) -> usize {
279         return self.iface_id;
280     }
281 
282     #[inline]
283     fn name(&self) -> String {
284         return self.name.clone();
285     }
286 
287     fn update_ip_addrs(&self, ip_addrs: &[wire::IpCidr]) -> Result<(), SystemError> {
288         if ip_addrs.len() != 1 {
289             return Err(SystemError::EINVAL);
290         }
291 
292         self.iface.lock().update_ip_addrs(|addrs| {
293             let dest = addrs.iter_mut().next();
294             if let None = dest {
295                 addrs.push(ip_addrs[0]).expect("Push ipCidr failed: full");
296             } else {
297                 let dest = dest.unwrap();
298                 *dest = ip_addrs[0];
299             }
300         });
301         return Ok(());
302     }
303 
304     fn poll(&self, sockets: &mut smoltcp::iface::SocketSet) -> Result<(), SystemError> {
305         let timestamp: smoltcp::time::Instant = Instant::now().into();
306         let mut guard = self.iface.lock();
307         let poll_res = guard.poll(timestamp, self.driver.force_get_mut(), sockets);
308         // todo: notify!!!
309         // kdebug!("Virtio Interface poll:{poll_res}");
310         if poll_res {
311             return Ok(());
312         }
313         return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
314     }
315 
316     #[inline(always)]
317     fn inner_iface(&self) -> &SpinLock<smoltcp::iface::Interface> {
318         return &self.iface;
319     }
320     // fn as_any_ref(&'static self) -> &'static dyn core::any::Any {
321     //     return self;
322     // }
323 }
324 
325 impl<T: Transport + 'static> KObject for VirtioInterface<T> {
326     fn as_any_ref(&self) -> &dyn core::any::Any {
327         self
328     }
329 
330     fn set_inode(&self, _inode: Option<Arc<crate::filesystem::kernfs::KernFSInode>>) {
331         todo!()
332     }
333 
334     fn inode(&self) -> Option<Arc<crate::filesystem::kernfs::KernFSInode>> {
335         todo!()
336     }
337 
338     fn parent(&self) -> Option<alloc::sync::Weak<dyn KObject>> {
339         todo!()
340     }
341 
342     fn set_parent(&self, _parent: Option<alloc::sync::Weak<dyn KObject>>) {
343         todo!()
344     }
345 
346     fn kset(&self) -> Option<Arc<crate::driver::base::kset::KSet>> {
347         todo!()
348     }
349 
350     fn set_kset(&self, _kset: Option<Arc<crate::driver::base::kset::KSet>>) {
351         todo!()
352     }
353 
354     fn kobj_type(&self) -> Option<&'static dyn crate::driver::base::kobject::KObjType> {
355         todo!()
356     }
357 
358     fn name(&self) -> String {
359         self.name.clone()
360     }
361 
362     fn set_name(&self, _name: String) {
363         todo!()
364     }
365 
366     fn kobj_state(
367         &self,
368     ) -> crate::libs::rwlock::RwLockReadGuard<crate::driver::base::kobject::KObjectState> {
369         todo!()
370     }
371 
372     fn kobj_state_mut(
373         &self,
374     ) -> crate::libs::rwlock::RwLockWriteGuard<crate::driver::base::kobject::KObjectState> {
375         todo!()
376     }
377 
378     fn set_kobj_state(&self, _state: KObjectState) {
379         todo!()
380     }
381 
382     fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
383         todo!()
384     }
385 }
386 
387 // 向编译器保证,VirtioNICDriver在线程之间是安全的.
388 // 由于smoltcp只会在token内真正操作网卡设备,并且在VirtioNetToken的consume
389 // 方法内,会对VirtioNet进行加【写锁】,因此,能够保证对设备操作的的互斥访问,
390 // 因此VirtioNICDriver在线程之间是安全的。
391 // unsafe impl<T: Transport> Sync for VirtioNICDriver<T> {}
392 // unsafe impl<T: Transport> Send for VirtioNICDriver<T> {}
393