Network Devices

  • include/nuttx/net/netdev.h. All structures and APIs needed to work with network drivers are provided in this header file. The structure struct net_driver_s defines the interface and is passed to the network via netdev_register().

  • include/nuttx/net/netdev_lowerhalf.h. (Recommended for new drivers, see Network Drivers) This header file defines the interface between the network device and the network stack. The network device is a lower-half driver that provides the network stack with the ability to send and receive packets.

IP Addresses

The structure struct net_driver_s now supports one IPv4 address and multiple IPv6 addresses. Multiple IPv6 addresses is common in modern network devices. For example, a network device may have a link-local address and a global address. The link-local address is used for neighbor discovery protocol and the global address is used for communication with the Internet.

Configuration Options

CONFIG_NETDEV_MULTIPLE_IPv6

Enable support for multiple IPv6 addresses per network device. Depends on CONFIG_NET_IPv6.

CONFIG_NETDEV_MAX_IPv6_ADDR

Maximum number of IPv6 addresses that can be assigned to a single network device. Normally a link-local address and a global address are needed.

IPv4 Interfaces

Now we only support one IPv4 address per network device, and directly use the d_ipaddr, d_draddr and d_netmask in net_driver_s.

struct net_driver_s
struct net_driver_s
{
#ifdef CONFIG_NET_IPv4
  in_addr_t      d_ipaddr;      /* Host IPv4 address assigned to the network interface */
  in_addr_t      d_draddr;      /* Default router IP address */
  in_addr_t      d_netmask;     /* Network subnet mask */
#endif
};

IPv6 Interfaces

Now we support multiple IPv6 addresses per network device, and use the d_ipv6 in net_driver_s to store the IPv6 addresses. For historical reason, we keep the old name d_ipv6addr and d_ipv6netmask for backward compatibility. Please use d_ipv6 for new drivers.

struct net_driver_s
struct net_driver_s
{
#ifdef CONFIG_NET_IPv6
  struct netdev_ifaddr6_s d_ipv6[CONFIG_NETDEV_MAX_IPv6_ADDR];
#endif
};

Managing the IPv6 addresses by provided APIs would be more flexible:

int netdev_ipv6_add(FAR struct net_driver_s *dev, const net_ipv6addr_t addr, unsigned int preflen);
int netdev_ipv6_del(FAR struct net_driver_s *dev, const net_ipv6addr_t addr, unsigned int preflen);

Add or delete an IPv6 address on the network device

Returns:

Zero is returned if the operation is successfully applied on the device; A negated errno value is returned if failed.

FAR const uint16_t *netdev_ipv6_srcaddr(FAR struct net_driver_s *dev, const net_ipv6addr_t dst);

Get the source IPv6 address (RFC6724).

Returns:

A pointer to the IPv6 address is returned on success. It will never be NULL, but can be an address containing g_ipv6_unspecaddr.

FAR const uint16_t *netdev_ipv6_lladdr(FAR struct net_driver_s *dev);

Get the link-local address of the network device.

Returns:

A pointer to the link-local address is returned on success. NULL is returned if the address is not found on the device.

FAR struct netdev_ifaddr6_s *netdev_ipv6_lookup(FAR struct net_driver_s *dev, const net_ipv6addr_t addr, bool maskcmp);

Look up an IPv6 address in the network device’s IPv6 addresses

Returns:

A pointer to the matching IPv6 address entry is returned on success. NULL is returned if the IPv6 address is not found in the device.

int netdev_ipv6_foreach(FAR struct net_driver_s *dev, devif_ipv6_callback_t callback, FAR void *arg);

Enumerate each IPv6 address on a network device. This function will terminate when either (1) all addresses have been enumerated or (2) when a callback returns any non-zero value.

Returns:

Zero is returned if the enumeration is successfully completed; Non-zero value is returned if enumeration is terminated early by callback.

Ioctls for IP Addresses

SIOCGIFADDR
SIOCSIFADDR
SIOCDIFADDR

We just follow the Linux convention[1]:

Get, set, or delete the address of the device using ifr_addr, or ifr6_addr with ifr6_prefixlen. For compatibility, SIOCGIFADDR returns only AF_INET addresses, SIOCSIFADDR accepts AF_INET and AF_INET6 addresses, and SIOCDIFADDR deletes only AF_INET6 addresses. A AF_INET address can be deleted by setting it to zero via SIOCSIFADDR.

Note: Unlike Linux, the maximum number of IPv6 addresses is limited on NuttX. If you add more IPv6 addresses when we have already reached the limit, the new addresses will replace addresses with same scope.

[1]: https://man7.org/linux/man-pages/man7/netdevice.7.html

SIOCGLIFADDR
SIOCSLIFADDR

Get or set the IPv6 address of the device using lifr_addr.

We follow the Linux convention[1] to allow interface name to be <eth>:<num>[2], to keep working with multiple IPv6 addresses.

Note: Recommend to use SIOCSIFADDR and SIOCDIFADDR to manage IPv6 addresses, by which you don’t need to care about the slot it stored.

[1]: https://man7.org/linux/man-pages/man7/netdevice.7.html [2]: e.g. ‘eth0:0’ stands for the secondary address on eth0

SIOCGIFNETMASK
SIOCSIFNETMASK

Get or set the IPv4 network mask for a device using ifr_netmask.

SIOCGLIFNETMASK
SIOCSLIFNETMASK

Get or set the IPv6 network mask for a device using lifr_netmask.

We follow the Linux convention to allow interface name to be <eth>:<num>, to keep working with multiple IPv6 addresses.

Note: Recommend to use SIOCSIFADDR and SIOCDIFADDR to manage IPv6 addresses, by which you don’t need to care about the slot it stored.