Merge pull request #10524 from miri64/gnrc_netif/enh/centralize-dev-type-functions

gnrc_netif: centralize device-type-specific functions
This commit is contained in:
Cenk Gündoğan 2019-01-16 16:44:43 +01:00 committed by GitHub
commit b24a8fbf3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 225 additions and 131 deletions

View File

@ -46,6 +46,7 @@
#endif
#include "net/ndp.h"
#include "net/netdev.h"
#include "net/netopt.h"
#include "rmutex.h"
#ifdef __cplusplus

View File

@ -22,6 +22,7 @@
#define NET_GNRC_NETIF_INTERNAL_H
#include "net/gnrc/netif.h"
#include "net/netopt.h"
#ifdef MODULE_GNRC_IPV6_NIB
#include "net/gnrc/ipv6/nib/conf.h"
@ -403,7 +404,37 @@ static inline bool gnrc_netif_is_6lbr(const gnrc_netif_t *netif)
#define gnrc_netif_is_6lbr(netif) (false)
#endif
/**
* @name Device type based function
*
* These functions' behavior is based around the gnrc_netif_t::device_type of
* an interface.
*
* @attention Special care needs to be taken for those functions when porting
* a new network device type or link-layer protocol: They might
* need adaptions for your port
* @{
*/
/**
* @brief Get the default link-layer address option for the given
* gnrc_netif_t::device_type of a network interface
*
* @param[in] netif The network interface to get the default link-layer
* address option for.
*
* @return Either @ref NETOPT_ADDRESS or @ref NETOPT_ADDRESS_LONG.
*/
netopt_t gnrc_netif_get_l2addr_opt(const gnrc_netif_t *netif);
#if defined(MODULE_GNRC_IPV6) || defined(DOXYGEN)
/**
* @brief Initialize IPv6 MTU and other packet length related members of
* @ref gnrc_netif_t based on gnrc_netif_t::device_type
*
* @param[in,out] netif The network interface to initialize the MTU for.
*/
void gnrc_netif_ipv6_init_mtu(gnrc_netif_t *netif);
/**
* @brief Converts a given hardware address to an IPv6 IID.
*
@ -484,11 +515,44 @@ static inline int gnrc_netif_ipv6_get_iid(gnrc_netif_t *netif, eui64_t *iid)
(void)iid;
return -ENOTSUP;
}
/**
* @brief Derives the length of the link-layer address in an NDP link-layer
* address option from that option's length field and the given device
* type.
*
* @note If an RFC exists that specifies how IPv6 operates over a link-layer,
* this function usually implements the section "Unicast Address
* Mapping".
*
* @see [RFC 4861, section 4.6.1](https://tools.ietf.org/html/rfc4861#section-4.6.1)
*
* @pre `netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR`
*
* @attention When `NDEBUG` is not defined, the node fails with an assertion
* instead of returning `-ENOTSUP`
*
* @param[in] netif The network interface @p opt was received on within an NDP
* message.
* @param[in] opt An NDP source/target link-layer address option.
*
* @return Length of the link-layer address in @p opt on success
* @return `-ENOTSUP`, when implementation does not know how to derive the
* length of the link-layer address from @p opt's length field based
* on gnrc_netif_t::device_type of @p netif.
* @return `-EINVAL` if `opt->len` was an invalid value for the given
* gnrc_netif_t::device_type of @p netif.
*/
int gnrc_netif_ndp_addr_len_from_l2ao(gnrc_netif_t *netif,
const ndp_opt_t *opt);
#else /* defined(MODULE_GNRC_IPV6) || defined(DOXYGEN) */
#define gnrc_netif_ipv6_iid_from_addr(netif, addr, addr_len, iid) (-ENOTSUP)
#define gnrc_netif_ipv6_iid_to_addr(netif, iid, addr) (-ENOTSUP)
#define gnrc_netif_ipv6_init_mtu(netif) (void)netif
#define gnrc_netif_ipv6_iid_from_addr(netif, addr, addr_len, iid) (-ENOTSUP)
#define gnrc_netif_ipv6_iid_to_addr(netif, iid, addr) (-ENOTSUP)
#define gnrc_netif_ndp_addr_len_from_l2ao(netif, opt) (-ENOTSUP)
#define gnrc_netif_ipv6_get_iid(netif, iid) (-ENOTSUP)
#endif /* defined(MODULE_GNRC_IPV6) || defined(DOXYGEN) */
/** @} */
#ifdef __cplusplus
}

View File

@ -1109,27 +1109,8 @@ static void _update_l2addr_from_dev(gnrc_netif_t *netif)
{
netdev_t *dev = netif->dev;
int res;
netopt_t opt = NETOPT_ADDRESS;
netopt_t opt = gnrc_netif_get_l2addr_opt(netif);
switch (netif->device_type) {
#if defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE) \
|| defined(MODULE_NORDIC_SOFTDEVICE_BLE)
case NETDEV_TYPE_BLE:
case NETDEV_TYPE_IEEE802154: {
uint16_t tmp;
res = dev->driver->get(dev, NETOPT_SRC_LEN, &tmp, sizeof(tmp));
assert(res == sizeof(tmp));
netif->l2addr_len = (uint8_t)tmp;
if (tmp == IEEE802154_LONG_ADDRESS_LEN) {
opt = NETOPT_ADDRESS_LONG;
}
}
break;
#endif
default:
break;
}
res = dev->driver->get(dev, opt, netif->l2addr,
sizeof(netif->l2addr));
if (res != -ENOTSUP) {
@ -1155,60 +1136,7 @@ static void _init_from_device(gnrc_netif_t *netif)
(void)res;
assert(res == sizeof(tmp));
netif->device_type = (uint8_t)tmp;
switch (netif->device_type) {
#if defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_NRFMIN) || \
defined(MODULE_XBEE) || defined(MODULE_ESP_NOW) || \
defined(MODULE_GNRC_SIXLOENC)
case NETDEV_TYPE_IEEE802154:
case NETDEV_TYPE_NRFMIN:
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
netif->flags |= GNRC_NETIF_FLAGS_6LO_HC;
#endif
/* intentionally falls through */
case NETDEV_TYPE_ESP_NOW:
#ifdef MODULE_GNRC_IPV6
res = dev->driver->get(dev, NETOPT_MAX_PACKET_SIZE, &tmp, sizeof(tmp));
assert(res == sizeof(tmp));
#ifdef MODULE_GNRC_SIXLOWPAN
netif->ipv6.mtu = IPV6_MIN_MTU;
netif->sixlo.max_frag_size = tmp;
#else
netif->ipv6.mtu = tmp;
#endif
#endif
break;
#endif /* MODULE_NETDEV_IEEE802154 */
#ifdef MODULE_NETDEV_ETH
case NETDEV_TYPE_ETHERNET:
#ifdef MODULE_GNRC_IPV6
netif->ipv6.mtu = ETHERNET_DATA_LEN;
#endif
#if defined(MODULE_GNRC_SIXLOWPAN_IPHC) && defined(MODULE_GNRC_SIXLOENC)
netif->flags |= GNRC_NETIF_FLAGS_6LO_HC;
#endif
break;
#endif
#ifdef MODULE_NORDIC_SOFTDEVICE_BLE
case NETDEV_TYPE_BLE:
netif->ipv6.mtu = IPV6_MIN_MTU;
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
netif->flags |= GNRC_NETIF_FLAGS_6LO_HC;
#endif
break;
#endif
default:
#ifdef MODULE_GNRC_IPV6
res = dev->driver->get(dev, NETOPT_MAX_PACKET_SIZE, &tmp, sizeof(tmp));
if (res < 0) {
/* assume maximum possible transition unit */
netif->ipv6.mtu = UINT16_MAX;
}
else {
netif->ipv6.mtu = tmp;
}
#endif
break;
}
gnrc_netif_ipv6_init_mtu(netif);
_update_l2addr_from_dev(netif);
}

View File

@ -17,11 +17,111 @@
#include <errno.h>
#include "log.h"
#ifdef MODULE_GNRC_IPV6
#include "net/ipv6.h"
#endif
#include "net/gnrc/netif.h"
#include "net/eui48.h"
#include "net/ethernet.h"
#include "net/ieee802154.h"
netopt_t gnrc_netif_get_l2addr_opt(const gnrc_netif_t *netif)
{
netopt_t res = NETOPT_ADDRESS;
switch (netif->device_type) {
#if defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE) || \
defined(MODULE_NORDIC_SOFTDEVICE_BLE)
case NETDEV_TYPE_IEEE802154:
case NETDEV_TYPE_BLE: {
netdev_t *dev = netif->dev;
int r;
uint16_t tmp;
r = dev->driver->get(dev, NETOPT_SRC_LEN, &tmp, sizeof(tmp));
assert(r == sizeof(tmp));
assert(r <= ((int)UINT8_MAX));
(void)r;
if (tmp == IEEE802154_LONG_ADDRESS_LEN) {
res = NETOPT_ADDRESS_LONG;
}
}
break;
#endif
default:
break;
}
return res;
}
#ifdef MODULE_GNRC_IPV6
void gnrc_netif_ipv6_init_mtu(gnrc_netif_t *netif)
{
#ifdef MODULE_GNRC_IPV6
netdev_t *dev = netif->dev;
int res;
uint16_t tmp;
switch (netif->device_type) {
#if defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_NRFMIN) || \
defined(MODULE_XBEE) || defined(MODULE_ESP_NOW) || \
defined(MODULE_GNRC_SIXLOENC)
case NETDEV_TYPE_IEEE802154:
case NETDEV_TYPE_NRFMIN:
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
netif->flags |= GNRC_NETIF_FLAGS_6LO_HC;
#endif
/* intentionally falls through */
case NETDEV_TYPE_ESP_NOW:
res = dev->driver->get(dev, NETOPT_MAX_PACKET_SIZE,
&tmp, sizeof(tmp));
assert(res == sizeof(tmp));
#ifdef MODULE_GNRC_SIXLOWPAN
netif->ipv6.mtu = IPV6_MIN_MTU;
netif->sixlo.max_frag_size = tmp;
#else
netif->ipv6.mtu = tmp;
#endif
break;
#endif /* defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_NRFMIN) || \
* defined(MODULE_XBEE) || defined(MODULE_ESP_NOW) */
#ifdef MODULE_NETDEV_ETH
case NETDEV_TYPE_ETHERNET:
#ifdef MODULE_GNRC_IPV6
netif->ipv6.mtu = ETHERNET_DATA_LEN;
#endif
#if defined(MODULE_GNRC_SIXLOWPAN_IPHC) && defined(MODULE_GNRC_SIXLOENC)
netif->flags |= GNRC_NETIF_FLAGS_6LO_HC;
#endif
break;
#endif
#ifdef MODULE_NORDIC_SOFTDEVICE_BLE
case NETDEV_TYPE_BLE:
netif->ipv6.mtu = IPV6_MIN_MTU;
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
netif->flags |= GNRC_NETIF_FLAGS_6LO_HC;
#endif
break;
#endif
default:
#ifdef DEVELHELP
LOG_DEBUG("gnrc_netif: getting MTU from device for interface %i\n",
netif->pid);
#endif
res = dev->driver->get(dev, NETOPT_MAX_PACKET_SIZE,
&tmp, sizeof(tmp));
if (res < 0) {
/* assume maximum possible transition unit */
netif->ipv6.mtu = UINT16_MAX;
}
else {
netif->ipv6.mtu = tmp;
}
break;
}
#endif
}
#if defined(MODULE_CC110X) || defined(MODULE_NRFMIN)
static void _create_iid_from_short(const uint8_t *addr, size_t addr_len,
eui64_t *iid)
@ -148,6 +248,56 @@ int gnrc_netif_ipv6_iid_to_addr(const gnrc_netif_t *netif, const eui64_t *iid,
}
return -ENOTSUP;
}
int gnrc_netif_ndp_addr_len_from_l2ao(gnrc_netif_t *netif,
const ndp_opt_t *opt)
{
assert(netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR);
switch (netif->device_type) {
#ifdef MODULE_CC110X
case NETDEV_TYPE_CC110X:
(void)opt;
return sizeof(uint8_t);
#endif /* MODULE_CC110X */
#if defined(MODULE_NETDEV_ETH) || defined(MODULE_ESP_NOW)
case NETDEV_TYPE_ETHERNET:
case NETDEV_TYPE_ESP_NOW:
/* see https://tools.ietf.org/html/rfc2464#section-6*/
if (opt->len == 1U) {
return ETHERNET_ADDR_LEN;
}
else {
return -EINVAL;
}
#endif /* defined(MODULE_NETDEV_ETH) || defined(MODULE_ESP_NOW) */
#ifdef MODULE_NRFMIN
case NETDEV_TYPE_NRFMIN:
(void)opt;
return sizeof(uint16_t);
#endif /* MODULE_NRFMIN */
#if defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE)
case NETDEV_TYPE_IEEE802154:
/* see https://tools.ietf.org/html/rfc4944#section-8 */
switch (opt->len) {
case 1U:
return IEEE802154_SHORT_ADDRESS_LEN;
case 2U:
return IEEE802154_LONG_ADDRESS_LEN;
default:
return -EINVAL;
}
#endif /* defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE) */
default:
(void)opt;
#ifdef DEVELHELP
LOG_ERROR("gnrc_netif: can't get address length from NDP link-layer "
"address option on interface %u\n", netif->pid);
#endif
assert(false);
break;
}
return -ENOTSUP;
}
#endif /* MODULE_GNRC_IPV6 */
/** @} */

View File

@ -30,18 +30,6 @@
static char addr_str[IPV6_ADDR_MAX_STR_LEN];
/**
* @brief Determines supposed link-layer address from interface and option
* length
*
* @param[in] netif A network interface.
* @param[in] opt A SL2AO or TL2AO.
*
* @return The length of the L2 address carried in @p opt.
*/
static inline unsigned _get_l2addr_len(gnrc_netif_t *netif,
const ndp_opt_t *opt);
void _snd_ns(const ipv6_addr_t *tgt, gnrc_netif_t *netif,
const ipv6_addr_t *src, const ipv6_addr_t *dst)
{
@ -104,10 +92,10 @@ void _handle_sl2ao(gnrc_netif_t *netif, const ipv6_hdr_t *ipv6,
{
assert(netif != NULL);
_nib_onl_entry_t *nce = _nib_onl_get(&ipv6->src, netif->pid);
unsigned l2addr_len;
int l2addr_len;
l2addr_len = _get_l2addr_len(netif, sl2ao);
if (l2addr_len == 0U) {
l2addr_len = gnrc_netif_ndp_addr_len_from_l2ao(netif, sl2ao);
if (l2addr_len < 0) {
DEBUG("nib: Unexpected SL2AO length. Ignoring SL2AO\n");
return;
}
@ -174,43 +162,6 @@ void _handle_sl2ao(gnrc_netif_t *netif, const ipv6_hdr_t *ipv6,
}
}
static inline unsigned _get_l2addr_len(gnrc_netif_t *netif,
const ndp_opt_t *opt)
{
switch (netif->device_type) {
#ifdef MODULE_CC110X
case NETDEV_TYPE_CC110X:
(void)opt;
return sizeof(uint8_t);
#endif /* MODULE_CC110X */
#if defined(MODULE_NETDEV_ETH) || defined(MODULE_ESP_NOW)
case NETDEV_TYPE_ETHERNET:
case NETDEV_TYPE_ESP_NOW:
(void)opt;
return ETHERNET_ADDR_LEN;
#endif /* defined(MODULE_NETDEV_ETH) || defined(MODULE_ESP_NOW) */
#ifdef MODULE_NRFMIN
case NETDEV_TYPE_NRFMIN:
(void)opt;
return sizeof(uint16_t);
#endif /* MODULE_NRFMIN */
#if defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE)
case NETDEV_TYPE_IEEE802154:
switch (opt->len) {
case 1U:
return IEEE802154_SHORT_ADDRESS_LEN;
case 2U:
return IEEE802154_LONG_ADDRESS_LEN;
default:
return 0U;
}
#endif /* defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE) */
default:
(void)opt;
return 0U;
}
}
#if GNRC_IPV6_NIB_CONF_ARSM
/**
* @brief Calculates exponential back-off for retransmission timer for
@ -379,13 +330,13 @@ void _probe_nbr(_nib_onl_entry_t *nbr, bool reset)
void _handle_adv_l2(gnrc_netif_t *netif, _nib_onl_entry_t *nce,
const icmpv6_hdr_t *icmpv6, const ndp_opt_t *tl2ao)
{
unsigned l2addr_len = 0;
int l2addr_len = 0;
assert(nce != NULL);
assert(netif != NULL);
if (tl2ao != NULL) {
l2addr_len = _get_l2addr_len(netif, tl2ao);
if (l2addr_len == 0U) {
l2addr_len = gnrc_netif_ndp_addr_len_from_l2ao(netif, tl2ao);
if (l2addr_len < 0) {
DEBUG("nib: Unexpected TL2AO length. Ignoring TL2AO\n");
return;
}