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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers borderrouter_ws.c Source File

borderrouter_ws.c

00001 /*
00002  * Copyright (c) 2019 ARM Limited. All rights reserved.
00003  */
00004 
00005 #define LOWPAN_ND 0
00006 #define THREAD 1
00007 #define LOWPAN_WS 2
00008 #if MBED_CONF_APP_MESH_MODE == LOWPAN_WS
00009 
00010 #include <string.h>
00011 #include <stdlib.h>
00012 #include <mbed_assert.h>
00013 #include "eventOS_event.h"
00014 #include "eventOS_event_timer.h"
00015 #include "eventOS_scheduler.h"
00016 #include "platform/arm_hal_timer.h"
00017 #include "borderrouter_tasklet.h"
00018 #include "borderrouter_helpers.h"
00019 #include "net_interface.h"
00020 #include "rf_wrapper.h"
00021 #include "fhss_api.h"
00022 #include "fhss_config.h"
00023 #include "ws_management_api.h"
00024 #include "ws_bbr_api.h"
00025 #include "ip6string.h"
00026 #include "mac_api.h"
00027 #include "ethernet_mac_api.h"
00028 #include "sw_mac.h"
00029 #include "nwk_stats_api.h"
00030 #include "randLIB.h"
00031 #ifdef MBED_CONF_APP_CERTIFICATE_HEADER
00032 #include MBED_CONF_APP_CERTIFICATE_HEADER
00033 #endif
00034 
00035 #include "ns_trace.h"
00036 #define TRACE_GROUP "brro"
00037 
00038 #define NR_BACKHAUL_INTERFACE_PHY_DRIVER_READY 2
00039 #define NR_BACKHAUL_INTERFACE_PHY_DOWN  3
00040 #define MESH_LINK_TIMEOUT 100
00041 #define MESH_METRIC 1000
00042 
00043 #define WS_DEFAULT_REGULATORY_DOMAIN 255
00044 #define WS_DEFAULT_OPERATING_CLASS 255
00045 #define WS_DEFAULT_OPERATING_MODE 255
00046 #define WS_DEFAULT_UC_CHANNEL_FUNCTION 255
00047 #define WS_DEFAULT_BC_CHANNEL_FUNCTION 255
00048 #define WS_DEFAULT_UC_DWELL_INTERVAL 0
00049 #define WS_DEFAULT_BC_INTERVAL 0
00050 #define WS_DEFAULT_BC_DWELL_INTERVAL 0
00051 #define WS_DEFAULT_UC_FIXED_CHANNEL 0xffff
00052 #define WS_DEFAULT_BC_FIXED_CHANNEL 0xffff
00053 
00054 static mac_api_t *mac_api;
00055 static eth_mac_api_t *eth_mac_api;
00056 
00057 typedef enum {
00058     STATE_UNKNOWN,
00059     STATE_DISCONNECTED,
00060     STATE_LINK_READY,
00061     STATE_BOOTSTRAP,
00062     STATE_CONNECTED,
00063     STATE_MAX_VALUE
00064 } connection_state_e;
00065 
00066 typedef struct {
00067     int8_t prefix_len;
00068     uint8_t prefix[16];
00069     uint8_t next_hop[16];
00070 } route_info_t;
00071 
00072 typedef struct {
00073     int8_t  ws_interface_id;
00074     int8_t  net_interface_id;
00075 } ws_br_handler_t;
00076 
00077 static ws_br_handler_t ws_br_handler;
00078 
00079 /* Backhaul prefix */
00080 static uint8_t backhaul_prefix[16] = {0};
00081 
00082 /* Backhaul default route information */
00083 static route_info_t backhaul_route;
00084 static int8_t br_tasklet_id = -1;
00085 
00086 /* Network statistics */
00087 static nwk_stats_t nwk_stats;
00088 
00089 /* Function forward declarations */
00090 
00091 static void network_interface_event_handler(arm_event_s *event);
00092 static void mesh_network_up(void);
00093 static void eth_network_data_init(void);
00094 static net_ipv6_mode_e backhaul_bootstrap_mode = NET_IPV6_BOOTSTRAP_STATIC;
00095 static void borderrouter_tasklet(arm_event_s *event);
00096 static int wisun_interface_up(void);
00097 static void wisun_interface_event_handler(arm_event_s *event);
00098 static void network_interface_event_handler(arm_event_s *event);
00099 static int backhaul_interface_down(void);
00100 static void borderrouter_backhaul_phy_status_cb(uint8_t link_up, int8_t driver_id);
00101 extern fhss_timer_t fhss_functions;
00102 
00103 typedef struct {
00104     char *network_name;
00105     uint8_t regulatory_domain;
00106     uint8_t operating_class;
00107     uint8_t operating_mode;
00108     uint8_t uc_channel_function;
00109     uint8_t bc_channel_function;
00110     uint8_t uc_dwell_interval;
00111     uint32_t bc_interval;
00112     uint8_t bc_dwell_interval;
00113     uint16_t uc_fixed_channel;
00114     uint16_t bc_fixed_channel;
00115 } ws_config_t;
00116 static ws_config_t ws_conf;
00117 
00118 static void mesh_network_up()
00119 {
00120     tr_debug("Create Mesh Interface");
00121 
00122     int status;
00123     int8_t wisun_if_id = ws_br_handler.ws_interface_id;
00124 
00125     status = arm_nwk_interface_configure_6lowpan_bootstrap_set(
00126                  wisun_if_id,
00127                  NET_6LOWPAN_BORDER_ROUTER,
00128                  NET_6LOWPAN_WS);
00129 
00130     if (status < 0) {
00131         tr_error("arm_nwk_interface_configure_6lowpan_bootstrap_set() failed");
00132         return;
00133     }
00134 
00135     status = wisun_interface_up();
00136     MBED_ASSERT(!status);
00137     if (status) {
00138         tr_error("wisun_interface_up() failed: %d", status);
00139     }
00140 }
00141 
00142 static void eth_network_data_init()
00143 {
00144     memset(&backhaul_prefix[8], 0, 8);
00145 
00146     /* Bootstrap mode for the backhaul interface */
00147 #if MBED_CONF_APP_BACKHAUL_DYNAMIC_BOOTSTRAP == 1
00148     backhaul_bootstrap_mode = NET_IPV6_BOOTSTRAP_AUTONOMOUS;
00149     tr_info("NET_IPV6_BOOTSTRAP_AUTONOMOUS");
00150 
00151 #else
00152     tr_info("NET_IPV6_BOOTSTRAP_STATIC");
00153     backhaul_bootstrap_mode = NET_IPV6_BOOTSTRAP_STATIC;
00154     // done like this so that prefix can be left out in the dynamic case.
00155     const char *param = MBED_CONF_APP_BACKHAUL_PREFIX;
00156     stoip6(param, strlen(param), backhaul_prefix);
00157     tr_info("backhaul_prefix: %s", print_ipv6(backhaul_prefix));
00158 
00159     /* Backhaul route configuration*/
00160     memset(&backhaul_route, 0, sizeof(backhaul_route));
00161 #ifdef MBED_CONF_APP_BACKHAUL_NEXT_HOP
00162     param = MBED_CONF_APP_BACKHAUL_NEXT_HOP;
00163     stoip6(param, strlen(param), backhaul_route.next_hop);
00164     tr_info("next hop: %s", print_ipv6(backhaul_route.next_hop));
00165 #endif
00166     param = MBED_CONF_APP_BACKHAUL_DEFAULT_ROUTE;
00167     char *prefix, route_buf[255] = {0};
00168     /* copy the config value to a non-const buffer */
00169     strncpy(route_buf, param, sizeof(route_buf) - 1);
00170     prefix = strtok(route_buf, "/");
00171     backhaul_route.prefix_len = atoi(strtok(NULL, "/"));
00172     stoip6(prefix, strlen(prefix), backhaul_route.prefix);
00173     tr_info("backhaul route prefix: %s", print_ipv6(backhaul_route.prefix));
00174 #endif
00175 }
00176 
00177 void load_config(void)
00178 {
00179     ws_conf.network_name = malloc(sizeof(MBED_CONF_APP_NETWORK_NAME) + 1);
00180     strcpy(ws_conf.network_name, MBED_CONF_APP_NETWORK_NAME);
00181 #ifdef MBED_CONF_APP_REGULATORY_DOMAIN
00182     ws_conf.regulatory_domain = MBED_CONF_APP_REGULATORY_DOMAIN;
00183 #else
00184     ws_conf.regulatory_domain = WS_DEFAULT_REGULATORY_DOMAIN;
00185 #endif //MBED_CONF_APP_REGULATORY_DOMAIN
00186 #ifdef MBED_CONF_APP_OPERATING_CLASS
00187     ws_conf.operating_class = MBED_CONF_APP_OPERATING_CLASS;
00188 #else
00189     ws_conf.operating_class = WS_DEFAULT_OPERATING_CLASS;
00190 #endif //MBED_CONF_APP_OPERATING_CLASS
00191 #ifdef MBED_CONF_APP_OPERATING_MODE
00192     ws_conf.operating_mode = MBED_CONF_APP_OPERATING_MODE;
00193 #else
00194     ws_conf.operating_mode = WS_DEFAULT_OPERATING_MODE;
00195 #endif //MBED_CONF_APP_OPERATING_MODE
00196 #ifdef MBED_CONF_APP_UC_CHANNEL_FUNCTION
00197     ws_conf.uc_channel_function = MBED_CONF_APP_UC_CHANNEL_FUNCTION;
00198 #else
00199     ws_conf.uc_channel_function = WS_DEFAULT_UC_CHANNEL_FUNCTION;
00200 #endif //MBED_CONF_APP_UC_CHANNEL_FUNCTION
00201 #ifdef MBED_CONF_APP_BC_CHANNEL_FUNCTION
00202     ws_conf.bc_channel_function = MBED_CONF_APP_BC_CHANNEL_FUNCTION;
00203 #else
00204     ws_conf.bc_channel_function = WS_DEFAULT_BC_CHANNEL_FUNCTION;
00205 #endif //MBED_CONF_APP_UC_CHANNEL_FUNCTION
00206 #ifdef MBED_CONF_APP_UC_DWELL_INTERVAL
00207     ws_conf.uc_dwell_interval = MBED_CONF_APP_UC_DWELL_INTERVAL;
00208 #else
00209     ws_conf.uc_dwell_interval = WS_DEFAULT_UC_DWELL_INTERVAL;
00210 #endif //MBED_CONF_APP_UC_DWELL_INTERVAL
00211 #ifdef MBED_CONF_APP_BC_INTERVAL
00212     ws_conf.bc_interval = MBED_CONF_APP_BC_INTERVAL;
00213 #else
00214     ws_conf.bc_interval = WS_DEFAULT_BC_INTERVAL;
00215 #endif //MBED_CONF_APP_BC_INTERVAL
00216 #ifdef MBED_CONF_APP_BC_DWELL_INTERVAL
00217     ws_conf.bc_dwell_interval = MBED_CONF_APP_BC_DWELL_INTERVAL;
00218 #else
00219     ws_conf.bc_dwell_interval = WS_DEFAULT_BC_DWELL_INTERVAL;
00220 #endif //MBED_CONF_APP_BC_DWELL_INTERVAL
00221 // Using randomized fixed channel by default
00222 #ifdef MBED_CONF_APP_UC_FIXED_CHANNEL
00223     ws_conf.uc_fixed_channel = MBED_CONF_APP_UC_FIXED_CHANNEL;
00224 #else
00225     ws_conf.uc_fixed_channel = WS_DEFAULT_UC_FIXED_CHANNEL;
00226 #endif //MBED_CONF_APP_UC_FIXED_CHANNEL
00227 #ifdef MBED_CONF_APP_BC_FIXED_CHANNEL
00228     ws_conf.bc_fixed_channel = MBED_CONF_APP_BC_FIXED_CHANNEL;
00229 #else
00230     ws_conf.bc_fixed_channel = WS_DEFAULT_BC_FIXED_CHANNEL;
00231 #endif //MBED_CONF_APP_BC_FIXED_CHANNEL
00232 }
00233 
00234 void wisun_rf_init()
00235 {
00236     mac_description_storage_size_t storage_sizes;
00237     storage_sizes.device_decription_table_size = 32;
00238     storage_sizes.key_description_table_size = 4;
00239     storage_sizes.key_lookup_size = 1;
00240     storage_sizes.key_usage_size = 1;
00241 
00242     int8_t rf_driver_id = rf_device_register();
00243     MBED_ASSERT(rf_driver_id >= 0);
00244     if (rf_driver_id >= 0) {
00245         randLIB_seed_random();
00246         if (!mac_api) {
00247             mac_api = ns_sw_mac_create(rf_driver_id, &storage_sizes);
00248         }
00249 
00250         ws_br_handler.ws_interface_id = arm_nwk_interface_lowpan_init(mac_api, ws_conf.network_name);
00251 
00252         if (ws_br_handler.ws_interface_id < 0) {
00253             tr_error("Wi-SUN interface creation failed");
00254             return;
00255         }
00256 
00257         if (ws_br_handler.ws_interface_id > -1 &&
00258                 ws_br_handler.net_interface_id > -1) {
00259             ws_bbr_start(ws_br_handler.ws_interface_id, ws_br_handler.net_interface_id);
00260         }
00261     }
00262 }
00263 
00264 
00265 static int wisun_interface_up(void)
00266 {
00267     int32_t ret;
00268 
00269     fhss_timer_t *fhss_timer_ptr = NULL;
00270 
00271     fhss_timer_ptr = &fhss_functions;
00272 
00273     ret = ws_management_node_init(ws_br_handler.ws_interface_id, ws_conf.regulatory_domain, ws_conf.network_name, fhss_timer_ptr);
00274     if (0 != ret) {
00275         tr_error("WS node init fail - code %"PRIi32"", ret);
00276         return -1;
00277     }
00278 
00279     if (ws_conf.uc_channel_function != WS_DEFAULT_UC_CHANNEL_FUNCTION) {
00280         ret = ws_management_fhss_unicast_channel_function_configure(ws_br_handler.ws_interface_id, ws_conf.uc_channel_function, ws_conf.uc_fixed_channel, ws_conf.uc_dwell_interval);
00281         if (ret != 0) {
00282             tr_error("Unicast channel function configuration failed %"PRIi32"", ret);
00283             return -1;
00284         }
00285     }
00286     if (ws_conf.bc_channel_function != WS_DEFAULT_BC_CHANNEL_FUNCTION ||
00287             ws_conf.bc_dwell_interval != WS_DEFAULT_BC_DWELL_INTERVAL ||
00288             ws_conf.bc_interval != WS_DEFAULT_BC_INTERVAL) {
00289         ret = ws_management_fhss_broadcast_channel_function_configure(ws_br_handler.ws_interface_id, ws_conf.bc_channel_function, ws_conf.bc_fixed_channel, ws_conf.bc_dwell_interval, ws_conf.bc_interval);
00290         if (ret != 0) {
00291             tr_error("Broadcast channel function configuration failed %"PRIi32"", ret);
00292             return -1;
00293         }
00294     }
00295 
00296     if (ws_conf.uc_dwell_interval != WS_DEFAULT_UC_DWELL_INTERVAL ||
00297             ws_conf.bc_dwell_interval != WS_DEFAULT_BC_DWELL_INTERVAL ||
00298             ws_conf.bc_interval != WS_DEFAULT_BC_INTERVAL) {
00299         ret = ws_management_fhss_timing_configure(ws_br_handler.ws_interface_id, ws_conf.uc_dwell_interval, ws_conf.bc_interval, ws_conf.bc_dwell_interval);
00300         if (ret != 0) {
00301             tr_error("fhss configuration failed %"PRIi32"", ret);
00302             return -1;
00303         }
00304     }
00305     if (ws_conf.regulatory_domain != WS_DEFAULT_REGULATORY_DOMAIN ||
00306             ws_conf.operating_mode != WS_DEFAULT_OPERATING_MODE ||
00307             ws_conf.operating_class != WS_DEFAULT_OPERATING_CLASS) {
00308         ret = ws_management_regulatory_domain_set(ws_br_handler.ws_interface_id, ws_conf.regulatory_domain, ws_conf.operating_class, ws_conf.operating_mode);
00309         if (ret != 0) {
00310             tr_error("Regulatory domain configuration failed %"PRIi32"", ret);
00311             return -1;
00312         }
00313     }
00314 
00315 #if defined(MBED_CONF_APP_CERTIFICATE_HEADER)
00316     arm_certificate_chain_entry_s chain_info;
00317     memset(&chain_info, 0, sizeof(arm_certificate_chain_entry_s));
00318     chain_info.cert_chain[0] = (const uint8_t *) MBED_CONF_APP_ROOT_CERTIFICATE;
00319     chain_info.cert_len[0] = strlen((const char *) MBED_CONF_APP_ROOT_CERTIFICATE) + 1;
00320     chain_info.cert_chain[1] = (const uint8_t *) MBED_CONF_APP_OWN_CERTIFICATE;
00321     chain_info.cert_len[1] = strlen((const char *) MBED_CONF_APP_OWN_CERTIFICATE) + 1;
00322     chain_info.key_chain[1] = (const uint8_t *) MBED_CONF_APP_OWN_CERTIFICATE_KEY;
00323     chain_info.chain_length = 2;
00324     arm_network_certificate_chain_set((const arm_certificate_chain_entry_s *) &chain_info);
00325 #endif
00326     ret = arm_nwk_interface_up(ws_br_handler.ws_interface_id);
00327     if (ret != 0) {
00328         tr_error("mesh0 up Fail with code: %"PRIi32"", ret);
00329         return ret;
00330     }
00331     tr_info("mesh0 bootstrap ongoing..");
00332     return 0;
00333 }
00334 
00335 void border_router_tasklet_start(void)
00336 {
00337     ws_br_handler.ws_interface_id = -1;
00338     ws_br_handler.net_interface_id = -1;
00339 
00340     load_config();
00341     wisun_rf_init();
00342     protocol_stats_start(&nwk_stats);
00343 
00344     eventOS_event_handler_create(
00345         &borderrouter_tasklet,
00346         ARM_LIB_TASKLET_INIT_EVENT);
00347 }
00348 
00349 #undef ETH
00350 #undef SLIP
00351 #undef EMAC
00352 #undef CELL
00353 #define ETH 1
00354 #define SLIP 2
00355 #define EMAC 3
00356 #define CELL 4
00357 
00358 static int backhaul_interface_up(int8_t driver_id)
00359 {
00360     int retval = -1;
00361     tr_debug("backhaul_interface_up: %i", driver_id);
00362     if (ws_br_handler.net_interface_id != -1) {
00363         tr_debug("Border RouterInterface already at active state");
00364         return retval;
00365     }
00366 
00367     if (!eth_mac_api) {
00368         eth_mac_api = ethernet_mac_create(driver_id);
00369     }
00370 
00371 #if MBED_CONF_APP_BACKHAUL_DRIVER == CELL
00372     if (eth_mac_api->iid64_get) {
00373         ws_br_handler.net_interface_id = arm_nwk_interface_ppp_init(eth_mac_api, "ppp0");
00374     } else
00375 #endif
00376     {
00377         ws_br_handler.net_interface_id = arm_nwk_interface_ethernet_init(eth_mac_api, "bh0");
00378     }
00379 
00380     MBED_ASSERT(ws_br_handler.net_interface_id >= 0);
00381     if (ws_br_handler.net_interface_id >= 0) {
00382         tr_debug("Backhaul interface ID: %d", ws_br_handler.net_interface_id);
00383         if (ws_br_handler.ws_interface_id > -1) {
00384             ws_bbr_start(ws_br_handler.ws_interface_id, ws_br_handler.net_interface_id);
00385         }
00386         arm_nwk_interface_configure_ipv6_bootstrap_set(
00387             ws_br_handler.net_interface_id, backhaul_bootstrap_mode, backhaul_prefix);
00388         arm_nwk_interface_up(ws_br_handler.net_interface_id);
00389         retval = 0;
00390     } else {
00391         tr_error("Could not init ethernet");
00392     }
00393 
00394     return retval;
00395 }
00396 
00397 #undef ETH
00398 #undef SLIP
00399 #undef EMAC
00400 #undef CELL
00401 
00402 static int backhaul_interface_down(void)
00403 {
00404     int retval = -1;
00405     if (ws_br_handler.net_interface_id != -1) {
00406         arm_nwk_interface_down(ws_br_handler.net_interface_id);
00407         ws_br_handler.net_interface_id = -1;
00408         retval = 0;
00409     } else {
00410         tr_debug("Could not set eth down");
00411     }
00412     return retval;
00413 }
00414 
00415 static void print_interface_addr(int id)
00416 {
00417     uint8_t address_buf[128];
00418     int address_count = 0;
00419     char buf[128];
00420 
00421     if (arm_net_address_list_get(id, 128, address_buf, &address_count) == 0) {
00422         uint8_t *t_buf = address_buf;
00423         for (int i = 0; i < address_count; ++i) {
00424             ip6tos(t_buf, buf);
00425             tr_info(" [%d] %s", i, buf);
00426             t_buf += 16;
00427         }
00428     }
00429 }
00430 
00431 #if MBED_CONF_APP_DEBUG_TRACE
00432 static void print_interface_addresses(void)
00433 {
00434     tr_info("Backhaul interface addresses:");
00435     print_interface_addr(ws_br_handler.net_interface_id);
00436 
00437     tr_info("RF interface addresses:");
00438     print_interface_addr(ws_br_handler.ws_interface_id);
00439 }
00440 #endif
00441 
00442 /**
00443   * \brief Border Router Main Tasklet
00444   *
00445   *  Tasklet Handle next items:
00446   *
00447   *  - EV_INIT event: Set Certificate Chain, RF Interface Boot UP, multicast Init
00448   *  - SYSTEM_TIMER event: For RF interface Handshake purpose
00449   *
00450   */
00451 static void borderrouter_tasklet(arm_event_s *event)
00452 {
00453     arm_library_event_type_e event_type;
00454     event_type = (arm_library_event_type_e)event->event_type;
00455 
00456     switch (event_type) {
00457         case ARM_LIB_NWK_INTERFACE_EVENT:
00458 
00459             if (event->event_id == ws_br_handler.net_interface_id) {
00460                 network_interface_event_handler(event);
00461             } else {
00462                 wisun_interface_event_handler(event);
00463             }
00464 
00465             break;
00466         // comes from the backhaul_driver_init.
00467         case APPLICATION_EVENT:
00468             if (event->event_id == NR_BACKHAUL_INTERFACE_PHY_DRIVER_READY) {
00469                 int8_t net_backhaul_id = (int8_t) event->event_data;
00470 
00471                 if (backhaul_interface_up(net_backhaul_id) != 0) {
00472                     tr_debug("Backhaul bootstrap start failed");
00473                 } else {
00474                     tr_debug("Backhaul bootstrap started");
00475                 }
00476             } else if (event->event_id == NR_BACKHAUL_INTERFACE_PHY_DOWN) {
00477                 if (backhaul_interface_down() == 0) {
00478                     tr_debug("Backhaul interface is down");
00479                 }
00480             }
00481             break;
00482 
00483         case ARM_LIB_TASKLET_INIT_EVENT:
00484             br_tasklet_id = event->receiver;
00485             eth_network_data_init();
00486             backhaul_driver_init(borderrouter_backhaul_phy_status_cb);
00487             mesh_network_up();
00488             eventOS_event_timer_request(9, ARM_LIB_SYSTEM_TIMER_EVENT, br_tasklet_id, 20000);
00489             break;
00490 
00491         case ARM_LIB_SYSTEM_TIMER_EVENT:
00492             eventOS_event_timer_cancel(event->event_id, event->receiver);
00493 
00494             if (event->event_id == 9) {
00495 #if MBED_CONF_APP_DEBUG_TRACE
00496                 arm_print_routing_table();
00497                 arm_print_neigh_cache();
00498                 print_memory_stats();
00499                 // Trace interface addresses. This trace can be removed if nanostack prints added/removed
00500                 // addresses.
00501                 print_interface_addresses();
00502 #endif
00503                 eventOS_event_timer_request(9, ARM_LIB_SYSTEM_TIMER_EVENT, br_tasklet_id, 20000);
00504             }
00505             break;
00506 
00507         default:
00508             break;
00509     }
00510 }
00511 
00512 static void borderrouter_backhaul_phy_status_cb(uint8_t link_up, int8_t driver_id)
00513 {
00514     arm_event_s event = {
00515         .sender = br_tasklet_id,
00516         .receiver = br_tasklet_id,
00517         .priority = ARM_LIB_MED_PRIORITY_EVENT,
00518         .event_type = APPLICATION_EVENT,
00519         .event_data = driver_id
00520     };
00521 
00522     if (link_up) {
00523         event.event_id = NR_BACKHAUL_INTERFACE_PHY_DRIVER_READY;
00524     } else {
00525         event.event_id = NR_BACKHAUL_INTERFACE_PHY_DOWN;
00526     }
00527 
00528     eventOS_event_send(&event);
00529 }
00530 
00531 // ethernet interface
00532 static void network_interface_event_handler(arm_event_s *event)
00533 {
00534     arm_nwk_interface_status_type_e status = (arm_nwk_interface_status_type_e)event->event_data;
00535     switch (status) {
00536         case (ARM_NWK_BOOTSTRAP_READY): { // Interface configured Bootstrap is ready
00537 
00538             tr_info("BR interface_id: %d", ws_br_handler.net_interface_id);
00539             if (-1 != ws_br_handler.net_interface_id) {
00540                 // metric set to high priority
00541                 if (0 != arm_net_interface_set_metric(ws_br_handler.net_interface_id, 0)) {
00542                     tr_warn("Failed to set metric for eth0.");
00543                 }
00544 
00545                 if (backhaul_bootstrap_mode == NET_IPV6_BOOTSTRAP_STATIC) {
00546                     uint8_t *next_hop_ptr;
00547 
00548                     if (memcmp(backhaul_route.next_hop, (const uint8_t[16]) {
00549                     0
00550                 }, 16) == 0) {
00551                         next_hop_ptr = NULL;
00552                     } else {
00553                         next_hop_ptr = backhaul_route.next_hop;
00554                     }
00555                     tr_debug("Default route prefix: %s/%d", print_ipv6(backhaul_route.prefix),
00556                              backhaul_route.prefix_len);
00557                     tr_debug("Default route next hop: %s", print_ipv6(backhaul_route.next_hop));
00558                     arm_net_route_add(backhaul_route.prefix,
00559                                       backhaul_route.prefix_len,
00560                                       next_hop_ptr, 0xffffffff, 128,
00561                                       ws_br_handler.net_interface_id);
00562                 }
00563                 tr_info("Backhaul interface addresses:");
00564                 print_interface_addr(ws_br_handler.net_interface_id);
00565             }
00566             break;
00567         }
00568         case (ARM_NWK_RPL_INSTANCE_FLOODING_READY): // RPL instance have been flooded
00569             tr_info("RPL instance have been flooded");
00570             break;
00571         case (ARM_NWK_SET_DOWN_COMPLETE): // Interface DOWN command successfully
00572             break;
00573         case (ARM_NWK_NWK_SCAN_FAIL):   // Interface have not detect any valid network
00574             tr_warning("mesh0 haven't detect any valid nwk");
00575             break;
00576         case (ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL): // IP address allocation fail(ND, DHCPv4 or DHCPv6)
00577             tr_error("NO GP address detected");
00578             break;
00579         case (ARM_NWK_DUPLICATE_ADDRESS_DETECTED): // User specific GP16 was not valid
00580             tr_error("Ethernet IPv6 Duplicate addr detected!");
00581             break;
00582         case (ARM_NWK_AUHTENTICATION_START_FAIL): // No valid Authentication server detected behind access point ;
00583             tr_error("No valid ath server detected behind AP");
00584             break;
00585         case (ARM_NWK_AUHTENTICATION_FAIL): // Network authentication fail by Handshake
00586             tr_error("Network authentication fail");
00587             break;
00588         case (ARM_NWK_NWK_CONNECTION_DOWN): // No connection between Access point or Default Router
00589             tr_warning("Prefix timeout");
00590             break;
00591         case (ARM_NWK_NWK_PARENT_POLL_FAIL): // Sleepy host poll fail 3 time
00592             tr_warning("Parent poll fail");
00593             break;
00594         case (ARM_NWK_PHY_CONNECTION_DOWN): // Interface PHY cable off or serial port interface not respond anymore
00595             tr_error("eth0 down");
00596             break;
00597         default:
00598             tr_warning("Unknown nwk if event (type: %02x, id: %02x, data: %02x)", event->event_type, event->event_id, (unsigned int)event->event_data);
00599             break;
00600     }
00601 }
00602 
00603 static void wisun_interface_event_handler(arm_event_s *event)
00604 {
00605     arm_nwk_interface_status_type_e status = (arm_nwk_interface_status_type_e)event->event_data;
00606     switch (status) {
00607         case (ARM_NWK_BOOTSTRAP_READY): { // Interface configured Bootstrap is ready
00608             tr_info("Wisun bootstrap ready");
00609 
00610             if (arm_net_interface_set_metric(ws_br_handler.ws_interface_id, MESH_METRIC) != 0) {
00611                 tr_warn("Failed to set metric for mesh0.");
00612             }
00613 
00614             tr_info("RF interface addresses:");
00615             print_interface_addr(ws_br_handler.ws_interface_id);
00616 
00617             break;
00618         }
00619         case (ARM_NWK_SET_DOWN_COMPLETE):
00620             tr_info("Wisun interface down");
00621             break;
00622         default:
00623             tr_warning("Unknown nwk if event (type: %02x, id: %02x, data: %02x)", event->event_type, event->event_id, (unsigned int)event->event_data);
00624             break;
00625     }
00626 
00627 }
00628 
00629 #endif