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