takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers protocol_core.c Source File

protocol_core.c

00001 /*
00002  * Copyright (c) 2014-2018, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include "nsconfig.h"
00019 #include "string.h"
00020 #include "ns_types.h"
00021 #include "eventOS_event.h"
00022 #include "eventOS_scheduler.h"
00023 #include "eventOS_callback_timer.h"
00024 #include "ns_trace.h"
00025 #include "nsdynmemLIB.h"
00026 #include "Core/include/socket.h"
00027 #include "NWK_INTERFACE/Include/protocol.h"
00028 #include "NWK_INTERFACE/Include/protocol_timer.h"
00029 #include "platform/arm_hal_interrupt.h"
00030 #ifndef NO_MLE
00031 #include "MLE/mle.h"
00032 #endif
00033 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
00034 #include "6LoWPAN/Bootstraps/protocol_6lowpan_bootstrap.h"
00035 #include "6LoWPAN/Bootstraps/network_lib.h"
00036 #include "NWK_INTERFACE/Include/protocol_stats.h"
00037 #include "NWK_INTERFACE/Include/protocol_timer.h"
00038 #include "common_functions.h"
00039 #include "randLIB.h"
00040 #include "platform/arm_hal_phy.h"
00041 #include "platform/arm_hal_interrupt.h"
00042 #ifdef ECC
00043 #include "libX509_V3.h"
00044 #include "ecc.h"
00045 #endif
00046 #include "shalib.h"
00047 #include "Security/TLS/tls_lib.h"
00048 #include "Security/Common/sec_lib.h"
00049 #include "net_nvm_api.h"
00050 #include "net_pana_parameters_api.h"
00051 #include "Security/PANA/pana.h"
00052 #include "Security/PANA/pana_internal_api.h"
00053 #include "Common_Protocols/ipv6.h"
00054 #include "Common_Protocols/ipv6_fragmentation.h"
00055 #include "Common_Protocols/icmpv6_radv.h"
00056 #include "Common_Protocols/icmpv6.h"
00057 #include "Common_Protocols/mld.h"
00058 #include "Common_Protocols/udp.h"
00059 #include "6LoWPAN/ND/nd_router_object.h"
00060 #include "MPL/mpl.h"
00061 #include "RPL/rpl_control.h"
00062 #include "libDHCPv6/libDHCPv6.h"
00063 #include "6LoWPAN/Thread/thread_common.h"
00064 #include "6LoWPAN/Thread/thread_bootstrap.h"
00065 #include "6LoWPAN/Thread/thread_routing.h"
00066 #include "6LoWPAN/Thread/thread_management_internal.h"
00067 #include "6LoWPAN/ws/ws_bootstrap.h"
00068 #include "6LoWPAN/ws/ws_common.h"
00069 #include "ipv6_stack/protocol_ipv6.h"
00070 #include "Service_Libs/whiteboard/whiteboard.h"
00071 
00072 #include "6LoWPAN/MAC/beacon_handler.h"
00073 #include "6LoWPAN/MAC/mac_helper.h"
00074 #include "6LoWPAN/MAC/mac_response_handler.h"
00075 #include "6LoWPAN/MAC/mac_data_poll.h"
00076 #include "6LoWPAN/NVM/nwk_nvm.h"
00077 #include "6LoWPAN/lowpan_adaptation_interface.h"
00078 #include "6LoWPAN/Fragmentation/cipv6_fragmenter.h"
00079 #include "Service_Libs/load_balance/load_balance_api.h"
00080 #include "Service_Libs/pan_blacklist/pan_blacklist_api.h"
00081 
00082 #include "mac_api.h"
00083 #include "ethernet_mac_api.h"
00084 
00085 #define TRACE_GROUP_CORE "core"
00086 
00087 #define TRACE_GROUP "core"
00088 
00089 #ifndef SEC_LIB_X_100MS_COUNTER
00090 #define SEC_LIB_X_100MS_COUNTER 1 //Default scaller is 100ms tick
00091 #endif
00092 
00093 // RFC 4861 says we only have to reroll ReachableTime every couple of hours, but
00094 // to make sure the code is regularly exercised, let's make it 10 minutes.
00095 #define REACHABLE_TIME_UPDATE_SECONDS       600
00096 
00097 /** Quick monotonic time for simple timestamp comparisons; 100ms ticks.
00098  * This can of course wrap, so to handle this correctly comparisons must be
00099  * expressed like:
00100  *
00101  * "if (time_now - time_then < 200)"
00102  * NOT
00103  * "if (time_now < time_then + 200)"
00104  */
00105 uint32_t protocol_core_monotonic_time;
00106 static int8_t protocol_root_tasklet_ID = -1;
00107 
00108 int protocol_core_buffers_in_event_queue;
00109 
00110 protocol_interface_info_entry_t *protocol_core_multicast_upstream;
00111 
00112 typedef struct {
00113     uint8_t core_timer_ticks;
00114     bool core_timer_event;
00115     uint16_t core_security_ticks_counter;
00116 } lowpan_core_timer_structures_s;
00117 
00118 protocol_interface_list_t NS_LIST_NAME_INIT(protocol_interface_info_list);
00119 
00120 static lowpan_core_timer_structures_s protocol_core_timer_info;
00121 
00122 /** Cores Power Save Varibale whic indicate States  */
00123 volatile uint8_t power_save_state =  0;
00124 
00125 void core_timer_event_handle(uint16_t ticksUpdate);
00126 static void protocol_buffer_poll(buffer_t *b);
00127 
00128 static int8_t net_interface_get_free_id(void);
00129 
00130 static void nwk_net_event_post(arm_nwk_interface_status_type_e posted_event, int8_t net_tasklet, int8_t nwk_id);
00131 
00132 static uint16_t  protocol_core_seconds_timer = 10;
00133 
00134 int8_t protocol_read_tasklet_id(void)
00135 {
00136     return protocol_root_tasklet_ID;
00137 }
00138 
00139 uint8_t check_power_state(uint8_t mode)
00140 {
00141     uint8_t ret_val = power_save_state & mode;
00142     return ret_val;
00143 }
00144 
00145 
00146 void set_power_state(uint8_t mode)
00147 {
00148     power_save_state |= mode;
00149 }
00150 
00151 void clear_power_state(uint8_t mode)
00152 {
00153     power_save_state &= ~mode;
00154 }
00155 
00156 void arm_net_protocol_packet_handler(buffer_t *buf, protocol_interface_info_entry_t *cur_interface)
00157 {
00158     if (cur_interface->if_stack_buffer_handler) {
00159         cur_interface->if_stack_buffer_handler(buf);
00160         //buf = 0;
00161     } else {
00162         buffer_free(buf);
00163     }
00164 }
00165 
00166 void protocol_root_tasklet(arm_event_t *event)
00167 {
00168     arm_internal_event_type_e event_type;
00169     event_type = (arm_internal_event_type_e)event->event_type;
00170 
00171     switch (event_type) {
00172         case ARM_LIB_TASKLET_INIT_EVENT:
00173             tr_debug("NS Root task Init");
00174             break;
00175 
00176         case ARM_IN_PROTOCOL_TIMER_EVENT: {
00177             uint16_t tick_update = (uint16_t)event->event_data;
00178             /* This event is delivered as "user-allocated", so finish reading
00179              * before "freeing" */
00180             protocol_timer_event_lock_free();
00181             protocol_timer_cb(tick_update);
00182             break;
00183         }
00184         case ARM_IN_INTERFACE_BOOTSTRAP_CB:
00185             net_bootsrap_cb_run(event->event_id);
00186             break;
00187         case ARM_IN_INTERFACE_CORE_TIMER_CB:
00188             /* This event is delivered as "user-allocated", so finish reading
00189              * before "freeing" */
00190             core_timer_event_handle((uint16_t)event->event_data);
00191             break;
00192         case ARM_IN_INTERFACE_PROTOCOL_HANDLE: {
00193             buffer_t *buf = event->data_ptr;
00194             protocol_buffer_poll(buf);
00195             break;
00196         }
00197         case ARM_IN_SECURITY_ECC_CALLER:
00198             sec_ecc_sceduler();
00199             break;
00200         default:
00201             break;
00202     }
00203 }
00204 void protocol_core_security_tick_update(uint16_t tick_update)
00205 {
00206     if (protocol_core_timer_info.core_security_ticks_counter <= tick_update) {
00207         sec_timer_handle();
00208         protocol_core_timer_info.core_security_ticks_counter = SEC_LIB_X_100MS_COUNTER;
00209     }
00210 }
00211 
00212 static void nwk_bootsrap_timer(protocol_interface_info_entry_t *cur)
00213 {
00214     if (cur->bootsrap_state_machine_cnt) {
00215         if (cur->bootsrap_state_machine_cnt-- == 1) {
00216             arm_event_s event = {
00217                 .receiver = protocol_root_tasklet_ID,
00218                 .sender = 0,
00219                 .event_id = (uint8_t)cur->id,
00220                 .event_type = ARM_IN_INTERFACE_BOOTSTRAP_CB,
00221                 .data_ptr = NULL,
00222                 .priority = ARM_LIB_LOW_PRIORITY_EVENT,
00223             };
00224             if (eventOS_event_send(&event) != 0) {
00225                 cur->bootsrap_state_machine_cnt = 1; // Try again next tick
00226                 tr_error("nwk_bootsrap_timer(): event send failed");
00227             }
00228         }
00229     }
00230 }
00231 
00232 void core_timer_event_handle(uint16_t ticksUpdate)
00233 {
00234     protocol_core_monotonic_time += ticksUpdate;
00235 
00236     if (protocol_core_seconds_timer <= ticksUpdate) {
00237         uint16_t extra_ticks = ticksUpdate - protocol_core_seconds_timer;
00238         uint16_t seconds = 1 + extra_ticks / 10;
00239         protocol_core_seconds_timer = (10 - extra_ticks % 10);
00240         // TODO: make this lot use "seconds", not 1
00241 
00242         ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
00243             if (cur->nwk_id == IF_6LoWPAN) {
00244                 if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
00245                     if (thread_info(cur)) {
00246                         thread_seconds_timer(cur, seconds);
00247                     } else if (ws_info(cur)) {
00248                         ws_common_seconds_timer(cur, seconds);
00249                     } else if (cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
00250                         beacon_join_priority_update(cur->id);
00251                     }
00252 
00253                     if (cur->mac_parameters) {
00254                         mac_neighbor_table_neighbor_timeout_update(mac_neighbor_info(cur), seconds);
00255                     }
00256 
00257                     if (cur->nwk_wpan_nvm_api) {
00258                         cur->nwk_wpan_nvm_api->nvm_params_update_cb(cur->nwk_wpan_nvm_api, false);
00259                     }
00260                 }
00261             } else if (cur->nwk_id == IF_IPV6) {
00262                 //Slow Pointer Update
00263                 ipv6_core_slow_timer_event_handle(cur);
00264             }
00265 
00266             if (cur->lb_api) {
00267                 cur->lb_api->lb_seconds_tick_update(cur->lb_api);
00268             }
00269 
00270 
00271 
00272             addr_slow_timer(cur, seconds);
00273             mld_slow_timer(cur, seconds);
00274             ipv6_neighbour_cache_slow_timer(&cur->ipv6_neighbour_cache, seconds);
00275             pan_blacklist_time_update(&cur->pan_blaclist_cache, seconds);
00276             pan_coordinator_blacklist_time_update(&cur->pan_cordinator_black_list, seconds);
00277             if (cur->reachable_time_ttl > seconds) {
00278                 cur->reachable_time_ttl -= seconds;
00279             } else {
00280                 protocol_stack_interface_set_reachable_time(cur, cur->base_reachable_time);
00281             }
00282 
00283             cur->icmp_ra_tokens += seconds;
00284             if (cur->icmp_ra_tokens > 3) {
00285                 cur->icmp_ra_tokens = 3;
00286             }
00287 
00288             cur->mle_link_reject_tokens += seconds;
00289             if (cur->mle_link_reject_tokens > 2) {
00290                 cur->mle_link_reject_tokens = 2;
00291             }
00292         }
00293 
00294         mpl_slow_timer(seconds);
00295         rpl_control_slow_timer(seconds);
00296         ipv6_route_table_ttl_update(seconds);
00297         ipv6_destination_cache_timer(seconds);
00298         ipv6_frag_timer(seconds);
00299         cipv6_frag_timer(seconds);
00300         protocol_6lowpan_mle_timer(seconds);
00301         /* This limit bad behaviour device's MLE link reject generation */
00302 
00303     } else {
00304         protocol_core_seconds_timer -= ticksUpdate;
00305     }
00306 
00307     //Fast Timer
00308     ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
00309         if (cur->nwk_id == IF_6LoWPAN) {
00310             if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
00311                 nwk_bootsrap_timer(cur);
00312                 nd_object_timer(cur,ticksUpdate);
00313                 if (thread_info(cur)) {
00314                     thread_timer(cur, ticksUpdate);
00315                 } else if (ws_info(cur)) {
00316                     ws_common_fast_timer(cur, ticksUpdate);
00317                 }
00318                 lowpan_context_timer(&cur->lowpan_contexts, ticksUpdate);
00319             }
00320         } else if (cur->nwk_id == IF_IPV6) {
00321             ipv6_core_timer_event_handle(cur, ticksUpdate);
00322         }
00323 
00324         ipv6_neighbour_cache_fast_timer(&cur->ipv6_neighbour_cache, ticksUpdate);
00325         addr_fast_timer(cur, ticksUpdate);
00326         mld_fast_timer(cur, ticksUpdate);
00327 
00328         /* This gives us the RFC 4443 default (10 tokens/s, bucket size 10) */
00329         cur->icmp_tokens += ticksUpdate;
00330         if (cur->icmp_tokens > 10) {
00331             cur->icmp_tokens = 10;
00332         }
00333     }
00334 
00335     rpl_control_fast_timer(ticksUpdate);
00336     icmpv6_radv_timer(ticksUpdate);
00337     protocol_core_security_tick_update(ticksUpdate);
00338     platform_enter_critical();
00339     protocol_core_timer_info.core_timer_event = false;
00340     platform_exit_critical();
00341 }
00342 
00343 void protocol_core_cb(uint16_t ticksUpdate)
00344 {
00345     protocol_timer_start(PROTOCOL_TIMER_STACK_TIM, protocol_core_cb, 100);
00346     protocol_core_timer_info.core_timer_ticks += ticksUpdate;
00347     if (!protocol_core_timer_info.core_timer_event) {
00348         protocol_core_timer_info.core_timer_event = true;
00349         /* Static initialised, constant values */
00350         static arm_event_storage_t event = {
00351             .data = {
00352                 .sender = 0,
00353                 .data_ptr = NULL,
00354                 .event_type = ARM_IN_INTERFACE_CORE_TIMER_CB,
00355                 .priority = ARM_LIB_HIGH_PRIORITY_EVENT,
00356             }
00357         };
00358         event.data.receiver = protocol_root_tasklet_ID;
00359         event.data.event_data = protocol_core_timer_info.core_timer_ticks;
00360         eventOS_event_send_user_allocated(&event);
00361         protocol_core_timer_info.core_timer_ticks = 0;
00362     }
00363 }
00364 
00365 
00366 void protocol_core_init(void)
00367 {
00368     protocol_root_tasklet_ID = eventOS_event_handler_create(&protocol_root_tasklet, ARM_LIB_TASKLET_INIT_EVENT);
00369     tr_debug("Allocate Root Tasklet");
00370     if (protocol_timer_init() == -1) {
00371         tr_error("Protocol timer init failed");
00372     }
00373     protocol_core_monotonic_time = 0;
00374     protocol_core_timer_info.core_timer_event = false;
00375     protocol_core_timer_info.core_timer_ticks = 0;
00376     protocol_core_timer_info.core_security_ticks_counter = SEC_LIB_X_100MS_COUNTER;
00377 
00378     protocol_timer_start(PROTOCOL_TIMER_STACK_TIM, protocol_core_cb, 100);
00379 
00380 }
00381 
00382 void protocol_core_interface_info_reset(protocol_interface_info_entry_t *entry)
00383 {
00384     if (entry) {
00385         entry->global_address_available = false;
00386         icmpv6_radv_disable(entry);
00387         icmpv6_stop_router_advertisements(entry, NULL);
00388         lowpan_context_list_free(&entry->lowpan_contexts);
00389         ipv6_neighbour_cache_flush(&entry->ipv6_neighbour_cache);
00390         entry->if_stack_buffer_handler = 0;
00391         entry->if_6lowpan_dad_process.active = false;
00392         //Clean
00393         ns_list_foreach_safe(if_address_entry_t, addr, &entry->ip_addresses) {
00394             addr_delete_entry(entry, addr);
00395         }
00396 #ifdef MULTICAST_FORWARDING
00397         ns_list_foreach_safe(if_group_fwd_entry_t, group, &entry->ip_groups_fwd) {
00398             addr_multicast_fwd_remove(entry, group->group);
00399         }
00400 #endif
00401 #ifdef HAVE_RPL
00402         /* This is done after address deletion, so RPL can act on them */
00403         rpl_control_remove_domain_from_interface(entry);
00404 #endif
00405     }
00406 }
00407 
00408 void bootsrap_next_state_kick(icmp_state_t new_state, protocol_interface_info_entry_t *cur)
00409 {
00410     cur->bootsrap_state_machine_cnt = 0;
00411     cur->nwk_bootstrap_state = new_state;
00412     arm_event_s event = {
00413         .receiver = protocol_root_tasklet_ID,
00414         .sender = 0,
00415         .event_id = (uint8_t)cur->id,
00416         .event_type = ARM_IN_INTERFACE_BOOTSTRAP_CB,
00417         .data_ptr = NULL,
00418         .priority = ARM_LIB_LOW_PRIORITY_EVENT,
00419     };
00420     if (eventOS_event_send(&event) != 0) {
00421         tr_error("bootsrap_next_state_kick(): event send failed");
00422     }
00423 }
00424 
00425 uint32_t protocol_stack_interface_set_reachable_time(protocol_interface_info_entry_t *cur, uint32_t base_reachable_time)
00426 {
00427     cur->base_reachable_time = base_reachable_time;
00428     cur->reachable_time_ttl = REACHABLE_TIME_UPDATE_SECONDS;
00429 
00430     return cur->ipv6_neighbour_cache.reachable_time = randLIB_randomise_base(base_reachable_time, 0x4000, 0xBFFF);
00431 }
00432 
00433 
00434 static void protocol_core_base_init(protocol_interface_info_entry_t *entry,nwk_interface_id nwk_id)
00435 {
00436     entry->nwk_id = nwk_id;
00437     switch (nwk_id) {
00438         case IF_IPV6:
00439             entry->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_ETHERNET_ROUTER;
00440             break;
00441        default:
00442             entry->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER;
00443             break;
00444     }
00445     entry->bootStrapId = -1;
00446     entry->lowpan_address_mode = NET_6LOWPAN_GP64_ADDRESS;
00447     entry->ipv6_configure = NULL;
00448     entry->if_lowpan_security_params = NULL;
00449     entry->if_ns_transmit = NULL;
00450     entry->if_special_forwarding = NULL;
00451     entry->if_snoop = NULL;
00452     entry->if_icmp_handler = NULL;
00453     entry->if_map_ip_to_link_addr = NULL;
00454     entry->if_map_link_addr_to_ip = NULL;
00455     entry->if_6lowpan_dad_process.active = false;
00456     entry->lowpan_desired_short_address = 0xfffe;
00457     entry->lowpan_info = 0;
00458     entry->rpl_domain = NULL;
00459     entry->if_down = NULL;
00460     entry->if_up = NULL;
00461 }
00462 
00463 static void protocol_core_base_finish_init(protocol_interface_info_entry_t *entry)
00464 {
00465     entry->configure_flags = 0;
00466     entry->bootsrap_state_machine_cnt = 0;
00467     entry->pana_sec_info_temp = NULL;
00468     entry->lb_api = NULL;
00469     entry->global_address_available = false;
00470     entry->reallocate_short_address_if_duplicate = true;
00471     entry->iids_map_to_mac = false;
00472     entry->opaque_slaac_iids = true;
00473     entry->ip_multicast_as_mac_unicast_to_parent = false;
00474     entry->dad_failures = 0;
00475     entry->icmp_tokens = 10;
00476     entry->mle_link_reject_tokens = 2;
00477     entry->ip_forwarding = true; /* Default to on for now... */
00478     entry->ip_multicast_forwarding = true; /* Default to on for now... */
00479 #ifdef HAVE_IPV6_ND
00480     entry->recv_ra_routes = true;
00481     entry->recv_ra_prefixes = true;
00482 #endif
00483     entry->send_mld = true;
00484 #ifdef HAVE_MPL
00485     entry->mpl_seed = false;
00486     entry->mpl_control_trickle_params = rfc7731_default_control_message_trickle_params;
00487     entry->mpl_data_trickle_params = rfc7731_default_data_message_trickle_params;
00488     entry->mpl_seed_set_entry_lifetime = RFC7731_DEFAULT_SEED_SET_ENTRY_LIFETIME;
00489     entry->mpl_proactive_forwarding = true;
00490     entry->mpl_seed_id_mode = MULTICAST_MPL_SEED_ID_IPV6_SRC_FOR_DOMAIN;
00491 #endif
00492     entry->cur_hop_limit = UNICAST_HOP_LIMIT_DEFAULT;
00493     protocol_stack_interface_set_reachable_time(entry, 30000);
00494     entry->dup_addr_detect_transmits = 1;
00495     entry->ipv6_neighbour_cache.link_mtu = IPV6_MIN_LINK_MTU;
00496     entry->max_link_mtu = IPV6_MIN_LINK_MTU;
00497     entry->pmtu_lifetime = 10 * 60; // RFC 1981 default - 10 minutes
00498     icmpv6_radv_init(entry);
00499     ns_list_link_init(entry, link);
00500     entry->if_stack_buffer_handler = NULL;
00501     entry->interface_name = 0;
00502     entry->border_router_setup = NULL;
00503 #ifdef HAVE_THREAD
00504     entry->thread_info = NULL;
00505 #endif
00506     entry->mesh_callbacks = NULL;
00507     entry->ip_addresses_max_slaac_entries = 0;
00508     ns_list_init(&entry->lowpan_contexts);
00509     ns_list_init(&entry->ip_addresses);
00510     ns_list_init(&entry->ip_groups);
00511 #ifdef MULTICAST_FORWARDING
00512     ns_list_init(&entry->ip_groups_fwd);
00513     entry->ip_mcast_fwd_for_scope = IPV6_SCOPE_SITE_LOCAL; // Default for backwards compatibility
00514 #endif
00515     ns_list_init(&entry->ipv6_neighbour_cache.list);
00516 }
00517 
00518 
00519 
00520 static int lowpan_security_parameters_allocate(protocol_interface_info_entry_t *entry)
00521 {
00522     entry->if_lowpan_security_params = ns_dyn_mem_alloc(sizeof(if_6lowpan_security_info_t));
00523     if (!entry->if_lowpan_security_params) {
00524         return -1;
00525     }
00526 
00527     entry->if_lowpan_security_params->security_level = 0;
00528     entry->if_lowpan_security_params->mle_security_frame_counter = 0;
00529     entry->if_lowpan_security_params->pana_params = NULL;
00530     entry->if_lowpan_security_params->nwk_security_mode = NET_SEC_MODE_NO_LINK_SECURITY;
00531     return 0;
00532 }
00533 
00534 static void lowpan_security_parameters_deallocate(protocol_interface_info_entry_t *entry)
00535 {
00536     ns_dyn_mem_free(entry->if_lowpan_security_params);
00537     entry->if_lowpan_security_params = NULL;
00538 
00539 }
00540 
00541 static protocol_interface_info_entry_t * protocol_interface_class_allocate(nwk_interface_id nwk_id)
00542 {
00543     protocol_interface_info_entry_t *entry = ns_dyn_mem_alloc(sizeof(protocol_interface_info_entry_t));
00544     if (entry) {
00545         memset(entry, 0, sizeof(protocol_interface_info_entry_t));
00546         /* We assume for now zone indexes for interface, link and realm all equal interface id */
00547         int8_t id = net_interface_get_free_id();
00548         entry->id = id;
00549         entry->zone_index[IPV6_SCOPE_INTERFACE_LOCAL] = id;
00550         entry->zone_index[IPV6_SCOPE_LINK_LOCAL] = id;
00551         entry->zone_index[IPV6_SCOPE_REALM_LOCAL] = id;
00552         protocol_core_base_init(entry,nwk_id);
00553     }
00554     return entry;
00555 }
00556 
00557 static protocol_interface_info_entry_t *protocol_core_interface_6lowpan_entry_get_with_mac(mac_api_t *api)
00558 {
00559     if( !api ){
00560         return NULL;
00561     }
00562     protocol_interface_info_entry_t *entry = protocol_interface_class_allocate(IF_6LoWPAN);
00563     if (!entry) {
00564         return NULL;
00565     }
00566 
00567     if (lowpan_adaptation_interface_init(entry->id, api->phyMTU) != 0) {
00568         goto interface_failure;
00569     }
00570 
00571     if (reassembly_interface_init(entry->id, 8, 5) != 0) {
00572         goto interface_failure;
00573     }
00574 
00575     if (lowpan_security_parameters_allocate(entry) != 0) {
00576         goto interface_failure;
00577     }
00578 
00579     entry->mac_parameters = ns_dyn_mem_alloc(sizeof(arm_15_4_mac_parameters_t));
00580     if (!entry->mac_parameters) {
00581         goto interface_failure;
00582     }
00583     memset(entry->mac_parameters, 0, sizeof(arm_15_4_mac_parameters_t));
00584     entry->mac_parameters->MacUnsusecured_2003_cab = mac_unsecured_2003_compatibility;
00585     entry->mac_parameters->mac_short_address = 0xffff;
00586     entry->mac_parameters->pan_id = 0xffff;
00587     entry->mac_parameters->nwk_filter_params.beacon_protocol_id_filter = 0xff;
00588     entry->mac_parameters->nwk_filter_params.net_pan_id_filter = 0xffff;
00589     entry->mac_parameters->mac_in_direct_entry_timeout = 7000; //default timeout
00590 
00591     entry->mac_parameters->mac_prev_key_attribute_id = 0;
00592     entry->mac_parameters->mac_default_key_attribute_id = 1;
00593     entry->mac_parameters->mac_next_key_attribute_id = 2;
00594 
00595     entry->beacon_cb = beacon_received;
00596 
00597     entry->mac_api = api;
00598     int8_t err = entry->mac_api->mac_initialize( entry->mac_api, &mcps_data_confirm_handler, &mcps_data_indication_handler,
00599                                                  &mcps_purge_confirm_handler, &mlme_confirm_handler, &mlme_indication_handler,
00600                                                  entry->id );
00601     if( err < 0 ){
00602         goto interface_failure;
00603     }
00604 
00605     //Set default key source
00606     mac_helper_set_default_key_source(entry);
00607 
00608     protocol_core_base_finish_init(entry);
00609     return entry;
00610 
00611 interface_failure:
00612     lowpan_adaptation_interface_free(entry->id);
00613     reassembly_interface_free(entry->id);
00614     ns_dyn_mem_free(entry->mac_parameters);
00615     lowpan_security_parameters_deallocate(entry);
00616     ns_dyn_mem_free(entry);
00617     entry = NULL;
00618     return NULL;
00619 }
00620 
00621 static void protocol_6lowpan_mac_set(protocol_interface_info_entry_t *cur, const uint8_t *mac)
00622 {
00623     memcpy(cur->iid_eui64, mac, 8);
00624     /* Invert U/L Bit */
00625     cur->iid_eui64[0] ^= 2;
00626 
00627     mac_helper_mac64_set(cur, mac);
00628 }
00629 
00630 #ifdef HAVE_ETHERNET
00631 static bool protocol_ipv6_setup_allocate(protocol_interface_info_entry_t *entry)
00632 {
00633     entry->ipv6_configure = ns_dyn_mem_alloc(sizeof(ipv6_interface_info_t));
00634     if (entry->ipv6_configure) {
00635         entry->lowpan_info = INTERFACE_NWK_ROUTER_DEVICE;
00636         memset(entry->ipv6_configure, 0, sizeof(ipv6_interface_info_t));
00637         entry->ipv6_configure->temporaryUlaAddressState = false;
00638         return true;
00639     }
00640     return false;
00641 }
00642 
00643 static protocol_interface_info_entry_t *protocol_core_interface_ethernet_entry_get(eth_mac_api_t *api)
00644 {
00645     protocol_interface_info_entry_t *entry = protocol_interface_class_allocate(IF_IPV6);
00646     if (!entry) {
00647         return NULL;
00648     }
00649     if (!protocol_ipv6_setup_allocate(entry)) {
00650         ns_dyn_mem_free(entry);
00651         entry = NULL;
00652     } else {
00653         entry->eth_mac_api = api;
00654         ipv6_interface_phy_sap_register(entry);
00655         protocol_core_base_finish_init(entry);
00656     }
00657 
00658     return entry;
00659 }
00660 
00661 static void protocol_ethernet_mac_set(protocol_interface_info_entry_t *cur, const uint8_t *mac)
00662 {
00663     if( !cur || !cur->eth_mac_api ) {
00664         return;
00665     }
00666 
00667     memcpy(cur->mac, mac, 6);
00668     cur->mac[6] = 0;
00669     cur->mac[7] = 0;
00670     cur->iid_eui64[0] = mac[0] ^ 2;
00671     cur->iid_eui64[1] = mac[1];
00672     cur->iid_eui64[2] = mac[2];
00673     cur->iid_eui64[3] = 0xff;
00674     cur->iid_eui64[4] = 0xfe;
00675     cur->iid_eui64[5] = mac[3];
00676     cur->iid_eui64[6] = mac[4];
00677     cur->iid_eui64[7] = mac[5];
00678 
00679     cur->eth_mac_api->mac48_set(cur->eth_mac_api, cur->mac);
00680 }
00681 
00682 #else
00683 protocol_interface_info_entry_t *protocol_core_interface_ethernet_entry_get(eth_mac_api_t *api)
00684 {
00685     (void)api;
00686     return NULL;
00687 }
00688 
00689 static void protocol_ethernet_mac_set(protocol_interface_info_entry_t *cur, const uint8_t *mac)
00690 {
00691     (void)cur;
00692     (void)mac;
00693 }
00694 #endif
00695 
00696 static void protocol_stack_interface_iid_eui64_generate(protocol_interface_info_entry_t *cur , const uint8_t *mac)
00697 {
00698     if (cur->nwk_id == IF_6LoWPAN) {
00699         protocol_6lowpan_mac_set(cur, mac);
00700     } else {
00701         protocol_ethernet_mac_set(cur, mac);
00702     }
00703     //By default use this EUI-64-based IID for SLAAC
00704     memcpy(cur->iid_slaac, cur->iid_eui64, 8);
00705     //And why not feed it into the random seed too?
00706     randLIB_add_seed(common_read_64_bit(cur->mac));
00707 }
00708 
00709 protocol_interface_info_entry_t *nwk_interface_get_ipv6_ptr(void)
00710 {
00711 #ifdef HAVE_ETHERNET
00712     ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
00713         if (cur->nwk_id == IF_IPV6) {
00714             return cur;
00715         }
00716     }
00717 #endif
00718 
00719     return NULL;
00720 }
00721 
00722 void nwk_interface_print_neigh_cache(route_print_fn_t *print_fn)
00723 {
00724     ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
00725         ipv6_neighbour_cache_print(&cur->ipv6_neighbour_cache, print_fn);
00726     }
00727 }
00728 
00729 void nwk_interface_flush_neigh_cache(void)
00730 {
00731     ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
00732         ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache);
00733     }
00734 }
00735 
00736 protocol_interface_info_entry_t *protocol_stack_interface_info_get(nwk_interface_id nwk_id)
00737 {
00738     ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list)
00739     if (cur->nwk_id == nwk_id) {
00740         return cur;
00741     }
00742 
00743     return NULL;
00744 }
00745 
00746 protocol_interface_info_entry_t *protocol_stack_interface_info_get_by_id(int8_t nwk_id)
00747 {
00748     ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list)
00749     if (cur->id == nwk_id) {
00750         return cur;
00751     }
00752 
00753     return NULL;
00754 }
00755 
00756 protocol_interface_info_entry_t *protocol_stack_interface_info_get_by_bootstrap_id(int8_t id)
00757 {
00758     ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list)
00759     if (cur->bootStrapId == id) {
00760         return cur;
00761     }
00762 
00763     return NULL;
00764 }
00765 
00766 protocol_interface_info_entry_t *protocol_stack_interface_info_get_by_rpl_domain(const struct rpl_domain *domain, int8_t last_id)
00767 {
00768     ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
00769         if (cur->id > last_id && cur->rpl_domain == domain) {
00770             return cur;
00771         }
00772     }
00773 
00774     return NULL;
00775 }
00776 
00777 protocol_interface_info_entry_t *protocol_stack_interface_info_get_by_fhss_api(const struct fhss_api *fhss_api)
00778 {
00779 #ifdef HAVE_WS
00780     ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
00781         if (cur->ws_info->fhss_api == fhss_api) {
00782             return cur;
00783         }
00784     }
00785 #else
00786     (void)fhss_api;
00787 #endif //HAVE_WS
00788     return NULL;
00789 }
00790 
00791 protocol_interface_info_entry_t *protocol_stack_interface_sleep_possibility(void)
00792 {
00793     ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
00794         if (!cur->if_stack_buffer_handler) {
00795             continue;
00796         }
00797 
00798         if (cur->nwk_id == IF_IPV6) {
00799             return NULL;
00800         }
00801 
00802         /* Note that rf_mac_setup == NULL is okay */
00803         if (cur->mac_parameters && cur->rfd_poll_info == NULL) {
00804             return NULL;
00805         }
00806     }
00807 
00808     ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
00809         if (cur->mac_parameters && cur->rfd_poll_info) {
00810             if (!cur->rfd_poll_info->pollActive && lowpan_adaptation_tx_active(cur->id)) {
00811                 return cur;
00812             }
00813         }
00814     }
00815 
00816     return NULL;
00817 }
00818 
00819 uint8_t nwk_bootsrap_ready(protocol_interface_info_entry_t *cur)
00820 {
00821     int8_t ret_val = 0;
00822     if ((cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE) == 0) {
00823         if (cur->nwk_bootstrap_state == ER_BOOTSRAP_DONE) {
00824             ret_val = 1;
00825         }
00826     }
00827     return ret_val;
00828 }
00829 
00830 static int8_t net_interface_get_free_id(void)
00831 {
00832     uint_fast8_t id; // Must be unsigned for loop test to work...
00833 
00834     for (id = 1; id <= INT8_MAX; id++) {
00835         bool in_use = false;
00836         /* interface index == default zone index for link, interface and realm, so
00837          * ensure selected ID is not in use for any of those scopes */
00838         ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
00839             if (cur->id == (int8_t) id ||
00840                 cur->zone_index[IPV6_SCOPE_INTERFACE_LOCAL] == id ||
00841                 cur->zone_index[IPV6_SCOPE_LINK_LOCAL] == id ||
00842                 cur->zone_index[IPV6_SCOPE_REALM_LOCAL] == id) {
00843                 in_use = true;
00844                 break;
00845             }
00846         }
00847         if (!in_use) {
00848             return id;
00849         }
00850     }
00851 
00852     return -1;
00853 }
00854 
00855 protocol_interface_info_entry_t *protocol_stack_interface_generate_ethernet(eth_mac_api_t *api)
00856 {
00857     if( !api ){
00858         return NULL;
00859     }
00860     protocol_interface_info_entry_t *new_entry = NULL;
00861 
00862     ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
00863         if (cur->eth_mac_api == api) {
00864             return cur;
00865         }
00866     }
00867 
00868     if (api) {
00869         new_entry = protocol_core_interface_ethernet_entry_get(api);
00870 
00871         if (new_entry) {
00872             neighbor_cache_init(&(new_entry->neigh_cache));
00873             pan_blacklist_cache_init(&(new_entry->pan_blaclist_cache));
00874             pan_coordinator_blacklist_cache_init(&(new_entry->pan_cordinator_black_list));
00875             ipv6_neighbour_cache_init(&new_entry->ipv6_neighbour_cache, new_entry->id);
00876             addr_max_slaac_entries_set(new_entry, 16);
00877             uint8_t mac[6];
00878             int8_t error = api->mac48_get( api, mac );
00879             if(error){
00880                 tr_error("mac_ext_mac64_address_get failed: %d", error);
00881                 ns_dyn_mem_free(new_entry);
00882                 return NULL;
00883             }
00884 
00885             protocol_stack_interface_iid_eui64_generate(new_entry, mac);
00886             ns_list_add_to_start(&protocol_interface_info_list, new_entry);
00887 
00888             (void) ipv6_route_table_set_max_entries(new_entry->id, ROUTE_RADV, 16);
00889 
00890             return new_entry;
00891         }
00892     }
00893     return NULL;
00894 }
00895 
00896 protocol_interface_info_entry_t *protocol_stack_interface_generate_lowpan(mac_api_t *api)
00897 {
00898     if( !api ){
00899         return NULL;
00900     }
00901     ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
00902         if (cur->mac_api == api) {
00903             return cur;
00904         }
00905     }
00906 
00907     protocol_interface_info_entry_t *new_entry = protocol_core_interface_6lowpan_entry_get_with_mac(api);
00908 
00909     if (new_entry) {
00910         neighbor_cache_init(&(new_entry->neigh_cache));
00911         pan_blacklist_cache_init(&(new_entry->pan_blaclist_cache));
00912         pan_coordinator_blacklist_cache_init(&(new_entry->pan_cordinator_black_list));
00913         ipv6_neighbour_cache_init(&new_entry->ipv6_neighbour_cache, new_entry->id);
00914 
00915         uint8_t mac[8];
00916         int8_t error = api->mac64_get( api, MAC_EXTENDED_READ_ONLY, mac );
00917         if(error){
00918             tr_error("mac_ext_mac64_address_get failed: %d", error);
00919             ns_dyn_mem_free(new_entry);
00920             return NULL;
00921         }
00922         protocol_stack_interface_iid_eui64_generate(new_entry, mac);
00923         ns_list_add_to_start(&protocol_interface_info_list, new_entry);
00924         return new_entry;
00925     }
00926     return NULL;
00927 }
00928 
00929 bool nwk_interface_compare_mac_address(protocol_interface_info_entry_t *cur, uint_fast8_t addrlen, const uint8_t addr[/*addrlen*/])
00930 {
00931     if (!cur) {
00932         return false;
00933     }
00934 
00935     switch (addrlen) {
00936         case 2:
00937             return cur->mac_parameters && cur->mac_parameters->mac_short_address == common_read_16_bit(addr);
00938         case 8:
00939             return memcmp(addr, cur->mac, 8) == 0;
00940         default:
00941             return false;
00942     }
00943 }
00944 
00945 /**
00946  * \brief Push Buffer to Protocol Core.
00947  *
00948  * \param buf pointer to buffer. NULL is accepted and ignored.
00949  */
00950 void protocol_push(buffer_t *buf)
00951 {
00952     /* Ignore NULL */
00953     if (!buf) {
00954         return;
00955     }
00956 
00957     arm_event_s event = {
00958             .receiver = protocol_root_tasklet_ID,
00959             .sender = 0,
00960             .event_type = ARM_IN_INTERFACE_PROTOCOL_HANDLE,
00961             .data_ptr = buf,
00962             .priority = ARM_LIB_LOW_PRIORITY_EVENT,
00963     };
00964 
00965     if (eventOS_event_send(&event) == 0) {
00966         protocol_core_buffers_in_event_queue++;
00967     } else {
00968         if ((buf->info  & B_DIR_MASK) == B_DIR_DOWN) {
00969             buf = socket_tx_buffer_event(buf, SOCKET_NO_RAM);
00970         }
00971         if (buf) {
00972             buffer_free(buf);
00973         } else {
00974             tr_debug("TCP Allocated");
00975         }
00976     }
00977 }
00978 
00979 /*
00980  * A protocol poll function to be typically called from 'Event Core'. This function is registered to the call queue by using event_cb_send() from 'Event Core'.
00981  */
00982 static void protocol_buffer_poll(buffer_t *b)
00983 {
00984     protocol_core_buffers_in_event_queue--;
00985 
00986     // Avoid the danger of with route data becoming stale (including
00987     // dead info pointers) while the packet is in the queue.
00988     if (b->route && ipv6_route_table_source_was_invalidated(b->route->route_info.source)) {
00989         buffer_free_route(b);
00990         // Attempt re-route immediately - some layers assume routing already
00991         // performed by higher layers.
00992         if (!ipv6_buffer_route(b)) {
00993             goto error;
00994         }
00995     }
00996 
00997     // Once buffer queue is empty, clear the invalidation flags for above test
00998     if (protocol_core_buffers_in_event_queue == 0) {
00999         ipv6_route_table_source_invalidated_reset();
01000     } else if (protocol_core_buffers_in_event_queue < 0) {
01001         tr_err("protocol_core_buffers_in_event_queue negative");
01002     }
01003 
01004     // Call the actual handler
01005     protocol_interface_info_entry_t *cur = b->interface ;
01006     if (cur && cur->if_stack_buffer_handler) {
01007         cur->if_stack_buffer_handler(b);
01008         return;
01009     }
01010 
01011 error:
01012     socket_tx_buffer_event_and_free(b, SOCKET_TX_FAIL);
01013 }
01014 
01015 static void nwk_net_event_post(arm_nwk_interface_status_type_e posted_event, int8_t net_tasklet, int8_t nwk_id)
01016 {
01017     arm_event_s event = {
01018         .receiver = net_tasklet,
01019         .sender = protocol_read_tasklet_id(), /**< Event sender Tasklet ID */
01020         .event_type = ARM_LIB_NWK_INTERFACE_EVENT,
01021         .event_data = posted_event,
01022         .event_id = (int8_t) nwk_id,
01023         .data_ptr = NULL,
01024         .priority = ARM_LIB_LOW_PRIORITY_EVENT,
01025     };
01026     if (eventOS_event_send(&event) != 0) {
01027         tr_error("nwk_net_event_post(): event send failed");
01028     }
01029 }
01030 
01031 void nwk_bootsrap_state_update(arm_nwk_interface_status_type_e posted_event, protocol_interface_info_entry_t *cur)
01032 {
01033     //Clear Bootsrap Active Bit allways
01034     cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_ACTIVE;
01035     cur->bootsrap_state_machine_cnt = 0;
01036     nwk_net_event_post(posted_event, cur->net_start_tasklet, cur->id);
01037 
01038     if (posted_event == ARM_NWK_BOOTSTRAP_READY) {
01039 
01040             switch (cur->bootsrap_mode) {
01041 
01042             case ARM_NWK_BOOTSRAP_MODE_6LoWPAN_RF_ACCESPOINT:
01043             case ARM_NWK_BOOTSRAP_MODE_6LoWPAN_RF_SNIFFER:
01044             case ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER:
01045             case ARM_NWK_BOOTSRAP_MODE_ETHERNET_HOST:
01046             case ARM_NWK_BOOTSRAP_MODE_ETHERNET_ROUTER:
01047 #ifdef HAVE_ETHERNET
01048                 if (cur->ipv6_configure) {
01049                     cur->ipv6_configure->IPv6_ND_state = IPV6_READY;
01050                     if (cur->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC) {
01051                         addr_add_router_groups(cur);
01052                         icmpv6_radv_enable(cur);//Activate RA send only with static enviroment
01053                         icmpv6_restart_router_advertisements(cur, ADDR_UNSPECIFIED);
01054                         if (cur->ipv6_configure->accept_ra != NET_IPV6_RA_ACCEPT_ALWAYS) {
01055                             icmpv6_recv_ra_routes(cur, false); // removes all existing RADV routes
01056                             icmpv6_recv_ra_prefixes(cur, false);
01057                         }
01058                     }
01059                 }
01060 #endif
01061                 break;
01062 
01063             default:
01064                 mac_data_poll_protocol_poll_mode_disable(cur);
01065                 if (!cur->rpl_domain) {
01066                     tr_debug("NON RPL Ready");
01067                     //nwk_protocol_poll_mode_disable(cur->nwk_id, 0);
01068                 } else {
01069                     tr_debug("RPL Ready");
01070                 }
01071         }
01072     } else {
01073         if (cur->if_down) {
01074             cur->if_down(cur);
01075         } else {
01076             tr_debug("if_down() NULL");
01077         }
01078     }
01079 }
01080 
01081 void net_bootsrap_cb_run(uint8_t event)
01082 {
01083     int8_t nwk_id = (int8_t) event;
01084     protocol_interface_info_entry_t *cur = 0;
01085     cur = protocol_stack_interface_info_get_by_id(nwk_id);
01086     if (cur) {
01087         if (cur->nwk_id == IF_6LoWPAN) {
01088             //eventOS_scheduler_set_active_tasklet(protocol_read_tasklet_id());
01089             if (thread_info(cur)) {
01090                 thread_bootstrap_state_machine(cur);
01091             } else if (ws_info(cur)) {
01092                 ws_bootstrap_state_machine(cur);
01093             } else {
01094                 protocol_6lowpan_bootstrap(cur);
01095             }
01096         } else if (cur->nwk_id == IF_IPV6) {
01097             //IPV6 Bootsrap Run
01098         }
01099     }
01100 }
01101 
01102 void protocol_core_dhcpv6_allocated_address_remove(protocol_interface_info_entry_t *cur, uint8_t *guaPrefix)
01103 {
01104     ipv6_stack_route_advert_remove(guaPrefix, 64);
01105     //Delete Address & Routes
01106     ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) {
01107         if (e->source == ADDR_SOURCE_DHCP && (e->prefix_len == 64) && bitsequal(e->address, guaPrefix, 64)) {
01108 
01109             ipv6_stack_route_advert_remove(e->address, 128);
01110 
01111             ns_list_remove(&cur->ip_addresses, e);
01112             ns_dyn_mem_free(e);
01113             tr_debug("Delete DHCPv6 Allocated Address");
01114             break;
01115         }
01116     }
01117 }
01118 
01119 /* XXX note that this does not perform any scope checks, so will for example match
01120  * link local addresses on any interface - you may want addr_interface_address_compare */
01121 int8_t protocol_interface_address_compare(const uint8_t *addr)
01122 {
01123     ns_list_foreach(protocol_interface_info_entry_t, cur, &protocol_interface_info_list) {
01124         if (addr_is_assigned_to_interface(cur, addr)) {
01125             return 0;
01126         }
01127     }
01128 
01129     return -1;
01130 }
01131