Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers protocol_6lowpan.c Source File

protocol_6lowpan.c

00001 /*
00002  * Copyright (c) 2013-2019, 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 "ns_trace.h"
00024 #include "nsdynmemLIB.h"
00025 #include "Core/include/ns_socket.h"
00026 #include "NWK_INTERFACE/Include/protocol.h"
00027 #include "Common_Protocols/udp.h"
00028 #include "Common_Protocols/ipv6.h"
00029 #include "Common_Protocols/icmpv6.h"
00030 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
00031 #include "6LoWPAN/Bootstraps/protocol_6lowpan_bootstrap.h"
00032 #include "6LoWPAN/ND/nd_router_object.h"
00033 #ifdef HAVE_RPL
00034 #include "RPL/rpl_control.h"
00035 #include "RPL/rpl_data.h"
00036 #include "RPL/rpl_protocol.h"
00037 #endif
00038 #include "6LoWPAN/IPHC_Decode/cipv6.h"
00039 #include "6LoWPAN/ND/nd_router_object.h"
00040 #ifndef NO_MLE
00041 #include "MLE/mle.h"
00042 #endif
00043 #include "6LoWPAN/Mesh/mesh.h"
00044 #include "6LoWPAN/Thread/thread_common.h"
00045 #include "6LoWPAN/Thread/thread_nd.h"
00046 #include "6LoWPAN/MAC/mac_helper.h"
00047 
00048 #ifdef ECC
00049 #include "libX509_V3.h"
00050 #include "ecc.h"
00051 #endif
00052 #include "ccmLIB.h"
00053 #include "shalib.h"
00054 #include "Security/TLS/tls_lib.h"
00055 #include "Security/Common/sec_lib.h"
00056 #include "net_nvm_api.h"
00057 #include "Security/PANA/pana.h"
00058 #include "Security/PANA/pana_internal_api.h"
00059 #include "Common_Protocols/tcp.h"
00060 #include "randLIB.h"
00061 #include "6LoWPAN/ND/nd_router_object.h"
00062 #include "common_functions.h"
00063 #include "BorderRouter/border_router.h"
00064 #include "net_rpl.h"
00065 #ifdef HAVE_RPL
00066 #ifndef NO_MLE
00067 #include "NWK_INTERFACE/Include/protocol_stats.h"
00068 #endif
00069 #endif
00070 #include "sw_mac.h"
00071 #include "6LoWPAN/MAC/mac_data_poll.h"
00072 #include "6LoWPAN/MAC/mpx_api.h"
00073 #include "6LoWPAN/lowpan_adaptation_interface.h"
00074 #include "6LoWPAN/Fragmentation/cipv6_fragmenter.h"
00075 #include "Service_Libs/etx/etx.h"
00076 #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
00077 #include "6LoWPAN/ws/ws_bootstrap.h"
00078 
00079 
00080 #define TRACE_GROUP_LOWPAN "6lo"
00081 #define TRACE_GROUP "6lo"
00082 
00083 #ifdef HAVE_RPL
00084 rpl_domain_t *protocol_6lowpan_rpl_domain;
00085 /* Having to sidestep old rpl_dodag_t type for the moment */
00086 struct rpl_dodag *protocol_6lowpan_rpl_root_dodag;
00087 #endif
00088 
00089 static uint8_t protocol_buffer_valid(buffer_t *b, protocol_interface_info_entry_t *cur)
00090 {
00091     uint8_t valid = 1;
00092     if (cur) {
00093         if ((b->info  & B_TO_MAC_MLME_MASK) != B_TO_MAC_FROM_MAC) {
00094             if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
00095                 //if((power_save_state & (SLEEP_MODE_REQ | ICMP_ACTIVE)) == SLEEP_MODE_REQ)
00096                 if (check_power_state(SLEEP_MODE_REQ | ICMP_ACTIVE) == SLEEP_MODE_REQ) {
00097                     /*  STill active but Sleep Req  and ICMP is not ACTIVE */
00098                     valid = 0;
00099                 }
00100             } else {
00101                 /*  Set Clean Core Becauce Protocol Is not Active */
00102                 valid = 0;
00103             }
00104         }
00105     } else {
00106         valid = 0;
00107     }
00108     return valid;
00109 }
00110 
00111 void protocol_init(void)
00112 {
00113     tr_debug("P.Init\n");
00114 #ifdef PANA
00115     sec_libray_init();
00116 #endif
00117 #ifdef HAVE_RPL
00118     protocol_6lowpan_rpl_domain = rpl_control_create_domain();
00119 #endif
00120 }
00121 
00122 void protocol_6lowpan_stack(buffer_t *b)
00123 {
00124     protocol_interface_info_entry_t *cur = b->interface ;
00125     if (protocol_buffer_valid(b, cur) == 0) {
00126         tr_debug("Drop Packets\n");
00127         buffer_free(b);
00128         return;
00129     }
00130     /* Protocol Buffer Handle until Buffer Go out from Stack */
00131     while (b) {
00132         /* Buffer Direction Select Switch */
00133         if ((b->info  & B_DIR_MASK) == B_DIR_DOWN) {
00134             /* Direction DOWN */
00135             switch (b->info  & B_TO_MASK) {
00136                 case B_TO_ICMP:
00137                     /* Build ICMP Header */
00138                     b = icmpv6_down(b);
00139                     break;
00140                 case B_TO_UDP:
00141                     /* Build UDP Header */
00142                     b = udp_down(b);
00143                     break;
00144 
00145                 case B_TO_IPV6:
00146                     /* Build IP header */
00147                     b = ipv6_down(b);
00148                     break;
00149 
00150                 case B_TO_IPV6_FWD:
00151                     /* IPv6 forwarding */
00152                     b = ipv6_forwarding_down(b);
00153                     break;
00154 
00155                 case B_TO_IPV6_TXRX:
00156                     /* Resolution, Compress IP header */
00157                     b = lowpan_down(b);
00158                     break;
00159 #ifdef HAVE_MESH
00160                 case B_TO_MESH_ROUTING:
00161                     /* Add mesh header */
00162                     b = mesh_down(b);
00163                     break;
00164 #endif
00165 
00166                 case B_TO_MAC:
00167                 /* no break */
00168                 case B_TO_PHY:
00169                     b = lowpan_adaptation_data_process_tx_preprocess(cur, b);
00170                     if (lowpan_adaptation_interface_tx(cur, b) != 0) {
00171                         tr_error("Adaptation Layer Data req fail");
00172                     }
00173                     b = NULL;
00174                     break;
00175 
00176                 default:
00177                     b = buffer_free(b);
00178                     break;
00179             }
00180         } else {
00181             /* Direction UP */
00182             switch (b->info  & B_TO_MASK) {
00183                 case B_TO_APP:
00184                     /* Push Socket Interface */
00185                     socket_up(b);
00186                     b = NULL;
00187                     break;
00188 
00189                 case B_TO_ICMP:
00190                     /* Parse ICMP Message */
00191                     b = icmpv6_up(b);
00192                     break;
00193 
00194                 case B_TO_FRAGMENTATION:
00195                     /* Packet Reasemley */
00196                     b = cipv6_frag_reassembly(cur->id, b);
00197 
00198                     break;
00199 
00200                 case B_TO_UDP:
00201                     /* Parse UDP Message */
00202                     b = udp_up(b);
00203                     break;
00204                 case B_TO_IPV6_FWD:
00205                     /* Handle IP Payload */
00206                     b = ipv6_forwarding_up(b);
00207                     break;
00208                 case B_TO_IPV6_TXRX:
00209                     /* Handle MAC Payload */
00210                     b = lowpan_up(b);
00211                     break;
00212 #ifdef HAVE_MESH
00213                 case B_TO_MESH_ROUTING:
00214                     /* Handle Mesh header */
00215                     b = mesh_up(b);
00216                     break;
00217 #endif
00218                 case B_TO_TCP:
00219                     b = tcp_up(b);
00220                     break;
00221                 default:
00222                     tr_debug("LLL\n");
00223                     b = buffer_free(b);
00224                     break;
00225             }
00226         }
00227         if (b) {
00228             //Check If Stack forward packet to different interface
00229             if (b->interface  != cur) {
00230                 protocol_push(b);
00231                 b = 0;
00232             }
00233         }
00234     }
00235 }
00236 
00237 /* Return length of option always, and write option if opt_out != NULL */
00238 static uint8_t protocol_6lowpan_llao_write(protocol_interface_info_entry_t *cur, uint8_t *opt_out, uint8_t opt_type, bool must, const uint8_t *ip_addr)
00239 {
00240     /* Don't bother including optional LLAO if it's a link-local address -
00241      * they should be mapping anyway.
00242      */
00243     if (!must && addr_is_ipv6_link_local(ip_addr)) {
00244         return 0;
00245     }
00246     uint16_t mac16 = mac_helper_mac16_address_get(cur);
00247 
00248     /* Even if we have a short address, use long address if the IP address's IID matches it */
00249     if (mac16 >= 0xfffe || addr_iid_matches_eui64(ip_addr + 8, cur->mac)) {
00250         if (opt_out) {
00251             opt_out[0] = opt_type;
00252             opt_out[1] = 2;
00253             memcpy(opt_out + 2, cur->mac, 8);
00254             memset(opt_out + 10, 0, 6);
00255         }
00256         return 16;
00257     } else {
00258         if (opt_out) {
00259             opt_out[0] = opt_type;
00260             opt_out[1] = 1;
00261             common_write_16_bit(mac16, opt_out + 2);
00262             memset(opt_out + 4, 0, 4);
00263         }
00264         return 8;
00265     }
00266 }
00267 
00268 /* Parse, and return actual size, or 0 if error */
00269 static uint8_t protocol_6lowpan_llao_parse(protocol_interface_info_entry_t *cur, const uint8_t *opt_in, sockaddr_t *ll_addr_out)
00270 {
00271     common_write_16_bit(cur->mac_parameters->pan_id, ll_addr_out->address  + 0);
00272 
00273     switch (opt_in[1]) {
00274         case 1:
00275             ll_addr_out->addr_type  = ADDR_802_15_4_SHORT ;
00276             memcpy(ll_addr_out->address  + 2, opt_in + 2, 2);
00277             return 2 + 2;
00278         case 2:
00279             ll_addr_out->addr_type  = ADDR_802_15_4_LONG ;
00280             memcpy(ll_addr_out->address  + 2, opt_in + 2, 8);
00281             return 2 + 8;
00282         default:
00283             return 0;
00284     }
00285 }
00286 
00287 static bool protocol_6lowpan_map_ip_to_link_addr(protocol_interface_info_entry_t *cur, const uint8_t *ip_addr, addrtype_t *ll_type, const uint8_t **ll_addr_out)
00288 {
00289     static uint8_t ll_addr[10];
00290     *ll_type = ADDR_NONE ;
00291 
00292     /* RFC 6775 says link-local addresses are based on extended MAC (LL64) */
00293     /* ZigBee IP and Thread both also have link-local addresses based on short MAC (LL16) */
00294     /* Our old IP stack assumed all addresses were based on MAC; this is available as an option */
00295     if (cur->iids_map_to_mac || addr_is_ipv6_link_local(ip_addr)) {
00296         if (memcmp(&ip_addr[8], ADDR_SHORT_ADR_SUFFIC, 6) == 0) {
00297             *ll_type = ADDR_802_15_4_SHORT ;
00298             memcpy(&ll_addr[2], &ip_addr[14], 2);
00299         } else {
00300             *ll_type = ADDR_802_15_4_LONG ;
00301             memcpy(&ll_addr[2], &ip_addr[8], 8);
00302             ll_addr[2] ^= 2;
00303         }
00304     } else if (thread_addr_is_mesh_local(ip_addr, cur)) {
00305         if (memcmp(&ip_addr[8], ADDR_SHORT_ADR_SUFFIC, 6) == 0) {
00306             /* Thread ML16s map directly to MAC (mesh) short */
00307             *ll_type = ADDR_802_15_4_SHORT ;
00308             memcpy(&ll_addr[2], &ip_addr[14], 2);
00309         }
00310     }
00311 
00312     if (*ll_type != ADDR_NONE ) {
00313         common_write_16_bit(cur->mac_parameters->pan_id, &ll_addr[0]);
00314         *ll_addr_out = ll_addr;
00315         return true;
00316     } else {
00317         return false;
00318     }
00319 
00320 }
00321 
00322 static bool protocol_6lowpan_map_link_addr_to_ip(protocol_interface_info_entry_t *cur, addrtype_t ll_type, const uint8_t *ll_addr, uint8_t *ip_addr_out)
00323 {
00324     (void)cur;
00325 
00326     switch (ll_type) {
00327         case ADDR_802_15_4_LONG :
00328             memcpy(ip_addr_out, ADDR_LINK_LOCAL_PREFIX, 8);
00329             memcpy(ip_addr_out + 8, ll_addr + 2, 8);
00330             ip_addr_out[8] ^= 0x02;
00331             return true;
00332         case ADDR_802_15_4_SHORT :
00333             if (common_read_16_bit(ll_addr + 2) > 0xfffd) {
00334                 return false;
00335             }
00336             memcpy(ip_addr_out, ADDR_LINK_LOCAL_PREFIX, 8);
00337             memcpy(ip_addr_out + 8, ADDR_SHORT_ADR_SUFFIC, 6);
00338             memcpy(ip_addr_out + 14, ll_addr + 2, 2);
00339             return true;
00340         default:
00341             return false;
00342     }
00343 }
00344 
00345 void protocol_6lowpan_host_init(protocol_interface_info_entry_t *cur, bool sleepy_host)
00346 {
00347     if (sleepy_host) {
00348         cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_SLEEPY_HOST;
00349     } else {
00350         cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_HOST;
00351     }
00352     //Clear always INTERFACE_NWK_ROUTER_DEVICE, INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE
00353     cur->lowpan_info &= ~(INTERFACE_NWK_ROUTER_DEVICE | INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE);
00354     mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, true);
00355     mac_data_poll_init(cur);
00356     arm_nwk_6lowpan_borderrouter_data_free(cur);
00357 }
00358 
00359 void protocol_6lowpan_router_init(protocol_interface_info_entry_t *cur)
00360 {
00361     cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER;
00362     cur->lowpan_info |= INTERFACE_NWK_ROUTER_DEVICE;
00363     cur->lowpan_info &= ~INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
00364     mac_data_poll_init(cur);
00365     arm_nwk_6lowpan_borderrouter_data_free(cur);
00366 }
00367 
00368 
00369 void protocol_6lowpan_configure_core(protocol_interface_info_entry_t *cur)
00370 {
00371     cur->dup_addr_detect_transmits = 0;
00372     cur->ipv6_neighbour_cache.max_ll_len = 2 + 8;
00373     cur->ipv6_neighbour_cache.link_mtu = LOWPAN_MTU;
00374 #ifdef HAVE_6LOWPAN_ND
00375     cur->ipv6_neighbour_cache.send_nud_probes = nd_params.send_nud_probes;
00376     cur->ipv6_neighbour_cache.probe_avoided_routers = nd_params.send_nud_probes;
00377     cur->iids_map_to_mac = nd_params.iids_map_to_mac;
00378 #endif
00379     cur->ip_multicast_as_mac_unicast_to_parent = false;
00380     cur->max_link_mtu = LOWPAN_MAX_MTU;
00381     cur->send_mld = false;
00382 #ifdef HAVE_6LOWPAN_ND
00383     nd_6lowpan_set_radv_params(cur);
00384 #endif
00385 }
00386 
00387 void protocol_6lowpan_register_handlers(protocol_interface_info_entry_t *cur)
00388 {
00389     cur->if_stack_buffer_handler = protocol_6lowpan_stack;
00390     cur->if_llao_parse = protocol_6lowpan_llao_parse;
00391     cur->if_llao_write = protocol_6lowpan_llao_write;
00392     cur->if_map_ip_to_link_addr = protocol_6lowpan_map_ip_to_link_addr;
00393     cur->if_map_link_addr_to_ip = protocol_6lowpan_map_link_addr_to_ip;
00394 
00395     if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER ||
00396             cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER) {
00397         cur->ipv6_neighbour_cache.recv_addr_reg = true;
00398         cur->ipv6_neighbour_cache.recv_ns_aro = true;
00399     }
00400 
00401     /* Always send AROs, (compulsory for hosts, and "SHOULD" in RFC 6557 6.5.5
00402      * for routers, as RPL doesn't deal with it) */
00403     cur->ipv6_neighbour_cache.send_addr_reg = true;
00404     cur->ipv6_neighbour_cache.recv_na_aro = true;
00405     cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro = false;
00406 }
00407 void protocol_6lowpan_release_short_link_address_from_neighcache(protocol_interface_info_entry_t *cur, uint16_t shortAddress)
00408 {
00409     uint8_t temp_ll[4];
00410     uint8_t *ptr = temp_ll;
00411     ptr = common_write_16_bit(cur->mac_parameters->pan_id, ptr);
00412     ptr = common_write_16_bit(shortAddress, ptr);
00413     ipv6_neighbour_invalidate_ll_addr(&cur->ipv6_neighbour_cache,
00414                                       ADDR_802_15_4_SHORT , temp_ll);
00415     if (thread_info(cur)) {
00416         thread_nd_address_remove(cur, ADDR_802_15_4_SHORT , temp_ll);
00417     } else {
00418         nd_remove_registration(cur, ADDR_802_15_4_SHORT , temp_ll);
00419     }
00420 }
00421 
00422 void protocol_6lowpan_release_long_link_address_from_neighcache(protocol_interface_info_entry_t *cur, uint8_t *mac64)
00423 {
00424     uint8_t temp_ll[10];
00425     uint8_t *ptr = temp_ll;
00426     ptr = common_write_16_bit(cur->mac_parameters->pan_id, ptr);
00427     memcpy(ptr, mac64, 8);
00428     ipv6_neighbour_invalidate_ll_addr(&cur->ipv6_neighbour_cache,
00429                                       ADDR_802_15_4_LONG , temp_ll);
00430     if (thread_info(cur)) {
00431         thread_nd_address_remove(cur, ADDR_802_15_4_LONG , temp_ll);
00432     } else  {
00433         nd_remove_registration(cur, ADDR_802_15_4_LONG , temp_ll);
00434     }
00435 }
00436 #ifdef HAVE_6LOWPAN_ND
00437 
00438 static int8_t  mle_set_link_priority(protocol_interface_info_entry_t *cur, const uint8_t *address, bool priority)
00439 {
00440     uint8_t mac64[8];
00441     mac_neighbor_table_entry_t *entry;
00442     if (!memcmp(address, ADDR_SHORT_ADR_SUFFIC, 6)) {
00443         entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), address + 6, ADDR_802_15_4_SHORT );
00444     } else {
00445 
00446         memcpy(mac64, address, 8);
00447         mac64[0] ^= 2;
00448         entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), mac64, ADDR_802_15_4_LONG );
00449     }
00450 
00451     if (!entry) {
00452         return -1;
00453     }
00454 
00455     if (priority) {
00456         entry->link_role  = PRIORITY_PARENT_NEIGHBOUR;
00457     } else {
00458         entry->link_role  = NORMAL_NEIGHBOUR;
00459     }
00460     return 0;
00461 }
00462 
00463 void protocol_6lowpan_neighbor_priority_update(protocol_interface_info_entry_t *cur, uint8_t *removed_priority, uint8_t *updated_priority)
00464 {
00465     if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) {
00466 #ifndef NO_MLE
00467         if (removed_priority) {
00468             mle_set_link_priority(cur, removed_priority, false);
00469         }
00470 
00471         if (updated_priority) {
00472             mle_set_link_priority(cur, updated_priority, true);
00473         }
00474 #endif
00475     }
00476 }
00477 
00478 #ifdef HAVE_RPL
00479 
00480 uint16_t protocol_6lowpan_neighbor_priority_set(int8_t interface_id, addrtype_t addr_type, const uint8_t *addr_ptr)
00481 {
00482     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00483 
00484     if (!cur || !addr_ptr) {
00485         return 0;
00486     }
00487 
00488     mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), addr_ptr + PAN_ID_LEN, addr_type);
00489 
00490     if (entry) {
00491 
00492         bool new_primary = false;
00493         etx_storage_t *etx_entry = etx_storage_entry_get(interface_id, entry->index );
00494         // If primary parent has changed clears priority from previous parent
00495         if (entry->link_role  != PRIORITY_PARENT_NEIGHBOUR) {
00496             new_primary = true;
00497             protocol_6lowpan_neighbor_priority_clear_all(interface_id, PRIORITY_1ST);
00498         }
00499         entry->link_role  = PRIORITY_PARENT_NEIGHBOUR;
00500 
00501 
00502         uint8_t temp[2];
00503         common_write_16_bit(entry->mac16 , temp);
00504         mac_helper_coordinator_address_set(cur, ADDR_802_15_4_SHORT , temp);
00505         mac_helper_coordinator_address_set(cur, ADDR_802_15_4_LONG , entry->mac64 );
00506         if (etx_entry) {
00507             protocol_stats_update(STATS_ETX_1ST_PARENT, etx_entry->etx >> 4);
00508         }
00509 
00510         if (new_primary) {
00511             ws_primary_parent_update(cur, entry);
00512         }
00513         return 1;
00514     } else {
00515         return 0;
00516     }
00517 }
00518 
00519 uint16_t protocol_6lowpan_neighbor_second_priority_set(int8_t interface_id, addrtype_t addr_type, const uint8_t *addr_ptr)
00520 {
00521 
00522     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00523 
00524     if (!cur || !addr_ptr) {
00525         return 0;
00526     }
00527 
00528     mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), addr_ptr + PAN_ID_LEN, addr_type);
00529 
00530     if (entry) {
00531         bool new_secondary = false;
00532         etx_storage_t *etx_entry = etx_storage_entry_get(interface_id, entry->index );
00533         // If secondary parent has changed clears priority from previous parent
00534         if (entry->link_role  != SECONDARY_PARENT_NEIGHBOUR) {
00535             new_secondary = true;
00536             protocol_6lowpan_neighbor_priority_clear_all(interface_id, PRIORITY_2ND);
00537         }
00538         entry->link_role  = SECONDARY_PARENT_NEIGHBOUR;
00539 
00540         if (etx_entry) {
00541             protocol_stats_update(STATS_ETX_2ND_PARENT, etx_entry->etx >> 4);
00542         }
00543         if (new_secondary) {
00544             ws_secondary_parent_update(cur);
00545         }
00546         return 1;
00547     } else {
00548         return 0;
00549     }
00550 }
00551 
00552 void protocol_6lowpan_neighbor_priority_clear_all(int8_t interface_id, neighbor_priority priority)
00553 {
00554     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00555 
00556     if (!cur) {
00557         return;
00558     }
00559     mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
00560 
00561     ns_list_foreach(mac_neighbor_table_entry_t, entry, mac_table_list) {
00562         if (priority == PRIORITY_1ST && entry->link_role  == PRIORITY_PARENT_NEIGHBOUR) {
00563             entry->link_role  = NORMAL_NEIGHBOUR;
00564         } else {
00565             if (entry->link_role  == SECONDARY_PARENT_NEIGHBOUR) {
00566                 protocol_stats_update(STATS_ETX_2ND_PARENT, 0);
00567                 entry->link_role  = NORMAL_NEIGHBOUR;
00568             }
00569 
00570         }
00571     }
00572 }
00573 
00574 #endif
00575 
00576 #endif
00577 
00578 int8_t protocol_6lowpan_neighbor_address_state_synch(protocol_interface_info_entry_t *cur, const uint8_t eui64[8], const uint8_t iid[8])
00579 {
00580     int8_t ret_val = -1;
00581 
00582     mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), eui64, ADDR_802_15_4_LONG );
00583     if (entry) {
00584         if (memcmp(iid, ADDR_SHORT_ADR_SUFFIC, 6) == 0) {
00585             iid += 6;
00586             //Set Short Address to MLE
00587             entry->mac16  = common_read_16_bit(iid);
00588         }
00589         if (!entry->ffd_device ) {
00590             if (entry->connected_device ) {
00591                 mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry, entry->link_lifetime );
00592             }
00593             ret_val = 1;
00594         } else {
00595             ret_val = 0;
00596         }
00597     }
00598     return ret_val;
00599 }
00600 
00601 int8_t protocol_6lowpan_neighbor_remove(protocol_interface_info_entry_t *cur, uint8_t *address_ptr, addrtype_t type)
00602 {
00603     mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), address_ptr, type);
00604     if (entry) {
00605         mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry);
00606     }
00607     return 0;
00608 }
00609 
00610 void protocol_6lowpan_allocate_mac16(protocol_interface_info_entry_t *cur)
00611 {
00612     if (cur) {
00613         cur->lowpan_desired_short_address = (randLIB_get_16bit() & 0x7fff);
00614     }
00615 }
00616 
00617 void protocol_6lowpan_interface_common_init(protocol_interface_info_entry_t *cur)
00618 {
00619     cur->lowpan_info |= INTERFACE_NWK_ACTIVE;
00620     protocol_6lowpan_register_handlers(cur);
00621     ipv6_route_add(ADDR_LINK_LOCAL_PREFIX, 64, cur->id, NULL, ROUTE_STATIC, 0xFFFFFFFF, 0);
00622     // Putting a multicast route to ff00::/8 makes sure we can always transmit multicast.
00623     // Interface metric will determine which interface is actually used, if we have multiple.
00624     ipv6_route_add(ADDR_LINK_LOCAL_ALL_NODES, 8, cur->id, NULL, ROUTE_STATIC, 0xFFFFFFFF, -1);
00625 }
00626 
00627 int8_t protocol_6lowpan_interface_compare_cordinator_netid(protocol_interface_info_entry_t *cur, uint8_t *adr_ptr)
00628 {
00629     int8_t ret_val = -1;
00630 
00631     if (cur) {
00632         addrtype_t addrType;
00633         uint8_t tempAddress[8];
00634         addrType = mac_helper_coordinator_address_get(cur, tempAddress);
00635 
00636         if (addrType == ADDR_802_15_4_LONG ) {
00637             tempAddress[0] ^= 2;
00638             if (memcmp(adr_ptr, tempAddress, 8) == 0) {
00639                 ret_val = 0;
00640             }
00641         } else if (addrType == ADDR_802_15_4_SHORT ) {
00642             if (adr_ptr[6] == tempAddress[0] && adr_ptr[7] == tempAddress[1]) {
00643                 ret_val = 0;
00644             }
00645         }
00646     }
00647     return ret_val;
00648 }
00649 
00650 int8_t protocol_6lowpan_interface_get_link_local_cordinator_address(protocol_interface_info_entry_t *cur, uint8_t *adr_ptr)
00651 {
00652     addrtype_t addrType;
00653     uint8_t tempAddress[8];
00654 
00655     addrType = mac_helper_coordinator_address_get(cur, tempAddress);
00656     if (addrType == ADDR_NONE ) {
00657         return -1;
00658     }
00659     memcpy(adr_ptr, ADDR_LINK_LOCAL_PREFIX, 8);
00660     adr_ptr += 8;
00661     if (addrType == ADDR_802_15_4_LONG ) {
00662         tempAddress[0] ^= 2;
00663         memcpy(adr_ptr, tempAddress, 8);
00664     } else {
00665         memcpy(adr_ptr, ADDR_SHORT_ADR_SUFFIC, 6);
00666         adr_ptr += 6;
00667         *adr_ptr++ = tempAddress[0];
00668         *adr_ptr = tempAddress[1];
00669     }
00670     return 0;
00671 }
00672 
00673 int8_t protocol_6lowpan_interface_get_mac_coordinator_address(protocol_interface_info_entry_t *cur, sockaddr_t *adr_ptr)
00674 {
00675     common_write_16_bit(cur->mac_parameters->pan_id, adr_ptr->address  + 0);
00676 
00677     adr_ptr->addr_type  = mac_helper_coordinator_address_get(cur, adr_ptr->address  + 2);
00678     if (adr_ptr->addr_type  == ADDR_NONE ) {
00679         return -1;
00680     }
00681     return 0;
00682 }
00683 
00684 int16_t protocol_6lowpan_rpl_global_priority_get(void)
00685 {
00686 #ifdef HAVE_RPL
00687     uint8_t instance_id_list[10];
00688     uint8_t rpl_instance_count;
00689     uint8_t instance_id = RPL_INSTANCE_LOCAL;
00690     uint8_t instance_id_new;
00691     uint8_t instance_index;
00692     rpl_instance_count = rpl_instance_list_read(&instance_id_list[0], sizeof(instance_id_list));
00693 
00694     /* Find lowest global instance ID (assumption: RPL instance with lowest instance ID has
00695            most generic routing rule and its rank should be indicated in beacon) */
00696     for (instance_index = 0; instance_index < rpl_instance_count; instance_index++) {
00697         instance_id_new = instance_id_list[instance_index];
00698 
00699         if ((instance_id_new & RPL_INSTANCE_LOCAL) == RPL_INSTANCE_LOCAL) {
00700             break;
00701         } else {
00702             if (instance_id_new < instance_id) {
00703                 instance_id = instance_id_new;
00704             }
00705         }
00706     }
00707 
00708     // Get DAG rank
00709     if (instance_id == RPL_INSTANCE_LOCAL) {
00710         return 255;
00711     }
00712 
00713     rpl_dodag_info_t rpl_dodag_info;
00714     if (!rpl_read_dodag_info(&rpl_dodag_info, instance_id)) {
00715         return 255;
00716     }
00717 
00718     if (rpl_dodag_info.curent_rank == RPL_RANK_INFINITE) {
00719         return 255;
00720     }
00721 
00722     // Default implementation is
00723     // 32 * (7 - DODAGPreference) + 3 * (DAGRank - 1)
00724     int16_t priority;
00725     priority = 32 * (7 - RPL_DODAG_PREF(rpl_dodag_info.flags));
00726     priority += 3 * (rpl_dodag_info.curent_rank / rpl_dodag_info.dag_min_hop_rank_inc - 1);
00727 
00728     return priority;
00729 #else
00730     return 255;
00731 #endif
00732 }
00733 
00734 uint8_t protocol_6lowpan_beacon_join_priority_tx(int8_t interface_id)
00735 {
00736     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00737     if (!cur) {
00738         return 255;
00739     }
00740 
00741     int16_t priority = 0;
00742 #ifdef HAVE_RPL
00743     if (cur->rpl_domain) {
00744         priority = protocol_6lowpan_rpl_global_priority_get();
00745     }
00746 #endif
00747 
00748 #ifndef NO_MLE
00749     mle_6lowpan_data_t *mle_6lowpan_data = protocol_6lowpan_mle_data_get();
00750 
00751     if (mle_6lowpan_data && mle_6lowpan_data->nbr_of_neigh_max != 0) {
00752         uint16_t mle_neigh_cnt = mle_class_active_neigh_counter(cur);
00753 
00754         if (mle_neigh_cnt > mle_6lowpan_data->nbr_of_neigh_lower_threshold) {
00755             uint16_t mle_neigh_limit;
00756             mle_neigh_cnt -= mle_6lowpan_data->nbr_of_neigh_lower_threshold;
00757             mle_neigh_limit = 32 * mle_neigh_cnt / (mle_6lowpan_data->nbr_of_neigh_max - mle_6lowpan_data->nbr_of_neigh_lower_threshold);
00758             priority += mle_neigh_limit;
00759         }
00760     }
00761 #endif
00762 
00763     if (priority < 0) {
00764         priority = 0;
00765     } else if (priority > 255) {
00766         priority = 255;
00767     }
00768 
00769     return priority;
00770 }
00771 
00772 uint8_t protocol_6lowpan_beacon_compare_rx(int8_t interface_id, uint8_t join_priority, uint8_t link_quality)
00773 {
00774     (void)interface_id; // not used, perhaps should be removed completely
00775 
00776     uint16_t conn_to_pref;
00777 
00778     conn_to_pref = ((256 - join_priority) * (uint16_t) link_quality) >> 8;
00779 
00780     return conn_to_pref;
00781 }