Skip to main content

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