From 64039650751496fdc9d305f6bd58e4f30529987f Mon Sep 17 00:00:00 2001 From: Zhe Weng Date: Tue, 31 Oct 2023 14:00:00 +0800 Subject: [PATCH] Documentation: Add netdev description with multiple IPv6 addresses Signed-off-by: Zhe Weng --- Documentation/reference/os/netdev.rst | 187 ++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 Documentation/reference/os/netdev.rst diff --git a/Documentation/reference/os/netdev.rst b/Documentation/reference/os/netdev.rst new file mode 100644 index 0000000000..2bc0fe7391 --- /dev/null +++ b/Documentation/reference/os/netdev.rst @@ -0,0 +1,187 @@ +=============== +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()``. + +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 :c:member:`d_ipaddr`, :c:member:`d_draddr` and :c:member:`d_netmask` +in :c:struct:`net_driver_s`. + +.. c:struct:: net_driver_s + + .. code-block:: c + + 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 :c:member:`d_ipv6` in :c:struct:`net_driver_s` to store the IPv6 +addresses. For historical reason, we keep the old name :c:member:`d_ipv6addr` +and :c:member:`d_ipv6netmask` for backward compatibility. Please use +:c:member:`d_ipv6` for new drivers. + +.. c:struct:: net_driver_s + + .. code-block:: c + + 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: + + - :c:func:`netdev_ipv6_add()` + - :c:func:`netdev_ipv6_del()` + - :c:func:`netdev_ipv6_srcaddr()` + - :c:func:`netdev_ipv6_lladdr()` + - :c:func:`netdev_ipv6_lookup()` + - :c:func:`netdev_ipv6_foreach()` + +.. c:function:: int netdev_ipv6_add(FAR struct net_driver_s *dev, const net_ipv6addr_t addr, \ + unsigned int preflen); +.. c:function:: 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 + + :return: Zero is returned if the operation is successfully applied on + the device; A negated errno value is returned if failed. + +.. c:function:: FAR const uint16_t *netdev_ipv6_srcaddr(FAR struct net_driver_s *dev, \ + const net_ipv6addr_t dst); + + Get the source IPv6 address (RFC6724). + + :return: A pointer to the IPv6 address is returned on success. It will never be + NULL, but can be an address containing g_ipv6_unspecaddr. + +.. c:function:: FAR const uint16_t *netdev_ipv6_lladdr(FAR struct net_driver_s *dev); + + Get the link-local address of the network device. + + :return: A pointer to the link-local address is returned on success. + NULL is returned if the address is not found on the device. + +.. c:function:: 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 + + :return: 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. + +.. c:function:: 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. + + :return: 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 +----------------------- + + - :c:macro:`SIOCGIFADDR` + - :c:macro:`SIOCSIFADDR` + - :c:macro:`SIOCDIFADDR` + - :c:macro:`SIOCGLIFADDR` + - :c:macro:`SIOCSLIFADDR` + - :c:macro:`SIOCGIFNETMASK` + - :c:macro:`SIOCSIFNETMASK` + - :c:macro:`SIOCGLIFNETMASK` + - :c:macro:`SIOCSLIFNETMASK` + +.. c:macro:: SIOCGIFADDR +.. c:macro:: SIOCSIFADDR +.. c:macro:: SIOCDIFADDR + + We just follow the Linux convention[1]: + + Get, set, or delete the address of the device using :c:member:`ifr_addr`, + or :c:member:`ifr6_addr` with :c:member:`ifr6_prefixlen`. + For compatibility, :c:macro:`SIOCGIFADDR` returns only :c:macro:`AF_INET` + addresses, :c:macro:`SIOCSIFADDR` accepts :c:macro:`AF_INET` and + :c:macro:`AF_INET6` addresses, and :c:macro:`SIOCDIFADDR` deletes + only :c:macro:`AF_INET6` addresses. A :c:macro:`AF_INET` address + can be deleted by setting it to zero via :c:macro:`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 + +.. c:macro:: SIOCGLIFADDR +.. c:macro:: SIOCSLIFADDR + + Get or set the IPv6 address of the device using :c:member:`lifr_addr`. + + We follow the Linux convention[1] to allow interface name to be + :[2], to keep working with multiple IPv6 addresses. + + Note: Recommend to use :c:macro:`SIOCSIFADDR` and :c:macro:`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 + +.. c:macro:: SIOCGIFNETMASK +.. c:macro:: SIOCSIFNETMASK + + Get or set the IPv4 network mask for a device using :c:member:`ifr_netmask`. + +.. c:macro:: SIOCGLIFNETMASK +.. c:macro:: SIOCSLIFNETMASK + + Get or set the IPv6 network mask for a device using :c:member:`lifr_netmask`. + + We follow the Linux convention to allow interface name to be :, + to keep working with multiple IPv6 addresses. + + Note: Recommend to use :c:macro:`SIOCSIFADDR` and :c:macro:`SIOCDIFADDR` + to manage IPv6 addresses, by which you don't need to care about the + slot it stored.