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