net.rs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. use core::mem::{size_of, MaybeUninit};
  2. use super::*;
  3. use crate::transport::Transport;
  4. use crate::volatile::{volread, ReadOnly, Volatile};
  5. use bitflags::*;
  6. use core::hint::spin_loop;
  7. use log::*;
  8. /// The virtio network device is a virtual ethernet card.
  9. ///
  10. /// It has enhanced rapidly and demonstrates clearly how support for new
  11. /// features are added to an existing device.
  12. /// Empty buffers are placed in one virtqueue for receiving packets, and
  13. /// outgoing packets are enqueued into another for transmission in that order.
  14. /// A third command queue is used to control advanced filtering features.
  15. pub struct VirtIONet<H: Hal, T: Transport> {
  16. transport: T,
  17. mac: EthernetAddress,
  18. recv_queue: VirtQueue<H>,
  19. send_queue: VirtQueue<H>,
  20. }
  21. impl<H: Hal, T: Transport> VirtIONet<H, T> {
  22. /// Create a new VirtIO-Net driver.
  23. pub fn new(mut transport: T) -> Result<Self> {
  24. transport.begin_init(|features| {
  25. let features = Features::from_bits_truncate(features);
  26. info!("Device features {:?}", features);
  27. let supported_features = Features::MAC | Features::STATUS;
  28. (features & supported_features).bits()
  29. });
  30. // read configuration space
  31. let config = transport.config_space().cast::<Config>();
  32. let mac;
  33. // Safe because config points to a valid MMIO region for the config space.
  34. unsafe {
  35. mac = volread!(config, mac);
  36. debug!("Got MAC={:?}, status={:?}", mac, volread!(config, status));
  37. }
  38. let queue_num = 2; // for simplicity
  39. let recv_queue = VirtQueue::new(&mut transport, QUEUE_RECEIVE, queue_num)?;
  40. let send_queue = VirtQueue::new(&mut transport, QUEUE_TRANSMIT, queue_num)?;
  41. transport.finish_init();
  42. Ok(VirtIONet {
  43. transport,
  44. mac,
  45. recv_queue,
  46. send_queue,
  47. })
  48. }
  49. /// Acknowledge interrupt.
  50. pub fn ack_interrupt(&mut self) -> bool {
  51. self.transport.ack_interrupt()
  52. }
  53. /// Get MAC address.
  54. pub fn mac(&self) -> EthernetAddress {
  55. self.mac
  56. }
  57. /// Whether can send packet.
  58. pub fn can_send(&self) -> bool {
  59. self.send_queue.available_desc() >= 2
  60. }
  61. /// Whether can receive packet.
  62. pub fn can_recv(&self) -> bool {
  63. self.recv_queue.can_pop()
  64. }
  65. /// Receive a packet.
  66. pub fn recv(&mut self, buf: &mut [u8]) -> Result<usize> {
  67. let mut header = MaybeUninit::<Header>::uninit();
  68. let header_buf = unsafe { (*header.as_mut_ptr()).as_buf_mut() };
  69. self.recv_queue.add(&[], &[header_buf, buf])?;
  70. self.transport.notify(QUEUE_RECEIVE as u32);
  71. while !self.recv_queue.can_pop() {
  72. spin_loop();
  73. }
  74. let (_, len) = self.recv_queue.pop_used()?;
  75. // let header = unsafe { header.assume_init() };
  76. Ok(len as usize - size_of::<Header>())
  77. }
  78. /// Send a packet.
  79. pub fn send(&mut self, buf: &[u8]) -> Result {
  80. let header = unsafe { MaybeUninit::<Header>::zeroed().assume_init() };
  81. self.send_queue.add(&[header.as_buf(), buf], &[])?;
  82. self.transport.notify(QUEUE_TRANSMIT as u32);
  83. while !self.send_queue.can_pop() {
  84. spin_loop();
  85. }
  86. self.send_queue.pop_used()?;
  87. Ok(())
  88. }
  89. }
  90. bitflags! {
  91. struct Features: u64 {
  92. /// Device handles packets with partial checksum.
  93. /// This "checksum offload" is a common feature on modern network cards.
  94. const CSUM = 1 << 0;
  95. /// Driver handles packets with partial checksum.
  96. const GUEST_CSUM = 1 << 1;
  97. /// Control channel offloads reconfiguration support.
  98. const CTRL_GUEST_OFFLOADS = 1 << 2;
  99. /// Device maximum MTU reporting is supported.
  100. ///
  101. /// If offered by the device, device advises driver about the value of
  102. /// its maximum MTU. If negotiated, the driver uses mtu as the maximum
  103. /// MTU value.
  104. const MTU = 1 << 3;
  105. /// Device has given MAC address.
  106. const MAC = 1 << 5;
  107. /// Device handles packets with any GSO type. (legacy)
  108. const GSO = 1 << 6;
  109. /// Driver can receive TSOv4.
  110. const GUEST_TSO4 = 1 << 7;
  111. /// Driver can receive TSOv6.
  112. const GUEST_TSO6 = 1 << 8;
  113. /// Driver can receive TSO with ECN.
  114. const GUEST_ECN = 1 << 9;
  115. /// Driver can receive UFO.
  116. const GUEST_UFO = 1 << 10;
  117. /// Device can receive TSOv4.
  118. const HOST_TSO4 = 1 << 11;
  119. /// Device can receive TSOv6.
  120. const HOST_TSO6 = 1 << 12;
  121. /// Device can receive TSO with ECN.
  122. const HOST_ECN = 1 << 13;
  123. /// Device can receive UFO.
  124. const HOST_UFO = 1 << 14;
  125. /// Driver can merge receive buffers.
  126. const MRG_RXBUF = 1 << 15;
  127. /// Configuration status field is available.
  128. const STATUS = 1 << 16;
  129. /// Control channel is available.
  130. const CTRL_VQ = 1 << 17;
  131. /// Control channel RX mode support.
  132. const CTRL_RX = 1 << 18;
  133. /// Control channel VLAN filtering.
  134. const CTRL_VLAN = 1 << 19;
  135. ///
  136. const CTRL_RX_EXTRA = 1 << 20;
  137. /// Driver can send gratuitous packets.
  138. const GUEST_ANNOUNCE = 1 << 21;
  139. /// Device supports multiqueue with automatic receive steering.
  140. const MQ = 1 << 22;
  141. /// Set MAC address through control channel.
  142. const CTL_MAC_ADDR = 1 << 23;
  143. // device independent
  144. const RING_INDIRECT_DESC = 1 << 28;
  145. const RING_EVENT_IDX = 1 << 29;
  146. const VERSION_1 = 1 << 32; // legacy
  147. }
  148. }
  149. bitflags! {
  150. struct Status: u16 {
  151. const LINK_UP = 1;
  152. const ANNOUNCE = 2;
  153. }
  154. }
  155. bitflags! {
  156. struct InterruptStatus : u32 {
  157. const USED_RING_UPDATE = 1 << 0;
  158. const CONFIGURATION_CHANGE = 1 << 1;
  159. }
  160. }
  161. #[repr(C)]
  162. #[derive(Debug)]
  163. struct Config {
  164. mac: ReadOnly<EthernetAddress>,
  165. status: ReadOnly<Status>,
  166. }
  167. type EthernetAddress = [u8; 6];
  168. // virtio 5.1.6 Device Operation
  169. #[repr(C)]
  170. #[derive(Debug)]
  171. struct Header {
  172. flags: Volatile<Flags>,
  173. gso_type: Volatile<GsoType>,
  174. hdr_len: Volatile<u16>, // cannot rely on this
  175. gso_size: Volatile<u16>,
  176. csum_start: Volatile<u16>,
  177. csum_offset: Volatile<u16>,
  178. // payload starts from here
  179. }
  180. unsafe impl AsBuf for Header {}
  181. bitflags! {
  182. struct Flags: u8 {
  183. const NEEDS_CSUM = 1;
  184. const DATA_VALID = 2;
  185. const RSC_INFO = 4;
  186. }
  187. }
  188. #[repr(u8)]
  189. #[derive(Debug, Copy, Clone, Eq, PartialEq)]
  190. enum GsoType {
  191. NONE = 0,
  192. TCPV4 = 1,
  193. UDP = 3,
  194. TCPV6 = 4,
  195. ECN = 0x80,
  196. }
  197. const QUEUE_RECEIVE: usize = 0;
  198. const QUEUE_TRANSMIT: usize = 1;