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 ChecksumOffloadSpec, CoreTimerContext, Device, DeviceIdContext, Inspectable, TimerContext,
15 WeakDeviceIdentifier,
16};
17use netstack3_ip::RawMetric;
18use netstack3_ip::device::{DualStackIpDeviceState, IpDeviceTimerId};
19
20use crate::internal::base::{DeviceCounters, DeviceLayerTypes, OriginTracker};
21use crate::internal::queue::DeviceBufferSpec;
22use crate::internal::socket::HeldDeviceSockets;
23
24pub trait DeviceStateSpec: Device + Sized + Send + Sync + 'static {
27 type State<BT: DeviceLayerTypes>: Send + Sync;
29 type External<BT: DeviceLayerTypes>: Send + Sync;
31 type CreationProperties: Debug;
33 type Counters: Inspectable;
35 type TimerId<D: WeakDeviceIdentifier>;
37
38 fn new_device_state<
40 CC: CoreTimerContext<Self::TimerId<CC::WeakDeviceId>, BC> + DeviceIdContext<Self>,
41 BC: DeviceLayerTypes + TimerContext,
42 >(
43 bindings_ctx: &mut BC,
44 self_id: CC::WeakDeviceId,
45 properties: Self::CreationProperties,
46 tx_allocator: <Self as DeviceBufferSpec<BC>>::TxAllocator,
47 ) -> Self::State<BC>
48 where
49 Self: DeviceBufferSpec<BC>;
50
51 const IS_LOOPBACK: bool;
53 const DEBUG_TYPE: &'static str;
55
56 fn tx_offload_spec<BT: DeviceLayerTypes>(
58 state: &Self::State<BT>,
59 ) -> Option<ChecksumOffloadSpec>;
60}
61
62pub(crate) struct WeakCookie<T: DeviceStateSpec, BT: DeviceLayerTypes> {
69 pub(crate) bindings_id: BT::DeviceIdentifier,
70 pub(crate) weak_ref: WeakRc<BaseDeviceState<T, BT>>,
71}
72
73pub(crate) struct BaseDeviceState<T: DeviceStateSpec, BT: DeviceLayerTypes> {
74 pub(crate) ip: IpLinkDeviceState<T, BT>,
75 pub(crate) external_state: T::External<BT>,
76 pub(crate) weak_cookie: Arc<WeakCookie<T, BT>>,
77}
78
79pub type IpLinkDeviceState<T, BT> = IpLinkDeviceStateInner<<T as DeviceStateSpec>::State<BT>, BT>;
83
84pub struct IpLinkDeviceStateInner<T, BT: DeviceLayerTypes> {
88 pub ip: DualStackIpDeviceState<BT>,
90 pub link: T,
92 pub(crate) origin: OriginTracker,
93 pub(super) sockets: RwLock<HeldDeviceSockets<BT>>,
94 pub counters: DeviceCounters,
96}
97
98impl<T, BC: DeviceLayerTypes + TimerContext> IpLinkDeviceStateInner<T, BC> {
99 pub fn new<
101 D: WeakDeviceIdentifier,
102 CC: CoreTimerContext<IpDeviceTimerId<Ipv6, D, BC>, BC>
103 + CoreTimerContext<IpDeviceTimerId<Ipv4, D, BC>, BC>,
104 >(
105 bindings_ctx: &mut BC,
106 device_id: D,
107 link: T,
108 metric: RawMetric,
109 origin: OriginTracker,
110 ) -> Self {
111 Self {
112 ip: DualStackIpDeviceState::new::<D, CC>(bindings_ctx, device_id, metric),
113 link,
114 origin,
115 sockets: RwLock::new(HeldDeviceSockets::default()),
116 counters: DeviceCounters::default(),
117 }
118 }
119}
120
121impl<T, BT: DeviceLayerTypes> AsRef<DualStackIpDeviceState<BT>> for IpLinkDeviceStateInner<T, BT> {
122 fn as_ref(&self) -> &DualStackIpDeviceState<BT> {
123 &self.ip
124 }
125}
126
127impl<T, BT: DeviceLayerTypes> OrderedLockAccess<HeldDeviceSockets<BT>>
128 for IpLinkDeviceStateInner<T, BT>
129{
130 type Lock = RwLock<HeldDeviceSockets<BT>>;
131 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
132 OrderedLockRef::new(&self.sockets)
133 }
134}
135
136pub trait DeviceTxOffloadSpecContext<D: DeviceStateSpec, BT: DeviceLayerTypes>:
138 DeviceIdContext<D>
139{
140 fn tx_offload_spec(&self, device: &Self::DeviceId) -> Option<ChecksumOffloadSpec>;
142}