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