Chapter 77: IPv4 Networking Fundamentals
Chapter Objectives
Upon completing this chapter, you will be able to:
- Grasp the foundational concepts of Internet Protocol version 4 (IPv4) addressing.
- Understand the role of subnet masks, network addresses, and broadcast addresses.
- Differentiate between public and private IP addresses and the concept of Network Address Translation (NAT).
- Configure ESP32 devices to obtain IP addresses dynamically using DHCP.
- Configure ESP32 devices with static IP addresses.
- Explain the function of a default gateway and DNS servers in an IPv4 network.
- Troubleshoot common IP addressing and connectivity issues.
Introduction
In the vast landscape of interconnected devices that form the Internet and local networks, a fundamental mechanism is required to uniquely identify each device and enable communication between them. This mechanism is known as the Internet Protocol (IP). This chapter focuses on IPv4, the fourth version of the Internet Protocol, which has been the cornerstone of network communication for decades. Understanding IPv4 addressing, its components, and how devices acquire and use these addresses is crucial for any embedded systems developer working with networked devices like the ESP32. We will explore both dynamic (DHCP) and static IP configuration methods, essential for deploying ESP32 devices in various network environments.
Theory
1. What is Internet Protocol version 4 (IPv4)?
IPv4 is a connectionless protocol that operates at the Network Layer (Layer 3) of the OSI model. Its primary function is to provide a unique addressing system for devices on a network and to route packets of data between them. An IPv4 address is a 32-bit numerical label that uniquely identifies an interface on a network.
These 32 bits are typically represented in dotted-decimal notation, divided into four 8-bit segments (octets), each ranging from 0 to 255, separated by dots. For example, 192.168.1.100
is a common IPv4 address.
2. IP Address Classes (Historical Context)
Historically, IPv4 addresses were categorized into classes (A, B, C, D, E) based on the first few bits of the address. This classful addressing scheme defined fixed network and host portions.
- Class A: Designed for very large networks. First octet 1-126. (e.g.,
10.0.0.0/8
) - Class B: For medium to large networks. First octet 128-191. (e.g.,
172.16.0.0/16
) - Class C: For small networks. First octet 192-223. (e.g.,
192.168.1.0/24
)
While these classes still define certain address ranges, the rigid classful system led to inefficient address allocation and is largely superseded by CIDR.
Class | First Octet Range | Default Subnet Mask | Example Network Prefix | Designed For |
---|---|---|---|---|
Class A | 1 – 126 | 255.0.0.0 |
10.0.0.0/8 |
Very large networks (few networks, many hosts) |
Class B | 128 – 191 | 255.255.0.0 |
172.16.0.0/16 |
Medium to large networks |
Class C | 192 – 223 | 255.255.255.0 |
192.168.1.0/24 |
Small networks (many networks, few hosts) |
Class D | 224 – 239 | N/A (Multicast) | 224.0.0.1 |
Multicast groups |
Class E | 240 – 255 | N/A (Reserved) | N/A | Experimental/Reserved for future use |
3. Subnet Mask
An IP address alone isn’t enough to define a network. It must be combined with a subnet mask. A subnet mask is also a 32-bit number, represented in dotted-decimal notation, that divides an IP address into two parts:
- Network Portion: Identifies the specific network segment to which the device belongs. All devices on the same local network must share the same network portion.
- Host Portion: Uniquely identifies a specific device within that network segment.
The subnet mask works by having all 1
s in the bits corresponding to the network portion and all 0
s in the bits corresponding to the host portion. When you perform a bitwise AND operation between an IP address and its subnet mask, the result is the network address.
Example:
- IP Address:
192.168.1.100
(binary:11000000.10101000.00000001.01100100
) - Subnet Mask:
255.255.255.0
(binary:11111111.11111111.11111111.00000000
) - Network Address (AND operation):
192.168.1.0
(binary:11000000.10101000.00000001.00000000
)
%%{init: {"theme": "base", "themeVariables": {"primaryTextColor": "#333333", "lineColor": "#777777"}}}%% graph LR; subgraph "Example: 192.168.1.100 / 255.255.255.0" IP["<b>IP Address:</b><br>192.168.1.100<br><br>Binary:<br>11000000.10101000.00000001.01100100"] Mask["<b>Subnet Mask:</b><br>255.255.255.0<br><br>Binary:<br>11111111.11111111.11111111.00000000"] IP -- "& (Bitwise AND)" --> Result; Mask -- "& (Bitwise AND)" --> Result; Result["<b>Network Address:</b><br>192.168.1.0<br><br>Binary:<br>11000000.10101000.00000001.00000000"] subgraph "Interpretation" NetPortion["<b>Network Portion (from Mask)</b><br>First 3 octets (24 bits)<br>192.168.1"] HostPortion["<b>Host Portion (from Mask)</b><br>Last octet (8 bits)<br>.100"] end Result --> NetPortion; IP --> HostPortion; end style IP fill:#DBEAFE,stroke:#2563EB,stroke-width:1px,color:#1E40AF style Mask fill:#DBEAFE,stroke:#2563EB,stroke-width:1px,color:#1E40AF style Result fill:#D1FAE5,stroke:#059669,stroke-width:2px,color:#065F46 style NetPortion fill:#FEF3C7,stroke:#D97706,stroke-width:1px,color:#92400E style HostPortion fill:#FEF3C7,stroke:#D97706,stroke-width:1px,color:#92400E
4. Network Address and Broadcast Address
Within any given network segment defined by an IP address and subnet mask, two special addresses are reserved:
- Network Address: The first address in a subnet, where all host bits are
0
. It represents the network itself and cannot be assigned to a device. (e.g.,192.168.1.0
for a255.255.255.0
subnet). - Broadcast Address: The last address in a subnet, where all host bits are
1
. Packets sent to this address are delivered to all devices within that specific network segment. (e.g.,192.168.1.255
for a255.255.255.0
subnet).
5. CIDR (Classless Inter-Domain Routing)
CIDR replaced the classful addressing system to provide more flexible and efficient allocation of IP addresses. Instead of fixed octet boundaries, CIDR uses a prefix-length notation (e.g., /24
, /16
) appended to the IP address. This prefix length indicates the number of bits in the network portion of the address. The remaining bits are for the host portion.
Example:
192.168.1.0/24
: This means the first 24 bits are the network portion, and the last 8 bits are for hosts. This is equivalent to a255.255.255.0
subnet mask.10.0.0.0/8
: The first 8 bits are the network portion. Equivalent to255.0.0.0
.
%%{init: {"theme": "base", "themeVariables": {"primaryTextColor": "#333333", "lineColor": "#777777"}}}%% graph LR; title["CIDR Notation: Network Prefix Length"] subgraph "Example 1: 192.168.1.0/24" direction LR N1["<b>Network: 24 bits</b><br>192.168.1"] H1["<b>Host: 8 bits</b><br>(254 usable IPs)"] N1 --- H1; Mask1["(Subnet Mask: 255.255.255.0)"] end subgraph "Example 2: 172.16.0.0/16" direction LR N2["<b>Network: 16 bits</b><br>172.16"] H2["<b>Host: 16 bits</b><br>(65,534 usable IPs)"] N2 --- H2; Mask2["(Subnet Mask: 255.255.0.0)"] end subgraph "Example 3: 10.0.0.0/8" direction LR N3["<b>Network: 8 bits</b><br>10"] H3["<b>Host: 24 bits</b><br>(16,777,214 usable IPs)"] N3 --- H3; Mask3["(Subnet Mask: 255.0.0.0)"] end style title fill:#EDE9FE,stroke:#5B21B6,stroke-width:2px,color:#5B21B6 style N1 fill:#DBEAFE,stroke:#2563EB,stroke-width:1px,color:#1E40AF style H1 fill:#FEF3C7,stroke:#D97706,stroke-width:1px,color:#92400E style N2 fill:#DBEAFE,stroke:#2563EB,stroke-width:1px,color:#1E40AF style H2 fill:#FEF3C7,stroke:#D97706,stroke-width:1px,color:#92400E style N3 fill:#DBEAFE,stroke:#2563EB,stroke-width:1px,color:#1E40AF style H3 fill:#FEF3C7,stroke:#D97706,stroke-width:1px,color:#92400E style Mask1 fill:#FEE2E2,stroke:#DC2626,stroke-width:1px,color:#991B1B style Mask2 fill:#FEE2E2,stroke:#DC2626,stroke-width:1px,color:#991B1B style Mask3 fill:#FEE2E2,stroke:#DC2626,stroke-width:1px,color:#991B1B
CIDR allows for the creation of subnets of varying sizes, optimizing IP address usage.
6. Private vs. Public IP Addresses and NAT
To conserve the limited supply of IPv4 addresses and enhance security, IP addresses are categorized as either public or private:
- Public IP Addresses: These are globally unique and routable on the Internet. Every device directly connected to the Internet must have a public IP address.
- Private IP Addresses: These are reserved for use within private networks (e.g., your home or office LAN) and are not routable on the Internet. They can be reused in different private networks.
Common Private IP Address Ranges:
Private Address Range (CIDR) | Full Range | Typical Use / Class Association (Historical) |
---|---|---|
10.0.0.0/8 |
10.0.0.0 to 10.255.255.255 |
Large private networks (often in enterprises); historically a single Class A network. |
172.16.0.0/12 |
172.16.0.0 to 172.31.255.255 |
Medium-sized private networks; historically 16 contiguous Class B networks. |
192.168.0.0/16 |
192.168.0.0 to 192.168.255.255 |
Small private networks (common for home and small office routers); historically 256 contiguous Class C networks. |
To allow devices with private IP addresses to access the Internet, Network Address Translation (NAT) is used. A router performs NAT by translating private IP addresses of devices on the local network to a single public IP address when communicating with the Internet, and vice-versa for incoming traffic.
graph TD subgraph LAN["Private Network (LAN)"] ESP32["ESP32<br/>192.168.1.101<br/>(Private IP)"] Laptop["Laptop<br/>192.168.1.102<br/>(Private IP)"] Phone["Phone<br/>192.168.1.103<br/>(Private IP)"] end Router["Router / NAT Device<br/>LAN IP: 192.168.1.1<br/>WAN IP: 203.0.113.45<br/>(Public IP)"] subgraph Internet["Internet"] WebServer["Web Server<br/>93.184.216.34<br/>(Public IP)"] end %% Connections ESP32 -.-> Router Laptop -.-> Router Phone -.-> Router Router -.-> WebServer %% Request flow (blue arrows) ESP32 -->|"1- Request from<br/>192.168.1.101:PortA"| Router Router -->|"2- NAT Translation<br/>192.168.1.101:PortA → 203.0.113.45:PortX<br/>To 93.184.216.34"| WebServer %% Response flow (green arrows) WebServer -->|"3- Response from<br/>93.184.216.34"| Router Router -->|"4- NAT Translation<br/>203.0.113.45:PortX → 192.168.1.101:PortA<br/>To 192.168.1.101"| ESP32 %% Styling classDef lanDevice fill:#DBEAFE,stroke:#2563EB,stroke-width:2px classDef router fill:#FEF3C7,stroke:#D97706,stroke-width:2px classDef internetDevice fill:#D1FAE5,stroke:#059669,stroke-width:2px classDef lanArea fill:#E0F2FE,stroke:#A5D8FF classDef internetArea fill:#E0F2F1,stroke:#A7D7C5 class ESP32,Laptop,Phone lanDevice class Router router class WebServer internetDevice
7. DHCP (Dynamic Host Configuration Protocol)
DHCP is a network protocol that enables a server to automatically assign IP addresses and other network configuration parameters (like subnet mask, default gateway, and DNS servers) to devices connected to a network. This eliminates the need for manual configuration, simplifying network management, especially in large networks.
- DHCP Client: The device requesting an IP address (e.g., ESP32).
- DHCP Server: The device providing IP addresses (e.g., a router).
%%{init: {"theme": "base", "themeVariables": {"primaryTextColor": "#333333", "lineColor": "#777777"}}}%% sequenceDiagram; participant Client as ESP32 (DHCP Client); participant Server as Router (DHCP Server); Client->>+Server: 1. DHCPDISCOVER (Broadcast)<br>"Anyone have an IP for me?"; Server->>-Client: 2. DHCPOFFER (Unicast or Broadcast)<br>"Here's an IP: 192.168.1.100"; Client->>+Server: 3. DHCPREQUEST (Broadcast)<br>"I'll take 192.168.1.100 from you, Router_MAC"; Server->>-Client: 4. DHCPACK (Unicast or Broadcast)<br>"OK, 192.168.1.100 is yours (lease time, gateway, DNS)"; Note right of Client: IP Address Acquired!
The process typically involves a DORA (Discover, Offer, Request, Acknowledge) sequence.
8. Static IP Configuration
Static IP configuration involves manually assigning a fixed IP address, subnet mask, default gateway, and DNS server addresses to a device. This method is used when:
- A device needs a consistent, unchanging IP address (e.g., a server, a network printer, or an embedded device that needs to be accessed reliably by other systems).
- No DHCP server is available on the network.
Feature | DHCP (Dynamic Host Configuration Protocol) | Static IP Configuration |
---|---|---|
IP Address Assignment | Automatic, by a DHCP server. | Manual, by an administrator on the device. |
Configuration Parameters | IP address, subnet mask, default gateway, DNS servers typically provided. | All parameters (IP, mask, gateway, DNS) must be manually entered. |
Ease of Management | Simpler for large networks; plug-and-play for clients. | Requires careful planning and record-keeping; prone to human error. |
IP Address Consistency | IP address can change (unless DHCP reservation is used). | IP address is fixed and predictable. |
Risk of IP Conflicts | Low, as DHCP server manages the IP pool. | Higher, if addresses are duplicated or misconfigured. |
Typical Use Cases | Client devices (laptops, phones, most IoT devices), temporary connections. | Servers, printers, network devices, specific embedded systems requiring a fixed address for access. |
ESP32 Implementation | Default for esp_netif_create_default_wifi_sta() or esp_netif_create_default_eth() . |
Requires stopping DHCP client (e.g., esp_netif_dhcpc_stop() ) and setting IP info (esp_netif_set_ip_info() ). |
Warning: When using static IP, ensure the chosen address is not already in use by another device on the network to avoid IP conflicts. Also, the static IP must be within the same subnet as other devices you wish to communicate with on the local network.
9. Default Gateway
The default gateway is the IP address of the router or device that connects your local network to other networks (including the Internet). When a device needs to send a packet to an IP address outside its local subnet, it forwards the packet to its default gateway. The gateway then handles the routing of that packet to its destination.
10. DNS (Domain Name System)
The DNS is a hierarchical and decentralized naming system for computers, services, or other resources connected to the Internet or a private network. It translates human-readable domain names (e.g., www.example.com
) into numerical IP addresses (e.g., 93.184.216.34
) that computers use to identify each other on the network. Without DNS, you would have to remember the IP addresses of all websites you want to visit.
Parameter | Example | Role / Function |
---|---|---|
IP Address | 192.168.1.100 |
Unique 32-bit numerical identifier for a device’s interface on a network. |
Subnet Mask | 255.255.255.0 (or /24 ) |
Divides the IP address into network and host portions. Defines the local network segment. |
Network Address | 192.168.1.0 |
The first address in a subnet, representing the network itself. Not assignable to devices. (Result of IP AND Mask). |
Broadcast Address | 192.168.1.255 |
The last address in a subnet. Packets sent here reach all devices on that local network segment. |
Default Gateway | 192.168.1.1 |
The IP address of the router that connects the local network to other networks (e.g., the Internet). |
DNS Server(s) | 8.8.8.8 (Primary)8.8.4.4 (Secondary) |
Translates human-readable domain names (e.g., www.google.com) into numerical IP addresses. |
11. ARP (Address Resolution Protocol)
ARP is a protocol used to resolve IP addresses to MAC (Media Access Control) addresses within a local network segment. When a device wants to send data to another device on the same local network, it first needs to know the destination’s MAC address. It sends an ARP request (a broadcast) asking “Who has this IP address? Tell me your MAC address.” The device with that IP address responds with its MAC address.
%%{init: {"theme": "base", "themeVariables": {"primaryTextColor": "#333333", "lineColor": "#777777"}}}%% sequenceDiagram; participant DeviceA as Device A (ESP32)<br>IP: 192.168.1.100<br>MAC: AA:AA:AA:AA:AA:AA; participant Network as Local Network Segment; participant DeviceB as Device B (Target)<br>IP: 192.168.1.105<br>MAC: BB:BB:BB:BB:BB:BB; Note over DeviceA: Wants to send data to 192.168.1.105.<br>Needs MAC address. DeviceA->>Network: 1. ARP Request (Broadcast)<br>"Who has IP 192.168.1.105?<br>Tell MAC AA:AA:AA:AA:AA:AA"; Network-->>DeviceB: ARP Request reaches all devices; Note over DeviceB: "That's my IP!"; DeviceB->>DeviceA: 2. ARP Reply (Unicast)<br>"IP 192.168.1.105 is at<br>MAC BB:BB:BB:BB:BB:BB"; Note over DeviceA: ARP cache updated:<br>192.168.1.105 -> BB:BB:BB:BB:BB:BB.<br>Can now send Ethernet frame.
Practical Examples
This example demonstrates how to configure an ESP32 for both DHCP and Static IP addressing, allowing you to switch between them via menuconfig
. It uses the Wi-Fi interface for simplicity, but the esp_netif
concepts are identical for Ethernet.
1. Project Setup
Create a new ESP-IDF project using VS Code. You can use the “ESP-IDF: New Project” command. Name it ipv4_config_example
.
2. main/ipv4_config_example_main.c
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "sdkconfig.h"
static const char *TAG = "IPV4_CONFIG";
// Event handler for Wi-Fi and IP events
static void event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
ESP_LOGI(TAG, "Wi-Fi STA started, connecting...");
esp_wifi_connect();
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
ESP_LOGI(TAG, "Wi-Fi STA disconnected, retrying connection...");
esp_wifi_connect(); // Retry connection
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
ESP_LOGI(TAG, "Got IP address: " 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));
}
}
void app_main(void)
{
// Initialize NVS (Non-Volatile Storage) for Wi-Fi configuration
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 TCP/IP stack
ESP_ERROR_CHECK(esp_netif_init());
// Create default event loop
ESP_ERROR_CHECK(esp_event_loop_create_default());
// Create Wi-Fi station interface
esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
assert(sta_netif);
// Register event handlers
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
// Initialize Wi-Fi
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
#if CONFIG_USE_STATIC_IP
ESP_LOGI(TAG, "Configuring static IP address.");
esp_netif_dhcpc_stop(sta_netif); // Stop DHCP client
esp_netif_ip_info_t ip_info;
// Set static IP, netmask, and gateway from menuconfig
IP4_ADDR(&ip_info.ip, CONFIG_STATIC_IP_ADDR_0, CONFIG_STATIC_IP_ADDR_1, CONFIG_STATIC_IP_ADDR_2, CONFIG_STATIC_IP_ADDR_3);
IP4_ADDR(&ip_info.netmask, CONFIG_STATIC_NETMASK_0, CONFIG_STATIC_NETMASK_1, CONFIG_STATIC_NETMASK_2, CONFIG_STATIC_NETMASK_3);
IP4_ADDR(&ip_info.gw, CONFIG_STATIC_GW_0, CONFIG_STATIC_GW_1, CONFIG_STATIC_GW_2, CONFIG_STATIC_GW_3);
ESP_ERROR_CHECK(esp_netif_set_ip_info(sta_netif, &ip_info));
// Optionally set static DNS servers
esp_netif_dns_info_t dns_info[2];
IP4_ADDR(&dns_info[0].ip.addr, CONFIG_STATIC_DNS1_ADDR_0, CONFIG_STATIC_DNS1_ADDR_1, CONFIG_STATIC_DNS1_ADDR_2, CONFIG_STATIC_DNS1_ADDR_3);
IP4_ADDR(&dns_info[1].ip.addr, CONFIG_STATIC_DNS2_ADDR_0, CONFIG_STATIC_DNS2_ADDR_1, CONFIG_STATIC_DNS2_ADDR_2, CONFIG_STATIC_DNS2_ADDR_3);
ESP_ERROR_CHECK(esp_netif_set_dns_info(sta_netif, ESP_NETIF_DNS_MAIN, &dns_info[0]));
ESP_ERROR_CHECK(esp_netif_set_dns_info(sta_netif, ESP_NETIF_DNS_BACKUP, &dns_info[1]));
#else // CONFIG_USE_DHCP
ESP_LOGI(TAG, "Configuring IP address via DHCP.");
// DHCP is enabled by default for esp_netif_create_default_wifi_sta()
#endif
// Configure Wi-Fi station mode
wifi_config_t wifi_config = {
.sta = {
.ssid = CONFIG_WIFI_SSID,
.password = CONFIG_WIFI_PASSWORD,
.threshold.authmode = WIFI_AUTH_WPA2_PSK,
.sae_pwe_h2e = WIFI_SAE_MODE_OWE, // For WPA3, if supported by AP
.sae_h2e_identifier = "",
},
};
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "Waiting for IP address...");
}
3. main/CMakeLists.txt
The default CMakeLists.txt
should be sufficient. Ensure idf_component_register
is present.
# In the main/CMakeLists.txt file
idf_component_register(SRCS "ipv4_config_example_main.c"
INCLUDE_DIRS ".")
4. main/Kconfig.projbuild
This file allows you to configure project-specific settings via idf.py menuconfig.
Create main/Kconfig.projbuild and add the following:
menu "Network Configuration"
config WIFI_SSID
string "Wi-Fi SSID"
default "YOUR_SSID"
help
SSID of your Wi-Fi network.
config WIFI_PASSWORD
string "Wi-Fi Password"
default "YOUR_PASSWORD"
help
Password of your Wi-Fi network.
config USE_STATIC_IP
bool "Use Static IP Address"
default n
help
Enable to use a static IP address instead of DHCP.
if USE_STATIC_IP
menu "Static IP Configuration"
config STATIC_IP_ADDR_0
int "Static IP Address Octet 0"
range 0 255
default 192
config STATIC_IP_ADDR_1
int "Static IP Address Octet 1"
range 0 255
default 168
config STATIC_IP_ADDR_2
int "Static IP Address Octet 2"
range 0 255
default 1
config STATIC_IP_ADDR_3
int "Static IP Address Octet 3"
range 0 255
default 100
config STATIC_NETMASK_0
int "Static Netmask Octet 0"
range 0 255
default 255
config STATIC_NETMASK_1
int "Static Netmask Octet 1"
range 0 255
default 255
config STATIC_NETMASK_2
int "Static Netmask Octet 2"
range 0 255
default 255
config STATIC_NETMASK_3
int "Static Netmask Octet 3"
range 0 255
default 0
config STATIC_GW_0
int "Static Gateway Octet 0"
range 0 255
default 192
config STATIC_GW_1
int "Static Gateway Octet 1"
range 0 255
default 168
config STATIC_GW_2
int "Static Gateway Octet 2"
range 0 255
default 1
config STATIC_GW_3
int "Static Gateway Octet 3"
range 0 255
default 1
config STATIC_DNS1_ADDR_0
int "Primary DNS Server Octet 0"
range 0 255
default 8
config STATIC_DNS1_ADDR_1
int "Primary DNS Server Octet 1"
range 0 255
default 8
config STATIC_DNS1_ADDR_2
int "Primary DNS Server Octet 2"
range 0 255
default 8
config STATIC_DNS1_ADDR_3
int "Primary DNS Server Octet 3"
range 0 255
default 8
config STATIC_DNS2_ADDR_0
int "Secondary DNS Server Octet 0"
range 0 255
default 8
config STATIC_DNS2_ADDR_1
int "Secondary DNS Server Octet 1"
range 0 255
default 8
config STATIC_DNS2_ADDR_2
int "Secondary DNS Server Octet 2"
range 0 255
default 4
config STATIC_DNS2_ADDR_3
int "Secondary DNS Server Octet 3"
range 0 255
default 4
endmenu # Static IP Configuration
endif # USE_STATIC_IP
endmenu # Network Configuration
5. Build Instructions
- Open VS Code: Open your
ipv4_config_example
project folder in VS Code. - Configure with
menuconfig
:- Press
Ctrl+Shift+P
(orCmd+Shift+P
on macOS) to open the command palette. - Type and select “ESP-IDF: SDK Configuration Editor (menuconfig)”.
- Navigate to “Network Configuration”.
- Enter your Wi-Fi SSID and Password.
- To use DHCP (default), ensure
Use Static IP Address
is unchecked. - To use Static IP, check
Use Static IP Address
and then configure the IP address, Netmask, Gateway, and DNS servers according to your network. - Save the configuration and exit
menuconfig
.
- Press
- Build the Project:
- Open the VS Code Terminal (
Terminal > New Terminal
). - Run
idf.py build
. This will compile the project.
- Open the VS Code Terminal (
6. Run/Flash/Observe Steps
- Connect Hardware:
- Connect your ESP32 development board to your computer via USB.
- Flash the Firmware:
- In the VS Code Terminal, run
idf.py flash
. This will erase the chip and flash your compiled firmware.
- In the VS Code Terminal, run
- Monitor Serial Output:
- After flashing, run
idf.py monitor
. This will open the serial monitor and display the logs from your ESP32.
- After flashing, run
Expected Output (DHCP):
I (XXX) IPV4_CONFIG: Waiting for IP address...
I (XXX) IPV4_CONFIG: Wi-Fi STA started, connecting...
I (XXX) IPV4_CONFIG: Got IP address: 192.168.1.105
I (XXX) IPV4_CONFIG: Netmask: 255.255.255.0
I (XXX) IPV4_CONFIG: Gateway: 192.168.1.1
Expected Output (Static IP):
I (XXX) IPV4_CONFIG: Configuring static IP address.
I (XXX) IPV4_CONFIG: Waiting for IP address...
I (XXX) IPV4_CONFIG: Wi-Fi STA started, connecting...
I (XXX) IPV4_CONFIG: Got IP address: 192.168.1.100
I (XXX) IPV4_CONFIG: Netmask: 255.255.255.0
I (XXX) IPV4_CONFIG: Gateway: 192.168.1.1
(Assuming you configured 192.168.1.100
as the static IP)
Variant Notes
The fundamental concepts of IPv4 networking, including IP addressing, subnet masks, gateways, DHCP, and DNS, are universal across all networking devices, including all ESP32 variants (ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6, ESP32-H2).
The ESP-IDF’s esp_netif
component provides a unified abstraction layer for network interfaces. Whether you are using Wi-Fi, Ethernet (with internal EMAC on ESP32 classic, or external SPI/SDIO controllers on other variants), or any other network interface, the API calls for configuring IP addresses (DHCP or static) and handling IP events remain consistent. The underlying hardware differences are handled by the specific Wi-Fi or Ethernet drivers, allowing your application code to interact with the network stack in a consistent manner. Therefore, no specific variant notes are required for this chapter on IPv4 fundamentals.
Common Mistakes & Troubleshooting Tips
Mistake / Issue | Symptom(s) | Troubleshooting / Solution |
---|---|---|
IP Address Conflicts (Static IP) | Device gets IP, but intermittent connectivity or other devices on network lose connection. Log messages may not indicate an error on ESP32. |
|
Incorrect Subnet Mask or Gateway (Static IP) | ESP32 gets IP but cannot communicate with devices outside its local subnet (e.g., internet) or sometimes even locally. Ping to gateway fails. |
|
DHCP Server Unavailability / Misconfiguration | ESP32 fails to get an IP address. IP_EVENT_STA_GOT_IP (or IP_EVENT_ETH_GOT_IP ) never triggers. Device keeps trying to connect. |
|
Underlying Connectivity Issues (Wi-Fi/Ethernet) | No IP address obtained. Symptoms might seem like IP issues, but the root cause is lower level. |
|
DNS Resolution Failures | ESP32 has an IP and can ping other IP addresses (e.g., 8.8.8.8 ), but cannot access websites by domain name (e.g., www.google.com ). HTTP client errors related to host not found. |
|
Firewall Blocking ESP32 | ESP32 connects to Wi-Fi/Ethernet, gets an IP, but cannot access local network resources or internet. Pings to gateway or other local devices might fail. |
|
Exercises
Exercise 1: Basic Ping Utility
Modify the provided example to include a simple ping functionality. Once the ESP32 obtains an IP address (either via DHCP or static), have it periodically ping a well-known public IP address (e.g., Google’s DNS 8.8.8.8
) and report the success or failure.
Steps:
- Include Ping Headers: Add
#include "lwip/sockets.h"
and#include "lwip/inet.h"
for socket operations. - Create Ping Task: Implement a FreeRTOS task (
ping_task
) that usessocket()
,sendto()
, andrecvfrom()
to send ICMP echo requests and receive replies. You’ll need to construct simple ICMP packets. - Trigger Ping: In the
event_handler
forIP_EVENT_STA_GOT_IP
, create and start theping_task
. - Log Results: Print whether the ping was successful and any round-trip time.
Exercise 2: Display Network Information on Boot
Enhance the application to display all obtained network information (IP address, netmask, gateway, and DNS servers) immediately after the IP_EVENT_STA_GOT_IP
event, and also after a short delay (e.g., 5 seconds) to demonstrate persistence.
Steps:
- Retrieve DNS Info: After
IP_EVENT_STA_GOT_IP
, useesp_netif_get_dns_info()
to retrieve the configured DNS servers. - Print All Info: Extend the
ip_event_handler
to print the primary and secondary DNS server IP addresses in addition to the existing IP, netmask, and gateway. - Delayed Print Task: Create a separate FreeRTOS task that waits for a few seconds using
vTaskDelay
and then callsesp_netif_get_ip_info()
andesp_netif_get_dns_info()
again to re-print the network details. Start this task after the initial IP event.
Exercise 3: Web Server with IP Display
Create a very simple HTTP web server on the ESP32 that, when accessed from a web browser, displays the ESP32’s currently assigned IP address, subnet mask, and gateway.
Steps:
- Include HTTP Server: Add
#include "esp_http_server.h"
and related headers. - Create HTTP Handler: Implement an HTTP GET handler function that generates an HTML page containing the network information. You’ll need to retrieve the IP info within this handler.
- Start HTTP Server: In the
event_handler
forIP_EVENT_STA_GOT_IP
, initialize and start the HTTP server usinghttpd_start()
. - Register URI Handler: Register your GET handler for the root path (
/
). - Test: After flashing, open a web browser and navigate to the ESP32’s IP address (e.g.,
http://192.168.1.100
). Verify the displayed network information matches the serial monitor output.
Summary
- IPv4 uses 32-bit addresses, commonly represented in dotted-decimal notation (e.g.,
192.168.1.100
), to uniquely identify devices on a network. - A subnet mask (e.g.,
255.255.255.0
or/24
in CIDR) divides an IP address into a network portion and a host portion. - The network address is the first address in a subnet, and the broadcast address is the last; both are reserved.
- Private IP addresses are used within local networks and are translated to public IP addresses by NAT for Internet access.
- DHCP (Dynamic Host Configuration Protocol) automatically assigns IP addresses and network settings, simplifying network management.
- Static IP configuration involves manually assigning fixed IP addresses, suitable for devices requiring consistent access.
- The default gateway is the router’s IP address, used for routing traffic outside the local network.
- DNS (Domain Name System) translates human-readable domain names into numerical IP addresses.
- ARP (Address Resolution Protocol) resolves IP addresses to MAC addresses on a local network segment.
- The ESP-IDF
esp_netif
component provides a consistent API for IP configuration across all ESP32 variants and network interfaces (Wi-Fi, Ethernet).
Further Reading
- Espressif ESP-IDF Programming Guide – Network Interfaces (esp_netif): https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_netif.html
- Espressif ESP-IDF Programming Guide – Wi-Fi Station Mode: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html#esp-wifi-sta-mode
- RFC 791 – Internet Protocol: https://datatracker.ietf.org/doc/html/rfc791
- RFC 1918 – Address Allocation for Private Internets: https://datatracker.ietf.org/doc/html/rfc1918
- Wikipedia – IPv4: https://en.wikipedia.org/wiki/IPv4
