• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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