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