netstack3_device/
state.rs1use alloc::sync::Arc;
8use core::fmt::Debug;
9
10use lock_order::lock::{OrderedLockAccess, OrderedLockRef};
11use net_types::ip::{Ipv4, Ipv6};
12use netstack3_base::sync::{RwLock, WeakRc};
13use netstack3_base::{
14 CoreTimerContext, Device, DeviceIdContext, Inspectable, TimerContext, WeakDeviceIdentifier,
15};
16use netstack3_ip::RawMetric;
17use netstack3_ip::device::{DualStackIpDeviceState, IpDeviceTimerId};
18
19use crate::internal::base::{DeviceCounters, DeviceLayerTypes, OriginTracker};
20use crate::internal::queue::DeviceBufferSpec;
21use crate::internal::socket::HeldDeviceSockets;
22
23pub trait DeviceStateSpec: Device + Sized + Send + Sync + 'static {
26 type State<BT: DeviceLayerTypes>: Send + Sync;
28 type External<BT: DeviceLayerTypes>: Send + Sync;
30 type CreationProperties: Debug;
32 type Counters: Inspectable;
34 type TimerId<D: WeakDeviceIdentifier>;
36
37 fn new_device_state<
39 CC: CoreTimerContext<Self::TimerId<CC::WeakDeviceId>, BC> + DeviceIdContext<Self>,
40 BC: DeviceLayerTypes + TimerContext,
41 >(
42 bindings_ctx: &mut BC,
43 self_id: CC::WeakDeviceId,
44 properties: Self::CreationProperties,
45 tx_allocator: <Self as DeviceBufferSpec<BC>>::TxAllocator,
46 ) -> Self::State<BC>
47 where
48 Self: DeviceBufferSpec<BC>;
49
50 const IS_LOOPBACK: bool;
52 const DEBUG_TYPE: &'static str;
54}
55
56pub(crate) struct WeakCookie<T: DeviceStateSpec, BT: DeviceLayerTypes> {
63 pub(crate) bindings_id: BT::DeviceIdentifier,
64 pub(crate) weak_ref: WeakRc<BaseDeviceState<T, BT>>,
65}
66
67pub(crate) struct BaseDeviceState<T: DeviceStateSpec, BT: DeviceLayerTypes> {
68 pub(crate) ip: IpLinkDeviceState<T, BT>,
69 pub(crate) external_state: T::External<BT>,
70 pub(crate) weak_cookie: Arc<WeakCookie<T, BT>>,
71}
72
73pub type IpLinkDeviceState<T, BT> = IpLinkDeviceStateInner<<T as DeviceStateSpec>::State<BT>, BT>;
77
78pub struct IpLinkDeviceStateInner<T, BT: DeviceLayerTypes> {
82 pub ip: DualStackIpDeviceState<BT>,
84 pub link: T,
86 pub(crate) origin: OriginTracker,
87 pub(super) sockets: RwLock<HeldDeviceSockets<BT>>,
88 pub counters: DeviceCounters,
90}
91
92impl<T, BC: DeviceLayerTypes + TimerContext> IpLinkDeviceStateInner<T, BC> {
93 pub fn new<
95 D: WeakDeviceIdentifier,
96 CC: CoreTimerContext<IpDeviceTimerId<Ipv6, D, BC>, BC>
97 + CoreTimerContext<IpDeviceTimerId<Ipv4, D, BC>, BC>,
98 >(
99 bindings_ctx: &mut BC,
100 device_id: D,
101 link: T,
102 metric: RawMetric,
103 origin: OriginTracker,
104 ) -> Self {
105 Self {
106 ip: DualStackIpDeviceState::new::<D, CC>(bindings_ctx, device_id, metric),
107 link,
108 origin,
109 sockets: RwLock::new(HeldDeviceSockets::default()),
110 counters: DeviceCounters::default(),
111 }
112 }
113}
114
115impl<T, BT: DeviceLayerTypes> AsRef<DualStackIpDeviceState<BT>> for IpLinkDeviceStateInner<T, BT> {
116 fn as_ref(&self) -> &DualStackIpDeviceState<BT> {
117 &self.ip
118 }
119}
120
121impl<T, BT: DeviceLayerTypes> OrderedLockAccess<HeldDeviceSockets<BT>>
122 for IpLinkDeviceStateInner<T, BT>
123{
124 type Lock = RwLock<HeldDeviceSockets<BT>>;
125 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
126 OrderedLockRef::new(&self.sockets)
127 }
128}