netstack3_core/
state.rs
1use lock_order::lock::UnlockedAccess;
8use netstack3_base::{BuildableCoreContext, ContextProvider, CoreTimerContext, CtxPair};
9use netstack3_device::{DeviceId, DeviceLayerState};
10use netstack3_ip::icmp::IcmpState;
11use netstack3_ip::{self as ip, IpLayerIpExt, IpLayerTimerId, IpStateInner, Ipv4State, Ipv6State};
12
13use crate::api::CoreApi;
14use crate::time::TimerId;
15use crate::transport::{TransportLayerState, TransportStateBuilder};
16use crate::{BindingsContext, BindingsTypes, CoreCtx};
17
18#[derive(Clone, Default)]
20pub struct StackStateBuilder {
21 transport: TransportStateBuilder,
22 ipv4: ip::Ipv4StateBuilder,
23 ipv6: ip::Ipv6StateBuilder,
24}
25
26impl StackStateBuilder {
27 pub fn transport_builder(&mut self) -> &mut TransportStateBuilder {
29 &mut self.transport
30 }
31
32 pub fn ipv4_builder(&mut self) -> &mut ip::Ipv4StateBuilder {
34 &mut self.ipv4
35 }
36
37 pub fn ipv6_builder(&mut self) -> &mut ip::Ipv6StateBuilder {
39 &mut self.ipv6
40 }
41
42 pub fn build_with_ctx<BC: BindingsContext>(self, bindings_ctx: &mut BC) -> StackState<BC> {
44 StackState {
45 transport: self.transport.build_with_ctx(bindings_ctx),
46 ipv4: self.ipv4.build::<StackState<BC>, _, _>(bindings_ctx),
47 ipv6: self.ipv6.build::<StackState<BC>, _, _>(bindings_ctx),
48 device: Default::default(),
49 }
50 }
51}
52
53impl<BC: BindingsContext> BuildableCoreContext<BC> for StackState<BC> {
54 type Builder = StackStateBuilder;
55 fn build(bindings_ctx: &mut BC, builder: StackStateBuilder) -> Self {
56 builder.build_with_ctx(bindings_ctx)
57 }
58}
59
60pub struct StackState<BT: BindingsTypes> {
62 pub(crate) transport: TransportLayerState<BT>,
63 pub(crate) ipv4: Ipv4State<DeviceId<BT>, BT>,
64 pub(crate) ipv6: Ipv6State<DeviceId<BT>, BT>,
65 pub(crate) device: DeviceLayerState<BT>,
66}
67
68impl<BT: BindingsTypes> StackState<BT> {
69 pub fn api<'a, BP: ContextProvider<Context = BT>>(
71 &'a self,
72 bindings_ctx: BP,
73 ) -> CoreApi<'a, BP> {
74 CoreApi::new(CtxPair { core_ctx: CoreCtx::new(self), bindings_ctx })
75 }
76
77 pub(crate) fn inner_ip_state<I: IpLayerIpExt>(&self) -> &IpStateInner<I, DeviceId<BT>, BT> {
78 I::map_ip((), |()| &self.ipv4.inner, |()| &self.ipv6.inner)
79 }
80
81 pub(crate) fn inner_icmp_state<I: netstack3_base::IpExt>(&self) -> &IcmpState<I, BT> {
82 I::map_ip((), |()| &self.ipv4.icmp.inner, |()| &self.ipv6.icmp.inner)
83 }
84}
85
86#[cfg(any(test, feature = "testutils"))]
89
90impl<BT: BindingsTypes> StackState<BT> {
91 pub fn transport(&self) -> &TransportLayerState<BT> {
93 &self.transport
94 }
95 pub fn ipv4(&self) -> &Ipv4State<DeviceId<BT>, BT> {
97 &self.ipv4
98 }
99 pub fn ipv6(&self) -> &Ipv6State<DeviceId<BT>, BT> {
101 &self.ipv6
102 }
103 pub fn device(&self) -> &DeviceLayerState<BT> {
105 &self.device
106 }
107 pub fn context(&self) -> crate::context::UnlockedCoreCtx<'_, BT> {
109 crate::context::UnlockedCoreCtx::new(self)
110 }
111 pub fn common_ip<I: IpLayerIpExt>(&self) -> &IpStateInner<I, DeviceId<BT>, BT> {
113 self.inner_ip_state::<I>()
114 }
115 pub fn common_icmp<I: netstack3_base::IpExt>(&self) -> &IcmpState<I, BT> {
117 self.inner_icmp_state::<I>()
118 }
119}
120
121impl<BT: BindingsTypes> CoreTimerContext<IpLayerTimerId, BT> for StackState<BT> {
122 fn convert_timer(timer: IpLayerTimerId) -> TimerId<BT> {
123 timer.into()
124 }
125}
126
127impl<BT: BindingsTypes> UnlockedAccess<crate::lock_ordering::UnlockedState> for StackState<BT> {
136 type Data = StackState<BT>;
137 type Guard<'l>
138 = &'l StackState<BT>
139 where
140 Self: 'l;
141
142 fn access(&self) -> Self::Guard<'_> {
143 &self
144 }
145}