1 //! Driver for VirtIO network devices. 2 3 #[cfg(feature = "alloc")] 4 mod dev; 5 mod dev_raw; 6 #[cfg(feature = "alloc")] 7 mod net_buf; 8 9 pub use self::dev_raw::VirtIONetRaw; 10 #[cfg(feature = "alloc")] 11 pub use self::{dev::VirtIONet, net_buf::RxBuffer, net_buf::TxBuffer}; 12 13 use crate::volatile::ReadOnly; 14 use bitflags::bitflags; 15 use zerocopy::{AsBytes, FromBytes, FromZeroes}; 16 17 const MAX_BUFFER_LEN: usize = 65535; 18 const MIN_BUFFER_LEN: usize = 1526; 19 const NET_HDR_SIZE: usize = core::mem::size_of::<VirtioNetHdr>(); 20 21 bitflags! { 22 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] 23 struct Features: u64 { 24 /// Device handles packets with partial checksum. 25 /// This "checksum offload" is a common feature on modern network cards. 26 const CSUM = 1 << 0; 27 /// Driver handles packets with partial checksum. 28 const GUEST_CSUM = 1 << 1; 29 /// Control channel offloads reconfiguration support. 30 const CTRL_GUEST_OFFLOADS = 1 << 2; 31 /// Device maximum MTU reporting is supported. 32 /// 33 /// If offered by the device, device advises driver about the value of 34 /// its maximum MTU. If negotiated, the driver uses mtu as the maximum 35 /// MTU value. 36 const MTU = 1 << 3; 37 /// Device has given MAC address. 38 const MAC = 1 << 5; 39 /// Device handles packets with any GSO type. (legacy) 40 const GSO = 1 << 6; 41 /// Driver can receive TSOv4. 42 const GUEST_TSO4 = 1 << 7; 43 /// Driver can receive TSOv6. 44 const GUEST_TSO6 = 1 << 8; 45 /// Driver can receive TSO with ECN. 46 const GUEST_ECN = 1 << 9; 47 /// Driver can receive UFO. 48 const GUEST_UFO = 1 << 10; 49 /// Device can receive TSOv4. 50 const HOST_TSO4 = 1 << 11; 51 /// Device can receive TSOv6. 52 const HOST_TSO6 = 1 << 12; 53 /// Device can receive TSO with ECN. 54 const HOST_ECN = 1 << 13; 55 /// Device can receive UFO. 56 const HOST_UFO = 1 << 14; 57 /// Driver can merge receive buffers. 58 const MRG_RXBUF = 1 << 15; 59 /// Configuration status field is available. 60 const STATUS = 1 << 16; 61 /// Control channel is available. 62 const CTRL_VQ = 1 << 17; 63 /// Control channel RX mode support. 64 const CTRL_RX = 1 << 18; 65 /// Control channel VLAN filtering. 66 const CTRL_VLAN = 1 << 19; 67 /// 68 const CTRL_RX_EXTRA = 1 << 20; 69 /// Driver can send gratuitous packets. 70 const GUEST_ANNOUNCE = 1 << 21; 71 /// Device supports multiqueue with automatic receive steering. 72 const MQ = 1 << 22; 73 /// Set MAC address through control channel. 74 const CTL_MAC_ADDR = 1 << 23; 75 76 // device independent 77 const RING_INDIRECT_DESC = 1 << 28; 78 const RING_EVENT_IDX = 1 << 29; 79 const VERSION_1 = 1 << 32; // legacy 80 } 81 } 82 83 bitflags! { 84 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] 85 pub(crate) struct Status: u16 { 86 const LINK_UP = 1; 87 const ANNOUNCE = 2; 88 } 89 } 90 91 bitflags! { 92 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] 93 struct InterruptStatus : u32 { 94 const USED_RING_UPDATE = 1 << 0; 95 const CONFIGURATION_CHANGE = 1 << 1; 96 } 97 } 98 99 #[repr(C)] 100 struct Config { 101 mac: ReadOnly<EthernetAddress>, 102 status: ReadOnly<Status>, 103 max_virtqueue_pairs: ReadOnly<u16>, 104 mtu: ReadOnly<u16>, 105 } 106 107 type EthernetAddress = [u8; 6]; 108 109 /// VirtIO 5.1.6 Device Operation: 110 /// 111 /// Packets are transmitted by placing them in the transmitq1. . .transmitqN, 112 /// and buffers for incoming packets are placed in the receiveq1. . .receiveqN. 113 /// In each case, the packet itself is preceded by a header. 114 #[repr(C)] 115 #[derive(AsBytes, Debug, Default, FromBytes, FromZeroes)] 116 pub struct VirtioNetHdr { 117 flags: Flags, 118 gso_type: GsoType, 119 hdr_len: u16, // cannot rely on this 120 gso_size: u16, 121 csum_start: u16, 122 csum_offset: u16, 123 // num_buffers: u16, // only available when the feature MRG_RXBUF is negotiated. 124 // payload starts from here 125 } 126 127 #[derive(AsBytes, Copy, Clone, Debug, Default, Eq, FromBytes, FromZeroes, PartialEq)] 128 #[repr(transparent)] 129 struct Flags(u8); 130 131 bitflags! { 132 impl Flags: u8 { 133 const NEEDS_CSUM = 1; 134 const DATA_VALID = 2; 135 const RSC_INFO = 4; 136 } 137 } 138 139 #[repr(transparent)] 140 #[derive(AsBytes, Debug, Copy, Clone, Default, Eq, FromBytes, FromZeroes, PartialEq)] 141 struct GsoType(u8); 142 143 impl GsoType { 144 const NONE: GsoType = GsoType(0); 145 const TCPV4: GsoType = GsoType(1); 146 const UDP: GsoType = GsoType(3); 147 const TCPV6: GsoType = GsoType(4); 148 const ECN: GsoType = GsoType(0x80); 149 } 150 151 const QUEUE_RECEIVE: u16 = 0; 152 const QUEUE_TRANSMIT: u16 = 1; 153 const SUPPORTED_FEATURES: Features = Features::MAC 154 .union(Features::STATUS) 155 .union(Features::RING_EVENT_IDX) 156 .union(Features::RING_INDIRECT_DESC); 157