Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gnrc_netif: add general IID to/from l2addr conversion functions #10513

Merged
merged 4 commits into from
Dec 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sys/include/net/gnrc/netif.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#ifdef MODULE_GNRC_MAC
#include "net/gnrc/netif/mac.h"
#endif
#include "net/ndp.h"
#include "net/netdev.h"
#include "rmutex.h"

Expand Down
56 changes: 56 additions & 0 deletions sys/include/net/gnrc/netif/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,62 @@ static inline bool gnrc_netif_is_6lbr(const gnrc_netif_t *netif)
#define gnrc_netif_is_6lbr(netif) (false)
#endif

#if defined(MODULE_GNRC_IPV6) || defined(DOXYGEN)
/**
* @brief Converts a given hardware address to an IPv6 IID.
*
* @attention When the link-layer of the interface has link-layer addresses, and
* `NDEBUG` is not defined, the node fails with an assertion instead
* returning `-ENOTSUP`.
*
* @param[in] netif The network interface @p addr came from (either as
* gnrc_netif_t::l2addr or from a packet that came over
* it).
* @param[in] addr A hardware address.
* @param[in] addr_len Number of bytes in @p addr.
* @param[out] iid The IID based on gnrc_netif_t::device_type
*
* @return `sizeof(eui64_t)` on success.
* @return `-ENOTSUP`, when gnrc_netif_t::device_type of @p netif does not
* support IID conversion.
* @return `-EINVAL`, when @p addr_len is invalid for the
* gnrc_netif_t::device_type of @p netif.
*/
int gnrc_netif_ipv6_iid_from_addr(const gnrc_netif_t *netif,
const uint8_t *addr, size_t addr_len,
eui64_t *iid);

/**
* @brief Converts an IPv6 IID to a hardware address
*
* @pre `netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR`
* @pre @p iid was based on a hardware address
* @pre The number of bytes available at @p addr is less or equal to
* @ref GNRC_NETIF_L2ADDR_MAXLEN.
*
* @attention When `NDEBUG` is not defined, the node fails with an assertion
* instead of returning `-ENOTSUP`
*
* @param[in] netif The network interface @p iid came from (either because
* it is paset on gnrc_netif_t::l2addr or from a packet
* that came over it).
* @param[in] iid An IID based on gnrc_netif_t::device_type.
* @param[out] addr The hardware address. It is assumed that @p iid was
* based on a hardware address and that the available bytes
* in @p addr are less or equal to
* `GNRC_NETIF_L2ADDR_MAXLEN`.
*
* @return Length of resulting @p addr on success.
* @return `-ENOTSUP`, when gnrc_netif_t::device_type of @p netif does not
* support reverse IID conversion.
*/
int gnrc_netif_ipv6_iid_to_addr(const gnrc_netif_t *netif, const eui64_t *iid,
uint8_t *addr);
#else /* defined(MODULE_GNRC_IPV6) || defined(DOXYGEN) */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the defined(DOXYGEN), right?!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ifdef in above opens with defined(MODULE_GNRC_IPV6) || defined(DOXYGEN), so I don't see why I would remove that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I mistakenly took the else for an if here...

#define gnrc_netif_ipv6_iid_to_addr(netif, addr, addr_len, iid) (-ENOTSUP)
#define gnrc_netif_ipv6_iid_from_addr(netif, iid, addr) (-ENOTSUP)
#endif /* defined(MODULE_GNRC_IPV6) || defined(DOXYGEN) */

#ifdef __cplusplus
}
#endif
Expand Down
70 changes: 5 additions & 65 deletions sys/net/gnrc/netif/gnrc_netif.c
Original file line number Diff line number Diff line change
Expand Up @@ -807,21 +807,6 @@ int gnrc_netif_ipv6_group_idx(gnrc_netif_t *netif, const ipv6_addr_t *addr)
return idx;
}

#if defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_CC110X) || \
defined(MODULE_NRFMIN) || defined(MODULE_XBEE)
static void _create_iid_from_short(const gnrc_netif_t *netif, eui64_t *eui64)
{
const unsigned offset = sizeof(eui64_t) - netif->l2addr_len;

assert(netif->l2addr_len <= 3);
memset(eui64->uint8, 0, sizeof(eui64->uint8));
eui64->uint8[3] = 0xff;
eui64->uint8[4] = 0xfe;
memcpy(&eui64->uint8[offset], netif->l2addr, netif->l2addr_len);
}
#endif /* defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_CC110X) ||
* defined(MODULE_NRFMIN) || defined(MODULE_XBEE) */

int gnrc_netif_ipv6_get_iid(gnrc_netif_t *netif, eui64_t *eui64)
{
#if GNRC_NETIF_L2ADDR_MAXLEN > 0
Expand All @@ -833,59 +818,14 @@ int gnrc_netif_ipv6_get_iid(gnrc_netif_t *netif, eui64_t *eui64)
if (res == sizeof(eui64_t)) {
return 0;
}

switch (netif->device_type) {
#if defined(MODULE_NETDEV_ETH) || defined(MODULE_ESP_NOW)
case NETDEV_TYPE_ETHERNET:
case NETDEV_TYPE_ESP_NOW:
assert(netif->l2addr_len == ETHERNET_ADDR_LEN);
eui64->uint8[0] = netif->l2addr[0] ^ 0x02;
eui64->uint8[1] = netif->l2addr[1];
eui64->uint8[2] = netif->l2addr[2];
eui64->uint8[3] = 0xff;
eui64->uint8[4] = 0xfe;
eui64->uint8[5] = netif->l2addr[3];
eui64->uint8[6] = netif->l2addr[4];
eui64->uint8[7] = netif->l2addr[5];
return 0;
#endif
#if defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE)
case NETDEV_TYPE_IEEE802154:
switch (netif->l2addr_len) {
case IEEE802154_SHORT_ADDRESS_LEN:
_create_iid_from_short(netif, eui64);
return 0;
case IEEE802154_LONG_ADDRESS_LEN:
memcpy(eui64, netif->l2addr, sizeof(eui64_t));
eui64->uint8[0] ^= 0x02;
return 0;
default:
/* this should not happen */
assert(false);
break;
}
break;
#endif
#ifdef MODULE_NORDIC_SOFTDEVICE_BLE
case NETDEV_TYPE_BLE:
assert(netif->l2addr_len == sizeof(eui64_t));
memcpy(eui64, netif->l2addr, sizeof(eui64_t));
eui64->uint8[0] ^= 0x02;
return 0;
#endif
#if defined(MODULE_CC110X) || defined(MODULE_NRFMIN)
case NETDEV_TYPE_CC110X:
case NETDEV_TYPE_NRFMIN:
_create_iid_from_short(netif, eui64);
return 0;
#endif
default:
(void)eui64;
break;
res = gnrc_netif_ipv6_iid_from_addr(netif,
netif->l2addr, netif->l2addr_len,
eui64);
if (res > 0) {
return 0;
}
}
#endif /* GNRC_NETIF_L2ADDR_MAXLEN > 0 */

return -ENOTSUP;
}

Expand Down
158 changes: 158 additions & 0 deletions sys/net/gnrc/netif/gnrc_netif_device_type.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/*
* Copyright (C) 2018 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @{
*
* @file
* @brief Functions that are based around a network interface's device type.
* @author Martine Lenders <[email protected]>
*/

#include <errno.h>

#include "log.h"
#include "net/gnrc/netif.h"
#include "net/ethernet.h"
#include "net/ieee802154.h"

#ifdef MODULE_GNRC_IPV6
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is pretty hacky. Better only build this file in case GNRC_IPV6 is selected: put

ifndef (,$(filter gnrc_ipv6,$(USEMODULE)))
  SRC += gnrc_netif_device_type.c`
endif

into the gnrc/netif/Makefile

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see #10546

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, see #10524 where introduce stuff to this file that is not IPv6 specific, as reflected by the name.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could make a separate submodule gnrc_netif_ipv6_device_type, but that would go against the centralizing idea of #10524 (putting all device-type depending and #ifdef constructed functions in one place.

#if defined(MODULE_CC110X) || defined(MODULE_NRFMIN)
static void _create_iid_from_short(const uint8_t *addr, size_t addr_len,
eui64_t *iid)
{
const unsigned offset = sizeof(eui64_t) - addr_len;

memset(iid->uint8, 0, sizeof(iid->uint8));
iid->uint8[3] = 0xff;
iid->uint8[4] = 0xfe;
memcpy(&iid->uint8[offset], addr, addr_len);
}
#endif /* defined(MODULE_CC110X) || defined(MODULE_NRFMIN) */

int gnrc_netif_ipv6_iid_from_addr(const gnrc_netif_t *netif,
const uint8_t *addr, size_t addr_len,
eui64_t *iid)
{
miri64 marked this conversation as resolved.
Show resolved Hide resolved
#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 == ETHERNET_ADDR_LEN) {
ethernet_get_iid(iid, (uint8_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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is never reached (every switch statement terminates, see the assert(false)). Is this wanted? So probably the doc for this functions needs to be updated...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is reached if NDEBUG is defined, in which case assert() does not generate any code. This is exactly the behavior documented.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What @maribu is saying. Also it is in accordance with what you proposed ;-).

}

int gnrc_netif_ipv6_iid_to_addr(const gnrc_netif_t *netif, const eui64_t *iid,
uint8_t *addr)
{
assert(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:
addr[0] = iid->uint8[0] ^ 0x02;
addr[1] = iid->uint8[1];
addr[2] = iid->uint8[2];
addr[3] = iid->uint8[5];
addr[4] = iid->uint8[6];
addr[5] = iid->uint8[7];
return ETHERNET_ADDR_LEN;
#endif /* defined(MODULE_NETDEV_ETH) || defined(MODULE_ESP_NOW) */
#if defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE)
case NETDEV_TYPE_IEEE802154:
/* assume address was based on EUI-64
* (see https://tools.ietf.org/html/rfc6775#section-5.2) */
memcpy(addr, iid, sizeof(eui64_t));
addr[0] ^= 0x02;
return sizeof(eui64_t);
#endif /* defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE) */
#ifdef MODULE_NRFMIN
case NETDEV_TYPE_NRFMIN:
addr[0] = iid->uint8[6];
addr[1] = iid->uint8[7];
return sizeof(uint16_t);
#endif /* MODULE_NETDEV_IEEE802154 */
#ifdef MODULE_NORDIC_SOFTDEVICE_BLE
case NETDEV_TYPE_BLE:
memcpy(addr, iid, sizeof(eui64_t));
addr[0] ^= 0x02;
return sizeof(eui64_t);
#endif /* MODULE_NORDIC_SOFTDEVICE_BLE */
#ifdef MODULE_CC110X
case NETDEV_TYPE_CC110X:
addr[0] = iid->uint8[7];
return sizeof(uint8_t);
#endif /* MODULE_CC110X */
default:
(void)iid;
(void)addr;
#ifdef DEVELHELP
LOG_ERROR("gnrc_netif: can't convert IID to hardware address "
"on interface %u\n", netif->pid);
#endif /* DEVELHELP */
assert(false);
break;
}
return -ENOTSUP;
miri64 marked this conversation as resolved.
Show resolved Hide resolved
}
#endif /* MODULE_GNRC_IPV6 */

/** @} */
45 changes: 3 additions & 42 deletions sys/net/gnrc/network_layer/ipv6/nib/_nib-6ln.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,47 +36,6 @@ static inline bool _is_iface_eui64(gnrc_netif_t *netif, const eui64_t *eui64)
(memcmp(&netif->l2addr, eui64, netif->l2addr_len) == 0);
}

static inline uint8_t _reverse_iid(const ipv6_addr_t *dst,
const gnrc_netif_t *netif, uint8_t *l2addr)
{
switch (netif->device_type) {
#if defined(MODULE_NETDEV_ETH) || defined(MODULE_ESP_NOW)
case NETDEV_TYPE_ETHERNET:
case NETDEV_TYPE_ESP_NOW:
l2addr[0] = dst->u8[8] ^ 0x02;
l2addr[1] = dst->u8[9];
l2addr[2] = dst->u8[10];
l2addr[3] = dst->u8[13];
l2addr[4] = dst->u8[14];
l2addr[5] = dst->u8[15];
return ETHERNET_ADDR_LEN;
#endif /* defined(MODULE_NETDEV_ETH) || defined(MODULE_ESP_NOW) */
#if defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE)
case NETDEV_TYPE_IEEE802154:
/* assume address was based on EUI-64
* (see https://tools.ietf.org/html/rfc6775#section-5.2) */
memcpy(l2addr, &dst->u64[1], sizeof(dst->u64[1]));
l2addr[0] ^= 0x02;
return sizeof(dst->u64[1]);
#endif /* defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE) */
#ifdef MODULE_NRFMIN
case NETDEV_TYPE_NRFMIN:
l2addr[0] = dst->u8[14];
l2addr[1] = dst->u8[15];
return sizeof(uint16_t);
#endif /* MODULE_NETDEV_IEEE802154 */
#ifdef MODULE_CC110X
case NETDEV_TYPE_CC110X:
l2addr[0] = dst->u8[15];
return sizeof(uint8_t);
#endif /* MODULE_CC110X */
default:
(void)dst;
(void)l2addr;
return 0;
}
}

bool _resolve_addr_from_ipv6(const ipv6_addr_t *dst, gnrc_netif_t *netif,
gnrc_ipv6_nib_nc_t *nce)
{
Expand All @@ -86,7 +45,9 @@ bool _resolve_addr_from_ipv6(const ipv6_addr_t *dst, gnrc_netif_t *netif,
if (res) {
uint8_t l2addr_len;

if ((l2addr_len = _reverse_iid(dst, netif, nce->l2addr)) > 0) {
if ((l2addr_len = gnrc_netif_ipv6_iid_to_addr(netif,
(eui64_t *)&dst->u64[1],
nce->l2addr)) > 0) {
DEBUG("nib: resolve address %s%%%u by reverse translating to ",
ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)),
(unsigned)netif->pid);
Expand Down
2 changes: 1 addition & 1 deletion tests/gnrc_sock_udp/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
include ../Makefile.tests_common

BOARD_INSUFFICIENT_MEMORY := arduino-duemilanove arduino-uno \
BOARD_INSUFFICIENT_MEMORY := arduino-mega2560 arduino-duemilanove arduino-uno \
chronos nucleo-f031k6 nucleo-f042k6 nucleo-l031k6 \
waspmote-pro

Expand Down