netstack3_core/ip/
raw.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 raw IP sockets that integrate with traits/types from
6//! foreign modules.
7
8use lock_order::lock::LockLevelFor;
9use lock_order::relation::LockBefore;
10use lock_order::wrap::{LockedWrapperApi, LockedWrapperUnlockedApi};
11use netstack3_base::{CounterContext, ResourceCounterContext, WeakDeviceIdentifier};
12use netstack3_device::WeakDeviceId;
13use netstack3_ip::raw::{
14    RawIpSocketCounters, RawIpSocketId, RawIpSocketLockedState, RawIpSocketMap,
15    RawIpSocketMapContext, RawIpSocketState, RawIpSocketStateContext,
16};
17
18use crate::marker::IpExt;
19use crate::{lock_ordering, BindingsContext, BindingsTypes, CoreCtx};
20
21#[netstack3_macros::instantiate_ip_impl_block(I)]
22impl<I: IpExt, BC: BindingsContext, L: LockBefore<lock_ordering::RawIpSocketState<I>>>
23    RawIpSocketStateContext<I, BC> for CoreCtx<'_, BC, L>
24{
25    type SocketHandler<'a> = CoreCtx<'a, BC, lock_ordering::RawIpSocketState<I>>;
26
27    fn with_locked_state<O, F: FnOnce(&RawIpSocketLockedState<I, Self::WeakDeviceId>) -> O>(
28        &mut self,
29        id: &RawIpSocketId<I, Self::WeakDeviceId, BC>,
30        cb: F,
31    ) -> O {
32        let mut locked = self.adopt(id.state());
33        let guard = locked.read_lock_with::<lock_ordering::RawIpSocketState<I>, _>(|c| c.right());
34        cb(&guard)
35    }
36    fn with_locked_state_and_socket_handler<
37        O,
38        F: FnOnce(&RawIpSocketLockedState<I, Self::WeakDeviceId>, &mut Self::SocketHandler<'_>) -> O,
39    >(
40        &mut self,
41        id: &RawIpSocketId<I, Self::WeakDeviceId, BC>,
42        cb: F,
43    ) -> O {
44        let mut locked = self.adopt(id.state());
45        let (state, mut core_ctx) =
46            locked.read_lock_with_and::<lock_ordering::RawIpSocketState<I>, _>(|c| c.right());
47        let mut core_ctx = core_ctx.cast_core_ctx();
48        cb(&state, &mut core_ctx)
49    }
50    fn with_locked_state_mut<
51        O,
52        F: FnOnce(&mut RawIpSocketLockedState<I, Self::WeakDeviceId>) -> O,
53    >(
54        &mut self,
55        id: &RawIpSocketId<I, Self::WeakDeviceId, BC>,
56        cb: F,
57    ) -> O {
58        let mut locked = self.adopt(id.state());
59        let mut guard =
60            locked.write_lock_with::<lock_ordering::RawIpSocketState<I>, _>(|c| c.right());
61        cb(&mut guard)
62    }
63}
64
65#[netstack3_macros::instantiate_ip_impl_block(I)]
66impl<I: IpExt, BC: BindingsContext, L: LockBefore<lock_ordering::AllRawIpSockets<I>>>
67    RawIpSocketMapContext<I, BC> for CoreCtx<'_, BC, L>
68{
69    type StateCtx<'a> = CoreCtx<'a, BC, lock_ordering::AllRawIpSockets<I>>;
70
71    fn with_socket_map_and_state_ctx<
72        O,
73        F: FnOnce(&RawIpSocketMap<I, Self::WeakDeviceId, BC>, &mut Self::StateCtx<'_>) -> O,
74    >(
75        &mut self,
76        cb: F,
77    ) -> O {
78        let (sockets, mut core_ctx) = self.read_lock_and::<lock_ordering::AllRawIpSockets<I>>();
79        cb(&sockets, &mut core_ctx)
80    }
81    fn with_socket_map_mut<O, F: FnOnce(&mut RawIpSocketMap<I, Self::WeakDeviceId, BC>) -> O>(
82        &mut self,
83        cb: F,
84    ) -> O {
85        let mut sockets = self.write_lock::<lock_ordering::AllRawIpSockets<I>>();
86        cb(&mut sockets)
87    }
88}
89
90impl<I: IpExt, BT: BindingsTypes> LockLevelFor<RawIpSocketState<I, WeakDeviceId<BT>, BT>>
91    for lock_ordering::RawIpSocketState<I>
92{
93    type Data = RawIpSocketLockedState<I, WeakDeviceId<BT>>;
94}
95
96impl<I: IpExt, BC: BindingsContext, L> CounterContext<RawIpSocketCounters<I>>
97    for CoreCtx<'_, BC, L>
98{
99    fn counters(&self) -> &RawIpSocketCounters<I> {
100        self.unlocked_access::<crate::lock_ordering::UnlockedState>()
101            .inner_ip_state()
102            .raw_ip_socket_counters()
103    }
104}
105
106// NB: Implement for any `D` rather than `Self::WeakDeviceId` to avoid a
107// circular dependency (e.g. referencing `Self` in the trait being implemented).
108impl<I: IpExt, BC: BindingsContext, L, D: WeakDeviceIdentifier>
109    ResourceCounterContext<RawIpSocketId<I, D, BC>, RawIpSocketCounters<I>> for CoreCtx<'_, BC, L>
110{
111    fn per_resource_counters<'a>(
112        &'a self,
113        id: &'a RawIpSocketId<I, D, BC>,
114    ) -> &'a RawIpSocketCounters<I> {
115        // NB: circumvent the lock ordering to access the counters, because it
116        // spares jumping through some hoops, and
117        // `crate::lock_ordering::RawIpSocketCounters<I>>` exists for unlocked
118        // access.
119        id.state().counters()
120    }
121}