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.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
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 }
Generated on Tue Jul 12 2022 13:54:43 by
