static rpl_rank_t
calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank)
{
  rpl_rank_t new_rank;
  rpl_rank_t rank_increase;

  if(p == NULL) {
    if(base_rank == 0) {
      return INFINITE_RANK;
    }
    rank_increase = NEIGHBOR_INFO_FIX2ETX(INITIAL_LINK_METRIC) * RPL_MIN_HOPRANKINC;
  } else {
    /* multiply first, then scale down to avoid truncation effects */
    rank_increase = NEIGHBOR_INFO_FIX2ETX(p->link_metric * p->dag->instance->min_hoprankinc);
    if(base_rank == 0) {
      base_rank = p->rank;
    }
  }

  if(INFINITE_RANK - base_rank < rank_increase) {
    /* Reached the maximum rank. */
    new_rank = INFINITE_RANK;
  } else {
   /* Calculate the rank based on the new rank information from DIO or
      stored otherwise. */
    new_rank = base_rank + rank_increase;
  }

  return new_rank;
}
Ejemplo n.º 2
0
static rpl_rank_t
calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank)
{
  rpl_rank_t new_rank;
  rpl_rank_t rank_increase;

  if(p == NULL) {
    if(base_rank == 0) {
      return INFINITE_RANK;
    }
    rank_increase = NEIGHBOR_INFO_FIX2ETX(INITIAL_LINK_METRIC) * DEFAULT_MIN_HOPRANKINC;
  } else {
    rank_increase = NEIGHBOR_INFO_FIX2ETX(p->link_metric) * p->dag->min_hoprankinc;
    if(base_rank == 0) {
      base_rank = p->rank;
    }
  }

  if(INFINITE_RANK - base_rank < rank_increase) {
    /* Reached the maximum rank. */
    new_rank = INFINITE_RANK;
  } else {
   /* Calculate the rank based on the new rank information from DIO or
      stored otherwise. */
    new_rank = base_rank + rank_increase;
  }

  return new_rank;
}
Ejemplo n.º 3
0
/*---------------------------------------------------------------------------*/
static void
update_metric(const rimeaddr_t *dest, int packet_metric)
{
  link_metric_t *metricp;
  link_metric_t recorded_metric, new_metric;
  unsigned long time;
  int first_update = 0;

  metricp = (link_metric_t *)neighbor_attr_get_data(&attr_etx, dest);
  packet_metric = NEIGHBOR_INFO_ETX2FIX(packet_metric);
  if(metricp == NULL || *metricp == 0) {
    recorded_metric = packet_metric;
    new_metric = ((uint16_t)recorded_metric * 5 +
         (uint16_t)packet_metric * (ETX_SCALE - 5)) / ETX_SCALE;
    first_update = 1;
  } else {
    recorded_metric = *metricp;
    /* Update the EWMA of the ETX for the neighbor. */
    if(packet_metric != NEIGHBOR_INFO_ETX2FIX(ETX_NOACK_PENALTY)) {
      new_metric = ((uint16_t)recorded_metric * ETX_ALPHA +
          (uint16_t)packet_metric * (ETX_SCALE - ETX_ALPHA)) / ETX_SCALE;
    } else {
      new_metric = ((uint16_t)recorded_metric * 5 +
                (uint16_t)packet_metric * 5) / ETX_SCALE;
    }
  }

  printf("neighbor-info: ETX of %u changed from %d to %d (packet ETX = %d)\n",
   node_id_from_rimeaddr(dest),
	 NEIGHBOR_INFO_FIX2ETX(recorded_metric),
	 NEIGHBOR_INFO_FIX2ETX(new_metric),
	 NEIGHBOR_INFO_FIX2ETX(packet_metric)
  );

  if(neighbor_attr_has_neighbor(dest)) {
    time = clock_seconds();
    neighbor_attr_set_data(&attr_etx, dest, &new_metric);
    neighbor_attr_set_data(&attr_timestamp, dest, &time);
    if(/*(first_update || new_metric != recorded_metric) &&*/ subscriber_callback != NULL) {
      subscriber_callback(dest, 1, new_metric);
    }
  }
}
Ejemplo n.º 4
0
/*---------------------------------------------------------------------------*/
static void
update_metric(const rimeaddr_t *dest, int packet_metric)
{
  static link_metric_t *metricp;
  static link_metric_t recorded_metric;
  static link_metric_t new_metric;
  unsigned long time;
  int first_update = 0;

  metricp = (link_metric_t *)neighbor_attr_get_data(&attr_etx, dest);
  packet_metric = NEIGHBOR_INFO_ETX2FIX(packet_metric);
  if(metricp == NULL || *metricp == 0) {
    recorded_metric = NEIGHBOR_INFO_ETX2FIX(ETX_LIMIT);
    new_metric = packet_metric;
    first_update = 1;
  } else {
    recorded_metric = *metricp;
    /* Update the EWMA of the ETX for the neighbor. */
    new_metric = ((uint16_t)recorded_metric * ETX_ALPHA +
               (uint16_t)packet_metric * (ETX_SCALE - ETX_ALPHA)) / ETX_SCALE;
  }

  PRINTF("neighbor-info: ETX changed from %d to %d (packet ETX = %d) %d\n",
	 NEIGHBOR_INFO_FIX2ETX(recorded_metric),
	 NEIGHBOR_INFO_FIX2ETX(new_metric),
	 NEIGHBOR_INFO_FIX2ETX(packet_metric),
         dest->u8[7]);

  if(neighbor_attr_has_neighbor(dest)) {
    time = clock_seconds();
    neighbor_attr_set_data(&attr_etx, dest, &new_metric);
    neighbor_attr_set_data(&attr_timestamp, dest, &time);
    if((first_update || new_metric != recorded_metric) && subscriber_callback != NULL) {
      subscriber_callback(dest, 1, new_metric);
    }
  }
}
Ejemplo n.º 5
0
static void
rpl_link_neighbor_callback(const rimeaddr_t *addr, int known, int etx)
{
  uip_ipaddr_t ipaddr;
  rpl_dag_t *dag;
  rpl_parent_t *parent;

  uip_ip6addr(&ipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0);
  uip_ds6_set_addr_iid(&ipaddr, (uip_lladdr_t *)addr);
  PRINTF("RPL: Neighbor ");
  PRINT6ADDR(&ipaddr);
  PRINTF(" is %sknown. ETX = %u\n", known ? "" : "no longer ", NEIGHBOR_INFO_FIX2ETX(etx));

  dag = rpl_get_dag(RPL_DEFAULT_INSTANCE);
  if(dag == NULL) {
    return;
  }

  parent = rpl_find_parent(dag, &ipaddr);
  if(parent == NULL) {
    if(!known) {
      PRINTF("RPL: Deleting routes installed by DAOs received from ");
      PRINT6ADDR(&ipaddr);
      PRINTF("\n");
      uip_ds6_route_rm_by_nexthop(&ipaddr);
    }
    return;
  }

  /* Trigger DAG rank recalculation. */
  parent->updated = 1;

  parent->link_metric = etx;

  if(dag->of->parent_state_callback != NULL) {
    dag->of->parent_state_callback(parent, known, etx);
  }

  if(!known) {
    PRINTF("RPL: Removing parent ");
    PRINT6ADDR(&parent->addr);
    PRINTF(" because of bad connectivity (ETX %d)\n", etx);
    parent->rank = INFINITE_RANK;
  }
}