@@ -17,7 +17,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
17
17
#include <zephyr/device.h>
18
18
#include <zephyr/sys/__assert.h>
19
19
#include <zephyr/sys/util.h>
20
- #include <zephyr/crc.h>
20
+ #include <zephyr/sys/ crc.h>
21
21
#include <errno.h>
22
22
#include <stdbool.h>
23
23
#include <zephyr/net/net_pkt.h>
@@ -97,8 +97,22 @@ static ETH_DMADescTypeDef dma_tx_desc_tab[ETH_TXBUFNB] __eth_stm32_desc;
97
97
static uint8_t dma_rx_buffer [ETH_RXBUFNB ][ETH_STM32_RX_BUF_SIZE ] __eth_stm32_buf ;
98
98
static uint8_t dma_tx_buffer [ETH_TXBUFNB ][ETH_STM32_TX_BUF_SIZE ] __eth_stm32_buf ;
99
99
100
+ #if defined(CONFIG_ETH_STM32_MULTICAST_FILTER )
101
+
100
102
static struct net_if_mcast_monitor mcast_monitor ;
101
103
104
+ static K_MUTEX_DEFINE (multicast_addr_lock );
105
+
106
+ #if defined(CONFIG_NET_NATIVE_IPV6 )
107
+ static struct in6_addr multicast_ipv6_joined_addrs [NET_IF_MAX_IPV6_MADDR ] = {0 };
108
+ #endif /* CONFIG_NET_NATIVE_IPV6 */
109
+
110
+ #if defined(CONFIG_NET_NATIVE_IPV4 )
111
+ static struct in_addr multicast_ipv4_joined_addrs [NET_IF_MAX_IPV4_MADDR ] = {0 };
112
+ #endif /* CONFIG_NET_NATIVE_IPV4 */
113
+
114
+ #endif /* CONFIG_ETH_STM32_MULTICAST_FILTER */
115
+
102
116
#if defined(CONFIG_ETH_STM32_HAL_API_V2 )
103
117
104
118
BUILD_ASSERT (ETH_STM32_RX_BUF_SIZE % 4 == 0 , "Rx buffer size must be a multiple of 4" );
@@ -217,16 +231,21 @@ static HAL_StatusTypeDef read_eth_phy_register(ETH_HandleTypeDef *heth,
217
231
#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_ETH_STM32_HAL_API_V2 */
218
232
}
219
233
220
- static inline void disable_mcast_filter (ETH_HandleTypeDef * heth )
234
+ static inline void setup_mac_filter (ETH_HandleTypeDef * heth )
221
235
{
222
236
__ASSERT_NO_MSG (heth != NULL );
223
237
224
238
#if defined(CONFIG_SOC_SERIES_STM32H7X )
225
239
ETH_MACFilterConfigTypeDef MACFilterConf ;
226
240
227
241
HAL_ETH_GetMACFilterConfig (heth , & MACFilterConf );
242
+ #if defined(CONFIG_ETH_STM32_MULTICAST_FILTER )
228
243
MACFilterConf .HashMulticast = ENABLE ;
229
244
MACFilterConf .PassAllMulticast = DISABLE ;
245
+ #else
246
+ MACFilterConf .HashMulticast = DISABLE ;
247
+ MACFilterConf .PassAllMulticast = ENABLE ;
248
+ #endif /* CONFIG_ETH_STM32_MULTICAST_FILTER */
230
249
MACFilterConf .HachOrPerfectFilter = DISABLE ;
231
250
232
251
HAL_ETH_SetMACFilterConfig (heth , & MACFilterConf );
@@ -237,10 +256,15 @@ static inline void disable_mcast_filter(ETH_HandleTypeDef *heth)
237
256
238
257
/* disable multicast perfect filtering */
239
258
tmp &= ~(ETH_MULTICASTFRAMESFILTER_PERFECTHASHTABLE |
259
+ #if !defined (CONFIG_ETH_STM32_MULTICAST_FILTER )
260
+ ETH_MULTICASTFRAMESFILTER_HASHTABLE |
261
+ #endif /* CONFIG_ETH_STM32_MULTICAST_FILTER */
240
262
ETH_MULTICASTFRAMESFILTER_PERFECT );
241
263
264
+ #if defined(CONFIG_ETH_STM32_MULTICAST_FILTER )
242
265
/* enable multicast hash receive filter */
243
266
tmp |= ETH_MULTICASTFRAMESFILTER_HASHTABLE ;
267
+ #endif /* CONFIG_ETH_STM32_MULTICAST_FILTER */
244
268
245
269
heth -> Instance -> MACFFR = tmp ;
246
270
@@ -1189,6 +1213,64 @@ static int eth_initialize(const struct device *dev)
1189
1213
return 0 ;
1190
1214
}
1191
1215
1216
+ #if defined(CONFIG_ETH_STM32_MULTICAST_FILTER )
1217
+
1218
+ #if defined(CONFIG_NET_NATIVE_IPV6 )
1219
+ static void add_ipv6_multicast_addr (const struct in6_addr * addr )
1220
+ {
1221
+ uint32_t i ;
1222
+
1223
+ for (i = 0 ; i < NET_IF_MAX_IPV6_MADDR ; i ++ ) {
1224
+ if (net_ipv6_is_addr_unspecified (& multicast_ipv6_joined_addrs [i ])) {
1225
+ net_ipv6_addr_copy_raw ((uint8_t * )& multicast_ipv6_joined_addrs [i ],
1226
+ (uint8_t * )addr );
1227
+ break ;
1228
+ }
1229
+ }
1230
+ }
1231
+
1232
+ static void remove_ipv6_multicast_addr (const struct in6_addr * addr )
1233
+ {
1234
+ uint32_t i ;
1235
+
1236
+ for (i = 0 ; i < NET_IF_MAX_IPV6_MADDR ; i ++ ) {
1237
+ if (net_ipv6_addr_cmp_raw (& multicast_ipv6_joined_addrs [i ], addr )) {
1238
+ net_ipv6_addr_copy_raw ((uint8_t * )& multicast_ipv6_joined_addrs [i ],
1239
+ (uint8_t * )net_ipv6_unspecified_address );
1240
+ break ;
1241
+ }
1242
+ }
1243
+ }
1244
+ #endif /* CONFIG_NET_NATIVE_IPV6 */
1245
+
1246
+ #if defined(CONFIG_NET_NATIVE_IPV4 )
1247
+ static void add_ipv4_multicast_addr (const struct in_addr * addr )
1248
+ {
1249
+ uint32_t i ;
1250
+
1251
+ for (i = 0 ; i < NET_IF_MAX_IPV4_MADDR ; i ++ ) {
1252
+ if (net_ipv4_is_addr_unspecified (& multicast_ipv4_joined_addrs [i ])) {
1253
+ net_ipv4_addr_copy_raw ((uint8_t * )& multicast_ipv4_joined_addrs [i ],
1254
+ (uint8_t * )addr );
1255
+ break ;
1256
+ }
1257
+ }
1258
+ }
1259
+
1260
+ static void remove_ipv4_multicast_addr (const struct in_addr * addr )
1261
+ {
1262
+ uint32_t i ;
1263
+
1264
+ for (i = 0 ; i < NET_IF_MAX_IPV4_MADDR ; i ++ ) {
1265
+ if (net_ipv4_addr_cmp_raw ((uint8_t * )& multicast_ipv4_joined_addrs [i ],
1266
+ (uint8_t * )addr )) {
1267
+ multicast_ipv4_joined_addrs [i ].s_addr = 0 ;
1268
+ break ;
1269
+ }
1270
+ }
1271
+ }
1272
+ #endif /* CONFIG_NET_NATIVE_IPV4 */
1273
+
1192
1274
static uint32_t reverse (uint32_t val )
1193
1275
{
1194
1276
uint32_t res = 0 ;
@@ -1203,89 +1285,124 @@ static uint32_t reverse(uint32_t val)
1203
1285
return res ;
1204
1286
}
1205
1287
1206
- static void net_if_mcast_cb (struct net_if * iface ,
1288
+ static void net_if_stm32_mcast_cb (struct net_if * iface ,
1207
1289
const struct net_addr * addr ,
1208
1290
bool is_joined )
1209
1291
{
1210
1292
ARG_UNUSED (addr );
1211
- ARG_UNUSED (is_joined );
1212
1293
1213
1294
const struct device * dev ;
1214
1295
struct eth_stm32_hal_dev_data * dev_data ;
1215
1296
ETH_HandleTypeDef * heth ;
1216
- #if defined(CONFIG_NET_NATIVE_IPV6 )
1217
- struct net_if_ipv6 * ipv6 ;
1218
- #endif
1219
- #if defined(CONFIG_NET_NATIVE_IPV4 )
1220
- struct net_if_ipv4 * ipv4 ;
1221
- #endif
1222
1297
struct net_eth_addr mac_addr ;
1223
1298
uint32_t crc ;
1224
1299
uint32_t hash_table [2 ];
1225
1300
uint32_t hash_index ;
1226
1301
int i ;
1227
1302
1228
- __ASSERT_NO_MSG (iface != NULL );
1229
-
1230
1303
dev = net_if_get_device (iface );
1231
- __ASSERT_NO_MSG (dev != NULL );
1232
1304
1233
- dev_data = DEV_DATA (dev );
1234
- __ASSERT_NO_MSG (dev_data != NULL );
1305
+ dev_data = (struct eth_stm32_hal_dev_data * )dev -> data ;
1235
1306
1236
1307
heth = & dev_data -> heth ;
1237
- __ASSERT_NO_MSG (heth != NULL );
1238
1308
1239
1309
hash_table [0 ] = 0 ;
1240
1310
hash_table [1 ] = 0 ;
1241
1311
1242
- #if defined(CONFIG_NET_NATIVE_IPV6 )
1243
- if (net_if_config_ipv6_get (iface , & ipv6 ) < 0 ) {
1244
- return ;
1312
+ if (is_joined ) {
1313
+ /* Save a copy of the hash table which we update with
1314
+ * the hash for a single multicast address for join
1315
+ */
1316
+ #if defined(CONFIG_SOC_SERIES_STM32H7X )
1317
+ hash_table [0 ] = heth -> Instance -> MACHT0R ;
1318
+ hash_table [1 ] = heth -> Instance -> MACHT1R ;
1319
+ #else
1320
+ hash_table [0 ] = heth -> Instance -> MACHTLR ;
1321
+ hash_table [1 ] = heth -> Instance -> MACHTHR ;
1322
+ #endif /* CONFIG_SOC_SERIES_STM32H7X */
1245
1323
}
1246
1324
1247
- for (i = 0 ; i < NET_IF_MAX_IPV6_MADDR ; i ++ ) {
1248
- if (!ipv6 -> mcast [i ].is_used ) {
1249
- continue ;
1250
- }
1325
+ k_mutex_lock (& multicast_addr_lock , K_FOREVER );
1251
1326
1252
- net_eth_ipv6_mcast_to_mac_addr (& ipv6 -> mcast [i ].address .in_addr ,
1253
- & mac_addr );
1327
+ #if defined(CONFIG_NET_NATIVE_IPV6 )
1328
+ if (is_joined ) {
1329
+ /* When joining only update the hash filter with the joining
1330
+ * multicast address.
1331
+ */
1332
+ add_ipv6_multicast_addr (& addr -> in6_addr );
1333
+
1334
+ net_eth_ipv6_mcast_to_mac_addr (& addr -> in6_addr , & mac_addr );
1254
1335
crc = reverse (crc32_ieee (mac_addr .addr ,
1255
- sizeof (struct net_eth_addr )));
1336
+ sizeof (struct net_eth_addr )));
1256
1337
hash_index = (crc >> 26 ) & 0x3f ;
1257
1338
hash_table [hash_index / 32 ] |= (1 << (hash_index % 32 ));
1339
+ } else {
1340
+ /* When leaving its better to compute the full hash table
1341
+ * for all the multicast addresses that we're aware of.
1342
+ */
1343
+ remove_ipv6_multicast_addr (& addr -> in6_addr );
1344
+
1345
+ for (i = 0 ; i < NET_IF_MAX_IPV6_MADDR ; i ++ ) {
1346
+ if (net_ipv6_is_addr_unspecified (& multicast_ipv6_joined_addrs [i ])) {
1347
+ continue ;
1348
+ }
1349
+
1350
+ net_eth_ipv6_mcast_to_mac_addr (& multicast_ipv6_joined_addrs [i ],
1351
+ & mac_addr );
1352
+ crc = reverse (crc32_ieee (mac_addr .addr ,
1353
+ sizeof (struct net_eth_addr )));
1354
+ hash_index = (crc >> 26 ) & 0x3f ;
1355
+ hash_table [hash_index / 32 ] |= (1 << (hash_index % 32 ));
1356
+ }
1258
1357
}
1259
1358
#endif /* CONFIG_NET_IPV6 */
1260
1359
1261
1360
#if defined(CONFIG_NET_NATIVE_IPV4 )
1262
- if (net_if_config_ipv4_get (iface , & ipv4 ) < 0 ) {
1263
- return ;
1264
- }
1265
-
1266
- for (i = 0 ; i < NET_IF_MAX_IPV4_MADDR ; i ++ ) {
1267
- if (!ipv4 -> mcast [i ].is_used ) {
1268
- continue ;
1269
- }
1361
+ if (is_joined ) {
1362
+ /* When joining only update the hash filter with the joining
1363
+ * multicast address.
1364
+ */
1365
+ add_ipv4_multicast_addr (& addr -> in_addr );
1270
1366
1271
- net_eth_ipv4_mcast_to_mac_addr (& ipv4 -> mcast [i ].address .in_addr ,
1272
- & mac_addr );
1367
+ net_eth_ipv4_mcast_to_mac_addr (& addr -> in_addr , & mac_addr );
1273
1368
crc = reverse (crc32_ieee (mac_addr .addr ,
1274
- sizeof (struct net_eth_addr )));
1369
+ sizeof (struct net_eth_addr )));
1275
1370
hash_index = (crc >> 26 ) & 0x3f ;
1276
1371
hash_table [hash_index / 32 ] |= (1 << (hash_index % 32 ));
1372
+ } else {
1373
+ /* When leaving its better to compute the full hash table
1374
+ * for all the multicast addresses that we're aware of.
1375
+ */
1376
+ remove_ipv4_multicast_addr (& addr -> in_addr );
1377
+
1378
+ for (i = 0 ; i < NET_IF_MAX_IPV4_MADDR ; i ++ ) {
1379
+ if (net_ipv4_is_addr_unspecified (& multicast_ipv4_joined_addrs [i ])) {
1380
+ continue ;
1381
+ }
1382
+
1383
+ net_eth_ipv4_mcast_to_mac_addr (& multicast_ipv4_joined_addrs [i ],
1384
+ & mac_addr );
1385
+ crc = reverse (crc32_ieee (mac_addr .addr ,
1386
+ sizeof (struct net_eth_addr )));
1387
+ hash_index = (crc >> 26 ) & 0x3f ;
1388
+ hash_table [hash_index / 32 ] |= (1 << (hash_index % 32 ));
1389
+ }
1277
1390
}
1278
1391
#endif /* CONFIG_NET_IPV4 */
1279
1392
1393
+ k_mutex_unlock (& multicast_addr_lock );
1394
+
1280
1395
#if defined(CONFIG_SOC_SERIES_STM32H7X )
1281
1396
heth -> Instance -> MACHT0R = hash_table [0 ];
1282
1397
heth -> Instance -> MACHT1R = hash_table [1 ];
1283
1398
#else
1284
1399
heth -> Instance -> MACHTLR = hash_table [0 ];
1285
1400
heth -> Instance -> MACHTHR = hash_table [1 ];
1286
- #endif
1401
+ #endif /* CONFIG_SOC_SERIES_STM32H7X */
1287
1402
}
1288
1403
1404
+ #endif /* CONFIG_ETH_STM32_MULTICAST_FILTER */
1405
+
1289
1406
static void eth_iface_init (struct net_if * iface )
1290
1407
{
1291
1408
const struct device * dev ;
@@ -1309,7 +1426,9 @@ static void eth_iface_init(struct net_if *iface)
1309
1426
is_first_init = true;
1310
1427
}
1311
1428
1312
- net_if_mcast_mon_register (& mcast_monitor , iface , net_if_mcast_cb );
1429
+ #if defined(CONFIG_ETH_STM32_MULTICAST_FILTER )
1430
+ net_if_mcast_mon_register (& mcast_monitor , iface , net_if_stm32_mcast_cb );
1431
+ #endif /* CONFIG_ETH_STM32_MULTICAST_FILTER */
1313
1432
1314
1433
/* Register Ethernet MAC Address with the upper layer */
1315
1434
net_if_set_link_addr (iface , dev_data -> mac_addr ,
0 commit comments