takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers protocol_6lowpan.c Source File

protocol_6lowpan.c

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