netstack3_core/ip/
multicast_forwarding.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//! Implementations for multicast forwarding that integrate with traits/types
6//! from foreign modules.
7
8use lock_order::lock::LockLevelFor;
9use lock_order::relation::LockBefore;
10use lock_order::wrap::{LockedWrapperApi, LockedWrapperUnlockedApi};
11use netstack3_base::{CoreTimerContext, CounterContext};
12use netstack3_device::{DeviceId, WeakDeviceId};
13use netstack3_ip::multicast_forwarding::{
14    MulticastForwardingCounters, MulticastForwardingEnabledState,
15    MulticastForwardingPendingPackets, MulticastForwardingPendingPacketsContext,
16    MulticastForwardingState, MulticastForwardingStateContext, MulticastForwardingTimerId,
17    MulticastRouteTable, MulticastRouteTableContext,
18};
19use netstack3_ip::IpLayerTimerId;
20
21use crate::{lock_ordering, BindingsContext, BindingsTypes, CoreCtx, IpExt};
22
23#[netstack3_macros::instantiate_ip_impl_block(I)]
24impl<
25        I: IpExt,
26        BC: BindingsContext,
27        L: LockBefore<lock_ordering::IpMulticastForwardingState<I>>,
28    > MulticastForwardingStateContext<I, BC> for CoreCtx<'_, BC, L>
29{
30    type Ctx<'a> = CoreCtx<'a, BC, lock_ordering::IpMulticastForwardingState<I>>;
31
32    fn with_state<
33        O,
34        F: FnOnce(&MulticastForwardingState<I, Self::DeviceId, BC>, &mut Self::Ctx<'_>) -> O,
35    >(
36        &mut self,
37        cb: F,
38    ) -> O {
39        let (state, mut core_ctx) =
40            self.read_lock_and::<lock_ordering::IpMulticastForwardingState<I>>();
41        cb(&state, &mut core_ctx)
42    }
43
44    fn with_state_mut<
45        O,
46        F: FnOnce(&mut MulticastForwardingState<I, Self::DeviceId, BC>, &mut Self::Ctx<'_>) -> O,
47    >(
48        &mut self,
49        cb: F,
50    ) -> O {
51        let (mut state, mut core_ctx) =
52            self.write_lock_and::<lock_ordering::IpMulticastForwardingState<I>>();
53        cb(&mut state, &mut core_ctx)
54    }
55}
56
57#[netstack3_macros::instantiate_ip_impl_block(I)]
58impl<I: IpExt, BC: BindingsContext, L: LockBefore<lock_ordering::IpMulticastRouteTable<I>>>
59    MulticastRouteTableContext<I, BC> for CoreCtx<'_, BC, L>
60{
61    type Ctx<'a> = CoreCtx<'a, BC, lock_ordering::IpMulticastRouteTable<I>>;
62
63    fn with_route_table<
64        O,
65        F: FnOnce(&MulticastRouteTable<I, Self::DeviceId, BC>, &mut Self::Ctx<'_>) -> O,
66    >(
67        &mut self,
68        state: &MulticastForwardingEnabledState<I, Self::DeviceId, BC>,
69        cb: F,
70    ) -> O {
71        let mut locked = self.adopt(state);
72        let (route_table, mut core_ctx) =
73            locked.read_lock_with_and::<lock_ordering::IpMulticastRouteTable<I>, _>(|c| c.right());
74        let mut core_ctx = core_ctx.cast_core_ctx();
75        cb(&route_table, &mut core_ctx)
76    }
77
78    fn with_route_table_mut<
79        O,
80        F: FnOnce(&mut MulticastRouteTable<I, Self::DeviceId, BC>, &mut Self::Ctx<'_>) -> O,
81    >(
82        &mut self,
83        state: &MulticastForwardingEnabledState<I, Self::DeviceId, BC>,
84        cb: F,
85    ) -> O {
86        let mut locked = self.adopt(state);
87        let (mut route_table, mut core_ctx) =
88            locked.write_lock_with_and::<lock_ordering::IpMulticastRouteTable<I>, _>(|c| c.right());
89        let mut core_ctx = core_ctx.cast_core_ctx();
90        cb(&mut route_table, &mut core_ctx)
91    }
92}
93
94#[netstack3_macros::instantiate_ip_impl_block(I)]
95impl<
96        I: IpExt,
97        BC: BindingsContext,
98        L: LockBefore<lock_ordering::IpMulticastForwardingPendingPackets<I>>,
99    > MulticastForwardingPendingPacketsContext<I, BC> for CoreCtx<'_, BC, L>
100{
101    fn with_pending_table_mut<
102        O,
103        F: FnOnce(&mut MulticastForwardingPendingPackets<I, Self::WeakDeviceId, BC>) -> O,
104    >(
105        &mut self,
106        state: &MulticastForwardingEnabledState<I, Self::DeviceId, BC>,
107        cb: F,
108    ) -> O {
109        let mut locked = self.adopt(state);
110        let mut pending_table = locked
111            .lock_with::<lock_ordering::IpMulticastForwardingPendingPackets<I>, _>(|c| c.right());
112        cb(&mut pending_table)
113    }
114}
115
116impl<I: IpExt, BT: BindingsTypes> LockLevelFor<MulticastForwardingEnabledState<I, DeviceId<BT>, BT>>
117    for lock_ordering::IpMulticastRouteTable<I>
118{
119    type Data = MulticastRouteTable<I, DeviceId<BT>, BT>;
120}
121
122impl<I: IpExt, BT: BindingsTypes> LockLevelFor<MulticastForwardingEnabledState<I, DeviceId<BT>, BT>>
123    for lock_ordering::IpMulticastForwardingPendingPackets<I>
124{
125    type Data = MulticastForwardingPendingPackets<I, WeakDeviceId<BT>, BT>;
126}
127
128impl<I, BC, L> CoreTimerContext<MulticastForwardingTimerId<I>, BC> for CoreCtx<'_, BC, L>
129where
130    I: IpExt,
131    BC: BindingsContext,
132{
133    fn convert_timer(dispatch_id: MulticastForwardingTimerId<I>) -> BC::DispatchId {
134        IpLayerTimerId::from(dispatch_id).into()
135    }
136}
137
138impl<I, BC, L> CounterContext<MulticastForwardingCounters<I>> for CoreCtx<'_, BC, L>
139where
140    I: IpExt,
141    BC: BindingsContext,
142{
143    fn counters(&self) -> &MulticastForwardingCounters<I> {
144        self.unlocked_access::<crate::lock_ordering::UnlockedState>()
145            .inner_ip_state()
146            .multicast_forwarding_counters()
147    }
148}