[recovery-netstack] Tell IP layer: unicast or broadcast frame?
- Introduce the new FrameDestination type, expressing whether a
frame was destined to a unicast link-layer address or a broadcast
address
- Pass this as a parameter to ip::receive_ip_packet
- This functionality is exercised in a later commit, where ICMP
needs the information in order to make decisions about whether to
send an ICMP response (in particular, the RFC 1122 restrictions)
Change-Id: I2cc2055b151047a918eeea0f38115a4647d3e7c6
diff --git a/garnet/bin/recovery_netstack/core/src/device/ethernet.rs b/garnet/bin/recovery_netstack/core/src/device/ethernet.rs
index 04df64c..6c1a396 100644
--- a/garnet/bin/recovery_netstack/core/src/device/ethernet.rs
+++ b/garnet/bin/recovery_netstack/core/src/device/ethernet.rs
@@ -12,7 +12,7 @@
use zerocopy::{AsBytes, FromBytes, Unaligned};
use crate::device::arp::{ArpDevice, ArpHardwareType, ArpState};
-use crate::device::DeviceId;
+use crate::device::{DeviceId, FrameDestination};
use crate::ip::{AddrSubnet, Ip, IpAddress, Ipv4, Ipv4Addr, Ipv6, Ipv6Addr};
use crate::wire::arp::peek_arp_types;
use crate::wire::ethernet::{EthernetFrame, EthernetFrameBuilder};
@@ -263,6 +263,14 @@
let (src, dst) = (frame.src_mac(), frame.dst_mac());
let device = DeviceId::new_ethernet(device_id);
+ let frame_dst = if dst == get_device_state(ctx, device_id).mac {
+ FrameDestination::Unicast
+ } else if dst.is_broadcast() {
+ FrameDestination::Broadcast
+ } else {
+ return;
+ };
+
match frame.ethertype() {
Some(EtherType::Arp) => {
let types = if let Ok(types) = peek_arp_types(buffer.as_ref()) {
@@ -280,8 +288,12 @@
types => debug!("got ARP packet for unsupported types: {:?}", types),
}
}
- Some(EtherType::Ipv4) => crate::ip::receive_ip_packet::<D, _, Ipv4>(ctx, device, buffer),
- Some(EtherType::Ipv6) => crate::ip::receive_ip_packet::<D, _, Ipv6>(ctx, device, buffer),
+ Some(EtherType::Ipv4) => {
+ crate::ip::receive_ip_packet::<D, _, Ipv4>(ctx, device, frame_dst, buffer)
+ }
+ Some(EtherType::Ipv6) => {
+ crate::ip::receive_ip_packet::<D, _, Ipv6>(ctx, device, frame_dst, buffer)
+ }
Some(EtherType::Other(_)) | None => {} // TODO(joshlf)
}
}
diff --git a/garnet/bin/recovery_netstack/core/src/device/mod.rs b/garnet/bin/recovery_netstack/core/src/device/mod.rs
index aae58ee..3a10803 100644
--- a/garnet/bin/recovery_netstack/core/src/device/mod.rs
+++ b/garnet/bin/recovery_netstack/core/src/device/mod.rs
@@ -65,6 +65,24 @@
}
}
+// TODO(joshlf): Does the IP layer ever need to distinguish between broadcast
+// and multicast frames?
+
+/// The type of address used as the source address in a device-layer frame:
+/// unicast or broadcast.
+#[derive(Copy, Clone, Eq, PartialEq)]
+pub(crate) enum FrameDestination {
+ Unicast,
+ Broadcast,
+}
+
+impl FrameDestination {
+ /// Is this `FrameDestination::Broadcast`?
+ pub(crate) fn is_broadcast(&self) -> bool {
+ *self == FrameDestination::Broadcast
+ }
+}
+
/// The state associated with the device layer.
pub(crate) struct DeviceLayerState {
// Invariant: even though each protocol has its own hash map, IDs (used as
diff --git a/garnet/bin/recovery_netstack/core/src/ip/icmp.rs b/garnet/bin/recovery_netstack/core/src/ip/icmp.rs
index b607cb552..76c3ca1 100644
--- a/garnet/bin/recovery_netstack/core/src/ip/icmp.rs
+++ b/garnet/bin/recovery_netstack/core/src/ip/icmp.rs
@@ -434,7 +434,7 @@
use std::num::NonZeroU16;
use super::*;
- use crate::device::DeviceId;
+ use crate::device::{DeviceId, FrameDestination};
use crate::ip::{receive_ip_packet, IpExt, Ipv4, Ipv4Addr};
use crate::testutil::{DummyEventDispatcherBuilder, DUMMY_CONFIG};
use crate::wire::icmp::{
@@ -482,7 +482,12 @@
let mut ctx = DummyEventDispatcherBuilder::from_config(DUMMY_CONFIG).build();
// currently only used by test_ttl_exceeded
ctx.state_mut().ip.v4.forward = true;
- receive_ip_packet::<_, _, Ipv4>(&mut ctx, DeviceId::new_ethernet(1), buffer);
+ receive_ip_packet::<_, _, Ipv4>(
+ &mut ctx,
+ DeviceId::new_ethernet(1),
+ FrameDestination::Unicast,
+ buffer,
+ );
for counter in assert_counters {
assert!(*ctx.state().test_counters.get(counter) > 0, "counter at zero: {}", counter);
diff --git a/garnet/bin/recovery_netstack/core/src/ip/mod.rs b/garnet/bin/recovery_netstack/core/src/ip/mod.rs
index 4fa24f0..d070ec10 100644
--- a/garnet/bin/recovery_netstack/core/src/ip/mod.rs
+++ b/garnet/bin/recovery_netstack/core/src/ip/mod.rs
@@ -23,7 +23,7 @@
};
use specialize_ip_macro::specialize_ip_address;
-use crate::device::DeviceId;
+use crate::device::{DeviceId, FrameDestination};
use crate::ip::forwarding::{Destination, ForwardingTable};
use crate::{Context, EventDispatcher};
@@ -160,9 +160,13 @@
}
/// Receive an IP packet from a device.
+///
+/// `frame_dst` specifies whether this packet was received in a broadcast or
+/// unicast link-layer frame.
pub(crate) fn receive_ip_packet<D: EventDispatcher, B: BufferMut, I: Ip>(
ctx: &mut Context<D>,
device: DeviceId,
+ frame_dst: FrameDestination,
mut buffer: B,
) {
trace!("receive_ip_packet({})", device);