Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers protocol_core.c Source File

protocol_core.c

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