netstack3_device/
queue.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Device queues.
6
7use alloc::collections::VecDeque;
8
9use netstack3_base::{ErrorAndSerializer, WorkQueueReport};
10use packet::SerializeError;
11
12use crate::internal::base::DeviceSendFrameError;
13
14pub(crate) mod api;
15mod fifo;
16pub(crate) mod rx;
17pub(crate) mod tx;
18
19/// The maximum number of elements that can be in the RX queue.
20const MAX_RX_QUEUED_LEN: usize = 10000;
21/// The maximum number of elements that can be in the TX queue.
22const MAX_TX_QUEUED_LEN: usize = 10000;
23
24/// Error returned when the receive queue is full.
25#[derive(Debug, PartialEq, Eq)]
26pub struct ReceiveQueueFullError<T>(pub T);
27
28#[derive(Debug, PartialEq, Eq)]
29pub enum TransmitQueueFrameError<S> {
30    NoQueue(DeviceSendFrameError),
31    QueueFull(S),
32    SerializeError(ErrorAndSerializer<SerializeError<()>, S>),
33}
34
35/// The state used to dequeue and handle frames from the device queue.
36pub struct DequeueState<Meta, Buffer> {
37    dequeued_frames: VecDeque<(Meta, Buffer)>,
38}
39
40impl<Meta, Buffer> Default for DequeueState<Meta, Buffer> {
41    fn default() -> DequeueState<Meta, Buffer> {
42        DequeueState {
43            // Make sure we can dequeue up to `BatchSize` frames without
44            // needing to reallocate.
45            dequeued_frames: VecDeque::with_capacity(BatchSize::MAX),
46        }
47    }
48}
49
50#[derive(Debug, PartialEq, Eq)]
51enum EnqueueResult {
52    QueueWasPreviouslyEmpty,
53    QueuePreviouslyWasOccupied,
54}
55
56#[derive(Debug)]
57enum DequeueResult {
58    MoreStillQueued,
59    NoMoreLeft,
60}
61
62impl From<DequeueResult> for WorkQueueReport {
63    fn from(value: DequeueResult) -> Self {
64        match value {
65            DequeueResult::MoreStillQueued => Self::Pending,
66            DequeueResult::NoMoreLeft => Self::AllDone,
67        }
68    }
69}
70
71/// A type representing an operation count in a queue (e.g. the number of
72/// packets allowed to be dequeued in a single operation).
73///
74/// `BatchSize` is always capped at the maximum supported batch size for the
75/// queue and defaults to that value.
76#[derive(Copy, Clone, Debug, Eq, PartialEq)]
77pub struct BatchSize(usize);
78
79impl BatchSize {
80    /// The maximum usize value that `BatchSize` can assume.
81    ///
82    /// Restricting the amount of work that can be done at once in a queue
83    /// serves two purposes:
84    ///
85    /// - It sets an upper bound on the amount of work that can be done before
86    ///   yielding the thread to other work.
87    /// - It sets an upper bound of memory consumption set aside for dequeueing,
88    ///   because dequeueing takes frames from the queue and "stages" them in a
89    ///   separate context.
90    pub const MAX: usize = 100;
91
92    /// Creates a new `BatchSize` with a value of `v` saturating to
93    /// [`BatchSize::MAX`].
94    pub fn new_saturating(v: usize) -> Self {
95        Self(v.min(Self::MAX))
96    }
97}
98
99impl From<BatchSize> for usize {
100    fn from(BatchSize(v): BatchSize) -> Self {
101        v
102    }
103}
104
105impl Default for BatchSize {
106    fn default() -> Self {
107        Self(Self::MAX)
108    }
109}