mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
l2util: initial import
This module provide stack independently (just dependent on netdev's network device types) several helper functions to get IPv6 over X specific values.
This commit is contained in:
parent
664763bb29
commit
573549c41f
@ -146,6 +146,7 @@ endif
|
||||
|
||||
ifneq (,$(filter gnrc_netif,$(USEMODULE)))
|
||||
USEMODULE += netif
|
||||
USEMODULE += l2util
|
||||
USEMODULE += fmt
|
||||
ifneq (,$(filter netdev_ieee802154,$(USEMODULE)))
|
||||
USEMODULE += gnrc_netif_ieee802154
|
||||
|
@ -121,6 +121,9 @@ endif
|
||||
ifneq (,$(filter l2filter,$(USEMODULE)))
|
||||
DIRS += net/link_layer/l2filter
|
||||
endif
|
||||
ifneq (,$(filter l2util,$(USEMODULE)))
|
||||
DIRS += net/link_layer/l2util
|
||||
endif
|
||||
ifneq (,$(filter nanocoap,$(USEMODULE)))
|
||||
DIRS += net/application_layer/nanocoap
|
||||
endif
|
||||
|
142
sys/include/net/l2util.h
Normal file
142
sys/include/net/l2util.h
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup net_l2util Stack-independent helpers for IPv6 over X
|
||||
* @ingroup net
|
||||
* @brief This implements some common helper functions for IPv6 over X
|
||||
* implementations based on [network device types]
|
||||
* (@ref net_netdev_type).
|
||||
*
|
||||
* @attention If you add a new [network device type](@ref net_netdev_type)
|
||||
* have at least a look at the implementation of these functions.
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Link-layer helper function definitions
|
||||
*
|
||||
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||
*/
|
||||
#ifndef NET_L2UTIL_H
|
||||
#define NET_L2UTIL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "net/eui64.h"
|
||||
#include "net/ndp.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define L2UTIL_ADDR_MAX_LEN (8U) /**< maximum expected length for addresses */
|
||||
|
||||
/**
|
||||
* @brief Converts a given hardware address to an EUI-64.
|
||||
*
|
||||
* @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] dev_type The network device type of the device @p addr came from
|
||||
* (either because it is the configured address of the
|
||||
* device 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] eui64 The EUI-64 based on gnrc_netif_t::device_type
|
||||
*
|
||||
* @return `sizeof(eui64_t)` on success.
|
||||
* @return `-ENOTSUP`, when @p dev_type does not support EUI-64 conversion.
|
||||
* @return `-EINVAL`, when @p addr_len is invalid for the @p dev_type.
|
||||
*/
|
||||
int l2util_eui64_from_addr(int dev_type, const uint8_t *addr, size_t addr_len,
|
||||
eui64_t *eui64);
|
||||
|
||||
/**
|
||||
* @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] dev_type The network device type of the device @p addr came from
|
||||
* (either because it is the configured address of the
|
||||
* device 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 @p dev_type does not support IID conversion.
|
||||
* @return `-EINVAL`, when @p addr_len is invalid for the @p dev_type.
|
||||
*/
|
||||
int l2util_ipv6_iid_from_addr(int dev_type,
|
||||
const uint8_t *addr, size_t addr_len,
|
||||
eui64_t *iid);
|
||||
|
||||
/**
|
||||
* @brief Converts an IPv6 IID to a hardware address
|
||||
*
|
||||
* @pre @p iid was based on a hardware address
|
||||
* @pre The number of bytes available at @p addr is less or equal to
|
||||
* @ref L2UTIL_ADDR_MAX_LEN.
|
||||
*
|
||||
* @attention When `NDEBUG` is not defined, the node fails with an assertion
|
||||
* instead of returning `-ENOTSUP`
|
||||
*
|
||||
* @param[in] dev_type The network device type of the device the @p iid came
|
||||
* from (either because it is based on the configured
|
||||
* address of the device or from a packet that came over
|
||||
* it).
|
||||
* @param[in] iid An IID based on @p dev_type.
|
||||
* @param[out] addr The hardware address. It is assumed that @p iid was
|
||||
* based on a hardware address and that the available
|
||||
* number of bytes in @p addr are greater or equal to
|
||||
* @ref L2UTIL_ADDR_MAX_LEN.
|
||||
*
|
||||
* @return Length of resulting @p addr on success.
|
||||
* @return `-ENOTSUP`, when @p dev_type does not support reverse IID
|
||||
* conversion.
|
||||
*/
|
||||
int l2util_ipv6_iid_to_addr(int dev_type, const eui64_t *iid, uint8_t *addr);
|
||||
|
||||
/**
|
||||
* @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)
|
||||
*
|
||||
* @attention When `NDEBUG` is not defined, the node fails with an assertion
|
||||
* instead of returning `-ENOTSUP`
|
||||
*
|
||||
* @param[in] dev_type The network device type of the device the @p opt came
|
||||
* over in 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 @p dev_type.
|
||||
* @return `-EINVAL` if `opt->len` was an invalid value for the given
|
||||
* @p dev_type.
|
||||
*/
|
||||
int l2util_ndp_addr_len_from_l2ao(int dev_type,
|
||||
const ndp_opt_t *opt);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NET_L2UTIL_H */
|
||||
/** @} */
|
1
sys/net/link_layer/l2util/Makefile
Normal file
1
sys/net/link_layer/l2util/Makefile
Normal file
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
228
sys/net/link_layer/l2util/l2util.c
Normal file
228
sys/net/link_layer/l2util/l2util.c
Normal file
@ -0,0 +1,228 @@
|
||||
/*
|
||||
* 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
|
||||
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "net/eui48.h"
|
||||
#include "net/ieee802154.h"
|
||||
#include "net/ipv6.h"
|
||||
#include "net/netdev.h"
|
||||
|
||||
#include "net/l2util.h"
|
||||
|
||||
#if defined(MODULE_CC110X) || defined(MODULE_NRFMIN)
|
||||
static void _create_eui64_from_short(const uint8_t *addr, size_t addr_len,
|
||||
eui64_t *eui64)
|
||||
{
|
||||
const unsigned offset = sizeof(eui64_t) - addr_len;
|
||||
|
||||
memset(eui64->uint8, 0, sizeof(eui64->uint8));
|
||||
eui64->uint8[3] = 0xff;
|
||||
eui64->uint8[4] = 0xfe;
|
||||
memcpy(&eui64->uint8[offset], addr, addr_len);
|
||||
}
|
||||
#endif /* defined(MODULE_CC110X) || defined(MODULE_NRFMIN) */
|
||||
|
||||
int l2util_eui64_from_addr(int dev_type, const uint8_t *addr, size_t addr_len,
|
||||
eui64_t *eui64)
|
||||
{
|
||||
switch (dev_type) {
|
||||
#if defined(MODULE_NETDEV_ETH) || defined(MODULE_ESP_NOW) || \
|
||||
defined(MODULE_NORDIC_SOFTDEVICE_BLE)
|
||||
case NETDEV_TYPE_ETHERNET:
|
||||
case NETDEV_TYPE_ESP_NOW:
|
||||
case NETDEV_TYPE_BLE:
|
||||
if (addr_len == sizeof(eui48_t)) {
|
||||
eui48_to_eui64(eui64, (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:
|
||||
switch (addr_len) {
|
||||
/* EUI-64 can *not* be generated from the short address */
|
||||
case IEEE802154_LONG_ADDRESS_LEN:
|
||||
memcpy(eui64, addr, addr_len);
|
||||
return sizeof(eui64_t);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif /* defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE) */
|
||||
#if defined(MODULE_CC110X) || defined(MODULE_NRFMIN)
|
||||
case NETDEV_TYPE_CC110X:
|
||||
case NETDEV_TYPE_NRFMIN:
|
||||
if (addr_len <= 3) {
|
||||
_create_eui64_from_short(addr, addr_len, eui64);
|
||||
return sizeof(eui64_t);
|
||||
}
|
||||
else {
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif /* defined(MODULE_CC110X) || defined(MODULE_NRFMIN) */
|
||||
default:
|
||||
(void)addr;
|
||||
(void)addr_len;
|
||||
(void)eui64;
|
||||
#ifdef DEVELHELP
|
||||
LOG_ERROR("l2util: can't convert hardware address to EUI-64 "
|
||||
"for device type %d\n", dev_type);
|
||||
#endif /* DEVELHELP */
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int l2util_ipv6_iid_from_addr(int dev_type,
|
||||
const uint8_t *addr, size_t addr_len,
|
||||
eui64_t *iid)
|
||||
{
|
||||
switch (dev_type) {
|
||||
#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) */
|
||||
#if defined(MODULE_CC110X) || defined(MODULE_NRFMIN)
|
||||
case NETDEV_TYPE_CC110X:
|
||||
case NETDEV_TYPE_NRFMIN:
|
||||
if (addr_len <= 3) {
|
||||
_create_eui64_from_short(addr, addr_len, iid);
|
||||
/* since this address conversion is based on the IEEE
|
||||
* 802.15.4 address conversion for short addresses, the
|
||||
* U/L bit doesn't need to be flipped.
|
||||
* see https://tools.ietf.org/html/rfc6282#section-3.2.2 */
|
||||
return sizeof(eui64_t);
|
||||
}
|
||||
else {
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif /* defined(MODULE_CC110X) || defined(MODULE_NRFMIN) */
|
||||
default: {
|
||||
int res = l2util_eui64_from_addr(dev_type, addr, addr_len, iid);
|
||||
if (res == sizeof(eui64_t)) {
|
||||
iid->uint8[0] ^= 0x02;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int l2util_ipv6_iid_to_addr(int dev_type, const eui64_t *iid, uint8_t *addr)
|
||||
{
|
||||
switch (dev_type) {
|
||||
#if defined(MODULE_NETDEV_ETH) || defined(MODULE_ESP_NOW) || \
|
||||
defined(MODULE_NORDIC_SOFTDEVICE_BLE)
|
||||
case NETDEV_TYPE_ETHERNET:
|
||||
case NETDEV_TYPE_ESP_NOW:
|
||||
case NETDEV_TYPE_BLE:
|
||||
eui48_from_ipv6_iid((eui48_t *)addr, iid);
|
||||
return sizeof(eui48_t);
|
||||
#endif /* defined(MODULE_NETDEV_ETH) || defined(MODULE_ESP_NOW) || \
|
||||
* defined(MODULE_NORDIC_SOFTDEVICE_BLE) */
|
||||
#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_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("l2util: can't convert IID to hardware address for "
|
||||
"device type %d\n", dev_type);
|
||||
#endif /* DEVELHELP */
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int l2util_ndp_addr_len_from_l2ao(int dev_type,
|
||||
const ndp_opt_t *opt)
|
||||
{
|
||||
switch (dev_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) || \
|
||||
defined(MODULE_NORDIC_SOFTDEVICE_BLE)
|
||||
case NETDEV_TYPE_ETHERNET:
|
||||
case NETDEV_TYPE_ESP_NOW:
|
||||
case NETDEV_TYPE_BLE:
|
||||
/* see https://tools.ietf.org/html/rfc2464#section-6*/
|
||||
if (opt->len == 1U) {
|
||||
return sizeof(eui48_t);
|
||||
}
|
||||
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("l2util: can't get address length from NDP link-layer "
|
||||
"address option for device type %d\n", dev_type);
|
||||
#endif
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
|
||||
/** @} */
|
Loading…
Reference in New Issue
Block a user