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::volatile::ReadOnly;
14use bitflags::bitflags;
15use zerocopy::{AsBytes, FromBytes, FromZeroes};
16
17const MAX_BUFFER_LEN: usize = 65535;
18const MIN_BUFFER_LEN: usize = 1526;
19const NET_HDR_SIZE: usize = core::mem::size_of::<VirtioNetHdr>();
20
21bitflags! {
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
84bitflags! {
85    #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
86    struct Status: u16 {
87        const LINK_UP = 1;
88        const ANNOUNCE = 2;
89    }
90}
91
92bitflags! {
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)]
101struct Config {
102    mac: ReadOnly<EthernetAddress>,
103    status: ReadOnly<Status>,
104    max_virtqueue_pairs: ReadOnly<u16>,
105    mtu: ReadOnly<u16>,
106}
107
108type 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)]
117pub 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)]
130struct Flags(u8);
131
132bitflags! {
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)]
142struct GsoType(u8);
143
144impl 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
152const QUEUE_RECEIVE: u16 = 0;
153const QUEUE_TRANSMIT: u16 = 1;
154const SUPPORTED_FEATURES: Features = Features::MAC
155    .union(Features::STATUS)
156    .union(Features::RING_EVENT_IDX)
157    .union(Features::RING_INDIRECT_DESC);