virtio_spec/features.rs
1//! Feature Bits
2
3use crate::le128;
4use crate::sealed::Sealed;
5
6/// Feature Bits
7#[doc(alias = "VIRTIO_F")]
8pub trait FeatureBits:
9 bitflags::Flags<Bits = le128> + From<F> + Into<F> + AsRef<F> + AsMut<F> + Sealed
10{
11 /// Returns `true` if all internal feature requirements are satisfied.
12 ///
13 /// # Driver Requirements
14 ///
15 /// The driver MUST NOT accept a feature which requires another feature which was not accepted.
16 ///
17 /// # Device Requirements
18 ///
19 /// The device MUST NOT offer a feature which requires another feature which was not offered.
20 ///
21 /// # Examples
22 ///
23 /// ```
24 /// # use virtio_spec as virtio;
25 /// use virtio::FeatureBits;
26 ///
27 /// assert!((virtio::net::F::GUEST_TSO4 | virtio::net::F::GUEST_CSUM).requirements_satisfied());
28 /// assert!(
29 /// (virtio::net::F::GUEST_ECN | virtio::net::F::GUEST_TSO4 | virtio::net::F::GUEST_CSUM)
30 /// .requirements_satisfied()
31 /// );
32 /// ```
33 fn requirements_satisfied(&self) -> bool {
34 true
35 }
36
37 /// Returns `true` if all internal feature recommendations are satisfied.
38 ///
39 /// # Driver Requirements
40 ///
41 /// The driver SHOULD NOT accept a feature which recommends another feature which was not accepted.
42 ///
43 /// # Device Requirements
44 ///
45 /// The device SHOULD NOT offer a feature which recommends another feature which was not offered.
46 ///
47 /// # Examples
48 ///
49 /// ```
50 /// # use virtio_spec as virtio;
51 /// use virtio::FeatureBits;
52 ///
53 /// assert!((virtio::net::F::HASH_REPORT | virtio::net::F::CTRL_VQ).recommendations_satisfied());
54 /// ```
55 fn recommendations_satisfied(&self) -> bool {
56 true
57 }
58}
59
60endian_bitflags! {
61 /// Device-independent Feature Bits
62 #[doc(alias = "VIRTIO_F")]
63 pub struct F: le128 {
64 /// Negotiating this feature indicates
65 /// that the driver can use descriptors with the VIRTQ_DESC_F_INDIRECT
66 /// flag set, as described in _Basic Facilities of a Virtio
67 /// Device / Virtqueues / The Virtqueue Descriptor Table / Indirect
68 /// Descriptors_ _Basic Facilities of a Virtio Device /
69 /// Virtqueues / The Virtqueue Descriptor Table / Indirect
70 /// Descriptors_ and _Packed Virtqueues / Indirect Flag: Scatter-Gather Support_ _Packed Virtqueues / Indirect Flag: Scatter-Gather Support_.
71 #[doc(alias = "VIRTIO_F_INDIRECT_DESC")]
72 const INDIRECT_DESC = 1 << 28;
73
74 /// This feature enables the _used_event_
75 /// and the _avail_event_ fields as described in
76 /// _Basic Facilities of a Virtio Device / Virtqueues / Used Buffer Notification Suppression_, _Basic Facilities of a Virtio Device / Virtqueues / The Virtqueue Used Ring_ and _Packed Virtqueues / Driver and Device Event Suppression_.
77 #[doc(alias = "VIRTIO_F_EVENT_IDX")]
78 const EVENT_IDX = 1 << 29;
79
80 /// This indicates compliance with this
81 /// specification, giving a simple way to detect legacy devices or drivers.
82 #[doc(alias = "VIRTIO_F_VERSION_1")]
83 const VERSION_1 = 1 << 32;
84
85 /// This feature indicates that
86 /// the device can be used on a platform where device access to data
87 /// in memory is limited and/or translated. E.g. this is the case if the device can be located
88 /// behind an IOMMU that translates bus addresses from the device into physical
89 /// addresses in memory, if the device can be limited to only access
90 /// certain memory addresses or if special commands such as
91 /// a cache flush can be needed to synchronise data in memory with
92 /// the device. Whether accesses are actually limited or translated
93 /// is described by platform-specific means.
94 /// If this feature bit is set to 0, then the device
95 /// has same access to memory addresses supplied to it as the
96 /// driver has.
97 /// In particular, the device will always use physical addresses
98 /// matching addresses used by the driver (typically meaning
99 /// physical addresses used by the CPU)
100 /// and not translated further, and can access any address supplied to it by
101 /// the driver. When clear, this overrides any platform-specific description of
102 /// whether device access is limited or translated in any way, e.g.
103 /// whether an IOMMU may be present.
104 #[doc(alias = "VIRTIO_F_ACCESS_PLATFORM")]
105 const ACCESS_PLATFORM = 1 << 33;
106
107 /// This feature indicates
108 /// support for the packed virtqueue layout as described in
109 /// _Basic Facilities of a Virtio Device / Packed Virtqueues_ _Basic Facilities of a Virtio Device / Packed Virtqueues_.
110 #[doc(alias = "VIRTIO_F_RING_PACKED")]
111 const RING_PACKED = 1 << 34;
112
113 /// This feature indicates
114 /// that all buffers are used by the device in the same
115 /// order in which they have been made available.
116 #[doc(alias = "VIRTIO_F_IN_ORDER")]
117 const IN_ORDER = 1 << 35;
118
119 /// This feature indicates
120 /// that memory accesses by the driver and the device are ordered
121 /// in a way described by the platform.
122 ///
123 /// If this feature bit is negotiated, the ordering in effect for any
124 /// memory accesses by the driver that need to be ordered in a specific way
125 /// with respect to accesses by the device is the one suitable for devices
126 /// described by the platform. This implies that the driver needs to use
127 /// memory barriers suitable for devices described by the platform; e.g.
128 /// for the PCI transport in the case of hardware PCI devices.
129 ///
130 /// If this feature bit is not negotiated, then the device
131 /// and driver are assumed to be implemented in software, that is
132 /// they can be assumed to run on identical CPUs
133 /// in an SMP configuration.
134 /// Thus a weaker form of memory barriers is sufficient
135 /// to yield better performance.
136 #[doc(alias = "VIRTIO_F_ORDER_PLATFORM")]
137 const ORDER_PLATFORM = 1 << 36;
138
139 /// This feature indicates that
140 /// the device supports Single Root I/O Virtualization.
141 /// Currently only PCI devices support this feature.
142 #[doc(alias = "VIRTIO_F_SR_IOV")]
143 const SR_IOV = 1 << 37;
144
145 /// This feature indicates
146 /// that the driver passes extra data (besides identifying the virtqueue)
147 /// in its device notifications.
148 /// See _Basic Facilities of a Virtio Device / Driver notifications_.
149 #[doc(alias = "VIRTIO_F_NOTIFICATION_DATA")]
150 const NOTIFICATION_DATA = 1 << 38;
151
152 /// This feature indicates that the driver
153 /// uses the data provided by the device as a virtqueue identifier in available
154 /// buffer notifications.
155 /// As mentioned in section _Basic Facilities of a Virtio Device / Driver notifications_, when the
156 /// driver is required to send an available buffer notification to the device, it
157 /// sends the virtqueue index to be notified. The method of delivering
158 /// notifications is transport specific.
159 /// With the PCI transport, the device can optionally provide a per-virtqueue value
160 /// for the driver to use in driver notifications, instead of the virtqueue index.
161 /// Some devices may benefit from this flexibility by providing, for example,
162 /// an internal virtqueue identifier, or an internal offset related to the
163 /// virtqueue index.
164 ///
165 /// This feature indicates the availability of such value. The definition of the
166 /// data to be provided in driver notification and the delivery method is
167 /// transport specific.
168 /// For more details about driver notifications over PCI see _Virtio Transport Options / Virtio Over PCI Bus / PCI-specific Initialization And Device Operation / Available Buffer Notifications_.
169 #[doc(alias = "VIRTIO_F_NOTIF_CONFIG_DATA")]
170 const NOTIF_CONFIG_DATA = 1 << 39;
171
172 /// This feature indicates
173 /// that the driver can reset a queue individually.
174 /// See _Basic Facilities of a Virtio Device / Virtqueues / Virtqueue Reset_.
175 #[doc(alias = "VIRTIO_F_RING_RESET")]
176 const RING_RESET = 1 << 40;
177
178 /// This feature indicates that the device exposes one or more
179 /// administration virtqueues.
180 /// At the moment this feature is only supported for devices using
181 /// _Virtio Transport Options / Virtio Over PCI Bus_
182 /// as the transport and is reserved for future use for
183 /// devices using other transports (see
184 /// _Basic Facilities of a Virtio Device / Feature Bits_ for
185 /// handling features reserved for future use.
186 #[doc(alias = "VIRTIO_F_ADMIN_VQ")]
187 const ADMIN_VQ = 1 << 41;
188
189 /// This feature indicates that the driver can
190 /// suspend the device by set the SUSPEND bit to 1.
191 /// See _Basic Facilities of a Virtio Device / Device Status Field_.
192 #[doc(alias = "VIRTIO_F_SUSPEND")]
193 const SUSPEND = 1 << 43;
194 }
195}
196
197impl AsRef<F> for F {
198 fn as_ref(&self) -> &F {
199 self
200 }
201}
202
203impl AsMut<F> for F {
204 fn as_mut(&mut self) -> &mut F {
205 self
206 }
207}
208
209impl FeatureBits for F {}
210
211impl Sealed for F {}
212
213macro_rules! feature_bits {
214 (
215 $(#[$outer:meta])*
216 $vis:vis struct $BitFlags:ident: $T:ty {
217 $(
218 $(#[$inner:ident $($args:tt)*])*
219 const $Flag:tt = $value:expr;
220 )*
221 }
222
223 $($t:tt)*
224 ) => {
225 endian_bitflags! {
226 $(#[$outer])*
227 $vis struct $BitFlags: $T {
228 $(
229 $(#[$inner $($args)*])*
230 const $Flag = $value;
231 )*
232
233 /// Device-independent Bit. See [`virtio::F::INDIRECT_DESC`](crate::F::INDIRECT_DESC).
234 const INDIRECT_DESC = $crate::F::INDIRECT_DESC.bits().to_ne();
235
236 /// Device-independent Bit. See [`virtio::F::EVENT_IDX`](crate::F::EVENT_IDX).
237 const EVENT_IDX = $crate::F::EVENT_IDX.bits().to_ne();
238
239 /// Device-independent Bit. See [`virtio::F::VERSION_1`](crate::F::VERSION_1).
240 const VERSION_1 = $crate::F::VERSION_1.bits().to_ne();
241
242 /// Device-independent Bit. See [`virtio::F::ACCESS_PLATFORM`](crate::F::ACCESS_PLATFORM).
243 const ACCESS_PLATFORM = $crate::F::ACCESS_PLATFORM.bits().to_ne();
244
245 /// Device-independent Bit. See [`virtio::F::RING_PACKED`](crate::F::RING_PACKED).
246 const RING_PACKED = $crate::F::RING_PACKED.bits().to_ne();
247
248 /// Device-independent Bit. See [`virtio::F::IN_ORDER`](crate::F::IN_ORDER).
249 const IN_ORDER = $crate::F::IN_ORDER.bits().to_ne();
250
251 /// Device-independent Bit. See [`virtio::F::ORDER_PLATFORM`](crate::F::ORDER_PLATFORM).
252 const ORDER_PLATFORM = $crate::F::ORDER_PLATFORM.bits().to_ne();
253
254 /// Device-independent Bit. See [`virtio::F::SR_IOV`](crate::F::SR_IOV).
255 const SR_IOV = $crate::F::SR_IOV.bits().to_ne();
256
257 /// Device-independent Bit. See [`virtio::F::NOTIFICATION_DATA`](crate::F::NOTIFICATION_DATA).
258 const NOTIFICATION_DATA = $crate::F::NOTIFICATION_DATA.bits().to_ne();
259
260 /// Device-independent Bit. See [`virtio::F::NOTIF_CONFIG_DATA`](crate::F::NOTIF_CONFIG_DATA).
261 const NOTIF_CONFIG_DATA = $crate::F::NOTIF_CONFIG_DATA.bits().to_ne();
262
263 /// Device-independent Bit. See [`virtio::F::RING_RESET`](crate::F::RING_RESET).
264 const RING_RESET = $crate::F::RING_RESET.bits().to_ne();
265
266 /// Device-independent Bit. See [`virtio::F::ADMIN_VQ`](crate::F::ADMIN_VQ).
267 const ADMIN_VQ = $crate::F::ADMIN_VQ.bits().to_ne();
268
269 /// Device-independent Bit. See [`virtio::F::SUSPEND`](crate::F::SUSPEND).
270 const SUSPEND = $crate::F::SUSPEND.bits().to_ne();
271 }
272 }
273
274 impl From<$crate::F> for $BitFlags {
275 fn from(value: $crate::F) -> Self {
276 Self::from_bits_retain(value.bits())
277 }
278 }
279
280 impl AsRef<$BitFlags> for $crate::F {
281 fn as_ref(&self) -> &$BitFlags {
282 unsafe { &*(self as *const Self as *const $BitFlags) }
283 }
284 }
285
286 impl AsMut<$BitFlags> for $crate::F {
287 fn as_mut(&mut self) -> &mut $BitFlags {
288 unsafe { &mut *(self as *mut Self as *mut $BitFlags) }
289 }
290 }
291
292 impl From<$BitFlags> for $crate::F {
293 /// Returns the device-independent feature bits while retaining device-specific feature bits.
294 fn from(value: $BitFlags) -> Self {
295 $crate::F::from_bits_retain(value.bits())
296 }
297 }
298
299 impl AsRef<$crate::F> for $BitFlags {
300 /// Returns a shared reference to the device-independent features while retaining device-specific feature bits.
301 fn as_ref(&self) -> &$crate::F {
302 unsafe { &*(self as *const Self as *const $crate::F) }
303 }
304 }
305
306 impl AsMut<$crate::F> for $BitFlags {
307 /// Returns a mutable reference to the device-independent features while retaining device-specific feature bits.
308 fn as_mut(&mut self) -> &mut $crate::F {
309 unsafe { &mut *(self as *mut Self as *mut $crate::F) }
310 }
311 }
312
313 impl $crate::sealed::Sealed for $BitFlags {}
314
315 feature_bits! {
316 $($t)*
317 }
318 };
319 () => {};
320}
321
322pub mod console {
323 use crate::le128;
324
325 feature_bits! {
326 /// Console Device Feature Bits
327 #[doc(alias = "VIRTIO_CONSOLE_F")]
328 pub struct F: le128 {
329 /// Configuration `cols` and `rows` are valid.
330 #[doc(alias = "VIRTIO_CONSOLE_F_SIZE")]
331 const SIZE = 1 << 0;
332
333 /// Device has support for multiple ports;
334 ///
335 /// `max_nr_ports` is valid and control virtqueues will be used.
336 #[doc(alias = "VIRTIO_CONSOLE_F_MULTIPORT")]
337 const MULTIPORT = 1 << 1;
338
339 /// Device has support for emergency write.
340 ///
341 /// Configuration field emerg_wr is valid.
342 #[doc(alias = "VIRTIO_CONSOLE_F_EMERG_WRITE")]
343 const EMERG_WRITE = 1 << 2;
344 }
345 }
346
347 impl crate::FeatureBits for F {}
348}
349
350pub mod blk {
351 use crate::le128;
352
353 feature_bits! {
354 /// Block Device Feature Bits
355 #[doc(alias = "VIRTIO_BLK_F")]
356 pub struct F: le128 {
357 /// Maximum size of any single segment is
358 // in `size_max`.
359 #[doc(alias = "VIRTIO_BLK_F_SIZE_MAX")]
360 const SIZE_MAX = 1 << 1;
361
362 /// Maximum number of segments in a
363 /// request is in `seg_max`.
364 #[doc(alias = "VIRTIO_BLK_F_SEG_MAX")]
365 const SEG_MAX = 1 << 2;
366
367 /// Disk-style geometry specified in
368 /// `geometry`.
369 #[doc(alias = "VIRTIO_BLK_F_GEOMETRY")]
370 const GEOMETRY = 1 << 4;
371
372 /// Device is read-only.
373 #[doc(alias = "VIRTIO_BLK_F_RO")]
374 const RO = 1 << 5;
375
376 /// Block size of disk is in `blk_size`.
377 #[doc(alias = "VIRTIO_BLK_F_BLK_SIZE")]
378 const BLK_SIZE = 1 << 6;
379
380 /// Cache flush command support.
381 #[doc(alias = "VIRTIO_BLK_F_FLUSH")]
382 const FLUSH = 1 << 9;
383
384 /// Device exports information on optimal I/O
385 /// alignment.
386 #[doc(alias = "VIRTIO_BLK_F_TOPOLOGY")]
387 const TOPOLOGY = 1 << 10;
388
389 /// Device can toggle its cache between writeback
390 /// and writethrough modes.
391 #[doc(alias = "VIRTIO_BLK_F_CONFIG_WCE")]
392 const CONFIG_WCE = 1 << 11;
393
394 /// Device supports multiqueue.
395 #[doc(alias = "VIRTIO_BLK_F_MQ")]
396 const MQ = 1 << 12;
397
398 /// Device can support discard command, maximum
399 /// discard sectors size in `max_discard_sectors` and maximum discard
400 /// segment number in `max_discard_seg`.
401 #[doc(alias = "VIRTIO_BLK_F_DISCARD")]
402 const DISCARD = 1 << 13;
403
404 /// Device can support write zeroes command,
405 /// maximum write zeroes sectors size in `max_write_zeroes_sectors` and
406 /// maximum write zeroes segment number in `max_write_zeroes_seg`.
407 #[doc(alias = "VIRTIO_BLK_F_WRITE_ZEROES")]
408 const WRITE_ZEROES = 1 << 14;
409
410 /// Device supports providing storage lifetime
411 /// information.
412 #[doc(alias = "VIRTIO_BLK_F_LIFETIME")]
413 const LIFETIME = 1 << 15;
414
415 /// Device supports secure erase command,
416 /// maximum erase sectors count in `max_secure_erase_sectors` and
417 /// maximum erase segment number in `max_secure_erase_seg`.
418 #[doc(alias = "VIRTIO_BLK_F_SECURE_ERASE")]
419 const SECURE_ERASE = 1 << 16;
420
421 /// Device is a Zoned Block Device, that is, a device
422 /// that follows the zoned storage device behavior that is also supported by
423 /// industry standards such as the T10 Zoned Block Command standard (ZBC r05) or
424 /// the NVMe(TM) NVM Express Zoned Namespace Command Set Specification 1.1b
425 /// (ZNS). For brevity, these standard documents are referred as "ZBD standards"
426 /// from this point on in the text.
427 #[doc(alias = "VIRTIO_BLK_F_ZONED")]
428 const ZONED = 1 << 17;
429 }
430 }
431
432 impl crate::FeatureBits for F {}
433}
434
435pub mod net {
436 use crate::le128;
437
438 feature_bits! {
439 /// Network Device Feature Bits
440 #[doc(alias = "VIRTIO_NET_F")]
441 pub struct F: le128 {
442 /// Device handles packets with partial checksum offload.
443 #[doc(alias = "VIRTIO_NET_F_CSUM")]
444 const CSUM = 1 << 0;
445
446 /// Driver handles packets with partial checksum.
447 #[doc(alias = "VIRTIO_NET_F_GUEST_CSUM")]
448 const GUEST_CSUM = 1 << 1;
449
450 /// Control channel offloads
451 /// reconfiguration support.
452 #[doc(alias = "VIRTIO_NET_F_CTRL_GUEST_OFFLOADS")]
453 const CTRL_GUEST_OFFLOADS = 1 << 2;
454
455 /// Device maximum MTU reporting is supported. If
456 /// offered by the device, device advises driver about the value of
457 /// its maximum MTU. If negotiated, the driver uses _mtu_ as
458 /// the maximum MTU value.
459 #[doc(alias = "VIRTIO_NET_F_MTU")]
460 const MTU = 1 << 3;
461
462 /// Device has given MAC address.
463 #[doc(alias = "VIRTIO_NET_F_MAC")]
464 const MAC = 1 << 5;
465
466 /// Driver can receive TSOv4.
467 #[doc(alias = "VIRTIO_NET_F_GUEST_TSO4")]
468 const GUEST_TSO4 = 1 << 7;
469
470 /// Driver can receive TSOv6.
471 #[doc(alias = "VIRTIO_NET_F_GUEST_TSO6")]
472 const GUEST_TSO6 = 1 << 8;
473
474 /// Driver can receive TSO with ECN.
475 #[doc(alias = "VIRTIO_NET_F_GUEST_ECN")]
476 const GUEST_ECN = 1 << 9;
477
478 /// Driver can receive UFO.
479 #[doc(alias = "VIRTIO_NET_F_GUEST_UFO")]
480 const GUEST_UFO = 1 << 10;
481
482 /// Device can receive TSOv4.
483 #[doc(alias = "VIRTIO_NET_F_HOST_TSO4")]
484 const HOST_TSO4 = 1 << 11;
485
486 /// Device can receive TSOv6.
487 #[doc(alias = "VIRTIO_NET_F_HOST_TSO6")]
488 const HOST_TSO6 = 1 << 12;
489
490 /// Device can receive TSO with ECN.
491 #[doc(alias = "VIRTIO_NET_F_HOST_ECN")]
492 const HOST_ECN = 1 << 13;
493
494 /// Device can receive UFO.
495 #[doc(alias = "VIRTIO_NET_F_HOST_UFO")]
496 const HOST_UFO = 1 << 14;
497
498 /// Driver can merge receive buffers.
499 #[doc(alias = "VIRTIO_NET_F_MRG_RXBUF")]
500 const MRG_RXBUF = 1 << 15;
501
502 /// Configuration status field is
503 /// available.
504 #[doc(alias = "VIRTIO_NET_F_STATUS")]
505 const STATUS = 1 << 16;
506
507 /// Control channel is available.
508 #[doc(alias = "VIRTIO_NET_F_CTRL_VQ")]
509 const CTRL_VQ = 1 << 17;
510
511 /// Control channel RX mode support.
512 #[doc(alias = "VIRTIO_NET_F_CTRL_RX")]
513 const CTRL_RX = 1 << 18;
514
515 /// Control channel VLAN filtering.
516 #[doc(alias = "VIRTIO_NET_F_CTRL_VLAN")]
517 const CTRL_VLAN = 1 << 19;
518
519 /// Control channel RX extra mode support.
520 #[doc(alias = "VIRTIO_NET_F_CTRL_RX_EXTRA")]
521 const CTRL_RX_EXTRA = 1 << 20;
522
523 /// Driver can send gratuitous
524 /// packets.
525 #[doc(alias = "VIRTIO_NET_F_GUEST_ANNOUNCE")]
526 const GUEST_ANNOUNCE = 1 << 21;
527
528 /// Device supports multiqueue with automatic
529 /// receive steering.
530 #[doc(alias = "VIRTIO_NET_F_MQ")]
531 const MQ = 1 << 22;
532
533 /// Set MAC address through control
534 /// channel.
535 #[doc(alias = "VIRTIO_NET_F_CTRL_MAC_ADDR")]
536 const CTRL_MAC_ADDR = 1 << 23;
537
538 /// Device can provide device-level statistics
539 /// to the driver through the control virtqueue.
540 #[doc(alias = "VIRTIO_NET_F_DEVICE_STATS")]
541 const DEVICE_STATS = 1 << 50;
542
543 /// Device supports inner header hash for encapsulated packets.
544 #[doc(alias = "VIRTIO_NET_F_HASH_TUNNEL")]
545 const HASH_TUNNEL = 1 << 51;
546
547 /// Device supports virtqueue notification coalescing.
548 #[doc(alias = "VIRTIO_NET_F_VQ_NOTF_COAL")]
549 const VQ_NOTF_COAL = 1 << 52;
550
551 /// Device supports notifications coalescing.
552 #[doc(alias = "VIRTIO_NET_F_NOTF_COAL")]
553 const NOTF_COAL = 1 << 53;
554
555 /// Driver can receive USOv4 packets.
556 #[doc(alias = "VIRTIO_NET_F_GUEST_USO4")]
557 const GUEST_USO4 = 1 << 54;
558
559 /// Driver can receive USOv6 packets.
560 #[doc(alias = "VIRTIO_NET_F_GUEST_USO6")]
561 const GUEST_USO6 = 1 << 55;
562
563 /// Device can receive USO packets. Unlike UFO
564 /// (fragmenting the packet) the USO splits large UDP packet
565 /// to several segments when each of these smaller packets has UDP header.
566 #[doc(alias = "VIRTIO_NET_F_HOST_USO")]
567 const HOST_USO = 1 << 56;
568
569 /// Device can report per-packet hash
570 /// value and a type of calculated hash.
571 #[doc(alias = "VIRTIO_NET_F_HASH_REPORT")]
572 const HASH_REPORT = 1 << 57;
573
574 /// Driver can provide the exact _hdr_len_
575 /// value. Device benefits from knowing the exact header length.
576 #[doc(alias = "VIRTIO_NET_F_GUEST_HDRLEN")]
577 const GUEST_HDRLEN = 1 << 59;
578
579 /// Device supports RSS (receive-side scaling)
580 /// with Toeplitz hash calculation and configurable hash
581 /// parameters for receive steering.
582 #[doc(alias = "VIRTIO_NET_F_RSS")]
583 const RSS = 1 << 60;
584
585 /// Device can process duplicated ACKs
586 /// and report number of coalesced segments and duplicated ACKs.
587 #[doc(alias = "VIRTIO_NET_F_RSC_EXT")]
588 const RSC_EXT = 1 << 61;
589
590 /// Device may act as a standby for a primary
591 /// device with the same MAC address.
592 #[doc(alias = "VIRTIO_NET_F_STANDBY")]
593 const STANDBY = 1 << 62;
594
595 /// Device reports speed and duplex.
596 #[doc(alias = "VIRTIO_NET_F_SPEED_DUPLEX")]
597 const SPEED_DUPLEX = 1 << 63;
598
599 /// Device supports multiple RSS contexts.
600 #[doc(alias = "VIRTIO_NET_F_RSS_CONTEXT")]
601 const RSS_CONTEXT = 1 << 64;
602
603 /// Driver can receive GSO packets
604 /// carried by a UDP tunnel.
605 #[doc(alias = "VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO")]
606 const GUEST_UDP_TUNNEL_GSO = 1 << 65;
607
608 /// Driver handles packets
609 /// carried by a UDP tunnel with partial csum for the outer header.
610 #[doc(alias = "VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO_CSUM")]
611 const GUEST_UDP_TUNNEL_GSO_CSUM = 1 << 66;
612
613 /// Device can receive GSO packets
614 /// carried by a UDP tunnel.
615 #[doc(alias = "VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO")]
616 const HOST_UDP_TUNNEL_GSO = 1 << 67;
617
618 /// Device handles packets
619 /// carried by a UDP tunnel with partial csum for the outer header.
620 #[doc(alias = "VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO_CSUM")]
621 const HOST_UDP_TUNNEL_GSO_CSUM = 1 << 68;
622
623 /// Driver can provide the start of
624 /// `outer_nh_offset` value. Device gains advantage by not reading packet
625 /// to calculate outer network header offset.
626 #[doc(alias = "VIRTIO_NET_F_OUT_NET_HEADER")]
627 const OUT_NET_HEADER = 1 << 69;
628
629 /// Device supports inline IPsec processing.
630 /// `struct virtio_net_hdr` size expands upto field `sturct ipsec_resource_hdr`
631 /// when VIRTIO_NET_F_IPSEC is negotiated. When a device offers IPsec feature, it SHOULD
632 /// also offer the VIRTIO_NET_F_OUT_NET_HEADER feature.
633 #[doc(alias = "VIRTIO_NET_F_IPSEC")]
634 const IPSEC = 1 << 70;
635 }
636 }
637
638 impl crate::FeatureBits for F {
639 fn requirements_satisfied(&self) -> bool {
640 self.iter().all(|feature| match feature {
641 Self::GUEST_TSO4 => self.contains(Self::GUEST_CSUM),
642 Self::GUEST_TSO6 => self.contains(Self::GUEST_CSUM),
643 Self::GUEST_ECN => self.intersects(Self::GUEST_TSO4 | Self::GUEST_TSO6),
644 Self::GUEST_UFO => self.contains(Self::GUEST_CSUM),
645 Self::GUEST_USO4 => self.contains(Self::GUEST_CSUM),
646 Self::GUEST_USO6 => self.contains(Self::GUEST_CSUM),
647 Self::GUEST_UDP_TUNNEL_GSO => self.contains(
648 Self::GUEST_TSO4 | Self::GUEST_TSO6 | Self::GUEST_USO4 | Self::GUEST_USO6,
649 ),
650 Self::GUEST_UDP_TUNNEL_GSO_CSUM => self.contains(Self::GUEST_UDP_TUNNEL_GSO),
651 Self::HOST_TSO4 => self.contains(Self::CSUM),
652 Self::HOST_TSO6 => self.contains(Self::CSUM),
653 Self::HOST_ECN => self.intersects(Self::HOST_TSO4 | Self::HOST_TSO6),
654 Self::HOST_UFO => self.contains(Self::CSUM),
655 Self::HOST_USO => self.contains(Self::CSUM),
656 Self::HOST_UDP_TUNNEL_GSO => {
657 self.contains(Self::HOST_TSO4 | Self::HOST_TSO6 | Self::HOST_USO)
658 }
659 Self::HOST_UDP_TUNNEL_GSO_CSUM => self.contains(Self::HOST_UDP_TUNNEL_GSO),
660 Self::CTRL_RX => self.contains(Self::CTRL_VQ),
661 Self::CTRL_VLAN => self.contains(Self::CTRL_VQ),
662 Self::GUEST_ANNOUNCE => self.contains(Self::CTRL_VQ),
663 Self::MQ => self.contains(Self::CTRL_VQ),
664 Self::CTRL_MAC_ADDR => self.contains(Self::CTRL_VQ),
665 Self::NOTF_COAL => self.contains(Self::CTRL_VQ),
666 Self::RSC_EXT => self.intersects(Self::HOST_TSO4 | Self::HOST_TSO6),
667 Self::RSS => self.contains(Self::CTRL_VQ),
668 Self::VQ_NOTF_COAL => self.contains(Self::CTRL_VQ),
669 Self::HASH_TUNNEL => {
670 self.contains(Self::CTRL_VQ) && self.intersects(Self::RSS | Self::HASH_REPORT)
671 }
672 Self::RSS_CONTEXT => self.contains(Self::CTRL_VQ | Self::RSS),
673 _ => true,
674 })
675 }
676
677 fn recommendations_satisfied(&self) -> bool {
678 self.iter().all(|feature| match feature {
679 Self::HASH_REPORT => self.contains(Self::CTRL_VQ),
680 Self::CTRL_RX_EXTRA => self.contains(Self::CTRL_VQ),
681 _ => true,
682 })
683 }
684 }
685}
686
687pub mod fs {
688 use crate::le128;
689
690 feature_bits! {
691 /// File System Device Feature Bits
692 #[doc(alias = "VIRTIO_FS_F")]
693 pub struct F: le128 {
694 /// Device has support for FUSE notify
695 /// messages. The notification queue is virtqueue 1.
696 #[doc(alias = "VIRTIO_FS_F_NOTIFICATION")]
697 const NOTIFICATION = 1 << 0;
698 }
699 }
700
701 impl crate::FeatureBits for F {}
702}
703
704pub mod vsock {
705 use crate::le128;
706
707 feature_bits! {
708 /// Socket Device Feature Bits
709 #[doc(alias = "VIRTIO_VSOCK_F")]
710 pub struct F: le128 {
711 /// stream socket type is supported.
712 #[doc(alias = "VIRTIO_VSOCK_F_STREAM")]
713 const STREAM = 1 << 0;
714
715 /// seqpacket socket type is supported.
716 #[doc(alias = "VIRTIO_VSOCK_F_SEQPACKET")]
717 const SEQPACKET = 1 << 1;
718
719 /// stream socket type is not implied.
720 #[doc(alias = "VIRTIO_VSOCK_F_NO_IMPLIED_STREAM")]
721 const NO_IMPLIED_STREAM = 1 << 2;
722 }
723 }
724
725 impl crate::FeatureBits for F {}
726}
727
728pub mod balloon {
729 use crate::le128;
730
731 feature_bits! {
732 /// Traditional Memory Balloon Device Feature Bits
733 #[doc(alias = "VIRTIO_BALLOON_F")]
734 pub struct F: le128 {
735 /// Host has to be told before pages from the balloon are used.
736 #[doc(alias = "VIRTIO_BALLOON_F_MUST_TELL_HOST")]
737 const MUST_TELL_HOST = 1 << 0;
738
739 /// A virtqueue for reporting guest memory statistics is present.
740 #[doc(alias = "VIRTIO_BALLOON_F_STATS_VQ")]
741 const STATS_VQ = 1 << 1;
742
743 /// Deflate balloon on guest out of memory condition.
744 ///
745 /// <div class="warning">
746 ///
747 /// The specification is a bit confusing on this feature, see [oasis-tcs/virtio-spec#228](https://github.com/oasis-tcs/virtio-spec/issues/228).
748 ///
749 /// </div>
750 #[doc(alias = "VIRTIO_BALLOON_F_DEFLATE_ON_OOM")]
751 const DEFLATE_ON_OOM = 1 << 2;
752
753 /// The device has support for free page hinting.
754 /// A virtqueue for providing hints as to what memory is currently free is present.
755 /// Configuration field [`free_page_hint_cmd_id`](`crate::balloon::ConfigVolatileFieldAccess::free_page_hint_cmd_id`) is valid.
756 #[doc(alias = "VIRTIO_BALLOON_F_FREE_PAGE_HINT")]
757 const FREE_PAGE_HINT = 1 << 3;
758
759 /// A hint to the device, that the driver will immediately write
760 /// [`poison_val`] to pages after deflating them.
761 /// Configuration field [`poison_val`] is valid.
762 ///
763 /// [`poison_val`]: crate::balloon::ConfigVolatileFieldAccess::poison_val
764 #[doc(alias = "VIRTIO_BALLOON_F_PAGE_POISON")]
765 const PAGE_POISON = 1 << 4;
766
767 /// The device has support for free page reporting.
768 /// A virtqueue for reporting free guest memory is present.
769 #[doc(alias = "VIRTIO_BALLOON_F_PAGE_REPORTING")]
770 const PAGE_REPORTING = 1 << 5;
771 }
772 }
773
774 impl crate::FeatureBits for F {}
775}
776
777#[cfg(test)]
778mod tests {
779 use super::*;
780
781 #[rustfmt::skip]
782 #[test]
783 fn requirements_satisfied() {
784 assert!(F::INDIRECT_DESC.requirements_satisfied());
785
786 assert!(net::F::CSUM.requirements_satisfied());
787
788 assert!(!net::F::MQ.requirements_satisfied());
789 assert!((net::F::MQ | net::F::CTRL_VQ).requirements_satisfied());
790
791 assert!(!net::F::HOST_TSO4.requirements_satisfied());
792 assert!((net::F::HOST_TSO4 | net::F::CSUM).requirements_satisfied());
793 assert!((net::F::HOST_TSO4 | net::F::HOST_TSO6 | net::F::CSUM).requirements_satisfied());
794
795 assert!(!net::F::HOST_ECN.requirements_satisfied());
796 assert!(!(net::F::HOST_ECN | net::F::CSUM).requirements_satisfied());
797 assert!(!(net::F::HOST_ECN | net::F::HOST_TSO4).requirements_satisfied());
798 assert!((net::F::HOST_ECN | net::F::HOST_TSO4 | net::F::CSUM).requirements_satisfied());
799 assert!((net::F::HOST_ECN | net::F::HOST_TSO4 | net::F::HOST_TSO6 | net::F::CSUM).requirements_satisfied());
800 }
801}