1use core::fmt::Debug;
8use core::hash::Hash;
9use core::num::NonZeroU16;
10
11use derivative::Derivative;
12use lock_order::lock::{OrderedLockAccess, OrderedLockRef};
13use net_types::ethernet::Mac;
14use net_types::ip::IpVersion;
15use netstack3_base::socket::SocketCookie;
16use netstack3_base::sync::{Mutex, PrimaryRc, RwLock, StrongRc, WeakRc};
17use netstack3_base::{
18 AnyDevice, ContextPair, Counter, Device, DeviceIdContext, FrameDestination, GsoInfo,
19 Inspectable, Inspector, InspectorDeviceExt, InspectorExt, NetworkSerializer, PacketType,
20 ReferenceNotifiers, ReferenceNotifiersExt as _, RemoveResourceResultWithContext,
21 ResourceCounterContext, SendFrameContext, SendFrameErrorReason, StrongDeviceIdentifier,
22 TxMetadataBindingsTypes, WeakDeviceIdentifier as _,
23};
24use netstack3_hashmap::{HashMap, HashSet};
25use netstack3_ip::DeviceIpLayerMetadata;
26use packet::{BufferMut, ParsablePacket as _};
27use packet_formats::error::ParseError;
28use packet_formats::ethernet::{EtherType, EthernetFrameLengthCheck};
29
30use crate::internal::base::DeviceLayerTypes;
31use crate::internal::id::WeakDeviceId;
32
33#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
35pub enum Protocol {
36 All,
38 Specific(NonZeroU16),
40}
41
42#[derive(Clone, Debug, Derivative, Eq, Hash, PartialEq)]
44#[derivative(Default(bound = ""))]
45pub enum TargetDevice<D> {
46 #[derivative(Default)]
48 AnyDevice,
49 SpecificDevice(D),
51}
52
53#[derive(Debug)]
55#[cfg_attr(test, derive(PartialEq))]
56pub struct SocketInfo<D> {
57 pub protocol: Option<Protocol>,
59 pub device: TargetDevice<D>,
61}
62
63pub trait DeviceSocketTypes {
66 type SocketState<D: Send + Sync + Debug>: Send + Sync + Debug;
68}
69
70pub enum ReceiveFrameError {
72 QueueFull,
74}
75
76pub trait DeviceSocketBindingsContext<DeviceId: StrongDeviceIdentifier>:
78 DeviceSocketTypes + Sized
79{
80 fn receive_frame(
84 &self,
85 socket_id: &DeviceSocketId<DeviceId::Weak, Self>,
86 device: &DeviceId,
87 frame: Frame<&[u8]>,
88 raw_frame: &[u8],
89 ) -> Result<(), ReceiveFrameError>;
90}
91
92#[derive(Debug)]
96pub struct PrimaryDeviceSocketId<D: Send + Sync + Debug, BT: DeviceSocketTypes>(
97 PrimaryRc<SocketState<D, BT>>,
98);
99
100impl<D: Send + Sync + Debug, BT: DeviceSocketTypes> PrimaryDeviceSocketId<D, BT> {
101 fn new(external_state: BT::SocketState<D>) -> Self {
103 Self(PrimaryRc::new(SocketState {
104 external_state,
105 counters: Default::default(),
106 target: Default::default(),
107 }))
108 }
109
110 fn clone_strong(&self) -> DeviceSocketId<D, BT> {
112 let PrimaryDeviceSocketId(rc) = self;
113 DeviceSocketId(PrimaryRc::clone_strong(rc))
114 }
115}
116
117#[derive(Derivative)]
122#[derivative(Clone(bound = ""), Hash(bound = ""), Eq(bound = ""), PartialEq(bound = ""))]
123pub struct DeviceSocketId<D: Send + Sync + Debug, BT: DeviceSocketTypes>(
124 StrongRc<SocketState<D, BT>>,
125);
126
127impl<D: Send + Sync + Debug, BT: DeviceSocketTypes> DeviceSocketId<D, BT> {
128 pub fn socket_cookie(&self) -> SocketCookie {
130 let Self(rc) = self;
131 SocketCookie::new(rc.resource_token())
132 }
133}
134
135impl<D: Send + Sync + Debug, BT: DeviceSocketTypes> Debug for DeviceSocketId<D, BT> {
136 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
137 let Self(rc) = self;
138 f.debug_tuple("DeviceSocketId").field(&StrongRc::debug_id(rc)).finish()
139 }
140}
141
142impl<D: Send + Sync + Debug, BT: DeviceSocketTypes> OrderedLockAccess<Target<D>>
143 for DeviceSocketId<D, BT>
144{
145 type Lock = Mutex<Target<D>>;
146 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
147 let Self(rc) = self;
148 OrderedLockRef::new(&rc.target)
149 }
150}
151
152#[derive(Derivative)]
157#[derivative(Clone(bound = ""), Hash(bound = ""), Eq(bound = ""), PartialEq(bound = ""))]
158pub struct WeakDeviceSocketId<D: Send + Sync + Debug, BT: DeviceSocketTypes>(
159 WeakRc<SocketState<D, BT>>,
160);
161
162impl<D: Send + Sync + Debug, BT: DeviceSocketTypes> Debug for WeakDeviceSocketId<D, BT> {
163 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
164 let Self(rc) = self;
165 f.debug_tuple("WeakDeviceSocketId").field(&WeakRc::debug_id(rc)).finish()
166 }
167}
168
169#[derive(Derivative)]
171#[derivative(Default(bound = ""))]
172pub struct Sockets<D: Send + Sync + Debug, BT: DeviceSocketTypes> {
173 any_device_sockets: RwLock<AnyDeviceSockets<D, BT>>,
176
177 all_sockets: RwLock<AllSockets<D, BT>>,
184}
185
186#[derive(Derivative)]
188#[derivative(Default(bound = ""))]
189pub struct AnyDeviceSockets<D: Send + Sync + Debug, BT: DeviceSocketTypes>(
190 HashSet<DeviceSocketId<D, BT>>,
191);
192
193#[derive(Derivative)]
195#[derivative(Default(bound = ""))]
196pub struct AllSockets<D: Send + Sync + Debug, BT: DeviceSocketTypes>(
197 HashMap<DeviceSocketId<D, BT>, PrimaryDeviceSocketId<D, BT>>,
198);
199
200#[derive(Debug)]
202pub struct SocketState<D: Send + Sync + Debug, BT: DeviceSocketTypes> {
203 pub external_state: BT::SocketState<D>,
205 target: Mutex<Target<D>>,
209 counters: DeviceSocketCounters,
211}
212
213#[derive(Debug, Derivative)]
215#[derivative(Default(bound = ""))]
216pub struct Target<D> {
217 protocol: Option<Protocol>,
218 device: TargetDevice<D>,
219}
220
221#[derive(Derivative)]
226#[derivative(Default(bound = ""))]
227#[cfg_attr(
228 test,
229 derivative(Debug, PartialEq(bound = "BT::SocketState<D>: Hash + Eq, D: Hash + Eq"))
230)]
231pub struct DeviceSockets<D: Send + Sync + Debug, BT: DeviceSocketTypes>(
232 HashSet<DeviceSocketId<D, BT>>,
233);
234
235pub type HeldDeviceSockets<BT> = DeviceSockets<WeakDeviceId<BT>, BT>;
237
238pub type HeldSockets<BT> = Sockets<WeakDeviceId<BT>, BT>;
242
243pub trait DeviceSocketContext<BT: DeviceSocketTypes>: DeviceIdContext<AnyDevice> {
245 type SocketTablesCoreCtx<'a>: DeviceSocketAccessor<BT, DeviceId = Self::DeviceId, WeakDeviceId = Self::WeakDeviceId>;
247
248 fn with_all_device_sockets<
251 F: FnOnce(&AllSockets<Self::WeakDeviceId, BT>, &mut Self::SocketTablesCoreCtx<'_>) -> R,
252 R,
253 >(
254 &mut self,
255 cb: F,
256 ) -> R;
257
258 fn with_all_device_sockets_mut<F: FnOnce(&mut AllSockets<Self::WeakDeviceId, BT>) -> R, R>(
261 &mut self,
262 cb: F,
263 ) -> R;
264
265 fn with_any_device_sockets<
267 F: FnOnce(&AnyDeviceSockets<Self::WeakDeviceId, BT>, &mut Self::SocketTablesCoreCtx<'_>) -> R,
268 R,
269 >(
270 &mut self,
271 cb: F,
272 ) -> R;
273
274 fn with_any_device_sockets_mut<
276 F: FnOnce(
277 &mut AnyDeviceSockets<Self::WeakDeviceId, BT>,
278 &mut Self::SocketTablesCoreCtx<'_>,
279 ) -> R,
280 R,
281 >(
282 &mut self,
283 cb: F,
284 ) -> R;
285}
286
287pub trait SocketStateAccessor<BT: DeviceSocketTypes>: DeviceIdContext<AnyDevice> {
289 fn with_socket_state<F: FnOnce(&Target<Self::WeakDeviceId>) -> R, R>(
291 &mut self,
292 socket: &DeviceSocketId<Self::WeakDeviceId, BT>,
293 cb: F,
294 ) -> R;
295
296 fn with_socket_state_mut<F: FnOnce(&mut Target<Self::WeakDeviceId>) -> R, R>(
298 &mut self,
299 socket: &DeviceSocketId<Self::WeakDeviceId, BT>,
300 cb: F,
301 ) -> R;
302}
303
304pub trait DeviceSocketAccessor<BT: DeviceSocketTypes>: SocketStateAccessor<BT> {
306 type DeviceSocketCoreCtx<'a>: SocketStateAccessor<BT, DeviceId = Self::DeviceId, WeakDeviceId = Self::WeakDeviceId>
308 + ResourceCounterContext<DeviceSocketId<Self::WeakDeviceId, BT>, DeviceSocketCounters>;
309
310 fn with_device_sockets<
313 F: FnOnce(&DeviceSockets<Self::WeakDeviceId, BT>, &mut Self::DeviceSocketCoreCtx<'_>) -> R,
314 R,
315 >(
316 &mut self,
317 device: &Self::DeviceId,
318 cb: F,
319 ) -> R;
320
321 fn with_device_sockets_mut<
324 F: FnOnce(&mut DeviceSockets<Self::WeakDeviceId, BT>, &mut Self::DeviceSocketCoreCtx<'_>) -> R,
325 R,
326 >(
327 &mut self,
328 device: &Self::DeviceId,
329 cb: F,
330 ) -> R;
331}
332
333enum MaybeUpdate<T> {
334 NoChange,
335 NewValue(T),
336}
337
338fn update_device_and_protocol<CC: DeviceSocketContext<BT>, BT: DeviceSocketTypes>(
339 core_ctx: &mut CC,
340 socket: &DeviceSocketId<CC::WeakDeviceId, BT>,
341 new_device: TargetDevice<&CC::DeviceId>,
342 protocol_update: MaybeUpdate<Protocol>,
343) {
344 core_ctx.with_any_device_sockets_mut(|AnyDeviceSockets(any_device_sockets), core_ctx| {
345 let old_device = core_ctx.with_socket_state_mut(socket, |Target { protocol, device }| {
351 match protocol_update {
352 MaybeUpdate::NewValue(p) => *protocol = Some(p),
353 MaybeUpdate::NoChange => (),
354 };
355 let old_device = match &device {
356 TargetDevice::SpecificDevice(device) => device.upgrade(),
357 TargetDevice::AnyDevice => {
358 assert!(any_device_sockets.remove(socket));
359 None
360 }
361 };
362 *device = match &new_device {
363 TargetDevice::AnyDevice => TargetDevice::AnyDevice,
364 TargetDevice::SpecificDevice(d) => TargetDevice::SpecificDevice(d.downgrade()),
365 };
366 old_device
367 });
368
369 if let Some(device) = old_device {
375 core_ctx.with_device_sockets_mut(
378 &device,
379 |DeviceSockets(device_sockets), _core_ctx| {
380 assert!(device_sockets.remove(socket), "socket not found in device state");
381 },
382 );
383 }
384
385 match &new_device {
387 TargetDevice::SpecificDevice(new_device) => core_ctx.with_device_sockets_mut(
388 new_device,
389 |DeviceSockets(device_sockets), _core_ctx| {
390 assert!(device_sockets.insert(socket.clone()));
391 },
392 ),
393 TargetDevice::AnyDevice => {
394 assert!(any_device_sockets.insert(socket.clone()))
395 }
396 }
397 })
398}
399
400pub struct DeviceSocketApi<C>(C);
402
403impl<C> DeviceSocketApi<C> {
404 pub fn new(ctx: C) -> Self {
406 Self(ctx)
407 }
408}
409
410type ApiSocketId<C> = DeviceSocketId<
415 <<C as ContextPair>::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId,
416 <C as ContextPair>::BindingsContext,
417>;
418
419impl<C> DeviceSocketApi<C>
420where
421 C: ContextPair,
422 C::CoreContext: DeviceSocketContext<C::BindingsContext>
423 + SocketStateAccessor<C::BindingsContext>
424 + ResourceCounterContext<ApiSocketId<C>, DeviceSocketCounters>,
425 C::BindingsContext: DeviceSocketBindingsContext<<C::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId>
426 + ReferenceNotifiers
427 + 'static,
428{
429 fn core_ctx(&mut self) -> &mut C::CoreContext {
430 let Self(pair) = self;
431 pair.core_ctx()
432 }
433
434 fn contexts(&mut self) -> (&mut C::CoreContext, &mut C::BindingsContext) {
435 let Self(pair) = self;
436 pair.contexts()
437 }
438
439 pub fn create(
441 &mut self,
442 external_state: <C::BindingsContext as DeviceSocketTypes>::SocketState<
443 <C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId,
444 >,
445 ) -> ApiSocketId<C> {
446 let core_ctx = self.core_ctx();
447
448 let strong = core_ctx.with_all_device_sockets_mut(|AllSockets(sockets)| {
449 let primary = PrimaryDeviceSocketId::new(external_state);
450 let strong = primary.clone_strong();
451 assert!(sockets.insert(strong.clone(), primary).is_none());
452 strong
453 });
454 core_ctx.with_any_device_sockets_mut(|AnyDeviceSockets(any_device_sockets), _core_ctx| {
455 assert!(any_device_sockets.insert(strong.clone()));
462 });
463 strong
464 }
465
466 pub fn set_device(
468 &mut self,
469 socket: &ApiSocketId<C>,
470 device: TargetDevice<&<C::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId>,
471 ) {
472 update_device_and_protocol(self.core_ctx(), socket, device, MaybeUpdate::NoChange)
473 }
474
475 pub fn set_device_and_protocol(
477 &mut self,
478 socket: &ApiSocketId<C>,
479 device: TargetDevice<&<C::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId>,
480 protocol: Protocol,
481 ) {
482 update_device_and_protocol(self.core_ctx(), socket, device, MaybeUpdate::NewValue(protocol))
483 }
484
485 pub fn get_info(
487 &mut self,
488 id: &ApiSocketId<C>,
489 ) -> SocketInfo<<C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId> {
490 self.core_ctx().with_socket_state(id, |Target { device, protocol }| SocketInfo {
491 device: device.clone(),
492 protocol: *protocol,
493 })
494 }
495
496 pub fn remove(
498 &mut self,
499 id: ApiSocketId<C>,
500 ) -> RemoveResourceResultWithContext<
501 <C::BindingsContext as DeviceSocketTypes>::SocketState<
502 <C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId,
503 >,
504 C::BindingsContext,
505 > {
506 let core_ctx = self.core_ctx();
507 core_ctx.with_any_device_sockets_mut(|AnyDeviceSockets(any_device_sockets), core_ctx| {
508 let old_device = core_ctx.with_socket_state_mut(&id, |target| {
509 let Target { device, protocol: _ } = target;
510 match &device {
511 TargetDevice::SpecificDevice(device) => device.upgrade(),
512 TargetDevice::AnyDevice => {
513 assert!(any_device_sockets.remove(&id));
514 None
515 }
516 }
517 });
518 if let Some(device) = old_device {
519 core_ctx.with_device_sockets_mut(
520 &device,
521 |DeviceSockets(device_sockets), _core_ctx| {
522 assert!(device_sockets.remove(&id), "device doesn't have socket");
523 },
524 )
525 }
526 });
527
528 core_ctx.with_all_device_sockets_mut(|AllSockets(sockets)| {
529 let primary = sockets
530 .remove(&id)
531 .unwrap_or_else(|| panic!("{id:?} not present in all socket map"));
532 drop(id);
535
536 let PrimaryDeviceSocketId(primary) = primary;
537 C::BindingsContext::unwrap_or_notify_with_new_reference_notifier(
538 primary,
539 |SocketState { external_state, counters: _, target: _ }| external_state,
540 )
541 })
542 }
543
544 pub fn send_frame<S, D>(
546 &mut self,
547 id: &ApiSocketId<C>,
548 metadata: DeviceSocketMetadata<D, C::CoreContext, C::BindingsContext>,
549 body: S,
550 ) -> Result<(), SendFrameErrorReason>
551 where
552 S: NetworkSerializer,
553 S::Buffer: BufferMut,
554 D: DeviceSocketSendTypes,
555 C::CoreContext: DeviceIdContext<D>
556 + SendFrameContext<
557 C::BindingsContext,
558 DeviceSocketMetadata<D, C::CoreContext, C::BindingsContext>,
559 >,
560 C::BindingsContext: DeviceLayerTypes,
561 {
562 let (core_ctx, bindings_ctx) = self.contexts();
563 let result = core_ctx.send_frame(bindings_ctx, metadata, body).map_err(|e| e.into_err());
564 match &result {
565 Ok(()) => {
566 core_ctx.increment_both(id, |counters: &DeviceSocketCounters| &counters.tx_frames)
567 }
568 Err(SendFrameErrorReason::QueueFull) => core_ctx
569 .increment_both(id, |counters: &DeviceSocketCounters| &counters.tx_err_queue_full),
570 Err(SendFrameErrorReason::Alloc) => core_ctx
571 .increment_both(id, |counters: &DeviceSocketCounters| &counters.tx_err_alloc),
572 Err(SendFrameErrorReason::SizeConstraintsViolation) => core_ctx
573 .increment_both(id, |counters: &DeviceSocketCounters| {
574 &counters.tx_err_size_constraint
575 }),
576 Err(SendFrameErrorReason::AddressResolutionFailed) => {
577 unreachable!("device socket send should not perform link-layer address resolution");
578 }
579 }
580 result
581 }
582
583 pub fn inspect<N>(&mut self, inspector: &mut N)
585 where
586 N: Inspector
587 + InspectorDeviceExt<<C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId>,
588 {
589 self.core_ctx().with_all_device_sockets(|AllSockets(sockets), core_ctx| {
590 sockets.keys().for_each(|socket| {
591 inspector.record_debug_child(socket, |node| {
592 core_ctx.with_socket_state(socket, |Target { protocol, device }| {
593 node.record_debug("Protocol", protocol);
594 match device {
595 TargetDevice::AnyDevice => node.record_str("Device", "Any"),
596 TargetDevice::SpecificDevice(d) => N::record_device(node, "Device", d),
597 }
598 });
599 node.record_child("Counters", |node| {
600 node.delegate_inspectable(socket.counters())
601 })
602 })
603 })
604 })
605 }
606}
607
608pub trait DeviceSocketSendTypes: Device {
610 type Metadata;
612}
613
614#[derive(Derivative)]
616#[derivative(Debug(bound = "D::Metadata: Debug"))]
617pub struct DeviceSocketMetadata<D, C, BT>
618where
619 D: DeviceSocketSendTypes,
620 C: DeviceIdContext<D>,
621 BT: TxMetadataBindingsTypes,
622{
623 pub device_id: C::DeviceId,
625 pub metadata: D::Metadata,
627 pub ip_layer_metadata: DeviceIpLayerMetadata<BT>,
630}
631
632#[derive(Debug, PartialEq)]
634pub struct EthernetHeaderParams {
635 pub dest_addr: Mac,
637 pub protocol: EtherType,
639}
640
641pub type SocketId<BC> = DeviceSocketId<WeakDeviceId<BC>, BC>;
646
647impl<D: Send + Sync + Debug, BT: DeviceSocketTypes> DeviceSocketId<D, BT> {
648 pub fn socket_state(&self) -> &BT::SocketState<D> {
651 let Self(strong) = self;
652 let SocketState { external_state, counters: _, target: _ } = &**strong;
653 external_state
654 }
655
656 pub fn downgrade(&self) -> WeakDeviceSocketId<D, BT> {
658 let Self(inner) = self;
659 WeakDeviceSocketId(StrongRc::downgrade(inner))
660 }
661
662 pub fn counters(&self) -> &DeviceSocketCounters {
664 let Self(strong) = self;
665 let SocketState { external_state: _, counters, target: _ } = &**strong;
666 counters
667 }
668}
669
670pub trait DeviceSocketHandler<D: Device, BC>: DeviceIdContext<D> {
675 fn handle_frame(
677 &mut self,
678 bindings_ctx: &mut BC,
679 device: &Self::DeviceId,
680 frame: Frame<&[u8]>,
681 whole_frame: &[u8],
682 );
683}
684
685#[derive(Clone, Copy, Debug, Eq, PartialEq)]
687pub enum ReceivedFrame<B> {
688 Ethernet {
690 destination: FrameDestination,
692 frame: EthernetFrame<B>,
694 packet_type: PacketType,
696 gso_info: Option<GsoInfo>,
698 },
699 Ip {
704 frame: IpFrame<B>,
706 gso_info: Option<GsoInfo>,
708 },
709}
710
711#[derive(Clone, Copy, Debug, Eq, PartialEq)]
713pub enum SentFrame<B> {
714 Ethernet(EthernetFrame<B>),
716 Ip(IpFrame<B>),
721}
722
723#[derive(Debug)]
725pub struct ParseSentFrameError;
726
727impl SentFrame<&[u8]> {
728 pub fn try_parse_as_ethernet(mut buf: &[u8]) -> Result<SentFrame<&[u8]>, ParseSentFrameError> {
730 packet_formats::ethernet::EthernetFrame::parse(&mut buf, EthernetFrameLengthCheck::NoCheck)
731 .map_err(|_: ParseError| ParseSentFrameError)
732 .map(|frame| SentFrame::Ethernet(frame.into()))
733 }
734}
735
736#[derive(Clone, Copy, Debug, Eq, PartialEq)]
738pub struct EthernetFrame<B> {
739 pub src_mac: Mac,
741 pub dst_mac: Mac,
743 pub ethertype: Option<EtherType>,
745 pub body_offset: usize,
747 pub body: B,
749}
750
751#[derive(Clone, Copy, Debug, Eq, PartialEq)]
753pub struct IpFrame<B> {
754 pub ip_version: IpVersion,
756 pub body: B,
758}
759
760impl<B> IpFrame<B> {
761 fn ethertype(&self) -> EtherType {
762 let IpFrame { ip_version, body: _ } = self;
763 EtherType::from_ip_version(*ip_version)
764 }
765}
766
767pub const PURE_IP_PACKET_TYPE: PacketType = PacketType::Host;
770
771#[derive(Clone, Copy, Debug, Eq, PartialEq)]
773pub enum Frame<B> {
774 Sent(SentFrame<B>),
776 Received(ReceivedFrame<B>),
778}
779
780impl<B> From<SentFrame<B>> for Frame<B> {
781 fn from(value: SentFrame<B>) -> Self {
782 Self::Sent(value)
783 }
784}
785
786impl<B> From<ReceivedFrame<B>> for Frame<B> {
787 fn from(value: ReceivedFrame<B>) -> Self {
788 Self::Received(value)
789 }
790}
791
792impl<'a> From<packet_formats::ethernet::EthernetFrame<&'a [u8]>> for EthernetFrame<&'a [u8]> {
793 fn from(frame: packet_formats::ethernet::EthernetFrame<&'a [u8]>) -> Self {
794 Self {
795 src_mac: frame.src_mac(),
796 dst_mac: frame.dst_mac(),
797 ethertype: frame.ethertype(),
798 body_offset: frame.parse_metadata().header_len(),
799 body: frame.into_body(),
800 }
801 }
802}
803
804impl<'a> ReceivedFrame<&'a [u8]> {
805 pub(crate) fn from_ethernet(
806 frame: packet_formats::ethernet::EthernetFrame<&'a [u8]>,
807 destination: FrameDestination,
808 packet_type: PacketType,
809 gso_info: Option<GsoInfo>,
810 ) -> Self {
811 Self::Ethernet { destination, frame: frame.into(), packet_type, gso_info }
812 }
813}
814
815impl<B> Frame<B> {
816 pub fn packet_type(&self) -> PacketType {
818 match self {
819 Self::Sent(_) => PacketType::Outgoing,
820 Self::Received(ReceivedFrame::Ethernet {
821 destination: _,
822 frame: _,
823 packet_type,
824 gso_info: _,
825 }) => *packet_type,
826 Self::Received(ReceivedFrame::Ip { frame: _, gso_info: _ }) => PURE_IP_PACKET_TYPE,
827 }
828 }
829
830 pub fn protocol(&self) -> Option<u16> {
832 let ethertype = match self {
833 Self::Sent(SentFrame::Ethernet(frame))
834 | Self::Received(ReceivedFrame::Ethernet {
835 destination: _,
836 frame,
837 packet_type: _,
838 gso_info: _,
839 }) => frame.ethertype,
840 Self::Sent(SentFrame::Ip(frame))
841 | Self::Received(ReceivedFrame::Ip { frame, gso_info: _ }) => Some(frame.ethertype()),
842 };
843 ethertype.map(Into::into)
844 }
845
846 pub fn gso_info(&self) -> Option<GsoInfo> {
848 match self {
849 Self::Sent(_) => None,
850 Self::Received(ReceivedFrame::Ethernet {
851 destination: _,
852 frame: _,
853 packet_type: _,
854 gso_info,
855 })
856 | Self::Received(ReceivedFrame::Ip { frame: _, gso_info }) => *gso_info,
857 }
858 }
859
860 pub fn into_body(self) -> B {
862 match self {
863 Self::Received(ReceivedFrame::Ethernet {
864 destination: _,
865 frame,
866 packet_type: _,
867 gso_info: _,
868 })
869 | Self::Sent(SentFrame::Ethernet(frame)) => frame.body,
870 Self::Received(ReceivedFrame::Ip { frame, gso_info: _ })
871 | Self::Sent(SentFrame::Ip(frame)) => frame.body,
872 }
873 }
874
875 pub fn body_offset(&self) -> usize {
877 match self {
878 Self::Received(ReceivedFrame::Ethernet {
879 destination: _,
880 frame,
881 packet_type: _,
882 gso_info: _,
883 })
884 | Self::Sent(SentFrame::Ethernet(frame)) => frame.body_offset,
885 Self::Received(ReceivedFrame::Ip { frame: _, gso_info: _ })
886 | Self::Sent(SentFrame::Ip(_)) => 0,
887 }
888 }
889}
890
891impl<
892 D: Device,
893 BC: DeviceSocketBindingsContext<<CC as DeviceIdContext<AnyDevice>>::DeviceId>,
894 CC: DeviceSocketContext<BC> + DeviceIdContext<D>,
895> DeviceSocketHandler<D, BC> for CC
896where
897 <CC as DeviceIdContext<D>>::DeviceId: Into<<CC as DeviceIdContext<AnyDevice>>::DeviceId>,
898{
899 fn handle_frame(
900 &mut self,
901 bindings_ctx: &mut BC,
902 device: &Self::DeviceId,
903 frame: Frame<&[u8]>,
904 whole_frame: &[u8],
905 ) {
906 let device = device.clone().into();
907
908 self.with_any_device_sockets(|AnyDeviceSockets(any_device_sockets), core_ctx| {
912 core_ctx.with_device_sockets(&device, |DeviceSockets(device_sockets), core_ctx| {
927 for socket in any_device_sockets.iter().chain(device_sockets) {
928 let delivered =
929 core_ctx.with_socket_state(socket, |Target { protocol, device: _ }| {
930 let should_deliver = match protocol {
931 None => false,
932 Some(p) => match p {
933 Protocol::Specific(p) => match frame {
937 Frame::Received(_) => Some(p.get()) == frame.protocol(),
938 Frame::Sent(_) => false,
939 },
940 Protocol::All => true,
941 },
942 };
943 should_deliver.then(|| {
944 bindings_ctx.receive_frame(socket, &device, frame, whole_frame)
945 })
946 });
947 match delivered {
948 None => {}
949 Some(result) => {
950 core_ctx.increment_both(socket, |counters: &DeviceSocketCounters| {
951 &counters.rx_frames
952 });
953 match result {
954 Ok(()) => {}
955 Err(ReceiveFrameError::QueueFull) => {
956 core_ctx.increment_both(
957 socket,
958 |counters: &DeviceSocketCounters| &counters.rx_queue_full,
959 );
960 }
961 }
962 }
963 }
964 }
965 })
966 })
967 }
968}
969
970#[derive(Debug, Default)]
974pub struct DeviceSocketCounters {
975 rx_frames: Counter,
981 rx_queue_full: Counter,
984 tx_frames: Counter,
986 tx_err_queue_full: Counter,
988 tx_err_alloc: Counter,
990 tx_err_size_constraint: Counter,
992}
993
994impl Inspectable for DeviceSocketCounters {
995 fn record<I: Inspector>(&self, inspector: &mut I) {
996 let Self {
997 rx_frames,
998 rx_queue_full,
999 tx_frames,
1000 tx_err_queue_full,
1001 tx_err_alloc,
1002 tx_err_size_constraint,
1003 } = self;
1004 inspector.record_child("Rx", |inspector| {
1005 inspector.record_counter("DeliveredFrames", rx_frames);
1006 inspector.record_counter("DroppedQueueFull", rx_queue_full);
1007 });
1008 inspector.record_child("Tx", |inspector| {
1009 inspector.record_counter("SentFrames", tx_frames);
1010 inspector.record_counter("QueueFullError", tx_err_queue_full);
1011 inspector.record_counter("AllocError", tx_err_alloc);
1012 inspector.record_counter("SizeConstraintError", tx_err_size_constraint);
1013 });
1014 }
1015}
1016
1017impl<D: Send + Sync + Debug, BT: DeviceSocketTypes> OrderedLockAccess<AnyDeviceSockets<D, BT>>
1018 for Sockets<D, BT>
1019{
1020 type Lock = RwLock<AnyDeviceSockets<D, BT>>;
1021 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
1022 OrderedLockRef::new(&self.any_device_sockets)
1023 }
1024}
1025
1026impl<D: Send + Sync + Debug, BT: DeviceSocketTypes> OrderedLockAccess<AllSockets<D, BT>>
1027 for Sockets<D, BT>
1028{
1029 type Lock = RwLock<AllSockets<D, BT>>;
1030 fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
1031 OrderedLockRef::new(&self.all_sockets)
1032 }
1033}
1034
1035#[cfg(any(test, feature = "testutils"))]
1036mod testutil {
1037 use alloc::vec::Vec;
1038 use core::num::NonZeroU64;
1039 use core::ops::DerefMut;
1040 use netstack3_base::StrongDeviceIdentifier;
1041 use netstack3_base::testutil::{FakeBindingsCtx, MonotonicIdentifier};
1042
1043 use super::*;
1044 use crate::internal::base::{
1045 DeviceClassMatcher, DeviceIdAndNameMatcher, DeviceLayerStateTypes,
1046 };
1047
1048 #[derive(Derivative, Debug)]
1049 #[derivative(Default(bound = ""))]
1050 pub struct RxQueue<D> {
1051 pub frames: Vec<ReceivedFrame<D>>,
1052 #[derivative(Default(value = "usize::MAX"))]
1053 pub max_size: usize,
1054 }
1055
1056 #[derive(Clone, Debug, PartialEq)]
1057 pub struct ReceivedFrame<D> {
1058 pub device: D,
1059 pub frame: Frame<Vec<u8>>,
1060 pub raw: Vec<u8>,
1061 }
1062
1063 #[derive(Debug, Derivative)]
1064 #[derivative(Default(bound = ""))]
1065 pub struct ExternalSocketState<D>(pub Mutex<RxQueue<D>>);
1066
1067 impl<TimerId, Event: Debug, State> DeviceSocketTypes
1068 for FakeBindingsCtx<TimerId, Event, State, ()>
1069 {
1070 type SocketState<D: Send + Sync + Debug> = ExternalSocketState<D>;
1071 }
1072
1073 impl Frame<&[u8]> {
1074 pub(crate) fn cloned(self) -> Frame<Vec<u8>> {
1075 match self {
1076 Self::Sent(SentFrame::Ethernet(frame)) => {
1077 Frame::Sent(SentFrame::Ethernet(frame.cloned()))
1078 }
1079 Self::Received(super::ReceivedFrame::Ethernet {
1080 destination,
1081 frame,
1082 packet_type,
1083 gso_info,
1084 }) => Frame::Received(super::ReceivedFrame::Ethernet {
1085 destination,
1086 frame: frame.cloned(),
1087 packet_type,
1088 gso_info,
1089 }),
1090 Self::Sent(SentFrame::Ip(frame)) => Frame::Sent(SentFrame::Ip(frame.cloned())),
1091 Self::Received(super::ReceivedFrame::Ip { frame, gso_info }) => {
1092 Frame::Received(super::ReceivedFrame::Ip { frame: frame.cloned(), gso_info })
1093 }
1094 }
1095 }
1096 }
1097
1098 impl EthernetFrame<&[u8]> {
1099 fn cloned(self) -> EthernetFrame<Vec<u8>> {
1100 let Self { src_mac, dst_mac, ethertype, body_offset, body } = self;
1101 EthernetFrame { src_mac, dst_mac, ethertype, body_offset, body: Vec::from(body) }
1102 }
1103 }
1104
1105 impl IpFrame<&[u8]> {
1106 fn cloned(self) -> IpFrame<Vec<u8>> {
1107 let Self { ip_version, body } = self;
1108 IpFrame { ip_version, body: Vec::from(body) }
1109 }
1110 }
1111
1112 impl<TimerId, Event: Debug, State, D: StrongDeviceIdentifier> DeviceSocketBindingsContext<D>
1113 for FakeBindingsCtx<TimerId, Event, State, ()>
1114 {
1115 fn receive_frame(
1116 &self,
1117 state: &DeviceSocketId<D::Weak, Self>,
1118 device: &D,
1119 frame: Frame<&[u8]>,
1120 raw_frame: &[u8],
1121 ) -> Result<(), ReceiveFrameError> {
1122 let ExternalSocketState(queue) = state.socket_state();
1123 let mut lock_guard = queue.lock();
1124 let RxQueue { frames, max_size } = lock_guard.deref_mut();
1125 if frames.len() < *max_size {
1126 frames.push(ReceivedFrame {
1127 device: device.downgrade(),
1128 frame: frame.cloned(),
1129 raw: raw_frame.into(),
1130 });
1131 Ok(())
1132 } else {
1133 Err(ReceiveFrameError::QueueFull)
1134 }
1135 }
1136 }
1137
1138 impl<
1139 TimerId: Debug + PartialEq + Clone + Send + Sync + 'static,
1140 Event: Debug + 'static,
1141 State: 'static,
1142 > DeviceLayerStateTypes for FakeBindingsCtx<TimerId, Event, State, ()>
1143 {
1144 type EthernetDeviceState = ();
1145 type LoopbackDeviceState = ();
1146 type PureIpDeviceState = ();
1147 type BlackholeDeviceState = ();
1148 type DeviceIdentifier = MonotonicIdentifier;
1149 }
1150
1151 impl DeviceClassMatcher<()> for () {
1152 fn device_class_matches(&self, (): &()) -> bool {
1153 unimplemented!()
1154 }
1155 }
1156
1157 impl DeviceIdAndNameMatcher for MonotonicIdentifier {
1158 fn id_matches(&self, _id: &NonZeroU64) -> bool {
1159 unimplemented!()
1160 }
1161
1162 fn name_matches(&self, _name: &str) -> bool {
1163 unimplemented!()
1164 }
1165 }
1166}
1167
1168#[cfg(test)]
1169mod tests {
1170 use alloc::vec;
1171 use alloc::vec::Vec;
1172 use core::marker::PhantomData;
1173 use core::ops::Deref;
1174
1175 use crate::internal::socket::testutil::{ExternalSocketState, ReceivedFrame};
1176 use netstack3_base::testutil::{
1177 FakeReferencyDeviceId, FakeStrongDeviceId, FakeWeakDeviceId, MultipleDevicesId,
1178 };
1179 use netstack3_base::{
1180 CounterContext, CtxPair, NetworkSerializationContext, SendFrameError, SendableFrameMeta,
1181 };
1182 use netstack3_hashmap::HashMap;
1183 use packet::ParsablePacket;
1184 use test_case::test_case;
1185
1186 use super::*;
1187
1188 type FakeCoreCtx<D> = netstack3_base::testutil::FakeCoreCtx<FakeSockets<D>, (), D>;
1189 type FakeBindingsCtx = netstack3_base::testutil::FakeBindingsCtx<(), (), (), ()>;
1190 type FakeCtx<D> = CtxPair<FakeCoreCtx<D>, FakeBindingsCtx>;
1191
1192 trait DeviceSocketApiExt: ContextPair + Sized {
1195 fn device_socket_api(&mut self) -> DeviceSocketApi<&mut Self> {
1196 DeviceSocketApi::new(self)
1197 }
1198 }
1199
1200 impl<O> DeviceSocketApiExt for O where O: ContextPair + Sized {}
1201
1202 #[derive(Derivative)]
1203 #[derivative(Default(bound = ""))]
1204 struct FakeSockets<D: FakeStrongDeviceId> {
1205 any_device_sockets: AnyDeviceSockets<D::Weak, FakeBindingsCtx>,
1206 device_sockets: HashMap<D, DeviceSockets<D::Weak, FakeBindingsCtx>>,
1207 all_sockets: AllSockets<D::Weak, FakeBindingsCtx>,
1208 counters: DeviceSocketCounters,
1210 sent_frames: Vec<Vec<u8>>,
1211 }
1212
1213 pub struct FakeSocketsMutRefs<'m, AnyDevice, AllSockets, Devices, Device>(
1215 &'m mut AnyDevice,
1216 &'m mut AllSockets,
1217 &'m mut Devices,
1218 PhantomData<Device>,
1219 &'m DeviceSocketCounters,
1220 );
1221
1222 pub trait AsFakeSocketsMutRefs {
1225 type AnyDevice: 'static;
1226 type AllSockets: 'static;
1227 type Devices: 'static;
1228 type Device: 'static;
1229 fn as_sockets_ref(
1230 &mut self,
1231 ) -> FakeSocketsMutRefs<'_, Self::AnyDevice, Self::AllSockets, Self::Devices, Self::Device>;
1232 }
1233
1234 impl<D: FakeStrongDeviceId> AsFakeSocketsMutRefs for FakeCoreCtx<D> {
1235 type AnyDevice = AnyDeviceSockets<D::Weak, FakeBindingsCtx>;
1236 type AllSockets = AllSockets<D::Weak, FakeBindingsCtx>;
1237 type Devices = HashMap<D, DeviceSockets<D::Weak, FakeBindingsCtx>>;
1238 type Device = D;
1239
1240 fn as_sockets_ref(
1241 &mut self,
1242 ) -> FakeSocketsMutRefs<
1243 '_,
1244 AnyDeviceSockets<D::Weak, FakeBindingsCtx>,
1245 AllSockets<D::Weak, FakeBindingsCtx>,
1246 HashMap<D, DeviceSockets<D::Weak, FakeBindingsCtx>>,
1247 D,
1248 > {
1249 let FakeSockets {
1250 any_device_sockets,
1251 device_sockets,
1252 all_sockets,
1253 counters,
1254 sent_frames: _,
1255 } = &mut self.state;
1256 FakeSocketsMutRefs(
1257 any_device_sockets,
1258 all_sockets,
1259 device_sockets,
1260 PhantomData,
1261 counters,
1262 )
1263 }
1264 }
1265
1266 impl<'m, AnyDevice: 'static, AllSockets: 'static, Devices: 'static, Device: 'static>
1267 AsFakeSocketsMutRefs for FakeSocketsMutRefs<'m, AnyDevice, AllSockets, Devices, Device>
1268 {
1269 type AnyDevice = AnyDevice;
1270 type AllSockets = AllSockets;
1271 type Devices = Devices;
1272 type Device = Device;
1273
1274 fn as_sockets_ref(
1275 &mut self,
1276 ) -> FakeSocketsMutRefs<'_, AnyDevice, AllSockets, Devices, Device> {
1277 let Self(any_device, all_sockets, devices, PhantomData, counters) = self;
1278 FakeSocketsMutRefs(any_device, all_sockets, devices, PhantomData, counters)
1279 }
1280 }
1281
1282 impl<D: Clone> TargetDevice<&D> {
1283 fn with_weak_id(&self) -> TargetDevice<FakeWeakDeviceId<D>> {
1284 match self {
1285 TargetDevice::AnyDevice => TargetDevice::AnyDevice,
1286 TargetDevice::SpecificDevice(d) => {
1287 TargetDevice::SpecificDevice(FakeWeakDeviceId((*d).clone()))
1288 }
1289 }
1290 }
1291 }
1292
1293 impl<D: Eq + Hash + FakeStrongDeviceId> FakeSockets<D> {
1294 fn new(devices: impl IntoIterator<Item = D>) -> Self {
1295 let device_sockets =
1296 devices.into_iter().map(|d| (d, DeviceSockets::default())).collect();
1297 Self {
1298 any_device_sockets: AnyDeviceSockets::default(),
1299 device_sockets,
1300 all_sockets: Default::default(),
1301 counters: Default::default(),
1302 sent_frames: Default::default(),
1303 }
1304 }
1305 }
1306
1307 impl<
1308 'm,
1309 DeviceId: FakeStrongDeviceId,
1310 As: AsFakeSocketsMutRefs
1311 + DeviceIdContext<AnyDevice, DeviceId = DeviceId, WeakDeviceId = DeviceId::Weak>,
1312 > SocketStateAccessor<FakeBindingsCtx> for As
1313 {
1314 fn with_socket_state<F: FnOnce(&Target<Self::WeakDeviceId>) -> R, R>(
1315 &mut self,
1316 socket: &DeviceSocketId<Self::WeakDeviceId, FakeBindingsCtx>,
1317 cb: F,
1318 ) -> R {
1319 let DeviceSocketId(rc) = socket;
1320 let target = rc.target.lock();
1322 cb(&target)
1323 }
1324
1325 fn with_socket_state_mut<F: FnOnce(&mut Target<Self::WeakDeviceId>) -> R, R>(
1326 &mut self,
1327 socket: &DeviceSocketId<Self::WeakDeviceId, FakeBindingsCtx>,
1328 cb: F,
1329 ) -> R {
1330 let DeviceSocketId(rc) = socket;
1331 let mut target = rc.target.lock();
1333 cb(&mut target)
1334 }
1335 }
1336
1337 impl<
1338 'm,
1339 DeviceId: FakeStrongDeviceId,
1340 As: AsFakeSocketsMutRefs<
1341 Devices = HashMap<DeviceId, DeviceSockets<DeviceId::Weak, FakeBindingsCtx>>,
1342 > + DeviceIdContext<AnyDevice, DeviceId = DeviceId, WeakDeviceId = DeviceId::Weak>,
1343 > DeviceSocketAccessor<FakeBindingsCtx> for As
1344 {
1345 type DeviceSocketCoreCtx<'a> =
1346 FakeSocketsMutRefs<'a, As::AnyDevice, As::AllSockets, HashSet<DeviceId>, DeviceId>;
1347 fn with_device_sockets<
1348 F: FnOnce(
1349 &DeviceSockets<Self::WeakDeviceId, FakeBindingsCtx>,
1350 &mut Self::DeviceSocketCoreCtx<'_>,
1351 ) -> R,
1352 R,
1353 >(
1354 &mut self,
1355 device: &Self::DeviceId,
1356 cb: F,
1357 ) -> R {
1358 let FakeSocketsMutRefs(any_device, all_sockets, device_sockets, PhantomData, counters) =
1359 self.as_sockets_ref();
1360 let mut devices = device_sockets.keys().cloned().collect();
1361 let device = device_sockets.get(device).unwrap();
1362 cb(
1363 device,
1364 &mut FakeSocketsMutRefs(
1365 any_device,
1366 all_sockets,
1367 &mut devices,
1368 PhantomData,
1369 counters,
1370 ),
1371 )
1372 }
1373 fn with_device_sockets_mut<
1374 F: FnOnce(
1375 &mut DeviceSockets<Self::WeakDeviceId, FakeBindingsCtx>,
1376 &mut Self::DeviceSocketCoreCtx<'_>,
1377 ) -> R,
1378 R,
1379 >(
1380 &mut self,
1381 device: &Self::DeviceId,
1382 cb: F,
1383 ) -> R {
1384 let FakeSocketsMutRefs(any_device, all_sockets, device_sockets, PhantomData, counters) =
1385 self.as_sockets_ref();
1386 let mut devices = device_sockets.keys().cloned().collect();
1387 let device = device_sockets.get_mut(device).unwrap();
1388 cb(
1389 device,
1390 &mut FakeSocketsMutRefs(
1391 any_device,
1392 all_sockets,
1393 &mut devices,
1394 PhantomData,
1395 counters,
1396 ),
1397 )
1398 }
1399 }
1400
1401 impl<
1402 'm,
1403 DeviceId: FakeStrongDeviceId,
1404 As: AsFakeSocketsMutRefs<
1405 AnyDevice = AnyDeviceSockets<DeviceId::Weak, FakeBindingsCtx>,
1406 AllSockets = AllSockets<DeviceId::Weak, FakeBindingsCtx>,
1407 Devices = HashMap<DeviceId, DeviceSockets<DeviceId::Weak, FakeBindingsCtx>>,
1408 > + DeviceIdContext<AnyDevice, DeviceId = DeviceId, WeakDeviceId = DeviceId::Weak>,
1409 > DeviceSocketContext<FakeBindingsCtx> for As
1410 {
1411 type SocketTablesCoreCtx<'a> = FakeSocketsMutRefs<
1412 'a,
1413 (),
1414 (),
1415 HashMap<DeviceId, DeviceSockets<DeviceId::Weak, FakeBindingsCtx>>,
1416 DeviceId,
1417 >;
1418
1419 fn with_any_device_sockets<
1420 F: FnOnce(
1421 &AnyDeviceSockets<Self::WeakDeviceId, FakeBindingsCtx>,
1422 &mut Self::SocketTablesCoreCtx<'_>,
1423 ) -> R,
1424 R,
1425 >(
1426 &mut self,
1427 cb: F,
1428 ) -> R {
1429 let FakeSocketsMutRefs(
1430 any_device_sockets,
1431 _all_sockets,
1432 device_sockets,
1433 PhantomData,
1434 counters,
1435 ) = self.as_sockets_ref();
1436 cb(
1437 any_device_sockets,
1438 &mut FakeSocketsMutRefs(&mut (), &mut (), device_sockets, PhantomData, counters),
1439 )
1440 }
1441 fn with_any_device_sockets_mut<
1442 F: FnOnce(
1443 &mut AnyDeviceSockets<Self::WeakDeviceId, FakeBindingsCtx>,
1444 &mut Self::SocketTablesCoreCtx<'_>,
1445 ) -> R,
1446 R,
1447 >(
1448 &mut self,
1449 cb: F,
1450 ) -> R {
1451 let FakeSocketsMutRefs(
1452 any_device_sockets,
1453 _all_sockets,
1454 device_sockets,
1455 PhantomData,
1456 counters,
1457 ) = self.as_sockets_ref();
1458 cb(
1459 any_device_sockets,
1460 &mut FakeSocketsMutRefs(&mut (), &mut (), device_sockets, PhantomData, counters),
1461 )
1462 }
1463
1464 fn with_all_device_sockets<
1465 F: FnOnce(
1466 &AllSockets<Self::WeakDeviceId, FakeBindingsCtx>,
1467 &mut Self::SocketTablesCoreCtx<'_>,
1468 ) -> R,
1469 R,
1470 >(
1471 &mut self,
1472 cb: F,
1473 ) -> R {
1474 let FakeSocketsMutRefs(
1475 _any_device_sockets,
1476 all_sockets,
1477 device_sockets,
1478 PhantomData,
1479 counters,
1480 ) = self.as_sockets_ref();
1481 cb(
1482 all_sockets,
1483 &mut FakeSocketsMutRefs(&mut (), &mut (), device_sockets, PhantomData, counters),
1484 )
1485 }
1486
1487 fn with_all_device_sockets_mut<
1488 F: FnOnce(&mut AllSockets<Self::WeakDeviceId, FakeBindingsCtx>) -> R,
1489 R,
1490 >(
1491 &mut self,
1492 cb: F,
1493 ) -> R {
1494 let FakeSocketsMutRefs(_, all_sockets, _, _, _) = self.as_sockets_ref();
1495 cb(all_sockets)
1496 }
1497 }
1498
1499 impl<'m, X, Y, Z, D: FakeStrongDeviceId> DeviceIdContext<AnyDevice>
1500 for FakeSocketsMutRefs<'m, X, Y, Z, D>
1501 {
1502 type DeviceId = D;
1503 type WeakDeviceId = FakeWeakDeviceId<D>;
1504 }
1505
1506 impl<D: FakeStrongDeviceId> CounterContext<DeviceSocketCounters> for FakeCoreCtx<D> {
1507 fn counters(&self) -> &DeviceSocketCounters {
1508 &self.state.counters
1509 }
1510 }
1511
1512 impl<D: FakeStrongDeviceId>
1513 ResourceCounterContext<DeviceSocketId<D::Weak, FakeBindingsCtx>, DeviceSocketCounters>
1514 for FakeCoreCtx<D>
1515 {
1516 fn per_resource_counters<'a>(
1517 &'a self,
1518 socket: &'a DeviceSocketId<D::Weak, FakeBindingsCtx>,
1519 ) -> &'a DeviceSocketCounters {
1520 socket.counters()
1521 }
1522 }
1523
1524 impl<'m, X, Y, Z, D> CounterContext<DeviceSocketCounters> for FakeSocketsMutRefs<'m, X, Y, Z, D> {
1525 fn counters(&self) -> &DeviceSocketCounters {
1526 let FakeSocketsMutRefs(_, _, _, _, counters) = self;
1527 counters
1528 }
1529 }
1530
1531 impl<'m, X, Y, Z, D: FakeStrongDeviceId>
1532 ResourceCounterContext<DeviceSocketId<D::Weak, FakeBindingsCtx>, DeviceSocketCounters>
1533 for FakeSocketsMutRefs<'m, X, Y, Z, D>
1534 {
1535 fn per_resource_counters<'a>(
1536 &'a self,
1537 socket: &'a DeviceSocketId<D::Weak, FakeBindingsCtx>,
1538 ) -> &'a DeviceSocketCounters {
1539 socket.counters()
1540 }
1541 }
1542
1543 const SOME_PROTOCOL: NonZeroU16 = NonZeroU16::new(2000).unwrap();
1544
1545 #[test]
1546 fn create_remove() {
1547 let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new(
1548 MultipleDevicesId::all(),
1549 )));
1550 let mut api = ctx.device_socket_api();
1551
1552 let bound = api.create(Default::default());
1553 assert_eq!(
1554 api.get_info(&bound),
1555 SocketInfo { device: TargetDevice::AnyDevice, protocol: None }
1556 );
1557
1558 let ExternalSocketState(_received_frames) = api.remove(bound).into_removed();
1559 }
1560
1561 #[test_case(TargetDevice::AnyDevice)]
1562 #[test_case(TargetDevice::SpecificDevice(&MultipleDevicesId::A))]
1563 fn test_set_device(device: TargetDevice<&MultipleDevicesId>) {
1564 let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new(
1565 MultipleDevicesId::all(),
1566 )));
1567 let mut api = ctx.device_socket_api();
1568
1569 let bound = api.create(Default::default());
1570 api.set_device(&bound, device.clone());
1571 assert_eq!(
1572 api.get_info(&bound),
1573 SocketInfo { device: device.with_weak_id(), protocol: None }
1574 );
1575
1576 let device_sockets = &api.core_ctx().state.device_sockets;
1577 if let TargetDevice::SpecificDevice(d) = device {
1578 let DeviceSockets(socket_ids) = device_sockets.get(d).expect("device state exists");
1579 assert_eq!(socket_ids, &HashSet::from([bound]));
1580 }
1581 }
1582
1583 #[test]
1584 fn update_device() {
1585 let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new(
1586 MultipleDevicesId::all(),
1587 )));
1588 let mut api = ctx.device_socket_api();
1589 let bound = api.create(Default::default());
1590
1591 api.set_device(&bound, TargetDevice::SpecificDevice(&MultipleDevicesId::A));
1592
1593 api.set_device(&bound, TargetDevice::SpecificDevice(&MultipleDevicesId::B));
1596 assert_eq!(
1597 api.get_info(&bound),
1598 SocketInfo {
1599 device: TargetDevice::SpecificDevice(FakeWeakDeviceId(MultipleDevicesId::B)),
1600 protocol: None
1601 }
1602 );
1603
1604 let device_sockets = &api.core_ctx().state.device_sockets;
1605 let device_socket_lists = device_sockets
1606 .iter()
1607 .map(|(d, DeviceSockets(indexes))| (d, indexes.iter().collect()))
1608 .collect::<HashMap<_, _>>();
1609
1610 assert_eq!(
1611 device_socket_lists,
1612 HashMap::from([
1613 (&MultipleDevicesId::A, vec![]),
1614 (&MultipleDevicesId::B, vec![&bound]),
1615 (&MultipleDevicesId::C, vec![])
1616 ])
1617 );
1618 }
1619
1620 #[test_case(Protocol::All, TargetDevice::AnyDevice)]
1621 #[test_case(Protocol::Specific(SOME_PROTOCOL), TargetDevice::AnyDevice)]
1622 #[test_case(Protocol::All, TargetDevice::SpecificDevice(&MultipleDevicesId::A))]
1623 #[test_case(
1624 Protocol::Specific(SOME_PROTOCOL),
1625 TargetDevice::SpecificDevice(&MultipleDevicesId::A)
1626 )]
1627 fn create_set_device_and_protocol_remove_multiple(
1628 protocol: Protocol,
1629 device: TargetDevice<&MultipleDevicesId>,
1630 ) {
1631 let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new(
1632 MultipleDevicesId::all(),
1633 )));
1634 let mut api = ctx.device_socket_api();
1635
1636 let mut sockets = [(); 3].map(|()| api.create(Default::default()));
1637 for socket in &mut sockets {
1638 api.set_device_and_protocol(socket, device.clone(), protocol);
1639 assert_eq!(
1640 api.get_info(socket),
1641 SocketInfo { device: device.with_weak_id(), protocol: Some(protocol) }
1642 );
1643 }
1644
1645 for socket in sockets {
1646 let ExternalSocketState(_received_frames) = api.remove(socket).into_removed();
1647 }
1648 }
1649
1650 #[test]
1651 fn change_device_after_removal() {
1652 let device_to_remove = FakeReferencyDeviceId::default();
1653 let device_to_maintain = FakeReferencyDeviceId::default();
1654 let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new([
1655 device_to_remove.clone(),
1656 device_to_maintain.clone(),
1657 ])));
1658 let mut api = ctx.device_socket_api();
1659
1660 let bound = api.create(Default::default());
1661 api.set_device(&bound, TargetDevice::SpecificDevice(&device_to_remove));
1664
1665 device_to_remove.mark_removed();
1668
1669 api.set_device(&bound, TargetDevice::SpecificDevice(&device_to_maintain));
1672 assert_eq!(
1673 api.get_info(&bound),
1674 SocketInfo {
1675 device: TargetDevice::SpecificDevice(FakeWeakDeviceId(device_to_maintain.clone())),
1676 protocol: None,
1677 }
1678 );
1679
1680 let device_sockets = &api.core_ctx().state.device_sockets;
1681 let DeviceSockets(weak_sockets) =
1682 device_sockets.get(&device_to_maintain).expect("device state exists");
1683 assert_eq!(weak_sockets, &HashSet::from([bound]));
1684 }
1685
1686 struct TestData;
1687 impl TestData {
1688 const SRC_MAC: Mac = Mac::new([0, 1, 2, 3, 4, 5]);
1689 const DST_MAC: Mac = Mac::new([6, 7, 8, 9, 10, 11]);
1690 const PROTO: NonZeroU16 = NonZeroU16::new(0x08AB).unwrap();
1692 const BODY: &'static [u8] = b"some pig";
1693 const BUFFER: &'static [u8] = &[
1694 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 0x08, 0xAB, b's', b'o', b'm', b'e', b' ', b'p',
1695 b'i', b'g',
1696 ];
1697 const BUFFER_OFFSET: usize = Self::BUFFER.len() - Self::BODY.len();
1698
1699 fn frame() -> packet_formats::ethernet::EthernetFrame<&'static [u8]> {
1701 let mut buffer_view = Self::BUFFER;
1702 packet_formats::ethernet::EthernetFrame::parse(
1703 &mut buffer_view,
1704 EthernetFrameLengthCheck::NoCheck,
1705 )
1706 .unwrap()
1707 }
1708 }
1709
1710 const WRONG_PROTO: NonZeroU16 = NonZeroU16::new(0x08ff).unwrap();
1711
1712 fn make_bound<D: FakeStrongDeviceId>(
1713 ctx: &mut FakeCtx<D>,
1714 device: TargetDevice<D>,
1715 protocol: Option<Protocol>,
1716 state: ExternalSocketState<D::Weak>,
1717 ) -> DeviceSocketId<D::Weak, FakeBindingsCtx> {
1718 let mut api = ctx.device_socket_api();
1719 let id = api.create(state);
1720 let device = match &device {
1721 TargetDevice::AnyDevice => TargetDevice::AnyDevice,
1722 TargetDevice::SpecificDevice(d) => TargetDevice::SpecificDevice(d),
1723 };
1724 match protocol {
1725 Some(protocol) => api.set_device_and_protocol(&id, device, protocol),
1726 None => api.set_device(&id, device),
1727 };
1728 id
1729 }
1730
1731 fn deliver_one_frame(
1734 delivered_frame: Frame<&[u8]>,
1735 FakeCtx { core_ctx, bindings_ctx }: &mut FakeCtx<MultipleDevicesId>,
1736 ) -> HashSet<DeviceSocketId<FakeWeakDeviceId<MultipleDevicesId>, FakeBindingsCtx>> {
1737 DeviceSocketHandler::handle_frame(
1738 core_ctx,
1739 bindings_ctx,
1740 &MultipleDevicesId::A,
1741 delivered_frame.clone(),
1742 TestData::BUFFER,
1743 );
1744
1745 let FakeSockets {
1746 all_sockets: AllSockets(all_sockets),
1747 any_device_sockets: _,
1748 device_sockets: _,
1749 counters: _,
1750 sent_frames: _,
1751 } = &core_ctx.state;
1752
1753 all_sockets
1754 .iter()
1755 .filter_map(|(id, _primary)| {
1756 let DeviceSocketId(rc) = &id;
1757 let ExternalSocketState(frames) = &rc.external_state;
1758 let lock_guard = frames.lock();
1759 let testutil::RxQueue { frames, .. } = lock_guard.deref();
1760 (!frames.is_empty()).then(|| {
1761 assert_eq!(
1762 &*frames,
1763 &[ReceivedFrame {
1764 device: FakeWeakDeviceId(MultipleDevicesId::A),
1765 frame: delivered_frame.cloned(),
1766 raw: TestData::BUFFER.into(),
1767 }]
1768 );
1769 id.clone()
1770 })
1771 })
1772 .collect()
1773 }
1774
1775 #[test]
1776 fn receive_frame_deliver_to_multiple() {
1777 let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new(
1778 MultipleDevicesId::all(),
1779 )));
1780
1781 use Protocol::*;
1782 use TargetDevice::*;
1783 let never_bound = {
1784 let state = ExternalSocketState::<FakeWeakDeviceId<MultipleDevicesId>>::default();
1785 ctx.device_socket_api().create(state)
1786 };
1787
1788 let mut make_bound = |device, protocol| {
1789 let state = ExternalSocketState::<FakeWeakDeviceId<MultipleDevicesId>>::default();
1790 make_bound(&mut ctx, device, protocol, state)
1791 };
1792 let bound_a_no_protocol = make_bound(SpecificDevice(MultipleDevicesId::A), None);
1793 let bound_a_all_protocols = make_bound(SpecificDevice(MultipleDevicesId::A), Some(All));
1794 let bound_a_right_protocol =
1795 make_bound(SpecificDevice(MultipleDevicesId::A), Some(Specific(TestData::PROTO)));
1796 let bound_a_wrong_protocol =
1797 make_bound(SpecificDevice(MultipleDevicesId::A), Some(Specific(WRONG_PROTO)));
1798 let bound_b_no_protocol = make_bound(SpecificDevice(MultipleDevicesId::B), None);
1799 let bound_b_all_protocols = make_bound(SpecificDevice(MultipleDevicesId::B), Some(All));
1800 let bound_b_right_protocol =
1801 make_bound(SpecificDevice(MultipleDevicesId::B), Some(Specific(TestData::PROTO)));
1802 let bound_b_wrong_protocol =
1803 make_bound(SpecificDevice(MultipleDevicesId::B), Some(Specific(WRONG_PROTO)));
1804 let bound_any_no_protocol = make_bound(AnyDevice, None);
1805 let bound_any_all_protocols = make_bound(AnyDevice, Some(All));
1806 let bound_any_right_protocol = make_bound(AnyDevice, Some(Specific(TestData::PROTO)));
1807 let bound_any_wrong_protocol = make_bound(AnyDevice, Some(Specific(WRONG_PROTO)));
1808
1809 let mut sockets_with_received_frames = deliver_one_frame(
1810 super::ReceivedFrame::from_ethernet(
1811 TestData::frame(),
1812 FrameDestination::Individual { local: true },
1813 PacketType::Host,
1814 None,
1815 )
1816 .into(),
1817 &mut ctx,
1818 );
1819
1820 let sockets_not_expecting_frames = [
1821 never_bound,
1822 bound_a_no_protocol,
1823 bound_a_wrong_protocol,
1824 bound_b_no_protocol,
1825 bound_b_all_protocols,
1826 bound_b_right_protocol,
1827 bound_b_wrong_protocol,
1828 bound_any_no_protocol,
1829 bound_any_wrong_protocol,
1830 ];
1831 let sockets_expecting_frames = [
1832 bound_a_all_protocols,
1833 bound_a_right_protocol,
1834 bound_any_all_protocols,
1835 bound_any_right_protocol,
1836 ];
1837
1838 for (n, socket) in sockets_expecting_frames.iter().enumerate() {
1839 assert!(
1840 sockets_with_received_frames.remove(socket),
1841 "socket {n} didn't receive the frame"
1842 );
1843 }
1844 assert!(sockets_with_received_frames.is_empty());
1845
1846 for (n, socket) in sockets_expecting_frames.iter().enumerate() {
1848 assert_eq!(socket.counters().rx_frames.get(), 1, "socket {n} has wrong rx_frames");
1849 }
1850 for (n, socket) in sockets_not_expecting_frames.iter().enumerate() {
1851 assert_eq!(socket.counters().rx_frames.get(), 0, "socket {n} has wrong rx_frames");
1852 }
1853 }
1854
1855 #[test]
1856 fn sent_frame_deliver_to_multiple() {
1857 let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new(
1858 MultipleDevicesId::all(),
1859 )));
1860
1861 use Protocol::*;
1862 use TargetDevice::*;
1863 let never_bound = {
1864 let state = ExternalSocketState::<FakeWeakDeviceId<MultipleDevicesId>>::default();
1865 ctx.device_socket_api().create(state)
1866 };
1867
1868 let mut make_bound = |device, protocol| {
1869 let state = ExternalSocketState::<FakeWeakDeviceId<MultipleDevicesId>>::default();
1870 make_bound(&mut ctx, device, protocol, state)
1871 };
1872 let bound_a_no_protocol = make_bound(SpecificDevice(MultipleDevicesId::A), None);
1873 let bound_a_all_protocols = make_bound(SpecificDevice(MultipleDevicesId::A), Some(All));
1874 let bound_a_same_protocol =
1875 make_bound(SpecificDevice(MultipleDevicesId::A), Some(Specific(TestData::PROTO)));
1876 let bound_a_wrong_protocol =
1877 make_bound(SpecificDevice(MultipleDevicesId::A), Some(Specific(WRONG_PROTO)));
1878 let bound_b_no_protocol = make_bound(SpecificDevice(MultipleDevicesId::B), None);
1879 let bound_b_all_protocols = make_bound(SpecificDevice(MultipleDevicesId::B), Some(All));
1880 let bound_b_same_protocol =
1881 make_bound(SpecificDevice(MultipleDevicesId::B), Some(Specific(TestData::PROTO)));
1882 let bound_b_wrong_protocol =
1883 make_bound(SpecificDevice(MultipleDevicesId::B), Some(Specific(WRONG_PROTO)));
1884 let bound_any_no_protocol = make_bound(AnyDevice, None);
1885 let bound_any_all_protocols = make_bound(AnyDevice, Some(All));
1886 let bound_any_same_protocol = make_bound(AnyDevice, Some(Specific(TestData::PROTO)));
1887 let bound_any_wrong_protocol = make_bound(AnyDevice, Some(Specific(WRONG_PROTO)));
1888
1889 let mut sockets_with_received_frames =
1890 deliver_one_frame(SentFrame::Ethernet(TestData::frame().into()).into(), &mut ctx);
1891
1892 let sockets_not_expecting_frames = [
1893 never_bound,
1894 bound_a_no_protocol,
1895 bound_a_same_protocol,
1896 bound_a_wrong_protocol,
1897 bound_b_no_protocol,
1898 bound_b_all_protocols,
1899 bound_b_same_protocol,
1900 bound_b_wrong_protocol,
1901 bound_any_no_protocol,
1902 bound_any_same_protocol,
1903 bound_any_wrong_protocol,
1904 ];
1905 let sockets_expecting_frames = [bound_a_all_protocols, bound_any_all_protocols];
1907
1908 for (n, socket) in sockets_expecting_frames.iter().enumerate() {
1909 assert!(
1910 sockets_with_received_frames.remove(socket),
1911 "socket {n} didn't receive the frame"
1912 );
1913 }
1914 assert!(sockets_with_received_frames.is_empty());
1915
1916 for (n, socket) in sockets_expecting_frames.iter().enumerate() {
1918 assert_eq!(socket.counters().rx_frames.get(), 1, "socket {n} has wrong rx_frames");
1919 }
1920 for (n, socket) in sockets_not_expecting_frames.iter().enumerate() {
1921 assert_eq!(socket.counters().rx_frames.get(), 0, "socket {n} has wrong rx_frames");
1922 }
1923 }
1924
1925 #[test]
1926 fn deliver_multiple_frames() {
1927 let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new(
1928 MultipleDevicesId::all(),
1929 )));
1930 let socket = make_bound(
1931 &mut ctx,
1932 TargetDevice::AnyDevice,
1933 Some(Protocol::All),
1934 ExternalSocketState::default(),
1935 );
1936 let FakeCtx { mut core_ctx, mut bindings_ctx } = ctx;
1937
1938 const GSO_INFO: GsoInfo = GsoInfo {
1940 gso_size: NonZeroU16::new(1000).unwrap(),
1941 gso_segs: NonZeroU16::new(3).unwrap(),
1942 ipv4_id_mode: None,
1943 };
1944
1945 const RECEIVE_COUNT: usize = 10;
1946 for _ in 0..RECEIVE_COUNT {
1947 DeviceSocketHandler::handle_frame(
1948 &mut core_ctx,
1949 &mut bindings_ctx,
1950 &MultipleDevicesId::A,
1951 super::ReceivedFrame::from_ethernet(
1952 TestData::frame(),
1953 FrameDestination::Individual { local: true },
1954 PacketType::Host,
1955 Some(GSO_INFO),
1956 )
1957 .into(),
1958 TestData::BUFFER,
1959 );
1960 }
1961
1962 let FakeSockets {
1963 all_sockets: AllSockets(mut all_sockets),
1964 any_device_sockets: _,
1965 device_sockets: _,
1966 counters: _,
1967 sent_frames: _,
1968 } = core_ctx.into_state();
1969 let primary = all_sockets.remove(&socket).unwrap();
1970 let PrimaryDeviceSocketId(primary) = primary;
1971 assert!(all_sockets.is_empty());
1972 drop(socket);
1973 let SocketState { external_state: ExternalSocketState(received), counters, target: _ } =
1974 PrimaryRc::unwrap(primary);
1975 assert_eq!(
1976 received.into_inner().frames,
1977 vec![
1978 ReceivedFrame {
1979 device: FakeWeakDeviceId(MultipleDevicesId::A),
1980 frame: Frame::Received(super::ReceivedFrame::Ethernet {
1981 destination: FrameDestination::Individual { local: true },
1982 frame: EthernetFrame {
1983 src_mac: TestData::SRC_MAC,
1984 dst_mac: TestData::DST_MAC,
1985 ethertype: Some(TestData::PROTO.get().into()),
1986 body_offset: TestData::BUFFER_OFFSET,
1987 body: Vec::from(TestData::BODY),
1988 },
1989 packet_type: PacketType::Host,
1990 gso_info: Some(GSO_INFO),
1991 }),
1992 raw: TestData::BUFFER.into()
1993 };
1994 RECEIVE_COUNT
1995 ]
1996 );
1997 assert_eq!(counters.rx_frames.get(), u64::try_from(RECEIVE_COUNT).unwrap());
1998 }
1999
2000 #[test]
2001 fn deliver_frame_queue_full() {
2002 let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new(
2003 MultipleDevicesId::all(),
2004 )));
2005
2006 let sock1 = make_bound(
2008 &mut ctx,
2009 TargetDevice::AnyDevice,
2010 Some(Protocol::All),
2011 ExternalSocketState(Mutex::new(testutil::RxQueue { frames: vec![], max_size: 0 })),
2012 );
2013 let sock2 = make_bound(
2014 &mut ctx,
2015 TargetDevice::AnyDevice,
2016 Some(Protocol::All),
2017 ExternalSocketState::default(),
2018 );
2019
2020 let FakeCtx { mut core_ctx, mut bindings_ctx } = ctx;
2021
2022 DeviceSocketHandler::handle_frame(
2023 &mut core_ctx,
2024 &mut bindings_ctx,
2025 &MultipleDevicesId::A,
2026 super::ReceivedFrame::from_ethernet(
2027 TestData::frame(),
2028 FrameDestination::Individual { local: true },
2029 PacketType::Host,
2030 None,
2031 )
2032 .into(),
2033 TestData::BUFFER,
2034 );
2035
2036 assert_eq!(core_ctx.state.counters.rx_frames.get(), 2);
2037 assert_eq!(core_ctx.state.counters.rx_queue_full.get(), 1);
2038 assert_eq!(sock1.counters().rx_frames.get(), 1);
2039 assert_eq!(sock1.counters().rx_queue_full.get(), 1);
2040 assert_eq!(sock2.counters().rx_frames.get(), 1);
2041 assert_eq!(sock2.counters().rx_queue_full.get(), 0);
2042
2043 drop(sock1);
2046 drop(sock2);
2047 }
2048
2049 pub struct FakeSendMetadata;
2050 impl DeviceSocketSendTypes for AnyDevice {
2051 type Metadata = FakeSendMetadata;
2052 }
2053 impl<BC: TxMetadataBindingsTypes, D: FakeStrongDeviceId> SendableFrameMeta<FakeCoreCtx<D>, BC>
2054 for DeviceSocketMetadata<AnyDevice, FakeCoreCtx<D>, BC>
2055 {
2056 fn send_meta<S>(
2057 self,
2058 core_ctx: &mut FakeCoreCtx<D>,
2059 _bindings_ctx: &mut BC,
2060 frame: S,
2061 ) -> Result<(), SendFrameError<S>>
2062 where
2063 S: NetworkSerializer,
2064 S::Buffer: BufferMut,
2065 {
2066 let frame = match frame.serialize_vec_outer(&mut NetworkSerializationContext::default())
2067 {
2068 Err(e) => {
2069 let _: (packet::SerializeError<!>, _) = e;
2070 unreachable!()
2071 }
2072 Ok(frame) => frame.unwrap_a().as_ref().to_vec(),
2073 };
2074 core_ctx.state.sent_frames.push(frame);
2075 Ok(())
2076 }
2077 }
2078
2079 #[test]
2080 fn send_multiple_frames() {
2081 let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new(
2082 MultipleDevicesId::all(),
2083 )));
2084
2085 const DEVICE: MultipleDevicesId = MultipleDevicesId::A;
2086 let socket = make_bound(
2087 &mut ctx,
2088 TargetDevice::SpecificDevice(DEVICE),
2089 Some(Protocol::All),
2090 ExternalSocketState::default(),
2091 );
2092 let mut api = ctx.device_socket_api();
2093
2094 const SEND_COUNT: usize = 10;
2095 const PAYLOAD: &'static [u8] = &[1, 2, 3, 4, 5];
2096 for _ in 0..SEND_COUNT {
2097 let buf = packet::Buf::new(PAYLOAD.to_vec(), ..);
2098 api.send_frame(
2099 &socket,
2100 DeviceSocketMetadata {
2101 device_id: DEVICE,
2102 metadata: FakeSendMetadata,
2103 ip_layer_metadata: DeviceIpLayerMetadata::empty(),
2104 },
2105 buf,
2106 )
2107 .expect("send failed");
2108 }
2109
2110 assert_eq!(ctx.core_ctx().state.sent_frames, vec![PAYLOAD.to_vec(); SEND_COUNT]);
2111
2112 assert_eq!(socket.counters().tx_frames.get(), u64::try_from(SEND_COUNT).unwrap());
2113 }
2114}