text: /**
   * \file
   *         Basado en los ejemplos simple-udp-rpl y rpl-tsch
   *         ambos en [CONTIKI_DIR]/examples/ipv6/.
   *
   * \author Remote Sync
   */
  
  #include "contiki.h"
  #include "node-id.h"
  #include "net/rpl/rpl.h"
  #include "net/ipv6/uip-ds6-route.h"
  #include "net/mac/tsch/tsch.h"
  #include "net/rpl/rpl-private.h"
  #include "core/sys/clock.h"
  #include "simple-udp.h"
  
  #include "sys/rtimer.h"
  #include "net/mac/tsch/tsch-asn.h"
  
  
  
  #define DEBUG DEBUG_PRINT
  #include "net/ip/uip-debug.h"
  
  #define UDP_PORT 1234
  
  rtimer_clock_t ti;
  struct tsch_asn_t ASync;
  static struct simple_udp_connection unicast_connection;
  /*---------------------------------------------------------------------------*/
  PROCESS(node_process, "RPL Node");
  AUTOSTART_PROCESSES(&node_process);
  
  /*---------------------------------------------------------------------------*/
  
  
  
  static void
  print_network_status(void)
  {
    int i;
    uint8_t state;
    uip_ds6_defrt_t *default_route;
  #if RPL_WITH_STORING
    uip_ds6_route_t *route;
  #endif /* RPL_WITH_STORING */
  #if RPL_WITH_NON_STORING
    rpl_ns_node_t *link;
  #endif /* RPL_WITH_NON_STORING */
  
    PRINTF("--- Network status ---\n");
  
    /* Our IPv6 addresses */
    PRINTF("- IPv6 addresses:\n");
    for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
      state = uip_ds6_if.addr_list[i].state;
      if(uip_ds6_if.addr_list[i].isused &&
         (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) {
        PRINTF("-- ");
        PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr);
        PRINTF("\n");
      }
    }
  
    /* Our default route */
    PRINTF("- Default route:\n");
    default_route = uip_ds6_defrt_lookup(uip_ds6_defrt_choose());
    if(default_route != NULL) {
      PRINTF("-- ");
      PRINT6ADDR(&default_route->ipaddr);
      PRINTF(" (lifetime: %lu seconds)\n", (unsigned long)default_route->lifetime.interval);
    } else {
      PRINTF("-- None\n");
    }
  
  #if RPL_WITH_STORING
    /* Our routing entries */
    PRINTF("- Routing entries (%u in total):\n", uip_ds6_route_num_routes());
    route = uip_ds6_route_head();
    while(route != NULL) {
      PRINTF("-- ");
      PRINT6ADDR(&route->ipaddr);
      PRINTF(" via ");
      PRINT6ADDR(uip_ds6_route_nexthop(route));
      PRINTF(" (lifetime: %lu seconds)\n", (unsigned long)route->state.lifetime);
      route = uip_ds6_route_next(route);
    }
  #endif
  
  #if RPL_WITH_NON_STORING
    /* Our routing links */
    PRINTF("- Routing links (%u in total):\n", rpl_ns_num_nodes());
    link = rpl_ns_node_head();
    while(link != NULL) {
      uip_ipaddr_t child_ipaddr;
      uip_ipaddr_t parent_ipaddr;
      rpl_ns_get_node_global_addr(&child_ipaddr, link);
      rpl_ns_get_node_global_addr(&parent_ipaddr, link->parent);
      PRINTF("-- ");
      PRINT6ADDR(&child_ipaddr);
      if(link->parent == NULL) {
        memset(&parent_ipaddr, 0, sizeof(parent_ipaddr));
        PRINTF(" --- DODAG root ");
      } else {
        PRINTF(" to ");
        PRINT6ADDR(&parent_ipaddr);
      }
      PRINTF(" (lifetime: %lu seconds)\n", (unsigned long)link->lifetime);
      link = rpl_ns_node_next(link);
    }
  #endif
  
    PRINTF("----------------------\n");
  }
  /*---------------------------------------------------------------------------*/
  static void
  net_init(uip_ipaddr_t *br_prefix)
  {
    uip_ipaddr_t global_ipaddr;
  
    if(br_prefix) { /* We are RPL root. Will be set automatically
                       as TSCH pan coordinator via the tsch-rpl module */
      memcpy(&global_ipaddr, br_prefix, 16);
      uip_ds6_set_addr_iid(&global_ipaddr, &uip_lladdr);
      uip_ds6_addr_add(&global_ipaddr, 0, ADDR_AUTOCONF);
      rpl_set_root(RPL_DEFAULT_INSTANCE, &global_ipaddr);
      rpl_set_prefix(rpl_get_any_dag(), br_prefix, 64);
      rpl_repair_root(RPL_DEFAULT_INSTANCE);
    }
  
    NETSTACK_MAC.on();
  }
  /*---------------------------------------------------------------------------*/
  static void
  receiver(struct simple_udp_connection *c,
           const uip_ipaddr_t *sender_addr,
           uint16_t sender_port,
           const uip_ipaddr_t *receiver_addr,
           uint16_t receiver_port,
           const uint8_t *data,
           uint16_t datalen)
  {
    printf("Data received from ");
    uip_debug_ipaddr_print(sender_addr);
    printf(" on port %d from port %d with length %d: '%s'\n",
           receiver_port, sender_port, datalen, data);
  }
  /*---------------------------------------------------------------------------*/
  static uip_ipaddr_t *
  set_global_address(void)
  {
    static uip_ipaddr_t ipaddr;
    int i;
    uint8_t state;
  
    uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
    uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
    uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
  
    printf("IPv6 addresses: ");
    for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
      state = uip_ds6_if.addr_list[i].state;
      if(uip_ds6_if.addr_list[i].isused &&
         (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) {
        uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr);
        printf("\n");
      }
    }
  
    return &ipaddr;
  }
  /*---------------------------------------------------------------------------*/
  static void
  create_rpl_dag(uip_ipaddr_t *ipaddr)
  {
    struct uip_ds6_addr *root_if;
  
    root_if = uip_ds6_addr_lookup(ipaddr);
    if(root_if != NULL) {
      rpl_dag_t *dag;
      uip_ipaddr_t prefix;
      
      rpl_set_root(RPL_DEFAULT_INSTANCE, ipaddr);
      dag = rpl_get_any_dag();
      uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
      rpl_set_prefix(dag, &prefix, 64);
      PRINTF("created a new RPL dag\n");
    } else {
      PRINTF("failed to create a new RPL DAG\n");
    }
  }
  /*---------------------------------------------------------------------------*/
  PROCESS_THREAD(node_process, ev, data)
  {
    static struct etimer print_timer;
    uip_ipaddr_t *ipaddr;
  
    PROCESS_BEGIN();
  
    ipaddr = set_global_address();
  
    create_rpl_dag(ipaddr);
  
    simple_udp_register(&unicast_connection, UDP_PORT, NULL, UDP_PORT, receiver);
  
  
    /* 2 possible TSCH roles:
     * - role_6dr: DAG root, will advertise (unsecured) beacons
     * - role_6dr_sec: DAG root, will advertise secured beacons
     */
  
    static enum { role_6ln, role_6dr, role_6dr_sec } node_role;
  
    if(LLSEC802154_ENABLED) {
      node_role = role_6dr_sec;
    } else {
      node_role = role_6dr;
    }
  
    printf("Init: node starting with role %s\n",
           node_role == role_6ln ? "6ln" : (node_role == role_6dr) ? "6dr" : "6dr-sec");
  
    tsch_set_pan_secured(LLSEC802154_ENABLED);
  
    uip_ipaddr_t prefix;
    uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
    net_init(&prefix);
  
  
    /* Print out routing tables every minute */
    etimer_set(&print_timer, CLOCK_SECOND * 60);
  
    while(1) {
      PROCESS_WAIT_EVENT();
      if(etimer_expired(&print_timer)) {
        print_network_status();
        etimer_reset(&print_timer);
      }
    }
  
    PROCESS_END();
  }
  /*---------------------------------------------------------------------------*/
  