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_thread_tasklet.c Source File

borderrouter_thread_tasklet.c

00001 /*
00002  * Copyright (c) 2016 ARM Limited. All rights reserved.
00003  */
00004 
00005 #define LOWPAN_ND 0
00006 #define THREAD 1
00007 #define LOWPAN_WS 2
00008 
00009 #if MBED_CONF_APP_MESH_MODE == THREAD
00010 
00011 #include <string.h>
00012 #include <stdlib.h>
00013 #include <mbed_assert.h>
00014 #include "ns_types.h"
00015 #include "eventOS_event.h"
00016 #include "eventOS_event_timer.h"
00017 #include "eventOS_scheduler.h"
00018 #include "platform/arm_hal_timer.h"
00019 #include "borderrouter_tasklet.h"
00020 #include "borderrouter_helpers.h"
00021 #include "net_interface.h"
00022 #include "rf_wrapper.h"
00023 #include "nwk_stats_api.h"
00024 #include "ip6string.h"
00025 #include "ethernet_mac_api.h"
00026 #include "mac_api.h"
00027 #include "sw_mac.h"
00028 #include "mbed_interface.h"
00029 #include "common_functions.h"
00030 #include "thread_management_if.h"
00031 #include "thread_br_conn_handler.h"
00032 #include "randLIB.h"
00033 
00034 #include "ns_trace.h"
00035 #define TRACE_GROUP "brro"
00036 
00037 #define NR_BACKHAUL_INTERFACE_PHY_DRIVER_READY 2
00038 #define NR_BACKHAUL_INTERFACE_PHY_DOWN  3
00039 #define MESH_LINK_TIMEOUT 100
00040 #define MESH_METRIC 1000
00041 #define THREAD_MAX_CHILD_COUNT 32
00042 
00043 const uint8_t addr_unspecified[16] = {0};
00044 static mac_api_t *api;
00045 static eth_mac_api_t *eth_mac_api;
00046 
00047 typedef enum {
00048     STATE_UNKNOWN,
00049     STATE_DISCONNECTED,
00050     STATE_LINK_READY,
00051     STATE_BOOTSTRAP,
00052     STATE_CONNECTED,
00053     STATE_MAX_VALUE
00054 } connection_state_e;
00055 
00056 typedef struct {
00057     int8_t prefix_len;
00058     uint8_t prefix[16];
00059     uint8_t next_hop[16];
00060 } route_info_t;
00061 
00062 /* Backhaul prefix */
00063 static uint8_t backhaul_prefix[16] = {0};
00064 
00065 /* Backhaul default route information */
00066 static route_info_t backhaul_route;
00067 static int8_t br_tasklet_id = -1;
00068 
00069 /* Network statistics */
00070 static nwk_stats_t nwk_stats;
00071 
00072 /* Function forward declarations */
00073 
00074 static link_configuration_s *thread_link_configuration_get(link_configuration_s *link_configuration);
00075 static void network_interface_event_handler(arm_event_s *event);
00076 static void mesh_network_up(void);
00077 static void eth_network_data_init(void);
00078 static net_ipv6_mode_e backhaul_bootstrap_mode = NET_IPV6_BOOTSTRAP_STATIC;
00079 static void borderrouter_tasklet(arm_event_s *event);
00080 
00081 static void print_interface_addr(int id)
00082 {
00083     uint8_t address_buf[128];
00084     int address_count = 0;
00085     char buf[128];
00086 
00087     if (arm_net_address_list_get(id, 128, address_buf, &address_count) == 0) {
00088         uint8_t *t_buf = address_buf;
00089         for (int i = 0; i < address_count; ++i) {
00090             ip6tos(t_buf, buf);
00091             tr_info(" [%d] %s", i, buf);
00092             t_buf += 16;
00093         }
00094     }
00095 }
00096 
00097 static void eth_network_data_init()
00098 {
00099     memset(&backhaul_prefix[8], 0, 8);
00100 
00101     /* Bootstrap mode for the backhaul interface */
00102 #if MBED_CONF_APP_BACKHAUL_DYNAMIC_BOOTSTRAP == 1
00103     backhaul_bootstrap_mode = NET_IPV6_BOOTSTRAP_AUTONOMOUS;
00104     tr_info("NET_IPV6_BOOTSTRAP_AUTONOMOUS");
00105 
00106 #else
00107     tr_info("NET_IPV6_BOOTSTRAP_STATIC");
00108     backhaul_bootstrap_mode = NET_IPV6_BOOTSTRAP_STATIC;
00109     // done like this so that prefix can be left out in the dynamic case.
00110     const char *param = MBED_CONF_APP_BACKHAUL_PREFIX;
00111     stoip6(param, strlen(param), backhaul_prefix);
00112     tr_info("backhaul_prefix: %s", print_ipv6(backhaul_prefix));
00113 
00114     /* Backhaul route configuration*/
00115     memset(&backhaul_route, 0, sizeof(backhaul_route));
00116 #ifdef MBED_CONF_APP_BACKHAUL_NEXT_HOP
00117     param = MBED_CONF_APP_BACKHAUL_NEXT_HOP;
00118     stoip6(param, strlen(param), backhaul_route.next_hop);
00119     tr_info("next hop: %s", print_ipv6(backhaul_route.next_hop));
00120 #endif
00121     param = MBED_CONF_APP_BACKHAUL_DEFAULT_ROUTE;
00122     char *prefix, route_buf[255] = {0};
00123     /* copy the config value to a non-const buffer */
00124     strncpy(route_buf, param, sizeof(route_buf) - 1);
00125     prefix = strtok(route_buf, "/");
00126     backhaul_route.prefix_len = atoi(strtok(NULL, "/"));
00127     stoip6(prefix, strlen(prefix), backhaul_route.prefix);
00128     tr_info("backhaul route prefix: %s", print_ipv6(backhaul_route.prefix));
00129 #endif
00130 }
00131 
00132 static int thread_interface_up(void)
00133 {
00134     int32_t val;
00135     device_configuration_s device_config;
00136     link_configuration_s link_setup;
00137     link_configuration_s *link_setup_ptr;
00138     int8_t thread_if_id = thread_br_conn_handler_thread_interface_id_get();
00139 
00140     tr_info("thread_interface_up");
00141     memset(&device_config, 0, sizeof(device_config));
00142 
00143     const char *param = MBED_CONF_APP_PSKD;
00144     uint16_t len = strlen(param);
00145     MBED_ASSERT(len > 5 && len < 33);
00146 
00147     device_config.PSKd_ptr = malloc(len + 1);
00148     device_config.PSKd_len = len;
00149     memset(device_config.PSKd_ptr, 0, len + 1);
00150     memcpy(device_config.PSKd_ptr, param, len);
00151 
00152     link_setup_ptr = thread_link_configuration_get(&link_setup);
00153     val = thread_management_node_init(thread_if_id, NULL, &device_config, link_setup_ptr);
00154 
00155     if (val) {
00156         tr_error("Thread init error with code: %is\r\n", (int)val);
00157         return val;
00158     }
00159 
00160     // Additional thread configurations
00161     thread_management_set_link_timeout(thread_if_id, MESH_LINK_TIMEOUT);
00162     thread_management_max_child_count(thread_if_id, THREAD_MAX_CHILD_COUNT);
00163 
00164     val = arm_nwk_interface_up(thread_if_id);
00165     if (val != 0) {
00166         tr_error("mesh0 up Fail with code: %i\r\n", (int)val);
00167         return -1;
00168     } else {
00169         tr_info("mesh0 bootstrap ongoing...");
00170     }
00171     return 0;
00172 }
00173 
00174 static link_configuration_s *thread_link_configuration_get(link_configuration_s *link_configuration)
00175 {
00176 #ifdef MBED_CONF_APP_THREAD_USE_STATIC_LINK_CONFIG
00177 #if (false == MBED_CONF_APP_THREAD_USE_STATIC_LINK_CONFIG)
00178     // NOT using static link configuration values, return NULL
00179     return NULL;
00180 #endif
00181 #endif
00182 
00183     memset(link_configuration, 0, sizeof(link_configuration_s));
00184 
00185     MBED_ASSERT(strlen(MBED_CONF_APP_NETWORK_NAME) > 0 && strlen(MBED_CONF_APP_NETWORK_NAME) < 17);
00186     const uint8_t master_key[] = MBED_CONF_APP_THREAD_MASTER_KEY;
00187     MBED_ASSERT(sizeof(master_key) == 16);
00188     const uint8_t pskc[] = MBED_CONF_APP_PSKC;
00189     MBED_ASSERT(sizeof(pskc) == 16);
00190 
00191     const uint8_t extented_panid[] = MBED_CONF_APP_EXTENDED_PAN_ID;
00192     MBED_ASSERT(sizeof(extented_panid) == 8);
00193     const uint8_t mesh_local_prefix[] = MBED_CONF_APP_MESH_LOCAL_PREFIX;
00194     MBED_ASSERT(sizeof(mesh_local_prefix) == 8);
00195 
00196     memcpy(link_configuration->extented_pan_id, extented_panid, sizeof(extented_panid));
00197     memcpy(link_configuration->mesh_local_ula_prefix, mesh_local_prefix, sizeof(mesh_local_prefix));
00198 
00199     link_configuration->panId = MBED_CONF_APP_PAN_ID;
00200     tr_info("PAN ID %x", link_configuration->panId);
00201     memcpy(link_configuration->name, MBED_CONF_APP_NETWORK_NAME, strlen(MBED_CONF_APP_NETWORK_NAME));
00202     link_configuration->timestamp = MBED_CONF_APP_COMMISSIONING_DATASET_TIMESTAMP;
00203 
00204     memcpy(link_configuration->PSKc, pskc, sizeof(pskc));
00205     memcpy(link_configuration->master_key, master_key, sizeof(master_key));
00206     link_configuration->securityPolicy = MBED_CONF_APP_THREAD_SECURITY_POLICY;
00207 
00208     link_configuration->rfChannel = MBED_CONF_APP_RF_CHANNEL;
00209     tr_info("RF channel %d", link_configuration->rfChannel);
00210     link_configuration->channel_page = MBED_CONF_APP_RF_CHANNEL_PAGE;
00211     uint32_t channel_mask = MBED_CONF_APP_RF_CHANNEL_MASK;
00212     common_write_32_bit(channel_mask, link_configuration->channel_mask);
00213 
00214     link_configuration->key_rotation = 3600;
00215     link_configuration->key_sequence = 0;
00216 
00217     return link_configuration;
00218 }
00219 
00220 // ethernet interface
00221 static void network_interface_event_handler(arm_event_s *event)
00222 {
00223     bool connectStatus = false;
00224     arm_nwk_interface_status_type_e status = (arm_nwk_interface_status_type_e)event->event_data;
00225     switch (status) {
00226         case (ARM_NWK_BOOTSTRAP_READY): { // Interface configured Bootstrap is ready
00227 
00228             connectStatus = true;
00229             tr_info("BR interface_id: %d", thread_br_conn_handler_eth_interface_id_get());
00230             if (-1 != thread_br_conn_handler_eth_interface_id_get()) {
00231                 // metric set to high priority
00232                 if (0 != arm_net_interface_set_metric(thread_br_conn_handler_eth_interface_id_get(), 0)) {
00233                     tr_warn("Failed to set metric for eth0.");
00234                 }
00235 
00236                 if (backhaul_bootstrap_mode == NET_IPV6_BOOTSTRAP_STATIC) {
00237                     uint8_t *next_hop_ptr;
00238                     if (memcmp(backhaul_route.next_hop, addr_unspecified, 16) == 0) {
00239                         next_hop_ptr = NULL;
00240                     } else {
00241                         next_hop_ptr = backhaul_route.next_hop;
00242                     }
00243                     tr_debug("Default route prefix: %s/%d", print_ipv6(backhaul_route.prefix),
00244                              backhaul_route.prefix_len);
00245                     tr_debug("Default route next hop: %s", print_ipv6(backhaul_route.next_hop));
00246                     arm_net_route_add(backhaul_route.prefix,
00247                                       backhaul_route.prefix_len,
00248                                       next_hop_ptr, 0xffffffff, 128,
00249                                       thread_br_conn_handler_eth_interface_id_get());
00250                 }
00251                 tr_info("Backhaul interface addresses:");
00252                 print_interface_addr(thread_br_conn_handler_eth_interface_id_get());
00253                 thread_br_conn_handler_ethernet_connection_update(connectStatus);
00254             }
00255             break;
00256         }
00257         case (ARM_NWK_RPL_INSTANCE_FLOODING_READY): // RPL instance have been flooded
00258             tr_info("\rRPL instance have been flooded\r\n");
00259             break;
00260         case (ARM_NWK_SET_DOWN_COMPLETE): // Interface DOWN command successfully
00261             break;
00262         case (ARM_NWK_NWK_SCAN_FAIL):   // Interface have not detect any valid network
00263             tr_warning("\rmesh0 haven't detect any valid nw\r\n");
00264             break;
00265         case (ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL): // IP address allocation fail(ND, DHCPv4 or DHCPv6)
00266             tr_error("\rNO GP address detected");
00267             break;
00268         case (ARM_NWK_DUPLICATE_ADDRESS_DETECTED): // User specific GP16 was not valid
00269             tr_error("\rEthernet IPv6 Duplicate addr detected!\r\n");
00270             break;
00271         case (ARM_NWK_AUHTENTICATION_START_FAIL): // No valid Authentication server detected behind access point ;
00272             tr_error("\rNo valid ath server detected behind AP\r\n");
00273             break;
00274         case (ARM_NWK_AUHTENTICATION_FAIL): // Network authentication fail by Handshake
00275             tr_error("\rNetwork authentication fail");
00276             break;
00277         case (ARM_NWK_NWK_CONNECTION_DOWN): // No connection between Access point or Default Router
00278             tr_warning("\rPrefix timeout\r\n");
00279             break;
00280         case (ARM_NWK_NWK_PARENT_POLL_FAIL): // Sleepy host poll fail 3 time
00281             tr_warning("\rParent poll fail\r\n");
00282             break;
00283         case (ARM_NWK_PHY_CONNECTION_DOWN): // Interface PHY cable off or serial port interface not respond anymore
00284             tr_error("\reth0 down\r\n");
00285             break;
00286         default:
00287             tr_warning("\rUnkown nw if event (type: %02x, id: %02x, data: %02x)\r\n", event->event_type, event->event_id, (unsigned int)event->event_data);
00288             break;
00289     }
00290 }
00291 
00292 void thread_interface_event_handler(arm_event_s *event)
00293 {
00294     bool connectStatus = false;
00295     arm_nwk_interface_status_type_e status = (arm_nwk_interface_status_type_e)event->event_data;
00296     switch (status) {
00297         case (ARM_NWK_BOOTSTRAP_READY): { // Interface configured Bootstrap is ready
00298             connectStatus = true;
00299             tr_info("Thread bootstrap ready");
00300 
00301             if (arm_net_interface_set_metric(thread_br_conn_handler_thread_interface_id_get(), MESH_METRIC) != 0) {
00302                 tr_warn("Failed to set metric for mesh0.");
00303             }
00304 
00305             tr_info("RF interface addresses:");
00306             print_interface_addr(thread_br_conn_handler_thread_interface_id_get());
00307 
00308             break;
00309         }
00310         case (ARM_NWK_SET_DOWN_COMPLETE):
00311             tr_info("Thread interface down");
00312             break;
00313         default:
00314             tr_warning("Unkown nw if event (type: %02x, id: %02x, data: %02x)\r\n", event->event_type, event->event_id, (unsigned int)event->event_data);
00315             break;
00316     }
00317 
00318     thread_br_conn_handler_thread_connection_update(connectStatus);
00319 }
00320 
00321 static void mesh_network_up()
00322 {
00323     tr_debug("Create Mesh Interface");
00324 
00325     int status;
00326     int8_t thread_if_id;
00327 
00328     thread_if_id = arm_nwk_interface_lowpan_init(api, "ThreadInterface");
00329     tr_info("thread_if_id: %d", thread_if_id);
00330     MBED_ASSERT(thread_if_id >= 0);
00331 
00332     if (thread_if_id < 0) {
00333         tr_error("arm_nwk_interface_lowpan_init() failed");
00334         return;
00335     }
00336 
00337     status = arm_nwk_interface_configure_6lowpan_bootstrap_set(
00338                  thread_if_id,
00339                  NET_6LOWPAN_ROUTER,
00340                  NET_6LOWPAN_THREAD);
00341 
00342     if (status < 0) {
00343         tr_error("arm_nwk_interface_configure_6lowpan_bootstrap_set() failed");
00344         return;
00345     }
00346 
00347     thread_br_conn_handler_thread_interface_id_set(thread_if_id);
00348 
00349     status = thread_interface_up();
00350     MBED_ASSERT(!status);
00351     if (status) {
00352         tr_error("thread_interface_up() failed: %d", status);
00353     }
00354 }
00355 
00356 void thread_rf_init()
00357 {
00358     mac_description_storage_size_t storage_sizes;
00359     storage_sizes.key_lookup_size = 1;
00360     storage_sizes.key_usage_size = 1;
00361     storage_sizes.device_decription_table_size = 32;
00362     storage_sizes.key_description_table_size = 6;
00363 
00364     int8_t rf_driver_id = rf_device_register();
00365     MBED_ASSERT(rf_driver_id >= 0);
00366     if (rf_driver_id >= 0) {
00367         randLIB_seed_random();
00368 
00369         if (!api) {
00370             api = ns_sw_mac_create(rf_driver_id, &storage_sizes);
00371         }
00372     }
00373 }
00374 
00375 void border_router_tasklet_start(void)
00376 {
00377     thread_rf_init();
00378     protocol_stats_start(&nwk_stats);
00379 
00380     eventOS_event_handler_create(
00381         &borderrouter_tasklet,
00382         ARM_LIB_TASKLET_INIT_EVENT);
00383 }
00384 
00385 
00386 static void borderrouter_backhaul_phy_status_cb(uint8_t link_up, int8_t driver_id)
00387 {
00388     arm_event_s event = {
00389         .sender = br_tasklet_id,
00390         .receiver = br_tasklet_id,
00391         .priority = ARM_LIB_MED_PRIORITY_EVENT,
00392         .event_type = APPLICATION_EVENT,
00393         .event_id =  NR_BACKHAUL_INTERFACE_PHY_DOWN,
00394         .event_data = driver_id
00395     };
00396 
00397     if (link_up) {
00398         event.event_id = NR_BACKHAUL_INTERFACE_PHY_DRIVER_READY;
00399     }
00400 
00401     eventOS_event_send(&event);
00402 }
00403 
00404 static int backhaul_interface_up(int8_t driver_id)
00405 {
00406     int retval = -1;
00407     tr_debug("backhaul_interface_up: %i\n", driver_id);
00408     int8_t backhaul_if_id = thread_br_conn_handler_eth_interface_id_get();
00409     if (backhaul_if_id != -1) {
00410         tr_debug("Border RouterInterface already at active state\n");
00411     } else {
00412 
00413         if (!eth_mac_api) {
00414             eth_mac_api = ethernet_mac_create(driver_id);
00415         }
00416 
00417         backhaul_if_id = arm_nwk_interface_ethernet_init(eth_mac_api, "bh0");
00418 
00419         MBED_ASSERT(backhaul_if_id >= 0);
00420         if (backhaul_if_id >= 0) {
00421             tr_debug("Backhaul interface ID: %d", backhaul_if_id);
00422             thread_br_conn_handler_eth_interface_id_set(backhaul_if_id);
00423             arm_nwk_interface_configure_ipv6_bootstrap_set(
00424                 backhaul_if_id, backhaul_bootstrap_mode, backhaul_prefix);
00425             arm_nwk_interface_up(backhaul_if_id);
00426             retval = 0;
00427         } else {
00428             tr_debug("Could not init ethernet");
00429         }
00430     }
00431     return retval;
00432 }
00433 
00434 static int backhaul_interface_down(void)
00435 {
00436     int retval = -1;
00437     if (thread_br_conn_handler_eth_interface_id_get() != -1) {
00438         arm_nwk_interface_down(thread_br_conn_handler_eth_interface_id_get());
00439         thread_br_conn_handler_eth_interface_id_set(-1);
00440         thread_br_conn_handler_ethernet_connection_update(false);
00441         retval = 0;
00442     } else {
00443         tr_debug("Could not set eth down");
00444     }
00445     return retval;
00446 }
00447 
00448 #if MBED_CONF_APP_DEBUG_TRACE
00449 static void print_interface_addresses(void)
00450 {
00451     tr_info("Backhaul interface addresses:");
00452     print_interface_addr(thread_br_conn_handler_eth_interface_id_get());
00453 
00454     tr_info("RF interface addresses:");
00455     print_interface_addr(thread_br_conn_handler_thread_interface_id_get());
00456 }
00457 #endif
00458 
00459 /**
00460   * \brief Border Router Main Tasklet
00461   *
00462   *  Tasklet Handle next items:
00463   *
00464   *  - EV_INIT event: Set Certificate Chain, RF Interface Boot UP, multicast Init
00465   *  - SYSTEM_TIMER event: For RF interface Handshake purpose
00466   *
00467   */
00468 static void borderrouter_tasklet(arm_event_s *event)
00469 {
00470     arm_library_event_type_e event_type;
00471     event_type = (arm_library_event_type_e)event->event_type;
00472 
00473     switch (event_type) {
00474         case ARM_LIB_NWK_INTERFACE_EVENT:
00475 
00476             if (event->event_id == thread_br_conn_handler_eth_interface_id_get()) {
00477                 network_interface_event_handler(event);
00478             } else {
00479                 thread_interface_event_handler(event);
00480             }
00481 
00482             break;
00483         // comes from the backhaul_driver_init.
00484         case APPLICATION_EVENT:
00485             if (event->event_id == NR_BACKHAUL_INTERFACE_PHY_DRIVER_READY) {
00486                 int8_t net_backhaul_id = (int8_t) event->event_data;
00487 
00488                 tr_debug("Backhaul driver ID: %d", net_backhaul_id);
00489 
00490                 if (backhaul_interface_up(net_backhaul_id) != 0) {
00491                     tr_debug("Backhaul bootstrap start failed");
00492                 } else {
00493                     tr_debug("Backhaul bootstrap started");
00494                 }
00495             } else if (event->event_id == NR_BACKHAUL_INTERFACE_PHY_DOWN) {
00496                 tr_debug("Backhaul driver ID: %d", (int8_t) event->event_data);
00497                 if (backhaul_interface_down() != 0) {
00498                 } else {
00499                     tr_debug("Backhaul interface is down");
00500                 }
00501             }
00502             break;
00503 
00504         case ARM_LIB_TASKLET_INIT_EVENT:
00505             appl_info_trace();
00506             br_tasklet_id = event->receiver;
00507             thread_br_conn_handler_init();
00508             eth_network_data_init();
00509             backhaul_driver_init(borderrouter_backhaul_phy_status_cb);
00510             mesh_network_up();
00511             eventOS_event_timer_request(9, ARM_LIB_SYSTEM_TIMER_EVENT, br_tasklet_id, 20000);
00512             break;
00513 
00514         case ARM_LIB_SYSTEM_TIMER_EVENT:
00515             eventOS_event_timer_cancel(event->event_id, event->receiver);
00516 
00517             if (event->event_id == 9) {
00518 #if MBED_CONF_APP_DEBUG_TRACE
00519                 arm_print_routing_table();
00520                 arm_print_neigh_cache();
00521                 print_memory_stats();
00522                 // Trace interface addresses. This trace can be removed if nanostack prints added/removed
00523                 // addresses.
00524                 print_interface_addresses();
00525 #endif
00526                 eventOS_event_timer_request(9, ARM_LIB_SYSTEM_TIMER_EVENT, br_tasklet_id, 20000);
00527             }
00528             break;
00529 
00530         default:
00531             break;
00532     }
00533 }
00534 
00535 #endif // MBED_CONF_APP_MESH_MODE
00536