1use alloc::vec::Vec;
8use core::fmt::Debug;
9use core::num::NonZeroU32;
10use lock_order::lock::{OrderedLockAccess, OrderedLockRef};
11
12use log::{debug, trace};
13use net_types::ethernet::Mac;
14use net_types::ip::{GenericOverIp, Ip, IpMarked, Ipv4, Ipv6, Mtu};
15use net_types::{MulticastAddr, UnicastAddr, Witness};
16use netstack3_base::ref_counted_hash_map::{InsertResult, RefCountedHashSet, RemoveResult};
17use netstack3_base::sync::{Mutex, RwLock};
18use netstack3_base::{
19 BroadcastIpExt, CoreTimerContext, Device, DeviceIdContext, FrameDestination, HandleableTimer,
20 LinkDevice, NestedIntoCoreTimerCtx, ReceivableFrameMeta, RecvFrameContext, RecvIpFrameMeta,
21 ResourceCounterContext, RngContext, SendFrameError, SendFrameErrorReason, SendableFrameMeta,
22 TimerContext, TimerHandler, TxMetadataBindingsTypes, WeakDeviceIdentifier, WrapBroadcastMarker,
23};
24use netstack3_ip::nud::{
25 LinkResolutionContext, NudBindingsTypes, NudHandler, NudState, NudTimerId, NudUserConfig,
26};
27use netstack3_ip::{DeviceIpLayerMetadata, IpPacketDestination};
28use netstack3_trace::trace_duration;
29use packet::{Buf, BufferMut, Serializer};
30use packet_formats::arp::{peek_arp_types, ArpHardwareType, ArpNetworkType};
31use packet_formats::ethernet::{
32 EtherType, EthernetFrame, EthernetFrameBuilder, EthernetFrameLengthCheck, EthernetIpExt,
33 ETHERNET_HDR_LEN_NO_TAG,
34};
35
36use crate::internal::arp::{ArpFrameMetadata, ArpPacketHandler, ArpState, ArpTimerId};
37use crate::internal::base::{
38 DeviceCounters, DeviceLayerTypes, DeviceReceiveFrameSpec, EthernetDeviceCounters,
39};
40use crate::internal::id::{DeviceId, EthernetDeviceId};
41use crate::internal::queue::tx::{
42 BufVecU8Allocator, TransmitQueue, TransmitQueueHandler, TransmitQueueState,
43};
44use crate::internal::queue::{DequeueState, TransmitQueueFrameError};
45use crate::internal::socket::{
46 DeviceSocketHandler, DeviceSocketMetadata, DeviceSocketSendTypes, EthernetHeaderParams,
47 ReceivedFrame,
48};
49use crate::internal::state::{DeviceStateSpec, IpLinkDeviceState};
50
51const ETHERNET_HDR_LEN_NO_TAG_U32: u32 = ETHERNET_HDR_LEN_NO_TAG as u32;
52
53pub trait EthernetIpLinkDeviceBindingsContext:
55 RngContext + TimerContext + DeviceLayerTypes + TxMetadataBindingsTypes
56{
57}
58impl<BC: RngContext + TimerContext + DeviceLayerTypes + TxMetadataBindingsTypes>
59 EthernetIpLinkDeviceBindingsContext for BC
60{
61}
62
63pub trait EthernetIpLinkDeviceStaticStateContext: DeviceIdContext<EthernetLinkDevice> {
65 fn with_static_ethernet_device_state<O, F: FnOnce(&StaticEthernetDeviceState) -> O>(
68 &mut self,
69 device_id: &Self::DeviceId,
70 cb: F,
71 ) -> O;
72}
73
74pub trait EthernetIpLinkDeviceDynamicStateContext<BC: EthernetIpLinkDeviceBindingsContext>:
76 EthernetIpLinkDeviceStaticStateContext
77{
78 fn with_ethernet_state<
81 O,
82 F: FnOnce(&StaticEthernetDeviceState, &DynamicEthernetDeviceState) -> O,
83 >(
84 &mut self,
85 device_id: &Self::DeviceId,
86 cb: F,
87 ) -> O;
88
89 fn with_ethernet_state_mut<
92 O,
93 F: FnOnce(&StaticEthernetDeviceState, &mut DynamicEthernetDeviceState) -> O,
94 >(
95 &mut self,
96 device_id: &Self::DeviceId,
97 cb: F,
98 ) -> O;
99}
100
101pub fn send_as_ethernet_frame_to_dst<S, BC, CC>(
103 core_ctx: &mut CC,
104 bindings_ctx: &mut BC,
105 device_id: &CC::DeviceId,
106 dst_mac: Mac,
107 body: S,
108 ether_type: EtherType,
109 meta: BC::TxMetadata,
110) -> Result<(), SendFrameError<S>>
111where
112 S: Serializer,
113 S::Buffer: BufferMut,
114 BC: EthernetIpLinkDeviceBindingsContext,
115 CC: EthernetIpLinkDeviceDynamicStateContext<BC>
116 + TransmitQueueHandler<EthernetLinkDevice, BC, Meta = BC::TxMetadata>
117 + ResourceCounterContext<CC::DeviceId, DeviceCounters>,
118{
119 const MIN_BODY_LEN: usize = 0;
125
126 let local_mac = get_mac(core_ctx, device_id);
127 let max_frame_size = get_max_frame_size(core_ctx, device_id);
128 let frame = body
129 .encapsulate(EthernetFrameBuilder::new(local_mac.get(), dst_mac, ether_type, MIN_BODY_LEN))
130 .with_size_limit(max_frame_size.into());
131 send_ethernet_frame(core_ctx, bindings_ctx, device_id, frame, meta)
132 .map_err(|err| err.into_inner().into_inner())
133}
134
135fn send_ethernet_frame<S, BC, CC>(
136 core_ctx: &mut CC,
137 bindings_ctx: &mut BC,
138 device_id: &CC::DeviceId,
139 frame: S,
140 meta: BC::TxMetadata,
141) -> Result<(), SendFrameError<S>>
142where
143 S: Serializer,
144 S::Buffer: BufferMut,
145 BC: EthernetIpLinkDeviceBindingsContext,
146 CC: EthernetIpLinkDeviceDynamicStateContext<BC>
147 + TransmitQueueHandler<EthernetLinkDevice, BC, Meta = BC::TxMetadata>
148 + ResourceCounterContext<CC::DeviceId, DeviceCounters>,
149{
150 core_ctx.increment_both(device_id, |counters| &counters.send_total_frames);
151 match TransmitQueueHandler::<EthernetLinkDevice, _>::queue_tx_frame(
152 core_ctx,
153 bindings_ctx,
154 device_id,
155 meta,
156 frame,
157 ) {
158 Ok(()) => {
159 core_ctx.increment_both(device_id, |counters| &counters.send_frame);
160 Ok(())
161 }
162 Err(TransmitQueueFrameError::NoQueue(err)) => {
163 core_ctx.increment_both(device_id, |counters| &counters.send_dropped_no_queue);
164 debug!("device {device_id:?} failed to send frame: {err:?}.");
165 Ok(())
166 }
167 Err(TransmitQueueFrameError::QueueFull(serializer)) => {
168 core_ctx.increment_both(device_id, |counters| &counters.send_queue_full);
169 Err(SendFrameError { serializer, error: SendFrameErrorReason::QueueFull })
170 }
171 Err(TransmitQueueFrameError::SerializeError(err)) => {
172 core_ctx.increment_both(device_id, |counters| &counters.send_serialize_error);
173 Err(err.err_into())
174 }
175 }
176}
177
178#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
184pub struct MaxEthernetFrameSize(NonZeroU32);
185
186impl MaxEthernetFrameSize {
187 pub const MIN: MaxEthernetFrameSize = MaxEthernetFrameSize(NonZeroU32::new(60).unwrap());
191
192 pub const fn new(frame_size: u32) -> Option<Self> {
195 if frame_size < Self::MIN.get().get() {
196 return None;
197 }
198 Some(Self(NonZeroU32::new(frame_size).unwrap()))
199 }
200
201 const fn get(&self) -> NonZeroU32 {
202 let Self(frame_size) = *self;
203 frame_size
204 }
205
206 pub const fn as_mtu(&self) -> Mtu {
208 Mtu::new(self.get().get().saturating_sub(ETHERNET_HDR_LEN_NO_TAG_U32))
210 }
211
212 pub const fn from_mtu(mtu: Mtu) -> Option<MaxEthernetFrameSize> {
214 let frame_size = mtu.get().saturating_add(ETHERNET_HDR_LEN_NO_TAG_U32);
215 Self::new(frame_size)
216 }
217}
218
219impl From<MaxEthernetFrameSize> for usize {
220 fn from(MaxEthernetFrameSize(v): MaxEthernetFrameSize) -> Self {
221 v.get().try_into().expect("u32 doesn't fit in usize")
222 }
223}
224
225#[derive(Debug)]
227pub struct EthernetCreationProperties {
228 pub mac: UnicastAddr<Mac>,
230 pub max_frame_size: MaxEthernetFrameSize,
241}
242
243pub struct DynamicEthernetDeviceState {
245 max_frame_size: MaxEthernetFrameSize,
247
248 link_multicast_groups: RefCountedHashSet<MulticastAddr<Mac>>,
252}
253
254impl DynamicEthernetDeviceState {
255 fn new(max_frame_size: MaxEthernetFrameSize) -> Self {
256 Self { max_frame_size, link_multicast_groups: Default::default() }
257 }
258}
259
260pub struct StaticEthernetDeviceState {
262 mac: UnicastAddr<Mac>,
264
265 max_frame_size: MaxEthernetFrameSize,
267}
268
269pub struct EthernetDeviceState<BT: NudBindingsTypes<EthernetLinkDevice>> {
271 pub counters: EthernetDeviceCounters,
273 pub static_state: StaticEthernetDeviceState,
275 pub tx_queue: TransmitQueue<BT::TxMetadata, Buf<Vec<u8>>, BufVecU8Allocator>,
277 ipv4_arp: Mutex<ArpState<EthernetLinkDevice, BT>>,
278 ipv6_nud: Mutex<NudState<Ipv6, EthernetLinkDevice, BT>>,
279 ipv4_nud_config: RwLock<IpMarked<Ipv4, NudUserConfig>>,
280 ipv6_nud_config: RwLock<IpMarked<Ipv6, NudUserConfig>>,
281 dynamic_state: RwLock<DynamicEthernetDeviceState>,
282}
283
284impl<BT: DeviceLayerTypes, I: Ip> OrderedLockAccess<IpMarked<I, NudUserConfig>>
285 for IpLinkDeviceState<EthernetLinkDevice, BT>
286{
287 type Lock = RwLock<IpMarked<I, NudUserConfig>>;
288 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
289 OrderedLockRef::new(I::map_ip(
290 (),
291 |()| &self.link.ipv4_nud_config,
292 |()| &self.link.ipv6_nud_config,
293 ))
294 }
295}
296
297impl<BT: DeviceLayerTypes> OrderedLockAccess<DynamicEthernetDeviceState>
298 for IpLinkDeviceState<EthernetLinkDevice, BT>
299{
300 type Lock = RwLock<DynamicEthernetDeviceState>;
301 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
302 OrderedLockRef::new(&self.link.dynamic_state)
303 }
304}
305
306impl<BT: DeviceLayerTypes> OrderedLockAccess<NudState<Ipv6, EthernetLinkDevice, BT>>
307 for IpLinkDeviceState<EthernetLinkDevice, BT>
308{
309 type Lock = Mutex<NudState<Ipv6, EthernetLinkDevice, BT>>;
310 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
311 OrderedLockRef::new(&self.link.ipv6_nud)
312 }
313}
314
315impl<BT: DeviceLayerTypes> OrderedLockAccess<ArpState<EthernetLinkDevice, BT>>
316 for IpLinkDeviceState<EthernetLinkDevice, BT>
317{
318 type Lock = Mutex<ArpState<EthernetLinkDevice, BT>>;
319 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
320 OrderedLockRef::new(&self.link.ipv4_arp)
321 }
322}
323
324impl<BT: DeviceLayerTypes>
325 OrderedLockAccess<TransmitQueueState<BT::TxMetadata, Buf<Vec<u8>>, BufVecU8Allocator>>
326 for IpLinkDeviceState<EthernetLinkDevice, BT>
327{
328 type Lock = Mutex<TransmitQueueState<BT::TxMetadata, Buf<Vec<u8>>, BufVecU8Allocator>>;
329 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
330 OrderedLockRef::new(&self.link.tx_queue.queue)
331 }
332}
333
334impl<BT: DeviceLayerTypes> OrderedLockAccess<DequeueState<BT::TxMetadata, Buf<Vec<u8>>>>
335 for IpLinkDeviceState<EthernetLinkDevice, BT>
336{
337 type Lock = Mutex<DequeueState<BT::TxMetadata, Buf<Vec<u8>>>>;
338 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
339 OrderedLockRef::new(&self.link.tx_queue.deque)
340 }
341}
342
343#[derive(Clone, Eq, PartialEq, Debug, Hash, GenericOverIp)]
347#[generic_over_ip()]
348#[allow(missing_docs)]
349pub enum EthernetTimerId<D: WeakDeviceIdentifier> {
350 Arp(ArpTimerId<EthernetLinkDevice, D>),
351 Nudv6(NudTimerId<Ipv6, EthernetLinkDevice, D>),
352}
353
354impl<I: Ip, D: WeakDeviceIdentifier> From<NudTimerId<I, EthernetLinkDevice, D>>
355 for EthernetTimerId<D>
356{
357 fn from(id: NudTimerId<I, EthernetLinkDevice, D>) -> EthernetTimerId<D> {
358 I::map_ip(id, EthernetTimerId::Arp, EthernetTimerId::Nudv6)
359 }
360}
361
362impl<CC, BC> HandleableTimer<CC, BC> for EthernetTimerId<CC::WeakDeviceId>
363where
364 BC: EthernetIpLinkDeviceBindingsContext,
365 CC: EthernetIpLinkDeviceDynamicStateContext<BC>
366 + TimerHandler<BC, NudTimerId<Ipv6, EthernetLinkDevice, CC::WeakDeviceId>>
367 + TimerHandler<BC, ArpTimerId<EthernetLinkDevice, CC::WeakDeviceId>>,
368{
369 fn handle(self, core_ctx: &mut CC, bindings_ctx: &mut BC, timer: BC::UniqueTimerId) {
370 match self {
371 EthernetTimerId::Arp(id) => core_ctx.handle_timer(bindings_ctx, id, timer),
372 EthernetTimerId::Nudv6(id) => core_ctx.handle_timer(bindings_ctx, id, timer),
373 }
374 }
375}
376
377pub fn send_ip_frame<BC, CC, I, S>(
384 core_ctx: &mut CC,
385 bindings_ctx: &mut BC,
386 device_id: &CC::DeviceId,
387 destination: IpPacketDestination<I, &DeviceId<BC>>,
388 body: S,
389 meta: BC::TxMetadata,
390) -> Result<(), SendFrameError<S>>
391where
392 BC: EthernetIpLinkDeviceBindingsContext + LinkResolutionContext<EthernetLinkDevice>,
393 CC: EthernetIpLinkDeviceDynamicStateContext<BC>
394 + NudHandler<I, EthernetLinkDevice, BC>
395 + TransmitQueueHandler<EthernetLinkDevice, BC, Meta = BC::TxMetadata>
396 + ResourceCounterContext<CC::DeviceId, DeviceCounters>,
397 I: EthernetIpExt + BroadcastIpExt,
398 S: Serializer,
399 S::Buffer: BufferMut,
400{
401 core_ctx.increment_both(device_id, DeviceCounters::send_frame::<I>);
402
403 trace!("ethernet::send_ip_frame: destination = {:?}; device = {:?}", destination, device_id);
404
405 match destination {
406 IpPacketDestination::Broadcast(marker) => {
407 I::map_ip::<_, ()>(
408 WrapBroadcastMarker(marker),
409 |WrapBroadcastMarker(())| (),
410 |WrapBroadcastMarker(never)| match never {},
411 );
412 send_as_ethernet_frame_to_dst(
413 core_ctx,
414 bindings_ctx,
415 device_id,
416 Mac::BROADCAST,
417 body,
418 I::ETHER_TYPE,
419 meta,
420 )
421 }
422 IpPacketDestination::Multicast(multicast_ip) => send_as_ethernet_frame_to_dst(
423 core_ctx,
424 bindings_ctx,
425 device_id,
426 Mac::from(&multicast_ip),
427 body,
428 I::ETHER_TYPE,
429 meta,
430 ),
431 IpPacketDestination::Neighbor(ip) => NudHandler::<I, _, _>::send_ip_packet_to_neighbor(
432 core_ctx,
433 bindings_ctx,
434 device_id,
435 ip,
436 body,
437 meta,
438 ),
439 IpPacketDestination::Loopback(_) => {
440 unreachable!("Loopback packets must be delivered through the loopback device")
441 }
442 }
443}
444
445pub struct RecvEthernetFrameMeta<D> {
447 pub device_id: D,
449}
450
451impl DeviceReceiveFrameSpec for EthernetLinkDevice {
452 type FrameMetadata<D> = RecvEthernetFrameMeta<D>;
453}
454
455impl<CC, BC> ReceivableFrameMeta<CC, BC> for RecvEthernetFrameMeta<CC::DeviceId>
456where
457 BC: EthernetIpLinkDeviceBindingsContext,
458 CC: EthernetIpLinkDeviceDynamicStateContext<BC>
459 + RecvFrameContext<RecvIpFrameMeta<CC::DeviceId, DeviceIpLayerMetadata<BC>, Ipv4>, BC>
460 + RecvFrameContext<RecvIpFrameMeta<CC::DeviceId, DeviceIpLayerMetadata<BC>, Ipv6>, BC>
461 + ArpPacketHandler<EthernetLinkDevice, BC>
462 + DeviceSocketHandler<EthernetLinkDevice, BC>
463 + ResourceCounterContext<CC::DeviceId, DeviceCounters>
464 + ResourceCounterContext<CC::DeviceId, EthernetDeviceCounters>,
465{
466 fn receive_meta<B: BufferMut + Debug>(
467 self,
468 core_ctx: &mut CC,
469 bindings_ctx: &mut BC,
470 mut buffer: B,
471 ) {
472 trace_duration!(c"device::ethernet::receive_frame");
473 let Self { device_id } = self;
474 trace!("ethernet::receive_frame: device_id = {:?}", device_id);
475 core_ctx.increment_both(&device_id, |counters: &DeviceCounters| &counters.recv_frame);
476 let (ethernet, whole_frame) = if let Ok(frame) =
485 buffer.parse_with_view::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::NoCheck)
486 {
487 frame
488 } else {
489 core_ctx
490 .increment_both(&device_id, |counters: &DeviceCounters| &counters.recv_parse_error);
491 trace!("ethernet::receive_frame: failed to parse ethernet frame");
492 return;
493 };
494
495 let dst = ethernet.dst_mac();
496
497 let frame_dst = core_ctx.with_static_ethernet_device_state(&device_id, |static_state| {
498 FrameDestination::from_dest(dst, static_state.mac.get())
499 });
500
501 let ethertype = ethernet.ethertype();
502
503 core_ctx.handle_frame(
504 bindings_ctx,
505 &device_id,
506 ReceivedFrame::from_ethernet(ethernet, frame_dst).into(),
507 whole_frame,
508 );
509
510 match ethertype {
511 Some(EtherType::Arp) => {
512 let types = if let Ok(types) = peek_arp_types(buffer.as_ref()) {
513 types
514 } else {
515 return;
516 };
517 match types {
518 (ArpHardwareType::Ethernet, ArpNetworkType::Ipv4) => {
519 ArpPacketHandler::handle_packet(
520 core_ctx,
521 bindings_ctx,
522 device_id,
523 frame_dst,
524 buffer,
525 )
526 }
527 }
528 }
529 Some(EtherType::Ipv4) => {
530 core_ctx.increment_both(&device_id, |counters: &DeviceCounters| {
531 &counters.recv_ipv4_delivered
532 });
533 core_ctx.receive_frame(
534 bindings_ctx,
535 RecvIpFrameMeta::<_, _, Ipv4>::new(
536 device_id,
537 Some(frame_dst),
538 DeviceIpLayerMetadata::default(),
539 ),
540 buffer,
541 )
542 }
543 Some(EtherType::Ipv6) => {
544 core_ctx.increment_both(&device_id, |counters: &DeviceCounters| {
545 &counters.recv_ipv6_delivered
546 });
547 core_ctx.receive_frame(
548 bindings_ctx,
549 RecvIpFrameMeta::<_, _, Ipv6>::new(
550 device_id,
551 Some(frame_dst),
552 DeviceIpLayerMetadata::default(),
553 ),
554 buffer,
555 )
556 }
557 Some(EtherType::Other(_)) => {
558 core_ctx.increment_both(&device_id, |counters: &EthernetDeviceCounters| {
559 &counters.recv_unsupported_ethertype
560 });
561 }
562 None => {
563 core_ctx.increment_both(&device_id, |counters: &EthernetDeviceCounters| {
564 &counters.recv_no_ethertype
565 });
566 }
567 }
568 }
569}
570
571pub fn join_link_multicast<
587 BC: EthernetIpLinkDeviceBindingsContext,
588 CC: EthernetIpLinkDeviceDynamicStateContext<BC>,
589>(
590 core_ctx: &mut CC,
591 _bindings_ctx: &mut BC,
592 device_id: &CC::DeviceId,
593 multicast_addr: MulticastAddr<Mac>,
594) {
595 core_ctx.with_ethernet_state_mut(device_id, |_static_state, dynamic_state| {
596 let groups = &mut dynamic_state.link_multicast_groups;
597
598 match groups.insert(multicast_addr) {
599 InsertResult::Inserted(()) => {
600 trace!(
601 "ethernet::join_link_multicast: joining link multicast {:?}",
602 multicast_addr
603 );
604 }
605 InsertResult::AlreadyPresent => {
606 trace!(
607 "ethernet::join_link_multicast: already joined link multicast {:?}",
608 multicast_addr,
609 );
610 }
611 }
612 })
613}
614
615pub fn leave_link_multicast<
634 BC: EthernetIpLinkDeviceBindingsContext,
635 CC: EthernetIpLinkDeviceDynamicStateContext<BC>,
636>(
637 core_ctx: &mut CC,
638 _bindings_ctx: &mut BC,
639 device_id: &CC::DeviceId,
640 multicast_addr: MulticastAddr<Mac>,
641) {
642 core_ctx.with_ethernet_state_mut(device_id, |_static_state, dynamic_state| {
643 let groups = &mut dynamic_state.link_multicast_groups;
644
645 match groups.remove(multicast_addr) {
646 RemoveResult::Removed(()) => {
647 trace!("ethernet::leave_link_multicast: leaving link multicast {:?}", multicast_addr);
648 }
649 RemoveResult::StillPresent => {
650 trace!(
651 "ethernet::leave_link_multicast: not leaving link multicast {:?} as there are still listeners for it",
652 multicast_addr,
653 );
654 }
655 RemoveResult::NotPresent => {
656 panic!(
657 "ethernet::leave_link_multicast: device {:?} has not yet joined link multicast {:?}",
658 device_id,
659 multicast_addr,
660 );
661 }
662 }
663 })
664}
665
666pub fn get_max_frame_size<
667 BC: EthernetIpLinkDeviceBindingsContext,
668 CC: EthernetIpLinkDeviceDynamicStateContext<BC>,
669>(
670 core_ctx: &mut CC,
671 device_id: &CC::DeviceId,
672) -> MaxEthernetFrameSize {
673 core_ctx
674 .with_ethernet_state(device_id, |_static_state, dynamic_state| dynamic_state.max_frame_size)
675}
676
677pub fn get_mtu<
679 BC: EthernetIpLinkDeviceBindingsContext,
680 CC: EthernetIpLinkDeviceDynamicStateContext<BC>,
681>(
682 core_ctx: &mut CC,
683 device_id: &CC::DeviceId,
684) -> Mtu {
685 get_max_frame_size(core_ctx, device_id).as_mtu()
686}
687
688pub trait UseArpFrameMetadataBlanket {}
694
695impl<
696 BC: EthernetIpLinkDeviceBindingsContext,
697 CC: EthernetIpLinkDeviceDynamicStateContext<BC>
698 + TransmitQueueHandler<EthernetLinkDevice, BC, Meta = BC::TxMetadata>
699 + ResourceCounterContext<CC::DeviceId, DeviceCounters>
700 + UseArpFrameMetadataBlanket,
701 > SendableFrameMeta<CC, BC> for ArpFrameMetadata<EthernetLinkDevice, CC::DeviceId>
702{
703 fn send_meta<S>(
704 self,
705 core_ctx: &mut CC,
706 bindings_ctx: &mut BC,
707 body: S,
708 ) -> Result<(), SendFrameError<S>>
709 where
710 S: Serializer,
711 S::Buffer: BufferMut,
712 {
713 let Self { device_id, dst_addr } = self;
714 let meta: BC::TxMetadata = Default::default();
715 send_as_ethernet_frame_to_dst(
716 core_ctx,
717 bindings_ctx,
718 &device_id,
719 dst_addr,
720 body,
721 EtherType::Arp,
722 meta,
723 )
724 }
725}
726
727impl DeviceSocketSendTypes for EthernetLinkDevice {
728 type Metadata = Option<EthernetHeaderParams>;
731}
732
733impl<
734 BC: EthernetIpLinkDeviceBindingsContext,
735 CC: EthernetIpLinkDeviceDynamicStateContext<BC>
736 + TransmitQueueHandler<EthernetLinkDevice, BC, Meta = BC::TxMetadata>
737 + ResourceCounterContext<CC::DeviceId, DeviceCounters>,
738 > SendableFrameMeta<CC, BC> for DeviceSocketMetadata<EthernetLinkDevice, EthernetDeviceId<BC>>
739where
740 CC: DeviceIdContext<EthernetLinkDevice, DeviceId = EthernetDeviceId<BC>>,
741{
742 fn send_meta<S>(
743 self,
744 core_ctx: &mut CC,
745 bindings_ctx: &mut BC,
746 body: S,
747 ) -> Result<(), SendFrameError<S>>
748 where
749 S: Serializer,
750 S::Buffer: BufferMut,
751 {
752 let Self { device_id, metadata } = self;
753 let tx_meta: BC::TxMetadata = Default::default();
756 match metadata {
757 Some(EthernetHeaderParams { dest_addr, protocol }) => send_as_ethernet_frame_to_dst(
758 core_ctx,
759 bindings_ctx,
760 &device_id,
761 dest_addr,
762 body,
763 protocol,
764 tx_meta,
765 ),
766 None => send_ethernet_frame(core_ctx, bindings_ctx, &device_id, body, tx_meta),
767 }
768 }
769}
770
771pub fn get_mac<
773 'a,
774 BC: EthernetIpLinkDeviceBindingsContext,
775 CC: EthernetIpLinkDeviceDynamicStateContext<BC>,
776>(
777 core_ctx: &'a mut CC,
778 device_id: &CC::DeviceId,
779) -> UnicastAddr<Mac> {
780 core_ctx.with_static_ethernet_device_state(device_id, |state| state.mac)
781}
782
783pub fn set_mtu<
785 BC: EthernetIpLinkDeviceBindingsContext,
786 CC: EthernetIpLinkDeviceDynamicStateContext<BC>,
787>(
788 core_ctx: &mut CC,
789 device_id: &CC::DeviceId,
790 mtu: Mtu,
791) {
792 core_ctx.with_ethernet_state_mut(device_id, |static_state, dynamic_state| {
793 if let Some(mut frame_size ) = MaxEthernetFrameSize::from_mtu(mtu) {
794 if frame_size > static_state.max_frame_size {
797 trace!("ethernet::ndp_device::set_mtu: MTU of {:?} is greater than the device {:?}'s max MTU of {:?}, using device's max MTU instead", mtu, device_id, static_state.max_frame_size.as_mtu());
798 frame_size = static_state.max_frame_size;
799 }
800 trace!("ethernet::ndp_device::set_mtu: setting link MTU to {:?}", mtu);
801 dynamic_state.max_frame_size = frame_size;
802 }
803 })
804}
805
806#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
808pub enum EthernetLinkDevice {}
809
810impl Device for EthernetLinkDevice {}
811
812impl LinkDevice for EthernetLinkDevice {
813 type Address = Mac;
814}
815
816impl DeviceStateSpec for EthernetLinkDevice {
817 type State<BT: DeviceLayerTypes> = EthernetDeviceState<BT>;
818 type External<BT: DeviceLayerTypes> = BT::EthernetDeviceState;
819 type CreationProperties = EthernetCreationProperties;
820 type Counters = EthernetDeviceCounters;
821 type TimerId<D: WeakDeviceIdentifier> = EthernetTimerId<D>;
822
823 fn new_device_state<
824 CC: CoreTimerContext<Self::TimerId<CC::WeakDeviceId>, BC> + DeviceIdContext<Self>,
825 BC: DeviceLayerTypes + TimerContext,
826 >(
827 bindings_ctx: &mut BC,
828 self_id: CC::WeakDeviceId,
829 EthernetCreationProperties { mac, max_frame_size }: Self::CreationProperties,
830 ) -> Self::State<BC> {
831 let ipv4_arp = Mutex::new(ArpState::new::<_, NestedIntoCoreTimerCtx<CC, _>>(
832 bindings_ctx,
833 self_id.clone(),
834 ));
835 let ipv6_nud =
836 Mutex::new(NudState::new::<_, NestedIntoCoreTimerCtx<CC, _>>(bindings_ctx, self_id));
837 EthernetDeviceState {
838 counters: Default::default(),
839 ipv4_arp,
840 ipv6_nud,
841 ipv4_nud_config: Default::default(),
842 ipv6_nud_config: Default::default(),
843 static_state: StaticEthernetDeviceState { mac, max_frame_size },
844 dynamic_state: RwLock::new(DynamicEthernetDeviceState::new(max_frame_size)),
845 tx_queue: Default::default(),
846 }
847 }
848 const IS_LOOPBACK: bool = false;
849 const DEBUG_TYPE: &'static str = "Ethernet";
850}
851
852#[cfg(any(test, feature = "testutils"))]
853pub(crate) mod testutil {
854 use super::*;
855
856 pub const IPV6_MIN_IMPLIED_MAX_FRAME_SIZE: MaxEthernetFrameSize =
858 MaxEthernetFrameSize::from_mtu(Ipv6::MINIMUM_LINK_MTU).unwrap();
859}
860
861#[cfg(test)]
862mod tests {
863 use alloc::vec;
864 use core::convert::Infallible as Never;
865
866 use net_types::ip::{Ipv4Addr, Ipv6Addr};
867 use net_types::SpecifiedAddr;
868 use netstack3_base::testutil::{
869 FakeDeviceId, FakeInstant, FakeTxMetadata, FakeWeakDeviceId, TEST_ADDRS_V4,
870 };
871 use netstack3_base::{CounterContext, CtxPair, IntoCoreTimerCtx};
872 use netstack3_ip::nud::{
873 self, DelegateNudContext, DynamicNeighborUpdateSource, NeighborApi, UseDelegateNudContext,
874 };
875 use packet_formats::testutil::parse_ethernet_frame;
876
877 use super::*;
878 use crate::internal::arp::{
879 ArpConfigContext, ArpContext, ArpCounters, ArpNudCtx, ArpSenderContext,
880 };
881 use crate::internal::base::DeviceSendFrameError;
882 use crate::internal::ethernet::testutil::IPV6_MIN_IMPLIED_MAX_FRAME_SIZE;
883 use crate::internal::queue::tx::{
884 TransmitQueueBindingsContext, TransmitQueueCommon, TransmitQueueContext,
885 };
886 use crate::internal::socket::{Frame, ParseSentFrameError, SentFrame};
887
888 struct FakeEthernetCtx {
889 static_state: StaticEthernetDeviceState,
890 dynamic_state: DynamicEthernetDeviceState,
891 tx_queue: TransmitQueueState<FakeTxMetadata, Buf<Vec<u8>>, BufVecU8Allocator>,
892 counters: DeviceCounters,
893 per_device_counters: DeviceCounters,
894 ethernet_counters: EthernetDeviceCounters,
895 arp_counters: ArpCounters,
896 }
897
898 impl FakeEthernetCtx {
899 fn new(mac: UnicastAddr<Mac>, max_frame_size: MaxEthernetFrameSize) -> FakeEthernetCtx {
900 FakeEthernetCtx {
901 static_state: StaticEthernetDeviceState { max_frame_size, mac },
902 dynamic_state: DynamicEthernetDeviceState::new(max_frame_size),
903 tx_queue: Default::default(),
904 counters: Default::default(),
905 per_device_counters: Default::default(),
906 ethernet_counters: Default::default(),
907 arp_counters: Default::default(),
908 }
909 }
910 }
911
912 type FakeBindingsCtx = netstack3_base::testutil::FakeBindingsCtx<
913 EthernetTimerId<FakeWeakDeviceId<FakeDeviceId>>,
914 nud::Event<Mac, FakeDeviceId, Ipv4, FakeInstant>,
915 (),
916 (),
917 >;
918
919 type FakeInnerCtx =
920 netstack3_base::testutil::FakeCoreCtx<FakeEthernetCtx, FakeDeviceId, FakeDeviceId>;
921
922 struct FakeCoreCtx {
923 arp_state: ArpState<EthernetLinkDevice, FakeBindingsCtx>,
924 inner: FakeInnerCtx,
925 }
926
927 fn new_context() -> CtxPair<FakeCoreCtx, FakeBindingsCtx> {
928 CtxPair::with_default_bindings_ctx(|bindings_ctx| FakeCoreCtx {
929 arp_state: ArpState::new::<_, IntoCoreTimerCtx>(
930 bindings_ctx,
931 FakeWeakDeviceId(FakeDeviceId),
932 ),
933 inner: FakeInnerCtx::with_state(FakeEthernetCtx::new(
934 TEST_ADDRS_V4.local_mac,
935 IPV6_MIN_IMPLIED_MAX_FRAME_SIZE,
936 )),
937 })
938 }
939
940 impl DeviceSocketHandler<EthernetLinkDevice, FakeBindingsCtx> for FakeCoreCtx {
941 fn handle_frame(
942 &mut self,
943 bindings_ctx: &mut FakeBindingsCtx,
944 device: &Self::DeviceId,
945 frame: Frame<&[u8]>,
946 whole_frame: &[u8],
947 ) {
948 self.inner.handle_frame(bindings_ctx, device, frame, whole_frame)
949 }
950 }
951
952 impl CounterContext<DeviceCounters> for FakeCoreCtx {
953 fn counters(&self) -> &DeviceCounters {
954 &self.inner.state.counters
955 }
956 }
957
958 impl CounterContext<DeviceCounters> for FakeInnerCtx {
959 fn counters(&self) -> &DeviceCounters {
960 &self.state.counters
961 }
962 }
963
964 impl ResourceCounterContext<FakeDeviceId, DeviceCounters> for FakeCoreCtx {
965 fn per_resource_counters<'a>(
966 &'a self,
967 &FakeDeviceId: &'a FakeDeviceId,
968 ) -> &'a DeviceCounters {
969 &self.inner.state.per_device_counters
970 }
971 }
972
973 impl ResourceCounterContext<FakeDeviceId, DeviceCounters> for FakeInnerCtx {
974 fn per_resource_counters<'a>(
975 &'a self,
976 &FakeDeviceId: &'a FakeDeviceId,
977 ) -> &'a DeviceCounters {
978 &self.state.per_device_counters
979 }
980 }
981
982 impl CounterContext<EthernetDeviceCounters> for FakeCoreCtx {
983 fn counters(&self) -> &EthernetDeviceCounters {
984 &self.inner.state.ethernet_counters
985 }
986 }
987
988 impl CounterContext<EthernetDeviceCounters> for FakeInnerCtx {
989 fn counters(&self) -> &EthernetDeviceCounters {
990 &self.state.ethernet_counters
991 }
992 }
993
994 impl DeviceSocketHandler<EthernetLinkDevice, FakeBindingsCtx> for FakeInnerCtx {
995 fn handle_frame(
996 &mut self,
997 _bindings_ctx: &mut FakeBindingsCtx,
998 _device: &Self::DeviceId,
999 _frame: Frame<&[u8]>,
1000 _whole_frame: &[u8],
1001 ) {
1002 }
1004 }
1005
1006 impl EthernetIpLinkDeviceStaticStateContext for FakeCoreCtx {
1007 fn with_static_ethernet_device_state<O, F: FnOnce(&StaticEthernetDeviceState) -> O>(
1008 &mut self,
1009 device_id: &FakeDeviceId,
1010 cb: F,
1011 ) -> O {
1012 self.inner.with_static_ethernet_device_state(device_id, cb)
1013 }
1014 }
1015
1016 impl EthernetIpLinkDeviceStaticStateContext for FakeInnerCtx {
1017 fn with_static_ethernet_device_state<O, F: FnOnce(&StaticEthernetDeviceState) -> O>(
1018 &mut self,
1019 &FakeDeviceId: &FakeDeviceId,
1020 cb: F,
1021 ) -> O {
1022 cb(&self.state.static_state)
1023 }
1024 }
1025
1026 impl EthernetIpLinkDeviceDynamicStateContext<FakeBindingsCtx> for FakeCoreCtx {
1027 fn with_ethernet_state<
1028 O,
1029 F: FnOnce(&StaticEthernetDeviceState, &DynamicEthernetDeviceState) -> O,
1030 >(
1031 &mut self,
1032 device_id: &FakeDeviceId,
1033 cb: F,
1034 ) -> O {
1035 self.inner.with_ethernet_state(device_id, cb)
1036 }
1037
1038 fn with_ethernet_state_mut<
1039 O,
1040 F: FnOnce(&StaticEthernetDeviceState, &mut DynamicEthernetDeviceState) -> O,
1041 >(
1042 &mut self,
1043 device_id: &FakeDeviceId,
1044 cb: F,
1045 ) -> O {
1046 self.inner.with_ethernet_state_mut(device_id, cb)
1047 }
1048 }
1049
1050 impl EthernetIpLinkDeviceDynamicStateContext<FakeBindingsCtx> for FakeInnerCtx {
1051 fn with_ethernet_state<
1052 O,
1053 F: FnOnce(&StaticEthernetDeviceState, &DynamicEthernetDeviceState) -> O,
1054 >(
1055 &mut self,
1056 &FakeDeviceId: &FakeDeviceId,
1057 cb: F,
1058 ) -> O {
1059 let FakeEthernetCtx { static_state, dynamic_state, .. } = &self.state;
1060 cb(static_state, dynamic_state)
1061 }
1062
1063 fn with_ethernet_state_mut<
1064 O,
1065 F: FnOnce(&StaticEthernetDeviceState, &mut DynamicEthernetDeviceState) -> O,
1066 >(
1067 &mut self,
1068 &FakeDeviceId: &FakeDeviceId,
1069 cb: F,
1070 ) -> O {
1071 let FakeEthernetCtx { static_state, dynamic_state, .. } = &mut self.state;
1072 cb(static_state, dynamic_state)
1073 }
1074 }
1075
1076 impl NudHandler<Ipv6, EthernetLinkDevice, FakeBindingsCtx> for FakeCoreCtx {
1077 fn handle_neighbor_update(
1078 &mut self,
1079 _bindings_ctx: &mut FakeBindingsCtx,
1080 _device_id: &Self::DeviceId,
1081 _neighbor: SpecifiedAddr<Ipv6Addr>,
1082 _link_addr: Mac,
1083 _is_confirmation: DynamicNeighborUpdateSource,
1084 ) {
1085 unimplemented!()
1086 }
1087
1088 fn flush(&mut self, _bindings_ctx: &mut FakeBindingsCtx, _device_id: &Self::DeviceId) {
1089 unimplemented!()
1090 }
1091
1092 fn send_ip_packet_to_neighbor<S>(
1093 &mut self,
1094 _bindings_ctx: &mut FakeBindingsCtx,
1095 _device_id: &Self::DeviceId,
1096 _neighbor: SpecifiedAddr<Ipv6Addr>,
1097 _body: S,
1098 _tx_meta: FakeTxMetadata,
1099 ) -> Result<(), SendFrameError<S>> {
1100 unimplemented!()
1101 }
1102 }
1103
1104 struct FakeCoreCtxWithDeviceId<'a> {
1105 core_ctx: &'a mut FakeInnerCtx,
1106 device_id: &'a FakeDeviceId,
1107 }
1108
1109 impl<'a> DeviceIdContext<EthernetLinkDevice> for FakeCoreCtxWithDeviceId<'a> {
1110 type DeviceId = FakeDeviceId;
1111 type WeakDeviceId = FakeWeakDeviceId<FakeDeviceId>;
1112 }
1113
1114 impl<'a> ArpConfigContext for FakeCoreCtxWithDeviceId<'a> {
1115 fn with_nud_user_config<O, F: FnOnce(&NudUserConfig) -> O>(&mut self, cb: F) -> O {
1116 cb(&NudUserConfig::default())
1117 }
1118 }
1119
1120 impl UseArpFrameMetadataBlanket for FakeCoreCtx {}
1121
1122 impl ArpContext<EthernetLinkDevice, FakeBindingsCtx> for FakeCoreCtx {
1123 type ConfigCtx<'a> = FakeCoreCtxWithDeviceId<'a>;
1124
1125 type ArpSenderCtx<'a> = FakeCoreCtxWithDeviceId<'a>;
1126
1127 fn with_arp_state_mut_and_sender_ctx<
1128 O,
1129 F: FnOnce(
1130 &mut ArpState<EthernetLinkDevice, FakeBindingsCtx>,
1131 &mut Self::ArpSenderCtx<'_>,
1132 ) -> O,
1133 >(
1134 &mut self,
1135 device_id: &Self::DeviceId,
1136 cb: F,
1137 ) -> O {
1138 let Self { arp_state, inner } = self;
1139 cb(arp_state, &mut FakeCoreCtxWithDeviceId { core_ctx: inner, device_id })
1140 }
1141
1142 fn addr_on_interface(&mut self, _device_id: &Self::DeviceId, _addr: Ipv4Addr) -> bool {
1143 unimplemented!()
1144 }
1145
1146 fn get_protocol_addr(&mut self, _device_id: &Self::DeviceId) -> Option<Ipv4Addr> {
1147 unimplemented!()
1148 }
1149
1150 fn get_hardware_addr(
1151 &mut self,
1152 _bindings_ctx: &mut FakeBindingsCtx,
1153 _device_id: &Self::DeviceId,
1154 ) -> UnicastAddr<Mac> {
1155 self.inner.state.static_state.mac
1156 }
1157
1158 fn with_arp_state_mut<
1159 O,
1160 F: FnOnce(
1161 &mut ArpState<EthernetLinkDevice, FakeBindingsCtx>,
1162 &mut Self::ConfigCtx<'_>,
1163 ) -> O,
1164 >(
1165 &mut self,
1166 device_id: &Self::DeviceId,
1167 cb: F,
1168 ) -> O {
1169 let Self { arp_state, inner } = self;
1170 cb(arp_state, &mut FakeCoreCtxWithDeviceId { core_ctx: inner, device_id })
1171 }
1172
1173 fn with_arp_state<O, F: FnOnce(&ArpState<EthernetLinkDevice, FakeBindingsCtx>) -> O>(
1174 &mut self,
1175 FakeDeviceId: &Self::DeviceId,
1176 cb: F,
1177 ) -> O {
1178 cb(&mut self.arp_state)
1179 }
1180 }
1181
1182 impl UseDelegateNudContext for FakeCoreCtx {}
1183 impl DelegateNudContext<Ipv4> for FakeCoreCtx {
1184 type Delegate<T> = ArpNudCtx<T>;
1185 }
1186
1187 impl ArpConfigContext for FakeInnerCtx {
1188 fn with_nud_user_config<O, F: FnOnce(&NudUserConfig) -> O>(&mut self, cb: F) -> O {
1189 cb(&NudUserConfig::default())
1190 }
1191 }
1192
1193 impl<'a> ArpSenderContext<EthernetLinkDevice, FakeBindingsCtx> for FakeCoreCtxWithDeviceId<'a> {
1194 fn send_ip_packet_to_neighbor_link_addr<S>(
1195 &mut self,
1196 bindings_ctx: &mut FakeBindingsCtx,
1197 link_addr: Mac,
1198 body: S,
1199 tx_meta: FakeTxMetadata,
1200 ) -> Result<(), SendFrameError<S>>
1201 where
1202 S: Serializer,
1203 S::Buffer: BufferMut,
1204 {
1205 let Self { core_ctx, device_id } = self;
1206 send_as_ethernet_frame_to_dst(
1207 *core_ctx,
1208 bindings_ctx,
1209 device_id,
1210 link_addr,
1211 body,
1212 EtherType::Ipv4,
1213 tx_meta,
1214 )
1215 }
1216 }
1217
1218 impl TransmitQueueBindingsContext<FakeDeviceId> for FakeBindingsCtx {
1219 fn wake_tx_task(&mut self, FakeDeviceId: &FakeDeviceId) {
1220 unimplemented!("unused by tests")
1221 }
1222 }
1223
1224 impl TransmitQueueCommon<EthernetLinkDevice, FakeBindingsCtx> for FakeCoreCtx {
1225 type Meta = FakeTxMetadata;
1226 type Allocator = BufVecU8Allocator;
1227 type Buffer = Buf<Vec<u8>>;
1228 type DequeueContext = Never;
1229
1230 fn parse_outgoing_frame<'a>(
1231 buf: &'a [u8],
1232 meta: &'a Self::Meta,
1233 ) -> Result<SentFrame<&'a [u8]>, ParseSentFrameError> {
1234 FakeInnerCtx::parse_outgoing_frame(buf, meta)
1235 }
1236 }
1237
1238 impl TransmitQueueCommon<EthernetLinkDevice, FakeBindingsCtx> for FakeInnerCtx {
1239 type Meta = FakeTxMetadata;
1240 type Allocator = BufVecU8Allocator;
1241 type Buffer = Buf<Vec<u8>>;
1242 type DequeueContext = Never;
1243
1244 fn parse_outgoing_frame<'a, 'b>(
1245 buf: &'a [u8],
1246 _tx_meta: &'b Self::Meta,
1247 ) -> Result<SentFrame<&'a [u8]>, ParseSentFrameError> {
1248 SentFrame::try_parse_as_ethernet(buf)
1249 }
1250 }
1251
1252 impl TransmitQueueContext<EthernetLinkDevice, FakeBindingsCtx> for FakeCoreCtx {
1253 fn with_transmit_queue_mut<
1254 O,
1255 F: FnOnce(&mut TransmitQueueState<Self::Meta, Self::Buffer, Self::Allocator>) -> O,
1256 >(
1257 &mut self,
1258 device_id: &Self::DeviceId,
1259 cb: F,
1260 ) -> O {
1261 self.inner.with_transmit_queue_mut(device_id, cb)
1262 }
1263
1264 fn with_transmit_queue<
1265 O,
1266 F: FnOnce(&TransmitQueueState<Self::Meta, Self::Buffer, Self::Allocator>) -> O,
1267 >(
1268 &mut self,
1269 device_id: &Self::DeviceId,
1270 cb: F,
1271 ) -> O {
1272 self.inner.with_transmit_queue(device_id, cb)
1273 }
1274
1275 fn send_frame(
1276 &mut self,
1277 bindings_ctx: &mut FakeBindingsCtx,
1278 device_id: &Self::DeviceId,
1279 dequeue_context: Option<&mut Never>,
1280 tx_meta: Self::Meta,
1281 buf: Self::Buffer,
1282 ) -> Result<(), DeviceSendFrameError> {
1283 TransmitQueueContext::send_frame(
1284 &mut self.inner,
1285 bindings_ctx,
1286 device_id,
1287 dequeue_context,
1288 tx_meta,
1289 buf,
1290 )
1291 }
1292 }
1293
1294 impl TransmitQueueContext<EthernetLinkDevice, FakeBindingsCtx> for FakeInnerCtx {
1295 fn with_transmit_queue_mut<
1296 O,
1297 F: FnOnce(&mut TransmitQueueState<Self::Meta, Self::Buffer, Self::Allocator>) -> O,
1298 >(
1299 &mut self,
1300 _device_id: &Self::DeviceId,
1301 cb: F,
1302 ) -> O {
1303 cb(&mut self.state.tx_queue)
1304 }
1305
1306 fn with_transmit_queue<
1307 O,
1308 F: FnOnce(&TransmitQueueState<Self::Meta, Self::Buffer, Self::Allocator>) -> O,
1309 >(
1310 &mut self,
1311 _device_id: &Self::DeviceId,
1312 cb: F,
1313 ) -> O {
1314 cb(&self.state.tx_queue)
1315 }
1316
1317 fn send_frame(
1318 &mut self,
1319 _bindings_ctx: &mut FakeBindingsCtx,
1320 device_id: &Self::DeviceId,
1321 dequeue_context: Option<&mut Never>,
1322 _tx_meta: Self::Meta,
1323 buf: Self::Buffer,
1324 ) -> Result<(), DeviceSendFrameError> {
1325 match dequeue_context {
1326 Some(never) => match *never {},
1327 None => (),
1328 }
1329 self.frames.push(device_id.clone(), buf.as_ref().to_vec());
1330 Ok(())
1331 }
1332 }
1333
1334 impl DeviceIdContext<EthernetLinkDevice> for FakeCoreCtx {
1335 type DeviceId = FakeDeviceId;
1336 type WeakDeviceId = FakeWeakDeviceId<FakeDeviceId>;
1337 }
1338
1339 impl DeviceIdContext<EthernetLinkDevice> for FakeInnerCtx {
1340 type DeviceId = FakeDeviceId;
1341 type WeakDeviceId = FakeWeakDeviceId<FakeDeviceId>;
1342 }
1343
1344 impl CounterContext<ArpCounters> for FakeCoreCtx {
1345 fn counters(&self) -> &ArpCounters {
1346 &self.inner.state.arp_counters
1347 }
1348 }
1349
1350 #[test]
1351 fn test_mtu() {
1352 fn test(size: usize, expect_frames_sent: bool) {
1356 let mut ctx = new_context();
1357 NeighborApi::<Ipv4, EthernetLinkDevice, _>::new(ctx.as_mut())
1358 .insert_static_entry(
1359 &FakeDeviceId,
1360 TEST_ADDRS_V4.remote_ip.get(),
1361 TEST_ADDRS_V4.remote_mac.get(),
1362 )
1363 .unwrap();
1364 let CtxPair { core_ctx, bindings_ctx } = &mut ctx;
1365 let result = send_ip_frame(
1366 core_ctx,
1367 bindings_ctx,
1368 &FakeDeviceId,
1369 IpPacketDestination::<Ipv4, _>::Neighbor(TEST_ADDRS_V4.remote_ip),
1370 Buf::new(&mut vec![0; size], ..),
1371 FakeTxMetadata::default(),
1372 )
1373 .map_err(|_serializer| ());
1374 let sent_frames = core_ctx.inner.frames().len();
1375 if expect_frames_sent {
1376 assert_eq!(sent_frames, 1);
1377 result.expect("should succeed");
1378 } else {
1379 assert_eq!(sent_frames, 0);
1380 result.expect_err("should fail");
1381 }
1382 }
1383
1384 test(usize::try_from(u32::from(Ipv6::MINIMUM_LINK_MTU)).unwrap(), true);
1385 test(usize::try_from(u32::from(Ipv6::MINIMUM_LINK_MTU)).unwrap() + 1, false);
1386 }
1387
1388 #[test]
1389 fn broadcast() {
1390 let mut ctx = new_context();
1391 let CtxPair { core_ctx, bindings_ctx } = &mut ctx;
1392 send_ip_frame(
1393 core_ctx,
1394 bindings_ctx,
1395 &FakeDeviceId,
1396 IpPacketDestination::<Ipv4, _>::Broadcast(()),
1397 Buf::new(&mut vec![0; 100], ..),
1398 FakeTxMetadata::default(),
1399 )
1400 .map_err(|_serializer| ())
1401 .expect("send_ip_frame should succeed");
1402 let sent_frames = core_ctx.inner.frames().len();
1403 assert_eq!(sent_frames, 1);
1404 let (FakeDeviceId, frame) = core_ctx.inner.frames()[0].clone();
1405 let (_body, _src_mac, dst_mac, _ether_type) =
1406 parse_ethernet_frame(&frame, EthernetFrameLengthCheck::NoCheck).unwrap();
1407 assert_eq!(dst_mac, Mac::BROADCAST);
1408 }
1409}