Skip to content

gnrc_ipv6_nib: 6Lo-ND EUI-64 checks not portable #10723

@miri64

Description

@miri64

Description

Capabilities of 6Lo-ND to get a device's EUI-64 for the ARO are not portable beyond IEEE 802.15.4 at the moment. The two culprits for that are

size_t l2src_len = (uint16_t)dev->driver->get(dev, NETOPT_ADDRESS_LONG,
l2src, sizeof(l2src));
if (l2src_len != sizeof(eui64_t)) {
DEBUG("nib: can't get EUI-64 of the interface for ARO\n");
return;
}

Which expects the device to provide NETOPT_ADDRESS_LONG which then is the EUI-64 (which isn't necessarily the case for non-IEEE-802.15.4 devices) and

static inline bool _is_iface_eui64(gnrc_netif_t *netif, const eui64_t *eui64)
{
/* TODO: adapt for short addresses */
return (netif->l2addr_len == sizeof(eui64_t)) &&
(memcmp(&netif->l2addr, eui64, netif->l2addr_len) == 0);
}

which expects the configured link-layer address for the interface to be the devices EUI-64 (which isn't necessarily the case even for IEEE 802.15.4 devices).

From the past handlings with device specific data that is not necessarily intrinsic to the device (but might be generated from such data) it became best practice to add the getters for such data to sys/net/gnrc/netif/gnrc_netif_device_type.c. There a e.g. gnrc_netif_get_eui64() could reside. However, most device types already support generating (or getting) getting the EUI-64 with the _get_iid() functionality

#if GNRC_NETIF_L2ADDR_MAXLEN > 0
if (netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR) {
switch (netif->device_type) {
#if defined(MODULE_NETDEV_ETH) || defined(MODULE_ESP_NOW)
case NETDEV_TYPE_ETHERNET:
case NETDEV_TYPE_ESP_NOW:
if (addr_len == sizeof(eui48_t)) {
eui48_to_ipv6_iid(iid, (const eui48_t *)addr);
return sizeof(eui64_t);
}
else {
return -EINVAL;
}
#endif /* defined(MODULE_NETDEV_ETH) || defined(MODULE_ESP_NOW) */
#if defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE)
case NETDEV_TYPE_IEEE802154:
if (ieee802154_get_iid(iid, addr, addr_len) != NULL) {
return sizeof(eui64_t);
}
else {
return -EINVAL;
}
#endif /* defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE) */
#ifdef MODULE_NORDIC_SOFTDEVICE_BLE
case NETDEV_TYPE_BLE:
if (addr_len == sizeof(eui64_t)) {
memcpy(iid, addr, sizeof(eui64_t));
iid->uint8[0] ^= 0x02;
return sizeof(eui64_t);
}
else {
return -EINVAL;
}
#endif /* MODULE_NORDIC_SOFTDEVICE_BLE */
#if defined(MODULE_CC110X) || defined(MODULE_NRFMIN)
case NETDEV_TYPE_CC110X:
case NETDEV_TYPE_NRFMIN:
if (addr_len <= 3) {
_create_iid_from_short(addr, addr_len, iid);
return sizeof(eui64_t);
}
else {
return -EINVAL;
}
#endif /* defined(MODULE_CC110X) || defined(MODULE_NRFMIN) */
default:
(void)addr;
(void)addr_len;
(void)iid;
#ifdef DEVELHELP
LOG_ERROR("gnrc_netif: can't convert hardware address to IID "
"on interface %u\n", netif->pid);
#endif /* DEVELHELP */
assert(false);
break;
}
}
#endif /* GNRC_NETIF_L2ADDR_MAXLEN > 0 */
return -ENOTSUP;

So to prevent further code duplication I'd like to attack this smart. For the most part (EUI-48 to IPv6 IID, Nordic softdevice, "short address devices...) it is easy to just wrap the get_iid function around a get_eui64 function, the latter being the same as the original get_iid function, just without flipping the 0x02 bit. However, device types like IEEE 802.15.4 where the EUI-64 is an actual address existing on the device might be problematic.

Metadata

Metadata

Labels

Area: networkArea: NetworkingType: bugThe issue reports a bug / The PR fixes a bug (including spelling errors)

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions