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

Implement net_if module

This commit is contained in:
Martin Lenders 2013-12-20 15:23:09 +01:00
parent 7f8e2c2991
commit 848ac70f90
10 changed files with 1186 additions and 1 deletions

View File

@ -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

View File

@ -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

View File

@ -1,3 +1,7 @@
MODULE = auto_init
ifneq (,$(filter net_if,$(USEMODULE)))
INCLUDES += -I$(RIOTBASE)/sys/net/include/
endif
include $(RIOTBASE)/Makefile.base

View File

@ -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();

View File

@ -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)) {

View File

@ -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))

504
sys/net/include/net_if.h Normal file
View File

@ -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 */

View File

@ -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

View File

@ -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;
}
/**
* @}
*/

View File

@ -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;
}