netstack3_base/
counters.rs

1// Copyright 2024 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//! Common counter abstractions.
6
7use core::sync::atomic::{AtomicU64, Ordering};
8
9/// An atomic counter for packet statistics, e.g. IPv4 packets received.
10#[derive(Debug, Default)]
11pub struct Counter(AtomicU64);
12
13impl Counter {
14    /// Increments the counter value by 1.
15    pub fn increment(&self) {
16        // Use relaxed ordering since we do not use packet counter values to
17        // synchronize other accesses.  See:
18        // https://doc.rust-lang.org/nomicon/atomics.html#relaxed
19        let Self(v) = self;
20        let _: u64 = v.fetch_add(1, Ordering::Relaxed);
21    }
22
23    /// Adds the provided value to the counter.
24    pub fn add(&self, n: u64) {
25        // Use relaxed ordering since we do not use packet counter values to
26        // synchronize other accesses.  See:
27        // https://doc.rust-lang.org/nomicon/atomics.html#relaxed
28        let Self(v) = self;
29        let _: u64 = v.fetch_add(n, Ordering::Relaxed);
30    }
31
32    /// Atomically retrieves the counter value as a `u64`.
33    pub fn get(&self) -> u64 {
34        // Use relaxed ordering since we do not use packet counter values to
35        // synchronize other accesses.  See:
36        // https://doc.rust-lang.org/nomicon/atomics.html#relaxed
37        let Self(v) = self;
38        v.load(Ordering::Relaxed)
39    }
40}
41
42/// A context that stores counters.
43///
44/// `CounterContext` exposes access to counters for observation and debugging.
45pub trait CounterContext<T> {
46    /// Returns a reference to the counters.
47    fn counters(&self) -> &T;
48}
49
50/// A context that provides access to per-resource counters for observation and
51/// debugging.
52pub trait ResourceCounterContext<R, T>: CounterContext<T> {
53    /// Returns a reference to the set of counters on `resource`.
54    fn per_resource_counters<'a>(&'a self, resource: &'a R) -> &'a T;
55
56    /// Increments both the per-resource and stackwide versions of
57    /// the counter returned by the callback.
58    fn increment_both<F: Fn(&T) -> &Counter>(&self, resource: &R, cb: F) {
59        cb(self.per_resource_counters(resource)).increment();
60        cb(self.counters()).increment();
61    }
62}