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::config::ReadOnly; 14 use bitflags::bitflags; 15 use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout}; 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 /// Device supports VIRTIO_NET_CTRL_RX_ALLUNI, VIRTIO_NET_CTRL_RX_NOMULTI, 68 /// VIRTIO_NET_CTRL_RX_NOUNI and VIRTIO_NET_CTRL_RX_NOBCAST. 69 const CTRL_RX_EXTRA = 1 << 20; 70 /// Driver can send gratuitous packets. 71 const GUEST_ANNOUNCE = 1 << 21; 72 /// Device supports multiqueue with automatic receive steering. 73 const MQ = 1 << 22; 74 /// Set MAC address through control channel. 75 const CTL_MAC_ADDR = 1 << 23; 76 77 // device independent 78 const RING_INDIRECT_DESC = 1 << 28; 79 const RING_EVENT_IDX = 1 << 29; 80 const VERSION_1 = 1 << 32; // legacy 81 } 82 } 83 84 #[derive(Copy, Clone, Debug, Default, Eq, FromBytes, Immutable, KnownLayout, PartialEq)] 85 #[repr(transparent)] 86 struct Status(u16); 87 88 bitflags! { 89 impl Status: u16 { 90 const LINK_UP = 1; 91 const ANNOUNCE = 2; 92 } 93 } 94 95 bitflags! { 96 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] 97 struct InterruptStatus : u32 { 98 const USED_RING_UPDATE = 1 << 0; 99 const CONFIGURATION_CHANGE = 1 << 1; 100 } 101 } 102 103 #[repr(C)] 104 struct Config { 105 mac: ReadOnly<EthernetAddress>, 106 status: ReadOnly<Status>, 107 max_virtqueue_pairs: ReadOnly<u16>, 108 mtu: ReadOnly<u16>, 109 } 110 111 type EthernetAddress = [u8; 6]; 112 113 /// VirtIO 5.1.6 Device Operation: 114 /// 115 /// Packets are transmitted by placing them in the transmitq1. . .transmitqN, 116 /// and buffers for incoming packets are placed in the receiveq1. . .receiveqN. 117 /// In each case, the packet itself is preceded by a header. 118 #[repr(C)] 119 #[derive(Debug, Default, FromBytes, Immutable, IntoBytes, KnownLayout)] 120 pub struct VirtioNetHdr { 121 flags: Flags, 122 gso_type: GsoType, 123 hdr_len: u16, // cannot rely on this 124 gso_size: u16, 125 csum_start: u16, 126 csum_offset: u16, 127 // num_buffers: u16, // only available when the feature MRG_RXBUF is negotiated. 128 // payload starts from here 129 } 130 131 #[derive( 132 IntoBytes, Copy, Clone, Debug, Default, Eq, FromBytes, Immutable, KnownLayout, PartialEq, 133 )] 134 #[repr(transparent)] 135 struct Flags(u8); 136 137 bitflags! { 138 impl Flags: u8 { 139 const NEEDS_CSUM = 1; 140 const DATA_VALID = 2; 141 const RSC_INFO = 4; 142 } 143 } 144 145 #[repr(transparent)] 146 #[derive( 147 IntoBytes, Debug, Copy, Clone, Default, Eq, FromBytes, Immutable, KnownLayout, PartialEq, 148 )] 149 struct GsoType(u8); 150 151 impl GsoType { 152 const NONE: GsoType = GsoType(0); 153 const TCPV4: GsoType = GsoType(1); 154 const UDP: GsoType = GsoType(3); 155 const TCPV6: GsoType = GsoType(4); 156 const ECN: GsoType = GsoType(0x80); 157 } 158 159 const QUEUE_RECEIVE: u16 = 0; 160 const QUEUE_TRANSMIT: u16 = 1; 161 const SUPPORTED_FEATURES: Features = Features::MAC 162 .union(Features::STATUS) 163 .union(Features::RING_EVENT_IDX) 164 .union(Features::RING_INDIRECT_DESC); 165