netstack3_core/device/
pure_ip.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 of traits defined in foreign modules for the types defined
6//! in the pure_ip module.
7
8use alloc::vec::Vec;
9use lock_order::lock::LockLevelFor;
10use lock_order::relation::LockBefore;
11use lock_order::wrap::LockedWrapperApi;
12use net_types::ip::Ip;
13use netstack3_base::DeviceIdContext;
14use netstack3_device::pure_ip::{
15    DynamicPureIpDeviceState, PureIpDevice, PureIpDeviceId, PureIpDeviceStateContext,
16    PureIpDeviceTxQueueFrameMetadata, PureIpPrimaryDeviceId, PureIpWeakDeviceId,
17};
18use netstack3_device::queue::{
19    BufVecU8Allocator, DequeueState, TransmitDequeueContext, TransmitQueueCommon,
20    TransmitQueueContext, TransmitQueueState,
21};
22use netstack3_device::socket::{IpFrame, ParseSentFrameError, SentFrame};
23use netstack3_device::{
24    DeviceCollectionContext, DeviceConfigurationContext, DeviceLayerEventDispatcher,
25    DeviceSendFrameError, IpLinkDeviceState,
26};
27use netstack3_ip::nud::NudUserConfig;
28use packet::Buf;
29
30use crate::device::integration;
31use crate::{BindingsContext, BindingsTypes, CoreCtx};
32
33impl<BT: BindingsTypes, L> DeviceIdContext<PureIpDevice> for CoreCtx<'_, BT, L> {
34    type DeviceId = PureIpDeviceId<BT>;
35    type WeakDeviceId = PureIpWeakDeviceId<BT>;
36}
37
38impl<'a, BT, L> DeviceCollectionContext<PureIpDevice, BT> for CoreCtx<'a, BT, L>
39where
40    BT: BindingsTypes,
41    L: LockBefore<crate::lock_ordering::DeviceLayerState>,
42{
43    fn insert(&mut self, device: PureIpPrimaryDeviceId<BT>) {
44        let mut devices = self.write_lock::<crate::lock_ordering::DeviceLayerState>();
45        let strong = device.clone_strong();
46        assert!(devices.pure_ip.insert(strong, device).is_none());
47    }
48
49    fn remove(&mut self, device: &PureIpDeviceId<BT>) -> Option<PureIpPrimaryDeviceId<BT>> {
50        let mut devices = self.write_lock::<crate::lock_ordering::DeviceLayerState>();
51        devices.pure_ip.remove(device)
52    }
53}
54
55impl<'a, BT, L> DeviceConfigurationContext<PureIpDevice> for CoreCtx<'a, BT, L>
56where
57    BT: BindingsTypes,
58{
59    fn with_nud_config<I: Ip, O, F: FnOnce(Option<&NudUserConfig>) -> O>(
60        &mut self,
61        _device_id: &Self::DeviceId,
62        f: F,
63    ) -> O {
64        // PureIp doesn't support NUD.
65        f(None)
66    }
67
68    fn with_nud_config_mut<I: Ip, O, F: FnOnce(Option<&mut NudUserConfig>) -> O>(
69        &mut self,
70        _device_id: &Self::DeviceId,
71        f: F,
72    ) -> O {
73        // PureIp doesn't support NUD.
74        f(None)
75    }
76}
77
78impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::PureIpDeviceTxQueue>>
79    TransmitQueueCommon<PureIpDevice, BC> for CoreCtx<'_, BC, L>
80{
81    type Meta = PureIpDeviceTxQueueFrameMetadata<BC>;
82    type Allocator = BufVecU8Allocator;
83    type Buffer = Buf<Vec<u8>>;
84    type DequeueContext = BC::DequeueContext;
85
86    fn parse_outgoing_frame<'a, 'b>(
87        buf: &'a [u8],
88        meta: &'b Self::Meta,
89    ) -> Result<SentFrame<&'a [u8]>, ParseSentFrameError> {
90        let PureIpDeviceTxQueueFrameMetadata { ip_version, tx_metadata: _ } = meta;
91        // NB: For conformance with Linux, don't verify that the contents of
92        // of the buffer are a valid IPv4/IPv6 packet. Device sockets are
93        // allowed to receive malformed packets.
94        Ok(SentFrame::Ip(IpFrame { ip_version: *ip_version, body: buf }))
95    }
96}
97
98impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::PureIpDeviceTxQueue>>
99    TransmitQueueContext<PureIpDevice, BC> for CoreCtx<'_, BC, L>
100{
101    fn with_transmit_queue_mut<
102        O,
103        F: FnOnce(&mut TransmitQueueState<Self::Meta, Self::Buffer, Self::Allocator>) -> O,
104    >(
105        &mut self,
106        device_id: &Self::DeviceId,
107        cb: F,
108    ) -> O {
109        let mut state = integration::device_state(self, device_id);
110        let mut x = state.lock::<crate::lock_ordering::PureIpDeviceTxQueue>();
111        cb(&mut x)
112    }
113
114    fn with_transmit_queue<
115        O,
116        F: FnOnce(&TransmitQueueState<Self::Meta, Self::Buffer, Self::Allocator>) -> O,
117    >(
118        &mut self,
119        device_id: &Self::DeviceId,
120        cb: F,
121    ) -> O {
122        let mut state = integration::device_state(self, device_id);
123        let x = state.lock::<crate::lock_ordering::PureIpDeviceTxQueue>();
124        cb(&x)
125    }
126
127    fn send_frame(
128        &mut self,
129        bindings_ctx: &mut BC,
130        device_id: &Self::DeviceId,
131        dequeue_context: Option<&mut BC::DequeueContext>,
132        meta: Self::Meta,
133        buf: Self::Buffer,
134    ) -> Result<(), DeviceSendFrameError> {
135        let PureIpDeviceTxQueueFrameMetadata {
136            ip_version,
137            // Drop metadata at the end of scope after publishing to bindings.
138            tx_metadata: _tx_metadata,
139        } = meta;
140        DeviceLayerEventDispatcher::send_ip_packet(
141            bindings_ctx,
142            device_id,
143            buf,
144            ip_version,
145            dequeue_context,
146        )
147    }
148}
149
150impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::PureIpDeviceTxDequeue>>
151    TransmitDequeueContext<PureIpDevice, BC> for CoreCtx<'_, BC, L>
152{
153    type TransmitQueueCtx<'a> = CoreCtx<'a, BC, crate::lock_ordering::PureIpDeviceTxDequeue>;
154
155    fn with_dequed_packets_and_tx_queue_ctx<
156        O,
157        F: FnOnce(&mut DequeueState<Self::Meta, Self::Buffer>, &mut Self::TransmitQueueCtx<'_>) -> O,
158    >(
159        &mut self,
160        device_id: &Self::DeviceId,
161        cb: F,
162    ) -> O {
163        let mut core_ctx_and_resource = integration::device_state_and_core_ctx(self, device_id);
164        let (mut x, mut locked) = core_ctx_and_resource
165            .lock_with_and::<crate::lock_ordering::PureIpDeviceTxDequeue, _>(|c| c.right());
166        cb(&mut x, &mut locked.cast_core_ctx())
167    }
168}
169
170impl<BT: BindingsTypes> LockLevelFor<IpLinkDeviceState<PureIpDevice, BT>>
171    for crate::lock_ordering::PureIpDeviceDynamicState
172{
173    type Data = DynamicPureIpDeviceState;
174}
175
176impl<BT: BindingsTypes> LockLevelFor<IpLinkDeviceState<PureIpDevice, BT>>
177    for crate::lock_ordering::PureIpDeviceTxQueue
178{
179    type Data =
180        TransmitQueueState<PureIpDeviceTxQueueFrameMetadata<BT>, Buf<Vec<u8>>, BufVecU8Allocator>;
181}
182
183impl<BT: BindingsTypes> LockLevelFor<IpLinkDeviceState<PureIpDevice, BT>>
184    for crate::lock_ordering::PureIpDeviceTxDequeue
185{
186    type Data = DequeueState<PureIpDeviceTxQueueFrameMetadata<BT>, Buf<Vec<u8>>>;
187}
188
189impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::PureIpDeviceDynamicState>>
190    PureIpDeviceStateContext for CoreCtx<'_, BC, L>
191{
192    fn with_pure_ip_state<O, F: FnOnce(&DynamicPureIpDeviceState) -> O>(
193        &mut self,
194        device_id: &Self::DeviceId,
195        cb: F,
196    ) -> O {
197        let mut state = integration::device_state(self, device_id);
198        let dynamic_state = state.read_lock::<crate::lock_ordering::PureIpDeviceDynamicState>();
199        cb(&dynamic_state)
200    }
201
202    fn with_pure_ip_state_mut<O, F: FnOnce(&mut DynamicPureIpDeviceState) -> O>(
203        &mut self,
204        device_id: &Self::DeviceId,
205        cb: F,
206    ) -> O {
207        let mut state = integration::device_state(self, device_id);
208        let mut dynamic_state =
209            state.write_lock::<crate::lock_ordering::PureIpDeviceDynamicState>();
210        cb(&mut dynamic_state)
211    }
212}