예제 #1
0
/*---------------------------------------------------------------------------*/
static rpl_parent_t *
find_parent_any_dag_any_instance(uip_ipaddr_t *addr)
{
  uip_ds6_nbr_t *ds6_nbr = uip_ds6_nbr_lookup(addr);
  const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(ds6_nbr);
  return nbr_table_get_from_lladdr(rpl_parents, (linkaddr_t *)lladdr);
}
예제 #2
0
파일: rpl-dag.c 프로젝트: Johnyren/orpl
/*---------------------------------------------------------------------------*/
void
rpl_set_parent_bc_ackcount(uip_lladdr_t *addr, uint16_t bc_ackcount)
{
  rpl_parent_t *p = nbr_table_get_from_lladdr(rpl_parents, (rimeaddr_t *)addr);
  if(p != NULL) {
    p->bc_ackcount = bc_ackcount;
  }
}
예제 #3
0
파일: rpl-dag.c 프로젝트: Johnyren/orpl
/*---------------------------------------------------------------------------*/
void
rpl_set_parent_rank(uip_lladdr_t *addr, rpl_rank_t rank)
{
  rpl_parent_t *p = nbr_table_get_from_lladdr(rpl_parents, (rimeaddr_t *)addr);
  if(p != NULL) {
    p->rank = rank;
  }
}
예제 #4
0
/*---------------------------------------------------------------------------*/
void
phase_update(const linkaddr_t *neighbor, rtimer_clock_t time, uint32_t cycle_time,
             int mac_status)
{
  struct phase *e;

  /* If we have an entry for this neighbor already, we renew it. */
  e = nbr_table_get_from_lladdr(nbr_phase, neighbor);
  if(e != NULL) {
    if(mac_status == MAC_TX_OK) {
#if PHASE_DRIFT_CORRECT
      e->drift = time-e->time;
#endif
      e->time = time;
      if(cycle_time!=0){
        e->cycle=cycle_time;
      }
      else{
        e->cycle=CONTIKIMAC_CONF_CYCLE_TIME;
      }
    }
    /* If the neighbor didn't reply to us, it may have switched
       phase (rebooted). We try a number of transmissions to it
       before we drop it from the phase list. */
    if(mac_status == MAC_TX_NOACK) {
      PRINTF("phase noacks %d to %d.%d\n", e->noacks, neighbor->u8[0], neighbor->u8[1]);
      e->noacks++;
      if(e->noacks == 1) {
        timer_set(&e->noacks_timer, MAX_NOACKS_TIME);
      }
      if(e->noacks >= MAX_NOACKS || timer_expired(&e->noacks_timer)) {
        PRINTF("drop %d\n", neighbor->u8[0]);
        nbr_table_remove(nbr_phase, e);
        return;
      }
      if(e->noacks >= MAX_NOACKbis){
        e->cycle=CONTIKIMAC_CONF_CYCLE_TIME;
      }

    } else if(mac_status == MAC_TX_OK) {
      e->noacks = 0;
    }
  } else {
    /* No matching phase was found, so we allocate a new one. */
    if(mac_status == MAC_TX_OK && e == NULL) {
      e = nbr_table_add_lladdr(nbr_phase, neighbor);
      if(e) {
        e->time = time;
#if PHASE_DRIFT_CORRECT
      e->drift = 0;
#endif
      e->noacks = 0;
      }
    }
  }
}
예제 #5
0
/*---------------------------------------------------------------------------*/
rpl_rank_t
rpl_get_parent_rank(uip_lladdr_t *addr)
{
  rpl_parent_t *p = nbr_table_get_from_lladdr(rpl_parents, (linkaddr_t *)addr);
  if(p != NULL) {
    return p->rank;
  } else {
    return 0;
  }
}
예제 #6
0
파일: rpl-dag.c 프로젝트: Johnyren/orpl
/*---------------------------------------------------------------------------*/
uint16_t
rpl_get_parent_link_metric(uip_lladdr_t *addr)
{
  rpl_parent_t *p = nbr_table_get_from_lladdr(rpl_parents, (rimeaddr_t *)addr);
  if(p != NULL) {
    return p->link_metric;
  } else {
    return 0;
  }
}
예제 #7
0
파일: rpl-dag.c 프로젝트: Johnyren/orpl
/*---------------------------------------------------------------------------*/
uint16_t
rpl_get_parent_bc_ackcount_default(uip_lladdr_t *addr, uint16_t default_value)
{
  rpl_parent_t *p = nbr_table_get_from_lladdr(rpl_parents, (rimeaddr_t *)addr);
  if(p != NULL) {
    return p->bc_ackcount;
  } else {
    return default_value;
  }
}
예제 #8
0
파일: rpl-dag.c 프로젝트: Johnyren/orpl
/*---------------------------------------------------------------------------*/
rpl_rank_t
rpl_get_parent_rank_default(uip_lladdr_t *addr, rpl_rank_t default_value)
{
  rpl_parent_t *p = nbr_table_get_from_lladdr(rpl_parents, (rimeaddr_t *)addr);
  if(p != NULL) {
    return p->rank;
  } else {
    return default_value;
  }
}
예제 #9
0
uint8_t
rpl_node_in_forwarder_set(const linkaddr_t *lladdr)
{
  uint8_t * val;
  val = (uint8_t *)nbr_table_get_from_lladdr(forwarder_set, lladdr);
  if(val != NULL) {
    return *val;
  }
  PRINTF("RPL: node not found in neighbor table\n");
  return 0;
}
예제 #10
0
/*---------------------------------------------------------------------------*/
uip_ds6_nbr_t *
rpl_get_nbr(rpl_parent_t *parent)
{
  linkaddr_t *lladdr = NULL;
  lladdr = nbr_table_get_lladdr(rpl_parents, parent);
  if(lladdr != NULL) {
    return nbr_table_get_from_lladdr(ds6_neighbors, lladdr);
  } else {
    return NULL;
  }
}
예제 #11
0
/*---------------------------------------------------------------------------*/
int
uip_ds6_route_is_nexthop(const uip_ipaddr_t *ipaddr)
{
  const uip_lladdr_t *lladdr;
  lladdr = uip_ds6_nbr_lladdr_from_ipaddr(ipaddr);

  if(lladdr == NULL) {
    return 0;
  }

  return nbr_table_get_from_lladdr(nbr_routes, (linkaddr_t *)lladdr) != NULL;
}
예제 #12
0
/*---------------------------------------------------------------------------*/
void
uip_ds6_route_rm_by_nexthop(uip_ipaddr_t *nexthop)
{
  /* Get routing entry list of this neighbor */
  const uip_lladdr_t *nexthop_lladdr;
  struct uip_ds6_route_neighbor_routes *routes;

  nexthop_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(nexthop);
  routes = nbr_table_get_from_lladdr(nbr_routes,
                                     (linkaddr_t *)nexthop_lladdr);
  rm_routelist(routes);
}
예제 #13
0
/*---------------------------------------------------------------------------*/
uint16_t
rpl_get_parent_link_metric(const uip_lladdr_t *addr)
{
  uip_ds6_nbr_t *nbr;
  nbr = nbr_table_get_from_lladdr(ds6_neighbors, (const linkaddr_t *)addr);
  
  if(nbr != NULL) {
    return nbr->link_metric;
  } else {
    return 0;
  }
}
예제 #14
0
/* Packet input callback. Updates statistics for receptions on a given link */
void
link_stats_input_callback(const linkaddr_t *lladdr)
{
  struct link_stats *stats;
  int16_t packet_rssi = packetbuf_attr(PACKETBUF_ATTR_RSSI);

  stats = nbr_table_get_from_lladdr(link_stats, lladdr);
  if(stats == NULL) {
    /* Add the neighbor */
    stats = nbr_table_add_lladdr(link_stats, lladdr, NBR_TABLE_REASON_LINK_STATS, NULL);
    if(stats != NULL) {
      /* Initialize */
      stats->rssi = packet_rssi;
      stats->etx = LINK_STATS_INIT_ETX(stats);
    }
    return;
  }

  /* Update RSSI EWMA */
  stats->rssi = ((int32_t)stats->rssi * (EWMA_SCALE - EWMA_ALPHA) +
      (int32_t)packet_rssi * EWMA_ALPHA) / EWMA_SCALE;
}
예제 #15
0
/* Packet sent callback. Updates stats for transmissions to lladdr */
void
link_stats_packet_sent(const linkaddr_t *lladdr, int status, int numtx)
{
  struct link_stats *stats;
  uint16_t packet_etx;
  uint8_t ewma_alpha;

  if(status != MAC_TX_OK && status != MAC_TX_NOACK) {
    /* Do not penalize the ETX when collisions or transmission errors occur. */
    return;
  }

  stats = nbr_table_get_from_lladdr(link_stats, lladdr);
  if(stats == NULL) {
    /* Add the neighbor */
    stats = nbr_table_add_lladdr(link_stats, lladdr, NBR_TABLE_REASON_LINK_STATS, NULL);
    if(stats != NULL) {
      stats->etx = LINK_STATS_INIT_ETX(stats);
    } else {
      return; /* No space left, return */
    }
  }

  /* Update last timestamp and freshness */
  stats->last_tx_time = clock_time();
  stats->freshness = MIN(stats->freshness + numtx, FRESHNESS_MAX);

  /* ETX used for this update */
  packet_etx = ((status == MAC_TX_NOACK) ? ETX_NOACK_PENALTY : numtx) * ETX_DIVISOR;
  /* ETX alpha used for this update */
  ewma_alpha = link_stats_is_fresh(stats) ? EWMA_ALPHA : EWMA_BOOTSTRAP_ALPHA;

  /* Compute EWMA and update ETX */
  stats->etx = ((uint32_t)stats->etx * (EWMA_SCALE - ewma_alpha) +
      (uint32_t)packet_etx * ewma_alpha) / EWMA_SCALE;
}
예제 #16
0
/*---------------------------------------------------------------------------*/
int
rpl_verify_header(int uip_ext_opt_offset)
{
  rpl_instance_t *instance;
  int down;
  uint16_t sender_rank;
  uint8_t sender_closer;
  uip_ds6_route_t *route;
  rpl_parent_t *sender = NULL;

  if(UIP_HBHO_BUF->len != RPL_HOP_BY_HOP_LEN - 8) {
    PRINTF("RPL: Hop-by-hop extension header has wrong size\n");
    return 1;
  }

  if(UIP_EXT_HDR_OPT_RPL_BUF->opt_type != UIP_EXT_HDR_OPT_RPL) {
    PRINTF("RPL: Non RPL Hop-by-hop option\n");
    return 1;
  }

  if(UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) {
    PRINTF("RPL: Bad header option! (wrong length)\n");
    return 1;
  }

  instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance);
  if(instance == NULL) {
    PRINTF("RPL: Unknown instance: %u\n",
           UIP_EXT_HDR_OPT_RPL_BUF->instance);
    return 1;
  }

  if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_FWD_ERR) {
    PRINTF("RPL: Forward error!\n");
    /* We should try to repair it by removing the neighbor that caused
       the packet to be forwareded in the first place. We drop any
       routes that go through the neighbor that sent the packet to
       us. */
    route = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr);
    if(route != NULL) {
      uip_ds6_route_rm(route);
    }
    RPL_STAT(rpl_stats.forward_errors++);
    /* Trigger DAO retransmission */
    rpl_reset_dio_timer(instance);
    /* drop the packet as it is not routable */
    return 1;
  }

  if(!instance->current_dag->joined) {
    PRINTF("RPL: No DAG in the instance\n");
    return 1;
  }

  down = 0;
  if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN) {
    down = 1;
  }

  sender_rank = UIP_HTONS(UIP_EXT_HDR_OPT_RPL_BUF->senderrank);
  sender_closer = sender_rank < instance->current_dag->rank;

  PRINTF("RPL: Packet going %s, sender closer %d (%d < %d)\n", down == 1 ? "down" : "up",
	 sender_closer,
	 sender_rank,
	 instance->current_dag->rank
	 );

  sender = nbr_table_get_from_lladdr(rpl_parents, packetbuf_addr(PACKETBUF_ADDR_SENDER));

  if(sender != NULL && (UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR)) {
    /* A rank error was signalled, attempt to repair it by updating
     * the sender's rank from ext header */
    sender->rank = sender_rank;
    rpl_select_dag(instance, sender);
  }

  if((down && !sender_closer) || (!down && sender_closer)) {
    PRINTF("RPL: Loop detected - senderrank: %d my-rank: %d sender_closer: %d\n",
	   sender_rank, instance->current_dag->rank,
	   sender_closer);
    /* Attempt to repair the loop by sending a unicast DIO back to the sender
     * so that it gets a fresh update of our rank. */
    if(sender != NULL) {
      instance->unicast_dio_target = sender;
      rpl_schedule_unicast_dio_immediately(instance);
    }
    if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) {
      RPL_STAT(rpl_stats.loop_errors++);
      PRINTF("RPL: Rank error signalled in RPL option!\n");
      /* Packet must be dropped and dio trickle timer reset, see RFC6550 - 11.2.2.2 */
      rpl_reset_dio_timer(instance);
      return 1;
    }
    PRINTF("RPL: Single error tolerated\n");
    RPL_STAT(rpl_stats.loop_warnings++);
    UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_RANK_ERR;
    return 0;
  }

  PRINTF("RPL: Rank OK\n");

  return 0;
}
예제 #17
0
/*---------------------------------------------------------------------------*/
uip_ds6_route_t *
uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length,
		  uip_ipaddr_t *nexthop)
{
  uip_ds6_route_t *r;
  struct uip_ds6_route_neighbor_route *nbrr;

#if DEBUG != DEBUG_NONE
  assert_nbr_routes_list_sane();
#endif /* DEBUG != DEBUG_NONE */

  /* Get link-layer address of next hop, make sure it is in neighbor table */
  const uip_lladdr_t *nexthop_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(nexthop);
  if(nexthop_lladdr == NULL) {
    PRINTF("uip_ds6_route_add: neighbor link-local address unknown for ");
    PRINT6ADDR(nexthop);
    PRINTF("\n");
    return NULL;
  }

  /* First make sure that we don't add a route twice. If we find an
     existing route for our destination, we'll delete the old
     one first. */
  r = uip_ds6_route_lookup(ipaddr);
  if(r != NULL) {
    PRINTF("uip_ds6_route_add: old route for ");
    PRINT6ADDR(ipaddr);
    PRINTF(" found, deleting it\n");
    uip_ds6_route_rm(r);
  }
  {
    struct uip_ds6_route_neighbor_routes *routes;
    /* If there is no routing entry, create one. We first need to
       check if we have room for this route. If not, we remove the
       least recently used one we have. */

    if(uip_ds6_route_num_routes() == UIP_DS6_ROUTE_NB) {
      /* Removing the oldest route entry from the route table. The
         least recently used route is the first route on the list. */
      uip_ds6_route_t *oldest;

      oldest = list_tail(routelist); /* uip_ds6_route_head(); */
      PRINTF("uip_ds6_route_add: dropping route to ");
      PRINT6ADDR(&oldest->ipaddr);
      PRINTF("\n");
      uip_ds6_route_rm(oldest);
    }


    /* Every neighbor on our neighbor table holds a struct
       uip_ds6_route_neighbor_routes which holds a list of routes that
       go through the neighbor. We add our route entry to this list.

       We first check to see if we already have this neighbor in our
       nbr_route table. If so, the neighbor already has a route entry
       list.
    */
    routes = nbr_table_get_from_lladdr(nbr_routes,
                                       (linkaddr_t *)nexthop_lladdr);

    if(routes == NULL) {
      /* If the neighbor did not have an entry in our neighbor table,
         we create one. The nbr_table_add_lladdr() function returns a
         pointer to a pointer that we may use for our own purposes. We
         initialize this pointer with the list of routing entries that
         are attached to this neighbor. */
      routes = nbr_table_add_lladdr(nbr_routes,
                                    (linkaddr_t *)nexthop_lladdr);
      if(routes == NULL) {
        /* This should not happen, as we explicitly deallocated one
           route table entry above. */
        PRINTF("uip_ds6_route_add: could not allocate neighbor table entry\n");
        return NULL;
      }
      LIST_STRUCT_INIT(routes, route_list);
    }

    /* Allocate a routing entry and populate it. */
    r = memb_alloc(&routememb);

    if(r == NULL) {
      /* This should not happen, as we explicitly deallocated one
         route table entry above. */
      PRINTF("uip_ds6_route_add: could not allocate route\n");
      return NULL;
    }

    /* add new routes first - assuming that there is a reason to add this
       and that there is a packet coming soon. */
    list_push(routelist, r);

    nbrr = memb_alloc(&neighborroutememb);
    if(nbrr == NULL) {
      /* This should not happen, as we explicitly deallocated one
         route table entry above. */
      PRINTF("uip_ds6_route_add: could not allocate neighbor route list entry\n");
      memb_free(&routememb, r);
      return NULL;
    }

    nbrr->route = r;
    /* Add the route to this neighbor */
    list_add(routes->route_list, nbrr);
    r->neighbor_routes = routes;
    num_routes++;

    PRINTF("uip_ds6_route_add num %d\n", num_routes);
  }

  uip_ipaddr_copy(&(r->ipaddr), ipaddr);
  r->length = length;

#ifdef UIP_DS6_ROUTE_STATE_TYPE
  memset(&r->state, 0, sizeof(UIP_DS6_ROUTE_STATE_TYPE));
#endif

  PRINTF("uip_ds6_route_add: adding route: ");
  PRINT6ADDR(ipaddr);
  PRINTF(" via ");
  PRINT6ADDR(nexthop);
  PRINTF("\n");
  ANNOTATE("#L %u 1;blue\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]);

#if UIP_DS6_NOTIFICATIONS
  call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_ADD, ipaddr, nexthop);
#endif

#if DEBUG != DEBUG_NONE
  assert_nbr_routes_list_sane();
#endif /* DEBUG != DEBUG_NONE */
  return r;
}
예제 #18
0
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(rpl_forwarder_set_update_process, ev, instance)
{
  static rpl_rank_t best_rank;
  static rpl_rank_t best_forwarder_rank;
  static rpl_rank_t curr_rank;
  static rpl_forwarder_set_member_t *curr_forwarder;
  static rpl_forwarder_set_member_t *next_forwarder;
  static rpl_forwarder_set_member_t *best_forwarder;
  static rpl_forwarder_set_member_t *last_forwarder;
  static nbr_table_item_t *nbr_table_parent;
  static uint8_t *membership_status;
  PROCESS_BEGIN();
  while(1) {
    PROCESS_WAIT_EVENT();
    if(ev == PROCESS_EVENT_CONTINUE) {
      nbr_table_parent = nbr_table_head(rpl_parents);
      best_rank = 0xFFFF;
      if(nbr_table_parent != NULL) {
        list_init(forwarder_set_list);
        list_init(current_set_list);

        /* Build a list of potential forwarders */
        int is_potential_forwarder;
        PRINTF("RPL: Potential forwarders: ");
        do {
          is_potential_forwarder = 0;
          curr_forwarder = memb_alloc(&forwarder_set_memb);
          if(curr_forwarder == NULL) {
            PRINTF("RPL: unable to allocate forwarder set member\n");
            return 0;
          }
          curr_forwarder->forwarder = (rpl_parent_t *)nbr_table_parent;
          if(((rpl_instance_t *)instance)->of->parent_path_cost(curr_forwarder->forwarder) < 0xFFFF) {
            list_add(forwarder_set_list, curr_forwarder);
            PRINTF("%u ", rpl_get_parent_lladdr(curr_forwarder->forwarder)->u8[7]);
            is_potential_forwarder = 1;
          }
          membership_status = (uint8_t *)nbr_table_add_lladdr(forwarder_set, rpl_get_parent_lladdr(curr_forwarder->forwarder), 
            NBR_TABLE_REASON_UNDEFINED, NULL);
          if(membership_status == NULL) {
            PRINTF("RPL: error setting membership status in forwarder set\n");
            return 0;
          } else {
            *membership_status = 0;
          }
          if(!is_potential_forwarder) {
            memb_free(&forwarder_set_memb, curr_forwarder);
          }
          nbr_table_parent = nbr_table_next(rpl_parents, nbr_table_parent);
        } while(nbr_table_parent != NULL);
        PRINTF("\n");

        last_forwarder = NULL;
        /* Try all incremental combinations in ascending order according to rank */
        while(list_head(forwarder_set_list) != NULL) {
          next_forwarder = list_head(forwarder_set_list);
          best_forwarder = next_forwarder;
          best_forwarder_rank = ((rpl_instance_t *)instance)->of->parent_path_cost(best_forwarder->forwarder);
          /* Instead of sorting, we'll go through and find the best forwarder each time */
          do {
            curr_forwarder = next_forwarder;
            curr_rank = ((rpl_instance_t *)instance)->of->parent_path_cost(curr_forwarder->forwarder);
            if(curr_rank < best_forwarder_rank) {
              best_forwarder = curr_forwarder;
              best_forwarder_rank = curr_rank;
            }
            next_forwarder = list_item_next(curr_forwarder);
          } while(next_forwarder != NULL);
          /* Add the best forwarder to the current list and remove it from the candidate list */
          //PRINTF("RPL: adding %u with rank %u\n", rpl_get_parent_lladdr(best_forwarder->forwarder)->u8[7], best_forwarder_rank);
          list_remove(forwarder_set_list, best_forwarder);
          list_add(current_set_list, best_forwarder);

          /* Find the routing metric with the current list and compare to the best so far */
          curr_rank = ((rpl_instance_t *)instance)->of->rank_via_set(list_head(current_set_list));
          //PRINTF("RPL: resulting rank %u, current best rank %u\n", curr_rank, best_rank);
          if(curr_rank <= best_rank) {
            best_rank = curr_rank;
            last_forwarder = list_tail(current_set_list);
          }
        }

        /* Trim the list back to the best combination. */
        if(last_forwarder != NULL) {
          while(list_head(current_set_list) != NULL) {
            curr_forwarder = list_chop(current_set_list);
            if(curr_forwarder == last_forwarder) {
              list_add(current_set_list, last_forwarder);
              break;
            }
            memb_free(&forwarder_set_memb, curr_forwarder);
          }
          if(list_head(current_set_list) == NULL) {
            PRINTF("RPL: error trimming forwarder set list\n");
          }

          PRINTF("RPL: best rank %u\n", best_rank);
#if DEBUG
          PRINTF("RPL: best set ");
          next_forwarder = list_head(current_set_list);
          do {
            curr_forwarder = next_forwarder;
            PRINTF("%u ", rpl_get_parent_lladdr(curr_forwarder->forwarder)->u8[7]);
            next_forwarder = list_item_next(curr_forwarder);
          } while(next_forwarder != NULL);
          PRINTF("\n");
#endif

          /* Now we have the best combination - store it in a neighbor table */
          while(list_head(current_set_list) != NULL) {
            curr_forwarder = list_pop(current_set_list);
            membership_status = nbr_table_get_from_lladdr(forwarder_set, rpl_get_parent_lladdr(curr_forwarder->forwarder));
            *membership_status = 1;
            memb_free(&forwarder_set_memb, curr_forwarder);
          }
        } else {
          PRINTF("RPL: empty forwarder set\n");
        }
      }
      PRINTF("RPL: updating opp routing rank from %d to %d\n", current_rank, best_rank);
      if(best_rank != 0xFFFF) {
        current_rank = best_rank;
      } else {
        current_rank = INFINITE_RANK;
      }
    }
  }
  PROCESS_END();
}
예제 #19
0
파일: phase.c 프로젝트: 13416795/contiki
/*---------------------------------------------------------------------------*/
phase_status_t
phase_wait(const linkaddr_t *neighbor, rtimer_clock_t cycle_time,
           rtimer_clock_t guard_time,
           mac_callback_t mac_callback, void *mac_callback_ptr,
           struct rdc_buf_list *buf_list)
{
  struct phase *e;
  //  const linkaddr_t *neighbor = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
  /* We go through the list of phases to find if we have recorded a
     phase for this particular neighbor. If so, we can compute the
     time for the next expected phase and setup a ctimer to switch on
     the radio just before the phase. */
  e = nbr_table_get_from_lladdr(nbr_phase, neighbor);
  if(e != NULL) {
    rtimer_clock_t wait, now, expected, sync;
    clock_time_t ctimewait;
    
    /* We expect phases to happen every CYCLE_TIME time
       units. The next expected phase is at time e->time +
       CYCLE_TIME. To compute a relative offset, we subtract
       with clock_time(). Because we are only interested in turning
       on the radio within the CYCLE_TIME period, we compute the
       waiting time with modulo CYCLE_TIME. */
    
    /*      printf("neighbor phase 0x%02x (cycle 0x%02x)\n", e->time & (cycle_time - 1),
            cycle_time);*/

    /*      if(e->noacks > 0) {
            printf("additional wait %d\n", additional_wait);
            }*/
    
    now = RTIMER_NOW();

    sync = (e == NULL) ? now : e->time;

#if PHASE_DRIFT_CORRECT
    {
      int32_t s;
      if(e->drift > cycle_time) {
        s = e->drift % cycle_time / (e->drift / cycle_time);  /* drift per cycle */
        s = s * (now - sync) / cycle_time;                    /* estimated drift to now */
        sync += s;                                            /* add it in */
      }
    }
#endif

    /* Check if cycle_time is a power of two */
    if(!(cycle_time & (cycle_time - 1))) {
      /* Faster if cycle_time is a power of two */
      wait = (rtimer_clock_t)((sync - now) & (cycle_time - 1));
    } else {
      /* Works generally */
      wait = cycle_time - (rtimer_clock_t)((now - sync) % cycle_time);
    }

    if(wait < guard_time) {
      wait += cycle_time;
    }

    ctimewait = (CLOCK_SECOND * (wait - guard_time)) / RTIMER_ARCH_SECOND;

    if(ctimewait > PHASE_DEFER_THRESHOLD) {
      struct phase_queueitem *p;
      
      p = memb_alloc(&queued_packets_memb);
      if(p != NULL) {
        if(buf_list == NULL) {
          packetbuf_set_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED, 1);
          p->q = queuebuf_new_from_packetbuf();
          if(p->q == NULL) {
            /* memory allocation failed */
            memb_free(&queued_packets_memb, p);
            return PHASE_UNKNOWN;
          }
        }
        p->mac_callback = mac_callback;
        p->mac_callback_ptr = mac_callback_ptr;
        p->buf_list = buf_list;
        ctimer_set(&p->timer, ctimewait, send_packet, p);
        return PHASE_DEFERRED;
      }
    }

    expected = now + wait - guard_time;
    if(!RTIMER_CLOCK_LT(expected, now)) {
      /* Wait until the receiver is expected to be awake */
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected));
    }
    return PHASE_SEND_NOW;
  }
  return PHASE_UNKNOWN;
}
예제 #20
0
/*---------------------------------------------------------------------------*/
static int
parse(void)
{
  int result;
  const linkaddr_t *sender;
  struct anti_replay_info* info;
  
  result = DECORATED_FRAMER.parse();
  if(result == FRAMER_FAILED) {
    return result;
  }
  
  if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) != SEC_LVL) {
    PRINTF("noncoresec: received frame with wrong security level\n");
    return FRAMER_FAILED;
  }
  sender = packetbuf_addr(PACKETBUF_ADDR_SENDER);
  if(linkaddr_cmp(sender, &linkaddr_node_addr)) {
    PRINTF("noncoresec: frame from ourselves\n");
    return FRAMER_FAILED;
  }
  
  packetbuf_set_datalen(packetbuf_datalen() - MIC_LEN);
  
  if(!aead(result, 0)) {
    PRINTF("noncoresec: received unauthentic frame %lu\n",
        anti_replay_get_counter());
    return FRAMER_FAILED;
  }
  
  info = nbr_table_get_from_lladdr(anti_replay_table, sender);
  if(!info) {
    info = nbr_table_add_lladdr(anti_replay_table, sender, NBR_TABLE_REASON_LLSEC, NULL);
    if(!info) {
      PRINTF("noncoresec: could not get nbr_table_item\n");
      return FRAMER_FAILED;
    }
    
    /*
     * Locking avoids replay attacks due to removed neighbor table items.
     * Unfortunately, an attacker can mount a memory-based DoS attack
     * on this by replaying broadcast frames from other network parts.
     * However, this is not an issue as long as the network size does not
     * exceed NBR_TABLE_MAX_NEIGHBORS.
     *  
     * To avoid locking, we could swap anti-replay information
     * to external flash. Locking is also unnecessary when using
     * pairwise session keys, as done in coresec.
     */
    if(!nbr_table_lock(anti_replay_table, info)) {
      nbr_table_remove(anti_replay_table, info);
      PRINTF("noncoresec: could not lock\n");
      return FRAMER_FAILED;
    }
    
    anti_replay_init_info(info);
  } else {
    if(anti_replay_was_replayed(info)) {
       PRINTF("noncoresec: received replayed frame %lu\n",
           anti_replay_get_counter());
       return FRAMER_FAILED;
    }
  }
  
  return result;
}
예제 #21
0
/*---------------------------------------------------------------------------*/
rpl_parent_t *
rpl_get_parent(uip_lladdr_t *addr)
{
  rpl_parent_t *p = nbr_table_get_from_lladdr(rpl_parents, (linkaddr_t *)addr);
  return p;
}
예제 #22
0
/*---------------------------------------------------------------------------*/
static void
eb_input(struct input_packet *current_input)
{
  /* PRINTF("TSCH: EB received\n"); */
  frame802154_t frame;
  /* Verify incoming EB (does its ASN match our Rx time?),
   * and update our join priority. */
  struct ieee802154_ies eb_ies;

  if(tsch_packet_parse_eb(current_input->payload, current_input->len,
                          &frame, &eb_ies, NULL, 1)) {
    /* PAN ID check and authentication done at rx time */

#if TSCH_AUTOSELECT_TIME_SOURCE
    if(!tsch_is_coordinator) {
      /* Maintain EB received counter for every neighbor */
      struct eb_stat *stat = (struct eb_stat *)nbr_table_get_from_lladdr(eb_stats, &frame.src_addr);
      if(stat == NULL) {
        stat = (struct eb_stat *)nbr_table_add_lladdr(eb_stats, &frame.src_addr);
      }
      if(stat != NULL) {
        stat->rx_count++;
        stat->jp = eb_ies.join_priority;
        best_neighbor_eb_count = MAX(best_neighbor_eb_count, stat->rx_count);
      }
      /* Select best time source */
      struct eb_stat *best_stat = NULL;
      stat = nbr_table_head(eb_stats);
      while(stat != NULL) {
        /* Is neighbor eligible as a time source? */
        if(stat->rx_count > best_neighbor_eb_count / 2) {
          if(best_stat == NULL ||
             stat->jp < best_stat->jp) {
            best_stat = stat;
          }
        }
        stat = nbr_table_next(eb_stats, stat);
      }
      /* Update time source */
      if(best_stat != NULL) {
        tsch_queue_update_time_source(nbr_table_get_lladdr(eb_stats, best_stat));
        tsch_join_priority = best_stat->jp + 1;
      }
    }
#endif

    struct tsch_neighbor *n = tsch_queue_get_time_source();
    /* Did the EB come from our time source? */
    if(n != NULL && linkaddr_cmp((linkaddr_t *)&frame.src_addr, &n->addr)) {
      /* Check for ASN drift */
      int32_t asn_diff = ASN_DIFF(current_input->rx_asn, eb_ies.ie_asn);
      if(asn_diff != 0) {
        /* We disagree with our time source's ASN -- leave the network */
        PRINTF("TSCH:! ASN drifted by %ld, leaving the network\n", asn_diff);
        tsch_disassociate();
      }

      if(eb_ies.ie_join_priority >= TSCH_MAX_JOIN_PRIORITY) {
        /* Join priority unacceptable. Leave network. */
        PRINTF("TSCH:! EB JP too high %u, leaving the network\n",
               eb_ies.ie_join_priority);
        tsch_disassociate();
      } else {
#if TSCH_AUTOSELECT_TIME_SOURCE
        /* Update join priority */
        if(tsch_join_priority != eb_ies.ie_join_priority + 1) {
          PRINTF("TSCH: update JP from EB %u -> %u\n",
                 tsch_join_priority, eb_ies.ie_join_priority + 1);
          tsch_join_priority = eb_ies.ie_join_priority + 1;
        }
#endif /* TSCH_AUTOSELECT_TIME_SOURCE */
      }
    }
  }
}
예제 #23
0
/*---------------------------------------------------------------------------*/
uip_ds6_route_t *
uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length,
		  uip_ipaddr_t *nexthop)
{
  uip_ds6_route_t *r;

#if DEBUG != DEBUG_NONE
  assert_nbr_routes_list_sane();
#endif /* DEBUG != DEBUG_NONE */

  /* Get link-layer address of next hop, make sure it is in neighbor table */
  const uip_lladdr_t *nexthop_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(nexthop);
  if(nexthop_lladdr == NULL) {
    PRINTF("uip_ds6_route_add: neighbor link-local address unknown ");
    PRINT6ADDR(ipaddr);
    PRINTF("\n");
    return NULL;
  }

  /* First make sure that we don't add a route twice. If we find an
     existing route for our destination, we'll just update the old
     one. */
  r = uip_ds6_route_lookup(ipaddr);
  if(r != NULL) {
    PRINTF("uip_ds6_route_add: old route already found, updating this one instead: ");
    PRINT6ADDR(ipaddr);
    PRINTF("\n");
  } else {
    struct uip_ds6_route_neighbor_routes *routes;
    /* If there is no routing entry, create one */

    /* Every neighbor on our neighbor table holds a struct
       uip_ds6_route_neighbor_routes which holds a list of routes that
       go through the neighbor. We add our route entry to this list.

       We first check to see if we already have this neighbor in our
       nbr_route table. If so, the neighbor already has a route entry
       list.
    */
    routes = nbr_table_get_from_lladdr(nbr_routes,
                                       (rimeaddr_t *)nexthop_lladdr);

    if(routes == NULL) {
      /* If the neighbor did not have an entry in our neighbor table,
         we create one. The nbr_table_add_lladdr() function returns a
         pointer to a pointer that we may use for our own purposes. We
         initialize this pointer with the list of routing entries that
         are attached to this neighbor. */
      routes = nbr_table_add_lladdr(nbr_routes,
                                    (rimeaddr_t *)nexthop_lladdr);
      if(routes == NULL) {
        PRINTF("uip_ds6_route_add: could not allocate a neighbor table entri for new route to ");
        PRINT6ADDR(ipaddr);
        PRINTF(", dropping it\n");
        return NULL;
      }
      LIST_STRUCT_INIT(routes, route_list);
    }

    /* Allocate a routing entry and populate it. */
    r = memb_alloc(&routememb);

    if(r == NULL) {
      PRINTF("uip_ds6_route_add: could not allocate memory for new route to ");
      PRINT6ADDR(ipaddr);
      PRINTF(", dropping it\n");
      return NULL;
    }


    /* Add the route to this neighbor */
    list_add(routes->route_list, r);
    num_routes++;

    PRINTF("uip_ds6_route_add num %d\n", num_routes);
    r->routes = routes;
  }

  uip_ipaddr_copy(&(r->ipaddr), ipaddr);
  r->length = length;

#ifdef UIP_DS6_ROUTE_STATE_TYPE
  memset(&r->state, 0, sizeof(UIP_DS6_ROUTE_STATE_TYPE));
#endif

  PRINTF("uip_ds6_route_add: adding route: ");
  PRINT6ADDR(ipaddr);
  PRINTF(" via ");
  PRINT6ADDR(nexthop);
  PRINTF("\n");
  ANNOTATE("#L %u 1;blue\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]);

#if UIP_DS6_NOTIFICATIONS
  call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_ADD, ipaddr, nexthop);
#endif

#if DEBUG != DEBUG_NONE
  assert_nbr_routes_list_sane();
#endif /* DEBUG != DEBUG_NONE */
  return r;
}
예제 #24
0
/*---------------------------------------------------------------------------*/
uip_ds6_nbr_t *
uip_ds6_nbr_ll_lookup(const uip_lladdr_t *lladdr)
{
  return nbr_table_get_from_lladdr(ds6_neighbors, (linkaddr_t*)lladdr);
}
예제 #25
0
/*---------------------------------------------------------------------------*/
uip_ds6_nbr_t *
uip_ds6_nbr_ll_lookup(uip_lladdr_t *lladdr)
{
  return nbr_table_get_from_lladdr(ds6_neighbors, (rimeaddr_t*)lladdr);
}
예제 #26
0
/* Returns the neighbor's link stats */
const struct link_stats *
link_stats_from_lladdr(const linkaddr_t *lladdr)
{
  return nbr_table_get_from_lladdr(link_stats, lladdr);
}