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 /// 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 bitflags! { 85 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] 86 pub(crate) struct Status: u16 { 87 const LINK_UP = 1; 88 const ANNOUNCE = 2; 89 } 90 } 91 92 bitflags! { 93 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] 94 struct InterruptStatus : u32 { 95 const USED_RING_UPDATE = 1 << 0; 96 const CONFIGURATION_CHANGE = 1 << 1; 97 } 98 } 99 100 #[repr(C)] 101 struct Config { 102 mac: ReadOnly<EthernetAddress>, 103 status: ReadOnly<Status>, 104 max_virtqueue_pairs: ReadOnly<u16>, 105 mtu: ReadOnly<u16>, 106 } 107 108 type EthernetAddress = [u8; 6]; 109 110 /// VirtIO 5.1.6 Device Operation: 111 /// 112 /// Packets are transmitted by placing them in the transmitq1. . .transmitqN, 113 /// and buffers for incoming packets are placed in the receiveq1. . .receiveqN. 114 /// In each case, the packet itself is preceded by a header. 115 #[repr(C)] 116 #[derive(AsBytes, Debug, Default, FromBytes, FromZeroes)] 117 pub struct VirtioNetHdr { 118 flags: Flags, 119 gso_type: GsoType, 120 hdr_len: u16, // cannot rely on this 121 gso_size: u16, 122 csum_start: u16, 123 csum_offset: u16, 124 // num_buffers: u16, // only available when the feature MRG_RXBUF is negotiated. 125 // payload starts from here 126 } 127 128 #[derive(AsBytes, Copy, Clone, Debug, Default, Eq, FromBytes, FromZeroes, PartialEq)] 129 #[repr(transparent)] 130 struct Flags(u8); 131 132 bitflags! { 133 impl Flags: u8 { 134 const NEEDS_CSUM = 1; 135 const DATA_VALID = 2; 136 const RSC_INFO = 4; 137 } 138 } 139 140 #[repr(transparent)] 141 #[derive(AsBytes, Debug, Copy, Clone, Default, Eq, FromBytes, FromZeroes, PartialEq)] 142 struct GsoType(u8); 143 144 impl GsoType { 145 const NONE: GsoType = GsoType(0); 146 const TCPV4: GsoType = GsoType(1); 147 const UDP: GsoType = GsoType(3); 148 const TCPV6: GsoType = GsoType(4); 149 const ECN: GsoType = GsoType(0x80); 150 } 151 152 const QUEUE_RECEIVE: u16 = 0; 153 const QUEUE_TRANSMIT: u16 = 1; 154 const SUPPORTED_FEATURES: Features = Features::MAC 155 .union(Features::STATUS) 156 .union(Features::RING_EVENT_IDX) 157 .union(Features::RING_INDIRECT_DESC); 158