mirror of https://github.com/ARMmbed/mbed-os.git
Add support for error cases for lwip and nanostack
parent
5a7482667e
commit
282f3c9da2
|
@ -482,6 +482,7 @@ static void mbed_lwip_netif_link_irq(struct netif *lwip_netif)
|
|||
|
||||
} else {
|
||||
sys_sem_signal(&lwip_netif_unlinked);
|
||||
netif_set_down(lwip_netif);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,9 +45,12 @@ typedef enum {
|
|||
*/
|
||||
typedef enum {
|
||||
MESH_CONNECTED = 0, /*<! connected to network */
|
||||
MESH_CONNECTED_LOCAL, /*<! connected to network, got local IP */
|
||||
MESH_CONNECTED_GLOBAL, /*<! connected to network, got global IP */
|
||||
MESH_DISCONNECTED, /*<! disconnected from network */
|
||||
MESH_BOOTSTRAP_START_FAILED, /*<! error during bootstrap start */
|
||||
MESH_BOOTSTRAP_FAILED /*<! error in bootstrap */
|
||||
MESH_BOOTSTRAP_FAILED, /*<! error in bootstrap */
|
||||
MESH_BOOTSTRAP_STARTED /*<! bootstrap started */
|
||||
} mesh_connection_status_t;
|
||||
|
||||
/*
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "NanostackInterface.h"
|
||||
#include "mesh_system.h"
|
||||
#include "net_interface.h"
|
||||
#include "thread_management_if.h"
|
||||
|
||||
|
||||
MeshInterfaceNanostack::MeshInterfaceNanostack()
|
||||
|
@ -49,7 +50,8 @@ void MeshInterfaceNanostack::mesh_network_handler(mesh_connection_status_t statu
|
|||
{
|
||||
nanostack_lock();
|
||||
|
||||
if (status == MESH_CONNECTED && _blocking) {
|
||||
if ((status == MESH_CONNECTED || status == MESH_CONNECTED_LOCAL ||
|
||||
status == MESH_CONNECTED_GLOBAL) && _blocking) {
|
||||
connect_semaphore.release();
|
||||
}
|
||||
|
||||
|
@ -57,12 +59,21 @@ void MeshInterfaceNanostack::mesh_network_handler(mesh_connection_status_t statu
|
|||
|
||||
|
||||
if (status == MESH_CONNECTED) {
|
||||
uint8_t temp_ipv6[16];
|
||||
if (!arm_net_address_get(_network_interface_id, ADDR_IPV6_GP, temp_ipv6)) {
|
||||
_connect_status = NSAPI_STATUS_GLOBAL_UP;
|
||||
} else {
|
||||
uint8_t temp_ipv6_global[16];
|
||||
uint8_t temp_ipv6_local[16];
|
||||
if (arm_net_address_get(_network_interface_id, ADDR_IPV6_LL, temp_ipv6_local) == 0) {
|
||||
_connect_status = NSAPI_STATUS_LOCAL_UP;
|
||||
}
|
||||
if (arm_net_address_get(_network_interface_id, ADDR_IPV6_GP, temp_ipv6_global) == 0
|
||||
&& (memcmp(temp_ipv6_global, temp_ipv6_local, 16) != 0)) {
|
||||
_connect_status = NSAPI_STATUS_GLOBAL_UP;
|
||||
}
|
||||
} else if (status == MESH_CONNECTED_LOCAL ) {
|
||||
_connect_status = NSAPI_STATUS_LOCAL_UP;
|
||||
} else if (status == MESH_CONNECTED_GLOBAL) {
|
||||
_connect_status = NSAPI_STATUS_GLOBAL_UP;
|
||||
} else if (status == MESH_BOOTSTRAP_STARTED) {
|
||||
_connect_status = NSAPI_STATUS_CONNECTING;
|
||||
} else {
|
||||
_connect_status = NSAPI_STATUS_DISCONNECTED;
|
||||
}
|
||||
|
|
|
@ -58,9 +58,12 @@ typedef enum {
|
|||
typedef struct {
|
||||
void (*mesh_api_cb)(mesh_connection_status_t nwk_status);
|
||||
tasklet_state_t tasklet_state;
|
||||
mesh_connection_status_t connection_status;
|
||||
timeout_t *poll_network_status_timeout;
|
||||
int8_t node_main_tasklet_id;
|
||||
int8_t network_interface_id;
|
||||
int8_t tasklet;
|
||||
uint8_t ip[16];
|
||||
} tasklet_data_str_t;
|
||||
|
||||
/* Tasklet data */
|
||||
|
@ -74,7 +77,7 @@ static void enet_tasklet_main(arm_event_s *event);
|
|||
static void enet_tasklet_network_state_changed(mesh_connection_status_t status);
|
||||
static void enet_tasklet_parse_network_event(arm_event_s *event);
|
||||
static void enet_tasklet_configure_and_connect_to_network(void);
|
||||
|
||||
static void enet_tasklet_poll_network_status();
|
||||
/*
|
||||
* \brief A function which will be eventually called by NanoStack OS when ever the OS has an event to deliver.
|
||||
* @param event, describes the sender, receiver and event type.
|
||||
|
@ -145,18 +148,20 @@ void enet_tasklet_parse_network_event(arm_event_s *event)
|
|||
if (tasklet_data_ptr->tasklet_state != TASKLET_STATE_BOOTSTRAP_READY) {
|
||||
tr_info("IPv6 bootstrap ready");
|
||||
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_READY;
|
||||
enet_tasklet_network_state_changed(MESH_CONNECTED);
|
||||
enet_tasklet_poll_network_status();
|
||||
}
|
||||
break;
|
||||
case ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL:
|
||||
/* No ND Router at current Channel Stack is Already at Idle state */
|
||||
tr_info("Bootstrap fail");
|
||||
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
|
||||
enet_tasklet_network_state_changed(MESH_DISCONNECTED);
|
||||
break;
|
||||
case ARM_NWK_NWK_CONNECTION_DOWN:
|
||||
/* Connection to Access point is lost wait for Scan Result */
|
||||
tr_info("Connection lost");
|
||||
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
|
||||
enet_tasklet_network_state_changed(MESH_DISCONNECTED);
|
||||
break;
|
||||
default:
|
||||
tr_warn("Unknown event %d", status);
|
||||
|
@ -172,6 +177,31 @@ void enet_tasklet_parse_network_event(arm_event_s *event)
|
|||
}
|
||||
}
|
||||
|
||||
static void enet_tasklet_poll_network_status(void)
|
||||
{
|
||||
/* Check if we do have an IP */
|
||||
uint8_t temp_ipv6[16];
|
||||
if (arm_net_address_get(tasklet_data_ptr->network_interface_id, ADDR_IPV6_GP, temp_ipv6) == 0) {
|
||||
/* Check if this is link local address or not */
|
||||
if (memcmp(temp_ipv6, tasklet_data_ptr->ip, 16) == 0) {
|
||||
return;
|
||||
} else {
|
||||
memcpy(tasklet_data_ptr->ip, temp_ipv6, 16);
|
||||
uint8_t temp_ipv6_local[16];
|
||||
if (arm_net_address_get(tasklet_data_ptr->network_interface_id, ADDR_IPV6_LL, temp_ipv6_local) == 0
|
||||
&& (memcmp(temp_ipv6, temp_ipv6_local, 16) != 0)) {
|
||||
enet_tasklet_network_state_changed(MESH_CONNECTED_GLOBAL);
|
||||
} else {
|
||||
enet_tasklet_network_state_changed(MESH_CONNECTED_LOCAL);;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (tasklet_data_ptr->connection_status != MESH_DISCONNECTED &&
|
||||
tasklet_data_ptr->connection_status != MESH_BOOTSTRAP_STARTED)
|
||||
enet_tasklet_network_state_changed(MESH_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* \brief Configure and establish network connection
|
||||
*
|
||||
|
@ -179,6 +209,7 @@ void enet_tasklet_parse_network_event(arm_event_s *event)
|
|||
void enet_tasklet_configure_and_connect_to_network(void)
|
||||
{
|
||||
arm_nwk_interface_up(tasklet_data_ptr->network_interface_id);
|
||||
enet_tasklet_network_state_changed(MESH_BOOTSTRAP_STARTED);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -186,6 +217,7 @@ void enet_tasklet_configure_and_connect_to_network(void)
|
|||
*/
|
||||
void enet_tasklet_network_state_changed(mesh_connection_status_t status)
|
||||
{
|
||||
tasklet_data_ptr->connection_status = status;
|
||||
if (tasklet_data_ptr->mesh_api_cb) {
|
||||
(tasklet_data_ptr->mesh_api_cb)(status);
|
||||
}
|
||||
|
@ -219,6 +251,8 @@ int8_t enet_tasklet_connect(mesh_interface_cb callback, int8_t nwk_interface_id)
|
|||
tasklet_data_ptr->mesh_api_cb = callback;
|
||||
tasklet_data_ptr->network_interface_id = nwk_interface_id;
|
||||
tasklet_data_ptr->tasklet_state = TASKLET_STATE_INITIALIZED;
|
||||
tasklet_data_ptr->poll_network_status_timeout =
|
||||
eventOS_timeout_every_ms(enet_tasklet_poll_network_status, 2000, NULL);
|
||||
|
||||
if (re_connecting == false) {
|
||||
tasklet_data_ptr->tasklet = eventOS_event_handler_create(&enet_tasklet_main,
|
||||
|
@ -248,6 +282,7 @@ int8_t enet_tasklet_disconnect(bool send_cb)
|
|||
}
|
||||
}
|
||||
tasklet_data_ptr->mesh_api_cb = NULL;
|
||||
eventOS_timeout_cancel(tasklet_data_ptr->poll_network_status_timeout);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -187,23 +187,28 @@ void nd_tasklet_parse_network_event(arm_event_s *event)
|
|||
/* Link Layer Active Scan Fail, Stack is Already at Idle state */
|
||||
tr_debug("Link Layer Scan Fail: No Beacons");
|
||||
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
|
||||
nd_tasklet_network_state_changed(MESH_DISCONNECTED);
|
||||
break;
|
||||
case ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL:
|
||||
/* No ND Router at current Channel Stack is Already at Idle state */
|
||||
tr_debug("ND Scan/ GP REG fail");
|
||||
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
|
||||
nd_tasklet_network_state_changed(MESH_DISCONNECTED);
|
||||
break;
|
||||
case ARM_NWK_NWK_CONNECTION_DOWN:
|
||||
/* Connection to Access point is lost wait for Scan Result */
|
||||
tr_debug("ND/RPL scan new network");
|
||||
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
|
||||
nd_tasklet_network_state_changed(MESH_DISCONNECTED);
|
||||
break;
|
||||
case ARM_NWK_NWK_PARENT_POLL_FAIL:
|
||||
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
|
||||
nd_tasklet_network_state_changed(MESH_DISCONNECTED);
|
||||
break;
|
||||
case ARM_NWK_AUHTENTICATION_FAIL:
|
||||
tr_debug("Network authentication fail");
|
||||
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
|
||||
nd_tasklet_network_state_changed(MESH_DISCONNECTED);
|
||||
break;
|
||||
default:
|
||||
tr_warn("Unknown event %d", status);
|
||||
|
@ -277,6 +282,7 @@ void nd_tasklet_configure_and_connect_to_network(void)
|
|||
if (status >= 0) {
|
||||
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_STARTED;
|
||||
tr_info("Start 6LoWPAN ND Bootstrap");
|
||||
nd_tasklet_network_state_changed(MESH_BOOTSTRAP_STARTED);
|
||||
} else {
|
||||
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
|
||||
tr_err("Bootstrap start failed, %d", status);
|
||||
|
|
|
@ -67,6 +67,8 @@ typedef struct {
|
|||
void (*mesh_api_cb)(mesh_connection_status_t nwk_status);
|
||||
channel_list_s channel_list;
|
||||
tasklet_state_t tasklet_state;
|
||||
mesh_connection_status_t connection_status;
|
||||
timeout_t *poll_network_status_timeout;
|
||||
int8_t tasklet;
|
||||
|
||||
net_6lowpan_mode_e operating_mode;
|
||||
|
@ -75,7 +77,8 @@ typedef struct {
|
|||
|
||||
/** Default network ID*/
|
||||
uint8_t networkid[16];
|
||||
uint8_t extented_panid[8];
|
||||
uint8_t extented_panid[8];
|
||||
uint8_t ip[16];
|
||||
} thread_tasklet_data_str_t;
|
||||
|
||||
|
||||
|
@ -88,6 +91,7 @@ void thread_tasklet_main(arm_event_s *event);
|
|||
void thread_tasklet_network_state_changed(mesh_connection_status_t status);
|
||||
void thread_tasklet_parse_network_event(arm_event_s *event);
|
||||
void thread_tasklet_configure_and_connect_to_network(void);
|
||||
void thread_tasklet_poll_network_status();
|
||||
#define TRACE_THREAD_TASKLET
|
||||
#ifndef TRACE_THREAD_TASKLET
|
||||
#define thread_tasklet_trace_bootstrap_info() ((void) 0)
|
||||
|
@ -127,8 +131,19 @@ void thread_tasklet_main(arm_event_s *event)
|
|||
thread_tasklet_data_ptr->tasklet);
|
||||
|
||||
if (event->event_id == TIMER_EVENT_START_BOOTSTRAP) {
|
||||
int8_t status;
|
||||
tr_debug("Restart bootstrap");
|
||||
arm_nwk_interface_up(thread_tasklet_data_ptr->nwk_if_id);
|
||||
status = arm_nwk_interface_up(thread_tasklet_data_ptr->nwk_if_id);
|
||||
|
||||
if (status >= 0) {
|
||||
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_STARTED;
|
||||
tr_info("Start Thread bootstrap (%s mode)", thread_tasklet_data_ptr->operating_mode == NET_6LOWPAN_SLEEPY_HOST ? "SED" : "Router");
|
||||
thread_tasklet_network_state_changed(MESH_BOOTSTRAP_STARTED);
|
||||
} else {
|
||||
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
|
||||
tr_err("Bootstrap start failed, %d", status);
|
||||
thread_tasklet_network_state_changed(MESH_BOOTSTRAP_START_FAILED);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -165,30 +180,36 @@ void thread_tasklet_parse_network_event(arm_event_s *event)
|
|||
tr_info("Thread bootstrap ready");
|
||||
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_READY;
|
||||
thread_tasklet_trace_bootstrap_info();
|
||||
thread_tasklet_network_state_changed(MESH_CONNECTED);
|
||||
/* We are connected, for Local or Global IP */
|
||||
thread_tasklet_poll_network_status();
|
||||
}
|
||||
break;
|
||||
case ARM_NWK_NWK_SCAN_FAIL:
|
||||
/* Link Layer Active Scan Fail, Stack is Already at Idle state */
|
||||
tr_debug("Link Layer Scan Fail: No Beacons");
|
||||
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
|
||||
thread_tasklet_network_state_changed(MESH_DISCONNECTED);
|
||||
break;
|
||||
case ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL:
|
||||
/* No ND Router at current Channel Stack is Already at Idle state */
|
||||
tr_debug("ND Scan/ GP REG fail");
|
||||
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
|
||||
thread_tasklet_network_state_changed(MESH_DISCONNECTED);
|
||||
break;
|
||||
case ARM_NWK_NWK_CONNECTION_DOWN:
|
||||
/* Connection to Access point is lost wait for Scan Result */
|
||||
tr_debug("ND/RPL scan new network");
|
||||
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
|
||||
thread_tasklet_network_state_changed(MESH_DISCONNECTED);
|
||||
break;
|
||||
case ARM_NWK_NWK_PARENT_POLL_FAIL:
|
||||
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
|
||||
thread_tasklet_network_state_changed(MESH_DISCONNECTED);
|
||||
break;
|
||||
case ARM_NWK_AUHTENTICATION_FAIL:
|
||||
tr_debug("Network authentication fail");
|
||||
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
|
||||
thread_tasklet_network_state_changed(MESH_DISCONNECTED);
|
||||
break;
|
||||
default:
|
||||
tr_warn("Unknown event %d", status);
|
||||
|
@ -204,6 +225,30 @@ void thread_tasklet_parse_network_event(arm_event_s *event)
|
|||
}
|
||||
}
|
||||
|
||||
void thread_tasklet_poll_network_status()
|
||||
{
|
||||
/* Check if we do have an IP */
|
||||
uint8_t temp_ipv6[16];
|
||||
if (arm_net_address_get(thread_tasklet_data_ptr->nwk_if_id, ADDR_IPV6_GP, temp_ipv6) == 0) {
|
||||
/* Check if this is the same IP than previously */
|
||||
if (memcmp(temp_ipv6, thread_tasklet_data_ptr->ip, 16) == 0) {
|
||||
return;
|
||||
} else {
|
||||
memcpy(thread_tasklet_data_ptr->ip, temp_ipv6, 16);
|
||||
link_configuration_s *link_cfg = thread_management_configuration_get(thread_tasklet_data_ptr->nwk_if_id);
|
||||
if (memcmp(thread_tasklet_data_ptr->ip, link_cfg->mesh_local_ula_prefix, 8) == 0) {
|
||||
thread_tasklet_network_state_changed(MESH_CONNECTED_LOCAL);
|
||||
} else {
|
||||
thread_tasklet_network_state_changed(MESH_CONNECTED_GLOBAL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (thread_tasklet_data_ptr->connection_status != MESH_DISCONNECTED &&
|
||||
thread_tasklet_data_ptr->connection_status != MESH_BOOTSTRAP_STARTED)
|
||||
thread_tasklet_network_state_changed(MESH_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
void read_link_configuration() {
|
||||
|
||||
thread_tasklet_data_ptr->link_config.panId = MBED_CONF_MBED_MESH_API_THREAD_CONFIG_PANID;
|
||||
|
@ -298,6 +343,7 @@ void thread_tasklet_configure_and_connect_to_network(void)
|
|||
if (status >= 0) {
|
||||
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_STARTED;
|
||||
tr_info("Start Thread bootstrap (%s mode)", thread_tasklet_data_ptr->operating_mode == NET_6LOWPAN_SLEEPY_HOST ? "SED" : "Router");
|
||||
thread_tasklet_network_state_changed(MESH_BOOTSTRAP_STARTED);
|
||||
} else {
|
||||
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
|
||||
tr_err("Bootstrap start failed, %d", status);
|
||||
|
@ -310,6 +356,7 @@ void thread_tasklet_configure_and_connect_to_network(void)
|
|||
*/
|
||||
void thread_tasklet_network_state_changed(mesh_connection_status_t status)
|
||||
{
|
||||
thread_tasklet_data_ptr->connection_status = status;
|
||||
if (thread_tasklet_data_ptr->mesh_api_cb) {
|
||||
(thread_tasklet_data_ptr->mesh_api_cb)(status);
|
||||
}
|
||||
|
@ -374,6 +421,8 @@ int8_t thread_tasklet_connect(mesh_interface_cb callback, int8_t nwk_interface_i
|
|||
thread_tasklet_data_ptr->mesh_api_cb = callback;
|
||||
thread_tasklet_data_ptr->nwk_if_id = nwk_interface_id;
|
||||
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_INITIALIZED;
|
||||
thread_tasklet_data_ptr->poll_network_status_timeout =
|
||||
eventOS_timeout_every_ms(thread_tasklet_poll_network_status, 2000, NULL);
|
||||
|
||||
if (re_connecting == false) {
|
||||
thread_tasklet_data_ptr->tasklet = eventOS_event_handler_create(&thread_tasklet_main,
|
||||
|
@ -383,6 +432,7 @@ int8_t thread_tasklet_connect(mesh_interface_cb callback, int8_t nwk_interface_i
|
|||
// -2 memory allocation failure
|
||||
return thread_tasklet_data_ptr->tasklet;
|
||||
}
|
||||
|
||||
ns_event_loop_thread_start();
|
||||
} else {
|
||||
thread_tasklet_data_ptr->tasklet = tasklet;
|
||||
|
@ -407,6 +457,8 @@ int8_t thread_tasklet_disconnect(bool send_cb)
|
|||
|
||||
// Clear callback, it will be set again in next connect
|
||||
thread_tasklet_data_ptr->mesh_api_cb = NULL;
|
||||
// Cancel the callback timeout
|
||||
eventOS_timeout_cancel(thread_tasklet_data_ptr->poll_network_status_timeout);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
@ -469,4 +521,3 @@ int8_t thread_tasklet_data_poll_rate_set(uint32_t timeout)
|
|||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue