diff --git a/Makefile.dep b/Makefile.dep index 578f190882f5db3592ed9657b9d19adbdd091ba5..9d86d5abad67f84048a1dc88ca49d02804cb54f6 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -102,3 +102,9 @@ ifneq (,$(filter vtimer,$(USEMODULE))) USEMODULE += timex endif endif + +ifneq (,$(filter net_if,$(USEMODULE))) + ifeq (,$(filter transceiver,$(USEMODULE))) + USEMODULE += transceiver + endif +endif diff --git a/sys/Makefile b/sys/Makefile index e6c9cfef07287cc843831870cb9b6961ccdb8731..0614547c705b8fecaa01359288aa310abf8eef16 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -42,6 +42,9 @@ endif ifneq (,$(filter vtimer,$(USEMODULE))) DIRS += vtimer endif +ifneq (,$(filter net_if,$(USEMODULE))) + DIRS += net/link_layer/net_if +endif ifneq (,$(filter destiny,$(USEMODULE))) DIRS += net/transport_layer/destiny endif diff --git a/sys/auto_init/Makefile b/sys/auto_init/Makefile index dc73b225e9b74e6d10730de15d9373c8b0556936..f5b62c8ad7ab2f7e6451048aba6d031d00b8f615 100644 --- a/sys/auto_init/Makefile +++ b/sys/auto_init/Makefile @@ -1,3 +1,7 @@ MODULE = auto_init +ifneq (,$(filter net_if,$(USEMODULE))) + INCLUDES += -I$(RIOTBASE)/sys/net/include/ +endif + include $(RIOTBASE)/Makefile.base diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index 8cf58b8dff59e641f3761668f3df30c12444e605..5652f3ce7ac462489fc4dc35f2c56160b8850875 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -55,6 +55,11 @@ #include "destiny.h" #endif +#ifdef MODULE_NET_IF +#include "net_if.h" +#include "transceiver.h" +#endif + #define ENABLE_DEBUG (0) #include "debug.h" @@ -97,6 +102,40 @@ void auto_init(void) DEBUG("Auto init mci module.\n"); MCI_initialize(); #endif +#ifdef MODULE_NET_IF + DEBUG("Auto init net_if module.\n"); + transceiver_type_t transceivers = 0; +#ifdef MODULE_AT86RF231 + transceivers |= TRANSCEIVER_AT86RF231; +#endif +#ifdef MODULE_CC1020 + transceivers |= TRANSCEIVER_CC1020; +#endif +#if MODULE_CC110X || MODULE_CC110X_NG + transceivers |= TRANSCEIVER_CC1100; +#endif +#ifdef MODULE_CC2420 + transceivers |= TRANSCEIVER_CC2420; +#endif +#ifdef MODULE_MC1322X + transceivers |= TRANSCEIVER_MC1322X; +#endif +#ifdef MODULE_NATIVENET + transceivers |= TRANSCEIVER_NATIVE; +#endif + net_if_init(); + + if (transceivers != 0) { + transceiver_init(transceivers); + transceiver_start(); + int iface = net_if_init_interface(0, transceivers); + + if (iface >= 0) { + DEBUG("Interface %d initialized\n", iface); + } + } + +#endif #ifdef MODULE_PROFILING extern void profiling_init(void); profiling_init(); diff --git a/sys/net/include/ieee802154_frame.h b/sys/net/include/ieee802154_frame.h index 132cc052f2bf47eed99152efa53a5e758fea0a7d..42af6b5dfaff2981b8af752dcd102fa4684eb578 100644 --- a/sys/net/include/ieee802154_frame.h +++ b/sys/net/include/ieee802154_frame.h @@ -38,6 +38,10 @@ #define IEEE_802154_SHORT_ADDR_M 2 #define IEEE_802154_LONG_ADDR_M 3 +#define IEEE_802154_SHORT_MCAST_ADDR (0xffff) +#define IEEE_802154_LONG_MCAST_ADDR {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ + 0xff, 0xff}} + #define IEEE_802154_PAN_ID 0x1234 typedef struct __attribute__((packed)) { diff --git a/sys/net/include/net_help.h b/sys/net/include/net_help.h index 6dd566efa1416d74fc315cdc2475cffac7890fac..03d890b711b33169d49f90a3a06970c472ef8ccd 100644 --- a/sys/net/include/net_help.h +++ b/sys/net/include/net_help.h @@ -21,8 +21,17 @@ (((uint32_t) (a) & 0x00ff0000) >> 8) | \ (((uint32_t) (a) & 0x0000ff00) << 8) | \ (((uint32_t) (a) & 0x000000ff) << 24)) +#define HTONLL(a) ((((uint64_t) (a) & 0xff00000000000000) >> 56) | \ + (((uint64_t) (a) & 0x00ff000000000000) >> 40) | \ + (((uint64_t) (a) & 0x0000ff0000000000) >> 24) | \ + (((uint64_t) (a) & 0x000000ff00000000) >> 8) | \ + (((uint64_t) (a) & 0x00000000ff000000) << 8) | \ + (((uint64_t) (a) & 0x0000000000ff0000) << 24) | \ + (((uint64_t) (a) & 0x000000000000ff00) << 40) | \ + (((uint64_t) (a) & 0x00000000000000ff) << 56)) #define NTOHS HTONS #define NTOHL HTONL +#define NTOHLL HTONLL #define CMP_IPV6_ADDR(a, b) (memcmp(a, b, 16)) diff --git a/sys/net/include/net_if.h b/sys/net/include/net_if.h new file mode 100644 index 0000000000000000000000000000000000000000..561788f0625e06657b2139ced68db56a10c30173 --- /dev/null +++ b/sys/net/include/net_if.h @@ -0,0 +1,504 @@ +/* + * Copyright (C) 2013 Freie Universität Berlin. + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @defgroup net_if Network interfaces + * @brief Abstraction layer between transceiver module and L3 protocol + * implementations. + * @ingroup net + * + * @{ + * + * @file net_if.h + * @brief Types and functions for network interfaces + * @author Freie Universität Berlin + * @author Martin Lenders <mlenders@inf.fu-berlin.de> + */ +#ifndef _NET_IF_H +#define _NET_IF_H + +#include <stdint.h> +#include <stdlib.h> + +#include "mutex.h" +#include "transceiver.h" + +/** + * @brief type to specify types of upper layer addresses + */ +typedef uint8_t net_if_l3p_t; + +/** + * @brief Interface protocols (for net_if_t.protocols): Use raw packets with + * static addresses in upper layer. + */ +#define NET_IF_L3P_RAW (0x00) + +/** + * @brief Interface protocols (for net_if_t.protocols): Use unicast IPv6 + * address in upper layer, addr_len must be 128. + */ +#define NET_IF_L3P_IPV6_UNICAST (0x01) + +/** + * @brief Interface protocols (for net_if_t.protocols): Use multicast IPv6 + * address in upper layer, addr_len must be 128. + */ +#define NET_IF_L3P_IPV6_MULTICAST (0x02) + +/** + * @brief Interface protocols (for net_if_t.protocols): Use anycast IPv6 + * address in upper layer, addr_len must be 128. + */ +#define NET_IF_L3P_IPV6_ANYCAST (0x04) + +/** + * @brief Interface protocols (for net_if_t.protocols): Use IPv6 prefix in + * upper layer, addr_len <= 128 becomes prefix length. + */ +#define NET_IF_L3P_IPV6_PREFIX (0x08) + +/** + * @brief Interface protocols (for net_if_t.protocols): Convenience macro + * combining NET_IF_L3P_IPV6_UNICAST, NET_IF_L3P_IPV6_ANYCAST, and + * NET_IF_L3P_IPV6_MULTICAST for comparisons + */ +#define NET_IF_L3P_IPV6_ADDR (NET_IF_L3P_IPV6_UNICAST | NET_IF_L3P_IPV6_ANYCAST \ + | NET_IF_L3P_IPV6_MULTICAST) + +/** + * @brief Interface protocols (for net_if_t.protocols): Convenience macro + * combining NET_IF_L3P_IPV6_UNICAST, NET_IF_L3P_IPV6_ANYCAST, + * NET_IF_L3P_IPV6_MULTICAST, and NET_IF_L3P_IPV6_PREFIX for + * comparisons + */ +#define NET_IF_L3P_IPV6 (NET_IF_L3P_IPV6_UNICAST | NET_IF_L3P_IPV6_ANYCAST \ + | NET_IF_L3P_IPV6_MULTICAST | NET_IF_L3P_IPV6_PREFIX) + +/** + * @brief Interface protocols: Return value of net_if_get_l3p_types() on + * error. + */ +#define NET_IF_L3P_FAILURE (0x80) + +#ifndef NET_IF_MAX +/** + * @brief Maximum number of interfaces. Redefinable via compiler flag. + */ +#define NET_IF_MAX (1) +#endif + +/** + * @brief Data type to represent an EUI-64. + */ +typedef union __attribute__((packed)) { + uint8_t uint8[8]; ///< split into 8 8-bit words. + uint16_t uint16[4]; ///< split into 4 16-bit words. + uint32_t uint32[2]; ///< split into 2 32-bit words. + uint64_t uint64; ///< as one 64-bit word. +} net_if_eui64_t; + +/** + * @brief list type for upper layer address of an interface. + * + * @details The interpretation of the address data is left to the upper layer + * implementations. + */ +typedef struct __attribute__((packed)) net_if_addr_t { + /** + * @brief The next address on the interface. Initialise with NULL + */ + struct net_if_addr_t *addr_next; + + /** + * @brief The next address on the interface. Initialise with NULL + */ + struct net_if_addr_t *addr_prev; + + /** + * @brief Flags to define upper layer protocols this address applies to + */ + net_if_l3p_t addr_protocol; + void *addr_data; ///< The actual upper layer address + uint8_t addr_len; ///< Length of the upper layer address in bit. +} net_if_addr_t; + +typedef uint8_t net_if_trans_addr_m_t; + +/** + * @brief Interface type. + */ +typedef struct __attribute__((packed)) { + uint8_t initialized; ///< Detemines if interface is initialized + uint8_t protocols; ///< Interface L3 protocols + transceiver_type_t transceivers; ///< Transceivers to use with this interface + net_if_trans_addr_m_t trans_src_addr_m; ///< Transceiver address mode + mutex_t address_buffer_mutex; ///< Mutex for address buffer operations + net_if_addr_t *addresses; ///< Adresses + uint8_t l3p_data[9]; ///< generic L3 data +} net_if_t; + +#define NET_IF_TRANS_ADDR_M_SHORT 2 ///< Transceiver address mode for short addresses +#define NET_IF_TRANS_ADDR_M_LONG 3 ///< Transceiver address mode for long addresses + +/** + * All registered interfaces. + */ +extern net_if_t interfaces[NET_IF_MAX]; + +/** + * @brief Initializes the module. + */ +void net_if_init(void); + +/** + * @brief Inititializes a new interface + * + * @pre *transceivers* may not be zero. + * + * @param[in] protocols The upper layer protocols to use on this interface. + * @param[in] transceivers The transceivers this interface uses. + * + * @return The new interface's ID on success, -1 on failure. + */ +int net_if_init_interface(net_if_l3p_t protocols, + transceiver_type_t transceivers); + +/** + * @brief Get interface. + * + * @param[in] if_id The interface's ID + * + * @return The interface identified by *if_id* or NULL on failure. + */ +static inline net_if_t *net_if_get_interface(int if_id) +{ + if (if_id < NET_IF_MAX && interfaces[if_id].initialized) { + return &interfaces[if_id]; + } + else { + return NULL; + } +} + + +/** + * @brief Iterates over all intitialized interfaces + * + * @param[in] start Return value of last iteration step. -1 to start iteration. + * + * @return ID of an initialized interface. -1 if end of interface list is + * reached. + */ +int net_if_iter_interfaces(int start); + +/** + * @brief Sets the source address mode for the interface + * + * @param[in] if_id Interface to set source address mode for. + * @param[in] mode The mode to set to. + * + * @return 1 on success, 0 on error + */ +static inline int net_if_set_src_address_mode(int if_id, + net_if_trans_addr_m_t mode) +{ + if (!interfaces[if_id].initialized) { + return 0; + } + + interfaces[if_id].trans_src_addr_m = mode; + return 1; +} + +/** + * @brief Gets the source address mode for the interface + * + * @param[in] if_id Interface to get source address mode from. + * + * @return The interfaces address mode, 0 on error + */ +static inline net_if_trans_addr_m_t net_if_get_src_address_mode(int if_id) +{ + if (!interfaces[if_id].initialized) { + return 0; + } + + return interfaces[if_id].trans_src_addr_m; +} + +/** + * @brief Adds new address to interface + * + * @pre *addr* is not NULL, *addr->addr_data* is not NULL + * + * @param[in] if_id The interface's ID + * @param[in] addr The address to add + * + * @return 1 on success, 0 on failure. + */ +int net_if_add_address(int if_id, net_if_addr_t *addr); + +/** + * @brief Removes first occurance of address from interface + * + * @pre *addr* is not NULL, *addr->addr_data* is not NULL + * + * @param[in] if_id The interface's ID + * @param[in] addr The address to remove + * + * @return 1 on success (and if given address is not registered to this + * interface), 0 on failure + */ +int net_if_del_address(int if_id, net_if_addr_t *addr); + +/** + * @brief Iterates over registered addresses of an interface. + * + * @param[in] if_id The interface's ID + * @param[in,out] addr The previous address as in or the next address as out. + * If *addr* points to NULL it will be set to the + * first address assigned to *if_id*, if *addr* points to + * NULL as out, the last address assigned to *if_id* was + * given as *addr* previously (and the address list was + * completely iterated). + * + * @return The pointer *addr* refers to after call of this function or NULL on + * error + */ +net_if_addr_t *net_if_iter_addresses(int if_id, net_if_addr_t **addr); + +/** + * @brief Get the upper layer protocol types assigned to the interface *if_id* + * + * @param[in] if_id The interface's ID + * @return The upper layer protocol types assigned to the interface *if_id* on + * success, NET_IF_L3P_FAILURE on failure. + */ +net_if_l3p_t net_if_get_l3p_types(int if_id); + +/** + * @brief Add an upper layer protocol types to the interface *if_id* + * + * @param[in] if_id The interface's ID + * @param[in] protocols The upper layer protocol types to assign to the + * interface *if_id* + * @return 1 on success, 0 on failure. + */ +int net_if_add_l3p_types(int if_id, net_if_l3p_t protocols); + +/** + * @brief Remove upper layer protocol types and all addresses of this scope + * from the interface *if_id* + * + * @param[in] if_id The interface's ID + * @param[in] protocols The upper layer protocol types to be removed from the + * interface *if_id* + * @return 1 on success, 0 on failure. + */ +int net_if_del_l3p_types(int if_id, net_if_l3p_t protocols); + +/** + * @brief Sends a packet to a short address over the interface. + * + * @pre Transceivers has to be initialized and transceiver thread has + * to be started. + * + * @param[in] if_id The interface's ID. + * @param[in] target The target's short transceiver address. + * @param[in] packet_data The packet to send + * @param[in] packet_len The length of the packet's data in byte, negative + * number on error. + * + * @return The number of bytes send on success, negative value on failure + */ +int net_if_send_packet(int if_id, uint16_t target, const void *packet_data, + size_t packet_len); + +/** + * @brief Sends a packet to a long address over the interface. If transceiver + * only supports smaller addresses the least significant bit of the + * address will be taken. + * + * @pre Transceivers has to be initialized and transceiver thread has + * to be started. + * + * @param[in] if_id The interface's ID. + * @param[in] target The target's long transceiver address. + * @param[in] packet_data The packet to send + * @param[in] packet_len The length of the packet's data in byte, negative + * number on error. + * + * @return The number of bytes send on success, negative value on failure + */ +int net_if_send_packet_long(int if_id, net_if_eui64_t *target, + const void *packet_data, size_t packet_len); + +/** + * @brief Sends a packet over all initialized interfaces. + * + * @pre Transceivers has to be initialized and transceiver thread has + * to be started. + * + * @param[in] preferred_dest_mode The preferred transceiver address mode for + * the destination broadcast address. Choose + * NET_IF_TRANS_ADDR_M_SHORT if you are not + * sure + * @param[in] packet_data The packet to send + * @param[in] packet_len The length of the packet's data in byte, + * negative number on error. + * + * @return The number of bytes send on success, negative value on failure + */ +int net_if_send_packet_broadcast(net_if_trans_addr_m_t preferred_dest_mode, + const void *payload, size_t payload_len); + +/** + * @brief register a thread for events an interface's transceiver + * @details This function just wraps transceiver_register(). + * + * @pre Transceivers has to be initialized and transceiver thread has + * to be started. + * + * @param[in] if_id The transceiver's interface to register for + * @param[in] pid The pid of the thread to register + * + * @return 1 on success, 0 otherwise + */ +int net_if_register(int if_id, int pid); + +/** + * Returns the EUI-64 of the transeivers attached to this interface. This can + * be get by the actual EUI-64 if the transceiver has one or a generated one + * based of the hardware address + * + * @pre Transceivers of this interface has to be initialized and + * transceiver thread has to be started. + * + * @see <a href="http://tools.ietf.org/html/rfc4944#section-6"> + * RFC 4944, section 5 + * </a> + * @see <a href="http://tools.ietf.org/search/rfc6282#section-3.2.2"> + * RFC 6282, section 3.2.2 + * </a> + * + * @param[out] eui64 The EUI-64 to fill + * @param[in] if_id The interface's ID + * @param[in] force_generation Force generation from a short address if the + * hardware supports it, even if the hardware + * supplies an EUI-64 + * + * @return 1 on success, 0 on failure + */ +int net_if_get_eui64(net_if_eui64_t *eui64, int if_id, int force_generation); + +/** + * @brief Parses a string to an EUI-64. + * @detail The parsing will be back to front, every non-hexadecimal character + * and every hexadecimal character beyond the count of 8 will be + * ignored + * + * @param[out] eui64 The generated binary EUI-64. + * @param[in] eui64_str A hexadecimal number in string representation. + */ +void net_if_hex_to_eui64(net_if_eui64_t *eui64, const char *eui64_str); + +/** + * Returns the address of the transceiver associated with the given interface. + * + * @pre Transceivers of this interface has to be initialized and + * transceiver thread has to be started. + * + * @param[in] if_id The interface's ID + * + * @return The transceiver's hardware address on success, 0 on failure + */ +uint16_t net_if_get_hardware_address(int if_id); + +/** + * Returns the EUI-64 of the transeivers attached to this interface. This can + * be get by the actual EUI-64 if the transceiver has one or a generated one + * based of the hardware address + * + * @pre Transceivers of this interface has to be initialized and + * transceiver thread has to be started. + * + * @param[in] if_id The interface's ID + * @param[in] eui64 The new EUI-64 + * + * @return 1 on success, 0 on failure + */ +int net_if_set_eui64(int if_id, net_if_eui64_t *eui64); + +/** + * Sets the address of the transceiver associated with the given interface. + * + * @pre Transceivers of this interface has to be initialized and + * transceiver thread has to be started. + * + * @param[in] if_id The interface's ID + * @param[in] addr The new hardware address + * + * @return the new hardware address on success, 0 on failure. + */ +uint16_t net_if_set_hardware_address(int if_id, uint16_t addr); + +/** + * Returns the channel of the transceiver associated with the given interface. + * + * @pre Transceivers of this interface has to be initialized and + * transceiver thread has to be started. + * + * @param[in] if_id The interface's ID + * + * @return The transceiver's frequency channel on success, -1 on failure. + */ +int32_t net_if_get_channel(int if_id); + +/** + * Sets the channel of the transceiver associated with the given interface. + * + * @pre Transceivers of this interface has to be initialized and + * transceiver thread has to be started. + * + * @param[in] if_id The interface's ID + * @param[in] channel The new frequency channel + * + * @return the new channel on success, -1 on failure. + */ +int32_t net_if_set_channel(int if_id, uint16_t channel); + +/** + * Returns the PAN ID of the transceiver associated with the given interface. + * + * @pre Transceivers of this interface has to be initialized and + * transceiver thread has to be started. + * + * @param[in] if_id The interface's ID + * + * @return The transceiver's PAN ID on success, -1 on failure + */ +int32_t net_if_get_pan_id(int if_id); + +/** + * Sets the PAN ID of the transceiver associated with the given interface. + * + * @pre Transceivers of this interface has to be initialized and + * transceiver thread has to be started. + * + * @param[in] if_id The interface's ID + * @param[in] pan_id The new frequency channel + * + * @return the PAN ID on success, -1 on failure. + */ +int32_t net_if_set_pan_id(int if_id, uint16_t pan_id); + +/** + * @} + */ +#endif /* _NET_IF_H */ diff --git a/sys/net/link_layer/net_if/Makefile b/sys/net/link_layer/net_if/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..81bfe881437e5f68d9b07aa8132fd5d2c4855c93 --- /dev/null +++ b/sys/net/link_layer/net_if/Makefile @@ -0,0 +1,5 @@ +MODULE:=$(shell basename $(CURDIR)) +INCLUDES += -I$(RIOTBASE)/drivers/include \ + -I$(RIOTBASE)/drivers/cc110x_ng/include \ + -I$(RIOTBASE)/sys/net/include +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/link_layer/net_if/net_if.c b/sys/net/link_layer/net_if/net_if.c new file mode 100644 index 0000000000000000000000000000000000000000..4ded2494a5e91bf836f86bec9c9da1c0c9eee696 --- /dev/null +++ b/sys/net/link_layer/net_if/net_if.c @@ -0,0 +1,552 @@ +/* + * Copyright (C) 2013 Freie Universität Berlin. + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup net_if + * @{ + * @file net_if.c + * @author Martin Lenders <mlenders@inf.fu-berlin.de> + */ +#include <string.h> + +#include "clist.h" +#include "ieee802154_frame.h" +#include "msg.h" +#include "mutex.h" +#include "net_help.h" +#include "transceiver.h" + +#include "net_if.h" + +#define ENABLE_DEBUG (0) +#if ENABLE_DEBUG +#define DEBUG_ENABLED +#endif +#include "debug.h" + +net_if_t interfaces[NET_IF_MAX]; + +#ifdef DEBUG_ENABLED +void print_addr_hex(net_if_addr_t *addr) +{ + int i; + DEBUG("0x"); + + for (i = 0; i < addr->addr_len; i++) { + DEBUG("%02x", ((char *)addr->addr_data)[i]); + } + + DEBUG("\n"); +} +#endif + +uint8_t net_if_hex_to_dec(char c) +{ + if (c >= '0' && c <= '9') { + return (uint8_t)(c - '0'); + } + else if (c >= 'A' && c <= 'F') { + return (uint8_t)(c - 55); + } + else if (c >= 'a' && c <= 'f') { + return (uint8_t)(c - 87); + } + else { + return 0xff; + } +} + +void net_if_hex_to_eui64(net_if_eui64_t *eui64, const char *eui64_str) +{ + int i; + const char *eui64_rev = &eui64_str[strlen(eui64_str) - 1]; + eui64->uint64 = 0; + + for (i = 7; i >= 0 || eui64_rev >= eui64_str; i--) { + uint8_t digit; + + while ((digit = net_if_hex_to_dec(*eui64_rev)) == 0xFF) { + if (--eui64_rev < eui64_str) { + return; + } + } + + eui64->uint8[i] = digit; + eui64_rev--; + + while ((digit = net_if_hex_to_dec(*eui64_rev)) == 0xFF) { + if (--eui64_rev < eui64_str) { + return; + } + } + + eui64->uint8[i] |= digit << 4; + eui64_rev--; + } +} + +void net_if_init(void) +{ + memset(&interfaces, 0, sizeof(net_if_t) * NET_IF_MAX); +} + +int net_if_init_interface(uint8_t protocols, transceiver_type_t transceivers) +{ + int i; + + if (transceivers == 0) { + DEBUG("Interface initialization: Precondition not met.\n"); + return -1; + } + + for (i = 0; i < NET_IF_MAX; i++) { + if (!interfaces[i].initialized) { + interfaces[i].initialized = 1; + interfaces[i].protocols = protocols; + mutex_init(&interfaces[i].address_buffer_mutex); + interfaces[i].transceivers = transceivers; + DEBUG("Initialized interface %d for protocols %d on transceivers 0x%x\n", + i, protocols, transceivers); + return i; + } + } + + DEBUG("Interface buffer full.\n"); + return -1; +} + +int net_if_iter_interfaces(int start) +{ + if (start == NET_IF_MAX - 1) { + return -1; + } + + start++; + + while (start < NET_IF_MAX && !interfaces[start].initialized) { + start++; + } + + return start; +} + +int net_if_add_address(int if_id, net_if_addr_t *addr) +{ + if (!addr || !addr->addr_data) { + DEBUG("Address addition: Precondition not met.\n"); + return 0; + } + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Address addition: No interface initialized with ID %d.\n", if_id); + return 0; + } + + mutex_lock(&interfaces[if_id].address_buffer_mutex); + + interfaces[if_id].protocols |= addr->addr_protocol; + + clist_add((clist_node_t **)&interfaces[if_id].addresses, + (clist_node_t *)addr); + + mutex_unlock(&interfaces[if_id].address_buffer_mutex); + + return 1; +} + +int net_if_del_address(int if_id, net_if_addr_t *addr) +{ + if (!addr || !addr->addr_data) { + DEBUG("Address deletion: Precondition not met.\n"); + return 0; + } + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Address deletion: No interface initialized with ID %d.\n", if_id); + return 0; + } + + mutex_lock(&interfaces[if_id].address_buffer_mutex); + + clist_remove((clist_node_t **)&interfaces[if_id].addresses, + (clist_node_t *)addr); + + mutex_unlock(&interfaces[if_id].address_buffer_mutex); + + return 1; +} + +net_if_addr_t *net_if_iter_addresses(int if_id, net_if_addr_t **addr) +{ + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Address iteration: No interface initialized with ID %d.\n", if_id); + return NULL; + } + + if (*addr == NULL) { + *addr = interfaces[if_id].addresses; + return *addr; + } + + clist_advance((clist_node_t **)addr); + + if (*addr == interfaces[if_id].addresses) { + *addr = NULL; + } + + return *addr; +} + +net_if_l3p_t net_if_get_l3p_types(int if_id) +{ + net_if_l3p_t protocols; + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Get L3 protocols: No interface initialized with ID %d.\n", if_id); + return NET_IF_L3P_FAILURE; + } + + mutex_lock(&interfaces[if_id].address_buffer_mutex); + + protocols = interfaces[if_id].protocols; + + mutex_unlock(&interfaces[if_id].address_buffer_mutex); + + return protocols; +} + +int net_if_add_l3p_types(int if_id, net_if_l3p_t protocols) +{ + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Add L3 protocols: No interface initialized with ID %d.\n", if_id); + return 0; + } + + interfaces[if_id].protocols |= protocols; + + return 1; +} + +int net_if_del_l3p_types(int if_id, net_if_l3p_t protocols) +{ + net_if_addr_t *addr_ptr = NULL; + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Remove L3 protocols: No interface initialized with ID %d.\n", if_id); + return 0; + } + + while (net_if_iter_addresses(if_id, &addr_ptr)) { + if (addr_ptr->addr_protocol & protocols) { + net_if_del_address(if_id, addr_ptr); + addr_ptr = NULL; + } + } + + interfaces[if_id].protocols &= ~protocols; + + return 1; +} + +uint32_t net_if_transceiver_get_set_handler(int if_id, uint16_t op_type, + void *data) +{ + DEBUG("net_if_transceiver_get_set_handler: if_id = %d, op_type = %d, data = %p\n", + if_id, op_type, data); + msg_t msg; + transceiver_command_t tcmd; + + tcmd.transceivers = interfaces[if_id].transceivers; + tcmd.data = (char *)data; + msg.content.ptr = (char *)&tcmd; + msg.type = op_type; + msg_send_receive(&msg, &msg, transceiver_pid); + + return msg.content.value; +} + +int net_if_send_packet_broadcast(net_if_trans_addr_m_t preferred_dest_mode, + const void *payload, size_t payload_len) +{ + int if_id = -1; + int res = 0, res_prev = 0; + + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + if (interfaces[if_id].transceivers & (TRANSCEIVER_CC1100 | TRANSCEIVER_NATIVE)) { + res = net_if_send_packet(if_id, 0, + payload, payload_len); + } + else if (preferred_dest_mode == NET_IF_TRANS_ADDR_M_SHORT) { + res = net_if_send_packet(if_id, IEEE_802154_SHORT_MCAST_ADDR, + payload, payload_len); + } + else { + net_if_eui64_t mcast_addr = IEEE_802154_LONG_MCAST_ADDR; + res = net_if_send_packet_long(if_id, &mcast_addr, payload, + payload_len); + } + + if (res_prev != 0) { + if (res != res_prev) { + return -1; + } + } + else { + if (res == 0) { + break; + } + } + + res_prev = res; + } + + return res; +} + +int net_if_send_packet(int if_id, uint16_t target, const void *payload, + size_t payload_len) +{ + DEBUG("net_if_send_packet: if_id = %d, target = %d, payload = %p, " + "payload_len = %d\n", if_id, target, payload, payload_len); + uint32_t response; + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Send packet: No interface initialized with ID %d.\n", if_id); + return -1; + } + + if (interfaces[if_id].transceivers & (TRANSCEIVER_CC2420 | TRANSCEIVER_AT86RF231 | TRANSCEIVER_MC1322X)) { + ieee802154_packet_t p; + + memset(&p, 0, sizeof(ieee802154_packet_t)); + + p.frame.payload = (uint8_t *)payload; + p.frame.payload_len = (uint8_t)payload_len; + p.frame.fcf.src_addr_m = (uint8_t)interfaces[if_id].trans_src_addr_m; + p.frame.fcf.dest_addr_m = IEEE_802154_SHORT_ADDR_M; + p.frame.fcf.ack_req = 0; + p.frame.fcf.sec_enb = 0; + p.frame.fcf.frame_type = 1; + p.frame.fcf.frame_pend = 0; + + p.frame.dest_pan_id = net_if_get_pan_id(if_id); + memcpy(p.frame.dest_addr, &target, 2); + response = net_if_transceiver_get_set_handler(if_id, SND_PKT, (void *)&p); + } + else { + radio_packet_t p; + memset(&p, 0, sizeof(radio_packet_t)); + p.data = (uint8_t *) payload; + p.length = payload_len; + p.dst = target; + response = net_if_transceiver_get_set_handler(if_id, SND_PKT, (void *)&p); + } + + + return (response > payload_len) ? (int)payload_len : (int)response; +} + +int net_if_send_packet_long(int if_id, net_if_eui64_t *target, + const void *payload, size_t payload_len) +{ + DEBUG("net_if_send_packet: if_id = %d, target = %016" PRIx64 ", " + "payload = %p, payload_len = %d\n", if_id, NTOHLL(target->uint64), payload, + payload_len); + uint32_t response; + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Send packet: No interface initialized with ID %d.\n", if_id); + return -1; + } + + if (interfaces[if_id].transceivers & (TRANSCEIVER_CC2420 | + TRANSCEIVER_AT86RF231 | + TRANSCEIVER_MC1322X)) { + ieee802154_packet_t p; + memset(&p, 0, sizeof(ieee802154_packet_t)); + p.frame.payload = (uint8_t *)payload; + p.frame.payload_len = (uint8_t)payload_len; + p.frame.fcf.src_addr_m = (uint8_t)interfaces[if_id].trans_src_addr_m; + p.frame.fcf.dest_addr_m = IEEE_802154_LONG_ADDR_M; + p.frame.fcf.ack_req = 0; + p.frame.fcf.sec_enb = 0; + p.frame.fcf.frame_type = 1; + p.frame.fcf.frame_pend = 0; + p.frame.dest_pan_id = net_if_get_pan_id(if_id); + memcpy(p.frame.dest_addr, target, 8); + response = net_if_transceiver_get_set_handler(if_id, SND_PKT, (void *)&p); + } + else { + radio_packet_t p; + memset(&p, 0, sizeof(radio_packet_t)); + p.data = (uint8_t *) payload; + p.length = payload_len; + p.dst = NTOHS(target->uint16[3]); + response = net_if_transceiver_get_set_handler(if_id, SND_PKT, (void *)&p); + } + + + return (response > payload_len) ? (int)payload_len : (int)response; +} + +int net_if_register(int if_id, int pid) +{ + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Register thread: No interface initialized with ID %d.\n", if_id); + return 0; + } + + return (int)transceiver_register(interfaces[if_id].transceivers, pid); +} + +int net_if_get_eui64(net_if_eui64_t *eui64, int if_id, int force_generation) +{ + uint64_t tmp; + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Get EUI-64: No interface initialized with ID %d.\n", if_id); + return 0; + } + + if (eui64 == NULL) { + DEBUG("Get EUI-64: parameter eui64 is a NULL pointer.\n"); + return 0; + } + + net_if_transceiver_get_set_handler(if_id, GET_LONG_ADDR, &tmp); + + eui64->uint64 = HTONLL(tmp); + + if (eui64->uint64 == 0 || force_generation) { + uint16_t hwaddr = net_if_get_hardware_address(if_id); + + if (hwaddr == 0) { + return 0; + } + + /* RFC 6282 Section 3.2.2 / RFC 2464 Section 4 */ + eui64->uint32[0] = HTONL(0x000000ff); + eui64->uint16[2] = HTONS(0xfe00); + + if (sizeof(hwaddr) == 2) { + eui64->uint16[3] = HTONS(hwaddr); + } + else if (sizeof(hwaddr) == 1) { + eui64->uint8[6] = 0; + eui64->uint8[7] = (uint8_t)hwaddr; + } + else { + DEBUG("Error on EUI-64 generation: do not know what to do with " + "hardware address of length %d\n", sizeof(hwaddr)); + return 0; + } + + } + + return 1; +} + +int net_if_set_eui64(int if_id, net_if_eui64_t *eui64) +{ + if (eui64 == NULL) { + return 0; + } + + uint64_t tmp = NTOHLL(eui64->uint64); + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Set EUI-64: No interface initialized with ID %d.\n", if_id); + return 0; + } + + net_if_transceiver_get_set_handler(if_id, SET_LONG_ADDR, (void *) &tmp); + + return eui64->uint64 != 0; +} + +uint16_t net_if_get_hardware_address(int if_id) +{ + uint16_t addr; + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Get hardware address: No interface initialized with ID %d.\n", if_id); + return 0; + } + + net_if_transceiver_get_set_handler(if_id, GET_ADDRESS, &addr); + return addr; +} + +uint16_t net_if_set_hardware_address(int if_id, uint16_t addr) +{ + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Set hardware address: No interface initialized with ID %d.\n", if_id); + return 0; + } + + net_if_transceiver_get_set_handler(if_id, SET_ADDRESS, &addr); + return addr; +} + +int32_t net_if_get_channel(int if_id) +{ + int32_t channel; + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Get channel: No interface initialized with ID %d.\n", if_id); + return -1; + } + + net_if_transceiver_get_set_handler(if_id, GET_CHANNEL, &channel); + return channel; +} + +int32_t net_if_set_channel(int if_id, uint16_t channel) +{ + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Set channel: No interface initialized with ID %d.\n", if_id); + return -1; + } + + net_if_transceiver_get_set_handler(if_id, SET_CHANNEL, &channel); + return channel; +} + +int32_t net_if_get_pan_id(int if_id) +{ + int32_t pan_id; + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Get PAN ID: No interface initialized with ID %d.\n", if_id); + return -1; + } + + net_if_transceiver_get_set_handler(if_id, GET_PAN, &pan_id); + if (pan_id < 0) { + return 0; + } + else { + return pan_id; + } + +} + +int32_t net_if_set_pan_id(int if_id, uint16_t pan_id) +{ + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Set PAN ID: No interface initialized with ID %d.\n", if_id); + return -1; + } + + net_if_transceiver_get_set_handler(if_id, SET_PAN, &pan_id); + return pan_id; +} + +/** + * @} + */ diff --git a/sys/shell/commands/sc_transceiver.c b/sys/shell/commands/sc_transceiver.c index f4029504faa4abffc8f9f58755a2d4b6adc3fa23..b5caa0a2682bc3127f1b5738e3bc4394c1861503 100644 --- a/sys/shell/commands/sc_transceiver.c +++ b/sys/shell/commands/sc_transceiver.c @@ -21,6 +21,9 @@ #include <string.h> #include <inttypes.h> +#ifdef MODULE_NET_IF +#include "net_if.h" +#endif #include "transceiver.h" #include "msg.h" @@ -80,6 +83,56 @@ void _transceiver_get_set_address_handler(int argc, char **argv) printf("[transceiver] got address: %" PRIu16 "\n", a); } +#ifndef MODULE_NET_IF +uint8_t hex_to_dec(char c) +{ + if (c >= '0' && c <= '9') { + return (uint8_t)(c - '0'); + } + else if (c >= 'A' && c <= 'F') { + return (uint8_t)(c - 55); + } + else if (c >= 'a' && c <= 'f') { + return (uint8_t)(c - 87); + } + else { + return 0xff; + } +} + +uint64_t _str_to_eui64(const char *eui64_str) +{ + int i; + const char *eui64_rev = &eui64_str[strlen(eui64_str) - 1]; + uint64_t eui64 = 0; + + for (i = 7; i >= 0 || eui64_rev >= eui64_str; i--) { + uint8_t digit; + eui64 <<= 8; + + while ((digit = hex_to_dec(*eui64_rev)) == 0xFF) { + if (--eui64_rev < eui64_str) { + return eui64; + } + } + + eui64 = digit; + eui64_rev--; + + while ((digit = hex_to_dec(*eui64_rev)) == 0xFF) { + if (--eui64_rev < eui64_str) { + return eui64; + } + } + + eui64 |= digit << 4; + eui64_rev--; + } + + return eui64; +} +#endif + /* checked for type safety */ void _transceiver_get_set_long_addr_handler(int argc, char **argv) { @@ -97,7 +150,13 @@ void _transceiver_get_set_long_addr_handler(int argc, char **argv) mesg.content.ptr = (char *) &tcmd; if (argc > 1) { - a = atoll(argv[1]); +#ifdef MODULE_NET_IF + net_if_eui64_t eui64; + net_if_hex_to_eui64(&eui64, argv[1]); + a = eui64.uint64; +#else + a = _str_to_eui64(argv[1]); +#endif printf("[transceiver] trying to set EUI-64 %016"PRIx64"\n", a); mesg.type = SET_LONG_ADDR; }