Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers protocol_6lowpan.c Source File

protocol_6lowpan.c

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