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 core_ctx.increment_both(&device_id, |counters: &DeviceCounters| &counters.recv_frame);
177
178 core_ctx.handle_frame(
182 bindings_ctx,
183 &device_id,
184 Frame::Received(ReceivedFrame::Ip(IpFrame { ip_version, body: buffer.as_ref() })),
185 buffer.as_ref(),
186 );
187
188 match ip_version {
189 IpVersion::V4 => {
190 core_ctx.increment_both(&device_id, |counters: &DeviceCounters| {
191 &counters.recv_ipv4_delivered
192 });
193 core_ctx.receive_frame(
194 bindings_ctx,
195 RecvIpFrameMeta::<_, _, Ipv4>::new(
196 device_id,
197 None,
198 DeviceIpLayerMetadata::default(),
199 ),
200 buffer,
201 )
202 }
203 IpVersion::V6 => {
204 core_ctx.increment_both(&device_id, |counters: &DeviceCounters| {
205 &counters.recv_ipv6_delivered
206 });
207 core_ctx.receive_frame(
208 bindings_ctx,
209 RecvIpFrameMeta::<_, _, Ipv6>::new(
210 device_id,
211 None,
212 DeviceIpLayerMetadata::default(),
213 ),
214 buffer,
215 )
216 }
217 }
218 }
219}
220
221impl<CC, BC> SendableFrameMeta<CC, BC> for DeviceSocketMetadata<PureIpDevice, CC::DeviceId>
222where
223 CC: TransmitQueueHandler<PureIpDevice, BC, Meta = PureIpDeviceTxQueueFrameMetadata<BC>>
224 + ResourceCounterContext<CC::DeviceId, DeviceCounters>,
225 BC: TxMetadataBindingsTypes,
226{
227 fn send_meta<S>(
228 self,
229 core_ctx: &mut CC,
230 bindings_ctx: &mut BC,
231 body: S,
232 ) -> Result<(), SendFrameError<S>>
233 where
234 S: Serializer,
235 S::Buffer: BufferMut,
236 {
237 let Self { device_id, metadata: PureIpHeaderParams { ip_version } } = self;
238 let tx_meta: BC::TxMetadata = Default::default();
241 net_types::for_any_ip_version!(
242 ip_version,
243 I,
244 queue_ip_frame::<_, _, I, _>(core_ctx, bindings_ctx, &device_id, body, tx_meta)
245 )
246 }
247}
248
249pub fn send_ip_frame<BC, CC, I, S>(
251 core_ctx: &mut CC,
252 bindings_ctx: &mut BC,
253 device_id: &CC::DeviceId,
254 destination: IpPacketDestination<I, &DeviceId<BC>>,
255 packet: S,
256 tx_meta: BC::TxMetadata,
257) -> Result<(), SendFrameError<S>>
258where
259 BC: DeviceLayerTypes,
260 CC: TransmitQueueHandler<PureIpDevice, BC, Meta = PureIpDeviceTxQueueFrameMetadata<BC>>
261 + ResourceCounterContext<CC::DeviceId, DeviceCounters>,
262 I: Ip + BroadcastIpExt,
263 S: Serializer,
264 S::Buffer: BufferMut,
265{
266 core_ctx.increment_both(device_id, |counters| &counters.send_total_frames);
267 core_ctx.increment_both(device_id, DeviceCounters::send_frame::<I>);
268
269 match destination {
270 IpPacketDestination::Broadcast(_)
271 | IpPacketDestination::Multicast(_)
272 | IpPacketDestination::Neighbor(_) => (),
273 IpPacketDestination::Loopback(_) => {
274 unreachable!("Loopback packets must be delivered through the loopback device");
275 }
276 };
277
278 queue_ip_frame::<_, _, I, _>(core_ctx, bindings_ctx, device_id, packet, tx_meta)
279}
280
281fn queue_ip_frame<BC, CC, I, S>(
282 core_ctx: &mut CC,
283 bindings_ctx: &mut BC,
284 device_id: &CC::DeviceId,
285 packet: S,
286 tx_metadata: BC::TxMetadata,
287) -> Result<(), SendFrameError<S>>
288where
289 CC: TransmitQueueHandler<PureIpDevice, BC, Meta = PureIpDeviceTxQueueFrameMetadata<BC>>
290 + ResourceCounterContext<CC::DeviceId, DeviceCounters>,
291 BC: TxMetadataBindingsTypes,
292 I: Ip,
293 S: Serializer,
294 S::Buffer: BufferMut,
295{
296 let result = TransmitQueueHandler::<PureIpDevice, _>::queue_tx_frame(
297 core_ctx,
298 bindings_ctx,
299 device_id,
300 PureIpDeviceTxQueueFrameMetadata { ip_version: I::VERSION, tx_metadata },
301 packet,
302 );
303 match result {
304 Ok(()) => {
305 core_ctx.increment_both(device_id, |counters| &counters.send_frame);
306 Ok(())
307 }
308 Err(TransmitQueueFrameError::NoQueue(err)) => {
309 core_ctx.increment_both(device_id, |counters| &counters.send_dropped_no_queue);
310 debug!("device {device_id:?} failed to send frame: {err:?}.");
311 Ok(())
312 }
313 Err(TransmitQueueFrameError::QueueFull(serializer)) => {
314 core_ctx.increment_both(device_id, |counters| &counters.send_queue_full);
315 Err(SendFrameError { serializer, error: SendFrameErrorReason::QueueFull })
316 }
317 Err(TransmitQueueFrameError::SerializeError(err)) => {
318 core_ctx.increment_both(device_id, |counters| &counters.send_serialize_error);
319 Err(err.err_into())
320 }
321 }
322}
323
324pub fn get_mtu<CC: PureIpDeviceStateContext>(core_ctx: &mut CC, device_id: &CC::DeviceId) -> Mtu {
326 core_ctx.with_pure_ip_state(device_id, |DynamicPureIpDeviceState { mtu }| *mtu)
327}
328
329pub fn set_mtu<CC: PureIpDeviceStateContext>(
331 core_ctx: &mut CC,
332 device_id: &CC::DeviceId,
333 new_mtu: Mtu,
334) {
335 core_ctx.with_pure_ip_state_mut(device_id, |DynamicPureIpDeviceState { mtu }| *mtu = new_mtu)
336}
337
338impl<BT: DeviceLayerTypes> OrderedLockAccess<DynamicPureIpDeviceState>
339 for IpLinkDeviceState<PureIpDevice, BT>
340{
341 type Lock = RwLock<DynamicPureIpDeviceState>;
342 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
343 OrderedLockRef::new(&self.link.dynamic_state)
344 }
345}
346
347impl<BT: DeviceLayerTypes>
348 OrderedLockAccess<
349 TransmitQueueState<PureIpDeviceTxQueueFrameMetadata<BT>, Buf<Vec<u8>>, BufVecU8Allocator>,
350 > for IpLinkDeviceState<PureIpDevice, BT>
351{
352 type Lock = Mutex<
353 TransmitQueueState<PureIpDeviceTxQueueFrameMetadata<BT>, Buf<Vec<u8>>, BufVecU8Allocator>,
354 >;
355 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
356 OrderedLockRef::new(&self.link.tx_queue.queue)
357 }
358}
359
360impl<BT: DeviceLayerTypes>
361 OrderedLockAccess<DequeueState<PureIpDeviceTxQueueFrameMetadata<BT>, Buf<Vec<u8>>>>
362 for IpLinkDeviceState<PureIpDevice, BT>
363{
364 type Lock = Mutex<DequeueState<PureIpDeviceTxQueueFrameMetadata<BT>, Buf<Vec<u8>>>>;
365 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
366 OrderedLockRef::new(&self.link.tx_queue.deque)
367 }
368}