-
Notifications
You must be signed in to change notification settings - Fork 2.1k
gnrc_ipv6_nib: 6Lo-ND EUI-64 checks not portable #10723
Description
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
RIOT/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.c
Lines 60 to 65 in 242bb55
| 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
RIOT/sys/net/gnrc/network_layer/ipv6/nib/_nib-6ln.c
Lines 32 to 37 in 242bb55
| 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
RIOT/sys/net/gnrc/netif/gnrc_netif_device_type.c
Lines 42 to 100 in 242bb55
| #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.