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