Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 }
Generated on Tue Jul 12 2022 14:24:32 by
