Skip to content

Commit c76aaf3

Browse files
mrfuchscarlescufi
authored andcommitted
drivers: ethernet: stm32: Enable multicast address filter
Use the MAC's hash table to filter incoming multicast frames that are targeted to subscribed multicast groups and discard all others. Signed-off-by: Markus Fuchs <[email protected]> # Conflicts: # drivers/ethernet/eth_stm32_hal.c
1 parent 5973a94 commit c76aaf3

File tree

1 file changed

+108
-7
lines changed

1 file changed

+108
-7
lines changed

drivers/ethernet/eth_stm32_hal.c

Lines changed: 108 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
1717
#include <zephyr/device.h>
1818
#include <zephyr/sys/__assert.h>
1919
#include <zephyr/sys/util.h>
20+
#include <zephyr/crc.h>
2021
#include <errno.h>
2122
#include <stdbool.h>
2223
#include <zephyr/net/net_pkt.h>
@@ -96,6 +97,8 @@ static ETH_DMADescTypeDef dma_tx_desc_tab[ETH_TXBUFNB] __eth_stm32_desc;
9697
static uint8_t dma_rx_buffer[ETH_RXBUFNB][ETH_STM32_RX_BUF_SIZE] __eth_stm32_buf;
9798
static uint8_t dma_tx_buffer[ETH_TXBUFNB][ETH_STM32_TX_BUF_SIZE] __eth_stm32_buf;
9899

100+
static struct net_if_mcast_monitor mcast_monitor;
101+
99102
#if defined(CONFIG_ETH_STM32_HAL_API_V2)
100103

101104
BUILD_ASSERT(ETH_STM32_RX_BUF_SIZE % 4 == 0, "Rx buffer size must be a multiple of 4");
@@ -222,8 +225,8 @@ static inline void disable_mcast_filter(ETH_HandleTypeDef *heth)
222225
ETH_MACFilterConfigTypeDef MACFilterConf;
223226

224227
HAL_ETH_GetMACFilterConfig(heth, &MACFilterConf);
225-
MACFilterConf.HashMulticast = DISABLE;
226-
MACFilterConf.PassAllMulticast = ENABLE;
228+
MACFilterConf.HashMulticast = ENABLE;
229+
MACFilterConf.PassAllMulticast = DISABLE;
227230
MACFilterConf.HachOrPerfectFilter = DISABLE;
228231

229232
HAL_ETH_SetMACFilterConfig(heth, &MACFilterConf);
@@ -232,13 +235,12 @@ static inline void disable_mcast_filter(ETH_HandleTypeDef *heth)
232235
#else
233236
uint32_t tmp = heth->Instance->MACFFR;
234237

235-
/* disable multicast filtering */
238+
/* disable multicast perfect filtering */
236239
tmp &= ~(ETH_MULTICASTFRAMESFILTER_PERFECTHASHTABLE |
237-
ETH_MULTICASTFRAMESFILTER_HASHTABLE |
238240
ETH_MULTICASTFRAMESFILTER_PERFECT);
239241

240-
/* enable receiving all multicast frames */
241-
tmp |= ETH_MULTICASTFRAMESFILTER_NONE;
242+
/* enable multicast hash receive filter */
243+
tmp |= ETH_MULTICASTFRAMESFILTER_HASHTABLE;
242244

243245
heth->Instance->MACFFR = tmp;
244246

@@ -1163,7 +1165,7 @@ static int eth_initialize(const struct device *dev)
11631165
LOG_ERR("HAL_ETH_Start{_IT} failed");
11641166
}
11651167

1166-
disable_mcast_filter(heth);
1168+
setup_mac_filter(heth);
11671169

11681170
#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_ETH_STM32_HAL_API_V2)
11691171
/* Adjust MDC clock range depending on HCLK frequency: */
@@ -1187,6 +1189,103 @@ static int eth_initialize(const struct device *dev)
11871189
return 0;
11881190
}
11891191

1192+
static uint32_t reverse(uint32_t val)
1193+
{
1194+
uint32_t res = 0;
1195+
int i;
1196+
1197+
for (i = 0; i < 32; i++) {
1198+
if (val & (1 << i)) {
1199+
res |= 1 << (31 - i);
1200+
}
1201+
}
1202+
1203+
return res;
1204+
}
1205+
1206+
static void net_if_mcast_cb(struct net_if *iface,
1207+
const struct net_addr *addr,
1208+
bool is_joined)
1209+
{
1210+
ARG_UNUSED(addr);
1211+
ARG_UNUSED(is_joined);
1212+
1213+
const struct device *dev;
1214+
struct eth_stm32_hal_dev_data *dev_data;
1215+
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+
struct net_eth_addr mac_addr;
1223+
uint32_t crc;
1224+
uint32_t hash_table[2];
1225+
uint32_t hash_index;
1226+
int i;
1227+
1228+
__ASSERT_NO_MSG(iface != NULL);
1229+
1230+
dev = net_if_get_device(iface);
1231+
__ASSERT_NO_MSG(dev != NULL);
1232+
1233+
dev_data = DEV_DATA(dev);
1234+
__ASSERT_NO_MSG(dev_data != NULL);
1235+
1236+
heth = &dev_data->heth;
1237+
__ASSERT_NO_MSG(heth != NULL);
1238+
1239+
hash_table[0] = 0;
1240+
hash_table[1] = 0;
1241+
1242+
#if defined(CONFIG_NET_NATIVE_IPV6)
1243+
if (net_if_config_ipv6_get(iface, &ipv6) < 0) {
1244+
return;
1245+
}
1246+
1247+
for (i = 0; i < NET_IF_MAX_IPV6_MADDR; i++) {
1248+
if (!ipv6->mcast[i].is_used) {
1249+
continue;
1250+
}
1251+
1252+
net_eth_ipv6_mcast_to_mac_addr(&ipv6->mcast[i].address.in_addr,
1253+
&mac_addr);
1254+
crc = reverse(crc32_ieee(mac_addr.addr,
1255+
sizeof(struct net_eth_addr)));
1256+
hash_index = (crc >> 26) & 0x3f;
1257+
hash_table[hash_index / 32] |= (1 << (hash_index % 32));
1258+
}
1259+
#endif /* CONFIG_NET_IPV6 */
1260+
1261+
#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+
}
1270+
1271+
net_eth_ipv4_mcast_to_mac_addr(&ipv4->mcast[i].address.in_addr,
1272+
&mac_addr);
1273+
crc = reverse(crc32_ieee(mac_addr.addr,
1274+
sizeof(struct net_eth_addr)));
1275+
hash_index = (crc >> 26) & 0x3f;
1276+
hash_table[hash_index / 32] |= (1 << (hash_index % 32));
1277+
}
1278+
#endif /* CONFIG_NET_IPV4 */
1279+
1280+
#if defined(CONFIG_SOC_SERIES_STM32H7X)
1281+
heth->Instance->MACHT0R = hash_table[0];
1282+
heth->Instance->MACHT1R = hash_table[1];
1283+
#else
1284+
heth->Instance->MACHTLR = hash_table[0];
1285+
heth->Instance->MACHTHR = hash_table[1];
1286+
#endif
1287+
}
1288+
11901289
static void eth_iface_init(struct net_if *iface)
11911290
{
11921291
const struct device *dev;
@@ -1210,6 +1309,8 @@ static void eth_iface_init(struct net_if *iface)
12101309
is_first_init = true;
12111310
}
12121311

1312+
net_if_mcast_mon_register(&mcast_monitor, iface, net_if_mcast_cb);
1313+
12131314
/* Register Ethernet MAC Address with the upper layer */
12141315
net_if_set_link_addr(iface, dev_data->mac_addr,
12151316
sizeof(dev_data->mac_addr),

0 commit comments

Comments
 (0)