Skip to main content

netstack3_device/
socket.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Link-layer sockets (analogous to Linux's AF_PACKET sockets).
6
7use 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, Inspectable,
19    Inspector, InspectorDeviceExt, InspectorExt, NetworkSerializer, ReferenceNotifiers,
20    ReferenceNotifiersExt as _, RemoveResourceResultWithContext, ResourceCounterContext,
21    SendFrameContext, SendFrameErrorReason, StrongDeviceIdentifier, WeakDeviceIdentifier as _,
22};
23use netstack3_hashmap::{HashMap, HashSet};
24use packet::{BufferMut, ParsablePacket as _};
25use packet_formats::error::ParseError;
26use packet_formats::ethernet::{EtherType, EthernetFrameLengthCheck};
27
28use crate::internal::base::DeviceLayerTypes;
29use crate::internal::id::WeakDeviceId;
30
31/// A selector for frames based on link-layer protocol number.
32#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
33pub enum Protocol {
34    /// Select all frames, regardless of protocol number.
35    All,
36    /// Select frames with the given protocol number.
37    Specific(NonZeroU16),
38}
39
40/// Selector for devices to send and receive packets on.
41#[derive(Clone, Debug, Derivative, Eq, Hash, PartialEq)]
42#[derivative(Default(bound = ""))]
43pub enum TargetDevice<D> {
44    /// Act on any device in the system.
45    #[derivative(Default)]
46    AnyDevice,
47    /// Act on a specific device.
48    SpecificDevice(D),
49}
50
51/// Information about the bound state of a socket.
52#[derive(Debug)]
53#[cfg_attr(test, derive(PartialEq))]
54pub struct SocketInfo<D> {
55    /// The protocol the socket is bound to, or `None` if no protocol is set.
56    pub protocol: Option<Protocol>,
57    /// The device selector for which the socket is set.
58    pub device: TargetDevice<D>,
59}
60
61/// Provides associated types for device sockets provided by the bindings
62/// context.
63pub trait DeviceSocketTypes {
64    /// State for the socket held by core and exposed to bindings.
65    type SocketState<D: Send + Sync + Debug>: Send + Sync + Debug;
66}
67
68/// Errors that Bindings may encounter when receiving frames on a Device Socket.
69pub enum ReceiveFrameError {
70    /// The socket's receive queue is full and can't hold the frame.
71    QueueFull,
72}
73
74/// The execution context for device sockets provided by bindings.
75pub trait DeviceSocketBindingsContext<DeviceId: StrongDeviceIdentifier>:
76    DeviceSocketTypes + Sized
77{
78    /// Called for each received frame that matches the provided socket.
79    ///
80    /// `frame` and `raw_frame` are parsed and raw views into the same data.
81    fn receive_frame(
82        &self,
83        socket_id: &DeviceSocketId<DeviceId::Weak, Self>,
84        device: &DeviceId,
85        frame: Frame<&[u8]>,
86        raw_frame: &[u8],
87    ) -> Result<(), ReceiveFrameError>;
88}
89
90/// Strong owner of socket state.
91///
92/// This type strongly owns the socket state.
93#[derive(Debug)]
94pub struct PrimaryDeviceSocketId<D: Send + Sync + Debug, BT: DeviceSocketTypes>(
95    PrimaryRc<SocketState<D, BT>>,
96);
97
98impl<D: Send + Sync + Debug, BT: DeviceSocketTypes> PrimaryDeviceSocketId<D, BT> {
99    /// Creates a new socket ID with `external_state`.
100    fn new(external_state: BT::SocketState<D>) -> Self {
101        Self(PrimaryRc::new(SocketState {
102            external_state,
103            counters: Default::default(),
104            target: Default::default(),
105        }))
106    }
107
108    /// Clones the primary's underlying reference and returns as a strong id.
109    fn clone_strong(&self) -> DeviceSocketId<D, BT> {
110        let PrimaryDeviceSocketId(rc) = self;
111        DeviceSocketId(PrimaryRc::clone_strong(rc))
112    }
113}
114
115/// Reference to live socket state.
116///
117/// The existence of a `StrongId` attests to the liveness of the state of the
118/// backing socket.
119#[derive(Derivative)]
120#[derivative(Clone(bound = ""), Hash(bound = ""), Eq(bound = ""), PartialEq(bound = ""))]
121pub struct DeviceSocketId<D: Send + Sync + Debug, BT: DeviceSocketTypes>(
122    StrongRc<SocketState<D, BT>>,
123);
124
125impl<D: Send + Sync + Debug, BT: DeviceSocketTypes> DeviceSocketId<D, BT> {
126    /// Returns [`SocketCookie`] for this socket.
127    pub fn socket_cookie(&self) -> SocketCookie {
128        let Self(rc) = self;
129        SocketCookie::new(rc.resource_token())
130    }
131}
132
133impl<D: Send + Sync + Debug, BT: DeviceSocketTypes> Debug for DeviceSocketId<D, BT> {
134    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
135        let Self(rc) = self;
136        f.debug_tuple("DeviceSocketId").field(&StrongRc::debug_id(rc)).finish()
137    }
138}
139
140impl<D: Send + Sync + Debug, BT: DeviceSocketTypes> OrderedLockAccess<Target<D>>
141    for DeviceSocketId<D, BT>
142{
143    type Lock = Mutex<Target<D>>;
144    fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
145        let Self(rc) = self;
146        OrderedLockRef::new(&rc.target)
147    }
148}
149
150/// A weak reference to socket state.
151///
152/// The existence of a [`WeakSocketDeviceId`] does not attest to the liveness of
153/// the backing socket.
154#[derive(Derivative)]
155#[derivative(Clone(bound = ""), Hash(bound = ""), Eq(bound = ""), PartialEq(bound = ""))]
156pub struct WeakDeviceSocketId<D: Send + Sync + Debug, BT: DeviceSocketTypes>(
157    WeakRc<SocketState<D, BT>>,
158);
159
160impl<D: Send + Sync + Debug, BT: DeviceSocketTypes> Debug for WeakDeviceSocketId<D, BT> {
161    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
162        let Self(rc) = self;
163        f.debug_tuple("WeakDeviceSocketId").field(&WeakRc::debug_id(rc)).finish()
164    }
165}
166
167/// Holds shared state for sockets.
168#[derive(Derivative)]
169#[derivative(Default(bound = ""))]
170pub struct Sockets<D: Send + Sync + Debug, BT: DeviceSocketTypes> {
171    /// Holds strong (but not owning) references to sockets that aren't
172    /// targeting a particular device.
173    any_device_sockets: RwLock<AnyDeviceSockets<D, BT>>,
174
175    /// Table of all sockets in the system, regardless of target.
176    ///
177    /// Holds the primary (owning) reference for all sockets.
178    // This needs to be after `any_device_sockets` so that when an instance of
179    // this type is dropped, any strong IDs get dropped before their
180    // corresponding primary IDs.
181    all_sockets: RwLock<AllSockets<D, BT>>,
182}
183
184/// The set of sockets associated with a device.
185#[derive(Derivative)]
186#[derivative(Default(bound = ""))]
187pub struct AnyDeviceSockets<D: Send + Sync + Debug, BT: DeviceSocketTypes>(
188    HashSet<DeviceSocketId<D, BT>>,
189);
190
191/// A collection of all device sockets in the system.
192#[derive(Derivative)]
193#[derivative(Default(bound = ""))]
194pub struct AllSockets<D: Send + Sync + Debug, BT: DeviceSocketTypes>(
195    HashMap<DeviceSocketId<D, BT>, PrimaryDeviceSocketId<D, BT>>,
196);
197
198/// State held by a device socket.
199#[derive(Debug)]
200pub struct SocketState<D: Send + Sync + Debug, BT: DeviceSocketTypes> {
201    /// State provided by bindings that is held in core.
202    pub external_state: BT::SocketState<D>,
203    /// The socket's target device and protocol.
204    // TODO(https://fxbug.dev/42077026): Consider splitting up the state here to
205    // improve performance.
206    target: Mutex<Target<D>>,
207    /// Statistics about the socket's usage.
208    counters: DeviceSocketCounters,
209}
210
211/// A device socket's binding information.
212#[derive(Debug, Derivative)]
213#[derivative(Default(bound = ""))]
214pub struct Target<D> {
215    protocol: Option<Protocol>,
216    device: TargetDevice<D>,
217}
218
219/// Per-device state for packet sockets.
220///
221/// Holds sockets that are bound to a particular device. An instance of this
222/// should be held in the state for each device in the system.
223#[derive(Derivative)]
224#[derivative(Default(bound = ""))]
225#[cfg_attr(
226    test,
227    derivative(Debug, PartialEq(bound = "BT::SocketState<D>: Hash + Eq, D: Hash + Eq"))
228)]
229pub struct DeviceSockets<D: Send + Sync + Debug, BT: DeviceSocketTypes>(
230    HashSet<DeviceSocketId<D, BT>>,
231);
232
233/// Convenience alias for use in device state storage.
234pub type HeldDeviceSockets<BT> = DeviceSockets<WeakDeviceId<BT>, BT>;
235
236/// Convenience alias for use in shared storage.
237///
238/// The type parameter is expected to implement [`DeviceSocketTypes`].
239pub type HeldSockets<BT> = Sockets<WeakDeviceId<BT>, BT>;
240
241/// Core context for accessing socket state.
242pub trait DeviceSocketContext<BT: DeviceSocketTypes>: DeviceIdContext<AnyDevice> {
243    /// The core context available in callbacks to methods on this context.
244    type SocketTablesCoreCtx<'a>: DeviceSocketAccessor<BT, DeviceId = Self::DeviceId, WeakDeviceId = Self::WeakDeviceId>;
245
246    /// Executes the provided callback with access to the collection of all
247    /// sockets.
248    fn with_all_device_sockets<
249        F: FnOnce(&AllSockets<Self::WeakDeviceId, BT>, &mut Self::SocketTablesCoreCtx<'_>) -> R,
250        R,
251    >(
252        &mut self,
253        cb: F,
254    ) -> R;
255
256    /// Executes the provided callback with mutable access to the collection of
257    /// all sockets.
258    fn with_all_device_sockets_mut<F: FnOnce(&mut AllSockets<Self::WeakDeviceId, BT>) -> R, R>(
259        &mut self,
260        cb: F,
261    ) -> R;
262
263    /// Executes the provided callback with immutable access to socket state.
264    fn with_any_device_sockets<
265        F: FnOnce(&AnyDeviceSockets<Self::WeakDeviceId, BT>, &mut Self::SocketTablesCoreCtx<'_>) -> R,
266        R,
267    >(
268        &mut self,
269        cb: F,
270    ) -> R;
271
272    /// Executes the provided callback with mutable access to socket state.
273    fn with_any_device_sockets_mut<
274        F: FnOnce(
275            &mut AnyDeviceSockets<Self::WeakDeviceId, BT>,
276            &mut Self::SocketTablesCoreCtx<'_>,
277        ) -> R,
278        R,
279    >(
280        &mut self,
281        cb: F,
282    ) -> R;
283}
284
285/// Core context for accessing the state of an individual socket.
286pub trait SocketStateAccessor<BT: DeviceSocketTypes>: DeviceIdContext<AnyDevice> {
287    /// Provides read-only access to the state of a socket.
288    fn with_socket_state<F: FnOnce(&Target<Self::WeakDeviceId>) -> R, R>(
289        &mut self,
290        socket: &DeviceSocketId<Self::WeakDeviceId, BT>,
291        cb: F,
292    ) -> R;
293
294    /// Provides mutable access to the state of a socket.
295    fn with_socket_state_mut<F: FnOnce(&mut Target<Self::WeakDeviceId>) -> R, R>(
296        &mut self,
297        socket: &DeviceSocketId<Self::WeakDeviceId, BT>,
298        cb: F,
299    ) -> R;
300}
301
302/// Core context for accessing the socket state for a device.
303pub trait DeviceSocketAccessor<BT: DeviceSocketTypes>: SocketStateAccessor<BT> {
304    /// Core context available in callbacks to methods on this context.
305    type DeviceSocketCoreCtx<'a>: SocketStateAccessor<BT, DeviceId = Self::DeviceId, WeakDeviceId = Self::WeakDeviceId>
306        + ResourceCounterContext<DeviceSocketId<Self::WeakDeviceId, BT>, DeviceSocketCounters>;
307
308    /// Executes the provided callback with immutable access to device-specific
309    /// socket state.
310    fn with_device_sockets<
311        F: FnOnce(&DeviceSockets<Self::WeakDeviceId, BT>, &mut Self::DeviceSocketCoreCtx<'_>) -> R,
312        R,
313    >(
314        &mut self,
315        device: &Self::DeviceId,
316        cb: F,
317    ) -> R;
318
319    /// Executes the provided callback with mutable access to device-specific
320    /// socket state.
321    fn with_device_sockets_mut<
322        F: FnOnce(&mut DeviceSockets<Self::WeakDeviceId, BT>, &mut Self::DeviceSocketCoreCtx<'_>) -> R,
323        R,
324    >(
325        &mut self,
326        device: &Self::DeviceId,
327        cb: F,
328    ) -> R;
329}
330
331enum MaybeUpdate<T> {
332    NoChange,
333    NewValue(T),
334}
335
336fn update_device_and_protocol<CC: DeviceSocketContext<BT>, BT: DeviceSocketTypes>(
337    core_ctx: &mut CC,
338    socket: &DeviceSocketId<CC::WeakDeviceId, BT>,
339    new_device: TargetDevice<&CC::DeviceId>,
340    protocol_update: MaybeUpdate<Protocol>,
341) {
342    core_ctx.with_any_device_sockets_mut(|AnyDeviceSockets(any_device_sockets), core_ctx| {
343        // Even if we're never moving the socket from/to the any-device
344        // state, we acquire the lock to make the move between devices
345        // atomic from the perspective of frame delivery. Otherwise there
346        // would be a brief period during which arriving frames wouldn't be
347        // delivered to the socket from either device.
348        let old_device = core_ctx.with_socket_state_mut(socket, |Target { protocol, device }| {
349            match protocol_update {
350                MaybeUpdate::NewValue(p) => *protocol = Some(p),
351                MaybeUpdate::NoChange => (),
352            };
353            let old_device = match &device {
354                TargetDevice::SpecificDevice(device) => device.upgrade(),
355                TargetDevice::AnyDevice => {
356                    assert!(any_device_sockets.remove(socket));
357                    None
358                }
359            };
360            *device = match &new_device {
361                TargetDevice::AnyDevice => TargetDevice::AnyDevice,
362                TargetDevice::SpecificDevice(d) => TargetDevice::SpecificDevice(d.downgrade()),
363            };
364            old_device
365        });
366
367        // This modification occurs without holding the socket's individual
368        // lock. That's safe because all modifications to the socket's
369        // device are done within a `with_sockets_mut` call, which
370        // synchronizes them.
371
372        if let Some(device) = old_device {
373            // Remove the reference to the socket from the old device if
374            // there is one, and it hasn't been removed.
375            core_ctx.with_device_sockets_mut(
376                &device,
377                |DeviceSockets(device_sockets), _core_ctx| {
378                    assert!(device_sockets.remove(socket), "socket not found in device state");
379                },
380            );
381        }
382
383        // Add the reference to the new device, if there is one.
384        match &new_device {
385            TargetDevice::SpecificDevice(new_device) => core_ctx.with_device_sockets_mut(
386                new_device,
387                |DeviceSockets(device_sockets), _core_ctx| {
388                    assert!(device_sockets.insert(socket.clone()));
389                },
390            ),
391            TargetDevice::AnyDevice => {
392                assert!(any_device_sockets.insert(socket.clone()))
393            }
394        }
395    })
396}
397
398/// The device socket API.
399pub struct DeviceSocketApi<C>(C);
400
401impl<C> DeviceSocketApi<C> {
402    /// Creates a new `DeviceSocketApi` for `ctx`.
403    pub fn new(ctx: C) -> Self {
404        Self(ctx)
405    }
406}
407
408/// A local alias for [`DeviceSocketId`] for use in [`DeviceSocketApi`].
409///
410/// TODO(https://github.com/rust-lang/rust/issues/8995): Make this an inherent
411/// associated type.
412type ApiSocketId<C> = DeviceSocketId<
413    <<C as ContextPair>::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId,
414    <C as ContextPair>::BindingsContext,
415>;
416
417impl<C> DeviceSocketApi<C>
418where
419    C: ContextPair,
420    C::CoreContext: DeviceSocketContext<C::BindingsContext>
421        + SocketStateAccessor<C::BindingsContext>
422        + ResourceCounterContext<ApiSocketId<C>, DeviceSocketCounters>,
423    C::BindingsContext: DeviceSocketBindingsContext<<C::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId>
424        + ReferenceNotifiers
425        + 'static,
426{
427    fn core_ctx(&mut self) -> &mut C::CoreContext {
428        let Self(pair) = self;
429        pair.core_ctx()
430    }
431
432    fn contexts(&mut self) -> (&mut C::CoreContext, &mut C::BindingsContext) {
433        let Self(pair) = self;
434        pair.contexts()
435    }
436
437    /// Creates an packet socket with no protocol set configured for all devices.
438    pub fn create(
439        &mut self,
440        external_state: <C::BindingsContext as DeviceSocketTypes>::SocketState<
441            <C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId,
442        >,
443    ) -> ApiSocketId<C> {
444        let core_ctx = self.core_ctx();
445
446        let strong = core_ctx.with_all_device_sockets_mut(|AllSockets(sockets)| {
447            let primary = PrimaryDeviceSocketId::new(external_state);
448            let strong = primary.clone_strong();
449            assert!(sockets.insert(strong.clone(), primary).is_none());
450            strong
451        });
452        core_ctx.with_any_device_sockets_mut(|AnyDeviceSockets(any_device_sockets), _core_ctx| {
453            // On creation, sockets do not target any device or protocol.
454            // Inserting them into the `any_device_sockets` table lets us treat
455            // newly-created sockets uniformly with sockets whose target device
456            // or protocol was set. The difference is unobservable at runtime
457            // since newly-created sockets won't match any frames being
458            // delivered.
459            assert!(any_device_sockets.insert(strong.clone()));
460        });
461        strong
462    }
463
464    /// Sets the device for which a packet socket will receive packets.
465    pub fn set_device(
466        &mut self,
467        socket: &ApiSocketId<C>,
468        device: TargetDevice<&<C::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId>,
469    ) {
470        update_device_and_protocol(self.core_ctx(), socket, device, MaybeUpdate::NoChange)
471    }
472
473    /// Sets the device and protocol for which a socket will receive packets.
474    pub fn set_device_and_protocol(
475        &mut self,
476        socket: &ApiSocketId<C>,
477        device: TargetDevice<&<C::CoreContext as DeviceIdContext<AnyDevice>>::DeviceId>,
478        protocol: Protocol,
479    ) {
480        update_device_and_protocol(self.core_ctx(), socket, device, MaybeUpdate::NewValue(protocol))
481    }
482
483    /// Gets the bound info for a socket.
484    pub fn get_info(
485        &mut self,
486        id: &ApiSocketId<C>,
487    ) -> SocketInfo<<C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId> {
488        self.core_ctx().with_socket_state(id, |Target { device, protocol }| SocketInfo {
489            device: device.clone(),
490            protocol: *protocol,
491        })
492    }
493
494    /// Removes a bound socket.
495    pub fn remove(
496        &mut self,
497        id: ApiSocketId<C>,
498    ) -> RemoveResourceResultWithContext<
499        <C::BindingsContext as DeviceSocketTypes>::SocketState<
500            <C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId,
501        >,
502        C::BindingsContext,
503    > {
504        let core_ctx = self.core_ctx();
505        core_ctx.with_any_device_sockets_mut(|AnyDeviceSockets(any_device_sockets), core_ctx| {
506            let old_device = core_ctx.with_socket_state_mut(&id, |target| {
507                let Target { device, protocol: _ } = target;
508                match &device {
509                    TargetDevice::SpecificDevice(device) => device.upgrade(),
510                    TargetDevice::AnyDevice => {
511                        assert!(any_device_sockets.remove(&id));
512                        None
513                    }
514                }
515            });
516            if let Some(device) = old_device {
517                core_ctx.with_device_sockets_mut(
518                    &device,
519                    |DeviceSockets(device_sockets), _core_ctx| {
520                        assert!(device_sockets.remove(&id), "device doesn't have socket");
521                    },
522                )
523            }
524        });
525
526        core_ctx.with_all_device_sockets_mut(|AllSockets(sockets)| {
527            let primary = sockets
528                .remove(&id)
529                .unwrap_or_else(|| panic!("{id:?} not present in all socket map"));
530            // Make sure to drop the strong ID before trying to unwrap the primary
531            // ID.
532            drop(id);
533
534            let PrimaryDeviceSocketId(primary) = primary;
535            C::BindingsContext::unwrap_or_notify_with_new_reference_notifier(
536                primary,
537                |SocketState { external_state, counters: _, target: _ }| external_state,
538            )
539        })
540    }
541
542    /// Sends a frame for the specified socket.
543    pub fn send_frame<S, D>(
544        &mut self,
545        id: &ApiSocketId<C>,
546        metadata: DeviceSocketMetadata<D, <C::CoreContext as DeviceIdContext<D>>::DeviceId>,
547        body: S,
548    ) -> Result<(), SendFrameErrorReason>
549    where
550        S: NetworkSerializer,
551        S::Buffer: BufferMut,
552        D: DeviceSocketSendTypes,
553        C::CoreContext: DeviceIdContext<D>
554            + SendFrameContext<
555                C::BindingsContext,
556                DeviceSocketMetadata<D, <C::CoreContext as DeviceIdContext<D>>::DeviceId>,
557            >,
558        C::BindingsContext: DeviceLayerTypes,
559    {
560        let (core_ctx, bindings_ctx) = self.contexts();
561        let result = core_ctx.send_frame(bindings_ctx, metadata, body).map_err(|e| e.into_err());
562        match &result {
563            Ok(()) => {
564                core_ctx.increment_both(id, |counters: &DeviceSocketCounters| &counters.tx_frames)
565            }
566            Err(SendFrameErrorReason::QueueFull) => core_ctx
567                .increment_both(id, |counters: &DeviceSocketCounters| &counters.tx_err_queue_full),
568            Err(SendFrameErrorReason::Alloc) => core_ctx
569                .increment_both(id, |counters: &DeviceSocketCounters| &counters.tx_err_alloc),
570            Err(SendFrameErrorReason::SizeConstraintsViolation) => core_ctx
571                .increment_both(id, |counters: &DeviceSocketCounters| {
572                    &counters.tx_err_size_constraint
573                }),
574            Err(SendFrameErrorReason::AddressResolutionFailed) => {
575                unreachable!("device socket send should not perform link-layer address resolution");
576            }
577        }
578        result
579    }
580
581    /// Provides inspect data for raw IP sockets.
582    pub fn inspect<N>(&mut self, inspector: &mut N)
583    where
584        N: Inspector
585            + InspectorDeviceExt<<C::CoreContext as DeviceIdContext<AnyDevice>>::WeakDeviceId>,
586    {
587        self.core_ctx().with_all_device_sockets(|AllSockets(sockets), core_ctx| {
588            sockets.keys().for_each(|socket| {
589                inspector.record_debug_child(socket, |node| {
590                    core_ctx.with_socket_state(socket, |Target { protocol, device }| {
591                        node.record_debug("Protocol", protocol);
592                        match device {
593                            TargetDevice::AnyDevice => node.record_str("Device", "Any"),
594                            TargetDevice::SpecificDevice(d) => N::record_device(node, "Device", d),
595                        }
596                    });
597                    node.record_child("Counters", |node| {
598                        node.delegate_inspectable(socket.counters())
599                    })
600                })
601            })
602        })
603    }
604}
605
606/// A provider of the types required to send on a device socket.
607pub trait DeviceSocketSendTypes: Device {
608    /// The metadata required to send a frame on the device.
609    type Metadata;
610}
611
612/// Metadata required to send a frame on a device socket.
613#[derive(Debug, PartialEq)]
614pub struct DeviceSocketMetadata<D: DeviceSocketSendTypes, DeviceId> {
615    /// The device ID to send via.
616    pub device_id: DeviceId,
617    /// The metadata required to send that's specific to the device type.
618    pub metadata: D::Metadata,
619    // TODO(https://fxbug.dev/391946195): Include send buffer ownership metadata
620    // here.
621}
622
623/// Parameters needed to apply system-framing of an Ethernet frame.
624#[derive(Debug, PartialEq)]
625pub struct EthernetHeaderParams {
626    /// The destination MAC address to send to.
627    pub dest_addr: Mac,
628    /// The upperlayer protocol of the data contained in this Ethernet frame.
629    pub protocol: EtherType,
630}
631
632/// Public identifier for a socket.
633///
634/// Strongly owns the state of the socket. So long as the `SocketId` for a
635/// socket is not dropped, the socket is guaranteed to exist.
636pub type SocketId<BC> = DeviceSocketId<WeakDeviceId<BC>, BC>;
637
638impl<D: Send + Sync + Debug, BT: DeviceSocketTypes> DeviceSocketId<D, BT> {
639    /// Provides immutable access to [`DeviceSocketTypes::SocketState`] for the
640    /// socket.
641    pub fn socket_state(&self) -> &BT::SocketState<D> {
642        let Self(strong) = self;
643        let SocketState { external_state, counters: _, target: _ } = &**strong;
644        external_state
645    }
646
647    /// Obtain a [`WeakDeviceSocketId`] from this [`DeviceSocketId`].
648    pub fn downgrade(&self) -> WeakDeviceSocketId<D, BT> {
649        let Self(inner) = self;
650        WeakDeviceSocketId(StrongRc::downgrade(inner))
651    }
652
653    /// Provides access to the socket's counters.
654    pub fn counters(&self) -> &DeviceSocketCounters {
655        let Self(strong) = self;
656        let SocketState { external_state: _, counters, target: _ } = &**strong;
657        counters
658    }
659}
660
661/// Allows the rest of the stack to dispatch packets to listening sockets.
662///
663/// This is implemented on top of [`DeviceSocketContext`] and abstracts packet
664/// socket delivery from the rest of the system.
665pub trait DeviceSocketHandler<D: Device, BC>: DeviceIdContext<D> {
666    /// Dispatch a received frame to sockets.
667    fn handle_frame(
668        &mut self,
669        bindings_ctx: &mut BC,
670        device: &Self::DeviceId,
671        frame: Frame<&[u8]>,
672        whole_frame: &[u8],
673    );
674}
675
676/// A frame received on a device.
677#[derive(Clone, Copy, Debug, Eq, PartialEq)]
678pub enum ReceivedFrame<B> {
679    /// An ethernet frame received on a device.
680    Ethernet {
681        /// Where the frame was destined.
682        destination: FrameDestination,
683        /// The parsed ethernet frame.
684        frame: EthernetFrame<B>,
685    },
686    /// An IP frame received on a device.
687    ///
688    /// Note that this is not an IP packet within an Ethernet Frame. This is an
689    /// IP packet received directly from the device (e.g. a pure IP device).
690    Ip(IpFrame<B>),
691}
692
693/// A frame sent on a device.
694#[derive(Clone, Copy, Debug, Eq, PartialEq)]
695pub enum SentFrame<B> {
696    /// An ethernet frame sent on a device.
697    Ethernet(EthernetFrame<B>),
698    /// An IP frame sent on a device.
699    ///
700    /// Note that this is not an IP packet within an Ethernet Frame. This is an
701    /// IP Packet send directly on the device (e.g. a pure IP device).
702    Ip(IpFrame<B>),
703}
704
705/// A frame couldn't be parsed as a [`SentFrame`].
706#[derive(Debug)]
707pub struct ParseSentFrameError;
708
709impl SentFrame<&[u8]> {
710    /// Tries to parse the given frame as an Ethernet frame.
711    pub fn try_parse_as_ethernet(mut buf: &[u8]) -> Result<SentFrame<&[u8]>, ParseSentFrameError> {
712        packet_formats::ethernet::EthernetFrame::parse(&mut buf, EthernetFrameLengthCheck::NoCheck)
713            .map_err(|_: ParseError| ParseSentFrameError)
714            .map(|frame| SentFrame::Ethernet(frame.into()))
715    }
716}
717
718/// Data from an Ethernet frame.
719#[derive(Clone, Copy, Debug, Eq, PartialEq)]
720pub struct EthernetFrame<B> {
721    /// The source address of the frame.
722    pub src_mac: Mac,
723    /// The destination address of the frame.
724    pub dst_mac: Mac,
725    /// The EtherType of the frame, or `None` if there was none.
726    pub ethertype: Option<EtherType>,
727    /// The offset of the body within the frame.
728    pub body_offset: usize,
729    /// The body of the frame.
730    pub body: B,
731}
732
733/// Data from an IP frame.
734#[derive(Clone, Copy, Debug, Eq, PartialEq)]
735pub struct IpFrame<B> {
736    /// The IP version of the frame.
737    pub ip_version: IpVersion,
738    /// The body of the frame.
739    pub body: B,
740}
741
742impl<B> IpFrame<B> {
743    fn ethertype(&self) -> EtherType {
744        let IpFrame { ip_version, body: _ } = self;
745        EtherType::from_ip_version(*ip_version)
746    }
747}
748
749/// A frame sent or received on a device
750#[derive(Clone, Copy, Debug, Eq, PartialEq)]
751pub enum Frame<B> {
752    /// A sent frame.
753    Sent(SentFrame<B>),
754    /// A received frame.
755    Received(ReceivedFrame<B>),
756}
757
758impl<B> From<SentFrame<B>> for Frame<B> {
759    fn from(value: SentFrame<B>) -> Self {
760        Self::Sent(value)
761    }
762}
763
764impl<B> From<ReceivedFrame<B>> for Frame<B> {
765    fn from(value: ReceivedFrame<B>) -> Self {
766        Self::Received(value)
767    }
768}
769
770impl<'a> From<packet_formats::ethernet::EthernetFrame<&'a [u8]>> for EthernetFrame<&'a [u8]> {
771    fn from(frame: packet_formats::ethernet::EthernetFrame<&'a [u8]>) -> Self {
772        Self {
773            src_mac: frame.src_mac(),
774            dst_mac: frame.dst_mac(),
775            ethertype: frame.ethertype(),
776            body_offset: frame.parse_metadata().header_len(),
777            body: frame.into_body(),
778        }
779    }
780}
781
782impl<'a> ReceivedFrame<&'a [u8]> {
783    pub(crate) fn from_ethernet(
784        frame: packet_formats::ethernet::EthernetFrame<&'a [u8]>,
785        destination: FrameDestination,
786    ) -> Self {
787        Self::Ethernet { destination, frame: frame.into() }
788    }
789}
790
791impl<B> Frame<B> {
792    /// Returns ether type for the packet if it's known.
793    pub fn protocol(&self) -> Option<u16> {
794        let ethertype = match self {
795            Self::Sent(SentFrame::Ethernet(frame))
796            | Self::Received(ReceivedFrame::Ethernet { destination: _, frame }) => frame.ethertype,
797            Self::Sent(SentFrame::Ip(frame)) | Self::Received(ReceivedFrame::Ip(frame)) => {
798                Some(frame.ethertype())
799            }
800        };
801        ethertype.map(Into::into)
802    }
803
804    /// Convenience method for consuming the `Frame` and producing the body.
805    pub fn into_body(self) -> B {
806        match self {
807            Self::Received(ReceivedFrame::Ethernet { destination: _, frame })
808            | Self::Sent(SentFrame::Ethernet(frame)) => frame.body,
809            Self::Received(ReceivedFrame::Ip(frame)) | Self::Sent(SentFrame::Ip(frame)) => {
810                frame.body
811            }
812        }
813    }
814
815    /// Returns the offset of the body within the frame.
816    pub fn body_offset(&self) -> usize {
817        match self {
818            Self::Received(ReceivedFrame::Ethernet { destination: _, frame })
819            | Self::Sent(SentFrame::Ethernet(frame)) => frame.body_offset,
820            Self::Received(ReceivedFrame::Ip(_)) | Self::Sent(SentFrame::Ip(_)) => 0,
821        }
822    }
823}
824
825impl<
826    D: Device,
827    BC: DeviceSocketBindingsContext<<CC as DeviceIdContext<AnyDevice>>::DeviceId>,
828    CC: DeviceSocketContext<BC> + DeviceIdContext<D>,
829> DeviceSocketHandler<D, BC> for CC
830where
831    <CC as DeviceIdContext<D>>::DeviceId: Into<<CC as DeviceIdContext<AnyDevice>>::DeviceId>,
832{
833    fn handle_frame(
834        &mut self,
835        bindings_ctx: &mut BC,
836        device: &Self::DeviceId,
837        frame: Frame<&[u8]>,
838        whole_frame: &[u8],
839    ) {
840        let device = device.clone().into();
841
842        // TODO(https://fxbug.dev/42076496): Invert the order of acquisition
843        // for the lock on the sockets held in the device and the any-device
844        // sockets lock.
845        self.with_any_device_sockets(|AnyDeviceSockets(any_device_sockets), core_ctx| {
846            // Iterate through the device's sockets while also holding the
847            // any-device sockets lock. This prevents double delivery to the
848            // same socket. If the two tables were locked independently,
849            // we could end up with a race, with the following thread
850            // interleaving (thread A is executing this code for device D,
851            // thread B is updating the device to D for the same socket X):
852            //   A) lock the any device sockets table
853            //   A) deliver to socket X in the table
854            //   A) unlock the any device sockets table
855            //   B) lock the any device sockets table, then D's sockets
856            //   B) remove X from the any table and add to D's
857            //   B) unlock D's sockets and any device sockets
858            //   A) lock D's sockets
859            //   A) deliver to socket X in D's table (!)
860            core_ctx.with_device_sockets(&device, |DeviceSockets(device_sockets), core_ctx| {
861                for socket in any_device_sockets.iter().chain(device_sockets) {
862                    let delivered =
863                        core_ctx.with_socket_state(socket, |Target { protocol, device: _ }| {
864                            let should_deliver = match protocol {
865                                None => false,
866                                Some(p) => match p {
867                                    // Sent frames are only delivered to sockets
868                                    // matching all protocols for Linux
869                                    // compatibility. See https://github.com/google/gvisor/blob/68eae979409452209e4faaeac12aee4191b3d6f0/test/syscalls/linux/packet_socket.cc#L331-L392.
870                                    Protocol::Specific(p) => match frame {
871                                        Frame::Received(_) => Some(p.get()) == frame.protocol(),
872                                        Frame::Sent(_) => false,
873                                    },
874                                    Protocol::All => true,
875                                },
876                            };
877                            should_deliver.then(|| {
878                                bindings_ctx.receive_frame(socket, &device, frame, whole_frame)
879                            })
880                        });
881                    match delivered {
882                        None => {}
883                        Some(result) => {
884                            core_ctx.increment_both(socket, |counters: &DeviceSocketCounters| {
885                                &counters.rx_frames
886                            });
887                            match result {
888                                Ok(()) => {}
889                                Err(ReceiveFrameError::QueueFull) => {
890                                    core_ctx.increment_both(
891                                        socket,
892                                        |counters: &DeviceSocketCounters| &counters.rx_queue_full,
893                                    );
894                                }
895                            }
896                        }
897                    }
898                }
899            })
900        })
901    }
902}
903
904/// Usage statistics about Device Sockets.
905///
906/// Tracked stack-wide and per-socket.
907#[derive(Debug, Default)]
908pub struct DeviceSocketCounters {
909    /// Count of incoming frames that were delivered to the socket.
910    ///
911    /// Note that a single frame may be delivered to multiple device sockets.
912    /// Thus this counter, when tracking the stack-wide aggregate, may exceed
913    /// the total number of frames received by the stack.
914    rx_frames: Counter,
915    /// Count of incoming frames that could not be delivered to a socket because
916    /// its receive buffer was full.
917    rx_queue_full: Counter,
918    /// Count of outgoing frames that were sent by the socket.
919    tx_frames: Counter,
920    /// Count of failed tx frames due to [`SendFrameErrorReason::QueueFull`].
921    tx_err_queue_full: Counter,
922    /// Count of failed tx frames due to [`SendFrameErrorReason::Alloc`].
923    tx_err_alloc: Counter,
924    /// Count of failed tx frames due to [`SendFrameErrorReason::SizeConstraintsViolation`].
925    tx_err_size_constraint: Counter,
926}
927
928impl Inspectable for DeviceSocketCounters {
929    fn record<I: Inspector>(&self, inspector: &mut I) {
930        let Self {
931            rx_frames,
932            rx_queue_full,
933            tx_frames,
934            tx_err_queue_full,
935            tx_err_alloc,
936            tx_err_size_constraint,
937        } = self;
938        inspector.record_child("Rx", |inspector| {
939            inspector.record_counter("DeliveredFrames", rx_frames);
940            inspector.record_counter("DroppedQueueFull", rx_queue_full);
941        });
942        inspector.record_child("Tx", |inspector| {
943            inspector.record_counter("SentFrames", tx_frames);
944            inspector.record_counter("QueueFullError", tx_err_queue_full);
945            inspector.record_counter("AllocError", tx_err_alloc);
946            inspector.record_counter("SizeConstraintError", tx_err_size_constraint);
947        });
948    }
949}
950
951impl<D: Send + Sync + Debug, BT: DeviceSocketTypes> OrderedLockAccess<AnyDeviceSockets<D, BT>>
952    for Sockets<D, BT>
953{
954    type Lock = RwLock<AnyDeviceSockets<D, BT>>;
955    fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
956        OrderedLockRef::new(&self.any_device_sockets)
957    }
958}
959
960impl<D: Send + Sync + Debug, BT: DeviceSocketTypes> OrderedLockAccess<AllSockets<D, BT>>
961    for Sockets<D, BT>
962{
963    type Lock = RwLock<AllSockets<D, BT>>;
964    fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
965        OrderedLockRef::new(&self.all_sockets)
966    }
967}
968
969#[cfg(any(test, feature = "testutils"))]
970mod testutil {
971    use alloc::vec::Vec;
972    use core::num::NonZeroU64;
973    use core::ops::DerefMut;
974    use netstack3_base::StrongDeviceIdentifier;
975    use netstack3_base::testutil::{FakeBindingsCtx, MonotonicIdentifier};
976
977    use super::*;
978    use crate::internal::base::{
979        DeviceClassMatcher, DeviceIdAndNameMatcher, DeviceLayerStateTypes,
980    };
981
982    #[derive(Derivative, Debug)]
983    #[derivative(Default(bound = ""))]
984    pub struct RxQueue<D> {
985        pub frames: Vec<ReceivedFrame<D>>,
986        #[derivative(Default(value = "usize::MAX"))]
987        pub max_size: usize,
988    }
989
990    #[derive(Clone, Debug, PartialEq)]
991    pub struct ReceivedFrame<D> {
992        pub device: D,
993        pub frame: Frame<Vec<u8>>,
994        pub raw: Vec<u8>,
995    }
996
997    #[derive(Debug, Derivative)]
998    #[derivative(Default(bound = ""))]
999    pub struct ExternalSocketState<D>(pub Mutex<RxQueue<D>>);
1000
1001    impl<TimerId, Event: Debug, State> DeviceSocketTypes
1002        for FakeBindingsCtx<TimerId, Event, State, ()>
1003    {
1004        type SocketState<D: Send + Sync + Debug> = ExternalSocketState<D>;
1005    }
1006
1007    impl Frame<&[u8]> {
1008        pub(crate) fn cloned(self) -> Frame<Vec<u8>> {
1009            match self {
1010                Self::Sent(SentFrame::Ethernet(frame)) => {
1011                    Frame::Sent(SentFrame::Ethernet(frame.cloned()))
1012                }
1013                Self::Received(super::ReceivedFrame::Ethernet { destination, frame }) => {
1014                    Frame::Received(super::ReceivedFrame::Ethernet {
1015                        destination,
1016                        frame: frame.cloned(),
1017                    })
1018                }
1019                Self::Sent(SentFrame::Ip(frame)) => Frame::Sent(SentFrame::Ip(frame.cloned())),
1020                Self::Received(super::ReceivedFrame::Ip(frame)) => {
1021                    Frame::Received(super::ReceivedFrame::Ip(frame.cloned()))
1022                }
1023            }
1024        }
1025    }
1026
1027    impl EthernetFrame<&[u8]> {
1028        fn cloned(self) -> EthernetFrame<Vec<u8>> {
1029            let Self { src_mac, dst_mac, ethertype, body_offset, body } = self;
1030            EthernetFrame { src_mac, dst_mac, ethertype, body_offset, body: Vec::from(body) }
1031        }
1032    }
1033
1034    impl IpFrame<&[u8]> {
1035        fn cloned(self) -> IpFrame<Vec<u8>> {
1036            let Self { ip_version, body } = self;
1037            IpFrame { ip_version, body: Vec::from(body) }
1038        }
1039    }
1040
1041    impl<TimerId, Event: Debug, State, D: StrongDeviceIdentifier> DeviceSocketBindingsContext<D>
1042        for FakeBindingsCtx<TimerId, Event, State, ()>
1043    {
1044        fn receive_frame(
1045            &self,
1046            state: &DeviceSocketId<D::Weak, Self>,
1047            device: &D,
1048            frame: Frame<&[u8]>,
1049            raw_frame: &[u8],
1050        ) -> Result<(), ReceiveFrameError> {
1051            let ExternalSocketState(queue) = state.socket_state();
1052            let mut lock_guard = queue.lock();
1053            let RxQueue { frames, max_size } = lock_guard.deref_mut();
1054            if frames.len() < *max_size {
1055                frames.push(ReceivedFrame {
1056                    device: device.downgrade(),
1057                    frame: frame.cloned(),
1058                    raw: raw_frame.into(),
1059                });
1060                Ok(())
1061            } else {
1062                Err(ReceiveFrameError::QueueFull)
1063            }
1064        }
1065    }
1066
1067    impl<
1068        TimerId: Debug + PartialEq + Clone + Send + Sync + 'static,
1069        Event: Debug + 'static,
1070        State: 'static,
1071    > DeviceLayerStateTypes for FakeBindingsCtx<TimerId, Event, State, ()>
1072    {
1073        type EthernetDeviceState = ();
1074        type LoopbackDeviceState = ();
1075        type PureIpDeviceState = ();
1076        type BlackholeDeviceState = ();
1077        type DeviceIdentifier = MonotonicIdentifier;
1078    }
1079
1080    impl DeviceClassMatcher<()> for () {
1081        fn device_class_matches(&self, (): &()) -> bool {
1082            unimplemented!()
1083        }
1084    }
1085
1086    impl DeviceIdAndNameMatcher for MonotonicIdentifier {
1087        fn id_matches(&self, _id: &NonZeroU64) -> bool {
1088            unimplemented!()
1089        }
1090
1091        fn name_matches(&self, _name: &str) -> bool {
1092            unimplemented!()
1093        }
1094    }
1095}
1096
1097#[cfg(test)]
1098mod tests {
1099    use alloc::vec;
1100    use alloc::vec::Vec;
1101    use core::marker::PhantomData;
1102    use core::ops::Deref;
1103
1104    use crate::internal::socket::testutil::{ExternalSocketState, ReceivedFrame};
1105    use netstack3_base::testutil::{
1106        FakeReferencyDeviceId, FakeStrongDeviceId, FakeWeakDeviceId, MultipleDevicesId,
1107    };
1108    use netstack3_base::{
1109        CounterContext, CtxPair, NetworkSerializationContext, SendFrameError, SendableFrameMeta,
1110    };
1111    use netstack3_hashmap::HashMap;
1112    use packet::ParsablePacket;
1113    use test_case::test_case;
1114
1115    use super::*;
1116
1117    type FakeCoreCtx<D> = netstack3_base::testutil::FakeCoreCtx<FakeSockets<D>, (), D>;
1118    type FakeBindingsCtx = netstack3_base::testutil::FakeBindingsCtx<(), (), (), ()>;
1119    type FakeCtx<D> = CtxPair<FakeCoreCtx<D>, FakeBindingsCtx>;
1120
1121    /// A trait providing a shortcut to instantiate a [`DeviceSocketApi`] from a
1122    /// context.
1123    trait DeviceSocketApiExt: ContextPair + Sized {
1124        fn device_socket_api(&mut self) -> DeviceSocketApi<&mut Self> {
1125            DeviceSocketApi::new(self)
1126        }
1127    }
1128
1129    impl<O> DeviceSocketApiExt for O where O: ContextPair + Sized {}
1130
1131    #[derive(Derivative)]
1132    #[derivative(Default(bound = ""))]
1133    struct FakeSockets<D: FakeStrongDeviceId> {
1134        any_device_sockets: AnyDeviceSockets<D::Weak, FakeBindingsCtx>,
1135        device_sockets: HashMap<D, DeviceSockets<D::Weak, FakeBindingsCtx>>,
1136        all_sockets: AllSockets<D::Weak, FakeBindingsCtx>,
1137        /// The stack-wide counters for device sockets.
1138        counters: DeviceSocketCounters,
1139        sent_frames: Vec<Vec<u8>>,
1140    }
1141
1142    /// Tuple of references
1143    pub struct FakeSocketsMutRefs<'m, AnyDevice, AllSockets, Devices, Device>(
1144        &'m mut AnyDevice,
1145        &'m mut AllSockets,
1146        &'m mut Devices,
1147        PhantomData<Device>,
1148        &'m DeviceSocketCounters,
1149    );
1150
1151    /// Helper trait to allow treating a `&mut self` as a
1152    /// [`FakeSocketsMutRefs`].
1153    pub trait AsFakeSocketsMutRefs {
1154        type AnyDevice: 'static;
1155        type AllSockets: 'static;
1156        type Devices: 'static;
1157        type Device: 'static;
1158        fn as_sockets_ref(
1159            &mut self,
1160        ) -> FakeSocketsMutRefs<'_, Self::AnyDevice, Self::AllSockets, Self::Devices, Self::Device>;
1161    }
1162
1163    impl<D: FakeStrongDeviceId> AsFakeSocketsMutRefs for FakeCoreCtx<D> {
1164        type AnyDevice = AnyDeviceSockets<D::Weak, FakeBindingsCtx>;
1165        type AllSockets = AllSockets<D::Weak, FakeBindingsCtx>;
1166        type Devices = HashMap<D, DeviceSockets<D::Weak, FakeBindingsCtx>>;
1167        type Device = D;
1168
1169        fn as_sockets_ref(
1170            &mut self,
1171        ) -> FakeSocketsMutRefs<
1172            '_,
1173            AnyDeviceSockets<D::Weak, FakeBindingsCtx>,
1174            AllSockets<D::Weak, FakeBindingsCtx>,
1175            HashMap<D, DeviceSockets<D::Weak, FakeBindingsCtx>>,
1176            D,
1177        > {
1178            let FakeSockets {
1179                any_device_sockets,
1180                device_sockets,
1181                all_sockets,
1182                counters,
1183                sent_frames: _,
1184            } = &mut self.state;
1185            FakeSocketsMutRefs(
1186                any_device_sockets,
1187                all_sockets,
1188                device_sockets,
1189                PhantomData,
1190                counters,
1191            )
1192        }
1193    }
1194
1195    impl<'m, AnyDevice: 'static, AllSockets: 'static, Devices: 'static, Device: 'static>
1196        AsFakeSocketsMutRefs for FakeSocketsMutRefs<'m, AnyDevice, AllSockets, Devices, Device>
1197    {
1198        type AnyDevice = AnyDevice;
1199        type AllSockets = AllSockets;
1200        type Devices = Devices;
1201        type Device = Device;
1202
1203        fn as_sockets_ref(
1204            &mut self,
1205        ) -> FakeSocketsMutRefs<'_, AnyDevice, AllSockets, Devices, Device> {
1206            let Self(any_device, all_sockets, devices, PhantomData, counters) = self;
1207            FakeSocketsMutRefs(any_device, all_sockets, devices, PhantomData, counters)
1208        }
1209    }
1210
1211    impl<D: Clone> TargetDevice<&D> {
1212        fn with_weak_id(&self) -> TargetDevice<FakeWeakDeviceId<D>> {
1213            match self {
1214                TargetDevice::AnyDevice => TargetDevice::AnyDevice,
1215                TargetDevice::SpecificDevice(d) => {
1216                    TargetDevice::SpecificDevice(FakeWeakDeviceId((*d).clone()))
1217                }
1218            }
1219        }
1220    }
1221
1222    impl<D: Eq + Hash + FakeStrongDeviceId> FakeSockets<D> {
1223        fn new(devices: impl IntoIterator<Item = D>) -> Self {
1224            let device_sockets =
1225                devices.into_iter().map(|d| (d, DeviceSockets::default())).collect();
1226            Self {
1227                any_device_sockets: AnyDeviceSockets::default(),
1228                device_sockets,
1229                all_sockets: Default::default(),
1230                counters: Default::default(),
1231                sent_frames: Default::default(),
1232            }
1233        }
1234    }
1235
1236    impl<
1237        'm,
1238        DeviceId: FakeStrongDeviceId,
1239        As: AsFakeSocketsMutRefs
1240            + DeviceIdContext<AnyDevice, DeviceId = DeviceId, WeakDeviceId = DeviceId::Weak>,
1241    > SocketStateAccessor<FakeBindingsCtx> for As
1242    {
1243        fn with_socket_state<F: FnOnce(&Target<Self::WeakDeviceId>) -> R, R>(
1244            &mut self,
1245            socket: &DeviceSocketId<Self::WeakDeviceId, FakeBindingsCtx>,
1246            cb: F,
1247        ) -> R {
1248            let DeviceSocketId(rc) = socket;
1249            // NB: Circumvent lock ordering for tests.
1250            let target = rc.target.lock();
1251            cb(&target)
1252        }
1253
1254        fn with_socket_state_mut<F: FnOnce(&mut Target<Self::WeakDeviceId>) -> R, R>(
1255            &mut self,
1256            socket: &DeviceSocketId<Self::WeakDeviceId, FakeBindingsCtx>,
1257            cb: F,
1258        ) -> R {
1259            let DeviceSocketId(rc) = socket;
1260            // NB: Circumvent lock ordering for tests.
1261            let mut target = rc.target.lock();
1262            cb(&mut target)
1263        }
1264    }
1265
1266    impl<
1267        'm,
1268        DeviceId: FakeStrongDeviceId,
1269        As: AsFakeSocketsMutRefs<
1270                Devices = HashMap<DeviceId, DeviceSockets<DeviceId::Weak, FakeBindingsCtx>>,
1271            > + DeviceIdContext<AnyDevice, DeviceId = DeviceId, WeakDeviceId = DeviceId::Weak>,
1272    > DeviceSocketAccessor<FakeBindingsCtx> for As
1273    {
1274        type DeviceSocketCoreCtx<'a> =
1275            FakeSocketsMutRefs<'a, As::AnyDevice, As::AllSockets, HashSet<DeviceId>, DeviceId>;
1276        fn with_device_sockets<
1277            F: FnOnce(
1278                &DeviceSockets<Self::WeakDeviceId, FakeBindingsCtx>,
1279                &mut Self::DeviceSocketCoreCtx<'_>,
1280            ) -> R,
1281            R,
1282        >(
1283            &mut self,
1284            device: &Self::DeviceId,
1285            cb: F,
1286        ) -> R {
1287            let FakeSocketsMutRefs(any_device, all_sockets, device_sockets, PhantomData, counters) =
1288                self.as_sockets_ref();
1289            let mut devices = device_sockets.keys().cloned().collect();
1290            let device = device_sockets.get(device).unwrap();
1291            cb(
1292                device,
1293                &mut FakeSocketsMutRefs(
1294                    any_device,
1295                    all_sockets,
1296                    &mut devices,
1297                    PhantomData,
1298                    counters,
1299                ),
1300            )
1301        }
1302        fn with_device_sockets_mut<
1303            F: FnOnce(
1304                &mut DeviceSockets<Self::WeakDeviceId, FakeBindingsCtx>,
1305                &mut Self::DeviceSocketCoreCtx<'_>,
1306            ) -> R,
1307            R,
1308        >(
1309            &mut self,
1310            device: &Self::DeviceId,
1311            cb: F,
1312        ) -> R {
1313            let FakeSocketsMutRefs(any_device, all_sockets, device_sockets, PhantomData, counters) =
1314                self.as_sockets_ref();
1315            let mut devices = device_sockets.keys().cloned().collect();
1316            let device = device_sockets.get_mut(device).unwrap();
1317            cb(
1318                device,
1319                &mut FakeSocketsMutRefs(
1320                    any_device,
1321                    all_sockets,
1322                    &mut devices,
1323                    PhantomData,
1324                    counters,
1325                ),
1326            )
1327        }
1328    }
1329
1330    impl<
1331        'm,
1332        DeviceId: FakeStrongDeviceId,
1333        As: AsFakeSocketsMutRefs<
1334                AnyDevice = AnyDeviceSockets<DeviceId::Weak, FakeBindingsCtx>,
1335                AllSockets = AllSockets<DeviceId::Weak, FakeBindingsCtx>,
1336                Devices = HashMap<DeviceId, DeviceSockets<DeviceId::Weak, FakeBindingsCtx>>,
1337            > + DeviceIdContext<AnyDevice, DeviceId = DeviceId, WeakDeviceId = DeviceId::Weak>,
1338    > DeviceSocketContext<FakeBindingsCtx> for As
1339    {
1340        type SocketTablesCoreCtx<'a> = FakeSocketsMutRefs<
1341            'a,
1342            (),
1343            (),
1344            HashMap<DeviceId, DeviceSockets<DeviceId::Weak, FakeBindingsCtx>>,
1345            DeviceId,
1346        >;
1347
1348        fn with_any_device_sockets<
1349            F: FnOnce(
1350                &AnyDeviceSockets<Self::WeakDeviceId, FakeBindingsCtx>,
1351                &mut Self::SocketTablesCoreCtx<'_>,
1352            ) -> R,
1353            R,
1354        >(
1355            &mut self,
1356            cb: F,
1357        ) -> R {
1358            let FakeSocketsMutRefs(
1359                any_device_sockets,
1360                _all_sockets,
1361                device_sockets,
1362                PhantomData,
1363                counters,
1364            ) = self.as_sockets_ref();
1365            cb(
1366                any_device_sockets,
1367                &mut FakeSocketsMutRefs(&mut (), &mut (), device_sockets, PhantomData, counters),
1368            )
1369        }
1370        fn with_any_device_sockets_mut<
1371            F: FnOnce(
1372                &mut AnyDeviceSockets<Self::WeakDeviceId, FakeBindingsCtx>,
1373                &mut Self::SocketTablesCoreCtx<'_>,
1374            ) -> R,
1375            R,
1376        >(
1377            &mut self,
1378            cb: F,
1379        ) -> R {
1380            let FakeSocketsMutRefs(
1381                any_device_sockets,
1382                _all_sockets,
1383                device_sockets,
1384                PhantomData,
1385                counters,
1386            ) = self.as_sockets_ref();
1387            cb(
1388                any_device_sockets,
1389                &mut FakeSocketsMutRefs(&mut (), &mut (), device_sockets, PhantomData, counters),
1390            )
1391        }
1392
1393        fn with_all_device_sockets<
1394            F: FnOnce(
1395                &AllSockets<Self::WeakDeviceId, FakeBindingsCtx>,
1396                &mut Self::SocketTablesCoreCtx<'_>,
1397            ) -> R,
1398            R,
1399        >(
1400            &mut self,
1401            cb: F,
1402        ) -> R {
1403            let FakeSocketsMutRefs(
1404                _any_device_sockets,
1405                all_sockets,
1406                device_sockets,
1407                PhantomData,
1408                counters,
1409            ) = self.as_sockets_ref();
1410            cb(
1411                all_sockets,
1412                &mut FakeSocketsMutRefs(&mut (), &mut (), device_sockets, PhantomData, counters),
1413            )
1414        }
1415
1416        fn with_all_device_sockets_mut<
1417            F: FnOnce(&mut AllSockets<Self::WeakDeviceId, FakeBindingsCtx>) -> R,
1418            R,
1419        >(
1420            &mut self,
1421            cb: F,
1422        ) -> R {
1423            let FakeSocketsMutRefs(_, all_sockets, _, _, _) = self.as_sockets_ref();
1424            cb(all_sockets)
1425        }
1426    }
1427
1428    impl<'m, X, Y, Z, D: FakeStrongDeviceId> DeviceIdContext<AnyDevice>
1429        for FakeSocketsMutRefs<'m, X, Y, Z, D>
1430    {
1431        type DeviceId = D;
1432        type WeakDeviceId = FakeWeakDeviceId<D>;
1433    }
1434
1435    impl<D: FakeStrongDeviceId> CounterContext<DeviceSocketCounters> for FakeCoreCtx<D> {
1436        fn counters(&self) -> &DeviceSocketCounters {
1437            &self.state.counters
1438        }
1439    }
1440
1441    impl<D: FakeStrongDeviceId>
1442        ResourceCounterContext<DeviceSocketId<D::Weak, FakeBindingsCtx>, DeviceSocketCounters>
1443        for FakeCoreCtx<D>
1444    {
1445        fn per_resource_counters<'a>(
1446            &'a self,
1447            socket: &'a DeviceSocketId<D::Weak, FakeBindingsCtx>,
1448        ) -> &'a DeviceSocketCounters {
1449            socket.counters()
1450        }
1451    }
1452
1453    impl<'m, X, Y, Z, D> CounterContext<DeviceSocketCounters> for FakeSocketsMutRefs<'m, X, Y, Z, D> {
1454        fn counters(&self) -> &DeviceSocketCounters {
1455            let FakeSocketsMutRefs(_, _, _, _, counters) = self;
1456            counters
1457        }
1458    }
1459
1460    impl<'m, X, Y, Z, D: FakeStrongDeviceId>
1461        ResourceCounterContext<DeviceSocketId<D::Weak, FakeBindingsCtx>, DeviceSocketCounters>
1462        for FakeSocketsMutRefs<'m, X, Y, Z, D>
1463    {
1464        fn per_resource_counters<'a>(
1465            &'a self,
1466            socket: &'a DeviceSocketId<D::Weak, FakeBindingsCtx>,
1467        ) -> &'a DeviceSocketCounters {
1468            socket.counters()
1469        }
1470    }
1471
1472    const SOME_PROTOCOL: NonZeroU16 = NonZeroU16::new(2000).unwrap();
1473
1474    #[test]
1475    fn create_remove() {
1476        let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new(
1477            MultipleDevicesId::all(),
1478        )));
1479        let mut api = ctx.device_socket_api();
1480
1481        let bound = api.create(Default::default());
1482        assert_eq!(
1483            api.get_info(&bound),
1484            SocketInfo { device: TargetDevice::AnyDevice, protocol: None }
1485        );
1486
1487        let ExternalSocketState(_received_frames) = api.remove(bound).into_removed();
1488    }
1489
1490    #[test_case(TargetDevice::AnyDevice)]
1491    #[test_case(TargetDevice::SpecificDevice(&MultipleDevicesId::A))]
1492    fn test_set_device(device: TargetDevice<&MultipleDevicesId>) {
1493        let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new(
1494            MultipleDevicesId::all(),
1495        )));
1496        let mut api = ctx.device_socket_api();
1497
1498        let bound = api.create(Default::default());
1499        api.set_device(&bound, device.clone());
1500        assert_eq!(
1501            api.get_info(&bound),
1502            SocketInfo { device: device.with_weak_id(), protocol: None }
1503        );
1504
1505        let device_sockets = &api.core_ctx().state.device_sockets;
1506        if let TargetDevice::SpecificDevice(d) = device {
1507            let DeviceSockets(socket_ids) = device_sockets.get(&d).expect("device state exists");
1508            assert_eq!(socket_ids, &HashSet::from([bound]));
1509        }
1510    }
1511
1512    #[test]
1513    fn update_device() {
1514        let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new(
1515            MultipleDevicesId::all(),
1516        )));
1517        let mut api = ctx.device_socket_api();
1518        let bound = api.create(Default::default());
1519
1520        api.set_device(&bound, TargetDevice::SpecificDevice(&MultipleDevicesId::A));
1521
1522        // Now update the device and make sure the socket only appears in the
1523        // one device's list.
1524        api.set_device(&bound, TargetDevice::SpecificDevice(&MultipleDevicesId::B));
1525        assert_eq!(
1526            api.get_info(&bound),
1527            SocketInfo {
1528                device: TargetDevice::SpecificDevice(FakeWeakDeviceId(MultipleDevicesId::B)),
1529                protocol: None
1530            }
1531        );
1532
1533        let device_sockets = &api.core_ctx().state.device_sockets;
1534        let device_socket_lists = device_sockets
1535            .iter()
1536            .map(|(d, DeviceSockets(indexes))| (d, indexes.iter().collect()))
1537            .collect::<HashMap<_, _>>();
1538
1539        assert_eq!(
1540            device_socket_lists,
1541            HashMap::from([
1542                (&MultipleDevicesId::A, vec![]),
1543                (&MultipleDevicesId::B, vec![&bound]),
1544                (&MultipleDevicesId::C, vec![])
1545            ])
1546        );
1547    }
1548
1549    #[test_case(Protocol::All, TargetDevice::AnyDevice)]
1550    #[test_case(Protocol::Specific(SOME_PROTOCOL), TargetDevice::AnyDevice)]
1551    #[test_case(Protocol::All, TargetDevice::SpecificDevice(&MultipleDevicesId::A))]
1552    #[test_case(
1553        Protocol::Specific(SOME_PROTOCOL),
1554        TargetDevice::SpecificDevice(&MultipleDevicesId::A)
1555    )]
1556    fn create_set_device_and_protocol_remove_multiple(
1557        protocol: Protocol,
1558        device: TargetDevice<&MultipleDevicesId>,
1559    ) {
1560        let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new(
1561            MultipleDevicesId::all(),
1562        )));
1563        let mut api = ctx.device_socket_api();
1564
1565        let mut sockets = [(); 3].map(|()| api.create(Default::default()));
1566        for socket in &mut sockets {
1567            api.set_device_and_protocol(socket, device.clone(), protocol);
1568            assert_eq!(
1569                api.get_info(socket),
1570                SocketInfo { device: device.with_weak_id(), protocol: Some(protocol) }
1571            );
1572        }
1573
1574        for socket in sockets {
1575            let ExternalSocketState(_received_frames) = api.remove(socket).into_removed();
1576        }
1577    }
1578
1579    #[test]
1580    fn change_device_after_removal() {
1581        let device_to_remove = FakeReferencyDeviceId::default();
1582        let device_to_maintain = FakeReferencyDeviceId::default();
1583        let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new([
1584            device_to_remove.clone(),
1585            device_to_maintain.clone(),
1586        ])));
1587        let mut api = ctx.device_socket_api();
1588
1589        let bound = api.create(Default::default());
1590        // Set the device for the socket before removing the device state
1591        // entirely.
1592        api.set_device(&bound, TargetDevice::SpecificDevice(&device_to_remove));
1593
1594        // Now remove the device; this should cause future attempts to upgrade
1595        // the device ID to fail.
1596        device_to_remove.mark_removed();
1597
1598        // Changing the device should gracefully handle the fact that the
1599        // earlier-bound device is now gone.
1600        api.set_device(&bound, TargetDevice::SpecificDevice(&device_to_maintain));
1601        assert_eq!(
1602            api.get_info(&bound),
1603            SocketInfo {
1604                device: TargetDevice::SpecificDevice(FakeWeakDeviceId(device_to_maintain.clone())),
1605                protocol: None,
1606            }
1607        );
1608
1609        let device_sockets = &api.core_ctx().state.device_sockets;
1610        let DeviceSockets(weak_sockets) =
1611            device_sockets.get(&device_to_maintain).expect("device state exists");
1612        assert_eq!(weak_sockets, &HashSet::from([bound]));
1613    }
1614
1615    struct TestData;
1616    impl TestData {
1617        const SRC_MAC: Mac = Mac::new([0, 1, 2, 3, 4, 5]);
1618        const DST_MAC: Mac = Mac::new([6, 7, 8, 9, 10, 11]);
1619        /// Arbitrary protocol number.
1620        const PROTO: NonZeroU16 = NonZeroU16::new(0x08AB).unwrap();
1621        const BODY: &'static [u8] = b"some pig";
1622        const BUFFER: &'static [u8] = &[
1623            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',
1624            b'i', b'g',
1625        ];
1626        const BUFFER_OFFSET: usize = Self::BUFFER.len() - Self::BODY.len();
1627
1628        /// Creates an EthernetFrame with the values specified above.
1629        fn frame() -> packet_formats::ethernet::EthernetFrame<&'static [u8]> {
1630            let mut buffer_view = Self::BUFFER;
1631            packet_formats::ethernet::EthernetFrame::parse(
1632                &mut buffer_view,
1633                EthernetFrameLengthCheck::NoCheck,
1634            )
1635            .unwrap()
1636        }
1637    }
1638
1639    const WRONG_PROTO: NonZeroU16 = NonZeroU16::new(0x08ff).unwrap();
1640
1641    fn make_bound<D: FakeStrongDeviceId>(
1642        ctx: &mut FakeCtx<D>,
1643        device: TargetDevice<D>,
1644        protocol: Option<Protocol>,
1645        state: ExternalSocketState<D::Weak>,
1646    ) -> DeviceSocketId<D::Weak, FakeBindingsCtx> {
1647        let mut api = ctx.device_socket_api();
1648        let id = api.create(state);
1649        let device = match &device {
1650            TargetDevice::AnyDevice => TargetDevice::AnyDevice,
1651            TargetDevice::SpecificDevice(d) => TargetDevice::SpecificDevice(d),
1652        };
1653        match protocol {
1654            Some(protocol) => api.set_device_and_protocol(&id, device, protocol),
1655            None => api.set_device(&id, device),
1656        };
1657        id
1658    }
1659
1660    /// Deliver one frame to the provided contexts and return the IDs of the
1661    /// sockets it was delivered to.
1662    fn deliver_one_frame(
1663        delivered_frame: Frame<&[u8]>,
1664        FakeCtx { core_ctx, bindings_ctx }: &mut FakeCtx<MultipleDevicesId>,
1665    ) -> HashSet<DeviceSocketId<FakeWeakDeviceId<MultipleDevicesId>, FakeBindingsCtx>> {
1666        DeviceSocketHandler::handle_frame(
1667            core_ctx,
1668            bindings_ctx,
1669            &MultipleDevicesId::A,
1670            delivered_frame.clone(),
1671            TestData::BUFFER,
1672        );
1673
1674        let FakeSockets {
1675            all_sockets: AllSockets(all_sockets),
1676            any_device_sockets: _,
1677            device_sockets: _,
1678            counters: _,
1679            sent_frames: _,
1680        } = &core_ctx.state;
1681
1682        all_sockets
1683            .iter()
1684            .filter_map(|(id, _primary)| {
1685                let DeviceSocketId(rc) = &id;
1686                let ExternalSocketState(frames) = &rc.external_state;
1687                let lock_guard = frames.lock();
1688                let testutil::RxQueue { frames, .. } = lock_guard.deref();
1689                (!frames.is_empty()).then(|| {
1690                    assert_eq!(
1691                        &*frames,
1692                        &[ReceivedFrame {
1693                            device: FakeWeakDeviceId(MultipleDevicesId::A),
1694                            frame: delivered_frame.cloned(),
1695                            raw: TestData::BUFFER.into(),
1696                        }]
1697                    );
1698                    id.clone()
1699                })
1700            })
1701            .collect()
1702    }
1703
1704    #[test]
1705    fn receive_frame_deliver_to_multiple() {
1706        let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new(
1707            MultipleDevicesId::all(),
1708        )));
1709
1710        use Protocol::*;
1711        use TargetDevice::*;
1712        let never_bound = {
1713            let state = ExternalSocketState::<FakeWeakDeviceId<MultipleDevicesId>>::default();
1714            ctx.device_socket_api().create(state)
1715        };
1716
1717        let mut make_bound = |device, protocol| {
1718            let state = ExternalSocketState::<FakeWeakDeviceId<MultipleDevicesId>>::default();
1719            make_bound(&mut ctx, device, protocol, state)
1720        };
1721        let bound_a_no_protocol = make_bound(SpecificDevice(MultipleDevicesId::A), None);
1722        let bound_a_all_protocols = make_bound(SpecificDevice(MultipleDevicesId::A), Some(All));
1723        let bound_a_right_protocol =
1724            make_bound(SpecificDevice(MultipleDevicesId::A), Some(Specific(TestData::PROTO)));
1725        let bound_a_wrong_protocol =
1726            make_bound(SpecificDevice(MultipleDevicesId::A), Some(Specific(WRONG_PROTO)));
1727        let bound_b_no_protocol = make_bound(SpecificDevice(MultipleDevicesId::B), None);
1728        let bound_b_all_protocols = make_bound(SpecificDevice(MultipleDevicesId::B), Some(All));
1729        let bound_b_right_protocol =
1730            make_bound(SpecificDevice(MultipleDevicesId::B), Some(Specific(TestData::PROTO)));
1731        let bound_b_wrong_protocol =
1732            make_bound(SpecificDevice(MultipleDevicesId::B), Some(Specific(WRONG_PROTO)));
1733        let bound_any_no_protocol = make_bound(AnyDevice, None);
1734        let bound_any_all_protocols = make_bound(AnyDevice, Some(All));
1735        let bound_any_right_protocol = make_bound(AnyDevice, Some(Specific(TestData::PROTO)));
1736        let bound_any_wrong_protocol = make_bound(AnyDevice, Some(Specific(WRONG_PROTO)));
1737
1738        let mut sockets_with_received_frames = deliver_one_frame(
1739            super::ReceivedFrame::from_ethernet(
1740                TestData::frame(),
1741                FrameDestination::Individual { local: true },
1742            )
1743            .into(),
1744            &mut ctx,
1745        );
1746
1747        let sockets_not_expecting_frames = [
1748            never_bound,
1749            bound_a_no_protocol,
1750            bound_a_wrong_protocol,
1751            bound_b_no_protocol,
1752            bound_b_all_protocols,
1753            bound_b_right_protocol,
1754            bound_b_wrong_protocol,
1755            bound_any_no_protocol,
1756            bound_any_wrong_protocol,
1757        ];
1758        let sockets_expecting_frames = [
1759            bound_a_all_protocols,
1760            bound_a_right_protocol,
1761            bound_any_all_protocols,
1762            bound_any_right_protocol,
1763        ];
1764
1765        for (n, socket) in sockets_expecting_frames.iter().enumerate() {
1766            assert!(
1767                sockets_with_received_frames.remove(&socket),
1768                "socket {n} didn't receive the frame"
1769            );
1770        }
1771        assert!(sockets_with_received_frames.is_empty());
1772
1773        // Verify Counters were set appropriately for each socket.
1774        for (n, socket) in sockets_expecting_frames.iter().enumerate() {
1775            assert_eq!(socket.counters().rx_frames.get(), 1, "socket {n} has wrong rx_frames");
1776        }
1777        for (n, socket) in sockets_not_expecting_frames.iter().enumerate() {
1778            assert_eq!(socket.counters().rx_frames.get(), 0, "socket {n} has wrong rx_frames");
1779        }
1780    }
1781
1782    #[test]
1783    fn sent_frame_deliver_to_multiple() {
1784        let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new(
1785            MultipleDevicesId::all(),
1786        )));
1787
1788        use Protocol::*;
1789        use TargetDevice::*;
1790        let never_bound = {
1791            let state = ExternalSocketState::<FakeWeakDeviceId<MultipleDevicesId>>::default();
1792            ctx.device_socket_api().create(state)
1793        };
1794
1795        let mut make_bound = |device, protocol| {
1796            let state = ExternalSocketState::<FakeWeakDeviceId<MultipleDevicesId>>::default();
1797            make_bound(&mut ctx, device, protocol, state)
1798        };
1799        let bound_a_no_protocol = make_bound(SpecificDevice(MultipleDevicesId::A), None);
1800        let bound_a_all_protocols = make_bound(SpecificDevice(MultipleDevicesId::A), Some(All));
1801        let bound_a_same_protocol =
1802            make_bound(SpecificDevice(MultipleDevicesId::A), Some(Specific(TestData::PROTO)));
1803        let bound_a_wrong_protocol =
1804            make_bound(SpecificDevice(MultipleDevicesId::A), Some(Specific(WRONG_PROTO)));
1805        let bound_b_no_protocol = make_bound(SpecificDevice(MultipleDevicesId::B), None);
1806        let bound_b_all_protocols = make_bound(SpecificDevice(MultipleDevicesId::B), Some(All));
1807        let bound_b_same_protocol =
1808            make_bound(SpecificDevice(MultipleDevicesId::B), Some(Specific(TestData::PROTO)));
1809        let bound_b_wrong_protocol =
1810            make_bound(SpecificDevice(MultipleDevicesId::B), Some(Specific(WRONG_PROTO)));
1811        let bound_any_no_protocol = make_bound(AnyDevice, None);
1812        let bound_any_all_protocols = make_bound(AnyDevice, Some(All));
1813        let bound_any_same_protocol = make_bound(AnyDevice, Some(Specific(TestData::PROTO)));
1814        let bound_any_wrong_protocol = make_bound(AnyDevice, Some(Specific(WRONG_PROTO)));
1815
1816        let mut sockets_with_received_frames =
1817            deliver_one_frame(SentFrame::Ethernet(TestData::frame().into()).into(), &mut ctx);
1818
1819        let sockets_not_expecting_frames = [
1820            never_bound,
1821            bound_a_no_protocol,
1822            bound_a_same_protocol,
1823            bound_a_wrong_protocol,
1824            bound_b_no_protocol,
1825            bound_b_all_protocols,
1826            bound_b_same_protocol,
1827            bound_b_wrong_protocol,
1828            bound_any_no_protocol,
1829            bound_any_same_protocol,
1830            bound_any_wrong_protocol,
1831        ];
1832        // Only any-protocol sockets receive sent frames.
1833        let sockets_expecting_frames = [bound_a_all_protocols, bound_any_all_protocols];
1834
1835        for (n, socket) in sockets_expecting_frames.iter().enumerate() {
1836            assert!(
1837                sockets_with_received_frames.remove(&socket),
1838                "socket {n} didn't receive the frame"
1839            );
1840        }
1841        assert!(sockets_with_received_frames.is_empty());
1842
1843        // Verify Counters were set appropriately for each socket.
1844        for (n, socket) in sockets_expecting_frames.iter().enumerate() {
1845            assert_eq!(socket.counters().rx_frames.get(), 1, "socket {n} has wrong rx_frames");
1846        }
1847        for (n, socket) in sockets_not_expecting_frames.iter().enumerate() {
1848            assert_eq!(socket.counters().rx_frames.get(), 0, "socket {n} has wrong rx_frames");
1849        }
1850    }
1851
1852    #[test]
1853    fn deliver_multiple_frames() {
1854        let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new(
1855            MultipleDevicesId::all(),
1856        )));
1857        let socket = make_bound(
1858            &mut ctx,
1859            TargetDevice::AnyDevice,
1860            Some(Protocol::All),
1861            ExternalSocketState::default(),
1862        );
1863        let FakeCtx { mut core_ctx, mut bindings_ctx } = ctx;
1864
1865        const RECEIVE_COUNT: usize = 10;
1866        for _ in 0..RECEIVE_COUNT {
1867            DeviceSocketHandler::handle_frame(
1868                &mut core_ctx,
1869                &mut bindings_ctx,
1870                &MultipleDevicesId::A,
1871                super::ReceivedFrame::from_ethernet(
1872                    TestData::frame(),
1873                    FrameDestination::Individual { local: true },
1874                )
1875                .into(),
1876                TestData::BUFFER,
1877            );
1878        }
1879
1880        let FakeSockets {
1881            all_sockets: AllSockets(mut all_sockets),
1882            any_device_sockets: _,
1883            device_sockets: _,
1884            counters: _,
1885            sent_frames: _,
1886        } = core_ctx.into_state();
1887        let primary = all_sockets.remove(&socket).unwrap();
1888        let PrimaryDeviceSocketId(primary) = primary;
1889        assert!(all_sockets.is_empty());
1890        drop(socket);
1891        let SocketState { external_state: ExternalSocketState(received), counters, target: _ } =
1892            PrimaryRc::unwrap(primary);
1893        assert_eq!(
1894            received.into_inner().frames,
1895            vec![
1896                ReceivedFrame {
1897                    device: FakeWeakDeviceId(MultipleDevicesId::A),
1898                    frame: Frame::Received(super::ReceivedFrame::Ethernet {
1899                        destination: FrameDestination::Individual { local: true },
1900                        frame: EthernetFrame {
1901                            src_mac: TestData::SRC_MAC,
1902                            dst_mac: TestData::DST_MAC,
1903                            ethertype: Some(TestData::PROTO.get().into()),
1904                            body_offset: TestData::BUFFER_OFFSET,
1905                            body: Vec::from(TestData::BODY),
1906                        }
1907                    }),
1908                    raw: TestData::BUFFER.into()
1909                };
1910                RECEIVE_COUNT
1911            ]
1912        );
1913        assert_eq!(counters.rx_frames.get(), u64::try_from(RECEIVE_COUNT).unwrap());
1914    }
1915
1916    #[test]
1917    fn deliver_frame_queue_full() {
1918        let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new(
1919            MultipleDevicesId::all(),
1920        )));
1921
1922        // Simulate a full RX queue for sock1.
1923        let sock1 = make_bound(
1924            &mut ctx,
1925            TargetDevice::AnyDevice,
1926            Some(Protocol::All),
1927            ExternalSocketState(Mutex::new(testutil::RxQueue { frames: vec![], max_size: 0 })),
1928        );
1929        let sock2 = make_bound(
1930            &mut ctx,
1931            TargetDevice::AnyDevice,
1932            Some(Protocol::All),
1933            ExternalSocketState::default(),
1934        );
1935
1936        let FakeCtx { mut core_ctx, mut bindings_ctx } = ctx;
1937
1938        DeviceSocketHandler::handle_frame(
1939            &mut core_ctx,
1940            &mut bindings_ctx,
1941            &MultipleDevicesId::A,
1942            super::ReceivedFrame::from_ethernet(
1943                TestData::frame(),
1944                FrameDestination::Individual { local: true },
1945            )
1946            .into(),
1947            TestData::BUFFER,
1948        );
1949
1950        assert_eq!(core_ctx.state.counters.rx_frames.get(), 2);
1951        assert_eq!(core_ctx.state.counters.rx_queue_full.get(), 1);
1952        assert_eq!(sock1.counters().rx_frames.get(), 1);
1953        assert_eq!(sock1.counters().rx_queue_full.get(), 1);
1954        assert_eq!(sock2.counters().rx_frames.get(), 1);
1955        assert_eq!(sock2.counters().rx_queue_full.get(), 0);
1956
1957        // Drop our strong references to the sockets so that `core_ctx` can tear
1958        // down successfully.
1959        drop(sock1);
1960        drop(sock2);
1961    }
1962
1963    pub struct FakeSendMetadata;
1964    impl DeviceSocketSendTypes for AnyDevice {
1965        type Metadata = FakeSendMetadata;
1966    }
1967    impl<BC, D: FakeStrongDeviceId> SendableFrameMeta<FakeCoreCtx<D>, BC>
1968        for DeviceSocketMetadata<AnyDevice, D>
1969    {
1970        fn send_meta<S>(
1971            self,
1972            core_ctx: &mut FakeCoreCtx<D>,
1973            _bindings_ctx: &mut BC,
1974            frame: S,
1975        ) -> Result<(), SendFrameError<S>>
1976        where
1977            S: NetworkSerializer,
1978            S::Buffer: BufferMut,
1979        {
1980            let frame = match frame.serialize_vec_outer(&mut NetworkSerializationContext::default())
1981            {
1982                Err(e) => {
1983                    let _: (packet::SerializeError<core::convert::Infallible>, _) = e;
1984                    unreachable!()
1985                }
1986                Ok(frame) => frame.unwrap_a().as_ref().to_vec(),
1987            };
1988            core_ctx.state.sent_frames.push(frame);
1989            Ok(())
1990        }
1991    }
1992
1993    #[test]
1994    fn send_multiple_frames() {
1995        let mut ctx = FakeCtx::with_core_ctx(FakeCoreCtx::with_state(FakeSockets::new(
1996            MultipleDevicesId::all(),
1997        )));
1998
1999        const DEVICE: MultipleDevicesId = MultipleDevicesId::A;
2000        let socket = make_bound(
2001            &mut ctx,
2002            TargetDevice::SpecificDevice(DEVICE),
2003            Some(Protocol::All),
2004            ExternalSocketState::default(),
2005        );
2006        let mut api = ctx.device_socket_api();
2007
2008        const SEND_COUNT: usize = 10;
2009        const PAYLOAD: &'static [u8] = &[1, 2, 3, 4, 5];
2010        for _ in 0..SEND_COUNT {
2011            let buf = packet::Buf::new(PAYLOAD.to_vec(), ..);
2012            api.send_frame(
2013                &socket,
2014                DeviceSocketMetadata { device_id: DEVICE, metadata: FakeSendMetadata },
2015                buf,
2016            )
2017            .expect("send failed");
2018        }
2019
2020        assert_eq!(ctx.core_ctx().state.sent_frames, vec![PAYLOAD.to_vec(); SEND_COUNT]);
2021
2022        assert_eq!(socket.counters().tx_frames.get(), u64::try_from(SEND_COUNT).unwrap());
2023    }
2024}