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