一:簡介
Ethernet 轉 WiFi 用于實作以太網口的裝置通過 WiFi 進行無線互聯。将從裝置 發出的 802.3 幀資料轉化為 802.11 幀資料發送出去,接收到的 802.11 幀資料轉換為 802.3 幀資料發送給裝置,其跳過了 ESP32 的 lwip,直接在實體層進行了資料的轉發,提高了資料轉發的效率。

在本 Demo 中,Ethernet 轉 WiFi 主要有兩種使用方式:STATION 模式和 SOFTAP 模式,
二:硬體準備
實作 Ethernet 轉 WiFi 需使用帶有 phy 功能的 ESP32 開發闆,本 Demo 使用的是 ESP32_Ethernet_v3。對于普通的 ESP32 開發闆,想要實作本 Demo 需外接 PHY,目前 ESP32 Ethernt driver 支援的 phy 有 TLK110 和 LAN8720,而在 ESP32_Ethernet_v3 中內建的是 TLK110 。
三:配置說明
3.1 PHY 配置
使用者可以在
make menuconfig
中對 PHY 進行配置。如果使用 ESP32_Ethernet_v3 開發闆,隻需要使用預設配置即可;對于外接 phy 的使用者,可以參照 Ethernet Demo 中的要求對 phy 進行修改。
3.2 WiFi 配置
WiFi 的配置主要是為了提高資料的吞吐率,在本 Demo 中,增加了 WiFi RX 和 TX 的 buffer 數量,并調整了 ESP32 的 CPU 時鐘,具體優化資訊請參照預設配置項 sdkconfig.defaults。
Note: 使用者可以根據自己需要通過
make menuconfig
調整相關參數,但是 STATIC_RX_BUFFER_NUM和 TX/RX BA Window(the size of WiFi Block Ack TX window) 均不要超過 16 ,否則可能會因為記憶體問題引起 crash,其中這些參數位于 Component config -> Wi-Fi 下。
四:Demo 使用步驟
通過如下方式擷取此 Demo
$ git clone https://github.com/espressif/esp-iot-solution
$ cd esp-iot-solution
$ git submodule update --init --recursive
本 Demo 位于 esp-iot-solution/examples/eth2wifi 下,Demo 提供了 ethernet 轉 WiFi 的兩種模式:ESP32 作為 STATION 模式和 ESP32 作為 SOFTAP 模式。
4.1 STATION 模式
STATION 模式是裝置将 Ethernet 幀資料轉化為 WiFi station 幀資料,然後将 WiFi station 資料無線發送給 AP ,進而實作類似于無線網卡的功能。
a) 使用 USB 轉序列槽線将開發闆連接配接到 PC 上
b) 進入 esp-iot-solution/examples/eth2wifi 所在目錄
c) 選擇配置
$ make menuconfig
- 在 Serial flasher config - Default serial port 中,配置需要下載下傳的序列槽
- 在 Component config - IoT Example - Ethernet to WiFi Demo Configuration - The SSID for demo 中設定 SSID
- 在 Component config - IoT Example - Ethernet to WiFi Demo Configuration - The PASSWORD for demo 中設定 WiFi 密碼
- 在 Component config - IoT Example - Ethernet to WiFi Demo Configuration - WiFi station mode 中,輸入 y,選擇 STA 模式(預設即為 Y )
d) 編譯并燒錄程式
$ make flash
e) 運作
- 燒錄成功後,打開序列槽工具,此時會列印 log,根據 SSID 連接配接 AP,然後 PC 會發起 DHCP 請求
- 檢視是否拿到 IP,并嘗試 ping 網關來測試是否正常
4.2 SOFTAP 模式
SOFTAP 模式是利用 ESP32 所屬的裝置作為一個 AP,進而可以組建一個小型的區域網路,因為互動需要 IP 資訊,是以需要裝置具備 DHCP Server 的能力,在本 Demo 中,使用 PC 來作為 DHCP Server。
4.2.1 Ubuntu DHCP server 配置
Ubuntu 配置 dhcp 伺服器需要:計算機設定靜态 ip ,(充當 dhcp 伺服器的計算機的 ip 需要是靜态 ip,不可以是通過動态獲得,設定靜态 ip 需要設定在對應的網卡:如 eth0 )設定子網路遮罩,預設網關,以及配置 dhcp。
a) PC 設定靜态 ip/子網路遮罩/網關
靜态 ip 的配置:
設定–>系統設定–>網絡–>選項–> ipv4 –>方法:手動;添加–> address, subnet, netmask.
我設定的靜态ip位址:192.168.5.0,子網路遮罩:255.255.255.0,網關:192.168.5.1。
$ sudo vim /etc/network/interfaces
設定成如下内容:
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address .5.0
gateway .5.1
netmask .255.0
Note: eth0 是測試 PC 上的網卡名稱,不同的電腦網卡名稱不同,可通過 ipconfig 檢視,替換成自己的網卡名稱即可
配置完成後重新開機網絡服務:
sudo /etc/init.d/networking restart
b) 配置 DHCP 伺服器
- 首先安裝 DHCP 伺服器
- 配置 DHCP 的網卡
設定使用網卡(我的是 eth0 )作為 DHCP Server
- 編輯目前配置
$ sudo vim /etc/dhcp/dhcpd.conf
在檔案末尾添加如下幾項
subnet netmask {
range ;
# option domain-name-servers ;
# option domain-name "internal.example.org";
# option routers ;
option broadcast-address ;
default-lease-time ;
max-lease-time ;
}
- 配置完成後,重新開機 dhcp 服務:
$ sudo /etc/init.d/isc-dhcpd-server restart
Note: /etc/dhcp/dhcpd.conf中的 subnet 一定要包含 server 本機的 ip 在内,否則啟動不了
最後可以通過 ifconfig eth0 檢視是否靜态 IP 設定成功
c) 燒寫步驟
燒寫 softap 的步驟與 STA 基本相同,隻需要在第 4 步時将 Ethernet to wifi station forwarding data 設定為 n 即為 softap 模式。
d) 運作
- 将 ESP32 連接配接到 PC 裝置上,確定 PC 裝置已經開啟了 DHCP Server,配置方法請參照前文 Ubuntu 配置 DHCP server
- 給 ESP32 上電,并打開 PC 上的序列槽工具,此時序列槽會列印 log
- 用手機連接配接 ESP32 的 SSID(預設為 DEMO_TEST),成功後會在步驟 2 中列印 STA 連接配接成功的 Log
- 嘗試 ping 手機拿到的 IP 位址測試是否正常
五:核心代碼分析
5.1 事件處理
ESP32 代碼中将網絡中的各種狀态全部封裝成了事件,是以 Ethernet 轉 WiFi 的核心是網絡事件( Event )的處理;在本次 Demo 中,主要做了如下事件的處理:
static esp_err_t event_handler(void* ctx, system_event_t* event)
{
switch (event->event_id) {
case SYSTEM_EVENT_STA_START:
printf("SYSTEM_EVENT_STA_START\r\n");
break;
case SYSTEM_EVENT_STA_CONNECTED:
printf("SYSTEM_EVENT_STA_CONNECTED\r\n");
wifi_is_connected = true;
esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, (wifi_rxcb_t)tcpip_adapter_sta_input_eth_output);
對于 SYSTEM_EVENT_STA_START 事件,我們并沒有進行常見的 esp_wifi_connect() 操作,而是放在 Ethernet task 中進行,這麼做主要是為了擷取 PC 的 MAC 位址,然後将 sta 的 MAC 替換為 PC 的 MAC。
對于 SYSTEM_EVENT_STA_CONNECTED 事件,ESP32 連接配接上 AP 後,會進入此事件,在一般的網絡互動中,此時開始進行 DHCP 請求操作,但因為此時 ESP32 隻是作為一個管道,是以在這裡我們并不是将資料抛給 lwip 而是将資料“竊取”并轉發 給 Ethernet。
case SYSTEM_EVENT_STA_GOT_IP:
printf("SYSTEM_EVENT_STA_GOT_IP\r\n");
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
printf("SlYSTEM_EVENT_STA_DISCONNECTED\r\n");
wifi_is_connected = false;
esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, NULL);
esp_wifi_connect();
break;
對于事件 SYSTEM_EVENT_STA_GOT_IP ,好吧,這個事件在這個 Demo 是不會被觸發了,因為我們沒使用 lwip 中的 DHCP client 功能。
當事件 SYSTEM_EVENT_STA_DISCONNECTED 被觸發,我們要做的是讓 Ethernet 收到的資料将不會通過 WiFi 進行轉發,同時重連網絡。
case SYSTEM_EVENT_AP_STACONNECTED:
printf("SYSTEM_EVENT_AP_STACONNECTED\r\n");
wifi_is_connected = true;
esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_AP, (wifi_rxcb_t)tcpip_adapter_ap_input_eth_output);
break;
case SYSTEM_EVENT_AP_STADISCONNECTED:
printf("SYSTEM_EVENT_AP_STADISCONNECTED\r\n");
wifi_is_connected = false;
esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_AP, NULL);
break;
作為 AP 時事件處理和 STA 相同,差別是這裡設定為 AP 模式,而不是 STA 模式。
case SYSTEM_EVENT_ETH_CONNECTED:
printf("SYSTEM_EVENT_ETH_CONNECTED\r\n");
ethernet_is_connected = true;
break;
case SYSTEM_EVENT_ETH_DISCONNECTED:
printf("SYSTEM_EVENT_ETH_DISCONNECTED\r\n");
ethernet2wifi_mac_status_set(false);
ethernet_is_connected = false;
break;
Ethernet 事件的處理主要是探測以太網是否連接配接或者斷開,同時在斷開時,ethernet2wifi_mac_status_set 還要置為 false,以保證下次重新連接配接時重新替換 sta 的 mac 位址。
5.2 MAC位址設定
因為 Ethernet 轉 WiFi 牽涉到 3 個 MAC(PC、Etherner 和 STA/AP ),而網絡很多操作需要校驗 MAC,為了確定在網絡互動時 MAC 還能保持 PC 的 MAC,在本 Demo 中将 STA 的 MAC 設定為 PC 的 MAC。
if (!ethernet2wifi_mac_status_get()) {
memcpy(eth_mac, (uint8_t*)msg.buffer + 6, sizeof(eth_mac));
ESP_ERROR_CHECK(esp_wifi_start());
#ifdef CONFIG_ETH_TO_STATION_MODE
esp_wifi_set_mac(WIFI_IF_STA, eth_mac);
esp_wifi_connect();
#else
esp_wifi_set_mac(WIFI_IF_AP, eth_mac);
#endif
ethernet2wifi_mac_status_set(true);
}
在 SYSTEM_EVENT_ETH_CONNECTED 事件被觸發之後,PC 開始發送包含 MAC 位址的網絡資料,如下圖所示:
我們截取之後将 STA 的 MAC 位址設定為 PC 的 MAC 位址,此時再連接配接 AP,并将狀态置為 true,以避免下次 PC 發送資料時重複設定 MAC。
在連接配接到 AP 之後,PC 再進行 DHCP 請求時,sta 就會使用 PC的 MAC 位址和 AP 進行互動,以此保證正常通訊。
六:性能名額分析
我們使用了 iperf 對吞吐率進行了簡單的測試,在開放工作環境下,其 TCP 吞吐量穩定在 45Mbps 左右。但周圍環境會對 WiFi 吞吐量造成較大影響,在環境較差時,WiFi 吞吐量可能會下降。