Esempio n. 1
0
/*---------------------------------------------------------------------------*/
int
rpl_repair_root(uint8_t instance_id)
{
  rpl_instance_t *instance;

  instance = rpl_get_instance(instance_id);
  if(instance == NULL ||
     instance->current_dag->rank != ROOT_RANK(instance)) {
    PRINTF("RPL: rpl_repair_root triggered but not root\n");
    return 0;
  }
  RPL_STAT(rpl_stats.root_repairs++);

  RPL_LOLLIPOP_INCREMENT(instance->current_dag->version);
  RPL_LOLLIPOP_INCREMENT(instance->dtsn_out);
#if CETIC_6LBR
  nvm_data.rpl_version_id = instance->current_dag->version;
  store_nvm_config();
#endif
  PRINTF("RPL: rpl_repair_root initiating global repair with version %d\n", instance->current_dag->version);
  rpl_reset_dio_timer(instance);
  return 1;
}
Esempio n. 2
0
/*---------------------------------------------------------------------------*/
rpl_dag_t *
rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id)
{
  rpl_dag_t *dag;
  rpl_instance_t *instance;
  uint8_t version;
  int i;

#if CETIC_6LBR
  version = nvm_data.rpl_version_id;
  RPL_LOLLIPOP_INCREMENT(version);
  nvm_data.rpl_version_id = version;
  store_nvm_config();
#else
  version = RPL_LOLLIPOP_INIT;
#endif
  instance = rpl_get_instance(instance_id);
  if(instance != NULL) {
    for(i = 0; i < RPL_MAX_DAG_PER_INSTANCE; ++i) {
      dag = &instance->dag_table[i];
      if(dag->used) {
        if(uip_ipaddr_cmp(&dag->dag_id, dag_id)) {
          version = dag->version;
          RPL_LOLLIPOP_INCREMENT(version);
#if CETIC_6LBR
          nvm_data.rpl_version_id = version;
          store_nvm_config();
#endif
        }
        if(dag == dag->instance->current_dag) {
          PRINTF("RPL: Dropping a joined DAG when setting this node as root");
          rpl_set_default_route(instance, NULL);
          dag->instance->current_dag = NULL;
        } else {
          PRINTF("RPL: Dropping a DAG when setting this node as root");
        }
        rpl_free_dag(dag);
      }
    }
  }

  dag = rpl_alloc_dag(instance_id, dag_id);
  if(dag == NULL) {
    PRINTF("RPL: Failed to allocate a DAG\n");
    return NULL;
  }

  instance = dag->instance;

  dag->version = version;
  dag->joined = 1;
  dag->grounded = RPL_GROUNDED;
  dag->preference = RPL_PREFERENCE;
  instance->mop = RPL_MOP_DEFAULT;
  instance->of = &RPL_OF;
  rpl_set_preferred_parent(dag, NULL);

  memcpy(&dag->dag_id, dag_id, sizeof(dag->dag_id));

  instance->dio_intdoubl = RPL_DIO_INTERVAL_DOUBLINGS;
  instance->dio_intmin = RPL_DIO_INTERVAL_MIN;
  /* The current interval must differ from the minimum interval in order to
     trigger a DIO timer reset. */
  instance->dio_intcurrent = RPL_DIO_INTERVAL_MIN +
    RPL_DIO_INTERVAL_DOUBLINGS;
  instance->dio_redundancy = RPL_DIO_REDUNDANCY;
  instance->max_rankinc = RPL_MAX_RANKINC;
  instance->min_hoprankinc = RPL_MIN_HOPRANKINC;
  instance->default_lifetime = RPL_DEFAULT_LIFETIME;
  instance->lifetime_unit = RPL_DEFAULT_LIFETIME_UNIT;

  dag->rank = ROOT_RANK(instance);

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

    instance->current_dag->joined = 0;
  }

  instance->current_dag = dag;
  instance->dtsn_out = RPL_LOLLIPOP_INIT;
  instance->of->update_metric_container(instance);
  default_instance = instance;

  PRINTF("RPL: Node set to be a DAG root with DAG ID ");
  PRINT6ADDR(&dag->dag_id);
  PRINTF("\n");

  ANNOTATE("#A root=%u\n", dag->dag_id.u8[sizeof(dag->dag_id) - 1]);

  rpl_reset_dio_timer(instance);

  return dag;
}
Esempio n. 3
0
static int
update_config(const char *name, uint8_t *reboot_needed)
{
  const char *ptr = name;
  char *next;
  uint8_t do_update = 1;
  uip_ipaddr_t loc_fipaddr;
#if CETIC_6LBR_IP64
  uip_ip4addr_t loc_fip4addr;
#endif

  *reboot_needed = 0;

  while(*ptr) {
    const char *param = ptr;

    next = index(ptr, '=');
    if(!next)
      break;
    *next = 0;
    ptr = next + 1;
    const char *value = ptr;

    next = index(ptr, '&');
    if(next) {
      *next = 0;
      ptr = next + 1;
    } else {
      ptr += strlen(ptr);
    }

    LOG6LBR_DEBUG("Got param: '%s' = '%s'\n", param, value);
    if (0) {
    }
    UPDATE_FLAG("smart_multi", mode, CETIC_MODE_SMART_MULTI_BR, 1)
    UPDATE_FLAG("wait_ra", mode, CETIC_MODE_WAIT_RA_MASK, 1)
    UPDATE_INT("channel", channel, 1)
    UPDATE_HEX("panid", pan_id, 1)
#if CETIC_6LBR_MAC_WRAPPER
    UPDATE_INT("mac", mac_layer, 1)
#endif
    UPDATE_INT("llsec", security_layer, 1)
    UPDATE_INT("llsec_level", security_level, 1)
    UPDATE_KEY("psk", noncoresec_key, 16, 1)
    UPDATE_FLAG( "sec_dis_ar", noncoresec_flags, CETIC_6LBR_NONCORESEC_DISABLE_ANTIREPLAY, 1)
    UPDATE_FLAG( "sec_ar_wa", noncoresec_flags, CETIC_6LBR_NONCORESEC_ANTIREPLAY_WORKAROUND, 1)
    UPDATE_IPADDR("wsn_pre", wsn_net_prefix, 1)
    UPDATE_INT("wsn_pre_len", wsn_net_prefix_len, 1)
    UPDATE_IPADDR("wsn_context_0", wsn_6lowpan_context_0, 1)
    UPDATE_FLAG("wsn_auto", mode, CETIC_MODE_WSN_AUTOCONF, 1)
    UPDATE_IPADDR("wsn_addr", wsn_ip_addr, 1)
    UPDATE_IPADDR("dns", dns_server, 1)
    UPDATE_IPADDR("eth_pre", eth_net_prefix, 1)
    UPDATE_INT("eth_pre_len", eth_net_prefix_len, 1)
    UPDATE_FLAG("eth_auto", mode, CETIC_MODE_ETH_AUTOCONF, 1)
    UPDATE_IPADDR("eth_addr", eth_ip_addr, 1)
    UPDATE_IPADDR("eth_dft", eth_dft_router, 1)
    UPDATE_FLAG("ra_daemon", mode, CETIC_MODE_ROUTER_RA_DAEMON, 1)
    UPDATE_FLAG("rewrite", mode, CETIC_MODE_REWRITE_ADDR_MASK, 1)
#if CETIC_6LBR_IP64
    UPDATE_FLAG("ip64", global_flags, CETIC_GLOBAL_IP64, 1)
    UPDATE_FLAG("ip64_dhcp", eth_ip64_flags, CETIC_6LBR_IP64_DHCP, 1)
    UPDATE_IP4ADDR("ip64_addr", eth_ip64_addr, 1)
    UPDATE_IP4ADDR("ip64_netmask", eth_ip64_netmask, 1)
    UPDATE_IP4ADDR("ip64_gateway", eth_ip64_gateway, 1)
    UPDATE_FLAG("ip64_port_map", eth_ip64_flags, CETIC_6LBR_IP64_SPECIAL_PORTS, 1)
    UPDATE_FLAG("ip64_6052", eth_ip64_flags, CETIC_6LBR_IP64_RFC6052_PREFIX, 1)
#endif
#if RESOLV_CONF_SUPPORTS_MDNS
    UPDATE_FLAG("mdns", global_flags, CETIC_GLOBAL_MDNS, 1)
    UPDATE_STRING("hostname", dns_host_name, NVM_DATA_DNS_HOST_NAME_SIZE, 1)
#if RESOLV_CONF_SUPPORTS_DNS_SD
    UPDATE_FLAG("dns_sd", dns_flags, CETIC_6LBR_DNS_DNS_SD, 1)
#endif
#endif
#if CETIC_NODE_CONFIG
    UPDATE_FLAG("nc_filter", global_flags, CETIC_GLOBAL_FILTER_NODES, 1)
#endif
    UPDATE_INT( "ra_lifetime", ra_router_lifetime, 1)
    UPDATE_INT( "ra_max_interval", ra_max_interval, 1)
    UPDATE_INT( "ra_min_interval", ra_min_interval, 1)
    UPDATE_INT( "ra_min_delay", ra_min_delay, 1)

    UPDATE_FLAG( "ra_pio", ra_prefix_flags, CETIC_6LBR_MODE_SEND_PIO, 1)
    UPDATE_FLAG( "ra_prefix_o", ra_prefix_flags, UIP_ND6_RA_FLAG_ONLINK, 1)
    UPDATE_FLAG( "ra_prefix_a", ra_prefix_flags, UIP_ND6_RA_FLAG_AUTONOMOUS, 1)
    UPDATE_INT( "ra_prefix_vtime", ra_prefix_vtime, 1)
    UPDATE_INT( "ra_prefix_ptime", ra_prefix_ptime, 1)

    UPDATE_FLAG( "ra_rio_en", ra_rio_flags, CETIC_6LBR_MODE_SEND_RIO, 1)
    UPDATE_INT( "ra_rio_lifetime", ra_rio_lifetime, 1)

    UPDATE_INT( "rpl_instance_id", rpl_instance_id, 1)
    UPDATE_FLAG("dodag_manual", rpl_config, CETIC_6LBR_MODE_MANUAL_DODAG, 1)
    UPDATE_FLAG("dodag_global", rpl_config, CETIC_6LBR_MODE_GLOBAL_DODAG, 1)
    UPDATE_IPADDR("dodag_id", rpl_dodag_id, 1)
    UPDATE_INT( "rpl_preference", rpl_preference, 1)
    UPDATE_INT( "rpl_dio_intdoubl", rpl_dio_intdoubl, 1)
    UPDATE_INT( "rpl_dio_intmin", rpl_dio_intmin, 1)
    UPDATE_INT( "rpl_dio_redundancy", rpl_dio_redundancy, 1)
    UPDATE_INT( "rpl_default_lifetime", rpl_default_lifetime, 1)
    UPDATE_INT( "rpl_min_hoprankinc", rpl_min_hoprankinc, 1)
    UPDATE_INT( "rpl_max_rankinc", rpl_max_rankinc, 1)
    UPDATE_INT( "rpl_lifetime_unit", rpl_lifetime_unit, 1)

#if !LOG6LBR_STATIC
    UPDATE_INT( "log_level", log_level, 0)
    UPDATE_HEX( "log_services", log_services, 0)
#endif
    else {
      LOG6LBR_WARN("Unknown parameter '%s'\n", param);
      do_update=0;
    }
  }
  if(do_update) {
    store_nvm_config();
#if !LOG6LBR_STATIC
    if(nvm_data.log_level != 0xFF) {
      Log6lbr_level = nvm_data.log_level;
      Log6lbr_services = nvm_data.log_services;
    }
#endif
  }
  return do_update;
}
Esempio n. 4
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;
}
Esempio n. 5
0
int
update_config(const char *name)
{
  const char *ptr = name;
  char *next;
  uint8_t reboot_needed = 0;
  uint8_t do_update = 1;
  uip_ipaddr_t loc_fipaddr;

  while(*ptr) {
    const char *param = ptr;

    next = index(ptr, '=');
    if(!next)
      break;
    *next = 0;
    ptr = next + 1;
    const char *value = ptr;

    next = index(ptr, '&');
    if(next) {
      *next = 0;
      ptr = next + 1;
    } else {
      ptr += strlen(ptr);
    }

    LOG6LBR_INFO("Got param: '%s' = '%s'\n", param, value);
    if (0) {
    }
    UPDATE_FLAG("smart_multi", mode, CETIC_MODE_SMART_MULTI_BR, 1)
    UPDATE_FLAG("wait_ra", mode, CETIC_MODE_WAIT_RA_MASK, 1)
    UPDATE_INT("channel", channel, 1)
    UPDATE_IPADDR("wsn_pre", wsn_net_prefix, 1)
    UPDATE_INT("wsn_pre_len", wsn_net_prefix_len, 1)
    UPDATE_FLAG("wsn_auto", mode, CETIC_MODE_WSN_AUTOCONF, 1)
    UPDATE_IPADDR("wsn_addr", wsn_ip_addr, 1)
    UPDATE_IPADDR("eth_pre", eth_net_prefix, 1)
    UPDATE_INT("eth_pre_len", eth_net_prefix_len, 1)
    UPDATE_FLAG("eth_auto", mode, CETIC_MODE_ETH_AUTOCONF, 1)
    UPDATE_IPADDR("eth_addr", eth_ip_addr, 1)
    UPDATE_IPADDR("eth_dft", eth_dft_router, 1)
    UPDATE_FLAG("ra_daemon", mode, CETIC_MODE_ROUTER_RA_DAEMON, 1)
    UPDATE_FLAG("rewrite", mode, CETIC_MODE_REWRITE_ADDR_MASK, 1)

    UPDATE_INT( "ra_lifetime", ra_router_lifetime, 1)
    UPDATE_INT( "ra_max_interval", ra_max_interval, 1)
    UPDATE_INT( "ra_min_interval", ra_min_interval, 1)
    UPDATE_INT( "ra_min_delay", ra_min_delay, 1)

    UPDATE_FLAG( "ra_pio", ra_prefix_flags, CETIC_6LBR_MODE_SEND_PIO, 1)
    UPDATE_FLAG( "ra_prefix_o", ra_prefix_flags, UIP_ND6_RA_FLAG_ONLINK, 1)
    UPDATE_FLAG( "ra_prefix_a", ra_prefix_flags, UIP_ND6_RA_FLAG_AUTONOMOUS, 1)
    UPDATE_INT( "ra_prefix_vtime", ra_prefix_vtime, 1)
    UPDATE_INT( "ra_prefix_ptime", ra_prefix_ptime, 1)

    UPDATE_FLAG( "ra_rio_en", ra_rio_flags, CETIC_6LBR_MODE_SEND_RIO, 1)
    UPDATE_INT( "ra_rio_lifetime", ra_rio_lifetime, 1)

    UPDATE_INT( "rpl_instance_id", rpl_instance_id, 1)
    UPDATE_INT( "rpl_preference", rpl_preference, 1)
    UPDATE_INT( "rpl_dio_intdoubl", rpl_dio_intdoubl, 1)
    UPDATE_INT( "rpl_dio_intmin", rpl_dio_intmin, 1)
    UPDATE_INT( "rpl_dio_redundancy", rpl_dio_redundancy, 1)
    UPDATE_INT( "rpl_default_lifetime", rpl_default_lifetime, 1)
    UPDATE_INT( "rpl_min_hoprankinc", rpl_min_hoprankinc, 1)
    UPDATE_INT( "rpl_lifetime_unit", rpl_lifetime_unit, 1)

    else {
      LOG6LBR_WARN("Unknown parameter '%s'\n", param);
      do_update=0;
    }
  }
  if(do_update) {
    store_nvm_config();
  }
  return !reboot_needed;
}