mirror of https://github.com/ARMmbed/mbed-os.git
328 lines
7.8 KiB
C
328 lines
7.8 KiB
C
/*
|
|
* Copyright (c) 2015-2017, Arm Limited and affiliates.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "nsconfig.h"
|
|
|
|
#ifdef HAVE_RPL
|
|
|
|
#include "ns_types.h"
|
|
#include "ns_trace.h"
|
|
|
|
#include "net_interface.h"
|
|
|
|
#include "Core/include/address.h"
|
|
#include "Service_Libs/etx/etx.h"
|
|
#include "Common_Protocols/ipv6_resolution.h"
|
|
#include "ipv6_stack/ipv6_routing_table.h"
|
|
|
|
#include "RPL/rpl_objective.h"
|
|
#include "RPL/rpl_policy.h"
|
|
|
|
#define TRACE_GROUP "RPLy"
|
|
|
|
/* TODO - application API to control when to join new instances / DODAGs
|
|
*
|
|
* Eg, allow application to ignore local DODAGs, or specify known instance IDs,
|
|
* select on something in the configuration...
|
|
*
|
|
* See RFC 6550 18.6. Policy
|
|
*/
|
|
bool rpl_policy_join_instance(rpl_domain_t *domain, uint8_t instance_id, const uint8_t *dodagid)
|
|
{
|
|
(void)domain;
|
|
(void)instance_id;
|
|
(void)dodagid;
|
|
|
|
/* And that will do for now. */
|
|
return true;
|
|
}
|
|
|
|
bool rpl_policy_join_dodag(rpl_domain_t *domain, uint8_t g_mop_prf, uint8_t instance_id, const uint8_t *addr)
|
|
{
|
|
(void)domain;
|
|
(void)g_mop_prf;
|
|
(void)instance_id;
|
|
(void)addr;
|
|
|
|
/* And that will do for now. */
|
|
return true;
|
|
}
|
|
|
|
bool rpl_policy_join_config(rpl_domain_t *domain, const rpl_dodag_conf_t *conf, bool *leaf_only)
|
|
{
|
|
(void)domain;
|
|
(void)conf;
|
|
(void)leaf_only;
|
|
|
|
/* Sanity checks */
|
|
if (conf->min_hop_rank_increase == 0) {
|
|
return false;
|
|
}
|
|
|
|
/* We don't support authentication */
|
|
if (conf->authentication) {
|
|
return false;
|
|
}
|
|
|
|
/* We're okay with DODAGs with unrecognised objectives - core will join as leaf using OF0 if we do nothing*/
|
|
#if 0
|
|
/* To reject unknowns: */
|
|
if (!rpl_objective_lookup(conf->objective_code_point)) {
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*bool rpl_policy_join_unsupported_as_leaf(rpl_domain_t *domain)
|
|
{
|
|
return true;
|
|
}*/
|
|
|
|
bool rpl_policy_request_dao_acks(const rpl_domain_t *domain, uint8_t mop)
|
|
{
|
|
(void)domain;
|
|
(void)mop;
|
|
|
|
return true;
|
|
}
|
|
|
|
uint16_t rpl_policy_initial_dao_ack_wait(const rpl_domain_t *domain, uint8_t mop)
|
|
{
|
|
(void)mop;
|
|
ipv6_neighbour_cache_t *ncache = ipv6_neighbour_cache_by_interface_id(domain->non_storing_downstream_interface);
|
|
if (ncache) {
|
|
//Check here RE trans timeout
|
|
if (ncache->retrans_timer > 2000) {
|
|
uint32_t reTransTimer = ncache->retrans_timer / 100;
|
|
if (reTransTimer > 0x7fff)
|
|
{
|
|
return 0xffff;
|
|
}
|
|
return (uint16_t)reTransTimer*2;
|
|
}
|
|
}
|
|
|
|
return 20; /* *100ms ticks = 2s */
|
|
}
|
|
|
|
/* Given the next-hop address from a source routing header, which interface,
|
|
* if any, should we assume that next hop is on?
|
|
*/
|
|
#define ETX_SRH_THRESHOLD 0x800 /* 8.8 fixed-point, so 4 */
|
|
int8_t rpl_policy_srh_next_hop_interface(rpl_domain_t *domain, int8_t if_id, const uint8_t *next_hop)
|
|
{
|
|
if (domain->non_storing_downstream_interface != -1) {
|
|
if_id = domain->non_storing_downstream_interface;
|
|
}
|
|
|
|
ipv6_neighbour_cache_t *ncache = ipv6_neighbour_cache_by_interface_id(if_id);
|
|
ipv6_neighbour_t *n = ncache ? ipv6_neighbour_lookup(ncache, next_hop) : NULL;
|
|
if (n && n->state == IP_NEIGHBOUR_UNREACHABLE) {
|
|
tr_warn("Rejecting SRH to %s: neighbour unreachable", trace_ipv6(next_hop));
|
|
goto reject;
|
|
}
|
|
|
|
uint16_t etx = ipv6_map_ip_to_ll_and_call_ll_addr_handler(NULL, if_id, n, next_hop, etx_read);
|
|
if (etx > ETX_SRH_THRESHOLD) {
|
|
tr_warn("Rejecting SRH to %s: etx = %x", trace_ipv6(next_hop), etx);
|
|
goto reject;
|
|
}
|
|
|
|
return if_id;
|
|
|
|
reject:
|
|
/* If rejecting due to SRH or unreachable, we should do some sort of probe
|
|
* to try to update state. This does the job. */
|
|
if (n) {
|
|
ipv6_neighbour_used(ncache, n);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
uint16_t rpl_policy_modify_downward_cost_to_root_neighbour(rpl_domain_t *domain, int8_t if_id, const uint8_t *next_hop, uint16_t cost)
|
|
{
|
|
(void)domain;
|
|
|
|
ipv6_neighbour_cache_t *ncache = ipv6_neighbour_cache_by_interface_id(if_id);
|
|
ipv6_neighbour_t *n = ncache ? ipv6_neighbour_lookup(ncache, next_hop) : NULL;
|
|
uint16_t etx = ipv6_map_ip_to_ll_and_call_ll_addr_handler(NULL, if_id, n, next_hop, etx_read);
|
|
|
|
if (etx == 0xFFFF) {
|
|
return cost + 256;
|
|
}
|
|
if (etx > ETX_SRH_THRESHOLD) {
|
|
return cost + 8;
|
|
}
|
|
if (!ipv6_neighbour_is_probably_reachable(ncache, n)) {
|
|
return cost + 4;
|
|
}
|
|
|
|
return cost;
|
|
}
|
|
|
|
uint16_t rpl_policy_parent_selection_period(rpl_domain_t *domain)
|
|
{
|
|
(void)domain;
|
|
|
|
return (10*60); /* seconds */
|
|
}
|
|
|
|
uint16_t rpl_policy_etx_hysteresis(rpl_domain_t *domain)
|
|
{
|
|
(void)domain;
|
|
|
|
return 0x0080; /* 8.8 fixed-point, so 0.5 */
|
|
}
|
|
|
|
uint16_t rpl_policy_etx_change_parent_selection_delay(rpl_domain_t *domain)
|
|
{
|
|
(void)domain;
|
|
|
|
return 30; /* seconds */
|
|
}
|
|
|
|
uint16_t rpl_policy_dio_parent_selection_delay(rpl_domain_t *domain)
|
|
{
|
|
(void)domain;
|
|
|
|
return 15; /* seconds */
|
|
}
|
|
|
|
uint16_t rpl_policy_repair_initial_dis_delay(rpl_domain_t *domain)
|
|
{
|
|
(void)domain;
|
|
|
|
return 10; /* seconds */
|
|
}
|
|
|
|
uint16_t rpl_policy_repair_maximum_dis_interval(rpl_domain_t *domain)
|
|
{
|
|
(void)domain;
|
|
|
|
return 60*60; /* seconds = 1 hour */
|
|
}
|
|
|
|
uint_fast8_t rpl_policy_repair_dis_count(rpl_domain_t *domain)
|
|
{
|
|
(void)domain;
|
|
|
|
return 6;
|
|
}
|
|
|
|
uint_fast8_t rpl_policy_repair_poison_count(rpl_domain_t *domain)
|
|
{
|
|
(void)domain;
|
|
|
|
return 2;
|
|
}
|
|
|
|
bool rpl_policy_dao_trigger_after_srh_error(rpl_domain_t *domain, uint32_t seconds_since_last_dao_trigger, uint16_t errors_since_last_dao_trigger, uint_fast16_t targets)
|
|
{
|
|
(void)domain;
|
|
(void)seconds_since_last_dao_trigger;
|
|
|
|
/* Trigger a DAO refresh after a number of errors proportional to the network size */
|
|
return errors_since_last_dao_trigger > 2 * targets;
|
|
}
|
|
|
|
bool rpl_policy_target_descriptor_for_own_address(rpl_domain_t *domain, const uint8_t addr[16], if_address_source_t source, void *data, uint32_t *descriptor_out)
|
|
{
|
|
(void)domain;
|
|
(void)addr;
|
|
(void)source;
|
|
(void)data;
|
|
(void)descriptor_out;
|
|
|
|
return false;
|
|
}
|
|
|
|
bool rpl_policy_target_descriptor_for_host_address(rpl_domain_t *domain, const uint8_t addr[16], uint32_t *descriptor_out)
|
|
{
|
|
(void)domain;
|
|
(void)addr;
|
|
(void)descriptor_out;
|
|
|
|
return false;
|
|
}
|
|
|
|
uint16_t rpl_policy_of0_stretch_of_rank(const rpl_domain_t *domain)
|
|
{
|
|
(void)domain;
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint_fast8_t rpl_policy_of0_rank_factor(const rpl_domain_t *domain)
|
|
{
|
|
(void)domain;
|
|
|
|
return 1;
|
|
}
|
|
|
|
bool rpl_policy_of0_dodag_preference_supersedes_grounded(const rpl_domain_t *domain)
|
|
{
|
|
(void)domain;
|
|
|
|
return false;
|
|
}
|
|
|
|
uint_fast8_t rpl_policy_of0_max_backup_successors(const rpl_domain_t *domain)
|
|
{
|
|
(void)domain;
|
|
|
|
return 1;
|
|
}
|
|
|
|
uint_fast8_t rpl_policy_mrhof_parent_set_size(const rpl_domain_t *domain)
|
|
{
|
|
(void)domain;
|
|
|
|
return 3;
|
|
}
|
|
|
|
uint16_t rpl_policy_mrhof_max_rank_stretch_for_extra_parents(const rpl_domain_t *domain)
|
|
{
|
|
(void)domain;
|
|
|
|
/* Conservative - will allow some backup, but not an extra hop */
|
|
return 64;
|
|
}
|
|
|
|
uint16_t rpl_policy_mrhof_max_link_metric(const rpl_domain_t *domain)
|
|
{
|
|
(void)domain;
|
|
|
|
return 512;
|
|
}
|
|
|
|
uint16_t rpl_policy_mrhof_parent_switch_threshold(const rpl_domain_t *domain)
|
|
{
|
|
(void)domain;
|
|
|
|
return 192;
|
|
}
|
|
|
|
|
|
#ifdef RPL_STRUCTURES_H_
|
|
#error "rpl_structures.h should not be included by rpl_policy.c"
|
|
#endif
|
|
|
|
#endif /* HAVE_RPL */
|