Skip to main content

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;
13use crate::internal::queue::tx::TxBufferAllocator;
14
15pub(crate) mod api;
16mod fifo;
17pub(crate) mod rx;
18pub(crate) mod tx;
19
20/// The maximum number of elements that can be in the RX queue.
21const MAX_RX_QUEUED_LEN: usize = 10000;
22/// The maximum number of elements that can be in the TX queue.
23const MAX_TX_QUEUED_LEN: usize = 10000;
24
25/// Error returned when the receive queue is full.
26#[derive(Debug, PartialEq, Eq)]
27pub struct ReceiveQueueFullError<T>(pub T);
28
29#[derive(Debug, PartialEq, Eq)]
30pub enum TransmitQueueFrameError<S> {
31    NoQueue(DeviceSendFrameError),
32    QueueFull(S),
33    SerializeError(ErrorAndSerializer<SerializeError<()>, S>),
34}
35
36/// The state used to dequeue and handle frames from the device queue.
37pub struct DequeueState<Meta, Buffer> {
38    dequeued_frames: VecDeque<(Meta, Buffer)>,
39}
40
41impl<Meta, Buffer> Default for DequeueState<Meta, Buffer> {
42    fn default() -> DequeueState<Meta, Buffer> {
43        DequeueState {
44            // Make sure we can dequeue up to `BatchSize` frames without
45            // needing to reallocate.
46            dequeued_frames: VecDeque::with_capacity(BatchSize::MAX),
47        }
48    }
49}
50
51#[derive(Debug, PartialEq, Eq)]
52enum EnqueueResult {
53    QueueWasPreviouslyEmpty,
54    QueuePreviouslyWasOccupied,
55}
56
57#[derive(Debug)]
58enum DequeueResult {
59    MoreStillQueued,
60    NoMoreLeft,
61}
62
63impl From<DequeueResult> for WorkQueueReport {
64    fn from(value: DequeueResult) -> Self {
65        match value {
66            DequeueResult::MoreStillQueued => Self::Pending,
67            DequeueResult::NoMoreLeft => Self::AllDone,
68        }
69    }
70}
71
72/// A type representing an operation count in a queue (e.g. the number of
73/// packets allowed to be dequeued in a single operation).
74///
75/// `BatchSize` is always capped at the maximum supported batch size for the
76/// queue and defaults to that value.
77#[derive(Copy, Clone, Debug, Eq, PartialEq)]
78pub struct BatchSize(usize);
79
80impl BatchSize {
81    /// The maximum usize value that `BatchSize` can assume.
82    ///
83    /// Restricting the amount of work that can be done at once in a queue
84    /// serves two purposes:
85    ///
86    /// - It sets an upper bound on the amount of work that can be done before
87    ///   yielding the thread to other work.
88    /// - It sets an upper bound of memory consumption set aside for dequeueing,
89    ///   because dequeueing takes frames from the queue and "stages" them in a
90    ///   separate context.
91    pub const MAX: usize = 100;
92
93    /// Creates a new `BatchSize` with a value of `v` saturating to
94    /// [`BatchSize::MAX`].
95    pub fn new_saturating(v: usize) -> Self {
96        Self(v.min(Self::MAX))
97    }
98}
99
100impl From<BatchSize> for usize {
101    fn from(BatchSize(v): BatchSize) -> Self {
102        v
103    }
104}
105
106impl Default for BatchSize {
107    fn default() -> Self {
108        Self(Self::MAX)
109    }
110}
111
112/// Specifies the buffer types for a device.
113pub trait DeviceBufferSpec<BT>: netstack3_base::Device + Send + Sync {
114    /// Used to for Tx Buffers.
115    type TxBuffer: packet::FragmentedBuffer + AsMut<[u8]>;
116    /// Used to allocate Tx Buffers.
117    type TxAllocator: TxBufferAllocator<Self::TxBuffer>;
118}