net.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. //! Driver for VirtIO network devices.
  2. use crate::hal::Hal;
  3. use crate::queue::VirtQueue;
  4. use crate::transport::Transport;
  5. use crate::volatile::{volread, ReadOnly};
  6. use crate::{Error, Result};
  7. use alloc::{vec, vec::Vec};
  8. use bitflags::bitflags;
  9. use core::{convert::TryInto, mem::size_of};
  10. use log::{debug, warn};
  11. use zerocopy::{AsBytes, FromBytes, FromZeroes};
  12. const MAX_BUFFER_LEN: usize = 65535;
  13. const MIN_BUFFER_LEN: usize = 1526;
  14. const NET_HDR_SIZE: usize = size_of::<VirtioNetHdr>();
  15. /// A buffer used for transmitting.
  16. pub struct TxBuffer(Vec<u8>);
  17. /// A buffer used for receiving.
  18. pub struct RxBuffer {
  19. buf: Vec<usize>, // for alignment
  20. packet_len: usize,
  21. idx: u16,
  22. }
  23. impl TxBuffer {
  24. /// Constructs the buffer from the given slice.
  25. pub fn from(buf: &[u8]) -> Self {
  26. Self(Vec::from(buf))
  27. }
  28. /// Returns the network packet length.
  29. pub fn packet_len(&self) -> usize {
  30. self.0.len()
  31. }
  32. /// Returns the network packet as a slice.
  33. pub fn packet(&self) -> &[u8] {
  34. self.0.as_slice()
  35. }
  36. /// Returns the network packet as a mutable slice.
  37. pub fn packet_mut(&mut self) -> &mut [u8] {
  38. self.0.as_mut_slice()
  39. }
  40. }
  41. impl RxBuffer {
  42. /// Allocates a new buffer with length `buf_len`.
  43. fn new(idx: usize, buf_len: usize) -> Self {
  44. Self {
  45. buf: vec![0; buf_len / size_of::<usize>()],
  46. packet_len: 0,
  47. idx: idx.try_into().unwrap(),
  48. }
  49. }
  50. /// Set the network packet length.
  51. fn set_packet_len(&mut self, packet_len: usize) {
  52. self.packet_len = packet_len
  53. }
  54. /// Returns the network packet length (witout header).
  55. pub const fn packet_len(&self) -> usize {
  56. self.packet_len
  57. }
  58. /// Returns all data in the buffer, including both the header and the packet.
  59. pub fn as_bytes(&self) -> &[u8] {
  60. self.buf.as_bytes()
  61. }
  62. /// Returns all data in the buffer with the mutable reference,
  63. /// including both the header and the packet.
  64. pub fn as_bytes_mut(&mut self) -> &mut [u8] {
  65. self.buf.as_bytes_mut()
  66. }
  67. /// Returns the reference of the header.
  68. pub fn header(&self) -> &VirtioNetHdr {
  69. unsafe { &*(self.buf.as_ptr() as *const VirtioNetHdr) }
  70. }
  71. /// Returns the network packet as a slice.
  72. pub fn packet(&self) -> &[u8] {
  73. &self.buf.as_bytes()[NET_HDR_SIZE..NET_HDR_SIZE + self.packet_len]
  74. }
  75. /// Returns the network packet as a mutable slice.
  76. pub fn packet_mut(&mut self) -> &mut [u8] {
  77. &mut self.buf.as_bytes_mut()[NET_HDR_SIZE..NET_HDR_SIZE + self.packet_len]
  78. }
  79. }
  80. /// The virtio network device is a virtual ethernet card.
  81. ///
  82. /// It has enhanced rapidly and demonstrates clearly how support for new
  83. /// features are added to an existing device.
  84. /// Empty buffers are placed in one virtqueue for receiving packets, and
  85. /// outgoing packets are enqueued into another for transmission in that order.
  86. /// A third command queue is used to control advanced filtering features.
  87. pub struct VirtIONet<H: Hal, T: Transport, const QUEUE_SIZE: usize> {
  88. transport: T,
  89. mac: EthernetAddress,
  90. recv_queue: VirtQueue<H, QUEUE_SIZE>,
  91. send_queue: VirtQueue<H, QUEUE_SIZE>,
  92. rx_buffers: [Option<RxBuffer>; QUEUE_SIZE],
  93. }
  94. impl<H: Hal, T: Transport, const QUEUE_SIZE: usize> VirtIONet<H, T, QUEUE_SIZE> {
  95. /// Create a new VirtIO-Net driver.
  96. pub fn new(mut transport: T, buf_len: usize) -> Result<Self> {
  97. let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
  98. // read configuration space
  99. let config = transport.config_space::<Config>()?;
  100. let mac;
  101. // Safe because config points to a valid MMIO region for the config space.
  102. unsafe {
  103. mac = volread!(config, mac);
  104. debug!(
  105. "Got MAC={:02x?}, status={:?}",
  106. mac,
  107. volread!(config, status)
  108. );
  109. }
  110. if !(MIN_BUFFER_LEN..=MAX_BUFFER_LEN).contains(&buf_len) {
  111. warn!(
  112. "Receive buffer len {} is not in range [{}, {}]",
  113. buf_len, MIN_BUFFER_LEN, MAX_BUFFER_LEN
  114. );
  115. return Err(Error::InvalidParam);
  116. }
  117. let send_queue = VirtQueue::new(
  118. &mut transport,
  119. QUEUE_TRANSMIT,
  120. false,
  121. negotiated_features.contains(Features::RING_EVENT_IDX),
  122. )?;
  123. let mut recv_queue = VirtQueue::new(
  124. &mut transport,
  125. QUEUE_RECEIVE,
  126. false,
  127. negotiated_features.contains(Features::RING_EVENT_IDX),
  128. )?;
  129. const NONE_BUF: Option<RxBuffer> = None;
  130. let mut rx_buffers = [NONE_BUF; QUEUE_SIZE];
  131. for (i, rx_buf_place) in rx_buffers.iter_mut().enumerate() {
  132. let mut rx_buf = RxBuffer::new(i, buf_len);
  133. // Safe because the buffer lives as long as the queue.
  134. let token = unsafe { recv_queue.add(&[], &mut [rx_buf.as_bytes_mut()])? };
  135. assert_eq!(token, i as u16);
  136. *rx_buf_place = Some(rx_buf);
  137. }
  138. if recv_queue.should_notify() {
  139. transport.notify(QUEUE_RECEIVE);
  140. }
  141. transport.finish_init();
  142. Ok(VirtIONet {
  143. transport,
  144. mac,
  145. recv_queue,
  146. send_queue,
  147. rx_buffers,
  148. })
  149. }
  150. /// Acknowledge interrupt.
  151. pub fn ack_interrupt(&mut self) -> bool {
  152. self.transport.ack_interrupt()
  153. }
  154. /// Get MAC address.
  155. pub fn mac_address(&self) -> EthernetAddress {
  156. self.mac
  157. }
  158. /// Whether can send packet.
  159. pub fn can_send(&self) -> bool {
  160. self.send_queue.available_desc() >= 2
  161. }
  162. /// Whether can receive packet.
  163. pub fn can_recv(&self) -> bool {
  164. self.recv_queue.can_pop()
  165. }
  166. /// Receives a [`RxBuffer`] from network. If currently no data, returns an
  167. /// error with type [`Error::NotReady`].
  168. ///
  169. /// It will try to pop a buffer that completed data reception in the
  170. /// NIC queue.
  171. pub fn receive(&mut self) -> Result<RxBuffer> {
  172. if let Some(token) = self.recv_queue.peek_used() {
  173. let mut rx_buf = self.rx_buffers[token as usize]
  174. .take()
  175. .ok_or(Error::WrongToken)?;
  176. if token != rx_buf.idx {
  177. return Err(Error::WrongToken);
  178. }
  179. // Safe because `token` == `rx_buf.idx`, we are passing the same
  180. // buffer as we passed to `VirtQueue::add` and it is still valid.
  181. let len = unsafe {
  182. self.recv_queue
  183. .pop_used(token, &[], &mut [rx_buf.as_bytes_mut()])?
  184. } as usize;
  185. rx_buf.set_packet_len(len.checked_sub(NET_HDR_SIZE).ok_or(Error::IoError)?);
  186. Ok(rx_buf)
  187. } else {
  188. Err(Error::NotReady)
  189. }
  190. }
  191. /// Gives back the ownership of `rx_buf`, and recycles it for next use.
  192. ///
  193. /// It will add the buffer back to the NIC queue.
  194. pub fn recycle_rx_buffer(&mut self, mut rx_buf: RxBuffer) -> Result {
  195. // Safe because we take the ownership of `rx_buf` back to `rx_buffers`,
  196. // it lives as long as the queue.
  197. let new_token = unsafe { self.recv_queue.add(&[], &mut [rx_buf.as_bytes_mut()]) }?;
  198. // `rx_buffers[new_token]` is expected to be `None` since it was taken
  199. // away at `Self::receive()` and has not been added back.
  200. if self.rx_buffers[new_token as usize].is_some() {
  201. return Err(Error::WrongToken);
  202. }
  203. rx_buf.idx = new_token;
  204. self.rx_buffers[new_token as usize] = Some(rx_buf);
  205. if self.recv_queue.should_notify() {
  206. self.transport.notify(QUEUE_RECEIVE);
  207. }
  208. Ok(())
  209. }
  210. /// Allocate a new buffer for transmitting.
  211. pub fn new_tx_buffer(&self, buf_len: usize) -> TxBuffer {
  212. TxBuffer(vec![0; buf_len])
  213. }
  214. /// Sends a [`TxBuffer`] to the network, and blocks until the request
  215. /// completed.
  216. pub fn send(&mut self, tx_buf: TxBuffer) -> Result {
  217. let header = VirtioNetHdr::default();
  218. if tx_buf.packet_len() == 0 {
  219. // Special case sending an empty packet, to avoid adding an empty buffer to the
  220. // virtqueue.
  221. self.send_queue.add_notify_wait_pop(
  222. &[header.as_bytes()],
  223. &mut [],
  224. &mut self.transport,
  225. )?;
  226. } else {
  227. self.send_queue.add_notify_wait_pop(
  228. &[header.as_bytes(), tx_buf.packet()],
  229. &mut [],
  230. &mut self.transport,
  231. )?;
  232. }
  233. Ok(())
  234. }
  235. }
  236. impl<H: Hal, T: Transport, const QUEUE_SIZE: usize> Drop for VirtIONet<H, T, QUEUE_SIZE> {
  237. fn drop(&mut self) {
  238. // Clear any pointers pointing to DMA regions, so the device doesn't try to access them
  239. // after they have been freed.
  240. self.transport.queue_unset(QUEUE_RECEIVE);
  241. self.transport.queue_unset(QUEUE_TRANSMIT);
  242. }
  243. }
  244. bitflags! {
  245. #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
  246. struct Features: u64 {
  247. /// Device handles packets with partial checksum.
  248. /// This "checksum offload" is a common feature on modern network cards.
  249. const CSUM = 1 << 0;
  250. /// Driver handles packets with partial checksum.
  251. const GUEST_CSUM = 1 << 1;
  252. /// Control channel offloads reconfiguration support.
  253. const CTRL_GUEST_OFFLOADS = 1 << 2;
  254. /// Device maximum MTU reporting is supported.
  255. ///
  256. /// If offered by the device, device advises driver about the value of
  257. /// its maximum MTU. If negotiated, the driver uses mtu as the maximum
  258. /// MTU value.
  259. const MTU = 1 << 3;
  260. /// Device has given MAC address.
  261. const MAC = 1 << 5;
  262. /// Device handles packets with any GSO type. (legacy)
  263. const GSO = 1 << 6;
  264. /// Driver can receive TSOv4.
  265. const GUEST_TSO4 = 1 << 7;
  266. /// Driver can receive TSOv6.
  267. const GUEST_TSO6 = 1 << 8;
  268. /// Driver can receive TSO with ECN.
  269. const GUEST_ECN = 1 << 9;
  270. /// Driver can receive UFO.
  271. const GUEST_UFO = 1 << 10;
  272. /// Device can receive TSOv4.
  273. const HOST_TSO4 = 1 << 11;
  274. /// Device can receive TSOv6.
  275. const HOST_TSO6 = 1 << 12;
  276. /// Device can receive TSO with ECN.
  277. const HOST_ECN = 1 << 13;
  278. /// Device can receive UFO.
  279. const HOST_UFO = 1 << 14;
  280. /// Driver can merge receive buffers.
  281. const MRG_RXBUF = 1 << 15;
  282. /// Configuration status field is available.
  283. const STATUS = 1 << 16;
  284. /// Control channel is available.
  285. const CTRL_VQ = 1 << 17;
  286. /// Control channel RX mode support.
  287. const CTRL_RX = 1 << 18;
  288. /// Control channel VLAN filtering.
  289. const CTRL_VLAN = 1 << 19;
  290. ///
  291. const CTRL_RX_EXTRA = 1 << 20;
  292. /// Driver can send gratuitous packets.
  293. const GUEST_ANNOUNCE = 1 << 21;
  294. /// Device supports multiqueue with automatic receive steering.
  295. const MQ = 1 << 22;
  296. /// Set MAC address through control channel.
  297. const CTL_MAC_ADDR = 1 << 23;
  298. // device independent
  299. const RING_INDIRECT_DESC = 1 << 28;
  300. const RING_EVENT_IDX = 1 << 29;
  301. const VERSION_1 = 1 << 32; // legacy
  302. }
  303. }
  304. bitflags! {
  305. #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
  306. struct Status: u16 {
  307. const LINK_UP = 1;
  308. const ANNOUNCE = 2;
  309. }
  310. }
  311. bitflags! {
  312. #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
  313. struct InterruptStatus : u32 {
  314. const USED_RING_UPDATE = 1 << 0;
  315. const CONFIGURATION_CHANGE = 1 << 1;
  316. }
  317. }
  318. #[repr(C)]
  319. struct Config {
  320. mac: ReadOnly<EthernetAddress>,
  321. status: ReadOnly<Status>,
  322. max_virtqueue_pairs: ReadOnly<u16>,
  323. mtu: ReadOnly<u16>,
  324. }
  325. type EthernetAddress = [u8; 6];
  326. /// VirtIO 5.1.6 Device Operation:
  327. ///
  328. /// Packets are transmitted by placing them in the transmitq1. . .transmitqN,
  329. /// and buffers for incoming packets are placed in the receiveq1. . .receiveqN.
  330. /// In each case, the packet itself is preceded by a header.
  331. #[repr(C)]
  332. #[derive(AsBytes, Debug, Default, FromBytes, FromZeroes)]
  333. pub struct VirtioNetHdr {
  334. flags: Flags,
  335. gso_type: GsoType,
  336. hdr_len: u16, // cannot rely on this
  337. gso_size: u16,
  338. csum_start: u16,
  339. csum_offset: u16,
  340. // num_buffers: u16, // only available when the feature MRG_RXBUF is negotiated.
  341. // payload starts from here
  342. }
  343. #[derive(AsBytes, Copy, Clone, Debug, Default, Eq, FromBytes, FromZeroes, PartialEq)]
  344. #[repr(transparent)]
  345. struct Flags(u8);
  346. bitflags! {
  347. impl Flags: u8 {
  348. const NEEDS_CSUM = 1;
  349. const DATA_VALID = 2;
  350. const RSC_INFO = 4;
  351. }
  352. }
  353. #[repr(transparent)]
  354. #[derive(AsBytes, Debug, Copy, Clone, Default, Eq, FromBytes, FromZeroes, PartialEq)]
  355. struct GsoType(u8);
  356. impl GsoType {
  357. const NONE: GsoType = GsoType(0);
  358. const TCPV4: GsoType = GsoType(1);
  359. const UDP: GsoType = GsoType(3);
  360. const TCPV6: GsoType = GsoType(4);
  361. const ECN: GsoType = GsoType(0x80);
  362. }
  363. const QUEUE_RECEIVE: u16 = 0;
  364. const QUEUE_TRANSMIT: u16 = 1;
  365. const SUPPORTED_FEATURES: Features = Features::MAC
  366. .union(Features::STATUS)
  367. .union(Features::RING_EVENT_IDX);