1use net_types::ethernet::Mac;
8use net_types::ip::{Ip, IpVersionMarker};
9use net_types::{BroadcastAddr, MulticastAddr};
10
11use core::convert::Infallible as Never;
12use core::fmt::Debug;
13use packet::{BufferMut, SerializeError, Serializer};
14use thiserror::Error;
15
16use crate::error::ErrorAndSerializer;
17use crate::socket::SocketCookie;
18
19pub trait RecvFrameContext<Meta, BC> {
25 fn receive_frame<B: BufferMut + Debug>(
29 &mut self,
30 bindings_ctx: &mut BC,
31 metadata: Meta,
32 frame: B,
33 );
34}
35
36impl<CC, BC> ReceivableFrameMeta<CC, BC> for Never {
37 fn receive_meta<B: BufferMut + Debug>(
38 self,
39 _core_ctx: &mut CC,
40 _bindings_ctx: &mut BC,
41 _frame: B,
42 ) {
43 match self {}
44 }
45}
46
47pub trait ReceivableFrameMeta<CC, BC> {
55 fn receive_meta<B: BufferMut + Debug>(self, core_ctx: &mut CC, bindings_ctx: &mut BC, frame: B);
57}
58
59impl<CC, BC, Meta> RecvFrameContext<Meta, BC> for CC
60where
61 Meta: ReceivableFrameMeta<CC, BC>,
62{
63 fn receive_frame<B: BufferMut + Debug>(
64 &mut self,
65 bindings_ctx: &mut BC,
66 metadata: Meta,
67 frame: B,
68 ) {
69 metadata.receive_meta(self, bindings_ctx, frame)
70 }
71}
72
73#[derive(Error, Debug, PartialEq)]
75pub enum SendFrameErrorReason {
76 #[error("size constraints violated")]
78 SizeConstraintsViolation,
79 #[error("failed to allocate")]
81 Alloc,
82 #[error("transmit queue is full")]
84 QueueFull,
85}
86
87impl<A> From<SerializeError<A>> for SendFrameErrorReason {
88 fn from(e: SerializeError<A>) -> Self {
89 match e {
90 SerializeError::Alloc(_) => Self::Alloc,
91 SerializeError::SizeLimitExceeded => Self::SizeConstraintsViolation,
92 }
93 }
94}
95
96pub type SendFrameError<S> = ErrorAndSerializer<SendFrameErrorReason, S>;
98
99pub trait SendFrameContext<BC, Meta> {
101 fn send_frame<S>(
110 &mut self,
111 bindings_ctx: &mut BC,
112 metadata: Meta,
113 frame: S,
114 ) -> Result<(), SendFrameError<S>>
115 where
116 S: Serializer,
117 S::Buffer: BufferMut;
118}
119
120pub trait SendableFrameMeta<CC, BC> {
128 fn send_meta<S>(
130 self,
131 core_ctx: &mut CC,
132 bindings_ctx: &mut BC,
133 frame: S,
134 ) -> Result<(), SendFrameError<S>>
135 where
136 S: Serializer,
137 S::Buffer: BufferMut;
138}
139
140impl<CC, BC, Meta> SendFrameContext<BC, Meta> for CC
141where
142 Meta: SendableFrameMeta<CC, BC>,
143{
144 fn send_frame<S>(
145 &mut self,
146 bindings_ctx: &mut BC,
147 metadata: Meta,
148 frame: S,
149 ) -> Result<(), SendFrameError<S>>
150 where
151 S: Serializer,
152 S::Buffer: BufferMut,
153 {
154 metadata.send_meta(self, bindings_ctx, frame)
155 }
156}
157
158#[derive(Copy, Clone, Debug, Eq, PartialEq)]
164pub enum FrameDestination {
165 Individual {
167 local: bool,
169 },
170 Multicast,
174 Broadcast,
178}
179
180impl FrameDestination {
181 pub fn is_broadcast(self) -> bool {
183 self == FrameDestination::Broadcast
184 }
185
186 pub fn from_dest(destination: Mac, local_mac: Mac) -> Self {
188 BroadcastAddr::new(destination)
189 .map(Into::into)
190 .or_else(|| MulticastAddr::new(destination).map(Into::into))
191 .unwrap_or_else(|| FrameDestination::Individual { local: destination == local_mac })
192 }
193}
194
195impl From<BroadcastAddr<Mac>> for FrameDestination {
196 fn from(_value: BroadcastAddr<Mac>) -> Self {
197 Self::Broadcast
198 }
199}
200
201impl From<MulticastAddr<Mac>> for FrameDestination {
202 fn from(_value: MulticastAddr<Mac>) -> Self {
203 Self::Multicast
204 }
205}
206
207pub struct RecvIpFrameMeta<D, M, I: Ip> {
209 pub device: D,
211 pub frame_dst: Option<FrameDestination>,
218 pub ip_layer_metadata: M,
221 pub marker: IpVersionMarker<I>,
223}
224
225impl<D, M, I: Ip> RecvIpFrameMeta<D, M, I> {
226 pub fn new(
229 device: D,
230 frame_dst: Option<FrameDestination>,
231 ip_layer_metadata: M,
232 ) -> RecvIpFrameMeta<D, M, I> {
233 RecvIpFrameMeta { device, frame_dst, ip_layer_metadata, marker: IpVersionMarker::new() }
234 }
235}
236
237pub trait TxMetadata: Default + Debug + Send + Sync + 'static {
242 fn socket_cookie(&self) -> Option<SocketCookie>;
246}
247
248pub trait TxMetadataBindingsTypes {
260 type TxMetadata: TxMetadata;
262}
263
264pub trait CoreTxMetadataContext<T, BT: TxMetadataBindingsTypes> {
269 fn convert_tx_meta(&self, tx_meta: T) -> BT::TxMetadata;
275}
276
277#[cfg(any(test, feature = "testutils"))]
278pub(crate) mod testutil {
279 use super::*;
280 use alloc::boxed::Box;
281 use alloc::vec::Vec;
282
283 use crate::testutil::FakeBindingsCtx;
284
285 pub struct FakeFrameCtx<Meta> {
287 frames: Vec<(Meta, Vec<u8>)>,
288 should_error_for_frame:
289 Option<Box<dyn FnMut(&Meta) -> Option<SendFrameErrorReason> + Send>>,
290 }
291
292 impl<Meta> FakeFrameCtx<Meta> {
293 pub fn set_should_error_for_frame<
296 F: Fn(&Meta) -> Option<SendFrameErrorReason> + Send + 'static,
297 >(
298 &mut self,
299 f: F,
300 ) {
301 self.should_error_for_frame = Some(Box::new(f));
302 }
303 }
304
305 impl<Meta> Default for FakeFrameCtx<Meta> {
306 fn default() -> FakeFrameCtx<Meta> {
307 FakeFrameCtx { frames: Vec::new(), should_error_for_frame: None }
308 }
309 }
310
311 impl<Meta> FakeFrameCtx<Meta> {
312 pub fn take_frames(&mut self) -> Vec<(Meta, Vec<u8>)> {
314 core::mem::take(&mut self.frames)
315 }
316
317 pub fn frames(&self) -> &[(Meta, Vec<u8>)] {
319 self.frames.as_slice()
320 }
321
322 pub fn push(&mut self, meta: Meta, frame: Vec<u8>) {
324 self.frames.push((meta, frame))
325 }
326 }
327
328 impl<Meta, BC> SendableFrameMeta<FakeFrameCtx<Meta>, BC> for Meta {
329 fn send_meta<S>(
330 self,
331 core_ctx: &mut FakeFrameCtx<Meta>,
332 _bindings_ctx: &mut BC,
333 frame: S,
334 ) -> Result<(), SendFrameError<S>>
335 where
336 S: Serializer,
337 S::Buffer: BufferMut,
338 {
339 if let Some(error) = core_ctx.should_error_for_frame.as_mut().and_then(|f| f(&self)) {
340 return Err(SendFrameError { serializer: frame, error });
341 }
342
343 let buffer = frame
344 .serialize_vec_outer()
345 .map_err(|(e, serializer)| SendFrameError { error: e.into(), serializer })?;
346 core_ctx.push(self, buffer.as_ref().to_vec());
347 Ok(())
348 }
349 }
350
351 pub trait WithFakeFrameContext<SendMeta> {
353 fn with_fake_frame_ctx_mut<O, F: FnOnce(&mut FakeFrameCtx<SendMeta>) -> O>(
355 &mut self,
356 f: F,
357 ) -> O;
358 }
359
360 impl<SendMeta> WithFakeFrameContext<SendMeta> for FakeFrameCtx<SendMeta> {
361 fn with_fake_frame_ctx_mut<O, F: FnOnce(&mut FakeFrameCtx<SendMeta>) -> O>(
362 &mut self,
363 f: F,
364 ) -> O {
365 f(self)
366 }
367 }
368
369 impl<TimerId, Event: Debug, State, FrameMeta> TxMetadataBindingsTypes
370 for FakeBindingsCtx<TimerId, Event, State, FrameMeta>
371 {
372 type TxMetadata = FakeTxMetadata;
373 }
374
375 #[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
377 pub struct FakeTxMetadata;
378
379 impl TxMetadata for FakeTxMetadata {
380 fn socket_cookie(&self) -> Option<SocketCookie> {
381 None
382 }
383 }
384}
385
386#[cfg(test)]
387mod tests {
388 use super::*;
389
390 use net_declare::net_mac;
391 use net_types::{UnicastAddr, Witness as _};
392
393 #[test]
394 fn frame_destination_from_dest() {
395 const LOCAL_ADDR: Mac = net_mac!("88:88:88:88:88:88");
396
397 assert_eq!(
398 FrameDestination::from_dest(
399 UnicastAddr::new(net_mac!("00:11:22:33:44:55")).unwrap().get(),
400 LOCAL_ADDR
401 ),
402 FrameDestination::Individual { local: false }
403 );
404 assert_eq!(
405 FrameDestination::from_dest(LOCAL_ADDR, LOCAL_ADDR),
406 FrameDestination::Individual { local: true }
407 );
408 assert_eq!(
409 FrameDestination::from_dest(Mac::BROADCAST, LOCAL_ADDR),
410 FrameDestination::Broadcast,
411 );
412 assert_eq!(
413 FrameDestination::from_dest(
414 MulticastAddr::new(net_mac!("11:11:11:11:11:11")).unwrap().get(),
415 LOCAL_ADDR
416 ),
417 FrameDestination::Multicast
418 );
419 }
420}