virtio_drivers/device/net/
mod.rs

1//! Driver for VirtIO network devices.
2
3#[cfg(feature = "alloc")]
4mod dev;
5mod dev_raw;
6#[cfg(feature = "alloc")]
7mod net_buf;
8
9pub use self::dev_raw::VirtIONetRaw;
10#[cfg(feature = "alloc")]
11pub use self::{dev::VirtIONet, net_buf::RxBuffer, net_buf::TxBuffer};
12
13use crate::config::ReadOnly;
14use bitflags::bitflags;
15use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
16
17const MAX_BUFFER_LEN: usize = 65535;
18const MIN_BUFFER_LEN: usize = 1526;
19
20bitflags! {
21    #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
22    struct Features: u64 {
23        /// Device handles packets with partial checksum.
24        /// This "checksum offload" is a common feature on modern network cards.
25        const CSUM = 1 << 0;
26        /// Driver handles packets with partial checksum.
27        const GUEST_CSUM = 1 << 1;
28        /// Control channel offloads reconfiguration support.
29        const CTRL_GUEST_OFFLOADS = 1 << 2;
30        /// Device maximum MTU reporting is supported.
31        ///
32        /// If offered by the device, device advises driver about the value of
33        /// its maximum MTU. If negotiated, the driver uses mtu as the maximum
34        /// MTU value.
35        const MTU = 1 << 3;
36        /// Device has given MAC address.
37        const MAC = 1 << 5;
38        /// Device handles packets with any GSO type. (legacy)
39        const GSO = 1 << 6;
40        /// Driver can receive TSOv4.
41        const GUEST_TSO4 = 1 << 7;
42        /// Driver can receive TSOv6.
43        const GUEST_TSO6 = 1 << 8;
44        /// Driver can receive TSO with ECN.
45        const GUEST_ECN = 1 << 9;
46        /// Driver can receive UFO.
47        const GUEST_UFO = 1 << 10;
48        /// Device can receive TSOv4.
49        const HOST_TSO4 = 1 << 11;
50        /// Device can receive TSOv6.
51        const HOST_TSO6 = 1 << 12;
52        /// Device can receive TSO with ECN.
53        const HOST_ECN = 1 << 13;
54        /// Device can receive UFO.
55        const HOST_UFO = 1 << 14;
56        /// Driver can merge receive buffers.
57        const MRG_RXBUF = 1 << 15;
58        /// Configuration status field is available.
59        const STATUS = 1 << 16;
60        /// Control channel is available.
61        const CTRL_VQ = 1 << 17;
62        /// Control channel RX mode support.
63        const CTRL_RX = 1 << 18;
64        /// Control channel VLAN filtering.
65        const CTRL_VLAN = 1 << 19;
66        /// Device supports VIRTIO_NET_CTRL_RX_ALLUNI, VIRTIO_NET_CTRL_RX_NOMULTI,
67        /// VIRTIO_NET_CTRL_RX_NOUNI and VIRTIO_NET_CTRL_RX_NOBCAST.
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#[derive(
84    Copy, Clone, Debug, Default, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq,
85)]
86#[repr(transparent)]
87struct Status(u16);
88
89bitflags! {
90    impl Status: u16 {
91        const LINK_UP = 1;
92        const ANNOUNCE = 2;
93    }
94}
95
96bitflags! {
97    #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
98    struct InterruptStatus : u32 {
99        const USED_RING_UPDATE = 1 << 0;
100        const CONFIGURATION_CHANGE = 1 << 1;
101    }
102}
103
104#[repr(C)]
105struct Config {
106    mac: ReadOnly<EthernetAddress>,
107    status: ReadOnly<Status>,
108    max_virtqueue_pairs: ReadOnly<u16>,
109    mtu: ReadOnly<u16>,
110}
111
112type EthernetAddress = [u8; 6];
113
114/// VirtIO 5.1.6 Device Operation:
115///
116/// Packets are transmitted by placing them in the transmitq1. . .transmitqN,
117/// and buffers for incoming packets are placed in the receiveq1. . .receiveqN.
118/// In each case, the packet itself is preceded by a header.
119#[repr(C)]
120#[derive(Debug, Default, FromBytes, Immutable, IntoBytes, KnownLayout)]
121pub(crate) struct VirtioNetHdrLegacy {
122    flags: Flags,
123    gso_type: GsoType,
124    hdr_len: u16, // cannot rely on this
125    gso_size: u16,
126    csum_start: u16,
127    csum_offset: u16,
128}
129
130/// VirtIO 5.1.6 Device Operation:
131///
132/// Packets are transmitted by placing them in the transmitq1. . .transmitqN,
133/// and buffers for incoming packets are placed in the receiveq1. . .receiveqN.
134/// In each case, the packet itself is preceded by a header.
135#[repr(C)]
136#[derive(Copy, Clone, Debug, Default, FromBytes, Immutable, IntoBytes, KnownLayout)]
137pub struct VirtioNetHdr {
138    flags: Flags,
139    gso_type: GsoType,
140    hdr_len: u16, // cannot rely on this
141    gso_size: u16,
142    csum_start: u16,
143    csum_offset: u16,
144    num_buffers: u16,
145    // payload starts from here
146}
147
148impl From<&VirtioNetHdrLegacy> for VirtioNetHdr {
149    fn from(legacy: &VirtioNetHdrLegacy) -> Self {
150        let VirtioNetHdrLegacy {
151            flags,
152            gso_type,
153            hdr_len,
154            gso_size,
155            csum_start,
156            csum_offset,
157        } = *legacy;
158
159        Self {
160            flags,
161            gso_type,
162            hdr_len,
163            gso_size,
164            csum_start,
165            csum_offset,
166            num_buffers: 0,
167        }
168    }
169}
170
171#[derive(
172    IntoBytes, Copy, Clone, Debug, Default, Eq, FromBytes, Immutable, KnownLayout, PartialEq,
173)]
174#[repr(transparent)]
175struct Flags(u8);
176
177bitflags! {
178    impl Flags: u8 {
179        const NEEDS_CSUM = 1;
180        const DATA_VALID = 2;
181        const RSC_INFO   = 4;
182    }
183}
184
185#[repr(transparent)]
186#[derive(
187    IntoBytes, Debug, Copy, Clone, Default, Eq, FromBytes, Immutable, KnownLayout, PartialEq,
188)]
189struct GsoType(u8);
190
191impl GsoType {
192    const NONE: GsoType = GsoType(0);
193    const TCPV4: GsoType = GsoType(1);
194    const UDP: GsoType = GsoType(3);
195    const TCPV6: GsoType = GsoType(4);
196    const ECN: GsoType = GsoType(0x80);
197}
198
199const QUEUE_RECEIVE: u16 = 0;
200const QUEUE_TRANSMIT: u16 = 1;
201const SUPPORTED_FEATURES: Features = Features::MAC
202    .union(Features::STATUS)
203    .union(Features::RING_EVENT_IDX)
204    .union(Features::RING_INDIRECT_DESC)
205    .union(Features::VERSION_1);