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