Merge commit '6dd01c679db4deb0a4a2c55832f3abe7b19bc51b' into mbedos511

* commit '6dd01c679db4deb0a4a2c55832f3abe7b19bc51b':
  Squashed 'features/nanostack/sal-stack-nanostack/' changes from 2535a6c..ccd30a3
pull/8647/head
Arto Kinnunen 2018-11-05 17:08:28 +02:00
commit ef39a19ba9
101 changed files with 2464 additions and 948 deletions

View File

@ -69,7 +69,8 @@
typedef enum dhcp_instance_type typedef enum dhcp_instance_type
{ {
DHCP_INSTANCE_CLIENT, DHCP_INSTANCE_CLIENT,
DHCP_INSTANCE_SERVER DHCP_INSTANCE_SERVER,
DHCP_INTANCE_RELAY_AGENT
} dhcp_instance_type_e; } dhcp_instance_type_e;
/** /**
@ -124,6 +125,16 @@ typedef int (dhcp_service_receive_resp_cb)(uint16_t instance_id, void *ptr, uint
uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_type, dhcp_service_receive_req_cb *receive_req_cb); uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_type, dhcp_service_receive_req_cb *receive_req_cb);
/**
* \brief Enable DHCPv6 Relay Agent to server.
*
*
* \param instance The instance ID of the registered server.
* \param server_address global server IPv6 address
*/
void dhcp_service_relay_instance_enable(uint16_t instance, uint8_t *server_address);
/** /**
* \brief Deletes a server instance. * \brief Deletes a server instance.
* *

View File

@ -132,8 +132,9 @@ typedef bool fhss_data_tx_fail(const fhss_api_t *api, uint8_t handle, int frame_
* @param api FHSS instance. * @param api FHSS instance.
* @param fhss_state FHSS state (FHSS states are defined by FHSS api). * @param fhss_state FHSS state (FHSS states are defined by FHSS api).
* @param pan_id PAN id of the network FHSS synchronizes with. * @param pan_id PAN id of the network FHSS synchronizes with.
* @return -1 when failed, otherwise current MAC channel.
*/ */
typedef void fhss_synch_state_set(const fhss_api_t *api, fhss_states fhss_state, uint16_t pan_id); typedef int16_t fhss_synch_state_set(const fhss_api_t *api, fhss_states fhss_state, uint16_t pan_id);
/** /**
* @brief Read timestamp. * @brief Read timestamp.
@ -215,6 +216,13 @@ typedef int mac_read_mac_address(const fhss_api_t *fhss_api, uint8_t *mac_addres
*/ */
typedef uint32_t mac_read_datarate(const fhss_api_t *fhss_api); typedef uint32_t mac_read_datarate(const fhss_api_t *fhss_api);
/**
* @brief Read 32-bit timestamp.
* @param fhss_api FHSS instance.
* @return Timestamp.
*/
typedef uint32_t mac_read_timestamp(const fhss_api_t *fhss_api);
/** /**
* @brief Change channel. * @brief Change channel.
* @param fhss_api FHSS instance. * @param fhss_api FHSS instance.
@ -287,6 +295,7 @@ struct fhss_callback {
mac_read_tx_queue_size *read_tx_queue_size; /**< Read MAC TX queue size. */ mac_read_tx_queue_size *read_tx_queue_size; /**< Read MAC TX queue size. */
mac_read_mac_address *read_mac_address; /**< Read MAC address. */ mac_read_mac_address *read_mac_address; /**< Read MAC address. */
mac_read_datarate *read_datarate; /**< Read PHY datarate. */ mac_read_datarate *read_datarate; /**< Read PHY datarate. */
mac_read_timestamp *read_timestamp; /**< Read timestamp. */
mac_change_channel *change_channel; /**< Change channel. */ mac_change_channel *change_channel; /**< Change channel. */
mac_send_fhss_frame *send_fhss_frame; /**< Send FHSS frame. */ mac_send_fhss_frame *send_fhss_frame; /**< Send FHSS frame. */
mac_synch_lost_notification *synch_lost_notification; /**< Send notification when FHSS synchronization is lost. */ mac_synch_lost_notification *synch_lost_notification; /**< Send notification when FHSS synchronization is lost. */

View File

@ -96,8 +96,11 @@ typedef int32_t fhss_vendor_defined_cf(const fhss_api_t *api, uint16_t slot, uin
*/ */
typedef struct fhss_ws_configuration typedef struct fhss_ws_configuration
{ {
/** WS channel function. */ /** WS unicast channel function. */
fhss_ws_channel_functions ws_channel_function; fhss_ws_channel_functions ws_uc_channel_function;
/** WS broadcast channel function. */
fhss_ws_channel_functions ws_bc_channel_function;
/** Broadcast schedule identifier. */ /** Broadcast schedule identifier. */
uint16_t bsi; uint16_t bsi;
@ -111,6 +114,12 @@ typedef struct fhss_ws_configuration
/** Broadcast dwell interval. Range: 15-250 milliseconds. */ /** Broadcast dwell interval. Range: 15-250 milliseconds. */
uint8_t fhss_bc_dwell_interval; uint8_t fhss_bc_dwell_interval;
/** Unicast fixed channel */
uint8_t unicast_fixed_channel;
/** Broadcast fixed channel */
uint8_t broadcast_fixed_channel;
/** Channel mask. */ /** Channel mask. */
uint32_t channel_mask[8]; uint32_t channel_mask[8];

View File

@ -37,6 +37,7 @@ typedef struct unicast_timing_info {
unsigned unicast_channel_function:3; /**< Unicast schedule channel function */ unsigned unicast_channel_function:3; /**< Unicast schedule channel function */
uint8_t unicast_dwell_interval; /**< Unicast dwell interval */ uint8_t unicast_dwell_interval; /**< Unicast dwell interval */
uint16_t unicast_number_of_channels; /**< Unicast number of channels */ uint16_t unicast_number_of_channels; /**< Unicast number of channels */
uint16_t fixed_channel; /**< Unicast fixed channel*/
uint_fast24_t ufsi; /**< Unicast fractional sequence interval */ uint_fast24_t ufsi; /**< Unicast fractional sequence interval */
uint32_t utt_rx_timestamp; /**< UTT-IE reception timestamp */ uint32_t utt_rx_timestamp; /**< UTT-IE reception timestamp */
} unicast_timing_info_t; } unicast_timing_info_t;
@ -47,6 +48,7 @@ typedef struct unicast_timing_info {
typedef struct broadcast_timing_info { typedef struct broadcast_timing_info {
unsigned broadcast_channel_function:3; /**< Broadcast schedule channel function */ unsigned broadcast_channel_function:3; /**< Broadcast schedule channel function */
uint8_t broadcast_dwell_interval; /**< Broadcast dwell interval */ uint8_t broadcast_dwell_interval; /**< Broadcast dwell interval */
uint16_t fixed_channel; /**< Broadcast fixed channel*/
uint16_t broadcast_slot; /**< Broadcast slot number */ uint16_t broadcast_slot; /**< Broadcast slot number */
uint16_t broadcast_schedule_id; /**< Broadcast schedule identifier */ uint16_t broadcast_schedule_id; /**< Broadcast schedule identifier */
uint_fast24_t broadcast_interval_offset; /**< Broadcast interval offset */ uint_fast24_t broadcast_interval_offset; /**< Broadcast interval offset */
@ -78,9 +80,10 @@ typedef fhss_ws_neighbor_timing_info_t *fhss_get_neighbor_info(const fhss_api_t
* @param fhss_api FHSS instance. * @param fhss_api FHSS instance.
* @param eui64 EUI-64 address of parent. * @param eui64 EUI-64 address of parent.
* @param bc_timing_info Pointer to parent broadcast timing/hopping schedule info. * @param bc_timing_info Pointer to parent broadcast timing/hopping schedule info.
* @param force_synch If false, synchronization is done only if minimum (internal) synchronization interval is exceed.
* @return 0 on success, -1 on fail. * @return 0 on success, -1 on fail.
*/ */
extern int ns_fhss_ws_set_parent(const fhss_api_t *fhss_api, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info); extern int ns_fhss_ws_set_parent(const fhss_api_t *fhss_api, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info, const bool force_synch);
/** /**
* @brief Remove parent which was set by ns_fhss_ws_set_parent function. * @brief Remove parent which was set by ns_fhss_ws_set_parent function.

View File

@ -137,8 +137,9 @@ typedef void mcps_data_request_ext(const mac_api_t* api, const mcps_data_req_t *
* @brief mcps_purge_request MCPS_PURGE request call * @brief mcps_purge_request MCPS_PURGE request call
* @param api API to handle the request * @param api API to handle the request
* @param data MCPS-PURGE.request specific values * @param data MCPS-PURGE.request specific values
* @return 0 in case of success, non-zero otherwise
*/ */
typedef void mcps_purge_request(const mac_api_t* api, const mcps_purge_t *data); typedef uint8_t mcps_purge_request(const mac_api_t* api, const mcps_purge_t *data);
//Upper layer specific callback functions (will also be set by Upper layer after mac_api_t has been created and given to it) //Upper layer specific callback functions (will also be set by Upper layer after mac_api_t has been created and given to it)

View File

@ -39,10 +39,9 @@ extern "C" {
extern fhss_api_t *ns_fhss_create(const fhss_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer, fhss_statistics_t *fhss_statistics); extern fhss_api_t *ns_fhss_create(const fhss_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer, fhss_statistics_t *fhss_statistics);
/** /**
* @brief TODO: description. * @brief Creates FHSS WS API instance which will be registered to software MAC.
* @param fhss_configuration Basic FHSS configuration. * @param fhss_configuration Basic FHSS configuration.
* @param fhss_timer FHSS platform timer interface and configuration. * @param fhss_timer FHSS platform timer interface and configuration.
* @param fhss_statistics FHSS statistics storage.
* @return New FHSS instance if successful, NULL otherwise. * @return New FHSS instance if successful, NULL otherwise.
*/ */
extern fhss_api_t *ns_fhss_ws_create(const fhss_ws_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer); extern fhss_api_t *ns_fhss_ws_create(const fhss_ws_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer);

View File

@ -75,6 +75,7 @@ int thread_bbr_start(int8_t interface_id, int8_t backbone_interface_id);
* *
*/ */
int thread_bbr_timeout_set(int8_t interface_id, uint32_t timeout_a, uint32_t timeout_b, uint32_t delay); int thread_bbr_timeout_set(int8_t interface_id, uint32_t timeout_a, uint32_t timeout_b, uint32_t delay);
/** /**
* Set prefix to be used as combining multiple thread networks on backbone. * Set prefix to be used as combining multiple thread networks on backbone.
* *
@ -89,6 +90,20 @@ int thread_bbr_timeout_set(int8_t interface_id, uint32_t timeout_a, uint32_t tim
*/ */
int thread_bbr_prefix_set(int8_t interface_id, uint8_t *prefix); int thread_bbr_prefix_set(int8_t interface_id, uint8_t *prefix);
/**
* Set sequence number to be used by bbr
*
* update sequence number value
*
* \param interface_id interface ID of the Thread network.
* \param sequence_number value that needs to be set on bbr
*
* \return 0 on success
* \return <0 in case of errors
*
*/
int thread_bbr_sequence_number_set(int8_t interface_id, uint8_t sequence_number);
/** /**
* Set the Thread validation interface destination address. * Set the Thread validation interface destination address.
* *

View File

@ -189,8 +189,10 @@ void *thread_commission_device_get_next(void *ptr, int8_t interface_id, bool *sh
typedef struct thread_commissioning_link_configuration { typedef struct thread_commissioning_link_configuration {
uint8_t name[16]; /**< Name of the Thread network. utf8 string nul terminated if shorter than 16. */ uint8_t name[16]; /**< Name of the Thread network. utf8 string nul terminated if shorter than 16. */
uint8_t destination_address[16]; /**<Border router destination address*/
uint8_t extented_pan_id[8]; /**< Extended PAN ID. */ uint8_t extented_pan_id[8]; /**< Extended PAN ID. */
uint16_t panId; /**< Network ID. */ uint16_t panId; /**< Network ID. */
uint16_t destination_port; /**<destination port for commissioning*/
uint8_t Protocol_id; /**< Current protocol ID. */ uint8_t Protocol_id; /**< Current protocol ID. */
uint8_t version; /**< Current protocol version. */ uint8_t version; /**< Current protocol version. */
uint8_t rfChannel; /**< Current RF channel. */ uint8_t rfChannel; /**< Current RF channel. */
@ -271,6 +273,18 @@ int thread_commissioning_native_commissioner_get_connection_info(int8_t interfac
*/ */
int8_t thread_commissioning_get_management_id(int8_t interface_id); int8_t thread_commissioning_get_management_id(int8_t interface_id);
/**
* \brief Attach native commissioner to destination address and port.
*
* \param interface_id Network interface ID.
* \param destination_address Destination address pointer.
* \param destination_port Commissioning port.
*
* \return 0 attach OK.
* \return < 0 fail.
*/
int thread_commissioning_attach(int8_t interface_id, uint8_t *destination_address, uint16_t destination_port);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -55,7 +55,8 @@
#define DIAGCOP_TLV_SUPPLY_VOLTAGE 15 /**< Can not reset*/ #define DIAGCOP_TLV_SUPPLY_VOLTAGE 15 /**< Can not reset*/
#define DIAGCOP_TLV_CHILD_TABLE 16 /**< Can not reset*/ #define DIAGCOP_TLV_CHILD_TABLE 16 /**< Can not reset*/
#define DIAGCOP_TLV_CHANNEL_PAGES 17 /**< Can not reset*/ #define DIAGCOP_TLV_CHANNEL_PAGES 17 /**< Can not reset*/
#define DIAGCOP_TLV_TYPE_LIST 18 /**< List type*/ #define DIAGCOP_TLV_TYPE_LIST 18 /**< Cannot reset*/
#define DIAGCOP_TLV_MAX_CHILD_TIMEOUT 19 /**< Cannot reset*/
/** /**
* \brief Write array TLV. * \brief Write array TLV.

View File

@ -74,6 +74,7 @@
#include "6LoWPAN/Fragmentation/cipv6_fragmenter.h" #include "6LoWPAN/Fragmentation/cipv6_fragmenter.h"
#include "Service_Libs/etx/etx.h" #include "Service_Libs/etx/etx.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#include "6LoWPAN/ws/ws_bootstrap.h"
#define TRACE_GROUP_LOWPAN "6lo" #define TRACE_GROUP_LOWPAN "6lo"
@ -473,7 +474,6 @@ void protocol_6lowpan_neighbor_priority_update(protocol_interface_info_entry_t *
} }
#ifdef HAVE_RPL #ifdef HAVE_RPL
#ifndef NO_MLE
uint16_t protocol_6lowpan_neighbor_priority_set(int8_t interface_id, addrtype_t addr_type, const uint8_t *addr_ptr) uint16_t protocol_6lowpan_neighbor_priority_set(int8_t interface_id, addrtype_t addr_type, const uint8_t *addr_ptr)
{ {
@ -486,9 +486,12 @@ uint16_t protocol_6lowpan_neighbor_priority_set(int8_t interface_id, addrtype_t
mac_neighbor_table_entry_t * entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), addr_ptr + PAN_ID_LEN, addr_type); mac_neighbor_table_entry_t * entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), addr_ptr + PAN_ID_LEN, addr_type);
if (entry) { if (entry) {
bool new_primary = false;
etx_storage_t *etx_entry = etx_storage_entry_get(interface_id, entry->index); etx_storage_t *etx_entry = etx_storage_entry_get(interface_id, entry->index);
// If primary parent has changed clears priority from previous parent // If primary parent has changed clears priority from previous parent
if (entry->link_role != PRIORITY_PARENT_NEIGHBOUR) { if (entry->link_role != PRIORITY_PARENT_NEIGHBOUR) {
new_primary = true;
protocol_6lowpan_neighbor_priority_clear_all(interface_id, PRIORITY_1ST); protocol_6lowpan_neighbor_priority_clear_all(interface_id, PRIORITY_1ST);
} }
entry->link_role = PRIORITY_PARENT_NEIGHBOUR; entry->link_role = PRIORITY_PARENT_NEIGHBOUR;
@ -501,6 +504,10 @@ uint16_t protocol_6lowpan_neighbor_priority_set(int8_t interface_id, addrtype_t
if (etx_entry) { if (etx_entry) {
protocol_stats_update(STATS_ETX_1ST_PARENT, etx_entry->etx >> 4); protocol_stats_update(STATS_ETX_1ST_PARENT, etx_entry->etx >> 4);
} }
if (new_primary) {
ws_primary_parent_update(cur, entry);
}
return 1; return 1;
} else { } else {
return 0; return 0;
@ -519,9 +526,11 @@ uint16_t protocol_6lowpan_neighbor_second_priority_set(int8_t interface_id, addr
mac_neighbor_table_entry_t * entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), addr_ptr + PAN_ID_LEN, addr_type); mac_neighbor_table_entry_t * entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), addr_ptr + PAN_ID_LEN, addr_type);
if (entry) { if (entry) {
bool new_secondary = false;
etx_storage_t *etx_entry = etx_storage_entry_get(interface_id, entry->index); etx_storage_t *etx_entry = etx_storage_entry_get(interface_id, entry->index);
// If secondary parent has changed clears priority from previous parent // If secondary parent has changed clears priority from previous parent
if (entry->link_role != SECONDARY_PARENT_NEIGHBOUR) { if (entry->link_role != SECONDARY_PARENT_NEIGHBOUR) {
new_secondary = true;
protocol_6lowpan_neighbor_priority_clear_all(interface_id, PRIORITY_2ND); protocol_6lowpan_neighbor_priority_clear_all(interface_id, PRIORITY_2ND);
} }
entry->link_role = SECONDARY_PARENT_NEIGHBOUR; entry->link_role = SECONDARY_PARENT_NEIGHBOUR;
@ -529,6 +538,9 @@ uint16_t protocol_6lowpan_neighbor_second_priority_set(int8_t interface_id, addr
if (etx_entry) { if (etx_entry) {
protocol_stats_update(STATS_ETX_2ND_PARENT, etx_entry->etx >> 4); protocol_stats_update(STATS_ETX_2ND_PARENT, etx_entry->etx >> 4);
} }
if (new_secondary) {
ws_secondary_parent_update(cur);
}
return 1; return 1;
} else { } else {
return 0; return 0;
@ -557,7 +569,6 @@ void protocol_6lowpan_neighbor_priority_clear_all(int8_t interface_id, neighbor_
} }
} }
#endif
#endif #endif
#endif #endif

View File

@ -1786,7 +1786,7 @@ int8_t arm_6lowpan_bootstarp_bootstrap_set(int8_t interface_id, net_6lowpan_mode
*/ */
if (cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) { if (cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
//rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true); //rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true);
//rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, cur); //rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, NULL, cur);
} }
#endif #endif
cur->configure_flags |= INTERFACE_BOOTSTRAP_DEFINED; cur->configure_flags |= INTERFACE_BOOTSTRAP_DEFINED;
@ -2073,6 +2073,8 @@ static void protocol_6lowpan_bootstrap_rpl_callback(rpl_event_t event, void *han
tr_error("RPL Local repair fail-->interface to idle"); tr_error("RPL Local repair fail-->interface to idle");
nwk_bootsrap_state_update(ARM_NWK_NWK_CONNECTION_DOWN, cur); nwk_bootsrap_state_update(ARM_NWK_NWK_CONNECTION_DOWN, cur);
break; break;
default:
break;
} }
} }
@ -2179,7 +2181,7 @@ void nwk_6lowpan_nd_address_registartion_ready(protocol_interface_info_entry_t *
// arm_nwk_6lowpan_rpl_dodag_poison from a previous connection may have left force_leaf set // arm_nwk_6lowpan_rpl_dodag_poison from a previous connection may have left force_leaf set
rpl_control_force_leaf(protocol_6lowpan_rpl_domain, false); rpl_control_force_leaf(protocol_6lowpan_rpl_domain, false);
rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true); rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true);
rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, cur); rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, NULL, cur);
} }
// Send unicast DIS to coordinator // Send unicast DIS to coordinator
nwk_bootstrap_icmp_rpl_dis_coord_msg_tx(cur); nwk_bootstrap_icmp_rpl_dis_coord_msg_tx(cur);

View File

@ -39,9 +39,10 @@ typedef void mpx_data_request(const mpx_api_t *api, const struct mcps_data_req_s
* @param api API to handle the request * @param api API to handle the request
* @param purge MCPS-purge request * @param purge MCPS-purge request
* @param user_id MPX user ID * @param user_id MPX user ID
* @return 0 if purge requst was OK, non-zero otherwise
* *
*/ */
typedef void mpx_data_purge_request(const mpx_api_t *api, struct mcps_purge_s *purge, uint16_t user_id); typedef uint8_t mpx_data_purge_request(const mpx_api_t *api, struct mcps_purge_s *purge, uint16_t user_id);
/** /**
* @brief mpx_data_confirm MPX-DATA confirm is called as a response to MPX-DATA request * @brief mpx_data_confirm MPX-DATA confirm is called as a response to MPX-DATA request

View File

@ -40,12 +40,16 @@
#include "common_functions.h" #include "common_functions.h"
#include "thread_border_router_api.h" #include "thread_border_router_api.h"
#include "thread_bbr_api.h" #include "thread_bbr_api.h"
#include "net_ipv6_api.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "Common_Protocols/ipv6_constants.h" #include "Common_Protocols/ipv6_constants.h"
#include "DHCPv6_Server/DHCPv6_server_service.h" #include "DHCPv6_Server/DHCPv6_server_service.h"
#include "6LoWPAN/Thread/thread_dhcpv6_server.h"
#include "thread_management_if.h" #include "thread_management_if.h"
#include "6LoWPAN/Thread/thread_config.h" #include "6LoWPAN/Thread/thread_config.h"
#include "6LoWPAN/Thread/thread_constants.h" #include "6LoWPAN/Thread/thread_constants.h"
#include "6LoWPAN/Thread/thread_common.h" #include "6LoWPAN/Thread/thread_common.h"
#include "6LoWPAN/Thread/thread_bootstrap.h"
#include "6LoWPAN/Thread/thread_joiner_application.h" #include "6LoWPAN/Thread/thread_joiner_application.h"
#include "6LoWPAN/Thread/thread_extension.h" #include "6LoWPAN/Thread/thread_extension.h"
#include "6LoWPAN/Thread/thread_extension_bbr.h" #include "6LoWPAN/Thread/thread_extension_bbr.h"
@ -96,7 +100,6 @@ typedef struct {
#define RFC6106_DNS_SEARCH_LIST_OPTION 31 #define RFC6106_DNS_SEARCH_LIST_OPTION 31
static NS_LIST_DEFINE(bbr_instance_list, thread_bbr_t, link); static NS_LIST_DEFINE(bbr_instance_list, thread_bbr_t, link);
static thread_bbr_t *thread_bbr_find_by_interface(int8_t interface_id) static thread_bbr_t *thread_bbr_find_by_interface(int8_t interface_id)
{ {
thread_bbr_t *this = NULL; thread_bbr_t *this = NULL;
@ -579,7 +582,7 @@ static void thread_bbr_network_data_send(thread_bbr_t *this, uint8_t prefix[8],
// delete old prefix // delete old prefix
memset(this->bbr_prefix,0,8); memset(this->bbr_prefix,0,8);
// create new prefix // create new prefix
if (DHCPv6_server_service_init(this->interface_id, prefix, eui64, DHCPV6_DUID_HARDWARE_EUI64_TYPE) != 0) { if (thread_dhcp6_server_init(this->interface_id, prefix, eui64, THREAD_MIN_PREFIX_LIFETIME) != 0) {
tr_warn("DHCP server alloc fail"); tr_warn("DHCP server alloc fail");
// set 20 seconds delay before next process // set 20 seconds delay before next process
this->br_delay_timer = 20; this->br_delay_timer = 20;
@ -587,8 +590,6 @@ static void thread_bbr_network_data_send(thread_bbr_t *this, uint8_t prefix[8],
} }
memcpy(this->bbr_prefix,prefix,8); memcpy(this->bbr_prefix,prefix,8);
DHCPv6_server_service_set_address_validlifetime(this->interface_id, this->bbr_prefix, THREAD_MIN_PREFIX_LIFETIME);
br_info.P_default_route = true; br_info.P_default_route = true;
br_info.P_dhcp = true; br_info.P_dhcp = true;
br_info.P_on_mesh = true; br_info.P_on_mesh = true;
@ -724,7 +725,7 @@ static bool thread_bbr_activated(thread_bbr_t *this, uint32_t seconds)
return true; return true;
} }
if (cur->thread_info->routerIdReqCoapID) { if (cur->thread_info->routerIdRequested) {
// Router id reguest pending we need to wait for response // Router id reguest pending we need to wait for response
return false; return false;
} }
@ -978,18 +979,18 @@ int thread_bbr_nd_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr,
int thread_bbr_dua_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr, uint32_t lifetime, const uint8_t *mleid_ptr) int thread_bbr_dua_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr, uint32_t lifetime, const uint8_t *mleid_ptr)
{ {
thread_bbr_t *this = thread_bbr_find_by_interface(interface_id); thread_bbr_t *this = thread_bbr_find_by_interface(interface_id);
thread_pbbr_dua_info_t *map;
if (!this || this->backbone_interface_id < 0) { if (!this || this->backbone_interface_id < 0) {
return -1; return -1;
} }
thread_pbbr_dua_info_t *map = ns_dyn_mem_alloc(sizeof(thread_pbbr_dua_info_t)); ipv6_route_t *route = ipv6_route_lookup_with_info(addr_data_ptr, 128, interface_id, NULL, ROUTE_THREAD_PROXIED_DUA_HOST, NULL, 0);
if (!route){
map = ns_dyn_mem_alloc(sizeof(thread_pbbr_dua_info_t));
if (!map) { if (!map) {
goto error; goto error;
} }
memcpy(map->mleid_ptr, mleid_ptr, 8);
map->last_contact_time = protocol_core_monotonic_time;
// We are using route info field to store BBR MLEID map // We are using route info field to store BBR MLEID map
ipv6_route_t *route = ipv6_route_add_with_info(addr_data_ptr, 128, interface_id, NULL, ROUTE_THREAD_PROXIED_DUA_HOST, map, 0, lifetime, 0); route = ipv6_route_add_with_info(addr_data_ptr, 128, interface_id, NULL, ROUTE_THREAD_PROXIED_DUA_HOST, map, 0, lifetime, 0);
if (!route) { if (!route) {
// Direct route to host allows ND proxying to work // Direct route to host allows ND proxying to work
ns_dyn_mem_free(map); ns_dyn_mem_free(map);
@ -997,6 +998,12 @@ int thread_bbr_dua_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr,
} }
// Route info autofreed // Route info autofreed
route->info_autofree = true; route->info_autofree = true;
}
map = route->info.info;
memcpy(map->mleid_ptr, mleid_ptr, 8);
map->last_contact_time = protocol_core_monotonic_time;
route->info.info = map;
// send NA // send NA
thread_bbr_na_send(this->backbone_interface_id, addr_data_ptr); thread_bbr_na_send(this->backbone_interface_id, addr_data_ptr);
@ -1006,15 +1013,6 @@ error:
return -2; return -2;
} }
struct ipv6_route *thread_bbr_dua_entry_find(int8_t interface_id, const uint8_t *addr_data_ptr) {
ipv6_route_t *route = ipv6_route_choose_next_hop(addr_data_ptr, interface_id, NULL);
if (!route || route->prefix_len < 128 || !route->on_link || route->info.source != ROUTE_THREAD_PROXIED_DUA_HOST ) {
//Not found
return NULL;
}
return route;
}
int thread_bbr_proxy_state_update(int8_t caller_interface_id , int8_t handler_interface_id, bool status) int thread_bbr_proxy_state_update(int8_t caller_interface_id , int8_t handler_interface_id, bool status)
{ {
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(handler_interface_id); protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(handler_interface_id);
@ -1099,7 +1097,11 @@ int thread_bbr_start(int8_t interface_id, int8_t backbone_interface_id)
// By default multicast forwarding is not enabled as it causes multicast loops // By default multicast forwarding is not enabled as it causes multicast loops
multicast_fwd_set_forwarding(this->interface_id, false); multicast_fwd_set_forwarding(this->interface_id, false);
// Adjust BBR neighbor and destination cache size
arm_nwk_ipv6_max_cache_entries(THREAD_BBR_IPV6_DESTINATION_CACHE_SIZE);
thread_extension_bbr_init(interface_id,backbone_interface_id); thread_extension_bbr_init(interface_id,backbone_interface_id);
return 0; return 0;
#else #else
return -1; return -1;
@ -1131,6 +1133,17 @@ int thread_bbr_prefix_set(int8_t interface_id, uint8_t *prefix)
#endif // HAVE_THREAD_BORDER_ROUTER #endif // HAVE_THREAD_BORDER_ROUTER
} }
int thread_bbr_sequence_number_set(int8_t interface_id, uint8_t sequence_number)
{
(void) interface_id;
(void) sequence_number;
#ifdef HAVE_THREAD_BORDER_ROUTER
return thread_extension_bbr_sequence_number_set(interface_id, sequence_number);
#else
return -1;
#endif // HAVE_THREAD_BORDER_ROUTER
}
int thread_bbr_validation_interface_address_set(int8_t interface_id, const uint8_t *addr_ptr, uint16_t port) int thread_bbr_validation_interface_address_set(int8_t interface_id, const uint8_t *addr_ptr, uint16_t port)
{ {
(void) interface_id; (void) interface_id;

View File

@ -67,7 +67,6 @@ void thread_bbr_seconds_timer(int8_t interface_id, uint32_t tics);
*/ */
int thread_bbr_commissioner_proxy_service_update(int8_t interface_id); int thread_bbr_commissioner_proxy_service_update(int8_t interface_id);
#else #else
#define thread_bbr_init(interface_id, external_commisssioner_port) #define thread_bbr_init(interface_id, external_commisssioner_port)
#define thread_bbr_delete(interface_id) #define thread_bbr_delete(interface_id)
@ -118,12 +117,6 @@ int thread_bbr_dua_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr,
*/ */
int thread_bbr_na_send(int8_t interface_id, const uint8_t target[static 16]); int thread_bbr_na_send(int8_t interface_id, const uint8_t target[static 16]);
/**
* \brief Find if bbr has dua entry
*
* \param interface_id addr_data_ptr
*/
struct ipv6_route *thread_bbr_dua_entry_find(int8_t interface_id, const uint8_t *addr_data_ptr);
#else #else
#define thread_bbr_proxy_state_update(caller_interface_id , handler_interface_id, status) (NULL) #define thread_bbr_proxy_state_update(caller_interface_id , handler_interface_id, status) (NULL)
@ -131,7 +124,6 @@ struct ipv6_route *thread_bbr_dua_entry_find(int8_t interface_id, const uint8_t
#define thread_bbr_network_data_update_notify(cur) #define thread_bbr_network_data_update_notify(cur)
#define thread_bbr_nd_entry_add(interface_id, addr_data_ptr, lifetime, info) (0) #define thread_bbr_nd_entry_add(interface_id, addr_data_ptr, lifetime, info) (0)
#define thread_bbr_dua_entry_add(interface_id, addr_data_ptr, lifetime, mleid_ptr) (0) #define thread_bbr_dua_entry_add(interface_id, addr_data_ptr, lifetime, mleid_ptr) (0)
#define thread_bbr_dua_entry_find(interface_id, addr_data_ptr) (NULL)
#define thread_bbr_na_send(interface_id, target) (0) #define thread_bbr_na_send(interface_id, target) (0)
#endif //HAVE_THREAD_BORDER_ROUTER #endif //HAVE_THREAD_BORDER_ROUTER

View File

@ -86,7 +86,7 @@
#include "MPL/mpl.h" #include "MPL/mpl.h"
#include "MLE/mle.h" #include "MLE/mle.h"
#include "MLE/mle_tlv.h" #include "MLE/mle_tlv.h"
#include "thread_dhcpv6_client.h" #include "DHCPv6_client/dhcpv6_client_api.h"
#include "thread_config.h" #include "thread_config.h"
#include "thread_meshcop_lib.h" #include "thread_meshcop_lib.h"
#include "multicast_api.h" #include "multicast_api.h"
@ -136,8 +136,6 @@ static void thread_neighbor_remove(mac_neighbor_table_entry_t *entry_ptr, void *
static bool thread_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data) static bool thread_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data)
{ {
// Sleepy host
protocol_interface_info_entry_t *cur_interface = user_data; protocol_interface_info_entry_t *cur_interface = user_data;
if (thread_am_router(cur_interface)) { if (thread_am_router(cur_interface)) {
@ -676,8 +674,6 @@ static void thread_bootstrap_ml_address_update(protocol_interface_info_entry_t *
// Generate new ML64 address // Generate new ML64 address
thread_generate_ml64_address(cur); thread_generate_ml64_address(cur);
// Generate new domain address
thread_extension_address_generate(cur);
// Register multicast addresses // Register multicast addresses
thread_bootstrap_all_nodes_multicast_register(cur); thread_bootstrap_all_nodes_multicast_register(cur);
@ -698,8 +694,6 @@ int thread_configuration_thread_activate(protocol_interface_info_entry_t *cur, l
//Define Default Contexts //Define Default Contexts
lowpan_context_update(&cur->lowpan_contexts, LOWPAN_CONTEXT_C, 0xFFFF, linkConfiguration->mesh_local_ula_prefix, 64, true); lowpan_context_update(&cur->lowpan_contexts, LOWPAN_CONTEXT_C, 0xFFFF, linkConfiguration->mesh_local_ula_prefix, 64, true);
thread_extension_activate(cur);
thread_extension_bbr_route_update(cur); thread_extension_bbr_route_update(cur);
blacklist_clear(); blacklist_clear();
@ -896,7 +890,7 @@ void thread_interface_init(protocol_interface_info_entry_t *cur)
{ {
thread_discovery_reset(cur->id); thread_discovery_reset(cur->id);
thread_routing_set_mesh_callbacks(cur); thread_routing_set_mesh_callbacks(cur);
thread_dhcp_client_init(cur->id); dhcp_client_init(cur->id);
thread_management_client_init(cur->id); thread_management_client_init(cur->id);
thread_address_registration_init(); thread_address_registration_init();
cur->mpl_seed_id_mode = MULTICAST_MPL_SEED_ID_MAC_SHORT; cur->mpl_seed_id_mode = MULTICAST_MPL_SEED_ID_MAC_SHORT;
@ -1069,9 +1063,7 @@ void thread_tasklet(arm_event_s *event)
case THREAD_CHILD_UPDATE: case THREAD_CHILD_UPDATE:
tr_debug_extra("Thread SM THREAD_CHILD_UPDATE"); tr_debug_extra("Thread SM THREAD_CHILD_UPDATE");
if (thread_info(cur)->thread_endnode_parent) {
thread_host_bootstrap_child_update(cur, cur->thread_info->thread_endnode_parent->mac64); thread_host_bootstrap_child_update(cur, cur->thread_info->thread_endnode_parent->mac64);
}
break; break;
case THREAD_ANNOUNCE_ACTIVE: { case THREAD_ANNOUNCE_ACTIVE: {
tr_debug_extra("Thread SM THREAD_ANNOUNCE_ACTIVE"); tr_debug_extra("Thread SM THREAD_ANNOUNCE_ACTIVE");
@ -1178,6 +1170,10 @@ void thread_bootstrap_ready(protocol_interface_info_entry_t *cur)
thread_leader_service_generate_network_data(cur); thread_leader_service_generate_network_data(cur);
} }
if (thread_addresses_needs_to_be_registered(cur)) {
thread_info(cur)->childUpdateReqTimer = 1;
}
cur->bootsrap_state_machine_cnt = 0; cur->bootsrap_state_machine_cnt = 0;
mac_data_poll_protocol_poll_mode_decrement(cur); mac_data_poll_protocol_poll_mode_decrement(cur);
} }
@ -1194,6 +1190,31 @@ void thread_neighbor_list_clean(struct protocol_interface_info_entry *cur)
} }
} }
void thread_reed_fed_neighbour_links_clean(struct protocol_interface_info_entry *cur)
{
mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
if (thread_i_am_router(cur)) {
return;
}
if (thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE ||
thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) {
return;
}
if (!thread_info(cur)->thread_endnode_parent) {
return;
}
ns_list_foreach_safe(mac_neighbor_table_entry_t, cur_entry, mac_table_list) {
// do not remove parent entry
if (memcmp(cur_entry->mac64, thread_info(cur)->thread_endnode_parent->mac64, 8) != 0) {
tr_debug("Free short addr: %x", cur_entry->mac16);
mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), cur_entry);
}
}
}
void thread_clean_old_16_bit_address_based_addresses(protocol_interface_info_entry_t *cur) void thread_clean_old_16_bit_address_based_addresses(protocol_interface_info_entry_t *cur)
{ {
uint8_t static_address[16]; uint8_t static_address[16];
@ -1612,7 +1633,6 @@ void thread_bootstrap_routing_activate(protocol_interface_info_entry_t *cur)
if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE || if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE ||
cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) {
thread_meshlocal_route_set(cur); thread_meshlocal_route_set(cur);
thread_extension_route_set(cur);
// FEDs and routers (REEDs) perform their own address resolution // FEDs and routers (REEDs) perform their own address resolution
thread_nd_service_activate(cur->id); thread_nd_service_activate(cur->id);
} else { } else {
@ -1627,7 +1647,7 @@ void thread_bootstrap_attached_finish(protocol_interface_info_entry_t *cur)
cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY; cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY;
cur->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE; cur->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE;
cur->bootsrap_state_machine_cnt = 10; cur->bootsrap_state_machine_cnt = 10;
cur->thread_info->routerIdReqCoapID = 0; cur->thread_info->routerIdRequested = false;
cur->thread_info->networkDataRequested = false; cur->thread_info->networkDataRequested = false;
clear_power_state(ICMP_ACTIVE); clear_power_state(ICMP_ACTIVE);
@ -1644,8 +1664,6 @@ void thread_bootstrap_attached_finish(protocol_interface_info_entry_t *cur)
thread_generate_ml16_address(cur); thread_generate_ml16_address(cur);
//GENERATE ML-EID64 //GENERATE ML-EID64
thread_generate_ml64_address(cur); thread_generate_ml64_address(cur);
// Generate new domain address
thread_extension_address_generate(cur);
thread_bootstrap_routing_activate(cur); thread_bootstrap_routing_activate(cur);
thread_bootstrap_network_data_update(cur); thread_bootstrap_network_data_update(cur);
// After successful attach if there is announcement info present, send announcement back to previous channel // After successful attach if there is announcement info present, send announcement back to previous channel
@ -1823,8 +1841,7 @@ static void thread_dhcp_client_gua_error_cb(int8_t interface, uint8_t dhcp_addr[
tr_warn("Address Get fail: %s from: %s", trace_ipv6(prefix), trace_ipv6(dhcp_addr)); tr_warn("Address Get fail: %s from: %s", trace_ipv6(prefix), trace_ipv6(dhcp_addr));
if (prefix && dhcp_addr) { if (prefix && dhcp_addr) {
tr_debug("Delete Current Server data"); tr_debug("Delete Current Server data");
thread_dhcp_client_global_address_delete(interface, dhcp_addr, prefix); dhcp_client_global_address_delete(interface, dhcp_addr, prefix);
//TODO shuold we try again or select new Server
} }
} }
} }
@ -1964,6 +1981,10 @@ void thread_discover_native_commissioner_response(protocol_interface_info_entry_
config_ptr[n].rfChannel = cur_class->channel; config_ptr[n].rfChannel = cur_class->channel;
memcpy(config_ptr[n].name, cur_class->network_name, 16); memcpy(config_ptr[n].name, cur_class->network_name, 16);
memcpy(config_ptr[n].extented_pan_id, cur_class->extented_pan_id, 8); memcpy(config_ptr[n].extented_pan_id, cur_class->extented_pan_id, 8);
memcpy(config_ptr[n].destination_address, ADDR_LINK_LOCAL_PREFIX, 8);
memcpy(&config_ptr[n].destination_address[8], cur_class->extented_mac, 8);
config_ptr[n].destination_address[8] ^= 2;
config_ptr[n].destination_port = cur_class->commissioner_port;
n++; n++;
} }
@ -2023,7 +2044,7 @@ void thread_discover_native_commissioner_response(protocol_interface_info_entry_
interface->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY; interface->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY;
interface->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE; interface->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE;
interface->thread_info->routerIdReqCoapID = 0; interface->thread_info->routerIdRequested = false;
interface->thread_info->networkDataRequested = false; interface->thread_info->networkDataRequested = false;
interface->bootsrap_state_machine_cnt = 10; interface->bootsrap_state_machine_cnt = 10;
@ -2128,6 +2149,12 @@ static bool thread_bootstrap_sync_after_reset_start(protocol_interface_info_entr
uint16_t my_short_address; uint16_t my_short_address;
uint8_t parent_mac64[8]; uint8_t parent_mac64[8];
// link sync is allowed only once in bootstrap start and we might get here in other cases also
if (!cur->thread_info->link_sync_allowed) {
return false;
}
cur->thread_info->link_sync_allowed = false;
int link_info_err = thread_nvm_store_link_info_get(parent_mac64, &my_short_address); int link_info_err = thread_nvm_store_link_info_get(parent_mac64, &my_short_address);
if ( link_info_err!= THREAD_NVM_FILE_SUCCESS) { if ( link_info_err!= THREAD_NVM_FILE_SUCCESS) {
tr_warning("thread_nvm_store_link_info_get returned %d", link_info_err); tr_warning("thread_nvm_store_link_info_get returned %d", link_info_err);
@ -2278,7 +2305,7 @@ void thread_bootstrap_stop(protocol_interface_info_entry_t *cur)
thread_leader_service_leader_data_free(cur->thread_info); thread_leader_service_leader_data_free(cur->thread_info);
thread_bootstrap_all_nodes_multicast_unregister(cur); thread_bootstrap_all_nodes_multicast_unregister(cur);
thread_data_base_init(cur->thread_info, cur->id); thread_data_base_init(cur->thread_info, cur->id);
thread_dhcp_client_delete(cur->id); dhcp_client_delete(cur->id);
thread_nd_service_delete(cur->id); thread_nd_service_delete(cur->id);
thread_child_id_request_entry_clean(cur); thread_child_id_request_entry_clean(cur);
thread_registered_mcast_addr_entry_clean(cur); thread_registered_mcast_addr_entry_clean(cur);
@ -2356,6 +2383,7 @@ static int thread_nd_prefix_context_allocate(protocol_interface_info_entry_t *cu
if (cid == 16) { if (cid == 16) {
return -1; return -1;
} }
context.cid = cid; context.cid = cid;
context.compression = true; context.compression = true;
context.stableData = stableData; context.stableData = stableData;
@ -2499,6 +2527,7 @@ int thread_bootstrap_network_data_process(protocol_interface_info_entry_t *cur,
genericService.P_slaac = ((flags >> THREAD_P_SLAAC_BIT_MOVE) & 1); genericService.P_slaac = ((flags >> THREAD_P_SLAAC_BIT_MOVE) & 1);
genericService.P_on_mesh = ((flags >> THREAD_P_ON_MESH_BIT_MOVE) & 1); genericService.P_on_mesh = ((flags >> THREAD_P_ON_MESH_BIT_MOVE) & 1);
genericService.P_nd_dns = ((flags >> THREAD_P_ND_DNS_BIT_MOVE) & 1); genericService.P_nd_dns = ((flags >> THREAD_P_ND_DNS_BIT_MOVE) & 1);
genericService.P_res1 = ((flags >> THREAD_P_ND_RES_BIT_MOVE) & 1);
if (thread_nd_local_list_add_on_mesh_prefix(networkDataStorage, &prefixTlv, &genericService) == 0) { if (thread_nd_local_list_add_on_mesh_prefix(networkDataStorage, &prefixTlv, &genericService) == 0) {
if (networkDataStorage->stableUpdatePushed || networkDataStorage->temporaryUpdatePushed) { if (networkDataStorage->stableUpdatePushed || networkDataStorage->temporaryUpdatePushed) {
if (!genericService.P_slaac) { if (!genericService.P_slaac) {
@ -2525,7 +2554,7 @@ int thread_bootstrap_network_data_process(protocol_interface_info_entry_t *cur,
memcpy(&addr[8], ADDR_SHORT_ADR_SUFFIC, 6); memcpy(&addr[8], ADDR_SHORT_ADR_SUFFIC, 6);
common_write_16_bit(genericService.routerID, &addr[14]); common_write_16_bit(genericService.routerID, &addr[14]);
tr_debug("Delete DHCPv6 given address"); tr_debug("Delete DHCPv6 given address");
thread_dhcp_client_global_address_delete(cur->id, addr, prefixTlv.Prefix); dhcp_client_global_address_delete(cur->id, addr, prefixTlv.Prefix);
} }
} }
@ -2702,6 +2731,8 @@ int thread_bootstrap_network_data_activate(protocol_interface_info_entry_t *cur)
thread_border_router_network_data_update_notify(cur); thread_border_router_network_data_update_notify(cur);
thread_bbr_network_data_update_notify(cur); thread_bbr_network_data_update_notify(cur);
thread_maintenance_timer_set(cur, THREAD_MAINTENANCE_TIMER_INTERVAL);
return 0; return 0;
} }
@ -2744,7 +2775,6 @@ int thread_bootstrap_network_data_save(protocol_interface_info_entry_t *cur, thr
return 0; return 0;
} }
void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *cur) void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *cur)
{ {
// Route prefix is variable-length, so need to zero pad for ip6tos // Route prefix is variable-length, so need to zero pad for ip6tos
@ -2794,6 +2824,8 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *
if (curBorderRouter->P_dhcp && weHostService && nd_proxy_enabled_for_upstream(cur->id) && nd_proxy_upstream_route_onlink(cur->id,curPrefix->servicesPrefix)) { if (curBorderRouter->P_dhcp && weHostService && nd_proxy_enabled_for_upstream(cur->id) && nd_proxy_upstream_route_onlink(cur->id,curPrefix->servicesPrefix)) {
// don't add // don't add
tr_debug("Suppressing onlink %s for proxy", trace_ipv6_prefix(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen)); tr_debug("Suppressing onlink %s for proxy", trace_ipv6_prefix(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen));
} else if (curBorderRouter->P_res1) {
ipv6_route_add(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, cur->id, NULL, ROUTE_THREAD_PROXIED_DUA_HOST, 0xffffffff, 0);
} else { } else {
//add //add
tr_debug("Adding onlink %s", trace_ipv6_prefix(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen)); tr_debug("Adding onlink %s", trace_ipv6_prefix(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen));
@ -2818,8 +2850,8 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *
if (!thread_dhcpv6_address_entry_available(curPrefix->servicesPrefix, &cur->ip_addresses)) { if (!thread_dhcpv6_address_entry_available(curPrefix->servicesPrefix, &cur->ip_addresses)) {
thread_addr_write_mesh_local_16(addr, curBorderRouter->routerID, cur->thread_info); thread_addr_write_mesh_local_16(addr, curBorderRouter->routerID, cur->thread_info);
/* Do not allow multiple DHCP solicits from one prefix => delete previous */ /* Do not allow multiple DHCP solicits from one prefix => delete previous */
thread_dhcp_client_global_address_delete(cur->id, NULL, curPrefix->servicesPrefix); dhcp_client_global_address_delete(cur->id, NULL, curPrefix->servicesPrefix);
if (thread_dhcp_client_get_global_address(cur->id, addr, curPrefix->servicesPrefix, cur->mac, thread_dhcp_client_gua_error_cb) == 0) { if (dhcp_client_get_global_address(cur->id, addr, curPrefix->servicesPrefix, cur->mac, thread_dhcp_client_gua_error_cb) == 0) {
tr_debug("GP Address Requested"); tr_debug("GP Address Requested");
} }
} }
@ -2839,6 +2871,10 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *
icmpv6_slaac_address_add(cur, curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, 0xffffffff, 0xffffffff, true, SLAAC_IID_DEFAULT); icmpv6_slaac_address_add(cur, curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, 0xffffffff, 0xffffffff, true, SLAAC_IID_DEFAULT);
} }
} }
// generate address based on res1 bit
if (curBorderRouter->P_res1) {
thread_extension_dua_address_generate(cur,curPrefix->servicesPrefix,64);
}
} // for each borderRouterList } // for each borderRouterList

View File

@ -106,6 +106,9 @@ void thread_general_mle_receive_cb(int8_t interface_id, mle_message_t *mle_msg,
void thread_bootstrap_ready(struct protocol_interface_info_entry *cur); void thread_bootstrap_ready(struct protocol_interface_info_entry *cur);
int thread_bootstrap_reset(struct protocol_interface_info_entry *cur); int thread_bootstrap_reset(struct protocol_interface_info_entry *cur);
void thread_neighbor_list_clean(struct protocol_interface_info_entry *cur); void thread_neighbor_list_clean(struct protocol_interface_info_entry *cur);
/* Function to remove linked neighbours for REEDs and FEDs */
void thread_reed_fed_neighbour_links_clean(struct protocol_interface_info_entry *cur);
bool thread_bootstrap_request_network_data(struct protocol_interface_info_entry *cur, struct thread_leader_data_s *leaderData, uint16_t short_address); bool thread_bootstrap_request_network_data(struct protocol_interface_info_entry *cur, struct thread_leader_data_s *leaderData, uint16_t short_address);
bool thread_check_is_this_my_parent(struct protocol_interface_info_entry *cur, struct mac_neighbor_table_entry *entry_temp); bool thread_check_is_this_my_parent(struct protocol_interface_info_entry *cur, struct mac_neighbor_table_entry *entry_temp);
void thread_clean_old_16_bit_address_based_addresses(struct protocol_interface_info_entry *cur); void thread_clean_old_16_bit_address_based_addresses(struct protocol_interface_info_entry *cur);
@ -191,7 +194,6 @@ int thread_bootstrap_announce_send(protocol_interface_info_entry_t *cur, uint8_t
void thread_bootstrap_announcement_start(protocol_interface_info_entry_t *cur, uint8_t channel_page, uint16_t channel, uint8_t count, uint16_t period); void thread_bootstrap_announcement_start(protocol_interface_info_entry_t *cur, uint8_t channel_page, uint16_t channel, uint8_t count, uint16_t period);
void thread_bootstrap_temporary_attach(protocol_interface_info_entry_t *cur, uint8_t channel_page, uint16_t channel, uint16_t panid, uint64_t timestamp); void thread_bootstrap_temporary_attach(protocol_interface_info_entry_t *cur, uint8_t channel_page, uint16_t channel, uint16_t panid, uint64_t timestamp);
#else #else
#define thread_interface_up(cur) ((void) 0) #define thread_interface_up(cur) ((void) 0)
#define thread_bootstrap_state_machine(cur) ((void)0) #define thread_bootstrap_state_machine(cur) ((void)0)

View File

@ -42,6 +42,7 @@
#include "NWK_INTERFACE/Include/protocol.h" #include "NWK_INTERFACE/Include/protocol.h"
#include "6LoWPAN/Thread/thread_config.h" #include "6LoWPAN/Thread/thread_config.h"
#include "6LoWPAN/Thread/thread_common.h" #include "6LoWPAN/Thread/thread_common.h"
#include "6LoWPAN/Thread/thread_extension_bbr.h"
#include "6LoWPAN/Thread/thread_network_data_lib.h" #include "6LoWPAN/Thread/thread_network_data_lib.h"
#include "6LoWPAN/Thread/thread_network_data_storage.h" #include "6LoWPAN/Thread/thread_network_data_storage.h"
#include "6LoWPAN/Thread/thread_management_client.h" #include "6LoWPAN/Thread/thread_management_client.h"
@ -591,6 +592,15 @@ void thread_border_router_network_data_update_notify(protocol_interface_info_ent
thread_border_router_network_data_appl_callback(cur); thread_border_router_network_data_appl_callback(cur);
} }
void thread_border_router_old_partition_data_clean(int8_t interface_id)
{
thread_border_router_t *this = thread_border_router_find_by_interface(interface_id);
if (this) {
coap_service_request_delete_by_service_id(this->coap_service_id);
}
thread_extension_bbr_old_partition_data_clean(interface_id);
}
#endif // HAVE_THREAD_ROUTER #endif // HAVE_THREAD_ROUTER
/*External APIs*/ /*External APIs*/
@ -837,7 +847,6 @@ int thread_border_router_dns_search_list_option_set(int8_t interface_id, uint8_t
static void thread_tmf_client_network_data_set_cb(int8_t interface_id, int8_t status, uint8_t *data_ptr, uint16_t data_len) static void thread_tmf_client_network_data_set_cb(int8_t interface_id, int8_t status, uint8_t *data_ptr, uint16_t data_len)
{ {
protocol_interface_info_entry_t *cur; protocol_interface_info_entry_t *cur;
(void) status;
(void) data_len; (void) data_len;
(void) data_ptr; (void) data_ptr;
@ -846,7 +855,7 @@ static void thread_tmf_client_network_data_set_cb(int8_t interface_id, int8_t st
return; return;
} }
cur->thread_info->localServerDataBase.publish_active = false; cur->thread_info->localServerDataBase.publish_coap_req_id = 0;
tr_debug("BR a/sd response status: %s, addr: %x",status?"Fail":"OK", cur->thread_info->localServerDataBase.registered_rloc16); tr_debug("BR a/sd response status: %s, addr: %x",status?"Fail":"OK", cur->thread_info->localServerDataBase.registered_rloc16);
@ -855,10 +864,12 @@ static void thread_tmf_client_network_data_set_cb(int8_t interface_id, int8_t st
thread_border_router_publish(cur->id); thread_border_router_publish(cur->id);
} }
// always update RLOC to new one. If COAP response fails then resubmit timer will trigger new a/sd if (status == 0) {
// If request was successful, then update RLOC to new one.
cur->thread_info->localServerDataBase.registered_rloc16 = mac_helper_mac16_address_get(cur); cur->thread_info->localServerDataBase.registered_rloc16 = mac_helper_mac16_address_get(cur);
cur->thread_info->localServerDataBase.release_old_address = false; cur->thread_info->localServerDataBase.release_old_address = false;
} }
}
#endif #endif
int thread_border_router_publish(int8_t interface_id) int thread_border_router_publish(int8_t interface_id)
@ -884,21 +895,20 @@ int thread_border_router_publish(int8_t interface_id)
rloc16 = mac_helper_mac16_address_get(cur); rloc16 = mac_helper_mac16_address_get(cur);
tr_debug("Border router old: %x, new: %x", cur->thread_info->localServerDataBase.registered_rloc16, rloc16); tr_debug("Border router old: %x, new: %x", cur->thread_info->localServerDataBase.registered_rloc16, rloc16);
if (cur->thread_info->localServerDataBase.publish_active) { if (cur->thread_info->localServerDataBase.publish_coap_req_id) {
if (rloc16 != cur->thread_info->localServerDataBase.registered_rloc16) { if (rloc16 != cur->thread_info->localServerDataBase.registered_rloc16) {
/* /*
* Device short address has changed, cancel previous a/sd and a/as requests * Device short address has changed, cancel previous a/sd requests
* and start resubmit timer * and start resubmit timer
* */ * */
tr_debug("address changed, kill pending reuqests"); tr_debug("RLOC changed, kill pending a/sd request");
thread_management_client_pending_coap_request_kill(cur->id); thread_management_client_coap_message_delete(cur->id, cur->thread_info->localServerDataBase.publish_coap_req_id);
thread_border_router_resubmit_timer_set(interface_id, 5); thread_border_router_resubmit_timer_set(interface_id, 5);
return 0;
} else { } else {
cur->thread_info->localServerDataBase.publish_pending = true; cur->thread_info->localServerDataBase.publish_pending = true;
tr_debug("Activate pending status for publish"); tr_debug("Activate pending status for publish");
return 0;
} }
return 0;
} }
//Allocate Memory for Data //Allocate Memory for Data
@ -926,8 +936,10 @@ int thread_border_router_publish(int8_t interface_id)
if (payload_ptr) { if (payload_ptr) {
ns_dyn_mem_free(payload_ptr); ns_dyn_mem_free(payload_ptr);
} }
if (ret_val == 0) { if (ret_val > 0) {
cur->thread_info->localServerDataBase.publish_active = true; // a/sd request successful, save coap request id
cur->thread_info->localServerDataBase.publish_coap_req_id = (uint16_t)ret_val;
ret_val = 0 ;
} }
thread_border_router_resubmit_timer_set(interface_id, -1); thread_border_router_resubmit_timer_set(interface_id, -1);

View File

@ -85,6 +85,14 @@ void thread_border_router_network_data_appl_callback(protocol_interface_info_ent
* *
*/ */
void thread_border_router_network_data_update_notify(protocol_interface_info_entry_t *cur); void thread_border_router_network_data_update_notify(protocol_interface_info_entry_t *cur);
/**
* \brief Clear data related to old partition.
*
* \param interface_id Network interface ID.
*/
void thread_border_router_old_partition_data_clean(int8_t interface_id);
#else #else
#define thread_border_router_init(interface_id) #define thread_border_router_init(interface_id)
#define thread_border_router_delete(interface_id) #define thread_border_router_delete(interface_id)
@ -92,6 +100,7 @@ void thread_border_router_network_data_update_notify(protocol_interface_info_ent
#define thread_border_router_resubmit_timer_set(interface_id, seconds) #define thread_border_router_resubmit_timer_set(interface_id, seconds)
#define thread_border_router_network_data_appl_callback(cur) #define thread_border_router_network_data_appl_callback(cur)
#define thread_border_router_network_data_update_notify(cur) #define thread_border_router_network_data_update_notify(cur)
#define thread_border_router_old_partition_data_clean(interface_id)
#endif #endif
#endif /* THREAD_BORDER_ROUTER_API_INTERNAL_H_ */ #endif /* THREAD_BORDER_ROUTER_API_INTERNAL_H_ */

View File

@ -35,6 +35,7 @@
#include "ns_list.h" #include "ns_list.h"
#include "ns_trace.h" #include "ns_trace.h"
#include "nsdynmemLIB.h" #include "nsdynmemLIB.h"
#include "randLIB.h"
#include "common_functions.h" #include "common_functions.h"
#include "ns_sha256.h" #include "ns_sha256.h"
@ -74,6 +75,8 @@ typedef NS_LIST_HEAD(device_t, link) device_list_t;
typedef struct commissioner_entry { typedef struct commissioner_entry {
device_list_t device_list; device_list_t device_list;
uint8_t destination_address[16]; uint8_t destination_address[16];
uint8_t final_dest_address[16]; // Relay message final destination
uint8_t leader_address[16]; // leader ALOC for contacting the leader
uint8_t PSKc_ptr[16]; uint8_t PSKc_ptr[16];
thread_commissioning_status_cb *status_cb_ptr; thread_commissioning_status_cb *status_cb_ptr;
uint16_t destination_port; uint16_t destination_port;
@ -82,7 +85,8 @@ typedef struct commissioner_entry {
int8_t interface_id; int8_t interface_id;
int8_t coap_service_id; int8_t coap_service_id;
int8_t coap_secure_service_id; int8_t coap_secure_service_id;
int8_t coap_virtual_service_id; int8_t coap_secure_virtual_service_id;
int8_t coap_udp_proxy_service_id;
bool registered: 1; bool registered: 1;
bool native_commissioner: 1; bool native_commissioner: 1;
@ -167,7 +171,7 @@ static commissioner_t *commissioner_find_by_service(int8_t service_id)
{ {
commissioner_t *this = NULL; commissioner_t *this = NULL;
ns_list_foreach(commissioner_t, cur_ptr, &instance_list) { ns_list_foreach(commissioner_t, cur_ptr, &instance_list) {
if (cur_ptr->coap_service_id == service_id || cur_ptr->coap_virtual_service_id == service_id || cur_ptr->coap_secure_service_id == service_id) { if (cur_ptr->coap_service_id == service_id || cur_ptr->coap_secure_virtual_service_id == service_id || cur_ptr->coap_secure_service_id == service_id || cur_ptr->coap_udp_proxy_service_id == service_id) {
this = cur_ptr; this = cur_ptr;
break; break;
} }
@ -237,12 +241,46 @@ static int commission_finalisation_resp_send(int8_t coap_service_id, device_t *d
* Callback functions * Callback functions
*/ */
static int thread_commissioning_active_get_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr)
{
commissioner_t *this = commissioner_find_by_service(service_id);
commissioning_state_e state = COMMISSIONING_STATE_REJECT;// Default is accept if we get error it is rejected
uint8_t *ptr;
uint16_t len;
(void) source_address;
(void) source_port;
/* Transaction failed */
if (!response_ptr) {
return -1;
}
tr_debug("management get response from comm module");
if (!this) {
return -2;
}
if ((len = thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_NETWORK_MESH_LOCAL_ULA, &ptr)) > 0) {
state = COMMISSIONING_STATE_ACCEPT;
tr_debug(" TLV ml prefix=%s\r\n", trace_array(ptr, len));
memcpy(this->leader_address, ptr, 8);
memcpy(this->leader_address + 8, ADDR_SHORT_ADR_SUFFIC, 6);
common_write_16_bit(0xfc00, this->leader_address + 14);
}
if (this->status_cb_ptr) {
this->status_cb_ptr(this->interface_id, this->session_id, state);
}
return 0;
}
static int commissioning_leader_petition_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) static int commissioning_leader_petition_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr)
{ {
commissioner_t *this = commissioner_find_by_service(service_id); commissioner_t *this = commissioner_find_by_service(service_id);
commissioning_state_e state = COMMISSIONING_STATE_REJECT; commissioning_state_e state = COMMISSIONING_STATE_REJECT;
uint16_t session_id = 0; uint16_t session_id = 0;
uint8_t *ptr; uint8_t *ptr = NULL;
char *uri_ptr = THREAD_URI_ACTIVE_GET;
(void) source_address; (void) source_address;
(void) source_port; (void) source_port;
@ -267,6 +305,16 @@ static int commissioning_leader_petition_recv_cb(int8_t service_id, uint8_t sour
} }
tr_debug("petition response session_id: %d state:%d",session_id, state); tr_debug("petition response session_id: %d state:%d",session_id, state);
// if registered and native commissioner send ACTIVE_GET to BBR to get mesh parameters
// if not native set leader ALOC from stack
if (this->native_commissioner) {
coap_service_request_send(service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port,
COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, uri_ptr, COAP_CT_OCTET_STREAM, NULL, 0, thread_commissioning_active_get_cb);
return 0;
} else {
thread_management_get_leader_aloc(this->interface_id, this->leader_address);
}
user_response: user_response:
if (state == COMMISSIONING_STATE_REJECT) { if (state == COMMISSIONING_STATE_REJECT) {
thci_trace("commissionerPetitionRejected"); thci_trace("commissionerPetitionRejected");
@ -376,10 +424,54 @@ static int commission_dataset_changed_notify_recv_cb(int8_t service_id, uint8_t
(void)source_port; (void)source_port;
tr_debug("Dataset changed - notification received from: %s", trace_ipv6(source_address)); tr_debug("Dataset changed - notification received from: %s", trace_ipv6(source_address));
commissioner_t *this = commissioner_find_by_service(service_id);
if (!this) {
return -1;
}
coap_service_request_send(service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port,
COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_ACTIVE_GET, COAP_CT_OCTET_STREAM, NULL, 0, thread_commissioning_active_get_cb);
coap_service_response_send(service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_NONE, NULL, 0); coap_service_response_send(service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_NONE, NULL, 0);
return 0; return 0;
} }
static int thread_commission_udp_proxy_receive_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
{
tr_debug("Recv UDP_RX.ntf");
commissioner_t *this = commissioner_find_by_service(service_id);
uint8_t *udp_encapsulation_ptr, *udp_tmf_ptr;
uint16_t udp_encapsulation_len, udp_tmf_len;
uint8_t *ipv6_addr_ptr;
uint16_t ipv6_addr_len;
uint16_t dest_port;
(void) source_port;
if (!this || !source_address || !request_ptr) {
return -1; // goto error response
}
udp_encapsulation_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_UDP_ENCAPSULATION, &udp_encapsulation_ptr);
ipv6_addr_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_IPV6_ADDRESS, &ipv6_addr_ptr);
if (udp_encapsulation_len == 0 || ipv6_addr_len < 16) {
tr_warn("Corrupted UDP_RX.ntf received (%d, %d)", udp_encapsulation_len, ipv6_addr_len);
return -1;
}
dest_port = common_read_16_bit(udp_encapsulation_ptr + 2);
udp_tmf_len = udp_encapsulation_len - 4;
udp_tmf_ptr = udp_encapsulation_ptr + 4;
tr_debug("UDP_RX tmf: %s", trace_array(udp_tmf_ptr, udp_tmf_len));
coap_service_virtual_socket_recv(this->coap_udp_proxy_service_id, ipv6_addr_ptr, dest_port, udp_tmf_ptr, udp_tmf_len);
return -1; // no response sent
}
static uint8_t *bloom_filter_calculate(uint8_t *bloom_filter_ptr,device_list_t device_list, int *steering_tlv_max_length) static uint8_t *bloom_filter_calculate(uint8_t *bloom_filter_ptr,device_list_t device_list, int *steering_tlv_max_length)
{ {
@ -403,6 +495,35 @@ static uint8_t *bloom_filter_calculate(uint8_t *bloom_filter_ptr,device_list_t d
return bloom_filter_ptr; return bloom_filter_ptr;
} }
static int thread_commissioner_set_steering_data(commissioner_t *this, uint16_t session_id, uint8_t *steering_data_ptr, uint8_t steering_data_len)
{
uint8_t payload[24];/* 4 + 16 + 4*/
uint8_t *ptr;
int8_t coap_service_id;
if (!this || steering_data_len > 16) {
return -1;
}
ptr = payload;
ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_STEERING_DATA, steering_data_len, steering_data_ptr);
ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_COMMISSIONER_SESSION_ID, session_id);
tr_debug("thread commissioner set steering data %s", trace_array(steering_data_ptr, steering_data_len));
memcpy(this->final_dest_address, this->leader_address,16);
//default uri for thread version 1.1
char *uri = THREAD_URI_COMMISSIONER_SET;
if (this->native_commissioner) {
coap_service_id = this->coap_udp_proxy_service_id;
} else {
coap_service_id = this->coap_service_id;
}
coap_service_request_send(coap_service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port,
COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, uri, COAP_CT_OCTET_STREAM, payload, ptr - payload, NULL);
return 0;
}
static int commission_steering_data_update(commissioner_t *this) static int commission_steering_data_update(commissioner_t *this)
{ {
@ -414,7 +535,7 @@ static int commission_steering_data_update(commissioner_t *this)
//bloom filter calculation function call //bloom filter calculation function call
bloom_filter_calculate(bloom_filter_ptr, this->device_list, &steering_tlv_length); bloom_filter_calculate(bloom_filter_ptr, this->device_list, &steering_tlv_length);
tr_debug("Steering bloom set :%s", trace_array(bloom_filter_ptr, 16)); tr_debug("Steering bloom set :%s", trace_array(bloom_filter_ptr, 16));
ret = thread_management_set_steering_data(this->management_instance, this->session_id,bloom_filter_ptr, steering_tlv_length, NULL); ret = thread_commissioner_set_steering_data(this, this->session_id,bloom_filter_ptr, steering_tlv_length);
if (ret) { if (ret) {
tr_warn("Steering data set failed %d", ret); tr_warn("Steering data set failed %d", ret);
return -1; return -1;
@ -475,7 +596,7 @@ static int commission_relay_rx_recv_cb(int8_t service_id, uint8_t source_address
tr_warn("catching device for iid:%s", trace_array(&joiner_address[8], 8)); tr_warn("catching device for iid:%s", trace_array(&joiner_address[8], 8));
} }
device_ptr->joiner_router_rloc = joiner_router_rloc; device_ptr->joiner_router_rloc = joiner_router_rloc;
coap_service_virtual_socket_recv(this->coap_virtual_service_id, joiner_address, joiner_port, udp_ptr, udp_len); coap_service_virtual_socket_recv(this->coap_secure_virtual_service_id, joiner_address, joiner_port, udp_ptr, udp_len);
return -1; // no response sent return -1; // no response sent
} }
@ -616,20 +737,55 @@ static int commissioner_br_security_done_cb(int8_t service_id, uint8_t address[1
return 0; return 0;
} }
static int thread_commissioning_remote_addr_set(commissioner_t *this) static int thread_commission_udp_proxy_virtual_socket_send_cb(int8_t service_id, uint8_t destination_addr_ptr[static 16], uint16_t port, const uint8_t *data_ptr, uint16_t data_len)
{ {
if (0 == thread_management_get_leader_address(this->interface_id, this->destination_address)) { (void) port;
tr_debug("on-mesh commissioner"); uint8_t *payload_ptr;
this->destination_port = THREAD_MANAGEMENT_PORT; uint8_t *ptr;
this->native_commissioner = false; uint16_t payload_len;
} else if (0 == thread_commissioning_native_commissioner_get_connection_info(this->interface_id, uint16_t source_port;
this->destination_address, &this->destination_port)) {
tr_debug("native commissioner"); commissioner_t *this = commissioner_find_by_service(service_id);
this->native_commissioner = true; if (!this) {
} else {
tr_error("No remote address");
return -1; return -1;
} }
tr_debug("UDP_TX.ntf tmf: %s", trace_array(data_ptr, data_len));
if (!this || !destination_addr_ptr || !data_ptr) {
return -1;
}
payload_len = 2 + THREAD_IPV6_ADDRESS_TLV_LENGTH + 4 + 4 + data_len; // MESHCOP_TLV_IPV6_ADDRESS + MESHCOP_TLV_UDP_ENCAPSULATION
payload_ptr = ns_dyn_mem_alloc(payload_len);
if (!payload_ptr) {
return -3;
}
ptr = payload_ptr;
tr_debug("br_address %s final dest_address %s and port %d", trace_ipv6(this->destination_address),
trace_ipv6(this->final_dest_address), this->destination_port);
/* MESHCOP_TLV_IPV6_ADDRESS */
ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_IPV6_ADDRESS, THREAD_IPV6_ADDRESS_TLV_LENGTH, this->final_dest_address);
/* MESHCOP_TLV_UDP_ENCAPSULATION */
*ptr++ = MESHCOP_TLV_UDP_ENCAPSULATION;
*ptr++ = 0xff;
ptr = common_write_16_bit(2 + 2 + data_len, ptr); // length (Port x 2 + TMF message)
source_port = randLIB_get_16bit(); // ephemeral port, 16-bit number
ptr = common_write_16_bit(source_port, ptr); // source port,
ptr = common_write_16_bit(THREAD_MANAGEMENT_PORT, ptr); // destination port
memcpy(ptr, data_ptr, data_len);
ptr += data_len;
/* Send UDP_TX.ntf */
coap_service_request_send(this->coap_secure_service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port,
COAP_MSG_TYPE_NON_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_UDP_TRANSMIT_NOTIFICATION, COAP_CT_OCTET_STREAM, payload_ptr, ptr - payload_ptr, NULL);
ns_dyn_mem_free(payload_ptr);
return 0; return 0;
} }
@ -638,16 +794,17 @@ Public api functions
*/ */
int thread_commissioning_register(int8_t interface_id, uint8_t PSKc[static 16]) int thread_commissioning_register(int8_t interface_id, uint8_t PSKc[static 16])
{ {
if (commissioner_find(interface_id)) { commissioner_t *this = commissioner_find(interface_id);
return -1; if (!this) {
this = commissioner_create(interface_id);
} }
commissioner_t *this = commissioner_create(interface_id);
if (!this) { if (!this) {
return -2; return -2;
} }
memcpy(this->PSKc_ptr,PSKc,16); memcpy(this->PSKc_ptr,PSKc,16);
if (this->registered) {
this->management_instance = thread_management_register(interface_id); return 0;
}
this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL);
coap_service_register_uri(this->coap_service_id, THREAD_URI_RELAY_RECEIVE, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_relay_rx_recv_cb); coap_service_register_uri(this->coap_service_id, THREAD_URI_RELAY_RECEIVE, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_relay_rx_recv_cb);
coap_service_register_uri(this->coap_service_id, THREAD_URI_JOINER_APPLICATION_REQUEST, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_application_provision_req_recv_cb); coap_service_register_uri(this->coap_service_id, THREAD_URI_JOINER_APPLICATION_REQUEST, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_application_provision_req_recv_cb);
@ -655,10 +812,15 @@ int thread_commissioning_register(int8_t interface_id, uint8_t PSKc[static 16])
this->coap_secure_service_id = coap_service_initialize(this->interface_id, THREAD_COMMISSIONING_PORT, COAP_SERVICE_OPTIONS_SECURE | COAP_SERVICE_OPTIONS_SECURE_BYPASS, commissioner_br_security_start_cb, commissioner_br_security_done_cb); this->coap_secure_service_id = coap_service_initialize(this->interface_id, THREAD_COMMISSIONING_PORT, COAP_SERVICE_OPTIONS_SECURE | COAP_SERVICE_OPTIONS_SECURE_BYPASS, commissioner_br_security_start_cb, commissioner_br_security_done_cb);
coap_service_register_uri(this->coap_secure_service_id, THREAD_URI_RELAY_RECEIVE, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_relay_rx_recv_cb); coap_service_register_uri(this->coap_secure_service_id, THREAD_URI_RELAY_RECEIVE, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_relay_rx_recv_cb);
coap_service_register_uri(this->coap_secure_service_id, THREAD_URI_UDP_RECVEIVE_NOTIFICATION, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_commission_udp_proxy_receive_cb);
this->coap_secure_virtual_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_SECURE | COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET, joiner_commissioner_security_start_cb, commissioning_security_done_cb);
coap_service_register_uri(this->coap_secure_virtual_service_id, THREAD_URI_JOINER_FINALIZATION, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_finalisation_req_recv_cb);
coap_service_virtual_socket_set_cb(this->coap_secure_virtual_service_id, commission_virtual_socket_send_cb);
this->coap_udp_proxy_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET, NULL, NULL);
coap_service_virtual_socket_set_cb(this->coap_udp_proxy_service_id, thread_commission_udp_proxy_virtual_socket_send_cb);
this->coap_virtual_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_SECURE | COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET, joiner_commissioner_security_start_cb, commissioning_security_done_cb);
coap_service_register_uri(this->coap_virtual_service_id, THREAD_URI_JOINER_FINALIZATION, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_finalisation_req_recv_cb);
coap_service_virtual_socket_set_cb(this->coap_virtual_service_id, commission_virtual_socket_send_cb);
return 0; return 0;
} }
@ -672,11 +834,11 @@ int thread_commissioning_unregister(int8_t interface_id)
// Unregister the commissioner // Unregister the commissioner
thread_commissioning_petition_keep_alive(this->interface_id, COMMISSIONING_STATE_REJECT); thread_commissioning_petition_keep_alive(this->interface_id, COMMISSIONING_STATE_REJECT);
} }
thread_management_unregister(this->management_instance);
coap_service_delete(this->coap_service_id); coap_service_delete(this->coap_service_id);
coap_service_delete(this->coap_secure_service_id); coap_service_delete(this->coap_secure_service_id);
coap_service_delete(this->coap_virtual_service_id); coap_service_delete(this->coap_secure_virtual_service_id);
coap_service_delete(this->coap_udp_proxy_service_id);
commissioner_delete(this); commissioner_delete(this);
return 0; return 0;
@ -690,7 +852,6 @@ int thread_commissioning_petition_start(int8_t interface_id, char *commissioner_
uint8_t service_id; uint8_t service_id;
uint8_t *ptr; uint8_t *ptr;
char *uri_ptr; char *uri_ptr;
this = commissioner_find(interface_id); this = commissioner_find(interface_id);
if (!this) { if (!this) {
@ -705,16 +866,14 @@ int thread_commissioning_petition_start(int8_t interface_id, char *commissioner_
return -3; return -3;
} }
if (thread_commissioning_remote_addr_set(this)) {
return -4;
}
if (this->native_commissioner) { if (this->native_commissioner) {
uri_ptr = THREAD_URI_COMMISSIONER_PETITION; uri_ptr = THREAD_URI_COMMISSIONER_PETITION;
service_id = this->coap_secure_service_id; service_id = this->coap_secure_service_id;
} else { } else {
uri_ptr = THREAD_URI_LEADER_PETITION; uri_ptr = THREAD_URI_LEADER_PETITION;
service_id = this->coap_service_id; service_id = this->coap_service_id;
thread_management_get_leader_aloc(this->interface_id, this->destination_address);
this->destination_port = THREAD_MANAGEMENT_PORT;
} }
this->status_cb_ptr = status_cb_ptr; this->status_cb_ptr = status_cb_ptr;
@ -747,16 +906,13 @@ int thread_commissioning_petition_keep_alive(int8_t interface_id, commissioning_
return -1; return -1;
} }
if (thread_commissioning_remote_addr_set(this)) {
return -4;
}
if (this->native_commissioner) { if (this->native_commissioner) {
uri_ptr = THREAD_URI_COMMISSIONER_KEEP_ALIVE; uri_ptr = THREAD_URI_COMMISSIONER_KEEP_ALIVE;
service_id = this->coap_secure_service_id; service_id = this->coap_secure_service_id;
} else { } else {
uri_ptr = THREAD_URI_LEADER_KEEP_ALIVE; uri_ptr = THREAD_URI_LEADER_KEEP_ALIVE;
service_id = this->coap_service_id; service_id = this->coap_service_id;
thread_management_get_leader_aloc(this->interface_id, this->destination_address);
} }
ptr = payload; ptr = payload;
@ -867,6 +1023,20 @@ void *thread_commission_device_get_next(void *ptr, int8_t interface_id, bool *sh
return cur_ptr; return cur_ptr;
} }
int thread_commissioning_attach(int8_t interface_id, uint8_t *destination_address, uint16_t destination_port)
{
tr_debug("start ethernet commissioner attach");
commissioner_t *this = commissioner_find(interface_id);
if (!this) {
return -1;
}
memcpy(this->destination_address, destination_address,16);
this->destination_port = destination_port;
this->native_commissioner = true;
return 0;
}
int thread_commissioning_native_commissioner_start(int8_t interface_id, thread_commissioning_native_select_cb *cb_ptr) int thread_commissioning_native_commissioner_start(int8_t interface_id, thread_commissioning_native_select_cb *cb_ptr)
{ {
protocol_interface_info_entry_t *cur; protocol_interface_info_entry_t *cur;
@ -909,6 +1079,18 @@ int thread_commissioning_native_commissioner_connect(int8_t interface_id, thread
return -2; return -2;
} }
*cur->thread_info->native_commissioner_link = *link_ptr; *cur->thread_info->native_commissioner_link = *link_ptr;
commissioner_t *this = commissioner_find(interface_id);
if (!this) {
this = commissioner_create(interface_id);
}
if (!this) {
return -3;
}
this->native_commissioner = true;
memcpy(this->destination_address, link_ptr->destination_address,16);
this->destination_port = link_ptr->destination_port;
//TODO check that we are scanning for networks and reset backup timers //TODO check that we are scanning for networks and reset backup timers
return 0; return 0;
@ -916,22 +1098,15 @@ int thread_commissioning_native_commissioner_connect(int8_t interface_id, thread
int thread_commissioning_native_commissioner_get_connection_info(int8_t interface_id, uint8_t *address_ptr, uint16_t *port) int thread_commissioning_native_commissioner_get_connection_info(int8_t interface_id, uint8_t *address_ptr, uint16_t *port)
{ {
protocol_interface_info_entry_t *cur; commissioner_t *this = commissioner_find(interface_id);
cur = protocol_stack_interface_info_get_by_id(interface_id);
tr_debug("get native connection info"); tr_debug("get native connection info");
if(!cur || !cur->thread_info) { if (!this) {
return -1; return -1;
} }
if (thread_attach_ready(cur) != 0) { memcpy(address_ptr,this->destination_address,16);
return -2;
} *port = this->destination_port;
if (protocol_6lowpan_interface_get_link_local_cordinator_address(cur, address_ptr) != 0) {
return -1;
}
if (port) {
*port = cur->thread_info->native_commissioner_port;
}
return 0; return 0;
} }
@ -1031,4 +1206,11 @@ int thread_commissioning_native_commissioner_connect(int8_t interface_id, thread
return -1; return -1;
} }
int thread_commissioning_attach(int8_t interface_id, uint8_t *destination_address, uint16_t destination_port) {
(void)interface_id;
(void)destination_address;
(void)destination_port;
return -1;
}
#endif #endif

View File

@ -44,9 +44,11 @@
#include "6LoWPAN/Bootstraps/protocol_6lowpan_interface.h" #include "6LoWPAN/Bootstraps/protocol_6lowpan_interface.h"
#include "6LoWPAN/Thread/thread_common.h" #include "6LoWPAN/Thread/thread_common.h"
#include "6LoWPAN/Thread/thread_beacon.h" #include "6LoWPAN/Thread/thread_beacon.h"
#include "6LoWPAN/Thread/thread_diagnostic.h"
#include "6LoWPAN/Thread/thread_extension_bbr.h"
#include "6LoWPAN/Thread/thread_leader_service.h" #include "6LoWPAN/Thread/thread_leader_service.h"
#include "6LoWPAN/Thread/thread_routing.h" #include "6LoWPAN/Thread/thread_routing.h"
#include "6LoWPAN/Thread/thread_dhcpv6_client.h" #include "DHCPv6_client/dhcpv6_client_api.h"
#include "6LoWPAN/Thread/thread_discovery.h" #include "6LoWPAN/Thread/thread_discovery.h"
#include "6LoWPAN/Thread/thread_bootstrap.h" #include "6LoWPAN/Thread/thread_bootstrap.h"
#include "6LoWPAN/Thread/thread_router_bootstrap.h" #include "6LoWPAN/Thread/thread_router_bootstrap.h"
@ -60,6 +62,7 @@
#include "6LoWPAN/Thread/thread_management_internal.h" #include "6LoWPAN/Thread/thread_management_internal.h"
#include "6LoWPAN/Thread/thread_management_client.h" #include "6LoWPAN/Thread/thread_management_client.h"
#include "6LoWPAN/Thread/thread_management_server.h" #include "6LoWPAN/Thread/thread_management_server.h"
#include "6LoWPAN/Thread/thread_resolution_server.h"
#include "6LoWPAN/Thread/thread_resolution_client.h" #include "6LoWPAN/Thread/thread_resolution_client.h"
#include "6LoWPAN/Thread/thread_address_registration_client.h" #include "6LoWPAN/Thread/thread_address_registration_client.h"
#include "6LoWPAN/Thread/thread_resolution_client.h" #include "6LoWPAN/Thread/thread_resolution_client.h"
@ -226,6 +229,7 @@ int8_t thread_bootstrap_up(protocol_interface_info_entry_t *cur)
ret_val = nwk_6lowpan_up(cur); ret_val = nwk_6lowpan_up(cur);
cur->nwk_nd_re_scan_count = 0; cur->nwk_nd_re_scan_count = 0;
cur->thread_info->link_sync_allowed = true;
return ret_val; return ret_val;
} }
@ -258,9 +262,11 @@ int8_t thread_bootstrap_down(protocol_interface_info_entry_t *cur)
thread_leader_mleid_rloc_map_to_nvm_write(cur); thread_leader_mleid_rloc_map_to_nvm_write(cur);
thread_bootstrap_stop(cur); thread_bootstrap_stop(cur);
mle_service_interface_unregister(cur->id); mle_service_interface_unregister(cur->id);
thread_diagnostic_delete(cur->id); // delete before thread_management_server_delete as they share same coap_service id
thread_management_client_delete(cur->id); // delete before thread_management_server_delete as they share same coap_service id
thread_nd_service_disable(cur->id); // delete before thread_management_server_delete as they share same coap_service id
thread_management_server_delete(cur->id); thread_management_server_delete(cur->id);
thread_joiner_application_deinit(cur->id); thread_joiner_application_deinit(cur->id);
thread_management_client_delete(cur->id);
//free network Data //free network Data
thread_network_data_free_and_clean(&cur->thread_info->networkDataStorage); thread_network_data_free_and_clean(&cur->thread_info->networkDataStorage);
//free local also here //free local also here
@ -451,7 +457,7 @@ void thread_data_base_init(thread_info_t *thread_info, int8_t interfaceId)
thread_leader_commissioner_create(thread_info); thread_leader_commissioner_create(thread_info);
thread_info->rfc6775 = false; thread_info->rfc6775 = false;
thread_info->threadPrivatePrefixInfo.ulaValid = false; thread_info->threadPrivatePrefixInfo.ulaValid = false;
thread_info->routerIdReqCoapID = 0; thread_info->routerIdRequested = false;
thread_info->networkDataRequested = false; thread_info->networkDataRequested = false;
thread_info->proactive_an_timer = 0; thread_info->proactive_an_timer = 0;
@ -905,6 +911,7 @@ static void thread_child_update_req_timer(protocol_interface_info_entry_t *cur,
if (cur->thread_info->childUpdateReqTimer == -1) { if (cur->thread_info->childUpdateReqTimer == -1) {
return; return;
} }
if (cur->thread_info->childUpdateReqTimer > seconds) { if (cur->thread_info->childUpdateReqTimer > seconds) {
cur->thread_info->childUpdateReqTimer -= seconds; cur->thread_info->childUpdateReqTimer -= seconds;
} else { } else {
@ -945,6 +952,20 @@ static void thread_key_switch_timer(protocol_interface_info_entry_t *cur, uint16
} }
} }
static void thread_maintenance_timer(protocol_interface_info_entry_t *cur, uint32_t seconds)
{
if (thread_info(cur)->thread_maintenance_timer) {
if (thread_info(cur)->thread_maintenance_timer > seconds) {
thread_info(cur)->thread_maintenance_timer -= seconds;
return;
}
}
thread_info(cur)->thread_maintenance_timer = THREAD_MAINTENANCE_TIMER_INTERVAL ;
thread_bootstrap_network_data_activate(cur);
}
void thread_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t ticks) void thread_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t ticks)
{ {
uint8_t leader_address[16]; uint8_t leader_address[16];
@ -1003,6 +1024,7 @@ void thread_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t ticks)
} }
thread_router_bootstrap_timer(cur, ticks); thread_router_bootstrap_timer(cur, ticks);
thread_maintenance_timer(cur, ticks);
thread_border_router_seconds_timer(cur->id, ticks); thread_border_router_seconds_timer(cur->id, ticks);
thread_bbr_seconds_timer(cur->id, ticks); thread_bbr_seconds_timer(cur->id, ticks);
thread_lowpower_timer(cur, ticks); thread_lowpower_timer(cur, ticks);
@ -1720,9 +1742,105 @@ uint8_t *thread_leader_data_tlv_write(uint8_t *ptr, protocol_interface_info_entr
return ptr; return ptr;
} }
bool thread_addresses_needs_to_be_registered(protocol_interface_info_entry_t *cur)
{
lowpan_context_t *ctx;
uint8_t thread_realm_local_mcast_addr[16];
uint8_t thread_ll_unicast_prefix_based_mcast_addr[16];
if (thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_SLEEPY_END_DEVICE &&
thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_END_DEVICE) {
// No address registration for others than MED or SED
return false;
}
// check for addresses
ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) {
if (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_GLOBAL || (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_REALM_LOCAL
&& !thread_addr_is_mesh_local_16(e->address, cur))) {
ctx = lowpan_context_get_by_address(&cur->lowpan_contexts, e->address);
if (!ctx) {
return true;
}
if (ctx->cid != 0) {
return true;
}
}
}
// check for multicast groups
thread_bootstrap_all_nodes_address_generate(thread_realm_local_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_REALM_LOCAL);
thread_bootstrap_all_nodes_address_generate(thread_ll_unicast_prefix_based_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_LINK_LOCAL);
ns_list_foreach(if_group_entry_t, entry, &cur->ip_groups)
{
if (!memcmp((entry->group), ADDR_MULTICAST_SOLICITED, 13)) {
/* Skip solicited node multicast address */
continue;
}
if (addr_ipv6_equal(entry->group, thread_realm_local_mcast_addr)) {
/* Skip well-known realm-local all Thread nodes multicast address */
continue;
}
if (addr_ipv6_equal(entry->group, thread_ll_unicast_prefix_based_mcast_addr)) {
/* Skip well-known link-local all Thread nodes multicast address */
continue;
}
if (addr_ipv6_equal(entry->group, ADDR_ALL_MPL_FORWARDERS)) {
/* Skip All MPL Forwarders address */
continue;
}
if (addr_ipv6_equal(entry->group, ADDR_REALM_LOCAL_ALL_NODES)) {
/* Skip Mesh local all nodes */
continue;
}
if (addr_ipv6_equal(entry->group, ADDR_REALM_LOCAL_ALL_ROUTERS)) {
/* Skip Mesh local all routers */
continue;
}
return true;
}
return false;
}
uint8_t *thread_ml_address_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur)
{
lowpan_context_t *ctx;
uint8_t *address_len_ptr;
if (thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_SLEEPY_END_DEVICE &&
thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_END_DEVICE) {
// No address registration for others than MED or SED
return ptr;
}
*ptr++ = MLE_TYPE_ADDRESS_REGISTRATION;
address_len_ptr = ptr++;
*address_len_ptr = 0;
ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) {
if (*address_len_ptr > 148 ) {
// Maximum length of address registrations
continue;
}
if (!thread_addr_is_mesh_local_16(e->address, cur)) {
ctx = lowpan_context_get_by_address(&cur->lowpan_contexts, e->address);
if (ctx && ctx->cid == 0) {
//Write TLV to list
*ptr++ = (ctx->cid | 0x80);
memcpy(ptr, e->address + 8, 8);
ptr += 8;
*address_len_ptr += 9;
}
}
}
return ptr;
}
uint8_t *thread_address_registration_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur) uint8_t *thread_address_registration_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur)
{ {
uint8_t thread_realm_local_mcast_addr[16]; uint8_t thread_realm_local_mcast_addr[16];
uint8_t thread_ll_unicast_prefix_based_mcast_addr[16];
lowpan_context_t *ctx; lowpan_context_t *ctx;
uint8_t *address_len_ptr; uint8_t *address_len_ptr;
@ -1738,7 +1856,6 @@ uint8_t *thread_address_registration_tlv_write(uint8_t *ptr, protocol_interface_
// Register all global addressess // Register all global addressess
ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) { ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) {
if (*address_len_ptr > 148 ) { if (*address_len_ptr > 148 ) {
// Maximum length of address registrations // Maximum length of address registrations
continue; continue;
@ -1762,23 +1879,27 @@ uint8_t *thread_address_registration_tlv_write(uint8_t *ptr, protocol_interface_
} }
/* Registers multicast addresses to the parent */ /* Registers multicast addresses to the parent */
thread_bootstrap_all_nodes_address_generate(thread_realm_local_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 3); thread_bootstrap_all_nodes_address_generate(thread_realm_local_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_REALM_LOCAL);
thread_bootstrap_all_nodes_address_generate(thread_ll_unicast_prefix_based_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_LINK_LOCAL);
ns_list_foreach(if_group_entry_t, entry, &cur->ip_groups) ns_list_foreach(if_group_entry_t, entry, &cur->ip_groups)
{ {
if (*address_len_ptr > 148) { if (*address_len_ptr > 148) {
// Maximum length of address registrations // Maximum length of address registrations
continue; continue;
} }
if (addr_ipv6_multicast_scope(entry->group) < IPV6_SCOPE_REALM_LOCAL) {
/* Skip Link Local multicast address */ if (!memcmp((entry->group), ADDR_MULTICAST_SOLICITED, 13)) {
/* Skip solicited node multicast address */
continue; continue;
} }
if (addr_ipv6_equal(entry->group, thread_realm_local_mcast_addr)) { if (addr_ipv6_equal(entry->group, thread_realm_local_mcast_addr)) {
/* Skip well-known realm-local all Thread nodes multicast address */ /* Skip well-known realm-local all Thread nodes multicast address */
continue; continue;
} }
if (addr_ipv6_equal(entry->group, thread_ll_unicast_prefix_based_mcast_addr)) {
/* Skip well-known link-local all Thread nodes multicast address */
continue;
}
if (addr_ipv6_equal(entry->group, ADDR_ALL_MPL_FORWARDERS)) { if (addr_ipv6_equal(entry->group, ADDR_ALL_MPL_FORWARDERS)) {
/* Skip All MPL Forwarders address */ /* Skip All MPL Forwarders address */
continue; continue;
@ -1935,9 +2056,34 @@ static void thread_address_notification_cb(struct protocol_interface_info_entry
} }
} }
static bool thread_mcast_should_register_address(struct protocol_interface_info_entry *cur, uint8_t *addr)
{
uint8_t thread_realm_local_mcast_addr[16];
uint8_t thread_ll_unicast_prefix_based_mcast_addr[16];
thread_bootstrap_all_nodes_address_generate(thread_realm_local_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_REALM_LOCAL);
thread_bootstrap_all_nodes_address_generate(thread_ll_unicast_prefix_based_mcast_addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_LINK_LOCAL);
if (addr_ipv6_multicast_scope(addr) >= IPV6_SCOPE_LINK_LOCAL) {
if (memcmp(addr, ADDR_MULTICAST_SOLICITED, 13) == 0) {
return false;
}
if (memcmp(addr, thread_realm_local_mcast_addr, 16) == 0) {
return false;
}
if (memcmp(addr, thread_ll_unicast_prefix_based_mcast_addr, 16) == 0) {
return false;
}
if (memcmp(addr, ADDR_LINK_LOCAL_ALL_NODES, 16) == 0) {
return false;
}
if (memcmp(addr, ADDR_LINK_LOCAL_ALL_ROUTERS, 16) == 0) {
return false;
}
}
return true;
}
void thread_mcast_group_change(struct protocol_interface_info_entry *interface, if_group_entry_t *group, bool addr_added) void thread_mcast_group_change(struct protocol_interface_info_entry *interface, if_group_entry_t *group, bool addr_added)
{ {
if (thread_attach_ready(interface) != 0) { if (thread_attach_ready(interface) != 0) {
return; return;
} }
@ -1946,7 +2092,7 @@ void thread_mcast_group_change(struct protocol_interface_info_entry *interface,
if (thread_bootstrap_should_register_address(interface)) { if (thread_bootstrap_should_register_address(interface)) {
/* Trigger Child Update Request only if MTD child's multicast address change */ /* Trigger Child Update Request only if MTD child's multicast address change */
if (addr_ipv6_multicast_scope(group->group) > IPV6_SCOPE_LINK_LOCAL) { if (thread_mcast_should_register_address(interface, group->group)) {
interface->thread_info->childUpdateReqTimer = 1; interface->thread_info->childUpdateReqTimer = 1;
} }
} else { } else {
@ -1956,10 +2102,16 @@ void thread_mcast_group_change(struct protocol_interface_info_entry *interface,
} }
} }
static void thread_old_partition_data_clean(int8_t interface_id)
{
thread_management_client_old_partition_data_clean(interface_id);
thread_border_router_old_partition_data_clean(interface_id);
}
void thread_partition_data_purge(protocol_interface_info_entry_t *cur) void thread_partition_data_purge(protocol_interface_info_entry_t *cur)
{ {
/* Partition has been changed. Wipe out data related to old partition */ /* Partition has been changed. Wipe out data related to old partition */
thread_management_client_pending_coap_request_kill(cur->id); thread_old_partition_data_clean(cur->id);
/* Reset previous routing information */ /* Reset previous routing information */
thread_routing_reset(&cur->thread_info->routing); thread_routing_reset(&cur->thread_info->routing);
@ -1967,6 +2119,9 @@ void thread_partition_data_purge(protocol_interface_info_entry_t *cur)
/* Flush address cache */ /* Flush address cache */
ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache); ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache);
/* Remove linked neighbours for REEDs and FEDs */
thread_reed_fed_neighbour_links_clean(cur);
} }
bool thread_partition_match(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData) bool thread_partition_match(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData)
@ -1997,5 +2152,10 @@ void thread_neighbor_communication_update(protocol_interface_info_entry_t *cur,
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, neighbor_attribute_index); thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, neighbor_attribute_index);
} }
void thread_maintenance_timer_set(protocol_interface_info_entry_t *cur, uint16_t delay)
{
thread_info(cur)->thread_maintenance_timer = delay;
}
#endif #endif

View File

@ -309,10 +309,10 @@ typedef struct thread_info_s {
uint16_t routerShortAddress; uint16_t routerShortAddress;
uint16_t reedJitterTimer; uint16_t reedJitterTimer;
uint16_t reedMergeAdvTimer; uint16_t reedMergeAdvTimer;
uint16_t routerIdReqCoapID; // COAP msg id of RouterID request
int16_t childUpdateReqTimer; int16_t childUpdateReqTimer;
uint16_t childUpdateReqMsgId; uint16_t childUpdateReqMsgId;
uint16_t proactive_an_timer; uint16_t proactive_an_timer;
uint16_t thread_maintenance_timer;
//uint8_t lastValidRouteMask[8]; //uint8_t lastValidRouteMask[8];
int8_t interface_id; //Thread Interface ID int8_t interface_id; //Thread Interface ID
uint8_t version; uint8_t version;
@ -322,11 +322,13 @@ typedef struct thread_info_s {
bool rfc6775: 1; bool rfc6775: 1;
bool requestFullNetworkData: 1; bool requestFullNetworkData: 1;
bool leaderCab: 1; bool leaderCab: 1;
bool routerIdRequested: 1;
bool releaseRouterId: 1; bool releaseRouterId: 1;
bool networkSynch: 1; bool networkSynch: 1;
bool networkDataRequested: 1; bool networkDataRequested: 1;
bool end_device_link_synch: 1; bool end_device_link_synch: 1;
bool router_mc_addrs_registered: 1; bool router_mc_addrs_registered: 1;
bool link_sync_allowed:1;
bool leader_synced:1; // flag used by leader after restart bool leader_synced:1; // flag used by leader after restart
} thread_info_t; } thread_info_t;
@ -397,6 +399,11 @@ void thread_child_mcast_entries_remove(protocol_interface_info_entry_t *cur, con
uint8_t thread_leader_data_tlv_size(protocol_interface_info_entry_t *cur); uint8_t thread_leader_data_tlv_size(protocol_interface_info_entry_t *cur);
uint8_t *thread_leader_data_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur); uint8_t *thread_leader_data_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur);
uint8_t *thread_address_registration_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur); uint8_t *thread_address_registration_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur);
// returns true if SED/MED needs to register additional address to parent
bool thread_addresses_needs_to_be_registered(protocol_interface_info_entry_t *cur);
// write mesh local address tlv
uint8_t *thread_ml_address_tlv_write(uint8_t *ptr, protocol_interface_info_entry_t *cur);
int thread_link_reject_send(protocol_interface_info_entry_t *interface, const uint8_t *ll64); int thread_link_reject_send(protocol_interface_info_entry_t *interface, const uint8_t *ll64);
thread_leader_info_t *thread_allocate_and_init_leader_private_data(void); thread_leader_info_t *thread_allocate_and_init_leader_private_data(void);
thread_route_cost_t thread_link_quality_to_cost(thread_link_quality_e quality); thread_route_cost_t thread_link_quality_to_cost(thread_link_quality_e quality);
@ -441,6 +448,7 @@ bool thread_partition_match(protocol_interface_info_entry_t *cur, thread_leader_
void thread_partition_info_update(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData); void thread_partition_info_update(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData);
void thread_neighbor_communication_update(protocol_interface_info_entry_t *cur, uint8_t neighbor_attribute_index); void thread_neighbor_communication_update(protocol_interface_info_entry_t *cur, uint8_t neighbor_attribute_index);
bool thread_stable_context_check(protocol_interface_info_entry_t *cur, buffer_t *buf); bool thread_stable_context_check(protocol_interface_info_entry_t *cur, buffer_t *buf);
void thread_maintenance_timer_set(protocol_interface_info_entry_t *cur, uint16_t delay);
#else // HAVE_THREAD #else // HAVE_THREAD
NS_DUMMY_DEFINITIONS_OK NS_DUMMY_DEFINITIONS_OK

View File

@ -326,6 +326,17 @@
*/ */
#define THREAD_BBR_ROUTER_ID_REQUEST_STATUS THREAD_COAP_STATUS_TLV_HAVE_CHILD_ID_REQUEST #define THREAD_BBR_ROUTER_ID_REQUEST_STATUS THREAD_COAP_STATUS_TLV_HAVE_CHILD_ID_REQUEST
/*
* Number of destination and neighbor cache entries assuming 250 thread devices (worst case) connecting to cloud service.
* Six entries reserved for backbone devices.
*/
#define THREAD_BBR_IPV6_DESTINATION_CACHE_SIZE 256
/*
* Timeout to solicit address from DHCP if previous request fails.
*/
#define THREAD_MAINTENANCE_TIMER_INTERVAL 300
/** /**
* Build time flag to enable THCI special traces for test harness purposes * Build time flag to enable THCI special traces for test harness purposes
*/ */

View File

@ -145,6 +145,7 @@
#define THREAD_DEFAULT_KEY_SWITCH_GUARD_TIME 624 // Hours #define THREAD_DEFAULT_KEY_SWITCH_GUARD_TIME 624 // Hours
#define THREAD_DEFAULT_KEY_ROTATION 672 // Hours #define THREAD_DEFAULT_KEY_ROTATION 672 // Hours
#define THREAD_COMMISSIONER_KEEP_ALIVE_INTERVAL 50000 // Default thread commissioner keep-alive message interval (milliseconds) #define THREAD_COMMISSIONER_KEEP_ALIVE_INTERVAL 50000 // Default thread commissioner keep-alive message interval (milliseconds)
#define THREAD_DELAY_JOIN_ENT 50 // Minimum delay for Joiner router before sending joiner entrust (milliseconds)
#define THREAD_FAILED_CHILD_TRANSMISSIONS 4 #define THREAD_FAILED_CHILD_TRANSMISSIONS 4
#define THREAD_FAILED_ROUTER_TRANSMISSIONS 4 #define THREAD_FAILED_ROUTER_TRANSMISSIONS 4

View File

@ -1,98 +0,0 @@
/*
* Copyright (c) 2014-2015, 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SOURCE_6LOWPAN_THREAD_THREAD_DHCPV6_CLIENT_H_
#define SOURCE_6LOWPAN_THREAD_THREAD_DHCPV6_CLIENT_H_
#include <ns_types.h>
/* Thread DHCP client implementation.
*
* Responsibilities of this module are:
* - send router id address request and receive new router address and inform it to thread bootstrap.
* - handle Global address queries and refresh inside thread network.
*
*/
/* Initialize dhcp thread dhcp client.
*
* This instance needs to bee initialized once for each thread network interface.
* if only one thread instance is supported this is needed to call only once.
*
* /param interface interface id of this thread instance.
*
*/
void thread_dhcp_client_init(int8_t interface);
/* Delete dhcp thread dhcp client.
*
* When this is called all addressed assigned by this module are removed from stack.
*/
void thread_dhcp_client_delete(int8_t interface);
/* Global address handler.
*
* This module updates the addresses from dhcp server and sets them in stack.
* this module makes refresh of address when needed.
*
*/
/* give dhcp server and prefix for global address assignment
*
* /param interface interface where address is got
* /param dhcp_addr dhcp server ML16 address where address is registered.
* /param prefix dhcp server ML16 address where address is registered.
* /param mac64 64 bit mac address for identifieng client.
* /param error_cb error callback that is called if address cannot be created or becomes invalid.
* /param register_status true if address registered.
*
*/
typedef void (thread_dhcp_client_global_adress_cb)(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], bool register_status);
int thread_dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], uint8_t mac64[static 8], thread_dhcp_client_global_adress_cb *error_cb);
/* Renew all leased adddresses might be used when short address changes
*
* /param interface interface where address is got
*/
void thread_dhcp_client_global_address_renew(int8_t interface);
/* Delete address from device
* if prefix is NULL all are deleted
*
* /param interface interface where address is got
* /param prefix dhcp server ML16 address where address is registered.
*
*/
void thread_dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16]);
#endif /* SOURCE_6LOWPAN_THREAD_THREAD_DHCPV6_CLIENT_H_ */

View File

@ -0,0 +1,114 @@
/*
* Copyright (c) 2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "nsconfig.h"
#if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER)
#include <string.h>
#include <ns_types.h>
#include "eventOS_event.h"
#include "eventOS_event_timer.h"
#include "common_functions.h"
#include "ns_trace.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "ipv6_stack/protocol_ipv6.h"
#include "Common_Protocols/ipv6_constants.h"
#include "Common_Protocols/ipv6.h"
#include "DHCPv6_Server/DHCPv6_server_service.h"
#include "6LoWPAN/Thread/thread_bbr_api_internal.h"
#define TRACE_GROUP "thds"
static void thread_service_remove_GUA_from_neighcache(protocol_interface_info_entry_t *cur, uint8_t *targetAddress)
{
ipv6_neighbour_t *neighbour_entry;
neighbour_entry = ipv6_neighbour_lookup(&cur->ipv6_neighbour_cache, targetAddress);
if (neighbour_entry) {
tr_debug("Remove from neigh Cache: %s", tr_ipv6(targetAddress));
ipv6_neighbour_entry_remove(&cur->ipv6_neighbour_cache, neighbour_entry);
}
}
static void thread_dhcp_address_prefer_remove_cb(int8_t interfaceId, uint8_t *targetAddress, void *prefix_info)
{
protocol_interface_info_entry_t *curPtr = protocol_stack_interface_info_get_by_id(interfaceId);
if (!curPtr) {
return;
}
if (!targetAddress) {
//Clear All targets routes
ipv6_route_table_remove_info(interfaceId, ROUTE_THREAD_PROXIED_HOST,prefix_info);
} else {
tr_debug("Address Preferred Timeout");
ipv6_route_delete(targetAddress, 128, interfaceId, NULL, ROUTE_THREAD_PROXIED_HOST);
thread_service_remove_GUA_from_neighcache(curPtr, targetAddress);
}
}
static bool thread_dhcp_address_add_cb(int8_t interfaceId, dhcp_address_cache_update_t *address_info, void *route_src)
{
protocol_interface_info_entry_t *curPtr = protocol_stack_interface_info_get_by_id(interfaceId);
if (!curPtr) {
return false;
}
// If this is solicit from existing address, flush ND cache.
if (address_info->allocatedNewAddress) {
// coverity[returned_null] for ignoring protocol_stack_interface_info_get_by_id NULL return
thread_service_remove_GUA_from_neighcache(curPtr, address_info->allocatedAddress);
}
if (thread_bbr_nd_entry_add(interfaceId,address_info->allocatedAddress, address_info->validLifeTime, route_src) == -1) {
// No nanostack BBR present we will put entry for application implemented BBR
ipv6_route_t *route = ipv6_route_add_with_info(address_info->allocatedAddress, 128, interfaceId, NULL, ROUTE_THREAD_PROXIED_HOST,route_src,0, address_info->validLifeTime, 0);
if (!route) {
return false;
}
}
return true;
}
int thread_dhcp6_server_init(int8_t interface_id, uint8_t prefix[8], uint8_t eui64[8], uint32_t validLifeTimne)
{
if (DHCPv6_server_service_init(interface_id, prefix, eui64, DHCPV6_DUID_HARDWARE_EUI64_TYPE) != 0) {
return -1;
}
//Register Callbacks
DHCPv6_server_service_callback_set(interface_id, prefix, thread_dhcp_address_prefer_remove_cb, thread_dhcp_address_add_cb);
//SET Timeout
DHCPv6_server_service_set_address_validlifetime(interface_id, prefix, validLifeTimne);
return 0;
}
#endif

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef THREAD_DHCPV6_SERVER_H_
#define THREAD_DHCPV6_SERVER_H_
#if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER)
int thread_dhcp6_server_init(int8_t interface_id, uint8_t prefix[8], uint8_t eui64[8], uint32_t validLifeTimne);
#else
#define thread_dhcp6_server_init(interface_id, prefix, eui64, validLifeTimne) (-1)
#endif
#endif /* THREAD_DHCPV6_SERVER_H_ */

View File

@ -35,6 +35,7 @@
#include "nsdynmemLIB.h" #include "nsdynmemLIB.h"
#include "net_interface.h" #include "net_interface.h"
#include "thread_management_if.h" #include "thread_management_if.h"
#include "thread_management_server.h"
#include "thread_common.h" #include "thread_common.h"
#include "thread_joiner_application.h" #include "thread_joiner_application.h"
#include "thread_leader_service.h" #include "thread_leader_service.h"
@ -229,6 +230,10 @@ static int thread_diagnostic_configuration_calc(protocol_interface_info_entry_t
payload_len += 2+1; payload_len += 2+1;
break; break;
case DIAGCOP_TLV_MAX_CHILD_TIMEOUT:
payload_len += 2 + 4;
break;
default: default:
// todo: Other TLV's not supported atm // todo: Other TLV's not supported atm
break; break;
@ -254,6 +259,7 @@ static uint8_t *thread_diagnostic_get_build(protocol_interface_info_entry_t *cur
uint8_t *ptr; uint8_t *ptr;
int written_address_count = 0; int written_address_count = 0;
uint16_t ipv6_address_count = 0; uint16_t ipv6_address_count = 0;
uint32_t max_child_timeout = 0;
uint8_t extended_address[8] = {0}; uint8_t extended_address[8] = {0};
arm_net_interface_address_list_size(cur->id, &ipv6_address_count); arm_net_interface_address_list_size(cur->id, &ipv6_address_count);
@ -352,6 +358,12 @@ static uint8_t *thread_diagnostic_get_build(protocol_interface_info_entry_t *cur
response_ptr = thread_diagcop_tlv_data_write_uint8(response_ptr, DIAGCOP_TLV_CHANNEL_PAGES, 0); response_ptr = thread_diagcop_tlv_data_write_uint8(response_ptr, DIAGCOP_TLV_CHANNEL_PAGES, 0);
break; break;
case DIAGCOP_TLV_MAX_CHILD_TIMEOUT:
if (thread_router_bootstrap_child_max_timeout_get(cur, &max_child_timeout) == 0) {
response_ptr = thread_diagcop_tlv_data_write_uint32(response_ptr, DIAGCOP_TLV_MAX_CHILD_TIMEOUT, max_child_timeout);
}
break;
default: default:
break; break;
@ -532,7 +544,7 @@ int thread_diagnostic_init(int8_t interface_id)
this->interface_id = interface_id; this->interface_id = interface_id;
this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); this->coap_service_id = thread_management_server_service_id_get(interface_id);
if (this->coap_service_id < 0) { if (this->coap_service_id < 0) {
tr_error("Thread diagnostic init failed"); tr_error("Thread diagnostic init failed");
ns_dyn_mem_free(this); ns_dyn_mem_free(this);
@ -556,8 +568,9 @@ int thread_diagnostic_delete(int8_t interface_id)
if (!this) { if (!this) {
return -1; return -1;
} }
coap_service_unregister_uri(this->coap_service_id, THREAD_URI_DIAGNOSTIC_REQUEST);
coap_service_delete(this->coap_service_id); coap_service_unregister_uri(this->coap_service_id, THREAD_URI_DIAGNOSTIC_RESET);
coap_service_unregister_uri(this->coap_service_id, THREAD_URI_DIAGNOSTIC_QUERY);
ns_list_remove(&instance_list, this); ns_list_remove(&instance_list, this);
ns_dyn_mem_free(this); ns_dyn_mem_free(this);
return 0; return 0;

View File

@ -46,19 +46,15 @@ void thread_extension_allocate(protocol_interface_info_entry_t *cur);
void thread_extension_free(protocol_interface_info_entry_t *cur); void thread_extension_free(protocol_interface_info_entry_t *cur);
void thread_extension_init(int8_t interface_id, int8_t coap_service_id); void thread_extension_init(int8_t interface_id, int8_t coap_service_id);
void thread_extension_mtd_service_register(protocol_interface_info_entry_t *cur); void thread_extension_mtd_service_register(protocol_interface_info_entry_t *cur);
int thread_extension_network_prefix_get(int8_t interface_id, uint8_t *options_ptr, uint8_t *prefix_ptr, uint8_t *prefix_len);
void thread_extension_network_data_process(struct protocol_interface_info_entry *cur); void thread_extension_network_data_process(struct protocol_interface_info_entry *cur);
int thread_extension_primary_bbr_get(struct protocol_interface_info_entry *cur, uint8_t *addr_ptr, uint8_t *seq_ptr, uint32_t *timer1_ptr, uint32_t *timer2_ptr); int thread_extension_primary_bbr_get(struct protocol_interface_info_entry *cur, uint8_t *addr_ptr, uint8_t *seq_ptr, uint32_t *timer1_ptr, uint32_t *timer2_ptr);
void thread_extension_address_registration(struct protocol_interface_info_entry *interface, const uint8_t *addr, const uint8_t *child_mac64, bool refresh_child_entry, bool duplicate_child_detected); void thread_extension_address_registration(struct protocol_interface_info_entry *interface, const uint8_t *addr, const uint8_t *child_mac64, bool refresh_child_entry, bool duplicate_child_detected);
void thread_extension_address_generate(protocol_interface_info_entry_t *cur); void thread_extension_dua_address_generate(protocol_interface_info_entry_t *cur, const uint8_t *domain_prefix, uint8_t domain_prefix_len);
void thread_extension_aloc_generate(struct protocol_interface_info_entry *cur); void thread_extension_aloc_generate(struct protocol_interface_info_entry *cur);
bool thread_extension_aloc_map(protocol_interface_info_entry_t *cur, uint16_t *addr16); bool thread_extension_aloc_map(protocol_interface_info_entry_t *cur, uint16_t *addr16);
void thread_extension_mcast_subscrition_change(protocol_interface_info_entry_t *interface); void thread_extension_mcast_subscrition_change(protocol_interface_info_entry_t *interface);
void thread_extension_address_registration_trigger(protocol_interface_info_entry_t *interface); void thread_extension_address_registration_trigger(protocol_interface_info_entry_t *interface);
void thread_extension_route_set(protocol_interface_info_entry_t *cur);
void thread_extension_activate(protocol_interface_info_entry_t *cur);
bool thread_extension_enabled(protocol_interface_info_entry_t *cur); bool thread_extension_enabled(protocol_interface_info_entry_t *cur);
bool thread_extension_context_can_delete(int8_t id, uint8_t servicesPrefix[16], uint8_t context_prefix_length);
bool thread_extension_version_check(uint8_t version); bool thread_extension_version_check(uint8_t version);
void thread_extension_discover_response_read(struct discovery_response_list *nwk_info, uint16_t discover_response_tlv, uint8_t *data_ptr, uint16_t data_len); void thread_extension_discover_response_read(struct discovery_response_list *nwk_info, uint16_t discover_response_tlv, uint8_t *data_ptr, uint16_t data_len);
void thread_extension_discover_response_tlv_write(uint16_t *data, uint8_t version, uint16_t securityPolicy); void thread_extension_discover_response_tlv_write(uint16_t *data, uint8_t version, uint16_t securityPolicy);
@ -70,35 +66,31 @@ uint8_t thread_extension_discover_response_len(protocol_interface_info_entry_t *
uint8_t *thread_extension_discover_response_write(protocol_interface_info_entry_t *cur, uint8_t *ptr); uint8_t *thread_extension_discover_response_write(protocol_interface_info_entry_t *cur, uint8_t *ptr);
#else #else
#define thread_extension_joining_enabled(interface_id) false #define thread_extension_joining_enabled(interface_id) (false)
#define thread_extension_discover_response_len(cur) 0 #define thread_extension_discover_response_len(cur) (0)
#define thread_extension_discover_response_write(cur, ptr) (ptr) #define thread_extension_discover_response_write(cur, ptr) (ptr)
#endif //HAVE_THREAD_ROUTER #endif //HAVE_THREAD_ROUTER
#else #else
#define thread_extension_allocate(cur) #define thread_extension_allocate(cur) ((void) 0)
#define thread_extension_free(cur) #define thread_extension_free(cur) ((void) 0)
#define thread_extension_init(interface_id,coap_service_id) #define thread_extension_init(interface_id,coap_service_id) ((void) 0)
#define thread_extension_network_prefix_get(interface_id,options_ptr,prefix_ptr,prefix_len) (-1) #define thread_extension_network_data_process(cur) ((void) 0)
#define thread_extension_network_data_process(cur)
#define thread_extension_primary_bbr_get(cur,addr_ptr,seq_ptr,timer1_ptr, timer2_ptr) (-1) #define thread_extension_primary_bbr_get(cur,addr_ptr,seq_ptr,timer1_ptr, timer2_ptr) (-1)
#define thread_extension_address_registration(interface,addr,child_mac64,refresh_child_entry,duplicate_child_detected) #define thread_extension_address_registration(interface,addr,child_mac64,refresh_child_entry,duplicate_child_detected) ((void) 0)
#define thread_extension_address_generate(cur) #define thread_extension_aloc_generate(cur) ((void) 0)
#define thread_extension_aloc_generate(cur) #define thread_extension_aloc_map(cur, addr16) (false)
#define thread_extension_aloc_map(cur, addr16) false #define thread_extension_mcast_subscrition_change(interface) ((void) 0)
#define thread_extension_mcast_subscrition_change(interface)
#define thread_extension_route_set(cur)
#define thread_extension_activate(cur)
#define thread_extension_enabled(cur) (false) #define thread_extension_enabled(cur) (false)
#define thread_extension_version_check(version) (false) #define thread_extension_version_check(version) (false)
#define thread_extension_discover_response_read(nwk_info, discover_response_tlv, data_ptr, data_len) #define thread_extension_discover_response_read(nwk_info, discover_response_tlv, data_ptr, data_len) ((void) 0)
#define thread_extension_discover_response_tlv_write(data, version, extension_bit) (data) #define thread_extension_discover_response_tlv_write(data, version, securityPolicy) ((void) 0)
#define thread_extension_service_init(cur) 0 #define thread_extension_service_init(cur) (0)
#define thread_extension_joining_enabled(interface_id) false #define thread_extension_joining_enabled(interface_id) (false)
#define thread_extension_discover_response_len(cur) 0 #define thread_extension_discover_response_len(cur) (0)
#define thread_extension_discover_response_write(cur, ptr) (ptr) #define thread_extension_discover_response_write(cur, ptr) (ptr)
#define thread_extension_addr_ntf_send(cur,destination_address,addr_data_ptr,bbr_status) #define thread_extension_addr_ntf_send(cur,destination_address,addr_data_ptr,bbr_status) ((void) 0)
#define thread_extension_context_can_delete(id, servicesPrefix, context_prefix_length) false #define thread_extension_dua_address_generate(cur, domain_prefix, domain_prefix_len) ((void) 0)
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -52,10 +52,12 @@ int8_t thread_extension_bbr_init(int8_t interface_id, int8_t backbone_interface_
void thread_extension_bbr_delete(int8_t interface_id); void thread_extension_bbr_delete(int8_t interface_id);
bool thread_extension_bbr_nd_query_process(protocol_interface_info_entry_t *cur, const uint8_t *target_addr, uint16_t rloc); bool thread_extension_bbr_nd_query_process(protocol_interface_info_entry_t *cur, const uint8_t *target_addr, uint16_t rloc);
void thread_extension_bbr_seconds_timer(int8_t interface_id, uint32_t seconds); void thread_extension_bbr_seconds_timer(int8_t interface_id, uint32_t seconds);
int thread_extension_bbr_sequence_number_set(int8_t interface_id, uint8_t seq_number);
int thread_extension_bbr_timeout_set(int8_t interface_id, uint32_t timeout_a, uint32_t timeout_b, uint32_t delay); int thread_extension_bbr_timeout_set(int8_t interface_id, uint32_t timeout_a, uint32_t timeout_b, uint32_t delay);
int thread_extension_bbr_address_set(int8_t interface_id, const uint8_t *addr_ptr, uint16_t port); int thread_extension_bbr_address_set(int8_t interface_id, const uint8_t *addr_ptr, uint16_t port);
void thread_extension_bbr_route_update(protocol_interface_info_entry_t *cur); void thread_extension_bbr_route_update(protocol_interface_info_entry_t *cur);
int thread_extension_bbr_prefix_set(int8_t interface_id, uint8_t *prefix); int thread_extension_bbr_prefix_set(int8_t interface_id, uint8_t *prefix);
void thread_extension_bbr_old_partition_data_clean(int8_t interface_id);
#else #else
@ -67,7 +69,9 @@ int thread_extension_bbr_prefix_set(int8_t interface_id, uint8_t *prefix);
#define thread_extension_bbr_timeout_set(interface_id, timeout_a, timeout_b, delay) #define thread_extension_bbr_timeout_set(interface_id, timeout_a, timeout_b, delay)
#define thread_extension_bbr_address_set(interface_id, addr_ptr, port) (-1) #define thread_extension_bbr_address_set(interface_id, addr_ptr, port) (-1)
#define thread_extension_bbr_route_update(cur) #define thread_extension_bbr_route_update(cur)
#define thread_extension_bbr_sequence_number_set(interface_id, seq_number) (-1)
#define thread_extension_bbr_prefix_set(interface_id, prefix) 0 #define thread_extension_bbr_prefix_set(interface_id, prefix) 0
#define thread_extension_bbr_old_partition_data_clean(interface_id)
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -45,6 +45,8 @@ extern "C" {
#define thread_extension_bootstrap_thread_name_length_get(cur) (0) #define thread_extension_bootstrap_thread_name_length_get(cur) (0)
#define thread_extension_bootstrap_thread_name_ptr_get(cur) (NULL) #define thread_extension_bootstrap_thread_name_ptr_get(cur) (NULL)
#define thread_extension_bootstrap_network_certificate_enable(cur, coap_service_id) (NULL) #define thread_extension_bootstrap_network_certificate_enable(cur, coap_service_id) (NULL)
#define thread_extension_bootstrap_reenrollment_start(cur, service_id, pbbr_addr) (-1)
#define thread_extension_bootstrap_network_reattach(interface_id, timeout) (-1)
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -121,11 +121,11 @@ static void thread_network_data_clean(protocol_interface_info_entry_t *cur)
static void thread_merge_prepare(protocol_interface_info_entry_t *cur) static void thread_merge_prepare(protocol_interface_info_entry_t *cur)
{ {
thread_partition_data_purge(cur);
thread_clean_old_16_bit_address_based_addresses(cur); thread_clean_old_16_bit_address_based_addresses(cur);
mpl_clear_realm_scope_seeds(cur); mpl_clear_realm_scope_seeds(cur);
ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_HOST, NULL); ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_HOST, NULL);
ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_DUA_HOST, NULL); ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_DUA_HOST, NULL);
thread_partition_data_purge(cur);
thread_network_data_clean(cur); thread_network_data_clean(cur);
cur->nwk_mode = ARM_NWK_GP_IP_MODE; cur->nwk_mode = ARM_NWK_GP_IP_MODE;
} }
@ -305,6 +305,7 @@ static int thread_end_device_synch_response_validate(protocol_interface_info_ent
uint16_t address16; uint16_t address16;
uint32_t llFrameCounter; uint32_t llFrameCounter;
thread_leader_data_t leaderData; thread_leader_data_t leaderData;
mle_tlv_info_t addressRegisteredTlv;
mac_neighbor_table_entry_t *entry_temp; mac_neighbor_table_entry_t *entry_temp;
bool new_entry_created; bool new_entry_created;
@ -320,6 +321,7 @@ static int thread_end_device_synch_response_validate(protocol_interface_info_ent
// Address // Address
// MLE_TYPE_SRC_ADDRESS // MLE_TYPE_SRC_ADDRESS
// MLE_TYPE_LEADER_DATA // MLE_TYPE_LEADER_DATA
// MLE_TYPE_ADDRESS_REGISTRATION
if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, ptr, data_length, &mode) || if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, ptr, data_length, &mode) ||
!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, ptr, data_length, &srcAddress) || !mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, ptr, data_length, &srcAddress) ||
!mle_tlv_read_16_bit_tlv(MLE_TYPE_ADDRESS16, ptr, data_length, &address16) || !mle_tlv_read_16_bit_tlv(MLE_TYPE_ADDRESS16, ptr, data_length, &address16) ||
@ -329,6 +331,25 @@ static int thread_end_device_synch_response_validate(protocol_interface_info_ent
return -1; return -1;
} }
if (!(mode & THREAD_DEVICE_FED)) {
// check for presence of Address registration TLV for MTDs
if (!mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, ptr, data_length, &addressRegisteredTlv) ||
(addressRegisteredTlv.tlvLen == 0)) {
tr_debug("MTD missed address registration TLV - reattach");
return -1;
}
}
// check if the source address is a router address
if (!thread_is_router_addr(srcAddress)) {
return -1;
}
// check if the address16 is a valid child address
if (!thread_addr_is_child(srcAddress, address16)) {
return -1;
}
if (securityHeader->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) { if (securityHeader->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) {
thread_management_key_synch_req(cur->id, common_read_32_bit(securityHeader->Keysource)); thread_management_key_synch_req(cur->id, common_read_32_bit(securityHeader->Keysource));
// if learning key sequence from link sync actual guard timer value is not known // if learning key sequence from link sync actual guard timer value is not known
@ -1103,7 +1124,7 @@ static int thread_attach_child_id_request_build(protocol_interface_info_entry_t
//Add ML-EID //Add ML-EID
if ((mode & MLE_FFD_DEV) == 0) { if ((mode & MLE_FFD_DEV) == 0) {
ptr = thread_address_registration_tlv_write(ptr, cur); ptr = thread_ml_address_tlv_write(ptr,cur);
} }
reqTlvCnt = 2; reqTlvCnt = 2;

View File

@ -54,6 +54,7 @@
#include "thread_management_if.h" #include "thread_management_if.h"
#include "thread_common.h" #include "thread_common.h"
#include "thread_bootstrap.h" #include "thread_bootstrap.h"
#include "thread_router_bootstrap.h"
#include "thread_network_synch.h" #include "thread_network_synch.h"
#include "thread_network_data_lib.h" #include "thread_network_data_lib.h"
#include "thread_joiner_application.h" #include "thread_joiner_application.h"
@ -1140,7 +1141,7 @@ void thread_joiner_pending_config_activate(int8_t interface_id)
this->active_configuration_ptr->timestamp = pending_active_timestamp; this->active_configuration_ptr->timestamp = pending_active_timestamp;
// All information is copied from old configuration so if configuration is corrupt we dont change anything. // All information is copied from old configuration so if configuration is corrupt we dont change anything.
this->pending_configuration_ptr = NULL; this->pending_configuration_ptr = NULL;
(void)thread_nvm_store_pending_configuration_remove(); thread_nvm_store_pending_configuration_remove();
configuration_set_copy_mandatory(this->active_configuration_ptr, this->old_active_configuration_ptr); configuration_set_copy_mandatory(this->active_configuration_ptr, this->old_active_configuration_ptr);
link_configuration_update(this->configuration_ptr,this->active_configuration_ptr->data, this->active_configuration_ptr->length); link_configuration_update(this->configuration_ptr,this->active_configuration_ptr->data, this->active_configuration_ptr->length);
link_configuration_trace(this->configuration_ptr); link_configuration_trace(this->configuration_ptr);
@ -1922,6 +1923,8 @@ int thread_joiner_application_update_configuration(uint8_t interface_id, uint8_t
} }
thread_meshcop_tlv_data_get_uint64(msg_ptr, msg_len, MESHCOP_TLV_ACTIVE_TIME_STAMP, &this->active_configuration_ptr->timestamp); thread_meshcop_tlv_data_get_uint64(msg_ptr, msg_len, MESHCOP_TLV_ACTIVE_TIME_STAMP, &this->active_configuration_ptr->timestamp);
link_configuration_update(this->configuration_ptr,msg_ptr,msg_len); link_configuration_update(this->configuration_ptr,msg_ptr,msg_len);
// allow 5 seconds delay before state change for data response propagation
thread_router_bootstrap_delay_reed_jitter(interface_id, 5);
ns_dyn_mem_free(configuration_ptr); ns_dyn_mem_free(configuration_ptr);
thread_joiner_application_configuration_nvm_save(interface_id); thread_joiner_application_configuration_nvm_save(interface_id);

View File

@ -41,7 +41,7 @@
#include "6LoWPAN/Thread/thread_config.h" #include "6LoWPAN/Thread/thread_config.h"
#include "6LoWPAN/Thread/thread_common.h" #include "6LoWPAN/Thread/thread_common.h"
#include "6LoWPAN/Thread/thread_bootstrap.h" #include "6LoWPAN/Thread/thread_bootstrap.h"
#include "6LoWPAN/Thread/thread_dhcpv6_client.h" #include "DHCPv6_client/dhcpv6_client_api.h"
#include "6LoWPAN/Thread/thread_discovery.h" #include "6LoWPAN/Thread/thread_discovery.h"
#include "6LoWPAN/Thread/thread_joiner_application.h" #include "6LoWPAN/Thread/thread_joiner_application.h"
#include "6LoWPAN/Thread/thread_network_data_lib.h" #include "6LoWPAN/Thread/thread_network_data_lib.h"
@ -305,7 +305,6 @@ static int thread_leader_service_commissioner_register(int8_t interface_id, uint
protocol_interface_info_entry_t *cur; protocol_interface_info_entry_t *cur;
link_configuration_s *linkConfiguration; link_configuration_s *linkConfiguration;
tr_debug("Register interface %d commissioner: %s", interface_id, trace_ipv6(border_router_address));
linkConfiguration = thread_joiner_application_get_config(interface_id); linkConfiguration = thread_joiner_application_get_config(interface_id);
if (!linkConfiguration) { if (!linkConfiguration) {
@ -341,6 +340,13 @@ static int thread_leader_service_commissioner_register(int8_t interface_id, uint
*session_id = cur->thread_info->registered_commissioner.session_id; *session_id = cur->thread_info->registered_commissioner.session_id;
} }
if (memcmp(border_router_address, linkConfiguration->mesh_local_ula_prefix, 8) == 0 &&
memcmp(border_router_address + 8, ADDR_SHORT_ADR_SUFFIC, 6) == 0 &&
border_router_address[14] == 0xfc) {
// source address is ALOC
common_write_16_bit(cur->thread_info->routerShortAddress, &border_router_address[14]);
}
tr_debug("Register interface %d commissioner: %s", interface_id, trace_ipv6(border_router_address));
//SET Border Router Locator //SET Border Router Locator
memcpy(cur->thread_info->registered_commissioner.border_router_address, border_router_address, 16); memcpy(cur->thread_info->registered_commissioner.border_router_address, border_router_address, 16);
cur->thread_info->registered_commissioner.commissioner_valid = true; cur->thread_info->registered_commissioner.commissioner_valid = true;
@ -1295,7 +1301,7 @@ static int thread_leader_service_leader_init(protocol_interface_info_entry_t *cu
thread_routing_free(&thread_info->routing); thread_routing_free(&thread_info->routing);
ipv6_route_table_remove_info(cur->id, ROUTE_THREAD, NULL); ipv6_route_table_remove_info(cur->id, ROUTE_THREAD, NULL);
ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_BORDER_ROUTER, NULL); ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_BORDER_ROUTER, NULL);
thread_dhcp_client_delete(cur->id); dhcp_client_delete(cur->id);
thread_nd_service_delete(cur->id); thread_nd_service_delete(cur->id);
mpl_clear_realm_scope_seeds(cur); mpl_clear_realm_scope_seeds(cur);
ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache); ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache);
@ -1352,7 +1358,6 @@ static void thread_leader_service_interface_setup_activate(protocol_interface_in
cur->lowpan_address_mode = NET_6LOWPAN_GP16_ADDRESS; cur->lowpan_address_mode = NET_6LOWPAN_GP16_ADDRESS;
thread_bootstrap_update_ml16_address(cur, cur->thread_info->routerShortAddress); thread_bootstrap_update_ml16_address(cur, cur->thread_info->routerShortAddress);
thread_generate_ml64_address(cur); thread_generate_ml64_address(cur);
thread_extension_address_generate(cur);
thread_bootstrap_routing_activate(cur); thread_bootstrap_routing_activate(cur);
thread_routing_update_id_set(cur, private->maskSeq, private->master_router_id_mask); thread_routing_update_id_set(cur, private->maskSeq, private->master_router_id_mask);
thread_routing_activate(&cur->thread_info->routing); thread_routing_activate(&cur->thread_info->routing);

View File

@ -287,7 +287,6 @@ int thread_management_register(int8_t interface_id)
this->get_response_cb_ptr = NULL; this->get_response_cb_ptr = NULL;
if (thread_management_get_remote_addr(this)) { if (thread_management_get_remote_addr(this)) {
ns_dyn_mem_free(this);
return -1; return -1;
} }

View File

@ -45,6 +45,7 @@
#include "6LoWPAN/Thread/thread_constants.h" #include "6LoWPAN/Thread/thread_constants.h"
#include "6LoWPAN/Thread/thread_tmfcop_lib.h" #include "6LoWPAN/Thread/thread_tmfcop_lib.h"
#include "6LoWPAN/Thread/thread_management_internal.h" #include "6LoWPAN/Thread/thread_management_internal.h"
#include "6LoWPAN/Thread/thread_management_server.h"
#include "6LoWPAN/Thread/thread_joiner_application.h" #include "6LoWPAN/Thread/thread_joiner_application.h"
#include "6LoWPAN/Thread/thread_network_data_lib.h" #include "6LoWPAN/Thread/thread_network_data_lib.h"
#include "6LoWPAN/Thread/thread_bootstrap.h" #include "6LoWPAN/Thread/thread_bootstrap.h"
@ -58,9 +59,8 @@ typedef struct thread_management {
thread_management_client_router_id_cb *router_id_release_cb_ptr; thread_management_client_router_id_cb *router_id_release_cb_ptr;
thread_management_client_network_data_set_cb *network_data_set_cb_ptr; thread_management_client_network_data_set_cb *network_data_set_cb_ptr;
thread_management_client_network_data_set_cb *neighbor_discovery_cb_ptr; thread_management_client_network_data_set_cb *neighbor_discovery_cb_ptr;
uint16_t coap_asd_msg_id; // COAP msg id for a/sd
int8_t interface_id; int8_t interface_id;
int8_t coap_service_id; int8_t coap_service_id; // COAP service ID from Management server
ns_list_link_t link; ns_list_link_t link;
} thread_management_t; } thread_management_t;
@ -150,9 +150,12 @@ void thread_management_client_init(int8_t interface_id)
this->neighbor_discovery_cb_ptr = NULL; this->neighbor_discovery_cb_ptr = NULL;
this->router_id_cb_ptr = NULL; this->router_id_cb_ptr = NULL;
this->interface_id = interface_id; this->interface_id = interface_id;
this->coap_asd_msg_id = 0;
//TODO: Check if to use ephemeral port here //TODO: Check if to use ephemeral port here
this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL);
this->coap_service_id = thread_management_server_service_id_get(interface_id);
if (this->coap_service_id < 0) {
tr_error("Failed to init COAP service");
}
ns_list_add_to_start(&instance_list, this); ns_list_add_to_start(&instance_list, this);
} }
return; return;
@ -165,19 +168,10 @@ void thread_management_client_delete(int8_t interface_id)
return; return;
} }
coap_service_delete(this->coap_service_id);
ns_list_remove(&instance_list, this); ns_list_remove(&instance_list, this);
ns_dyn_mem_free(this); ns_dyn_mem_free(this);
return; return;
} }
int8_t thread_management_client_service_id_get(int8_t interface_id)
{
thread_management_t *this = thread_management_find(interface_id);
if (!this) {
return -1;
}
return this->coap_service_id;
}
int thread_management_client_router_id_get(int8_t interface_id, uint8_t mac[8], uint16_t router_id, thread_management_client_router_id_cb *id_cb, uint8_t status) int thread_management_client_router_id_get(int8_t interface_id, uint8_t mac[8], uint16_t router_id, thread_management_client_router_id_cb *id_cb, uint8_t status)
{ {
@ -251,8 +245,6 @@ static int thread_management_client_register_cb(int8_t service_id, uint8_t sourc
return -1; return -1;
} }
this->coap_asd_msg_id = 0; //clear the coap message id
if (this->network_data_set_cb_ptr) { if (this->network_data_set_cb_ptr) {
if (response_ptr) { if (response_ptr) {
// If we get response status is OK // If we get response status is OK
@ -281,10 +273,8 @@ int thread_management_client_network_data_register(int8_t interface_id, uint8_t
this->network_data_set_cb_ptr = set_cb; this->network_data_set_cb_ptr = set_cb;
tr_debug("thread network data send to %s", trace_ipv6(destination)); tr_debug("thread network data send to %s", trace_ipv6(destination));
this->coap_asd_msg_id = coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT, return coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT,
COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_NETWORK_DATA, COAP_CT_OCTET_STREAM, data_ptr, data_len, thread_management_client_register_cb); COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_NETWORK_DATA, COAP_CT_OCTET_STREAM, data_ptr, data_len, thread_management_client_register_cb);
return 0;
} }
int thread_management_client_network_data_unregister(int8_t interface_id, uint16_t rloc16) int thread_management_client_network_data_unregister(int8_t interface_id, uint16_t rloc16)
@ -306,7 +296,7 @@ int thread_management_client_network_data_unregister(int8_t interface_id, uint16
tr_debug("thread network data unregister"); tr_debug("thread network data unregister");
this->coap_asd_msg_id = coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT, coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT,
COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_NETWORK_DATA, COAP_CT_OCTET_STREAM, payload, ptr - payload, thread_management_client_register_cb); COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_NETWORK_DATA, COAP_CT_OCTET_STREAM, payload, ptr - payload, thread_management_client_register_cb);
return 0; return 0;
} }
@ -616,7 +606,18 @@ void thread_management_client_proactive_an(int8_t interface_id, const uint8_t ad
payload, ptr - payload, thread_management_client_proactive_an_cb); payload, ptr - payload, thread_management_client_proactive_an_cb);
} }
void thread_management_client_pending_coap_request_kill(int8_t interface_id) void thread_management_client_coap_message_delete(int8_t interface_id, uint16_t coap_message_id)
{
thread_management_t *this = thread_management_find(interface_id);
if (!this) {
return;
}
coap_service_request_delete(this->coap_service_id, coap_message_id);
}
void thread_management_client_old_partition_data_clean(int8_t interface_id)
{ {
thread_management_t *this = thread_management_find(interface_id); thread_management_t *this = thread_management_find(interface_id);
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
@ -625,17 +626,9 @@ void thread_management_client_pending_coap_request_kill(int8_t interface_id)
return; return;
} }
cur->thread_info->localServerDataBase.publish_active = false; cur->thread_info->localServerDataBase.publish_coap_req_id = 0;
cur->thread_info->routerIdRequested = false;
if (this->coap_asd_msg_id != 0) { coap_service_request_delete_by_service_id(this->coap_service_id);
coap_service_request_delete(this->coap_service_id, this->coap_asd_msg_id);
this->coap_asd_msg_id = 0;
}
if (cur->thread_info->routerIdReqCoapID != 0) {
coap_service_request_delete(this->coap_service_id, cur->thread_info->routerIdReqCoapID);
cur->thread_info->routerIdReqCoapID = 0;
}
} }
#endif #endif

View File

@ -65,12 +65,6 @@ void thread_management_client_init(int8_t interface_id);
*/ */
void thread_management_client_delete(int8_t interface_id); void thread_management_client_delete(int8_t interface_id);
/** Get service id of management service.
*
* When using Coap Management port service this service is the only instance used to make client transactions.
*/
int8_t thread_management_client_service_id_get(int8_t interface_id);
/** Router id handler callback. /** Router id handler callback.
* *
* callback to inform when new router id is received from leader. * callback to inform when new router id is received from leader.
@ -213,9 +207,20 @@ int thread_management_client_provision_request(int8_t interface_id, uint8_t *dst
*/ */
void thread_management_client_proactive_an(int8_t interface_id, const uint8_t address[16], const uint16_t rloc, const uint8_t ml_eid[8], const uint8_t dst_addr[16]); void thread_management_client_proactive_an(int8_t interface_id, const uint8_t address[16], const uint16_t rloc, const uint8_t ml_eid[8], const uint8_t dst_addr[16]);
/** Kill pending COAP requests. /** Delete COAP message .
*
* Delete COAP message that is sent to COAP service.
*
* \param interface_id interface id of this Thread instance.
* \param coap_message_id COAP message to be deleted.
*/
void thread_management_client_coap_message_delete(int8_t interface_id, uint16_t coap_message_id);
/** Clear old partition data.
*
* Clear data related to old partition, like pending COAP transactions.
* *
* \param interface_id interface id of this Thread instance. * \param interface_id interface id of this Thread instance.
*/ */
void thread_management_client_pending_coap_request_kill(int8_t interface_id); void thread_management_client_old_partition_data_clean(int8_t interface_id);
#endif /* THREAD_MANAGEMENT_CLIENT_H_ */ #endif /* THREAD_MANAGEMENT_CLIENT_H_ */

View File

@ -50,7 +50,7 @@
#include "6LoWPAN/Thread/thread_leader_service.h" #include "6LoWPAN/Thread/thread_leader_service.h"
#include "6LoWPAN/Thread/thread_nd.h" #include "6LoWPAN/Thread/thread_nd.h"
#include "thread_diagnostic.h" #include "thread_diagnostic.h"
#include "6LoWPAN/Thread/thread_dhcpv6_client.h" #include "DHCPv6_client/dhcpv6_client_api.h"
#include "6LoWPAN/Thread/thread_discovery.h" #include "6LoWPAN/Thread/thread_discovery.h"
#include "6LoWPAN/Thread/thread_network_synch.h" #include "6LoWPAN/Thread/thread_network_synch.h"
#include "6LoWPAN/Thread/thread_management_internal.h" #include "6LoWPAN/Thread/thread_management_internal.h"
@ -63,6 +63,7 @@
#include "6LoWPAN/Thread/thread_constants.h" #include "6LoWPAN/Thread/thread_constants.h"
#include "6LoWPAN/Thread/thread_extension_bootstrap.h" #include "6LoWPAN/Thread/thread_extension_bootstrap.h"
#include "6LoWPAN/Thread/thread_extension.h" #include "6LoWPAN/Thread/thread_extension.h"
#include "6LoWPAN/Thread/thread_bbr_api_internal.h"
#include "6LoWPAN/Bootstraps/protocol_6lowpan.h" #include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
#include "RPL/rpl_control.h" // insanity - bootstraps shouldn't be doing each others' clean-up #include "RPL/rpl_control.h" // insanity - bootstraps shouldn't be doing each others' clean-up
#include "MLE/mle.h" #include "MLE/mle.h"
@ -71,9 +72,8 @@
#include "thread_commissioning_if.h" #include "thread_commissioning_if.h"
#include "shalib.h" #include "shalib.h"
#include "Common_Protocols/icmpv6.h" #include "Common_Protocols/icmpv6.h"
#include "libDHCPv6/libDHCPv6.h"
#include "libDHCPv6/libDHCPv6_server.h"
#include "DHCPv6_Server/DHCPv6_server_service.h" #include "DHCPv6_Server/DHCPv6_server_service.h"
#include "6LoWPAN/Thread/thread_dhcpv6_server.h"
#include "Service_Libs/mle_service/mle_service_api.h" #include "Service_Libs/mle_service/mle_service_api.h"
#include "Service_Libs/blacklist/blacklist.h" #include "Service_Libs/blacklist/blacklist.h"
#include "6LoWPAN/MAC/mac_helper.h" #include "6LoWPAN/MAC/mac_helper.h"
@ -606,7 +606,7 @@ int thread_management_get_ml_prefix_112(int8_t interface_id, uint8_t *prefix_ptr
*/ */
int thread_dhcpv6_server_add(int8_t interface_id, uint8_t *prefix_ptr, uint32_t max_client_cnt, bool stableData) int thread_dhcpv6_server_add(int8_t interface_id, uint8_t *prefix_ptr, uint32_t max_client_cnt, bool stableData)
{ {
#ifdef HAVE_DHCPV6_SERVER #if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER)
protocol_interface_info_entry_t *cur; protocol_interface_info_entry_t *cur;
thread_prefix_tlv_t prefixTlv; thread_prefix_tlv_t prefixTlv;
thread_border_router_tlv_entry_t service; thread_border_router_tlv_entry_t service;
@ -622,7 +622,7 @@ int thread_dhcpv6_server_add(int8_t interface_id, uint8_t *prefix_ptr, uint32_t
return -1; return -1;
} }
if (DHCPv6_server_service_init(interface_id, prefix_ptr, cur->mac, DHCPV6_DUID_HARDWARE_EUI64_TYPE) != 0) { if (thread_dhcp6_server_init(interface_id, prefix_ptr, cur->mac, THREAD_MIN_PREFIX_LIFETIME) != 0) {
tr_warn("SerVER alloc fail"); tr_warn("SerVER alloc fail");
return -1; return -1;
} }
@ -637,14 +637,9 @@ int thread_dhcpv6_server_add(int8_t interface_id, uint8_t *prefix_ptr, uint32_t
service.P_on_mesh = true; service.P_on_mesh = true;
service.stableData = stableData; service.stableData = stableData;
//SET Timeout
DHCPv6_server_service_set_address_validlifetime(interface_id, prefix_ptr, THREAD_MIN_PREFIX_LIFETIME);
// SET maximum number of accepted clients // SET maximum number of accepted clients
DHCPv6_server_service_set_max_clients_accepts_count(interface_id, prefix_ptr, max_client_cnt); DHCPv6_server_service_set_max_clients_accepts_count(interface_id, prefix_ptr, max_client_cnt);
//Enable Mapping
//DHCPv6_server_service_set_gua_address_mapping(interface_id,prefix_ptr, true, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix);
tr_debug("GUA server Generate OK"); tr_debug("GUA server Generate OK");
memcpy(ptr, prefix_ptr, 8); memcpy(ptr, prefix_ptr, 8);
memset(ptr + 8, 0, 8); memset(ptr + 8, 0, 8);
@ -665,7 +660,7 @@ int thread_dhcpv6_server_add(int8_t interface_id, uint8_t *prefix_ptr, uint32_t
int thread_dhcpv6_server_set_lifetime(int8_t interface_id, uint8_t *prefix_ptr, uint32_t valid_lifetime) int thread_dhcpv6_server_set_lifetime(int8_t interface_id, uint8_t *prefix_ptr, uint32_t valid_lifetime)
{ {
#ifdef HAVE_DHCPV6_SERVER #if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER)
if (!prefix_ptr) { if (!prefix_ptr) {
return -1; return -1;
} }
@ -681,7 +676,7 @@ int thread_dhcpv6_server_set_lifetime(int8_t interface_id, uint8_t *prefix_ptr,
int thread_dhcpv6_server_set_max_client(int8_t interface_id, uint8_t *prefix_ptr, uint32_t max_client_count) int thread_dhcpv6_server_set_max_client(int8_t interface_id, uint8_t *prefix_ptr, uint32_t max_client_count)
{ {
#ifdef HAVE_DHCPV6_SERVER #if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER)
if (!prefix_ptr) { if (!prefix_ptr) {
return -1; return -1;
} }
@ -697,7 +692,7 @@ int thread_dhcpv6_server_set_max_client(int8_t interface_id, uint8_t *prefix_ptr
int thread_dhcpv6_server_set_anonymous_addressing(int8_t interface_id, uint8_t *prefix_ptr, bool anonymous) int thread_dhcpv6_server_set_anonymous_addressing(int8_t interface_id, uint8_t *prefix_ptr, bool anonymous)
{ {
#ifdef HAVE_DHCPV6_SERVER #if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER)
if (!prefix_ptr) { if (!prefix_ptr) {
return -1; return -1;
} }
@ -715,7 +710,7 @@ int thread_dhcpv6_server_set_anonymous_addressing(int8_t interface_id, uint8_t *
int thread_dhcpv6_server_delete(int8_t interface_id, uint8_t *prefix_ptr) int thread_dhcpv6_server_delete(int8_t interface_id, uint8_t *prefix_ptr)
{ {
#ifdef HAVE_DHCPV6_SERVER #if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER)
uint8_t temp[16]; uint8_t temp[16];
protocol_interface_info_entry_t *cur; protocol_interface_info_entry_t *cur;
thread_prefix_tlv_t prefixTlv; thread_prefix_tlv_t prefixTlv;

View File

@ -100,6 +100,9 @@ typedef struct announce {
typedef struct thread_management_server { typedef struct thread_management_server {
scan_query_t *scan_ptr; scan_query_t *scan_ptr;
announce_t *announce_ptr; announce_t *announce_ptr;
timeout_t *join_ent_timer;
uint8_t destination_address[16];
uint8_t one_time_key[16];
uint16_t relay_port_joiner; uint16_t relay_port_joiner;
uint16_t external_commissioner_port; uint16_t external_commissioner_port;
int8_t interface_id; int8_t interface_id;
@ -994,7 +997,6 @@ error_exit:
return -1; return -1;
} }
static void thread_announce_timeout_cb(void* arg) static void thread_announce_timeout_cb(void* arg)
{ {
link_configuration_s *linkConfiguration; link_configuration_s *linkConfiguration;
@ -1132,6 +1134,9 @@ int thread_management_server_init(int8_t interface_id)
this->relay_port_joiner = 0; this->relay_port_joiner = 0;
this->scan_ptr = NULL; this->scan_ptr = NULL;
this->announce_ptr = NULL; this->announce_ptr = NULL;
this->join_ent_timer = NULL;
memset(this->destination_address,0,16);
memset(this->one_time_key,0,16);
this->external_commissioner_port = THREAD_COMMISSIONING_PORT; this->external_commissioner_port = THREAD_COMMISSIONING_PORT;
#ifdef HAVE_THREAD_ROUTER #ifdef HAVE_THREAD_ROUTER
@ -1147,13 +1152,13 @@ int thread_management_server_init(int8_t interface_id)
#endif #endif
this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL);
if (this->coap_service_id < 0) { if (this->coap_service_id < 0) {
tr_warn("Thread management init failed"); tr_error("Thread management init failed");
ns_dyn_mem_free(this); ns_dyn_mem_free(this);
return -3; return -3;
} }
#ifdef HAVE_THREAD_ROUTER #ifdef HAVE_THREAD_ROUTER
if (thread_leader_service_init(interface_id, this->coap_service_id) != 0) { if (thread_leader_service_init(interface_id, this->coap_service_id) != 0) {
tr_warn("Thread leader service init failed"); tr_error("Thread leader service init failed");
ns_dyn_mem_free(this); ns_dyn_mem_free(this);
return -3; return -3;
} }
@ -1191,6 +1196,7 @@ void thread_management_server_delete(int8_t interface_id)
coap_service_unregister_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_GET); coap_service_unregister_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_GET);
coap_service_unregister_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_SET); coap_service_unregister_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_SET);
coap_service_delete(this->coap_service_id); coap_service_delete(this->coap_service_id);
ns_list_remove(&instance_list, this); ns_list_remove(&instance_list, this);
if (this->announce_ptr) { if (this->announce_ptr) {
if (this->announce_ptr->timer) { if (this->announce_ptr->timer) {
@ -1215,6 +1221,15 @@ void thread_management_server_delete(int8_t interface_id)
return; return;
} }
int8_t thread_management_server_service_id_get(int8_t interface_id)
{
thread_management_server_t *this = thread_management_server_find(interface_id);
if (!this) {
return -1;
}
return this->coap_service_id;
}
int8_t thread_management_server_interface_id_get(int8_t coap_service_id) int8_t thread_management_server_interface_id_get(int8_t coap_service_id)
{ {
thread_management_server_t *this = thread_management_find_by_service(coap_service_id); thread_management_server_t *this = thread_management_find_by_service(coap_service_id);
@ -1312,6 +1327,19 @@ static int thread_management_server_entrust_send(thread_management_server_t *thi
ns_dyn_mem_free(response_ptr); ns_dyn_mem_free(response_ptr);
return 0; return 0;
} }
static void thread_join_ent_timeout_cb(void *arg)
{
thread_management_server_t *this = arg;
if(!this || !this->join_ent_timer) {
return;
}
this->join_ent_timer = NULL;
thread_management_server_entrust_send(this, this->destination_address, this->one_time_key);
return;
}
void joiner_router_recv_commission_msg(void *cb_res) void joiner_router_recv_commission_msg(void *cb_res)
{ {
socket_callback_t *sckt_data = 0; socket_callback_t *sckt_data = 0;
@ -1412,7 +1440,13 @@ static int thread_management_server_relay_tx_cb(int8_t service_id, uint8_t sourc
if (0 < thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_ROUTER_KEK, &kek_ptr)) { if (0 < thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_ROUTER_KEK, &kek_ptr)) {
// KEK present in relay set pairwise key and send entrust // KEK present in relay set pairwise key and send entrust
tr_debug("Kek received"); tr_debug("Kek received");
thread_management_server_entrust_send(this, destination_address.address, kek_ptr); if (this->join_ent_timer) {
eventOS_timeout_cancel(this->join_ent_timer);
thread_management_server_entrust_send(this, this->destination_address, this->one_time_key);
}
memcpy(this->destination_address, destination_address.address, 16);
memcpy(this->one_time_key, kek_ptr, 16);
this->join_ent_timer = eventOS_timeout_ms(thread_join_ent_timeout_cb, THREAD_DELAY_JOIN_ENT, this);
} }
tr_debug("Relay TX sendto addr:%s port:%d, length:%d", trace_ipv6(destination_address.address), port, udp_data_len); tr_debug("Relay TX sendto addr:%s port:%d, length:%d", trace_ipv6(destination_address.address), port, udp_data_len);
thci_trace("joinerrouterJoinerDataRelayedOutbound"); thci_trace("joinerrouterJoinerDataRelayedOutbound");

View File

@ -99,6 +99,13 @@ int thread_management_server_joiner_router_init(int8_t interface_id);
* *
*/ */
void thread_management_server_joiner_router_deinit(int8_t interface_id); void thread_management_server_joiner_router_deinit(int8_t interface_id);
/** Get service id of management service.
*
* When using Coap Management port service this service is the only instance used to make client transactions.
*/
int8_t thread_management_server_service_id_get(int8_t interface_id);
int8_t thread_management_server_interface_id_get(int8_t coap_service_id); int8_t thread_management_server_interface_id_get(int8_t coap_service_id);
int thread_management_server_commisoner_data_get(int8_t interface_id, thread_management_server_data_t *server_data); int thread_management_server_commisoner_data_get(int8_t interface_id, thread_management_server_data_t *server_data);

View File

@ -30,6 +30,7 @@
#ifdef HAVE_THREAD #ifdef HAVE_THREAD
#include "ns_trace.h" #include "ns_trace.h"
#include "string.h"
#include "common_functions.h" #include "common_functions.h"
#include "NWK_INTERFACE/Include/protocol.h" #include "NWK_INTERFACE/Include/protocol.h"
#include <nsdynmemLIB.h> #include <nsdynmemLIB.h>
@ -53,6 +54,7 @@
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#include "6LoWPAN/MAC/mac_helper.h" #include "6LoWPAN/MAC/mac_helper.h"
#include "6LoWPAN/MAC/mac_data_poll.h" #include "6LoWPAN/MAC/mac_data_poll.h"
#include "Common_Protocols/ipv6.h"
#include "MLE/mle.h" #include "MLE/mle.h"
#include "mac_api.h" #include "mac_api.h"
#define TRACE_GROUP "thmh" #define TRACE_GROUP "thmh"
@ -699,6 +701,54 @@ static int thread_host_child_update_response_send(protocol_interface_info_entry_
return 0; return 0;
} }
static bool thread_address_registration_tlv_search(if_address_entry_t *entry, mle_tlv_info_t *tlv_info)
{
uint8_t context;
uint16_t length = tlv_info->tlvLen;
uint8_t *ptr = tlv_info->dataPtr;
while (length) {
context = *ptr++;
if (context & 0x80) {
if (memcmp(ptr, entry->address + 8, 8) == 0) {
return true;
}
ptr += 8;
length -= 9;
} else {
if (memcmp(ptr, entry->address, 16) == 0) {
return true;
}
ptr += 16;
length -= 17;
}
}
return false;
}
static bool thread_address_registration_tlv_check(protocol_interface_info_entry_t *cur, mle_tlv_info_t *tlv_info)
{
bool ret_val = true;
ns_list_foreach_safe(if_address_entry_t, e, &cur->ip_addresses) {
if (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_GLOBAL || (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_REALM_LOCAL &&
!thread_addr_is_mesh_local_16(e->address, cur))) {
if (thread_address_registration_tlv_search(e, tlv_info) == false) {
tr_debug("Address %s registration to parent failed", trace_ipv6(e->address));
addr_set_preferred_lifetime(cur, e, 0); // deprecate address
ret_val = false;
} else if (e->preferred_lifetime == 0) {
addr_set_preferred_lifetime(cur, e, 0xffffffff); // set preferred lifetime to infinite
}
}
}
return ret_val;
}
static void thread_host_child_update_request_process(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin) static void thread_host_child_update_request_process(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin)
{ {
thread_leader_data_t leaderData; thread_leader_data_t leaderData;
@ -710,6 +760,7 @@ static void thread_host_child_update_request_process(protocol_interface_info_ent
uint64_t pending_timestamp = 0;// means no pending timestamp uint64_t pending_timestamp = 0;// means no pending timestamp
mac_neighbor_table_entry_t *entry_temp; mac_neighbor_table_entry_t *entry_temp;
bool data_request_needed = false; bool data_request_needed = false;
mle_tlv_info_t tlv_info = {0};
tr_debug("Child update request"); tr_debug("Child update request");
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL); entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
@ -738,6 +789,11 @@ static void thread_host_child_update_request_process(protocol_interface_info_ent
thread_bootstrap_network_data_update(cur); thread_bootstrap_network_data_update(cur);
} }
// Check Address Registration TLV
if (true == mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &tlv_info)) {
thread_address_registration_tlv_check(cur, &tlv_info);
}
if (thread_info(cur)->thread_leader_data->stableDataVersion != leaderData.stableDataVersion || if (thread_info(cur)->thread_leader_data->stableDataVersion != leaderData.stableDataVersion ||
thread_info(cur)->thread_leader_data->dataVersion != leaderData.dataVersion) { thread_info(cur)->thread_leader_data->dataVersion != leaderData.dataVersion) {
// version numbers not in sync need to send data request // version numbers not in sync need to send data request
@ -776,6 +832,7 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t *
thread_leader_data_t leaderData = {0}; thread_leader_data_t leaderData = {0};
uint8_t status; uint8_t status;
bool leader_data_received; bool leader_data_received;
mle_tlv_info_t tlv_info = {0};
if (cur->thread_info->thread_endnode_parent == NULL) { if (cur->thread_info->thread_endnode_parent == NULL) {
return; return;
@ -822,6 +879,10 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t *
tr_debug("Setting child timeout, value=%"PRIu32, timeout); tr_debug("Setting child timeout, value=%"PRIu32, timeout);
} }
if (true == mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &tlv_info)) {
thread_address_registration_tlv_check(cur, &tlv_info);
}
tr_debug("Keep-Alive -->Respond from Parent"); tr_debug("Keep-Alive -->Respond from Parent");
mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, timeout); mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, timeout);

View File

@ -294,7 +294,7 @@ static void thread_nd_address_error(int8_t interface_id, const uint8_t ip_addr[1
if_address_entry_t *addr_entry = addr_get_entry(cur, ip_addr); if_address_entry_t *addr_entry = addr_get_entry(cur, ip_addr);
if (addr_entry && memcmp(ml_eid, cur->iid_slaac, 8)) { if (addr_entry && memcmp(ml_eid, cur->iid_slaac, 8)) {
addr_duplicate_detected(cur, ip_addr); addr_duplicate_detected(cur, ip_addr);
thread_extension_address_generate(cur); thread_extension_dua_address_generate(cur, ip_addr, 64);
} }
/* Scan IPv6 neighbour cache for registered entries of children */ /* Scan IPv6 neighbour cache for registered entries of children */
@ -547,8 +547,7 @@ int thread_nd_address_registration(protocol_interface_info_entry_t *cur, const u
} }
uint8_t *nce_eui64 = ipv6_neighbour_eui64(&cur->ipv6_neighbour_cache, neigh); uint8_t *nce_eui64 = ipv6_neighbour_eui64(&cur->ipv6_neighbour_cache, neigh);
if (neigh->state != IP_NEIGHBOUR_NEW && memcmp(nce_eui64, mac64, 8) != 0) if (neigh->type == IP_NEIGHBOUR_REGISTERED && memcmp(nce_eui64, mac64, 8) != 0) {
{
return -2; return -2;
} }

View File

@ -48,7 +48,7 @@
#include "6LoWPAN/Thread/thread_joiner_application.h" #include "6LoWPAN/Thread/thread_joiner_application.h"
#include "6LoWPAN/Thread/thread_network_data_lib.h" #include "6LoWPAN/Thread/thread_network_data_lib.h"
#include "6LoWPAN/Thread/thread_network_data_storage.h" #include "6LoWPAN/Thread/thread_network_data_storage.h"
#include "6LoWPAN/Thread/thread_dhcpv6_client.h" #include "DHCPv6_client/dhcpv6_client_api.h"
#include "6LoWPAN/MAC/mac_helper.h" #include "6LoWPAN/MAC/mac_helper.h"
#include "thread_management_if.h" #include "thread_management_if.h"
#include "thread_meshcop_lib.h" #include "thread_meshcop_lib.h"
@ -193,6 +193,7 @@ static uint16_t thread_nd_service_border_router_flags_read(thread_network_server
flags |= (cur->P_default_route << THREAD_P_DEF_ROUTE_BIT_MOVE); flags |= (cur->P_default_route << THREAD_P_DEF_ROUTE_BIT_MOVE);
flags |= (cur->P_on_mesh << THREAD_P_ON_MESH_BIT_MOVE); flags |= (cur->P_on_mesh << THREAD_P_ON_MESH_BIT_MOVE);
flags |= (cur->P_nd_dns << THREAD_P_ND_DNS_BIT_MOVE); flags |= (cur->P_nd_dns << THREAD_P_ND_DNS_BIT_MOVE);
flags |= (cur->P_res1 << THREAD_P_ND_RES_BIT_MOVE);
return flags; return flags;
} }
@ -872,6 +873,7 @@ static int thread_service_data_delete_mark_by_router_id(thread_network_data_serv
static int thread_server_context_clean(int8_t id, thread_network_data_cache_entry_t *cachePtr, thread_data_context_list_t *listPtr, thread_network_data_prefix_cache_entry_t *prefixEntry, lowpan_context_list_t *context_list) static int thread_server_context_clean(int8_t id, thread_network_data_cache_entry_t *cachePtr, thread_data_context_list_t *listPtr, thread_network_data_prefix_cache_entry_t *prefixEntry, lowpan_context_list_t *context_list)
{ {
(void) id;
int retVal = -1; int retVal = -1;
(void) prefixEntry; (void) prefixEntry;
ns_list_foreach_safe(thread_network_data_context_entry_t, cur, listPtr) { ns_list_foreach_safe(thread_network_data_context_entry_t, cur, listPtr) {
@ -881,9 +883,7 @@ static int thread_server_context_clean(int8_t id, thread_network_data_cache_entr
cachePtr->stableUpdatePushed = true; cachePtr->stableUpdatePushed = true;
} }
// Set context lifetime to 0 to delete // Set context lifetime to 0 to delete
if (thread_extension_context_can_delete(id, prefixEntry->servicesPrefix, cur->contextPrefixLength)) {
lowpan_context_update(context_list, cur->cid, 0, NULL, 0, true); lowpan_context_update(context_list, cur->cid, 0, NULL, 0, true);
}
ns_list_remove(listPtr, cur); ns_list_remove(listPtr, cur);
ns_dyn_mem_free(cur); ns_dyn_mem_free(cur);
retVal = 0; retVal = 0;
@ -930,11 +930,18 @@ static bool thread_server_data_clean_by_router_id(thread_network_data_cache_entr
if (cur->P_dhcp) { if (cur->P_dhcp) {
tr_debug("Delete DHCPv6 given address"); tr_debug("Delete DHCPv6 given address");
thread_dhcp_client_global_address_delete(curInterface->id, addr, prefixEntry->servicesPrefix); dhcp_client_global_address_delete(curInterface->id, addr, prefixEntry->servicesPrefix);
} else { }
if (cur->P_slaac) {
tr_debug("Delete SLAAC address"); tr_debug("Delete SLAAC address");
addr_delete_matching(curInterface, prefixEntry->servicesPrefix, 64, ADDR_SOURCE_SLAAC); addr_delete_matching(curInterface, prefixEntry->servicesPrefix, 64, ADDR_SOURCE_SLAAC);
} }
if (cur->P_res1) {
tr_debug("Delete thread domain address");
addr_delete_matching(curInterface, prefixEntry->servicesPrefix, 64, ADDR_SOURCE_THREAD_DOMAIN);
}
} }
ns_list_remove(listPtr, cur); ns_list_remove(listPtr, cur);
@ -995,7 +1002,7 @@ void thread_network_local_server_data_base_init(thread_network_local_data_cache_
ns_list_init(&cachePtr->service_list); ns_list_init(&cachePtr->service_list);
cachePtr->registered_rloc16 = 0xffff; cachePtr->registered_rloc16 = 0xffff;
cachePtr->release_old_address = false; cachePtr->release_old_address = false;
cachePtr->publish_active = false; cachePtr->publish_coap_req_id = 0;
cachePtr->publish_pending = false; cachePtr->publish_pending = false;
} }
@ -1077,6 +1084,7 @@ bool thread_network_data_router_id_free(thread_network_data_cache_entry_t *cache
void thread_network_data_context_re_use_timer_update(int8_t id, thread_network_data_cache_entry_t *cachePtr, uint32_t ticks, lowpan_context_list_t *context_list) void thread_network_data_context_re_use_timer_update(int8_t id, thread_network_data_cache_entry_t *cachePtr, uint32_t ticks, lowpan_context_list_t *context_list)
{ {
(void) id;
ns_list_foreach_safe(thread_network_data_prefix_cache_entry_t, cur, &cachePtr->localPrefixList) { ns_list_foreach_safe(thread_network_data_prefix_cache_entry_t, cur, &cachePtr->localPrefixList) {
ns_list_foreach_safe(thread_network_data_context_entry_t, curContext, &cur->contextList) { ns_list_foreach_safe(thread_network_data_context_entry_t, curContext, &cur->contextList) {
if (!curContext->compression) { if (!curContext->compression) {
@ -1090,9 +1098,7 @@ void thread_network_data_context_re_use_timer_update(int8_t id, thread_network_d
cachePtr->temporaryUpdatePushed = true; cachePtr->temporaryUpdatePushed = true;
} }
// Set context lifetime to 0 to delete // Set context lifetime to 0 to delete
if (thread_extension_context_can_delete(id, cur->servicesPrefix,curContext->contextPrefixLength)) {
lowpan_context_update(context_list, curContext->cid, 0, NULL, 0, true); lowpan_context_update(context_list, curContext->cid, 0, NULL, 0, true);
}
ns_dyn_mem_free(curContext); ns_dyn_mem_free(curContext);
} }
} }
@ -1162,7 +1168,7 @@ void thread_network_local_data_free_and_clean(thread_network_local_data_cache_en
} }
cachePtr->publish_pending = false; cachePtr->publish_pending = false;
cachePtr->publish_active = false; cachePtr->publish_coap_req_id = 0;
cachePtr->release_old_address = false; cachePtr->release_old_address = false;
} }
@ -1628,6 +1634,7 @@ int thread_nd_local_list_add_on_mesh_prefix(thread_network_data_cache_entry_t *n
server_entry->P_nd_dns = service->P_nd_dns; server_entry->P_nd_dns = service->P_nd_dns;
trigDataPropagate = true; trigDataPropagate = true;
} }
} }
if (trigDataPropagate) { if (trigDataPropagate) {
@ -1707,9 +1714,9 @@ int thread_nd_local_list_del_on_mesh_server(thread_network_data_cache_entry_t *n
int thread_local_server_list_add_on_mesh_server(thread_network_local_data_cache_entry_t *networkDataList, thread_prefix_tlv_t *prefixTlv, thread_border_router_tlv_entry_t *service) int thread_local_server_list_add_on_mesh_server(thread_network_local_data_cache_entry_t *networkDataList, thread_prefix_tlv_t *prefixTlv, thread_border_router_tlv_entry_t *service)
{ {
int retVal = -1; int retVal = -1;
tr_debug("Add prefix: %s prf:%d %s%s%s%s%s", trace_ipv6_prefix(prefixTlv->Prefix, prefixTlv->PrefixLen), service->Prf, tr_debug("Add prefix: %s prf:%d %s%s%s%s%s%s", trace_ipv6_prefix(prefixTlv->Prefix, prefixTlv->PrefixLen), service->Prf,
service->P_default_route?"Default Route ":"",service->P_dhcp?"DHCPv6 Server ":"", service->P_configure?"DHCPv6 Configuration ":"", service->P_default_route?"Default Route ":"",service->P_dhcp?"DHCPv6 Server ":"", service->P_configure?"DHCPv6 Configuration ":"",
service->P_slaac?"SLAAC ":"",service->P_preferred?"Preferred ":""); service->P_slaac?"SLAAC ":"",service->P_preferred?"Preferred ":"",service->P_res1?"P_res1 ":"");
if (networkDataList) { if (networkDataList) {
thread_network_local_data_entry_t *prefix_entry = thread_local_prefix_entry_get(&networkDataList->prefix_list, prefixTlv); thread_network_local_data_entry_t *prefix_entry = thread_local_prefix_entry_get(&networkDataList->prefix_list, prefixTlv);
@ -2341,7 +2348,9 @@ bool thread_nd_service_anycast_address_mapping_from_network_data(thread_network_
if (curService->S_id != S_id) { if (curService->S_id != S_id) {
continue; continue;
} }
ns_list_foreach(thread_network_data_service_server_entry_t, curServiceServer, &curService->server_list) { /* any server will do - take first from the list */
thread_network_data_service_server_entry_t *curServiceServer = ns_list_get_first(&curService->server_list);
if (curServiceServer) {
*rlocAddress = curServiceServer->router_id; *rlocAddress = curServiceServer->router_id;
return true; return true;
} }
@ -2352,7 +2361,7 @@ bool thread_nd_service_anycast_address_mapping_from_network_data(thread_network_
bool thread_nd_on_mesh_address_valid(thread_network_server_data_entry_t *curRoute) bool thread_nd_on_mesh_address_valid(thread_network_server_data_entry_t *curRoute)
{ {
bool onMeshActive = false; bool onMeshActive = false;
if (curRoute->P_dhcp || curRoute->P_slaac || curRoute->P_preferred) { if (curRoute->P_dhcp || curRoute->P_slaac || curRoute->P_preferred || curRoute->P_on_mesh) {
onMeshActive = true; onMeshActive = true;
} }

View File

@ -187,8 +187,8 @@ typedef struct thread_network_local_data_cache_entry_s {
thread_network_data_prefix_list_t prefix_list; /*!< Local parsed or generated service list */ thread_network_data_prefix_list_t prefix_list; /*!< Local parsed or generated service list */
thread_network_data_service_list_t service_list; thread_network_data_service_list_t service_list;
uint16_t registered_rloc16;/*!< Address used for latest registration */ uint16_t registered_rloc16;/*!< Address used for latest registration */
uint16_t publish_coap_req_id;/*!< Non-zero when publish is active */
bool release_old_address:1;/*!< true if network data can be released from old address */ bool release_old_address:1;/*!< true if network data can be released from old address */
bool publish_active:1;/*!< true when publish is active */
bool publish_pending:1;/*!< true when publish attempt made during active publish */ bool publish_pending:1;/*!< true when publish attempt made during active publish */
} thread_network_local_data_cache_entry_t; } thread_network_local_data_cache_entry_t;
@ -344,7 +344,7 @@ uint8_t *thread_network_data_prefix_set_write(thread_network_data_cache_entry_t
uint8_t *thread_network_data_service_set_write(thread_network_data_cache_entry_t *networkDataList, uint8_t *ptr); uint8_t *thread_network_data_service_set_write(thread_network_data_cache_entry_t *networkDataList, uint8_t *ptr);
bool thread_network_data_service_hosted_by_this_router_id(thread_network_data_service_cache_entry_t *dataList, uint16_t router_id); bool thread_network_data_service_hosted_by_this_router_id(thread_network_data_service_cache_entry_t *dataList, uint16_t router_id);
uint16_t thread_network_data_service_child_id_from_networkdata_get(thread_network_data_cache_entry_t *networkDataList, uint16_t router_short_addr); uint16_t thread_network_data_service_child_id_from_networkdata_get(thread_network_data_cache_entry_t *networkDataList, uint16_t router_short_addr);
thread_network_data_prefix_cache_entry_t *thread_prefix_entry_find(thread_network_prefix_list_t *list, thread_prefix_tlv_t *prefixTlv);
uint8_t * thread_nd_own_service_list_data_write(thread_network_local_data_cache_entry_t *serverDataList, uint8_t *ptr, uint16_t routerID); uint8_t * thread_nd_own_service_list_data_write(thread_network_local_data_cache_entry_t *serverDataList, uint8_t *ptr, uint16_t routerID);
uint16_t thread_nd_own_service_list_data_size(thread_network_local_data_cache_entry_t *serverDataList); uint16_t thread_nd_own_service_list_data_size(thread_network_local_data_cache_entry_t *serverDataList);

View File

@ -292,7 +292,11 @@ int thread_nvm_store_active_configuration_remove(void)
} }
char ac_data_path[ACTIVE_CONF_STRING_LEN]; char ac_data_path[ACTIVE_CONF_STRING_LEN];
thread_nvm_store_create_path(ac_data_path, THREAD_NVM_ACTIVE_CONF_FILE); thread_nvm_store_create_path(ac_data_path, THREAD_NVM_ACTIVE_CONF_FILE);
return remove(ac_data_path); int status = remove(ac_data_path);
if (status != 0) {
return THREAD_NVM_FILE_REMOVE_ERROR;
}
return THREAD_NVM_FILE_SUCCESS;
} }
int thread_nvm_store_pending_configuration_remove(void) int thread_nvm_store_pending_configuration_remove(void)
@ -302,7 +306,11 @@ int thread_nvm_store_pending_configuration_remove(void)
} }
char ac_data_path[PENDING_CONF_STRING_LEN]; char ac_data_path[PENDING_CONF_STRING_LEN];
thread_nvm_store_create_path(ac_data_path, THREAD_NVM_PENDING_CONF_FILE); thread_nvm_store_create_path(ac_data_path, THREAD_NVM_PENDING_CONF_FILE);
return remove(ac_data_path); int status = remove(ac_data_path);
if (status != 0) {
return THREAD_NVM_FILE_REMOVE_ERROR;
}
return THREAD_NVM_FILE_SUCCESS;
} }

View File

@ -39,6 +39,7 @@
#include "coap_service_api.h" #include "coap_service_api.h"
#include "thread_config.h" #include "thread_config.h"
#include "thread_management_server.h"
#include "thread_resolution_client.h" #include "thread_resolution_client.h"
#define TRACE_GROUP TRACE_GROUP_THREAD_RESOLUTION_CLIENT #define TRACE_GROUP TRACE_GROUP_THREAD_RESOLUTION_CLIENT
@ -294,7 +295,7 @@ void thread_resolution_client_init(int8_t interface_id)
this->error_cb_ptr = NULL; this->error_cb_ptr = NULL;
ns_list_init(&this->queries); ns_list_init(&this->queries);
//TODO: Check if to use ephemeral port here //TODO: Check if to use ephemeral port here
this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); this->coap_service_id = thread_management_server_service_id_get(interface_id);
ns_list_add_to_start(&instance_list, this); ns_list_add_to_start(&instance_list, this);
coap_service_register_uri(this->coap_service_id, THREAD_URI_ADDRESS_NOTIFICATION, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_resolution_client_notification_post_cb); coap_service_register_uri(this->coap_service_id, THREAD_URI_ADDRESS_NOTIFICATION, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_resolution_client_notification_post_cb);
@ -309,7 +310,7 @@ void thread_resolution_client_delete(int8_t interface_id)
} }
coap_service_unregister_uri(this->coap_service_id, THREAD_URI_ADDRESS_NOTIFICATION); coap_service_unregister_uri(this->coap_service_id, THREAD_URI_ADDRESS_NOTIFICATION);
coap_service_delete(this->coap_service_id); coap_service_unregister_uri(this->coap_service_id, THREAD_URI_ADDRESS_ERROR);
ns_list_foreach_safe(address_query_t, query, &this->queries) { ns_list_foreach_safe(address_query_t, query, &this->queries) {
ns_list_remove(&this->queries, query); ns_list_remove(&this->queries, query);
ns_dyn_mem_free(query); ns_dyn_mem_free(query);
@ -465,6 +466,7 @@ void thread_resolution_client_timer(int8_t interface_id, uint16_t seconds)
} }
} }
} }
} }
#endif // HAVE_THREAD_NEIGHBOR_DISCOVERY #endif // HAVE_THREAD_NEIGHBOR_DISCOVERY

View File

@ -47,6 +47,7 @@
#include "thread_config.h" #include "thread_config.h"
#include "thread_tmfcop_lib.h" #include "thread_tmfcop_lib.h"
#include "thread_management_if.h" #include "thread_management_if.h"
#include "thread_management_server.h"
#include "thread_commissioning_if.h" #include "thread_commissioning_if.h"
@ -170,9 +171,9 @@ int thread_resolution_server_init(int8_t interface_id, thread_resolution_server_
} }
this->interface_id = interface_id; this->interface_id = interface_id;
this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); this->coap_service_id = thread_management_server_service_id_get(interface_id);
if (this->coap_service_id < 0) { if (this->coap_service_id < 0) {
tr_warn("Thread resolution init failed"); tr_warn("Thread resolution srv init failed");
ns_dyn_mem_free(this); ns_dyn_mem_free(this);
return -3; return -3;
} }
@ -193,7 +194,6 @@ void thread_resolution_server_delete(int8_t interface_id)
coap_service_unregister_uri(this->coap_service_id, THREAD_URI_ADDRESS_QUERY_REQUEST); coap_service_unregister_uri(this->coap_service_id, THREAD_URI_ADDRESS_QUERY_REQUEST);
coap_service_delete(this->coap_service_id);
ns_list_remove(&instance_list, this); ns_list_remove(&instance_list, this);
ns_dyn_mem_free(this); ns_dyn_mem_free(this);
} }

View File

@ -78,7 +78,7 @@
#include "Service_Libs/nd_proxy/nd_proxy.h" #include "Service_Libs/nd_proxy/nd_proxy.h"
#include "Service_Libs/mle_service/mle_service_api.h" #include "Service_Libs/mle_service/mle_service_api.h"
#include "Service_Libs/blacklist/blacklist.h" #include "Service_Libs/blacklist/blacklist.h"
#include "thread_dhcpv6_client.h" #include "DHCPv6_client/dhcpv6_client_api.h"
#include "6LoWPAN/MAC/mac_helper.h" #include "6LoWPAN/MAC/mac_helper.h"
#include "mac_api.h" #include "mac_api.h"
#include "6LoWPAN/MAC/mac_data_poll.h" #include "6LoWPAN/MAC/mac_data_poll.h"
@ -1027,10 +1027,10 @@ static void thread_bootstrap_client_router_id_cb(int8_t interface_id, int8_t sta
if (!cur) { if (!cur) {
return; return;
} }
if (!cur->thread_info->routerIdReqCoapID) { if (!cur->thread_info->routerIdRequested) {
return; return;
} }
cur->thread_info->routerIdReqCoapID = 0; cur->thread_info->routerIdRequested = false;
if (cur->thread_info->thread_device_mode != THREAD_DEVICE_MODE_ROUTER || if (cur->thread_info->thread_device_mode != THREAD_DEVICE_MODE_ROUTER ||
cur->thread_info->leader_private_data ) { cur->thread_info->leader_private_data ) {
@ -1088,15 +1088,15 @@ void thread_router_bootstrap_router_id_request(protocol_interface_info_entry_t *
{ {
int router_id_req_status; int router_id_req_status;
tr_debug("Router ID Request"); tr_debug("Router ID Request");
if (cur->thread_info->routerIdReqCoapID) { if (cur->thread_info->routerIdRequested) {
tr_warn("Router ID already requested"); tr_warn("Router ID already requested");
return; return;
} }
router_id_req_status = thread_management_client_router_id_get(cur->id, cur->mac, cur->thread_info->routerShortAddress, thread_bootstrap_client_router_id_cb, status); router_id_req_status = thread_management_client_router_id_get(cur->id, cur->mac, cur->thread_info->routerShortAddress, thread_bootstrap_client_router_id_cb, status);
tr_debug("Coap address req, ID=%d", router_id_req_status); tr_debug("RouterIDReq COAP ID=%d", router_id_req_status);
if (router_id_req_status > 0) { if (router_id_req_status > 0) {
cur->thread_info->routerIdReqCoapID = (uint16_t)router_id_req_status; cur->thread_info->routerIdRequested = true;
} }
} }
@ -1196,6 +1196,32 @@ static int mle_attach_child_id_response_build(protocol_interface_info_entry_t *c
} }
int thread_router_bootstrap_child_max_timeout_get(protocol_interface_info_entry_t *cur, uint32_t *max_child_timeout)
{
uint16_t router_address = thread_info(cur)->routerShortAddress;
uint32_t max_timeout = 0;
if (router_address >= 0xfffe) {
router_address = mac_helper_mac16_address_get(cur);
}
if (router_address & THREAD_CHILD_MASK) {
return -1; //I am child
}
if (router_address >= 0xfffe) {
return -1;
}
mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, mac_table_list) {
if (thread_router_addr_from_addr(cur_entry->mac16) == router_address &&
!cur_entry->ffd_device && cur_entry->lifetime > max_timeout) {
max_timeout = cur_entry->lifetime;
}
}
*max_child_timeout = max_timeout;
return 0;
}
uint16_t thread_router_bootstrap_child_count_get(protocol_interface_info_entry_t *cur) uint16_t thread_router_bootstrap_child_count_get(protocol_interface_info_entry_t *cur)
{ {
uint16_t child_count = 0; uint16_t child_count = 0;
@ -1277,7 +1303,7 @@ void thread_router_bootstrap_child_id_handler(protocol_interface_info_entry_t *c
bool new_neigbour = false; bool new_neigbour = false;
if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED) { if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED) {
if (!cur->thread_info->routerIdReqCoapID) { if (!cur->thread_info->routerIdRequested) {
tr_info("Upgrade REED to Router"); tr_info("Upgrade REED to Router");
thread_router_bootstrap_router_id_request(cur, THREAD_COAP_STATUS_TLV_HAVE_CHILD_ID_REQUEST); thread_router_bootstrap_router_id_request(cur, THREAD_COAP_STATUS_TLV_HAVE_CHILD_ID_REQUEST);
} }
@ -1366,7 +1392,7 @@ static void thread_address_registration_tlv_parse(uint8_t *ptr, uint16_t data_le
uint8_t tempIPv6Address[16]; uint8_t tempIPv6Address[16];
uint8_t ctxId; uint8_t ctxId;
bool new_neighbour_created; bool new_neighbour_created;
thread_child_mcast_entries_remove(cur,mac64);
while (data_length) { while (data_length) {
//Read //Read
ctxId = *ptr++; ctxId = *ptr++;
@ -1389,8 +1415,8 @@ static void thread_address_registration_tlv_parse(uint8_t *ptr, uint16_t data_le
tr_debug("Register %s", trace_ipv6(ptr)); tr_debug("Register %s", trace_ipv6(ptr));
if (addr_is_ipv6_multicast(ptr)) { if (addr_is_ipv6_multicast(ptr)) {
// Register multicast address (higher scope than link-local) // Register multicast address (link-local & higher)
if (addr_ipv6_multicast_scope(ptr) > IPV6_SCOPE_LINK_LOCAL) { if (addr_ipv6_multicast_scope(ptr) >= IPV6_SCOPE_LINK_LOCAL) {
addr_add_group(cur, ptr); addr_add_group(cur, ptr);
if (thread_child_mcast_entry_get(cur, ptr, mac64)) { if (thread_child_mcast_entry_get(cur, ptr, mac64)) {
tr_debug("Added sleepy multicast registration entry."); tr_debug("Added sleepy multicast registration entry.");
@ -1665,6 +1691,11 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
} }
} }
if (!(id_req->mode & MLE_FFD_DEV) && addressRegisteredTlv.tlvLen == 0) {
tr_debug("No address registration TLV in MTD child id request");
thread_child_id_request_entry_remove(cur, id_req);
return;
}
id_req->keyId = security_headers->KeyIndex; id_req->keyId = security_headers->KeyIndex;
id_req->keySeq = common_read_32_bit(security_headers->Keysource); id_req->keySeq = common_read_32_bit(security_headers->Keysource);
@ -1991,10 +2022,22 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
if (!entry_temp || !mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &requestTlv)) { if (!entry_temp || !mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &requestTlv)) {
return; return;
} }
uint8_t mode = mle_mode_write_from_mac_entry(entry_temp);
/* check if thread neighbor class is not initialized */
if ((thread_neighbor_entry_linkmargin_get(&cur->thread_info->neighbor_class, entry_temp->index) == 0) &&
(thread_neighbor_last_communication_time_get(&cur->thread_info->neighbor_class, entry_temp->index) == 0)) {
/*
* Thread neighbor class is not yet initialized and we receive data_request from such child.
* Always send full network data in this case
*/
mode |= MLE_THREAD_REQ_FULL_DATA_SET | MLE_THREAD_SECURED_DATA_REQUEST;
} else {
mode |= thread_neighbor_class_mode_write_from_entry(&cur->thread_info->neighbor_class, entry_temp->index);
}
thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index,linkMargin, false); thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index,linkMargin, false);
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index); thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index);
uint8_t mode = mle_mode_write_from_mac_entry(entry_temp);
mode |= thread_neighbor_class_mode_write_from_entry(&cur->thread_info->neighbor_class, entry_temp->index);
mle_build_and_send_data_response_msg(cur, mle_msg->packet_src_address, mle_msg->data_ptr, mle_msg->data_length, &requestTlv, mode); mle_build_and_send_data_response_msg(cur, mle_msg->packet_src_address, mle_msg->data_ptr, mle_msg->data_length, &requestTlv, mode);
} }
break; break;
@ -2026,8 +2069,9 @@ static int8_t thread_router_bootstrap_synch_request_send(protocol_interface_info
tr_debug("Buffer overflow at message write"); tr_debug("Buffer overflow at message write");
} }
timeout.retrans_max = THREAD_REQUEST_MAX_RETRY_CNT; // timeout set to two seconds, no retries
timeout.timeout_init = 1; timeout.retrans_max = 1;
timeout.timeout_init = 2;
timeout.timeout_max = 3; timeout.timeout_max = 3;
timeout.delay = MLE_NO_DELAY; timeout.delay = MLE_NO_DELAY;
@ -2325,7 +2369,6 @@ static uint32_t thread_reed_timeout_calculate(thread_router_select_t *routerSele
static int thread_reed_advertise (protocol_interface_info_entry_t *cur) static int thread_reed_advertise (protocol_interface_info_entry_t *cur)
{ {
uint32_t keySequence; uint32_t keySequence;
tr_debug("MLE REED ADVERTISEMENT STARTED");
struct link_configuration *linkConfiguration; struct link_configuration *linkConfiguration;
linkConfiguration = thread_joiner_application_get_config(cur->id); linkConfiguration = thread_joiner_application_get_config(cur->id);
if (!linkConfiguration) { if (!linkConfiguration) {
@ -2336,11 +2379,17 @@ static int thread_reed_advertise (protocol_interface_info_entry_t *cur)
return -1; return -1;
} }
// FED not allowed to send advertisements
if (thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE) {
return -1;
}
uint16_t bufId = mle_service_msg_allocate(cur->id, 16, false, MLE_COMMAND_ADVERTISEMENT); uint16_t bufId = mle_service_msg_allocate(cur->id, 16, false, MLE_COMMAND_ADVERTISEMENT);
if (bufId == 0) { if (bufId == 0) {
return -1; return -1;
} }
tr_debug("MLE REED ADVERTISEMENT STARTED");
thread_management_get_current_keysequence(cur->id, &keySequence); thread_management_get_current_keysequence(cur->id, &keySequence);
mle_service_msg_update_security_params(bufId, 5, 2, keySequence); mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
@ -2734,4 +2783,18 @@ void thread_router_bootstrap_address_change_notify_send(protocol_interface_info_
thread_info(cur)->proactive_an_timer = THREAD_PROACTIVE_AN_SEND_DELAY; thread_info(cur)->proactive_an_timer = THREAD_PROACTIVE_AN_SEND_DELAY;
} }
void thread_router_bootstrap_delay_reed_jitter(int8_t interface_id, uint16_t delay)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur) {
return;
}
if (cur->thread_info->thread_device_mode != THREAD_DEVICE_MODE_ROUTER) {
return;
}
// delay reed jitter timer to allow for settings changes to distribute
thread_info(cur)->reedJitterTimer += delay;
return;
}
#endif /* HAVE_THREAD_ROUTER */ #endif /* HAVE_THREAD_ROUTER */

View File

@ -52,6 +52,9 @@ int thread_router_bootstrap_mle_advertise(struct protocol_interface_info_entry *
void thread_router_bootstrap_child_information_clear(protocol_interface_info_entry_t *cur); void thread_router_bootstrap_child_information_clear(protocol_interface_info_entry_t *cur);
int thread_router_bootstrap_reset_child_info(protocol_interface_info_entry_t *cur, struct mac_neighbor_table_entry *child); int thread_router_bootstrap_reset_child_info(protocol_interface_info_entry_t *cur, struct mac_neighbor_table_entry *child);
uint16_t thread_router_bootstrap_child_count_get(protocol_interface_info_entry_t *cur); uint16_t thread_router_bootstrap_child_count_get(protocol_interface_info_entry_t *cur);
// max_child_timeout is longest MLE Timeout a router has registered for all of its active MTD children
int thread_router_bootstrap_child_max_timeout_get(protocol_interface_info_entry_t *cur, uint32_t *max_child_timeout);
void thread_router_bootstrap_child_id_handler(struct protocol_interface_info_entry *cur); void thread_router_bootstrap_child_id_handler(struct protocol_interface_info_entry *cur);
void thread_router_bootstrap_child_id_reject(struct protocol_interface_info_entry *cur); void thread_router_bootstrap_child_id_reject(struct protocol_interface_info_entry *cur);
void thread_router_bootstrap_router_id_request(struct protocol_interface_info_entry *cur, uint8_t status); void thread_router_bootstrap_router_id_request(struct protocol_interface_info_entry *cur, uint8_t status);
@ -73,6 +76,7 @@ void thread_router_bootstrap_anycast_address_register(protocol_interface_info_en
void thread_router_bootstrap_network_data_distribute(protocol_interface_info_entry_t *cur); void thread_router_bootstrap_network_data_distribute(protocol_interface_info_entry_t *cur);
bool thread_router_bootstrap_routing_allowed(struct protocol_interface_info_entry *cur); bool thread_router_bootstrap_routing_allowed(struct protocol_interface_info_entry *cur);
void thread_router_bootstrap_address_change_notify_send(protocol_interface_info_entry_t *cur); void thread_router_bootstrap_address_change_notify_send(protocol_interface_info_entry_t *cur);
void thread_router_bootstrap_delay_reed_jitter(int8_t interface_id, uint16_t delay);
#else #else
@ -81,6 +85,7 @@ void thread_router_bootstrap_address_change_notify_send(protocol_interface_info_
#define thread_router_bootstrap_child_information_clear(cur) #define thread_router_bootstrap_child_information_clear(cur)
#define thread_router_bootstrap_child_count_get(cur) 0 #define thread_router_bootstrap_child_count_get(cur) 0
#define thread_router_bootstrap_child_max_timeout_get(cur, max_child_timeout) 0
#define thread_router_bootstrap_child_id_handler(cur) #define thread_router_bootstrap_child_id_handler(cur)
#define thread_router_bootstrap_child_id_reject(cur) #define thread_router_bootstrap_child_id_reject(cur)
#define thread_router_bootstrap_router_id_request(cur, status) #define thread_router_bootstrap_router_id_request(cur, status)
@ -104,7 +109,7 @@ void thread_router_bootstrap_address_change_notify_send(protocol_interface_info_
#define thread_router_bootstrap_routing_allowed(cur) false #define thread_router_bootstrap_routing_allowed(cur) false
#define thread_router_bootstrap_address_change_notify_send(cur) #define thread_router_bootstrap_address_change_notify_send(cur)
#define thread_router_bootstrap_reed_merge_advertisement(cur) #define thread_router_bootstrap_reed_merge_advertisement(cur)
#define thread_router_bootstrap_delay_reed_jitter(interface_id, delay)
#endif/*HAVE_THREAD_ROUTER*/ #endif/*HAVE_THREAD_ROUTER*/
#endif /* THREAD_ROUTER_BOOTSTRAP_H_ */ #endif /* THREAD_ROUTER_BOOTSTRAP_H_ */

View File

@ -43,7 +43,6 @@
#ifdef HAVE_RPL #ifdef HAVE_RPL
#include "RPL/rpl_data.h" #include "RPL/rpl_data.h"
#endif #endif
#include "6LoWPAN/ws/ws_common.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#include "6LoWPAN/Thread/thread_common.h" #include "6LoWPAN/Thread/thread_common.h"
#include "6LoWPAN/ws/ws_common.h" #include "6LoWPAN/ws/ws_common.h"
@ -72,7 +71,7 @@ typedef struct {
bool fragmented_data:1; bool fragmented_data:1;
bool first_fragment:1; bool first_fragment:1;
bool indirect_data:1; bool indirect_data:1;
bool indirect_data_cached:1; /* Data cached for delayed transmission as mac request is already active */ bool indirect_data_cached:1; /*!< Data cached for delayed transmission as mac request is already active */
buffer_t *buf; buffer_t *buf;
uint8_t *fragmenter_buf; uint8_t *fragmenter_buf;
ns_list_link_t link; /*!< List link entry */ ns_list_link_t link; /*!< List link entry */
@ -132,7 +131,7 @@ static bool lowpan_adaptation_tx_process_ready(fragmenter_tx_entry_t *tx_ptr);
/* Fragmentation local functions */ /* Fragmentation local functions */
static int8_t lowpan_message_fragmentation_init(buffer_t *buf, fragmenter_tx_entry_t *frag_entry, protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr); static int8_t lowpan_message_fragmentation_init(buffer_t *buf, fragmenter_tx_entry_t *frag_entry, protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr);
static bool lowpan_message_fragmentation_message_write(const fragmenter_tx_entry_t *frag_entry, mcps_data_req_t *dataReq); static bool lowpan_message_fragmentation_message_write(const fragmenter_tx_entry_t *frag_entry, mcps_data_req_t *dataReq);
static void lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr); static bool lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr);
static fragmenter_tx_entry_t* lowpan_adaptation_indirect_mac_data_request_active(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr); static fragmenter_tx_entry_t* lowpan_adaptation_indirect_mac_data_request_active(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr);
@ -613,18 +612,21 @@ buffer_t * lowpan_adaptation_data_process_tx_preprocess(protocol_interface_info_
{ {
mac_neighbor_table_entry_t *neigh_entry_ptr = NULL; mac_neighbor_table_entry_t *neigh_entry_ptr = NULL;
//Validate is link known and set indirect, datareq and security key id mode //Validate is link known and set indirect, datareq and security key id mode
if (buf->dst_sa.addr_type == ADDR_NONE) { if (buf->dst_sa.addr_type == ADDR_NONE) {
goto tx_error_handler; goto tx_error_handler;
} }
/* If MLE is enabled, we will talk if we have an MLE association */ if (addr_check_broadcast(buf->dst_sa.address, buf->dst_sa.addr_type) == eOK ) {
if (buf->dst_sa.addr_type == ADDR_802_15_4_LONG ) { buf->dst_sa.addr_type = ADDR_802_15_4_SHORT;
neigh_entry_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), buf->dst_sa.address + 2, buf->dst_sa.addr_type); buf->dst_sa.address[2] = 0xff;
buf->dst_sa.address[3] = 0xff;
buf->link_specific.ieee802_15_4.indirectTxProcess = false;
buf->link_specific.ieee802_15_4.requestAck = false;
} else {
} else if(buf->dst_sa.addr_type == ADDR_802_15_4_SHORT && (common_read_16_bit(buf->dst_sa.address + 2)) != 0xffff) {
neigh_entry_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), buf->dst_sa.address + 2, buf->dst_sa.addr_type); neigh_entry_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), buf->dst_sa.address + 2, buf->dst_sa.addr_type);
}
//Validate neighbour //Validate neighbour
if (!buf->options.ll_security_bypass_tx && neigh_entry_ptr) { if (!buf->options.ll_security_bypass_tx && neigh_entry_ptr) {
@ -635,18 +637,10 @@ buffer_t * lowpan_adaptation_data_process_tx_preprocess(protocol_interface_info_
//tr_warn("Drop TX to unassociated %s", trace_sockaddr(&buf->dst_sa, true)); //tr_warn("Drop TX to unassociated %s", trace_sockaddr(&buf->dst_sa, true));
goto tx_error_handler; goto tx_error_handler;
} }
} else if (ws_info(cur) && !neigh_entry_ptr) {
//Do not accept to send unknow device
goto tx_error_handler;
} }
//Check indirect
if (addr_check_broadcast(buf->dst_sa.address, buf->dst_sa.addr_type) == eOK) {
buf->dst_sa.addr_type = ADDR_802_15_4_SHORT;
buf->dst_sa.address[2] = 0xff;
buf->dst_sa.address[3] = 0xff;
buf->link_specific.ieee802_15_4.indirectTxProcess = false;
buf->link_specific.ieee802_15_4.requestAck = false;
} else {
buf->link_specific.ieee802_15_4.requestAck = true; buf->link_specific.ieee802_15_4.requestAck = true;
buf->link_specific.ieee802_15_4.indirectTxProcess = lowpan_adaptation_indirect_data_request(neigh_entry_ptr); buf->link_specific.ieee802_15_4.indirectTxProcess = lowpan_adaptation_indirect_data_request(neigh_entry_ptr);
} }
@ -755,7 +749,7 @@ static bool lowpan_adaptation_indirect_cache_trigger(protocol_interface_info_ent
ns_list_foreach(fragmenter_tx_entry_t, fragmenter_tx_entry, &interface_ptr->indirect_tx_queue) { ns_list_foreach(fragmenter_tx_entry_t, fragmenter_tx_entry, &interface_ptr->indirect_tx_queue) {
if (fragmenter_tx_entry->indirect_data_cached) { if (fragmenter_tx_entry->indirect_data_cached) {
if (addr_ipv6_equal(tx_ptr->buf->dst_sa.address, fragmenter_tx_entry->buf->dst_sa.address)) { if (addr_ipv6_equal(tx_ptr->buf->dst_sa.address, fragmenter_tx_entry->buf->dst_sa.address)) {
tr_debug_extra("pushing seq %d to addr %s", fragmenter_tx_entry->buf->seq, trace_ipv6(fragmenter_tx_entry->buf->dst_sa.address)); tr_debug_extra("Pushing seq %d to addr %s", fragmenter_tx_entry->buf->seq, trace_ipv6(fragmenter_tx_entry->buf->dst_sa.address));
fragmenter_tx_entry->indirect_data_cached = false; fragmenter_tx_entry->indirect_data_cached = false;
lowpan_data_request_to_mac(cur, fragmenter_tx_entry->buf, fragmenter_tx_entry, interface_ptr); lowpan_data_request_to_mac(cur, fragmenter_tx_entry->buf, fragmenter_tx_entry, interface_ptr);
return true; return true;
@ -805,7 +799,12 @@ static void lowpan_adaptation_make_room_for_small_packet(protocol_interface_info
mac_neighbor_table_entry_t *tx_neighbour = mac_neighbor_table_address_discover(mac_neighbor_info(cur), tx_entry->buf->dst_sa.address + 2, tx_entry->buf->dst_sa.addr_type); mac_neighbor_table_entry_t *tx_neighbour = mac_neighbor_table_address_discover(mac_neighbor_info(cur), tx_entry->buf->dst_sa.address + 2, tx_entry->buf->dst_sa.addr_type);
if (tx_neighbour == neighbour_to_count && buffer_data_length(tx_entry->buf) <= interface_ptr->indirect_big_packet_threshold) { if (tx_neighbour == neighbour_to_count && buffer_data_length(tx_entry->buf) <= interface_ptr->indirect_big_packet_threshold) {
if (++count >= interface_ptr->max_indirect_small_packets_per_child) { if (++count >= interface_ptr->max_indirect_small_packets_per_child) {
lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry); tr_debug_extra("Purge seq: %d", tx_entry->buf->seq);
if (lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry) == false) {
/* entry could not be purged from mac, try next entry */
tr_debug_extra("Purge failed, try next");
count--;
}
} }
} }
} }
@ -822,8 +821,12 @@ static void lowpan_adaptation_make_room_for_big_packet(struct protocol_interface
ns_list_foreach_reverse_safe(fragmenter_tx_entry_t, tx_entry, &interface_ptr->indirect_tx_queue) { ns_list_foreach_reverse_safe(fragmenter_tx_entry_t, tx_entry, &interface_ptr->indirect_tx_queue) {
if (buffer_data_length(tx_entry->buf) > interface_ptr->indirect_big_packet_threshold) { if (buffer_data_length(tx_entry->buf) > interface_ptr->indirect_big_packet_threshold) {
if (++count >= interface_ptr->max_indirect_big_packets_total) { if (++count >= interface_ptr->max_indirect_big_packets_total) {
tr_debug_extra("free seq: %d", tx_entry->buf->seq); tr_debug_extra("Purge seq: %d", tx_entry->buf->seq);
lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry); if (lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry) == false) {
tr_debug("Purge failed, try next entry");
/* entry could not be purged from mac, try next entry */
count--;
}
} }
} }
} }
@ -911,6 +914,8 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff
if (indirect) { if (indirect) {
ns_dyn_mem_free(tx_ptr->fragmenter_buf); ns_dyn_mem_free(tx_ptr->fragmenter_buf);
ns_dyn_mem_free(tx_ptr); ns_dyn_mem_free(tx_ptr);
} else {
tx_ptr->buf = NULL;
} }
goto tx_error_handler; goto tx_error_handler;
} }
@ -1281,29 +1286,44 @@ static bool lowpan_tx_buffer_address_compare(sockaddr_t *dst_sa, uint8_t *addres
return true; return true;
} }
static void lowpan_adaptation_purge_from_mac(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, uint8_t msduhandle) static bool lowpan_adaptation_purge_from_mac(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, uint8_t msduhandle)
{ {
mcps_purge_t purge_req; mcps_purge_t purge_req;
purge_req.msduHandle = msduhandle; purge_req.msduHandle = msduhandle;
bool mac_purge_success = false;
if (interface_ptr->mpx_api) { if (interface_ptr->mpx_api) {
interface_ptr->mpx_api->mpx_data_purge(interface_ptr->mpx_api, &purge_req, interface_ptr->mpx_user_id); if (interface_ptr->mpx_api->mpx_data_purge(interface_ptr->mpx_api, &purge_req, interface_ptr->mpx_user_id) == 0) {
mac_purge_success = true;
}
} else { } else {
if (cur->mac_api->mcps_purge_req) { if (cur->mac_api->mcps_purge_req) {
cur->mac_api->mcps_purge_req(cur->mac_api, &purge_req); if (cur->mac_api->mcps_purge_req(cur->mac_api, &purge_req) == 0) {
mac_purge_success = true;
} }
} }
} }
static void lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr) return mac_purge_success;
}
static bool lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr)
{ {
tr_debug("Purge from indirect handle %u", tx_ptr->buf->seq); tr_debug("Purge from indirect handle %u, cached %d", tx_ptr->buf->seq, tx_ptr->indirect_data_cached);
lowpan_adaptation_purge_from_mac(cur, interface_ptr, tx_ptr->buf->seq); if (tx_ptr->indirect_data_cached == false) {
if (lowpan_adaptation_purge_from_mac(cur, interface_ptr, tx_ptr->buf->seq) == false) {
// MAC purge failed
return false;
}
}
lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, SOCKET_TX_FAIL); lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, SOCKET_TX_FAIL);
return true;
} }
void lowpan_adaptation_remove_free_indirect_table(protocol_interface_info_entry_t *cur_interface, mac_neighbor_table_entry_t *entry_ptr) void lowpan_adaptation_remove_free_indirect_table(protocol_interface_info_entry_t *cur_interface, mac_neighbor_table_entry_t *entry_ptr)
{ {
//Free firts by defined short address //Free first by defined short address
if (entry_ptr->mac16 < 0xfffe) { if (entry_ptr->mac16 < 0xfffe) {
uint8_t temp_address[2]; uint8_t temp_address[2];
common_write_16_bit(entry_ptr->mac16, temp_address); common_write_16_bit(entry_ptr->mac16, temp_address);
@ -1323,7 +1343,6 @@ int8_t lowpan_adaptation_indirect_free_messages_from_queues_by_address(struct pr
//Check first indirect queue //Check first indirect queue
ns_list_foreach_safe(fragmenter_tx_entry_t, entry, &interface_ptr->indirect_tx_queue) { ns_list_foreach_safe(fragmenter_tx_entry_t, entry, &interface_ptr->indirect_tx_queue) {
if (lowpan_tx_buffer_address_compare(&entry->buf->dst_sa, address_ptr, adr_type)) { if (lowpan_tx_buffer_address_compare(&entry->buf->dst_sa, address_ptr, adr_type)) {
//Purge from mac //Purge from mac
lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, entry); lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, entry);
@ -1331,7 +1350,6 @@ int8_t lowpan_adaptation_indirect_free_messages_from_queues_by_address(struct pr
} }
return 0; return 0;
} }
int8_t lowpan_adaptation_indirect_queue_params_set(struct protocol_interface_info_entry *cur, uint16_t indirect_big_packet_threshold, uint16_t max_indirect_big_packets_total, uint16_t max_indirect_small_packets_per_child) int8_t lowpan_adaptation_indirect_queue_params_set(struct protocol_interface_info_entry *cur, uint16_t indirect_big_packet_threshold, uint16_t max_indirect_big_packets_total, uint16_t max_indirect_small_packets_per_child)

View File

@ -35,6 +35,8 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode);
void ws_bootstrap_state_machine(protocol_interface_info_entry_t *cur); void ws_bootstrap_state_machine(protocol_interface_info_entry_t *cur);
int ws_bootstrap_restart(int8_t interface_id);
/*State machine transactions*/ /*State machine transactions*/
void ws_bootstrap_event_discovery_start(protocol_interface_info_entry_t *cur); void ws_bootstrap_event_discovery_start(protocol_interface_info_entry_t *cur);
@ -50,12 +52,27 @@ void ws_bootstrap_configuration_trickle_reset(protocol_interface_info_entry_t *c
void ws_bootstrap_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds); void ws_bootstrap_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds);
void ws_bootstrap_trigle_timer(protocol_interface_info_entry_t *cur, uint16_t ticks); void ws_bootstrap_trickle_timer(protocol_interface_info_entry_t *cur, uint16_t ticks);
void ws_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor);
void ws_secondary_parent_update(protocol_interface_info_entry_t *interface);
void ws_nud_entry_remove_active(protocol_interface_info_entry_t *cur, void *neighbor);
void ws_nud_active_timer(protocol_interface_info_entry_t *cur, uint16_t ticks);
void ws_dhcp_client_address_request(protocol_interface_info_entry_t *cur, uint8_t *prefix, uint8_t *parent_link_local);
void ws_dhcp_client_address_delete(protocol_interface_info_entry_t *cur, uint8_t *prefix);
#else #else
#define ws_bootstrap_init(interface_id, bootstrap_mode) (-1) #define ws_bootstrap_init(interface_id, bootstrap_mode) (-1)
#define ws_bootstrap_state_machine(cur) #define ws_bootstrap_state_machine(cur)
#define ws_bootstrap_restart(cur)
#define ws_primary_parent_update(interface, neighbor)
#define ws_secondary_parent_update(interface)
#endif //HAVE_WS #endif //HAVE_WS

View File

@ -20,11 +20,13 @@
#include "ns_types.h" #include "ns_types.h"
#include "ns_list.h"
#include "fhss_api.h" #include "fhss_api.h"
#include "fhss_config.h" #include "fhss_config.h"
#include "net_fhss.h" #include "net_fhss.h"
#include "6LoWPAN/ws/ws_common_defines.h" #include "6LoWPAN/ws/ws_common_defines.h"
#include "6LoWPAN/ws/ws_neighbor_class.h" #include "6LoWPAN/ws/ws_neighbor_class.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
struct ws_pan_information_s; struct ws_pan_information_s;
struct ws_neighbor_class_s; struct ws_neighbor_class_s;
@ -40,6 +42,17 @@ typedef struct parent_info_s {
uint32_t timestamp; /**< Timestamp when packet was received */ uint32_t timestamp; /**< Timestamp when packet was received */
}parent_info_t; }parent_info_t;
typedef struct ws_nud_table_entry {
void *neighbor_info;
uint16_t timer; /*!< Timer which resolution is 100ms*/
unsigned retry_count:2;
bool wait_response:1; /*!< True when NS is sended and wait NA, False when random timer is active*/
bool nud_process;
ns_list_link_t link;
} ws_nud_table_entry_t;
typedef NS_LIST_HEAD(ws_nud_table_entry_t, link) ws_nud_table_list_t;
typedef struct ws_info_s { typedef struct ws_info_s {
char network_name[33]; // Network name max 32 octets + terminating 0. char network_name[33]; // Network name max 32 octets + terminating 0.
uint16_t network_pan_id; uint16_t network_pan_id;
@ -54,8 +67,24 @@ typedef struct ws_info_s {
uint32_t pan_version_timer; /**< border router version udate timeout */ uint32_t pan_version_timer; /**< border router version udate timeout */
uint32_t pan_version_timeout_timer; /**< routers will fallback to previous state after this */ uint32_t pan_version_timeout_timer; /**< routers will fallback to previous state after this */
uint8_t gtkhash[32]; uint8_t gtkhash[32];
bool address_registration_event_active : 1;
bool configuration_learned:1; bool configuration_learned:1;
bool trickle_pas_running:1;
bool trickle_pa_running:1;
bool trickle_pcs_running:1;
bool trickle_pc_running:1;
// default fhss parameters for this device
uint8_t fhss_uc_dwell_interval;
uint8_t fhss_bc_dwell_interval;
uint32_t fhss_bc_interval;
uint8_t fhss_uc_channel_function;
uint8_t fhss_bc_channel_function;
uint16_t fhss_uc_fixed_channel;
uint16_t fhss_bc_fixed_channel;
uint32_t fhss_channel_mask[8];
ws_nud_table_entry_t nud_table_entrys[ACTIVE_NUD_PROCESS_MAX];
ws_nud_table_list_t active_nud_process;
ws_nud_table_list_t free_nud_entries;
struct ws_pan_information_s pan_information; struct ws_pan_information_s pan_information;
ws_hopping_schedule_t hopping_schdule; ws_hopping_schedule_t hopping_schdule;
struct ws_neighbor_class_s neighbor_storage; struct ws_neighbor_class_s neighbor_storage;
@ -65,6 +94,8 @@ typedef struct ws_info_s {
#ifdef HAVE_WS #ifdef HAVE_WS
int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain);
int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur); int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur);
int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur); int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur);

View File

@ -73,12 +73,14 @@ typedef struct ws_hopping_schedule_s {
uint8_t operating_class; /**< PHY operating class default to 1 */ uint8_t operating_class; /**< PHY operating class default to 1 */
uint8_t operating_mode; /**< PHY operating mode default to "1b" symbol rate 50, modulation index 1 */ uint8_t operating_mode; /**< PHY operating mode default to "1b" symbol rate 50, modulation index 1 */
uint8_t channel_plan; /**< 0: use regulatory domain values 1: application defined plan */ uint8_t channel_plan; /**< 0: use regulatory domain values 1: application defined plan */
uint8_t channel_function; /**< 0: Fixed channel, 1:TR51CF, 2: Direct Hash, 3: Vendor defined */ uint8_t uc_channel_function; /**< 0: Fixed channel, 1:TR51CF, 2: Direct Hash, 3: Vendor defined */
uint8_t bc_channel_function; /**< 0: Fixed channel, 1:TR51CF, 2: Direct Hash, 3: Vendor defined */
uint8_t channel_spacing; /**< derived from regulatory domain. 0:200k, 1:400k, 2:600k, 3:100k */ uint8_t channel_spacing; /**< derived from regulatory domain. 0:200k, 1:400k, 2:600k, 3:100k */
uint8_t number_of_channels; /**< derived from regulatory domain */ uint8_t number_of_channels; /**< derived from regulatory domain */
uint8_t clock_drift; uint8_t clock_drift;
uint8_t timing_accurancy; uint8_t timing_accurancy;
uint16_t fixed_channel; uint16_t uc_fixed_channel;
uint16_t bc_fixed_channel;
uint16_t fhss_bsi; uint16_t fhss_bsi;
uint32_t fhss_broadcast_interval; uint32_t fhss_broadcast_interval;
uint32_t channel_mask[8]; uint32_t channel_mask[8];
@ -182,9 +184,19 @@ typedef struct ws_bs_ie {
#define WS_FAN_VERSION_1_0 1 #define WS_FAN_VERSION_1_0 1
#define WS_NEIGHBOR_LINK_TIMEOUT 240 #define WS_NEIGHBOR_LINK_TIMEOUT 2200
#define WS_NEIGHBOR_NUD_TIMEOUT WS_NEIGHBOR_LINK_TIMEOUT / 2 #define WS_NEIGHBOR_NUD_TIMEOUT WS_NEIGHBOR_LINK_TIMEOUT / 2
#define WS_NEIGBOR_ETX_SAMPLE_MAX 3
#define WS_PROBE_INIT_BASE_SECONDS 8
#define WS_NUD_RAND_PROBABILITY 1
#define WS_NUD_RANDOM_SAMPLE_LENGTH WS_NEIGHBOR_NUD_TIMEOUT / 2
#define WS_NUD_RANDOM_COMPARE (WS_NUD_RAND_PROBABILITY*WS_NUD_RANDOM_SAMPLE_LENGTH) / 100
/* /*
* Threshold (referenced to DEVICE_MIN_SENS) above which a neighbor node may be considered for inclusion into candidate parent set * Threshold (referenced to DEVICE_MIN_SENS) above which a neighbor node may be considered for inclusion into candidate parent set
*/ */
@ -203,4 +215,12 @@ typedef struct ws_bs_ie {
*/ */
#define WS_RPL_DIS_TIMEOUT 1800 #define WS_RPL_DIS_TIMEOUT 1800
/* Default FHSS timing information
*
*/
#define WS_FHSS_UC_DWELL_INTERVAL 250;
#define WS_FHSS_BC_INTERVAL 800;
#define WS_FHSS_BC_DWELL_INTERVAL 200;
#endif /* WS_COMMON_DEFINES_H_ */ #endif /* WS_COMMON_DEFINES_H_ */

View File

@ -21,11 +21,16 @@
#include "fhss_ws_extension.h" #include "fhss_ws_extension.h"
#include "6LoWPAN/ws/ws_common_defines.h" #include "6LoWPAN/ws/ws_common_defines.h"
#define RSL_UNITITIALIZED 0x7fff
typedef struct ws_neighbor_class_entry { typedef struct ws_neighbor_class_entry {
fhss_ws_neighbor_timing_info_t fhss_data; fhss_ws_neighbor_timing_info_t fhss_data;
uint16_t rsl_in; /*!< RSL EWMA heard from neighbour*/ uint16_t rsl_in; /*!< RSL EWMA heard from neighbour*/
uint16_t rsl_out; /*!< RSL EWMA heard by neighbour*/ uint16_t rsl_out; /*!< RSL EWMA heard by neighbour*/
uint16_t routing_cost; /*!< ETX to border Router. */
bool candidate_parent:1; bool candidate_parent:1;
bool broadcast_timing_info_stored:1;
bool broadcast_shedule_info_stored:1;
} ws_neighbor_class_entry_t; } ws_neighbor_class_entry_t;
/** /**

View File

@ -583,6 +583,24 @@ buffer_t *ipv6_forwarding_down(buffer_t *buf)
return icmpv6_error(buf, NULL, ICMPV6_TYPE_ERROR_DESTINATION_UNREACH, ICMPV6_CODE_DST_UNREACH_NO_ROUTE, 0); return icmpv6_error(buf, NULL, ICMPV6_TYPE_ERROR_DESTINATION_UNREACH, ICMPV6_CODE_DST_UNREACH_NO_ROUTE, 0);
} }
/* Consider multicast forwarding /before/ calling routing code to modify
* extension headers - if that actually decides to tunnel it will
* overwrite the buffer's src_sa and dst_sa, when we want to consider
* forwarding the inner packet. This ordering works out for our only
* header-modifying multicast case of MPL:
* 1) We never want to forward packets with MPL headers, which means the
* outer packet in a tunnel gets ignored anyway.
* 2) This also means we don't have to worry that we're forwarding packets
* with the extension header not filled in yet.
* If we ever do have a multicast system where we are working with
* extension headers and forwarding those across interfaces, ipv6_get_exthdrs
* system will need a rework - probably split the "try MODIFY" call from the
* subsequent "give me tunnel parameters" part.
*/
if (!buf->ip_routed_up && addr_is_ipv6_multicast(buf->dst_sa.address)) {
buf = ipv6_consider_forwarding_multicast_packet(buf, buf->interface, true);
}
/* Allow routing code to update extension headers */ /* Allow routing code to update extension headers */
int16_t exthdr_result; int16_t exthdr_result;
buf = ipv6_get_exthdrs(buf, IPV6_EXTHDR_MODIFY, &exthdr_result); buf = ipv6_get_exthdrs(buf, IPV6_EXTHDR_MODIFY, &exthdr_result);
@ -593,10 +611,6 @@ buffer_t *ipv6_forwarding_down(buffer_t *buf)
goto drop; goto drop;
} }
if (!buf->ip_routed_up && addr_is_ipv6_multicast(buf->dst_sa.address)) {
buf = ipv6_consider_forwarding_multicast_packet(buf, buf->interface, true);
}
/* Routing code may say it needs to tunnel to add headers - loop back to IP layer if requested */ /* Routing code may say it needs to tunnel to add headers - loop back to IP layer if requested */
if (exthdr_result == IPV6_EXTHDR_MODIFY_TUNNEL) { if (exthdr_result == IPV6_EXTHDR_MODIFY_TUNNEL) {
/* Avoid an infinite loop in the event of routing code failure - never /* Avoid an infinite loop in the event of routing code failure - never

View File

@ -34,7 +34,6 @@
#include "DHCPv6_Server/DHCPv6_server_service.h" #include "DHCPv6_Server/DHCPv6_server_service.h"
#include "common_functions.h" #include "common_functions.h"
#include "NWK_INTERFACE/Include/protocol.h" #include "NWK_INTERFACE/Include/protocol.h"
#include "6LoWPAN/Thread/thread_bbr_api_internal.h"
#include "Common_Protocols/icmpv6.h" #include "Common_Protocols/icmpv6.h"
#include "dhcp_service_api.h" #include "dhcp_service_api.h"
@ -57,9 +56,6 @@ static int8_t dhcpv6_service_tasklet = -1;
static arm_event_storage_t *dhcp_timer_storage = NULL; static arm_event_storage_t *dhcp_timer_storage = NULL;
static void DHCPV6_server_service_remove_GUA_from_neighcache(protocol_interface_info_entry_t *cur, uint8_t *targetAddress);
static bool DHCP_server_service_timer_start(void) static bool DHCP_server_service_timer_start(void)
{ {
if(!dhcp_timer_storage) { if(!dhcp_timer_storage) {
@ -101,19 +97,16 @@ int DHCPv6_server_respond_client(dhcpv6_gua_server_entry_s *serverBase, dhcpv6_r
nonTemporalAddress.validLifeTime = dhcp_allocated_address->lifetime; nonTemporalAddress.validLifeTime = dhcp_allocated_address->lifetime;
nonTemporalAddress.preferredLifeTime = dhcp_allocated_address->preferredLifetime; nonTemporalAddress.preferredLifeTime = dhcp_allocated_address->preferredLifetime;
// If this is solicit from existing address, flush ND cache. if (serverBase->addCb) {
if (allocateNew) { dhcp_address_cache_update_t update_info;
// coverity[returned_null] for ignoring protocol_stack_interface_info_get_by_id NULL return update_info.allocatedAddress = dhcp_allocated_address->nonTemporalAddress;
DHCPV6_server_service_remove_GUA_from_neighcache(protocol_stack_interface_info_get_by_id(serverBase->interfaceId), nonTemporalAddress.requestedAddress); update_info.allocatedNewAddress = allocateNew;
} update_info.validLifeTime = nonTemporalAddress.validLifeTime;
if (thread_bbr_nd_entry_add(serverBase->interfaceId,dhcp_allocated_address->nonTemporalAddress, nonTemporalAddress.validLifeTime, serverBase->guaPrefix) == -1) {
// No nanostack BBR present we will put entry for application implemented BBR if (!serverBase->addCb(serverBase->interfaceId, &update_info, serverBase->guaPrefix)) {
ipv6_route_t *route = ipv6_route_add_with_info(dhcp_allocated_address->nonTemporalAddress, 128, serverBase->interfaceId, NULL, ROUTE_THREAD_PROXIED_HOST,serverBase->guaPrefix,0, nonTemporalAddress.validLifeTime, 0);
if (!route) {
address_allocated = false; address_allocated = false;
libdhcpv6_address_rm_from_allocated_list(serverBase,dhcp_allocated_address->nonTemporalAddress); libdhcpv6_address_rm_from_allocated_list(serverBase,dhcp_allocated_address->nonTemporalAddress);
} }
} }
} }
@ -213,30 +206,6 @@ void DHCPv6_server_service_tasklet(arm_event_s *event)
} }
} }
static void DHCPV6_server_service_remove_GUA_from_neighcache(protocol_interface_info_entry_t *cur, uint8_t *targetAddress)
{
ipv6_neighbour_t *neighbour_entry;
neighbour_entry = ipv6_neighbour_lookup(&cur->ipv6_neighbour_cache, targetAddress);
if (neighbour_entry) {
tr_debug("Remove from neigh Cache: %s", tr_ipv6(targetAddress));
ipv6_neighbour_entry_remove(&cur->ipv6_neighbour_cache, neighbour_entry);
}
}
void DHCPv6_server_service_address_preferred_timeout_handler(int8_t interfaceId, uint8_t *targetAddress)
{
tr_warn("Address Preferred Timeout");
protocol_interface_info_entry_t *cur = 0;
//allocate Socket Service
cur = protocol_stack_interface_info_get_by_id(interfaceId);
if (cur) {
ipv6_route_delete(targetAddress, 128, interfaceId, NULL, ROUTE_THREAD_PROXIED_HOST);
DHCPV6_server_service_remove_GUA_from_neighcache(cur, targetAddress);
}
}
static int8_t dhcpv6_server_service_tasklet_generated(void) static int8_t dhcpv6_server_service_tasklet_generated(void)
{ {
if (dhcpv6_service_tasklet == -1) { if (dhcpv6_service_tasklet == -1) {
@ -267,30 +236,23 @@ int DHCPv6_server_service_init(int8_t interface, uint8_t guaPrefix[static 16], u
//allocate Socket Service //allocate Socket Service
socketInstance = dhcp_service_init(interface, DHCP_INSTANCE_SERVER, DHCPV6_server_service_request_handler); socketInstance = dhcp_service_init(interface, DHCP_INSTANCE_SERVER, DHCPV6_server_service_request_handler);
cur = protocol_stack_interface_info_get_by_id(interface); cur = protocol_stack_interface_info_get_by_id(interface);
if (cur) { if (!cur) {
return -1;
}
if (dhcpv6_server_service_tasklet_generated() < 0) { if (dhcpv6_server_service_tasklet_generated() < 0) {
retVal = -2; retVal = -2;
} else if (!DHCP_server_service_timer_start()) { } else if (!DHCP_server_service_timer_start()) {
retVal = -2; retVal = -2;
} else { } else {
//allocate server //allocate server
dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_gua_server_allocate(guaPrefix, interface, cur->mac, DHCPV6_DUID_HARDWARE_EUI64_TYPE, DHCPv6_server_service_address_preferred_timeout_handler); dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_gua_server_allocate(guaPrefix, interface, cur->mac, DHCPV6_DUID_HARDWARE_EUI64_TYPE);
if (serverInfo) { if (serverInfo) {
//if_address_entry_t *def_address = NULL;
uint8_t temp[16];
uint8_t *ptr = temp;
//define address & Route advert's
memcpy(ptr, guaPrefix, 8);
ptr += 8;
memcpy(ptr, cur->iid_slaac, 8);
serverInfo->socketInstance_id = socketInstance; serverInfo->socketInstance_id = socketInstance;
socketInstance = 0; socketInstance = 0;
//Generate Address for current interface
retVal = 0; retVal = 0;
} }
} }
}
if (socketInstance > 0) { if (socketInstance > 0) {
dhcp_service_delete(socketInstance); dhcp_service_delete(socketInstance);
DHCP_server_service_timer_stop(); DHCP_server_service_timer_stop();
@ -303,25 +265,6 @@ void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds)
libdhcpv6_gua_servers_time_update(timeUpdateInSeconds); libdhcpv6_gua_servers_time_update(timeUpdateInSeconds);
} }
void DHCPv6_GUA64_ML64_route_control(int8_t interfaceId, uint8_t *allocatedGuaAddress, uint8_t *clientEUID64, uint8_t *meshLocalPrefix, bool deleteMapping)
{
uint8_t ml64[16];
uint8_t *ptr = ml64;
memcpy(ptr, meshLocalPrefix, 8);
ptr += 8;
memcpy(ptr, clientEUID64, 8);
*ptr ^= 2;
//Generate Route Info
if (deleteMapping) {
ipv6_route_delete(allocatedGuaAddress, 128, interfaceId, ml64, ROUTE_STATIC);
} else if (ipv6_route_add(allocatedGuaAddress, 128, interfaceId, ml64, ROUTE_STATIC, 0xffffffff, 0) == 0) {
tr_debug("Route ADD OK");
} else {
tr_warn("Route Add fail");
}
}
/* Delete dhcp thread dhcp router ID server. /* Delete dhcp thread dhcp router ID server.
* *
* When this is called it close selected service and free all allocated memory. * When this is called it close selected service and free all allocated memory.
@ -332,30 +275,32 @@ void DHCPv6_GUA64_ML64_route_control(int8_t interfaceId, uint8_t *allocatedGuaAd
*/ */
void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 16], bool delete_gua_addresses) void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 16], bool delete_gua_addresses)
{ {
protocol_interface_info_entry_t *curPtr = 0;
//allocate Socket Service
curPtr = protocol_stack_interface_info_get_by_id(interface);
if (curPtr) {
dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix);
if (serverInfo) { if (serverInfo) {
ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) { ns_list_foreach_safe(dhcpv6_alloacted_address_entry_t, cur, &serverInfo->allocatedAddressList) {
//Delete Server data base //Delete Server data base
DHCPV6_server_service_remove_GUA_from_neighcache(curPtr, cur->nonTemporalAddress); if (serverInfo->removeCb) {
serverInfo->removeCb(interface, cur->nonTemporalAddress, NULL);
} }
}
if (serverInfo->removeCb) {
// Clean all /128 'Thread Proxy' routes to self and others added when acting as a DHCP server // Clean all /128 'Thread Proxy' routes to self and others added when acting as a DHCP server
ipv6_route_table_remove_info(curPtr->id, ROUTE_THREAD_PROXIED_HOST,serverInfo->guaPrefix); serverInfo->removeCb(interface, NULL, serverInfo->guaPrefix);
}
dhcp_service_delete(serverInfo->socketInstance_id); dhcp_service_delete(serverInfo->socketInstance_id);
} }
if (delete_gua_addresses) { if (delete_gua_addresses) {
protocol_interface_info_entry_t *curPtr = protocol_stack_interface_info_get_by_id(interface);
if (curPtr) {
protocol_core_dhcpv6_allocated_address_remove(curPtr, guaPrefix); protocol_core_dhcpv6_allocated_address_remove(curPtr, guaPrefix);
} }
}
libdhcpv6_gua_server_free_by_prefix_and_interfaceid(guaPrefix, interface); libdhcpv6_gua_server_free_by_prefix_and_interfaceid(guaPrefix, interface);
DHCP_server_service_timer_stop(); DHCP_server_service_timer_stop();
}
} }
/* Control GUA address for client by DUI.Default value is true /* Control GUA address for client by DUI.Default value is true
@ -379,33 +324,15 @@ int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t gu
return retVal; return retVal;
} }
/* Enable or disable GUA64 Address mapping to ML64 void DHCPv6_server_service_callback_set(int8_t interface, uint8_t guaPrefix[static 16], dhcp_address_prefer_remove_cb *remove_cb, dhcp_address_add_notify_cb *add_cb)
*
*
* /param interface interface id of this thread instance.
* /param guaPrefix Prefix which will be removed
* /param mode
* /param meshLocalPrefix mesh local prefix for generate ML6 from client EUID64
*/
int DHCPv6_server_service_set_gua_address_mapping(int8_t interface, uint8_t guaPrefix[static 16], bool mode, uint8_t meshLocalPrefix[8])
{ {
int retVal = -1; dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix);
dhcpv6_gua_server_entry_s *serverInfo; if (!serverInfo) {
return;
serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix);
if (serverInfo) {
if (mode == true && meshLocalPrefix == NULL) {
retVal = -2;
} else {
serverInfo->enableAddressMapping = mode;
if (meshLocalPrefix) {
memcpy(serverInfo->meshLocalPrefix, meshLocalPrefix, 8);
}
retVal = 0;
}
} }
return retVal; serverInfo->addCb = add_cb;
serverInfo->removeCb = remove_cb;
} }
/* SET max accepted clients to server, Default is 200 /* SET max accepted clients to server, Default is 200
@ -453,21 +380,6 @@ int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t gu
} }
return retVal; return retVal;
} }
int DHCPv6_server_service_gua_target_mac_check(int8_t interfaceId, const uint8_t *targetGUA, uint8_t *targetEUI64)
{
dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, targetGUA);
if (serverInfo) {
dhcpv6_alloacted_address_entry_t *entry = libdhcpv6_address_get_from_allocated_list(serverInfo, targetGUA);
if (entry) {
if (entry->preferredLifetime && (entry->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE)) {
memcpy(targetEUI64, entry->linkId, 8);
return 0;
}
}
}
return -1;
}
#else #else
int DHCPv6_server_service_init(int8_t interface, uint8_t guaPrefix[static 16], uint8_t serverDUID[static 8], uint16_t serverDUIDType) int DHCPv6_server_service_init(int8_t interface, uint8_t guaPrefix[static 16], uint8_t serverDUID[static 8], uint16_t serverDUIDType)
@ -497,15 +409,6 @@ int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t gu
return -1; return -1;
} }
int DHCPv6_server_service_set_gua_address_mapping(int8_t interface, uint8_t guaPrefix[static 16], bool mode, uint8_t meshLocalPrefix[8])
{
(void) interface;
(void) guaPrefix;
(void) mode;
(void) meshLocalPrefix;
return -1;
}
int DHCPv6_server_service_set_max_clients_accepts_count(int8_t interface, uint8_t guaPrefix[static 16], uint32_t maxClientCount) int DHCPv6_server_service_set_max_clients_accepts_count(int8_t interface, uint8_t guaPrefix[static 16], uint32_t maxClientCount)
{ {
(void) interface; (void) interface;
@ -522,13 +425,5 @@ int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t gu
return -1; return -1;
} }
int DHCPv6_server_service_gua_target_mac_check(int8_t interfaceId, const uint8_t *targetGUA, uint8_t *targetEUI64)
{
(void) interfaceId;
(void) targetGUA;
(void) targetEUI64;
return -1;
}
#endif #endif

View File

@ -23,6 +23,10 @@
#ifndef DHCPV6_SERVER_SERVICE_H_ #ifndef DHCPV6_SERVER_SERVICE_H_
#define DHCPV6_SERVER_SERVICE_H_ #define DHCPV6_SERVER_SERVICE_H_
#ifdef HAVE_DHCPV6_SERVER
#include "libDHCPv6/libDHCPv6.h"
#include "libDHCPv6/libDHCPv6_server.h"
/* Initialize dhcp Global address server. /* Initialize dhcp Global address server.
* *
* This instance needs to bee initialized once for each thread network interface. * This instance needs to bee initialized once for each thread network interface.
@ -38,6 +42,10 @@
*/ */
int DHCPv6_server_service_init(int8_t interface, uint8_t guaPrefix[static 16], uint8_t serverDUID[static 8], uint16_t serverDUIDType); int DHCPv6_server_service_init(int8_t interface, uint8_t guaPrefix[static 16], uint8_t serverDUID[static 8], uint16_t serverDUIDType);
void DHCPv6_server_service_callback_set(int8_t interface, uint8_t guaPrefix[static 16], dhcp_address_prefer_remove_cb *remove_cb, dhcp_address_add_notify_cb *add_cb);
/* Delete dhcp thread dhcp router ID server. /* Delete dhcp thread dhcp router ID server.
* *
* When this is called it close selected service and free all allocated memory. * When this is called it close selected service and free all allocated memory.
@ -51,8 +59,6 @@ void DHCPv6_server_service_delete(int8_t interface, uint8_t guaPrefix[static 16]
void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds); void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds);
//void DHCPv6_GUA64_ML64_route_control(int8_t interfaceId, uint8_t *allocatedGuaAddress, uint8_t *clientEUID64, uint8_t *meshLocalPrefix, bool deleteMapping);
/* Control GUA address for client by DUI.Default value is true /* Control GUA address for client by DUI.Default value is true
* *
* *
@ -63,16 +69,6 @@ void DHCPv6_server_service_timeout_cb(uint32_t timeUpdateInSeconds);
int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode); int DHCPv6_server_service_set_address_autonous_flag(int8_t interface, uint8_t guaPrefix[static 16], bool mode);
/* Enable or disable GUA64 Address mapping to ML64
*
*
* /param interface interface id of this thread instance.
* /param guaPrefix Prefix which will be removed
* /param mode
* /param meshLocalPrefix mesh local prefix for generate ML6 from client EUID64
*/
int DHCPv6_server_service_set_gua_address_mapping(int8_t interface, uint8_t guaPrefix[static 16], bool mode, uint8_t meshLocalPrefix[8]);
/* SET max accepted clients to server, Default is 200 /* SET max accepted clients to server, Default is 200
* *
* *
@ -91,7 +87,7 @@ int DHCPv6_server_service_set_max_clients_accepts_count(int8_t interface, uint8_
* /param validLifeTimne in seconds * /param validLifeTimne in seconds
*/ */
int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t guaPrefix[static 16], uint32_t validLifeTimne); int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t guaPrefix[static 16], uint32_t validLifeTimne);
#else
#define DHCPv6_server_service_delete(interface, guaPrefix, delete_gua_addresses)
int DHCPv6_server_service_gua_target_mac_check(int8_t interfaceId, const uint8_t *targetGUA, uint8_t *targetEUI64); #endif
#endif /* DHCPV6_SERVER_SERVICE_H_ */ #endif /* DHCPV6_SERVER_SERVICE_H_ */

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef DHCPV6_CLIENT_API_H_
#define DHCPV6_CLIENT_API_H_
#include <ns_types.h>
/* DHCP client implementation.
*
* Responsibilities of this module are:
* - handle Global address queries and refresh inside network.
*
*/
/* Initialize dhcp client.
*
* This instance needs to bee initialized once for each network interface.
* if only one thread instance is supported this is needed to call only once.
*
* /param interface interface id of this instance.
*
*/
void dhcp_client_init(int8_t interface);
/* Delete dhcp client.
*
* When this is called all addressed assigned by this module are removed from stack.
*/
void dhcp_client_delete(int8_t interface);
/* Global address handler.
*
* This module updates the addresses from dhcp server and sets them in stack.
* this module makes refresh of address when needed.
*
*/
/* give dhcp server and prefix for global address assignment
*
* /param interface interface where address is got
* /param dhcp_addr dhcp server ML16 address where address is registered.
* /param prefix dhcp server ML16 address where address is registered.
* /param mac64 64 bit mac address for identifieng client.
* /param error_cb error callback that is called if address cannot be created or becomes invalid.
* /param register_status true if address registered.
*
*/
typedef void (dhcp_client_global_adress_cb)(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], bool register_status);
int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], uint8_t mac64[static 8], dhcp_client_global_adress_cb *error_cb);
/* Renew all leased adddresses might be used when short address changes
*
* /param interface interface where address is got
*/
void dhcp_client_global_address_renew(int8_t interface);
/* Delete address from device
* if prefix is NULL all are deleted
*
* /param interface interface where address is got
* /param prefix dhcp server ML16 address where address is registered.
*
*/
void dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16]);
void dhcp_relay_agent_enable(int8_t interface, uint8_t border_router_address[static 16]);
#endif /* DHCPV6_CLIENT_API_H_ */

View File

@ -1,34 +1,21 @@
/* /*
* Copyright (c) 2013-2018, Arm Limited and affiliates. * Copyright (c) 2018, Arm Limited and affiliates.
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: Apache-2.0
* *
* Redistribution and use in source and binary forms, with or without * Licensed under the Apache License, Version 2.0 (the "License");
* modification, are permitted provided that the following conditions are met: * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* *
* 1. Redistributions of source code must retain the above copyright * http://www.apache.org/licenses/LICENSE-2.0
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * Unless required by applicable law or agreed to in writing, software
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * distributed under the License is distributed on an "AS IS" BASIS,
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * See the License for the specific language governing permissions and
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * limitations under the License.
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "nsconfig.h" #include "nsconfig.h"
#ifdef HAVE_THREAD
#include <string.h> #include <string.h>
#include <ns_types.h> #include <ns_types.h>
#include <ns_trace.h> #include <ns_trace.h>
@ -36,31 +23,30 @@
#include "ns_list.h" #include "ns_list.h"
#include "common_functions.h" #include "common_functions.h"
#ifdef HAVE_DHCPV6
#include "dhcp_service_api.h" #include "dhcp_service_api.h"
#include "thread_dhcpv6_client.h" #include "dhcpv6_client_api.h"
#include "libDHCPv6/libDHCPv6.h" #include "libDHCPv6/libDHCPv6.h"
#include "NWK_INTERFACE/Include/protocol.h" #include "NWK_INTERFACE/Include/protocol.h"
#include "6LoWPAN/Thread/thread_common.h"
#include "6LoWPAN/Thread/thread_bootstrap.h"
#define TRACE_GROUP "TDHP" #define TRACE_GROUP "DHP"
typedef struct { typedef struct {
thread_dhcp_client_global_adress_cb *global_address_cb; dhcp_client_global_adress_cb *global_address_cb;
uint16_t service_instance; uint16_t service_instance;
uint16_t relay_instance;
uint8_t libDhcp_instance; uint8_t libDhcp_instance;
int8_t interface; int8_t interface;
} thread_dhcp_client_class_t; } dhcp_client_class_t;
thread_dhcp_client_class_t dhcp_client; static dhcp_client_class_t dhcp_client;
void thread_dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr); void dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr);
void thread_dhcp_client_init(int8_t interface) void dhcp_client_init(int8_t interface)
{ {
// No support for multible thread instances yet. // No support for multible instances yet.
dhcp_client.service_instance = dhcp_service_init(interface, DHCP_INSTANCE_CLIENT, NULL); dhcp_client.service_instance = dhcp_service_init(interface, DHCP_INSTANCE_CLIENT, NULL);
dhcp_client.interface = interface; dhcp_client.interface = interface;
dhcp_client.libDhcp_instance = libdhcpv6_nonTemporal_entry_get_unique_instance_id(); dhcp_client.libDhcp_instance = libdhcpv6_nonTemporal_entry_get_unique_instance_id();
@ -68,7 +54,13 @@ void thread_dhcp_client_init(int8_t interface)
return; return;
} }
void thread_dhcp_client_delete(int8_t interface) void dhcp_relay_agent_enable(int8_t interface, uint8_t border_router_address[static 16])
{
dhcp_client.relay_instance = dhcp_service_init(interface, DHCP_INTANCE_RELAY_AGENT, NULL);
dhcp_service_relay_instance_enable(dhcp_client.relay_instance, border_router_address);
}
void dhcp_client_delete(int8_t interface)
{ {
protocol_interface_info_entry_t *cur = NULL; protocol_interface_info_entry_t *cur = NULL;
dhcpv6_client_server_data_t *srv_data_ptr; dhcpv6_client_server_data_t *srv_data_ptr;
@ -96,7 +88,7 @@ void thread_dhcp_client_delete(int8_t interface)
} }
void thread_dhcpv6_client_send_error_cb(dhcpv6_client_server_data_t *srv_data_ptr) void dhcpv6_client_send_error_cb(dhcpv6_client_server_data_t *srv_data_ptr)
{ {
if (srv_data_ptr != NULL) { if (srv_data_ptr != NULL) {
@ -159,12 +151,11 @@ int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uin
srv_data_ptr->iaNontemporalAddress.validLifetime = dhcp_ia_non_temporal_params.validLifeTime; srv_data_ptr->iaNontemporalAddress.validLifetime = dhcp_ia_non_temporal_params.validLifeTime;
memcpy(srv_data_ptr->serverLinkId, serverId.linkID, 8); memcpy(srv_data_ptr->serverLinkId, serverId.linkID, 8);
srv_data_ptr->serverLinkType = serverId.linkType; srv_data_ptr->serverLinkType = serverId.linkType;
srv_data_ptr->serverLinkType = serverId.linkType;
srv_data_ptr->T0 = dhcp_ia_non_temporal_params.T0; srv_data_ptr->T0 = dhcp_ia_non_temporal_params.T0;
srv_data_ptr->T1 = dhcp_ia_non_temporal_params.T1; srv_data_ptr->T1 = dhcp_ia_non_temporal_params.T1;
srv_data_ptr->iaNonTemporalStructValid = true; srv_data_ptr->iaNonTemporalStructValid = true;
thread_dhcpv6_client_set_address(dhcp_client.interface, srv_data_ptr); dhcpv6_client_set_address(dhcp_client.interface, srv_data_ptr);
if (dhcp_client.global_address_cb) { if (dhcp_client.global_address_cb) {
@ -172,11 +163,11 @@ int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uin
} }
return RET_MSG_ACCEPTED; return RET_MSG_ACCEPTED;
error_exit: error_exit:
thread_dhcpv6_client_send_error_cb(srv_data_ptr); dhcpv6_client_send_error_cb(srv_data_ptr);
return RET_MSG_ACCEPTED; return RET_MSG_ACCEPTED;
} }
int thread_dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], uint8_t mac64[static 8], thread_dhcp_client_global_adress_cb *error_cb) int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], uint8_t mac64[static 8], dhcp_client_global_adress_cb *error_cb)
{ {
dhcpv6_solication_base_packet_s solPacket = {0}; dhcpv6_solication_base_packet_s solPacket = {0};
dhcpv6_ia_non_temporal_address_s nonTemporalAddress = {0}; dhcpv6_ia_non_temporal_address_s nonTemporalAddress = {0};
@ -190,16 +181,19 @@ int thread_dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[st
} }
srv_data_ptr = libdhcvp6_nontemporalAddress_server_data_allocate(interface, dhcp_client.libDhcp_instance, mac64, DHCPV6_DUID_HARDWARE_EUI64_TYPE, prefix, dhcp_addr); srv_data_ptr = libdhcvp6_nontemporalAddress_server_data_allocate(interface, dhcp_client.libDhcp_instance, mac64, DHCPV6_DUID_HARDWARE_EUI64_TYPE, prefix, dhcp_addr);
if (!srv_data_ptr) {
tr_error("OOM srv_data_ptr");
return -1;
}
payload_len = libdhcpv6_solication_message_length(DHCPV6_DUID_HARDWARE_EUI64_TYPE, true, 0); payload_len = libdhcpv6_solication_message_length(DHCPV6_DUID_HARDWARE_EUI64_TYPE, true, 0);
payload_ptr = ns_dyn_mem_temporary_alloc(payload_len); payload_ptr = ns_dyn_mem_temporary_alloc(payload_len);
if (!payload_ptr) {
if (payload_ptr == NULL || srv_data_ptr == NULL) {
ns_dyn_mem_free(payload_ptr);
libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr); libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
tr_error("Out of memory"); tr_error("OOM payload_ptr");
return -1; return -1;
} }
dhcp_client.global_address_cb = error_cb; //TODO Only supporting one instance globaly if we need more for different instances needs code. dhcp_client.global_address_cb = error_cb; //TODO Only supporting one instance globaly if we need more for different instances needs code.
srv_data_ptr->GlobalAddress = true; srv_data_ptr->GlobalAddress = true;
// Build solicit // Build solicit
@ -214,17 +208,22 @@ int thread_dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[st
// send solicit // send solicit
srv_data_ptr->transActionId = dhcp_service_send_req(dhcp_client.service_instance, 0, srv_data_ptr , dhcp_addr, payload_ptr, payload_len, dhcp_solicit_resp_cb); srv_data_ptr->transActionId = dhcp_service_send_req(dhcp_client.service_instance, 0, srv_data_ptr , dhcp_addr, payload_ptr, payload_len, dhcp_solicit_resp_cb);
return srv_data_ptr->transActionId ? 0 : -1; if (srv_data_ptr->transActionId == 0) {
ns_dyn_mem_free(payload_ptr);
libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
return -1;
} }
void thread_dhcp_client_global_address_renew(int8_t interface) return 0;
}
void dhcp_client_global_address_renew(int8_t interface)
{ {
// only prepared for changes in thread specifications
(void)interface; (void)interface;
return; return;
} }
void thread_dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16]) void dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16])
{ {
protocol_interface_info_entry_t *cur; protocol_interface_info_entry_t *cur;
dhcpv6_client_server_data_t *srv_data_ptr; dhcpv6_client_server_data_t *srv_data_ptr;
@ -249,7 +248,7 @@ void thread_dhcp_client_global_address_delete(int8_t interface, uint8_t dhcp_add
return; return;
} }
void thread_dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, if_address_callback_t reason) void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, if_address_callback_t reason)
{ {
dhcpv6_ia_non_temporal_address_s nonTemporalAddress = {0}; dhcpv6_ia_non_temporal_address_s nonTemporalAddress = {0};
dhcp_link_options_params_t serverLink; dhcp_link_options_params_t serverLink;
@ -275,7 +274,7 @@ void thread_dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_
payload_len = libdhcpv6_address_request_message_len(srv_data_ptr->clientLinkIdType, srv_data_ptr->serverLinkType, 0); payload_len = libdhcpv6_address_request_message_len(srv_data_ptr->clientLinkIdType, srv_data_ptr->serverLinkType, 0);
payload_ptr = ns_dyn_mem_temporary_alloc(payload_len); payload_ptr = ns_dyn_mem_temporary_alloc(payload_len);
if (payload_ptr == NULL) { if (payload_ptr == NULL) {
addr->state_timer = 200;//Retry after? should there be maximum 20 second retry addr->state_timer = 200; //Retry after 20 seconds
tr_error("Out of memory"); tr_error("Out of memory");
return ; return ;
} }
@ -299,9 +298,14 @@ void thread_dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_
libdhcpv6_generic_nontemporal_address_message_write(payload_ptr, &packetReq, &nonTemporalAddress, &serverLink); libdhcpv6_generic_nontemporal_address_message_write(payload_ptr, &packetReq, &nonTemporalAddress, &serverLink);
// send solicit // send solicit
srv_data_ptr->transActionId = dhcp_service_send_req(dhcp_client.service_instance, 0, srv_data_ptr, srv_data_ptr->server_address, payload_ptr, payload_len, dhcp_solicit_resp_cb); srv_data_ptr->transActionId = dhcp_service_send_req(dhcp_client.service_instance, 0, srv_data_ptr, srv_data_ptr->server_address, payload_ptr, payload_len, dhcp_solicit_resp_cb);
if (srv_data_ptr->transActionId == 0) {
ns_dyn_mem_free(payload_ptr);
addr->state_timer = 200; //Retry after 20 seconds
tr_error("DHCP renew send failed");
}
} }
void thread_dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr) void dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr)
{ {
protocol_interface_info_entry_t *cur = NULL; protocol_interface_info_entry_t *cur = NULL;
if_address_entry_t *address_entry = NULL; if_address_entry_t *address_entry = NULL;
@ -335,6 +339,7 @@ void thread_dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_
} }
} }
address_entry->state_timer = renewTimer; address_entry->state_timer = renewTimer;
address_entry->cb = thread_dhcpv6_renew; address_entry->cb = dhcpv6_renew;
} }
#endif #endif

View File

@ -37,7 +37,9 @@ typedef enum mac_event_t {
MAC_TIMER_ACK, MAC_TIMER_ACK,
MAC_TIMER_CCA, MAC_TIMER_CCA,
MAC_TX_FAIL, MAC_TX_FAIL,
MAC_TX_TIMEOUT MAC_TX_TIMEOUT,
MAC_UNKNOWN_DESTINATION,
MAC_TX_PRECOND_FAIL
} mac_event_t; } mac_event_t;
typedef enum mac_tx_status_type_t { typedef enum mac_tx_status_type_t {
@ -89,8 +91,12 @@ typedef enum arm_nwk_mlme_event_type {
ARM_NWK_MAC_MLME_INDIRECT_DATA_POLL_AFTER_DATA = 5, ARM_NWK_MAC_MLME_INDIRECT_DATA_POLL_AFTER_DATA = 5,
} arm_nwk_mlme_event_type_e; } arm_nwk_mlme_event_type_e;
#define ENHANCED_ACK_MAX_LENGTH 255
typedef struct dev_driver_tx_buffer { typedef struct dev_driver_tx_buffer {
uint8_t *buf; uint8_t *buf;
uint8_t *enhanced_ack_buf;
uint16_t ack_len;
uint16_t len; uint16_t len;
unsigned priority:2; unsigned priority:2;
} dev_driver_tx_buffer_s; } dev_driver_tx_buffer_s;
@ -134,6 +140,11 @@ typedef struct mac_tx_status_t {
uint8_t retry; uint8_t retry;
} mac_tx_status_t; } mac_tx_status_t;
typedef struct mac_mcps_data_conf_fail_s {
uint8_t msduHandle; /**< Handle associated with MSDU */
uint8_t status; /**< Status of the failing MSDU transmission */
} mac_mcps_data_conf_fail_t;
typedef struct protocol_interface_rf_mac_setup { typedef struct protocol_interface_rf_mac_setup {
int8_t mac_interface_id; int8_t mac_interface_id;
bool macUpState; bool macUpState;
@ -229,6 +240,7 @@ typedef struct protocol_interface_rf_mac_setup {
uint8_t max_ED; uint8_t max_ED;
uint16_t mlme_ED_counter; uint16_t mlme_ED_counter;
mac_tx_status_t mac_tx_status; mac_tx_status_t mac_tx_status;
mac_mcps_data_conf_fail_t mac_mcps_data_conf_fail;
struct cca_structure_s *cca_structure; struct cca_structure_s *cca_structure;
/* MAC Security components */ /* MAC Security components */
struct mlme_device_descriptor_s *device_description_table; struct mlme_device_descriptor_s *device_description_table;

View File

@ -65,13 +65,24 @@ uint32_t mac_read_phy_datarate(const fhss_api_t *fhss_api)
return datarate; return datarate;
} }
uint32_t mac_read_phy_timestamp(const fhss_api_t *fhss_api)
{
protocol_interface_rf_mac_setup_s *mac_setup = get_sw_mac_ptr_by_fhss_api(fhss_api);
if (!mac_setup) {
return 0;
}
uint32_t timestamp;
mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_GET_TIMESTAMP, (uint8_t *)&timestamp);
return timestamp;
}
int mac_set_channel(const fhss_api_t *fhss_api, uint8_t channel_number) int mac_set_channel(const fhss_api_t *fhss_api, uint8_t channel_number)
{ {
protocol_interface_rf_mac_setup_s *mac_setup = get_sw_mac_ptr_by_fhss_api(fhss_api); protocol_interface_rf_mac_setup_s *mac_setup = get_sw_mac_ptr_by_fhss_api(fhss_api);
if (!mac_setup) { if (!mac_setup) {
return -1; return -1;
} }
if (mac_setup->mac_ack_tx_active || (mac_setup->active_pd_data_request && mac_setup->active_pd_data_request->asynch_request)) { if (mac_setup->mac_ack_tx_active || (mac_setup->active_pd_data_request && (mac_setup->active_pd_data_request->asynch_request || mac_setup->timer_mac_event == MAC_TIMER_ACK))) {
return -1; return -1;
} }
return mac_mlme_rf_channel_change(mac_setup, channel_number); return mac_mlme_rf_channel_change(mac_setup, channel_number);

View File

@ -21,6 +21,7 @@
uint16_t mac_read_tx_queue_sizes(const fhss_api_t *fhss_api, bool broadcast_queue); uint16_t mac_read_tx_queue_sizes(const fhss_api_t *fhss_api, bool broadcast_queue);
int mac_read_64bit_mac_address(const fhss_api_t *fhss_api, uint8_t *mac_address); int mac_read_64bit_mac_address(const fhss_api_t *fhss_api, uint8_t *mac_address);
uint32_t mac_read_phy_datarate(const fhss_api_t *fhss_api); uint32_t mac_read_phy_datarate(const fhss_api_t *fhss_api);
uint32_t mac_read_phy_timestamp(const fhss_api_t *fhss_api);
int mac_set_channel(const fhss_api_t *fhss_api, uint8_t channel_number); int mac_set_channel(const fhss_api_t *fhss_api, uint8_t channel_number);
int mac_fhss_frame_tx(const fhss_api_t *fhss_api, int frame_type); int mac_fhss_frame_tx(const fhss_api_t *fhss_api, int frame_type);
int mac_synch_lost(const fhss_api_t *fhss_api); int mac_synch_lost(const fhss_api_t *fhss_api);

View File

@ -337,16 +337,16 @@ void mac_header_security_components_read(mac_pre_parsed_frame_t *buffer, mlme_se
} }
uint16_t mac_header_get_src_panid(const mac_fcf_sequence_t *header, const uint8_t *ptr) static bool mac_header_pan_full_compressed(const mac_fcf_sequence_t *header)
{ {
if (header->frameVersion == MAC_FRAME_VERSION_2015 && (!header->DstPanPresents && !header->SrcPanPresents) && header->intraPan) {
if (!header->SrcPanPresents) { return true;
if (!header->DstPanPresents) {
return 0xffff;
} }
return mac_header_get_dst_panid(header, ptr); return false;
} }
static uint16_t mac_header_read_src_pan(const mac_fcf_sequence_t *header, const uint8_t *ptr)
{
ptr += mac_fcf_lenght(header);//Skip FCF + DSN ptr += mac_fcf_lenght(header);//Skip FCF + DSN
ptr += mac_dst_address_length_with_panid(header); //Skip Dst panID & Address ptr += mac_dst_address_length_with_panid(header); //Skip Dst panID & Address
@ -354,17 +354,44 @@ uint16_t mac_header_get_src_panid(const mac_fcf_sequence_t *header, const uint8_
return common_read_16_bit_inverse(ptr); return common_read_16_bit_inverse(ptr);
} }
uint16_t mac_header_get_dst_panid(const mac_fcf_sequence_t *header, const uint8_t *ptr) static uint16_t mac_header_read_dst_pan(const mac_fcf_sequence_t *header, const uint8_t *ptr)
{ {
if (!header->DstPanPresents) {
return 0xffff;
}
ptr += mac_fcf_lenght(header);//Skip FCF + DSN ptr += mac_fcf_lenght(header);//Skip FCF + DSN
return common_read_16_bit_inverse(ptr); return common_read_16_bit_inverse(ptr);
} }
uint16_t mac_header_get_src_panid(const mac_fcf_sequence_t *header, const uint8_t *ptr, uint16_t configured_pan_id)
{
if (mac_header_pan_full_compressed(header)) {
return configured_pan_id;
}
if (!header->SrcPanPresents) {
if (!header->DstPanPresents) {
return 0xffff;
}
return mac_header_read_dst_pan(header, ptr);
}
return mac_header_read_src_pan(header, ptr);
}
uint16_t mac_header_get_dst_panid(const mac_fcf_sequence_t *header, const uint8_t *ptr, uint16_t configured_pan_id)
{
if (mac_header_pan_full_compressed(header)) {
return configured_pan_id;
}
if (!header->DstPanPresents) {
if (header->SrcPanPresents && header->frameVersion == MAC_FRAME_VERSION_2015 && header->DstAddrMode == MAC_ADDR_MODE_NONE) {
return mac_header_read_src_pan(header, ptr);
}
return 0xffff;
}
return mac_header_read_dst_pan(header, ptr);
}
void mac_header_get_src_address(const mac_fcf_sequence_t *header, const uint8_t *ptr, uint8_t *address_ptr) void mac_header_get_src_address(const mac_fcf_sequence_t *header, const uint8_t *ptr, uint8_t *address_ptr)
{ {

View File

@ -59,8 +59,8 @@ uint16_t mac_buffer_total_payload_length(struct mac_pre_build_frame *buffer);
/** /**
* Next function should only call when address mode is not MAC_ADDR_MODE_NONE and parsed proper header! * Next function should only call when address mode is not MAC_ADDR_MODE_NONE and parsed proper header!
*/ */
uint16_t mac_header_get_src_panid(const struct mac_fcf_sequence_s *header, const uint8_t *ptr); uint16_t mac_header_get_src_panid(const struct mac_fcf_sequence_s *header, const uint8_t *ptr, uint16_t configured_pan_id);
uint16_t mac_header_get_dst_panid(const struct mac_fcf_sequence_s *header, const uint8_t *ptr); uint16_t mac_header_get_dst_panid(const struct mac_fcf_sequence_s *header, const uint8_t *ptr, uint16_t configured_pan_id);
void mac_header_get_src_address(const struct mac_fcf_sequence_s *header, const uint8_t *ptr, uint8_t *address_ptr); void mac_header_get_src_address(const struct mac_fcf_sequence_s *header, const uint8_t *ptr, uint8_t *address_ptr);
void mac_header_get_dst_address(const struct mac_fcf_sequence_s *header, const uint8_t *ptr, uint8_t *address_ptr); void mac_header_get_dst_address(const struct mac_fcf_sequence_s *header, const uint8_t *ptr, uint8_t *address_ptr);
uint8_t mac_address_length(uint8_t address_mode); uint8_t mac_address_length(uint8_t address_mode);

View File

@ -134,7 +134,7 @@ uint8_t mac_indirect_data_req_handle(mac_pre_parsed_frame_t *buf, protocol_inter
comm_status.status = MLME_DATA_POLL_NOTIFICATION; comm_status.status = MLME_DATA_POLL_NOTIFICATION;
//Call com status //Call com status
comm_status.PANId = mac_header_get_dst_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf)); comm_status.PANId = mac_header_get_dst_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), mac_ptr->pan_id);
comm_status.DstAddrMode = buf->fcf_dsn.DstAddrMode;; comm_status.DstAddrMode = buf->fcf_dsn.DstAddrMode;;
mac_header_get_dst_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), comm_status.DstAddr); mac_header_get_dst_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), comm_status.DstAddr);
comm_status.SrcAddrMode = buf->fcf_dsn.SrcAddrMode; comm_status.SrcAddrMode = buf->fcf_dsn.SrcAddrMode;

View File

@ -70,6 +70,7 @@ static void mac_set_active_event(protocol_interface_rf_mac_setup_s *rf_mac_setup
static void mac_clear_active_event(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint8_t event_type); static void mac_clear_active_event(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint8_t event_type);
static bool mac_read_active_event(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint8_t event_type); static bool mac_read_active_event(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint8_t event_type);
static int8_t mcps_pd_data_cca_trig(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer); static int8_t mcps_pd_data_cca_trig(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer);
static void mac_pd_data_confirm_failure_handle(protocol_interface_rf_mac_setup_s *rf_mac_setup);
static int8_t mac_tasklet_event_handler = -1; static int8_t mac_tasklet_event_handler = -1;
@ -87,47 +88,18 @@ static uint32_t mac_mcps_sap_get_phy_timestamp(protocol_interface_rf_mac_setup_s
return timestamp; return timestamp;
} }
static void mac_data_request_init(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_pre_build_frame_t *buffer)
{
rf_mac_setup->active_pd_data_request = buffer;
if (buffer->asynch_request) {
buffer->asynch_channel = rf_mac_setup->mac_channel; //Store Original channel
uint16_t channel = mlme_scan_analyze_next_channel(&buffer->asynch_channel_list);
if (channel <= 0xff) {
uint8_t switch_channel = channel;
if (rf_mac_setup->mac_channel != switch_channel) {
mac_mlme_mac_radio_disabled(rf_mac_setup);
rf_mac_setup->mac_channel = channel;
mac_mlme_mac_radio_enable(rf_mac_setup);
}
}
}
}
static bool mac_data_request_confirmation_finnish(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_pre_build_frame_t *buffer) static bool mac_data_request_confirmation_finnish(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_pre_build_frame_t *buffer)
{ {
if (!buffer->asynch_request) { if (!buffer->asynch_request) {
return true; return true;
} }
uint16_t channel = mlme_scan_analyze_next_channel(&buffer->asynch_channel_list); if (mlme_scan_analyze_next_channel(&buffer->asynch_channel_list, false) > 0x00ff) {
uint8_t switch_channel; mac_mlme_rf_channel_change(rf_mac_setup, buffer->asynch_channel);
bool return_value; return true;
}
if (channel > 0x00ff) { return false;
return_value = true;
switch_channel = buffer->asynch_channel;
} else {
switch_channel = channel;
return_value = false;
}
//Set original Channel back if channel is switched
if (rf_mac_setup->mac_channel != switch_channel) {
mac_mlme_mac_radio_disabled(rf_mac_setup);
rf_mac_setup->mac_channel = switch_channel;
mac_mlme_mac_radio_enable(rf_mac_setup);
}
return return_value;
} }
@ -145,7 +117,6 @@ static void mac_data_poll_radio_disable_check(protocol_interface_rf_mac_setup_s
static void mcps_data_confirm_cb(protocol_interface_rf_mac_setup_s *rf_mac_setup, mcps_data_conf_t *confirm, mac_pre_parsed_frame_t *ack_buf) static void mcps_data_confirm_cb(protocol_interface_rf_mac_setup_s *rf_mac_setup, mcps_data_conf_t *confirm, mac_pre_parsed_frame_t *ack_buf)
{ {
mac_data_poll_radio_disable_check(rf_mac_setup); mac_data_poll_radio_disable_check(rf_mac_setup);
if( get_sw_mac_api(rf_mac_setup) ) { if( get_sw_mac_api(rf_mac_setup) ) {
@ -363,13 +334,14 @@ void mcps_sap_data_req_handler_ext(protocol_interface_rf_mac_setup_s *rf_mac_set
verify_status: verify_status:
if (status != MLME_SUCCESS){ if (status != MLME_SUCCESS){
mcps_data_conf_t confirm;
memset(&confirm, 0, sizeof(mcps_data_conf_t));
confirm.msduHandle = data_req->msduHandle;
confirm.status = status;
tr_debug("DATA REQ Fail %u", status); tr_debug("DATA REQ Fail %u", status);
rf_mac_setup->mac_mcps_data_conf_fail.msduHandle = data_req->msduHandle;
rf_mac_setup->mac_mcps_data_conf_fail.status = status;
mcps_sap_prebuild_frame_buffer_free(buffer); mcps_sap_prebuild_frame_buffer_free(buffer);
mcps_data_confirm_cb(rf_mac_setup, &confirm, NULL); if (mcps_sap_pd_confirm_failure(rf_mac_setup) != 0) {
// event sending failed, calling handler directly
mac_pd_data_confirm_failure_handle(rf_mac_setup);
}
} }
} }
@ -568,7 +540,7 @@ static uint8_t mac_data_interface_decrypt_packet(mac_pre_parsed_frame_t *b, mlme
//READ SRC Address //READ SRC Address
uint16_t SrcPANId = mac_header_get_src_panid(&b->fcf_dsn, mac_header_message_start_pointer(b)); uint16_t SrcPANId = mac_header_get_src_panid(&b->fcf_dsn, mac_header_message_start_pointer(b), rf_mac_setup->pan_id);
mac_header_get_src_address(&b->fcf_dsn, mac_header_message_start_pointer(b), neighbour_validation.address); mac_header_get_src_address(&b->fcf_dsn, mac_header_message_start_pointer(b), neighbour_validation.address);
neighbour_validation.addr_type = b->fcf_dsn.SrcAddrMode; neighbour_validation.addr_type = b->fcf_dsn.SrcAddrMode;
neighbour_validation.keyId = security_params->KeyIndex; neighbour_validation.keyId = security_params->KeyIndex;
@ -670,10 +642,11 @@ static uint8_t mac_data_interface_decrypt_packet(mac_pre_parsed_frame_t *b, mlme
static void mcps_comm_status_indication_generate(uint8_t status, mac_pre_parsed_frame_t *buf, mac_api_t * mac) static void mcps_comm_status_indication_generate(uint8_t status, mac_pre_parsed_frame_t *buf, mac_api_t * mac)
{ {
mlme_comm_status_t comm_status; mlme_comm_status_t comm_status;
protocol_interface_rf_mac_setup_s *rf_ptr = buf->mac_class_ptr;
memset(&comm_status,0 ,sizeof(mlme_comm_status_t) ); memset(&comm_status,0 ,sizeof(mlme_comm_status_t) );
comm_status.status = status; comm_status.status = status;
//Call com status //Call com status
comm_status.PANId = mac_header_get_dst_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf)); comm_status.PANId = mac_header_get_dst_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), rf_ptr->pan_id);
comm_status.DstAddrMode = buf->fcf_dsn.DstAddrMode;; comm_status.DstAddrMode = buf->fcf_dsn.DstAddrMode;;
mac_header_get_dst_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), comm_status.DstAddr); mac_header_get_dst_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), comm_status.DstAddr);
comm_status.SrcAddrMode = buf->fcf_dsn.SrcAddrMode; comm_status.SrcAddrMode = buf->fcf_dsn.SrcAddrMode;
@ -723,12 +696,14 @@ static int8_t mac_data_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inte
//Parse data //Parse data
data_ind->DSN = buf->fcf_dsn.DSN; data_ind->DSN = buf->fcf_dsn.DSN;
data_ind->DstAddrMode = buf->fcf_dsn.DstAddrMode; data_ind->DstAddrMode = buf->fcf_dsn.DstAddrMode;
data_ind->DstPANId = mac_header_get_dst_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf));
mac_header_get_dst_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), data_ind->DstAddr); mac_header_get_dst_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), data_ind->DstAddr);
data_ind->SrcAddrMode = buf->fcf_dsn.SrcAddrMode; data_ind->SrcAddrMode = buf->fcf_dsn.SrcAddrMode;
data_ind->SrcPANId = mac_header_get_src_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf));
mac_header_get_src_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), data_ind->SrcAddr); mac_header_get_src_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), data_ind->SrcAddr);
data_ind->SrcPANId = mac_header_get_src_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), rf_mac_setup->pan_id);
data_ind->DstPANId = mac_header_get_dst_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), rf_mac_setup->pan_id);
data_ind->mpduLinkQuality = buf->LQI; data_ind->mpduLinkQuality = buf->LQI;
data_ind->signal_dbm = buf->dbm; data_ind->signal_dbm = buf->dbm;
data_ind->timestamp = buf->timestamp; data_ind->timestamp = buf->timestamp;
@ -739,7 +714,6 @@ static int8_t mac_data_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inte
if (buf->fcf_dsn.securityEnabled) { if (buf->fcf_dsn.securityEnabled) {
status = mac_data_interface_decrypt_packet(buf, &data_ind->Key); status = mac_data_interface_decrypt_packet(buf, &data_ind->Key);
if (status != MLME_SUCCESS) { if (status != MLME_SUCCESS) {
tr_debug("Decrypt fail, %d", status);
mcps_comm_status_indication_generate(status, buf, mac); mcps_comm_status_indication_generate(status, buf, mac);
goto DROP_PACKET; goto DROP_PACKET;
} }
@ -772,6 +746,12 @@ static int8_t mac_data_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inte
ie_list.payloadIeListLength = buf->payloadsIeLength; ie_list.payloadIeListLength = buf->payloadsIeLength;
ie_list.headerIeList = buf->headerIePtr; ie_list.headerIeList = buf->headerIePtr;
ie_list.headerIeListLength = buf->headerIeLength; ie_list.headerIeListLength = buf->headerIeLength;
//Swap compressed address to broadcast when dst Address is elided
if (buf->fcf_dsn.DstAddrMode == MAC_ADDR_MODE_NONE) {
data_ind->DstAddrMode = MAC_ADDR_MODE_16_BIT;
data_ind->DstAddr[0] = 0xff;
data_ind->DstAddr[1] = 0xff;
}
mac->data_ind_ext_cb(mac, data_ind, &ie_list); mac->data_ind_ext_cb(mac, data_ind, &ie_list);
} else { } else {
@ -796,7 +776,7 @@ static void mac_lib_res_no_data_to_req(mac_pre_parsed_frame_t *buffer, protocol_
buf->fcf_dsn.SrcAddrMode = buffer->fcf_dsn.DstAddrMode; buf->fcf_dsn.SrcAddrMode = buffer->fcf_dsn.DstAddrMode;
buf->fcf_dsn.DstAddrMode = buffer->fcf_dsn.SrcAddrMode; buf->fcf_dsn.DstAddrMode = buffer->fcf_dsn.SrcAddrMode;
//SET PANID //SET PANID
buf->SrcPANId = mac_header_get_dst_panid(&buffer->fcf_dsn, mac_header_message_start_pointer(buffer)); buf->SrcPANId = mac_header_get_dst_panid(&buffer->fcf_dsn, mac_header_message_start_pointer(buffer), rf_mac_setup->pan_id);
buf->DstPANId = buf->SrcPANId; buf->DstPANId = buf->SrcPANId;
mac_header_get_dst_address(&buffer->fcf_dsn, mac_header_message_start_pointer(buffer), buf->SrcAddr); mac_header_get_dst_address(&buffer->fcf_dsn, mac_header_message_start_pointer(buffer), buf->SrcAddr);
@ -910,7 +890,7 @@ static void mac_data_interface_parse_beacon(mac_pre_parsed_frame_t *buf, protoco
uint8_t *pending_address_list = NULL; uint8_t *pending_address_list = NULL;
uint8_t SuperframeSpec[2]; uint8_t SuperframeSpec[2];
uint16_t src_pan_id = mac_header_get_src_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf)); uint16_t src_pan_id = mac_header_get_src_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), rf_mac_setup->pan_id);
//validate beacon pan-id and filter other network out //validate beacon pan-id and filter other network out
if (rf_mac_setup->pan_id < 0xffff && (rf_mac_setup->pan_id != src_pan_id && !rf_mac_setup->macAcceptAnyBeacon)) { if (rf_mac_setup->pan_id < 0xffff && (rf_mac_setup->pan_id != src_pan_id && !rf_mac_setup->macAcceptAnyBeacon)) {
@ -1045,6 +1025,14 @@ static void mac_data_interface_frame_handler(mac_pre_parsed_frame_t *buf)
} }
static void mac_mcps_asynch_finish(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_pre_build_frame_t *buffer)
{
if (buffer->asynch_request && rf_mac_setup->fhss_api) {
// Must return to scheduled channel after asynch process by calling TX done
rf_mac_setup->fhss_api->data_tx_done(rf_mac_setup->fhss_api, false, true, buffer->msduHandle);
}
}
void mac_mcps_trig_buffer_from_queue(protocol_interface_rf_mac_setup_s *rf_mac_setup) void mac_mcps_trig_buffer_from_queue(protocol_interface_rf_mac_setup_s *rf_mac_setup)
{ {
if (!rf_mac_setup) { if (!rf_mac_setup) {
@ -1064,9 +1052,10 @@ void mac_mcps_trig_buffer_from_queue(protocol_interface_rf_mac_setup_s *rf_mac_s
buffer = mcps_sap_pd_req_queue_read(rf_mac_setup, is_bc_queue, false); buffer = mcps_sap_pd_req_queue_read(rf_mac_setup, is_bc_queue, false);
if (buffer) { if (buffer) {
mac_data_request_init(rf_mac_setup, buffer); rf_mac_setup->active_pd_data_request = buffer;
if (mcps_pd_data_request(rf_mac_setup, buffer) != 0) { if (mcps_pd_data_request(rf_mac_setup, buffer) != 0) {
rf_mac_setup->active_pd_data_request = NULL; rf_mac_setup->active_pd_data_request = NULL;
mac_mcps_asynch_finish(rf_mac_setup, buffer);
mcps_data_confirm_handle(rf_mac_setup, buffer, NULL); mcps_data_confirm_handle(rf_mac_setup, buffer, NULL);
} else { } else {
return; return;
@ -1077,7 +1066,6 @@ void mac_mcps_trig_buffer_from_queue(protocol_interface_rf_mac_setup_s *rf_mac_s
} }
} }
static int8_t mac_ack_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_interface_rf_mac_setup_s *rf_mac_setup) static int8_t mac_ack_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_interface_rf_mac_setup_s *rf_mac_setup)
{ {
//allocate Data ind primitiv and parse packet to that //allocate Data ind primitiv and parse packet to that
@ -1106,20 +1094,18 @@ static int8_t mac_ack_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inter
return 0; return 0;
} }
static void mac_pd_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_mac_setup) { static void mac_pd_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_mac_setup)
{
if (rf_mac_setup->active_pd_data_request) { if (rf_mac_setup->active_pd_data_request) {
mac_pre_build_frame_t *buffer = rf_mac_setup->active_pd_data_request; mac_pre_build_frame_t *buffer = rf_mac_setup->active_pd_data_request;
if (mac_data_request_confirmation_finnish(rf_mac_setup, buffer) ) { if (mac_data_request_confirmation_finnish(rf_mac_setup, buffer) ) {
rf_mac_setup->active_pd_data_request = NULL; rf_mac_setup->active_pd_data_request = NULL;
if (buffer->asynch_request && rf_mac_setup->fhss_api) { mac_mcps_asynch_finish(rf_mac_setup, buffer);
// Must return to scheduled channel after asynch process by calling TX done
rf_mac_setup->fhss_api->data_tx_done(rf_mac_setup->fhss_api, false, true, buffer->msduHandle);
}
mcps_data_confirm_handle(rf_mac_setup, buffer, NULL); mcps_data_confirm_handle(rf_mac_setup, buffer, NULL);
} else { } else {
if (mcps_pd_data_request(rf_mac_setup, buffer) != 0) { if (mcps_pd_data_request(rf_mac_setup, buffer) != 0) {
rf_mac_setup->active_pd_data_request = NULL; rf_mac_setup->active_pd_data_request = NULL;
mac_mcps_asynch_finish(rf_mac_setup, buffer);
mcps_data_confirm_handle(rf_mac_setup, buffer, NULL); mcps_data_confirm_handle(rf_mac_setup, buffer, NULL);
} else { } else {
return; return;
@ -1130,9 +1116,17 @@ static void mac_pd_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_mac
mac_mcps_trig_buffer_from_queue(rf_mac_setup); mac_mcps_trig_buffer_from_queue(rf_mac_setup);
} }
static void mac_pd_data_confirm_failure_handle(protocol_interface_rf_mac_setup_s *rf_mac_setup)
{
mcps_data_conf_t mcps_data_conf;
memset(&mcps_data_conf, 0, sizeof(mcps_data_conf_t));
mcps_data_conf.msduHandle = rf_mac_setup->mac_mcps_data_conf_fail.msduHandle;
mcps_data_conf.status = rf_mac_setup->mac_mcps_data_conf_fail.status;
mcps_data_confirm_cb(rf_mac_setup, &mcps_data_conf, NULL);
}
static void mac_pd_data_ack_handler(mac_pre_parsed_frame_t *buf) { static void mac_pd_data_ack_handler(mac_pre_parsed_frame_t *buf)
{
protocol_interface_rf_mac_setup_s *rf_mac_setup = buf->mac_class_ptr; protocol_interface_rf_mac_setup_s *rf_mac_setup = buf->mac_class_ptr;
if (!rf_mac_setup->active_pd_data_request) { if (!rf_mac_setup->active_pd_data_request) {
@ -1147,10 +1141,6 @@ static void mac_pd_data_ack_handler(mac_pre_parsed_frame_t *buf) {
} }
rf_mac_setup->active_pd_data_request = NULL; rf_mac_setup->active_pd_data_request = NULL;
if (buffer->asynch_request && rf_mac_setup->fhss_api) {
// Must return to scheduled channel after asynch process by calling TX done
rf_mac_setup->fhss_api->data_tx_done(rf_mac_setup->fhss_api, false, true, buffer->msduHandle);
}
mcps_data_confirm_handle(rf_mac_setup, buffer, buf); mcps_data_confirm_handle(rf_mac_setup, buffer, buf);
mcps_sap_pre_parsed_frame_buffer_free(buf); mcps_sap_pre_parsed_frame_buffer_free(buf);
@ -1177,6 +1167,10 @@ static void mac_mcps_sap_data_tasklet(arm_event_s *event)
mac_pd_data_confirm_handle((protocol_interface_rf_mac_setup_s*)event->data_ptr); mac_pd_data_confirm_handle((protocol_interface_rf_mac_setup_s*)event->data_ptr);
break; break;
case MCPS_SAP_DATA_CNF_FAIL_EVENT:
mac_pd_data_confirm_failure_handle((protocol_interface_rf_mac_setup_s*)event->data_ptr);
break;
case MCPS_SAP_DATA_ACK_CNF_EVENT: case MCPS_SAP_DATA_ACK_CNF_EVENT:
mac_pd_data_ack_handler((mac_pre_parsed_frame_t*)event->data_ptr); mac_pd_data_ack_handler((mac_pre_parsed_frame_t*)event->data_ptr);
break; break;
@ -1277,16 +1271,10 @@ static bool mac_frame_security_parameters_init(ccm_globals_t *ccm_ptr, protocol_
if (buffer->fcf_dsn.DstAddrMode && buffer->fcf_dsn.ackRequested) { if (buffer->fcf_dsn.DstAddrMode && buffer->fcf_dsn.ackRequested) {
device_description = mac_sec_mib_device_description_get(rf_ptr, buffer->DstAddr, buffer->fcf_dsn.DstAddrMode); device_description = mac_sec_mib_device_description_get(rf_ptr, buffer->DstAddr, buffer->fcf_dsn.DstAddrMode);
if (!device_description) { if (!device_description) {
if (rf_ptr->mac_security_bypass_unknow_device && (buffer->fcf_dsn.SrcAddrMode == MAC_ADDR_MODE_64_BIT
&& buffer->aux_header.securityLevel > AES_SECURITY_LEVEL_ENC)) {
} else {
buffer->status = MLME_UNAVAILABLE_KEY; buffer->status = MLME_UNAVAILABLE_KEY;
return false; return false;
} }
} }
}
nonce_ext_64_ptr = rf_ptr->mac64; nonce_ext_64_ptr = rf_ptr->mac64;
} }
@ -1350,7 +1338,11 @@ static void mac_common_data_confirmation_handle (protocol_interface_rf_mac_setup
//Enable Radio //Enable Radio
mac_mlme_mac_radio_enable(rf_mac_setup); mac_mlme_mac_radio_enable(rf_mac_setup);
buf->status = MLME_TRANSACTION_EXPIRED; buf->status = MLME_TRANSACTION_EXPIRED;
} } else if (m_event == MAC_UNKNOWN_DESTINATION) {
buf->status = MLME_UNAVAILABLE_KEY;
}/** else if (m_event == MAC_TX_PRECOND_FAIL) {
* Nothing to do, status already set to buf->status.
}**/
} }
} }
@ -1419,7 +1411,7 @@ static void mcps_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_ptr,
sw_mac_stats_update(rf_ptr, STAT_MAC_TX_CCA_ATT, rf_ptr->mac_tx_status.cca_cnt); sw_mac_stats_update(rf_ptr, STAT_MAC_TX_CCA_ATT, rf_ptr->mac_tx_status.cca_cnt);
sw_mac_stats_update(rf_ptr, STAT_MAC_TX_RETRY, rf_ptr->mac_tx_status.retry); sw_mac_stats_update(rf_ptr, STAT_MAC_TX_RETRY, rf_ptr->mac_tx_status.retry);
mcps_data_conf_t confirm; mcps_data_conf_t confirm;
if (rf_ptr->fhss_api) { if (rf_ptr->fhss_api && !buffer->asynch_request) {
// FHSS checks if this failed buffer needs to be pushed back to TX queue and retransmitted // FHSS checks if this failed buffer needs to be pushed back to TX queue and retransmitted
if ((rf_ptr->mac_tx_result == MAC_TX_FAIL) || (rf_ptr->mac_tx_result == MAC_CCA_FAIL)) { if ((rf_ptr->mac_tx_result == MAC_TX_FAIL) || (rf_ptr->mac_tx_result == MAC_CCA_FAIL)) {
if (rf_ptr->fhss_api->data_tx_fail(rf_ptr->fhss_api, buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype)) == true) { if (rf_ptr->fhss_api->data_tx_fail(rf_ptr->fhss_api, buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype)) == true) {
@ -1615,6 +1607,7 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const m
buffer->fcf_dsn.frameVersion = fcf->frameVersion; buffer->fcf_dsn.frameVersion = fcf->frameVersion;
buffer->fcf_dsn.framePending = rf_ptr->mac_frame_pending; buffer->fcf_dsn.framePending = rf_ptr->mac_frame_pending;
buffer->fcf_dsn.DSN = fcf->DSN; buffer->fcf_dsn.DSN = fcf->DSN;
buffer->fcf_dsn.intraPan = fcf->intraPan;
buffer->fcf_dsn.sequenceNumberSuppress = fcf->sequenceNumberSuppress; buffer->fcf_dsn.sequenceNumberSuppress = fcf->sequenceNumberSuppress;
buffer->fcf_dsn.DstPanPresents = fcf->DstPanPresents; buffer->fcf_dsn.DstPanPresents = fcf->DstPanPresents;
buffer->fcf_dsn.SrcAddrMode = fcf->DstAddrMode; buffer->fcf_dsn.SrcAddrMode = fcf->DstAddrMode;
@ -1628,9 +1621,8 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const m
buffer->mac_header_length_with_security += mac_header_address_length(&buffer->fcf_dsn); buffer->mac_header_length_with_security += mac_header_address_length(&buffer->fcf_dsn);
buffer->DstPANId = mac_header_get_src_panid(fcf, data_ptr); buffer->DstPANId = mac_header_get_src_panid(fcf, data_ptr, rf_ptr->pan_id);
buffer->SrcPANId = mac_header_get_dst_panid(fcf, data_ptr); buffer->SrcPANId = mac_header_get_dst_panid(fcf, data_ptr, rf_ptr->pan_id);
mac_header_get_src_address(fcf, data_ptr, buffer->DstAddr); mac_header_get_src_address(fcf, data_ptr, buffer->DstAddr);
mac_header_get_dst_address(fcf, data_ptr, buffer->SrcAddr); mac_header_get_dst_address(fcf, data_ptr, buffer->SrcAddr);
@ -1696,7 +1688,15 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const m
//Add MHR length to total length //Add MHR length to total length
frame_length += buffer->mac_header_length_with_security + buffer->security_mic_len; frame_length += buffer->mac_header_length_with_security + buffer->security_mic_len;
if ((frame_length) > dev_driver->phy_MTU - 2) { uint16_t ack_mtu_size;
if (ENHANCED_ACK_MAX_LENGTH > dev_driver->phy_MTU) {
ack_mtu_size = dev_driver->phy_MTU;
} else {
ack_mtu_size = ENHANCED_ACK_MAX_LENGTH;
}
if ((frame_length) > ack_mtu_size - 2) {
buffer->status = MLME_FRAME_TOO_LONG; buffer->status = MLME_FRAME_TOO_LONG;
if (buffer->fcf_dsn.securityEnabled) { if (buffer->fcf_dsn.securityEnabled) {
@ -1708,14 +1708,14 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const m
} }
rf_ptr->mac_tx_status.length = frame_length; rf_ptr->mac_tx_status.length = frame_length;
uint8_t *ptr = tx_buf->buf; uint8_t *ptr = tx_buf->enhanced_ack_buf;
if (dev_driver->phy_header_length) { if (dev_driver->phy_header_length) {
ptr += dev_driver->phy_header_length; ptr += dev_driver->phy_header_length;
} }
tx_buf->len = frame_length; tx_buf->ack_len = frame_length;
uint8_t *mhr_start = ptr; uint8_t *mhr_start = ptr;
buffer->tx_time = rx_time + 196; //Send 196 us later buffer->tx_time = mac_mcps_sap_get_phy_timestamp(rf_ptr) + 300; //Send 300 us later
ptr = mac_generic_packet_write(rf_ptr, ptr, buffer); ptr = mac_generic_packet_write(rf_ptr, ptr, buffer);
@ -1731,9 +1731,9 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, const m
csma_params.cca_enabled = false; csma_params.cca_enabled = false;
rf_ptr->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CSMA_PARAMETERS, (uint8_t*) &csma_params); rf_ptr->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CSMA_PARAMETERS, (uint8_t*) &csma_params);
if (rf_ptr->active_pd_data_request) { if (rf_ptr->active_pd_data_request) {
timer_mac_stop(rf_ptr);
mac_pd_sap_set_phy_tx_time(rf_ptr, 0, false); mac_pd_sap_set_phy_tx_time(rf_ptr, 0, false);
} }
return mcps_pd_data_cca_trig(rf_ptr, buffer); return mcps_pd_data_cca_trig(rf_ptr, buffer);
} }
@ -1803,6 +1803,7 @@ static int8_t mcps_generic_packet_rebuild(protocol_interface_rf_mac_setup_s *rf_
static int8_t mcps_pd_data_cca_trig(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer) static int8_t mcps_pd_data_cca_trig(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer)
{ {
platform_enter_critical();
mac_mlme_mac_radio_enable(rf_ptr); mac_mlme_mac_radio_enable(rf_ptr);
rf_ptr->macTxProcessActive = true; rf_ptr->macTxProcessActive = true;
if (rf_ptr->rf_csma_extension_supported) { if (rf_ptr->rf_csma_extension_supported) {
@ -1810,18 +1811,35 @@ static int8_t mcps_pd_data_cca_trig(protocol_interface_rf_mac_setup_s *rf_ptr, m
bool cca_enabled; bool cca_enabled;
if (buffer->fcf_dsn.frametype == MAC_FRAME_ACK) { if (buffer->fcf_dsn.frametype == MAC_FRAME_ACK) {
cca_enabled = false; cca_enabled = false;
rf_ptr->mac_ack_tx_active = true;
} else { } else {
if (rf_ptr->mac_ack_tx_active) {
mac_csma_backoff_start(rf_ptr);
platform_exit_critical();
return -1;
}
cca_enabled = true; cca_enabled = true;
} }
mac_pd_sap_set_phy_tx_time(rf_ptr, buffer->tx_time, cca_enabled); mac_pd_sap_set_phy_tx_time(rf_ptr, buffer->tx_time, cca_enabled);
if (mac_plme_cca_req(rf_ptr) != 0) { if (mac_plme_cca_req(rf_ptr) != 0) {
if (buffer->fcf_dsn.frametype == MAC_FRAME_ACK) {
rf_ptr->mac_ack_tx_active = false;
// For Ack, stop the active TX process
rf_ptr->macTxProcessActive = false; rf_ptr->macTxProcessActive = false;
// If MAC had TX process active before Ack transmission,
// the TX process has to be restarted in case the Ack transmission failed.
if (rf_ptr->active_pd_data_request) {
mac_csma_backoff_start(rf_ptr);
}
platform_exit_critical();
return -1; return -1;
} }
mac_csma_backoff_start(rf_ptr);
}
} else { } else {
timer_mac_start(rf_ptr, MAC_TIMER_CCA, (uint16_t)(buffer->tx_time / 50)); timer_mac_start(rf_ptr, MAC_TIMER_CCA, (uint16_t)(buffer->tx_time / 50));
} }
platform_exit_critical();
return 0; return 0;
} }
@ -1891,19 +1909,18 @@ void mcps_sap_pd_req_queue_write(protocol_interface_rf_mac_setup_s *rf_mac_setup
} }
} }
//Start TX process immediately //Start TX process immediately
mac_data_request_init(rf_mac_setup, buffer); rf_mac_setup->active_pd_data_request = buffer;
if (mcps_pd_data_request(rf_mac_setup, buffer) != 0) { if (mcps_pd_data_request(rf_mac_setup, buffer) != 0) {
rf_mac_setup->active_pd_data_request = NULL; rf_mac_setup->mac_tx_result = MAC_TX_PRECOND_FAIL;
mcps_data_conf_t confirm; rf_mac_setup->macTxRequestAck = false;
memset(&confirm, 0, sizeof(mcps_data_conf_t)); if (mcps_sap_pd_confirm(rf_mac_setup) != 0) {
confirm.msduHandle = buffer->msduHandle; // can't send event, try calling error handler directly
confirm.status = buffer->status; rf_mac_setup->mac_mcps_data_conf_fail.msduHandle = buffer->msduHandle;
bool requested_from_up = buffer->upper_layer_request; rf_mac_setup->mac_mcps_data_conf_fail.status = buffer->status;
mcps_sap_prebuild_frame_buffer_free(buffer); mcps_sap_prebuild_frame_buffer_free(buffer);
if (requested_from_up) { rf_mac_setup->active_pd_data_request = NULL;
mcps_data_confirm_cb(rf_mac_setup, &confirm, NULL); mac_pd_data_confirm_failure_handle(rf_mac_setup);
} }
//Call
} }
return; return;
@ -1981,7 +1998,7 @@ static mac_pre_build_frame_t * mcps_sap_pd_req_queue_read(protocol_interface_rf_
// With FHSS, check TX conditions // With FHSS, check TX conditions
if (rf_mac_setup->fhss_api) { if (rf_mac_setup->fhss_api) {
while (buffer) { while (buffer) {
if ((flush == true) || (rf_mac_setup->fhss_api->check_tx_conditions(rf_mac_setup->fhss_api, !mac_is_ack_request_set(buffer), if (buffer->asynch_request || (flush == true) || (rf_mac_setup->fhss_api->check_tx_conditions(rf_mac_setup->fhss_api, !mac_is_ack_request_set(buffer),
buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype), buffer->mac_payload_length, buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype), buffer->mac_payload_length,
rf_mac_setup->dev_driver->phy_driver->phy_header_length, rf_mac_setup->dev_driver->phy_driver->phy_tail_length) == true)) { rf_mac_setup->dev_driver->phy_driver->phy_header_length, rf_mac_setup->dev_driver->phy_driver->phy_tail_length) == true)) {
break; break;
@ -2083,10 +2100,10 @@ int8_t mcps_sap_pd_ind(mac_pre_parsed_frame_t *buffer)
return eventOS_event_send(&event); return eventOS_event_send(&event);
} }
void mcps_sap_pd_confirm(void *mac_ptr) int8_t mcps_sap_pd_confirm(void *mac_ptr)
{ {
if (mac_tasklet_event_handler < 0 || !mac_ptr) { if (mac_tasklet_event_handler < 0 || !mac_ptr) {
return; return -2;
} }
arm_event_s event = { arm_event_s event = {
.receiver = mac_tasklet_event_handler, .receiver = mac_tasklet_event_handler,
@ -2097,8 +2114,24 @@ void mcps_sap_pd_confirm(void *mac_ptr)
.priority = ARM_LIB_HIGH_PRIORITY_EVENT, .priority = ARM_LIB_HIGH_PRIORITY_EVENT,
}; };
eventOS_event_send(&event); return eventOS_event_send(&event);
}
int8_t mcps_sap_pd_confirm_failure(void *mac_ptr)
{
if (mac_tasklet_event_handler < 0 || !mac_ptr) {
return -2;
}
arm_event_s event = {
.receiver = mac_tasklet_event_handler,
.sender = 0,
.event_id = 0,
.data_ptr = mac_ptr,
.event_type = MCPS_SAP_DATA_CNF_FAIL_EVENT,
.priority = ARM_LIB_HIGH_PRIORITY_EVENT,
};
return eventOS_event_send(&event);
} }
void mcps_sap_pd_ack(void *ack_ptr) void mcps_sap_pd_ack(void *ack_ptr)
@ -2226,17 +2259,14 @@ static bool mcps_sap_purge_req_from_queue(protocol_interface_rf_mac_setup_s *rf_
uint8_t status = false; uint8_t status = false;
rf_mac_setup->pd_data_request_queue_to_go = mcps_sap_purge_from_list(rf_mac_setup->pd_data_request_queue_to_go, msduhandle, &status); rf_mac_setup->pd_data_request_queue_to_go = mcps_sap_purge_from_list(rf_mac_setup->pd_data_request_queue_to_go, msduhandle, &status);
if (status) { if (!status) {
return true;
}
rf_mac_setup->indirect_pd_data_request_queue = mcps_sap_purge_from_list(rf_mac_setup->indirect_pd_data_request_queue, msduhandle, &status); rf_mac_setup->indirect_pd_data_request_queue = mcps_sap_purge_from_list(rf_mac_setup->indirect_pd_data_request_queue, msduhandle, &status);
}
return status; return status;
} }
void mcps_sap_purge_reg_handler(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mcps_purge_t *purge_req) uint8_t mcps_sap_purge_reg_handler(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mcps_purge_t *purge_req)
{ {
mcps_purge_conf_t confirmation; mcps_purge_conf_t confirmation;
confirmation.msduHandle = purge_req->msduHandle; confirmation.msduHandle = purge_req->msduHandle;
@ -2250,4 +2280,6 @@ void mcps_sap_purge_reg_handler(protocol_interface_rf_mac_setup_s *rf_mac_setup,
if( get_sw_mac_api(rf_mac_setup) ) { if( get_sw_mac_api(rf_mac_setup) ) {
get_sw_mac_api(rf_mac_setup)->purge_conf_cb(get_sw_mac_api(rf_mac_setup), &confirmation); get_sw_mac_api(rf_mac_setup)->purge_conf_cb(get_sw_mac_api(rf_mac_setup), &confirmation);
} }
return confirmation.status;
} }

View File

@ -50,12 +50,12 @@ typedef enum {
#define MCPS_SAP_DATA_IND_EVENT 1 #define MCPS_SAP_DATA_IND_EVENT 1
#define MCPS_SAP_DATA_CNF_EVENT 2 #define MCPS_SAP_DATA_CNF_EVENT 2
#define MAC_MLME_EVENT_HANDLER 3 #define MCPS_SAP_DATA_CNF_FAIL_EVENT 3
#define MAC_MCPS_INDIRECT_TIMER_CB 4 #define MAC_MLME_EVENT_HANDLER 4
#define MAC_MLME_SCAN_CONFIRM_HANDLER 5 #define MAC_MCPS_INDIRECT_TIMER_CB 5
#define MAC_SAP_TRIG_TX 6 #define MAC_MLME_SCAN_CONFIRM_HANDLER 6
#define MCPS_SAP_DATA_ACK_CNF_EVENT 7 #define MAC_SAP_TRIG_TX 7
#define MCPS_SAP_DATA_ACK_CNF_EVENT 8
/** /**
* @brief struct mac_aux_security_header_t MAC auxiliarity security header structure * @brief struct mac_aux_security_header_t MAC auxiliarity security header structure
@ -180,7 +180,9 @@ int8_t mcps_sap_pd_ind(mac_pre_parsed_frame_t *buffer);
/** /**
* MAC MCPS SAP layer data confirmation event trig * MAC MCPS SAP layer data confirmation event trig
*/ */
void mcps_sap_pd_confirm(void *mac_ptr); int8_t mcps_sap_pd_confirm(void *mac_ptr);
int8_t mcps_sap_pd_confirm_failure(void *mac_ptr);
void mcps_sap_pd_ack(void *ack_ptr); void mcps_sap_pd_ack(void *ack_ptr);
@ -200,7 +202,7 @@ int mac_convert_frame_type_to_fhss(uint8_t frame_type);
void mcps_sap_trig_tx(void *mac_ptr); void mcps_sap_trig_tx(void *mac_ptr);
void mcps_sap_purge_reg_handler(struct protocol_interface_rf_mac_setup *rf_mac_setup, const struct mcps_purge_s *purge_req); uint8_t mcps_sap_purge_reg_handler(struct protocol_interface_rf_mac_setup *rf_mac_setup, const struct mcps_purge_s *purge_req);
int8_t mcps_pd_data_rebuild(struct protocol_interface_rf_mac_setup *rf_ptr, mac_pre_build_frame_t *buffer); int8_t mcps_pd_data_rebuild(struct protocol_interface_rf_mac_setup *rf_ptr, mac_pre_build_frame_t *buffer);

View File

@ -85,7 +85,7 @@ static void mac_mlme_energy_scan_start(protocol_interface_rf_mac_setup_s *rf_mac
rf_mac_setup->macRfRadioTxActive = false; rf_mac_setup->macRfRadioTxActive = false;
} }
uint16_t mlme_scan_analyze_next_channel(channel_list_s *mac_channel_list) uint16_t mlme_scan_analyze_next_channel(channel_list_s *mac_channel_list, bool clear_channel)
{ {
uint8_t i, j = 0, k = 1; uint8_t i, j = 0, k = 1;
uint32_t mask = 1; uint32_t mask = 1;
@ -101,7 +101,9 @@ uint16_t mlme_scan_analyze_next_channel(channel_list_s *mac_channel_list)
{ {
if (*channel_mask & mask) if (*channel_mask & mask)
{ {
if (clear_channel) {
*channel_mask &= ~mask; *channel_mask &= ~mask;
}
return (i+j*32); return (i+j*32);
} }
mask <<= 1; mask <<= 1;
@ -280,7 +282,7 @@ static void mac_mlme_scan_start(protocol_interface_rf_mac_setup_s *rf_mac_setup)
{ {
uint8_t channel; uint8_t channel;
channel = (uint8_t) mlme_scan_analyze_next_channel(&rf_mac_setup->mac_channel_list); channel = (uint8_t) mlme_scan_analyze_next_channel(&rf_mac_setup->mac_channel_list, true);
mac_mlme_scan_init(channel, rf_mac_setup); mac_mlme_scan_init(channel, rf_mac_setup);
} }
@ -400,14 +402,14 @@ int8_t mac_mlme_start_req(const mlme_start_t *s, struct protocol_interface_rf_ma
tr_debug("MAC: Start network %u channel %x panid", s->LogicalChannel, s->PANId); tr_debug("MAC: Start network %u channel %x panid", s->LogicalChannel, s->PANId);
mac_mlme_set_panid(rf_mac_setup, s->PANId); mac_mlme_set_panid(rf_mac_setup, s->PANId);
// Synchronize FHSS // Synchronize FHSS
if (rf_mac_setup->fhss_api) { if (rf_mac_setup->fhss_api) {
rf_mac_setup->fhss_api->synch_state_set(rf_mac_setup->fhss_api, FHSS_SYNCHRONIZED, s->PANId); rf_mac_setup->mac_channel = rf_mac_setup->fhss_api->synch_state_set(rf_mac_setup->fhss_api, FHSS_SYNCHRONIZED, s->PANId);
} } else {
if (!rf_mac_setup->fhss_api) {
rf_mac_setup->mac_channel = s->LogicalChannel; rf_mac_setup->mac_channel = s->LogicalChannel;
} }
mac_mlme_start_request(rf_mac_setup); mac_mlme_start_request(rf_mac_setup);
if (s->PANCoordinator) { if (s->PANCoordinator) {
//tr_debug("Cordinator"); //tr_debug("Cordinator");
@ -795,7 +797,7 @@ static void mlme_scan_operation(protocol_interface_rf_mac_setup_s *rf_mac_setup)
resp->ResultListSize++; resp->ResultListSize++;
} }
channel = mlme_scan_analyze_next_channel(&rf_mac_setup->mac_channel_list); channel = mlme_scan_analyze_next_channel(&rf_mac_setup->mac_channel_list, true);
if (channel > 0xff || rf_mac_setup->mac_mlme_scan_resp->ResultListSize == MLME_MAC_RES_SIZE_MAX) { if (channel > 0xff || rf_mac_setup->mac_mlme_scan_resp->ResultListSize == MLME_MAC_RES_SIZE_MAX) {
resp->status = MLME_SUCCESS; resp->status = MLME_SUCCESS;
tr_debug("Scan Complete..Halt MAC"); tr_debug("Scan Complete..Halt MAC");
@ -981,6 +983,7 @@ void mac_mlme_data_base_deallocate(struct protocol_interface_rf_mac_setup *rf_ma
eventOS_callback_timer_unregister(rf_mac->mac_mcps_timer); eventOS_callback_timer_unregister(rf_mac->mac_mcps_timer);
ns_dyn_mem_free(rf_mac->dev_driver_tx_buffer.buf); ns_dyn_mem_free(rf_mac->dev_driver_tx_buffer.buf);
ns_dyn_mem_free(rf_mac->dev_driver_tx_buffer.enhanced_ack_buf);
ns_dyn_mem_free(rf_mac->mac_beacon_payload); ns_dyn_mem_free(rf_mac->mac_beacon_payload);
mac_sec_mib_deinit(rf_mac); mac_sec_mib_deinit(rf_mac);
@ -1510,8 +1513,9 @@ int8_t mac_mlme_rf_channel_change(protocol_interface_rf_mac_setup_s *rf_mac_setu
return 0; return 0;
} }
platform_enter_critical(); platform_enter_critical();
if (rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CHANNEL, &new_channel) == 0) {
rf_mac_setup->mac_channel = new_channel; rf_mac_setup->mac_channel = new_channel;
rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CHANNEL, &rf_mac_setup->mac_channel); }
platform_exit_critical(); platform_exit_critical();
return 0; return 0;
} }

View File

@ -125,6 +125,6 @@ int8_t mac_mlme_beacon_tx(struct protocol_interface_rf_mac_setup *rf_ptr);
uint8_t mac_mlme_beacon_req_tx(struct protocol_interface_rf_mac_setup *rf_ptr); uint8_t mac_mlme_beacon_req_tx(struct protocol_interface_rf_mac_setup *rf_ptr);
int8_t mac_mlme_virtual_confirmation_handle(int8_t driver_id, const uint8_t *data_ptr, uint16_t length); int8_t mac_mlme_virtual_confirmation_handle(int8_t driver_id, const uint8_t *data_ptr, uint16_t length);
uint16_t mlme_scan_analyze_next_channel(struct channel_list_s *mac_channel_list); uint16_t mlme_scan_analyze_next_channel(struct channel_list_s *mac_channel_list, bool clear_channel);
#endif /* MAC_MLME_H_ */ #endif /* MAC_MLME_H_ */

View File

@ -38,8 +38,13 @@
/* Define TX Timeot Period */ /* Define TX Timeot Period */
// Hardcoded to 1200ms. Should be changed dynamic: (FHSS) channel retries needs longer timeout // Hardcoded to 1200ms. Should be changed dynamic: (FHSS) channel retries needs longer timeout
#define NWKTX_TIMEOUT_PERIOD (1200*20) #define NWKTX_TIMEOUT_PERIOD (1200*20)
// Measured 3750us with 1280 byte secured packet from calculating TX time to starting CSMA timer on PHY.
// Typically varies from 500us to several milliseconds depending on packet size and the platform.
// MAC should learn and make this dynamic by sending first few packets with predefined CSMA period.
#define MIN_FHSS_CSMA_PERIOD_US 4000
static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *rf_ptr, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry); static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *rf_ptr, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry);
static void mac_sap_cca_fail_cb(protocol_interface_rf_mac_setup_s *rf_ptr);
void mac_csma_param_init(protocol_interface_rf_mac_setup_s *rf_mac_setup) void mac_csma_param_init(protocol_interface_rf_mac_setup_s *rf_mac_setup)
{ {
@ -64,7 +69,7 @@ static uint16_t mac_csma_backoff_period_convert_to50us(uint8_t random, uint8_t b
return (random * backoff_period_in_10us) / 5; return (random * backoff_period_in_10us) / 5;
} }
static void mac_csma_backoff_start(protocol_interface_rf_mac_setup_s *rf_mac_setup) void mac_csma_backoff_start(protocol_interface_rf_mac_setup_s *rf_mac_setup)
{ {
uint8_t backoff = mac_csma_random_backoff_get(rf_mac_setup); uint8_t backoff = mac_csma_random_backoff_get(rf_mac_setup);
uint16_t backoff_slots = mac_csma_backoff_period_convert_to50us(backoff, rf_mac_setup->backoff_period_in_10us); uint16_t backoff_slots = mac_csma_backoff_period_convert_to50us(backoff, rf_mac_setup->backoff_period_in_10us);
@ -90,6 +95,13 @@ uint32_t mac_csma_backoff_get(protocol_interface_rf_mac_setup_s *rf_mac_setup)
if (backoff_in_us == 0) { if (backoff_in_us == 0) {
backoff_in_us = 1; backoff_in_us = 1;
} }
if (rf_mac_setup->fhss_api) {
// Synchronization error when backoff time is shorter than allowed.
// TODO: Make this dynamic.
if (backoff_in_us < MIN_FHSS_CSMA_PERIOD_US) {
backoff_in_us += MIN_FHSS_CSMA_PERIOD_US;
}
}
return backoff_in_us; return backoff_in_us;
} }
@ -136,21 +148,31 @@ int8_t mac_plme_cca_req(protocol_interface_rf_mac_setup_s *rf_mac_setup) {
dev_driver_tx_buffer_s *tx_buf = &rf_mac_setup->dev_driver_tx_buffer; dev_driver_tx_buffer_s *tx_buf = &rf_mac_setup->dev_driver_tx_buffer;
phy_device_driver_s *dev_driver = rf_mac_setup->dev_driver->phy_driver; phy_device_driver_s *dev_driver = rf_mac_setup->dev_driver->phy_driver;
rf_mac_setup->macRfRadioTxActive = true;
if (dev_driver->arm_net_virtual_tx_cb) { if (dev_driver->arm_net_virtual_tx_cb) {
if (dev_driver->tx(tx_buf->buf, tx_buf->len, 1, PHY_LAYER_PAYLOAD) == 0) { if (dev_driver->tx(tx_buf->buf, tx_buf->len, 1, PHY_LAYER_PAYLOAD) == 0) {
rf_mac_setup->macRfRadioTxActive = true;
timer_mac_start(rf_mac_setup, MAC_TX_TIMEOUT, NWKTX_TIMEOUT_PERIOD); /*Start Timeout timer for virtual packet loss*/ timer_mac_start(rf_mac_setup, MAC_TX_TIMEOUT, NWKTX_TIMEOUT_PERIOD); /*Start Timeout timer for virtual packet loss*/
} else { } else {
rf_mac_setup->macRfRadioTxActive = false;
mac_data_interface_tx_to_cb(rf_mac_setup); mac_data_interface_tx_to_cb(rf_mac_setup);
} }
return 0; return 0;
} }
if (dev_driver->tx(tx_buf->buf, tx_buf->len, 1, PHY_LAYER_PAYLOAD) == 0) { uint8_t *buffer;
rf_mac_setup->macRfRadioTxActive = true; uint16_t length;
if (rf_mac_setup->mac_ack_tx_active) {
buffer = tx_buf->enhanced_ack_buf;
length = tx_buf->ack_len;
} else {
buffer = tx_buf->buf;
length = tx_buf->len;
}
if (dev_driver->tx(buffer, length, 1, PHY_LAYER_PAYLOAD) == 0) {
return 0; return 0;
} }
rf_mac_setup->macRfRadioTxActive = false;
return -1; return -1;
} }
@ -219,6 +241,12 @@ void mac_pd_sap_state_machine(protocol_interface_rf_mac_setup_s *rf_mac_setup)
if (rf_mac_setup->macUpState && rf_mac_setup->macTxProcessActive) { if (rf_mac_setup->macUpState && rf_mac_setup->macTxProcessActive) {
if (rf_mac_setup->mac_tx_result == MAC_TIMER_CCA) { if (rf_mac_setup->mac_tx_result == MAC_TIMER_CCA) {
if (rf_mac_setup->rf_csma_extension_supported) {
mac_sap_cca_fail_cb(rf_mac_setup);
return;
}
if (rf_mac_setup->fhss_api) { if (rf_mac_setup->fhss_api) {
uint8_t *synch_info = NULL; uint8_t *synch_info = NULL;
mac_pre_build_frame_t *active_buf = rf_mac_setup->active_pd_data_request; mac_pre_build_frame_t *active_buf = rf_mac_setup->active_pd_data_request;
@ -254,6 +282,9 @@ void mac_pd_sap_state_machine(protocol_interface_rf_mac_setup_s *rf_mac_setup)
if (tx_handle_retval == -3) { if (tx_handle_retval == -3) {
mac_tx_done_state_set(rf_mac_setup, MAC_CCA_FAIL); mac_tx_done_state_set(rf_mac_setup, MAC_CCA_FAIL);
return; return;
} else if (tx_handle_retval == -2) {
mac_tx_done_state_set(rf_mac_setup, MAC_UNKNOWN_DESTINATION);
return;
} }
} }
if (mac_plme_cca_req(rf_mac_setup) != 0) { if (mac_plme_cca_req(rf_mac_setup) != 0) {
@ -267,7 +298,14 @@ void mac_pd_sap_state_machine(protocol_interface_rf_mac_setup_s *rf_mac_setup)
} }
} }
static void mac_sap_cca_fail_cb(protocol_interface_rf_mac_setup_s *rf_ptr) { static void mac_sap_cca_fail_cb(protocol_interface_rf_mac_setup_s *rf_ptr)
{
if (rf_ptr->mac_ack_tx_active) {
if (rf_ptr->active_pd_data_request) {
mac_csma_backoff_start(rf_ptr);
}
} else {
rf_ptr->macRfRadioTxActive = false; rf_ptr->macRfRadioTxActive = false;
if (rf_ptr->mac_cca_retry > rf_ptr->macMaxCSMABackoffs || (rf_ptr->active_pd_data_request && rf_ptr->active_pd_data_request->asynch_request)) { if (rf_ptr->mac_cca_retry > rf_ptr->macMaxCSMABackoffs || (rf_ptr->active_pd_data_request && rf_ptr->active_pd_data_request->asynch_request)) {
//Send MAC_CCA_FAIL //Send MAC_CCA_FAIL
@ -280,6 +318,7 @@ static void mac_sap_cca_fail_cb(protocol_interface_rf_mac_setup_s *rf_ptr) {
} }
} }
} }
}
//static uint16_t mac_get_retry_period(protocol_interface_rf_mac_setup_s *rf_ptr) //static uint16_t mac_get_retry_period(protocol_interface_rf_mac_setup_s *rf_ptr)
//{ //{
@ -322,6 +361,20 @@ static bool mac_data_counter_too_small(uint32_t current_counter, uint32_t packet
} }
static bool mac_data_asynch_channel_switch(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *active_buf)
{
if (!active_buf || !active_buf->asynch_request) {
return false;
}
active_buf->asynch_channel = rf_ptr->mac_channel; //Store Original channel
uint16_t channel = mlme_scan_analyze_next_channel(&active_buf->asynch_channel_list, true);
if (channel <= 0xff) {
mac_mlme_rf_channel_change(rf_ptr, channel);
}
return true;
}
static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *rf_ptr, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry) static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *rf_ptr, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry)
{ {
@ -330,10 +383,16 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
} }
if (status == PHY_LINK_CCA_PREPARE) { if (status == PHY_LINK_CCA_PREPARE) {
if (rf_ptr->fhss_api) {
if (rf_ptr->mac_ack_tx_active) { if (rf_ptr->mac_ack_tx_active) {
return 0; return 0;
} }
if (mac_data_asynch_channel_switch(rf_ptr, rf_ptr->active_pd_data_request) ) {
return 0;
}
if (rf_ptr->fhss_api) {
mac_pre_build_frame_t *active_buf = rf_ptr->active_pd_data_request; mac_pre_build_frame_t *active_buf = rf_ptr->active_pd_data_request;
if (!active_buf) { if (!active_buf) {
return -1; return -1;
@ -345,7 +404,7 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
uint8_t *synch_info = tx_buf->buf + rf_ptr->dev_driver->phy_driver->phy_header_length + tx_buf->len - FHSS_SYNCH_INFO_LENGTH; uint8_t *synch_info = tx_buf->buf + rf_ptr->dev_driver->phy_driver->phy_header_length + tx_buf->len - FHSS_SYNCH_INFO_LENGTH;
rf_ptr->fhss_api->write_synch_info(rf_ptr->fhss_api, synch_info, 0, FHSS_SYNCH_FRAME, 0); rf_ptr->fhss_api->write_synch_info(rf_ptr->fhss_api, synch_info, 0, FHSS_SYNCH_FRAME, 0);
} }
if (active_buf->asynch_request == false) {
// Change to destination channel and write synchronization info to Beacon frames here // Change to destination channel and write synchronization info to Beacon frames here
int tx_handle_retval = rf_ptr->fhss_api->tx_handle(rf_ptr->fhss_api, !mac_is_ack_request_set(active_buf), int tx_handle_retval = rf_ptr->fhss_api->tx_handle(rf_ptr->fhss_api, !mac_is_ack_request_set(active_buf),
active_buf->DstAddr, mac_convert_frame_type_to_fhss(active_buf->fcf_dsn.frametype), active_buf->DstAddr, mac_convert_frame_type_to_fhss(active_buf->fcf_dsn.frametype),
@ -361,9 +420,12 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
if (tx_handle_retval == -3) { if (tx_handle_retval == -3) {
mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL); mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL);
return -3; return -3;
} else if (tx_handle_retval == -2) {
mac_tx_done_state_set(rf_ptr, MAC_UNKNOWN_DESTINATION);
return -2;
} }
} }
}
return 0; return 0;
} }
@ -373,6 +435,10 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
if (rf_ptr->mac_ack_tx_active) { if (rf_ptr->mac_ack_tx_active) {
rf_ptr->mac_ack_tx_active = false; rf_ptr->mac_ack_tx_active = false;
if (rf_ptr->fhss_api) {
//SET tx completed false because ack isnot never queued
rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, false, 0xff);
}
if (rf_ptr->active_pd_data_request) { if (rf_ptr->active_pd_data_request) {
if (rf_ptr->active_pd_data_request->fcf_dsn.securityEnabled) { if (rf_ptr->active_pd_data_request->fcf_dsn.securityEnabled) {
@ -450,7 +516,7 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
static int8_t mac_data_interface_tx_done_by_ack_cb(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_parsed_frame_t *buf) static int8_t mac_data_interface_tx_done_by_ack_cb(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_parsed_frame_t *buf)
{ {
if (!rf_ptr->macRfRadioTxActive) { if (!rf_ptr->macRfRadioTxActive || !rf_ptr->active_pd_data_request || rf_ptr->active_pd_data_request->fcf_dsn.DSN != buf->fcf_dsn.DSN) {
return -1; return -1;
} }
@ -465,10 +531,8 @@ static int8_t mac_data_interface_tx_done_by_ack_cb(protocol_interface_rf_mac_set
mcps_sap_pd_ack(buf); mcps_sap_pd_ack(buf);
if (rf_ptr->fhss_api) { if (rf_ptr->fhss_api) {
if (rf_ptr->active_pd_data_request->asynch_request == false) {
rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, true, rf_ptr->active_pd_data_request->msduHandle); rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, true, rf_ptr->active_pd_data_request->msduHandle);
} }
}
return 0; return 0;
} }
@ -611,8 +675,6 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message)
if (mcps_generic_ack_build(rf_ptr, &fcf_read, pd_data_ind->data_ptr, &ack_payload, time_stamp) !=0) { if (mcps_generic_ack_build(rf_ptr, &fcf_read, pd_data_ind->data_ptr, &ack_payload, time_stamp) !=0) {
return -1; return -1;
} }
rf_ptr->mac_ack_tx_active = true;
} }
} }

View File

@ -48,6 +48,8 @@ int8_t mac_pd_sap_data_cb(void *identifier, struct arm_phy_sap_msg_s *message);
void mac_csma_param_init(struct protocol_interface_rf_mac_setup *rf_mac_setup); void mac_csma_param_init(struct protocol_interface_rf_mac_setup *rf_mac_setup);
uint32_t mac_csma_backoff_get(struct protocol_interface_rf_mac_setup *rf_mac_setup); uint32_t mac_csma_backoff_get(struct protocol_interface_rf_mac_setup *rf_mac_setup);
void mac_csma_backoff_start(struct protocol_interface_rf_mac_setup *rf_mac_setup);
/** /**
* Run Mac data interface state Machine. * Run Mac data interface state Machine.
* *

View File

@ -54,7 +54,7 @@ static int8_t ns_sw_mac_api_enable_mcps_ext(mac_api_t *api, mcps_data_indication
static void mlme_req(const mac_api_t* api, mlme_primitive id, const void *data); static void mlme_req(const mac_api_t* api, mlme_primitive id, const void *data);
static void mcps_req(const mac_api_t* api, const mcps_data_req_t *data); static void mcps_req(const mac_api_t* api, const mcps_data_req_t *data);
static void mcps_req_ext(const mac_api_t* api, const mcps_data_req_t *data, const mcps_data_req_ie_list_t *ie_ext, const channel_list_s *asynch_channel_list); static void mcps_req_ext(const mac_api_t* api, const mcps_data_req_t *data, const mcps_data_req_ie_list_t *ie_ext, const channel_list_s *asynch_channel_list);
static void purge_req(const mac_api_t* api, const mcps_purge_t *data); static uint8_t purge_req(const mac_api_t* api, const mcps_purge_t *data);
static int8_t macext_mac64_address_set( const mac_api_t* api, const uint8_t *mac64); static int8_t macext_mac64_address_set( const mac_api_t* api, const uint8_t *mac64);
static int8_t macext_mac64_address_get( const mac_api_t* api, mac_extended_address_type type, uint8_t *mac64_buf); static int8_t macext_mac64_address_get( const mac_api_t* api, mac_extended_address_type type, uint8_t *mac64_buf);
@ -176,6 +176,7 @@ int ns_sw_mac_fhss_register(mac_api_t *mac_api, fhss_api_t *fhss_api)
fhss_callback_t callbacks; fhss_callback_t callbacks;
callbacks.read_tx_queue_size = &mac_read_tx_queue_sizes; callbacks.read_tx_queue_size = &mac_read_tx_queue_sizes;
callbacks.read_datarate = &mac_read_phy_datarate; callbacks.read_datarate = &mac_read_phy_datarate;
callbacks.read_timestamp = &mac_read_phy_timestamp;
callbacks.read_mac_address = &mac_read_64bit_mac_address; callbacks.read_mac_address = &mac_read_64bit_mac_address;
callbacks.change_channel = &mac_set_channel; callbacks.change_channel = &mac_set_channel;
callbacks.send_fhss_frame = &mac_fhss_frame_tx; callbacks.send_fhss_frame = &mac_fhss_frame_tx;
@ -251,6 +252,22 @@ static int8_t ns_sw_mac_api_enable_mcps_ext(mac_api_t *api, mcps_data_indication
cur->data_ind_ext_cb = data_ind_cb; cur->data_ind_ext_cb = data_ind_cb;
cur->enhanced_ack_data_req_cb = ack_data_req_cb; cur->enhanced_ack_data_req_cb = ack_data_req_cb;
if (data_cnf_cb && data_ind_cb && ack_data_req_cb) { if (data_cnf_cb && data_ind_cb && ack_data_req_cb) {
arm_device_driver_list_s *dev_driver = mac_store.setup->dev_driver;
ns_dyn_mem_free(mac_store.setup->dev_driver_tx_buffer.enhanced_ack_buf);
uint16_t total_length;
if (ENHANCED_ACK_MAX_LENGTH > dev_driver->phy_driver->phy_MTU) {
total_length = dev_driver->phy_driver->phy_MTU;
} else {
total_length = ENHANCED_ACK_MAX_LENGTH;
}
total_length += (dev_driver->phy_driver->phy_header_length + dev_driver->phy_driver->phy_tail_length);
mac_store.setup->dev_driver_tx_buffer.enhanced_ack_buf = ns_dyn_mem_alloc(total_length);
if (!mac_store.setup->dev_driver_tx_buffer.enhanced_ack_buf) {
return -2;
}
mac_store.setup->mac_extension_enabled = true; mac_store.setup->mac_extension_enabled = true;
} else { } else {
mac_store.setup->mac_extension_enabled = false; mac_store.setup->mac_extension_enabled = false;
@ -509,11 +526,12 @@ void mcps_req_ext(const mac_api_t* api, const mcps_data_req_t *data, const mcps_
} }
static void purge_req(const mac_api_t* api, const mcps_purge_t *data) static uint8_t purge_req(const mac_api_t* api, const mcps_purge_t *data)
{ {
if (mac_store.mac_api == api) { if (mac_store.mac_api == api) {
mcps_sap_purge_reg_handler(mac_store.setup , data ); return mcps_sap_purge_reg_handler(mac_store.setup , data );
} }
return MLME_INVALID_HANDLE;
} }
static int8_t macext_mac64_address_set( const mac_api_t* api, const uint8_t *mac64) static int8_t macext_mac64_address_set( const mac_api_t* api, const uint8_t *mac64)
@ -587,8 +605,7 @@ static int8_t sw_mac_net_phy_tx_done(int8_t driver_id, uint8_t tx_handle, phy_li
phy_msg.message.mac15_4_pd_sap_confirm.cca_retry = cca_retry; phy_msg.message.mac15_4_pd_sap_confirm.cca_retry = cca_retry;
phy_msg.message.mac15_4_pd_sap_confirm.tx_retry = tx_retry; phy_msg.message.mac15_4_pd_sap_confirm.tx_retry = tx_retry;
mac_pd_sap_data_cb(driver->phy_sap_identifier, &phy_msg); return mac_pd_sap_data_cb(driver->phy_sap_identifier, &phy_msg);
return 0;
} }
static void bc_enable_timer_cb(int8_t timer_id, uint16_t slots) static void bc_enable_timer_cb(int8_t timer_id, uint16_t slots)

View File

@ -1011,17 +1011,41 @@ void mpl_clear_realm_scope_seeds(protocol_interface_info_entry_t *cur)
static buffer_t *mpl_exthdr_provider(buffer_t *buf, ipv6_exthdr_stage_t stage, int16_t *result) static buffer_t *mpl_exthdr_provider(buffer_t *buf, ipv6_exthdr_stage_t stage, int16_t *result)
{ {
mpl_domain_t *domain = mpl_domain_lookup_with_realm_check(buf->interface, buf->dst_sa.address); mpl_domain_t *domain = mpl_domain_lookup_with_realm_check(buf->interface, buf->dst_sa.address);
if (!domain) {
// We need to tunnel
if (stage != IPV6_EXTHDR_MODIFY) { /* Deal with simpler modify-already-created-header case first. Note that no error returns. */
if (stage == IPV6_EXTHDR_MODIFY) {
if (!domain) {
*result = IPV6_EXTHDR_MODIFY_TUNNEL;
memcpy(buf->dst_sa.address, ADDR_ALL_MPL_FORWARDERS, 16);
buf->src_sa.addr_type = ADDR_NONE; // force auto-selection
return buf;
}
if (buf->options.ip_extflags & IPEXT_HBH_MPL_UNFILLED) {
/* We assume we created this, therefore our option is in place
* in the expected place. Sequence is set now, AFTER
* fragmentation.
*/
uint8_t *iphdr = buffer_data_pointer(buf);
uint8_t *ext = iphdr + IPV6_HDRLEN;
if (iphdr[IPV6_HDROFF_NH] != IPV6_NH_HOP_BY_HOP || ext[2] != IPV6_OPTION_MPL) {
tr_err("modify");
return buffer_free(buf);
}
/* We don't bother setting the M flag on these initial packets. Setting to 0 is always acceptable. */
ext[5] = domain->sequence++;
buf->options.ip_extflags &=~ IPEXT_HBH_MPL_UNFILLED;
buf->mpl_option_data_offset = IPV6_HDRLEN + 4;
mpl_forwarder_process_message(buf, domain, true);
}
*result = 0; *result = 0;
return buf; return buf;
} }
*result = IPV6_EXTHDR_MODIFY_TUNNEL; /* Rest of code deals with header insertion */
memcpy(buf->dst_sa.address, ADDR_ALL_MPL_FORWARDERS, 16); if (!domain) {
buf->src_sa.addr_type = ADDR_NONE; // force auto-selection // We will need to tunnel - do nothing on the inner packet
*result = 0;
return buf; return buf;
} }
@ -1112,26 +1136,6 @@ static buffer_t *mpl_exthdr_provider(buffer_t *buf, ipv6_exthdr_stage_t stage, i
buf->options.ip_extflags |= IPEXT_HBH_MPL | IPEXT_HBH_MPL_UNFILLED; buf->options.ip_extflags |= IPEXT_HBH_MPL | IPEXT_HBH_MPL_UNFILLED;
return buf; return buf;
} }
case IPV6_EXTHDR_MODIFY:
if (buf->options.ip_extflags & IPEXT_HBH_MPL_UNFILLED) {
/* We assume we created this, therefore our option is in place
* in the expected place. Sequence is set now, AFTER
* fragmentation.
*/
uint8_t *iphdr = buffer_data_pointer(buf);
uint8_t *ext = iphdr + IPV6_HDRLEN;
if (iphdr[IPV6_HDROFF_NH] != IPV6_NH_HOP_BY_HOP || ext[2] != IPV6_OPTION_MPL) {
tr_err("modify");
return buffer_free(buf);
}
/* We don't bother setting the M flag on these initial packets. Setting to 0 is always acceptable. */
ext[5] = domain->sequence++;
buf->options.ip_extflags &=~ IPEXT_HBH_MPL_UNFILLED;
buf->mpl_option_data_offset = IPV6_HDRLEN + 4;
mpl_forwarder_process_message(buf, domain, true);
}
*result = 0;
return buf;
default: default:
return buffer_free(buf); return buffer_free(buf);
} }

View File

@ -348,9 +348,10 @@ void rpl_control_remove_domain_from_interface(protocol_interface_info_entry_t *c
} }
} }
void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, void *cb_handle) void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, void *cb_handle)
{ {
domain->callback = callback; domain->callback = callback;
domain->prefix_cb = prefix_learn_cb;
domain->cb_handle = cb_handle; domain->cb_handle = cb_handle;
} }
@ -677,28 +678,22 @@ static void rpl_control_process_prefix_options(protocol_interface_info_entry_t *
const uint8_t *prefix = ptr + 16; const uint8_t *prefix = ptr + 16;
if (!pref_parent || neighbour == pref_parent) { if (!pref_parent || neighbour == pref_parent) {
//Check is L Flag active
if (flags & PIO_L) {
//define ONLink Route Information
//tr_debug("Register On Link Prefix to routing table");
ipv6_route_add(prefix, prefix_len, cur->id, NULL, ROUTE_RADV, valid, 0);
}
/* Check if A-Flag.
* A RPL node may use this option for the purpose of Stateless Address Autoconfiguration (SLAAC)
* from a prefix advertised by a parent.
*/
if (pref_parent && (flags & PIO_A)) {
if (icmpv6_slaac_prefix_update(cur, prefix, prefix_len, valid, preferred) != 0) {
ipv6_interface_slaac_handler(cur, prefix, prefix_len, valid, preferred);
}
}
/* Store prefixes for possible forwarding */ /* Store prefixes for possible forwarding */
/* XXX if leaf - don't bother? Or do we want to remember them for /* XXX if leaf - don't bother? Or do we want to remember them for
* when we switch DODAG, as mentioned above? * when we switch DODAG, as mentioned above?
*/ */
rpl_dodag_update_dio_prefix(dodag, prefix, prefix_len, flags, valid, preferred, false, true); prefix_entry_t *prefix_entry = rpl_dodag_update_dio_prefix(dodag, prefix, prefix_len, flags, valid, preferred, false, true);
if (prefix_entry && pref_parent) {
rpl_control_process_prefix_option(prefix_entry, cur);
rpl_domain_t *domain = cur->rpl_domain;
if (domain && domain->prefix_cb) {
uint8_t ll_address[16];
memcpy(ll_address, rpl_neighbour_ll_address(pref_parent), 16);
domain->prefix_cb(prefix_entry, domain->cb_handle,ll_address);
}
}
} }
if ((flags & PIO_R) && !router_addr_set) { if ((flags & PIO_R) && !router_addr_set) {
@ -715,6 +710,18 @@ static void rpl_control_process_prefix_options(protocol_interface_info_entry_t *
} }
} }
void rpl_control_process_prefix_option(prefix_entry_t *prefix, protocol_interface_info_entry_t *cur)
{
//Check is L Flag active
if (prefix->options & PIO_L) {
//define ONLink Route Information
//tr_debug("Register On Link Prefix to routing table");
ipv6_route_add(prefix->prefix, prefix->prefix_len, cur->id, NULL, ROUTE_RADV, prefix->lifetime, 0);
}
}
/* /*
* 0 1 2 3 * 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@ -1004,7 +1011,7 @@ static buffer_t *rpl_control_dio_handler(protocol_interface_info_entry_t *cur, r
rpl_instance_consistent_rx(instance); rpl_instance_consistent_rx(instance);
} }
rpl_instance_neighbours_changed(instance); rpl_instance_neighbours_changed(instance, dodag);
return buffer_free(buf); return buffer_free(buf);

View File

@ -29,15 +29,19 @@ struct rpl_dodag;
struct buffer; struct buffer;
struct protocol_interface_info_entry; struct protocol_interface_info_entry;
struct rpl_dodag_info_t; struct rpl_dodag_info_t;
struct prefix_entry_t;
typedef enum rpl_event { typedef enum rpl_event {
RPL_EVENT_DAO_DONE, /* Simplistic trigger for bootstrap advance - a DAO registration completed */ RPL_EVENT_DAO_DONE, /* Simplistic trigger for bootstrap advance - a DAO registration completed */
RPL_EVENT_LOCAL_REPAIR_START, /* RPL start scanning new parent by multicast DIS user can disable beacon request responser here*/ RPL_EVENT_LOCAL_REPAIR_START, /* RPL start scanning new parent by multicast DIS user can disable beacon request responser here*/
RPL_EVENT_LOCAL_REPAIR_NO_MORE_DIS, /* RPL not sending DIS anymore user can report bootstrap error */ RPL_EVENT_LOCAL_REPAIR_NO_MORE_DIS, /* RPL not sending DIS anymore user can report bootstrap error */
RPL_EVENT_DAO_PARENT_SWITCH, /* RPL indicate that DAO downward Parent state have been updated */
} rpl_event_t; } rpl_event_t;
typedef void rpl_domain_callback_t(rpl_event_t event, void *handle); typedef void rpl_domain_callback_t(rpl_event_t event, void *handle);
typedef void rpl_prefix_callback_t(struct prefix_entry_t *prefix, void *handle, uint8_t *parent_link_local);
typedef struct rpl_domain typedef struct rpl_domain
{ {
NS_LIST_HEAD_INCOMPLETE(struct rpl_instance) instances; NS_LIST_HEAD_INCOMPLETE(struct rpl_instance) instances;
@ -50,6 +54,7 @@ typedef struct rpl_domain
/* As part of shutdown, we can force entering leaf mode */ /* As part of shutdown, we can force entering leaf mode */
bool force_leaf; bool force_leaf;
rpl_domain_callback_t *callback; rpl_domain_callback_t *callback;
rpl_prefix_callback_t *prefix_cb;
void *cb_handle; void *cb_handle;
} rpl_domain_t; } rpl_domain_t;
@ -100,6 +105,7 @@ void rpl_control_transmit_dio(struct rpl_domain *domain, struct protocol_interfa
bool rpl_control_transmit_dao(struct rpl_domain *domain, struct protocol_interface_info_entry *cur, struct rpl_instance *instance, uint8_t instance_id, uint8_t dao_sequence, const uint8_t dodagid[16], const uint8_t *opts, uint16_t opts_size, const uint8_t *dst); bool rpl_control_transmit_dao(struct rpl_domain *domain, struct protocol_interface_info_entry *cur, struct rpl_instance *instance, uint8_t instance_id, uint8_t dao_sequence, const uint8_t dodagid[16], const uint8_t *opts, uint16_t opts_size, const uint8_t *dst);
void rpl_control_disable_ra_routes(struct rpl_domain *domain); void rpl_control_disable_ra_routes(struct rpl_domain *domain);
void rpl_control_event(struct rpl_domain *domain, rpl_event_t event); void rpl_control_event(struct rpl_domain *domain, rpl_event_t event);
void rpl_control_process_prefix_option(struct prefix_entry_t *prefix, struct protocol_interface_info_entry *cur);
/*********************** RPL control API to rest of system *******************/ /*********************** RPL control API to rest of system *******************/
@ -138,7 +144,7 @@ rpl_domain_t *rpl_control_create_domain(void);
void rpl_control_delete_domain(rpl_domain_t *domain); void rpl_control_delete_domain(rpl_domain_t *domain);
void rpl_control_set_domain_on_interface(struct protocol_interface_info_entry *cur, rpl_domain_t *domain, bool downstream); void rpl_control_set_domain_on_interface(struct protocol_interface_info_entry *cur, rpl_domain_t *domain, bool downstream);
void rpl_control_remove_domain_from_interface(struct protocol_interface_info_entry *cur); void rpl_control_remove_domain_from_interface(struct protocol_interface_info_entry *cur);
void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, void *cb_handle); void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, void *cb_handle);
/* Target publishing */ /* Target publishing */
void rpl_control_publish_host_address(rpl_domain_t *domain, const uint8_t addr[16], uint32_t lifetime); void rpl_control_publish_host_address(rpl_domain_t *domain, const uint8_t addr[16], uint32_t lifetime);
@ -160,7 +166,6 @@ const rpl_dodag_conf_t *rpl_control_get_dodag_config(const struct rpl_instance *
const uint8_t *rpl_control_preferred_parent_addr(const struct rpl_instance *instance, bool global); const uint8_t *rpl_control_preferred_parent_addr(const struct rpl_instance *instance, bool global);
uint16_t rpl_control_current_rank(const struct rpl_instance *instance); uint16_t rpl_control_current_rank(const struct rpl_instance *instance);
#else /* HAVE_RPL */ #else /* HAVE_RPL */
#define rpl_control_fast_timer(ticks) ((void) 0) #define rpl_control_fast_timer(ticks) ((void) 0)

View File

@ -243,6 +243,8 @@ void rpl_downward_process_dao_parent_changes(rpl_instance_t *instance)
} }
} }
} }
//GENERATE PARENT Update event
rpl_control_event(instance->domain, RPL_EVENT_DAO_PARENT_SWITCH);
rpl_instance_dao_trigger(instance, 0); rpl_instance_dao_trigger(instance, 0);
} }
} }
@ -588,7 +590,7 @@ void rpl_instance_send_address_registration(protocol_interface_info_entry_t *int
aro.status = ARO_SUCCESS; aro.status = ARO_SUCCESS;
aro.present = true; aro.present = true;
aro.lifetime = addr->preferred_lifetime; aro.lifetime = addr->valid_lifetime;
memcpy(aro.eui64, interface->mac, 8); memcpy(aro.eui64, interface->mac, 8);
// go through neighbour list, and send to all assigned parents. // go through neighbour list, and send to all assigned parents.

View File

@ -134,6 +134,7 @@ typedef struct rpl_dao_non_root
uint32_t refresh_timer; /* Refresh timer (seconds) - 0xFFFFFFFF = infinite, 0 = not yet set */ uint32_t refresh_timer; /* Refresh timer (seconds) - 0xFFFFFFFF = infinite, 0 = not yet set */
} rpl_dao_non_root_t; } rpl_dao_non_root_t;
/* Descriptor for a RPL DAO target */ /* Descriptor for a RPL DAO target */
struct rpl_dao_target struct rpl_dao_target
{ {

View File

@ -427,7 +427,7 @@ void rpl_delete_neighbour(rpl_instance_t *instance, rpl_neighbour_t *neighbour)
} }
if (neighbour->dodag_parent) { if (neighbour->dodag_parent) {
rpl_instance_remove_system_routes_through_parent(instance, neighbour); rpl_instance_remove_system_routes_through_parent(instance, neighbour);
rpl_instance_neighbours_changed(instance); rpl_instance_neighbours_changed(instance, NULL);
} }
rpl_free(neighbour, sizeof *neighbour); rpl_free(neighbour, sizeof *neighbour);
@ -1171,13 +1171,18 @@ bool rpl_instance_purge(rpl_instance_t *instance)
return false; return false;
} }
void rpl_instance_neighbours_changed(rpl_instance_t *instance) void rpl_instance_neighbours_changed(rpl_instance_t *instance, const rpl_dodag_t *dodag)
{ {
instance->neighbours_changed = true; instance->neighbours_changed = true;
if (!rpl_instance_preferred_parent(instance)) { uint16_t delay = rpl_policy_dio_parent_selection_delay(instance->domain);
rpl_instance_set_local_repair(instance, true); if (dodag) {
//Convert imin 100ms tick to seconds
uint16_t i_min_delay = dodag->dio_timer_params.Imin / 10;
if (i_min_delay > delay) {
delay = i_min_delay;
} }
rpl_instance_trigger_parent_selection(instance, rpl_policy_dio_parent_selection_delay(instance->domain)); }
rpl_instance_trigger_parent_selection(instance, delay);
} }
static void rpl_instance_remove_parents(rpl_instance_t *instance) static void rpl_instance_remove_parents(rpl_instance_t *instance)
@ -1366,7 +1371,18 @@ void rpl_instance_run_parent_selection(rpl_instance_t *instance)
} }
} }
rpl_instance_set_local_repair(instance, preferred_parent == NULL); //Control Local repair state
if (preferred_parent) {
// Always stop repair if we find a parent
rpl_instance_set_local_repair(instance, false);
} else if (original_preferred) {
// Only start repair if we just lost a parent
rpl_instance_set_local_repair(instance, true);
} else {
// !preferred_parent && !original_preferred - didn't have a parent,
// still don't. Leave repair flag as-is (would be off on initial start
// up, may be on if having problems mid-session).
}
if (rpl_instance_mop(instance) != RPL_MODE_NO_DOWNWARD) { if (rpl_instance_mop(instance) != RPL_MODE_NO_DOWNWARD) {
rpl_downward_process_dao_parent_changes(instance); rpl_downward_process_dao_parent_changes(instance);
@ -1384,6 +1400,20 @@ void rpl_instance_run_parent_selection(rpl_instance_t *instance)
rpl_control_print(trace_info_print); rpl_control_print(trace_info_print);
/* Changing DODAG version is an inconsistency */ /* Changing DODAG version is an inconsistency */
if (original_version != instance->current_dodag_version) { if (original_version != instance->current_dodag_version) {
//learn Routes an Prefixes
if (preferred_parent && instance->current_dodag_version) {
rpl_dodag_t *dodag = instance->current_dodag_version->dodag;
protocol_interface_info_entry_t *rpl_interface = protocol_stack_interface_info_get_by_id(preferred_parent->interface_id);
if (rpl_interface) {
ns_list_foreach(prefix_entry_t, prefix, &dodag->prefixes) {
rpl_control_process_prefix_option(prefix, rpl_interface);
if (instance->domain->prefix_cb) {
instance->domain->prefix_cb(prefix, rpl_interface, preferred_parent->ll_address);
}
}
}
}
rpl_instance_inconsistency(instance); rpl_instance_inconsistency(instance);
return; return;
} }
@ -1536,6 +1566,7 @@ void rpl_instance_slow_timer(rpl_instance_t *instance, uint16_t seconds)
} }
} }
void rpl_upward_dio_timer(rpl_instance_t *instance, uint16_t ticks) void rpl_upward_dio_timer(rpl_instance_t *instance, uint16_t ticks)
{ {
rpl_dodag_version_t *dodag_version = instance->current_dodag_version; rpl_dodag_version_t *dodag_version = instance->current_dodag_version;

View File

@ -135,7 +135,7 @@ void rpl_neighbour_update_dodag_version(rpl_neighbour_t *neighbour, rpl_dodag_ve
bool rpl_neighbour_update_dtsn(rpl_neighbour_t *neighbour, uint8_t dtsn); bool rpl_neighbour_update_dtsn(rpl_neighbour_t *neighbour, uint8_t dtsn);
rpl_instance_t *rpl_neighbour_instance(const rpl_neighbour_t *neighbour); rpl_instance_t *rpl_neighbour_instance(const rpl_neighbour_t *neighbour);
void rpl_instance_neighbours_changed(rpl_instance_t *instance); void rpl_instance_neighbours_changed(rpl_instance_t *instance, const rpl_dodag_t *dodag);
void rpl_instance_run_parent_selection(rpl_instance_t *instance); void rpl_instance_run_parent_selection(rpl_instance_t *instance);
void rpl_upward_print_instance(rpl_instance_t *instance, route_print_fn_t *print_fn); void rpl_upward_print_instance(rpl_instance_t *instance, route_print_fn_t *print_fn);

View File

@ -81,6 +81,9 @@ void etx_transm_attempts_update(int8_t interface_id, uint8_t attempts, bool succ
if (!entry) { if (!entry) {
return; return;
} }
if (entry->etx_samples < 7) {
entry->etx_samples++;
}
accumulated_failures = entry->accumulated_failures; accumulated_failures = entry->accumulated_failures;

View File

@ -38,6 +38,7 @@ typedef struct etx_storage_s {
unsigned accumulated_failures: 5; unsigned accumulated_failures: 5;
unsigned tmp_etx: 1; unsigned tmp_etx: 1;
unsigned linkIdr: 4; unsigned linkIdr: 4;
unsigned etx_samples: 3;
} etx_storage_t; } etx_storage_t;
/** /**

View File

@ -17,25 +17,44 @@
#ifndef CHANNEL_FUNC_H_ #ifndef CHANNEL_FUNC_H_
#define CHANNEL_FUNC_H_ #define CHANNEL_FUNC_H_
/**
* @brief Function calculates nearest (higher) prime number for given start value.
* @param start_value Start value.
* @return Calculated prime number.
*/
uint16_t tr51_calc_nearest_prime_number(uint16_t start_value);
/**
* @brief Initialize channel table for TR51 channel function.
* @param channel_table Channel table to be initialized.
* @param number_of_channels Number of channels.
* @return 0 Success, -1 Failure.
*/
int tr51_init_channel_table(int16_t *channel_table, int16_t number_of_channels);
/** /**
* @brief Compute the unicast schedule channel index using tr51 channel function. * @brief Compute the unicast schedule channel index using tr51 channel function.
* @param channel_table Channel table.
* @param output_table Table used to generate output channel.
* @param slot_number Current slot number. * @param slot_number Current slot number.
* @param mac MAC address of the node for which the index is calculated. * @param mac MAC address of the node for which the index is calculated.
* @param number_of_channels Number of channels. * @param number_of_channels Number of channels.
* @param excluded_channels Excluded channels. * @param excluded_channels Excluded channels.
* @return Channel index. * @return Channel index.
*/ */
int32_t tr51_get_uc_channel_index(uint16_t slot_number, uint8_t *mac, int16_t number_of_channels, uint32_t *excluded_channels); int32_t tr51_get_uc_channel_index(int16_t *channel_table, uint8_t *output_table, uint16_t slot_number, uint8_t *mac, int16_t number_of_channels, uint32_t *excluded_channels);
/** /**
* @brief Compute the broadcast schedule channel index using tr51 channel function. * @brief Compute the broadcast schedule channel index using tr51 channel function.
* @param channel_table Channel table.
* @param output_table Table used to generate output channel.
* @param slot_number Current slot number. * @param slot_number Current slot number.
* @param bsi Broadcast schedule identifier of the node for which the index is calculated. * @param bsi Broadcast schedule identifier of the node for which the index is calculated.
* @param number_of_channels Number of channels. * @param number_of_channels Number of channels.
* @param excluded_channels Excluded channels. * @param excluded_channels Excluded channels.
* @return Channel index. * @return Channel index.
*/ */
int32_t tr51_get_bc_channel_index(uint16_t slot_number, uint16_t bsi, int16_t number_of_channels, uint32_t *excluded_channels); int32_t tr51_get_bc_channel_index(int16_t *channel_table, uint8_t *output_table, uint16_t slot_number, uint16_t bsi, int16_t number_of_channels, uint32_t *excluded_channels);
/** /**
* @brief Compute the unicast schedule channel index using direct hash channel function. * @brief Compute the unicast schedule channel index using direct hash channel function.

View File

@ -88,6 +88,19 @@ uint8_t channel_list_get_channel(const uint32_t* list, int current_index)
return found_index; return found_index;
} }
void channel_list_set_channel(uint32_t* list, int channel, bool active)
{
if (channel >= CHANNEL_LIST_SIZE_IN_BITS) {
return;
}
if (active) {
list[channel/32] |= (1 << channel % 32);
} else {
list[channel/32] &= ~(1 << channel % 32);
}
return;
}
// count the amount of channels enabled in a list // count the amount of channels enabled in a list
int channel_list_count_channels(const uint32_t* list) int channel_list_count_channels(const uint32_t* list)
{ {

View File

@ -31,6 +31,16 @@ extern "C" {
* @return channel number * @return channel number
*/ */
uint8_t channel_list_get_channel(const uint32_t* list, int current_index); uint8_t channel_list_get_channel(const uint32_t* list, int current_index);
/**
* set matching bit on in in channel mask.
*
* @param list channel mask
* @param channel channel number
* @param active set the channel on if true, disable channel if false.
*
* @return channel number
*/
void channel_list_set_channel(uint32_t* list, int channel, bool active);
/** /**
* Count the amount of channels enabled in a list. * Count the amount of channels enabled in a list.

View File

@ -34,6 +34,7 @@
#define TRACE_GROUP "fhss" #define TRACE_GROUP "fhss"
static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots);
static int fhss_reset(fhss_structure_t *fhss_structure); static int fhss_reset(fhss_structure_t *fhss_structure);
static bool fhss_is_bc_sending_superframe(fhss_structure_t *fhss_structure); static bool fhss_is_bc_sending_superframe(fhss_structure_t *fhss_structure);
static bool fhss_check_remaining_tx_time(fhss_structure_t *fhss_structure, uint16_t tx_length, uint8_t phy_header_length, uint8_t phy_tail_length); static bool fhss_check_remaining_tx_time(fhss_structure_t *fhss_structure, uint16_t tx_length, uint8_t phy_header_length, uint8_t phy_tail_length);
@ -67,6 +68,7 @@ fhss_structure_t *fhss_enable(fhss_api_t *fhss_api, const fhss_configuration_t *
} }
memset(fhss_struct->bs, 0, sizeof(fhss_bs_t)); memset(fhss_struct->bs, 0, sizeof(fhss_bs_t));
fhss_struct->fhss_event_timer = eventOS_callback_timer_register(fhss_event_timer_cb);
fhss_struct->bs->fhss_configuration = *fhss_configuration; fhss_struct->bs->fhss_configuration = *fhss_configuration;
fhss_struct->bs->fhss_stats_ptr = fhss_statistics; fhss_struct->bs->fhss_stats_ptr = fhss_statistics;
fhss_struct->number_of_channels = channel_count; fhss_struct->number_of_channels = channel_count;
@ -99,6 +101,15 @@ bool fhss_is_synch_root(fhss_structure_t *fhss_structure)
return true; return true;
} }
static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots)
{
(void) slots;
fhss_structure_t *fhss_structure = fhss_get_object_with_timer_id(timer_id);
if (fhss_structure) {
fhss_structure->callbacks.tx_poll(fhss_structure->fhss_api);
}
}
static bool fhss_is_bc_sending_superframe(fhss_structure_t *fhss_structure) static bool fhss_is_bc_sending_superframe(fhss_structure_t *fhss_structure)
{ {
if (fhss_structure->bs->current_superframe >= fhss_structure->bs->broadcast_start_superframe) { if (fhss_structure->bs->current_superframe >= fhss_structure->bs->broadcast_start_superframe) {
@ -689,16 +700,16 @@ static void fhss_update_beacon_info_lifetimes(fhss_structure_t *fhss_structure,
} }
} }
static void fhss_synch_state_set_callback(const fhss_api_t *api, fhss_states fhss_state, uint16_t pan_id) static int16_t fhss_synch_state_set_callback(const fhss_api_t *api, fhss_states fhss_state, uint16_t pan_id)
{ {
fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); fhss_structure_t *fhss_structure = fhss_get_object_with_api(api);
if (!fhss_structure) { if (!fhss_structure) {
return; return -1;
} }
// State is already set // State is already set
if (fhss_structure->fhss_state == fhss_state) { if (fhss_structure->fhss_state == fhss_state) {
tr_debug("Synch same state %u", fhss_state); tr_debug("Synch same state %u", fhss_state);
return; return -1;
} }
if (fhss_state == FHSS_UNSYNCHRONIZED) { if (fhss_state == FHSS_UNSYNCHRONIZED) {
@ -712,7 +723,7 @@ static void fhss_synch_state_set_callback(const fhss_api_t *api, fhss_states fhs
// Do not synchronize to current pan // Do not synchronize to current pan
if (fhss_structure->bs->synch_panid == pan_id) { if (fhss_structure->bs->synch_panid == pan_id) {
tr_debug("Synch same panid %u", pan_id); tr_debug("Synch same panid %u", pan_id);
return; return -1;
} }
fhss_generate_scramble_table(fhss_structure); fhss_generate_scramble_table(fhss_structure);
@ -737,11 +748,11 @@ static void fhss_synch_state_set_callback(const fhss_api_t *api, fhss_states fhs
fhss_start_timer(fhss_structure, fhss_structure->bs->synch_configuration.fhss_superframe_length, fhss_superframe_handler); fhss_start_timer(fhss_structure, fhss_structure->bs->synch_configuration.fhss_superframe_length, fhss_superframe_handler);
} else { } else {
tr_error("Synch info not found"); tr_error("Synch info not found");
return; return -1;
} }
} }
fhss_structure->fhss_state = fhss_state; fhss_structure->fhss_state = fhss_state;
return; return fhss_structure->rx_channel;
} }
static void fhss_beacon_decode_raw(fhss_synchronization_beacon_payload_s* dest, const uint8_t* buffer) static void fhss_beacon_decode_raw(fhss_synchronization_beacon_payload_s* dest, const uint8_t* buffer)

View File

@ -34,8 +34,6 @@
static fhss_structure_t *fhss_struct = NULL; static fhss_structure_t *fhss_struct = NULL;
static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots);
static fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id);
static void fhss_set_active_event(fhss_structure_t *fhss_structure, uint8_t event_type); static void fhss_set_active_event(fhss_structure_t *fhss_structure, uint8_t event_type);
static bool fhss_read_active_event(fhss_structure_t *fhss_structure, uint8_t event_type); static bool fhss_read_active_event(fhss_structure_t *fhss_structure, uint8_t event_type);
@ -52,7 +50,6 @@ fhss_structure_t *fhss_allocate_instance(fhss_api_t *fhss_api, const fhss_timer_
memset(fhss_struct, 0, sizeof(fhss_structure_t)); memset(fhss_struct, 0, sizeof(fhss_structure_t));
fhss_struct->fhss_api = fhss_api; fhss_struct->fhss_api = fhss_api;
fhss_struct->platform_functions = *fhss_timer; fhss_struct->platform_functions = *fhss_timer;
fhss_struct->fhss_event_timer = eventOS_callback_timer_register(fhss_event_timer_cb);
if (!fhss_struct->platform_functions.fhss_resolution_divider) { if (!fhss_struct->platform_functions.fhss_resolution_divider) {
fhss_struct->platform_functions.fhss_resolution_divider = 1; fhss_struct->platform_functions.fhss_resolution_divider = 1;
} }
@ -69,16 +66,7 @@ int8_t fhss_free_instance(fhss_api_t *fhss_api)
return 0; return 0;
} }
static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots) fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id)
{
(void) slots;
fhss_structure_t *fhss_structure = fhss_get_object_with_timer_id(timer_id);
if (fhss_structure) {
fhss_structure->callbacks.tx_poll(fhss_structure->fhss_api);
}
}
static fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id)
{ {
if (timer_id < 0 || !fhss_struct) { if (timer_id < 0 || !fhss_struct) {
return NULL; return NULL;
@ -142,6 +130,13 @@ void fhss_start_timer(fhss_structure_t *fhss_structure, uint32_t time, void (*ca
} }
} }
void fhss_stop_timer(fhss_structure_t *fhss_structure, void (*callback)(const fhss_api_t *fhss_api, uint16_t))
{
if (callback){
fhss_structure->platform_functions.fhss_timer_stop(callback, fhss_structure->fhss_api);
}
}
int fhss_timeout_start(fhss_structure_t *fhss_structure, uint32_t time) int fhss_timeout_start(fhss_structure_t *fhss_structure, uint32_t time)
{ {
if (!fhss_structure) { if (!fhss_structure) {

View File

@ -54,6 +54,7 @@ struct fhss_structure
uint8_t synch_parent[8]; uint8_t synch_parent[8];
}; };
fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id);
fhss_structure_t *fhss_allocate_instance(fhss_api_t *fhss_api, const fhss_timer_t *fhss_timer); fhss_structure_t *fhss_allocate_instance(fhss_api_t *fhss_api, const fhss_timer_t *fhss_timer);
int8_t fhss_free_instance(fhss_api_t *fhss_api); int8_t fhss_free_instance(fhss_api_t *fhss_api);
int8_t fhss_set_datarate(fhss_structure_t *fhss_structure, uint32_t datarate); int8_t fhss_set_datarate(fhss_structure_t *fhss_structure, uint32_t datarate);
@ -61,6 +62,7 @@ fhss_structure_t *fhss_get_object_with_api(const fhss_api_t *fhss_api);
void fhss_clear_active_event(fhss_structure_t *fhss_structure, uint8_t event_type); void fhss_clear_active_event(fhss_structure_t *fhss_structure, uint8_t event_type);
int8_t fhss_disable(fhss_structure_t *fhss_structure); int8_t fhss_disable(fhss_structure_t *fhss_structure);
void fhss_start_timer(fhss_structure_t *fhss_structure, uint32_t time, void (*callback)(const fhss_api_t *fhss_api, uint16_t)); void fhss_start_timer(fhss_structure_t *fhss_structure, uint32_t time, void (*callback)(const fhss_api_t *fhss_api, uint16_t));
void fhss_stop_timer(fhss_structure_t *fhss_structure, void (*callback)(const fhss_api_t *fhss_api, uint16_t));
int fhss_timeout_start(fhss_structure_t *fhss_structure, uint32_t time); int fhss_timeout_start(fhss_structure_t *fhss_structure, uint32_t time);
int fhss_timeout_stop(fhss_structure_t *fhss_structure); int fhss_timeout_stop(fhss_structure_t *fhss_structure);
int fhss_update_synch_parent_address(fhss_structure_t *fhss_structure); int fhss_update_synch_parent_address(fhss_structure_t *fhss_structure);

View File

@ -62,13 +62,13 @@ fhss_api_t *ns_fhss_ws_create(const fhss_ws_configuration_t *fhss_configuration,
return this; return this;
} }
int ns_fhss_ws_set_parent(const fhss_api_t *fhss_api, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info) int ns_fhss_ws_set_parent(const fhss_api_t *fhss_api, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info, const bool force_synch)
{ {
fhss_structure_t *fhss_structure = fhss_get_object_with_api(fhss_api); fhss_structure_t *fhss_structure = fhss_get_object_with_api(fhss_api);
if (!fhss_structure || !eui64 || !bc_timing_info) { if (!fhss_structure || !eui64 || !bc_timing_info) {
return -1; return -1;
} }
return fhss_ws_set_parent(fhss_structure, eui64, bc_timing_info); return fhss_ws_set_parent(fhss_structure, eui64, bc_timing_info, force_synch);
} }
int ns_fhss_ws_remove_parent(const fhss_api_t *fhss_api, const uint8_t eui64[8]) int ns_fhss_ws_remove_parent(const fhss_api_t *fhss_api, const uint8_t eui64[8])

View File

@ -23,6 +23,8 @@
#define WS_NUMBER_OF_CHANNEL_RETRIES 4 #define WS_NUMBER_OF_CHANNEL_RETRIES 4
//TX/RX slot length in milliseconds //TX/RX slot length in milliseconds
#define WS_MAX_TXRX_SLOT_LEN_MS 100 #define WS_MAX_TXRX_SLOT_LEN_MS 100
// Default minimum broadcast synchronization interval in seconds
#define DEFAULT_MIN_SYNCH_INTERVAL 60
typedef struct fhss_ws fhss_ws_t; typedef struct fhss_ws fhss_ws_t;
struct fhss_ws struct fhss_ws
@ -30,6 +32,12 @@ struct fhss_ws
uint8_t bc_channel; uint8_t bc_channel;
uint16_t uc_slot; uint16_t uc_slot;
uint16_t bc_slot; uint16_t bc_slot;
uint16_t min_synch_interval;
uint32_t txrx_slot_length_ms;
uint32_t synchronization_time;
int16_t *tr51_channel_table;
uint8_t *tr51_output_table;
bool unicast_timer_running;
bool is_on_bc_channel; bool is_on_bc_channel;
struct fhss_ws_configuration fhss_configuration; struct fhss_ws_configuration fhss_configuration;
const struct broadcast_timing_info *parent_bc_info; const struct broadcast_timing_info *parent_bc_info;
@ -38,7 +46,7 @@ struct fhss_ws
fhss_structure_t *fhss_ws_enable(fhss_api_t *fhss_api, const fhss_ws_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer); fhss_structure_t *fhss_ws_enable(fhss_api_t *fhss_api, const fhss_ws_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer);
int fhss_ws_set_callbacks(fhss_structure_t *fhss_structure); int fhss_ws_set_callbacks(fhss_structure_t *fhss_structure);
int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info); int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info, const bool force_synch);
int fhss_ws_remove_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8]); int fhss_ws_remove_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8]);
int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_configuration_t *fhss_configuration); int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_configuration_t *fhss_configuration);
int fhss_ws_set_hop_count(fhss_structure_t *fhss_structure, const uint8_t hop_count); int fhss_ws_set_hop_count(fhss_structure_t *fhss_structure, const uint8_t hop_count);

View File

@ -46,7 +46,7 @@ int fhss_ws_set_callbacks(fhss_structure_t *fhss_structure)
return -1; return -1;
} }
int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info) int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8], const broadcast_timing_info_t *bc_timing_info, const bool force_synch)
{ {
(void) fhss_structure; (void) fhss_structure;
(void) eui64; (void) eui64;

View File

@ -192,6 +192,9 @@ void mac_neighbor_table_neighbor_connected(mac_neighbor_table_t *table_class, ma
void mac_neighbor_table_trusted_neighbor(mac_neighbor_table_t *table_class, mac_neighbor_table_entry_t *neighbor_entry, bool trusted_device) void mac_neighbor_table_trusted_neighbor(mac_neighbor_table_t *table_class, mac_neighbor_table_entry_t *neighbor_entry, bool trusted_device)
{ {
(void)table_class; (void)table_class;
if (!neighbor_entry->trusted_device && trusted_device) {
neighbor_entry->lifetime = neighbor_entry->link_lifetime;
}
neighbor_entry->trusted_device = trusted_device; neighbor_entry->trusted_device = trusted_device;
} }
@ -271,4 +274,13 @@ mac_neighbor_table_entry_t *mac_neighbor_entry_get_by_mac64(mac_neighbor_table_t
return mac_neighbor_table_entry_allocate(table_class, mac64); return mac_neighbor_table_entry_allocate(table_class, mac64);
} }
mac_neighbor_table_entry_t* mac_neighbor_entry_get_priority(mac_neighbor_table_t *table_class)
{
ns_list_foreach(mac_neighbor_table_entry_t, entry, &table_class->neighbour_list) {
if (entry->link_role == PRIORITY_PARENT_NEIGHBOUR) {
return entry;
}
}
return NULL;
}

View File

@ -202,4 +202,6 @@ mac_neighbor_table_entry_t *mac_neighbor_entry_get_by_ll64(mac_neighbor_table_t
mac_neighbor_table_entry_t *mac_neighbor_entry_get_by_mac64(mac_neighbor_table_t *table_class, const uint8_t *mac64, bool allocateNew, bool *new_entry_allocated); mac_neighbor_table_entry_t *mac_neighbor_entry_get_by_mac64(mac_neighbor_table_t *table_class, const uint8_t *mac64, bool allocateNew, bool *new_entry_allocated);
mac_neighbor_table_entry_t* mac_neighbor_entry_get_priority(mac_neighbor_table_t *table_class);
#endif /* MAC_NEIGHBOR_TABLE_H_ */ #endif /* MAC_NEIGHBOR_TABLE_H_ */

View File

@ -72,9 +72,8 @@ fnet_bool_t fnet_netif_get_ip6_addr (fnet_netif_desc_t netif_desc, fnet_index_t
addr_info->type = FNET_NETIF_IP_ADDR_TYPE_AUTOCONFIGURABLE; /* How the address was acquired.*/ addr_info->type = FNET_NETIF_IP_ADDR_TYPE_AUTOCONFIGURABLE; /* How the address was acquired.*/
result = FNET_TRUE; result = FNET_TRUE;
} }
}
FNET_DEBUG("fnet_netif_get_ip6_addr(), if=%d: %s", (int8_t)netif->scope_id, trace_ipv6(addr_info->address.addr)); FNET_DEBUG("fnet_netif_get_ip6_addr(), if=%d: %s", (int8_t)netif->scope_id, trace_ipv6(addr_info->address.addr));
}
return result; return result;
} }

View File

@ -1589,6 +1589,7 @@ ipv6_route_t *ipv6_route_add_metric(const uint8_t *prefix, uint8_t prefix_len, i
route->metric = metric; route->metric = metric;
changed_info = UPDATED; changed_info = UPDATED;
} }
} }
if (changed_info != UNCHANGED) { if (changed_info != UNCHANGED) {

View File

@ -394,16 +394,16 @@ void ipv6_stack_route_advert_update(uint8_t *address, uint8_t prefixLength, uint
return; return;
} }
if (addr_interface_gp_prefix_compare(cur, address) == 0) {
return;
}
if (addr_interface_gp_prefix_compare(cur, address) != 0) {
ns_list_foreach(ipv6_interface_route_on_link_t, cur_prefix, &route_on_link) { ns_list_foreach(ipv6_interface_route_on_link_t, cur_prefix, &route_on_link) {
if ((cur_prefix->prefix_len == prefixLength) && bitsequal(cur_prefix->prefix, address, prefixLength)) { if ((cur_prefix->prefix_len == prefixLength) && bitsequal(cur_prefix->prefix, address, prefixLength)) {
cur_prefix->routePrefer = routePrefer; cur_prefix->routePrefer = routePrefer;
return; return;
} }
} }
}
ipv6_interface_route_on_link_t *new_entry = ns_dyn_mem_alloc(sizeof(ipv6_interface_route_on_link_t)); ipv6_interface_route_on_link_t *new_entry = ns_dyn_mem_alloc(sizeof(ipv6_interface_route_on_link_t));
if (new_entry) { if (new_entry) {

View File

@ -53,6 +53,16 @@ typedef struct {
} server_instance_t; } server_instance_t;
typedef NS_LIST_HEAD(server_instance_t, link) server_instance_list_t; typedef NS_LIST_HEAD(server_instance_t, link) server_instance_list_t;
typedef struct {
uint16_t instance_id;
int8_t interface_id;
uint8_t server_address[16];
bool relay_activated;
ns_list_link_t link;
} relay_instance_t;
typedef NS_LIST_HEAD(relay_instance_t, link) relay_instance_list_t;
typedef struct { typedef struct {
ns_address_t addr; ns_address_t addr;
dhcp_service_receive_resp_cb *recv_resp_cb; dhcp_service_receive_resp_cb *recv_resp_cb;
@ -71,6 +81,7 @@ typedef struct {
uint8_t retrans; uint8_t retrans;
uint8_t *msg_ptr; uint8_t *msg_ptr;
uint16_t msg_len; uint16_t msg_len;
uint8_t *relay_start;
ns_list_link_t link; ns_list_link_t link;
} msg_tr_t; } msg_tr_t;
typedef NS_LIST_HEAD(msg_tr_t, link) tr_list_t; typedef NS_LIST_HEAD(msg_tr_t, link) tr_list_t;
@ -78,9 +89,11 @@ typedef NS_LIST_HEAD(msg_tr_t, link) tr_list_t;
typedef struct { typedef struct {
ns_address_t src_address; ns_address_t src_address;
server_instance_list_t srv_list; server_instance_list_t srv_list;
relay_instance_list_t relay_list;
tr_list_t tr_list; tr_list_t tr_list;
int8_t dhcp_server_socket; int8_t dhcp_server_socket;
int8_t dhcp_client_socket; int8_t dhcp_client_socket;
int8_t dhcp_relay_socket;
int8_t dhcpv6_socket_service_tasklet; int8_t dhcpv6_socket_service_tasklet;
} dhcp_service_class_t; } dhcp_service_class_t;
@ -120,9 +133,11 @@ bool dhcp_service_allocate(void)
dhcp_service = ns_dyn_mem_alloc(sizeof(dhcp_service_class_t)); dhcp_service = ns_dyn_mem_alloc(sizeof(dhcp_service_class_t));
if (dhcp_service) { if (dhcp_service) {
ns_list_init(&dhcp_service->srv_list); ns_list_init(&dhcp_service->srv_list);
ns_list_init(&dhcp_service->relay_list);
ns_list_init(&dhcp_service->tr_list); ns_list_init(&dhcp_service->tr_list);
dhcp_service->dhcp_client_socket = -1; dhcp_service->dhcp_client_socket = -1;
dhcp_service->dhcp_server_socket = -1; dhcp_service->dhcp_server_socket = -1;
dhcp_service->dhcp_relay_socket = -1;
dhcp_service->dhcpv6_socket_service_tasklet = eventOS_event_handler_create(DHCPv6_socket_service_tasklet, DHCPV6_SOCKET_SERVICE_TASKLET_INIT); dhcp_service->dhcpv6_socket_service_tasklet = eventOS_event_handler_create(DHCPv6_socket_service_tasklet, DHCPV6_SOCKET_SERVICE_TASKLET_INIT);
if (dhcp_service->dhcpv6_socket_service_tasklet < 0) { if (dhcp_service->dhcpv6_socket_service_tasklet < 0) {
ns_dyn_mem_free(dhcp_service); ns_dyn_mem_free(dhcp_service);
@ -229,13 +244,50 @@ server_instance_t *dhcp_service_client_find(uint16_t instance_id)
} }
static uint16_t dhcp_service_relay_interface_get(int8_t interface_id)
{
ns_list_foreach(server_instance_t, cur_ptr, &dhcp_service->srv_list) {
if (cur_ptr->interface_id == interface_id && cur_ptr->instance_type == DHCP_INTANCE_RELAY_AGENT) {
return cur_ptr->instance_id;
}
}
return 0;
}
static relay_instance_t *dhcp_service_relay_find(uint16_t instance_id)
{
relay_instance_t *result = NULL;
ns_list_foreach(relay_instance_t, cur_ptr, &dhcp_service->relay_list) {
if (cur_ptr->instance_id == instance_id) {
result = cur_ptr;
}
}
return result;
}
static relay_instance_t *dhcp_service_relay_interface(int8_t interface_id)
{
relay_instance_t *result = NULL;
ns_list_foreach(relay_instance_t, cur_ptr, &dhcp_service->relay_list) {
if (cur_ptr->interface_id == interface_id) {
result = cur_ptr;
}
}
return result;
}
void recv_dhcp_server_msg(void *cb_res) void recv_dhcp_server_msg(void *cb_res)
{ {
socket_callback_t *sckt_data; socket_callback_t *sckt_data;
server_instance_t *srv_ptr = NULL; server_instance_t *srv_ptr = NULL;
msg_tr_t *msg_tr_ptr; msg_tr_t *msg_tr_ptr;
uint8_t *msg_ptr; uint8_t *msg_ptr, *allocated_ptr;
uint16_t msg_len; uint16_t msg_len;
dhcpv6_relay_msg_t relay_msg;
sckt_data = cb_res; sckt_data = cb_res;
@ -245,12 +297,33 @@ void recv_dhcp_server_msg(void *cb_res)
tr_debug("dhcp Server recv request"); tr_debug("dhcp Server recv request");
msg_tr_ptr = dhcp_tr_create(); msg_tr_ptr = dhcp_tr_create();
msg_ptr = ns_dyn_mem_temporary_alloc(sckt_data->d_len); msg_ptr = ns_dyn_mem_temporary_alloc(sckt_data->d_len);
allocated_ptr = msg_ptr;
if (msg_ptr == NULL || msg_tr_ptr == NULL) { if (msg_ptr == NULL || msg_tr_ptr == NULL) {
// read actual message // read actual message
tr_error("Out of resources"); tr_error("Out of resources");
goto cleanup; goto cleanup;
} }
msg_len = socket_read(sckt_data->socket_id, &msg_tr_ptr->addr, msg_ptr, sckt_data->d_len); msg_len = socket_read(sckt_data->socket_id, &msg_tr_ptr->addr, msg_ptr, sckt_data->d_len);
uint8_t msg_type = *msg_ptr;
if (msg_type == DHCPV6_RELAY_FORWARD) {
if ( !libdhcpv6_relay_msg_read(msg_ptr, msg_len, &relay_msg) ) {
tr_error("Relay forward not correct");
goto cleanup;
}
//Update Source and data
msg_tr_ptr->relay_start = msg_ptr;
memcpy(msg_tr_ptr->addr.address,relay_msg.peer_address , 16);
msg_ptr = relay_msg.relay_options.msg_ptr;
msg_len = relay_msg.relay_options.len;
msg_type = *msg_ptr;
} else if (msg_type == DHCPV6_RELAY_REPLY) {
tr_error("Relay reply drop at server");
goto cleanup;
}
//TODO use real function from lib also call validity check //TODO use real function from lib also call validity check
msg_tr_ptr->message_tr_id = common_read_24_bit(&msg_ptr[1]); msg_tr_ptr->message_tr_id = common_read_24_bit(&msg_ptr[1]);
@ -265,7 +338,7 @@ void recv_dhcp_server_msg(void *cb_res)
msg_tr_ptr->instance_id = cur_ptr->instance_id; msg_tr_ptr->instance_id = cur_ptr->instance_id;
msg_tr_ptr->interface_id = sckt_data->interface_id; msg_tr_ptr->interface_id = sckt_data->interface_id;
if ((RET_MSG_ACCEPTED == if ((RET_MSG_ACCEPTED ==
cur_ptr->recv_req_cb(cur_ptr->instance_id, msg_tr_ptr->msg_tr_id, *msg_ptr, msg_ptr + 4, msg_len - 4))) { cur_ptr->recv_req_cb(cur_ptr->instance_id, msg_tr_ptr->msg_tr_id, msg_type, msg_ptr + 4, msg_len - 4))) {
// should not modify pointers but library requires. // should not modify pointers but library requires.
msg_tr_ptr = NULL; msg_tr_ptr = NULL;
srv_ptr = cur_ptr; srv_ptr = cur_ptr;
@ -276,7 +349,7 @@ void recv_dhcp_server_msg(void *cb_res)
cleanup: cleanup:
dhcp_tr_delete(msg_tr_ptr); dhcp_tr_delete(msg_tr_ptr);
ns_dyn_mem_free(msg_ptr); ns_dyn_mem_free(allocated_ptr);
if (srv_ptr == NULL) { if (srv_ptr == NULL) {
//no owner found //no owner found
tr_warn("No handler for this message found"); tr_warn("No handler for this message found");
@ -285,6 +358,118 @@ cleanup:
return; return;
} }
void recv_dhcp_relay_msg(void *cb_res)
{
socket_callback_t *sckt_data;
uint16_t msg_len;
sckt_data = cb_res;
if (sckt_data->event_type != SOCKET_DATA || sckt_data->d_len < 4) {
return;
}
protocol_interface_info_entry_t *interface_ptr = protocol_stack_interface_info_get_by_id(sckt_data->interface_id);
relay_instance_t *relay_srv =dhcp_service_relay_interface(sckt_data->interface_id);
if (!interface_ptr || !relay_srv || !relay_srv->relay_activated) {
return;
}
ns_address_t src_address;
uint8_t relay_frame[DHCPV6_RELAY_LENGTH + 4];
ns_iovec_t msg_iov[2];
msg_iov[0].iov_base = relay_frame;
msg_iov[0].iov_len = 34;
msg_iov[1].iov_base = ns_dyn_mem_temporary_alloc(sckt_data->d_len);
msg_iov[1].iov_len = sckt_data->d_len;
if (msg_iov[1].iov_base == NULL ) {
// read actual message
tr_error("Out of resources");
goto cleanup;
}
ns_msghdr_t msghdr;
//Set messages name buffer
msghdr.msg_name = &src_address;
msghdr.msg_namelen = sizeof(src_address);
msghdr.msg_iov = &msg_iov[1];
msghdr.msg_iovlen = 1;
msghdr.msg_control = NULL;
msghdr.msg_controllen = 0;
msg_len = socket_recvmsg(sckt_data->socket_id, &msghdr, NS_MSG_LEGACY0);
tr_debug("dhcp Relay recv msg");
//Parse type
uint8_t *ptr = msg_iov[1].iov_base;
uint8_t msg_type = *ptr;
if (msg_type == DHCPV6_RELAY_FORWARD) {
tr_error("Drop not supported DHCPv6 forward at Agent");
goto cleanup;
} else if (msg_type == DHCPV6_RELAY_REPLY) {
//Parse and validate Relay
dhcpv6_relay_msg_t relay_msg;
if (!libdhcpv6_relay_msg_read(ptr, msg_len, &relay_msg) ) {
tr_error("Not valid relay");
goto cleanup;
}
if (0 != libdhcpv6_message_malformed_check(relay_msg.relay_options.msg_ptr, relay_msg.relay_options.len)) {
tr_error("Malformed packet");
goto cleanup;
}
//Copy DST address
memcpy(src_address.address, relay_msg.peer_address, 16);
src_address.type = ADDRESS_IPV6;
src_address.identifier = DHCPV6_CLIENT_PORT;
msghdr.msg_iov = &msg_iov[0];
msghdr.msg_iovlen = 1;
msg_iov[0].iov_base = relay_msg.relay_options.msg_ptr;
msg_iov[0].iov_len = relay_msg.relay_options.len;
tr_debug("Forward Original relay msg to client");
} else {
if (0 != libdhcpv6_message_malformed_check(ptr, msg_len)) {
tr_error("Malformed packet");
goto cleanup;
}
uint8_t gp_address[16];
//Get blobal address from interface
if (arm_net_address_get(sckt_data->interface_id, ADDR_IPV6_GP, gp_address) != 0) {
// No global prefix available
tr_error("No GP address");
goto cleanup;
}
//Build
libdhcpv6_dhcp_relay_msg_write(relay_frame, DHCPV6_RELAY_FORWARD, 0, src_address.address, gp_address);
libdhcpv6_dhcp_option_header_write(relay_frame + 34, msg_len);
//Copy DST address
memcpy(src_address.address, relay_srv->server_address, 16);
src_address.type = ADDRESS_IPV6;
src_address.identifier = DHCPV6_SERVER_PORT;
//ADD relay frame vector front of original data
msghdr.msg_iov = &msg_iov[0];
msghdr.msg_iovlen = 2;
msg_iov[0].iov_base = relay_frame;
msg_iov[0].iov_len = 38;
msg_iov[1].iov_len = msg_len;
tr_debug("Forward Client msg to server");
}
socket_sendmsg(sckt_data->socket_id, &msghdr, NS_MSG_LEGACY0);
cleanup:
ns_dyn_mem_free(msg_iov[1].iov_base);
return;
}
void recv_dhcp_client_msg(void *cb_res) void recv_dhcp_client_msg(void *cb_res)
{ {
ns_address_t address; ns_address_t address;
@ -351,8 +536,19 @@ uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_ty
return 0; return 0;
} }
if (instance_type == DHCP_INSTANCE_SERVER && dhcp_service->dhcp_server_socket < 0) { if (instance_type == DHCP_INSTANCE_SERVER && dhcp_service->dhcp_server_socket < 0) {
if (dhcp_service->dhcp_relay_socket >= 0) {
tr_error("dhcp Server socket can't open because Agent open already");
}
dhcp_service->dhcp_server_socket = socket_open(SOCKET_UDP, DHCPV6_SERVER_PORT, recv_dhcp_server_msg); dhcp_service->dhcp_server_socket = socket_open(SOCKET_UDP, DHCPV6_SERVER_PORT, recv_dhcp_server_msg);
} }
if (instance_type == DHCP_INTANCE_RELAY_AGENT && dhcp_service->dhcp_relay_socket < 0) {
if (dhcp_service->dhcp_server_socket >= 0) {
tr_error("dhcp Relay agent can't open because server open already");
}
dhcp_service->dhcp_relay_socket = socket_open(SOCKET_UDP, DHCPV6_SERVER_PORT, recv_dhcp_relay_msg);
}
if (instance_type == DHCP_INSTANCE_CLIENT && dhcp_service->dhcp_client_socket < 0) { if (instance_type == DHCP_INSTANCE_CLIENT && dhcp_service->dhcp_client_socket < 0) {
dhcp_service->dhcp_client_socket = socket_open(SOCKET_UDP, DHCPV6_CLIENT_PORT, recv_dhcp_client_msg); dhcp_service->dhcp_client_socket = socket_open(SOCKET_UDP, DHCPV6_CLIENT_PORT, recv_dhcp_client_msg);
} }
@ -364,6 +560,18 @@ uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_ty
tr_error("No sockets available for DHCP client"); tr_error("No sockets available for DHCP client");
return 0; return 0;
} }
if (instance_type == DHCP_INTANCE_RELAY_AGENT) {
if (dhcp_service->dhcp_relay_socket < 0) {
tr_error("No sockets available for DHCP server");
}
uint16_t temp_id = dhcp_service_relay_interface_get(interface_id);
if (temp_id) {
return temp_id;
}
}
for (; id < MAX_SERVERS; id++) { for (; id < MAX_SERVERS; id++) {
if (dhcp_service_client_find(id) == NULL) { if (dhcp_service_client_find(id) == NULL) {
break; break;
@ -375,6 +583,22 @@ uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_ty
ns_dyn_mem_free(srv_ptr); ns_dyn_mem_free(srv_ptr);
return 0; return 0;
} }
if (instance_type == DHCP_INTANCE_RELAY_AGENT) {
//Allocate Realay Agent
relay_instance_t *relay_srv = ns_dyn_mem_alloc(sizeof(relay_instance_t));
if (!relay_srv) {
tr_error("Out of realy instances");
ns_dyn_mem_free(srv_ptr);
return 0;
}
ns_list_add_to_start(&dhcp_service->relay_list, relay_srv);
relay_srv->instance_id = id;
relay_srv->interface_id = interface_id;
relay_srv->relay_activated = false;
}
ns_list_add_to_start(&dhcp_service->srv_list, srv_ptr); ns_list_add_to_start(&dhcp_service->srv_list, srv_ptr);
srv_ptr->instance_id = id; srv_ptr->instance_id = id;
srv_ptr->instance_type = instance_type; srv_ptr->instance_type = instance_type;
@ -383,6 +607,15 @@ uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_ty
return srv_ptr->instance_id; return srv_ptr->instance_id;
} }
void dhcp_service_relay_instance_enable(uint16_t instance, uint8_t *server_address)
{
relay_instance_t * realay_srv = dhcp_service_relay_find(instance);
if (realay_srv) {
realay_srv->relay_activated = true;
memcpy(realay_srv->server_address, server_address, 16);
}
}
void dhcp_service_delete(uint16_t instance) void dhcp_service_delete(uint16_t instance)
{ {
server_instance_t *srv_ptr; server_instance_t *srv_ptr;
@ -393,7 +626,16 @@ void dhcp_service_delete(uint16_t instance)
//TODO delete all transactions //TODO delete all transactions
if (srv_ptr != NULL) { if (srv_ptr != NULL) {
ns_list_remove(&dhcp_service->srv_list, srv_ptr); ns_list_remove(&dhcp_service->srv_list, srv_ptr);
if (srv_ptr->instance_type == DHCP_INTANCE_RELAY_AGENT) {
//Free relay service
relay_instance_t *relay = dhcp_service_relay_find(instance);
if (relay) {
ns_list_remove(&dhcp_service->relay_list, relay);
ns_dyn_mem_free(relay);
}
}
ns_dyn_mem_free(srv_ptr); ns_dyn_mem_free(srv_ptr);
} }
ns_list_foreach_safe(msg_tr_t, cur_ptr, &dhcp_service->tr_list) { ns_list_foreach_safe(msg_tr_t, cur_ptr, &dhcp_service->tr_list) {
if (cur_ptr->instance_id == instance) { if (cur_ptr->instance_id == instance) {
@ -401,17 +643,19 @@ void dhcp_service_delete(uint16_t instance)
} }
} }
int8_t server_instances = 0, client_instances = 0; int8_t server_instances = 0, client_instances = 0, relay_instances = 0;
ns_list_foreach(server_instance_t, srv, &dhcp_service->srv_list) { ns_list_foreach(server_instance_t, srv, &dhcp_service->srv_list) {
if (srv->instance_type == DHCP_INSTANCE_SERVER) { if (srv->instance_type == DHCP_INSTANCE_SERVER) {
++server_instances; ++server_instances;
} else if (srv->instance_type == DHCP_INSTANCE_CLIENT) { } else if (srv->instance_type == DHCP_INSTANCE_CLIENT) {
++client_instances; ++client_instances;
} else if (srv->instance_type == DHCP_INTANCE_RELAY_AGENT) {
++relay_instances;
} }
} }
if (server_instances == 0 && dhcp_service->dhcp_server_socket > -1) { if ((server_instances == 0 && relay_instances == 0) && dhcp_service->dhcp_server_socket > -1) {
socket_close(dhcp_service->dhcp_server_socket); socket_close(dhcp_service->dhcp_server_socket);
dhcp_service->dhcp_server_socket = -1; dhcp_service->dhcp_server_socket = -1;
} }
@ -458,7 +702,7 @@ uint32_t dhcp_service_send_req(uint16_t instance_id, uint8_t options, void *ptr,
msg_tr_ptr = dhcp_tr_create(); msg_tr_ptr = dhcp_tr_create();
if (msg_tr_ptr == NULL || srv_ptr == NULL || msg_ptr == NULL || receive_resp_cb == NULL || msg_len < 5) { if (msg_tr_ptr == NULL || srv_ptr == NULL || msg_ptr == NULL || receive_resp_cb == NULL || msg_len < 5) {
tr_error("request sending failed"); tr_error("Request sending failed");
return 0; return 0;
} }
@ -530,7 +774,38 @@ void dhcp_service_send_message(msg_tr_t *msg_tr_ptr)
} }
socket_setsockopt(msg_tr_ptr->socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_MULTICAST_HOPS, &multicast_hop_limit, sizeof multicast_hop_limit); socket_setsockopt(msg_tr_ptr->socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_MULTICAST_HOPS, &multicast_hop_limit, sizeof multicast_hop_limit);
socket_setsockopt(msg_tr_ptr->socket, SOCKET_IPPROTO_IPV6, SOCKET_INTERFACE_SELECT, &msg_tr_ptr->interface_id, sizeof(int8_t)); socket_setsockopt(msg_tr_ptr->socket, SOCKET_IPPROTO_IPV6, SOCKET_INTERFACE_SELECT, &msg_tr_ptr->interface_id, sizeof(int8_t));
if (msg_tr_ptr->relay_start) {
//Build Relay Reply only server do this
ns_iovec_t data_vector[2];
ns_msghdr_t msghdr;
memcpy(msg_tr_ptr->addr.address, msg_tr_ptr->relay_start + 2, 16);
msg_tr_ptr->addr.identifier = DHCPV6_SERVER_PORT;
//SET IOV vectors
//Relay Reply
data_vector[0].iov_base = (void *) msg_tr_ptr->relay_start;
data_vector[0].iov_len = DHCPV6_RELAY_LENGTH + 4;
//DHCPV normal message vector
data_vector[1].iov_base = (void *) msg_tr_ptr->msg_ptr;
data_vector[1].iov_len = msg_tr_ptr->msg_len;
//Set message name
msghdr.msg_name = (void *) &msg_tr_ptr->addr;
msghdr.msg_namelen = sizeof(ns_address_t);
msghdr.msg_iov = &data_vector[0];
msghdr.msg_iovlen = 2;
//No ancillary data
msghdr.msg_control = NULL;
msghdr.msg_controllen = 0;
uint8_t *ptr = msg_tr_ptr->relay_start;
*ptr = DHCPV6_RELAY_REPLY;
libdhcpv6_dhcp_option_header_write(ptr +34, msg_tr_ptr->msg_len);
retval = socket_sendmsg(msg_tr_ptr->socket, &msghdr, NS_MSG_LEGACY0);
} else {
retval = socket_sendto(msg_tr_ptr->socket, &msg_tr_ptr->addr, msg_tr_ptr->msg_ptr, msg_tr_ptr->msg_len); retval = socket_sendto(msg_tr_ptr->socket, &msg_tr_ptr->addr, msg_tr_ptr->msg_ptr, msg_tr_ptr->msg_len);
}
if (retval != 0) { if (retval != 0) {
tr_warn("dhcp service socket_sendto fails: %i", retval); tr_warn("dhcp service socket_sendto fails: %i", retval);
} }
@ -588,6 +863,12 @@ void dhcp_service_delete(uint16_t instance)
(void)instance; (void)instance;
} }
void dhcp_service_relay_instance_enable(uint16_t instance, uint8_t *server_address)
{
(void)instance;
(void)server_address;
}
int dhcp_service_send_resp(uint32_t msg_tr_id, uint8_t options, uint8_t *msg_ptr, uint16_t msg_len) int dhcp_service_send_resp(uint32_t msg_tr_id, uint8_t options, uint8_t *msg_ptr, uint16_t msg_len)
{ {
(void)msg_tr_id; (void)msg_tr_id;
@ -626,4 +907,5 @@ bool dhcp_service_timer_tick(uint16_t ticks)
(void)ticks; (void)ticks;
return false; return false;
} }
#endif #endif

View File

@ -795,4 +795,43 @@ uint16_t libdhcpv6_solication_message_length(uint16_t clientLinkType, bool addre
return length; return length;
} }
uint8_t *libdhcpv6_dhcp_relay_msg_write(uint8_t *ptr, uint8_t type, uint8_t hop_limit, uint8_t *peer_addres, uint8_t *link_address)
{
*ptr++ = type;
*ptr++ = hop_limit;
memcpy(ptr, link_address, 16);
ptr += 16;
memcpy(ptr, peer_addres, 16);
ptr += 16;
return ptr;
}
uint8_t *libdhcpv6_dhcp_option_header_write(uint8_t *ptr, uint16_t length)
{
ptr = common_write_16_bit(DHCPV6_OPTION_RELAY, ptr);
ptr = common_write_16_bit(length, ptr);
return ptr;
}
bool libdhcpv6_relay_msg_read(uint8_t *ptr, uint16_t length, dhcpv6_relay_msg_t *relay_msg)
{
if (length < DHCPV6_RELAY_LENGTH + 4) {
return false;
}
// Relay message base first
relay_msg->type = *ptr++;
relay_msg->hop_limit = *ptr++;
relay_msg->link_address = ptr;
relay_msg->peer_address = ptr + 16;
ptr += 32;
//Discover
if (libdhcpv6_message_option_discover(ptr, length - 34, DHCPV6_OPTION_RELAY, &relay_msg->relay_options) != 0) {
return false;
}
return true;
}
#endif #endif

View File

@ -112,6 +112,14 @@ typedef struct dhcpv6_client_server_entry_s {
typedef NS_LIST_HEAD(dhcpv6_client_server_data_t, link) dhcpv6_client_server_entry_s; typedef NS_LIST_HEAD(dhcpv6_client_server_data_t, link) dhcpv6_client_server_entry_s;
typedef struct dhcpv6_relay_msg {
uint8_t type;
uint8_t hop_limit;
uint8_t *link_address;
uint8_t *peer_address;
dhcp_options_msg_t relay_options;
} dhcpv6_relay_msg_t;
/** UDP Port Number definition */ /** UDP Port Number definition */
#define DHCPV6_SERVER_PORT 547 #define DHCPV6_SERVER_PORT 547
#define DHCPV6_CLIENT_PORT 546 #define DHCPV6_CLIENT_PORT 546
@ -123,6 +131,8 @@ typedef NS_LIST_HEAD(dhcpv6_client_server_data_t, link) dhcpv6_client_server_ent
#define DHCPV6_RENEW_TYPE 5 #define DHCPV6_RENEW_TYPE 5
#define DHCPV6_REPLY_TYPE 7 #define DHCPV6_REPLY_TYPE 7
#define DHCPV6_RELEASE_TYPE 8 #define DHCPV6_RELEASE_TYPE 8
#define DHCPV6_RELAY_FORWARD 12
#define DHCPV6_RELAY_REPLY 13
#define DHCPV6_LEASEQUERY_TYPE 14 #define DHCPV6_LEASEQUERY_TYPE 14
#define DHCPV6_LEASEQUERY_REPLY_TYPE 15 #define DHCPV6_LEASEQUERY_REPLY_TYPE 15
@ -209,6 +219,11 @@ typedef NS_LIST_HEAD(dhcpv6_client_server_data_t, link) dhcpv6_client_server_ent
#define DHCPV6_OPTION_CLT_TIME 0x002e #define DHCPV6_OPTION_CLT_TIME 0x002e
#define DHCPV6_RELAY_LENGTH 34
#define DHCPV6_OPTION_RELAY 0x0009
/** DHCPv6 client Nontemporal address and server data allocate, free and search */ /** DHCPv6 client Nontemporal address and server data allocate, free and search */
dhcpv6_client_server_data_t *libdhcvp6_nontemporalAddress_server_data_allocate(int8_t interfaceId, uint8_t instanceId, uint8_t *duiId, uint16_t duiLinkType, uint8_t *nonTemporalPrefix, uint8_t *serverIPv6Address); dhcpv6_client_server_data_t *libdhcvp6_nontemporalAddress_server_data_allocate(int8_t interfaceId, uint8_t instanceId, uint8_t *duiId, uint16_t duiLinkType, uint8_t *nonTemporalPrefix, uint8_t *serverIPv6Address);
void libdhcvp6_nontemporalAddress_server_data_free(dhcpv6_client_server_data_t *removedEntry); void libdhcvp6_nontemporalAddress_server_data_free(dhcpv6_client_server_data_t *removedEntry);
@ -259,7 +274,8 @@ uint16_t libdhcpv6_address_reply_message_len(uint16_t clientLinkType, uint16_t s
uint8_t *libdhcpv6_generic_nontemporal_address_message_write(uint8_t *ptr, dhcpv6_solication_base_packet_s *packet, dhcpv6_ia_non_temporal_address_s *nonTemporalAddress, dhcp_link_options_params_t *serverLink); uint8_t *libdhcpv6_generic_nontemporal_address_message_write(uint8_t *ptr, dhcpv6_solication_base_packet_s *packet, dhcpv6_ia_non_temporal_address_s *nonTemporalAddress, dhcp_link_options_params_t *serverLink);
uint8_t *libdhcpv6_reply_message_write(uint8_t *ptr, dhcpv6_reply_packet_s *replyPacket, dhcpv6_ia_non_temporal_address_s *nonTemporalAddress, dhcpv6_vendor_data_packet_s *vendorData); uint8_t *libdhcpv6_reply_message_write(uint8_t *ptr, dhcpv6_reply_packet_s *replyPacket, dhcpv6_ia_non_temporal_address_s *nonTemporalAddress, dhcpv6_vendor_data_packet_s *vendorData);
uint8_t *libdhcpv6_dhcp_relay_msg_write(uint8_t *ptr, uint8_t type, uint8_t hop_limit, uint8_t *peer_addres, uint8_t *link_address);
uint8_t *libdhcpv6_dhcp_option_header_write(uint8_t *ptr, uint16_t length);
int libdhcpv6_get_IA_address(uint8_t *ptr, uint16_t data_length, dhcp_ia_non_temporal_params_t *params); int libdhcpv6_get_IA_address(uint8_t *ptr, uint16_t data_length, dhcp_ia_non_temporal_params_t *params);
int libdhcpv6_get_duid_by_selected_type_id_opt(uint8_t *ptr, uint16_t data_length, uint16_t type , dhcp_link_options_params_t *params); int libdhcpv6_get_duid_by_selected_type_id_opt(uint8_t *ptr, uint16_t data_length, uint16_t type , dhcp_link_options_params_t *params);
@ -347,5 +363,6 @@ int libdhcpv6_solication_message_options_validate(uint8_t *ptr, uint16_t data_le
int libdhcpv6_advertisment_message_option_validate(dhcp_link_options_params_t *clientId, dhcp_link_options_params_t *serverId, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params, uint8_t *ptr, uint16_t data_length); int libdhcpv6_advertisment_message_option_validate(dhcp_link_options_params_t *clientId, dhcp_link_options_params_t *serverId, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params, uint8_t *ptr, uint16_t data_length);
bool libdhcpv6_rapid_commit_option_at_packet(uint8_t *ptr, uint16_t length); bool libdhcpv6_rapid_commit_option_at_packet(uint8_t *ptr, uint16_t length);
bool libdhcpv6_time_elapsed_option_at_packet(uint8_t *ptr, uint16_t length); bool libdhcpv6_time_elapsed_option_at_packet(uint8_t *ptr, uint16_t length);
bool libdhcpv6_relay_msg_read(uint8_t *ptr, uint16_t length, dhcpv6_relay_msg_t *relay_msg);
#endif /* LIBDHCPV6_H_ */ #endif /* LIBDHCPV6_H_ */

View File

@ -43,11 +43,12 @@ static dhcpv6_gua_server_entry_s *libdhcpv6_server_entry_allocate(void)
dhcpv6_gua_server_entry_s *entry = ns_dyn_mem_alloc(sizeof(dhcpv6_gua_server_entry_s)); dhcpv6_gua_server_entry_s *entry = ns_dyn_mem_alloc(sizeof(dhcpv6_gua_server_entry_s));
if (entry) { if (entry) {
entry->clientIdSequence = 0; entry->clientIdSequence = 0;
entry->enableAddressMapping = false;
entry->enableAddressAutonous = true; entry->enableAddressAutonous = true;
entry->clientIdDefaultSuffics = 0x0000000; entry->clientIdDefaultSuffics = 0x0000000;
entry->maxSuppertedClients = 200; entry->maxSuppertedClients = 200;
entry->validLifetime = 7200; entry->validLifetime = 7200;
entry->removeCb = NULL;
entry->addCb = NULL;
ns_list_init(&entry->allocatedAddressList); ns_list_init(&entry->allocatedAddressList);
} }
return entry; return entry;
@ -62,7 +63,7 @@ static void libdhcpv6_address_generate(dhcpv6_gua_server_entry_s *serverInfo, dh
if (entry->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE) { if (entry->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE) {
memcpy(ptr, entry->linkId, 8); memcpy(ptr, entry->linkId, 8);
*ptr ^= 2; *ptr ^= 2;
} else if (entry->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE) { } else if (entry->linkType == DHCPV6_DUID_HARDWARE_EUI48_TYPE) {
*ptr++ = entry->linkId[0] ^ 2; *ptr++ = entry->linkId[0] ^ 2;
*ptr++ = entry->linkId[1]; *ptr++ = entry->linkId[1];
*ptr++ = entry->linkId[2]; *ptr++ = entry->linkId[2];
@ -96,7 +97,9 @@ void libdhcpv6_gua_servers_time_update(uint32_t timeUpdateInSeconds)
//Stop use this address for leasequery and delete Route or address map //Stop use this address for leasequery and delete Route or address map
address->preferredLifetime = 0; address->preferredLifetime = 0;
cur->timeoutCb(cur->interfaceId, address->nonTemporalAddress); if (cur->removeCb) {
cur->removeCb(cur->interfaceId, address->nonTemporalAddress, cur->guaPrefix);
}
} else { } else {
address->preferredLifetime -= timeUpdateInSeconds; address->preferredLifetime -= timeUpdateInSeconds;
} }
@ -137,17 +140,16 @@ dhcpv6_gua_server_entry_s *libdhcpv6_server_data_get_by_prefix_and_socketinstanc
} }
dhcpv6_gua_server_entry_s *libdhcpv6_gua_server_allocate(uint8_t *prefix, int8_t interfaceId, uint8_t *serverDUID, uint16_t serverDUIDType, dhcp_address_prefer_timeout_cb *prefered_timeout_cb) dhcpv6_gua_server_entry_s *libdhcpv6_gua_server_allocate(uint8_t *prefix, int8_t interfaceId, uint8_t *serverDUID, uint16_t serverDUIDType)
{ {
dhcpv6_gua_server_entry_s *entry = NULL; dhcpv6_gua_server_entry_s *entry = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefix);
if (libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefix) == NULL) { if (entry == NULL) {
entry = libdhcpv6_server_entry_allocate(); entry = libdhcpv6_server_entry_allocate();
if (entry) { if (entry) {
memcpy(entry->guaPrefix, prefix, 8); memcpy(entry->guaPrefix, prefix, 8);
memcpy(entry->serverDUID, serverDUID, 8); memcpy(entry->serverDUID, serverDUID, 8);
entry->serverLinkType = serverDUIDType; entry->serverLinkType = serverDUIDType;
entry->interfaceId = interfaceId; entry->interfaceId = interfaceId;
entry->timeoutCb = prefered_timeout_cb;
ns_list_add_to_end(&dhcpv6_gua_server_list, entry); ns_list_add_to_end(&dhcpv6_gua_server_list, entry);
} }
} }

View File

@ -26,7 +26,7 @@
#ifdef HAVE_DHCPV6_SERVER #ifdef HAVE_DHCPV6_SERVER
#include "ns_list.h" #include "ns_list.h"
typedef void (dhcp_address_prefer_timeout_cb)(int8_t interfaceId, uint8_t *targetAddress); typedef void (dhcp_address_prefer_remove_cb)(int8_t interfaceId, uint8_t *targetAddress, void *prefix_info);
typedef struct dhcpv6_alloacted_address_entry_s { typedef struct dhcpv6_alloacted_address_entry_s {
uint8_t nonTemporalAddress[16]; uint8_t nonTemporalAddress[16];
@ -50,10 +50,16 @@ typedef struct thread_dhcpv6_server_data_s {
ns_list_link_t link; /*!< List link entry */ ns_list_link_t link; /*!< List link entry */
} dhcpv6_server_data_entry_t; } dhcpv6_server_data_entry_t;
typedef struct dhcp_address_cache_update{
uint8_t *allocatedAddress;
bool allocatedNewAddress;
uint32_t validLifeTime;
} dhcp_address_cache_update_t;
typedef bool (dhcp_address_add_notify_cb)(int8_t interfaceId, dhcp_address_cache_update_t *address_info, void *route_src);
typedef struct dhcpv6_gua_server_entry_s { typedef struct dhcpv6_gua_server_entry_s {
int8_t interfaceId; int8_t interfaceId;
bool enableAddressMapping;
uint8_t meshLocalPrefix[8];
bool enableAddressAutonous; bool enableAddressAutonous;
uint16_t socketInstance_id; uint16_t socketInstance_id;
uint8_t guaPrefix[8]; uint8_t guaPrefix[8];
@ -63,13 +69,14 @@ typedef struct dhcpv6_gua_server_entry_s {
uint32_t clientIdDefaultSuffics; uint32_t clientIdDefaultSuffics;
uint32_t clientIdSequence; /*!< Define */ uint32_t clientIdSequence; /*!< Define */
uint32_t validLifetime; uint32_t validLifetime;
dhcp_address_prefer_timeout_cb *timeoutCb; dhcp_address_prefer_remove_cb *removeCb;
dhcp_address_add_notify_cb *addCb;
dhcpv6_alloacted_address_list_t allocatedAddressList; dhcpv6_alloacted_address_list_t allocatedAddressList;
ns_list_link_t link; /*!< List link entry */ ns_list_link_t link; /*!< List link entry */
} dhcpv6_gua_server_entry_s; } dhcpv6_gua_server_entry_s;
bool libdhcpv6_gua_server_list_empty(void); bool libdhcpv6_gua_server_list_empty(void);
dhcpv6_gua_server_entry_s *libdhcpv6_gua_server_allocate(uint8_t *prefix, int8_t interfaceId, uint8_t *serverDUID, uint16_t serverDUIDType, dhcp_address_prefer_timeout_cb *prefered_timeout_cb); dhcpv6_gua_server_entry_s *libdhcpv6_gua_server_allocate(uint8_t *prefix, int8_t interfaceId, uint8_t *serverDUID, uint16_t serverDUIDType);
void libdhcpv6_gua_server_free_by_prefix_and_interfaceid(uint8_t *prefix, int8_t interfaceId); void libdhcpv6_gua_server_free_by_prefix_and_interfaceid(uint8_t *prefix, int8_t interfaceId);
void libdhcpv6_gua_servers_time_update(uint32_t timeUpdateInSeconds); void libdhcpv6_gua_servers_time_update(uint32_t timeUpdateInSeconds);
void libdhcpv6_address_rm_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address); void libdhcpv6_address_rm_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address);
@ -81,7 +88,7 @@ dhcpv6_alloacted_address_entry_t *libdhcpv6_address_allocated_list_scan(dhcpv6_g
#define libdhcpv6_gua_server_list_empty() true #define libdhcpv6_gua_server_list_empty() true
#define libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefixPtr) NULL #define libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefixPtr) NULL
#define libdhcpv6_server_data_get_by_prefix_and_socketinstance(socketInstance, prefixPtr) NULL #define libdhcpv6_server_data_get_by_prefix_and_socketinstance(socketInstance, prefixPtr) NULL
#define libdhcpv6_gua_server_allocate(prefix, interfaceId, serverDUID, serverDUIDType, prefered_timeout_cb) NULL #define libdhcpv6_gua_server_allocate(prefix, interfaceId, serverDUID, serverDUIDType) NULL
#define libdhcpv6_gua_server_free_by_prefix_and_interfaceid(prefix, interfaceId) ((void)0) #define libdhcpv6_gua_server_free_by_prefix_and_interfaceid(prefix, interfaceId) ((void)0)
#define libdhcpv6_gua_servers_time_update(timeUpdateInSeconds) ((void)0) #define libdhcpv6_gua_servers_time_update(timeUpdateInSeconds) ((void)0)
#define libdhcpv6_gua_server_free_by_interfaceid(interfaceId) ((void)0) #define libdhcpv6_gua_server_free_by_interfaceid(interfaceId) ((void)0)

View File

@ -57,6 +57,12 @@
#endif #endif
#endif /* HAVE_THREAD */ #endif /* HAVE_THREAD */
#if defined(HAVE_WS)
#ifndef HAVE_DHCPV6
#define HAVE_DHCPV6
#endif
#endif /* HAVE_WS */
#endif // ifndef _NANOSTACK_SOURCE_CONFIG_H #endif // ifndef _NANOSTACK_SOURCE_CONFIG_H

Some files were not shown because too many files have changed in this diff Show More