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, TxMetadata};
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 { ip_version, tx_metadata } = meta;
132        DeviceLayerEventDispatcher::send_ip_packet(
133            bindings_ctx,
134            device_id,
135            buf,
136            ip_version,
137            dequeue_context,
138            tx_metadata.checksum_offload_result(),
139        )
140        // Metadata is dropped at the end of the scope after publishing to
141        // bindings.
142    }
143}
144
145impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::PureIpDeviceTxDequeue>>
146    TransmitDequeueContext<PureIpDevice, BC> for CoreCtx<'_, BC, L>
147{
148    type TransmitQueueCtx<'a> = CoreCtx<'a, BC, crate::lock_ordering::PureIpDeviceTxDequeue>;
149
150    fn with_dequed_packets_and_tx_queue_ctx<
151        O,
152        F: FnOnce(&mut DequeueState<Self::Meta, BC::TxBuffer>, &mut Self::TransmitQueueCtx<'_>) -> O,
153    >(
154        &mut self,
155        device_id: &Self::DeviceId,
156        cb: F,
157    ) -> O {
158        let mut core_ctx_and_resource = integration::device_state_and_core_ctx(self, device_id);
159        let (mut x, mut locked) = core_ctx_and_resource
160            .lock_with_and::<crate::lock_ordering::PureIpDeviceTxDequeue, _>(|c| c.right());
161        cb(&mut x, &mut locked.cast_core_ctx())
162    }
163}
164
165impl<BT: BindingsTypes> LockLevelFor<IpLinkDeviceState<PureIpDevice, BT>>
166    for crate::lock_ordering::PureIpDeviceDynamicState
167{
168    type Data = DynamicPureIpDeviceState;
169}
170
171impl<BT: BindingsTypes> LockLevelFor<IpLinkDeviceState<PureIpDevice, BT>>
172    for crate::lock_ordering::PureIpDeviceTxQueue
173{
174    type Data =
175        TransmitQueueState<PureIpDeviceTxQueueFrameMetadata<BT>, BT::TxBuffer, BT::TxAllocator>;
176}
177
178impl<BT: BindingsTypes> LockLevelFor<IpLinkDeviceState<PureIpDevice, BT>>
179    for crate::lock_ordering::PureIpDeviceTxDequeue
180{
181    type Data = DequeueState<PureIpDeviceTxQueueFrameMetadata<BT>, BT::TxBuffer>;
182}
183
184impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::PureIpDeviceDynamicState>>
185    PureIpDeviceStateContext for CoreCtx<'_, BC, L>
186{
187    fn with_pure_ip_state<O, F: FnOnce(&DynamicPureIpDeviceState) -> O>(
188        &mut self,
189        device_id: &Self::DeviceId,
190        cb: F,
191    ) -> O {
192        let mut state = integration::device_state(self, device_id);
193        let dynamic_state = state.read_lock::<crate::lock_ordering::PureIpDeviceDynamicState>();
194        cb(&dynamic_state)
195    }
196
197    fn with_pure_ip_state_mut<O, F: FnOnce(&mut DynamicPureIpDeviceState) -> O>(
198        &mut self,
199        device_id: &Self::DeviceId,
200        cb: F,
201    ) -> O {
202        let mut state = integration::device_state(self, device_id);
203        let mut dynamic_state =
204            state.write_lock::<crate::lock_ordering::PureIpDeviceDynamicState>();
205        cb(&mut dynamic_state)
206    }
207}