Beispiel #1
0
/*---------------------------------------------------------------------------*/
void
rpl_nullify_parent(rpl_parent_t *parent)
{
  rpl_dag_t *dag = parent->dag;
  /* This function can be called when the preferred parent is NULL, so we
     need to handle this condition in order to trigger uip_ds6_defrt_rm. */
  if(parent == dag->preferred_parent || dag->preferred_parent == NULL) {
    dag->rank = INFINITE_RANK;
    if(dag->joined) {
      if(dag->instance->def_route != NULL) {
        PRINTF("RPL: Removing default route ");
        PRINT6ADDR(rpl_get_parent_ipaddr(parent));
        PRINTF("\n");
        uip_ds6_defrt_rm(dag->instance->def_route);
        dag->instance->def_route = NULL;
      }
      /* Send No-Path DAO only to preferred parent, if any */
      if(parent == dag->preferred_parent) {
        dao_output(parent, RPL_ZERO_LIFETIME);
        rpl_set_preferred_parent(dag, NULL);
      }
    }
  }

  PRINTF("RPL: Nullifying parent ");
  PRINT6ADDR(rpl_get_parent_ipaddr(parent));
  PRINTF("\n");
}
Beispiel #2
0
/*---------------------------------------------------------------------------*/
static void
handle_dao_timer(void *ptr)
{
  rpl_instance_t *instance;

  instance = (rpl_instance_t *)ptr;

  if(!dio_send_ok && uip_ds6_get_link_local(ADDR_PREFERRED) == NULL) {
    PRINTF("RPL: Postpone DAO transmission\n");
    ctimer_set(&instance->dao_timer, CLOCK_SECOND, handle_dao_timer, instance);
    return;
  }

  /* Send the DAO to the DAO parent set -- the preferred parent in our case. */
  if(instance->current_dag->preferred_parent != NULL) {
    PRINTF("RPL: handle_dao_timer - sending DAO\n");
    /* Set the route lifetime to the default value. */
    dao_output(instance->current_dag->preferred_parent, instance->default_lifetime);
  } else {
    PRINTF("RPL: No suitable DAO parent\n");
  }

  ctimer_stop(&instance->dao_timer);

  if(etimer_expired(&instance->dao_lifetime_timer.etimer)) {
    set_dao_lifetime_timer(instance);
  }
}
Beispiel #3
0
/*---------------------------------------------------------------------------*/
static void
handle_dao_timer(struct net_buf *not_used, void *ptr)
{
  rpl_instance_t *instance;
#if RPL_CONF_MULTICAST
  uip_mcast6_route_t *mcast_route;
  uint8_t i;
#endif

  instance = (rpl_instance_t *)ptr;

  if(!dio_send_ok && uip_ds6_get_link_local(ADDR_PREFERRED) == NULL) {
    PRINTF("RPL: Postpone DAO transmission\n");
    ctimer_set(NULL, &instance->dao_timer, CLOCK_SECOND, handle_dao_timer, instance);
    return;
  }

  /* Send the DAO to the DAO parent set -- the preferred parent in our case. */
  if(instance->current_dag->preferred_parent != NULL) {
    PRINTF("RPL: handle_dao_timer - sending DAO\n");
    /* Set the route lifetime to the default value. */
    dao_output(instance->current_dag->preferred_parent,
	       instance->default_lifetime);

#if RPL_CONF_MULTICAST
    /* Send DAOs for multicast prefixes only if the instance is in MOP 3 */
    if(instance->mop == RPL_MOP_STORING_MULTICAST) {
      /* Send a DAO for own multicast addresses */
      for(i = 0; i < UIP_DS6_MADDR_NB; i++) {
        if(uip_ds6_if.maddr_list[i].isused
            && uip_is_addr_mcast_global(&uip_ds6_if.maddr_list[i].ipaddr)) {
          dao_output_target(instance->current_dag->preferred_parent,
			    &uip_ds6_if.maddr_list[i].ipaddr,
			    RPL_MCAST_LIFETIME);
        }
      }

      /* Iterate over multicast routes and send DAOs */
      mcast_route = uip_mcast6_route_list_head();
      while(mcast_route != NULL) {
        /* Don't send if it's also our own address, done that already */
        if(uip_ds6_maddr_lookup(&mcast_route->group) == NULL) {
          dao_output_target(instance->current_dag->preferred_parent,
			    &mcast_route->group, RPL_MCAST_LIFETIME);
        }
        mcast_route = list_item_next(mcast_route);
      }
    }
#endif
  } else {
    PRINTF("RPL: No suitable DAO parent\n");
  }

  ctimer_stop(&instance->dao_timer);

  if(etimer_expired(&instance->dao_lifetime_timer.etimer)) {
    set_dao_lifetime_timer(instance);
  }
}
Beispiel #4
0
static void
handle_dao_timer(void *ptr)
{
  rpl_instance_t *instance;

  instance = (rpl_instance_t *)ptr;

  if(!dio_send_ok && uip_ds6_get_link_local(ADDR_PREFERRED) == NULL) {
    PRINTF("RPL: Postpone DAO transmission\n");
    ctimer_set(&instance->dao_timer, CLOCK_SECOND, handle_dao_timer, instance);
    return;
  }

  /* Send the DAO to the DAO parent set -- the preferred parent in our case. */
  if(instance->current_dag->preferred_parent != NULL) {
    PRINTF("RPL: handle_dao_timer - sending DAO\n");
    /* Set the route lifetime to the default value. */
    dao_output(instance->current_dag->preferred_parent, instance->default_lifetime, NULL);
#if UIP_IPV6_MULTICAST_RPL
    if(instance->mop == RPL_MOP_STORING_MULTICAST) {
      /* Send a DAO for own multicast addresses */
      for(i = 0; i < UIP_DS6_MADDR_NB; i++) {
        if(uip_ds6_if.maddr_list[i].isused
            && uip_is_addr_mcast_global(&uip_ds6_if.maddr_list[i].ipaddr)) {
          dao_output(instance->current_dag->preferred_parent, RPL_MCAST_LIFETIME,
              &uip_ds6_if.maddr_list[i].ipaddr);
        }
      }
      /* Iterate multicast routes and send DAOs */
      for(i = 0; i < UIP_DS6_MCAST_ROUTES; i++) {
        /* Don't send if it's also our own address, done that already */
        if(uip_ds6_mcast_table[i].isused) {
          if(uip_ds6_maddr_lookup(&uip_ds6_mcast_table[i].group) == NULL) {
            dao_output(instance->current_dag->preferred_parent, RPL_MCAST_LIFETIME,
                &uip_ds6_mcast_table[i].group);
          }
        }
      }
    }
#endif
  } else {
    PRINTF("RPL: No suitable DAO parent\n");
  }
  ctimer_stop(&instance->dao_timer);
}
Beispiel #5
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) {
    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. */
    dao_output(p, ZERO_LIFETIME);

    remove_parents(dag, 0);
    return NULL;
  }

  return best;
}
ConnectionState PicoIPv6StateSendingDAOState::connect(){
        if (dodag_instance_id != -1){
          if (currentState == DIO_RECEIVED){
            dao_output(gateway_ip_address, RPL_DEFAULT_LIFETIME, dodag_instance_id);
            delay(200);
            currentState = WAITING_DAO_ACK;
            timer_set(&wait_dao_ack_timer, timeout);
          }
          if (currentState == WAITING_DAO_ACK && !timer_expired(&wait_dao_ack_timer)){
            if (receive_DAO_ACK()){
              currentState = DAO_ACK_RECEIVED;
            }
          }
        }else{
          //dodag_instance_id not valid! we should remain disconnected
          PRINTF("NOT VALID INSTANCE ID! Changing state to DISCONNECTED");
          currentState = DISCONNECTED;
        }
        return currentState;
}
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. */
    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;
}
Beispiel #8
0
/*---------------------------------------------------------------------------*/
enum rpl_mode
rpl_set_mode(enum rpl_mode m)
{
  enum rpl_mode oldmode = mode;

  /* We need to do different things depending on what mode we are
     switching to. */
  if(m == RPL_MODE_MESH) {

    /* If we switch to mesh mode, we should send out a DAO message to
       inform our parent that we now are reachable. Before we do this,
       we must set the mode variable, since DAOs will not be sent if
       we are in feather mode. */
    PRINTF("RPL: switching to mesh mode\n");
    mode = m;

    if(default_instance != NULL) {
      rpl_schedule_dao_immediately(default_instance);
    }
  } else if(m == RPL_MODE_FEATHER) {

    PRINTF("RPL: switching to feather mode\n");
    if(default_instance != NULL) {
      PRINTF("rpl_set_mode: RPL sending DAO with zero lifetime\n");
      if(default_instance->current_dag != NULL) {
        dao_output(default_instance->current_dag->preferred_parent, RPL_ZERO_LIFETIME);
      }
      rpl_cancel_dao(default_instance);
    } else {
      PRINTF("rpl_set_mode: no default instance\n");
    }

    mode = m;
  } else {
    mode = m;
  }

  return oldmode;
}
Beispiel #9
0
/*---------------------------------------------------------------------------*/
void
rpl_nullify_parent(rpl_dag_t *dag, rpl_parent_t *parent)
{
  if(parent == dag->preferred_parent) {
    dag->preferred_parent = NULL;
    dag->rank = INFINITE_RANK;
    if(dag->joined) {
      if(dag->instance->def_route != NULL) {
	PRINTF("RPL: Removing default route ");
	PRINT6ADDR(&parent->addr);
	PRINTF("\n");
	uip_ds6_defrt_rm(dag->instance->def_route);
        dag->instance->def_route = NULL;
      }
      dao_output(parent, RPL_ZERO_LIFETIME);
    }
  }

  PRINTF("RPL: Nullifying parent ");
  PRINT6ADDR(&parent->addr);
  PRINTF("\n");
}
static void
handle_dao_timer(void *ptr)
{
  rpl_dag_t *dag;

  dag = (rpl_dag_t *)ptr;

  if (!dio_send_ok && uip_ds6_get_link_local(ADDR_PREFERRED) == NULL) {
    PRINTF("RPL: Postpone DAO transmission... ");
    ctimer_set(&dag->dao_timer, CLOCK_SECOND, handle_dao_timer, dag);
    return;
  }

  /* Send the DAO to the DAO parent set -- the preferred parent in our case. */
  if(dag->preferred_parent != NULL) {
    PRINTF("RPL: handle_dao_timer - sending DAO");
    /* Set the route lifetime to the default value. */
    dao_output(dag->preferred_parent, dag->default_lifetime);
  } else {
    PRINTF("RPL: No suitable DAO parent");
  }
  ctimer_stop(&dag->dao_timer);
}
bool PicoIPv6StateSendingDAOState::receive_DAO_ACK(){

	if (receive_mac() == RECEIVED){ //GOT SOMETHING AT MAC LEVEL
        PRINTF("RECEIVED AT MAC LEVEL");

        if (receive_ipv6() != NOT_EXPECTED_OR_ERROR){ //IF WE RECEIVED SOMETHING THAT WE COULD EXPECT, SEE IF IT IS A DIO
          PRINTF("RECEIVED SOMETHING EXPECTED");

          if (lastReceived == DAO_ACK){
            PRINTF("RECEIVED DAO ACK!");
            return true;
          }else{
				if (this->lastReceived == NS){
					//if we are expecting a DAO ACK but we receive an NS, this means that the GW is performing ND with us so we have just sent a NA as response.
					//This means also that if the GW received the NA successfully, it will be able to respond our DAO with a DAO ACK this time, so send a new DAO!
					dao_output(this->gateway_ip_address, RPL_DEFAULT_LIFETIME, this->dodag_instance_id);
					return false; //Because we did not yet receive the DAO ACK
				}
			}
        }
      }
      return false;
}
Beispiel #12
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;
}