incubator-nuttx/Documentation/components/net/netdev.rst

195 lines
7.0 KiB
ReStructuredText

===============
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 :ref:`Network Drivers <netdriver>`)
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 :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
<eth>:<num>[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 <eth>:<num>,
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.