
10 changed files with 1186 additions and 1 deletions
@ -1,3 +1,7 @@
|
||||
MODULE = auto_init
|
||||
|
||||
ifneq (,$(filter net_if,$(USEMODULE))) |
||||
INCLUDES += -I$(RIOTBASE)/sys/net/include/
|
||||
endif |
||||
|
||||
include $(RIOTBASE)/Makefile.base |
||||
|
@ -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 */ |
@ -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 |
@ -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; |
||||
} |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
Loading…
Reference in new issue