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