Exemple #1
0
/*---------------------------------------------------------------------------*/
void
rpl_print_neighbor_list()
{
  if(default_instance != NULL && default_instance->current_dag != NULL &&
      default_instance->of != NULL && default_instance->of->calculate_rank != NULL) {
    int curr_dio_interval = default_instance->dio_intcurrent;
    int curr_rank = default_instance->current_dag->rank;
    rpl_parent_t *p = nbr_table_head(rpl_parents);
    clock_time_t now = clock_time();

    printf("RPL: rank %u dioint %u, %u nbr(s)\n", curr_rank, curr_dio_interval, uip_ds6_nbr_num());
    while(p != NULL) {
      uip_ds6_nbr_t *nbr = rpl_get_nbr(p);
      printf("RPL: nbr %3u %5u, %5u => %5u %c%c (last tx %u min ago)\n",
          nbr_table_get_lladdr(rpl_parents, p)->u8[7],
          p->rank, nbr ? nbr->link_metric : 0,
          default_instance->of->calculate_rank(p, 0),
          default_instance->current_dag == p->dag ? 'd' : ' ',
          p == default_instance->current_dag->preferred_parent ? '*' : ' ',
          (unsigned)((now - p->last_tx_time) / (60 * CLOCK_SECOND)));
      p = nbr_table_next(rpl_parents, p);
    }
    printf("RPL: end of list\n");
  }
}
Exemple #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;
  uip_ds6_nbr_t *nbr;

  if(p == NULL || (nbr = rpl_get_nbr(p)) == NULL) {
    if(base_rank == 0) {
      return INFINITE_RANK;
    }
    rank_increase = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR;
  } else {
    rank_increase = nbr->link_metric;
    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;
}
Exemple #3
0
/*---------------------------------------------------------------------------*/
static void res_rpl_link_metric_get_handler(void *request, void *response,
  uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
  uint16_t length;
  rpl_instance_t *instance;
  uip_ds6_nbr_t *nbr;
  char message[REST_MAX_CHUNK_SIZE];

  memset(message, 0, REST_MAX_CHUNK_SIZE);
  instance = rpl_get_instance(RPL_DEFAULT_INSTANCE);
  /* Print the link metric to parent */
  if(instance != NULL &&
    instance->current_dag != NULL &&
    instance->current_dag->preferred_parent != NULL &&
     (nbr = rpl_get_nbr(instance->current_dag->preferred_parent)) != NULL) {
    snprintf(message, sizeof(message) - 1, "Link Metric: %u.%02u\n",
             nbr->link_metric / RPL_DAG_MC_ETX_DIVISOR,
             (100 * (nbr->link_metric % RPL_DAG_MC_ETX_DIVISOR)) / RPL_DAG_MC_ETX_DIVISOR);
  } else {
    snprintf(message, sizeof(message) - 1, "No link metric yet\n");
  }
  length = strlen(message);
  memcpy(buffer, message, length);

  REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
  REST.set_header_etag(response, (uint8_t *)&length, 1);
  REST.set_response_payload(response, buffer, length);
}
Exemple #4
0
uint16_t
create_parent_msg(char *buf,rpl_parent_t *parent, uint8_t preferred)
{
	uint8_t n = 0;
	uip_ds6_nbr_t *nbr;

	uip_ipaddr_t * addr = rpl_get_parent_ipaddr(parent);

	n += sprintf(&(buf[n]), "{\"eui\":\"%04x%04x%04x%04x\",",
					UIP_HTONS(addr->u16[4]),
					UIP_HTONS(addr->u16[5]),
					UIP_HTONS(addr->u16[6]),
					UIP_HTONS(addr->u16[7]));
	
	n += sprintf(&(buf[n]), "\"pref\":");

	if(preferred == 1)
	{
		n += sprintf(&(buf[n]), "true,");
	}else
	{
		n += sprintf(&(buf[n]), "false,");
	}

	nbr = rpl_get_nbr(parent); // Estimated Retransmission part (ETX) value

	n += sprintf(&(buf[n]), "\"etx\":%d}",nbr->link_metric);

	buf[n] = 0; // clear next buffer value
	PRINTF("buf: %s\n", buf); // print the buffer value
	return n;
}
Exemple #5
0
/* rpl_purge_parents is called with the periodic timer in rpl-timers.c */
void
rpl_purge_parents(void)
{
  rpl_parent_t *p;
  p = nbr_table_head(rpl_parents);
  while(p != NULL) {
    if(rpl_get_nbr(p) == NULL) {
      PRINTF("RPL: No NBR entry for parent - removing parent\n");
      rpl_remove_parent(p);
      /* continue with the removal next periodic tick */
      return;
    }
    p = nbr_table_next(rpl_parents, p);
  }
}
Exemple #6
0
static void
neighbor_link_callback(rpl_parent_t *p, int status, int numtx)
{
  uint16_t recorded_etx = 0;
  uint16_t packet_etx = numtx * RPL_DAG_MC_ETX_DIVISOR;
  uint16_t new_etx;
  uip_ds6_nbr_t *nbr = NULL;

  nbr = rpl_get_nbr(p);
  if(nbr == NULL) {
    /* No neighbor for this parent - something bad has occurred */
    return;
  }

  recorded_etx = nbr->link_metric;

  /* Do not penalize the ETX when collisions or transmission errors occur. */
  if(status == MAC_TX_OK || status == MAC_TX_NOACK) {
    if(status == MAC_TX_NOACK) {
      packet_etx = MAX_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR;
    }

    if(p->flags & RPL_PARENT_FLAG_LINK_METRIC_VALID) {
      /* We already have a valid link metric, use weighted moving average to update it */
      new_etx = ((uint32_t)recorded_etx * ETX_ALPHA +
                 (uint32_t)packet_etx * (ETX_SCALE - ETX_ALPHA)) / ETX_SCALE;
    } else {
      /* We don't have a valid link metric, set it to the current packet's ETX */
      new_etx = packet_etx;
      /* Set link metric as valid */
      p->flags |= RPL_PARENT_FLAG_LINK_METRIC_VALID;
    }

    PRINTF("RPL: ETX changed from %u to %u (packet ETX = %u)\n",
        (unsigned)(recorded_etx / RPL_DAG_MC_ETX_DIVISOR),
        (unsigned)(new_etx  / RPL_DAG_MC_ETX_DIVISOR),
        (unsigned)(packet_etx / RPL_DAG_MC_ETX_DIVISOR));
    /* update the link metric for this nbr */
    nbr->link_metric = new_etx;
  }
}
Exemple #7
0
/*---------------------------------------------------------------------------*/
rpl_parent_t *
rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr)
{
  rpl_parent_t *p = NULL;
  /* Is the parent known by ds6? Drop this request if not.
   * Typically, the parent is added upon receiving a DIO. */
  const uip_lladdr_t *lladdr = uip_ds6_nbr_lladdr_from_ipaddr(addr);

  PRINTF("RPL: rpl_add_parent lladdr %p ", lladdr);
  PRINTLLADDR(lladdr);
  PRINTF(" ");
  PRINT6ADDR(addr);
  PRINTF("\n");
  if(lladdr != NULL) {
    /* Add parent in rpl_parents */
    p = nbr_table_add_lladdr(rpl_parents, (linkaddr_t *)lladdr);
    if(p == NULL) {
      PRINTF("RPL: rpl_add_parent p NULL\n");
    } else {
      uip_ds6_nbr_t *nbr;
      nbr = rpl_get_nbr(p);

      p->dag = dag;
      p->rank = dio->rank;
      p->dtsn = dio->dtsn;

      /* Check whether we have a neighbor that has not gotten a link metric yet */
      if(nbr != NULL && nbr->link_metric == 0) {
	nbr->link_metric = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR;
      }
#if RPL_DAG_MC != RPL_DAG_MC_NONE
      memcpy(&p->mc, &dio->mc, sizeof(p->mc));
#endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */
    }
  }

  return p;
}
Exemple #8
0
static rpl_path_metric_t
calculate_path_metric(rpl_parent_t *p)
{
  uip_ds6_nbr_t *nbr;
  if(p == NULL) {
    return MAX_PATH_COST * RPL_DAG_MC_ETX_DIVISOR;
  }
  nbr = rpl_get_nbr(p);
  if(nbr == NULL) {
    return MAX_PATH_COST * RPL_DAG_MC_ETX_DIVISOR;
  }
#if RPL_DAG_MC == RPL_DAG_MC_NONE
  {
    return p->rank + (uint16_t)nbr->link_metric;
  }
#elif RPL_DAG_MC == RPL_DAG_MC_ETX
  return p->mc.obj.etx + (uint16_t)nbr->link_metric;
#elif RPL_DAG_MC == RPL_DAG_MC_ENERGY
  return p->mc.obj.energy.energy_est + (uint16_t)nbr->link_metric;
#else
#error "Unsupported RPL_DAG_MC configured. See rpl.h."
#endif /* RPL_DAG_MC */
}
Exemple #9
0
/*---------------------------------------------------------------------------*/
void
rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
{
  rpl_instance_t *instance;
  rpl_dag_t *dag, *previous_dag;
  rpl_parent_t *p;

#if RPL_CONF_MULTICAST
  /* If the root is advertising MOP 2 but we support MOP 3 we can still join
   * In that scenario, we suppress DAOs for multicast targets */
  if(dio->mop < RPL_MOP_STORING_NO_MULTICAST) {
#else
  if(dio->mop != RPL_MOP_DEFAULT) {
#endif
    PRINTF("RPL: Ignoring a DIO with an unsupported MOP: %d\n", dio->mop);
    return;
  }

  dag = get_dag(dio->instance_id, &dio->dag_id);
  instance = rpl_get_instance(dio->instance_id);

#if CETIC_6LBR
  if(!cetic_6lbr_dio_input_hook(from, instance, dag, dio)) {
    return;
  }
#endif

  if(dag != NULL && instance != NULL) {
    if(lollipop_greater_than(dio->version, dag->version)) {
      if(dag->rank == ROOT_RANK(instance)) {
	PRINTF("RPL: Root received inconsistent DIO version number\n");
	dag->version = dio->version;
	RPL_LOLLIPOP_INCREMENT(dag->version);
	rpl_reset_dio_timer(instance);
#if CETIC_6LBR
    nvm_data.rpl_version_id = dag->version;
    store_nvm_config();
#endif
      } else {
        PRINTF("RPL: Global repair\n");
        if(dio->prefix_info.length != 0) {
          if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
            PRINTF("RPL : Prefix announced in DIO\n");
            rpl_set_prefix(dag, &dio->prefix_info.prefix, dio->prefix_info.length);
          }
        }
	global_repair(from, dag, dio);
      }
      return;
    }

    if(lollipop_greater_than(dag->version, dio->version)) {
      /* The DIO sender is on an older version of the DAG. */
      PRINTF("RPL: old version received => inconsistency detected\n");
      if(dag->joined) {
        rpl_reset_dio_timer(instance);
        return;
      }
    }
  }

  if(instance == NULL) {
    PRINTF("RPL: New instance detected: Joining...\n");
    rpl_join_instance(from, dio);
    return;
  }

  if(instance->current_dag->rank == ROOT_RANK(instance) && instance->current_dag != dag) {
    PRINTF("RPL: Root ignored DIO for different DAG\n");
    return;
  }

  if(dag == NULL) {
#if RPL_MAX_DAG_PER_INSTANCE > 1
    PRINTF("RPL: Adding new DAG to known instance.\n");
    dag = rpl_add_dag(from, dio);
    if(dag == NULL) {
      PRINTF("RPL: Failed to add DAG.\n");
      return;
    }
#else /* RPL_MAX_DAG_PER_INSTANCE > 1 */
    PRINTF("RPL: Only one instance supported.\n");
    return;
#endif /* RPL_MAX_DAG_PER_INSTANCE > 1 */
  }


  if(dio->rank < ROOT_RANK(instance)) {
    PRINTF("RPL: Ignoring DIO with too low rank: %u\n",
           (unsigned)dio->rank);
    return;
  } else if(dio->rank == INFINITE_RANK && dag->joined) {
    rpl_reset_dio_timer(instance);
  }

  /* Prefix Information Option treated to add new prefix */
  if(dio->prefix_info.length != 0) {
    if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
      PRINTF("RPL : Prefix announced in DIO\n");
      rpl_set_prefix(dag, &dio->prefix_info.prefix, dio->prefix_info.length);
    }
  }

  if(dag->rank == ROOT_RANK(instance)) {
    if(dio->rank != INFINITE_RANK) {
      instance->dio_counter++;
    }
    return;
  }

  /* The DIO comes from a valid DAG, we can refresh its lifetime */
  dag->lifetime = (1UL << (instance->dio_intmin + instance->dio_intdoubl)) * RPL_DAG_LIFETIME / 1000;
  PRINTF("Set dag ");
  PRINT6ADDR(&dag->dag_id);
  PRINTF(" lifetime to %ld\n", dag->lifetime);

  /*
   * At this point, we know that this DIO pertains to a DAG that
   * we are already part of. We consider the sender of the DIO to be
   * a candidate parent, and let rpl_process_parent_event decide
   * whether to keep it in the set.
   */
  rpl_update_dag(instance, dag, dio);
  p = rpl_find_parent(dag, from);
  if(p == NULL) {
    previous_dag = find_parent_dag(instance, from);
    if(previous_dag == NULL) {
      /* Add the DIO sender as a candidate parent. */
      p = rpl_add_parent(dag, dio, from);
      if(p == NULL) {
        PRINTF("RPL: Failed to add a new parent (");
        PRINT6ADDR(from);
        PRINTF(")\n");
        return;
      }
      PRINTF("RPL: New candidate parent with rank %u: ", (unsigned)p->rank);
      PRINT6ADDR(from);
      PRINTF("\n");
    } else {
      p = rpl_find_parent(previous_dag, from);
      if(p != NULL) {
        rpl_move_parent(previous_dag, dag, p);
      }
    }
  } else {
    if(p->rank == dio->rank) {
      PRINTF("RPL: Received consistent DIO\n");
      if(dag->joined) {
        instance->dio_counter++;
      }
    }
  }
  p->rank = dio->rank;

  /* Parent info has been updated, trigger rank recalculation */
  p->flags |= RPL_PARENT_FLAG_UPDATED;

  PRINTF("RPL: preferred DAG ");
  PRINT6ADDR(&instance->current_dag->dag_id);
  PRINTF(", rank %u, min_rank %u, ",
	 instance->current_dag->rank, instance->current_dag->min_rank);
  PRINTF("parent rank %u, parent etx %u, link metric %u, instance etx %u\n",
	 p->rank, -1/*p->mc.obj.etx*/, rpl_get_nbr(p)->link_metric, instance->mc.obj.etx);

  /* We have allocated a candidate parent; process the DIO further. */

#if RPL_DAG_MC != RPL_DAG_MC_NONE
  memcpy(&p->mc, &dio->mc, sizeof(p->mc));
#endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */
  if(rpl_process_parent_event(instance, p) == 0) {
    PRINTF("RPL: The candidate parent is rejected\n");
    return;
  }

  /* We don't use route control, so we can have only one official parent. */
  if(dag->joined && p == dag->preferred_parent) {
    if(should_send_dao(instance, dio, p)) {
      RPL_LOLLIPOP_INCREMENT(instance->dtsn_out);
      rpl_schedule_dao(instance);
    }
    /* We received a new DIO from our preferred parent.
     * Call uip_ds6_defrt_add to set a fresh value for the lifetime counter */
    uip_ds6_defrt_add(from, RPL_DEFAULT_ROUTE_INFINITE_LIFETIME ? 0 : RPL_LIFETIME(instance, instance->default_lifetime));
  }
  p->dtsn = dio->dtsn;
}
Exemple #10
0
/*---------------------------------------------------------------------------*/
static void
res_rpl_info_get_handler(void *request, void *response, uint8_t *buffer,
  uint16_t preferred_size, int32_t *offset)
{
  /*Return RPL information in JSON format */
  uint16_t length = 0;
  rpl_instance_t *instance;
  uip_ds6_nbr_t *nbr;
  char message[REST_MAX_CHUNK_SIZE];
  memset(message, 0, sizeof(message));

  instance = rpl_get_instance(RPL_DEFAULT_INSTANCE);
  if(instance != NULL &&
     instance->current_dag != NULL &&
     instance->current_dag->preferred_parent != NULL) {
    nbr = rpl_get_nbr(instance->current_dag->preferred_parent);
  } else {
    nbr = NULL;
  }

  /* Write all RPL info in JSON format */
  snprintf(message, sizeof(message) - 1, "{\"parent\":\"");
  length = strlen(message);

  if(instance != NULL &&
    instance->current_dag != NULL &&
    instance->current_dag->preferred_parent != NULL) {
    sprint_addr6(&message[length],
                 rpl_get_parent_ipaddr(instance->current_dag->preferred_parent));
    length = strlen(message);
    snprintf(&message[length], sizeof(message) - length - 1, "\"");
  } else {
    snprintf(&message[length], sizeof(message) - length - 1, "None\"");
  }
  length = strlen(message);

  snprintf(&message[length], sizeof(message) - length - 1, " ,\"rank\":\"");
  length = strlen(message);

  if(instance != NULL && instance->current_dag != NULL) {
    snprintf(&message[length], sizeof(message) - length - 1, "%u.%02u\"",
             (instance->current_dag->rank / RPL_DAG_MC_ETX_DIVISOR),
             (100 * (instance->current_dag->rank % RPL_DAG_MC_ETX_DIVISOR)) / RPL_DAG_MC_ETX_DIVISOR);
  } else {
    snprintf(&message[length], sizeof(message) - length - 1, "inf\"");
  }
  length = strlen(message);

  snprintf(&message[length], sizeof(message) - length - 1, " ,\"link-metric\":\"");
  length = strlen(message);
  if(nbr != NULL) {
    snprintf(&message[length], sizeof(message) - length - 1, "%u.%02u\"",
             nbr->link_metric / RPL_DAG_MC_ETX_DIVISOR,
             (100 * (nbr->link_metric % RPL_DAG_MC_ETX_DIVISOR)) / RPL_DAG_MC_ETX_DIVISOR);
  } else {
    snprintf(&message[length], sizeof(message) - length - 1, "inf\"");
  }
  length = strlen(message);
  snprintf(&message[length], sizeof(message) - length - 1, "}");
  length = strlen(message);
  memcpy(buffer, message, length);

  REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
  REST.set_header_etag(response, (uint8_t *)&length, 1);
  REST.set_response_payload(response, buffer, length);
}