2015-05-22 21:47:37 +02:00
|
|
|
|
/**
|
2017-11-30 21:23:44 +01:00
|
|
|
|
* Copyright (C) 2018 HAW Hamburg
|
|
|
|
|
* Copyright (C) 2015–2017 Cenk Gündoğan <cenk.guendogan@haw-hamburg.de>
|
2017-11-30 21:17:11 +01:00
|
|
|
|
* Copyright (C) 2013–2014 INRIA.
|
2015-05-22 21:47:37 +02:00
|
|
|
|
*
|
|
|
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
|
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
|
|
|
* directory for more details.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @{
|
|
|
|
|
*
|
|
|
|
|
* @file
|
|
|
|
|
* @author Eric Engel <eric.engel@fu-berlin.de>
|
2017-11-30 21:23:44 +01:00
|
|
|
|
* @author Cenk Gündoğan <cenk.guendogan@haw-hamburg.de>
|
2015-05-22 21:47:37 +02:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdbool.h>
|
2018-07-21 10:13:00 +02:00
|
|
|
|
#include <string.h>
|
|
|
|
|
|
2015-08-18 22:50:51 +02:00
|
|
|
|
#include "net/af.h"
|
2015-08-12 19:04:43 +02:00
|
|
|
|
#include "net/gnrc/ipv6.h"
|
2017-11-16 18:06:46 +01:00
|
|
|
|
#include "net/gnrc/netif/internal.h"
|
2015-08-17 15:41:29 +02:00
|
|
|
|
#include "net/gnrc/rpl/dodag.h"
|
|
|
|
|
#include "net/gnrc/rpl/structs.h"
|
2017-11-30 21:23:26 +01:00
|
|
|
|
#include "gnrc_rpl_internal/globals.h"
|
2015-05-22 21:47:37 +02:00
|
|
|
|
#include "utlist.h"
|
2015-08-17 15:41:29 +02:00
|
|
|
|
|
|
|
|
|
#include "net/gnrc/rpl.h"
|
2015-08-23 14:25:39 +02:00
|
|
|
|
#ifdef MODULE_GNRC_RPL_P2P
|
|
|
|
|
#include "net/gnrc/rpl/p2p.h"
|
|
|
|
|
#include "net/gnrc/rpl/p2p_dodag.h"
|
|
|
|
|
#endif
|
2015-05-22 21:47:37 +02:00
|
|
|
|
|
|
|
|
|
#define ENABLE_DEBUG (0)
|
|
|
|
|
#include "debug.h"
|
|
|
|
|
|
|
|
|
|
static char addr_str[IPV6_ADDR_MAX_STR_LEN];
|
|
|
|
|
|
2015-08-21 10:56:43 +02:00
|
|
|
|
static gnrc_rpl_parent_t *_gnrc_rpl_find_preferred_parent(gnrc_rpl_dodag_t *dodag);
|
|
|
|
|
|
|
|
|
|
static void _rpl_trickle_send_dio(void *args)
|
2015-05-22 21:47:37 +02:00
|
|
|
|
{
|
2015-08-27 22:29:08 +02:00
|
|
|
|
gnrc_rpl_instance_t *inst = (gnrc_rpl_instance_t *) args;
|
|
|
|
|
gnrc_rpl_dodag_t *dodag = &inst->dodag;
|
2015-08-22 09:19:27 +02:00
|
|
|
|
|
|
|
|
|
/* a leaf node does not send DIOs periodically */
|
|
|
|
|
if (dodag->node_status == GNRC_RPL_LEAF_NODE) {
|
|
|
|
|
trickle_stop(&dodag->trickle);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-23 14:25:39 +02:00
|
|
|
|
#ifdef MODULE_GNRC_RPL_P2P
|
|
|
|
|
if (dodag->instance->mop == GNRC_RPL_P2P_MOP) {
|
|
|
|
|
gnrc_rpl_p2p_ext_t *p2p_ext = gnrc_rpl_p2p_ext_get(dodag);
|
|
|
|
|
if (p2p_ext && (p2p_ext->for_me || ((p2p_ext->lifetime_sec <= 0) || p2p_ext->stop))) {
|
|
|
|
|
trickle_stop(&dodag->trickle);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2016-03-22 10:17:32 +01:00
|
|
|
|
gnrc_rpl_send_DIO(inst, (ipv6_addr_t *) &ipv6_addr_all_rpl_nodes);
|
2015-08-27 22:29:08 +02:00
|
|
|
|
DEBUG("trickle callback: Instance (%d) | DODAG: (%s)\n", inst->id,
|
|
|
|
|
ipv6_addr_to_str(addr_str,&dodag->dodag_id, sizeof(addr_str)));
|
2015-05-22 21:47:37 +02:00
|
|
|
|
}
|
|
|
|
|
|
2015-08-17 15:41:29 +02:00
|
|
|
|
bool gnrc_rpl_instance_add(uint8_t instance_id, gnrc_rpl_instance_t **inst)
|
2015-05-22 21:47:37 +02:00
|
|
|
|
{
|
|
|
|
|
*inst = NULL;
|
|
|
|
|
bool first = true;
|
2015-08-17 15:41:29 +02:00
|
|
|
|
for (uint8_t i = 0; i < GNRC_RPL_INSTANCES_NUMOF; ++i) {
|
2015-05-22 21:47:37 +02:00
|
|
|
|
/* save position to the first unused instance */
|
2015-08-17 15:41:29 +02:00
|
|
|
|
if ((gnrc_rpl_instances[i].state == 0) && first) {
|
|
|
|
|
*inst = &gnrc_rpl_instances[i];
|
2015-05-22 21:47:37 +02:00
|
|
|
|
first = false;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2015-08-17 15:41:29 +02:00
|
|
|
|
else if ((gnrc_rpl_instances[i].state != 0) && (gnrc_rpl_instances[i].id == instance_id)) {
|
2015-05-22 21:47:37 +02:00
|
|
|
|
DEBUG("Instance with id %d exists\n", instance_id);
|
2015-08-17 15:41:29 +02:00
|
|
|
|
*inst = &gnrc_rpl_instances[i];
|
2015-05-22 21:47:37 +02:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*inst != NULL) {
|
|
|
|
|
(*inst)->id = instance_id;
|
|
|
|
|
(*inst)->state = 1;
|
2015-08-17 15:41:29 +02:00
|
|
|
|
(*inst)->max_rank_inc = GNRC_RPL_DEFAULT_MAX_RANK_INCREASE;
|
|
|
|
|
(*inst)->min_hop_rank_inc = GNRC_RPL_DEFAULT_MIN_HOP_RANK_INCREASE;
|
2015-08-27 22:29:08 +02:00
|
|
|
|
(*inst)->dodag.parents = NULL;
|
2017-11-30 21:23:26 +01:00
|
|
|
|
(*inst)->cleanup_event.msg.content.ptr = (*inst);
|
2015-05-22 21:47:37 +02:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* no space available to allocate a new instance */
|
|
|
|
|
DEBUG("Could not allocate a new RPL instance\n");
|
|
|
|
|
*inst = NULL;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-17 15:41:29 +02:00
|
|
|
|
bool gnrc_rpl_instance_remove_by_id(uint8_t instance_id)
|
2015-05-22 21:47:37 +02:00
|
|
|
|
{
|
2015-08-17 15:41:29 +02:00
|
|
|
|
for(uint8_t i = 0; i < GNRC_RPL_INSTANCES_NUMOF; ++i) {
|
|
|
|
|
if (gnrc_rpl_instances[i].id == instance_id) {
|
2015-08-27 22:29:08 +02:00
|
|
|
|
return gnrc_rpl_instance_remove(&gnrc_rpl_instances[i]);
|
2015-05-22 21:47:37 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-17 15:41:29 +02:00
|
|
|
|
bool gnrc_rpl_instance_remove(gnrc_rpl_instance_t *inst)
|
2015-05-22 21:47:37 +02:00
|
|
|
|
{
|
2015-08-27 22:29:08 +02:00
|
|
|
|
gnrc_rpl_dodag_t *dodag = &inst->dodag;
|
2015-08-23 14:25:39 +02:00
|
|
|
|
#ifdef MODULE_GNRC_RPL_P2P
|
|
|
|
|
gnrc_rpl_p2p_ext_remove(dodag);
|
|
|
|
|
#endif
|
2015-08-27 22:29:08 +02:00
|
|
|
|
gnrc_rpl_dodag_remove_all_parents(dodag);
|
|
|
|
|
trickle_stop(&dodag->trickle);
|
2018-06-21 10:41:13 +02:00
|
|
|
|
evtimer_del(&gnrc_rpl_evtimer, (evtimer_event_t *)&dodag->dao_event);
|
|
|
|
|
evtimer_del(&gnrc_rpl_evtimer, (evtimer_event_t *)&inst->cleanup_event);
|
2015-08-17 15:41:29 +02:00
|
|
|
|
memset(inst, 0, sizeof(gnrc_rpl_instance_t));
|
2015-05-22 21:47:37 +02:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-17 15:41:29 +02:00
|
|
|
|
gnrc_rpl_instance_t *gnrc_rpl_instance_get(uint8_t instance_id)
|
2015-05-22 21:47:37 +02:00
|
|
|
|
{
|
2015-08-17 15:41:29 +02:00
|
|
|
|
for (uint8_t i = 0; i < GNRC_RPL_INSTANCES_NUMOF; ++i) {
|
2015-08-27 22:29:08 +02:00
|
|
|
|
if ((gnrc_rpl_instances[i].state != 0) && (gnrc_rpl_instances[i].id == instance_id)) {
|
2015-08-17 15:41:29 +02:00
|
|
|
|
return &gnrc_rpl_instances[i];
|
2015-05-22 21:47:37 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-27 15:26:49 +02:00
|
|
|
|
bool gnrc_rpl_dodag_init(gnrc_rpl_instance_t *instance, ipv6_addr_t *dodag_id, kernel_pid_t iface)
|
2015-05-22 21:47:37 +02:00
|
|
|
|
{
|
2016-03-22 17:35:14 +01:00
|
|
|
|
assert(instance && (instance->state > 0));
|
2015-05-22 21:47:37 +02:00
|
|
|
|
|
2016-03-22 17:35:14 +01:00
|
|
|
|
gnrc_rpl_dodag_t *dodag = &instance->dodag;
|
2018-02-21 20:23:36 +01:00
|
|
|
|
gnrc_netif_t *netif = gnrc_netif_get_by_pid(iface);
|
2015-05-22 21:47:37 +02:00
|
|
|
|
|
2015-08-27 22:29:08 +02:00
|
|
|
|
dodag->dodag_id = *dodag_id;
|
|
|
|
|
dodag->my_rank = GNRC_RPL_INFINITE_RANK;
|
|
|
|
|
dodag->trickle.callback.func = &_rpl_trickle_send_dio;
|
|
|
|
|
dodag->trickle.callback.args = instance;
|
2020-04-17 16:51:25 +02:00
|
|
|
|
dodag->dio_interval_doubl = CONFIG_GNRC_RPL_DEFAULT_DIO_INTERVAL_DOUBLINGS;
|
2020-04-17 16:57:47 +02:00
|
|
|
|
dodag->dio_min = CONFIG_GNRC_RPL_DEFAULT_DIO_INTERVAL_MIN;
|
2020-04-23 10:21:17 +02:00
|
|
|
|
dodag->dio_redun = CONFIG_GNRC_RPL_DEFAULT_DIO_REDUNDANCY_CONSTANT;
|
2015-08-27 22:29:08 +02:00
|
|
|
|
dodag->default_lifetime = GNRC_RPL_DEFAULT_LIFETIME;
|
|
|
|
|
dodag->lifetime_unit = GNRC_RPL_LIFETIME_UNIT;
|
|
|
|
|
dodag->node_status = GNRC_RPL_NORMAL_NODE;
|
|
|
|
|
dodag->dao_seq = GNRC_RPL_COUNTER_INIT;
|
|
|
|
|
dodag->dtsn = 0;
|
|
|
|
|
dodag->dao_ack_received = false;
|
|
|
|
|
dodag->dao_counter = 0;
|
|
|
|
|
dodag->instance = instance;
|
2016-03-22 14:58:23 +01:00
|
|
|
|
dodag->iface = iface;
|
2017-11-30 21:23:26 +01:00
|
|
|
|
dodag->dao_event.msg.content.ptr = instance;
|
|
|
|
|
dodag->dao_event.msg.type = GNRC_RPL_MSG_TYPE_DODAG_DAO_TX;
|
2015-05-22 21:47:37 +02:00
|
|
|
|
|
2018-02-21 20:23:36 +01:00
|
|
|
|
if ((netif != NULL) && !(netif->flags & GNRC_NETIF_FLAGS_IPV6_FORWARDING)) {
|
|
|
|
|
gnrc_rpl_leaf_operation(dodag);
|
|
|
|
|
}
|
2015-08-23 14:25:39 +02:00
|
|
|
|
#ifdef MODULE_GNRC_RPL_P2P
|
|
|
|
|
if ((instance->mop == GNRC_RPL_P2P_MOP) && (gnrc_rpl_p2p_ext_new(dodag) == NULL)) {
|
|
|
|
|
DEBUG("RPL: could not allocate new P2P-RPL DODAG extension. Remove DODAG\n");
|
|
|
|
|
gnrc_rpl_instance_remove(instance);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2015-05-22 21:47:37 +02:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-17 15:41:29 +02:00
|
|
|
|
void gnrc_rpl_dodag_remove_all_parents(gnrc_rpl_dodag_t *dodag)
|
2015-05-22 21:47:37 +02:00
|
|
|
|
{
|
2017-08-22 13:02:38 +02:00
|
|
|
|
gnrc_rpl_parent_t *elt = NULL;
|
|
|
|
|
gnrc_rpl_parent_t *tmp = NULL;
|
2015-05-22 21:47:37 +02:00
|
|
|
|
LL_FOREACH_SAFE(dodag->parents, elt, tmp) {
|
2015-08-17 15:41:29 +02:00
|
|
|
|
gnrc_rpl_parent_remove(elt);
|
2015-05-22 21:47:37 +02:00
|
|
|
|
}
|
2015-08-23 14:25:39 +02:00
|
|
|
|
dodag->my_rank = GNRC_RPL_INFINITE_RANK;
|
2015-05-22 21:47:37 +02:00
|
|
|
|
}
|
|
|
|
|
|
2015-08-27 22:29:08 +02:00
|
|
|
|
bool gnrc_rpl_parent_add_by_addr(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *addr,
|
|
|
|
|
gnrc_rpl_parent_t **parent)
|
2015-05-22 21:47:37 +02:00
|
|
|
|
{
|
|
|
|
|
*parent = NULL;
|
|
|
|
|
bool first = true;
|
2015-08-17 15:41:29 +02:00
|
|
|
|
for (uint8_t i = 0; i < GNRC_RPL_PARENTS_NUMOF; ++i) {
|
2015-08-27 22:29:08 +02:00
|
|
|
|
/* save position to the first unused parent */
|
2015-08-17 15:41:29 +02:00
|
|
|
|
if ((gnrc_rpl_parents[i].state == 0) && first) {
|
|
|
|
|
*parent = &gnrc_rpl_parents[i];
|
2015-05-22 21:47:37 +02:00
|
|
|
|
first = false;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
/* return false if parent exists */
|
2015-08-27 22:29:08 +02:00
|
|
|
|
else if ((gnrc_rpl_parents[i].state != 0) && (gnrc_rpl_parents[i].dodag == dodag) &&
|
|
|
|
|
ipv6_addr_equal(&gnrc_rpl_parents[i].addr, addr)) {
|
|
|
|
|
DEBUG("parent (%s) exists\n", ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)));
|
2015-08-17 15:41:29 +02:00
|
|
|
|
*parent = &gnrc_rpl_parents[i];
|
2015-05-22 21:47:37 +02:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*parent != NULL) {
|
|
|
|
|
(*parent)->dodag = dodag;
|
|
|
|
|
LL_APPEND(dodag->parents, *parent);
|
2017-11-30 21:23:26 +01:00
|
|
|
|
(*parent)->state = GNRC_RPL_PARENT_ACTIVE;
|
2015-05-22 21:47:37 +02:00
|
|
|
|
(*parent)->addr = *addr;
|
2017-11-30 21:23:26 +01:00
|
|
|
|
(*parent)->rank = GNRC_RPL_INFINITE_RANK;
|
|
|
|
|
evtimer_del((evtimer_t *)(&gnrc_rpl_evtimer), (evtimer_event_t *)(&(*parent)->timeout_event));
|
|
|
|
|
((evtimer_event_t *)(&(*parent)->timeout_event))->next = NULL;
|
|
|
|
|
(*parent)->timeout_event.msg.type = GNRC_RPL_MSG_TYPE_PARENT_TIMEOUT;
|
|
|
|
|
(*parent)->timeout_event.msg.content.ptr = (*parent);
|
2015-05-22 21:47:37 +02:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* no space available to allocate a new parent */
|
|
|
|
|
DEBUG("Could not allocate a new parent\n");
|
|
|
|
|
*parent = NULL;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-17 15:41:29 +02:00
|
|
|
|
bool gnrc_rpl_parent_remove(gnrc_rpl_parent_t *parent)
|
2015-05-22 21:47:37 +02:00
|
|
|
|
{
|
2016-03-23 11:17:37 +01:00
|
|
|
|
assert(parent != NULL);
|
|
|
|
|
|
|
|
|
|
gnrc_rpl_dodag_t *dodag = parent->dodag;
|
|
|
|
|
|
|
|
|
|
if (parent == dodag->parents) {
|
2017-11-11 21:28:52 +01:00
|
|
|
|
gnrc_ipv6_nib_ft_del(NULL, 0);
|
2016-03-23 11:17:37 +01:00
|
|
|
|
|
|
|
|
|
/* set the default route to the next parent for now */
|
|
|
|
|
if (parent->next) {
|
2017-11-11 21:28:52 +01:00
|
|
|
|
gnrc_ipv6_nib_ft_add(NULL, 0,
|
|
|
|
|
&parent->next->addr, dodag->iface,
|
2017-11-30 21:23:26 +01:00
|
|
|
|
dodag->default_lifetime * dodag->lifetime_unit * MS_PER_SEC);
|
2016-03-23 11:17:37 +01:00
|
|
|
|
}
|
2015-05-22 21:47:37 +02:00
|
|
|
|
}
|
2016-03-23 11:17:37 +01:00
|
|
|
|
LL_DELETE(dodag->parents, parent);
|
2017-11-30 21:23:26 +01:00
|
|
|
|
evtimer_del((evtimer_t *)(&gnrc_rpl_evtimer), (evtimer_event_t *)&parent->timeout_event);
|
2015-08-17 15:41:29 +02:00
|
|
|
|
memset(parent, 0, sizeof(gnrc_rpl_parent_t));
|
2015-05-22 21:47:37 +02:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-14 11:41:30 +01:00
|
|
|
|
void gnrc_rpl_cleanup_start(gnrc_rpl_dodag_t *dodag)
|
|
|
|
|
{
|
|
|
|
|
evtimer_del((evtimer_t *)(&gnrc_rpl_evtimer), (evtimer_event_t *)&dodag->instance->cleanup_event);
|
|
|
|
|
((evtimer_event_t *)&(dodag->instance->cleanup_event))->offset = GNRC_RPL_CLEANUP_TIME;
|
|
|
|
|
dodag->instance->cleanup_event.msg.type = GNRC_RPL_MSG_TYPE_INSTANCE_CLEANUP;
|
|
|
|
|
evtimer_add_msg(&gnrc_rpl_evtimer, &dodag->instance->cleanup_event, gnrc_rpl_pid);
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-17 15:41:29 +02:00
|
|
|
|
void gnrc_rpl_local_repair(gnrc_rpl_dodag_t *dodag)
|
2015-05-22 21:47:37 +02:00
|
|
|
|
{
|
|
|
|
|
DEBUG("RPL: [INFO] Local Repair started\n");
|
|
|
|
|
|
|
|
|
|
dodag->dtsn++;
|
|
|
|
|
|
|
|
|
|
if (dodag->parents) {
|
2015-08-17 15:41:29 +02:00
|
|
|
|
gnrc_rpl_dodag_remove_all_parents(dodag);
|
2017-11-11 21:28:52 +01:00
|
|
|
|
gnrc_ipv6_nib_ft_del(NULL, 0);
|
2015-05-22 21:47:37 +02:00
|
|
|
|
}
|
|
|
|
|
|
2015-08-17 15:41:29 +02:00
|
|
|
|
if (dodag->my_rank != GNRC_RPL_INFINITE_RANK) {
|
2015-08-27 22:29:08 +02:00
|
|
|
|
dodag->my_rank = GNRC_RPL_INFINITE_RANK;
|
2015-05-22 21:47:37 +02:00
|
|
|
|
trickle_reset_timer(&dodag->trickle);
|
2020-02-14 11:41:30 +01:00
|
|
|
|
gnrc_rpl_cleanup_start(dodag);
|
2015-05-22 21:47:37 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-17 15:41:29 +02:00
|
|
|
|
void gnrc_rpl_parent_update(gnrc_rpl_dodag_t *dodag, gnrc_rpl_parent_t *parent)
|
2015-05-22 21:47:37 +02:00
|
|
|
|
{
|
|
|
|
|
/* update Parent lifetime */
|
2017-11-30 21:23:26 +01:00
|
|
|
|
if ((parent != NULL) && (parent->state != GNRC_RPL_PARENT_UNUSED)) {
|
|
|
|
|
parent->state = GNRC_RPL_PARENT_ACTIVE;
|
|
|
|
|
evtimer_del((evtimer_t *)(&gnrc_rpl_evtimer), (evtimer_event_t *)&parent->timeout_event);
|
|
|
|
|
((evtimer_event_t *)&(parent->timeout_event))->offset = dodag->default_lifetime * dodag->lifetime_unit * MS_PER_SEC;
|
|
|
|
|
parent->timeout_event.msg.type = GNRC_RPL_MSG_TYPE_PARENT_TIMEOUT;
|
|
|
|
|
evtimer_add_msg(&gnrc_rpl_evtimer, &parent->timeout_event, gnrc_rpl_pid);
|
2015-08-23 14:25:39 +02:00
|
|
|
|
#ifdef MODULE_GNRC_RPL_P2P
|
|
|
|
|
if (dodag->instance->mop != GNRC_RPL_P2P_MOP) {
|
|
|
|
|
#endif
|
2015-05-22 21:47:37 +02:00
|
|
|
|
if (parent == dodag->parents) {
|
2018-05-03 19:12:24 +02:00
|
|
|
|
gnrc_ipv6_nib_ft_del(NULL, 0);
|
2017-11-11 21:28:52 +01:00
|
|
|
|
gnrc_ipv6_nib_ft_add(NULL, 0, &parent->addr, dodag->iface,
|
|
|
|
|
dodag->default_lifetime * dodag->lifetime_unit);
|
2015-05-22 21:47:37 +02:00
|
|
|
|
}
|
2015-08-23 14:25:39 +02:00
|
|
|
|
#ifdef MODULE_GNRC_RPL_P2P
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2015-05-22 21:47:37 +02:00
|
|
|
|
}
|
|
|
|
|
|
2015-08-21 10:56:43 +02:00
|
|
|
|
if (_gnrc_rpl_find_preferred_parent(dodag) == NULL) {
|
2015-08-17 15:41:29 +02:00
|
|
|
|
gnrc_rpl_local_repair(dodag);
|
2015-05-22 21:47:37 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-21 10:56:43 +02:00
|
|
|
|
/**
|
|
|
|
|
* @brief Find the parent with the lowest rank and update the DODAG's preferred parent
|
|
|
|
|
*
|
|
|
|
|
* @param[in] dodag Pointer to the DODAG
|
|
|
|
|
*
|
|
|
|
|
* @return Pointer to the preferred parent, on success.
|
|
|
|
|
* @return NULL, otherwise.
|
|
|
|
|
*/
|
|
|
|
|
static gnrc_rpl_parent_t *_gnrc_rpl_find_preferred_parent(gnrc_rpl_dodag_t *dodag)
|
2015-05-22 21:47:37 +02:00
|
|
|
|
{
|
2015-08-17 15:41:29 +02:00
|
|
|
|
gnrc_rpl_parent_t *old_best = dodag->parents;
|
2018-11-08 14:53:32 +01:00
|
|
|
|
gnrc_rpl_parent_t *new_best;
|
2015-08-27 22:29:08 +02:00
|
|
|
|
uint16_t old_rank = dodag->my_rank;
|
2017-08-22 13:02:38 +02:00
|
|
|
|
gnrc_rpl_parent_t *elt = NULL;
|
|
|
|
|
gnrc_rpl_parent_t *tmp = NULL;
|
2015-05-22 21:47:37 +02:00
|
|
|
|
|
2015-08-27 22:29:08 +02:00
|
|
|
|
if (dodag->parents == NULL) {
|
2015-05-22 21:47:37 +02:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-10 12:28:39 +02:00
|
|
|
|
LL_SORT(dodag->parents, dodag->instance->of->parent_cmp);
|
|
|
|
|
new_best = dodag->parents;
|
2015-08-27 22:29:08 +02:00
|
|
|
|
|
|
|
|
|
if (new_best->rank == GNRC_RPL_INFINITE_RANK) {
|
|
|
|
|
return NULL;
|
2015-05-22 21:47:37 +02:00
|
|
|
|
}
|
|
|
|
|
|
2015-08-27 22:29:08 +02:00
|
|
|
|
if (new_best != old_best) {
|
2015-08-23 14:25:39 +02:00
|
|
|
|
/* no-path DAOs only for the storing mode */
|
|
|
|
|
if ((dodag->instance->mop == GNRC_RPL_MOP_STORING_MODE_NO_MC) ||
|
|
|
|
|
(dodag->instance->mop == GNRC_RPL_MOP_STORING_MODE_MC)) {
|
2015-08-27 22:29:08 +02:00
|
|
|
|
gnrc_rpl_send_DAO(dodag->instance, &old_best->addr, 0);
|
2015-08-17 15:41:29 +02:00
|
|
|
|
gnrc_rpl_delay_dao(dodag);
|
2015-05-22 21:47:37 +02:00
|
|
|
|
}
|
|
|
|
|
|
2015-08-23 14:25:39 +02:00
|
|
|
|
#ifdef MODULE_GNRC_RPL_P2P
|
|
|
|
|
if (dodag->instance->mop != GNRC_RPL_P2P_MOP) {
|
|
|
|
|
#endif
|
2018-05-03 19:12:24 +02:00
|
|
|
|
gnrc_ipv6_nib_ft_del(NULL, 0);
|
2017-11-11 21:28:52 +01:00
|
|
|
|
gnrc_ipv6_nib_ft_add(NULL, 0, &dodag->parents->addr, dodag->iface,
|
|
|
|
|
dodag->default_lifetime * dodag->lifetime_unit);
|
2015-08-23 14:25:39 +02:00
|
|
|
|
#ifdef MODULE_GNRC_RPL_P2P
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2015-08-27 22:29:08 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-22 13:02:38 +02:00
|
|
|
|
dodag->my_rank = dodag->instance->of->calc_rank(dodag, 0);
|
2015-08-27 22:29:08 +02:00
|
|
|
|
if (dodag->my_rank != old_rank) {
|
|
|
|
|
trickle_reset_timer(&dodag->trickle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LL_FOREACH_SAFE(dodag->parents, elt, tmp) {
|
|
|
|
|
if (DAGRANK(dodag->my_rank, dodag->instance->min_hop_rank_inc)
|
|
|
|
|
<= DAGRANK(elt->rank, dodag->instance->min_hop_rank_inc)) {
|
|
|
|
|
gnrc_rpl_parent_remove(elt);
|
|
|
|
|
}
|
2015-05-22 21:47:37 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return dodag->parents;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-27 22:29:08 +02:00
|
|
|
|
gnrc_rpl_instance_t *gnrc_rpl_root_instance_init(uint8_t instance_id, ipv6_addr_t *dodag_id,
|
|
|
|
|
uint8_t mop)
|
2015-08-23 18:33:51 +02:00
|
|
|
|
{
|
|
|
|
|
if (gnrc_rpl_pid == KERNEL_PID_UNDEF) {
|
|
|
|
|
DEBUG("RPL: RPL thread not started\n");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-16 18:06:46 +01:00
|
|
|
|
gnrc_netif_t *netif;
|
2015-08-23 18:33:51 +02:00
|
|
|
|
gnrc_rpl_instance_t *inst = NULL;
|
|
|
|
|
gnrc_rpl_dodag_t *dodag = NULL;
|
|
|
|
|
|
2015-10-29 13:11:26 +01:00
|
|
|
|
if (!(ipv6_addr_is_global(dodag_id) || ipv6_addr_is_unique_local_unicast(dodag_id))) {
|
|
|
|
|
DEBUG("RPL: dodag id (%s) must be a global or unique local IPv6 address\n",
|
|
|
|
|
ipv6_addr_to_str(addr_str, dodag_id, sizeof(addr_str)));
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-16 18:06:46 +01:00
|
|
|
|
if ((netif = gnrc_netif_get_by_ipv6_addr(dodag_id)) == NULL) {
|
2015-08-23 18:33:51 +02:00
|
|
|
|
DEBUG("RPL: no IPv6 address configured to match the given dodag id: %s\n",
|
|
|
|
|
ipv6_addr_to_str(addr_str, dodag_id, sizeof(addr_str)));
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (gnrc_rpl_instance_add(instance_id, &inst)) {
|
|
|
|
|
inst->of = (gnrc_rpl_of_t *) gnrc_rpl_get_of_for_ocp(GNRC_RPL_DEFAULT_OCP);
|
|
|
|
|
inst->mop = mop;
|
|
|
|
|
inst->min_hop_rank_inc = GNRC_RPL_DEFAULT_MIN_HOP_RANK_INCREASE;
|
|
|
|
|
inst->max_rank_inc = GNRC_RPL_DEFAULT_MAX_RANK_INCREASE;
|
|
|
|
|
}
|
|
|
|
|
else if (inst == NULL) {
|
2016-09-27 23:38:41 +02:00
|
|
|
|
DEBUG("RPL: could not allocate memory for a new instance with id %d\n", instance_id);
|
2015-08-23 18:33:51 +02:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2015-08-27 22:29:08 +02:00
|
|
|
|
else {
|
2016-09-27 23:38:41 +02:00
|
|
|
|
DEBUG("RPL: instance (%d) exists\n", instance_id);
|
2015-08-23 18:33:51 +02:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-23 22:59:13 +01:00
|
|
|
|
if (!gnrc_rpl_dodag_init(inst, dodag_id, netif->pid)) {
|
2016-09-27 23:38:41 +02:00
|
|
|
|
DEBUG("RPL: could not initialize DODAG\n");
|
2016-03-22 17:35:14 +01:00
|
|
|
|
gnrc_rpl_instance_remove(inst);
|
2015-08-23 18:33:51 +02:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-27 22:29:08 +02:00
|
|
|
|
dodag = &inst->dodag;
|
|
|
|
|
dodag->instance = inst;
|
2015-08-23 18:33:51 +02:00
|
|
|
|
|
2015-08-27 22:29:08 +02:00
|
|
|
|
return inst;
|
2015-08-23 18:33:51 +02:00
|
|
|
|
}
|
|
|
|
|
|
2015-08-22 09:19:27 +02:00
|
|
|
|
void gnrc_rpl_leaf_operation(gnrc_rpl_dodag_t *dodag)
|
|
|
|
|
{
|
|
|
|
|
dodag->node_status = GNRC_RPL_LEAF_NODE;
|
|
|
|
|
/* send INFINITE_RANK DIO to current children */
|
2015-08-27 22:29:08 +02:00
|
|
|
|
gnrc_rpl_send_DIO(dodag->instance, NULL);
|
2015-08-22 09:19:27 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void gnrc_rpl_router_operation(gnrc_rpl_dodag_t *dodag)
|
|
|
|
|
{
|
|
|
|
|
dodag->node_status = GNRC_RPL_NORMAL_NODE;
|
|
|
|
|
/* announce presence to neighborhood */
|
|
|
|
|
trickle_reset_timer(&dodag->trickle);
|
|
|
|
|
}
|
2015-05-22 21:47:37 +02:00
|
|
|
|
/**
|
|
|
|
|
* @}
|
|
|
|
|
*/
|