1
1
//! Hardware filtering of Ethernet frames
2
2
3
3
use crate :: hal:: pac:: ETHERNET_MAC ;
4
- use heapless:: Vec ;
5
4
6
5
mod destination;
7
6
pub use destination:: * ;
@@ -53,7 +52,10 @@ impl FrameFilteringMode {
53
52
pub struct FrameFiltering {
54
53
/// The MAC address of this station. This address is always
55
54
/// 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 ] ,
57
59
58
60
/// Frame filtering applied to frames based on
59
61
/// their destination address.
@@ -94,16 +96,30 @@ impl FrameFiltering {
94
96
/// * Does not filter out multicast frames.
95
97
/// * Does not filter out broadcast frames.
96
98
/// * 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
+ }
102
117
103
118
FrameFiltering {
104
- address : station_addr,
119
+ base_address : station_addr,
120
+ address_filters,
105
121
destination_address_filter : DestinationAddressFiltering {
106
- perfect_filtering : PerfectDestinationAddressFiltering :: Normal ( extra_addrs ) ,
122
+ perfect_filtering : PerfectDestinationAddressFilteringMode :: Normal ,
107
123
hash_table_filtering : false ,
108
124
} ,
109
125
source_address_filter : SourceAddressFiltering :: Ignore ,
@@ -117,7 +133,8 @@ impl FrameFiltering {
117
133
118
134
fn configure ( & self , eth_mac : & ETHERNET_MAC ) {
119
135
let FrameFiltering {
120
- address,
136
+ base_address,
137
+ address_filters,
121
138
destination_address_filter,
122
139
source_address_filter,
123
140
multicast_address_filter,
@@ -127,27 +144,29 @@ impl FrameFiltering {
127
144
receive_all,
128
145
} = self ;
129
146
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 ( ) ) ) ;
132
153
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 ,
136
157
} ;
137
158
let hu = destination_address_filter. hash_table_filtering ;
138
159
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 ) ,
145
164
} ;
146
165
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 ) ,
151
170
} ;
152
171
153
172
let pcf = match & control_filter {
@@ -157,32 +176,23 @@ impl FrameFiltering {
157
176
ControlFrameFiltering :: AddressFilter => 0b11 ,
158
177
} ;
159
178
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
-
169
179
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
+
177
187
eth_mac. $regh. write( |w| {
178
188
w. ae( )
179
189
. set_bit( )
180
190
. sa( )
181
191
. bit( sa)
182
192
. mbc( )
183
- . bits( addr . mask. bits( ) )
193
+ . bits( filter . mask. bits( ) )
184
194
. $ah( )
185
- . bits( addr . address. high( ) )
195
+ . bits( filter . address. high( ) )
186
196
} ) ;
187
197
188
198
// This operation is only unsafe for register maca2lr STM32F107
@@ -192,14 +202,16 @@ impl FrameFiltering {
192
202
#[ allow( unused_unsafe) ]
193
203
eth_mac
194
204
. $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( ) ) ;
196
208
}
197
209
} ;
198
210
}
199
211
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) ;
203
215
204
216
eth_mac. macffr . write ( |w| {
205
217
w. hpf ( )
@@ -237,7 +249,7 @@ impl FrameFiltering {
237
249
}
238
250
239
251
/// A big-endian MAC address.
240
- #[ derive( Debug , Clone ) ]
252
+ #[ derive( Debug , Clone , Copy ) ]
241
253
pub struct Mac ( [ u8 ; 6 ] ) ;
242
254
243
255
impl Mac {
@@ -303,10 +315,22 @@ impl defmt::Format for Mac {
303
315
}
304
316
}
305
317
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
+
306
327
/// A MAC address filter
307
- #[ derive( Debug , Clone ) ]
328
+ #[ derive( Debug , Clone , Copy ) ]
308
329
309
330
pub struct MacAddressFilter {
331
+ /// The address on which this filter
332
+ /// should operate.
333
+ pub ty : AddressFilterType ,
310
334
/// The address that this filter should use.
311
335
pub address : Mac ,
312
336
/// The byte mask that should be used to mask
@@ -317,8 +341,8 @@ pub struct MacAddressFilter {
317
341
318
342
impl MacAddressFilter {
319
343
/// 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 }
322
346
}
323
347
}
324
348
0 commit comments