# ESP-NETIF Programmers Manual

[中文]

## Configure IP, Gateway, and DNS

Typically, IP addresses -- including the gateway, network mask, and DNS servers -- are automatically obtained through a DHCP server or Router Advertisement services. Notifications regarding IP address assignments are received via the `IP_EVENT`, which provides the relevant IP address information. You can also retrieve the current address details using the function `esp_netif_get_ip_info()`. This function returns a structure, `esp_netif_ip_info_t`, that contains the IPv4 address of the network interface, along with its network mask and gateway address. Similarly, the function `esp_netif_get_all_ip6()` can be used to obtain all IPv6 addresses associated with the interface.

In order to configure static IP addresses and DNS servers, it's necessary to disable or stop DHCP client (which is enabled by default on some network interfaces, such as the default Ethernet, or the default WiFi station). Please refer to the example /protocols/static_ip for more details.

To set IPv4 address, you can use `esp_netif_set_ip_info()`. For IPv6, these two functions can be used for adding or removing addresses: `esp_netif_add_ip6_address()`, `esp_netif_remove_ip6_address()`. To configure DNS servers, please use `esp_netif_set_dns_info()` API.

## Configure DHCP options

Some network interfaces are pre-configured to use either a DHCP client (commonly for Ethernet interfaces) or a DHCP server (typically for Wi-Fi software access points). When manually creating a custom network interface, the configuration flags `esp_netif_flags_t` are used to specify the behavior of the interface. Adding `ESP_NETIF_DHCP_CLIENT` or `ESP_NETIF_DHCP_SERVER` will enable the DHCP client or server, respectively.

It is important to note that these two options are mutually exclusive and cannot be changed at runtime. If an interface is configured as a DHCP client upon creation, it cannot later be used as a DHCP server. The only option is to destroy the existing network interface and create a new one with the desired configuration.

To set or get a specific DHCP option, the common type `esp_netif_dhcp_option_id_t` is used for both the DHCP server and client. However, not all options are supported for both. For details on the available options for the DHCP client, refer to the API documentation for `esp_netif_dhcpc_option()`. Similarly, for the options available for the DHCP server, consult the API documentation for `esp_netif_dhcps_option()`.

## SNTP Service

A brief introduction to SNTP, its initialization code, and basic modes can be found in Section SNTP Time Synchronization in System Time.

This section provides more details on specific use cases for the SNTP service, such as using statically configured servers, DHCP-provided servers, or both. The workflow is typically straightforward:

1. Initialize and configure the service using `esp_netif_sntp_init()`. This function can only be called once unless the SNTP service has been destroyed using `esp_netif_sntp_deinit()`.

2. Start the service with `esp_netif_sntp_start()`. This step is not necessary if the service was auto-started in the previous step (default behavior). However, it can be useful to start the service explicitly after connecting if DHCP-provided NTP servers are being used. Note that this option needs to be enabled before connecting, but the SNTP service should only be started afterward.

3. Wait for the system time to synchronize using `esp_netif_sntp_sync_wait()` (if required).

4. Stop and destroy the service using `esp_netif_sntp_deinit()`.

### Basic Mode with Statically Defined Server(s)

Initialize the module with the default configuration after connecting to the network. Note that it is possible to provide multiple NTP servers in the configuration struct:

    esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG_MULTIPLE(2,
                               ESP_SNTP_SERVER_LIST("time.windows.com", "pool.ntp.org" ) );
    esp_netif_sntp_init(&config);

Note

If you want to configure multiple SNTP servers, update the lwIP configuration option CONFIG_LWIP_SNTP_MAX_SERVERS.

### Use DHCP-Obtained SNTP Server(s)

First, you need to enable the lwIP configuration option CONFIG_LWIP_DHCP_GET_NTP_SRV. Then, initialize the SNTP module with the DHCP option, without specifying an NTP server.

    esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG_MULTIPLE(0, {} );
    config.start = false;                       // start the SNTP service explicitly
    config.server_from_dhcp = true;             // accept the NTP offer from the DHCP server
    esp_netif_sntp_init(&config);

Once connected, you can start the service using:

    esp_netif_sntp_start();

Note

It is also possible to start the service during initialization (with the default `config.start=true`). However, this may cause the initial SNTP request to fail since you are not connected yet, which could result in a back-off period for subsequent requests.

### Use Both Static and Dynamic Servers

This scenario is similar to using DHCP-provided SNTP servers. However, in this configuration, you need to ensure that the static server configuration is refreshed when obtaining NTP servers via DHCP. The underlying lwIP code removes the existing list of NTP servers when DHCP-provided information is accepted. Therefore, the ESP-NETIF SNTP module retains the statically configured server(s) and appends them to the list after obtaining a DHCP lease.

The typical configuration now looks as per below, providing the specific `IP_EVENT` to update the config and index of the first server to reconfigure (for example setting `config.index_of_first_server=1` would keep the DHCP provided server at index 0, and the statically configured server at index 1).

    esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("pool.ntp.org");
    config.start = false;                       // start the SNTP service explicitly (after connecting)
    config.server_from_dhcp = true;             // accept the NTP offers from DHCP server
    config.renew_servers_after_new_IP = true;   // let esp-netif update the configured SNTP server(s) after receiving the DHCP lease
    config.index_of_first_server = 1;           // updates from server num 1, leaving server 0 (from DHCP) intact
    config.ip_event_to_renew = IP_EVENT_STA_GOT_IP;  // IP event on which you refresh your configuration

Then you start the service normally with `esp_netif_sntp_start()`.

## L2 TAP Interface Usage

The ESP-NETIF L2 TAP interface is used to access Data Link Layer, please refer to the ESP-NETIF Architecture diagram to see how L2 TAP interacts with ESP-NETIF and application.

From a user perspective, the ESP-NETIF L2 TAP interface is accessed using file descriptors of VFS, which provides file-like interfacing (using functions like `open()`, `read()`, `write()`, etc). To learn more, refer to Virtual Filesystem Component.

There is only one ESP-NETIF L2 TAP interface device (path name) available, but you can open multiple file descriptors from it, each with its own unique configuration. Think of the ESP-NETIF L2 TAP interface as a general gateway to the Layer 2 network infrastructure. The key point is that each file descriptor can be individually configured, which is crucial. For example, a file descriptor can be set up to access a specific network interface identified by if_key (like ETH_DEF) and to filter specific types of frames (such as filtering by Ethernet type for IEEE 802.3 frames).

This filtering is essential because the ESP-NETIF L2 TAP works alongside the IP stack, meaning that IP-related traffic (like IP, ARP, etc.) should not be sent directly to your application. Although this option is still possible, it is not recommended in standard use cases. The benefit of filtering is that it allows your application to receive only the frame types it cares about, while other traffic is either routed to different L2 TAP file descriptors or handled by the IP stack.

### Initialization

To be able to use the ESP-NETIF L2 TAP interface, it needs to be enabled in Kconfig by CONFIG_ESP_NETIF_L2_TAP first and then registered by `esp_vfs_l2tap_intf_register()` prior usage of any VFS function.

### `open()`

Once the ESP-NETIF L2 TAP is registered, it can be opened at path name "/dev/net/tap". The same path name can be opened multiple times up to CONFIG_ESP_NETIF_L2_TAP_MAX_FDS and multiple file descriptors with a different configuration may access the Data Link Layer frames.

The ESP-NETIF L2 TAP can be opened with the `O_NONBLOCK` file status flag to make sure the `read()` does not block. Note that the `write()` may block in the current implementation when accessing a Network interface since it is a shared resource among multiple ESP-NETIF L2 TAP file descriptors and IP stack, and there is currently no queuing mechanism deployed. The file status flag can be retrieved and modified using `fcntl()`.

On success, `open()` returns the new file descriptor (a nonnegative integer). On error, -1 is returned, and `errno` is set to indicate the error.

### `ioctl()`

The newly opened ESP-NETIF L2 TAP file descriptor needs to be configured prior to its usage since it is not bounded to any specific Network Interface and no frame type filter is configured. The following configuration options are available to do so:

> - `L2TAP_S_INTF_DEVICE` - bounds the file descriptor to a specific Network Interface that is identified by its `if_key`. ESP-NETIF Network Interface `if_key` is passed to `ioctl()` as the third parameter. Note that default Network Interfaces `if_key`'s used in ESP-IDF can be found in esp_netif/include/esp_netif_defaults.h.

> - `L2TAP_S_DEVICE_DRV_HNDL` - is another way to bound the file descriptor to a specific Network Interface. In this case, the Network interface is identified directly by IO Driver handle (e.g., `esp_eth_handle_t` in case of Ethernet). The IO Driver handle is passed to `ioctl()` as the third parameter.

> - `L2TAP_S_RCV_FILTER` - sets the filter to frames with the type to be passed to the file descriptor. In the case of Ethernet frames, the frames are to be filtered based on the Length and Ethernet type field. In case the filter value is set less than or equal to 0x05DC, the Ethernet type field is considered to represent IEEE802.3 Length Field, and all frames with values in interval <0, 0x05DC> at that field are passed to the file descriptor. The IEEE802.2 logical link control (LLC) resolution is then expected to be performed by the user's application. In case the filter value is set greater than 0x05DC, the Ethernet type field is considered to represent protocol identification and only frames that are equal to the set value are to be passed to the file descriptor.

> - `L2TAP_S_TIMESTAMP_EN` - enables the hardware Time Stamping processing inside the file descriptor. The Time Stamps are retrieved to user space by using Extended Buffer mechanism when accessing the file descriptor by `read()` and `write()` functions. Hardware time stamping needs to be supported by target and needs to be enabled in IO Driver to this option work as expected.

All above-set configuration options have a getter counterpart option to read the current settings except for `L2TAP_S_TIMESTAMP_EN`.

Warning

The file descriptor needs to be firstly bounded to a specific Network Interface by `L2TAP_S_INTF_DEVICE` or `L2TAP_S_DEVICE_DRV_HNDL` to make `L2TAP_S_RCV_FILTER` option available.

Note

VLAN-tagged frames are currently not recognized. If the user needs to process VLAN-tagged frames, they need a set filter to be equal to the VLAN tag (i.e., 0x8100 or 0x88A8) and process the VLAN-tagged frames in the user application.

Note

`L2TAP_S_DEVICE_DRV_HNDL` is particularly useful when the user's application does not require the usage of an IP stack and so ESP-NETIF is not required to be initialized too. As a result, Network Interface cannot be identified by its `if_key` and hence it needs to be identified directly by its IO Driver handle.

On success, `ioctl()` returns 0. On error, -1 is returned, and `errno` is set to indicate the error.
* EBADF - not a valid file descriptor.
* EACCES - options change is denied in this state (e.g., file descriptor has not been bounded to Network interface yet).
* EINVAL - invalid configuration argument. Ethernet type filter is already used by other file descriptors on that same Network interface.
* ENODEV - no such Network Interface which is tried to be assigned to the file descriptor exists.
* ENOSYS - unsupported operation, passed configuration option does not exist.

### `fcntl()`

The `fcntl()` is used to manipulate with properties of opened ESP-NETIF L2 TAP file descriptor.

The following commands manipulate the status flags associated with the file descriptor:

> - `F_GETFD` - the function returns the file descriptor flags, and the third argument is ignored.

> - `F_SETFD` - sets the file descriptor flags to the value specified by the third argument. Zero is returned.

On success, `fcntl()` returns 0. On error, -1 is returned, and `errno` is set to indicate the error.
* EBADF - not a valid file descriptor.
* ENOSYS - unsupported command.

### `read()`

Opened and configured ESP-NETIF L2 TAP file descriptor can be accessed by `read()` to get inbound frames. The read operation can be either blocking or non-blocking based on the actual state of the `O_NONBLOCK` file status flag. When the file status flag is set to blocking, the read operation waits until a frame is received and the context is switched to other tasks. When the file status flag is set to non-blocking, the read operation returns immediately. In such case, either a frame is returned if it was already queued or the function indicates the queue is empty. The number of queued frames associated with one file descriptor is limited by CONFIG_ESP_NETIF_L2_TAP_RX_QUEUE_SIZE Kconfig option. Once the number of queued frames reached a configured threshold, the newly arrived frames are dropped until the queue has enough room to accept incoming traffic (Tail Drop queue management).

On success, `read()` returns the number of bytes read. Zero is returned when the size of the destination buffer is 0. On error, -1 is returned, and `errno` is set to indicate the error.
* EBADF - not a valid file descriptor.
* EAGAIN - the file descriptor has been marked non-blocking (`O_NONBLOCK`), and the read would block.

Note

ESP-NETIF L2 TAP `read()` implementation extends the standard and offers Extended Buffer mechanism to retrieve additional information about received frame. See Extended Buffer section for more information.

### `write()`

A raw Data Link Layer frame can be sent to Network Interface via opened and configured ESP-NETIF L2 TAP file descriptor. The user's application is responsible to construct the whole frame except for fields which are added automatically by the physical interface device. The following fields need to be constructed by the user's application in case of an Ethernet link: source/destination MAC addresses, Ethernet type, actual protocol header, and user data. The length of these fields is as follows:

In other words, there is no additional frame processing performed by the ESP-NETIF L2 TAP interface. It only checks the Ethernet type of the frame is the same as the filter configured in the file descriptor. If the Ethernet type is different, an error is returned and the frame is not sent. Note that the `write()` may block in the current implementation when accessing a Network interface since it is a shared resource among multiple ESP-NETIF L2 TAP file descriptors and IP stack, and there is currently no queuing mechanism deployed.

On success, `write()` returns the number of bytes written. Zero is returned when the size of the input buffer is 0. On error, -1 is returned, and `errno` is set to indicate the error.
* EBADF - not a valid file descriptor.
* EBADMSG - The Ethernet type of the frame is different from the file descriptor configured filter.
* EIO - Network interface not available or busy.

Note

ESP-NETIF L2 TAP `write()` implementation extends the standard and offers Extended Buffer mechanism to retrieve additional information about transmitted frame. See Extended Buffer section for more information.

### `close()`

Opened ESP-NETIF L2 TAP file descriptor can be closed by the `close()` to free its allocated resources. The ESP-NETIF L2 TAP implementation of `close()` may block. On the other hand, it is thread-safe and can be called from a different task than the file descriptor is actually used. If such a situation occurs and one task is blocked in the I/O operation and another task tries to close the file descriptor, the first task is unblocked. The first's task `read` operation then ends with returning 0 bytes was read.

On success, `close()` returns zero. On error, -1 is returned, and `errno` is set to indicate the error.
* EBADF - not a valid file descriptor.

### `select()`

Select is used in a standard way, just CONFIG_VFS_SUPPORT_SELECT needs to be enabled to make the `select()` function available.

### Extended Buffer

The Extended Buffer is ESP-NETIF L2 TAP's mechanism of how to retrieve additional information about transmitted or received IO frame via `write()` or `read()` functions. The Extended Buffer must be only used when specific functionality is enabled in the file descriptor (such as `L2TAP_S_TIMESTAMP_EN`) and you want to access the additional data (such as Time Stamp) or control the frame processing.

The Extended Buffer is a structure with fields which serve as arguments to drive underlying functionality in the ESP-NETIF L2 TAP file descriptor. The structure is defined as follows:

    typedef struct {
        size_t info_recs_len;       /*!< Length of Information Records buffer */
        void *info_recs_buff;       /*!< Buffer holding extended information (IRECs) related to IO frames */
        size_t buff_len;            /*!< Length of the actual IO Frame buffer */
        void *buff;                 /*!< Pointer to the IO Frame buffer */
    } l2tap_extended_buff_t;

One Extended buffer may hold multiple Information Records (IRECs). These are variable data typed (and sized) records which may hold any datatype of additional information associated with the IO frame. The IREC structure is defined as follows:

    typedef struct
    {
        size_t len;                         /*!< Length of the record including header and data*/
        l2tap_irec_type_t type;             /*!< Type of the record */
        alignas(long long) uint8_t data[];  /*!< Records Data aligned to double word */
    } l2tap_irec_hdr_t;

Currently implement and used IREC data types are defined in `l2tap_irec_type_t`.

Since the flexible array to hold data is used, proper memory alignment of multiple IRECs in the records buffer is required to correctly access memory. Improper alignment can result in slower memory access due to misaligned read/write operations, or in the worst case, cause undefined behavior on certain architectures. Therefore it is strictly recommended to use the below macros when manipulating with IRECs:

- `L2TAP_IREC_SPACE()` - determines the space required for an IREC, ensuring that it is properly aligned.

- `L2TAP_IREC_LEN()` - calculates the total length of one IREC, including the header and the data section of the record.

- `L2TAP_IREC_FIRST()` - retrieves the first IREC from the `l2tap_extended_buff_t::info_recs_buff` pool of Extended Buffer. If the `l2tap_extended_buff_t::info_recs_len` is smaller than the size of a record header, it returns NULL.

- `L2TAP_IREC_NEXT()` - retrieves the next IREC in the Extended Buffer after the current record. If the current record is NULL, it returns the first record.

#### Extended Buffer Usage

Prior any Extended Buffer IO operation (either `write()` or `read()`), you first need to fully populate the Extended Buffer and its IREC fields. For example, when you want to retrieve Time Stamp, you need to set type of the IREC to `L2TAP_IREC_TIME_STAMP` and configure appropriate length. If you don't set the type correctly, the frame is still received or transmitted but information to be retrieved is lost. Similarly, when the IREC length is less than expected length, the frame is still received or transmitted but the type of affected IREC is marked to `L2TAP_IREC_INVALID` by the ESP-NETIF L2 TAP and information to be retrieved is lost.

When accessing the file descriptor using Extended Buffer, `size` parameter of `write()` or `read()` function must be set equal to `0`. Failing to do so (i.e. accessing such file descriptor in a standard way with `size` parameter set to data length) will result in an -1 error and `errno` set to EINVAL.

    // wrap "Info Records Buffer" into union to ensure proper alignment of data (this is typically needed when
    // accessing double word variables or structs containing double word variables)
    union {
        uint8_t info_recs_buff[L2TAP_IREC_SPACE(sizeof(struct timespec))];
        l2tap_irec_hdr_t align;
    } u;

    l2tap_extended_buff_t ptp_msg_ext_buff;

    ptp_msg_ext_buff.info_recs_len = sizeof(u.info_recs_buff);
    ptp_msg_ext_buff.info_recs_buff = u.info_recs_buff;
    ptp_msg_ext_buff.buff = eth_frame;
    ptp_msg_ext_buff.buff_len = sizeof(eth_frame);

    l2tap_irec_hdr_t *ts_info = L2TAP_IREC_FIRST(&ptp_msg_ext_buff);
    ts_info->len = L2TAP_IREC_LEN(sizeof(struct timespec));
    ts_info->type = L2TAP_IREC_TIME_STAMP;

    int ret = write(state->ptp_socket, &ptp_msg_ext_buff, 0);

    // check if write was successful and ts_info is valid
    if (ret > 0 && ts_info->type == L2TAP_IREC_TIME_STAMP) {
        *ts = *(struct timespec *)ts_info->data;
    }

## IP Event: Transmit/Receive Packet

This event, `IP_EVENT_TX_RX`, is triggered for every transmitted or received IP packet. It provides information about packet transmission or reception, data length, and the `esp_netif` handle.

### Enabling the Event

Compile Time:

The feature can be completely disabled during compilation time using the flag CONFIG_ESP_NETIF_REPORT_DATA_TRAFFIC in the kconfig.

Run Time:

At runtime, you can enable or disable this event using the functions `esp_netif_tx_rx_event_enable()` and `esp_netif_tx_rx_event_disable()`.

### Event Registration

To handle this event, you need to register a handler using the following syntax:

    static void
    tx_rx_event_handler(void *arg, esp_event_base_t event_base,
                                    int32_t event_id, void *event_data)
    {
        ip_event_tx_rx_t *event = (ip_event_tx_rx_t *)event_data;

        if (event->dir == ESP_NETIF_TX) {
            ESP_LOGI(TAG, "Got TX event: Interface \"%s\" data len: %d", esp_netif_get_desc(event->esp_netif), event->len);
        } else if (event->dir == ESP_NETIF_RX) {
            ESP_LOGI(TAG, "Got RX event: Interface \"%s\" data len: %d", esp_netif_get_desc(event->esp_netif), event->len);
        } else {
            ESP_LOGI(TAG, "Got Unknown event: Interface \"%s\"", esp_netif_get_desc(event->esp_netif));
        }
    }

    esp_event_handler_register(IP_EVENT, IP_EVENT_TX_RX, &tx_rx_event_handler, NULL);

Here, `tx_rx_event_handler` is the name of the function that will handle the event.

### Event Data Structure

The event data structure, `ip_event_tx_rx_t`, contains the following fields:

- `ip_event_tx_rx_t::dir`: Indicates whether the packet was transmitted (`ESP_NETIF_TX`) or received (`ESP_NETIF_RX`).

- `ip_event_tx_rx_t::len`: Length of the data frame.

- `ip_event_tx_rx_t::esp_netif`: The network interface on which the packet was sent or received.

## API Reference

### Header File

- components/esp_netif/include/esp_netif.h

- This header file can be included with:

  >     #include "esp_netif.h"

- This header file is a part of the API provided by the `esp_netif` component. To declare that your component depends on `esp_netif`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_netif

  > or

  >     PRIV_REQUIRES esp_netif

### Header File

- components/esp_netif/include/esp_netif_sntp.h

- This header file can be included with:

  >     #include "esp_netif_sntp.h"

- This header file is a part of the API provided by the `esp_netif` component. To declare that your component depends on `esp_netif`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_netif

  > or

  >     PRIV_REQUIRES esp_netif

### Structures

struct esp_sntp_config

  SNTP configuration struct.

  Public Members

  bool smooth_sync

    set to true if smooth sync required

  bool server_from_dhcp

    set to true to request NTP server config from DHCP

  bool wait_for_sync

    if true, we create a semaphore to signal time sync event

  bool start

    set to true to automatically start the SNTP service

  esp_sntp_time_cb_t sync_cb

    optionally sets callback function on time sync event

  bool renew_servers_after_new_IP

    this is used to refresh server list if NTP provided by DHCP (which cleans other pre-configured servers)

  ip_event_t ip_event_to_renew

    set the IP event id on which we refresh server list (if renew_servers_after_new_IP=true)

  size_t index_of_first_server

    refresh server list after this server (if renew_servers_after_new_IP=true)

  size_t num_of_servers

    number of preconfigured NTP servers

  const char *servers[1]

    list of servers

### Header File

- components/esp_netif/include/esp_netif_types.h

- This header file can be included with:

  >     #include "esp_netif_types.h"

- This header file is a part of the API provided by the `esp_netif` component. To declare that your component depends on `esp_netif`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_netif

  > or

  >     PRIV_REQUIRES esp_netif

### Structures

struct esp_netif_dns_info_t

  DNS server info.

  Public Members

  esp_ip_addr_t ip

    IPV4 address of DNS server

struct esp_netif_ip_info_t

  Event structure for IP_EVENT_STA_GOT_IP, IP_EVENT_ETH_GOT_IP events

  Public Members

  esp_ip4_addr_t ip

    Interface IPV4 address

  esp_ip4_addr_t netmask

    Interface IPV4 netmask

  esp_ip4_addr_t gw

    Interface IPV4 gateway address

struct esp_netif_ip6_info_t

  IPV6 IP address information.

  Public Members

  esp_ip6_addr_t ip

    Interface IPV6 address

struct ip_event_got_ip_t

  Event structure for IP_EVENT_GOT_IP event.

  Public Members

  esp_netif_t *esp_netif

    Pointer to corresponding esp-netif object

  esp_netif_ip_info_t ip_info

    IP address, netmask, gateway IP address

  bool ip_changed

    Whether the assigned IP has changed or not

struct ip_event_got_ip6_t

  Event structure for IP_EVENT_GOT_IP6 event

  Public Members

  esp_netif_t *esp_netif

    Pointer to corresponding esp-netif object

  esp_netif_ip6_info_t ip6_info

    IPv6 address of the interface

  int ip_index

    IPv6 address index

struct ip_event_add_ip6_t

  Event structure for ADD_IP6 event

  Public Members

  esp_ip6_addr_t addr

    The address to be added to the interface

  bool preferred

    The default preference of the address

struct ip_event_ap_staipassigned_t

  Event structure for IP_EVENT_AP_STAIPASSIGNED event

  Public Members

  esp_netif_t *esp_netif

    Pointer to the associated netif handle

  esp_ip4_addr_t ip

    IP address which was assigned to the station

  uint8_t mac[6]

    MAC address of the connected client

struct ip_event_tx_rx_t

  Event structure for IP_EVENT_TRANSMIT and IP_EVENT_RECEIVE

  Public Members

  esp_netif_t *esp_netif

    Pointer to the associated netif handle

  size_t len

    Length of the data

  esp_netif_tx_rx_direction_t dir

    Directions for data transfer >

struct bridgeif_config

  LwIP bridge configuration

  Public Members

  uint16_t max_fdb_dyn_entries

    maximum number of entries in dynamic forwarding database

  uint16_t max_fdb_sta_entries

    maximum number of entries in static forwarding database

  uint8_t max_ports

    maximum number of ports the bridge can consist of

struct esp_netif_inherent_config

  ESP-netif inherent config parameters.

  Public Members

  esp_netif_flags_t flags

    flags that define esp-netif behavior

  uint8_t mac[6]

    initial mac address for this interface

  const esp_netif_ip_info_t *ip_info

    initial ip address for this interface

  uint32_t get_ip_event

    event id to be raised when interface gets an IP

  uint32_t lost_ip_event

    event id to be raised when interface losts its IP

  const char *if_key

    string identifier of the interface

  const char *if_desc

    textual description of the interface

  int route_prio

    numeric priority of this interface to become a default routing if (if other netifs are up). A higher value of route_prio indicates a higher priority

  bridgeif_config_t *bridge_info

    LwIP bridge configuration

struct esp_netif_driver_base_s

  ESP-netif driver base handle.

  Public Members

  esp_err_t (*post_attach)(esp_netif_t *netif, esp_netif_iodriver_handle h)

    post attach function pointer

  esp_netif_t *netif

    netif handle

struct esp_netif_driver_ifconfig

  Specific IO driver configuration.

  Public Members

  esp_netif_iodriver_handle handle

    io-driver handle

  esp_err_t (*transmit)(void *h, void *buffer, size_t len)

    transmit function pointer

  esp_err_t (*transmit_wrap)(void *h, void *buffer, size_t len, void *netstack_buffer)

    transmit wrap function pointer

  void (*driver_free_rx_buffer)(void *h, void *buffer)

    free rx buffer function pointer

  esp_err_t (*driver_set_mac_filter)(void *h, const uint8_t *mac, size_t mac_len, bool add)

    set mac filter function pointer

struct esp_netif_config

  Generic esp_netif configuration.

  Public Members

  const esp_netif_inherent_config_t *base

    base config

  const esp_netif_driver_ifconfig_t *driver

    driver config

  const esp_netif_netstack_config_t *stack

    stack config

struct esp_netif_pair_mac_ip_t

  DHCP client's addr info (pair of MAC and IP address)

  Public Members

  uint8_t mac[6]

    Clients MAC address

  esp_ip4_addr_t ip

    Clients IP address

### Macros

ESP_ERR_ESP_NETIF_BASE

  Definition of ESP-NETIF based errors.

ESP_ERR_ESP_NETIF_INVALID_PARAMS

ESP_ERR_ESP_NETIF_IF_NOT_READY

ESP_ERR_ESP_NETIF_DHCPC_START_FAILED

ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED

ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED

ESP_ERR_ESP_NETIF_NO_MEM

ESP_ERR_ESP_NETIF_DHCP_NOT_STOPPED

ESP_ERR_ESP_NETIF_DRIVER_ATTACH_FAILED

ESP_ERR_ESP_NETIF_INIT_FAILED

ESP_ERR_ESP_NETIF_DNS_NOT_CONFIGURED

ESP_ERR_ESP_NETIF_MLD6_FAILED

ESP_ERR_ESP_NETIF_IP6_ADDR_FAILED

ESP_ERR_ESP_NETIF_DHCPS_START_FAILED

ESP_ERR_ESP_NETIF_TX_FAILED

ESP_NETIF_BR_FLOOD

  Definition of ESP-NETIF bridge control.

ESP_NETIF_BR_DROP

ESP_NETIF_BR_FDW_CPU

### Type Definitions

typedef struct esp_netif_obj esp_netif_t

typedef enum esp_netif_flags esp_netif_flags_t

typedef enum esp_netif_ip_event_type esp_netif_ip_event_type_t

typedef struct bridgeif_config bridgeif_config_t

  LwIP bridge configuration

typedef struct esp_netif_inherent_config esp_netif_inherent_config_t

  ESP-netif inherent config parameters.

typedef struct esp_netif_config esp_netif_config_t

typedef void *esp_netif_iodriver_handle

  IO driver handle type.

typedef struct esp_netif_driver_base_s esp_netif_driver_base_t

  ESP-netif driver base handle.

typedef struct esp_netif_driver_ifconfig esp_netif_driver_ifconfig_t

typedef struct esp_netif_netstack_config esp_netif_netstack_config_t

  Specific L3 network stack configuration.

typedef esp_err_t (*esp_netif_receive_t)(esp_netif_t *esp_netif, void *buffer, size_t len, void *eb)

  ESP-NETIF Receive function type.

### Enumerations

enum esp_netif_dns_type_t

  Type of DNS server.

  Values:

  enumerator ESP_NETIF_DNS_MAIN

    DNS main server address

  enumerator ESP_NETIF_DNS_BACKUP

    DNS backup server address (Wi-Fi STA and Ethernet only)

  enumerator ESP_NETIF_DNS_FALLBACK

    DNS fallback server address (Wi-Fi STA and Ethernet only)

  enumerator ESP_NETIF_DNS_MAX

enum esp_netif_dhcp_status_t

  Status of DHCP client or DHCP server.

  Values:

  enumerator ESP_NETIF_DHCP_INIT

    DHCP client/server is in initial state (not yet started)

  enumerator ESP_NETIF_DHCP_STARTED

    DHCP client/server has been started

  enumerator ESP_NETIF_DHCP_STOPPED

    DHCP client/server has been stopped

  enumerator ESP_NETIF_DHCP_STATUS_MAX

enum esp_netif_dhcp_option_mode_t

  Mode for DHCP client or DHCP server option functions.

  Values:

  enumerator ESP_NETIF_OP_START
  enumerator ESP_NETIF_OP_SET

    Set option

  enumerator ESP_NETIF_OP_GET

    Get option

  enumerator ESP_NETIF_OP_MAX

enum esp_netif_dhcp_option_id_t

  Supported options for DHCP client or DHCP server.

  Values:

  enumerator ESP_NETIF_SUBNET_MASK

    Network mask

  enumerator ESP_NETIF_DOMAIN_NAME_SERVER

    Domain name server

  enumerator ESP_NETIF_ROUTER_SOLICITATION_ADDRESS

    Solicitation router address

  enumerator ESP_NETIF_REQUESTED_IP_ADDRESS

    Request specific IP address

  enumerator ESP_NETIF_IP_ADDRESS_LEASE_TIME

    Request IP address lease time

  enumerator ESP_NETIF_IP_REQUEST_RETRY_TIME

    Request IP address retry counter

  enumerator ESP_NETIF_VENDOR_CLASS_IDENTIFIER

    Vendor Class Identifier of a DHCP client

  enumerator ESP_NETIF_VENDOR_SPECIFIC_INFO

    Vendor Specific Information of a DHCP server

  enumerator ESP_NETIF_CAPTIVEPORTAL_URI

    Captive Portal Identification

enum ip_event_t

  IP event declarations

  Values:

  enumerator IP_EVENT_STA_GOT_IP

    station got IP from connected AP

  enumerator IP_EVENT_STA_LOST_IP

    station lost IP and the IP is reset to 0

  enumerator IP_EVENT_AP_STAIPASSIGNED

    soft-AP assign an IP to a connected station

  enumerator IP_EVENT_GOT_IP6

    station or ap or ethernet interface v6IP addr is preferred

  enumerator IP_EVENT_ETH_GOT_IP

    ethernet got IP from connected AP

  enumerator IP_EVENT_ETH_LOST_IP

    ethernet lost IP and the IP is reset to 0

  enumerator IP_EVENT_PPP_GOT_IP

    PPP interface got IP

  enumerator IP_EVENT_PPP_LOST_IP

    PPP interface lost IP

  enumerator IP_EVENT_TX_RX

    transmitting/receiving data packet

enum esp_netif_tx_rx_direction_t

  Values:

  enumerator ESP_NETIF_TX
  enumerator ESP_NETIF_RX

enum esp_netif_flags

  Values:

  enumerator ESP_NETIF_DHCP_CLIENT
  enumerator ESP_NETIF_DHCP_SERVER
  enumerator ESP_NETIF_FLAG_AUTOUP
  enumerator ESP_NETIF_FLAG_GARP
  enumerator ESP_NETIF_FLAG_EVENT_IP_MODIFIED
  enumerator ESP_NETIF_FLAG_IS_PPP
  enumerator ESP_NETIF_FLAG_IS_BRIDGE
  enumerator ESP_NETIF_FLAG_MLDV6_REPORT
  enumerator ESP_NETIF_FLAG_IPV6_AUTOCONFIG_ENABLED

enum esp_netif_ip_event_type

  Values:

  enumerator ESP_NETIF_IP_EVENT_GOT_IP
  enumerator ESP_NETIF_IP_EVENT_LOST_IP

### Header File

- components/esp_netif/include/esp_netif_ip_addr.h

- This header file can be included with:

  >     #include "esp_netif_ip_addr.h"

- This header file is a part of the API provided by the `esp_netif` component. To declare that your component depends on `esp_netif`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_netif

  > or

  >     PRIV_REQUIRES esp_netif

### Functions

esp_ip6_addr_type_t esp_netif_ip6_get_addr_type(esp_ip6_addr_t *ip6_addr)

  Get the IPv6 address type.

  Parameters:

    ip6_addr -- [in] IPv6 type

  Returns:

    IPv6 type in form of enum esp_ip6_addr_type_t

static inline void esp_netif_ip_addr_copy(esp_ip_addr_t *dest, const esp_ip_addr_t *src)

  Copy IP addresses.

  Parameters:

    - dest -- [out] destination IP

    - src -- [in] source IP

### Structures

struct esp_ip6_addr

  IPv6 address.

  Public Members

  uint32_t addr[4]

    IPv6 address

  uint8_t zone

    zone ID

struct esp_ip4_addr

  IPv4 address.

  Public Members

  uint32_t addr

    IPv4 address

struct _ip_addr

  IP address.

  Public Members

  esp_ip6_addr_t ip6

    IPv6 address type

  esp_ip4_addr_t ip4

    IPv4 address type

  union _ip_addr u_addr

    IP address union

  uint8_t type

    ipaddress type

### Macros

esp_netif_htonl(x)

esp_netif_ip4_makeu32(a, b, c, d)

ESP_IP6_ADDR_BLOCK1(ip6addr)

ESP_IP6_ADDR_BLOCK2(ip6addr)

ESP_IP6_ADDR_BLOCK3(ip6addr)

ESP_IP6_ADDR_BLOCK4(ip6addr)

ESP_IP6_ADDR_BLOCK5(ip6addr)

ESP_IP6_ADDR_BLOCK6(ip6addr)

ESP_IP6_ADDR_BLOCK7(ip6addr)

ESP_IP6_ADDR_BLOCK8(ip6addr)

IPSTR

esp_ip4_addr_get_byte(ipaddr, idx)

esp_ip4_addr1(ipaddr)

esp_ip4_addr2(ipaddr)

esp_ip4_addr3(ipaddr)

esp_ip4_addr4(ipaddr)

esp_ip4_addr1_16(ipaddr)

esp_ip4_addr2_16(ipaddr)

esp_ip4_addr3_16(ipaddr)

esp_ip4_addr4_16(ipaddr)

IP2STR(ipaddr)

IPV6STR

IPV62STR(ipaddr)

ESP_IPADDR_TYPE_V4

ESP_IPADDR_TYPE_V6

ESP_IPADDR_TYPE_ANY

ESP_IP4TOUINT32(a, b, c, d)

ESP_IP4TOADDR(a, b, c, d)

ESP_IP4ADDR_INIT(a, b, c, d)

ESP_IP6ADDR_INIT(a, b, c, d)

IP4ADDR_STRLEN_MAX

ESP_IP_IS_ANY(addr)

### Type Definitions

typedef struct esp_ip4_addr esp_ip4_addr_t

typedef struct esp_ip6_addr esp_ip6_addr_t

typedef struct _ip_addr esp_ip_addr_t

  IP address.

### Enumerations

enum esp_ip6_addr_type_t

  Values:

  enumerator ESP_IP6_ADDR_IS_UNKNOWN
  enumerator ESP_IP6_ADDR_IS_GLOBAL
  enumerator ESP_IP6_ADDR_IS_LINK_LOCAL
  enumerator ESP_IP6_ADDR_IS_SITE_LOCAL
  enumerator ESP_IP6_ADDR_IS_UNIQUE_LOCAL
  enumerator ESP_IP6_ADDR_IS_IPV4_MAPPED_IPV6

### Header File

- components/esp_netif/include/esp_vfs_l2tap.h

- This header file can be included with:

  >     #include "esp_vfs_l2tap.h"

- This header file is a part of the API provided by the `esp_netif` component. To declare that your component depends on `esp_netif`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_netif

  > or

  >     PRIV_REQUIRES esp_netif

### Functions

esp_err_t esp_vfs_l2tap_intf_register(l2tap_vfs_config_t *config)

  Add L2 TAP virtual filesystem driver.

  This function must be called prior usage of ESP-NETIF L2 TAP Interface

  Parameters:

    config -- L2 TAP virtual filesystem driver configuration. Default base path /dev/net/tap is used when this parameter is NULL.

  Returns:

    esp_err_t

    - ESP_OK on success

esp_err_t esp_vfs_l2tap_intf_unregister(const char *base_path)

  Removes L2 TAP virtual filesystem driver.

  Parameters:

    base_path -- Base path to the L2 TAP virtual filesystem driver. Default path /dev/net/tap is used when this parameter is NULL.

  Returns:

    esp_err_t

    - ESP_OK on success

esp_err_t esp_vfs_l2tap_eth_filter_frame(l2tap_iodriver_handle driver_handle, void *buff, size_t *size, void *info)

  Filters received Ethernet L2 frames into L2 TAP infrastructure.

  Parameters:

    - driver_handle -- handle of driver at which the frame was received

    - buff -- received L2 frame

    - size -- input length of the L2 frame which is set to 0 when frame is filtered into L2 TAP

    - info -- extra information about received Ethernet frame

  Returns:

    esp_err_t

    - ESP_OK is always returned

### Structures

struct l2tap_vfs_config_t

  L2Tap VFS config parameters.

  Public Members

  const char *base_path

    vfs base path

struct l2tap_irec_hdr_t

  Information Record (IREC)

  Public Members

  size_t len

    Length of the record including header and data

  l2tap_irec_type_t type

    Type of the record

  uint8_t data[]

    Records Data aligned to double word

struct l2tap_extended_buff_t

  Extended Buffer.

  Attention

    Use macros when allocating buffer for Information Records and when manipulating with data in the records to ensure proper memory alignment

  Public Members

  size_t info_recs_len

    Length of Information Records buffer

  void *info_recs_buff

    Buffer holding extended information (IRECs) related to IO frames

  size_t buff_len

    Length of the actual IO Frame buffer

  void *buff

    Pointer to the IO Frame buffer

### Macros

L2TAP_VFS_DEFAULT_PATH

L2TAP_VFS_CONFIG_DEFAULT()

L2TAP_ALIGN(size)

  Macros for operations with Information Records.

  Align to double word size to each info record starts aligned in memory even if not aligned info data size is used by previous record. Double word alignment (at 32-bit arch) is needed when accessing double word variables or structs containing double word variables.

L2TAP_IREC_LEN(size)

L2TAP_IREC_SPACE(size)

L2TAP_IREC_FIRST(ext_buff)

L2TAP_IREC_NEXT(ext_buff, curr_rec)

esp_vfs_l2tap_eth_filter(drv_hndl, buf, size)

  Wrapper over L2 TAP filter function to ensure backward compatibility.

  This macro is provided for backward compatibility with the original `esp_vfs_l2tap_eth_filter` function. It calls `esp_vfs_l2tap_eth_filter_frame()` with the `info` parameter set to `NULL`, which means L2 TAP features that depend on extra information about the received Ethernet frame (e.g., timestamps) will not work as expected.

  Note

  For new implementations, it is recommended to use `esp_vfs_l2tap_eth_filter_frame()` directly to take advantage of the extended functionality.

### Type Definitions

typedef void *l2tap_iodriver_handle

### Enumerations

enum l2tap_ioctl_opt_t

  Values:

  enumerator L2TAP_S_RCV_FILTER

    Set Ethertype filter, frames with this type to be passed to the file descriptor.

  enumerator L2TAP_G_RCV_FILTER

    Get current Ethertype filter.

  enumerator L2TAP_S_INTF_DEVICE

    Bound the file descriptor to a specific Network Interface is identified by its `if_key`.

  enumerator L2TAP_G_INTF_DEVICE

    Get the Network Interface `if_key` the file descriptor is bound to.

  enumerator L2TAP_S_DEVICE_DRV_HNDL

    Bound the file descriptor to a specific Network Interface identified by IO Driver handle.

  enumerator L2TAP_G_DEVICE_DRV_HNDL

    Get the Network Interface IO Driver handle the file descriptor is bound to.

  enumerator L2TAP_S_TIMESTAMP_EN

    Enables the hardware Time Stamping (TS) processing by the file descriptor. TS needs to be supported by hardware and enabled in the IO driver.

enum l2tap_irec_type_t

  Information Record (IREC) Header Type indicates expected type of Header Data.

  Values:

  enumerator L2TAP_IREC_INVALID

    Indicate invalid IREC (data is not valid)

  enumerator L2TAP_IREC_TIME_STAMP

    To retrieve time stamp in `struct timespec` format

## Wi-Fi Default API Reference

### Header File

- components/esp_wifi/include/esp_wifi_default.h

- This header file can be included with:

  >     #include "esp_wifi_default.h"

- This header file is a part of the API provided by the `esp_wifi` component. To declare that your component depends on `esp_wifi`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_wifi

  > or

  >     PRIV_REQUIRES esp_wifi

### Functions

esp_err_t esp_netif_attach_wifi_station(esp_netif_t *esp_netif)

  Attaches wifi station interface to supplied netif.

  Parameters:

    esp_netif -- instance to attach the wifi station to

  Returns:

    - ESP_OK on success

    - ESP_FAIL if attach failed

esp_err_t esp_netif_attach_wifi_ap(esp_netif_t *esp_netif)

  Attaches wifi soft AP interface to supplied netif.

  Parameters:

    esp_netif -- instance to attach the wifi AP to

  Returns:

    - ESP_OK on success

    - ESP_FAIL if attach failed

esp_err_t esp_wifi_set_default_wifi_sta_handlers(void)

  Sets default wifi event handlers for STA interface.

  Returns:

    - ESP_OK on success, error returned from esp_event_handler_register if failed

esp_err_t esp_wifi_set_default_wifi_ap_handlers(void)

  Sets default wifi event handlers for AP interface.

  Returns:

    - ESP_OK on success, error returned from esp_event_handler_register if failed

esp_err_t esp_wifi_set_default_wifi_nan_handlers(void)

  Sets default wifi event handlers for NAN interface.

  Returns:

    - ESP_OK on success, error returned from esp_event_handler_register if failed

esp_err_t esp_wifi_clear_default_wifi_driver_and_handlers(void *esp_netif)

  Clears default wifi event handlers for supplied network interface.

  Parameters:

    esp_netif -- instance of corresponding if object

  Returns:

    - ESP_OK on success, error returned from esp_event_handler_register if failed

esp_netif_t *esp_netif_create_default_wifi_ap(void)

  Creates default WIFI AP. In case of any init error this API aborts.

  Note

  The API creates esp_netif object with default WiFi access point config, attaches the netif to wifi and registers wifi handlers to the default event loop. This API uses assert() to check for potential errors, so it could abort the program. (Note that the default event loop needs to be created prior to calling this API)

  Returns:

    pointer to esp-netif instance

esp_netif_t *esp_netif_create_default_wifi_sta(void)

  Creates default WIFI STA. In case of any init error this API aborts.

  Note

  The API creates esp_netif object with default WiFi station config, attaches the netif to wifi and registers wifi handlers to the default event loop. This API uses assert() to check for potential errors, so it could abort the program. (Note that the default event loop needs to be created prior to calling this API)

  Returns:

    pointer to esp-netif instance

esp_netif_t *esp_netif_create_default_wifi_nan(void)

  Creates default WIFI NAN. In case of any init error this API aborts.

  Note

  The API creates esp_netif object with default WiFi station config, attaches the netif to wifi and registers wifi handlers to the default event loop. (Note that the default event loop needs to be created prior to calling this API)

  Returns:

    pointer to esp-netif instance

void esp_netif_destroy_default_wifi(void *esp_netif)

  Destroys default WIFI netif created with esp_netif_create_default_wifi_...() API.

  Note

  This API unregisters wifi handlers and detaches the created object from the wifi. (this function is a no-operation if esp_netif is NULL)

  Parameters:

    esp_netif -- [in] object to detach from WiFi and destroy

esp_netif_t *esp_netif_create_wifi(wifi_interface_t wifi_if, const esp_netif_inherent_config_t *esp_netif_config)

  Creates esp_netif WiFi object based on the custom configuration.

  Attention

    This API DOES NOT register default handlers!

  Parameters:

    - wifi_if -- [in] type of wifi interface

    - esp_netif_config -- [in] inherent esp-netif configuration pointer

  Returns:

    pointer to esp-netif instance

esp_err_t esp_netif_create_default_wifi_mesh_netifs(esp_netif_t **p_netif_sta, esp_netif_t **p_netif_ap)

  Creates default STA and AP network interfaces for esp-mesh.

  Both netifs are almost identical to the default station and softAP, but with DHCP client and server disabled. Please note that the DHCP client is typically enabled only if the device is promoted to a root node.

  Returns created interfaces which could be ignored setting parameters to NULL if an application code does not need to save the interface instances for further processing.

  Parameters:

    - p_netif_sta -- [out] pointer where the resultant STA interface is saved (if non NULL)

    - p_netif_ap -- [out] pointer where the resultant AP interface is saved (if non NULL)

  Returns:

    ESP_OK on success

Was this page helpful?

- Thank you! We received your feedback.
- If you have any comments, fill in Espressif Documentation Feedback Form.

- We value your feedback.
- Let us know how we can improve this page by filling in Espressif Documentation Feedback Form.