Merge branch 'feature/eth_bridge_test' into 'master'

lwIP bridge FDB add entry fix and bridge test

Closes IDF-5394

See merge request espressif/esp-idf!20464
pull/6808/head
Ondrej Kosta 2022-12-01 17:51:11 +08:00
commit 4ded1ea4cf
6 zmienionych plików z 196 dodań i 9 usunięć

Wyświetl plik

@ -378,11 +378,9 @@ esp_err_t esp_netif_bridge_add_port(esp_netif_t *esp_netif_br, esp_netif_t *esp_
esp_err_t esp_netif_bridge_fdb_add(esp_netif_t *esp_netif_br, uint8_t *addr, uint64_t ports_mask) esp_err_t esp_netif_bridge_fdb_add(esp_netif_t *esp_netif_br, uint8_t *addr, uint64_t ports_mask)
{ {
bridgeif_portmask_t ports; bridgeif_portmask_t ports = (bridgeif_portmask_t)ports_mask;
if (ports_mask == ESP_NETIF_BR_FDW_CPU) { if (ports_mask & ESP_NETIF_BR_FDW_CPU) {
ports = 1 << BRIDGEIF_MAX_PORTS; ports |= 1 << BRIDGEIF_MAX_PORTS;
} else {
ports = (bridgeif_portmask_t)ports_mask;
} }
if (ERR_OK != bridgeif_fdb_add(esp_netif_br->lwip_netif, (const struct eth_addr *)addr, ports)) { if (ERR_OK != bridgeif_fdb_add(esp_netif_br->lwip_netif, (const struct eth_addr *)addr, ports)) {

Wyświetl plik

@ -72,10 +72,14 @@ idf.py -p PORT build flash monitor
(Replace PORT with the name of the serial port to use.) (Replace PORT with the name of the serial port to use.)
(To exit the serial monitor, type ``Ctrl-]``.) (To exit the serial monitor, press ``Ctrl-]``.)
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
### Forwarding Database Configuration
You can configure bridges static Forwarding Database (FDB) via interactive console. Type ``help`` in the serial monitor to show available options.
## Example Output ## Example Output
**ESP32 output:** **ESP32 output:**

Wyświetl plik

@ -1,2 +1,3 @@
idf_component_register(SRCS "bridge_example_main.c" idf_component_register(SRCS "bridge_example_main.c"
"bridge_console_cmd.c"
INCLUDE_DIRS ".") INCLUDE_DIRS ".")

Wyświetl plik

@ -0,0 +1,150 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <string.h>
#include <inttypes.h>
#include "esp_log.h"
#include "esp_check.h"
#include "esp_console.h"
#include "argtable3/argtable3.h"
#include "esp_eth_spec.h"
#include "bridge_console_cmd.h"
typedef struct {
struct arg_str *addr;
struct arg_int *port;
struct arg_lit *drop;
struct arg_lit *flood;
struct arg_lit *cpu;
struct arg_end *end;
} br_add_fdb_args_t;
typedef struct {
struct arg_str *addr;
struct arg_end *end;
} br_remove_fdb_args_t;
static const char *TAG = "br_config_console";
static br_add_fdb_args_t s_add_args;
static br_remove_fdb_args_t s_remove_args;
static esp_netif_t *s_br_netif;
static uint8_t s_br_port_cnt;
static esp_err_t str2mac(const char *str, uint8_t *mac_addr)
{
unsigned int mac_tmp[ETH_ADDR_LEN];
if (ETH_ADDR_LEN != sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x%*c",
&mac_tmp[0], &mac_tmp[1], &mac_tmp[2],
&mac_tmp[3], &mac_tmp[4], &mac_tmp[5])) {
return ESP_ERR_INVALID_MAC;
}
for (int i = 0; i < ETH_ADDR_LEN; i++) {
mac_addr[i] = (uint8_t)mac_tmp[i];
}
return ESP_OK;
}
static int cmd_br_fdb_add(int argc, char **argv)
{
int nerrors = arg_parse(argc, argv, (void **) &s_add_args);
if (nerrors != 0) {
arg_print_errors(stderr, s_add_args.end, argv[0]);
return 1;
}
int exp_argc = 2;
if (s_add_args.port->count > 0) {
exp_argc += 2 * s_add_args.port->count;
if (s_add_args.cpu->count > 0) {
exp_argc++;
}
} else {
exp_argc++;
}
ESP_RETURN_ON_FALSE(argc == exp_argc, 1, TAG, "Invalid number or combination of arguments");
uint64_t port_mask = ESP_NETIF_BR_DROP;
for (int i = 0; i < s_add_args.port->count; i++) {
ESP_RETURN_ON_FALSE(s_add_args.port->ival[i] > 0 && s_add_args.port->ival[i] <= s_br_port_cnt, 1, TAG, "Invalid port number");
port_mask |= 1 << ((uint64_t)(s_add_args.port->ival[i]) - 1);
}
if (s_add_args.drop->count > 0) {
port_mask = ESP_NETIF_BR_DROP;
}
if (s_add_args.flood->count > 0) {
port_mask = ESP_NETIF_BR_FLOOD;
}
if (s_add_args.cpu->count > 0) {
port_mask |= ESP_NETIF_BR_FDW_CPU;
}
uint8_t mac_addr[ETH_ADDR_LEN];
ESP_RETURN_ON_FALSE(str2mac(s_add_args.addr->sval[0], mac_addr) == ESP_OK,
1, TAG, "Ivalid MAC address format (expected xx:xx:xx:xx:xx:xx)");
ESP_RETURN_ON_FALSE(esp_netif_bridge_fdb_add(s_br_netif, mac_addr, port_mask) == ESP_OK,
1, TAG, "Adding FDB entry failed");
ESP_LOG_BUFFER_HEX_LEVEL(TAG, mac_addr, ETH_ADDR_LEN, ESP_LOG_DEBUG);
ESP_LOGD(TAG, "portmask 0x%" PRIu64 "\n", port_mask);
ESP_LOGI(TAG, "Bridge Config OK!");
return 0;
}
static int cmd_br_fdb_remove(int argc, char **argv)
{
int nerrors = arg_parse(argc, argv, (void **) &s_remove_args);
if (nerrors != 0) {
arg_print_errors(stderr, s_remove_args.end, argv[0]);
return 1;
}
uint8_t mac_addr[ETH_ADDR_LEN];
ESP_RETURN_ON_FALSE(str2mac(s_remove_args.addr->sval[0], mac_addr) == ESP_OK,
1, TAG, "Ivalid MAC address format (expected xx:xx:xx:xx:xx:xx)");
ESP_RETURN_ON_FALSE(esp_netif_bridge_fdb_remove(s_br_netif, mac_addr) == ESP_OK,
1, TAG, "Removing FDB entry failed");
ESP_LOG_BUFFER_HEX_LEVEL(TAG, mac_addr, ETH_ADDR_LEN, ESP_LOG_DEBUG);
ESP_LOGI(TAG, "Bridge Config OK!");
return 0;
}
void example_register_br_config_commands(esp_netif_t *br_netif, uint8_t br_port_cnt)
{
ESP_LOGI(TAG, "Registering Bridge config commands.");
s_add_args.addr = arg_str1(NULL, "addr", "<MAC address>", "MAC address to be added in expected xx:xx:xx:xx:xx:xx format");
s_add_args.port = arg_intn("p", "port", "<port_num>", 0, br_port_cnt + 1, "Forward to Port Number");
s_add_args.drop = arg_lit0("d", "drop", "Drop");
s_add_args.flood = arg_lit0("f", "flood", "Flood to all ports");
s_add_args.cpu = arg_lit0("c", "cpu", "Forward to CPU");
s_add_args.end = arg_end(2);
const esp_console_cmd_t br_add_fdb_cmd = {
.command = "add",
.help = "Add Forwarding Database entry",
.hint = NULL,
.func = &cmd_br_fdb_add,
.argtable = &s_add_args
};
ESP_ERROR_CHECK(esp_console_cmd_register(&br_add_fdb_cmd));
s_remove_args.addr = arg_str1(NULL, "addr", "<MAC address>", "MAC address to be removed in expected xx:xx:xx:xx:xx:xx format");
s_remove_args.end = arg_end(1);
const esp_console_cmd_t br_remove_fdb_cmd = {
.command = "remove",
.help = "Remove Forwarding Database entry",
.hint = NULL,
.func = &cmd_br_fdb_remove,
.argtable = &s_remove_args
};
ESP_ERROR_CHECK(esp_console_cmd_register(&br_remove_fdb_cmd));
s_br_netif = br_netif;
s_br_port_cnt = br_port_cnt;
}

Wyświetl plik

@ -0,0 +1,20 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#pragma once
#include <stdint.h>
#include "esp_netif.h"
#ifdef __cplusplus
extern "C" {
#endif
// Register Bridge configuration commands
void example_register_br_config_commands(esp_netif_t *br_netif, uint8_t br_port_cnt);
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -16,6 +16,8 @@
#include "esp_mac.h" #include "esp_mac.h"
#include "ethernet_init.h" #include "ethernet_init.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#include "esp_console.h"
#include "bridge_console_cmd.h"
static const char *TAG = "eth_bridge_example"; static const char *TAG = "eth_bridge_example";
@ -57,9 +59,9 @@ static void got_ip_event_handler(void *arg, esp_event_base_t event_base,
ESP_LOGI(TAG, "Ethernet Got IP Address"); ESP_LOGI(TAG, "Ethernet Got IP Address");
ESP_LOGI(TAG, "~~~~~~~~~~~"); ESP_LOGI(TAG, "~~~~~~~~~~~");
ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip)); ESP_LOGI(TAG, "ETHIP:" IPSTR "\r", IP2STR(&ip_info->ip));
ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask)); ESP_LOGI(TAG, "ETHMASK:" IPSTR "\r", IP2STR(&ip_info->netmask));
ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw)); ESP_LOGI(TAG, "ETHGW:" IPSTR "\r", IP2STR(&ip_info->gw));
ESP_LOGI(TAG, "~~~~~~~~~~~"); ESP_LOGI(TAG, "~~~~~~~~~~~");
} }
@ -146,4 +148,16 @@ void app_main(void)
// Start Ethernet driver state machine // Start Ethernet driver state machine
ESP_ERROR_CHECK(esp_eth_start(eth_handles[i])); ESP_ERROR_CHECK(esp_eth_start(eth_handles[i]));
} }
// --- Initialize Console ---
esp_console_repl_t *repl = NULL;
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
repl_config.prompt = "bridge>";
// install console REPL environment
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
example_register_br_config_commands(br_netif, eth_port_cnt);
// start console REPL
ESP_ERROR_CHECK(esp_console_start_repl(repl));
} }