1use alloc::vec::Vec;
9
10use lock_order::lock::LockLevelFor;
11use lock_order::relation::LockBefore;
12use log::error;
13use netstack3_base::DeviceIdContext;
14use netstack3_device::loopback::{
15 LoopbackDevice, LoopbackDeviceId, LoopbackRxQueueMeta, LoopbackTxQueueMeta,
16 LoopbackWeakDeviceId,
17};
18use netstack3_device::queue::{
19 BufVecU8Allocator, DequeueState, ReceiveDequeContext, ReceiveQueueContext,
20 ReceiveQueueFullError, ReceiveQueueHandler, ReceiveQueueState, ReceiveQueueTypes,
21 TransmitDequeueContext, TransmitQueueCommon, TransmitQueueContext, TransmitQueueState,
22};
23use netstack3_device::socket::{ParseSentFrameError, SentFrame};
24use netstack3_device::{DeviceLayerTypes, DeviceSendFrameError, IpLinkDeviceState, WeakDeviceId};
25use packet::Buf;
26
27use crate::context::WrapLockLevel;
28use crate::context::prelude::*;
29use crate::device::integration;
30use crate::{BindingsContext, BindingsTypes, CoreCtx};
31
32impl<BT: BindingsTypes, L> DeviceIdContext<LoopbackDevice> for CoreCtx<'_, BT, L> {
33 type DeviceId = LoopbackDeviceId<BT>;
34 type WeakDeviceId = LoopbackWeakDeviceId<BT>;
35}
36
37impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::LoopbackRxQueue>>
38 ReceiveQueueTypes<LoopbackDevice, BC> for CoreCtx<'_, BC, L>
39{
40 type Meta = LoopbackRxQueueMeta<WeakDeviceId<BC>, BC>;
41 type Buffer = Buf<Vec<u8>>;
42}
43
44impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::LoopbackRxQueue>>
45 ReceiveQueueContext<LoopbackDevice, BC> for CoreCtx<'_, BC, L>
46{
47 fn with_receive_queue_mut<
48 O,
49 F: FnOnce(&mut ReceiveQueueState<Self::Meta, Buf<Vec<u8>>>) -> O,
50 >(
51 &mut self,
52 device_id: &LoopbackDeviceId<BC>,
53 cb: F,
54 ) -> O {
55 let mut state = integration::device_state(self, device_id);
56 let mut x = state.lock::<crate::lock_ordering::LoopbackRxQueue>();
57 cb(&mut x)
58 }
59}
60
61impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::LoopbackRxDequeue>>
62 ReceiveDequeContext<LoopbackDevice, BC> for CoreCtx<'_, BC, L>
63{
64 type ReceiveQueueCtx<'a> =
65 CoreCtx<'a, BC, WrapLockLevel<crate::lock_ordering::LoopbackRxDequeue>>;
66
67 fn with_dequed_frames_and_rx_queue_ctx<
68 O,
69 F: FnOnce(&mut DequeueState<Self::Meta, Buf<Vec<u8>>>, &mut Self::ReceiveQueueCtx<'_>) -> O,
70 >(
71 &mut self,
72 device_id: &LoopbackDeviceId<BC>,
73 cb: F,
74 ) -> O {
75 let mut core_ctx_and_resource = integration::device_state_and_core_ctx(self, device_id);
76 let (mut x, mut locked) = core_ctx_and_resource
77 .lock_with_and::<crate::lock_ordering::LoopbackRxDequeue, _>(|c| c.right());
78 cb(&mut x, &mut locked.cast_core_ctx())
79 }
80}
81
82impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::LoopbackTxQueue>>
83 TransmitQueueCommon<LoopbackDevice, BC> for CoreCtx<'_, BC, L>
84{
85 type Meta = LoopbackTxQueueMeta<WeakDeviceId<BC>, BC>;
86 type DequeueContext = !;
87
88 fn parse_outgoing_frame<'a, 'b>(
89 buf: &'a [u8],
90 _meta: &'b Self::Meta,
91 ) -> Result<SentFrame<&'a [u8]>, ParseSentFrameError> {
92 SentFrame::try_parse_as_ethernet(buf)
93 }
94}
95
96impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::LoopbackTxQueue>>
97 TransmitQueueContext<LoopbackDevice, BC> for CoreCtx<'_, BC, L>
98{
99 fn with_transmit_queue_mut<
100 O,
101 F: FnOnce(&mut TransmitQueueState<Self::Meta, Buf<Vec<u8>>, BufVecU8Allocator>) -> O,
102 >(
103 &mut self,
104 device_id: &LoopbackDeviceId<BC>,
105 cb: F,
106 ) -> O {
107 let mut state = integration::device_state(self, device_id);
108 let mut x = state.lock::<crate::lock_ordering::LoopbackTxQueue>();
109 cb(&mut x)
110 }
111
112 fn with_transmit_queue<
113 O,
114 F: FnOnce(&TransmitQueueState<Self::Meta, Buf<Vec<u8>>, BufVecU8Allocator>) -> O,
115 >(
116 &mut self,
117 device_id: &LoopbackDeviceId<BC>,
118 cb: F,
119 ) -> O {
120 let mut state = integration::device_state(self, device_id);
121 let x = state.lock::<crate::lock_ordering::LoopbackTxQueue>();
122 cb(&x)
123 }
124
125 fn send_frame(
126 &mut self,
127 bindings_ctx: &mut BC,
128 device_id: &Self::DeviceId,
129 dequeue_context: Option<&mut !>,
130 meta: Self::Meta,
131 buf: Buf<Vec<u8>>,
132 ) -> Result<(), DeviceSendFrameError> {
133 match dequeue_context {
135 Some(never) => match *never {},
136 None => (),
137 };
138 match ReceiveQueueHandler::queue_rx_frame(self, bindings_ctx, device_id, meta.into(), buf) {
147 Ok(()) => {}
148 Err(ReceiveQueueFullError((_meta, _frame))) => {
149 error!("dropped RX frame on loopback device due to full RX queue")
151 }
152 }
153
154 Ok(())
155 }
156}
157
158impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::LoopbackTxDequeue>>
159 TransmitDequeueContext<LoopbackDevice, BC> for CoreCtx<'_, BC, L>
160{
161 type TransmitQueueCtx<'a> =
162 CoreCtx<'a, BC, WrapLockLevel<crate::lock_ordering::LoopbackTxDequeue>>;
163
164 fn with_dequed_packets_and_tx_queue_ctx<
165 O,
166 F: FnOnce(&mut DequeueState<Self::Meta, Buf<Vec<u8>>>, &mut Self::TransmitQueueCtx<'_>) -> O,
167 >(
168 &mut self,
169 device_id: &Self::DeviceId,
170 cb: F,
171 ) -> O {
172 let mut core_ctx_and_resource = integration::device_state_and_core_ctx(self, device_id);
173 let (mut x, mut locked) = core_ctx_and_resource
174 .lock_with_and::<crate::lock_ordering::LoopbackTxDequeue, _>(|c| c.right());
175 cb(&mut x, &mut locked.cast_core_ctx())
176 }
177}
178
179impl<BT: DeviceLayerTypes> LockLevelFor<IpLinkDeviceState<LoopbackDevice, BT>>
180 for crate::lock_ordering::LoopbackRxQueue
181{
182 type Data = ReceiveQueueState<LoopbackRxQueueMeta<WeakDeviceId<BT>, BT>, Buf<Vec<u8>>>;
183}
184
185impl<BT: DeviceLayerTypes> LockLevelFor<IpLinkDeviceState<LoopbackDevice, BT>>
186 for crate::lock_ordering::LoopbackRxDequeue
187{
188 type Data = DequeueState<LoopbackRxQueueMeta<WeakDeviceId<BT>, BT>, Buf<Vec<u8>>>;
189}
190
191impl<BT: DeviceLayerTypes> LockLevelFor<IpLinkDeviceState<LoopbackDevice, BT>>
192 for crate::lock_ordering::LoopbackTxQueue
193{
194 type Data = TransmitQueueState<
195 LoopbackTxQueueMeta<WeakDeviceId<BT>, BT>,
196 Buf<Vec<u8>>,
197 BufVecU8Allocator,
198 >;
199}
200
201impl<BT: DeviceLayerTypes> LockLevelFor<IpLinkDeviceState<LoopbackDevice, BT>>
202 for crate::lock_ordering::LoopbackTxDequeue
203{
204 type Data = DequeueState<LoopbackTxQueueMeta<WeakDeviceId<BT>, BT>, Buf<Vec<u8>>>;
205}