diff --git a/drivers/ethernet/eth_stm32_hal.c b/drivers/ethernet/eth_stm32_hal.c index b9d4c19186d..fcea86e4049 100644 --- a/drivers/ethernet/eth_stm32_hal.c +++ b/drivers/ethernet/eth_stm32_hal.c @@ -100,22 +100,6 @@ static ETH_DMADescTypeDef dma_tx_desc_tab[ETH_TXBUFNB] __eth_stm32_desc; static uint8_t dma_rx_buffer[ETH_RXBUFNB][ETH_STM32_RX_BUF_SIZE] __eth_stm32_buf; static uint8_t dma_tx_buffer[ETH_TXBUFNB][ETH_STM32_TX_BUF_SIZE] __eth_stm32_buf; -#if defined(CONFIG_ETH_STM32_MULTICAST_FILTER) - -static struct net_if_mcast_monitor mcast_monitor; - -static K_MUTEX_DEFINE(multicast_addr_lock); - -#if defined(CONFIG_NET_NATIVE_IPV6) -static struct in6_addr multicast_ipv6_joined_addrs[NET_IF_MAX_IPV6_MADDR] = {0}; -#endif /* CONFIG_NET_NATIVE_IPV6 */ - -#if defined(CONFIG_NET_NATIVE_IPV4) -static struct in_addr multicast_ipv4_joined_addrs[NET_IF_MAX_IPV4_MADDR] = {0}; -#endif /* CONFIG_NET_NATIVE_IPV4 */ - -#endif /* CONFIG_ETH_STM32_MULTICAST_FILTER */ - #if defined(CONFIG_ETH_STM32_HAL_API_V2) BUILD_ASSERT(ETH_STM32_RX_BUF_SIZE % 4 == 0, "Rx buffer size must be a multiple of 4"); @@ -1305,62 +1289,6 @@ static int eth_initialize(const struct device *dev) } #if defined(CONFIG_ETH_STM32_MULTICAST_FILTER) - -#if defined(CONFIG_NET_NATIVE_IPV6) -static void add_ipv6_multicast_addr(const struct in6_addr *addr) -{ - uint32_t i; - - for (i = 0; i < NET_IF_MAX_IPV6_MADDR; i++) { - if (net_ipv6_is_addr_unspecified(&multicast_ipv6_joined_addrs[i])) { - net_ipv6_addr_copy_raw((uint8_t *)&multicast_ipv6_joined_addrs[i], - (uint8_t *)addr); - break; - } - } -} - -static void remove_ipv6_multicast_addr(const struct in6_addr *addr) -{ - uint32_t i; - - for (i = 0; i < NET_IF_MAX_IPV6_MADDR; i++) { - if (net_ipv6_addr_cmp(&multicast_ipv6_joined_addrs[i], addr)) { - net_ipv6_addr_copy_raw((uint8_t *)&multicast_ipv6_joined_addrs[i], - (uint8_t *)net_ipv6_unspecified_address); - break; - } - } -} -#endif /* CONFIG_NET_NATIVE_IPV6 */ - -#if defined(CONFIG_NET_NATIVE_IPV4) -static void add_ipv4_multicast_addr(const struct in_addr *addr) -{ - uint32_t i; - - for (i = 0; i < NET_IF_MAX_IPV4_MADDR; i++) { - if (net_ipv4_is_addr_unspecified(&multicast_ipv4_joined_addrs[i])) { - net_ipv4_addr_copy_raw((uint8_t *)&multicast_ipv4_joined_addrs[i], - (uint8_t *)addr); - break; - } - } -} - -static void remove_ipv4_multicast_addr(const struct in_addr *addr) -{ - uint32_t i; - - for (i = 0; i < NET_IF_MAX_IPV4_MADDR; i++) { - if (net_ipv4_addr_cmp(&multicast_ipv4_joined_addrs[i], addr)) { - multicast_ipv4_joined_addrs[i].s_addr = 0; - break; - } - } -} -#endif /* CONFIG_NET_NATIVE_IPV4 */ - static uint32_t reverse(uint32_t val) { uint32_t res = 0; @@ -1375,112 +1303,43 @@ static uint32_t reverse(uint32_t val) return res; } -static void net_if_stm32_mcast_cb(struct net_if *iface, - const struct net_addr *addr, - bool is_joined) +static void eth_stm32_mcast_filter(const struct device *dev, const struct ethernet_filter *filter) { - ARG_UNUSED(addr); - - const struct device *dev; - struct eth_stm32_hal_dev_data *dev_data; + struct eth_stm32_hal_dev_data *dev_data = (struct eth_stm32_hal_dev_data *)dev->data; ETH_HandleTypeDef *heth; - struct net_eth_addr mac_addr; uint32_t crc; uint32_t hash_table[2]; uint32_t hash_index; - int i; - - dev = net_if_get_device(iface); - - dev_data = (struct eth_stm32_hal_dev_data *)dev->data; heth = &dev_data->heth; - hash_table[0] = 0; - hash_table[1] = 0; + crc = reverse(crc32_ieee(filter->mac_address.addr, sizeof(struct net_eth_addr))); + hash_index = (crc >> 26) & 0x3f; + + __ASSERT_NO_MSG(hash_index < ARRAY_SIZE(dev_data->hash_index_cnt)); - if (is_joined) { - /* Save a copy of the hash table which we update with - * the hash for a single multicast address for join - */ #if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) - hash_table[0] = heth->Instance->MACHT0R; - hash_table[1] = heth->Instance->MACHT1R; + hash_table[0] = heth->Instance->MACHT0R; + hash_table[1] = heth->Instance->MACHT1R; #else - hash_table[0] = heth->Instance->MACHTLR; - hash_table[1] = heth->Instance->MACHTHR; + hash_table[0] = heth->Instance->MACHTLR; + hash_table[1] = heth->Instance->MACHTHR; #endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ - } - k_mutex_lock(&multicast_addr_lock, K_FOREVER); - -#if defined(CONFIG_NET_NATIVE_IPV6) - if (is_joined) { - /* When joining only update the hash filter with the joining - * multicast address. - */ - add_ipv6_multicast_addr(&addr->in6_addr); - - net_eth_ipv6_mcast_to_mac_addr(&addr->in6_addr, &mac_addr); - crc = reverse(crc32_ieee(mac_addr.addr, - sizeof(struct net_eth_addr))); - hash_index = (crc >> 26) & 0x3f; + if (filter->set) { + dev_data->hash_index_cnt[hash_index]++; hash_table[hash_index / 32] |= (1 << (hash_index % 32)); } else { - /* When leaving its better to compute the full hash table - * for all the multicast addresses that we're aware of. - */ - remove_ipv6_multicast_addr(&addr->in6_addr); + if (dev_data->hash_index_cnt[hash_index] == 0) { + __ASSERT_NO_MSG(false); + return; + } - for (i = 0; i < NET_IF_MAX_IPV6_MADDR; i++) { - if (net_ipv6_is_addr_unspecified(&multicast_ipv6_joined_addrs[i])) { - continue; - } - - net_eth_ipv6_mcast_to_mac_addr(&multicast_ipv6_joined_addrs[i], - &mac_addr); - crc = reverse(crc32_ieee(mac_addr.addr, - sizeof(struct net_eth_addr))); - hash_index = (crc >> 26) & 0x3f; - hash_table[hash_index / 32] |= (1 << (hash_index % 32)); + dev_data->hash_index_cnt[hash_index]--; + if (dev_data->hash_index_cnt[hash_index] == 0) { + hash_table[hash_index / 32] &= ~(1 << (hash_index % 32)); } } -#endif /* CONFIG_NET_IPV6 */ - -#if defined(CONFIG_NET_NATIVE_IPV4) - if (is_joined) { - /* When joining only update the hash filter with the joining - * multicast address. - */ - add_ipv4_multicast_addr(&addr->in_addr); - - net_eth_ipv4_mcast_to_mac_addr(&addr->in_addr, &mac_addr); - crc = reverse(crc32_ieee(mac_addr.addr, - sizeof(struct net_eth_addr))); - hash_index = (crc >> 26) & 0x3f; - hash_table[hash_index / 32] |= (1 << (hash_index % 32)); - } else { - /* When leaving its better to compute the full hash table - * for all the multicast addresses that we're aware of. - */ - remove_ipv4_multicast_addr(&addr->in_addr); - - for (i = 0; i < NET_IF_MAX_IPV4_MADDR; i++) { - if (net_ipv4_is_addr_unspecified(&multicast_ipv4_joined_addrs[i])) { - continue; - } - - net_eth_ipv4_mcast_to_mac_addr(&multicast_ipv4_joined_addrs[i], - &mac_addr); - crc = reverse(crc32_ieee(mac_addr.addr, - sizeof(struct net_eth_addr))); - hash_index = (crc >> 26) & 0x3f; - hash_table[hash_index / 32] |= (1 << (hash_index % 32)); - } - } -#endif /* CONFIG_NET_IPV4 */ - - k_mutex_unlock(&multicast_addr_lock); #if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) heth->Instance->MACHT0R = hash_table[0]; @@ -1516,10 +1375,6 @@ static void eth_iface_init(struct net_if *iface) is_first_init = true; } -#if defined(CONFIG_ETH_STM32_MULTICAST_FILTER) - net_if_mcast_mon_register(&mcast_monitor, iface, net_if_stm32_mcast_cb); -#endif /* CONFIG_ETH_STM32_MULTICAST_FILTER */ - /* Register Ethernet MAC Address with the upper layer */ net_if_set_link_addr(iface, dev_data->mac_addr, sizeof(dev_data->mac_addr), @@ -1575,6 +1430,9 @@ static enum ethernet_hw_caps eth_stm32_hal_get_capabilities(const struct device #endif #if defined(CONFIG_NET_DSA) | ETHERNET_DSA_MASTER_PORT +#endif +#if defined(CONFIG_ETH_STM32_MULTICAST_FILTER) + | ETHERNET_HW_FILTERING #endif ; } @@ -1622,6 +1480,11 @@ static int eth_stm32_hal_set_config(const struct device *dev, ret = 0; #endif /* CONFIG_NET_PROMISCUOUS_MODE */ break; +#if defined(CONFIG_ETH_STM32_MULTICAST_FILTER) + case ETHERNET_CONFIG_TYPE_FILTER: + eth_stm32_mcast_filter(dev, &config->filter); + break; +#endif /* CONFIG_ETH_STM32_MULTICAST_FILTER */ default: break; } diff --git a/drivers/ethernet/eth_stm32_hal_priv.h b/drivers/ethernet/eth_stm32_hal_priv.h index 99644585dff..55ae396c90d 100644 --- a/drivers/ethernet/eth_stm32_hal_priv.h +++ b/drivers/ethernet/eth_stm32_hal_priv.h @@ -49,6 +49,9 @@ struct eth_stm32_hal_dev_data { CONFIG_ETH_STM32_HAL_RX_THREAD_STACK_SIZE); struct k_thread rx_thread; bool link_up; +#if defined(CONFIG_ETH_STM32_MULTICAST_FILTER) + uint8_t hash_index_cnt[64]; +#endif /* CONFIG_ETH_STM32_MULTICAST_FILTER */ #if defined(CONFIG_PTP_CLOCK_STM32_HAL) const struct device *ptp_clock; float clk_ratio;