// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! The Ethernet protocol.

use alloc::{collections::HashMap, collections::VecDeque, vec::Vec};
use core::fmt::Debug;

use log::{debug, trace};
use net_types::{
    ethernet::Mac,
    ip::{
        AddrSubnet, Ip, IpAddr, IpAddress, Ipv4, Ipv4Addr, Ipv6, Ipv6Addr,
        UnicastOrMulticastIpv6Addr,
    },
    BroadcastAddress, MulticastAddr, MulticastAddress, SpecifiedAddr, UnicastAddr, UnicastAddress,
    Witness,
};
use packet::{Buf, BufferMut, EmptyBuf, Nested, Serializer};
use packet_formats::{
    arp::{peek_arp_types, ArpHardwareType, ArpNetworkType},
    ethernet::{
        EtherType, EthernetFrame, EthernetFrameBuilder, EthernetFrameLengthCheck, EthernetIpExt,
    },
    utils::NonZeroDuration,
};

use crate::{
    context::{FrameContext, RngContext, StateContext},
    data_structures::ref_counted_hash_map::{InsertResult, RefCountedHashSet, RemoveResult},
    device::{
        arp::{self, ArpContext, ArpDeviceIdContext, ArpFrameMetadata, ArpState, ArpTimerId},
        link::LinkDevice,
        ndp::{self, NdpContext, NdpHandler, NdpState, NdpTimerId},
        BufferIpLinkDeviceContext, DeviceIdContext, EthernetDeviceId, FrameDestination,
        IpLinkDeviceContext, IpLinkDeviceNonSyncContext, RecvIpFrameMeta,
    },
    error::ExistsError,
    ip::device::state::{AddrConfig, IpDeviceState},
    NonSyncContext, SyncCtx,
};

const ETHERNET_MAX_PENDING_FRAMES: usize = 10;

impl From<Mac> for FrameDestination {
    fn from(mac: Mac) -> FrameDestination {
        if mac.is_broadcast() {
            FrameDestination::Broadcast
        } else if mac.is_multicast() {
            FrameDestination::Multicast
        } else {
            debug_assert!(mac.is_unicast());
            FrameDestination::Unicast
        }
    }
}

/// The non-synchronized execution context for an Ethernet device.
pub(crate) trait EthernetIpLinkDeviceNonSyncContext<DeviceId>:
    RngContext + IpLinkDeviceNonSyncContext<EthernetTimerId<DeviceId>>
{
}
impl<DeviceId, C: RngContext + IpLinkDeviceNonSyncContext<EthernetTimerId<DeviceId>>>
    EthernetIpLinkDeviceNonSyncContext<DeviceId> for C
{
}

/// The execution context for an Ethernet device.
pub(crate) trait EthernetIpLinkDeviceContext<C: EthernetIpLinkDeviceNonSyncContext<Self::DeviceId>>:
    IpLinkDeviceContext<
    EthernetLinkDevice,
    C,
    EthernetTimerId<<Self as DeviceIdContext<EthernetLinkDevice>>::DeviceId>,
>
{
    /// Adds an IPv6 address to the device.
    // TODO(https://fxbug.dev/72378): Remove this method once NDP operates at
    // L3.
    fn add_ipv6_addr_subnet(
        &mut self,
        ctx: &mut C,
        device_id: Self::DeviceId,
        addr_sub: AddrSubnet<Ipv6Addr>,
        config: AddrConfig<C::Instant>,
    ) -> Result<(), ExistsError>;

    /// Joins an IPv6 multicast group.
    // TODO(https://fxbug.dev/72378): Remove this method once NDP operates at
    // L3.
    fn join_ipv6_multicast(
        &mut self,
        ctx: &mut C,
        device_id: Self::DeviceId,
        multicast_addr: MulticastAddr<Ipv6Addr>,
    );

    /// Leaves an IPv6 multicast group.
    // TODO(https://fxbug.dev/72378): Remove this method once NDP operates at
    // L3.
    fn leave_ipv6_multicast(
        &mut self,
        ctx: &mut C,
        device_id: Self::DeviceId,
        multicast_addr: MulticastAddr<Ipv6Addr>,
    );
}

impl<NonSyncCtx: NonSyncContext> EthernetIpLinkDeviceContext<NonSyncCtx> for SyncCtx<NonSyncCtx> {
    fn add_ipv6_addr_subnet(
        &mut self,
        ctx: &mut NonSyncCtx,
        device_id: EthernetDeviceId,
        addr_sub: AddrSubnet<Ipv6Addr>,
        config: AddrConfig<NonSyncCtx::Instant>,
    ) -> Result<(), ExistsError> {
        crate::ip::device::add_ipv6_addr_subnet(self, ctx, device_id.into(), addr_sub, config)
    }

    fn join_ipv6_multicast(
        &mut self,
        ctx: &mut NonSyncCtx,
        device_id: Self::DeviceId,
        multicast_addr: MulticastAddr<Ipv6Addr>,
    ) {
        crate::ip::device::join_ip_multicast::<Ipv6, _, _>(
            self,
            ctx,
            device_id.into(),
            multicast_addr,
        )
    }

    fn leave_ipv6_multicast(
        &mut self,
        ctx: &mut NonSyncCtx,
        device_id: Self::DeviceId,
        multicast_addr: MulticastAddr<Ipv6Addr>,
    ) {
        crate::ip::device::leave_ip_multicast::<Ipv6, _, _>(
            self,
            ctx,
            device_id.into(),
            multicast_addr,
        )
    }
}

/// A shorthand for `BufferIpLinkDeviceContext` with all of the appropriate type
/// arguments fixed to their Ethernet values.
pub(super) trait BufferEthernetIpLinkDeviceContext<
    C: EthernetIpLinkDeviceNonSyncContext<Self::DeviceId>,
    B: BufferMut,
>:
    EthernetIpLinkDeviceContext<C>
    + BufferIpLinkDeviceContext<
        EthernetLinkDevice,
        C,
        EthernetTimerId<<Self as DeviceIdContext<EthernetLinkDevice>>::DeviceId>,
        B,
    >
{
}

impl<
        C: EthernetIpLinkDeviceNonSyncContext<SC::DeviceId>,
        B: BufferMut,
        SC: EthernetIpLinkDeviceContext<C>
            + BufferIpLinkDeviceContext<
                EthernetLinkDevice,
                C,
                EthernetTimerId<<SC as DeviceIdContext<EthernetLinkDevice>>::DeviceId>,
                B,
            >,
    > BufferEthernetIpLinkDeviceContext<C, B> for SC
{
}

/// Builder for [`EthernetDeviceState`].
pub(crate) struct EthernetDeviceStateBuilder {
    mac: UnicastAddr<Mac>,
    mtu: u32,
}

impl EthernetDeviceStateBuilder {
    /// Create a new `EthernetDeviceStateBuilder`.
    pub(crate) fn new(mac: UnicastAddr<Mac>, mtu: u32) -> Self {
        // TODO(joshlf): Add a minimum MTU for all Ethernet devices such that
        //  you cannot create an `EthernetDeviceState` with an MTU smaller than
        //  the minimum. The absolute minimum needs to be at least the minimum
        //  body size of an Ethernet frame. For IPv6-capable devices, the
        //  minimum needs to be higher - the IPv6 minimum MTU. The easy path is
        //  to simply use the IPv6 minimum MTU as the minimum in all cases,
        //  although we may at some point want to figure out how to configure
        //  devices which don't support IPv6, and allow smaller MTUs for those
        //  devices.
        //
        //  A few questions:
        //  - How do we wire error information back up the call stack? Should
        //    this just return a Result or something?
        Self { mac, mtu }
    }

    /// Build the `EthernetDeviceState` from this builder.
    pub(super) fn build(self) -> EthernetDeviceState {
        EthernetDeviceState {
            mac: self.mac,
            mtu: self.mtu,
            hw_mtu: self.mtu,
            link_multicast_groups: RefCountedHashSet::default(),
            ipv4_arp: ArpState::default(),
            ndp: NdpState::new(),
            pending_frames: HashMap::new(),
            promiscuous_mode: false,
        }
    }
}

/// The state associated with an Ethernet device.
pub(crate) struct EthernetDeviceState {
    /// Mac address of the device this state is for.
    mac: UnicastAddr<Mac>,

    /// The value this netstack assumes as the device's current MTU.
    mtu: u32,

    /// The maximum MTU allowed by the hardware.
    ///
    /// `mtu` MUST NEVER be greater than `hw_mtu`.
    hw_mtu: u32,

    /// Link multicast groups this device has joined.
    link_multicast_groups: RefCountedHashSet<MulticastAddr<Mac>>,

    /// IPv4 ARP state.
    ipv4_arp: ArpState<EthernetLinkDevice, Ipv4Addr>,

    /// (IPv6) NDP state.
    ndp: ndp::NdpState<EthernetLinkDevice>,

    // pending_frames stores a list of serialized frames indexed by their
    // destination IP addresses. The frames contain an entire EthernetFrame
    // body and the MTU check is performed before queueing them here.
    pending_frames: HashMap<IpAddr, VecDeque<Buf<Vec<u8>>>>,

    /// A flag indicating whether the device will accept all ethernet frames
    /// that it receives, regardless of the ethernet frame's destination MAC
    /// address.
    promiscuous_mode: bool,
}

impl EthernetDeviceState {
    /// Adds a pending frame `frame` associated with `local_addr` to the list of
    /// pending frames in the current device state.
    ///
    /// If an older frame had to be dropped because it exceeds the maximum
    /// allowed number of pending frames, it is returned.
    fn add_pending_frame(
        &mut self,
        local_addr: IpAddr,
        frame: Buf<Vec<u8>>,
    ) -> Option<Buf<Vec<u8>>> {
        let buff = self.pending_frames.entry(local_addr).or_insert_with(Default::default);
        buff.push_back(frame);
        if buff.len() > ETHERNET_MAX_PENDING_FRAMES {
            buff.pop_front()
        } else {
            None
        }
    }

    /// Takes all pending frames associated with address `local_addr`.
    fn take_pending_frames(
        &mut self,
        local_addr: IpAddr,
    ) -> Option<impl Iterator<Item = Buf<Vec<u8>>>> {
        match self.pending_frames.remove(&local_addr) {
            Some(buff) => Some(buff.into_iter()),
            None => None,
        }
    }

    /// Is a packet with a destination MAC address, `dst`, destined for this
    /// device?
    ///
    /// Returns `true` if this device is has `dst_mac` as its assigned MAC
    /// address, `dst_mac` is the broadcast MAC address, or it is one of the
    /// multicast MAC addresses the device has joined.
    fn should_accept(&self, dst_mac: &Mac) -> bool {
        (self.mac.get() == *dst_mac)
            || dst_mac.is_broadcast()
            || (MulticastAddr::new(*dst_mac)
                .map(|a| self.link_multicast_groups.contains(&a))
                .unwrap_or(false))
    }

    /// Should a packet with destination MAC address, `dst`, be accepted by this
    /// device?
    ///
    /// Returns `true` if this device is in promiscuous mode or the frame is
    /// destined for this device.
    fn should_deliver(&self, dst_mac: &Mac) -> bool {
        self.promiscuous_mode || self.should_accept(dst_mac)
    }
}

/// A timer ID for Ethernet devices.
///
/// `D` is the type of device ID that identifies different Ethernet devices.
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
pub(crate) enum EthernetTimerId<D> {
    Arp(ArpTimerId<EthernetLinkDevice, Ipv4Addr, D>),
    Ndp(NdpTimerId<EthernetLinkDevice, D>),
}

impl<D> From<ArpTimerId<EthernetLinkDevice, Ipv4Addr, D>> for EthernetTimerId<D> {
    fn from(id: ArpTimerId<EthernetLinkDevice, Ipv4Addr, D>) -> EthernetTimerId<D> {
        EthernetTimerId::Arp(id)
    }
}

impl<D> From<NdpTimerId<EthernetLinkDevice, D>> for EthernetTimerId<D> {
    fn from(id: NdpTimerId<EthernetLinkDevice, D>) -> EthernetTimerId<D> {
        EthernetTimerId::Ndp(id)
    }
}

/// Handle an Ethernet timer firing.
pub(super) fn handle_timer<
    C: EthernetIpLinkDeviceNonSyncContext<SC::DeviceId>,
    SC: EthernetIpLinkDeviceContext<C>,
>(
    sync_ctx: &mut SC,
    ctx: &mut C,
    id: EthernetTimerId<SC::DeviceId>,
) {
    match id {
        EthernetTimerId::Arp(id) => arp::handle_timer(sync_ctx, ctx, id.into()),
        EthernetTimerId::Ndp(id) => <SC as NdpHandler<_, _>>::handle_timer(sync_ctx, ctx, id),
    }
}

// If we are provided with an impl of `TimerContext<EthernetTimerId<_>>`, then
// we can in turn provide impls of `TimerContext` for ARP, NDP, IGMP, and MLD
// timers.
impl_timer_context!(
    DeviceId,
    EthernetTimerId<DeviceId>,
    ArpTimerId<EthernetLinkDevice, Ipv4Addr, DeviceId>,
    EthernetTimerId::Arp(id),
    id
);
impl_timer_context!(
    DeviceId,
    EthernetTimerId<DeviceId>,
    NdpTimerId<EthernetLinkDevice, DeviceId>,
    EthernetTimerId::Ndp(id),
    id
);

/// Send an IP packet in an Ethernet frame.
///
/// `send_ip_frame` accepts a device ID, a local IP address, and a
/// serializer. It computes the routing information, serializes
/// the serializer, and sends the resulting buffer in a new Ethernet
/// frame.
pub(super) fn send_ip_frame<
    B: BufferMut,
    C: EthernetIpLinkDeviceNonSyncContext<SC::DeviceId>,
    SC: EthernetIpLinkDeviceContext<C>
        + FrameContext<C, B, <SC as DeviceIdContext<EthernetLinkDevice>>::DeviceId>,
    A: IpAddress,
    S: Serializer<Buffer = B>,
>(
    sync_ctx: &mut SC,
    ctx: &mut C,
    device_id: SC::DeviceId,
    local_addr: SpecifiedAddr<A>,
    body: S,
) -> Result<(), S> {
    sync_ctx.increment_counter("ethernet::send_ip_frame");

    trace!("ethernet::send_ip_frame: local_addr = {:?}; device = {:?}", local_addr, device_id);

    let state = &mut sync_ctx.get_state_mut_with(device_id).link;
    let (local_mac, mtu) = (state.mac, state.mtu);

    let dst_mac = match local_addr.into() {
        IpAddr::V4(local_addr) => match MulticastAddr::from_witness(local_addr) {
            Some(multicast) => Ok(Mac::from(&multicast)),
            None => arp::lookup(sync_ctx, ctx, device_id, local_mac.get(), local_addr.get())
                .ok_or(IpAddr::V4(local_addr)),
        },
        IpAddr::V6(local_addr) => match UnicastOrMulticastIpv6Addr::from_specified(local_addr) {
            UnicastOrMulticastIpv6Addr::Multicast(addr) => Ok(Mac::from(&addr)),
            UnicastOrMulticastIpv6Addr::Unicast(addr) => {
                <SC as NdpHandler<_, _>>::lookup(sync_ctx, ctx, device_id, addr)
                    .ok_or(IpAddr::V6(local_addr))
            }
        },
    };

    match dst_mac {
        Ok(dst_mac) => sync_ctx
            .send_frame(
                ctx,
                device_id.into(),
                body.with_mtu(mtu as usize).encapsulate(EthernetFrameBuilder::new(
                    local_mac.get(),
                    dst_mac,
                    A::Version::ETHER_TYPE,
                )),
            )
            .map_err(|ser| ser.into_inner().into_inner()),
        Err(local_addr) => {
            let state = &mut sync_ctx.get_state_mut_with(device_id).link;
            // The `serialize_vec_outer` call returns an `Either<B,
            // Buf<Vec<u8>>`. We could naively call `.as_ref().to_vec()` on it,
            // but if it were the `Buf<Vec<u8>>` variant, we'd be unnecessarily
            // allocating a new `Vec` when we already have one. Instead, we
            // leave the `Buf<Vec<u8>>` variant as it is, and only convert the
            // `B` variant by calling `map_a`. That gives us an
            // `Either<Buf<Vec<u8>>, Buf<Vec<u8>>`, which we call `into_inner`
            // on to get a `Buf<Vec<u8>>`.
            let frame = body
                .with_mtu(mtu as usize)
                .serialize_vec_outer()
                .map_err(|ser| ser.1.into_inner())?
                .map_a(|buffer| Buf::new(buffer.as_ref().to_vec(), ..))
                .into_inner();
            let dropped = state
                .add_pending_frame(local_addr.transpose::<SpecifiedAddr<IpAddr>>().get(), frame);
            if let Some(_dropped) = dropped {
                // TODO(brunodalbo): Is it ok to silently just let this drop? Or
                //  should the IP layer be notified in any way?
                log_unimplemented!((), "Ethernet dropped frame because ran out of allowable space");
            }
            Ok(())
        }
    }
}

/// Receive an Ethernet frame from the network.
pub(super) fn receive_frame<
    C: EthernetIpLinkDeviceNonSyncContext<SC::DeviceId>,
    B: BufferMut,
    SC: BufferEthernetIpLinkDeviceContext<C, B>,
>(
    sync_ctx: &mut SC,
    ctx: &mut C,
    device_id: SC::DeviceId,
    mut buffer: B,
) {
    trace!("ethernet::receive_frame: device_id = {:?}", device_id);
    // NOTE(joshlf): We do not currently validate that the Ethernet frame
    // satisfies the minimum length requirement. We expect that if this
    // requirement is necessary (due to requirements of the physical medium),
    // the driver or hardware will have checked it, and that if this requirement
    // is not necessary, it is acceptable for us to operate on a smaller
    // Ethernet frame. If this becomes insufficient in the future, we may want
    // to consider making this behavior configurable (at compile time, at
    // runtime on a global basis, or at runtime on a per-device basis).
    let frame = if let Ok(frame) =
        buffer.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::NoCheck)
    {
        frame
    } else {
        trace!("ethernet::receive_frame: failed to parse ethernet frame");
        // TODO(joshlf): Do something else?
        return;
    };

    let (_, dst) = (frame.src_mac(), frame.dst_mac());

    if !sync_ctx.get_state_with(device_id).link.should_deliver(&dst) {
        trace!("ethernet::receive_frame: destination mac {:?} not for device {:?}", dst, device_id);
        return;
    }

    let frame_dst = FrameDestination::from(dst);

    match frame.ethertype() {
        Some(EtherType::Arp) => {
            let types = if let Ok(types) = peek_arp_types(buffer.as_ref()) {
                types
            } else {
                // TODO(joshlf): Do something else here?
                return;
            };
            match types {
                (ArpHardwareType::Ethernet, ArpNetworkType::Ipv4) => {
                    arp::handle_packet(sync_ctx, ctx, device_id, buffer)
                }
            }
        }
        Some(EtherType::Ipv4) => sync_ctx.receive_frame(
            ctx,
            RecvIpFrameMeta::<_, Ipv4>::new(device_id, frame_dst),
            buffer,
        ),
        Some(EtherType::Ipv6) => sync_ctx.receive_frame(
            ctx,
            RecvIpFrameMeta::<_, Ipv6>::new(device_id, frame_dst),
            buffer,
        ),
        Some(EtherType::Other(_)) | None => {} // TODO(joshlf)
    }
}

/// Set the promiscuous mode flag on `device_id`.
pub(super) fn set_promiscuous_mode<
    C: EthernetIpLinkDeviceNonSyncContext<SC::DeviceId>,
    SC: EthernetIpLinkDeviceContext<C>,
>(
    sync_ctx: &mut SC,
    _ctx: &mut C,
    device_id: SC::DeviceId,
    enabled: bool,
) {
    sync_ctx.get_state_mut_with(device_id).link.promiscuous_mode = enabled;
}

/// Add `device_id` to a link multicast group `multicast_addr`.
///
/// Calling `join_link_multicast` with the same `device_id` and `multicast_addr`
/// is completely safe. A counter will be kept for the number of times
/// `join_link_multicast` has been called with the same `device_id` and
/// `multicast_addr` pair. To completely leave a multicast group,
/// [`leave_link_multicast`] must be called the same number of times
/// `join_link_multicast` has been called for the same `device_id` and
/// `multicast_addr` pair. The first time `join_link_multicast` is called for a
/// new `device` and `multicast_addr` pair, the device will actually join the
/// multicast group.
///
/// `join_link_multicast` is different from [`join_ip_multicast`] as
/// `join_link_multicast` joins an L2 multicast group, whereas
/// `join_ip_multicast` joins an L3 multicast group.
pub(super) fn join_link_multicast<
    C: EthernetIpLinkDeviceNonSyncContext<SC::DeviceId>,
    SC: EthernetIpLinkDeviceContext<C>,
>(
    sync_ctx: &mut SC,
    _ctx: &mut C,
    device_id: SC::DeviceId,
    multicast_addr: MulticastAddr<Mac>,
) {
    let device_state = &mut sync_ctx.get_state_mut_with(device_id).link;

    let groups = &mut device_state.link_multicast_groups;

    match groups.insert(multicast_addr) {
        InsertResult::Inserted(()) => {
            trace!("ethernet::join_link_multicast: joining link multicast {:?}", multicast_addr);
        }
        InsertResult::AlreadyPresent => {
            trace!(
                "ethernet::join_link_multicast: already joined link multicast {:?}",
                multicast_addr,
            );
        }
    }
}

/// Remove `device_id` from a link multicast group `multicast_addr`.
///
/// `leave_link_multicast` will attempt to remove `device_id` from the multicast
/// group `multicast_addr`. `device_id` may have "joined" the same multicast
/// address multiple times, so `device_id` will only leave the multicast group
/// once `leave_ip_multicast` has been called for each corresponding
/// [`join_link_multicast`]. That is, if `join_link_multicast` gets called 3
/// times and `leave_link_multicast` gets called two times (after all 3
/// `join_link_multicast` calls), `device_id` will still be in the multicast
/// group until the next (final) call to `leave_link_multicast`.
///
/// `leave_link_multicast` is different from [`leave_ip_multicast`] as
/// `leave_link_multicast` leaves an L2 multicast group, whereas
/// `leave_ip_multicast` leaves an L3 multicast group.
///
/// # Panics
///
/// If `device_id` is not in the multicast group `multicast_addr`.
pub(super) fn leave_link_multicast<
    C: EthernetIpLinkDeviceNonSyncContext<SC::DeviceId>,
    SC: EthernetIpLinkDeviceContext<C>,
>(
    sync_ctx: &mut SC,
    _ctx: &mut C,
    device_id: SC::DeviceId,
    multicast_addr: MulticastAddr<Mac>,
) {
    let device_state = &mut sync_ctx.get_state_mut_with(device_id).link;

    let groups = &mut device_state.link_multicast_groups;

    match groups.remove(multicast_addr) {
        RemoveResult::Removed(()) => {
            trace!("ethernet::leave_link_multicast: leaving link multicast {:?}", multicast_addr);
        }
        RemoveResult::StillPresent => {
            trace!(
                "ethernet::leave_link_multicast: not leaving link multicast {:?} as there are still listeners for it",
                multicast_addr,
            );
        }
        RemoveResult::NotPresent => {
            panic!(
                "ethernet::leave_link_multicast: device {:?} has not yet joined link multicast {:?}",
                device_id,
                multicast_addr,
            );
        }
    }
}

/// Get the MTU associated with this device.
pub(super) fn get_mtu<
    C: EthernetIpLinkDeviceNonSyncContext<SC::DeviceId>,
    SC: EthernetIpLinkDeviceContext<C>,
>(
    sync_ctx: &SC,
    device_id: SC::DeviceId,
) -> u32 {
    sync_ctx.get_state_with(device_id).link.mtu
}

/// Insert a static entry into this device's ARP table.
///
/// This will cause any conflicting dynamic entry to be removed, and
/// any future conflicting gratuitous ARPs to be ignored.
// TODO(rheacock): remove `cfg(test)` when this is used. Will probably be called
// by a pub fn in the device mod.
#[cfg(test)]
pub(super) fn insert_static_arp_table_entry<
    C: EthernetIpLinkDeviceNonSyncContext<SC::DeviceId>,
    SC: EthernetIpLinkDeviceContext<C>,
>(
    sync_ctx: &mut SC,
    ctx: &mut C,
    device_id: SC::DeviceId,
    addr: Ipv4Addr,
    mac: Mac,
) {
    arp::insert_static_neighbor(sync_ctx, ctx, device_id, addr, mac)
}

/// Insert an entry into this device's NDP table.
///
/// This method only gets called when testing to force set a neighbor's link
/// address so that lookups succeed immediately, without doing address
/// resolution.
// TODO(rheacock): Remove when this is called from non-test code.
#[cfg(test)]
pub(super) fn insert_ndp_table_entry<
    C: EthernetIpLinkDeviceNonSyncContext<SC::DeviceId>,
    SC: EthernetIpLinkDeviceContext<C>,
>(
    sync_ctx: &mut SC,
    ctx: &mut C,
    device_id: SC::DeviceId,
    addr: UnicastAddr<Ipv6Addr>,
    mac: Mac,
) {
    <SC as NdpHandler<_, _>>::insert_static_neighbor(sync_ctx, ctx, device_id, addr, mac)
}

/// Deinitializes and cleans up state for ethernet devices
///
/// After this function is called, the ethernet device should not be used and
/// nothing else should be done with the state.
pub(super) fn deinitialize<
    C: EthernetIpLinkDeviceNonSyncContext<SC::DeviceId>,
    SC: EthernetIpLinkDeviceContext<C>,
>(
    sync_ctx: &mut SC,
    ctx: &mut C,
    device_id: SC::DeviceId,
) {
    arp::deinitialize(sync_ctx, ctx, device_id);
    <SC as NdpHandler<_, _>>::deinitialize(sync_ctx, ctx, device_id);
}

impl<C: EthernetIpLinkDeviceNonSyncContext<SC::DeviceId>, SC: EthernetIpLinkDeviceContext<C>>
    StateContext<C, ArpState<EthernetLinkDevice, Ipv4Addr>, SC::DeviceId> for SC
{
    fn get_state_with(&self, id: SC::DeviceId) -> &ArpState<EthernetLinkDevice, Ipv4Addr> {
        &self.get_state_with(id).link.ipv4_arp
    }

    fn get_state_mut_with(
        &mut self,
        id: SC::DeviceId,
    ) -> &mut ArpState<EthernetLinkDevice, Ipv4Addr> {
        &mut self.get_state_mut_with(id).link.ipv4_arp
    }
}

impl<
        C: EthernetIpLinkDeviceNonSyncContext<SC::DeviceId>,
        B: BufferMut,
        SC: EthernetIpLinkDeviceContext<C>
            + FrameContext<C, B, <SC as DeviceIdContext<EthernetLinkDevice>>::DeviceId>,
    > FrameContext<C, B, ArpFrameMetadata<EthernetLinkDevice, SC::DeviceId>> for SC
{
    fn send_frame<S: Serializer<Buffer = B>>(
        &mut self,
        ctx: &mut C,
        meta: ArpFrameMetadata<EthernetLinkDevice, SC::DeviceId>,
        body: S,
    ) -> Result<(), S> {
        let src = self.get_state_with(meta.device_id).link.mac;
        self.send_frame(
            ctx,
            meta.device_id,
            body.encapsulate(EthernetFrameBuilder::new(src.get(), meta.dst_addr, EtherType::Arp)),
        )
        .map_err(Nested::into_inner)
    }
}

impl<C: DeviceIdContext<EthernetLinkDevice>> ArpDeviceIdContext<EthernetLinkDevice> for C {
    type DeviceId = <C as DeviceIdContext<EthernetLinkDevice>>::DeviceId;
}

impl<C: EthernetIpLinkDeviceNonSyncContext<SC::DeviceId>, SC: EthernetIpLinkDeviceContext<C>>
    ArpContext<EthernetLinkDevice, Ipv4Addr, C> for SC
{
    fn get_protocol_addr(
        &self,
        _ctx: &mut C,
        device_id: <SC as ArpDeviceIdContext<EthernetLinkDevice>>::DeviceId,
    ) -> Option<Ipv4Addr> {
        self.get_state_with(device_id.into())
            .ip
            .ipv4
            .ip_state
            .iter_addrs()
            .next()
            .cloned()
            .map(|addr| addr.addr().get())
    }
    fn get_hardware_addr(
        &self,
        _ctx: &mut C,
        device_id: <SC as ArpDeviceIdContext<EthernetLinkDevice>>::DeviceId,
    ) -> UnicastAddr<Mac> {
        self.get_state_with(device_id.into()).link.mac
    }
    fn address_resolved(
        &mut self,
        ctx: &mut C,
        device_id: <SC as ArpDeviceIdContext<EthernetLinkDevice>>::DeviceId,
        proto_addr: Ipv4Addr,
        hw_addr: Mac,
    ) {
        mac_resolved(self, ctx, device_id.into(), IpAddr::V4(proto_addr), hw_addr);
    }
    fn address_resolution_failed(
        &mut self,
        ctx: &mut C,
        device_id: <SC as ArpDeviceIdContext<EthernetLinkDevice>>::DeviceId,
        proto_addr: Ipv4Addr,
    ) {
        mac_resolution_failed(self, ctx, device_id.into(), IpAddr::V4(proto_addr));
    }
    fn address_resolution_expired(
        &mut self,
        _ctx: &mut C,
        _device_id: <SC as ArpDeviceIdContext<EthernetLinkDevice>>::DeviceId,
        _proto_addr: Ipv4Addr,
    ) {
        log_unimplemented!((), "ArpContext::address_resolution_expired");
    }
}

impl<C: EthernetIpLinkDeviceNonSyncContext<SC::DeviceId>, SC: EthernetIpLinkDeviceContext<C>>
    StateContext<C, NdpState<EthernetLinkDevice>, SC::DeviceId> for SC
{
    fn get_state_with(&self, id: SC::DeviceId) -> &NdpState<EthernetLinkDevice> {
        &self.get_state_with(id).link.ndp
    }

    fn get_state_mut_with(&mut self, id: SC::DeviceId) -> &mut NdpState<EthernetLinkDevice> {
        &mut self.get_state_mut_with(id).link.ndp
    }
}

pub(super) fn get_mac<
    'a,
    C: EthernetIpLinkDeviceNonSyncContext<SC::DeviceId>,
    SC: EthernetIpLinkDeviceContext<C>,
>(
    sync_ctx: &'a SC,
    device_id: SC::DeviceId,
) -> &'a UnicastAddr<Mac> {
    &sync_ctx.get_state_with(device_id).link.mac
}

impl<C: EthernetIpLinkDeviceNonSyncContext<SC::DeviceId>, SC: EthernetIpLinkDeviceContext<C>>
    NdpContext<EthernetLinkDevice, C> for SC
{
    fn get_retrans_timer(&self, device_id: Self::DeviceId) -> NonZeroDuration {
        self.get_state_with(device_id).ip.ipv6.retrans_timer
    }

    fn get_link_layer_addr(&self, device_id: SC::DeviceId) -> UnicastAddr<Mac> {
        get_mac(self, device_id).clone()
    }

    fn get_ip_device_state(&self, device_id: Self::DeviceId) -> &IpDeviceState<C::Instant, Ipv6> {
        &self.get_state_with(device_id).ip.ipv6.ip_state
    }

    fn get_ip_device_state_mut(
        &mut self,
        device_id: Self::DeviceId,
    ) -> &mut IpDeviceState<C::Instant, Ipv6> {
        &mut self.get_state_mut_with(device_id).ip.ipv6.ip_state
    }

    fn send_ipv6_frame<S: Serializer<Buffer = EmptyBuf>>(
        &mut self,
        ctx: &mut C,
        device_id: Self::DeviceId,
        next_hop: SpecifiedAddr<Ipv6Addr>,
        body: S,
    ) -> Result<(), S> {
        // TODO(joshlf): Wire `SpecifiedAddr` through the `ndp` module.
        send_ip_frame(self, ctx, device_id, next_hop, body)
    }

    fn address_resolved(
        &mut self,
        ctx: &mut C,
        device_id: SC::DeviceId,
        address: &UnicastAddr<Ipv6Addr>,
        link_address: Mac,
    ) {
        mac_resolved(self, ctx, device_id, IpAddr::V6(address.get()), link_address);
    }

    fn address_resolution_failed(
        &mut self,
        ctx: &mut C,
        device_id: SC::DeviceId,
        address: &UnicastAddr<Ipv6Addr>,
    ) {
        mac_resolution_failed(self, ctx, device_id, IpAddr::V6(address.get()));
    }

    fn set_mtu(&mut self, _ctx: &mut C, device_id: SC::DeviceId, mut mtu: u32) {
        // TODO(ghanan): Should this new MTU be updated only from the netstack's
        //               perspective or be exposed to the device hardware?

        // `mtu` must not be less than the minimum IPv6 MTU.
        assert!(mtu >= Ipv6::MINIMUM_LINK_MTU.into());

        let dev_state = &mut self.get_state_mut_with(device_id).link;

        // If `mtu` is greater than what the device supports, set `mtu` to the
        // maximum MTU the device supports.
        if mtu > dev_state.hw_mtu {
            trace!("ethernet::ndp_device::set_mtu: MTU of {:?} is greater than the device {:?}'s max MTU of {:?}, using device's max MTU instead", mtu, device_id, dev_state.hw_mtu);
            mtu = dev_state.hw_mtu;
        }

        trace!("ethernet::ndp_device::set_mtu: setting link MTU to {:?}", mtu);
        dev_state.mtu = mtu;
    }
}

/// An implementation of the [`LinkDevice`] trait for Ethernet devices.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub(crate) struct EthernetLinkDevice;

impl LinkDevice for EthernetLinkDevice {
    type Address = Mac;
    type State = EthernetDeviceState;
}

/// Sends out any pending frames that are waiting for link layer address
/// resolution.
///
/// `mac_resolved` is the common logic used when a link layer address is
/// resolved either by ARP or NDP.
fn mac_resolved<
    C: EthernetIpLinkDeviceNonSyncContext<SC::DeviceId>,
    SC: EthernetIpLinkDeviceContext<C>,
>(
    sync_ctx: &mut SC,
    ctx: &mut C,
    device_id: SC::DeviceId,
    address: IpAddr,
    dst_mac: Mac,
) {
    let state = &mut sync_ctx.get_state_mut_with(device_id).link;
    let src_mac = state.mac;
    let ether_type = match &address {
        IpAddr::V4(_) => EtherType::Ipv4,
        IpAddr::V6(_) => EtherType::Ipv6,
    };
    if let Some(pending) = state.take_pending_frames(address) {
        for frame in pending {
            // NOTE(brunodalbo): We already performed MTU checking when we saved
            //  the buffer waiting for address resolution. It should be noted
            //  that the MTU check back then didn't account for ethernet frame
            //  padding required by EthernetFrameBuilder, but that's fine (as it
            //  stands right now) because the MTU is guaranteed to be larger
            //  than an Ethernet minimum frame body size.
            let res = sync_ctx.send_frame(
                ctx,
                device_id.into(),
                frame.encapsulate(EthernetFrameBuilder::new(src_mac.get(), dst_mac, ether_type)),
            );
            if let Err(_) = res {
                // TODO(joshlf): Do we want to handle this differently?
                debug!("Failed to send pending frame; MTU changed since frame was queued");
            }
        }
    }
}

/// Clears out any pending frames that are waiting for link layer address
/// resolution.
///
/// `mac_resolution_failed` is the common logic used when a link layer address
/// fails to resolve either by ARP or NDP.
fn mac_resolution_failed<
    C: EthernetIpLinkDeviceNonSyncContext<SC::DeviceId>,
    SC: EthernetIpLinkDeviceContext<C>,
>(
    sync_ctx: &mut SC,
    _ctx: &mut C,
    device_id: SC::DeviceId,
    address: IpAddr,
) {
    // TODO(brunodalbo) what do we do here in regards to the pending frames?
    //  NDP's RFC explicitly states unreachable ICMP messages must be generated:
    //  "If no Neighbor Advertisement is received after MAX_MULTICAST_SOLICIT
    //  solicitations, address resolution has failed. The sender MUST return
    //  ICMP destination unreachable indications with code 3
    //  (Address Unreachable) for each packet queued awaiting address
    //  resolution."
    //  For ARP, we don't have such a clear statement on the RFC, it would make
    //  sense to do the same thing though.
    let state = &mut sync_ctx.get_state_mut_with(device_id).link;
    if let Some(_) = state.take_pending_frames(address) {
        log_unimplemented!((), "ethernet mac resolution failed not implemented");
    }
}

#[cfg(test)]
mod tests {
    use alloc::vec;

    use assert_matches::assert_matches;
    use net_types::ip::IpVersion;
    use packet::Buf;
    use packet_formats::{
        icmp::{IcmpDestUnreachable, IcmpIpExt},
        ip::{IpExt, IpPacketBuilder, IpProto},
        testdata::{dns_request_v4, dns_request_v6},
        testutil::{
            parse_icmp_packet_in_ip_packet_in_ethernet_frame, parse_ip_packet_in_ethernet_frame,
        },
    };
    use rand::Rng;
    use specialize_ip_macro::ip_test;

    use super::*;
    use crate::{
        context::testutil::DummyInstant,
        device::{
            arp::ArpHandler, testutil::DeviceTestIpExt, DeviceId, DeviceIdInner, EthernetDeviceId,
            IpLinkDeviceState,
        },
        error::NotFoundError,
        ip::{
            device::{
                is_ipv4_routing_enabled, is_ipv6_routing_enabled, set_routing_enabled,
                state::AssignedAddress,
            },
            dispatch_receive_ip_packet_name, receive_ip_packet, DummyDeviceId,
        },
        testutil::{
            add_arp_or_ndp_table_entry, assert_empty, get_counter_val, new_rng,
            DummyEventDispatcherBuilder, TestIpExt, DUMMY_CONFIG_V4,
        },
        Ctx,
    };

    struct DummyEthernetCtx {
        state: IpLinkDeviceState<DummyInstant, EthernetDeviceState>,
    }

    impl DummyEthernetCtx {
        fn new(mac: UnicastAddr<Mac>, mtu: u32) -> DummyEthernetCtx {
            DummyEthernetCtx {
                state: IpLinkDeviceState::new(EthernetDeviceStateBuilder::new(mac, mtu).build()),
            }
        }
    }

    type DummyNonSyncCtx =
        crate::context::testutil::DummyNonSyncCtx<EthernetTimerId<DummyDeviceId>, (), ()>;

    type DummyCtx =
        crate::context::testutil::DummySyncCtx<DummyEthernetCtx, DummyDeviceId, DummyDeviceId>;

    impl
        StateContext<
            DummyNonSyncCtx,
            IpLinkDeviceState<DummyInstant, EthernetDeviceState>,
            DummyDeviceId,
        > for DummyCtx
    {
        fn get_state_with(
            &self,
            _id0: DummyDeviceId,
        ) -> &IpLinkDeviceState<DummyInstant, EthernetDeviceState> {
            &self.get_ref().state
        }

        fn get_state_mut_with(
            &mut self,
            _id0: DummyDeviceId,
        ) -> &mut IpLinkDeviceState<DummyInstant, EthernetDeviceState> {
            &mut self.get_mut().state
        }
    }

    impl EthernetIpLinkDeviceContext<DummyNonSyncCtx> for DummyCtx {
        fn add_ipv6_addr_subnet(
            &mut self,
            _ctx: &mut DummyNonSyncCtx,
            _device_id: DummyDeviceId,
            _addr_sub: AddrSubnet<Ipv6Addr>,
            _config: AddrConfig<DummyInstant>,
        ) -> Result<(), ExistsError> {
            unimplemented!()
        }

        fn join_ipv6_multicast(
            &mut self,
            _ctx: &mut DummyNonSyncCtx,
            _device_id: DummyDeviceId,
            _multicast_addr: MulticastAddr<Ipv6Addr>,
        ) {
            unimplemented!()
        }

        fn leave_ipv6_multicast(
            &mut self,
            _ctx: &mut DummyNonSyncCtx,
            _device_id: DummyDeviceId,
            _multicast_addr: MulticastAddr<Ipv6Addr>,
        ) {
            unimplemented!()
        }
    }

    impl DeviceIdContext<EthernetLinkDevice> for DummyCtx {
        type DeviceId = DummyDeviceId;
    }

    impl IpLinkDeviceContext<EthernetLinkDevice, DummyNonSyncCtx, EthernetTimerId<DummyDeviceId>>
        for DummyCtx
    {
    }

    fn contains_addr<A: IpAddress>(
        ctx: &crate::testutil::DummySyncCtx,
        device: DeviceId,
        addr: SpecifiedAddr<A>,
    ) -> bool
    where
        A::Version: DeviceTestIpExt<DummyInstant>,
    {
        <A::Version as DeviceTestIpExt<_>>::get_ip_device_state(ctx, device)
            .iter_addrs()
            .any(|a| a.addr() == addr)
    }

    fn is_in_ip_multicast<A: IpAddress>(
        ctx: &crate::testutil::DummySyncCtx,
        device: DeviceId,
        addr: MulticastAddr<A>,
    ) -> bool
    where
        A::Version: DeviceTestIpExt<DummyInstant>,
    {
        <A::Version as DeviceTestIpExt<_>>::get_ip_device_state(ctx, device)
            .multicast_groups
            .contains(&addr)
    }

    #[test]
    fn test_mtu() {
        // Test that we send an Ethernet frame whose size is less than the MTU,
        // and that we don't send an Ethernet frame whose size is greater than
        // the MTU.
        fn test(size: usize, expect_frames_sent: usize) {
            let crate::context::testutil::DummyCtx { mut sync_ctx, mut non_sync_ctx } =
                crate::context::testutil::DummyCtx::with_sync_ctx(DummyCtx::with_state(
                    DummyEthernetCtx::new(DUMMY_CONFIG_V4.local_mac, Ipv6::MINIMUM_LINK_MTU.into()),
                ));
            <DummyCtx as ArpHandler<_, _, _>>::insert_static_neighbor(
                &mut sync_ctx,
                &mut non_sync_ctx,
                DummyDeviceId,
                DUMMY_CONFIG_V4.remote_ip.get(),
                DUMMY_CONFIG_V4.remote_mac.get(),
            );
            let _ = send_ip_frame(
                &mut sync_ctx,
                &mut non_sync_ctx,
                DummyDeviceId,
                DUMMY_CONFIG_V4.remote_ip,
                Buf::new(&mut vec![0; size], ..),
            );
            assert_eq!(sync_ctx.frames().len(), expect_frames_sent);
        }

        test(Ipv6::MINIMUM_LINK_MTU.into(), 1);
        test(usize::from(Ipv6::MINIMUM_LINK_MTU) + 1, 0);
    }

    #[test]
    fn test_pending_frames() {
        let mut state = EthernetDeviceStateBuilder::new(
            DUMMY_CONFIG_V4.local_mac,
            Ipv6::MINIMUM_LINK_MTU.into(),
        )
        .build();
        let ip = IpAddr::V4(DUMMY_CONFIG_V4.local_ip.get());
        assert_matches!(state.add_pending_frame(ip, Buf::new(vec![1], ..)), None);
        assert_matches!(state.add_pending_frame(ip, Buf::new(vec![2], ..)), None);
        assert_matches!(state.add_pending_frame(ip, Buf::new(vec![3], ..)), None);

        // Check that we're accumulating correctly...
        assert_eq!(3, state.take_pending_frames(ip).unwrap().count());
        // ...and that take_pending_frames clears all the buffered data.
        assert!(state.take_pending_frames(ip).is_none());

        for i in 0..ETHERNET_MAX_PENDING_FRAMES {
            assert!(state.add_pending_frame(ip, Buf::new(vec![i as u8], ..)).is_none());
        }
        // Check that adding more than capacity will drop the older buffers as
        // a proper FIFO queue.
        assert_eq!(0, state.add_pending_frame(ip, Buf::new(vec![255], ..)).unwrap().as_ref()[0]);
        assert_eq!(1, state.add_pending_frame(ip, Buf::new(vec![255], ..)).unwrap().as_ref()[0]);
        assert_eq!(2, state.add_pending_frame(ip, Buf::new(vec![255], ..)).unwrap().as_ref()[0]);
    }

    fn test_receive_ip_frame<I: Ip + TestIpExt>(enable: bool) {
        // Should only receive a frame if the device is enabled.

        let config = I::DUMMY_CONFIG;
        let Ctx { mut sync_ctx, mut non_sync_ctx } = DummyEventDispatcherBuilder::default().build();
        let device = crate::add_ethernet_device(
            &mut sync_ctx,
            &mut non_sync_ctx,
            config.local_mac,
            Ipv6::MINIMUM_LINK_MTU.into(),
        );

        let mut bytes = match I::VERSION {
            IpVersion::V4 => dns_request_v4::ETHERNET_FRAME,
            IpVersion::V6 => dns_request_v6::ETHERNET_FRAME,
        }
        .bytes
        .to_vec();

        let mac_bytes = config.local_mac.bytes();
        bytes[0..6].copy_from_slice(&mac_bytes);

        let expected_received = if enable {
            crate::device::testutil::enable_device(&mut sync_ctx, &mut non_sync_ctx, device);
            1
        } else {
            0
        };

        crate::device::receive_frame(&mut sync_ctx, &mut non_sync_ctx, device, Buf::new(bytes, ..))
            .expect("error receiving frame");

        let counter = match I::VERSION {
            IpVersion::V4 => "receive_ipv4_packet",
            IpVersion::V6 => "receive_ipv6_packet",
        };
        assert_eq!(get_counter_val(&mut sync_ctx, counter), expected_received);
    }

    // TODO(https://fxbug.dev/102105): Unify these when #[ip_test] works with
    // #[test_case].
    #[ip_test]
    fn receive_frame_disabled<I: Ip + TestIpExt>() {
        test_receive_ip_frame::<I>(false);
    }

    #[ip_test]
    fn receive_frame_enabled<I: Ip + TestIpExt>() {
        test_receive_ip_frame::<I>(true);
    }

    fn test_send_ip_frame<I: Ip + TestIpExt>(enable: bool) {
        // Should only send a frame if the device is enabled.

        let config = I::DUMMY_CONFIG;
        let Ctx { mut sync_ctx, mut non_sync_ctx } = crate::testutil::DummyCtx::default();
        let device = crate::add_ethernet_device(
            &mut sync_ctx,
            &mut non_sync_ctx,
            config.local_mac,
            Ipv6::MINIMUM_LINK_MTU.into(),
        );

        let expected_sent = if enable {
            crate::device::testutil::enable_device(&mut sync_ctx, &mut non_sync_ctx, device);
            1
        } else {
            0
        };

        match I::VERSION {
            IpVersion::V4 => {
                let addr = SpecifiedAddr::new(dns_request_v4::IPV4_PACKET.metadata.dst_ip).unwrap();
                crate::device::insert_static_arp_table_entry(
                    &mut sync_ctx,
                    &mut non_sync_ctx,
                    device,
                    addr.get(),
                    config.remote_mac,
                )
                .expect("insert static ARP entry");

                crate::ip::device::send_ip_frame::<Ipv4, _, _, _, _>(
                    &mut sync_ctx,
                    &mut non_sync_ctx,
                    device,
                    addr,
                    Buf::new(dns_request_v4::IPV4_PACKET.bytes.to_vec(), ..),
                )
                .expect("error sending IPv4 frame")
            }

            IpVersion::V6 => {
                let addr = UnicastAddr::new(dns_request_v6::IPV6_PACKET.metadata.dst_ip).unwrap();
                crate::device::insert_ndp_table_entry(
                    &mut sync_ctx,
                    &mut non_sync_ctx,
                    device,
                    addr,
                    config.remote_mac.get(),
                )
                .expect("insert static NDP entry");
                crate::ip::device::send_ip_frame::<Ipv6, _, _, _, _>(
                    &mut sync_ctx,
                    &mut non_sync_ctx,
                    device,
                    addr.into_specified(),
                    Buf::new(dns_request_v6::IPV6_PACKET.bytes.to_vec(), ..),
                )
                .expect("error sending IPv6 frame")
            }
        }

        assert_eq!(get_counter_val(&mut sync_ctx, "ethernet::send_ip_frame"), expected_sent);
    }

    // TODO(https://fxbug.dev/102105): Unify these when #[ip_test] works with
    // #[test_case].
    #[ip_test]
    fn test_send_frame_disabled<I: Ip + TestIpExt>() {
        test_send_ip_frame::<I>(false);
    }

    #[ip_test]
    fn test_send_frame_enabled<I: Ip + TestIpExt>() {
        test_send_ip_frame::<I>(true);
    }

    #[test]
    fn initialize_once() {
        let Ctx { mut sync_ctx, mut non_sync_ctx } = DummyEventDispatcherBuilder::default().build();
        let device = crate::add_ethernet_device(
            &mut sync_ctx,
            &mut non_sync_ctx,
            DUMMY_CONFIG_V4.local_mac,
            Ipv6::MINIMUM_LINK_MTU.into(),
        );
        crate::device::testutil::enable_device(&mut sync_ctx, &mut non_sync_ctx, device);
    }

    fn is_routing_enabled<I: Ip>(
        sync_ctx: &crate::testutil::DummySyncCtx,
        device: DeviceId,
    ) -> bool {
        match I::VERSION {
            IpVersion::V4 => is_ipv4_routing_enabled(sync_ctx, device),
            IpVersion::V6 => is_ipv6_routing_enabled(sync_ctx, device),
        }
    }

    #[ip_test]
    fn test_set_ip_routing<I: Ip + TestIpExt + IcmpIpExt + IpExt>() {
        fn check_other_is_routing_enabled<I: Ip>(
            sync_ctx: &crate::testutil::DummySyncCtx,
            device: DeviceId,
            expected: bool,
        ) {
            let enabled = match I::VERSION {
                IpVersion::V4 => is_routing_enabled::<Ipv6>(sync_ctx, device),
                IpVersion::V6 => is_routing_enabled::<Ipv4>(sync_ctx, device),
            };

            assert_eq!(enabled, expected);
        }

        fn check_icmp<I: Ip>(buf: &[u8]) {
            match I::VERSION {
                IpVersion::V4 => {
                    let _ = parse_icmp_packet_in_ip_packet_in_ethernet_frame::<
                        Ipv4,
                        _,
                        IcmpDestUnreachable,
                        _,
                    >(buf, |_| {})
                    .unwrap();
                }
                IpVersion::V6 => {
                    let _ = parse_icmp_packet_in_ip_packet_in_ethernet_frame::<
                        Ipv6,
                        _,
                        IcmpDestUnreachable,
                        _,
                    >(buf, |_| {})
                    .unwrap();
                }
            }
        }

        let src_ip = I::get_other_ip_address(3);
        let src_mac = UnicastAddr::new(Mac::new([10, 11, 12, 13, 14, 15])).unwrap();
        let config = I::DUMMY_CONFIG;
        let device = DeviceId::new_ethernet(0);
        let frame_dst = FrameDestination::Unicast;
        let mut rng = new_rng(70812476915813);
        let mut body: Vec<u8> = core::iter::repeat_with(|| rng.gen()).take(100).collect();
        let buf = Buf::new(&mut body[..], ..)
            .encapsulate(I::PacketBuilder::new(
                src_ip.get(),
                config.remote_ip.get(),
                64,
                IpProto::Tcp.into(),
            ))
            .serialize_vec_outer()
            .ok()
            .unwrap()
            .unwrap_b();

        // Test with netstack no forwarding

        let mut builder = DummyEventDispatcherBuilder::from_config(config.clone());
        let device_builder_id = 0;
        add_arp_or_ndp_table_entry(&mut builder, device_builder_id, src_ip.get(), src_mac);
        let Ctx { mut sync_ctx, mut non_sync_ctx } = builder.build();

        // Should not be a router (default).
        assert!(!is_routing_enabled::<I>(&sync_ctx, device));
        check_other_is_routing_enabled::<I>(&sync_ctx, device, false);

        // Receiving a packet not destined for the node should only result in a
        // dest unreachable message if routing is enabled.
        receive_ip_packet::<_, _, I>(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            frame_dst,
            buf.clone(),
        );
        assert_empty(non_sync_ctx.frames_sent().iter());

        // Set routing and expect packets to be forwarded.
        set_routing_enabled::<_, _, I>(&mut sync_ctx, &mut non_sync_ctx, device, true)
            .expect("error setting routing enabled");
        assert!(is_routing_enabled::<I>(&sync_ctx, device));
        // Should not update other Ip routing status.
        check_other_is_routing_enabled::<I>(&sync_ctx, device, false);

        // Should route the packet since routing fully enabled (netstack &
        // device).
        receive_ip_packet::<_, _, I>(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            frame_dst,
            buf.clone(),
        );
        assert_eq!(non_sync_ctx.frames_sent().len(), 1);
        let (packet_buf, _, _, packet_src_ip, packet_dst_ip, proto, ttl) =
            parse_ip_packet_in_ethernet_frame::<I>(&non_sync_ctx.frames_sent()[0].1[..]).unwrap();
        assert_eq!(src_ip.get(), packet_src_ip);
        assert_eq!(config.remote_ip.get(), packet_dst_ip);
        assert_eq!(proto, IpProto::Tcp.into());
        assert_eq!(body, packet_buf);
        assert_eq!(ttl, 63);

        // Test routing a packet to an unknown address.
        let buf_unknown_dest = Buf::new(&mut body[..], ..)
            .encapsulate(I::PacketBuilder::new(
                src_ip.get(),
                // Addr must be remote, otherwise this will cause an NDP/ARP
                // request rather than ICMP unreachable.
                I::get_other_remote_ip_address(10).get(),
                64,
                IpProto::Tcp.into(),
            ))
            .serialize_vec_outer()
            .ok()
            .unwrap()
            .unwrap_b();
        receive_ip_packet::<_, _, I>(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            frame_dst,
            buf_unknown_dest,
        );
        assert_eq!(non_sync_ctx.frames_sent().len(), 2);
        check_icmp::<I>(&non_sync_ctx.frames_sent()[1].1);

        // Attempt to unset router
        set_routing_enabled::<_, _, I>(&mut sync_ctx, &mut non_sync_ctx, device, false)
            .expect("error setting routing enabled");
        assert!(!is_routing_enabled::<I>(&sync_ctx, device));
        check_other_is_routing_enabled::<I>(&sync_ctx, device, false);

        // Should not route packets anymore
        receive_ip_packet::<_, _, I>(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            frame_dst,
            buf.clone(),
        );
        assert_eq!(non_sync_ctx.frames_sent().len(), 2);
    }

    #[ip_test]
    fn test_promiscuous_mode<I: Ip + TestIpExt + IpExt>() {
        // Test that frames not destined for a device will still be accepted
        // when the device is put into promiscuous mode. In all cases, frames
        // that are destined for a device must always be accepted.

        let config = I::DUMMY_CONFIG;
        let Ctx { mut sync_ctx, mut non_sync_ctx } =
            DummyEventDispatcherBuilder::from_config(config.clone()).build();
        let device = DeviceId::new_ethernet(0);
        let other_mac = Mac::new([13, 14, 15, 16, 17, 18]);

        let buf = Buf::new(Vec::new(), ..)
            .encapsulate(I::PacketBuilder::new(
                config.remote_ip.get(),
                config.local_ip.get(),
                64,
                IpProto::Tcp.into(),
            ))
            .encapsulate(EthernetFrameBuilder::new(
                config.remote_mac.get(),
                config.local_mac.get(),
                I::ETHER_TYPE,
            ))
            .serialize_vec_outer()
            .ok()
            .unwrap()
            .unwrap_b();

        // Accept packet destined for this device if promiscuous mode is off.
        crate::device::set_promiscuous_mode(&mut sync_ctx, &mut non_sync_ctx, device, false)
            .expect("error setting promiscuous mode");
        crate::device::receive_frame(&mut sync_ctx, &mut non_sync_ctx, device, buf.clone())
            .expect("error receiving frame");
        assert_eq!(get_counter_val(&mut sync_ctx, dispatch_receive_ip_packet_name::<I>()), 1);

        // Accept packet destined for this device if promiscuous mode is on.
        crate::device::set_promiscuous_mode(&mut sync_ctx, &mut non_sync_ctx, device, true)
            .expect("error setting promiscuous mode");
        crate::device::receive_frame(&mut sync_ctx, &mut non_sync_ctx, device, buf.clone())
            .expect("error receiving frame");
        assert_eq!(get_counter_val(&mut sync_ctx, dispatch_receive_ip_packet_name::<I>()), 2);

        let buf = Buf::new(Vec::new(), ..)
            .encapsulate(I::PacketBuilder::new(
                config.remote_ip.get(),
                config.local_ip.get(),
                64,
                IpProto::Tcp.into(),
            ))
            .encapsulate(EthernetFrameBuilder::new(
                config.remote_mac.get(),
                other_mac,
                I::ETHER_TYPE,
            ))
            .serialize_vec_outer()
            .ok()
            .unwrap()
            .unwrap_b();

        // Reject packet not destined for this device if promiscuous mode is
        // off.
        crate::device::set_promiscuous_mode(&mut sync_ctx, &mut non_sync_ctx, device, false)
            .expect("error setting promiscuous mode");
        crate::device::receive_frame(&mut sync_ctx, &mut non_sync_ctx, device, buf.clone())
            .expect("error receiving frame");
        assert_eq!(get_counter_val(&mut sync_ctx, dispatch_receive_ip_packet_name::<I>()), 2);

        // Accept packet not destined for this device if promiscuous mode is on.
        crate::device::set_promiscuous_mode(&mut sync_ctx, &mut non_sync_ctx, device, true)
            .expect("error setting promiscuous mode");
        crate::device::receive_frame(&mut sync_ctx, &mut non_sync_ctx, device, buf.clone())
            .expect("error receiving frame");
        assert_eq!(get_counter_val(&mut sync_ctx, dispatch_receive_ip_packet_name::<I>()), 3);
    }

    #[ip_test]
    fn test_add_remove_ip_addresses<I: Ip + TestIpExt + DeviceTestIpExt<DummyInstant>>() {
        let config = I::DUMMY_CONFIG;
        let Ctx { mut sync_ctx, mut non_sync_ctx } = DummyEventDispatcherBuilder::default().build();
        let device = crate::add_ethernet_device(
            &mut sync_ctx,
            &mut non_sync_ctx,
            config.local_mac,
            Ipv6::MINIMUM_LINK_MTU.into(),
        );
        crate::device::testutil::enable_device(&mut sync_ctx, &mut non_sync_ctx, device);

        let ip1 = I::get_other_ip_address(1);
        let ip2 = I::get_other_ip_address(2);
        let ip3 = I::get_other_ip_address(3);

        let prefix = I::Addr::BYTES * 8;
        let as1 = AddrSubnet::new(ip1.get(), prefix).unwrap();
        let as2 = AddrSubnet::new(ip2.get(), prefix).unwrap();

        assert!(!contains_addr(&sync_ctx, device, ip1));
        assert!(!contains_addr(&sync_ctx, device, ip2));
        assert!(!contains_addr(&sync_ctx, device, ip3));

        // Add ip1 (ok)
        crate::device::add_ip_addr_subnet(&mut sync_ctx, &mut non_sync_ctx, device, as1).unwrap();
        assert!(contains_addr(&sync_ctx, device, ip1));
        assert!(!contains_addr(&sync_ctx, device, ip2));
        assert!(!contains_addr(&sync_ctx, device, ip3));

        // Add ip2 (ok)
        crate::device::add_ip_addr_subnet(&mut sync_ctx, &mut non_sync_ctx, device, as2).unwrap();
        assert!(contains_addr(&sync_ctx, device, ip1));
        assert!(contains_addr(&sync_ctx, device, ip2));
        assert!(!contains_addr(&sync_ctx, device, ip3));

        // Del ip1 (ok)
        crate::device::del_ip_addr(&mut sync_ctx, &mut non_sync_ctx, device, &ip1).unwrap();
        assert!(!contains_addr(&sync_ctx, device, ip1));
        assert!(contains_addr(&sync_ctx, device, ip2));
        assert!(!contains_addr(&sync_ctx, device, ip3));

        // Del ip1 again (ip1 not found)
        assert_eq!(
            crate::device::del_ip_addr(&mut sync_ctx, &mut non_sync_ctx, device, &ip1),
            Err(NotFoundError)
        );
        assert!(!contains_addr(&sync_ctx, device, ip1));
        assert!(contains_addr(&sync_ctx, device, ip2));
        assert!(!contains_addr(&sync_ctx, device, ip3));

        // Add ip2 again (ip2 already exists)
        assert_eq!(
            crate::device::add_ip_addr_subnet(&mut sync_ctx, &mut non_sync_ctx, device, as2)
                .unwrap_err(),
            ExistsError,
        );
        assert!(!contains_addr(&sync_ctx, device, ip1));
        assert!(contains_addr(&sync_ctx, device, ip2));
        assert!(!contains_addr(&sync_ctx, device, ip3));

        // Add ip2 with different subnet (ip2 already exists)
        assert_eq!(
            crate::device::add_ip_addr_subnet(
                &mut sync_ctx,
                &mut non_sync_ctx,
                device,
                AddrSubnet::new(ip2.get(), prefix - 1).unwrap()
            )
            .unwrap_err(),
            ExistsError,
        );
        assert!(!contains_addr(&sync_ctx, device, ip1));
        assert!(contains_addr(&sync_ctx, device, ip2));
        assert!(!contains_addr(&sync_ctx, device, ip3));
    }

    fn receive_simple_ip_packet_test<A: IpAddress>(
        sync_ctx: &mut crate::testutil::DummySyncCtx,
        non_sync_ctx: &mut crate::testutil::DummyNonSyncCtx,
        device: DeviceId,
        src_ip: A,
        dst_ip: A,
        expected: usize,
    ) {
        let buf = Buf::new(Vec::new(), ..)
            .encapsulate(<A::Version as IpExt>::PacketBuilder::new(
                src_ip,
                dst_ip,
                64,
                IpProto::Tcp.into(),
            ))
            .serialize_vec_outer()
            .ok()
            .unwrap()
            .into_inner();

        receive_ip_packet::<_, _, A::Version>(
            sync_ctx,
            non_sync_ctx,
            device,
            FrameDestination::Unicast,
            buf,
        );
        assert_eq!(
            get_counter_val(sync_ctx, dispatch_receive_ip_packet_name::<A::Version>()),
            expected
        );
    }

    #[ip_test]
    fn test_multiple_ip_addresses<I: Ip + TestIpExt + DeviceTestIpExt<DummyInstant>>() {
        let config = I::DUMMY_CONFIG;
        let Ctx { mut sync_ctx, mut non_sync_ctx } = DummyEventDispatcherBuilder::default().build();
        let device = crate::add_ethernet_device(
            &mut sync_ctx,
            &mut non_sync_ctx,
            config.local_mac,
            Ipv6::MINIMUM_LINK_MTU.into(),
        );
        crate::device::testutil::enable_device(&mut sync_ctx, &mut non_sync_ctx, device);

        let ip1 = I::get_other_ip_address(1);
        let ip2 = I::get_other_ip_address(2);
        let from_ip = I::get_other_ip_address(3).get();

        assert!(!contains_addr(&sync_ctx, device, ip1));
        assert!(!contains_addr(&sync_ctx, device, ip2));

        // Should not receive packets on any IP.
        receive_simple_ip_packet_test(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            from_ip,
            ip1.get(),
            0,
        );
        receive_simple_ip_packet_test(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            from_ip,
            ip2.get(),
            0,
        );

        // Add ip1 to device.
        crate::device::add_ip_addr_subnet(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            AddrSubnet::new(ip1.get(), I::Addr::BYTES * 8).unwrap(),
        )
        .unwrap();
        assert!(contains_addr(&sync_ctx, device, ip1));
        assert!(!contains_addr(&sync_ctx, device, ip2));

        // Should receive packets on ip1 but not ip2
        receive_simple_ip_packet_test(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            from_ip,
            ip1.get(),
            1,
        );
        receive_simple_ip_packet_test(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            from_ip,
            ip2.get(),
            1,
        );

        // Add ip2 to device.
        crate::device::add_ip_addr_subnet(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            AddrSubnet::new(ip2.get(), I::Addr::BYTES * 8).unwrap(),
        )
        .unwrap();
        assert!(contains_addr(&sync_ctx, device, ip1));
        assert!(contains_addr(&sync_ctx, device, ip2));

        // Should receive packets on both ips
        receive_simple_ip_packet_test(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            from_ip,
            ip1.get(),
            2,
        );
        receive_simple_ip_packet_test(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            from_ip,
            ip2.get(),
            3,
        );

        // Remove ip1
        crate::device::del_ip_addr(&mut sync_ctx, &mut non_sync_ctx, device, &ip1).unwrap();
        assert!(!contains_addr(&sync_ctx, device, ip1));
        assert!(contains_addr(&sync_ctx, device, ip2));

        // Should receive packets on ip2
        receive_simple_ip_packet_test(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            from_ip,
            ip1.get(),
            3,
        );
        receive_simple_ip_packet_test(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            from_ip,
            ip2.get(),
            4,
        );
    }

    fn join_ip_multicast<A: IpAddress, NonSyncCtx: NonSyncContext>(
        sync_ctx: &mut SyncCtx<NonSyncCtx>,
        ctx: &mut NonSyncCtx,
        device: DeviceId,
        multicast_addr: MulticastAddr<A>,
    ) {
        match multicast_addr.into() {
            IpAddr::V4(multicast_addr) => crate::ip::device::join_ip_multicast::<Ipv4, _, _>(
                sync_ctx,
                ctx,
                device,
                multicast_addr,
            ),
            IpAddr::V6(multicast_addr) => crate::ip::device::join_ip_multicast::<Ipv6, _, _>(
                sync_ctx,
                ctx,
                device,
                multicast_addr,
            ),
        }
    }

    fn leave_ip_multicast<A: IpAddress, NonSyncCtx: NonSyncContext>(
        sync_ctx: &mut SyncCtx<NonSyncCtx>,
        ctx: &mut NonSyncCtx,
        device: DeviceId,
        multicast_addr: MulticastAddr<A>,
    ) {
        match multicast_addr.into() {
            IpAddr::V4(multicast_addr) => crate::ip::device::leave_ip_multicast::<Ipv4, _, _>(
                sync_ctx,
                ctx,
                device,
                multicast_addr,
            ),
            IpAddr::V6(multicast_addr) => crate::ip::device::leave_ip_multicast::<Ipv6, _, _>(
                sync_ctx,
                ctx,
                device,
                multicast_addr,
            ),
        }
    }

    /// Test that we can join and leave a multicast group, but we only truly
    /// leave it after calling `leave_ip_multicast` the same number of times as
    /// `join_ip_multicast`.
    #[ip_test]
    fn test_ip_join_leave_multicast_addr_ref_count<
        I: Ip + TestIpExt + DeviceTestIpExt<DummyInstant>,
    >() {
        let config = I::DUMMY_CONFIG;
        let Ctx { mut sync_ctx, mut non_sync_ctx } = DummyEventDispatcherBuilder::default().build();
        let device = crate::add_ethernet_device(
            &mut sync_ctx,
            &mut non_sync_ctx,
            config.local_mac,
            Ipv6::MINIMUM_LINK_MTU.into(),
        );
        crate::device::testutil::enable_device(&mut sync_ctx, &mut non_sync_ctx, device);

        let multicast_addr = I::get_multicast_addr(3);

        // Should not be in the multicast group yet.
        assert!(!is_in_ip_multicast(&sync_ctx, device, multicast_addr));

        // Join the multicast group.
        join_ip_multicast(&mut sync_ctx, &mut non_sync_ctx, device, multicast_addr);
        assert!(is_in_ip_multicast(&sync_ctx, device, multicast_addr));

        // Leave the multicast group.
        leave_ip_multicast(&mut sync_ctx, &mut non_sync_ctx, device, multicast_addr);
        assert!(!is_in_ip_multicast(&sync_ctx, device, multicast_addr));

        // Join the multicst group.
        join_ip_multicast(&mut sync_ctx, &mut non_sync_ctx, device, multicast_addr);
        assert!(is_in_ip_multicast(&sync_ctx, device, multicast_addr));

        // Join it again...
        join_ip_multicast(&mut sync_ctx, &mut non_sync_ctx, device, multicast_addr);
        assert!(is_in_ip_multicast(&sync_ctx, device, multicast_addr));

        // Leave it (still in it because we joined twice).
        leave_ip_multicast(&mut sync_ctx, &mut non_sync_ctx, device, multicast_addr);
        assert!(is_in_ip_multicast(&sync_ctx, device, multicast_addr));

        // Leave it again... (actually left now).
        leave_ip_multicast(&mut sync_ctx, &mut non_sync_ctx, device, multicast_addr);
        assert!(!is_in_ip_multicast(&sync_ctx, device, multicast_addr));
    }

    /// Test leaving a multicast group a device has not yet joined.
    ///
    /// # Panics
    ///
    /// This method should always panic as leaving an unjoined multicast group
    /// is a panic condition.
    #[ip_test]
    #[should_panic(expected = "attempted to leave IP multicast group we were not a member of:")]
    fn test_ip_leave_unjoined_multicast<I: Ip + TestIpExt + DeviceTestIpExt<DummyInstant>>() {
        let config = I::DUMMY_CONFIG;
        let Ctx { mut sync_ctx, mut non_sync_ctx } = DummyEventDispatcherBuilder::default().build();
        let device = crate::add_ethernet_device(
            &mut sync_ctx,
            &mut non_sync_ctx,
            config.local_mac,
            Ipv6::MINIMUM_LINK_MTU.into(),
        );
        crate::device::testutil::enable_device(&mut sync_ctx, &mut non_sync_ctx, device);

        let multicast_addr = I::get_multicast_addr(3);

        // Should not be in the multicast group yet.
        assert!(!is_in_ip_multicast(&sync_ctx, device, multicast_addr));

        // Leave it (this should panic).
        leave_ip_multicast(&mut sync_ctx, &mut non_sync_ctx, device, multicast_addr);
    }

    #[test]
    fn test_ipv6_duplicate_solicited_node_address() {
        // Test that we still receive packets destined to a solicited-node
        // multicast address of an IP address we deleted because another
        // (distinct) IP address that is still assigned uses the same
        // solicited-node multicast address.

        let config = Ipv6::DUMMY_CONFIG;
        let Ctx { mut sync_ctx, mut non_sync_ctx } = DummyEventDispatcherBuilder::default().build();
        let device = crate::add_ethernet_device(
            &mut sync_ctx,
            &mut non_sync_ctx,
            config.local_mac,
            Ipv6::MINIMUM_LINK_MTU.into(),
        );
        crate::device::testutil::enable_device(&mut sync_ctx, &mut non_sync_ctx, device);

        let ip1 = SpecifiedAddr::new(Ipv6Addr::new([0, 0, 0, 1, 0, 0, 0, 1])).unwrap();
        let ip2 = SpecifiedAddr::new(Ipv6Addr::new([0, 0, 0, 2, 0, 0, 0, 1])).unwrap();
        let from_ip = Ipv6Addr::new([0, 0, 0, 3, 0, 0, 0, 1]);

        // ip1 and ip2 are not equal but their solicited node addresses are the
        // same.
        assert_ne!(ip1, ip2);
        assert_eq!(ip1.to_solicited_node_address(), ip2.to_solicited_node_address());
        let sn_addr = ip1.to_solicited_node_address().get();

        let addr_sub1 = AddrSubnet::new(ip1.get(), 64).unwrap();
        let addr_sub2 = AddrSubnet::new(ip2.get(), 64).unwrap();

        assert_eq!(get_counter_val(&mut sync_ctx, "dispatch_receive_ip_packet"), 0);

        // Add ip1 to the device.
        //
        // Should get packets destined for the solicited node address and ip1.
        crate::device::add_ip_addr_subnet(&mut sync_ctx, &mut non_sync_ctx, device, addr_sub1)
            .unwrap();
        receive_simple_ip_packet_test(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            from_ip,
            ip1.get(),
            1,
        );
        receive_simple_ip_packet_test(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            from_ip,
            ip2.get(),
            1,
        );
        receive_simple_ip_packet_test(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            from_ip,
            sn_addr,
            2,
        );

        // Add ip2 to the device.
        //
        // Should get packets destined for the solicited node address, ip1 and
        // ip2.
        crate::device::add_ip_addr_subnet(&mut sync_ctx, &mut non_sync_ctx, device, addr_sub2)
            .unwrap();
        receive_simple_ip_packet_test(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            from_ip,
            ip1.get(),
            3,
        );
        receive_simple_ip_packet_test(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            from_ip,
            ip2.get(),
            4,
        );
        receive_simple_ip_packet_test(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            from_ip,
            sn_addr,
            5,
        );

        // Remove ip1 from the device.
        //
        // Should get packets destined for the solicited node address and ip2.
        crate::device::del_ip_addr(&mut sync_ctx, &mut non_sync_ctx, device, &ip1).unwrap();
        receive_simple_ip_packet_test(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            from_ip,
            ip1.get(),
            5,
        );
        receive_simple_ip_packet_test(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            from_ip,
            ip2.get(),
            6,
        );
        receive_simple_ip_packet_test(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device,
            from_ip,
            sn_addr,
            7,
        );
    }

    #[test]
    fn test_add_ip_addr_subnet_link_local() {
        // Test that `add_ip_addr_subnet` allows link-local addresses.

        let config = Ipv6::DUMMY_CONFIG;
        let Ctx { mut sync_ctx, mut non_sync_ctx } = DummyEventDispatcherBuilder::default().build();
        let device = EthernetDeviceId(0);
        assert_eq!(
            crate::add_ethernet_device(
                &mut sync_ctx,
                &mut non_sync_ctx,
                config.local_mac,
                Ipv6::MINIMUM_LINK_MTU.into()
            ),
            DeviceIdInner::Ethernet(device).into()
        );

        crate::device::testutil::enable_device(&mut sync_ctx, &mut non_sync_ctx, device.into());
        // Verify that there is a single assigned address.
        assert_eq!(
            sync_ctx
                .state
                .device
                .ethernet
                .get(0)
                .unwrap()
                .ip
                .ipv6
                .ip_state
                .iter_addrs()
                .map(|entry| entry.addr_sub().addr())
                .collect::<Vec<_>>(),
            [config.local_mac.to_ipv6_link_local().addr().get()]
        );
        crate::device::add_ip_addr_subnet(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device.into(),
            AddrSubnet::new(Ipv6::LINK_LOCAL_UNICAST_SUBNET.network(), 128).unwrap(),
        )
        .unwrap();
        // Assert that the new address got added.
        let addr_subs: Vec<_> = sync_ctx
            .state
            .device
            .ethernet
            .get(0)
            .unwrap()
            .ip
            .ipv6
            .ip_state
            .iter_addrs()
            .map(|entry| entry.addr_sub().addr().get())
            .collect();
        assert_eq!(
            addr_subs,
            [
                config.local_mac.to_ipv6_link_local().addr().get(),
                Ipv6::LINK_LOCAL_UNICAST_SUBNET.network()
            ]
        );
    }
}
