Exemple #1
0
/*---------------------------------------------------------------------------*/
static void
free_packet(struct neighbor_queue *n, struct rdc_buf_list *p)
{
  if(p != NULL) {
    /* Remove packet from list and deallocate */
    list_remove(n->queued_packet_list, p);

    queuebuf_free(p->buf);
    memb_free(&metadata_memb, p->ptr);
    memb_free(&packet_memb, p);
    PRINTF("csma: free_queued_packet, queue length %d\n",
        list_length(n->queued_packet_list));
    if(list_head(n->queued_packet_list) != NULL) {
      /* There is a next packet. We reset current tx information */
      n->transmissions = 0;
      n->collisions = 0;
      n->deferrals = 0;
      /* Set a timer for next transmissions */
      ctimer_set(&n->transmit_timer, default_timebase(),
                 transmit_packet_list, n);
    } else {
      /* This was the last packet in the queue, we free the neighbor */
      ctimer_stop(&n->transmit_timer);
      list_remove(neighbor_list, n);
      memb_free(&neighbor_memb, n);
    }
  }
}
Exemple #2
0
/*---------------------------------------------------------------------------*/
static void
free_packet(struct neighbor_queue *n, struct rdc_buf_list *p)
{
  if(p != NULL) {

//ADILA EDIT 09/02/14
//cc2420_set_channel(list_length(n->queued_packet_list) + 10);
//printf("%d BEFORE FREE Q %d\n", cc2420_get_channel(), list_length(n->queued_packet_list));
//-------------------

    /* Remove packet from list and deallocate */
    list_remove(n->queued_packet_list, p);

    queuebuf_free(p->buf);
    memb_free(&metadata_memb, p->ptr);
    memb_free(&packet_memb, p);

//ADILA EDIT 09/02/14
if((list_length(n->queued_packet_list)) == 0) {
cc2420_set_channel(26);
//printf("%d empty Q %d\n", cc2420_get_channel(), list_length(n->queued_packet_list));

}
//-------------------

    PRINTF("csma: free_queued_packet, queue length %d\n",
        list_length(n->queued_packet_list));
    if(list_head(n->queued_packet_list) != NULL) {
      /* There is a next packet. We reset current tx information */
      n->transmissions = 0;
      n->collisions = 0;
      n->deferrals = 0;
      /* Set a timer for next transmissions */
      ctimer_set(&n->transmit_timer, default_timebase(),
                 transmit_packet_list, n);
    } else {
      /* This was the last packet in the queue, we free the neighbor */
      ctimer_stop(&n->transmit_timer);
      list_remove(neighbor_list, n);
      memb_free(&neighbor_memb, n);
    }
  }
}
Exemple #3
0
/*---------------------------------------------------------------------------*/
static void
free_queued_packet(void)
{
  struct queued_packet *q;

  //  printf("q %d\n", list_length(queued_packet_list));

  q = list_head(queued_packet_list);

  if(q != NULL) {
    queuebuf_free(q->buf);
    list_remove(queued_packet_list, q);
    memb_free(&packet_memb, q);
    PRINTF("csma: free_queued_packet, queue length %d\n",
           list_length(queued_packet_list));
    if(list_length(queued_packet_list) > 0) {
      ctimer_set(&transmit_timer, default_timebase(), transmit_queued_packet, NULL);
    }
  }
}
Exemple #4
0
/*---------------------------------------------------------------------------*/
static void
packet_sent(void *ptr, int status, int num_transmissions)
{
  struct neighbor_queue *n;
  struct rdc_buf_list *q;
  struct qbuf_metadata *metadata;
  clock_time_t time = 0;
  mac_callback_t sent;
  void *cptr;
  int num_tx;
  int backoff_exponent;
  int backoff_transmissions;

  n = ptr;
  if(n == NULL) {
    return;
  }
  switch(status) {
  case MAC_TX_OK:
  case MAC_TX_NOACK:
    n->transmissions++;
    break;
  case MAC_TX_COLLISION:
    n->collisions++;
    break;
  case MAC_TX_DEFERRED:
    n->deferrals++;
    break;
  }

  for(q = list_head(n->queued_packet_list);
      q != NULL; q = list_item_next(q)) {
    if(queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO) ==
       packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) {
      break;
    }
  }

  if(q != NULL) {
    metadata = (struct qbuf_metadata *)q->ptr;

    if(metadata != NULL) {
      sent = metadata->sent;
      cptr = metadata->cptr;
      num_tx = n->transmissions;
      if(status == MAC_TX_COLLISION ||
         status == MAC_TX_NOACK) {

        /* If the transmission was not performed because of a
           collision or noack, we must retransmit the packet. */

        switch(status) {
        case MAC_TX_COLLISION:
          PRINTF("csma: rexmit collision %d\n", n->transmissions);
          break;
        case MAC_TX_NOACK:
          PRINTF("csma: rexmit noack %d\n", n->transmissions);
          break;
        default:
          PRINTF("csma: rexmit err %d, %d\n", status, n->transmissions);
        }

        /* The retransmission time must be proportional to the channel
           check interval of the underlying radio duty cycling layer. */
        time = default_timebase();

        /* The retransmission time uses a truncated exponential backoff
         * so that the interval between the transmissions increase with
         * each retransmit. */
        backoff_exponent = num_tx;

        /* Truncate the exponent if needed. */
        if(backoff_exponent > CSMA_MAX_BACKOFF_EXPONENT) {
          backoff_exponent = CSMA_MAX_BACKOFF_EXPONENT;
        }

        /* Proceed to exponentiation. */
        backoff_transmissions = 1 << backoff_exponent;

        /* Pick a time for next transmission, within the interval:
         * [time, time + 2^backoff_exponent * time[ */
        time = time + (random_rand() % (backoff_transmissions * time));

        if(n->transmissions < metadata->max_transmissions) {
          PRINTF("csma: retransmitting with time %lu %p\n", time, q);
          ctimer_set(&n->transmit_timer, time,
                     transmit_packet_list, n);
          /* This is needed to correctly attribute energy that we spent
             transmitting this packet. */
          queuebuf_update_attr_from_packetbuf(q->buf);
        } else {
          PRINTF("csma: drop with status %d after %d transmissions, %d collisions\n",
                 status, n->transmissions, n->collisions);
          free_packet(n, q);
          mac_call_sent_callback(sent, cptr, status, num_tx);
        }
      } else {
        if(status == MAC_TX_OK) {
          PRINTF("csma: rexmit ok %d\n", n->transmissions);
        } else {
          PRINTF("csma: rexmit failed %d: %d\n", n->transmissions, status);
        }
        free_packet(n, q);
        mac_call_sent_callback(sent, cptr, status, num_tx);
      }
    }
  }
}
Exemple #5
0
/*---------------------------------------------------------------------------*/
static void
packet_sent(void *ptr, int status, int num_transmissions)
{
  struct neighbor_queue *n;
  struct rdc_buf_list *q;
  struct qbuf_metadata *metadata;
  clock_time_t time = 0;
  mac_callback_t sent;
  void *cptr;
  int num_tx;
  int backoff_transmissions;

  n = ptr;
  if(n == NULL) {
    return;
  }
  switch(status) {
  case MAC_TX_OK:
  case MAC_TX_NOACK:
    n->transmissions++;
    break;
  case MAC_TX_COLLISION:
    n->collisions++;
    break;
  case MAC_TX_DEFERRED:
    n->deferrals++;
    break;
  }

  for(q = list_head(n->queued_packet_list);
      q != NULL; q = list_item_next(q)) {
    if(queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO) ==
       packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) {
      break;
    }
  }

  if(q != NULL) {
    metadata = (struct qbuf_metadata *)q->ptr;

    if(metadata != NULL) {
      sent = metadata->sent;
      cptr = metadata->cptr;
#if CSMA_ADVANCED
      num_tx = n->transmissions + n->collisions/8;
#else
      num_tx = n->transmissions;
#endif

      if(status == MAC_TX_COLLISION ||
           status == MAC_TX_NOACK) {
        /* If the transmission was not performed because of a
           collision or noack, we must retransmit the packet. */

        switch(status) {
        case MAC_TX_COLLISION:
          PRINTF("csma: rexmit collision %d\n", n->transmissions);
          break;
        case MAC_TX_NOACK:
          PRINTF("csma: rexmit noack %d\n", n->transmissions);
          break;
        case MAC_TX_DEFERRED:
          PRINTF("phase deferred\n");
          break;
        default:
          PRINTF("csma: rexmit err %d, %d\n", status, n->transmissions);
        }
#if CSMA_ADVANCED
          int i;
          /* The retransmission time must be proportional to the channel
           check interval of the underlying radio duty cycling layer. */
          time = default_timebase() / 3;

          /* The retransmission time uses a linear backoff so that the
           interval between the transmissions increase with each
           retransmit. */
          backoff_transmissions = 1;
          for(i=0; i<num_tx-1; i++) {
            backoff_transmissions *= 3;
          }

          /* Clamp the number of backoffs so that we don't get a too long
           timeout here, since that will delay all packets in the
           queue. */
          if(backoff_transmissions > 3 * 3) {
            backoff_transmissions = 3 * 3;
          }

          time = default_timebase() + (random_rand() % (backoff_transmissions * time));

        if(num_tx < metadata->max_transmissions) {
#else
        /* The retransmission time must be proportional to the channel
           check interval of the underlying radio duty cycling layer. */
        time = default_timebase();

        /* The retransmission time uses a linear backoff so that the
           interval between the transmissions increase with each
           retransmit. */
        backoff_transmissions = n->transmissions + 1;

        /* Clamp the number of backoffs so that we don't get a too long
           timeout here, since that will delay all packets in the
           queue. */
        if(backoff_transmissions > 3) {
          backoff_transmissions = 3;
        }

        time = time + (random_rand() % (backoff_transmissions * time));
        if(n->transmissions < metadata->max_transmissions) {
#endif
          PRINTF("csma: retransmitting with time %lu %p\n", time, q);
          ctimer_set(&n->transmit_timer, time,
                     transmit_packet_list, n);
          /* This is needed to correctly attribute energy that we spent
             transmitting this packet. */
          queuebuf_update_attr_from_packetbuf(q->buf);
        } else {
          if(!rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                                 &rimeaddr_null)) {
            LOG_FROM_PACKETBUF("csma: drop with status %d after %d transmissions, %d collisions",
                               status, n->transmissions, n->collisions);
          }
          free_packet(n, q);
          mac_call_sent_callback(sent, cptr, status, num_tx);
        }
      } else {
        if(status == MAC_TX_OK) {
          if(!rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                                 &rimeaddr_null)) {
          LOG_FROM_PACKETBUF("csma: rexmit ok after %d transmissions, %d collisions", n->transmissions, n->collisions);
          }
        } else {
          //LOG_FROM_PACKETBUF("csma: rexmit failed %d: %d\n", n->transmissions, status);
        }
        free_packet(n, q);
        mac_call_sent_callback(sent, cptr, status, num_tx);
      }
    }
  }
}
/*---------------------------------------------------------------------------*/
static void
send_packet(mac_callback_t sent, void *ptr)
{
  struct rdc_buf_list *q;
  struct neighbor_queue *n;
  static uint16_t seqno;
  const rimeaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);

  if(seqno == 0) {
    /* PACKETBUF_ATTR_MAC_SEQNO cannot be zero, due to a pecuilarity
       in framer-802154.c. */
    seqno++;
  }
  packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++);

  /* Look for the neighbor entry */
  n = neighbor_queue_from_addr(addr);
  if(n == NULL) {
    /* Allocate a new neighbor entry */
    n = memb_alloc(&neighbor_memb);
    if(n != NULL) {
      /* Init neighbor entry */
      rimeaddr_copy(&n->addr, addr);
      n->transmissions = 0;
      n->collisions = 0;
      n->deferrals = 0;
      /* Init packet list for this neighbor */
      LIST_STRUCT_INIT(n, queued_packet_list);
      /* Add neighbor to the list */
      list_add(neighbor_list, n);
    }
  }

  if(n != NULL) {
    /* Add packet to the neighbor's queue */
    q = memb_alloc(&packet_memb);
    if(q != NULL) {
      q->ptr = memb_alloc(&metadata_memb);
      if(q->ptr != NULL) {
	q->buf = queuebuf_new_from_packetbuf();
	if(q->buf != NULL) {
	  struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr;
	  /* Neighbor and packet successfully allocated */
	  if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) == 0) {
	    /* Use default configuration for max transmissions */
	    metadata->max_transmissions = CSMA_MAX_MAC_TRANSMISSIONS;
	  } else {
	    metadata->max_transmissions =
                  packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
	  }
	  metadata->sent = sent;
	  metadata->cptr = ptr;

	  if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
	     PACKETBUF_ATTR_PACKET_TYPE_ACK) {
	    list_push(n->queued_packet_list, q);
	  } else {
	    list_add(n->queued_packet_list, q);
	  }

	  /* If q is the first packet in the neighbor's queue, send asap */
	  if(list_head(n->queued_packet_list) == q) {
	    ctimer_set(&n->transmit_timer, 0, transmit_packet_list, n);
	  }
	  return;
	}
	memb_free(&metadata_memb, q->ptr);
	PRINTF("csma: could not allocate queuebuf, dropping packet\n");
      }
      memb_free(&packet_memb, q);
      PRINTF("csma: could not allocate queuebuf, dropping packet\n");
    }
    /* The packet allocation failed. Remove and free neighbor entry if empty. */
    if(list_length(n->queued_packet_list) == 0) {
      list_remove(neighbor_list, n);
      memb_free(&neighbor_memb, n);
    }
    PRINTF("csma: could not allocate packet, dropping packet\n");
  } else {
    PRINTF("csma: could not allocate neighbor, dropping packet\n");
  }
  mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1);
}
/*---------------------------------------------------------------------------*/
static void
input_packet(void)
{
  NETSTACK_NETWORK.input();
}
/*---------------------------------------------------------------------------*/
static int
on(void)
{
  return NETSTACK_RDC.on();
}
/*---------------------------------------------------------------------------*/
static int
off(int keep_radio_on)
{
  return NETSTACK_RDC.off(keep_radio_on);
}
/*---------------------------------------------------------------------------*/
static unsigned short
channel_check_interval(void)
{
  if(NETSTACK_RDC.channel_check_interval) {
    return NETSTACK_RDC.channel_check_interval();
  }
  return 0;
}
/*---------------------------------------------------------------------------*/
static void
init(void)
{
  memb_init(&packet_memb);
  memb_init(&metadata_memb);
  memb_init(&neighbor_memb);
}
/*---------------------------------------------------------------------------*/
static void
packet_sent(void *ptr, int status, int num_transmissions)
{
  struct neighbor_queue *n = ptr;
  struct rdc_buf_list *q = list_head(n->queued_packet_list);
  struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr;
  clock_time_t time = 0;
  mac_callback_t sent;
  void *cptr;
  int num_tx;
  int backoff_transmissions;

  switch(status) {
  case MAC_TX_OK:
  case MAC_TX_NOACK:
    n->transmissions++;
    break;
  case MAC_TX_COLLISION:
    n->collisions++;
    break;
  case MAC_TX_DEFERRED:
    n->deferrals++;
    break;
  }

  sent = metadata->sent;
  cptr = metadata->cptr;
  num_tx = n->transmissions;

  if(status == MAC_TX_COLLISION ||
     status == MAC_TX_NOACK) {

    /* If the transmission was not performed because of a collision or
       noack, we must retransmit the packet. */
    
    switch(status) {
    case MAC_TX_COLLISION:
      PRINTF("csma: rexmit collision %d\n", n->transmissions);
      break;
    case MAC_TX_NOACK:
      PRINTF("csma: rexmit noack %d\n", n->transmissions);
      break;
    default:
      PRINTF("csma: rexmit err %d, %d\n", status, n->transmissions);
    }

    /* The retransmission time must be proportional to the channel
       check interval of the underlying radio duty cycling layer. */
    time = default_timebase();

    /* The retransmission time uses a linear backoff so that the
       interval between the transmissions increase with each
       retransmit. */
    backoff_transmissions = n->transmissions + 1;

    /* Clamp the number of backoffs so that we don't get a too long
       timeout here, since that will delay all packets in the
       queue. */
    if(backoff_transmissions > 3) {
      backoff_transmissions = 3;
    }

    time = time + (random_rand() % (backoff_transmissions * time));

    if(n->transmissions < metadata->max_transmissions) {
      PRINTF("csma: retransmitting with time %lu %p\n", time, q);
      ctimer_set(&n->transmit_timer, time,
                 transmit_packet_list, n);
      /* This is needed to correctly attribute energy that we spent
         transmitting this packet. */
      queuebuf_update_attr_from_packetbuf(q->buf);
    } else {
      PRINTF("csma: drop with status %d after %d transmissions, %d collisions\n",
             status, n->transmissions, n->collisions);
      free_first_packet(n);
      mac_call_sent_callback(sent, cptr, status, num_tx);
    }
  } else {
    if(status == MAC_TX_OK) {
      PRINTF("csma: rexmit ok %d\n", n->transmissions);
    } else {
      PRINTF("csma: rexmit failed %d: %d\n", n->transmissions, status);
    }
    free_first_packet(n);
    mac_call_sent_callback(sent, cptr, status, num_tx);
  }
}