Skip to content

Commit eba9549

Browse files
committed
Merge branch 'feat/eth_mac_filter' into 'master'
feat(esp_eth): added option to set MAC filter for mcast Closes IDF-12503 and IDFGH-14897 See merge request espressif/esp-idf!36944
2 parents 4a2273b + e941910 commit eba9549

File tree

27 files changed

+1251
-257
lines changed

27 files changed

+1251
-257
lines changed

components/esp_eth/include/esp_eth_driver.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -175,6 +175,9 @@ typedef enum {
175175
ETH_CMD_S_PHY_LOOPBACK, /*!< Set PHY loopback */
176176
ETH_CMD_READ_PHY_REG, /*!< Read PHY register */
177177
ETH_CMD_WRITE_PHY_REG, /*!< Write PHY register */
178+
ETH_CMD_S_ALL_MULTICAST, /*!< Set receive all multicast */
179+
ETH_CMD_ADD_MAC_FILTER, /*!< Add MAC filter */
180+
ETH_CMD_DEL_MAC_FILTER, /*!< Delete MAC filter */
178181

179182
ETH_CMD_CUSTOM_MAC_CMDS = ETH_CMD_CUSTOM_MAC_CMDS_OFFSET, // Offset for start of MAC custom commands
180183
ETH_CMD_CUSTOM_PHY_CMDS = ETH_CMD_CUSTOM_PHY_CMDS_OFFSET, // Offset for start of PHY custom commands
@@ -380,6 +383,9 @@ esp_err_t esp_eth_transmit_ctrl_vargs(esp_eth_handle_t hdl, void *ctrl, uint32_t
380383
* Preconditions: Ethernet driver needs to be stopped and auto-negotiation disabled.
381384
* @li @c ETH_CMD_G_DUPLEX_MODE gets current Ethernet link duplex mode. @c data argument is pointer to memory of eth_duplex_t datatype to which the duplex mode is to be stored.
382385
* @li @c ETH_CMD_S_PHY_LOOPBACK sets/resets PHY to/from loopback mode. @c data argument is pointer to memory of bool datatype from which the configuration option is read.
386+
* @li @c ETH_CMD_S_ALL_MULTICAST sets/resets Ethernet interface to/from receive all multicast mode. @c data argument is pointer to memory of bool datatype from which the configuration option is read.
387+
* @li @c ETH_CMD_ADD_MAC_FILTER adds a MAC address to the MAC filter. @c data argument is pointer to MAC address buffer with expected size of 6 bytes.
388+
* @li @c ETH_CMD_DEL_MAC_FILTER deletes a MAC address from the MAC filter. @c data argument is pointer to MAC address buffer with expected size of 6 bytes.
383389
*
384390
* @li Note that additional control commands may be available for specific MAC or PHY chips. Please consult specific MAC or PHY documentation or driver code.
385391
*/

components/esp_eth/include/esp_eth_mac.h

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -231,6 +231,30 @@ struct esp_eth_mac_s {
231231
*/
232232
esp_err_t (*get_addr)(esp_eth_mac_t *mac, uint8_t *addr);
233233

234+
/**
235+
* @brief Add Destination address MAC filter
236+
*
237+
* @param[in] mac: Ethernet MAC instance
238+
* @param[in] addr: MAC address
239+
*
240+
* @return
241+
* - ESP_OK: add MAC filter successfully
242+
* - ESP_FAIL: add MAC filter failed because some error occurred
243+
*/
244+
esp_err_t (*add_mac_filter)(esp_eth_mac_t *mac, uint8_t *addr);
245+
246+
/**
247+
* @brief Remove Destination address MAC filter
248+
*
249+
* @param[in] mac: Ethernet MAC instance
250+
* @param[in] addr: MAC address
251+
*
252+
* @return
253+
* - ESP_OK: remove MAC filter successfully
254+
* - ESP_FAIL: remove MAC filter failed because some error occurred
255+
*/
256+
esp_err_t (*rm_mac_filter)(esp_eth_mac_t *mac, uint8_t *addr);
257+
234258
/**
235259
* @brief Set speed of MAC
236260
*
@@ -286,6 +310,18 @@ struct esp_eth_mac_s {
286310
*/
287311
esp_err_t (*set_promiscuous)(esp_eth_mac_t *mac, bool enable);
288312

313+
/**
314+
* @brief Set receive all multicast
315+
*
316+
* @param[in] mac: Ethernet MAC instance
317+
* @param[in] enable: set true to enable receive all multicast; set false to disable receive all multicast
318+
*
319+
* @return
320+
* - ESP_OK: set receive all multicast successfully
321+
* - ESP_FAIL: set receive all multicast failed because some error occurred
322+
*/
323+
esp_err_t (*set_all_multicast)(esp_eth_mac_t *mac, bool enable);
324+
289325
/**
290326
* @brief Enable flow control on MAC layer or not
291327
*

components/esp_eth/src/esp_eth.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -483,6 +483,11 @@ esp_err_t esp_eth_ioctl(esp_eth_handle_t hdl, esp_eth_io_cmd_t cmd, void *data)
483483
ESP_GOTO_ON_FALSE(data, ESP_ERR_INVALID_ARG, err, TAG, "can't set promiscuous to null");
484484
ESP_GOTO_ON_ERROR(mac->set_promiscuous(mac, *(bool *)data), err, TAG, "set promiscuous mode failed");
485485
break;
486+
case ETH_CMD_S_ALL_MULTICAST:
487+
ESP_GOTO_ON_FALSE(data, ESP_ERR_INVALID_ARG, err, TAG, "can't set all multicast to null");
488+
ESP_GOTO_ON_FALSE(mac->set_all_multicast != NULL, ESP_ERR_NOT_SUPPORTED, err, TAG, "set receive all multicast not supported");
489+
ESP_GOTO_ON_ERROR(mac->set_all_multicast(mac, *(bool *)data), err, TAG, "set all multicast mode failed");
490+
break;
486491
case ETH_CMD_S_FLOW_CTRL:
487492
ESP_GOTO_ON_FALSE(data, ESP_ERR_INVALID_ARG, err, TAG, "can't set flow ctrl to null");
488493
ESP_GOTO_ON_ERROR(mac->enable_flow_ctrl(mac, *(bool *)data), err, TAG, "enable mac flow control failed");
@@ -523,6 +528,18 @@ esp_err_t esp_eth_ioctl(esp_eth_handle_t hdl, esp_eth_io_cmd_t cmd, void *data)
523528
phy_addr, phy_w_data->reg_addr, *(phy_w_data->reg_value_p)), err, TAG, "failed to write PHY register");
524529
}
525530
break;
531+
case ETH_CMD_ADD_MAC_FILTER: {
532+
ESP_GOTO_ON_FALSE(data, ESP_ERR_INVALID_ARG, err, TAG, "can't set mac addr to null");
533+
ESP_GOTO_ON_FALSE(mac->add_mac_filter != NULL, ESP_ERR_NOT_SUPPORTED, err, TAG, "add mac address to filter not supported");
534+
ESP_GOTO_ON_ERROR(mac->add_mac_filter(mac, (uint8_t *)data), err, TAG, "add mac address to filter failed");
535+
}
536+
break;
537+
case ETH_CMD_DEL_MAC_FILTER: {
538+
ESP_GOTO_ON_FALSE(data, ESP_ERR_INVALID_ARG, err, TAG, "can't set mac addr to null");
539+
ESP_GOTO_ON_FALSE(mac->rm_mac_filter != NULL, ESP_ERR_NOT_SUPPORTED, err, TAG, "remove mac address from filter not supported");
540+
ESP_GOTO_ON_ERROR(mac->rm_mac_filter(mac, (uint8_t *)data), err, TAG, "remove mac address from filter failed");
541+
}
542+
break;
526543
default:
527544
if (phy->custom_ioctl != NULL && cmd >= ETH_CMD_CUSTOM_PHY_CMDS) {
528545
ret = phy->custom_ioctl(phy, cmd, data);

components/esp_eth/src/esp_eth_netif_glue.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -46,9 +46,23 @@ static void eth_l2_free(void *h, void* buffer)
4646
free(buffer);
4747
}
4848

49+
static esp_err_t eth_set_mac_filter(void *h, const uint8_t *eth_mac, size_t mac_len, bool add)
50+
{
51+
esp_eth_handle_t *eth_handle = (esp_eth_handle_t *)h;
52+
ESP_RETURN_ON_FALSE(mac_len == ETH_ADDR_LEN, ESP_ERR_INVALID_ARG, TAG, "invalid MAC length");
53+
ESP_LOGD(TAG, "%s filter MAC: %02x:%02x:%02x:%02x:%02x:%02x", add ? "Add" : "Del", eth_mac[0], eth_mac[1],
54+
eth_mac[2], eth_mac[3], eth_mac[4], eth_mac[5]);
55+
if (add) {
56+
ESP_RETURN_ON_ERROR(esp_eth_ioctl(eth_handle, ETH_CMD_ADD_MAC_FILTER, (void *)eth_mac), TAG, "failed to add mac filter");
57+
} else {
58+
ESP_RETURN_ON_ERROR(esp_eth_ioctl(eth_handle, ETH_CMD_DEL_MAC_FILTER, (void *)eth_mac), TAG, "failed to delete mac filter");
59+
}
60+
return ESP_OK;
61+
}
62+
4963
static esp_err_t esp_eth_post_attach(esp_netif_t *esp_netif, void *args)
5064
{
51-
uint8_t eth_mac[6];
65+
uint8_t eth_mac[ETH_ADDR_LEN];
5266
esp_eth_netif_glue_t *netif_glue = (esp_eth_netif_glue_t *)args;
5367
netif_glue->base.netif = esp_netif;
5468

@@ -58,7 +72,8 @@ static esp_err_t esp_eth_post_attach(esp_netif_t *esp_netif, void *args)
5872
esp_netif_driver_ifconfig_t driver_ifconfig = {
5973
.handle = netif_glue->eth_driver,
6074
.transmit = esp_eth_transmit,
61-
.driver_free_rx_buffer = eth_l2_free
75+
.driver_free_rx_buffer = eth_l2_free,
76+
.driver_set_mac_filter = eth_set_mac_filter
6277
};
6378

6479
ESP_ERROR_CHECK(esp_netif_set_driver_config(esp_netif, &driver_ifconfig));

components/esp_eth/src/mac/esp_eth_mac_esp.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ static const char *TAG = "esp.emac";
4747
#define RMII_10M_SPEED_RX_TX_CLK_DIV (19)
4848
#define RMII_100M_SPEED_RX_TX_CLK_DIV (1)
4949

50+
#define EMAC_MULTI_REG_MUTEX_TIMEOUT_MS (100)
51+
5052
#if CONFIG_IDF_TARGET_ESP32P4
5153
// ESP32P4 EMAC interface clock configuration is shared among other modules in registers
5254
#define EMAC_IF_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
@@ -70,6 +72,7 @@ typedef struct {
7072
bool flow_ctrl_enabled; // indicates whether the user want to do flow control
7173
bool do_flow_ctrl; // indicates whether we need to do software flow control
7274
bool use_pll; // Only use (A/M)PLL in EMAC_DATA_INTERFACE_RMII && EMAC_CLK_OUT
75+
SemaphoreHandle_t multi_reg_mutex; // lock for multiple register access
7376
#ifdef CONFIG_PM_ENABLE
7477
esp_pm_lock_handle_t pm_lock;
7578
#endif
@@ -89,6 +92,16 @@ static void emac_esp_free_driver_obj(emac_esp32_t *emac);
8992
static esp_err_t emac_esp32_start(esp_eth_mac_t *mac);
9093
static esp_err_t emac_esp32_stop(esp_eth_mac_t *mac);
9194

95+
static esp_err_t emac_esp32_lock_multi_reg(emac_esp32_t *emac)
96+
{
97+
return xSemaphoreTake(emac->multi_reg_mutex, pdMS_TO_TICKS(EMAC_MULTI_REG_MUTEX_TIMEOUT_MS)) == pdTRUE ? ESP_OK : ESP_ERR_TIMEOUT;
98+
}
99+
100+
static esp_err_t emac_esp32_unlock_multi_reg(emac_esp32_t *emac)
101+
{
102+
return xSemaphoreGive(emac->multi_reg_mutex) == pdTRUE ? ESP_OK : ESP_FAIL;
103+
}
104+
92105
static esp_err_t emac_esp32_set_mediator(esp_eth_mac_t *mac, esp_eth_mediator_t *eth)
93106
{
94107
esp_err_t ret = ESP_OK;
@@ -167,6 +180,28 @@ static esp_err_t emac_esp32_get_addr(esp_eth_mac_t *mac, uint8_t *addr)
167180
return ret;
168181
}
169182

183+
static esp_err_t emac_esp32_add_mac_filter(esp_eth_mac_t *mac, uint8_t *addr)
184+
{
185+
esp_err_t ret = ESP_OK;
186+
emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
187+
ESP_RETURN_ON_ERROR(emac_esp32_lock_multi_reg(emac), TAG, "failed to lock multiple register access");
188+
ESP_GOTO_ON_ERROR(emac_hal_add_addr_da_filter_auto(&emac->hal, addr), err, TAG, "failed to add MAC filter");
189+
err:
190+
emac_esp32_unlock_multi_reg(emac);
191+
return ret;
192+
}
193+
194+
static esp_err_t emac_esp32_rm_mac_filter(esp_eth_mac_t *mac, uint8_t *addr)
195+
{
196+
esp_err_t ret = ESP_OK;
197+
emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
198+
ESP_RETURN_ON_ERROR(emac_esp32_lock_multi_reg(emac), TAG, "failed to lock multiple register access");
199+
ESP_GOTO_ON_ERROR(emac_hal_rm_addr_da_filter_auto(&emac->hal, addr), err, TAG, "failed to remove MAC filter");
200+
err:
201+
emac_esp32_unlock_multi_reg(emac);
202+
return ret;
203+
}
204+
170205
static esp_err_t emac_esp32_set_link(esp_eth_mac_t *mac, eth_link_t link)
171206
{
172207
esp_err_t ret = ESP_OK;
@@ -233,6 +268,13 @@ static esp_err_t emac_esp32_set_promiscuous(esp_eth_mac_t *mac, bool enable)
233268
return ESP_OK;
234269
}
235270

271+
static esp_err_t emac_esp32_set_all_multicast(esp_eth_mac_t *mac, bool enable)
272+
{
273+
emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
274+
emac_hal_pass_all_multicast_enable(&emac->hal, enable);
275+
return ESP_OK;
276+
}
277+
236278
static esp_err_t emac_esp32_enable_flow_ctrl(esp_eth_mac_t *mac, bool enable)
237279
{
238280
emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
@@ -631,6 +673,10 @@ static void emac_esp_free_driver_obj(emac_esp32_t *emac)
631673
}
632674
#endif // CONFIG_IDF_TARGET_ESP32
633675

676+
if (emac->multi_reg_mutex) {
677+
vSemaphoreDelete(emac->multi_reg_mutex);
678+
}
679+
634680
#ifdef CONFIG_PM_ENABLE
635681
if (emac->pm_lock) {
636682
esp_pm_lock_delete(emac->pm_lock);
@@ -660,6 +706,10 @@ static esp_err_t emac_esp_alloc_driver_obj(const eth_mac_config_t *config, emac_
660706
#ifdef CONFIG_PM_ENABLE
661707
ESP_GOTO_ON_ERROR(esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "emac_esp32", &emac->pm_lock), err, TAG, "create pm lock failed");
662708
#endif
709+
710+
emac->multi_reg_mutex = xSemaphoreCreateMutex();
711+
ESP_GOTO_ON_FALSE(emac->multi_reg_mutex, ESP_ERR_NO_MEM, err, TAG, "failed to create multiple register access mutex");
712+
663713
/* create rx task */
664714
BaseType_t core_num = tskNO_AFFINITY;
665715
if (config->flags & ETH_MAC_FLAG_PIN_TO_CORE) {
@@ -805,10 +855,13 @@ esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_esp32_emac_config_t *esp32_config
805855
emac->parent.read_phy_reg = emac_esp32_read_phy_reg;
806856
emac->parent.set_addr = emac_esp32_set_addr;
807857
emac->parent.get_addr = emac_esp32_get_addr;
858+
emac->parent.add_mac_filter = emac_esp32_add_mac_filter;
859+
emac->parent.rm_mac_filter = emac_esp32_rm_mac_filter;
808860
emac->parent.set_speed = emac_esp32_set_speed;
809861
emac->parent.set_duplex = emac_esp32_set_duplex;
810862
emac->parent.set_link = emac_esp32_set_link;
811863
emac->parent.set_promiscuous = emac_esp32_set_promiscuous;
864+
emac->parent.set_all_multicast = emac_esp32_set_all_multicast;
812865
emac->parent.set_peer_pause_ability = emac_esp32_set_peer_pause_ability;
813866
emac->parent.enable_flow_ctrl = emac_esp32_enable_flow_ctrl;
814867
emac->parent.transmit = emac_esp32_transmit;

0 commit comments

Comments
 (0)