diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index f67764094d9..74f5fdafef7 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -204,6 +204,12 @@ void rpl_control_set_mrhof_parent_set_size(uint16_t parent_set_size) rpl_policy_set_mrhof_parent_set_size(parent_set_size); } +/* True Force RPL to use IPv6 tunneling when it send and forward data to Border router direction, This feature is disabled by default */ +void rpl_control_set_force_tunnel(bool requested) +{ + rpl_policy_force_tunnel_set(requested); +} + /* Send address registration to either specified address, or to non-registered address */ void rpl_control_register_address(protocol_interface_info_entry_t *interface, const uint8_t addr[16]) { diff --git a/source/RPL/rpl_control.h b/source/RPL/rpl_control.h index 7251cafcb61..e1525eee81c 100644 --- a/source/RPL/rpl_control.h +++ b/source/RPL/rpl_control.h @@ -177,6 +177,7 @@ bool rpl_control_find_worst_neighbor(struct protocol_interface_info_entry *inter /* Parent link confirmation API extension */ void rpl_control_request_parent_link_confirmation(bool requested); +void rpl_control_set_force_tunnel(bool requested); void rpl_control_set_dio_multicast_min_config_advertisment_count(uint8_t min_count); void rpl_control_set_address_registration_timeout(uint16_t timeout_in_minutes); void rpl_control_set_dao_retry_count(uint8_t count); diff --git a/source/RPL/rpl_data.c b/source/RPL/rpl_data.c index 236b6a5431e..ad51c5fa8ab 100644 --- a/source/RPL/rpl_data.c +++ b/source/RPL/rpl_data.c @@ -334,8 +334,24 @@ static buffer_t *rpl_data_exthdr_provider_hbh_2(buffer_t *buf, rpl_instance_t *i bool destination_in_instance = false; uint16_t ext_size = 0; - if (addr_ipv6_equal(route_info->next_hop_addr, buf->dst_sa.address) || - addr_ipv6_equal(buf->dst_sa.address, dodag->id)) { + + // Limit creation of multi-hop RPL packets + // Previous code created multi-hop RPL packets as much as possible, + // sending direct to border router in particular. + // This has caused WiSUN interop problems, so limit this. + // a) When creating a basic packet, have a policy option that prevents + // direct RPL header insertion, forcing tunnelling. This means + // we never put a RPL header on the innermost packet. Option is + // off by default, except for WiSUN, as it increases packet size + // when talking to the border router (eg DAOs). + // b) When putting a packet into a tunnel, set the tunnel exit to the + // next hop always, rather than having a special case for exiting + // at the border router. This is probably a net benefit to packet + // size because of the LL addresses used on the outer header, so + // this is an unconditional change. Exception remains for local + // DODAGs, where the destination address must be the DODAGID. + if (addr_ipv6_equal(route_info->next_hop_addr, buf->dst_sa.address) || (!rpl_policy_force_tunnel() && + addr_ipv6_equal(buf->dst_sa.address, dodag->id))) { destination_in_instance = true; if (buf->rpl_option) { @@ -409,10 +425,12 @@ static buffer_t *rpl_data_exthdr_provider_hbh_2(buffer_t *buf, rpl_instance_t *i rpl_data_locate_info(buf, &opt, NULL); if (!opt) { *result = IPV6_EXTHDR_MODIFY_TUNNEL; - // Tunnel to next hop in general case, but if going to DODAGID, - // it can tunnel all the way (and it HAS to if it is a local - // DODAG). - if (!addr_ipv6_equal(buf->dst_sa.address, dodag->id)) { + // Tunnel to next hop always, even if we could tunnel all + // the way to DODAG root (this may be better for + // packet compression, and it was found to be necessary for + // Wi-SUN interoperability). Except for local DODAGs the + // destination must be the DODAGID, so retain that in dst_sa. + if (!rpl_instance_id_is_local(instance->id)) { memcpy(buf->dst_sa.address, route_info->next_hop_addr, 16); } buf->src_sa.addr_type = ADDR_NONE; // force auto-selection diff --git a/source/RPL/rpl_policy.c b/source/RPL/rpl_policy.c index 5e6b7258d4e..11a67375979 100644 --- a/source/RPL/rpl_policy.c +++ b/source/RPL/rpl_policy.c @@ -48,6 +48,17 @@ static uint8_t rpl_policy_mrhof_parent_set_size_conf = 3; // default parent set static uint16_t rpl_policy_minimum_dao_target_refresh_conf = 0; // by default follow the configuration static uint16_t rpl_policy_address_registration_timeout_value = 0; // Address registration timeouts in minutes 0 use address lifetime +static bool rpl_policy_force_tunnel_to_BR = false; + +bool rpl_policy_force_tunnel(void) +{ + return rpl_policy_force_tunnel_to_BR; +} + +void rpl_policy_force_tunnel_set(bool enable) +{ + rpl_policy_force_tunnel_to_BR = enable; +} /* TODO - application API to control when to join new instances / DODAGs * * Eg, allow application to ignore local DODAGs, or specify known instance IDs, diff --git a/source/RPL/rpl_policy.h b/source/RPL/rpl_policy.h index ac9ca67a1f5..91e49175879 100644 --- a/source/RPL/rpl_policy.h +++ b/source/RPL/rpl_policy.h @@ -21,6 +21,9 @@ #include "Core/include/ns_address_internal.h" #include "rpl_control.h" +bool rpl_policy_force_tunnel(void); +void rpl_policy_force_tunnel_set(bool enable); + bool rpl_policy_join_instance(rpl_domain_t *domain, uint8_t instance_id, const uint8_t *dodagid); bool rpl_policy_join_dodag(rpl_domain_t *domain, uint8_t g_mop_prf, uint8_t instance_id, const uint8_t *dodagid); bool rpl_policy_join_config(rpl_domain_t *domain, const rpl_dodag_conf_t *conf, bool *leaf_only); diff --git a/test/nanostack/unittest/stub/rpl_control_stub.c b/test/nanostack/unittest/stub/rpl_control_stub.c index a0dbd927616..181ec212a68 100644 --- a/test/nanostack/unittest/stub/rpl_control_stub.c +++ b/test/nanostack/unittest/stub/rpl_control_stub.c @@ -278,6 +278,11 @@ void rpl_control_set_minimum_dao_target_refresh(uint16_t seconds) } +void rpl_control_set_force_tunnel(bool requested) +{ + +} + void rpl_control_set_initial_dao_ack_wait(uint16_t timeout_in_ms) { diff --git a/test/nanostack/unittest/stub/rpl_policy_stub.c b/test/nanostack/unittest/stub/rpl_policy_stub.c index c90409cd88c..8779842f368 100644 --- a/test/nanostack/unittest/stub/rpl_policy_stub.c +++ b/test/nanostack/unittest/stub/rpl_policy_stub.c @@ -34,6 +34,15 @@ #define TRACE_GROUP "RPLy" +bool rpl_policy_force_tunnel(void) +{ + return false; +} +void rpl_policy_force_tunnel_set(bool enable) +{ + +} + bool rpl_policy_join_instance(rpl_domain_t *domain, uint8_t instance_id, const uint8_t *dodagid) {