Netdev

Introduction

Netdev (network interface device) also known as software network driver. In order to adapt each devices to more kinds of network cards and avoid dependence on a single network card in the system, the RT-Thread provides netdev components for network card management and control.

The main function of the netdev component is to solve the network connection problem when the device is connected to multiple nics, to uniformly manage the information and network connection status of each network card, and to provide a unified network card debugging command interface. Its main functional features are as follows:

  • Abstract NIC concept, each network connection device can register a unique Netdev.
  • Provide a variety of network connection information query, convenient for users to obtain the current network card network status in real time;
  • Create a list of Netdev and default Netdev, which can be used to switch network connections;
  • Provide a variety of Netdev operation interfaces (set IP, DNS server address, set Netdev status, etc.);
  • Unified management of Netdev debugging commands (ping, ifconfig, netstat, dns, etc.);

Working Principle

Concept

Before introducing the concept of network card, let's take a look at the concept of protocol stack, the protocol stack refers to the sum of the various layers of protocols in the network, each protocol stack reflects a different network data interaction mode, RT-Thread currently supports three types of protocol stack: lwIP protocol stack, AT Socket protocol stack, WIZnet TCP/IP hardware protocol stack. Each protocol stack corresponds to a protocol family type, and the protocol family types corresponding to the above protocol stacks are: AF_INET, AF_AT, AF_WIZ.

The initialization and registration of the Netdev is based on the protocol family type, so each Netdev corresponds to a unique protocol family type. The Socket descriptor is created on the basis of the Netdev, so each created Socket corresponds to a unique Netdev. The relationship between the protocol family, the Netdev, and the socket is shown in the following figure:

netdev 网络关系图

Each Netdevs corresponds to a unique Netdev struct object, which contains the main information and real-time status of the Netdev for the acquisition and setting of the following Netdev information:

/* Netdev struct object */
struct netdev
{
    rt_slist_t list;                                   /* Netdev List */

    char name[RT_NAME_MAX];                            /* Netdev Name */
    ip_addr_t ip_addr;                                 /* IP Address */
    ip_addr_t netmask;                                 /* Subnet Mask Address */
    ip_addr_t gw;                                      /* Gateway Address */
    ip_addr_t dns_servers[NETDEV_DNS_SERVERS_NUM];     /* DNS Server Address */
    uint8_t hwaddr_len;                                /* Hardware Address Length */
    uint8_t hwaddr[NETDEV_HWADDR_MAX_LEN];             /* Hardware Address */

    uint16_t flags;                                    /* Netdev Status Bit */
    uint16_t mtu;                                      /* The maximum transmission unit of the Netdev */
    const struct netdev_ops *ops;                      /* Netdev operation callback function */

    netdev_callback_fn status_callback;                /* Netdev status change callback */
    netdev_callback_fn addr_callback;                  /* Netdev address change callback */

#ifdef RT_USING_SAL
    void *sal_user_data;                               /* The parameter data related to the protocol family in Netdev */
#endif /* RT_USING_SAL */
    void *user_data;                                   /* Reserve user data */
};

Netdev State

The Netdev component provides management and control of the network state of the Netdev, and its types mainly include the following four: up/down, link_up/link_down, internet_up/internet_down, dhcp_enable/dhcp_disable.

  • up/down: The underlying Netdev is set to the up state after initialization is completed, which is used to determine whether the Netdev is enabled or disabled.
  • link_up/link_down: Used to determine whether the Netdev has a valid link connection, which can communicate with other network devices after connection. This state is generally set by the underlying driver of the netdev
  • internet_up/internet_down: Used to determine whether the device is connected to the Internet and can communicate with the extranet device after access.
  • dhcp_enable/dhcp_disable: Used to determine whether the current Netdev device has enabled the DHCP.

The up/down state and the dhcp_enable/dhcp_disable state can be set through the interface provided by the Netdev component and can be controlled at the application layer. Other states are automatically set by the underlying Netdev driver or the netdev component based on the current Netdev network connection.

Default Netdev and Netdev List

In order to facilitate the management and control of the Netdev, the Netdev component provides a list of Netdev for unified management of each Netdev device, and each Netdev in the system will create and register the Netdev object to the Netdev component Netdev list during initialization.

There is and only one default Netdev in the list of Netdev, generally takes the first registered Netdev in the system, the default Netdev can be set through the netdev_set_default() function, the main role of the default Netdev is to determine the type of Netdev that is used preferentially for network communication, and facilitate the switching of the Netdev and the acquisition of Netdev information.

Settings

The Netdev-related macro definitions are as follows, and you need to add the corresponding macro definitions to rtconfig.h:

Macro Definition Description
RT_USING_NETDEV Enable netdev function
NETDEV_USING_IFCONFIG Enable ifconfig command
NETDEV_USING_PING Enable ping command
NETDEV_USING_NETSTAT Enable netstat command
NETDEV_USING_AUTO_DEFAULT Enable the default Netdev auto-switch function

The above configuration options can be added directly in the rtconfig.h file, or they can be added through the RT-Thread ENV configuration option, and the specific configuration path in the ENV tool is as follows:

RT-Thread Components  --->
    Network  --->
        Network interface device  --->
        [*] Enable network interface device
        [*]   Enable ifconfig features
        [*]   Enable ping features
        [*]   Enable netstat features
        [*]   Enable default netdev automatic change features

Configuration can be done by regenerating functionality with the scons command to complete the addition of Netdev components.

User Guide

Header file definition

Use the following Netdev function related operation functions, you need to include the following header file:

#include <arpa/inet.h>         /* Contains header files related to addresses such as ip_addr_t */
#include <netdev.h>            /* Contains all netdev-related operation interface functions*/

Netdev Registration and Acquisition

Register Netdev

After the initialization of each Netdev is completed, you need to call the Netdev registration function to register the Netdev into the Netdev list, and the interface of the registered Netdev is as follows:

int netdev_register(struct netdev *netdev, const char *name, void *user_data);
Paremeter Description
netdev Netdev Object
name Netdev Name
user_data User data
Return ——
0 Netdev successfully registered
-1 Netdev failed to register

This function does not need to be called at the user level, and is generally called automatically after the initialization of the Netdev driver is completed, for example, the registration of the esp8266 Netdev is automatically completed after the network initialization of the esp8266 device.

Ungitster Netdev

This function can cancel the registration of the Netdev when it is used, that is, remove the corresponding Netdev from the list of Netdev, and its interface is as follows:

int netdev_unregister(struct netdev *netdev);
Parameter Description
netdev Netdev Object
Return ——
0 Netdev successfully cancelled
-1 Netdev failed to cancel

Get the first matching Netdev object by state

If you want to match the default Netdev by specific state, you can call the following function:

struct netdev *netdev_get_first_by_flags(uint16_t flags);
Parameter Description
flags Specify the matching state
Return ——
!= NULL Obtaining the Netdev object succeeded
NULL Obtaining the Netdev object failed

The states that can be used to match a Netdev are as follows:

State Description
NETDEV_FLAG_UP Netdev up state
NETDEV_FLAG_LINK_UP Netdev link_up state
NETDEV_FLAG_INTERNET_UP The state of the Netdev connection
NETDEV_FLAG_DHCP The state of the DHCP is enabled

Gets the first Netdev object of the specified protocol family type

Each Netdev corresponds to a unique protocol family type, and the following function can obtain the first Netdev object in the Netdev list by specifying the protocol family type:

struct netdev *netdev_get_by_family(int family);
Parameter Description
family Protocol Family Type
Return ——
!= NULL Obtaining the Netdev object succeeded
NULL Obtaining the Netdev object failed

There are several protocol familyl types supported in the RT-Thread:

Protocol Family Type Introduction
AF_INET The Netdev for the lwIP stack
AF_AT The Netdev for AT Socket
AF_WIZ The Netdev for WIZnet TCP/IP

This function is mainly used for specifying the operation of the protocol family Netdev and switching between the protocol family netdev in a multi-Netdevs environment.

Get the Netdev object by IP address

Each Netdev contains the basic information of the Netdev such as IP address, gateway and subnet mask, etc. The following function can obtain the Neydev object by IP address:

struct netdev *netdev_get_by_ipaddr(ip_addr_t *ip_addr);
Parameter Description
ip_addr IP address object
Return ——
!= NULL Obtaining the Netdev object succeeded
NULL Obtaining the Netdev object failed

This function is used to obtain Netdev state information when the bind function binds to a specified IP address.

can convert an IP address from a string format to a ip_addr_t type through the inet_aton () function.

Get the Netdev object by name

Each Netdev has a unique Netdev name, and the Netdev object can be obtained by the Netdev name:

struct netdev *netdev_get_by_name(const char *name);
Parameter Description
name Netdev Name
Return ——
!= NULL Obtaining the Netdev object succeeded
NULL Obtaining the Netdev object failed

This function is a commonly used interface for obtaining Netdev in the application layer, and the names in the current Netdev list can be viewed by the 'ifconfig' command.

Set Netdev Info

Set Default Netdev

The registered Netdev in the system is managed through the unified Netdev list, and provides a unique default Netdev, the following functions can be used to switch the default Netdev:

void netdev_set_default(struct netdev *netdev);

Set Netdev up/down state

The up/down state of the Netdev is used to control whether the Netdev state can be used.

The following functions are used to enable the Netdev:

int netdev_set_up(struct netdev *netdev);

The following functions are used to disable the Netdev:

int netdev_set_down(struct netdev *netdev);

After disabling the Netdev, the corresponding Socket on the Netdev will not be able to communicate data, and the Socket will not be created and bound on the Netdev until the Netdev state is set to the up state.

Set Netedev DHCP function state

DHCP is a dynamic host configuration protocol, if you enable the Netdev DHCP function, you can not set the Netdev IP, gateway and subnet mask address and other information by yourself, only after you disabled this function you can then set the above information. The following functions can be used to control the Netdev DHCP function:

int netdev_dhcp_enabled(struct netdev *netdev, rt_bool_t is_enabled);
Parameter Description
netdev Netdev Object
is_enabled Whether to enable(RT_TRUE / RT_FALSE)
Return ——
0 Setting the DHCP Function State succeeded
< 0 Setting the DHCP Function State failed

Some Netdevs do not support setting DHCP stats functions, such as M26 and EC20, and GRPS modules, an error message will be reported when this function is called.

Set Netdev Address Information

The following functions can be used to set the specified Netdev address IP, gateway, and subnet mask address, while Netdev disabled the DHCP function.

/* Set Netdev IP address */
int netdev_set_ipaddr(struct netdev *netdev, const ip_addr_t *ipaddr);
/* Set Netdev Gateway address */
int netdev_set_gw(struct netdev *netdev, const ip_addr_t *gw);
/* Set Subnet Mask address */
int netdev_set_netmask(struct netdev *netdev, const ip_addr_t *netmask);
Parameter Description
netdev Netdev Object
ipaddr/gw/netmask The IP/gateway/subnet mask address that needs to be set
Return ——
0 Setting the address info succeeded
< 0 Setting the address info failed

The following functions can be used to set the DNS server address of the Netdev, which is mainly used for the domain name resolution.

int netdev_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_t *dns_server);
Parameter Description
netdev Netdev Object
dns_num The DNS server that needs to be set
dns_server The DNS server address that needs to be set
Return ——
0 Setting the address info succeeded
< 0 Setting the address info failed

Set Netdev callback function

The following functions can be used to call back the callback function when the state of the device Netdev changes, including: up/down, link_up/link_down, internet_up/internet_down, dhcp_enable/dhcp_disable and so on.

typedef void (*netdev_callback_fn )(struct netdev *netdev, enum netdev_cb_type type);
void netdev_set_status_callback(struct netdev *netdev, netdev_callback_fn status_callback);
Paramter Description
netdev Netdev Object
status_callback Status changes callback function pointer
Return ——
NONE NONE

The following functions can be used to set the callback function when the Netdev address information changes, including: IP, subnet mask, gateway, DNS server and other addresses.

void netdev_set_addr_callback(struct netdev *netdev, netdev_callback_fn addr_callback)
Parameter Description
netdev Netdev Object
addr_callback Address changes callback function pointer
**Return ** ——
NONE NONE

Obtain Netdev Info

Determine whether the Netdev is in up

#define netdev_is_up(netdev)

Determine whether the Netdev is in link_up

#define netdev_is_link_up(netdev)

Determine whether the Netdev is in internet_up

#define netdev_is_internet_up(netdev)

Determine whether the DHCP function is enable

#define netdev_is_dhcp_enable(netdev)

Default Netdev Auto Switch

The menuconfig configuration enables the following options, can enable the default Netdev auto switch function:

[*]   Enable default netdev automatic change features

In single Netdev mode, the auto switch function of the default Netdev is enabled and disabled without obvious effect.

In multi-Netdev mode, if you enable the auto switch function of the default Netdev and the current default Netdev state is changed to down or link_down, the default Netdev switches to the Netdev with the state up and link_up in the list of Netdev. This allows one Netdev to quickly switch to another available Netdev after disconnection, simplifying the application layer Netdev switching operation. If this feature is not enabled the default NIC will not automatically switched.

Sample

FinSH Command

In order to facilitate the management and control of the Netdev in the multi-Netdevs environment, the Netdev component provides a variety of network debugging commands. The commonly used FinSH commands are shown in the following:

FinSH Command Description
ping Used to check if the network is connected
ifconfig Used to display and configure Netdev information, such as setting IP, gateway, and subnet mask addresses
dns Used to display and configure the Netdev DNS server address
netstat Used to view network connection information and port usage for each Netdev

ping command to test the network connection, and the result is as follows:

msh />ping rt-thread.org
60 bytes from 118.31.15.152 icmp_seq=0 ttl=52 time=13 ms
60 bytes from 118.31.15.152 icmp_seq=1 ttl=52 time=13 ms
60 bytes from 118.31.15.152 icmp_seq=2 ttl=52 time=14 ms
60 bytes from 118.31.15.152 icmp_seq=3 ttl=52 time=14 ms
  • This command sends ping protocol data by default using the default Netdev in the Netdev list, or sends ping protocol request data using the first up and link_up state of the Netdev in the Netdev list if the default Netdev state is down or link_down.

Use the ifconfig command to query and set the Netdev information, and the running result is as follows:

msh />ifconfig                                             /* Displays all Netdev information */
network interface device: w0 (Default)
MTU: 1500
MAC: 98 3b 16 55 9a 87
FLAGS: UP LINK_UP INTERNET_UP DHCP_DISABLE ETHARP BROADCAST IGMP
ip address: 192.168.12.92
gw address: 192.168.10.1
net mask  : 255.255.0.0
dns server #0: 192.168.10.1
dns server #1: 223.5.5.5
msh />
msh />ifconfig w0 192.168.12.93 192.168.10.1 255.255.0.0   /* Sets the IP address of the specified Netdev*/
config : w0
IP addr: 192.168.12.93
Gateway: 192.168.10.1
netmask: 255.255.0.0
  • The ifconfig command will sequentially display the information of all the Netdevs in the list of Netdev;
  • The default logo will be added after the list of Netdev default the Netdev command;
  • The ifconfig command sets the Netdev information function, which can only be called when the Netdev DHCP function is disabled, otherwise an error will be reported.

Use the dns command to query and set the DNS server address of the Netdev, and the result is as follows:

msh />dns                                         /* Display all Netdev DNS server addresses */
network interface device: w0 (Default)
dns server #0: 192.168.10.1
dns server #1: 223.5.5.5
msh />
msh />dns w0 192.168.12.1                          /* Sets the DNS server address for the specified Netdev */
set network interface device(w0) dns server #0: 192.168.12.1
  • The dns command sequentially displays the DNS server address information for all Netdevs in the Netdev list.
  • Currently, each Netdev only supports 2 DNS server addresses at the same time.

Use the netstat command can view the network connection state and port usage of all Netdevs, which are as follows:

msh />netstat
Active PCB states:
#0 192.168.12.93:49153 <==> 183.230.40.39:6002
Listen PCB states:
TIME-WAIT PCB states:
Active UDP PCB states:
#0 4 0.0.0.0:68 <==> 0.0.0.0:67
  • This command can view the address and port information for the TCP/UDP connection used on the current Netdev.

Switch Default Netdevs Sample

In the case of multiple Netdevs connections, you can switch Netdevs by setting the default Netdev. When creating a Socket connection, the default Netdev is preferred when using domain name resolution-related functions such as gethostbyname, and when the ping network function is completed.

In the following example, the export command is used to switch the default Netdev:

#include <arpa/inet.h>
#include <netdev.h>       /* When the NIC operation is required, both header files need to be included */

static int netdev_set_default_test(int argc, char **argv)
{
    struct netdev *netdev = RT_NULL;

    if (argc != 2)
    {
        rt_kprintf("netdev_set_default [netdev_name]   --set default network interface device.\n");
        return -1;
    }

    /* Obtain the Netdev object by using the Netdev name, which can be viewed by the ifconfig command*/
    netdev = netdev_get_by_name(argv[1]);
    if (netdev == RT_NULL)
    {
        rt_kprintf("not find network interface device name(%s).\n", argv[1]);
        return -1;
    }

    /* Set default Netdev object*/
    netdev_set_default(netdev);

    rt_kprintf("set default network interface device(%s) success.\n", argv[1]);
    return 0;
}
#ifdef FINSH_USING_MSH
#include <finsh.h>
/* Export commands to the FinSH console*/
MSH_CMD_EXPORT_ALIAS(netdev_set_default_test, netdev_set_default, set default network interface device);
#endif /* FINSH_USING_MSH */

Set Netdev up/down State Example

The up/down state of the Netdev is used to set of to disable the Netdev, and the following commands shows how to export settings Netdev state:

#include <arpa/inet.h>
#include <netdev.h>         /* When Netdev operation is required, both header files need to be included */

int netdev_set_status_test(int argc, char **argv)
{
    struct netdev *netdev = RT_NULL;

    if (argc != 3)
    {
        rt_kprintf("netdev_set_status [netdev_name] [up/down]   --set network interface device status.\n");
        return -1;
    }

    /* Obtain the Netdev object by using the Netdev name */
    netdev = netdev_get_by_name(argv[1]);
    if (netdev == RT_NULL)
    {
        rt_kprintf("input network interface name(%s) error.\n", argv[1]);
        return -1;
    }

    /*  Set the Netdev state to up or down */
    if (strcmp(argv[2], "up") == 0)
    {
        netdev_set_up(netdev);
        rt_kprintf("set network interface device(%s) up status.\n", argv[1]);
    }
    else if (strcmp(argv[2], "down") == 0)
    {
        netdev_set_down(netdev);
        rt_kprintf("set network interface device(%s) down status.\n", argv[1]);
    }
    else
    {
        rt_kprintf("netdev_set_status [netdev_name] [up/down].\n");
        return -1;
    }

    return 0;
}
#ifdef FINSH_USING_MSH
#include <finsh.h>
/* Export commands to the FinSH console */
MSH_CMD_EXPORT_ALIAS(netdev_set_status_test, netdev_set_status, set network interface device status);
#endif /* FINSH_USING_MSH */

Set Netdev IP Address Sample

Each Netdev corresponds to a unique IP address, and the Netdev IP address can be set through the interface provided by Netdev as follows:

#include <arpa/inet.h>
#include <netdev.h>         /* When the NIC operation is required, both header files need to be included */

int netdev_set_ipaddr_test(int argc, char **argv)
{
    struct netdev *netdev = RT_NULL;
    ip_addr_t addr;

    if (argc != 3)
    {
        rt_kprintf("netdev_set_status [netdev_name] [ip_addr]   --set network interface device IP address.\n");
        return -1;
    }

    /* Obtain the Netdev object by using the Netdev name */
    netdev = netdev_get_by_name(argv[1]);
    if (netdev == RT_NULL)
    {
        rt_kprintf("input network interface name(%s) error.\n", argv[1]);
        return -1;
    }

    /*  Set Netdev IP Address*/
    inet_aton(argv[2], &addr);
    netdev_set_ipaddr(netdev, &addr);

    return 0;
}
#ifdef FINSH_USING_MSH
#include <finsh.h>
/* Export commands to the FinSH console */
MSH_CMD_EXPORT_ALIAS(netdev_set_ipaddr_test, netdev_set_ipaddr, set network interface device IP
 address);
#endif /* FINSH_USING_MSH */

Q&A

Q: When setting the IP address, gateway and subnet mask, errors reported so not be able to set?

A: When setting the IP address, gateway, and subnet mask, you need to determine the current Netdev DHCP state, you can only set it when the Netdev DHCP state is disabled, you can call the netdev_dhcp_enabled () function to set the Netdev DHCP state.

Q: In the case of multiple Netdevs, what should I do if the ping function or the Netdev called when creating the socket is not the Netdev I want to use, what should I do?

A: First, use the ifconfig command to view the Netdev in the current list, confirm the name of the Netdev, use netdev_set_default() to set the default Netdev as the Netdev that you want to use, and then determine that the Netdev state is UP and LINK_UP.