Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-os by
nd_tasklet.c
00001 /* 00002 * Copyright (c) 2015 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include <string.h> //memset 00018 #include "eventOS_event_timer.h" 00019 #include "common_functions.h" 00020 #include "net_interface.h" 00021 #include "ip6string.h" //ip6tos 00022 #include "nsdynmemLIB.h" 00023 #include "include/nd_tasklet.h" 00024 #include "include/static_config.h" 00025 #include "include/mesh_system.h" 00026 #ifndef YOTTA_CFG 00027 #include "ns_event_loop.h" 00028 #endif 00029 // For tracing we need to define flag, have include and define group 00030 #define HAVE_DEBUG 1 00031 #include "ns_trace.h" 00032 #define TRACE_GROUP "m6LND" 00033 00034 #include "mac_api.h" 00035 #include "sw_mac.h" 00036 00037 #define INTERFACE_NAME "6L-ND" 00038 00039 // Tasklet timer events 00040 #define TIMER_EVENT_START_BOOTSTRAP 1 00041 00042 #define INVALID_INTERFACE_ID (-1) 00043 00044 #define STR_HELPER(x) #x 00045 #define STR(x) STR_HELPER(x) 00046 00047 /* 00048 * Mesh tasklet states. 00049 */ 00050 typedef enum { 00051 TASKLET_STATE_CREATED = 0, 00052 TASKLET_STATE_INITIALIZED, 00053 TASKLET_STATE_BOOTSTRAP_STARTED, 00054 TASKLET_STATE_BOOTSTRAP_FAILED, 00055 TASKLET_STATE_BOOTSTRAP_READY 00056 } tasklet_state_t; 00057 00058 /* 00059 * Mesh tasklet data structure. 00060 */ 00061 typedef struct { 00062 void (*mesh_api_cb)(mesh_connection_status_t nwk_status); 00063 channel_list_s channel_list; 00064 tasklet_state_t tasklet_state; 00065 net_6lowpan_mode_e mode; 00066 net_6lowpan_link_layer_sec_mode_e sec_mode; 00067 net_link_layer_psk_security_info_s psk_sec_info; 00068 int8_t node_main_tasklet_id; 00069 int8_t network_interface_id; 00070 int8_t tasklet; 00071 } tasklet_data_str_t; 00072 00073 /* Tasklet data */ 00074 static tasklet_data_str_t *tasklet_data_ptr = NULL; 00075 static mac_api_t *mac_api = NULL; 00076 00077 /* private function prototypes */ 00078 void nd_tasklet_main(arm_event_s *event); 00079 void nd_tasklet_network_state_changed(mesh_connection_status_t status); 00080 void nd_tasklet_parse_network_event(arm_event_s *event); 00081 void nd_tasklet_configure_and_connect_to_network(void); 00082 #define TRACE_ND_TASKLET 00083 #ifndef TRACE_ND_TASKLET 00084 #define nd_tasklet_trace_bootstrap_info() ((void) 0) 00085 #else 00086 void nd_tasklet_trace_bootstrap_info(void); 00087 #endif 00088 00089 static void initialize_channel_list(void) 00090 { 00091 uint32_t channel = MBED_MESH_API_6LOWPAN_ND_CHANNEL; 00092 00093 const int_fast8_t word_index = channel / 32; 00094 const int_fast8_t bit_index = channel % 32; 00095 00096 memset(&tasklet_data_ptr->channel_list, 0, sizeof(tasklet_data_ptr->channel_list)); 00097 00098 tasklet_data_ptr->channel_list.channel_page = (channel_page_e)MBED_MESH_API_6LOWPAN_ND_CHANNEL_PAGE; 00099 tasklet_data_ptr->channel_list.channel_mask[0] = MBED_MESH_API_6LOWPAN_ND_CHANNEL_MASK; 00100 00101 if (channel > 0) { 00102 memset(&tasklet_data_ptr->channel_list.channel_mask, 0, sizeof(tasklet_data_ptr->channel_list.channel_mask)); 00103 tasklet_data_ptr->channel_list.channel_mask[word_index] |= ((uint32_t) 1 << bit_index); 00104 } 00105 00106 arm_nwk_set_channel_list(tasklet_data_ptr->network_interface_id, &tasklet_data_ptr->channel_list); 00107 00108 tr_debug("Channel: %ld", channel); 00109 tr_debug("Channel page: %d", tasklet_data_ptr->channel_list.channel_page); 00110 tr_debug("Channel mask: %ld", tasklet_data_ptr->channel_list.channel_mask[word_index]); 00111 } 00112 00113 /* 00114 * \brief A function which will be eventually called by NanoStack OS when ever the OS has an event to deliver. 00115 * @param event, describes the sender, receiver and event type. 00116 * 00117 * NOTE: Interrupts requested by HW are possible during this function! 00118 */ 00119 void nd_tasklet_main(arm_event_s *event) 00120 { 00121 arm_library_event_type_e event_type; 00122 event_type = (arm_library_event_type_e) event->event_type; 00123 00124 switch (event_type) { 00125 case ARM_LIB_NWK_INTERFACE_EVENT: 00126 /* This event is delivered every and each time when there is new 00127 * information of network connectivity. 00128 */ 00129 nd_tasklet_parse_network_event(event); 00130 break; 00131 00132 case ARM_LIB_TASKLET_INIT_EVENT: 00133 /* Event with type EV_INIT is an initializer event of NanoStack OS. 00134 * The event is delivered when the NanoStack OS is running fine. 00135 * This event should be delivered ONLY ONCE. 00136 */ 00137 tasklet_data_ptr->node_main_tasklet_id = event->receiver; 00138 mesh_system_send_connect_event(tasklet_data_ptr->tasklet); 00139 break; 00140 00141 case ARM_LIB_SYSTEM_TIMER_EVENT: 00142 eventOS_event_timer_cancel(event->event_id, 00143 tasklet_data_ptr->node_main_tasklet_id); 00144 00145 if (event->event_id == TIMER_EVENT_START_BOOTSTRAP) { 00146 tr_debug("Restart bootstrap"); 00147 nd_tasklet_configure_and_connect_to_network(); 00148 } 00149 break; 00150 00151 case APPLICATION_EVENT: 00152 if (event->event_id == APPL_EVENT_CONNECT) { 00153 nd_tasklet_configure_and_connect_to_network(); 00154 } 00155 break; 00156 00157 default: 00158 break; 00159 } // switch(event_type) 00160 } 00161 00162 /** 00163 * \brief Network state event handler. 00164 * \param event show network start response or current network state. 00165 * 00166 * - ARM_NWK_BOOTSTRAP_READY: Save NVK persistent data to NVM and Net role 00167 * - ARM_NWK_NWK_SCAN_FAIL: Link Layer Active Scan Fail, Stack is Already at Idle state 00168 * - ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL: No ND Router at current Channel Stack is Already at Idle state 00169 * - ARM_NWK_NWK_CONNECTION_DOWN: Connection to Access point is lost wait for Scan Result 00170 * - ARM_NWK_NWK_PARENT_POLL_FAIL: Host should run net start without any PAN-id filter and all channels 00171 * - ARM_NWK_AUHTENTICATION_FAIL: Pana Authentication fail, Stack is Already at Idle state 00172 */ 00173 void nd_tasklet_parse_network_event(arm_event_s *event) 00174 { 00175 arm_nwk_interface_status_type_e status = (arm_nwk_interface_status_type_e) event->event_data; 00176 tr_debug("app_parse_network_event() %d", status); 00177 switch (status) { 00178 case ARM_NWK_BOOTSTRAP_READY: 00179 /* Network is ready and node is connected to Access Point */ 00180 if (tasklet_data_ptr->tasklet_state != TASKLET_STATE_BOOTSTRAP_READY) { 00181 tr_info("6LoWPAN ND bootstrap ready"); 00182 tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_READY; 00183 nd_tasklet_trace_bootstrap_info(); 00184 nd_tasklet_network_state_changed(MESH_CONNECTED); 00185 } 00186 break; 00187 case ARM_NWK_NWK_SCAN_FAIL: 00188 /* Link Layer Active Scan Fail, Stack is Already at Idle state */ 00189 tr_debug("Link Layer Scan Fail: No Beacons"); 00190 tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; 00191 break; 00192 case ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL: 00193 /* No ND Router at current Channel Stack is Already at Idle state */ 00194 tr_debug("ND Scan/ GP REG fail"); 00195 tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; 00196 break; 00197 case ARM_NWK_NWK_CONNECTION_DOWN: 00198 /* Connection to Access point is lost wait for Scan Result */ 00199 tr_debug("ND/RPL scan new network"); 00200 tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; 00201 break; 00202 case ARM_NWK_NWK_PARENT_POLL_FAIL: 00203 tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; 00204 break; 00205 case ARM_NWK_AUHTENTICATION_FAIL: 00206 tr_debug("Network authentication fail"); 00207 tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; 00208 break; 00209 default: 00210 tr_warn("Unknown event %d", status); 00211 break; 00212 } 00213 00214 if (tasklet_data_ptr->tasklet_state != TASKLET_STATE_BOOTSTRAP_READY) { 00215 // Set 5s timer for new network scan 00216 eventOS_event_timer_request(TIMER_EVENT_START_BOOTSTRAP, 00217 ARM_LIB_SYSTEM_TIMER_EVENT, 00218 tasklet_data_ptr->node_main_tasklet_id, 00219 5000); 00220 } 00221 } 00222 00223 /* 00224 * \brief Configure and establish network connection 00225 * 00226 */ 00227 void nd_tasklet_configure_and_connect_to_network(void) 00228 { 00229 int8_t status; 00230 char *sec_mode; 00231 00232 // configure bootstrap 00233 arm_nwk_interface_configure_6lowpan_bootstrap_set( 00234 tasklet_data_ptr->network_interface_id, tasklet_data_ptr->mode, 00235 NET_6LOWPAN_ND_WITH_MLE); 00236 00237 sec_mode = STR(MBED_MESH_API_6LOWPAN_ND_SECURITY_MODE); 00238 00239 if (strcmp(sec_mode, "PSK") == 0) { 00240 tr_debug("Using PSK security mode."); 00241 tasklet_data_ptr->sec_mode = NET_SEC_MODE_PSK_LINK_SECURITY; 00242 tasklet_data_ptr->psk_sec_info.key_id = MBED_MESH_API_6LOWPAN_ND_PSK_KEY_ID; 00243 memcpy(tasklet_data_ptr->psk_sec_info.security_key, (const uint8_t[16])MBED_MESH_API_6LOWPAN_ND_PSK_KEY, 16); 00244 } else { 00245 tr_debug("Link-layer security NOT enabled."); 00246 tasklet_data_ptr->sec_mode = NET_SEC_MODE_NO_LINK_SECURITY; 00247 } 00248 00249 // configure link layer security 00250 arm_nwk_link_layer_security_mode( 00251 tasklet_data_ptr->network_interface_id, 00252 tasklet_data_ptr->sec_mode, 00253 MBED_MESH_API_6LOWPAN_ND_SEC_LEVEL, 00254 &tasklet_data_ptr->psk_sec_info); 00255 00256 // configure scan parameters 00257 arm_nwk_6lowpan_link_scan_parameter_set(tasklet_data_ptr->network_interface_id, 5); 00258 00259 // configure scan channels 00260 initialize_channel_list(); 00261 00262 // Configure scan options (NULL disables filter) 00263 arm_nwk_6lowpan_link_nwk_id_filter_for_nwk_scan( 00264 tasklet_data_ptr->network_interface_id, NULL); 00265 00266 status = arm_nwk_interface_up(tasklet_data_ptr->network_interface_id); 00267 if (status >= 0) { 00268 tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_STARTED; 00269 tr_info("Start 6LoWPAN ND Bootstrap"); 00270 } else { 00271 tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; 00272 tr_err("Bootstrap start failed, %d", status); 00273 nd_tasklet_network_state_changed(MESH_BOOTSTRAP_START_FAILED); 00274 } 00275 } 00276 00277 /* 00278 * Inform application about network state change 00279 */ 00280 void nd_tasklet_network_state_changed(mesh_connection_status_t status) 00281 { 00282 if (tasklet_data_ptr->mesh_api_cb) { 00283 (tasklet_data_ptr->mesh_api_cb)(status); 00284 } 00285 } 00286 00287 /* 00288 * Trace bootstrap information. 00289 */ 00290 #ifdef TRACE_ND_TASKLET 00291 void nd_tasklet_trace_bootstrap_info() 00292 { 00293 network_layer_address_s app_nd_address_info; 00294 link_layer_address_s app_link_address_info; 00295 uint8_t temp_ipv6[16]; 00296 if (arm_nwk_nd_address_read(tasklet_data_ptr->network_interface_id, 00297 &app_nd_address_info) != 0) { 00298 tr_error("ND Address read fail"); 00299 } else { 00300 tr_debug("ND Access Point: %s", trace_ipv6(app_nd_address_info.border_router)); 00301 tr_debug("ND Prefix 64: %s", trace_array(app_nd_address_info.prefix, 8)); 00302 00303 if (arm_net_address_get(tasklet_data_ptr->network_interface_id, 00304 ADDR_IPV6_GP, temp_ipv6) == 0) { 00305 tr_debug("GP IPv6: %s", trace_ipv6(temp_ipv6)); 00306 } 00307 } 00308 00309 if (arm_nwk_mac_address_read(tasklet_data_ptr->network_interface_id, 00310 &app_link_address_info) != 0) { 00311 tr_error("MAC Address read fail\n"); 00312 } else { 00313 uint8_t temp[2]; 00314 common_write_16_bit(app_link_address_info.mac_short,temp); 00315 tr_debug("MAC 16-bit: %s", trace_array(temp, 2)); 00316 common_write_16_bit(app_link_address_info.PANId, temp); 00317 tr_debug("PAN ID: %s", trace_array(temp, 2)); 00318 tr_debug("MAC 64-bit: %s", trace_array(app_link_address_info.mac_long, 8)); 00319 tr_debug("IID (Based on MAC 64-bit address): %s", trace_array(app_link_address_info.iid_eui64, 8)); 00320 } 00321 00322 tr_debug("Channel: %d", arm_net_get_current_channel(tasklet_data_ptr->network_interface_id)); 00323 } 00324 #endif /* #define TRACE_ND_TASKLET */ 00325 00326 /* Public functions */ 00327 int8_t nd_tasklet_get_ip_address(char *address, int8_t len) 00328 { 00329 uint8_t binary_ipv6[16]; 00330 00331 if ((len >= 40) && (0 == arm_net_address_get( 00332 tasklet_data_ptr->network_interface_id, ADDR_IPV6_GP, binary_ipv6))) { 00333 ip6tos(binary_ipv6, address); 00334 //tr_debug("IP address: %s", address); 00335 return 0; 00336 } else { 00337 return -1; 00338 } 00339 } 00340 00341 int8_t nd_tasklet_get_router_ip_address(char *address, int8_t len) 00342 { 00343 network_layer_address_s nd_address; 00344 00345 if ((len >= 40) && (0 == arm_nwk_nd_address_read( 00346 tasklet_data_ptr->network_interface_id, &nd_address))) { 00347 ip6tos(nd_address.border_router, address); 00348 //tr_debug("Router IP address: %s", address); 00349 return 0; 00350 } else { 00351 return -1; 00352 } 00353 } 00354 00355 int8_t nd_tasklet_connect(mesh_interface_cb callback, int8_t nwk_interface_id) 00356 { 00357 int8_t re_connecting = true; 00358 int8_t tasklet_id = tasklet_data_ptr->tasklet; 00359 00360 if (tasklet_data_ptr->network_interface_id != INVALID_INTERFACE_ID) { 00361 return -3; // already connected to network 00362 } 00363 00364 if (tasklet_data_ptr->tasklet_state == TASKLET_STATE_CREATED) { 00365 re_connecting = false; 00366 } 00367 00368 memset(tasklet_data_ptr, 0, sizeof(tasklet_data_str_t)); 00369 tasklet_data_ptr->mesh_api_cb = callback; 00370 tasklet_data_ptr->network_interface_id = nwk_interface_id; 00371 tasklet_data_ptr->tasklet_state = TASKLET_STATE_INITIALIZED; 00372 00373 tasklet_data_ptr->mode = MBED_CONF_MBED_MESH_API_6LOWPAN_ND_DEVICE_TYPE; 00374 tasklet_data_ptr->sec_mode = NET_SEC_MODE_NO_LINK_SECURITY; 00375 //tasklet_data_ptr->psk_sec_info.key_id = 0; 00376 00377 if (re_connecting == false) { 00378 tasklet_data_ptr->tasklet = eventOS_event_handler_create(&nd_tasklet_main, 00379 ARM_LIB_TASKLET_INIT_EVENT); 00380 if (tasklet_data_ptr->tasklet < 0) { 00381 // -1 handler already used by other tasklet 00382 // -2 memory allocation failure 00383 return tasklet_data_ptr->tasklet; 00384 } 00385 #ifndef YOTTA_CFG 00386 ns_event_loop_thread_start(); 00387 #endif 00388 } else { 00389 tasklet_data_ptr->tasklet = tasklet_id; 00390 mesh_system_send_connect_event(tasklet_data_ptr->tasklet); 00391 } 00392 00393 return tasklet_data_ptr->tasklet; 00394 } 00395 00396 int8_t nd_tasklet_disconnect(bool send_cb) 00397 { 00398 int8_t status = -1; 00399 if (tasklet_data_ptr != NULL) { 00400 if (tasklet_data_ptr->network_interface_id != INVALID_INTERFACE_ID) { 00401 status = arm_nwk_interface_down(tasklet_data_ptr->network_interface_id); 00402 tasklet_data_ptr->network_interface_id = INVALID_INTERFACE_ID; 00403 if (send_cb == true) { 00404 nd_tasklet_network_state_changed(MESH_DISCONNECTED); 00405 } 00406 } 00407 tasklet_data_ptr->mesh_api_cb = NULL; 00408 } 00409 return status; 00410 } 00411 00412 void nd_tasklet_init(void) 00413 { 00414 if (tasklet_data_ptr == NULL) { 00415 // memory allocation will not fail as memory was just initialized 00416 tasklet_data_ptr = ns_dyn_mem_alloc(sizeof(tasklet_data_str_t)); 00417 tasklet_data_ptr->tasklet_state = TASKLET_STATE_CREATED; 00418 tasklet_data_ptr->network_interface_id = INVALID_INTERFACE_ID; 00419 } 00420 } 00421 00422 int8_t nd_tasklet_network_init(int8_t device_id) 00423 { 00424 // TODO, read interface name from configuration 00425 mac_description_storage_size_t storage_sizes; 00426 storage_sizes.device_decription_table_size = 32; 00427 storage_sizes.key_description_table_size = 3; 00428 storage_sizes.key_lookup_size = 1; 00429 storage_sizes.key_usage_size = 3; 00430 if (!mac_api) { 00431 mac_api = ns_sw_mac_create(device_id, &storage_sizes); 00432 } 00433 return arm_nwk_interface_lowpan_init(mac_api, INTERFACE_NAME); 00434 } 00435
Generated on Tue Jul 12 2022 13:16:00 by
