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}