Exemplo n.º 1
0
rpl_parent_t *
rpl_select_parent(rpl_dag_t *dag)
{
  rpl_parent_t *p;
  rpl_parent_t *best;

  best = NULL;
  for(p = list_head(dag->parents); p != NULL; p = p->next) {
    if(p->rank == INFINITE_RANK) {
      /* ignore this neighbor */
    } else if(best == NULL) {
      best = p;
    } else {
      best = dag->of->best_parent(best, p);
    }
  }

  if(best == NULL) {
    /* need to handle update of best... */
    return NULL;
  }

  if(dag->preferred_parent != best) {
    if(dag->mop != RPL_MOP_NO_DOWNWARD_ROUTES) {
      PRINTF("RPL: Sending a No-Path DAO to old DAO parent\n");
      dao_output(dag->preferred_parent, ZERO_LIFETIME);
    }
    dag->preferred_parent = best; /* Cache the value. */
    dag->of->update_metric_container(dag);
    rpl_set_default_route(dag, &best->addr);
    /* The DAO parent set changed - schedule a DAO transmission. */
    if(dag->mop != RPL_MOP_NO_DOWNWARD_ROUTES) {
      rpl_schedule_dao(dag);
    }
    rpl_reset_dio_timer(dag, 1);
    PRINTF("RPL: New preferred parent, rank changed from %u to %u\n",
	   (unsigned)dag->rank, dag->of->calculate_rank(best, 0));
    RPL_STAT(rpl_stats.parent_switch++);
  }

  /* Update the DAG rank, since link-layer information may have changed
     the local confidence. */
  dag->rank = dag->of->calculate_rank(best, 0);
  if(dag->rank < dag->min_rank) {
    dag->min_rank = dag->rank;
  } else if(!acceptable_rank(dag, best->rank)) {
    /* Send a No-Path DAO to the soon-to-be-removed preferred parent. */
    if(dag->mop != RPL_MOP_NO_DOWNWARD_ROUTES) {
      dao_output(best, ZERO_LIFETIME);
    }

    remove_parents(dag, 0);
    return NULL;
  }

  return best;
}
Exemplo n.º 2
0
/*---------------------------------------------------------------------------*/
int
rpl_process_parent_event(rpl_instance_t *instance, rpl_parent_t *p)
{
  int return_value;

#if DEBUG
  rpl_rank_t old_rank;

  old_rank = instance->current_dag->rank;
#endif /* DEBUG */

  return_value = 1;

  if(!acceptable_rank(p->dag, p->rank)) {
    /* The candidate parent is no longer valid: the rank increase resulting
       from the choice of it as a parent would be too high. */
    PRINTF("RPL: Unacceptable rank %u\n", (unsigned)p->rank);
    rpl_nullify_parent(p);
    if(p != instance->current_dag->preferred_parent) {
      return 0;
    } else {
      return_value = 0;
    }
  }

  if(rpl_select_dag(instance, p) == NULL) {
    /* No suitable parent; trigger a local repair. */
    PRINTF("RPL: No parents found in any DAG\n");
    rpl_local_repair(instance);
    return 0;
  }
#if DEBUG
  if(DAG_RANK(old_rank, instance) !=
     DAG_RANK(instance->current_dag->rank, instance)) {
    PRINTF("RPL: Moving in the instance from rank %hu to %hu\n",
           DAG_RANK(old_rank, instance), DAG_RANK(instance->current_dag->rank,
                                                  instance));
    if(instance->current_dag->rank != INFINITE_RANK) {
      PRINTF("RPL: The preferred parent is ");
      PRINT6ADDR(rpl_get_parent_ipaddr
                   (instance->current_dag->preferred_parent));
      PRINTF(" (rank %u)\n",
             (unsigned)DAG_RANK(instance->current_dag->preferred_parent->rank,
                                instance));
    } else {
      PRINTF("RPL: We don't have any parent");
    }
  }
#endif /* DEBUG */

  return return_value;
}
Exemplo n.º 3
0
rpl_parent_t *
rpl_select_parent(rpl_dag_t *dag)
{
  rpl_parent_t *p;
  rpl_parent_t *best;

  best = NULL;
  for(p = list_head(dag->parents); p != NULL; p = p->next) {
    if(best == NULL) {
      best = p;
    } else {
      best = dag->of->best_parent(best, p);
    }
  }

  if(dag->preferred_parent != best) {
    dag->preferred_parent = best; /* Cache the value. */
    dag->of->update_metric_container(dag);
    rpl_set_default_route(dag, &best->addr);
    /* The DAO parent set changed - schedule a DAO transmission. */
    rpl_schedule_dao(dag);
    rpl_reset_dio_timer(dag, 1);
    PRINTF("RPL: New preferred parent, rank changed from %u to %u\n",
	   (unsigned)dag->rank, dag->of->calculate_rank(best, 0));
  }

  /* Update the DAG rank, since link-layer information may have changed
     the local confidence. */
  dag->rank = dag->of->calculate_rank(best, 0);
  if(dag->rank < dag->min_rank) {
    dag->min_rank = dag->rank;
  } else if(!acceptable_rank(dag, best->rank)) {
    /* Send a No-Path DAO to the soon-to-be-removed preferred parent. */
    dao_output(p, ZERO_LIFETIME);

    remove_parents(dag, 0);
    return NULL;
  }

  return best;
}
int
rpl_process_parent_event(rpl_dag_t *dag, rpl_parent_t *p)
{
  rpl_rank_t parent_rank;
  rpl_rank_t old_rank;

  /* Update the parent rank. */
  parent_rank = p->rank;
  old_rank = dag->rank;

  if(rpl_select_parent(dag) == NULL) {
    /* No suitable parent; trigger a local repair. */
    PRINTF("RPL: No parents found in a DAG\n");
    rpl_local_repair(dag);
    return 1;
  }

  if(DAG_RANK(old_rank, dag) != DAG_RANK(dag->rank, dag)) {
    if(dag->rank < dag->min_rank) {
      dag->min_rank = dag->rank;
    }
    PRINTF("RPL: Moving in the DAG from rank %hu to %hu\n",
	   DAG_RANK(old_rank, dag), DAG_RANK(dag->rank, dag));
    PRINTF("RPL: The preferred parent is ");
    PRINT6ADDR(&dag->preferred_parent->addr);
    PRINTF(" (rank %u)\n",
           (unsigned)DAG_RANK(dag->preferred_parent->rank, dag));
    rpl_reset_dio_timer(dag, 1);
  }

  if(parent_rank == INFINITE_RANK ||
     !acceptable_rank(dag, dag->of->calculate_rank(NULL, parent_rank))) {
    /* The candidate parent is no longer valid: the rank increase resulting
       from the choice of it as a parent would be too high. */
    return 0;
  }

  return 1;
}
Exemplo n.º 5
0
/*---------------------------------------------------------------------------*/
rpl_dag_t *
rpl_select_dag(rpl_instance_t *instance, rpl_parent_t *p)
{
  rpl_parent_t *last_parent;
  rpl_dag_t *dag, *end, *best_dag;
  rpl_rank_t old_rank;

  old_rank = instance->current_dag->rank;
  last_parent = instance->current_dag->preferred_parent;

  if(instance->current_dag->rank != ROOT_RANK(instance)) {
    rpl_select_parent(p->dag);
  }

  best_dag = NULL;
  for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) {
    if(dag->used && dag->preferred_parent != NULL && dag->preferred_parent->rank != INFINITE_RANK) {
      if(best_dag == NULL) {
        best_dag = dag;
      } else {
        best_dag = instance->of->best_dag(best_dag, dag);
      }
    }
  }

  if(best_dag == NULL) {
    /* No parent found: the calling function handle this problem. */
    return NULL;
  }

  if(instance->current_dag != best_dag) {
    /* Remove routes installed by DAOs. */
    rpl_remove_routes(instance->current_dag);

    PRINTF("RPL: New preferred DAG: ");
    PRINT6ADDR(&best_dag->dag_id);
    PRINTF("\n");

    if(best_dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
      check_prefix(&instance->current_dag->prefix_info, &best_dag->prefix_info);
    } else if(instance->current_dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
      check_prefix(&instance->current_dag->prefix_info, NULL);
    }

    best_dag->joined = 1;
    instance->current_dag->joined = 0;
    instance->current_dag = best_dag;
  }

  instance->of->update_metric_container(instance);
  /* Update the DAG rank. */
  best_dag->rank = instance->of->calculate_rank(best_dag->preferred_parent, 0);
  if(last_parent == NULL || best_dag->rank < best_dag->min_rank) {
    best_dag->min_rank = best_dag->rank;
  } else if(!acceptable_rank(best_dag, best_dag->rank)) {
    PRINTF("RPL: New rank unacceptable!\n");
    rpl_set_preferred_parent(instance->current_dag, NULL);
    if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES && last_parent != NULL) {
      /* Send a No-Path DAO to the removed preferred parent. */
      dao_output(last_parent, RPL_ZERO_LIFETIME);
    }
    return NULL;
  }

  if(best_dag->preferred_parent != last_parent) {
    rpl_set_default_route(instance, rpl_get_parent_ipaddr(best_dag->preferred_parent));
    PRINTF("RPL: Changed preferred parent, rank changed from %u to %u\n",
  	(unsigned)old_rank, best_dag->rank);
    RPL_STAT(rpl_stats.parent_switch++);
    if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) {
      if(last_parent != NULL) {
        /* Send a No-Path DAO to the removed preferred parent. */
        dao_output(last_parent, RPL_ZERO_LIFETIME);
      }
      /* The DAO parent set changed - schedule a DAO transmission. */
      RPL_LOLLIPOP_INCREMENT(instance->dtsn_out);
      rpl_schedule_dao(instance);
    }
    rpl_reset_dio_timer(instance);
#if DEBUG
    rpl_print_neighbor_list();
#endif
  } else if(best_dag->rank != old_rank) {
    PRINTF("RPL: Preferred parent update, rank changed from %u to %u\n",
  	(unsigned)old_rank, best_dag->rank);
  }
  return best_dag;
}