11//! Hardware filtering of Ethernet frames
22
33use crate :: hal:: pac:: ETHERNET_MAC ;
4- use heapless:: Vec ;
54
65mod destination;
76pub use destination:: * ;
@@ -53,7 +52,10 @@ impl FrameFilteringMode {
5352pub struct FrameFiltering {
5453 /// The MAC address of this station. This address is always
5554 /// used for Destination Address filtering.
56- pub address : Mac ,
55+ pub base_address : Mac ,
56+
57+ /// Extra address filters to be used.
58+ pub address_filters : [ Option < MacAddressFilter > ; 3 ] ,
5759
5860 /// Frame filtering applied to frames based on
5961 /// their destination address.
@@ -94,16 +96,30 @@ impl FrameFiltering {
9496 /// * Does not filter out multicast frames.
9597 /// * Does not filter out broadcast frames.
9698 /// * Filters out all control frames.
97- pub fn filter_destinations ( station_addr : Mac , extra_addresses : Vec < Mac , 3 > ) -> Self {
98- let extra_addrs = extra_addresses
99- . into_iter ( )
100- . map ( |a| MacAddressFilter :: new ( a, MacAddressFilterMask :: empty ( ) ) )
101- . collect ( ) ;
99+ pub const fn filter_destinations ( station_addr : Mac , extra_addresses : & [ Mac ] ) -> Self {
100+ assert ! ( extra_addresses. len( ) <= 3 ) ;
101+
102+ let mut address_filters = [ None , None , None ] ;
103+
104+ let mut i = 0 ;
105+ loop {
106+ address_filters[ i] = Some ( MacAddressFilter :: new (
107+ AddressFilterType :: Destination ,
108+ extra_addresses[ i] ,
109+ MacAddressFilterMask :: empty ( ) ,
110+ ) ) ;
111+
112+ i += 1 ;
113+ if i == 3 || i == extra_addresses. len ( ) {
114+ break ;
115+ }
116+ }
102117
103118 FrameFiltering {
104- address : station_addr,
119+ base_address : station_addr,
120+ address_filters,
105121 destination_address_filter : DestinationAddressFiltering {
106- perfect_filtering : PerfectDestinationAddressFiltering :: Normal ( extra_addrs ) ,
122+ perfect_filtering : PerfectDestinationAddressFilteringMode :: Normal ,
107123 hash_table_filtering : false ,
108124 } ,
109125 source_address_filter : SourceAddressFiltering :: Ignore ,
@@ -117,7 +133,8 @@ impl FrameFiltering {
117133
118134 fn configure ( & self , eth_mac : & ETHERNET_MAC ) {
119135 let FrameFiltering {
120- address,
136+ base_address,
137+ address_filters,
121138 destination_address_filter,
122139 source_address_filter,
123140 multicast_address_filter,
@@ -127,27 +144,29 @@ impl FrameFiltering {
127144 receive_all,
128145 } = self ;
129146
130- eth_mac. maca0hr . write ( |w| w. maca0h ( ) . bits ( address. high ( ) ) ) ;
131- eth_mac. maca0lr . write ( |w| w. maca0l ( ) . bits ( address. low ( ) ) ) ;
147+ eth_mac
148+ . maca0hr
149+ . write ( |w| w. maca0h ( ) . bits ( base_address. high ( ) ) ) ;
150+ eth_mac
151+ . maca0lr
152+ . write ( |w| w. maca0l ( ) . bits ( base_address. low ( ) ) ) ;
132153
133- let ( daif, dest_addrs ) = match & destination_address_filter. perfect_filtering {
134- PerfectDestinationAddressFiltering :: Normal ( addrs ) => ( false , addrs ) ,
135- PerfectDestinationAddressFiltering :: Inverse ( addrs ) => ( true , addrs ) ,
154+ let daif = match & destination_address_filter. perfect_filtering {
155+ PerfectDestinationAddressFilteringMode :: Normal => false ,
156+ PerfectDestinationAddressFilteringMode :: Inverse => true ,
136157 } ;
137158 let hu = destination_address_filter. hash_table_filtering ;
138159
139- let empty_vec = Vec :: new ( ) ;
140-
141- let ( saf, saif, source_addrs) = match & source_address_filter {
142- SourceAddressFiltering :: Ignore => ( false , false , & empty_vec) ,
143- SourceAddressFiltering :: Normal ( addrs) => ( true , false , addrs) ,
144- SourceAddressFiltering :: Inverse ( addrs) => ( true , true , addrs) ,
160+ let ( saf, saif) = match & source_address_filter {
161+ SourceAddressFiltering :: Ignore => ( false , false ) ,
162+ SourceAddressFiltering :: Normal => ( true , false ) ,
163+ SourceAddressFiltering :: Inverse => ( true , true ) ,
145164 } ;
146165
147- let ( pam, hm, multicast_addrs ) = match & multicast_address_filter {
148- MulticastAddressFiltering :: PassAll => ( true , false , & empty_vec ) ,
149- MulticastAddressFiltering :: DestinationAddressHash => ( false , true , & empty_vec ) ,
150- MulticastAddressFiltering :: DestinationAddress ( addrs ) => ( false , false , addrs ) ,
166+ let ( pam, hm) = match & multicast_address_filter {
167+ MulticastAddressFiltering :: PassAll => ( true , false ) ,
168+ MulticastAddressFiltering :: DestinationAddressHash => ( false , true ) ,
169+ MulticastAddressFiltering :: DestinationAddress => ( false , false ) ,
151170 } ;
152171
153172 let pcf = match & control_filter {
@@ -157,32 +176,23 @@ impl FrameFiltering {
157176 ControlFrameFiltering :: AddressFilter => 0b11 ,
158177 } ;
159178
160- assert ! (
161- source_addrs. len( ) + dest_addrs. len( ) + multicast_addrs. len( ) <= 3 ,
162- "A maximum of 3 combined source, destination, and multicast address filters may be configured at any time."
163- ) ;
164-
165- let mut dest_addrs = dest_addrs. iter ( ) ;
166- let mut source_addrs = source_addrs. iter ( ) ;
167- let mut multicast_addrs = multicast_addrs. iter ( ) ;
168-
169179 macro_rules! next_addr_reg {
170- ( $regh: ident, $regl: ident, $ah: ident, $al: ident) => {
171- if let Some ( ( addr , sa ) ) = dest_addrs
172- . next ( )
173- . map ( |v| ( v , false ) )
174- . or ( source_addrs . next ( ) . map ( |v| ( v , true ) ) )
175- . or ( multicast_addrs . next ( ) . map ( |v| ( v , false ) ) )
176- {
180+ ( $idx : literal , $ regh: ident, $regl: ident, $ah: ident, $al: ident) => {
181+ if let Some ( filter ) = & address_filters [ $idx ] {
182+ let sa = match filter . ty {
183+ AddressFilterType :: Destination => false ,
184+ AddressFilterType :: Source => true ,
185+ } ;
186+
177187 eth_mac. $regh. write( |w| {
178188 w. ae( )
179189 . set_bit( )
180190 . sa( )
181191 . bit( sa)
182192 . mbc( )
183- . bits( addr . mask. bits( ) )
193+ . bits( filter . mask. bits( ) )
184194 . $ah( )
185- . bits( addr . address. high( ) )
195+ . bits( filter . address. high( ) )
186196 } ) ;
187197
188198 // This operation is only unsafe for register maca2lr STM32F107
@@ -192,14 +202,16 @@ impl FrameFiltering {
192202 #[ allow( unused_unsafe) ]
193203 eth_mac
194204 . $regl
195- . write( |w| unsafe { w. $al( ) . bits( addr. address. low( ) ) } ) ;
205+ . write( |w| unsafe { w. $al( ) . bits( filter. address. low( ) ) } ) ;
206+ } else {
207+ eth_mac. $regh. write( |w| w. ae( ) . clear_bit( ) ) ;
196208 }
197209 } ;
198210 }
199211
200- next_addr_reg ! ( maca1hr, maca1lr, maca1h, maca1l) ;
201- next_addr_reg ! ( maca2hr, maca2lr, maca2h, maca2l) ;
202- next_addr_reg ! ( maca3hr, maca3lr, maca3h, maca3l) ;
212+ next_addr_reg ! ( 0 , maca1hr, maca1lr, maca1h, maca1l) ;
213+ next_addr_reg ! ( 1 , maca2hr, maca2lr, maca2h, maca2l) ;
214+ next_addr_reg ! ( 2 , maca3hr, maca3lr, maca3h, maca3l) ;
203215
204216 eth_mac. macffr . write ( |w| {
205217 w. hpf ( )
@@ -237,7 +249,7 @@ impl FrameFiltering {
237249}
238250
239251/// A big-endian MAC address.
240- #[ derive( Debug , Clone ) ]
252+ #[ derive( Debug , Clone , Copy ) ]
241253pub struct Mac ( [ u8 ; 6 ] ) ;
242254
243255impl Mac {
@@ -303,10 +315,22 @@ impl defmt::Format for Mac {
303315 }
304316}
305317
318+ #[ derive( Debug , Clone , Copy ) ]
319+ /// The type of an address filter.
320+ pub enum AddressFilterType {
321+ /// Filter based on Source Address.
322+ Source ,
323+ /// Filter based on Destination address.
324+ Destination ,
325+ }
326+
306327/// A MAC address filter
307- #[ derive( Debug , Clone ) ]
328+ #[ derive( Debug , Clone , Copy ) ]
308329
309330pub struct MacAddressFilter {
331+ /// The address on which this filter
332+ /// should operate.
333+ pub ty : AddressFilterType ,
310334 /// The address that this filter should use.
311335 pub address : Mac ,
312336 /// The byte mask that should be used to mask
@@ -317,8 +341,8 @@ pub struct MacAddressFilter {
317341
318342impl MacAddressFilter {
319343 /// Create a new MAC address filter.
320- pub fn new ( address : Mac , mask : MacAddressFilterMask ) -> Self {
321- Self { address, mask }
344+ pub const fn new ( ty : AddressFilterType , address : Mac , mask : MacAddressFilterMask ) -> Self {
345+ Self { ty , address, mask }
322346 }
323347}
324348
0 commit comments