netstack3_ip/multicast_forwarding/
state.rs
1use alloc::collections::BTreeMap;
8use derivative::Derivative;
9use lock_order::lock::{OrderedLockAccess, OrderedLockRef};
10use netstack3_base::sync::{Mutex, RwLock};
11use netstack3_base::{
12 AnyDevice, CoreTimerContext, CounterContext, DeviceIdContext, StrongDeviceIdentifier,
13};
14
15use crate::internal::multicast_forwarding::counters::MulticastForwardingCounters;
16use crate::internal::multicast_forwarding::packet_queue::MulticastForwardingPendingPackets;
17use crate::internal::multicast_forwarding::route::{MulticastRouteEntry, MulticastRouteKey};
18use crate::internal::multicast_forwarding::{
19 MulticastForwardingBindingsContext, MulticastForwardingBindingsTypes,
20 MulticastForwardingTimerId,
21};
22use crate::IpLayerIpExt;
23
24#[derive(Derivative)]
29#[derivative(Debug(bound = ""), Default(bound = ""))]
30pub enum MulticastForwardingState<
31 I: IpLayerIpExt,
32 D: StrongDeviceIdentifier,
33 BT: MulticastForwardingBindingsTypes,
34> {
35 #[derivative(Default)]
37 Disabled,
38 Enabled(MulticastForwardingEnabledState<I, D, BT>),
40}
41
42impl<I: IpLayerIpExt, D: StrongDeviceIdentifier, BT: MulticastForwardingBindingsTypes>
43 MulticastForwardingState<I, D, BT>
44{
45 pub(crate) fn enabled(&self) -> Option<&MulticastForwardingEnabledState<I, D, BT>> {
46 match self {
47 MulticastForwardingState::Disabled => None,
48 MulticastForwardingState::Enabled(state) => Some(state),
49 }
50 }
51}
52
53#[derive(Derivative)]
55#[derivative(Debug(bound = ""))]
56pub struct MulticastForwardingEnabledState<
57 I: IpLayerIpExt,
58 D: StrongDeviceIdentifier,
59 BT: MulticastForwardingBindingsTypes,
60> {
61 route_table: RwLock<MulticastRouteTable<I, D, BT>>,
65 pending_table: Mutex<MulticastForwardingPendingPackets<I, D::Weak, BT>>,
69}
70
71impl<I: IpLayerIpExt, D: StrongDeviceIdentifier, BC: MulticastForwardingBindingsContext<I, D>>
72 MulticastForwardingEnabledState<I, D, BC>
73{
74 pub(super) fn new<CC>(bindings_ctx: &mut BC) -> Self
75 where
76 CC: CoreTimerContext<MulticastForwardingTimerId<I>, BC>,
77 {
78 Self {
79 route_table: Default::default(),
80 pending_table: Mutex::new(MulticastForwardingPendingPackets::new::<CC>(bindings_ctx)),
81 }
82 }
83
84 #[cfg(test)]
86 pub(super) fn route_table(&self) -> &RwLock<MulticastRouteTable<I, D, BC>> {
87 &self.route_table
88 }
89 #[cfg(test)]
91 pub(super) fn pending_table(
92 &self,
93 ) -> &Mutex<MulticastForwardingPendingPackets<I, D::Weak, BC>> {
94 &self.pending_table
95 }
96}
97
98pub type MulticastRouteTable<I, D, BT> = BTreeMap<MulticastRouteKey<I>, MulticastRouteEntry<D, BT>>;
100
101impl<I: IpLayerIpExt, D: StrongDeviceIdentifier, BT: MulticastForwardingBindingsTypes>
102 OrderedLockAccess<MulticastRouteTable<I, D, BT>> for MulticastForwardingEnabledState<I, D, BT>
103{
104 type Lock = RwLock<MulticastRouteTable<I, D, BT>>;
105 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
106 OrderedLockRef::new(&self.route_table)
107 }
108}
109
110impl<I: IpLayerIpExt, D: StrongDeviceIdentifier, BT: MulticastForwardingBindingsTypes>
111 OrderedLockAccess<MulticastForwardingPendingPackets<I, D::Weak, BT>>
112 for MulticastForwardingEnabledState<I, D, BT>
113{
114 type Lock = Mutex<MulticastForwardingPendingPackets<I, D::Weak, BT>>;
115 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
116 OrderedLockRef::new(&self.pending_table)
117 }
118}
119
120pub trait MulticastForwardingStateContext<I: IpLayerIpExt, BT: MulticastForwardingBindingsTypes>:
122 DeviceIdContext<AnyDevice>
123{
124 type Ctx<'a>: MulticastRouteTableContext<
126 I,
127 BT,
128 DeviceId = Self::DeviceId,
129 WeakDeviceId = Self::WeakDeviceId,
130 > + MulticastForwardingPendingPacketsContext<
131 I,
132 BT,
133 DeviceId = Self::DeviceId,
134 WeakDeviceId = Self::WeakDeviceId,
135 > + CounterContext<MulticastForwardingCounters<I>>;
136 fn with_state<
138 O,
139 F: FnOnce(&MulticastForwardingState<I, Self::DeviceId, BT>, &mut Self::Ctx<'_>) -> O,
140 >(
141 &mut self,
142 cb: F,
143 ) -> O;
144 fn with_state_mut<
146 O,
147 F: FnOnce(&mut MulticastForwardingState<I, Self::DeviceId, BT>, &mut Self::Ctx<'_>) -> O,
148 >(
149 &mut self,
150 cb: F,
151 ) -> O;
152}
153
154pub trait MulticastRouteTableContext<I: IpLayerIpExt, BT: MulticastForwardingBindingsTypes>:
156 DeviceIdContext<AnyDevice>
157{
158 type Ctx<'a>: MulticastForwardingPendingPacketsContext<
160 I,
161 BT,
162 DeviceId = Self::DeviceId,
163 WeakDeviceId = Self::WeakDeviceId,
164 > + CounterContext<MulticastForwardingCounters<I>>;
165 fn with_route_table<
167 O,
168 F: FnOnce(&MulticastRouteTable<I, Self::DeviceId, BT>, &mut Self::Ctx<'_>) -> O,
169 >(
170 &mut self,
171 state: &MulticastForwardingEnabledState<I, Self::DeviceId, BT>,
172 cb: F,
173 ) -> O;
174 fn with_route_table_mut<
176 O,
177 F: FnOnce(&mut MulticastRouteTable<I, Self::DeviceId, BT>, &mut Self::Ctx<'_>) -> O,
178 >(
179 &mut self,
180 state: &MulticastForwardingEnabledState<I, Self::DeviceId, BT>,
181 cb: F,
182 ) -> O;
183}
184
185pub trait MulticastForwardingPendingPacketsContext<
187 I: IpLayerIpExt,
188 BT: MulticastForwardingBindingsTypes,
189>: DeviceIdContext<AnyDevice>
190{
191 fn with_pending_table_mut<
193 O,
194 F: FnOnce(&mut MulticastForwardingPendingPackets<I, Self::WeakDeviceId, BT>) -> O,
195 >(
196 &mut self,
197 state: &MulticastForwardingEnabledState<I, Self::DeviceId, BT>,
198 cb: F,
199 ) -> O;
200}