1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #14634 from benpicco/eui_provider

net/link_layer: implement EUI provider
This commit is contained in:
Francisco 2020-09-01 16:26:08 +02:00 committed by GitHub
commit 6f84870c26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 574 additions and 5 deletions

View File

@ -189,6 +189,10 @@ ifneq (,$(filter trickle,$(USEMODULE)))
USEMODULE += xtimer
endif
ifneq (,$(filter eui_provider,$(USEMODULE)))
USEMODULE += luid
endif
ifneq (,$(filter gnrc_netif,$(USEMODULE)))
USEMODULE += netif
USEMODULE += l2util

View File

@ -1,5 +1,9 @@
USEMODULE += boards_common_atmega
ifneq (,$(filter eui_provider,$(USEMODULE)))
USEMODULE += at24mac
endif
ifneq (,$(filter saul_default,$(USEMODULE)))
USEMODULE += bme280_i2c
USEMODULE += saul_gpio

View File

@ -23,6 +23,9 @@
#include "cpu.h"
#include "periph/gpio.h"
#include "at24mac.h"
#include "net/eui_provider.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -35,6 +38,24 @@ extern "C" {
#define AT24MAC_PARAM_TYPE AT24MAC6XX
/** @} */
/**
* @brief AT24Mac provides a EUI-64, this is also printed on the board
*/
static inline int _at24mac_get_eui64(const void *arg, eui64_t *addr)
{
return at24mac_get_eui64((uintptr_t)arg, addr);
}
/**
* @name EUI-64 sources on the board
* AT24Mac is present on the board
* @{
*/
#define EUI64_PROVIDER_FUNC _at24mac_get_eui64
#define EUI64_PROVIDER_TYPE NETDEV_AT86RF2XX
#define EUI64_PROVIDER_INDEX 0
/** @} */
/**
* @name LED pin definitions and handlers
* @{

View File

@ -1 +1,5 @@
USEMODULE += boards_common_atmega
ifneq (,$(filter eui_provider,$(USEMODULE)))
FEATURES_REQUIRED += periph_eeprom
endif

View File

@ -21,10 +21,44 @@
#include "cpu.h"
#include "periph/eeprom.h"
#include "net/eui_provider.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name MAC configuration
* Offset of the MAC address in the EEPROM
*/
#define EEPROM_MAC_ADDR (0x1fe4)
/**
* @brief Constant in EEPROM provides a EUI-64, this is also printed on the board
*/
static inline int _eeprom_mac_get_eui64(const void *arg, eui64_t *addr)
{
(void) arg;
if (eeprom_read(EEPROM_MAC_ADDR, addr, sizeof(eui64_t)) != sizeof(eui64_t)) {
return -1;
}
addr->uint64.u64 = byteorder_htonll(addr->uint64.u64).u64;
return 0;
}
/**
* @name EUI-64 sources on the board
* @{
*/
#define EUI64_PROVIDER_FUNC _eeprom_mac_get_eui64
#define EUI64_PROVIDER_TYPE NETDEV_AT86RF2XX
#define EUI64_PROVIDER_INDEX 0
/** @} */
/**
* @name xtimer configuration values
* @{

View File

@ -2,6 +2,10 @@ ifneq (,$(filter netdev_default,$(USEMODULE)))
USEMODULE += at86rf233
endif
ifneq (,$(filter eui_provider,$(USEMODULE)))
USEMODULE += edbg_eui
endif
ifneq (,$(filter saul_default,$(USEMODULE)))
USEMODULE += saul_gpio
endif

View File

@ -25,6 +25,8 @@
#include "periph_conf.h"
#include "periph_cpu.h"
#include "edbg_eui.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -57,6 +59,25 @@ extern "C" {
#define AT86RF2XX_PARAM_SLEEP GPIO_PIN(PA, 20)
#define AT86RF2XX_PARAM_RESET GPIO_PIN(PB, 15)
/**
* @brief EDBG provides a EUI-64, the same that is printed on the board
*/
static inline int _edbg_get_eui64(const void *arg, eui64_t *addr)
{
(void) arg;
return edbg_get_eui64(addr);
}
/**
* @name EUI sources on the board
* EUI-64 inside EDBG for the internal radio
* @{
*/
#define EUI64_PROVIDER_FUNC _edbg_get_eui64
#define EUI64_PROVIDER_TYPE NETDEV_AT86RF2XX
#define EUI64_PROVIDER_INDEX 0
/** @} */
/**
* @name OpenWSN timing constants
*

View File

@ -16,7 +16,6 @@ ifeq (,$(filter at86rf215m,$(USEMODULE)))
endif
USEMODULE += xtimer
USEMODULE += luid
USEMODULE += netif
USEMODULE += ieee802154
USEMODULE += netdev_ieee802154

View File

@ -2,7 +2,6 @@ DEFAULT_MODULE += auto_init_at86rf2xx
DEFAULT_MODULE += netdev_ieee802154_oqpsk
USEMODULE += xtimer
USEMODULE += luid
USEMODULE += netif
USEMODULE += ieee802154
USEMODULE += netdev_ieee802154

View File

@ -20,11 +20,11 @@
#ifndef NET_NETDEV_IEEE802154_H
#define NET_NETDEV_IEEE802154_H
#include "net/eui_provider.h"
#include "net/ieee802154.h"
#include "net/gnrc/nettype.h"
#include "net/netopt.h"
#include "net/netdev.h"
#include "luid.h"
#ifdef __cplusplus
extern "C" {
@ -208,8 +208,10 @@ int netdev_ieee802154_dst_filter(netdev_ieee802154_t *dev, const uint8_t *mhr);
*/
static inline void netdev_ieee802154_setup(netdev_ieee802154_t *dev)
{
luid_netdev_get_eui64(&dev->netdev, (eui64_t *)&dev->long_addr);
luid_get_short((network_uint16_t *)&dev->short_addr);
/* generate EUI-64 and short address */
netdev_eui64_get(&dev->netdev, (eui64_t *)&dev->long_addr);
eui_short_from_eui64((eui64_t *)&dev->long_addr,
(network_uint16_t *)&dev->short_addr);
}
#ifdef __cplusplus

View File

@ -0,0 +1 @@
USEMODULE += eui_provider

View File

@ -47,6 +47,9 @@ endif
ifneq (,$(filter emcute,$(USEMODULE)))
DIRS += net/application_layer/emcute
endif
ifneq (,$(filter eui_provider,$(USEMODULE)))
DIRS += net/link_layer/eui_provider
endif
ifneq (,$(filter fib,$(USEMODULE)))
DIRS += net/network_layer/fib
endif

View File

@ -33,6 +33,10 @@ ifneq (,$(filter oneway_malloc,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/oneway-malloc/include
endif
ifneq (,$(filter eui_provider,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/link_layer/eui_provider/include
endif
ifneq (,$(filter app_metadata,$(USEMODULE)))
# Overwrite the application shell formats.
# This is an optional macro that can be used to coordinate

View File

@ -0,0 +1,209 @@
/*
* Copyright (C) 2020 ML!PA Consulting GmbH
*
* 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_eui_provider IEEE EUI-48/64 provider
* @ingroup net
* @brief MAC address management
*
* About
* =====
*
* An EUI provider provides an Extended Unique Identifier, that is
* a hardware address for a network device.
*
* A board may have an EEPROM with a unique ID (e.g. @ref drivers_at24mac) that is used
* to store an address, a unique address is stored in a config
* area of the board's flash during production, etc.
*
* The EUI provider is connected to a network device that will then use
* this address.
*
* How it works
* ============
*
* If there is only one EUI provider on the board, the configuration
* is done through three defines:
*
* - `EUIxx_PROVIDER_TYPE` to specify which device the EUI should be used for.
* That is to prevent it from matching to 'virtual' devices like ethos or SLIP.
* It is of course also possible to provide a fixed address for 'virtual' devices
* this way.
* - `EUIxx_PROVIDER_INDEX` to specify which interface the EUI should be used for if
* there are multiple interfaces.
*
* - `EUIxx_PROVIDER_FUNC` the function that provides the EUI. It can use an optional
* `EUIxx_PROVIDER_ARG` argument that is passed unmodified.
*
* If more than one EUI provider is present on the board, an array of `euiXX_conf_t`
* has to be provided to `EUI64_PROVIDER_PARAMS`:
*
* ```C
* #define EUI64_PROVIDER_PARAMS { \
* .provider = _board_get_eui, \
* .arg = BOARD_ADDR_SUBGHZ, \
* .type = NETDEV_AT86RF215, \
* .index = 0, }, \
* { \
* .provider = _board_get_eui, \
* .arg = BOARD_ADDR_24GHZ, \
* .type = NETDEV_AT86RF215, \
* .index = 1, }
* ```
*
* This also assumes a `_board_get_eui()` function to provide the EUI.
* For example, it could read an EUI from a config region on the flash
* that is provided with the memory-mapped addresses `BOARD_ADDR_SUBGHZ` and
* `BOARD_ADDR_24GHZ`.
* The function would then do
*
* ```C
* static inline int _board_get_eui(const void *src, eui64_t *addr)
* {
* memcpy(addr, src, sizeof(*addr));
* return 0;
* }
*
* ```
*
* Recommendations
* ===============
*
* While it is possible to match EUIs with any netdev in a first come, first serve
* fashion (`NETDEV_ANY`, `NETDEV_INDEX_ANY`) it is recommended to fix the EUI
* providers to a device and interface to avoid them being used for 'virtual'
* interfaces.
*
* Fixed addresses are only guaranteed if the network devices are also fixed.
* E.g. if you usually have two netdevs and disable the first one at compile-time
* the second interface will now use the first slot / index and therefore also
* use the EUI provider that was previously used by interface in the first slot.
*
* @{
*
* @file
* @brief EUI-48 and EUI-64 address provider
*
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
*/
#ifndef NET_EUI_PROVIDER_H
#define NET_EUI_PROVIDER_H
#include "net/eui48.h"
#include "net/eui64.h"
#include "net/netdev.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Will match any device index
*/
#define NETDEV_INDEX_ANY (0xFF)
/**
* @brief Function for providing a EUI-48 to a device
*
* @param[in] arg Optional argument provided by eui48_conf_t
* @param[out] addr Destination pointer for the EUI-48 address
*
* @return 0 on success, next provider in eui48_conf_t will be
* used otherwise.
* Will fall back to @see luid_get_eui48 eventually.
*/
typedef int (*netdev_get_eui48_cb_t)(const void *arg, eui48_t *addr);
/**
* @brief Function for providing a EUI-64 to a device
*
* @param[in] arg Optional argument provided by eui64_conf_t
* @param[out] addr Destination pointer for the EUI-64 address
*
* @return 0 on success, next provider in eui64_conf_t will be
* used otherwise.
* Will fall back to @see luid_get_eui64 eventually.
*/
typedef int (*netdev_get_eui64_cb_t)(const void *arg, eui64_t *addr);
/**
* @brief Structure to hold providers for EUI-48 addresses
*/
typedef struct {
netdev_get_eui48_cb_t provider; /**< function to provide an EUI-48 */
const void *arg; /**< argument to the provider function */
netdev_type_t type; /**< device type to match or `NETDEV_ANY` */
uint8_t index; /**< device index to match or `NETDEV_INDEX_ANY` */
} eui48_conf_t;
/**
* @brief Structure to hold providers for EUI-64 addresses
*/
typedef struct {
netdev_get_eui64_cb_t provider; /**< function to provide an EUI-64 */
const void *arg; /**< argument to the provider function */
netdev_type_t type; /**< device type to match or `NETDEV_ANY` */
uint8_t index; /**< device index to match or `NETDEV_INDEX_ANY` */
} eui64_conf_t;
/**
* @brief Generates an EUI-48 address for the netdev interface.
*
* @note It is possible to supply a board-specific, constant address
* by implementing a EUI-48 provider function.
* If no such function is available, this will fall back to
* @ref luid_get_eui48.
*
* @param[in] netdev The network device for which the address is
* generated.
* @param[out] addr The generated EUI-48 address
*
*/
void netdev_eui48_get(netdev_t *netdev, eui48_t *addr);
/**
* @brief Generates an EUI-64 address for the netdev interface.
*
* @note It is possible to supply a board-specific, constant address
* by implementing a EUI-64 provider function.
* If no such function is available, this will fall back to
* @ref luid_get_eui64.
*
* @param[in] netdev The network device for which the address is
* generated.
* @param[out] addr The generated EUI-64 address
*
*/
void netdev_eui64_get(netdev_t *netdev, eui64_t *addr);
/**
* @brief Get a short unicast address from an EUI-64
*
* The resulting address is built from the provided long address.
* The last two bytes of the long address will be used as the short
* address with the first bit cleared.
*
* @param[in] addr_long the address to base the short address on
* @param[out] addr_short memory location to copy the address into.
*/
static inline void eui_short_from_eui64(eui64_t *addr_long,
network_uint16_t *addr_short)
{
/* https://tools.ietf.org/html/rfc4944#section-12 requires the first bit to
* 0 for unicast addresses */
addr_short->u8[0] = addr_long->uint8[6] & 0x7F;
addr_short->u8[1] = addr_long->uint8[7];
}
#ifdef __cplusplus
}
#endif
#endif /* NET_EUI_PROVIDER_H */
/** @} */

View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,71 @@
/*
* Copyright (C) 2020 ML!PA Consulting GmbH
*
* 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 Benjamin Valentin <benjamin.valentin@ml-pa.com>
*/
#include "eui48_provider_params.h"
#include "eui64_provider_params.h"
#include "luid.h"
#include "net/eui_provider.h"
void netdev_eui48_get(netdev_t *netdev, eui48_t *addr)
{
unsigned i = EUI48_PROVIDER_NUMOF;
while (i--) {
#ifdef MODULE_NETDEV_REGISTER
if (eui48_conf[i].type != netdev->type &&
eui48_conf[i].type != NETDEV_ANY) {
continue;
}
if (eui48_conf[i].index != netdev->index &&
eui48_conf[i].index != NETDEV_INDEX_ANY) {
continue;
}
#else
(void) netdev;
#endif
if (eui48_conf[i].provider(eui48_conf[i].arg, addr) == 0) {
return;
}
}
luid_netdev_get_eui48(netdev, addr);
}
void netdev_eui64_get(netdev_t *netdev, eui64_t *addr)
{
unsigned i = EUI64_PROVIDER_NUMOF;
while (i--) {
#ifdef MODULE_NETDEV_REGISTER
if (eui64_conf[i].type != netdev->type &&
eui64_conf[i].type != NETDEV_ANY) {
continue;
}
if (eui64_conf[i].index != netdev->index &&
eui64_conf[i].index != NETDEV_INDEX_ANY) {
continue;
}
#else
(void) netdev;
#endif
if (eui64_conf[i].provider(eui64_conf[i].arg, addr) == 0) {
return;
}
}
luid_netdev_get_eui64(netdev, addr);
}
/** @} */

View File

@ -0,0 +1,94 @@
/*
* Copyright (C) 2020 ML!PA Consulting GmbH
*
* 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.
*/
/**
* @ingroup net_eui_provider
*
* @file
* @brief EUI-48 address provider default values
*
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
*/
#ifndef EUI48_PROVIDER_PARAMS_H
#define EUI48_PROVIDER_PARAMS_H
#include "board.h"
#include "net/eui_provider.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief A `netdev_get_eui48_cb_t` function
*/
#ifndef EUI48_PROVIDER_FUNC
#define EUI48_PROVIDER_FUNC NULL
/**
* @brief Number of EUI-48 providers, determined automatically
*/
#ifndef EUI48_PROVIDER_PARAMS
#define EUI48_PROVIDER_NUMOF 0U
#endif
#endif
/**
* @brief Optional function argument to `netdev_get_eui48_cb_t`
*/
#ifndef EUI48_PROVIDER_ARG
#define EUI48_PROVIDER_ARG NULL
#endif
/**
* @brief Driver type to match with EUI-48 provider
*/
#ifndef EUI48_PROVIDER_TYPE
#define EUI48_PROVIDER_TYPE NETDEV_ANY
#endif
/**
* @brief If multiple instances of a device exist, which one should
* be assigned the EUI-48
*/
#ifndef EUI48_PROVIDER_INDEX
#define EUI48_PROVIDER_INDEX NETDEV_INDEX_ANY
#endif
/**
* @brief Array of available EUI-48 providers
*/
#ifndef EUI48_PROVIDER_PARAMS
#define EUI48_PROVIDER_PARAMS { \
.provider = EUI48_PROVIDER_FUNC, \
.arg = EUI48_PROVIDER_ARG, \
.type = EUI48_PROVIDER_TYPE, \
.index = EUI48_PROVIDER_INDEX, \
},
#endif
/**
* @name EUI-48 sources on the board
*
* @{
*/
static const eui48_conf_t eui48_conf[] = {
EUI48_PROVIDER_PARAMS
};
#ifndef EUI48_PROVIDER_NUMOF
#define EUI48_PROVIDER_NUMOF ARRAY_SIZE(eui48_conf)
#endif
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* EUI48_PROVIDER_PARAMS_H */

View File

@ -0,0 +1,94 @@
/*
* Copyright (C) 2020 ML!PA Consulting GmbH
*
* 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.
*/
/**
* @ingroup net_eui_provider
*
* @file
* @brief EUI-64 address provider default values
*
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
*/
#ifndef EUI64_PROVIDER_PARAMS_H
#define EUI64_PROVIDER_PARAMS_H
#include "board.h"
#include "net/eui_provider.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief A `netdev_get_eui64_cb_t` function
*/
#ifndef EUI64_PROVIDER_FUNC
#define EUI64_PROVIDER_FUNC NULL
/**
* @brief Number of EUI-64 providers, determined automatically
*/
#ifndef EUI64_PROVIDER_PARAMS
#define EUI64_PROVIDER_NUMOF 0U
#endif
#endif
/**
* @brief Optional function argument to `netdev_get_eui64_cb_t`
*/
#ifndef EUI64_PROVIDER_ARG
#define EUI64_PROVIDER_ARG NULL
#endif
/**
* @brief Driver type to match with EUI-64 provider
*/
#ifndef EUI64_PROVIDER_TYPE
#define EUI64_PROVIDER_TYPE NETDEV_ANY
#endif
/**
* @brief If multiple instances of a device exist, which one should
* be assigned the EUI-64
*/
#ifndef EUI64_PROVIDER_INDEX
#define EUI64_PROVIDER_INDEX NETDEV_INDEX_ANY
#endif
/**
* @brief Array of available EUI-64 providers
*/
#ifndef EUI64_PROVIDER_PARAMS
#define EUI64_PROVIDER_PARAMS { \
.provider = EUI64_PROVIDER_FUNC, \
.arg = EUI64_PROVIDER_ARG, \
.type = EUI64_PROVIDER_TYPE, \
.index = EUI64_PROVIDER_INDEX, \
},
#endif
/**
* @name EUI-64 sources on the board
*
* @{
*/
static const eui64_conf_t eui64_conf[] = {
EUI64_PROVIDER_PARAMS
};
#ifndef EUI64_PROVIDER_NUMOF
#define EUI64_PROVIDER_NUMOF ARRAY_SIZE(eui64_conf)
#endif
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* EUI64_PROVIDER_PARAMS_H */