From 81b0d7269c0c20b3f73046797ce87efd5e1d48f0 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 17 Dec 2022 16:45:32 +0100 Subject: [PATCH 1/9] Begin work on address filtering --- Cargo.toml | 8 +- src/mac/frame_filtering/control.rs | 31 +++ src/mac/frame_filtering/destination.rs | 58 ++++++ src/mac/frame_filtering/hash_table.rs | 25 +++ src/mac/frame_filtering/mod.rs | 264 +++++++++++++++++++++++++ src/mac/frame_filtering/multicast.rs | 33 ++++ src/mac/frame_filtering/source.rs | 33 ++++ src/mac/mod.rs | 21 +- 8 files changed, 459 insertions(+), 14 deletions(-) create mode 100644 src/mac/frame_filtering/control.rs create mode 100644 src/mac/frame_filtering/destination.rs create mode 100644 src/mac/frame_filtering/hash_table.rs create mode 100644 src/mac/frame_filtering/mod.rs create mode 100644 src/mac/frame_filtering/multicast.rs create mode 100644 src/mac/frame_filtering/source.rs diff --git a/Cargo.toml b/Cargo.toml index 644c8f4..5b2f44e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,8 @@ ieee802_3_miim = "0.7" cortex-m = "0.7" log = { version = "0.4", optional = true } defmt = { version = "0.3", optional = true } +bitflags = "1.3.2" +heapless = "0.7.16" [dependencies.smoltcp] version = "0.8" @@ -36,7 +38,7 @@ features = ["medium-ethernet", "proto-ipv4"] optional = true [features] -default = [ "defmt" ] +default = ["defmt"] device-selected = [] fence = [] @@ -64,8 +66,8 @@ stm32f779 = ["stm32f7xx-hal/stm32f779", "device-selected", "fence"] smoltcp-phy = ["smoltcp"] # Example features -example-nucleo-pins = [ ] -rtic-echo-example = [ "defmt", "smoltcp-phy", "smoltcp/defmt", "smoltcp/medium-ethernet", "smoltcp/socket-tcp" ] +example-nucleo-pins = [] +rtic-echo-example = ["defmt", "smoltcp-phy", "smoltcp/defmt", "smoltcp/medium-ethernet", "smoltcp/socket-tcp"] [dev-dependencies] cortex-m = { version = "0.7", features = ["critical-section-single-core"] } diff --git a/src/mac/frame_filtering/control.rs b/src/mac/frame_filtering/control.rs new file mode 100644 index 0000000..f8ffa6d --- /dev/null +++ b/src/mac/frame_filtering/control.rs @@ -0,0 +1,31 @@ +/// The type of frame filtering that the MAC should perform +/// on received control frames, +#[derive(Debug, Clone)] + +pub enum ControlFrameFiltering { + /// Prevent all control frames from reaching + /// the application. + BlockAll, + /// Allow all control frames to reach the application, + /// except for PAUSE control frames. + NoPause, + /// Allow all control frames to reach the application. + AllowAll, + /// Block control frames that do not pass the + /// configured address filter, but allow those that do. + AddressFilter, +} + +impl ControlFrameFiltering { + /// Create a new [`ControlFrameFiltering`] that filters out + /// all control frames. + pub const fn new() -> Self { + Self::BlockAll + } +} + +impl Default for ControlFrameFiltering { + fn default() -> Self { + Self::new() + } +} diff --git a/src/mac/frame_filtering/destination.rs b/src/mac/frame_filtering/destination.rs new file mode 100644 index 0000000..397148a --- /dev/null +++ b/src/mac/frame_filtering/destination.rs @@ -0,0 +1,58 @@ +use heapless::Vec; + +use super::MacAddressFilter; + +/// The type of filtering that the MAC should apply to +/// frames that are to be transmitted. +#[derive(Debug, Clone)] +pub struct DestinationAddressFiltering { + /// Filtering to be performed based on perfect address matches. + pub perfect_filtering: PerfectDestinationAddressFiltering, + /// Enable or disable hash table filtering for destination + /// addresses. + pub hash_table_filtering: bool, +} + +impl DestinationAddressFiltering { + /// Create a new [`DestinationAddressFiltering`] that does + /// not filter any frames. + pub const fn new() -> Self { + Self { + perfect_filtering: PerfectDestinationAddressFiltering::new(), + hash_table_filtering: false, + } + } +} + +impl Default for DestinationAddressFiltering { + fn default() -> Self { + Self::new() + } +} + +/// The type of destination address filtering that +/// the MAC should apply to frames. +#[derive(Debug, Clone)] + +pub enum PerfectDestinationAddressFiltering { + /// Filter frames by their Destination Address, based on + /// the provided addresses. + Normal(Vec), + /// Filter frames by their Destination Address, based on + /// the inverse of the provided addresses. + Inverse(Vec), +} + +impl PerfectDestinationAddressFiltering { + /// Create a new [`PerfectDestinationAddressFiltering`] that filters + /// out all frames. + pub const fn new() -> Self { + Self::Normal(Vec::new()) + } +} + +impl Default for PerfectDestinationAddressFiltering { + fn default() -> Self { + Self::new() + } +} diff --git a/src/mac/frame_filtering/hash_table.rs b/src/mac/frame_filtering/hash_table.rs new file mode 100644 index 0000000..e554736 --- /dev/null +++ b/src/mac/frame_filtering/hash_table.rs @@ -0,0 +1,25 @@ +#[derive(Debug, Clone)] +/// Configuration of the hash table used by the MAC for +/// destination address filtering. +pub struct HashTableValue { + /// The low register of the hash table. + pub low: u32, + /// The high register of the hash table. + pub high: u32, +} + +impl HashTableValue { + /// Create a new hash table value that filters + /// out all frames. + pub const fn new() -> Self { + Self { low: 0, high: 0 } + } +} + +/// By default, the hash table is configured so that +/// it filters out all frames. +impl Default for HashTableValue { + fn default() -> Self { + Self::new() + } +} diff --git a/src/mac/frame_filtering/mod.rs b/src/mac/frame_filtering/mod.rs new file mode 100644 index 0000000..c39e53a --- /dev/null +++ b/src/mac/frame_filtering/mod.rs @@ -0,0 +1,264 @@ +//! Hardware filtering of Ethernet frames + +use crate::hal::pac::ETHERNET_MAC; +use heapless::Vec; + +mod destination; +pub use destination::*; + +mod source; +pub use source::*; + +mod multicast; +pub use multicast::*; + +mod hash_table; +pub use hash_table::*; + +mod control; +pub use control::*; + +/// The frame filtering that the MAC should apply to +/// received Ethernet frames. +#[derive(Debug, Clone)] +pub enum FrameFilteringMode { + /// No frame filtering on any frames. + Promiscuous, + /// Perform frame filtering based on the provided + /// configuration. + Filter(FrameFiltering), +} + +impl Default for FrameFilteringMode { + fn default() -> Self { + Self::Promiscuous + } +} + +impl FrameFilteringMode { + pub(crate) fn configure(&self, eth_mac: ÐERNET_MAC) { + match self { + FrameFilteringMode::Promiscuous => eth_mac.macffr.write(|w| w.pm().set_bit()), + FrameFilteringMode::Filter(config) => config.configure(eth_mac), + } + } +} + +/// The type of frame filtering that the MAC +/// should perform. +/// +/// The total amount of [`MacAddressFilter`]s in this configuration object may +/// be at most 3. +#[derive(Debug, Clone)] +pub struct FrameFiltering { + /// The MAC address of this station. This address is always + /// used for Destination Address filtering. + pub address: Mac, + + /// Frame filtering applied to frames based on + /// their destination address. + pub destination_address_filter: DestinationAddressFiltering, + + /// Frame filtering applied to frames based on + /// their source address. + pub source_address_filter: SourceAddressFiltering, + + /// Frame filtering applied to frames based on + /// whether they have a multicast address or not. + pub multicast_address_filter: MulticastAddressFiltering, + + /// Control frame filtering mode, + pub control_filter: ControlFrameFiltering, + + /// Hash table configuration. + pub hash_table_value: HashTableValue, + + /// Enable or disable broadcast frame filtering. + /// + /// If set to `true`, broadcast frames will be filtered out. + pub filter_broadcast: bool, + + /// Enable or disable receive all mode. + /// + /// If receive all mode is disabled, address filtering + /// is applied to incoming frames (and corresponding bits + /// in the descriptors are configured), but the MAC does not + /// drop any frames. + pub receive_all: bool, +} + +impl FrameFiltering { + fn configure(&self, eth_mac: ÐERNET_MAC) { + let FrameFiltering { + address, + destination_address_filter, + source_address_filter, + multicast_address_filter, + control_filter, + hash_table_value: hash_table_filtering, + filter_broadcast, + receive_all, + } = self; + + eth_mac.maca0hr.write(|w| w.maca0h().bits(address.high())); + eth_mac.maca0lr.write(|w| w.maca0l().bits(address.low())); + + let (daif, dest_addrs) = match &destination_address_filter.perfect_filtering { + PerfectDestinationAddressFiltering::Normal(addrs) => (false, addrs), + PerfectDestinationAddressFiltering::Inverse(addrs) => (true, addrs), + }; + let hu = destination_address_filter.hash_table_filtering; + + let empty_vec = Vec::new(); + + let (saf, saif, source_addrs) = match &source_address_filter { + SourceAddressFiltering::PassAll => (false, false, &empty_vec), + SourceAddressFiltering::Normal(addrs) => (true, false, addrs), + SourceAddressFiltering::Inverse(addrs) => (true, true, addrs), + }; + + let (pam, hm, multicast_addrs) = match &multicast_address_filter { + MulticastAddressFiltering::PassAll => (true, false, &empty_vec), + MulticastAddressFiltering::DestinationAddressHash => (false, true, &empty_vec), + MulticastAddressFiltering::DestinationAddress(addrs) => (false, false, addrs), + }; + + let pcf = match &control_filter { + ControlFrameFiltering::BlockAll => 0b00, + ControlFrameFiltering::NoPause => 0b01, + ControlFrameFiltering::AllowAll => 0b10, + ControlFrameFiltering::AddressFilter => 0b11, + }; + + assert!( + source_addrs.len() + dest_addrs.len() + multicast_addrs.len() <= 3, + "A maximum of 3 combined source, destination, and multicast address filters may be configured at any time." + ); + + let mut dest_addrs = dest_addrs.iter(); + let mut source_addrs = source_addrs.iter(); + + macro_rules! next_addr_reg { + ($regh:ident, $regl:ident, $ah:ident, $al:ident) => { + if let Some((addr, sa)) = dest_addrs + .next() + .map(|v| (v, false)) + .or(source_addrs.next().map(|v| (v, true))) + { + eth_mac.$regh.write(|w| { + w.ae() + .set_bit() + .sa() + .bit(sa) + .mbc() + .bits(addr.mask.bits()) + .$ah() + .bits(addr.address.high()) + }); + + eth_mac.$regl.write(|w| w.$al().bits(addr.address.low())); + } + }; + } + + next_addr_reg!(maca1hr, maca1lr, maca1h, maca1l); + next_addr_reg!(maca2hr, maca2lr, maca2h, maca2l); + next_addr_reg!(maca3hr, maca3lr, maca3h, maca3l); + + eth_mac.macffr.write(|w| { + w.hpf() + .clear_bit() + .pm() + .clear_bit() + .ra() + .bit(*receive_all) + .saf() + .bit(saf) + .saif() + .bit(saif) + .pcf() + .bits(pcf) + .bfd() + .bit(*filter_broadcast) + .pam() + .bit(pam) + .daif() + .bit(daif) + .hm() + .bit(hm) + .hu() + .bit(hu) + }); + + eth_mac + .machthr + .write(|w| w.hth().bits(hash_table_filtering.high)); + + eth_mac + .machtlr + .write(|w| w.htl().bits(hash_table_filtering.low)); + } +} + +/// A big-endian MAC address. +#[derive(Debug, Clone)] +pub struct Mac([u8; 6]); + +impl Mac { + /// Create a new MAC address with the given big-endian value. + pub fn new(address: [u8; 6]) -> Self { + Self(address) + } + + /// Return bytes in a form that can be put into the high portion + /// of a MAC address register by converting them to little-endian + fn high(&self) -> u16 { + let high_bytes = [self.0[5], self.0[4]]; + u16::from_ne_bytes(high_bytes) + } + + /// Return bytes in a form that can be put into the low portion + /// of a MAC address register by converting them to little-endian. + fn low(&self) -> u32 { + let low_bytes = [self.0[3], self.0[2], self.0[1], self.0[0]]; + u32::from_ne_bytes(low_bytes) + } +} + +impl From<[u8; 6]> for Mac { + fn from(value: [u8; 6]) -> Self { + Self::new(value) + } +} + +/// A MAC address filter +#[derive(Debug, Clone)] + +pub struct MacAddressFilter { + /// The address that this filter should use. + pub address: Mac, + /// The byte mask that should be used to mask + /// out specific parts of the to-be-compared address + /// for comparison. + pub mask: MacAddressFilterMask, +} + +bitflags::bitflags! { + /// A mask to be applied when comparing a [`MacAddressFilter`] + /// to an incoming address. + pub struct MacAddressFilterMask: u8 { + /// Ignore byte 5 (the most significant byte) + /// during address comparison. + const BYTE5 = 1 << 5; + /// Ignore byte 4 during address comparison. + const BYTE4 = 1 << 4; + /// Ignore byte 3 during address comparison. + const BYTE3 = 1 << 3; + /// Ignore byte 2 during address comparison. + const BYTE2 = 1 << 2; + /// Ignore byte 1 during address comparison. + const BYTE1 = 1 << 1; + /// Ignore byte 0 during address comparison. + const BYTE0 = 1 << 0; + } +} diff --git a/src/mac/frame_filtering/multicast.rs b/src/mac/frame_filtering/multicast.rs new file mode 100644 index 0000000..24f75e9 --- /dev/null +++ b/src/mac/frame_filtering/multicast.rs @@ -0,0 +1,33 @@ +use heapless::Vec; + +use super::MacAddressFilter; + +/// Multicast address filtering +#[derive(Debug, Clone)] +pub enum MulticastAddressFiltering { + /// All received multicast frames are passed to the + /// application. + PassAll, + /// Only multicast frames whose destination address + /// passes the hash table check are passed to the + /// application. + DestinationAddressHash, + /// Only multicast frames whose destination address + /// is equal to one of the provided destination addresses + /// are passed to the application. + DestinationAddress(Vec), +} + +impl MulticastAddressFiltering { + /// Create a new MulticastAddressFiltering that does not + /// filter any multicast frames. + pub const fn new() -> Self { + Self::PassAll + } +} + +impl Default for MulticastAddressFiltering { + fn default() -> Self { + Self::new() + } +} diff --git a/src/mac/frame_filtering/source.rs b/src/mac/frame_filtering/source.rs new file mode 100644 index 0000000..9ccfe6f --- /dev/null +++ b/src/mac/frame_filtering/source.rs @@ -0,0 +1,33 @@ +use heapless::Vec; + +use super::MacAddressFilter; + +/// The type of frame filtering that the MAC should perform +/// on received frames. +#[derive(Debug, Clone)] + +pub enum SourceAddressFiltering { + /// All received frames are passed to the application, + /// ignoring all frame filtering settings. + PassAll, + /// Filter frames by their Source Address, based on + /// the provided addresses. + Normal(Vec), + /// Filter frames by their Source Address, based on + /// the inverse of the provided addresses. + Inverse(Vec), +} + +impl SourceAddressFiltering { + /// Create a new [`SourceAddressFiltering`] that + /// does not filter any frames. + pub const fn new() -> Self { + Self::Inverse(Vec::new()) + } +} + +impl Default for SourceAddressFiltering { + fn default() -> Self { + Self::new() + } +} diff --git a/src/mac/mod.rs b/src/mac/mod.rs index 7f0c706..9668670 100644 --- a/src/mac/mod.rs +++ b/src/mac/mod.rs @@ -11,6 +11,8 @@ use crate::{ mod miim; pub use miim::*; +pub mod frame_filtering; + /// Speeds at which this MAC can be configured #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -37,7 +39,7 @@ mod consts { /* For HCLK over 150 MHz */ pub const ETH_MACMIIAR_CR_HCLK_DIV_102: u8 = 4; } -use self::consts::*; +use self::{consts::*, frame_filtering::FrameFilteringMode}; /// HCLK must be at least 25MHz to use the ethernet peripheral. /// This (empty) struct is returned to indicate that it is not set @@ -115,16 +117,6 @@ impl EthernetMAC { .set_bit() }); - // Frame filter register - eth_mac.macffr.modify(|_, w| { - // Receive All - w.ra() - .set_bit() - // Promiscuous mode - .pm() - .set_bit() - }); - // Flow Control Register eth_mac.macfcr.modify(|_, w| { // Pause time @@ -147,6 +139,8 @@ impl EthernetMAC { .mmctimr .modify(|r, w| unsafe { w.bits(r.bits() | (1 << 21)) }); + FrameFilteringMode::Promiscuous.configure(ð_mac); + let mut me = Self { eth_mac }; me.set_speed(initial_speed); @@ -210,6 +204,11 @@ impl EthernetMAC { (true, true) => Speed::FullDuplexBase100Tx, } } + + /// Configure the frame filtering performed by this MAC. + pub fn configure_filtering(&self, filtering_config: &FrameFilteringMode) { + filtering_config.configure(&self.eth_mac); + } } /// Ethernet media access control (MAC) with owned MII From 575a0d0e8a96319e630c420ebae864c4cc32df86 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 17 Dec 2022 18:33:28 +0100 Subject: [PATCH 2/9] Add a basic FrameFiltering setup --- src/mac/frame_filtering/mod.rs | 36 ++++++++++++++++++++++++++++++- src/mac/frame_filtering/source.rs | 5 ++--- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/mac/frame_filtering/mod.rs b/src/mac/frame_filtering/mod.rs index c39e53a..135f66a 100644 --- a/src/mac/frame_filtering/mod.rs +++ b/src/mac/frame_filtering/mod.rs @@ -88,6 +88,33 @@ pub struct FrameFiltering { } impl FrameFiltering { + /// Create a new basic [`FrameFiltering`] that: + /// * Does not filter out frames destined for `station_addr` or an address + /// contained in `extra_address. + /// * Does not filter out multicast frames. + /// * Does not filter out broadcast frames. + /// * Filters out all control frames. + pub fn filter_destinations(station_addr: Mac, extra_addresses: Vec) -> Self { + let extra_addrs = extra_addresses + .into_iter() + .map(|a| MacAddressFilter::new(a, MacAddressFilterMask::empty())) + .collect(); + + FrameFiltering { + address: station_addr, + destination_address_filter: DestinationAddressFiltering { + perfect_filtering: PerfectDestinationAddressFiltering::Normal(extra_addrs), + hash_table_filtering: false, + }, + source_address_filter: SourceAddressFiltering::Ignore, + multicast_address_filter: MulticastAddressFiltering::PassAll, + control_filter: ControlFrameFiltering::BlockAll, + hash_table_value: HashTableValue::new(), + filter_broadcast: false, + receive_all: false, + } + } + fn configure(&self, eth_mac: ÐERNET_MAC) { let FrameFiltering { address, @@ -112,7 +139,7 @@ impl FrameFiltering { let empty_vec = Vec::new(); let (saf, saif, source_addrs) = match &source_address_filter { - SourceAddressFiltering::PassAll => (false, false, &empty_vec), + SourceAddressFiltering::Ignore => (false, false, &empty_vec), SourceAddressFiltering::Normal(addrs) => (true, false, addrs), SourceAddressFiltering::Inverse(addrs) => (true, true, addrs), }; @@ -243,6 +270,13 @@ pub struct MacAddressFilter { pub mask: MacAddressFilterMask, } +impl MacAddressFilter { + /// Create a new MAC address filter. + pub fn new(address: Mac, mask: MacAddressFilterMask) -> Self { + Self { address, mask } + } +} + bitflags::bitflags! { /// A mask to be applied when comparing a [`MacAddressFilter`] /// to an incoming address. diff --git a/src/mac/frame_filtering/source.rs b/src/mac/frame_filtering/source.rs index 9ccfe6f..2ca5b98 100644 --- a/src/mac/frame_filtering/source.rs +++ b/src/mac/frame_filtering/source.rs @@ -7,9 +7,8 @@ use super::MacAddressFilter; #[derive(Debug, Clone)] pub enum SourceAddressFiltering { - /// All received frames are passed to the application, - /// ignoring all frame filtering settings. - PassAll, + /// Source address filtering never fails. + Ignore, /// Filter frames by their Source Address, based on /// the provided addresses. Normal(Vec), From 518f3746a1e929f7682502530101dc25a54916a3 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 17 Dec 2022 22:17:14 +0100 Subject: [PATCH 3/9] Put unsafe operations in an `unsafe` --- src/mac/frame_filtering/mod.rs | 9 ++++++++- src/tx.rs | 1 - 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/mac/frame_filtering/mod.rs b/src/mac/frame_filtering/mod.rs index 135f66a..b4f2a8b 100644 --- a/src/mac/frame_filtering/mod.rs +++ b/src/mac/frame_filtering/mod.rs @@ -183,7 +183,14 @@ impl FrameFiltering { .bits(addr.address.high()) }); - eth_mac.$regl.write(|w| w.$al().bits(addr.address.low())); + // This operation is only unsafe for register maca2lr STM32F107 + // + // NOTE(safety): this operation is only unsafe for a single one + // of the lower-address-part registers, so this should be fine. + #[allow(unused_unsafe)] + eth_mac + .$regl + .write(|w| unsafe { w.$al().bits(addr.address.low()) }); } }; } diff --git a/src/tx.rs b/src/tx.rs index d2214ed..f2fd478 100644 --- a/src/tx.rs +++ b/src/tx.rs @@ -222,7 +222,6 @@ impl<'a> TxRing<'a> { // Register TxDescriptor eth_dma .dmatdlar - // Note: unsafe block required for `stm32f107`. .write(|w| unsafe { w.stl().bits(ring_ptr as u32) }); // "Preceding reads and writes cannot be moved past subsequent writes." From 48e48f64bbc77f953e63213445c0cdb3f6f9d574 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sun, 18 Dec 2022 13:56:55 +0100 Subject: [PATCH 4/9] Add some more status bit checks and pretty defmt print for `Mac` --- src/mac/frame_filtering/mod.rs | 38 +++++++++++++++++++++++++++++++++- src/rx.rs | 11 ++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/mac/frame_filtering/mod.rs b/src/mac/frame_filtering/mod.rs index b4f2a8b..f4670ff 100644 --- a/src/mac/frame_filtering/mod.rs +++ b/src/mac/frame_filtering/mod.rs @@ -90,7 +90,7 @@ pub struct FrameFiltering { impl FrameFiltering { /// Create a new basic [`FrameFiltering`] that: /// * Does not filter out frames destined for `station_addr` or an address - /// contained in `extra_address. + /// contained in `extra_address`. /// * Does not filter out multicast frames. /// * Does not filter out broadcast frames. /// * Filters out all control frames. @@ -244,6 +244,25 @@ impl Mac { Self(address) } + /// Get the raw bytes of this MAC address. + pub fn raw(&self) -> &[u8; 6] { + &self.0 + } + /// Returns `true` if this MAC is locally administred, i.e. it has the I/G bit set. + pub fn is_multicast(&self) -> bool { + (self.0[0] & 0b1) == 0b1 + } + + /// Returns `true` if this MAC is locally administred, i.e. it has the U/L bit set. + pub fn is_locally_administred(&self) -> bool { + (self.0[0] & 0b10) == 0b10 + } + + /// Returns `true` if this MAC is the broadcast address. + pub fn is_broadcast(&self) -> bool { + self.0.iter().all(|v| v == &0xFF) + } + /// Return bytes in a form that can be put into the high portion /// of a MAC address register by converting them to little-endian fn high(&self) -> u16 { @@ -265,6 +284,23 @@ impl From<[u8; 6]> for Mac { } } +#[cfg(feature = "defmt")] +impl defmt::Format for Mac { + fn format(&self, fmt: defmt::Formatter) { + let addr = self.0; + defmt::write!( + fmt, + "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}", + addr[0], + addr[1], + addr[2], + addr[3], + addr[4], + addr[5] + ) + } +} + /// A MAC address filter #[derive(Debug, Clone)] diff --git a/src/rx.rs b/src/rx.rs index cc08b73..0a5882c 100644 --- a/src/rx.rs +++ b/src/rx.rs @@ -34,6 +34,8 @@ const RXDESC_0_ES: u32 = 1 << 15; const RXDESC_0_FL_MASK: u32 = 0x3FFF; const RXDESC_0_FL_SHIFT: usize = 16; +const RXDESC_0_SAF: u32 = 1 << 13; + const RXDESC_1_RBS_SHIFT: usize = 0; const RXDESC_1_RBS_MASK: u32 = 0x0fff << RXDESC_1_RBS_SHIFT; /// Second address chained @@ -123,6 +125,10 @@ impl RxDescriptor { fn get_frame_len(&self) -> usize { ((self.desc.read(0) >> RXDESC_0_FL_SHIFT) & RXDESC_0_FL_MASK) as usize } + + fn failed_saf(&self) -> bool { + (self.desc.read(0) & RXDESC_0_SAF) == RXDESC_0_SAF + } } /// An RX DMA Ring Descriptor entry @@ -203,6 +209,11 @@ impl<'a> RxPacket<'a> { pub fn free(self) { drop(self) } + + // Whether or not the packet failed the source address filter. + pub fn failed_source_address_filter(&self) -> bool { + self.entry.desc().failed_saf() + } } /// Rx DMA state From e5fddc592becd4384e0cbbe2beba7283c1c00915 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sun, 18 Dec 2022 22:01:41 +0100 Subject: [PATCH 5/9] Also configure multicast addrs --- src/mac/frame_filtering/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mac/frame_filtering/mod.rs b/src/mac/frame_filtering/mod.rs index f4670ff..a2cca75 100644 --- a/src/mac/frame_filtering/mod.rs +++ b/src/mac/frame_filtering/mod.rs @@ -164,6 +164,7 @@ impl FrameFiltering { let mut dest_addrs = dest_addrs.iter(); let mut source_addrs = source_addrs.iter(); + let mut multicast_addrs = multicast_addrs.iter(); macro_rules! next_addr_reg { ($regh:ident, $regl:ident, $ah:ident, $al:ident) => { @@ -171,6 +172,7 @@ impl FrameFiltering { .next() .map(|v| (v, false)) .or(source_addrs.next().map(|v| (v, true))) + .or(multicast_addrs.next().map(|v| (v, false))) { eth_mac.$regh.write(|w| { w.ae() From 6b39f9cdb4be5862c9959490ad0cb5d5c5ec7f3e Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sun, 18 Dec 2022 22:08:18 +0100 Subject: [PATCH 6/9] Add #[inline(always)] for space savings --- src/mac/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mac/mod.rs b/src/mac/mod.rs index 9668670..795e327 100644 --- a/src/mac/mod.rs +++ b/src/mac/mod.rs @@ -206,6 +206,7 @@ impl EthernetMAC { } /// Configure the frame filtering performed by this MAC. + #[inline(always)] pub fn configure_filtering(&self, filtering_config: &FrameFilteringMode) { filtering_config.configure(&self.eth_mac); } From 3cc823ccefa4c1f4ffc200154fef66fa6ae02137 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Mon, 19 Dec 2022 22:29:05 +0100 Subject: [PATCH 7/9] Sacrifice some usability for a lot of space savings --- Cargo.toml | 1 - examples/arp.rs | 24 ++++- src/mac/frame_filtering/destination.rs | 31 +++--- src/mac/frame_filtering/mod.rs | 126 +++++++++++++++---------- src/mac/frame_filtering/multicast.rs | 6 +- src/mac/frame_filtering/source.rs | 18 ++-- 6 files changed, 124 insertions(+), 82 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5b2f44e..b9d1f6c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,6 @@ cortex-m = "0.7" log = { version = "0.4", optional = true } defmt = { version = "0.3", optional = true } bitflags = "1.3.2" -heapless = "0.7.16" [dependencies.smoltcp] version = "0.8" diff --git a/examples/arp.rs b/examples/arp.rs index 1aa18fd..424d1f8 100644 --- a/examples/arp.rs +++ b/examples/arp.rs @@ -16,7 +16,11 @@ use cortex_m_rt::{entry, exception}; use cortex_m::interrupt::Mutex; use stm32_eth::{ - mac::{phy::BarePhy, Phy}, + mac::{ + frame_filtering::{FrameFiltering, FrameFilteringMode, Mac}, + phy::BarePhy, + Phy, + }, stm32::{interrupt, CorePeripherals, Peripherals, SYST}, }; @@ -57,6 +61,15 @@ fn main() -> ! { .unwrap(); eth_dma.enable_interrupt(); + let some_mac = if eth_dma.tx_is_running() { 1 } else { 0 }; + + let frame_filtering = FrameFiltering::filter_destinations( + Mac::new([some_mac, some_mac, some_mac, some_mac, some_mac, some_mac]), + &[], + ); + + eth_mac.configure_filtering(&FrameFilteringMode::Filter(frame_filtering)); + let mut last_link_up = false; let mut bare_phy = BarePhy::new(eth_mac.with_mii(mdio, mdc), PHY_ADDR, Default::default()); @@ -111,6 +124,15 @@ fn main() -> ! { } Err(TxError::WouldBlock) => defmt::info!("ARP failed"), } + + // while let Ok(message) = eth_dma.recv_next() { + // let mut chunks = message.chunks(6); + + // let dst_mac = Mac::try_from(chunks.next().unwrap()).ok().unwrap(); + // let src_mac = Mac::try_from(chunks.next().unwrap()).ok().unwrap(); + + // defmt::warn!("DA: {}, SA: {}", dst_mac, src_mac); + // } } else { defmt::info!("Down"); } diff --git a/src/mac/frame_filtering/destination.rs b/src/mac/frame_filtering/destination.rs index 397148a..f0c4e32 100644 --- a/src/mac/frame_filtering/destination.rs +++ b/src/mac/frame_filtering/destination.rs @@ -1,13 +1,9 @@ -use heapless::Vec; - -use super::MacAddressFilter; - /// The type of filtering that the MAC should apply to /// frames that are to be transmitted. #[derive(Debug, Clone)] pub struct DestinationAddressFiltering { /// Filtering to be performed based on perfect address matches. - pub perfect_filtering: PerfectDestinationAddressFiltering, + pub perfect_filtering: PerfectDestinationAddressFilteringMode, /// Enable or disable hash table filtering for destination /// addresses. pub hash_table_filtering: bool, @@ -18,7 +14,7 @@ impl DestinationAddressFiltering { /// not filter any frames. pub const fn new() -> Self { Self { - perfect_filtering: PerfectDestinationAddressFiltering::new(), + perfect_filtering: PerfectDestinationAddressFilteringMode::new(), hash_table_filtering: false, } } @@ -34,24 +30,29 @@ impl Default for DestinationAddressFiltering { /// the MAC should apply to frames. #[derive(Debug, Clone)] -pub enum PerfectDestinationAddressFiltering { +pub enum PerfectDestinationAddressFilteringMode { /// Filter frames by their Destination Address, based on - /// the provided addresses. - Normal(Vec), + /// the addresses configured with [`AddressFilterType::Destination`]. + /// + /// [`AddressFilterType::Destination`]: `super::AddressFilterType::Destination` + Normal, /// Filter frames by their Destination Address, based on - /// the inverse of the provided addresses. - Inverse(Vec), + /// the inverse of the addresses configured with + /// [`AddressFilterType::Destination`]. + /// + /// [`AddressFilterType::Destination`]: `super::AddressFilterType::Destination` + Inverse, } -impl PerfectDestinationAddressFiltering { - /// Create a new [`PerfectDestinationAddressFiltering`] that filters +impl PerfectDestinationAddressFilteringMode { + /// Create a new [`PerfectDestinationAddressFilteringMode`] that filters /// out all frames. pub const fn new() -> Self { - Self::Normal(Vec::new()) + Self::Normal } } -impl Default for PerfectDestinationAddressFiltering { +impl Default for PerfectDestinationAddressFilteringMode { fn default() -> Self { Self::new() } diff --git a/src/mac/frame_filtering/mod.rs b/src/mac/frame_filtering/mod.rs index a2cca75..515635c 100644 --- a/src/mac/frame_filtering/mod.rs +++ b/src/mac/frame_filtering/mod.rs @@ -1,7 +1,6 @@ //! Hardware filtering of Ethernet frames use crate::hal::pac::ETHERNET_MAC; -use heapless::Vec; mod destination; pub use destination::*; @@ -53,7 +52,10 @@ impl FrameFilteringMode { pub struct FrameFiltering { /// The MAC address of this station. This address is always /// used for Destination Address filtering. - pub address: Mac, + pub base_address: Mac, + + /// Extra address filters to be used. + pub address_filters: [Option; 3], /// Frame filtering applied to frames based on /// their destination address. @@ -94,16 +96,30 @@ impl FrameFiltering { /// * Does not filter out multicast frames. /// * Does not filter out broadcast frames. /// * Filters out all control frames. - pub fn filter_destinations(station_addr: Mac, extra_addresses: Vec) -> Self { - let extra_addrs = extra_addresses - .into_iter() - .map(|a| MacAddressFilter::new(a, MacAddressFilterMask::empty())) - .collect(); + pub const fn filter_destinations(station_addr: Mac, extra_addresses: &[Mac]) -> Self { + assert!(extra_addresses.len() <= 3); + + let mut address_filters = [None, None, None]; + + let mut i = 0; + loop { + address_filters[i] = Some(MacAddressFilter::new( + AddressFilterType::Destination, + extra_addresses[i], + MacAddressFilterMask::empty(), + )); + + i += 1; + if i == 3 || i == extra_addresses.len() { + break; + } + } FrameFiltering { - address: station_addr, + base_address: station_addr, + address_filters, destination_address_filter: DestinationAddressFiltering { - perfect_filtering: PerfectDestinationAddressFiltering::Normal(extra_addrs), + perfect_filtering: PerfectDestinationAddressFilteringMode::Normal, hash_table_filtering: false, }, source_address_filter: SourceAddressFiltering::Ignore, @@ -117,7 +133,8 @@ impl FrameFiltering { fn configure(&self, eth_mac: ÐERNET_MAC) { let FrameFiltering { - address, + base_address, + address_filters, destination_address_filter, source_address_filter, multicast_address_filter, @@ -127,27 +144,29 @@ impl FrameFiltering { receive_all, } = self; - eth_mac.maca0hr.write(|w| w.maca0h().bits(address.high())); - eth_mac.maca0lr.write(|w| w.maca0l().bits(address.low())); + eth_mac + .maca0hr + .write(|w| w.maca0h().bits(base_address.high())); + eth_mac + .maca0lr + .write(|w| w.maca0l().bits(base_address.low())); - let (daif, dest_addrs) = match &destination_address_filter.perfect_filtering { - PerfectDestinationAddressFiltering::Normal(addrs) => (false, addrs), - PerfectDestinationAddressFiltering::Inverse(addrs) => (true, addrs), + let daif = match &destination_address_filter.perfect_filtering { + PerfectDestinationAddressFilteringMode::Normal => false, + PerfectDestinationAddressFilteringMode::Inverse => true, }; let hu = destination_address_filter.hash_table_filtering; - let empty_vec = Vec::new(); - - let (saf, saif, source_addrs) = match &source_address_filter { - SourceAddressFiltering::Ignore => (false, false, &empty_vec), - SourceAddressFiltering::Normal(addrs) => (true, false, addrs), - SourceAddressFiltering::Inverse(addrs) => (true, true, addrs), + let (saf, saif) = match &source_address_filter { + SourceAddressFiltering::Ignore => (false, false), + SourceAddressFiltering::Normal => (true, false), + SourceAddressFiltering::Inverse => (true, true), }; - let (pam, hm, multicast_addrs) = match &multicast_address_filter { - MulticastAddressFiltering::PassAll => (true, false, &empty_vec), - MulticastAddressFiltering::DestinationAddressHash => (false, true, &empty_vec), - MulticastAddressFiltering::DestinationAddress(addrs) => (false, false, addrs), + let (pam, hm) = match &multicast_address_filter { + MulticastAddressFiltering::PassAll => (true, false), + MulticastAddressFiltering::DestinationAddressHash => (false, true), + MulticastAddressFiltering::DestinationAddress => (false, false), }; let pcf = match &control_filter { @@ -157,32 +176,23 @@ impl FrameFiltering { ControlFrameFiltering::AddressFilter => 0b11, }; - assert!( - source_addrs.len() + dest_addrs.len() + multicast_addrs.len() <= 3, - "A maximum of 3 combined source, destination, and multicast address filters may be configured at any time." - ); - - let mut dest_addrs = dest_addrs.iter(); - let mut source_addrs = source_addrs.iter(); - let mut multicast_addrs = multicast_addrs.iter(); - macro_rules! next_addr_reg { - ($regh:ident, $regl:ident, $ah:ident, $al:ident) => { - if let Some((addr, sa)) = dest_addrs - .next() - .map(|v| (v, false)) - .or(source_addrs.next().map(|v| (v, true))) - .or(multicast_addrs.next().map(|v| (v, false))) - { + ($idx:literal, $regh:ident, $regl:ident, $ah:ident, $al:ident) => { + if let Some(filter) = &address_filters[$idx] { + let sa = match filter.ty { + AddressFilterType::Destination => false, + AddressFilterType::Source => true, + }; + eth_mac.$regh.write(|w| { w.ae() .set_bit() .sa() .bit(sa) .mbc() - .bits(addr.mask.bits()) + .bits(filter.mask.bits()) .$ah() - .bits(addr.address.high()) + .bits(filter.address.high()) }); // This operation is only unsafe for register maca2lr STM32F107 @@ -192,14 +202,16 @@ impl FrameFiltering { #[allow(unused_unsafe)] eth_mac .$regl - .write(|w| unsafe { w.$al().bits(addr.address.low()) }); + .write(|w| unsafe { w.$al().bits(filter.address.low()) }); + } else { + eth_mac.$regh.write(|w| w.ae().clear_bit()); } }; } - next_addr_reg!(maca1hr, maca1lr, maca1h, maca1l); - next_addr_reg!(maca2hr, maca2lr, maca2h, maca2l); - next_addr_reg!(maca3hr, maca3lr, maca3h, maca3l); + next_addr_reg!(0, maca1hr, maca1lr, maca1h, maca1l); + next_addr_reg!(1, maca2hr, maca2lr, maca2h, maca2l); + next_addr_reg!(2, maca3hr, maca3lr, maca3h, maca3l); eth_mac.macffr.write(|w| { w.hpf() @@ -237,7 +249,7 @@ impl FrameFiltering { } /// A big-endian MAC address. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub struct Mac([u8; 6]); impl Mac { @@ -303,10 +315,22 @@ impl defmt::Format for Mac { } } +#[derive(Debug, Clone, Copy)] +/// The type of an address filter. +pub enum AddressFilterType { + /// Filter based on Source Address. + Source, + /// Filter based on Destination address. + Destination, +} + /// A MAC address filter -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub struct MacAddressFilter { + /// The address on which this filter + /// should operate. + pub ty: AddressFilterType, /// The address that this filter should use. pub address: Mac, /// The byte mask that should be used to mask @@ -317,8 +341,8 @@ pub struct MacAddressFilter { impl MacAddressFilter { /// Create a new MAC address filter. - pub fn new(address: Mac, mask: MacAddressFilterMask) -> Self { - Self { address, mask } + pub const fn new(ty: AddressFilterType, address: Mac, mask: MacAddressFilterMask) -> Self { + Self { ty, address, mask } } } diff --git a/src/mac/frame_filtering/multicast.rs b/src/mac/frame_filtering/multicast.rs index 24f75e9..769cf8b 100644 --- a/src/mac/frame_filtering/multicast.rs +++ b/src/mac/frame_filtering/multicast.rs @@ -1,7 +1,3 @@ -use heapless::Vec; - -use super::MacAddressFilter; - /// Multicast address filtering #[derive(Debug, Clone)] pub enum MulticastAddressFiltering { @@ -15,7 +11,7 @@ pub enum MulticastAddressFiltering { /// Only multicast frames whose destination address /// is equal to one of the provided destination addresses /// are passed to the application. - DestinationAddress(Vec), + DestinationAddress, } impl MulticastAddressFiltering { diff --git a/src/mac/frame_filtering/source.rs b/src/mac/frame_filtering/source.rs index 2ca5b98..477e3f9 100644 --- a/src/mac/frame_filtering/source.rs +++ b/src/mac/frame_filtering/source.rs @@ -1,7 +1,3 @@ -use heapless::Vec; - -use super::MacAddressFilter; - /// The type of frame filtering that the MAC should perform /// on received frames. #[derive(Debug, Clone)] @@ -10,18 +6,22 @@ pub enum SourceAddressFiltering { /// Source address filtering never fails. Ignore, /// Filter frames by their Source Address, based on - /// the provided addresses. - Normal(Vec), + /// the addresses configured with [`AddressFilterType::Source`]. + /// + /// [`AddressFilterType::Source`]: `super::AddressFilterType::Destination` + Normal, /// Filter frames by their Source Address, based on - /// the inverse of the provided addresses. - Inverse(Vec), + /// the addresses configured with [`AddressFilterType::Source`]. + /// + /// [`AddressFilterType::Source`]: `super::AddressFilterType::Destination` + Inverse, } impl SourceAddressFiltering { /// Create a new [`SourceAddressFiltering`] that /// does not filter any frames. pub const fn new() -> Self { - Self::Inverse(Vec::new()) + Self::Inverse } } From fdb5d450925e2d57ae57320a7555495d98a2a583 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Mon, 19 Dec 2022 22:33:50 +0100 Subject: [PATCH 8/9] From smoltcp mac address impls --- src/mac/frame_filtering/mod.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/mac/frame_filtering/mod.rs b/src/mac/frame_filtering/mod.rs index 515635c..78e43e1 100644 --- a/src/mac/frame_filtering/mod.rs +++ b/src/mac/frame_filtering/mod.rs @@ -315,6 +315,20 @@ impl defmt::Format for Mac { } } +#[cfg(feature = "smoltcp-phy")] +impl From for Mac { + fn from(value: smoltcp::wire::EthernetAddress) -> Self { + Self::new(value.0) + } +} + +#[cfg(feature = "smoltcp-phy")] +impl From for smoltcp::wire::EthernetAddress { + fn from(value: Mac) -> Self { + smoltcp::wire::EthernetAddress::from_bytes(&value.0) + } +} + #[derive(Debug, Clone, Copy)] /// The type of an address filter. pub enum AddressFilterType { From 8f6e9bc6b01e05c67d3259e76fea0096277973f0 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Tue, 3 Jan 2023 21:34:57 +0100 Subject: [PATCH 9/9] Shorten D(estination)A(ddress) and S(ource)A(ddress), Filtering -> Filter --- examples/arp.rs | 6 +- .../control.rs | 8 +-- .../destination.rs | 26 ++++---- .../hash_table.rs | 0 .../{frame_filtering => frame_filter}/mod.rs | 64 +++++++++---------- .../multicast.rs | 6 +- .../source.rs | 12 ++-- src/mac/mod.rs | 10 +-- 8 files changed, 66 insertions(+), 66 deletions(-) rename src/mac/{frame_filtering => frame_filter}/control.rs (80%) rename src/mac/{frame_filtering => frame_filter}/destination.rs (62%) rename src/mac/{frame_filtering => frame_filter}/hash_table.rs (100%) rename src/mac/{frame_filtering => frame_filter}/mod.rs (84%) rename src/mac/{frame_filtering => frame_filter}/multicast.rs (85%) rename src/mac/{frame_filtering => frame_filter}/source.rs (73%) diff --git a/examples/arp.rs b/examples/arp.rs index 424d1f8..2c5c363 100644 --- a/examples/arp.rs +++ b/examples/arp.rs @@ -17,7 +17,7 @@ use cortex_m_rt::{entry, exception}; use cortex_m::interrupt::Mutex; use stm32_eth::{ mac::{ - frame_filtering::{FrameFiltering, FrameFilteringMode, Mac}, + frame_filter::{Filter, FilterConfig, Mac}, phy::BarePhy, Phy, }, @@ -63,12 +63,12 @@ fn main() -> ! { let some_mac = if eth_dma.tx_is_running() { 1 } else { 0 }; - let frame_filtering = FrameFiltering::filter_destinations( + let filter_config = FilterConfig::filter_destinations( Mac::new([some_mac, some_mac, some_mac, some_mac, some_mac, some_mac]), &[], ); - eth_mac.configure_filtering(&FrameFilteringMode::Filter(frame_filtering)); + eth_mac.configure_frame_filter(&Filter::Filter(filter_config)); let mut last_link_up = false; diff --git a/src/mac/frame_filtering/control.rs b/src/mac/frame_filter/control.rs similarity index 80% rename from src/mac/frame_filtering/control.rs rename to src/mac/frame_filter/control.rs index f8ffa6d..432a7ef 100644 --- a/src/mac/frame_filtering/control.rs +++ b/src/mac/frame_filter/control.rs @@ -2,7 +2,7 @@ /// on received control frames, #[derive(Debug, Clone)] -pub enum ControlFrameFiltering { +pub enum ControlFrameFilter { /// Prevent all control frames from reaching /// the application. BlockAll, @@ -16,15 +16,15 @@ pub enum ControlFrameFiltering { AddressFilter, } -impl ControlFrameFiltering { - /// Create a new [`ControlFrameFiltering`] that filters out +impl ControlFrameFilter { + /// Create a new [`ControlFrameFilter`] that filters out /// all control frames. pub const fn new() -> Self { Self::BlockAll } } -impl Default for ControlFrameFiltering { +impl Default for ControlFrameFilter { fn default() -> Self { Self::new() } diff --git a/src/mac/frame_filtering/destination.rs b/src/mac/frame_filter/destination.rs similarity index 62% rename from src/mac/frame_filtering/destination.rs rename to src/mac/frame_filter/destination.rs index f0c4e32..456d1b6 100644 --- a/src/mac/frame_filtering/destination.rs +++ b/src/mac/frame_filter/destination.rs @@ -1,36 +1,36 @@ -/// The type of filtering that the MAC should apply to -/// frames that are to be transmitted. +/// The type of destination address filtering that +/// the MAC should apply to incoming frames. #[derive(Debug, Clone)] -pub struct DestinationAddressFiltering { +pub struct DaFilter { /// Filtering to be performed based on perfect address matches. - pub perfect_filtering: PerfectDestinationAddressFilteringMode, + pub perfect_filtering: PerfectDaFilterMode, /// Enable or disable hash table filtering for destination /// addresses. pub hash_table_filtering: bool, } -impl DestinationAddressFiltering { - /// Create a new [`DestinationAddressFiltering`] that does +impl DaFilter { + /// Create a new [`DaFilter`] that does /// not filter any frames. pub const fn new() -> Self { Self { - perfect_filtering: PerfectDestinationAddressFilteringMode::new(), + perfect_filtering: PerfectDaFilterMode::new(), hash_table_filtering: false, } } } -impl Default for DestinationAddressFiltering { +impl Default for DaFilter { fn default() -> Self { Self::new() } } /// The type of destination address filtering that -/// the MAC should apply to frames. +/// the MAC should apply to incoming frames. #[derive(Debug, Clone)] -pub enum PerfectDestinationAddressFilteringMode { +pub enum PerfectDaFilterMode { /// Filter frames by their Destination Address, based on /// the addresses configured with [`AddressFilterType::Destination`]. /// @@ -44,15 +44,15 @@ pub enum PerfectDestinationAddressFilteringMode { Inverse, } -impl PerfectDestinationAddressFilteringMode { - /// Create a new [`PerfectDestinationAddressFilteringMode`] that filters +impl PerfectDaFilterMode { + /// Create a new [`PerfectDaFilterMode`] that filters /// out all frames. pub const fn new() -> Self { Self::Normal } } -impl Default for PerfectDestinationAddressFilteringMode { +impl Default for PerfectDaFilterMode { fn default() -> Self { Self::new() } diff --git a/src/mac/frame_filtering/hash_table.rs b/src/mac/frame_filter/hash_table.rs similarity index 100% rename from src/mac/frame_filtering/hash_table.rs rename to src/mac/frame_filter/hash_table.rs diff --git a/src/mac/frame_filtering/mod.rs b/src/mac/frame_filter/mod.rs similarity index 84% rename from src/mac/frame_filtering/mod.rs rename to src/mac/frame_filter/mod.rs index 78e43e1..41af9bd 100644 --- a/src/mac/frame_filtering/mod.rs +++ b/src/mac/frame_filter/mod.rs @@ -20,25 +20,25 @@ pub use control::*; /// The frame filtering that the MAC should apply to /// received Ethernet frames. #[derive(Debug, Clone)] -pub enum FrameFilteringMode { +pub enum Filter { /// No frame filtering on any frames. Promiscuous, /// Perform frame filtering based on the provided /// configuration. - Filter(FrameFiltering), + Filter(FilterConfig), } -impl Default for FrameFilteringMode { +impl Default for Filter { fn default() -> Self { Self::Promiscuous } } -impl FrameFilteringMode { +impl Filter { pub(crate) fn configure(&self, eth_mac: ÐERNET_MAC) { match self { - FrameFilteringMode::Promiscuous => eth_mac.macffr.write(|w| w.pm().set_bit()), - FrameFilteringMode::Filter(config) => config.configure(eth_mac), + Filter::Promiscuous => eth_mac.macffr.write(|w| w.pm().set_bit()), + Filter::Filter(config) => config.configure(eth_mac), } } } @@ -49,7 +49,7 @@ impl FrameFilteringMode { /// The total amount of [`MacAddressFilter`]s in this configuration object may /// be at most 3. #[derive(Debug, Clone)] -pub struct FrameFiltering { +pub struct FilterConfig { /// The MAC address of this station. This address is always /// used for Destination Address filtering. pub base_address: Mac, @@ -59,18 +59,18 @@ pub struct FrameFiltering { /// Frame filtering applied to frames based on /// their destination address. - pub destination_address_filter: DestinationAddressFiltering, + pub destination_address_filter: DaFilter, /// Frame filtering applied to frames based on /// their source address. - pub source_address_filter: SourceAddressFiltering, + pub source_address_filter: SaFilter, /// Frame filtering applied to frames based on /// whether they have a multicast address or not. - pub multicast_address_filter: MulticastAddressFiltering, + pub multicast_address_filter: MulticastAddressFilter, /// Control frame filtering mode, - pub control_filter: ControlFrameFiltering, + pub control_filter: ControlFrameFilter, /// Hash table configuration. pub hash_table_value: HashTableValue, @@ -89,8 +89,8 @@ pub struct FrameFiltering { pub receive_all: bool, } -impl FrameFiltering { - /// Create a new basic [`FrameFiltering`] that: +impl FilterConfig { + /// Create a new basic [`FilterConfig`] that: /// * Does not filter out frames destined for `station_addr` or an address /// contained in `extra_address`. /// * Does not filter out multicast frames. @@ -115,16 +115,16 @@ impl FrameFiltering { } } - FrameFiltering { + FilterConfig { base_address: station_addr, address_filters, - destination_address_filter: DestinationAddressFiltering { - perfect_filtering: PerfectDestinationAddressFilteringMode::Normal, + destination_address_filter: DaFilter { + perfect_filtering: PerfectDaFilterMode::Normal, hash_table_filtering: false, }, - source_address_filter: SourceAddressFiltering::Ignore, - multicast_address_filter: MulticastAddressFiltering::PassAll, - control_filter: ControlFrameFiltering::BlockAll, + source_address_filter: SaFilter::Ignore, + multicast_address_filter: MulticastAddressFilter::PassAll, + control_filter: ControlFrameFilter::BlockAll, hash_table_value: HashTableValue::new(), filter_broadcast: false, receive_all: false, @@ -132,7 +132,7 @@ impl FrameFiltering { } fn configure(&self, eth_mac: ÐERNET_MAC) { - let FrameFiltering { + let FilterConfig { base_address, address_filters, destination_address_filter, @@ -152,28 +152,28 @@ impl FrameFiltering { .write(|w| w.maca0l().bits(base_address.low())); let daif = match &destination_address_filter.perfect_filtering { - PerfectDestinationAddressFilteringMode::Normal => false, - PerfectDestinationAddressFilteringMode::Inverse => true, + PerfectDaFilterMode::Normal => false, + PerfectDaFilterMode::Inverse => true, }; let hu = destination_address_filter.hash_table_filtering; let (saf, saif) = match &source_address_filter { - SourceAddressFiltering::Ignore => (false, false), - SourceAddressFiltering::Normal => (true, false), - SourceAddressFiltering::Inverse => (true, true), + SaFilter::Ignore => (false, false), + SaFilter::Normal => (true, false), + SaFilter::Inverse => (true, true), }; let (pam, hm) = match &multicast_address_filter { - MulticastAddressFiltering::PassAll => (true, false), - MulticastAddressFiltering::DestinationAddressHash => (false, true), - MulticastAddressFiltering::DestinationAddress => (false, false), + MulticastAddressFilter::PassAll => (true, false), + MulticastAddressFilter::DestinationAddressHash => (false, true), + MulticastAddressFilter::DestinationAddress => (false, false), }; let pcf = match &control_filter { - ControlFrameFiltering::BlockAll => 0b00, - ControlFrameFiltering::NoPause => 0b01, - ControlFrameFiltering::AllowAll => 0b10, - ControlFrameFiltering::AddressFilter => 0b11, + ControlFrameFilter::BlockAll => 0b00, + ControlFrameFilter::NoPause => 0b01, + ControlFrameFilter::AllowAll => 0b10, + ControlFrameFilter::AddressFilter => 0b11, }; macro_rules! next_addr_reg { diff --git a/src/mac/frame_filtering/multicast.rs b/src/mac/frame_filter/multicast.rs similarity index 85% rename from src/mac/frame_filtering/multicast.rs rename to src/mac/frame_filter/multicast.rs index 769cf8b..4581d80 100644 --- a/src/mac/frame_filtering/multicast.rs +++ b/src/mac/frame_filter/multicast.rs @@ -1,6 +1,6 @@ /// Multicast address filtering #[derive(Debug, Clone)] -pub enum MulticastAddressFiltering { +pub enum MulticastAddressFilter { /// All received multicast frames are passed to the /// application. PassAll, @@ -14,7 +14,7 @@ pub enum MulticastAddressFiltering { DestinationAddress, } -impl MulticastAddressFiltering { +impl MulticastAddressFilter { /// Create a new MulticastAddressFiltering that does not /// filter any multicast frames. pub const fn new() -> Self { @@ -22,7 +22,7 @@ impl MulticastAddressFiltering { } } -impl Default for MulticastAddressFiltering { +impl Default for MulticastAddressFilter { fn default() -> Self { Self::new() } diff --git a/src/mac/frame_filtering/source.rs b/src/mac/frame_filter/source.rs similarity index 73% rename from src/mac/frame_filtering/source.rs rename to src/mac/frame_filter/source.rs index 477e3f9..983fbec 100644 --- a/src/mac/frame_filtering/source.rs +++ b/src/mac/frame_filter/source.rs @@ -1,8 +1,8 @@ -/// The type of frame filtering that the MAC should perform -/// on received frames. +/// The type of source address frame filtering that +/// the MAC should perform to received frames. #[derive(Debug, Clone)] -pub enum SourceAddressFiltering { +pub enum SaFilter { /// Source address filtering never fails. Ignore, /// Filter frames by their Source Address, based on @@ -17,15 +17,15 @@ pub enum SourceAddressFiltering { Inverse, } -impl SourceAddressFiltering { - /// Create a new [`SourceAddressFiltering`] that +impl SaFilter { + /// Create a new [`SaFilter`] that /// does not filter any frames. pub const fn new() -> Self { Self::Inverse } } -impl Default for SourceAddressFiltering { +impl Default for SaFilter { fn default() -> Self { Self::new() } diff --git a/src/mac/mod.rs b/src/mac/mod.rs index 795e327..7440dbd 100644 --- a/src/mac/mod.rs +++ b/src/mac/mod.rs @@ -11,7 +11,7 @@ use crate::{ mod miim; pub use miim::*; -pub mod frame_filtering; +pub mod frame_filter; /// Speeds at which this MAC can be configured #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -39,7 +39,7 @@ mod consts { /* For HCLK over 150 MHz */ pub const ETH_MACMIIAR_CR_HCLK_DIV_102: u8 = 4; } -use self::{consts::*, frame_filtering::FrameFilteringMode}; +use self::{consts::*, frame_filter::Filter}; /// HCLK must be at least 25MHz to use the ethernet peripheral. /// This (empty) struct is returned to indicate that it is not set @@ -139,7 +139,7 @@ impl EthernetMAC { .mmctimr .modify(|r, w| unsafe { w.bits(r.bits() | (1 << 21)) }); - FrameFilteringMode::Promiscuous.configure(ð_mac); + Filter::Promiscuous.configure(ð_mac); let mut me = Self { eth_mac }; @@ -207,8 +207,8 @@ impl EthernetMAC { /// Configure the frame filtering performed by this MAC. #[inline(always)] - pub fn configure_filtering(&self, filtering_config: &FrameFilteringMode) { - filtering_config.configure(&self.eth_mac); + pub fn configure_frame_filter(&self, filter_config: &Filter) { + filter_config.configure(&self.eth_mac); } }