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-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 }
Generated on Tue Aug 9 2022 00:37:18 by
1.7.2