Nanostack Border Router is a generic mbed border router implementation that provides the 6LoWPAN ND or Thread border router initialization logic.

Revision:
0:85f4174a8e29
Child:
7:571f9a90b972
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/borderrouter_tasklet.c	Thu Mar 09 17:47:03 2017 +0000
@@ -0,0 +1,663 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ */
+
+#define LOWPAN_ND 0
+#define THREAD 1
+#if MBED_CONF_APP_MESH_MODE == LOWPAN_ND
+
+#include <string.h>
+#include <stdlib.h>
+#include "ns_types.h"
+#include "eventOS_event.h"
+#include "eventOS_event_timer.h"
+#include "eventOS_scheduler.h"
+#include "multicast_api.h"
+#include "whiteboard_api.h"
+#include "platform/arm_hal_timer.h"
+#include "borderrouter_tasklet.h"
+#include "borderrouter_helpers.h"
+#include "net_interface.h"
+#include "cfg_parser.h"
+#include "rf_wrapper.h"
+#include "nwk_stats_api.h"
+#include "net_interface.h"
+#include "ip6string.h"
+#include "net_rpl.h"
+#include "mac_api.h"
+#include "ethernet_mac_api.h"
+#include "sw_mac.h"
+
+#include "static_6lowpan_config.h"
+
+#include "ns_trace.h"
+#define TRACE_GROUP "brro"
+
+#define NR_BACKHAUL_INTERFACE_PHY_DRIVER_READY 2
+#define NR_BACKHAUL_INTERFACE_PHY_DOWN  3
+
+static mac_api_t *api;
+static eth_mac_api_t *eth_mac_api;
+
+/* The border router tasklet runs in grounded/non-storing mode */
+#define RPL_FLAGS RPL_GROUNDED | BR_DODAG_MOP_NON_STORING | RPL_DODAG_PREF(0)
+
+typedef enum interface_bootstrap_state {
+    INTERFACE_IDLE_PHY_NOT_READY,
+    INTERFACE_IDLE_STATE,
+    INTERFACE_BOOTSTRAP_ACTIVE,
+    INTERFACE_CONNECTED
+} interface_bootstrap_state_e;
+
+typedef struct {
+    uint8_t DODAG_ID[16];
+    uint8_t rpl_instance_id;
+    uint8_t rpl_setups;
+} rpl_setup_info_t;
+
+typedef struct {
+    int8_t prefix_len;
+    uint8_t prefix[16];
+    uint8_t next_hop[16];
+} route_info_t;
+
+/* Border router channel list */
+static channel_list_s channel_list;
+
+/* Channel masks for different RF types */
+static const uint32_t channel_mask_0_2_4ghz = 0x07fff800;
+
+/* Border router settings */
+static border_router_setup_s br;
+
+/* RPL routing settings */
+static rpl_setup_info_t rpl_setup_info;
+
+/* DODAG configuration */
+static dodag_config_t dodag_config;
+
+/* Backhaul prefix */
+static uint8_t backhaul_prefix[16] = {0};
+
+/* Backhaul default route information */
+static route_info_t backhaul_route;
+
+/* Should prefix on the backhaul used for PAN as well? */
+static uint8_t rf_prefix_from_backhaul = 0;
+
+static net_6lowpan_mode_e operating_mode = NET_6LOWPAN_BORDER_ROUTER;
+static net_6lowpan_mode_extension_e operating_mode_extension = NET_6LOWPAN_ND_WITH_MLE;
+static interface_bootstrap_state_e net_6lowpan_state = INTERFACE_IDLE_PHY_NOT_READY;
+static interface_bootstrap_state_e net_backhaul_state = INTERFACE_IDLE_PHY_NOT_READY;
+static net_ipv6_mode_e backhaul_bootstrap_mode = NET_IPV6_BOOTSTRAP_STATIC;
+
+static const uint8_t gp16_address_suffix[6] = {0x00, 0x00, 0x00, 0xff, 0xfe, 0x00};
+
+static int8_t br_tasklet_id = -1;
+static int8_t net_6lowpan_id = -1;
+static int8_t backhaul_if_id = -1;
+
+/* Network statistics */
+static nwk_stats_t nwk_stats;
+
+/* Link layer security information */
+static net_6lowpan_link_layer_sec_mode_e link_security_mode;
+static net_link_layer_psk_security_info_s link_layer_psk;
+static net_tls_cipher_e pana_security_suite;
+
+static uint8_t multicast_addr[16] = {0};
+
+/* Function forward declarations */
+static void app_parse_network_event(arm_event_s *event);
+static void borderrouter_tasklet(arm_event_s *event);
+static void initialize_channel_list(uint32_t channel);
+static void start_6lowpan(const uint8_t *backhaul_address);
+static int8_t rf_interface_init(void);
+static void load_config(void);
+
+void border_router_start(void)
+{
+    load_config();
+    net_init_core();
+    /* initialize Radio module*/
+    net_6lowpan_id = rf_interface_init();
+
+    protocol_stats_start(&nwk_stats);
+
+    eventOS_event_handler_create(
+        &borderrouter_tasklet,
+        ARM_LIB_TASKLET_INIT_EVENT);
+}
+
+static void print_interface_addr(int id)
+{
+    uint8_t address_buf[128];
+    int address_count = 0;
+    char buf[128];
+
+    if (arm_net_address_list_get(id, 128, address_buf, &address_count) == 0) {
+        uint8_t *t_buf = address_buf;
+        for (int i = 0; i < address_count; ++i) {
+            ip6tos(t_buf, buf);
+            tr_info("   [%d] %s", i, buf);
+            t_buf += 16;
+        }
+    }
+}
+
+static void initialize_channel_list(uint32_t channel)
+{
+    const int_fast8_t word_index = channel / 32;
+    const int_fast8_t bit_index = channel % 32;
+
+    if (channel > 0) {
+        /* Zero channel value means listen all channels */
+        memset(&channel_list.channel_mask, 0, sizeof(channel_list.channel_mask));
+        channel_list.channel_mask[word_index] |= ((uint32_t) 1 << bit_index);
+    }
+}
+
+static void load_config(void)
+{
+    const char *prefix, *psk;
+    uint8_t nd_prefix[16];
+
+    prefix = cfg_string(global_config, "PREFIX", NULL);
+
+    if (!prefix) {
+        tr_error("No RF prefix in configuration!");
+        return;
+    }
+
+    stoip6(prefix, strlen(prefix), nd_prefix);
+
+    prefix = cfg_string(global_config, "BACKHAUL_PREFIX", NULL);
+    if (!prefix) {
+        tr_error("No backhaul prefix in configuration!");
+        return;
+    }
+
+    stoip6(prefix, strlen(prefix), backhaul_prefix);
+    memset(&backhaul_prefix[8], 0, 8);
+
+    prefix = cfg_string(global_config, "MULTICAST_ADDR", NULL);
+    if (!prefix) {
+        tr_error("No multicast address in configuration!");
+        return;
+    }
+
+    stoip6(prefix, strlen(prefix), multicast_addr);
+
+    /* Set up channel page and channgel mask */
+    memset(&channel_list, 0, sizeof(channel_list));
+    channel_list.channel_page = (channel_page_e)cfg_int(global_config, "RF_CHANNEL_PAGE", CHANNEL_PAGE_0);
+    channel_list.channel_mask[0] = cfg_int(global_config, "RF_CHANNEL_MASK", channel_mask_0_2_4ghz);
+
+    prefix = cfg_string(global_config, "NETWORK_ID", "NETWORK000000000");
+    memcpy(br.network_id, prefix, 16);
+
+    br.mac_panid = cfg_int(global_config, "PAN_ID", 0x0691);
+    tr_info("PANID: %x", br.mac_panid);
+    br.mac_short_adr = cfg_int(global_config, "SHORT_MAC_ADDRESS", 0xffff);
+    br.ra_life_time = cfg_int(global_config, "RA_ROUTER_LIFETIME", 1024);
+    br.beacon_protocol_id = cfg_int(global_config, "BEACON_PROTOCOL_ID", 4);
+
+    memcpy(br.lowpan_nd_prefix, nd_prefix, 8);
+    br.abro_version_num = 0;
+
+    /* RPL routing setup */
+    rpl_setup_info.rpl_instance_id = cfg_int(global_config, "RPL_INSTANCE_ID", 1);
+    rpl_setup_info.rpl_setups = RPL_FLAGS;
+
+    /* generate DODAG ID */
+    memcpy(rpl_setup_info.DODAG_ID, nd_prefix, 8);
+    memcpy(&rpl_setup_info.DODAG_ID[8], gp16_address_suffix, 6);
+    rpl_setup_info.DODAG_ID[14] = (br.mac_short_adr >> 8);
+    rpl_setup_info.DODAG_ID[15] = br.mac_short_adr;
+
+    /* DODAG configuration */
+    dodag_config.DAG_DIO_INT_DOUB = cfg_int(global_config, "RPL_IDOUBLINGS", 12);
+    dodag_config.DAG_DIO_INT_MIN = cfg_int(global_config, "RPL_IMIN", 9);
+    dodag_config.DAG_DIO_REDU = cfg_int(global_config, "RPL_K", 10);
+    dodag_config.DAG_MAX_RANK_INC = cfg_int(global_config, "RPL_MAX_RANK_INC", 2048);
+    dodag_config.DAG_MIN_HOP_RANK_INC = cfg_int(global_config, "RPL_MIN_HOP_RANK_INC", 128);
+    dodag_config.LIFE_IN_SECONDS = cfg_int(global_config, "RPL_LIFETIME_UNIT", 64);
+    dodag_config.LIFETIME_UNIT = cfg_int(global_config, "RPL_DEFAULT_LIFETIME", 60);
+    dodag_config.DAG_SEC_PCS = cfg_int(global_config, "RPL_PCS", 1);
+    dodag_config.DAG_OCP = cfg_int(global_config, "RPL_OCP", 1);
+
+    bool dynamic_bootstrap = (net_ipv6_mode_e)cfg_int(global_config, "BACKHAUL_DYNAMIC_BOOTSTRAP", 0);
+
+    if (dynamic_bootstrap == 1) {
+        backhaul_bootstrap_mode = NET_IPV6_BOOTSTRAP_AUTONOMOUS;
+        tr_info("NET_IPV6_BOOTSTRAP_AUTONOMOUS");
+    } else {
+        tr_info("NET_IPV6_BOOTSTRAP_STATIC");
+        backhaul_bootstrap_mode = NET_IPV6_BOOTSTRAP_STATIC;
+    }
+
+    /* Bootstrap mode for the backhaul interface */
+    rf_prefix_from_backhaul = cfg_int(global_config, "PREFIX_FROM_BACKHAUL", 0);
+
+    /* Backhaul default route */
+    memset(&backhaul_route, 0, sizeof(backhaul_route));
+    psk = cfg_string(global_config, "BACKHAUL_NEXT_HOP", NULL);
+
+    if (psk) {
+        stoip6(psk, strlen(psk), backhaul_route.next_hop);
+    }
+
+    psk = cfg_string(global_config, "BACKHAUL_DEFAULT_ROUTE", NULL);
+
+    if (psk) {
+        char *prefix, route_buf[255] = {0};
+
+        /* copy the config value to a non-const buffer */
+        strncpy(route_buf, psk, sizeof(route_buf) - 1);
+        prefix = strtok(route_buf, "/");
+        backhaul_route.prefix_len = atoi(strtok(NULL, "/"));
+
+        stoip6(prefix, strlen(prefix), backhaul_route.prefix);
+    }
+
+    prefix = cfg_string(global_config, "SECURITY_MODE", "NONE");
+
+    if (strcmp(prefix, "NONE") == 0) {
+        link_security_mode = NET_SEC_MODE_NO_LINK_SECURITY;
+        tr_warn("Security NOT enabled");
+        return;
+    }
+
+    psk = cfg_string(global_config, "PSK_KEY", NULL);
+
+    if (!psk) {
+        tr_error("No PSK set in configuration!");
+        return;
+    }
+
+    link_layer_psk.key_id = cfg_int(global_config, "PSK_KEY_ID", 1);
+    memcpy(link_layer_psk.security_key, psk, 16);
+
+    if (strcmp(prefix, "PSK") == 0) {
+        tr_debug("Using PSK security mode, key ID = %d", link_layer_psk.key_id);
+        link_security_mode = NET_SEC_MODE_PSK_LINK_SECURITY;
+    } else if (strcmp(prefix, "PANA") == 0) {
+        const char *mode = cfg_string(global_config, "PANA_MODE", "PSK");
+        link_security_mode = NET_SEC_MODE_PANA_LINK_SECURITY;
+        if (strcmp(mode, "ECC") == 0) {
+            pana_security_suite = NET_TLS_ECC_CIPHER;
+        } else if (strcmp(mode, "ECC+PSK") == 0) {
+            pana_security_suite = NET_TLS_PSK_AND_ECC_CIPHER;
+        } else {
+            pana_security_suite = NET_TLS_PSK_CIPHER;
+        }
+    }
+}
+
+static int8_t rf_interface_init(void)
+{
+    static char phy_name[] = "mesh0";
+    int8_t rfid = -1;
+    int8_t rf_phy_device_register_id = rf_device_register();
+    tr_debug("RF device ID: %d", rf_phy_device_register_id);
+
+    if (rf_phy_device_register_id >= 0) {
+        mac_description_storage_size_t storage_sizes;
+        storage_sizes.device_decription_table_size = 32;
+        storage_sizes.key_description_table_size = 3;
+        storage_sizes.key_lookup_size = 1;
+        storage_sizes.key_usage_size = 3;
+        if (!api) {
+            api = ns_sw_mac_create(rf_phy_device_register_id, &storage_sizes);
+        }
+        rfid = arm_nwk_interface_lowpan_init(api, phy_name);
+        tr_debug("RF interface ID: %d", rfid);
+    }
+
+    return rfid;
+}
+
+static void borderrouter_backhaul_phy_status_cb(uint8_t link_up, int8_t driver_id)
+{
+    arm_event_s event = {
+        .sender = br_tasklet_id,
+        .receiver = br_tasklet_id,
+        .priority = ARM_LIB_MED_PRIORITY_EVENT,
+        .event_type = APPLICATION_EVENT,
+        .event_data = driver_id
+    };
+
+    if (link_up) {
+        event.event_id = NR_BACKHAUL_INTERFACE_PHY_DRIVER_READY;
+    } else {
+        event.event_id = NR_BACKHAUL_INTERFACE_PHY_DOWN;
+    }
+
+    tr_debug("Backhaul driver ID: %d", driver_id);
+
+    eventOS_event_send(&event);
+}
+
+static int backhaul_interface_up(int8_t driver_id)
+{
+    int retval = -1;
+    if (backhaul_if_id != -1) {
+        tr_debug("Border RouterInterface already at active state\n");
+    } else {
+        if (!eth_mac_api) {
+            eth_mac_api = ethernet_mac_create(driver_id);
+        }
+
+        backhaul_if_id = arm_nwk_interface_ethernet_init(eth_mac_api, "bh0");
+
+        if (backhaul_if_id >= 0) {
+            tr_debug("Backhaul interface ID: %d", backhaul_if_id);
+            if (memcmp(backhaul_prefix, (const uint8_t[8]) { 0 }, 8) == 0) {
+                memcpy(backhaul_prefix, rpl_setup_info.DODAG_ID, 8);
+            }
+            arm_nwk_interface_configure_ipv6_bootstrap_set(
+                backhaul_if_id, backhaul_bootstrap_mode, backhaul_prefix);
+            arm_nwk_interface_up(backhaul_if_id);
+            retval = 0;
+        }
+    }
+    return retval;
+}
+
+static int backhaul_interface_down(void)
+{
+    int retval = -1;
+    if (backhaul_if_id != -1) {
+        arm_nwk_interface_down(backhaul_if_id);
+        backhaul_if_id = -1;
+        retval = 0;
+    }
+    return retval;
+}
+
+/**
+  * \brief Border Router Main Tasklet
+  *
+  *  Tasklet Handle next items:
+  *
+  *  - EV_INIT event: Set Certificate Chain, RF Interface Boot UP, multicast Init
+  *  - SYSTEM_TIMER event: For RF interface Handshake purpose
+  *
+  */
+static void borderrouter_tasklet(arm_event_s *event)
+{
+    arm_library_event_type_e event_type;
+    event_type = (arm_library_event_type_e)event->event_type;
+
+    switch (event_type) {
+        case ARM_LIB_NWK_INTERFACE_EVENT:
+            app_parse_network_event(event);
+            break;
+
+        case APPLICATION_EVENT:
+            if (event->event_id == NR_BACKHAUL_INTERFACE_PHY_DRIVER_READY) {
+                int8_t net_backhaul_id = (int8_t) event->event_data;
+                if (net_backhaul_state == INTERFACE_IDLE_PHY_NOT_READY) {
+                    net_backhaul_state = INTERFACE_IDLE_STATE;
+                }
+
+                if (backhaul_interface_up(net_backhaul_id) != 0) {
+                    tr_debug("Backhaul bootstrap start failed");
+                } else {
+                    tr_debug("Backhaul bootstrap started");
+                    net_backhaul_state = INTERFACE_BOOTSTRAP_ACTIVE;
+                }
+            } else if (event->event_id == NR_BACKHAUL_INTERFACE_PHY_DOWN) {
+                if (backhaul_interface_down() != 0) {
+                    tr_error("Backhaul interface down failed");
+                } else {
+                    tr_debug("Backhaul interface is down");
+                    backhaul_if_id = -1;
+                    net_backhaul_state = INTERFACE_IDLE_STATE;
+                }
+            }
+            break;
+
+        case ARM_LIB_TASKLET_INIT_EVENT:
+            print_appl_info();
+            br_tasklet_id = event->receiver;
+
+            /* initialize the backhaul interface */
+            backhaul_driver_init(borderrouter_backhaul_phy_status_cb);
+
+            if (net_6lowpan_id < 0) {
+                tr_error("RF interface initialization failed");
+                return;
+            }
+            net_6lowpan_state = INTERFACE_IDLE_STATE;
+            eventOS_event_timer_request(9, ARM_LIB_SYSTEM_TIMER_EVENT, br_tasklet_id, 20000);
+            break;
+
+        case ARM_LIB_SYSTEM_TIMER_EVENT:
+            eventOS_event_timer_cancel(event->event_id, event->receiver);
+
+            if (event->event_id == 9) {
+#ifdef MBED_CONF_APP_DEBUG_TRACE
+#if MBED_CONF_APP_DEBUG_TRACE == 1
+                arm_print_routing_table();
+                arm_print_neigh_cache();
+#endif
+#endif
+                eventOS_event_timer_request(9, ARM_LIB_SYSTEM_TIMER_EVENT, br_tasklet_id, 20000);
+            }
+            break;
+
+        default:
+            break;
+    }
+}
+
+static void start_6lowpan(const uint8_t *backhaul_address)
+{
+    uint8_t p[16] = {0};
+
+    if (arm_net_address_get(backhaul_if_id, ADDR_IPV6_GP, p) == 0) {
+        uint32_t lifetime = 0xffffffff; // infinite
+        uint8_t prefix_len = 0;
+        uint8_t t_flags = 0;
+        int8_t retval = -1;
+
+        /* Channel list: listen to a channel (default: all channels) */
+        uint32_t channel = cfg_int(global_config, "RF_CHANNEL", 0);
+        tr_info("RF channel: %d", channel);
+        initialize_channel_list(channel);
+
+        // configure as border router and set the operation mode
+        retval = arm_nwk_interface_configure_6lowpan_bootstrap_set(net_6lowpan_id,
+                 operating_mode, operating_mode_extension);
+
+        if (retval < 0) {
+            tr_error("Configuring 6LoWPAN bootstrap failed, retval = %d", retval);
+            return;
+        }
+
+        retval = arm_nwk_link_layer_security_mode(net_6lowpan_id, link_security_mode, 5, &link_layer_psk);
+
+        if (retval < 0) {
+            tr_error("Failed to set link layer security mode, retval = %d", retval);
+            return;
+        }
+
+        /* Should we use the backhaul prefix on the PAN as well? */
+        if (backhaul_address && rf_prefix_from_backhaul) {
+            memcpy(br.lowpan_nd_prefix, p, 8);
+            memcpy(rpl_setup_info.DODAG_ID, br.lowpan_nd_prefix, 8);
+        }
+
+        retval = arm_nwk_6lowpan_border_router_init(net_6lowpan_id, &br);
+
+        if (retval < 0) {
+            tr_error("Initializing 6LoWPAN border router failed, retval = %d", retval);
+            return;
+        }
+
+        /* configure both /64 and /128 context prefixes */
+        retval = arm_nwk_6lowpan_border_router_context_update(net_6lowpan_id, ((1 << 4) | 0x03),
+                 128, 0xffff, rpl_setup_info.DODAG_ID);
+
+        if (retval < 0) {
+            tr_error("Setting ND context failed, retval = %d", retval);
+            return;
+        }
+
+        // configure the RPL routing protocol for the 6LoWPAN mesh network
+        if (arm_nwk_6lowpan_rpl_dodag_init(net_6lowpan_id, rpl_setup_info.DODAG_ID,
+                                           &dodag_config, rpl_setup_info.rpl_instance_id,
+                                           rpl_setup_info.rpl_setups) == 0) {
+            prefix_len = 64;
+            t_flags = RPL_PREFIX_ROUTER_ADDRESS_FLAG;
+            /* add "/64" prefix with the full BR address (DODAG ID) */
+            arm_nwk_6lowpan_rpl_dodag_prefix_update(net_6lowpan_id, rpl_setup_info.DODAG_ID,
+                                                    prefix_len, t_flags, lifetime);
+
+            t_flags = 0;
+            prefix_len = 0;
+            /* add default route "::/0" */
+            arm_nwk_6lowpan_rpl_dodag_route_update(net_6lowpan_id, rpl_setup_info.DODAG_ID,
+                                                   prefix_len, t_flags, lifetime);
+        }
+
+        if (link_security_mode == NET_SEC_MODE_PANA_LINK_SECURITY) {
+            uint8_t *psk = (uint8_t *)cfg_string(global_config, "TLS_PSK_KEY", NULL);
+
+            if (!psk) {
+                tr_error("No TLS PSK key set in configuration");
+                return;
+            }
+
+            if (arm_tls_add_psk_key(psk, cfg_int(global_config, "TLS_PSK_KEY_ID", 0)) != 0) {
+                tr_error("No TLS PSK key ID set in configuration");
+                return;
+            }
+
+            retval = arm_pana_server_library_init(net_6lowpan_id, pana_security_suite, NULL, 120);
+
+            if (retval) {
+                tr_error("Failed to initialize PANA server library, retval = %d", retval);
+                return;
+            }
+        }
+
+        retval = arm_nwk_set_channel_list(net_6lowpan_id, &channel_list);
+
+        if (retval) {
+            tr_error("Failed to set channel list, retval = %d", retval);
+            return;
+        }
+
+        retval = arm_nwk_interface_up(net_6lowpan_id);
+
+        if (retval < 0) {
+            tr_error("Failed to bring up the RF interface, retval = %d", retval);
+            return;
+        }
+
+        /* mark the RF interface active */
+        net_6lowpan_state = INTERFACE_BOOTSTRAP_ACTIVE;
+
+        multicast_set_parameters(10, 0, 20, 3, 75);
+        multicast_add_address(multicast_addr, 1);
+    }
+}
+
+/**
+  * \brief Network state event handler.
+  * \param event show network start response or current network state.
+  *
+  */
+static void app_parse_network_event(arm_event_s *event)
+{
+    switch ((arm_nwk_interface_status_type_e)event->event_data) {
+        case ARM_NWK_BOOTSTRAP_READY: {
+            bool gp_address_available;
+            uint8_t p[16];
+            char buf[128];
+            if (0 == arm_net_address_get(event->event_id, ADDR_IPV6_GP, p)) {
+                ip6tos(p, buf);
+                gp_address_available = true;
+            } else {
+                gp_address_available = false;
+            }
+
+            if (backhaul_if_id == event->event_id) {
+
+                if (gp_address_available) {
+                    tr_info("Backhaul bootstrap ready, IPv6 = %s", buf);
+                } else {
+                    tr_info("Backhaul interface in ULA Mode");
+                }
+
+                if (backhaul_bootstrap_mode == NET_IPV6_BOOTSTRAP_STATIC) {
+                    int8_t retval;
+                    uint8_t *next_hop_ptr;
+
+                    if (memcmp(backhaul_route.next_hop, (const uint8_t[16]) {0}, 16) == 0) {
+                        tr_info("Next hop not defined");
+                        next_hop_ptr = NULL;
+                    }
+                    else {
+                        next_hop_ptr = backhaul_route.next_hop;
+                    }
+
+                    tr_info("Backhaul default route:");
+                    tr_info("   prefix:   %s", print_ipv6_prefix(backhaul_route.prefix, backhaul_route.prefix_len));
+                    tr_info("   next hop: %s", next_hop_ptr ? print_ipv6(backhaul_route.next_hop) : "on-link");
+
+                    retval = arm_net_route_add(backhaul_route.prefix, backhaul_route.prefix_len,
+                                               next_hop_ptr, 0xffffffff, 128, backhaul_if_id);
+
+                    if (retval < 0) {
+                        tr_error("Failed to add backhaul default route, retval = %d", retval);
+                    }
+                }
+
+                tr_info("Backhaul interface addresses:");
+                print_interface_addr(backhaul_if_id);
+
+                net_backhaul_state = INTERFACE_CONNECTED;
+                if (net_6lowpan_state == INTERFACE_IDLE_STATE) {
+                    //Start 6lowpan
+                    start_6lowpan(p);
+                }
+            } else {
+                tr_info("RF bootstrap ready, IPv6 = %s", buf);
+                arm_nwk_6lowpan_rpl_dodag_start(net_6lowpan_id);
+                net_6lowpan_state = INTERFACE_CONNECTED;
+                tr_info("RF interface addresses:");
+                print_interface_addr(net_6lowpan_id);
+                tr_info("6LoWPAN Border Router Bootstrap Complete.");
+            }
+        }
+            /* Network connection Ready */
+        break;
+        case ARM_NWK_NWK_SCAN_FAIL:
+            /* Link Layer Active Scan Fail, Stack is Already in Idle state */
+            break;
+        case ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL:
+            /* No ND Router at current Channel Stack is Already at Idle state */
+            break;
+        case ARM_NWK_NWK_CONNECTION_DOWN:
+            /* Connection to Access point is lost wait for Scan Result */
+            break;
+        case ARM_NWK_NWK_PARENT_POLL_FAIL:
+            break;
+        case ARM_NWK_AUHTENTICATION_FAIL:
+            /* Network authentication fail */
+            break;
+        case ARM_NWK_DUPLICATE_ADDRESS_DETECTED:
+            if (backhaul_if_id == event->event_id) {
+                tr_error("Backhaul DAD failed.");
+            }
+            break;
+        default:
+            /* Unknow event */
+            break;
+    }
+}
+
+#endif // MBED_CONF_APP_MESH_MODE