4G PPPoS Internet forward or NAT to W5500 SPI Ethernet Port with DHCP
Posted: Sat Apr 13, 2024 1:20 pm
Good day,
I am trying to forward or NAT internet coming from a 4g module PPPoS (with ESP_MODEM component) to a SPI Ethernet module (W5500). So basically the ap_to_ppp example just instead of the wifi it should use the ethernet.
The follwoing works:
- Internet connection on ESP via 4G
- ap_to_ppp example works perfectly
- Internet connection on ESP via W5500 (did it to test the hardware setup), IP gets received from the DHCP Server in the Network
- ESP DHCP Server on W5500, the connected client can ping the IP address of the ESP W5500 interface
Not working:
when I swap the wifi hotspot on the ap_to_ppp example with the w5500 ethernet interface the client can't connect to internet (it can ping the esp W5500 interface though). I tried with manual DNS Settings on the client or ping an IP in the internet (8.8.8.8).
Does anyone have an idea what I am doing wrong?
Any help is much appreciated, I starting to get desperate here . Thank you very much!
I am trying to forward or NAT internet coming from a 4g module PPPoS (with ESP_MODEM component) to a SPI Ethernet module (W5500). So basically the ap_to_ppp example just instead of the wifi it should use the ethernet.
The follwoing works:
- Internet connection on ESP via 4G
- ap_to_ppp example works perfectly
- Internet connection on ESP via W5500 (did it to test the hardware setup), IP gets received from the DHCP Server in the Network
- ESP DHCP Server on W5500, the connected client can ping the IP address of the ESP W5500 interface
Not working:
when I swap the wifi hotspot on the ap_to_ppp example with the w5500 ethernet interface the client can't connect to internet (it can ping the esp W5500 interface though). I tried with manual DNS Settings on the client or ping an IP in the internet (8.8.8.8).
Does anyone have an idea what I am doing wrong?
Any help is much appreciated, I starting to get desperate here . Thank you very much!
Code: Select all
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/*
* softAP to PPPoS Example
*/
#include <string.h>
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_idf_version.h"
#include "nvs_flash.h"
#include "lwip/netif.h"
#include "lwip/lwip_napt.h"
#include "esp_modem_api.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "network_dce.h"
#include "esp_mac.h"
#include "dhcpserver/dhcpserver.h"
#include "driver/gpio.h"
#include <stdio.h>
#include "esp_eth.h"
#include "sdkconfig.h"
#include "driver/spi_master.h"
#include "ethernet_init.h"
#include "nvs.h"
#include "esp_netif.h"
#include "esp_event.h"
#include "ethernet_init.h"
#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID
#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD
#define EXAMPLE_ESP_WIFI_CHANNEL CONFIG_ESP_WIFI_CHANNEL
#define EXAMPLE_MAX_STA_CONN CONFIG_ESP_MAX_STA_CONN
esp_modem_dce_t *dce;
static const char *TAG = "ap_to_pppos";
static EventGroupHandle_t event_group = NULL;
static const int CONNECT_BIT = BIT0;
static const int DISCONNECT_BIT = BIT1;
static void on_ip_event(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data){
ESP_LOGD(TAG, "IP event! %" PRId32, event_id);
if (event_id == IP_EVENT_PPP_GOT_IP) {
esp_netif_dns_info_t dns_info;
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
esp_netif_t *netif = event->esp_netif;
ESP_LOGI(TAG, "Modem Connect to PPP Server");
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
ESP_LOGI(TAG, "IP : " IPSTR, IP2STR(&event->ip_info.ip));
ESP_LOGI(TAG, "Netmask : " IPSTR, IP2STR(&event->ip_info.netmask));
ESP_LOGI(TAG, "Gateway : " IPSTR, IP2STR(&event->ip_info.gw));
esp_netif_get_dns_info(netif, 0, &dns_info);
ESP_LOGI(TAG, "Name Server1: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
esp_netif_get_dns_info(netif, 1, &dns_info);
ESP_LOGI(TAG, "Name Server2: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
xEventGroupSetBits(event_group, CONNECT_BIT);
ESP_LOGI(TAG, "GOT ip event!!!");
} else if (event_id == IP_EVENT_PPP_LOST_IP) {
ESP_LOGI(TAG, "Modem Disconnect from PPP Server");
xEventGroupSetBits(event_group, DISCONNECT_BIT);
} else if (event_id == IP_EVENT_GOT_IP6) {
ESP_LOGI(TAG, "GOT IPv6 event!");
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
ESP_LOGI(TAG, "Got IPv6 address " IPV6STR, IPV62STR(event->ip6_info.ip));
}
}
static esp_err_t set_dhcps_dns(esp_netif_t *netif, uint32_t addr)
{
esp_netif_dns_info_t dns;
dns.ip.u_addr.ip4.addr = addr;
dns.ip.type = IPADDR_TYPE_V4;
dhcps_offer_t dhcps_dns_value = OFFER_DNS;
ESP_LOGW(TAG, "in function dhcp bevor important");
ESP_ERROR_CHECK(esp_netif_dhcps_option(netif, ESP_NETIF_OP_SET, ESP_NETIF_DOMAIN_NAME_SERVER, &dhcps_dns_value, sizeof(dhcps_dns_value)));
ESP_LOGW(TAG, "in function after dhcp options");
ESP_ERROR_CHECK(esp_netif_set_dns_info(netif, ESP_NETIF_DNS_MAIN, &dns));
ESP_LOGW(TAG, "in function dns set");
return ESP_OK;
}
static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data){
if (event_id == WIFI_EVENT_AP_STACONNECTED) {
wifi_event_ap_staconnected_t *event = (wifi_event_ap_staconnected_t *) event_data;
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
MAC2STR(event->mac), event->aid);
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
wifi_event_ap_stadisconnected_t *event = (wifi_event_ap_stadisconnected_t *) event_data;
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
MAC2STR(event->mac), event->aid);
}
}
void wifi_init_softap(void){
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&wifi_event_handler,
NULL,
NULL));
wifi_config_t wifi_config = {
.ap = {
.ssid = EXAMPLE_ESP_WIFI_SSID,
.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),
.channel = EXAMPLE_ESP_WIFI_CHANNEL,
.password = EXAMPLE_ESP_WIFI_PASS,
.max_connection = EXAMPLE_MAX_STA_CONN,
.authmode = WIFI_AUTH_WPA_WPA2_PSK
},
};
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
}
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d",
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL);
}
void start_network(void){
EventBits_t bits = 0;
while ((bits & CONNECT_BIT) == 0) {
if (!modem_check_sync()) {
ESP_LOGE(TAG, "Modem does not respond, maybe in DATA mode? ...exiting network mode");
modem_stop_network();
if (!modem_check_sync()) {
ESP_LOGE(TAG, "Modem does not respond to AT ...restarting");
modem_reset();
ESP_LOGI(TAG, "Restarted");
}
continue;
}
if (!modem_check_signal()) {
ESP_LOGI(TAG, "Poor signal ...will check after 5s");
vTaskDelay(pdMS_TO_TICKS(5000));
continue;
}
if (!modem_start_network()) {
ESP_LOGE(TAG, "Modem could not enter network mode ...will retry after 10s");
vTaskDelay(pdMS_TO_TICKS(10000));
continue;
}
bits = xEventGroupWaitBits(event_group, (DISCONNECT_BIT | CONNECT_BIT), pdTRUE, pdFALSE, pdMS_TO_TICKS(30000));
if (bits & DISCONNECT_BIT) {
ESP_LOGE(TAG, "Modem got disconnected ...retrying");
modem_stop_network();
}
}
}
/** Event handler for IP_EVENT_ETH_GOT_IP */
static void got_ip_event_handler(void *arg, esp_event_base_t event_base,int32_t event_id, void *event_data){
ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
const esp_netif_ip_info_t *ip_info = &event->ip_info;
ESP_LOGI(TAG, "Ethernet Got IP Address");
ESP_LOGI(TAG, "~~~~~~~~~~~");
ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip));
ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask));
ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw));
ESP_LOGI(TAG, "~~~~~~~~~~~");
}
void app_main(void){
gpio_config_t io_conf;
// GSM Reset Pin
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = (1ULL << 25);
io_conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
gpio_config(&io_conf);
gpio_set_level(25, 0);
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pin_bit_mask = (1ULL << 34);
io_conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
gpio_config(&io_conf);
ESP_LOGE(TAG, "GSM Reset On");
gpio_set_level(25, 1);
vTaskDelay(100 / portTICK_PERIOD_MS);
ESP_LOGE(TAG, "GSM Reset Off");
gpio_set_level(25, 0);
vTaskDelay(1000 / portTICK_PERIOD_MS);
while (1){
if (gpio_get_level (34) == 0){
vTaskDelay (1000/portTICK_PERIOD_MS);
}else{
vTaskDelay (2000/portTICK_PERIOD_MS);
break;
}
}
// Initialize NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
// Initialize esp_netif and default event loop
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
event_group = xEventGroupCreate();
// Initialize lwip network interface in PPP mode
esp_netif_config_t ppp_netif_config = ESP_NETIF_DEFAULT_PPP();
esp_netif_t *ppp_netif = esp_netif_new(&ppp_netif_config);
assert(ppp_netif);
// Initialize the PPP network and register for IP event
ESP_ERROR_CHECK(modem_init_network(ppp_netif));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, on_ip_event, NULL));
// Start the PPP network and wait for connection
modem_start_network();
EventBits_t bits;
do {
bits = xEventGroupWaitBits(event_group, (CONNECT_BIT | DISCONNECT_BIT), pdTRUE, pdFALSE, portMAX_DELAY);
if (bits & DISCONNECT_BIT) {
ESP_LOGW(TAG, "Modem got disconnected from the PPP server: retrying...");
modem_stop_network();
modem_start_network();
}
} while ((bits & CONNECT_BIT) == 0);
// ETH with DHCP - inet not working
uint8_t eth_port_cnt = 0;
esp_eth_handle_t *eth_handles;
ESP_ERROR_CHECK(ethernet_init_all(ð_handles, ð_port_cnt));
const esp_netif_ip_info_t my_ap_ip = {
.ip = { .addr = ESP_IP4TOADDR( 192, 168, 4, 1) },
.gw = { .addr = ESP_IP4TOADDR( 192, 168, 4, 1) },
.netmask = { .addr = ESP_IP4TOADDR( 255, 255, 255, 0) },
};
const esp_netif_inherent_config_t eth_behav_cfg = {
.get_ip_event = IP_EVENT_ETH_GOT_IP,
.lost_ip_event = 0,
.flags = ESP_NETIF_DHCP_SERVER | ESP_NETIF_FLAG_AUTOUP,
.ip_info = (esp_netif_ip_info_t*)& my_ap_ip,
.if_key = "ETHDHCPS",
.if_desc = "eth",
.route_prio = 50
};
esp_netif_config_t my_eth_cfg = { .base = ð_behav_cfg, .stack = ESP_NETIF_NETSTACK_DEFAULT_ETH };
esp_netif_t *eth_netif = esp_netif_new(& my_eth_cfg);
assert(eth_netif);
esp_netif_dns_info_t dns;
ESP_ERROR_CHECK(esp_netif_get_dns_info(ppp_netif, ESP_NETIF_DNS_MAIN, &dns));
set_dhcps_dns(eth_netif, dns.ip.u_addr.ip4.addr);
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[0])));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
// Start Ethernet driver state machine
for (int i = 0; i < eth_port_cnt; i++) {
ESP_ERROR_CHECK(esp_eth_start(eth_handles[i]));
}
/*
// Initialize the AP and setup the NAT
esp_netif_t *ap_netif = esp_netif_create_default_wifi_ap();
assert(ap_netif);
esp_netif_dns_info_t dns;
ESP_ERROR_CHECK(esp_netif_get_dns_info(ppp_netif, ESP_NETIF_DNS_MAIN, &dns));
set_dhcps_dns(ap_netif, dns.ip.u_addr.ip4.addr);
wifi_init_softap();
ip_napt_enable(_g_esp_netif_soft_ap_ip.ip.addr, 1);
*/
// if(esp_netif_is_netif_up(ap_netif) == ESP_OK){
if(esp_netif_is_netif_up(eth_netif) == ESP_OK){
ESP_LOGW(TAG, "alt_netif is up");
}else{
ESP_LOGW(TAG, "alt_netif is down");
}
if(esp_netif_is_netif_up(ppp_netif) == ESP_OK){
ESP_LOGW(TAG, "ppp_netif is up");
}else{
ESP_LOGW(TAG, "ppp_netif is down");
}
ESP_LOGW(TAG, "bevore napt");
vTaskDelay (5000/portTICK_PERIOD_MS);
ESP_LOGW(TAG, "afeter break");
// esp_netif_napt_enable(ap_netif);
ip_napt_enable(my_ap_ip.ip.addr, 1);
ESP_LOGW(TAG, "after everything");
// Provide a recovery if disconnection of some kind registered
while (true) {
bits = xEventGroupWaitBits(event_group, DISCONNECT_BIT, pdTRUE, pdFALSE, portMAX_DELAY);
if (bits & DISCONNECT_BIT) {
ESP_LOGW(TAG, "Modem got disconnected from the PPP server: restarting the network...");
modem_stop_network();
modem_start_network();
}
}
}