1use core::convert::Infallible as Never;
8use core::fmt::Debug;
9
10use lock_order::lock::{OrderedLockAccess, OrderedLockRef};
11use log::debug;
12use net_types::ip::{Ip, IpVersion, Ipv4, Ipv6, Mtu};
13use netstack3_base::sync::{Mutex, RwLock};
14use netstack3_base::{
15 BroadcastIpExt, ChecksumOffloadSpec, CoreTimerContext, Device, DeviceIdContext,
16 NetworkParsingContext, NetworkSerializer, ReceivableFrameMeta, RecvFrameContext,
17 RecvIpFrameMeta, ResourceCounterContext, SendFrameError, SendFrameErrorReason,
18 SendableFrameMeta, TimerContext, TxMetadataBindingsTypes, WeakDeviceIdentifier,
19};
20use netstack3_ip::{DeviceIpLayerMetadata, IpPacketDestination};
21use packet::BufferMut;
22
23use crate::internal::base::{
24 DeviceBufferBindingsTypes, DeviceCounters, DeviceLayerTypes, DeviceReceiveFrameSpec,
25 PureIpDeviceCounters,
26};
27use crate::internal::id::{BaseDeviceId, BasePrimaryDeviceId, BaseWeakDeviceId, DeviceId};
28use crate::internal::queue::tx::{TransmitQueue, TransmitQueueHandler, TransmitQueueState};
29use crate::internal::queue::{DequeueState, DeviceBufferSpec, TransmitQueueFrameError};
30use crate::internal::socket::{
31 DeviceSocketHandler, DeviceSocketMetadata, DeviceSocketSendTypes, Frame, IpFrame, ReceivedFrame,
32};
33use crate::internal::state::{DeviceStateSpec, IpLinkDeviceState};
34
35pub type PureIpWeakDeviceId<BT> = BaseWeakDeviceId<PureIpDevice, BT>;
42
43pub type PureIpDeviceId<BT> = BaseDeviceId<PureIpDevice, BT>;
49
50pub type PureIpPrimaryDeviceId<BT> = BasePrimaryDeviceId<PureIpDevice, BT>;
52
53#[derive(Copy, Clone)]
55pub enum PureIpDevice {}
56
57#[derive(Debug)]
59pub struct PureIpDeviceCreationProperties {
60 pub mtu: Mtu,
62 pub tx_offload_spec: netstack3_base::ChecksumOffloadSpec,
64}
65
66pub struct PureIpDeviceTxQueueFrameMetadata<BT: TxMetadataBindingsTypes> {
68 pub ip_version: IpVersion,
70 pub tx_metadata: BT::TxMetadata,
72}
73
74#[derive(Debug, PartialEq)]
76pub struct PureIpHeaderParams {
77 pub ip_version: IpVersion,
79}
80
81pub struct PureIpDeviceState<BT: DeviceLayerTypes> {
83 dynamic_state: RwLock<DynamicPureIpDeviceState>,
85 pub tx_queue: TransmitQueue<
87 PureIpDeviceTxQueueFrameMetadata<BT>,
88 <PureIpDevice as DeviceBufferSpec<BT>>::TxBuffer,
89 <PureIpDevice as DeviceBufferSpec<BT>>::TxAllocator,
90 >,
91 pub counters: PureIpDeviceCounters,
93}
94
95pub struct DynamicPureIpDeviceState {
97 pub(crate) mtu: Mtu,
99}
100
101impl Device for PureIpDevice {}
102
103impl<BT: DeviceBufferBindingsTypes> DeviceBufferSpec<BT> for PureIpDevice {
104 type TxBuffer = BT::TxBuffer;
105 type TxAllocator = BT::TxAllocator;
106}
107
108impl DeviceStateSpec for PureIpDevice {
109 type State<BT: DeviceLayerTypes> = PureIpDeviceState<BT>;
110 type External<BT: DeviceLayerTypes> = BT::PureIpDeviceState;
111 type CreationProperties = PureIpDeviceCreationProperties;
112 type Counters = PureIpDeviceCounters;
113 const IS_LOOPBACK: bool = false;
114 const DEBUG_TYPE: &'static str = "PureIP";
115 type TimerId<D: WeakDeviceIdentifier> = Never;
116
117 fn new_device_state<
118 CC: CoreTimerContext<Self::TimerId<CC::WeakDeviceId>, BC> + DeviceIdContext<Self>,
119 BC: DeviceLayerTypes + TimerContext,
120 >(
121 _bindings_ctx: &mut BC,
122 _self_id: CC::WeakDeviceId,
123 PureIpDeviceCreationProperties { mtu, tx_offload_spec: _ }: Self::CreationProperties,
124 tx_allocator: <Self as DeviceBufferSpec<BC>>::TxAllocator,
125 ) -> Self::State<BC>
126 where
127 Self: DeviceBufferSpec<BC>,
128 {
129 PureIpDeviceState {
130 dynamic_state: RwLock::new(DynamicPureIpDeviceState { mtu }),
131 tx_queue: TransmitQueue::new(tx_allocator, ChecksumOffloadSpec::default()),
132 counters: PureIpDeviceCounters::default(),
133 }
134 }
135}
136
137pub struct PureIpDeviceReceiveFrameMetadata<D> {
139 pub device_id: D,
141 pub ip_version: IpVersion,
143 pub parsing_context: NetworkParsingContext,
145}
146
147impl DeviceReceiveFrameSpec for PureIpDevice {
148 type FrameMetadata<D> = PureIpDeviceReceiveFrameMetadata<D>;
149}
150
151pub trait PureIpDeviceStateContext: DeviceIdContext<PureIpDevice> {
153 fn with_pure_ip_state<O, F: FnOnce(&DynamicPureIpDeviceState) -> O>(
156 &mut self,
157 device_id: &Self::DeviceId,
158 cb: F,
159 ) -> O;
160
161 fn with_pure_ip_state_mut<O, F: FnOnce(&mut DynamicPureIpDeviceState) -> O>(
164 &mut self,
165 device_id: &Self::DeviceId,
166 cb: F,
167 ) -> O;
168}
169
170impl DeviceSocketSendTypes for PureIpDevice {
171 type Metadata = PureIpHeaderParams;
172}
173
174impl<CC, BC> ReceivableFrameMeta<CC, BC> for PureIpDeviceReceiveFrameMetadata<CC::DeviceId>
175where
176 CC: DeviceIdContext<PureIpDevice>
177 + RecvFrameContext<RecvIpFrameMeta<CC::DeviceId, DeviceIpLayerMetadata<BC>, Ipv4>, BC>
178 + RecvFrameContext<RecvIpFrameMeta<CC::DeviceId, DeviceIpLayerMetadata<BC>, Ipv6>, BC>
179 + ResourceCounterContext<CC::DeviceId, DeviceCounters>
180 + DeviceSocketHandler<PureIpDevice, BC>,
181 BC: TxMetadataBindingsTypes,
182{
183 fn receive_meta<B: BufferMut + Debug>(
184 self,
185 core_ctx: &mut CC,
186 bindings_ctx: &mut BC,
187 buffer: B,
188 ) {
189 let Self { device_id, ip_version, parsing_context } = self;
190
191 core_ctx.add_both_usize(&device_id, buffer.len(), |counters: &DeviceCounters| {
192 &counters.recv_bytes
193 });
194 core_ctx.increment_both(&device_id, |counters: &DeviceCounters| &counters.recv_frame);
195
196 core_ctx.handle_frame(
200 bindings_ctx,
201 &device_id,
202 Frame::Received(ReceivedFrame::Ip(IpFrame { ip_version, body: buffer.as_ref() })),
203 buffer.as_ref(),
204 );
205
206 match ip_version {
207 IpVersion::V4 => {
208 core_ctx.increment_both(&device_id, |counters: &DeviceCounters| {
209 &counters.recv_ipv4_delivered
210 });
211 core_ctx.receive_frame(
212 bindings_ctx,
213 RecvIpFrameMeta::<_, _, Ipv4>::new(
214 device_id,
215 None,
216 DeviceIpLayerMetadata::default(),
217 parsing_context,
218 ),
219 buffer,
220 )
221 }
222 IpVersion::V6 => {
223 core_ctx.increment_both(&device_id, |counters: &DeviceCounters| {
224 &counters.recv_ipv6_delivered
225 });
226 core_ctx.receive_frame(
227 bindings_ctx,
228 RecvIpFrameMeta::<_, _, Ipv6>::new(
229 device_id,
230 None,
231 DeviceIpLayerMetadata::default(),
232 parsing_context,
233 ),
234 buffer,
235 )
236 }
237 }
238 }
239}
240
241impl<CC, BC> SendableFrameMeta<CC, BC> for DeviceSocketMetadata<PureIpDevice, CC::DeviceId>
242where
243 CC: TransmitQueueHandler<PureIpDevice, BC, Meta = PureIpDeviceTxQueueFrameMetadata<BC>>
244 + ResourceCounterContext<CC::DeviceId, DeviceCounters>,
245 BC: TxMetadataBindingsTypes,
246{
247 fn send_meta<S>(
248 self,
249 core_ctx: &mut CC,
250 bindings_ctx: &mut BC,
251 body: S,
252 ) -> Result<(), SendFrameError<S>>
253 where
254 S: NetworkSerializer,
255 S::Buffer: BufferMut,
256 {
257 let Self { device_id, metadata: PureIpHeaderParams { ip_version } } = self;
258 let tx_meta: BC::TxMetadata = Default::default();
261 net_types::for_any_ip_version!(
262 ip_version,
263 I,
264 queue_ip_frame::<_, _, I, _>(core_ctx, bindings_ctx, &device_id, body, tx_meta)
265 )
266 }
267}
268
269pub fn send_ip_frame<BC, CC, I, S>(
271 core_ctx: &mut CC,
272 bindings_ctx: &mut BC,
273 device_id: &CC::DeviceId,
274 destination: IpPacketDestination<I, &DeviceId<BC>>,
275 packet: S,
276 tx_meta: BC::TxMetadata,
277) -> Result<(), SendFrameError<S>>
278where
279 BC: DeviceLayerTypes,
280 CC: TransmitQueueHandler<PureIpDevice, BC, Meta = PureIpDeviceTxQueueFrameMetadata<BC>>
281 + ResourceCounterContext<CC::DeviceId, DeviceCounters>,
282 I: Ip + BroadcastIpExt,
283 S: NetworkSerializer,
284 S::Buffer: BufferMut,
285{
286 core_ctx.increment_both(device_id, |counters| &counters.send_total_frames);
287 core_ctx.increment_both(device_id, DeviceCounters::send_frame::<I>);
288
289 match destination {
290 IpPacketDestination::Broadcast(_)
291 | IpPacketDestination::Multicast(_)
292 | IpPacketDestination::Neighbor(_) => (),
293 IpPacketDestination::Loopback(_) => {
294 unreachable!("Loopback packets must be delivered through the loopback device");
295 }
296 };
297
298 queue_ip_frame::<_, _, I, _>(core_ctx, bindings_ctx, device_id, packet, tx_meta)
299}
300
301fn queue_ip_frame<BC, CC, I, S>(
302 core_ctx: &mut CC,
303 bindings_ctx: &mut BC,
304 device_id: &CC::DeviceId,
305 packet: S,
306 tx_metadata: BC::TxMetadata,
307) -> Result<(), SendFrameError<S>>
308where
309 CC: TransmitQueueHandler<PureIpDevice, BC, Meta = PureIpDeviceTxQueueFrameMetadata<BC>>
310 + ResourceCounterContext<CC::DeviceId, DeviceCounters>,
311 BC: TxMetadataBindingsTypes,
312 I: Ip,
313 S: NetworkSerializer,
314 S::Buffer: BufferMut,
315{
316 let result = TransmitQueueHandler::<PureIpDevice, _>::queue_tx_frame(
317 core_ctx,
318 bindings_ctx,
319 device_id,
320 PureIpDeviceTxQueueFrameMetadata { ip_version: I::VERSION, tx_metadata },
321 packet,
322 );
323 match result {
324 Ok(len) => {
325 core_ctx.add_both_usize(device_id, len, |counters| &counters.send_bytes);
326 core_ctx.increment_both(device_id, |counters| &counters.send_frame);
327 Ok(())
328 }
329 Err(TransmitQueueFrameError::NoQueue(err)) => {
330 core_ctx.increment_both(device_id, |counters| &counters.send_dropped_no_queue);
331 debug!("device {device_id:?} failed to send frame: {err:?}.");
332 Ok(())
333 }
334 Err(TransmitQueueFrameError::QueueFull(serializer)) => {
335 core_ctx.increment_both(device_id, |counters| &counters.send_queue_full);
336 Err(SendFrameError { serializer, error: SendFrameErrorReason::QueueFull })
337 }
338 Err(TransmitQueueFrameError::SerializeError(err)) => {
339 core_ctx.increment_both(device_id, |counters| &counters.send_serialize_error);
340 Err(err.err_into())
341 }
342 }
343}
344
345pub fn get_mtu<CC: PureIpDeviceStateContext>(core_ctx: &mut CC, device_id: &CC::DeviceId) -> Mtu {
347 core_ctx.with_pure_ip_state(device_id, |DynamicPureIpDeviceState { mtu }| *mtu)
348}
349
350pub fn set_mtu<CC: PureIpDeviceStateContext>(
352 core_ctx: &mut CC,
353 device_id: &CC::DeviceId,
354 new_mtu: Mtu,
355) {
356 core_ctx.with_pure_ip_state_mut(device_id, |DynamicPureIpDeviceState { mtu }| *mtu = new_mtu)
357}
358
359impl<BT: DeviceLayerTypes> OrderedLockAccess<DynamicPureIpDeviceState>
360 for IpLinkDeviceState<PureIpDevice, BT>
361{
362 type Lock = RwLock<DynamicPureIpDeviceState>;
363 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
364 OrderedLockRef::new(&self.link.dynamic_state)
365 }
366}
367
368impl<BT: DeviceLayerTypes>
369 OrderedLockAccess<
370 TransmitQueueState<PureIpDeviceTxQueueFrameMetadata<BT>, BT::TxBuffer, BT::TxAllocator>,
371 > for IpLinkDeviceState<PureIpDevice, BT>
372{
373 type Lock = Mutex<
374 TransmitQueueState<PureIpDeviceTxQueueFrameMetadata<BT>, BT::TxBuffer, BT::TxAllocator>,
375 >;
376 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
377 OrderedLockRef::new(&self.link.tx_queue.queue)
378 }
379}
380
381impl<BT: DeviceLayerTypes>
382 OrderedLockAccess<DequeueState<PureIpDeviceTxQueueFrameMetadata<BT>, BT::TxBuffer>>
383 for IpLinkDeviceState<PureIpDevice, BT>
384{
385 type Lock = Mutex<DequeueState<PureIpDeviceTxQueueFrameMetadata<BT>, BT::TxBuffer>>;
386 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
387 OrderedLockRef::new(&self.link.tx_queue.deque)
388 }
389}