netstack3_base/
inspect.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//! Abstractions to expose netstack3 core state to human inspection in bindings.
6//!
7//! This module mostly exists to abstract the dependency to Fuchsia inspect via
8//! a trait, so we don't have to expose all of the internal core types to
9//! bindings for it to perform the inspection.
10
11use core::fmt::Display;
12
13pub use diagnostics_traits::{Inspectable, InspectableValue, Inspector, InspectorDeviceExt};
14use net_types::ip::IpAddress;
15use net_types::{AddrAndPortFormatter, ZonedAddr};
16
17use crate::counters::Counter;
18
19/// Extension trait for [`Inspector`] adding support for netstack3-specific
20/// types.
21pub trait InspectorExt: Inspector {
22    /// Records a counter.
23    fn record_counter(&mut self, name: &str, value: &Counter) {
24        self.record_uint(name, value.get())
25    }
26
27    /// Records a `ZonedAddr` and it's port, mapping the zone into an
28    /// inspectable device identifier.
29    fn record_zoned_addr_with_port<I: InspectorDeviceExt<D>, A: IpAddress, D, P: Display>(
30        &mut self,
31        name: &str,
32        addr: ZonedAddr<A, D>,
33        port: P,
34    ) {
35        self.record_display(
36            name,
37            AddrAndPortFormatter::<_, _, A::Version>::new(
38                addr.map_zone(|device| I::device_identifier_as_address_zone(device)),
39                port,
40            ),
41        )
42    }
43
44    /// Records the local address of a socket.
45    fn record_local_socket_addr<I: InspectorDeviceExt<D>, A: IpAddress, D, P: Display>(
46        &mut self,
47        addr_with_port: Option<(ZonedAddr<A, D>, P)>,
48    ) {
49        const NAME: &str = "LocalAddress";
50        if let Some((addr, port)) = addr_with_port {
51            self.record_zoned_addr_with_port::<I, _, _, _>(NAME, addr, port);
52        } else {
53            self.record_str(NAME, "[NOT BOUND]")
54        }
55    }
56
57    /// Records the remote address of a socket.
58    fn record_remote_socket_addr<I: InspectorDeviceExt<D>, A: IpAddress, D, P: Display>(
59        &mut self,
60        addr_with_port: Option<(ZonedAddr<A, D>, P)>,
61    ) {
62        const NAME: &str = "RemoteAddress";
63        if let Some((addr, port)) = addr_with_port {
64            self.record_zoned_addr_with_port::<I, _, _, _>(NAME, addr, port);
65        } else {
66            self.record_str(NAME, "[NOT CONNECTED]")
67        }
68    }
69}
70
71impl<T: Inspector> InspectorExt for T {}