diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index ffa950cae2..e51c1100ad 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -8,6 +8,7 @@ endif ifneq (,$(filter at86rf2%,$(USEMODULE))) USEMODULE += at86rf2xx USEMODULE += xtimer + USEMODULE += uuid USEMODULE += netif USEMODULE += ieee802154 USEMODULE += netdev2_ieee802154 @@ -30,6 +31,7 @@ endif ifneq (,$(filter cc110x,$(USEMODULE))) USEMODULE += ieee802154 + USEMODULE += uuid ifneq (,$(filter gnrc_netdev_default,$(USEMODULE))) USEMODULE += gnrc_cc110x # XXX: this can be modelled as a dependency for gnrc_netdev_default as soon @@ -40,6 +42,7 @@ endif ifneq (,$(filter cc2420,$(USEMODULE))) USEMODULE += xtimer + USEMODULE += uuid USEMODULE += netif USEMODULE += ieee802154 USEMODULE += netdev2_ieee802154 @@ -60,6 +63,7 @@ endif ifneq (,$(filter enc28j60,$(USEMODULE))) USEMODULE += netdev2_eth USEMODULE += xtimer + USEMODULE += uuid endif ifneq (,$(filter encx24j600,$(USEMODULE))) @@ -152,6 +156,7 @@ endif ifneq (,$(filter w5100,$(USEMODULE))) USEMODULE += netdev2_eth + USEMODULE += uuid endif ifneq (,$(filter xbee,$(USEMODULE))) diff --git a/drivers/at86rf2xx/at86rf2xx.c b/drivers/at86rf2xx/at86rf2xx.c index 427408f16a..8f28b4f712 100644 --- a/drivers/at86rf2xx/at86rf2xx.c +++ b/drivers/at86rf2xx/at86rf2xx.c @@ -23,7 +23,8 @@ * @} */ -#include "periph/cpuid.h" + +#include "uuid.h" #include "byteorder.h" #include "net/ieee802154.h" #include "net/gnrc.h" @@ -51,15 +52,7 @@ void at86rf2xx_setup(at86rf2xx_t *dev, const at86rf2xx_params_t *params) void at86rf2xx_reset(at86rf2xx_t *dev) { -#if CPUID_LEN -/* make sure that the buffer is always big enough to store a 64bit value */ -# if CPUID_LEN < IEEE802154_LONG_ADDRESS_LEN - uint8_t cpuid[IEEE802154_LONG_ADDRESS_LEN]; -# else - uint8_t cpuid[CPUID_LEN]; -#endif eui64_t addr_long; -#endif at86rf2xx_hardware_reset(dev); @@ -69,30 +62,16 @@ void at86rf2xx_reset(at86rf2xx_t *dev) /* reset options and sequence number */ dev->netdev.seq = 0; dev->netdev.flags = 0; - /* set short and long address */ -#if CPUID_LEN - /* in case CPUID_LEN < 8, fill missing bytes with zeros */ - memset(cpuid, 0, CPUID_LEN); - - cpuid_get(cpuid); - -#if CPUID_LEN > IEEE802154_LONG_ADDRESS_LEN - for (unsigned int i = IEEE802154_LONG_ADDRESS_LEN; i < CPUID_LEN; i++) { - cpuid[i & 0x07] ^= cpuid[i]; - } -#endif + /* get an 8-byte unique ID to use as hardware address */ + uuid_get(addr_long.uint8, IEEE802154_LONG_ADDRESS_LEN); /* make sure we mark the address as non-multicast and not globally unique */ - cpuid[0] &= ~(0x01); - cpuid[0] |= 0x02; - /* copy and set long address */ - memcpy(&addr_long, cpuid, IEEE802154_LONG_ADDRESS_LEN); + addr_long.uint8[0] &= ~(0x01); + addr_long.uint8[0] |= (0x02); + /* set short and long address */ at86rf2xx_set_addr_long(dev, NTOHLL(addr_long.uint64.u64)); at86rf2xx_set_addr_short(dev, NTOHS(addr_long.uint16[0].u16)); -#else - at86rf2xx_set_addr_long(dev, AT86RF2XX_DEFAULT_ADDR_LONG); - at86rf2xx_set_addr_short(dev, AT86RF2XX_DEFAULT_ADDR_SHORT); -#endif + /* set default PAN id */ at86rf2xx_set_pan(dev, AT86RF2XX_DEFAULT_PANID); /* set default channel */ diff --git a/drivers/cc110x/cc110x-netdev2.c b/drivers/cc110x/cc110x-netdev2.c index c8f58bdd7a..e7c862acc4 100644 --- a/drivers/cc110x/cc110x-netdev2.c +++ b/drivers/cc110x/cc110x-netdev2.c @@ -29,7 +29,6 @@ #include "cc110x-interface.h" #include "net/eui64.h" -#include "periph/cpuid.h" #include "periph/gpio.h" #include "net/netdev2.h" #include "net/gnrc/nettype.h" diff --git a/drivers/cc110x/cc110x.c b/drivers/cc110x/cc110x.c index 4e6b547750..778a103597 100644 --- a/drivers/cc110x/cc110x.c +++ b/drivers/cc110x/cc110x.c @@ -20,8 +20,8 @@ * @} */ +#include "uuid.h" #include "board.h" -#include "periph/cpuid.h" #include "periph/gpio.h" #include "periph/spi.h" #include "xtimer.h" @@ -87,14 +87,9 @@ int cc110x_setup(cc110x_t *dev, const cc110x_params_t *params) cc110x_set_channel(dev, CC110X_DEFAULT_CHANNEL); /* set default node id */ -#if CPUID_LEN - char cpuid[CPUID_LEN]; - cpuid_get(cpuid); - for (int i = 1; i < CPUID_LEN; i++) { - cpuid[0] ^= cpuid[i]; - } - cc110x_set_address(dev, (uint8_t) cpuid[0]); -#endif + uint8_t addr; + uuid_get(&addr, 1); + cc110x_set_address(dev, addr); LOG_INFO("cc110x: initialized with address=%u and channel=%i\n", (unsigned)dev->radio_address, diff --git a/drivers/cc2420/cc2420.c b/drivers/cc2420/cc2420.c index b75ceafcde..abe8cde527 100644 --- a/drivers/cc2420/cc2420.c +++ b/drivers/cc2420/cc2420.c @@ -20,7 +20,7 @@ * @} */ -#include "periph/cpuid.h" +#include "uuid.h" #include "byteorder.h" #include "net/ieee802154.h" #include "net/gnrc.h" @@ -32,36 +32,6 @@ #define ENABLE_DEBUG (0) #include "debug.h" -/** - * @todo Move this function to a global module - */ -#if CPUID_ID_LEN -static void addr_from_cpuid(uint8_t *addr) -{ - /* option 1: generate addresses from CPUID */ - uint8_t cpuid[CPUID_ID_LEN]; - - cpuid_get(cpuid); - memcpy(addr, cpuid, 8); - -#if CPUID_ID_LEN < 8 - /* in case CPUID_ID_LEN < 8, fill missing bytes with zeros */ - for (int i = CPUID_ID_LEN; i < 8; i++) { - addr_long[i] = 0; - } -#else - /* in case CPUID_ID_LEN > 8, XOR those bytes on top of the first 8 */ - for (int i = 8; i < CPUID_ID_LEN; i++) { - addr_long[i & 0x07] ^= cpuid[i]; - } -#endif - - /* make sure we mark the address as non-multicast and not globally unique */ - addr_long[0] &= ~(0x01); - addr_long[0] |= 0x02; -} -#endif - void cc2420_setup(cc2420_t * dev, const cc2420_params_t *params) { @@ -78,16 +48,17 @@ void cc2420_setup(cc2420_t * dev, const cc2420_params_t *params) int cc2420_init(cc2420_t *dev) { uint16_t reg; - uint8_t addr[8] = CC2420_ADDR_FALLBACK; + uint8_t addr[8]; /* reset options and sequence number */ dev->netdev.seq = 0; dev->netdev.flags = 0; /* set default address, channel, PAN ID, and TX power */ -#if CPUID_ID_LEN - addr_from_cpuid(addr); -#endif + uuid_get(addr, sizeof(addr)); + /* make sure we mark the address as non-multicast and not globally unique */ + addr[0] &= ~(0x01); + addr[0] |= 0x02; cc2420_set_addr_short(dev, &addr[6]); cc2420_set_addr_long(dev, addr); cc2420_set_pan(dev, CC2420_PANID_DEFAULT); diff --git a/drivers/cc2420/cc2420_getset.c b/drivers/cc2420/cc2420_getset.c index bd5d749468..0a48092328 100644 --- a/drivers/cc2420/cc2420_getset.c +++ b/drivers/cc2420/cc2420_getset.c @@ -21,6 +21,7 @@ */ #include +#include #include "cc2420.h" #include "cc2420_internal.h" diff --git a/drivers/enc28j60/enc28j60.c b/drivers/enc28j60/enc28j60.c index 5a7616dafa..848d8ad3cd 100644 --- a/drivers/enc28j60/enc28j60.c +++ b/drivers/enc28j60/enc28j60.c @@ -21,6 +21,7 @@ #include #include +#include "uuid.h" #include "mutex.h" #include "xtimer.h" #include "assert.h" @@ -30,10 +31,6 @@ #include "enc28j60.h" #include "enc28j60_regs.h" -#if CPUID_LEN -#include "periph/cpuid.h" -#endif - #define ENABLE_DEBUG (0) #include "debug.h" @@ -269,7 +266,7 @@ static int nd_recv(netdev2_t *netdev, void *buf, size_t max_len, void *info) if (buf != NULL) { #ifdef MODULE_NETSTATS_L2 netdev->stats.rx_count++; - netdev2->stats.rx_bytes += size; + netdev->stats.rx_bytes += size; #endif /* read packet content into the supplied buffer */ if (size <= max_len) { @@ -354,14 +351,10 @@ static int nd_init(netdev2_t *netdev) /* set non-back-to-back inter packet gap -> 0x12 is default */ cmd_wcr(dev, REG_B2_MAIPGL, 2, MAIPGL_FD); /* set default MAC address */ -#if CPUID_LEN - uint8_t macbuf[CPUID_LEN]; - cpuid_get(&macbuf); /* we get the full ID but use only parts of it */ + uint8_t macbuf[ETHERNET_ADDR_LEN]; + uuid_get(macbuf, ETHERNET_ADDR_LEN); macbuf[0] |= 0x02; /* locally administered address */ macbuf[0] &= ~0x01; /* unicast address */ -#else - uint8_t macbuf[] = ENC28J60_FALLBACK_MAC; -#endif mac_set(dev, macbuf); /* PHY configuration */ diff --git a/drivers/include/at86rf2xx.h b/drivers/include/at86rf2xx.h index 588d107096..2f2696fd6d 100644 --- a/drivers/include/at86rf2xx.h +++ b/drivers/include/at86rf2xx.h @@ -48,14 +48,6 @@ extern "C" { */ #define AT86RF2XX_MAX_PKT_LENGTH (IEEE802154_FRAME_LEN_MAX) -/** - * @brief Default addresses used if the CPUID module is not present - * @{ - */ -#define AT86RF2XX_DEFAULT_ADDR_SHORT (0x0230) -#define AT86RF2XX_DEFAULT_ADDR_LONG (0x1222334455667788) -/** @} */ - /** * @brief Channel configuration * @{ diff --git a/drivers/include/cc2420.h b/drivers/include/cc2420.h index ac4c80c3ed..c10d0cf0a5 100644 --- a/drivers/include/cc2420.h +++ b/drivers/include/cc2420.h @@ -38,14 +38,6 @@ extern "C" { */ #define CC2420_PKT_MAXLEN (IEEE802154_FRAME_LEN_MAX) -/** - * @brief Default addresses used if the CPUID module is not present - * - * In case this address is used, that short address will be created by using the - * last two bytes of the long address. - */ -#define CC2420_ADDR_FALLBACK {0x12, 0x22, 0x33, 0x44, 0x55, 0x66, 0x08, 0x15} - /** * @brief PAN ID configuration */ diff --git a/drivers/include/enc28j60.h b/drivers/include/enc28j60.h index 0eb2330ce4..87b61a03fa 100644 --- a/drivers/include/enc28j60.h +++ b/drivers/include/enc28j60.h @@ -32,15 +32,6 @@ extern "C" { #endif -/** - * @brief Fallback MAC address in case CPUID is not available - * - * The enc28j60 does not provide a globally unique, pre-set MAC address, so we - * need to create one. For this the CPUID module is used to create a locally - * administered MAC. If this is not available, we use the MAC address below. - */ -#define ENC28J60_FALLBACK_MAC {0x02, 0x22, 0x33, 0x44, 0x55, 0x66} - /** * @brief Struct containing the needed peripheral configuration */ diff --git a/drivers/w5100/w5100.c b/drivers/w5100/w5100.c index 11c9a353a6..af958da9e8 100644 --- a/drivers/w5100/w5100.c +++ b/drivers/w5100/w5100.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Freie Universität Berlin + * Copyright (C) 2016-2017 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 @@ -22,8 +22,8 @@ #include #include "log.h" +#include "uuid.h" #include "assert.h" -#include "periph/cpuid.h" #include "net/ethernet.h" #include "net/netdev2/eth.h" @@ -37,7 +37,6 @@ #define SPI_CONF SPI_CONF_FIRST_RISING #define RMSR_DEFAULT_VALUE (0x55) -#define MAC_SEED (0x23) #define S0_MEMSIZE (0x2000) #define S0_MASK (S0_MEMSIZE - 1) @@ -143,9 +142,6 @@ static int init(netdev2_t *netdev) w5100_t *dev = (w5100_t *)netdev; uint8_t tmp; uint8_t hwaddr[ETHERNET_ADDR_LEN]; -#if CPUID_LEN - uint8_t cpuid[CPUID_LEN]; -#endif /* test the SPI connection by reading the value of the RMSR register */ tmp = rreg(dev, REG_TMSR); @@ -159,13 +155,7 @@ static int init(netdev2_t *netdev) while (rreg(dev, REG_MODE) & MODE_RESET) {}; /* initialize the device, start with writing the MAC address */ - memset(hwaddr, MAC_SEED, ETHERNET_ADDR_LEN); -#if CPUID_LEN - cpuid_get(cpuid); - for (int i = 0; i < CPUID_LEN; i++) { - hwaddr[i % ETHERNET_ADDR_LEN] ^= cpuid[i]; - } -#endif + uuid_get(hwaddr, ETHERNET_ADDR_LEN); hwaddr[0] &= ~0x03; /* no group address and not globally unique */ wchunk(dev, REG_SHAR0, hwaddr, ETHERNET_ADDR_LEN); diff --git a/sys/include/uuid.h b/sys/include/uuid.h new file mode 100644 index 0000000000..aa6ef59029 --- /dev/null +++ b/sys/include/uuid.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2017 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 sys_uuid (Locally) Unique ID Generator + * @ingroup sys + * @brief Generate system wide unique IDs + * + * This module generates system wide, variable length unique IDs based on on the + * cpuid module. If the cpuid module is not present, the module falls back to a + * pre-defined, constant seed for creating unique ids. + * + * The main purpose of this module is to have a unified way for e.g. creating + * hardware addresses and similar. + * + * The IDs generated by this module are base created from a constant base part + * and a dynamic portion, which is XORed into the base ID. If the cpuid module + * is present, the base ID is created from the CPU's unique ID. If not, the + * base ID is created by simple 'memsetting' the base ID with the defined + * backup seed value. + * + * Once the base ID is generated, a UUID is generated by (i) XORing a counter + * value with the LSB of the base ID, or (ii) by XORing the least significant + * byes with a value given by the user. + * + * Example: Calling `uuid_base(&buf, 8)` will always yield an identical value, + * independent how often the function is called. But calling + * `uuid_base(&buf, 2)` afterwards will results in a different value, if the + * cpuid module is present, and in the same (but shorter) value if not. + * + * Example: Calling `uuid_get(&buf, 8)` four times in a row, will yield four + * different IDs, differing in their LSB. + * + * Example: Calling `uuid_custom(&buf, 8, 123)` will always yield the same + * value, but calling `uuid_custom(&buf, 8, 124)` will differ. + * + * @note This module generates unique IDs without any guarantees on their + * structure. These UUIDs are not compatible nor conform to the + * UUIDs as defined in RFC4122. + * + * @{ + * @file + * @brief Header of the unique ID generation module + * + * @author Hauke Petersen + */ + +#ifndef UUID_H_ +#define UUID_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Value used as based for the UUIDs in case the cpuid module is not + * present + */ +#ifndef UUID_BACKUP_SEED +#define UUID_BACKUP_SEED 0x23 +#endif + +/** + * @brief Get a unique ID + * + * The resulting ID is built from the base ID generated with uuid_base(), which + * isXORed with an 8-bit incrementing counter value into the most significant + * byte. + * + * @note The resulting UUID will repeat after 255 calls. + * + * @param[out] buf memory location to copy the UUID into. MUST be able to + * hold at least @p len bytes + * @param[in] len length of the UUID in bytes + */ +void uuid_get(void *buf, size_t len); + +/** + * @brief Get a custom unique ID based on a user given generator value + * + * The resulting ID is built from the base ID XORed with @p gen in the base + * ID's most significant bytes. + * + * @note Calling this function with identical values for @p gen and @p len + * will always result in identical UUIDs. + * + * @param[out] buf memory location to copy the UUID into. MUST be able to + * hold at least @p len bytes + * @param[in] len length of the UUID in bytes + * @param[in] gen custom UUID generator value + */ +void uuid_custom(void *buf, size_t len, int gen); + +/** + * @brief Get a UUID base value + * + * The uuid module creates the value dependent on the given @p len value using + * the cpuid module if present or a static seed value (@ref UUID_BACKUP_SEED) if + * not. + * + * @param[out] buf memory location to copy the UUID into. MUST be able to + * hold at least @p len bytes + * @param[in] len length of the UUID in bytes + */ +void uuid_base(void *buf, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* UUID_H_ */ +/** @} */ diff --git a/sys/uuid/Makefile b/sys/uuid/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/sys/uuid/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/sys/uuid/uuid.c b/sys/uuid/uuid.c new file mode 100644 index 0000000000..07e901a177 --- /dev/null +++ b/sys/uuid/uuid.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2017 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. + */ + +/** + * @ingroup sys_uuid + * @{ + * + * @file + * @brief UUID module implementation + * + * @author Hauke Petersen + * + * @} + */ + +#include +#include + +#include "assert.h" +#include "periph/cpuid.h" + +#include "uuid.h" + +static uint8_t lastused = 1; + +void uuid_get(void *buf, size_t len) +{ + uuid_base(buf, len); + + ((uint8_t *)buf)[0] ^= lastused++; +} + +void uuid_custom(void *buf, size_t len, int gen) +{ + uuid_base(buf, len); + + for (int i = 0; i < sizeof(gen); i++) { + ((uint8_t *)buf)[i % len] ^= ((gen >> (i * 8)) & 0xff); + } +} + +void uuid_base(void *buf, size_t len) +{ + assert(buf && (len > 0)); + + memset(buf, UUID_BACKUP_SEED, len); + +#if CPUID_LEN + uint8_t *out = (uint8_t *)buf; + uint8_t cid[CPUID_LEN]; + + cpuid_get(cid); + for (size_t i = 0; i < CPUID_LEN; i++) { + out[i % len] ^= cid[i]; + } +#endif +}