Exemplo n.º 1
0
/*---------------------------------------------------------------------------*/
static uint8_t
send_packet(struct net_buf *buf, mac_callback_t sent, bool last_fragment, void *ptr)
{
  struct rdc_buf_list *q;
  struct neighbor_queue *n;
  static uint8_t initialized = 0;
  static uint16_t seqno;
  const linkaddr_t *addr = packetbuf_addr(buf, PACKETBUF_ADDR_RECEIVER);

  if (!buf) {
    UIP_LOG("csma: send_packet(): net_buf is NULL, cannot send packet");
    return 0;
  }

  if(!initialized) {
    initialized = 1;
    /* Initialize the sequence number to a random value as per 802.15.4. */
    seqno = random_rand();
  }

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

  /* Look for the neighbor entry */
  n = neighbor_queue_from_addr(buf, addr);
  if(n == NULL) {
    /* Allocate a new neighbor entry */
    n = memb_alloc(&neighbor_memb);
    if(n != NULL) {
      /* Init neighbor entry */
      linkaddr_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(uip_neighbor_list(buf), n);
    }
  }

  if(n != NULL) {
    /* Add packet to the neighbor's queue */
    if(list_length(n->queued_packet_list) < CSMA_MAX_PACKET_PER_NEIGHBOR) {
      q = memb_alloc(&packet_memb);
      if(q != NULL) {
        q->ptr = memb_alloc(&metadata_memb);
        if(q->ptr != NULL) {
          q->buf = queuebuf_new_from_packetbuf(buf);
          if(q->buf != NULL) {
            struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr;
            /* Neighbor and packet successfully allocated */
            if(packetbuf_attr(buf, 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(buf, PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
            }
            metadata->sent = sent;
            metadata->cptr = ptr;

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

            PRINTF("csma: send_packet, queue length %d, free packets %d\n",
                   list_length(n->queued_packet_list), memb_numfree(&packet_memb));
            /* if received packet is last fragment/only one packet start sending
             * packets in list, do not start any timer.*/
            if (last_fragment) {
               transmit_packet_list(buf, n);
            }
            return 1;
          }
          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(uip_neighbor_list(buf), n);
        memb_free(&neighbor_memb, n);
      }
    } else {
      PRINTF("csma: Neighbor queue full\n");
    }
    PRINTF("csma: could not allocate packet, dropping packet\n");
  } else {
    PRINTF("csma: could not allocate neighbor, dropping packet\n");
  }
  mac_call_sent_callback(buf, sent, ptr, MAC_TX_ERR, 1);
  return 0;
}
Exemplo n.º 2
0
/**
 * Read a packet from the underlying radio driver. If the incoming
 * packet is a probe packet and the sender of the probe matches the
 * destination address of the queued packet (if any), the queued packet
 * is sent.
 */
static void
input_packet(void)
{
  struct lpp_hdr hdr;
  clock_time_t reception_time;

  reception_time = clock_time();

  if(!NETSTACK_FRAMER.parse()) {
    printf("lpp input_packet framer error\n");
  }

  memcpy(&hdr, packetbuf_dataptr(), sizeof(struct lpp_hdr));;
  packetbuf_hdrreduce(sizeof(struct lpp_hdr));
  /*    PRINTF("got packet type %d\n", hdr->type);*/

  if(hdr.type == TYPE_PROBE) {
    struct announcement_msg adata;
    
    /* Register the encounter with the sending node. We now know the
       neighbor's phase. */
    register_encounter(&hdr.sender, reception_time);

    /* Parse incoming announcements */
    memcpy(&adata, packetbuf_dataptr(),
           MIN(packetbuf_datalen(), sizeof(adata)));
#if 0
    PRINTF("%d.%d: probe from %d.%d with %d announcements\n",
           rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
           hdr.sender.u8[0], hdr.sender.u8[1], adata->num);
    
    if(adata.num / sizeof(struct announcement_data) > sizeof(struct announcement_msg)) {
      /* Sanity check. The number of announcements is too large -
         corrupt packet has been received. */
      return 0;
    }

    for(i = 0; i < adata.num; ++i) {
      /*	  PRINTF("%d.%d: announcement %d: %d\n",
		  rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
		  adata->data[i].id,
		  adata->data[i].value);*/

      announcement_heard(&hdr.sender,
                         adata.data[i].id,
                         adata.data[i].value);
    }
#endif  /* 0 */

    /* Go through the list of packets to be sent to see if any of
       them match the sender of the probe, or if they are a
       broadcast packet that should be sent. */
    if(list_length(queued_packets_list) > 0) {
      struct queue_list_item *i;
      for(i = list_head(queued_packets_list); i != NULL; i = list_item_next(i)) {
        const rimeaddr_t *receiver;
        uint8_t sent;

        sent = 0;
 
        receiver = queuebuf_addr(i->packet, PACKETBUF_ADDR_RECEIVER);
        if(rimeaddr_cmp(receiver, &hdr.sender) ||
           rimeaddr_cmp(receiver, &rimeaddr_null)) {
          queuebuf_to_packetbuf(i->packet);

#if WITH_PENDING_BROADCAST
          if(i->broadcast_flag == BROADCAST_FLAG_NONE ||
             i->broadcast_flag == BROADCAST_FLAG_SEND) {
            i->num_transmissions = 1;
            NETSTACK_RADIO.send(queuebuf_dataptr(i->packet),
                                queuebuf_datalen(i->packet));
            sent = 1;
            PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n",
		   rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
                   hdr.sender.u8[0], hdr.sender.u8[1],
                   receiver->u8[0], receiver->u8[1]);
	      
          } else {
            PRINTF("%d.%d: got a probe from %d.%d, did not send packet\n",
                   rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
                   hdr.sender.u8[0], hdr.sender.u8[1]);
          }
#else /* WITH_PENDING_BROADCAST */
          i->num_transmissions = 1;
          NETSTACK_RADIO.send(queuebuf_dataptr(i->packet),
                               queuebuf_datalen(i->packet));
          PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n",
                 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
                 hdr.sender.u8[0], hdr.sender.u8[1],
                 receiver->u8[0], receiver->u8[1]);
#endif /* WITH_PENDING_BROADCAST */

          /*          off();*/

          /* Attribute the energy spent on listening for the probe
             to this packet transmission. */
          compower_accumulate(&i->compower);
	    
          /* If the packet was not a broadcast packet, we dequeue it
             now. Broadcast packets should be transmitted to all
             neighbors, and are dequeued by the dutycycling function
             instead, after the appropriate time. */
          if(!rimeaddr_cmp(receiver, &rimeaddr_null)) {
            if(detect_ack()) {
              remove_queued_packet(i, 1);
            } else {
              remove_queued_packet(i, 0);
            }

#if WITH_PROBE_AFTER_TRANSMISSION
            /* Send a probe packet to catch any reply from the other node. */
            restart_dutycycle(PROBE_AFTER_TRANSMISSION_TIME);
#endif /* WITH_PROBE_AFTER_TRANSMISSION */

#if WITH_STREAMING
            if(is_streaming) {
              ctimer_set(&stream_probe_timer, STREAM_PROBE_TIME,
                         send_stream_probe, NULL);
            }
#endif /* WITH_STREAMING */
          }

          if(sent) {
            turn_radio_off();
          }

#if WITH_ACK_OPTIMIZATION
          if(packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
             packetbuf_attr(PACKETBUF_ATTR_ERELIABLE)) {
            /* We're sending a packet that needs an ACK, so we keep
               the radio on in anticipation of the ACK. */
            turn_radio_on();
          }
#endif /* WITH_ACK_OPTIMIZATION */

        }
      }
    }

  } else if(hdr.type == TYPE_DATA) {
    turn_radio_off();
    if(!rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) {
      if(!rimeaddr_cmp(&hdr.receiver, &rimeaddr_node_addr)) {
        /* Not broadcast or for us */
        PRINTF("%d.%d: data not for us from %d.%d\n",
               rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
               hdr.sender.u8[0], hdr.sender.u8[1]);
        return;
      }
      packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &hdr.receiver);
    }
    packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &hdr.sender);

    PRINTF("%d.%d: got data from %d.%d\n",
           rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
           hdr.sender.u8[0], hdr.sender.u8[1]);

    /* Accumulate the power consumption for the packet reception. */
    compower_accumulate(&current_packet);
    /* Convert the accumulated power consumption for the received
       packet to packet attributes so that the higher levels can
       keep track of the amount of energy spent on receiving the
       packet. */
    compower_attrconv(&current_packet);
      
    /* Clear the accumulated power consumption so that it is ready
       for the next packet. */
    compower_clear(&current_packet);

#if WITH_PENDING_BROADCAST
    if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) {
      /* This is a broadcast packet. Check the list of pending
         packets to see if we are currently sending a broadcast. If
         so, we refrain from sending our broadcast until one sleep
         cycle period, so that the other broadcaster will have
         finished sending. */
	
      struct queue_list_item *i;
      for(i = list_head(queued_packets_list); i != NULL; i = list_item_next(i)) {
        /* If the packet is a broadcast packet that is not yet
           ready to be sent, we do not send it. */
        if(i->broadcast_flag == BROADCAST_FLAG_PENDING) {
          PRINTF("Someone else is sending, pending -> waiting\n");
          set_broadcast_flag(i, BROADCAST_FLAG_WAITING);
        }
      }
    }
#endif /* WITH_PENDING_BROADCAST */


#if WITH_PROBE_AFTER_RECEPTION
    /* XXX send probe after receiving a packet to facilitate data
       streaming. We must first copy the contents of the packetbuf into
       a queuebuf to avoid overwriting the data with the probe packet. */
    if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_node_addr)) {
      struct queuebuf *q;
      q = queuebuf_new_from_packetbuf();
      if(q != NULL) {
        send_probe();
        queuebuf_to_packetbuf(q);
        queuebuf_free(q);
      }
    }
#endif /* WITH_PROBE_AFTER_RECEPTION */

#if WITH_ADAPTIVE_OFF_TIME
    off_time = LOWEST_OFF_TIME;
    restart_dutycycle(off_time);
#endif /* WITH_ADAPTIVE_OFF_TIME */

    NETSTACK_MAC.input();
  }
}
Exemplo n.º 3
0
/*---------------------------------------------------------------------------*/
static int
create_frame(int type, int do_create)
{
  frame802154_t params;
  int hdr_len;

  if(frame802154_get_pan_id() == 0xffff) {
    return -1;
  }

  /* init to zeros */
  memset(&params, 0, sizeof(params));

  if(!initialized) {
    initialized = 1;
    mac_dsn = random_rand() & 0xff;
  }

  /* Build the FCF. */
  params.fcf.frame_type = packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE);
  params.fcf.frame_pending = packetbuf_attr(PACKETBUF_ATTR_PENDING);
  if(packetbuf_holds_broadcast()) {
    params.fcf.ack_required = 0;
  } else {
    params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_MAC_ACK);
  }
  /* We do not compress PAN ID in outgoing frames, i.e. include one PAN ID (dest by default)
   * There is one exception, seemingly a typo in Table 2a: rows 2 and 3: when there is no
   * source nor destination address, we have dest PAN ID iff compression is *set*. */
  params.fcf.panid_compression = 0;
  params.fcf.sequence_number_suppression = FRAME802154_SUPPR_SEQNO;

  /* Insert IEEE 802.15.4 version bits. */
  params.fcf.frame_version = FRAME802154_VERSION;
  
#if LLSEC802154_USES_AUX_HEADER
  if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL)) {
    params.fcf.security_enabled = 1;
  }
  /* Setting security-related attributes */
  params.aux_hdr.security_control.security_level = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL);
#if LLSEC802154_USES_FRAME_COUNTER
  params.aux_hdr.frame_counter.u16[0] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1);
  params.aux_hdr.frame_counter.u16[1] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3);
#else /* LLSEC802154_USES_FRAME_COUNTER */
  params.aux_hdr.security_control.frame_counter_suppression = 1;
  params.aux_hdr.security_control.frame_counter_size = 1;
#endif /* LLSEC802154_USES_FRAME_COUNTER */
#if LLSEC802154_USES_EXPLICIT_KEYS
  params.aux_hdr.security_control.key_id_mode = packetbuf_attr(PACKETBUF_ATTR_KEY_ID_MODE);
  params.aux_hdr.key_index = packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX);
  params.aux_hdr.key_source.u16[0] = packetbuf_attr(PACKETBUF_ATTR_KEY_SOURCE_BYTES_0_1);
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
#endif /* LLSEC802154_USES_AUX_HEADER */

  /* Increment and set the data sequence number. */
  if(!do_create) {
    /* Only length calculation - no sequence number is needed and
       should not be consumed. */

  } else if(packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) {
    params.seq = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO);

  } else {
    /* Ensure that the sequence number 0 is not used as it would bypass the above check. */
    if(mac_dsn == 0) {
      mac_dsn++;
    }
    params.seq = mac_dsn++;
    packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, params.seq);
  }

  /* Complete the addressing fields. */
  /**
     \todo For phase 1 the addresses are all long. We'll need a mechanism
     in the rime attributes to tell the mac to use long or short for phase 2.
   */
  if(LINKADDR_SIZE == 2) {
    /* Use short address mode if linkaddr size is short. */
    params.fcf.src_addr_mode = FRAME802154_SHORTADDRMODE;
  } else {
    params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE;
  }
  params.dest_pid = frame802154_get_pan_id();

  if(packetbuf_holds_broadcast()) {
    /* Broadcast requires short address mode. */
    params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE;
    params.dest_addr[0] = 0xFF;
    params.dest_addr[1] = 0xFF;
  } else {
    linkaddr_copy((linkaddr_t *)&params.dest_addr,
                  packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
    /* Use short address mode if linkaddr size is small */
    if(LINKADDR_SIZE == 2) {
      params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE;
    } else {
      params.fcf.dest_addr_mode = FRAME802154_LONGADDRMODE;
    }
  }

  /* Set the source PAN ID to the global variable. */
  params.src_pid = frame802154_get_pan_id();

  /*
   * Set up the source address using only the long address mode for
   * phase 1.
   */
  linkaddr_copy((linkaddr_t *)&params.src_addr, &linkaddr_node_addr);

  params.payload = packetbuf_dataptr();
  params.payload_len = packetbuf_datalen();
  hdr_len = frame802154_hdrlen(&params);
  if(!do_create) {
    /* Only calculate header length */
    return hdr_len;
  } else if(packetbuf_hdralloc(hdr_len)) {
    frame802154_create(&params, packetbuf_hdrptr());

    PRINTF("15.4-OUT: %2X", params.fcf.frame_type);
    PRINTADDR(params.dest_addr);
    PRINTF("%d %u (%u)\n", hdr_len, packetbuf_datalen(), packetbuf_totlen());

    return hdr_len;
  } else {
    PRINTF("15.4-OUT: too large header: %u\n", hdr_len);
    return FRAMER_FAILED;
  }
}
Exemplo n.º 4
0
/*
 * Solution:
 * http://www.prenhall.com/divisions/bp/app/russellcd/PROTECT/CHAPTERS/CHAP10/REVIEWIT.HTM
 * y = a + bx - the regression
 * a = (sum (xy) - n * x_mean * y_mean) / (sum x*x - n * x_mean * x_mean)
 * b = y_mean - b x_mean
 *
 * We define:
 * y = estimated prr (packet received ratio) = cost
 * x = current rssi
 * x_mean = mean of rssi over a pre-defined time window
 * y_mean = mean prr over a pre-defined time wondow
 *
 *
 * */
void
c_lqe_linregr_recv(struct pipe *p, struct stackmodule_i *module){
	PRINTF("c_linregr_recv \n");

	uint16_t crtseqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);
	uint16_t rssi = packetbuf_attr(PACKETBUF_ATTR_RSSI);
	int16_t l = 0;

	uint8_t list_len = list_length(p->neighbor_list);
	struct c_neighbor *n;
	clock_time_t last_heard = 100000;
	struct c_neighbor *new_n = memb_alloc(&p->neighbor_mem);;
	rimeaddr_copy(&new_n->addr, get_node_addr(0, 1, 0));

	/* Find the neighbor. */
	for(n = list_head(p->neighbor_list); n != NULL; n = list_item_next(n)) {
	    if(rimeaddr_cmp(&new_n->addr, &n->addr)) {
	    	memcpy(new_n, n, sizeof (struct c_neighbor));
	    	PRINTF("node found \n");

	    	new_n->m = crtseqno - n->last_seq_no - 1; //the current seq number - last seq number - crt packet no
	    	if (new_n->m > n->k) {
	    		l = new_n->m - n->k;
	    		new_n->k = n->k;
	    	} else { l = 0; new_n->k = 0; }
	    	uint8_t lost_p; double delta;
	    	for(lost_p = 0; lost_p < l; lost_p++) {
	    		delta = 0 - n->prr;
	    		n->prr = n->prr + delta / (n->count + lost_p);
	        }
	    	delta = 1 - n->prr;
	        new_n->prr = n->prr + delta / (n->count + l);

	        new_n->xy = n->xy + rssi * n->count / (n->count + n->m );
	    	new_n->x_2 = n->x_2 + rssi * rssi;

	    	double b = (new_n->xy - new_n->count * new_n->rssi * new_n->prr) /
	    			(new_n->x_2 - new_n->count * new_n->rssi);
	    	double a = new_n->prr - b * n->rssi;

	    	new_n->cost = a + b * rssi;

	    	PRINTF("a %f b %f new_n_cost %f rssi %d\n", a, b, new_n->cost, rssi);

	    	list_remove(p->neighbor_list, n);
	    	memb_free(&p->neighbor_mem, n);
	    	list_push(p->neighbor_list, new_n);
	    	return;
	    }
	 }

	/*If neighbor is not in the list and list is full, remove from list before adding*/
	if (list_len >= NUM_NEIGHBOR_ENTRIES) {
		for(n = list_head(p->neighbor_list); n != NULL; n = list_item_next(n)) {
			if (last_heard == n->last_time_stamp) {
				list_remove(p->neighbor_list, n);
				memb_free(&p->neighbor_mem, n);
			}
		}
	}
	list_push(p->neighbor_list, new_n);
}
Exemplo n.º 5
0
/* This function goes through all encounters to see if it finds a
   matching neighbor. If so, we set a ctimer that will turn on the
   radio just before we expect the neighbor to send a probe packet. If
   we cannot find a matching encounter, we just turn on the radio.

   The outbound packet is put on either the pending_packets_list or
   the queued_packets_list, depending on if the packet should be sent
   immediately.
*/
static void
turn_radio_on_for_neighbor(rimeaddr_t *neighbor, struct queue_list_item *i)
{

#if WITH_STREAMING
  if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
     PACKETBUF_ATTR_PACKET_TYPE_STREAM) {
    is_streaming = 1;
    turn_radio_on();
    list_add(queued_packets_list, i);
    ctimer_set(&stream_off_timer, STREAM_OFF_TIME,
	       stream_off, NULL);
    return;
  }
#endif /* WITH_STREAMING */
  
  if(rimeaddr_cmp(neighbor, &rimeaddr_null)) {
#if ! WITH_PENDING_BROADCAST
    /* We have been asked to turn on the radio for a broadcast, so we
       just turn on the radio. */
    turn_radio_on();
#endif /* ! WITH_PENDING_BROADCAST */
    list_add(queued_packets_list, i);
    return;
  }

#if WITH_ENCOUNTER_OPTIMIZATION
  struct encounter *e;
  
  /* We go through the list of encounters to find if we have recorded
     an encounter with this particular neighbor. If so, we can compute
     the time for the next expected encounter and setup a ctimer to
     switch on the radio just before the encounter. */
  for(e = list_head(encounter_list); e != NULL; e = list_item_next(e)) {
    if(rimeaddr_cmp(neighbor, &e->neighbor)) {
      clock_time_t wait, now;

      /* We expect encounters to happen roughly every OFF_TIME time
	 units. The next expected encounter is at time e->time +
	 OFF_TIME. To compute a relative offset, we subtract with
	 clock_time(). Because we are only interested in turning on
	 the radio within the OFF_TIME period, we compute the waiting
	 time with modulo OFF_TIME. */

      now = clock_time();
      wait = (((clock_time_t)(e->time - now)) % (OFF_TIME + LISTEN_TIME)) -
        2 * LISTEN_TIME;

      /*      printf("now %d e %d e-n %d w %d %d\n", now, e->time, e->time - now, (e->time - now) % (OFF_TIME), wait);
      
      printf("Time now %lu last encounter %lu next expected encouter %lu wait %lu/%d (%lu)\n",
	     (1000ul * (unsigned long)now) / CLOCK_SECOND,
	     (1000ul * (unsigned long)e->time) / CLOCK_SECOND,
	     (1000ul * (unsigned long)(e->time + OFF_TIME)) / CLOCK_SECOND,
	     (1000ul * (unsigned long)wait) / CLOCK_SECOND, wait,
	     (1000ul * (unsigned long)(wait + now)) / CLOCK_SECOND);*/
      
      /*      printf("Neighbor %d.%d found encounter, waiting %d ticks\n",
	      neighbor->u8[0], neighbor->u8[1], wait);*/
      
      ctimer_set(&e->turn_on_radio_timer, wait, turn_radio_on_callback, i);
      list_add(pending_packets_list, i);
      return;
    }
  }
#endif /* WITH_ENCOUNTER_OPTIMIZATION */
  
  /* We did not find the neighbor in the list of recent encounters, so
     we just turn on the radio. */
  /*  printf("Neighbor %d.%d not found in recent encounters\n",
      neighbor->u8[0], neighbor->u8[1]);*/
  turn_radio_on();
  list_add(queued_packets_list, i);
  return;
}
Exemplo n.º 6
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 += num_transmissions;
    break;
  case MAC_TX_COLLISION:
    n->collisions += num_transmissions;
    break;
  case MAC_TX_DEFERRED:
    n->deferrals += num_transmissions;
    break;
  }

  /* Find out what packet this callback refers to */
  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);
      }
    }
  }
}
Exemplo n.º 7
0
/*---------------------------------------------------------------------------*/
static int
send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_list *buf_list)
{
  rtimer_clock_t t0;
  rtimer_clock_t encounter_time = 0;
  int strobes;
  uint8_t got_strobe_ack = 0;
  int hdrlen, len;
  uint8_t is_broadcast = 0;
  uint8_t is_reliable = 0;
  uint8_t is_known_receiver = 0;
  uint8_t collisions;
  int transmit_len;
  int ret;
  uint8_t contikimac_was_on;
  uint8_t seqno;
#if WITH_CONTIKIMAC_HEADER
  struct hdr *chdr;
#endif /* WITH_CONTIKIMAC_HEADER */

 /* Exit if RDC and radio were explicitly turned off */
   if (!contikimac_is_on && !contikimac_keep_radio_on) {
    PRINTF("contikimac: radio is turned off\n");
    return MAC_TX_ERR_FATAL;
  }
 
  if(packetbuf_totlen() == 0) {
    PRINTF("contikimac: send_packet data len 0\n");
    return MAC_TX_ERR_FATAL;
  }

  packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
  if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
    is_broadcast = 1;
    PRINTDEBUG("contikimac: send broadcast\n");

    if(broadcast_rate_drop()) {
      return MAC_TX_COLLISION;
    }
  } else {
#if UIP_CONF_IPV6
    PRINTDEBUG("contikimac: send unicast to %02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[2],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[3],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[4],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[5],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[6],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[7]);
#else /* UIP_CONF_IPV6 */
    PRINTDEBUG("contikimac: send unicast to %u.%u\n",
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1]);
#endif /* UIP_CONF_IPV6 */
  }
  is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
    packetbuf_attr(PACKETBUF_ATTR_ERELIABLE);

  packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);

#if WITH_CONTIKIMAC_HEADER
  hdrlen = packetbuf_totlen();
  if(packetbuf_hdralloc(sizeof(struct hdr)) == 0) {
    /* Failed to allocate space for contikimac header */
    PRINTF("contikimac: send failed, too large header\n");
    return MAC_TX_ERR_FATAL;
  }
  chdr = packetbuf_hdrptr();
  chdr->id = CONTIKIMAC_ID;
  chdr->len = hdrlen;
  
  /* Create the MAC header for the data packet. */
  hdrlen = NETSTACK_FRAMER.create();
  if(hdrlen < 0) {
    /* Failed to send */
    PRINTF("contikimac: send failed, too large header\n");
    packetbuf_hdr_remove(sizeof(struct hdr));
    return MAC_TX_ERR_FATAL;
  }
  hdrlen += sizeof(struct hdr);
#else
  /* Create the MAC header for the data packet. */
  hdrlen = NETSTACK_FRAMER.create();
  if(hdrlen < 0) {
    /* Failed to send */
    PRINTF("contikimac: send failed, too large header\n");
    return MAC_TX_ERR_FATAL;
  }
#endif


  /* Make sure that the packet is longer or equal to the shortest
     packet length. */
  transmit_len = packetbuf_totlen();
  if(transmit_len < SHORTEST_PACKET_SIZE) {
    /* Pad with zeroes */
    uint8_t *ptr;
    ptr = packetbuf_dataptr();
    memset(ptr + packetbuf_datalen(), 0, SHORTEST_PACKET_SIZE - packetbuf_totlen());

    PRINTF("contikimac: shorter than shortest (%d)\n", packetbuf_totlen());
    transmit_len = SHORTEST_PACKET_SIZE;
  }


  packetbuf_compact();

  NETSTACK_RADIO.prepare(packetbuf_hdrptr(), transmit_len);

  /* Remove the MAC-layer header since it will be recreated next time around. */
  packetbuf_hdr_remove(hdrlen);

  if(!is_broadcast && !is_receiver_awake) {
#if WITH_PHASE_OPTIMIZATION
    ret = phase_wait(&phase_list, packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                     CYCLE_TIME, GUARD_TIME,
                     mac_callback, mac_callback_ptr, buf_list);
    if(ret == PHASE_DEFERRED) {
      return MAC_TX_DEFERRED;
    }
    if(ret != PHASE_UNKNOWN) {
      is_known_receiver = 1;
    }
#endif /* WITH_PHASE_OPTIMIZATION */ 
  }
  


  /* By setting we_are_sending to one, we ensure that the rtimer
     powercycle interrupt do not interfere with us sending the packet. */
  we_are_sending = 1;

  /* If we have a pending packet in the radio, we should not send now,
     because we will trash the received packet. Instead, we signal
     that we have a collision, which lets the packet be received. This
     packet will be retransmitted later by the MAC protocol
     instread. */
  if(NETSTACK_RADIO.receiving_packet() || NETSTACK_RADIO.pending_packet()) {
    we_are_sending = 0;
    PRINTF("contikimac: collision receiving %d, pending %d\n",
           NETSTACK_RADIO.receiving_packet(), NETSTACK_RADIO.pending_packet());
    return MAC_TX_COLLISION;
  }
  
  /* Switch off the radio to ensure that we didn't start sending while
     the radio was doing a channel check. */
  off();


  strobes = 0;

  /* Send a train of strobes until the receiver answers with an ACK. */
  collisions = 0;

  got_strobe_ack = 0;

  /* Set contikimac_is_on to one to allow the on() and off() functions
     to control the radio. We restore the old value of
     contikimac_is_on when we are done. */
  contikimac_was_on = contikimac_is_on;
  contikimac_is_on = 1;

#if !RDC_CONF_HARDWARE_CSMA
    /* Check if there are any transmissions by others. */
    /* TODO: why does this give collisions before sending with the mc1322x? */
  if(is_receiver_awake == 0) {
	int i;
    for(i = 0; i < CCA_COUNT_MAX_TX; ++i) {
      t0 = RTIMER_NOW();
      on();
#if CCA_CHECK_TIME > 0
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + CCA_CHECK_TIME)) { }
#endif
      if(NETSTACK_RADIO.channel_clear() == 0) {
        collisions++;
        off();
        break;
      }
      off();
      t0 = RTIMER_NOW();
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + CCA_SLEEP_TIME)) { }
    }
  }

  if(collisions > 0) {
    we_are_sending = 0;
    off();
    PRINTF("contikimac: collisions before sending\n");
    contikimac_is_on = contikimac_was_on;
    return MAC_TX_COLLISION;
  }
#endif /* RDC_CONF_HARDWARE_CSMA */

#if !RDC_CONF_HARDWARE_ACK
  if(!is_broadcast) {
  /* Turn radio on to receive expected unicast ack.
      Not necessary with hardware ack detection, and may trigger an unnecessary cca or rx cycle */	 
     on();
  }
#endif

  watchdog_periodic();
  t0 = RTIMER_NOW();
  seqno = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO);
  for(strobes = 0, collisions = 0;
      got_strobe_ack == 0 && collisions == 0 &&
      RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + STROBE_TIME); strobes++) {

    watchdog_periodic();

    if((is_receiver_awake || is_known_receiver) && !RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + MAX_PHASE_STROBE_TIME)) {
      PRINTF("miss to %d\n", packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0]);
      break;
    }

    len = 0;


    {
      rtimer_clock_t wt;
      rtimer_clock_t txtime;
      int ret;

      txtime = RTIMER_NOW();
      ret = NETSTACK_RADIO.transmit(transmit_len);

#if RDC_CONF_HARDWARE_ACK
     /* For radios that block in the transmit routine and detect the ACK in hardware */
      if(ret == RADIO_TX_OK) {
        if(!is_broadcast) {
          got_strobe_ack = 1;
          encounter_time = txtime;
          break;
        }
      } else if (ret == RADIO_TX_NOACK) {
      } else if (ret == RADIO_TX_COLLISION) {
          PRINTF("contikimac: collisions while sending\n");
          collisions++;
      }
	  wt = RTIMER_NOW();
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }
#else
     /* Wait for the ACK packet */
      wt = RTIMER_NOW();
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }

      if(!is_broadcast && (NETSTACK_RADIO.receiving_packet() ||
                           NETSTACK_RADIO.pending_packet() ||
                           NETSTACK_RADIO.channel_clear() == 0)) {
        uint8_t ackbuf[ACK_LEN];
        wt = RTIMER_NOW();
        while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + AFTER_ACK_DETECTECT_WAIT_TIME)) { }

        len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
        if(len == ACK_LEN && seqno == ackbuf[ACK_LEN-1]) {
          got_strobe_ack = 1;
          encounter_time = txtime;
          break;
        } else {
          PRINTF("contikimac: collisions while sending\n");
          collisions++;
        }
      }
#endif /* RDC_CONF_HARDWARE_ACK */
    }
  }

  off();

  PRINTF("contikimac: send (strobes=%u, len=%u, %s, %s), done\n", strobes,
         packetbuf_totlen(),
         got_strobe_ack ? "ack" : "no ack",
         collisions ? "collision" : "no collision");

#if CONTIKIMAC_CONF_COMPOWER
  /* Accumulate the power consumption for the packet transmission. */
  compower_accumulate(&current_packet);

  /* Convert the accumulated power consumption for the transmitted
     packet to packet attributes so that the higher levels can keep
     track of the amount of energy spent on transmitting the
     packet. */
  compower_attrconv(&current_packet);

  /* Clear the accumulated power consumption so that it is ready for
     the next packet. */
  compower_clear(&current_packet);
#endif /* CONTIKIMAC_CONF_COMPOWER */

  contikimac_is_on = contikimac_was_on;
  we_are_sending = 0;

  /* Determine the return value that we will return from the
     function. We must pass this value to the phase module before we
     return from the function.  */
  if(collisions > 0) {
    ret = MAC_TX_COLLISION;
  } else if(!is_broadcast && !got_strobe_ack) {
    ret = MAC_TX_NOACK;
  } else {
    ret = MAC_TX_OK;
  }

#if WITH_PHASE_OPTIMIZATION

  if(is_known_receiver && got_strobe_ack) {
    PRINTF("no miss %d wake-ups %d\n", packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
           strobes);
  }

  if(!is_broadcast) {
    if(collisions == 0 && is_receiver_awake == 0) {
      phase_update(&phase_list, packetbuf_addr(PACKETBUF_ADDR_RECEIVER), encounter_time,
                   ret);
    }
  }
#endif /* WITH_PHASE_OPTIMIZATION */

  return ret;
}
Exemplo n.º 8
0
/*---------------------------------------------------------------------------*/
static void
send_packet(mac_callback_t sent, void *ptr)
{
  struct rdc_buf_list *q;
  struct neighbor_queue *n;
  const linkaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);

  /* 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 */
      linkaddr_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 */
    if(list_length(n->queued_packet_list) < CSMA_MAX_PACKET_PER_NEIGHBOR) {
      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_WITH_PACKET_TYPE
            if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
               PACKETBUF_ATTR_PACKET_TYPE_ACK) {
              list_push(n->queued_packet_list, q);
            } else
#endif
            {
              list_add(n->queued_packet_list, q);
            }

            PRINTF("csma: send_packet, queue length %d, free packets %d\n",
                   list_length(n->queued_packet_list), memb_numfree(&packet_memb));
            /* 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);
      }
    } else {
      PRINTF("csma: Neighbor queue full\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);
}
Exemplo n.º 9
0
/*---------------------------------------------------------------------------*/
static int
create_frame(int type, int do_create)
{

	frame802154_t params;
	int hdr_len;

	/* init to zeros */
	memset(&params, 0, sizeof(params));

	if(!initialized) {
		initialized = 1;
		mac_dsn = random_rand()*linkaddr_node_addr.u8[7];
	}
	/* Build the FCF. */

	params.fcf.frame_type = type;
	params.fcf.frame_pending = packetbuf_attr(PACKETBUF_ATTR_PENDING);
	params.fcf.timestamp_flag= packetbuf_attr( PACKETBUF_ATTR_NODE_TIMESTAMP_FLAG);
	params.fcf.rand_seed_flag = packetbuf_attr( PACKETBUF_ATTR_NODE_RAND_SEED_FLAG);
	params.fcf.state_flag =packetbuf_attr( PACKETBUF_ATTR_NODE_STATE_FLAG);
	if(packetbuf_holds_broadcast()) {
		params.fcf.ack_required = 0;
	} else {
		params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_MAC_ACK);
	}
	params.fcf.panid_compression = 0;

	/* Insert IEEE 802.15.4 (2006) version bits. */
	params.fcf.frame_version = FRAME802154_IEEE802154_2006;

#if LLSEC802154_SECURITY_LEVEL
	if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL)) {
		params.fcf.security_enabled = 1;
	}
	/* Setting security-related attributes */
	params.aux_hdr.security_control.security_level = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL);
	params.aux_hdr.frame_counter.u16[0] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1);
	params.aux_hdr.frame_counter.u16[1] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3);
#if LLSEC802154_USES_EXPLICIT_KEYS
	params.aux_hdr.security_control.key_id_mode = packetbuf_attr(PACKETBUF_ATTR_KEY_ID_MODE);
	params.aux_hdr.key_index = packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX);
	params.aux_hdr.key_source.u16[0] = packetbuf_attr(PACKETBUF_ATTR_KEY_SOURCE_BYTES_0_1);
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
#endif /* LLSEC802154_SECURITY_LEVEL */

	/* Increment and set the data sequence number. */
	if(!do_create || type==0 ) {
		/* Only length calculation - no sequence number is needed and
       should not be consumed. */

	} else if(packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) {
		params.seq = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO);

	} else {
		/* Ensure that the sequence number 0 is not used as it would bypass the above check. */
		if(mac_dsn == 0) {
			mac_dsn++;
		}
		params.seq = mac_dsn++;
		packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, params.seq);
	}

	/* Complete the addressing fields. */
	/**
     \todo For phase 1 the addresses are all long. We'll need a mechanism
     in the rime attributes to tell the mac to use long or short for phase 2.
	 */
	if(LINKADDR_SIZE == 2) {
		/* Use short address mode if linkaddr size is short. */
		params.fcf.src_addr_mode = FRAME802154_SHORTADDRMODE;
	} else {
		params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE;
	}
	params.dest_pid = mac_dst_pan_id;

	if(packetbuf_holds_broadcast()) {
		/* Broadcast requires short address mode. */
		params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE;
		params.dest_addr[0] = 0xFF;
		params.dest_addr[1] = 0xFF;

	} else {
		linkaddr_copy((linkaddr_t *)&params.dest_addr,
				packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
		/* Use short address mode if linkaddr size is small */
		if(LINKADDR_SIZE == 2) {
			params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE;
		} else {
			params.fcf.dest_addr_mode = FRAME802154_LONGADDRMODE;
		}
	}

	/* Set the source PAN ID to the global variable. */
	params.src_pid = mac_src_pan_id;

	/*
	 * Set up the source address using only the long address mode for
	 * phase 1.
	 */
	linkaddr_copy((linkaddr_t *)&params.src_addr, &linkaddr_node_addr);

	/* Set the timestamp*/
	if(params.fcf.timestamp_flag){
		params.timestamp=packetbuf_attr(PACKETBUF_ATTR_NODE_TIMESTAMP);
		params.clock_time=packetbuf_attr(PACKETBUF_ATTR_NODE_CLOCK_TIME);
	}

	/*Set the random seed*/
	if(params.fcf.rand_seed_flag)
		params.random_seed=packetbuf_attr(PACKETBUF_ATTR_NODE_RAND_SEED);

	/*Set the blacklist*/
	if(params.fcf.frame_type==0)
		params.blacklist=packetbuf_attr(PACKETBUF_ATTR_NODE_BLACKLIST);

	params.payload = packetbuf_dataptr();
	params.payload_len = packetbuf_datalen();

	hdr_len = frame_emmac_hdrlen(&params);
	if(!do_create) {
		/* Only calculate header length */
		return hdr_len;

	} else if(packetbuf_hdralloc(hdr_len)) {
		frame_emmac_create(&params, packetbuf_hdrptr());

		PRINTF("15.4-OUT: %2X", params.fcf.frame_type);
		PRINTADDR(params.dest_addr);
		PRINTF("%d %u (%u)\n", hdr_len, packetbuf_datalen(), packetbuf_totlen());

		return hdr_len;
	} else {
		printf("15.4-OUT: too large header: %u\n", hdr_len);
		return FRAMER_FAILED;
	}
}
Exemplo n.º 10
0
Arquivo: xmac.c Projeto: aiss83/nucbit
/*---------------------------------------------------------------------------*/
static void
input_packet(void)
{
    struct xmac_hdr *hdr;

    if(NETSTACK_FRAMER.parse() >= 0)
    {
        hdr = packetbuf_dataptr();

        if(hdr->dispatch != DISPATCH)
        {
            someone_is_sending = 0;
            if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                            &rimeaddr_node_addr) ||
                    rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                                 &rimeaddr_null))
            {
                /* This is a regular packet that is destined to us or to the
                   broadcast address. */

                /* We have received the final packet, so we can go back to being
                   asleep. */
                off();

                /* Check for duplicate packet by comparing the sequence number
                   of the incoming packet with the last few ones we saw. */
                {
                    int i;
                    for(i = 0; i < MAX_SEQNOS; ++i)
                    {
                        if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == received_seqnos[i].seqno &&
                                rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER),
                                             &received_seqnos[i].sender))
                        {
                            /* Drop the packet. */
                            return;
                        }
                    }
                    for(i = MAX_SEQNOS - 1; i > 0; --i)
                    {
                        memcpy(&received_seqnos[i], &received_seqnos[i - 1],
                               sizeof(struct seqno));
                    }
                    received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);
                    rimeaddr_copy(&received_seqnos[0].sender,
                                  packetbuf_addr(PACKETBUF_ADDR_SENDER));
                }

#if XMAC_CONF_COMPOWER
                /* Accumulate the power consumption for the packet reception. */
                compower_accumulate(&current_packet);
                /* Convert the accumulated power consumption for the received
                   packet to packet attributes so that the higher levels can
                   keep track of the amount of energy spent on receiving the
                   packet. */
                compower_attrconv(&current_packet);

                /* Clear the accumulated power consumption so that it is ready
                   for the next packet. */
                compower_clear(&current_packet);
#endif /* XMAC_CONF_COMPOWER */

                waiting_for_packet = 0;

                PRINTDEBUG("xmac: data(%u)\n", packetbuf_datalen());
                NETSTACK_MAC.input();
                return;
            }
            else
            {
                PRINTDEBUG("xmac: data not for us\n");
            }

        }
        else if(hdr->type == TYPE_STROBE)
        {
            someone_is_sending = 2;

            if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                            &rimeaddr_node_addr))
            {
                /* This is a strobe packet for us. */

                /* If the sender address is someone else, we should
                   acknowledge the strobe and wait for the packet. By using
                   the same address as both sender and receiver, we flag the
                   message is a strobe ack. */
                waiting_for_packet = 1;
#if 0
                hdr->type = TYPE_STROBE_ACK;
                packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER,
                                   packetbuf_addr(PACKETBUF_ADDR_SENDER));
                packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
                packetbuf_compact();
                if(NETSTACK_FRAMER.create() >= 0)
                {
                    /* We turn on the radio in anticipation of the incoming
                       packet. */
                    someone_is_sending = 1;
                    waiting_for_packet = 1;
                    on();
                    NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
                    PRINTDEBUG("xmac: send strobe ack %u\n", packetbuf_totlen());
                }
                else
                {
                    PRINTF("xmac: failed to send strobe ack\n");
                }
#endif /* 0 */
            }
            else if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                                 &rimeaddr_null))
            {
                /* If the receiver address is null, the strobe is sent to
                   prepare for an incoming broadcast packet. If this is the
                   case, we turn on the radio and wait for the incoming
                   broadcast packet. */
                waiting_for_packet = 1;
                on();
            }
            else
            {
                PRINTDEBUG("xmac: strobe not for us\n");
            }

            /* We are done processing the strobe and we therefore return
            	 to the caller. */
            return;
#if XMAC_CONF_ANNOUNCEMENTS
        }
        else if(hdr->type == TYPE_ANNOUNCEMENT)
        {
            packetbuf_hdrreduce(sizeof(struct xmac_hdr));
            parse_announcements(packetbuf_addr(PACKETBUF_ADDR_SENDER));
#endif /* XMAC_CONF_ANNOUNCEMENTS */
        }
        else if(hdr->type == TYPE_STROBE_ACK)
        {
            PRINTDEBUG("xmac: stray strobe ack\n");
        }
        else
        {
            PRINTF("xmac: unknown type %u (%u/%u)\n", hdr->type,
                   packetbuf_datalen(), len);
        }
    }
    else
    {
        PRINTF("xmac: failed to parse (%u)\n", packetbuf_totlen());
    }
}
Exemplo n.º 11
0
/* contiki mac driver functions */
void /* put packet into transmit buffer */
ieee_send(mac_callback_t cb, void *ptr)
{
  MAC_McpsReqRsp_s    req;
  MAC_McpsSyncCfm_s   cfm;

  if(!ieee_started)
    return;

  mac_cb = cb;
  mac_cb_ptr = ptr;

  /* check buffer size */
  if(packetbuf_datalen() > MAC_MAX_DATA_PAYLOAD_LEN)
    return;

  /* prepare packet request */
  req.u8Type = MAC_MCPS_REQ_DATA;
  req.u8ParamLength = sizeof(MAC_McpsReqData_s);
  req.uParam.sReqData.u8Handle = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);
  req.uParam.sReqData.sFrame.u8TxOptions = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ? MAC_TX_OPTION_ACK : 0;

  /* fill in destination address. */
  if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null))
  {
    req.uParam.sReqData.sFrame.sDstAddr.u8AddrMode     = SHORT;
    req.uParam.sReqData.sFrame.sDstAddr.u16PanId       = BROADCAST_PANID;
    req.uParam.sReqData.sFrame.sDstAddr.uAddr.u16Short = BROADCAST_ADDR;
  }
  else
  {
    req.uParam.sReqData.sFrame.sDstAddr.u8AddrMode      = LONG;
    req.uParam.sReqData.sFrame.sDstAddr.u16PanId        = IEEE802154_PANDID;
    req.uParam.sReqData.sFrame.sDstAddr.uAddr.sExt.u32H =
      ((MAC_ExtAddr_s*) packetbuf_addr(PACKETBUF_ADDR_RECEIVER))->u32L;
    req.uParam.sReqData.sFrame.sDstAddr.uAddr.sExt.u32L =
      ((MAC_ExtAddr_s*) packetbuf_addr(PACKETBUF_ADDR_RECEIVER))->u32H;
  }

  /* fill in source address */
  req.uParam.sReqData.sFrame.sSrcAddr.u8AddrMode      = LONG;
  req.uParam.sReqData.sFrame.sSrcAddr.u16PanId        = IEEE802154_PANDID;
  req.uParam.sReqData.sFrame.sSrcAddr.uAddr.sExt.u32H =
    ((MAC_ExtAddr_s*) ieee_get_mac())->u32L;
  req.uParam.sReqData.sFrame.sSrcAddr.uAddr.sExt.u32L =
    ((MAC_ExtAddr_s*) ieee_get_mac())->u32H;

//  printf("mac addr: 0x%x%x 0x%x lladdr: 0x%x%x%x%x%x%x%x%x 0x%x%x\n",
//                                    *((uint32_t*) pvAppApiGetMacAddrLocation()),
//                                    *((uint32_t*) pvAppApiGetMacAddrLocation()+1),
//                                    pvAppApiGetMacAddrLocation(),
//                                    (int) uip_lladdr.addr[0],
//                                    (int) uip_lladdr.addr[1],
//                                    (int) uip_lladdr.addr[2],
//                                    (int) uip_lladdr.addr[3],
//                                    (int) uip_lladdr.addr[4],
//                                    (int) uip_lladdr.addr[5],
//                                    (int) uip_lladdr.addr[6],
//                                    (int) uip_lladdr.addr[7],
//                                    *((uint32_t*) uip_lladdr.addr),
//                                    *((uint32_t*) uip_lladdr.addr+1));

  /* copy over payload */
  req.uParam.sReqData.sFrame.u8SduLength = packetbuf_datalen();
  memcpy( req.uParam.sReqData.sFrame.au8Sdu, packetbuf_dataptr(),
          MIN(packetbuf_datalen(), MAC_MAX_DATA_PAYLOAD_LEN) );

  while (bTACframeInProgress())
    ;

  GDB2_PUTS(".");
  vAppApiMcpsRequest(&req, &cfm);

  switch(cfm.u8Status) {
    case MAC_MCPS_CFM_OK:
      mac_call_sent_callback(mac_cb, mac_cb_ptr, MAC_TX_OK, 1);
      break;
    case MAC_MCPS_CFM_DEFERRED:
      mac_call_sent_callback(mac_cb, mac_cb_ptr, MAC_TX_DEFERRED, 1);
      break;
    default:
      mac_call_sent_callback(mac_cb, mac_cb_ptr, MAC_TX_ERR, 1);
      break;
  }

  return;
}
Exemplo n.º 12
0
void
c_lqe_ewma_recv(struct pipe *p, struct stackmodule_i *module){
	PRINTF("c_lqe_ewma_recv seqno %u \n", packetbuf_attr(PACKETBUF_ATTR_PACKET_ID));

	uint16_t crtseqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);
	int16_t l = 0;

	struct c_neighbor *n;
	struct c_neighbor *new_n = memb_alloc(&p->neighbor_mem);;
	rimeaddr_copy(&new_n->addr, get_node_addr(0, 1, 0));
	double alpha = p->lqe_ewma_param.alpha;
	uint8_t list_len = list_length(p->neighbor_list);

	double highest_cost = 100.0;
	/* Find the neighbor. */
	for(n = list_head(p->neighbor_list); n != NULL; n = list_item_next(n)) {
	    if(rimeaddr_cmp(&new_n->addr, &n->addr)) {
	    	if (highest_cost > n->cost) { highest_cost = n->cost; }

	    	PRINTF("node found \n");
	    	PRINTF("n-lastseqno %d n-m %d n-k %d\n", n->last_seq_no, n->m, n->k);

	    	new_n->m = crtseqno - n->last_seq_no - 1; //the current seq number - last seq number - crt packet no
	    	if (new_n->m > n->k) {
	    		l = new_n->m - n->k;
	    		new_n->k = n->k;
	    	} else { l = 0; new_n->k = 0; }

	    	PRINTF("newn-lastseqno %d newn-m %d newn-k %d\n", new_n->last_seq_no, new_n->m, new_n->k);

	    	uint8_t lost_p;
	    	for(lost_p = 0; lost_p < l; lost_p++) {	n->cost *= alpha; }
	    	new_n->cost = n->cost * alpha + (1 - alpha);
	    	PRINTF("l %d cost %f\n", l, new_n->cost);

	    	if (n->count_lock == 1) {
	    		new_n->count = n->count;
	    	} else { new_n->count = n->count + 1; }
	    	new_n->first_time_stamp = n->first_time_stamp;
	    	new_n->last_seq_no = crtseqno;
	    	new_n->last_time_stamp = clock_time();
	    	new_n->rate = (new_n->count + new_n->m) / (new_n->last_time_stamp - new_n->first_time_stamp);
	    	new_n->cost_lock = 1;

	    	list_remove(p->neighbor_list, n);
	    	memb_free(&p->neighbor_mem, n);
	    	list_push(p->neighbor_list, new_n);
	    	print_list(p->neighbor_list);

	    	return;
	    }
	 }

	new_n->count = 1;
	new_n->cost = 1;
	new_n->m = 0;
	new_n->k = 0;
	new_n->last_seq_no = crtseqno;
	new_n->rate = 1 / clock_time();
	new_n->last_time_stamp = clock_time();
	new_n->cost_lock = 1;
	new_n->first_time_stamp = new_n->last_time_stamp;

	/*If neighbor is not in the list and list is full, remove from list before adding*/
	if (list_len >= NUM_NEIGHBOR_ENTRIES) {
		for(n = list_head(p->neighbor_list); n != NULL; n = list_item_next(n)) {
			if (highest_cost == n->cost) {
				list_remove(p->neighbor_list, n);
				memb_free(&p->neighbor_mem, n);
			}
		}
	}
	list_push(p->neighbor_list, new_n);
	print_list(p->neighbor_list);
}
/*---------------------------------------------------------------------------*/
static void
send_packet(mac_callback_t sent, void *ptr)
{
  struct rdc_buf_list *q;
  struct neighbor_queue *n;
  static uint16_t seqno;

  packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++);
  
  /* If the packet is a broadcast, do not allocate a queue
     entry. Instead, just send it out.  */
  if(!rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),&rimeaddr_null)) {
    const rimeaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);

    /* 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 */
        n->queued_packet_list = ttc_list_create((const char*)n->queued_packet_list);
        ttc_list_init(n->queued_packet_list, (const char*)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);
  } else {
    PRINTF("csma: send broadcast\n");
    NETSTACK_RDC.send(sent, ptr);
  }
}
Exemplo n.º 14
0
/* This function is called whenever a broadcast message is received. */
static void
broadcast_recv(struct broadcast_conn *c, const linkaddr_t *from)
{
  struct neighbor *n;
  struct broadcast_message *m;
  uint8_t seqno_gap;

  /* The packetbuf_dataptr() returns a pointer to the first data byte
     in the received packet. */
  m = packetbuf_dataptr();

  /* Check if we already know this neighbor. */
  for(n = list_head(neighbors_list); n != NULL; n = list_item_next(n)) {

    /* We break out of the loop if the address of the neighbor matches
       the address of the neighbor from which we received this
       broadcast message. */
    if(linkaddr_cmp(&n->addr, from)) {
      break;
    }
  }

  /* If n is NULL, this neighbor was not found in our list, and we
     allocate a new struct neighbor from the neighbors_memb memory
     pool. */
  if(n == NULL) {
    n = memb_alloc(&neighbors_memb);

    /* If we could not allocate a new neighbor entry, we give up. We
       could have reused an old neighbor entry, but we do not do this
       for now. */
    if(n == NULL) {
      return;
    }

    /* Initialize the fields. */
    linkaddr_copy(&n->addr, from);
    n->last_seqno = m->seqno - 1;
    n->avg_seqno_gap = SEQNO_EWMA_UNITY;

    /* Place the neighbor on the neighbor list. */
    list_add(neighbors_list, n);
  }

  /* We can now fill in the fields in our neighbor entry. */
  n->last_rssi = packetbuf_attr(PACKETBUF_ATTR_RSSI);
  n->last_lqi = packetbuf_attr(PACKETBUF_ATTR_LINK_QUALITY);

  /* Compute the average sequence number gap we have seen from this neighbor. */
  seqno_gap = m->seqno - n->last_seqno;
  n->avg_seqno_gap = (((uint32_t)seqno_gap * SEQNO_EWMA_UNITY) *
                      SEQNO_EWMA_ALPHA) / SEQNO_EWMA_UNITY +
                      ((uint32_t)n->avg_seqno_gap * (SEQNO_EWMA_UNITY -
                                                     SEQNO_EWMA_ALPHA)) /
    SEQNO_EWMA_UNITY;

  /* Remember last seqno we heard. */
  n->last_seqno = m->seqno;

  /* Print out a message. */
  printf("broadcast message received from %d.%d with seqno %d, RSSI %u, LQI %u, avg seqno gap %d.%02d\n",
         from->u8[0], from->u8[1],
         m->seqno,
         packetbuf_attr(PACKETBUF_ATTR_RSSI),
         packetbuf_attr(PACKETBUF_ATTR_LINK_QUALITY),
         (int)(n->avg_seqno_gap / SEQNO_EWMA_UNITY),
         (int)(((100UL * n->avg_seqno_gap) / SEQNO_EWMA_UNITY) % 100));
}
Exemplo n.º 15
0
/*---------------------------------------------------------------------------*/
static void
input_packet(void)
{
  static struct ctimer ct;
  int duplicate = 0;

#if CONTIKIMAC_SEND_SW_ACK
  int original_datalen;
  uint8_t *original_dataptr;

  original_datalen = packetbuf_datalen();
  original_dataptr = packetbuf_dataptr();
#endif

  if(!we_are_receiving_burst) {
    off();
  }

  if(packetbuf_datalen() == ACK_LEN) {
    /* Ignore ack packets */
    PRINTF("ContikiMAC: ignored ack\n");
    return;
  }

  /*  printf("cycle_start 0x%02x 0x%02x\n", cycle_start, cycle_start % CYCLE_TIME);*/

  if(packetbuf_totlen() > 0 && NETSTACK_FRAMER.parse() >= 0) {
    if(packetbuf_datalen() > 0 &&
       packetbuf_totlen() > 0 &&
       (linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                     &linkaddr_node_addr) ||
        packetbuf_holds_broadcast())) {
      /* This is a regular packet that is destined to us or to the
         broadcast address. */

      /* If FRAME_PENDING is set, we are receiving a packets in a burst */
      we_are_receiving_burst = packetbuf_attr(PACKETBUF_ATTR_PENDING);
      if(we_are_receiving_burst) {
        on();
        /* Set a timer to turn the radio off in case we do not receive
	   a next packet */
        ctimer_set(&ct, INTER_PACKET_DEADLINE, recv_burst_off, NULL);
      } else {
        off();
        ctimer_stop(&ct);
      }

#if RDC_WITH_DUPLICATE_DETECTION
      /* Check for duplicate packet. */
      duplicate = mac_sequence_is_duplicate();
      if(duplicate) {
        /* Drop the packet. */
        PRINTF("contikimac: Drop duplicate\n");
      } else {
        mac_sequence_register_seqno();
      }
#endif /* RDC_WITH_DUPLICATE_DETECTION */

#if CONTIKIMAC_CONF_COMPOWER
      /* Accumulate the power consumption for the packet reception. */
      compower_accumulate(&current_packet);
      /* Convert the accumulated power consumption for the received
         packet to packet attributes so that the higher levels can
         keep track of the amount of energy spent on receiving the
         packet. */
      compower_attrconv(&current_packet);

      /* Clear the accumulated power consumption so that it is ready
         for the next packet. */
      compower_clear(&current_packet);
#endif /* CONTIKIMAC_CONF_COMPOWER */

      PRINTDEBUG("contikimac: data (%u)\n", packetbuf_datalen());

#if CONTIKIMAC_SEND_SW_ACK
      {
        frame802154_t info154;
        frame802154_parse(original_dataptr, original_datalen, &info154);
        if(info154.fcf.frame_type == FRAME802154_DATAFRAME &&
            info154.fcf.ack_required != 0 &&
            linkaddr_cmp((linkaddr_t *)&info154.dest_addr,
                &linkaddr_node_addr)) {
          uint8_t ackdata[ACK_LEN] = {0, 0, 0};

          we_are_sending = 1;
          ackdata[0] = FRAME802154_ACKFRAME;
          ackdata[1] = 0;
          ackdata[2] = info154.seq;
          NETSTACK_RADIO.send(ackdata, ACK_LEN);
          we_are_sending = 0;
        }
      }
#endif /* CONTIKIMAC_SEND_SW_ACK */

      if(!duplicate) {
        NETSTACK_MAC.input();
      }
      return;
    } else {
      PRINTDEBUG("contikimac: data not for us\n");
    }
  } else {
    PRINTF("contikimac: failed to parse (%u)\n", packetbuf_totlen());
  }
}
Exemplo n.º 16
0
/* Create an EB packet */
int
tsch_packet_create_eb(uint8_t *buf, int buf_size, uint8_t seqno,
                      uint8_t *hdr_len, uint8_t *tsch_sync_ie_offset)
{
    int ret = 0;
    uint8_t curr_len = 0;
    uint8_t mlme_ie_offset;

    frame802154_t p;
    struct ieee802154_ies ies;

    if(buf_size < TSCH_PACKET_MAX_LEN) {
        return 0;
    }

    /* Create 802.15.4 header */
    memset(&p, 0, sizeof(p));
    p.fcf.frame_type = FRAME802154_BEACONFRAME;
    p.fcf.ie_list_present = 1;
    p.fcf.frame_version = FRAME802154_IEEE802154E_2012;
    p.fcf.src_addr_mode = LINKADDR_SIZE > 2 ? FRAME802154_LONGADDRMODE : FRAME802154_SHORTADDRMODE;
    p.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE;
    p.seq = seqno;
    p.fcf.sequence_number_suppression = FRAME802154_SUPPR_SEQNO;
    /* It is important not to compress PAN ID, as this would result in not including either
     * source nor destination PAN ID, leaving potential joining devices unaware of the PAN ID. */
    p.fcf.panid_compression = 0;

    p.src_pid = frame802154_get_pan_id();
    p.dest_pid = frame802154_get_pan_id();
    linkaddr_copy((linkaddr_t *)&p.src_addr, &linkaddr_node_addr);
    p.dest_addr[0] = 0xff;
    p.dest_addr[1] = 0xff;

#if LLSEC802154_ENABLED
    if(tsch_is_pan_secured) {
        p.fcf.security_enabled = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) > 0;
        p.aux_hdr.security_control.security_level = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL);
        p.aux_hdr.security_control.key_id_mode = packetbuf_attr(PACKETBUF_ATTR_KEY_ID_MODE);
        p.aux_hdr.security_control.frame_counter_suppression = 1;
        p.aux_hdr.security_control.frame_counter_size = 1;
        p.aux_hdr.key_index = packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX);
    }
#endif /* LLSEC802154_ENABLED */

    if((curr_len = frame802154_create(&p, buf)) == 0) {
        return 0;
    }

    /* Prepare Information Elements for inclusion in the EB */
    memset(&ies, 0, sizeof(ies));

    /* Add TSCH timeslot timing IE. */
#if TSCH_PACKET_EB_WITH_TIMESLOT_TIMING
    {
        int i;
        ies.ie_tsch_timeslot_id = 1;
        for(i = 0; i < tsch_ts_elements_count; i++) {
            ies.ie_tsch_timeslot[i] = RTIMERTICKS_TO_US(tsch_timing[i]);
        }
    }
#endif /* TSCH_PACKET_EB_WITH_TIMESLOT_TIMING */

    /* Add TSCH hopping sequence IE */
#if TSCH_PACKET_EB_WITH_HOPPING_SEQUENCE
    if(tsch_hopping_sequence_length.val <= sizeof(ies.ie_hopping_sequence_list)) {
        ies.ie_channel_hopping_sequence_id = 1;
        ies.ie_hopping_sequence_len = tsch_hopping_sequence_length.val;
        memcpy(ies.ie_hopping_sequence_list, tsch_hopping_sequence, ies.ie_hopping_sequence_len);
    }
#endif /* TSCH_PACKET_EB_WITH_HOPPING_SEQUENCE */

    /* Add Slotframe and Link IE */
#if TSCH_PACKET_EB_WITH_SLOTFRAME_AND_LINK
    {
        /* Send slotframe 0 with link at timeslot 0 */
        struct tsch_slotframe *sf0 = tsch_schedule_get_slotframe_by_handle(0);
        struct tsch_link *link0 = tsch_schedule_get_link_by_timeslot(sf0, 0);
        if(sf0 && link0) {
            ies.ie_tsch_slotframe_and_link.num_slotframes = 1;
            ies.ie_tsch_slotframe_and_link.slotframe_handle = sf0->handle;
            ies.ie_tsch_slotframe_and_link.slotframe_size = sf0->size.val;
            ies.ie_tsch_slotframe_and_link.num_links = 1;
            ies.ie_tsch_slotframe_and_link.links[0].timeslot = link0->timeslot;
            ies.ie_tsch_slotframe_and_link.links[0].channel_offset = link0->channel_offset;
            ies.ie_tsch_slotframe_and_link.links[0].link_options = link0->link_options;
        }
    }
#endif /* TSCH_PACKET_EB_WITH_SLOTFRAME_AND_LINK */

    /* First add header-IE termination IE to stipulate that next come payload IEs */
    if((ret = frame80215e_create_ie_header_list_termination_1(buf + curr_len, buf_size - curr_len, &ies)) == -1) {
        return -1;
    }
    curr_len += ret;

    /* We start payload IEs, save offset */
    if(hdr_len != NULL) {
        *hdr_len = curr_len;
    }

    /* Save offset of the MLME IE descriptor, we need to know the total length
     * before writing it */
    mlme_ie_offset = curr_len;
    curr_len += 2; /* Space needed for MLME descriptor */

    /* Save the offset of the TSCH Synchronization IE, needed to update ASN and join priority before sending */
    if(tsch_sync_ie_offset != NULL) {
        *tsch_sync_ie_offset = curr_len;
    }
    if((ret = frame80215e_create_ie_tsch_synchronization(buf + curr_len, buf_size - curr_len, &ies)) == -1) {
        return -1;
    }
    curr_len += ret;

    if((ret = frame80215e_create_ie_tsch_timeslot(buf + curr_len, buf_size - curr_len, &ies)) == -1) {
        return -1;
    }
    curr_len += ret;

    if((ret = frame80215e_create_ie_tsch_channel_hopping_sequence(buf + curr_len, buf_size - curr_len, &ies)) == -1) {
        return -1;
    }
    curr_len += ret;

    if((ret = frame80215e_create_ie_tsch_slotframe_and_link(buf + curr_len, buf_size - curr_len, &ies)) == -1) {
        return -1;
    }
    curr_len += ret;

    ies.ie_mlme_len = curr_len - mlme_ie_offset - 2;
    if((ret = frame80215e_create_ie_mlme(buf + mlme_ie_offset, buf_size - mlme_ie_offset, &ies)) == -1) {
        return -1;
    }

    /* Payload IE list termination: optional */
    /*
    if((ret = frame80215e_create_ie_payload_list_termination(buf + curr_len, buf_size - curr_len, &ies)) == -1) {
      return -1;
    }
    curr_len += ret;
    */

    return curr_len;
}
Exemplo n.º 17
0
//APP Callback function
static void app_recv(void)
{
	PROCESS_CONTEXT_BEGIN(&null_app_process);

	uint8_t *data = packetbuf_dataptr();

	rimeaddr_t *sent_sn_addr = packetbuf_addr(PACKETBUF_ADDR_SENDER);

	uint8_t rx_sn_id = sent_sn_addr->u8[0];
	uint8_t pkt_seq = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);
	uint8_t payload_len = packetbuf_datalen();

/*
	If this node is base station, then print out received messages.

	The current print function prints the output in ASCII code because
	the execution time can be reduced significantly. If the execution
	time is not a constraint, then printf should work as well.

	Please see readUSB_MPU6050_BS.py
*/

	if(node_id == 0)
	{
		//start byte
		putchar(126);
		putchar(126);

		// packet information

		packet_counter = packet_counter + 1;
		packet_counter = ((packet_counter == 10) ? 11 : packet_counter);

		 putchar(rx_sn_id);
		 putchar(packet_counter);
		 putchar(pkt_seq);
		 putchar(payload_len);
		//putchar(0);

		// //printf("%u",rx_sn_id);
		uint8_t i = 0;

		for(i = 0; i < (payload_len); i++)
		{
			//printf("%d,",((data[2*i+1]<<8)|data[2*i]));
			putchar(data[i]);
		}



	}



	uart1_writeb('\n');
	uart1_writeb('\n');


	PROCESS_CONTEXT_END(&null_app_process);

}
Exemplo n.º 18
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;
}
Exemplo n.º 19
0
/*---------------------------------------------------------------------------*/
static void
send_packet(mac_callback_t sent, void *ptr)
{
  struct rdc_buf_list *q;
  struct neighbor_queue *n;
  static uint8_t initialized = 0;
  static uint16_t seqno;
  const linkaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);

  if(!initialized) {
    initialized = 1;
    /* Initialize the sequence number to a random value as per 802.15.4. */
    seqno = random_rand();
  }

  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 */
      linkaddr_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);
}
Exemplo n.º 20
0
/* Attempt to associate to a network form an incoming EB */
static int
tsch_associate(rtimer_clock_t timestamp)
{
  struct ieee802154_ies ies;
  uint8_t hdrlen;
  int i;

  if(NETSTACK_FRAMER.parse() == FRAMER_FAILED) {
    PRINTF("TSCH:! framer failed to parse EB (len %u)\n", packetbuf_totlen());
    return 0;
  }

  if(tsch_packet_parse_eb(&ies, &hdrlen, 0) == 0) {
    PRINTF("TSCH:! tsch_packet_parse_eb failed to parse EB (len %u)\n", packetbuf_totlen());
    return 0;
  }

  tsch_current_asn = ies.ie_asn;
  tsch_join_priority = ies.ie_join_priority + 1;

#if TSCH_JOIN_SECURED_ONLY
  if(!packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL)) {
    PRINTF("TSCH:! parse_eb: EB is not secured\n");
    return 0;
  }
#endif /* TSCH_JOIN_SECURED_ONLY */
  
#if LLSEC802154_ENABLED
  if(!tsch_security_parse_frame(packetbuf_hdrptr(), hdrlen,
      packetbuf_totlen() - hdrlen - tsch_security_mic_len(),
      packetbuf_addr(PACKETBUF_ADDR_SENDER), &tsch_current_asn)) {
    PRINTF("TSCH:! parse_eb: failed to authenticate\n");
    return 0;
  }
#endif /* LLSEC802154_ENABLED */

#if TSCH_JOIN_MY_PANID_ONLY
  /* Check if the EB comes from the PAN ID we expect */
  if(packetbuf_attr(PACKETBUF_ATTR_SOURCE_PANID) != IEEE802154_PANID) {
    PRINTF("TSCH:! parse_eb: PAN ID %x != %x\n", packetbuf_attr(PACKETBUF_ATTR_SOURCE_PANID), IEEE802154_PANID);
    return 0;
  }
#endif /* TSCH_JOIN_MY_PANID_ONLY */

  /* There was no join priority (or 0xff) in the EB, do not join */
  if(ies.ie_join_priority == 0xff) {
    PRINTF("TSCH:! parse_eb: no join priority\n");
    return 0;
  }

  /* TSCH timeslot timing */
  for(i = 0; i < tsch_ts_elements_count; i++) {
    if(ies.ie_tsch_timeslot_id == 0) {
      tsch_timing[i] = US_TO_RTIMERTICKS(tsch_default_timing_us[i]);
    } else {
      tsch_timing[i] = US_TO_RTIMERTICKS(ies.ie_tsch_timeslot[i]);
    }
  }

  /* TSCH hopping sequence */
  if(ies.ie_channel_hopping_sequence_id == 0) {
    memcpy(tsch_hopping_sequence, TSCH_DEFAULT_HOPPING_SEQUENCE, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
    TSCH_ASN_DIVISOR_INIT(tsch_hopping_sequence_length, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
  } else {
    if(ies.ie_hopping_sequence_len <= sizeof(tsch_hopping_sequence)) {
      memcpy(tsch_hopping_sequence, ies.ie_hopping_sequence_list, ies.ie_hopping_sequence_len);
      TSCH_ASN_DIVISOR_INIT(tsch_hopping_sequence_length, ies.ie_hopping_sequence_len);
    } else {
      PRINTF("TSCH:! parse_eb: hopping sequence too long (%u)\n", ies.ie_hopping_sequence_len);
      return 0;
    }
  }

#if TSCH_CHECK_TIME_AT_ASSOCIATION > 0
  /* Divide by 4k and multiply again to avoid integer overflow */
  uint32_t expected_asn = 4096 * TSCH_CLOCK_TO_SLOTS(clock_time() / 4096, tsch_timing_timeslot_length); /* Expected ASN based on our current time*/
  int32_t asn_threshold = TSCH_CHECK_TIME_AT_ASSOCIATION * 60ul * TSCH_CLOCK_TO_SLOTS(CLOCK_SECOND, tsch_timing_timeslot_length);
  int32_t asn_diff = (int32_t)tsch_current_asn.ls4b - expected_asn;
  if(asn_diff > asn_threshold) {
    PRINTF("TSCH:! EB ASN rejected %lx %lx %ld\n",
           tsch_current_asn.ls4b, expected_asn, asn_diff);
    return 0;
  }
#endif

#if TSCH_INIT_SCHEDULE_FROM_EB
  /* Create schedule */
  if(ies.ie_tsch_slotframe_and_link.num_slotframes == 0) {
#if TSCH_SCHEDULE_WITH_6TISCH_MINIMAL
    PRINTF("TSCH: parse_eb: no schedule, setting up minimal schedule\n");
    tsch_schedule_create_minimal();
#else
    PRINTF("TSCH: parse_eb: no schedule\n");
#endif
  } else {
    /* First, empty current schedule */
    tsch_schedule_remove_all_slotframes();
    /* We support only 0 or 1 slotframe in this IE */
    int num_links = ies.ie_tsch_slotframe_and_link.num_links;
    if(num_links <= FRAME802154E_IE_MAX_LINKS) {
      int i;
      struct tsch_slotframe *sf = tsch_schedule_add_slotframe(
          ies.ie_tsch_slotframe_and_link.slotframe_handle,
          ies.ie_tsch_slotframe_and_link.slotframe_size);
      for(i = 0; i < num_links; i++) {
        tsch_schedule_add_link(sf,
            ies.ie_tsch_slotframe_and_link.links[i].link_options,
            LINK_TYPE_ADVERTISING, &tsch_broadcast_address,
            ies.ie_tsch_slotframe_and_link.links[i].timeslot, ies.ie_tsch_slotframe_and_link.links[i].channel_offset);
      }
    } else {
      PRINTF("TSCH:! parse_eb: too many links in schedule (%u)\n", num_links);
      return 0;
    }
  }
#endif /* TSCH_INIT_SCHEDULE_FROM_EB */

  if(tsch_join_priority < TSCH_MAX_JOIN_PRIORITY) {
    struct tsch_neighbor *n;

    /* Add coordinator to list of neighbors, lock the entry */
    n = tsch_queue_add_nbr(packetbuf_addr(PACKETBUF_ADDR_SENDER));

    if(n != NULL) {
      tsch_queue_update_time_source(packetbuf_addr(PACKETBUF_ADDR_SENDER));

      /* Set PANID */
      frame802154_set_pan_id(packetbuf_attr(PACKETBUF_ATTR_SOURCE_PANID));

      /* Synchronize on EB */
      tsch_slot_operation_sync(timestamp - tsch_timing[tsch_ts_tx_offset], &tsch_current_asn);

      /* Update global flags */
      tsch_is_associated = 1;
#if LLSEC802154_ENABLED
      tsch_is_pan_secured = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL);
#else /* LLSEC802154_ENABLED */
      tsch_is_pan_secured = 0;
#endif /* LLSEC802154_ENABLED */

      /* Start sending keep-alives now that tsch_is_associated is set */
      tsch_schedule_keepalive();

#ifdef TSCH_CALLBACK_JOINING_NETWORK
      TSCH_CALLBACK_JOINING_NETWORK();
#endif

      PRINTF("TSCH: association done, sec %u, PAN ID %x, asn-%x.%lx, jp %u, timeslot id %u, hopping id %u, slotframe len %u with %u links, from ",
             tsch_is_pan_secured,
             packetbuf_attr(PACKETBUF_ATTR_SOURCE_PANID),
             tsch_current_asn.ms1b, tsch_current_asn.ls4b, tsch_join_priority,
             ies.ie_tsch_timeslot_id,
             ies.ie_channel_hopping_sequence_id,
             ies.ie_tsch_slotframe_and_link.slotframe_size,
             ies.ie_tsch_slotframe_and_link.num_links);
      PRINTLLADDR((const uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
      PRINTF("\n");

      return 1;
    }
  }
  PRINTF("TSCH:! did not associate.\n");
  return 0;
}
Exemplo n.º 21
0
/*---------------------------------------------------------------------------*/
static void
input_packet(void)
{
  static struct ctimer ct;
  if(!we_are_receiving_burst) {
    off();
  }

  /*  printf("cycle_start 0x%02x 0x%02x\n", cycle_start, cycle_start % CYCLE_TIME);*/
  
  if(packetbuf_totlen() > 0 && NETSTACK_FRAMER.parse() >= 0) {

#if WITH_CONTIKIMAC_HEADER
    struct hdr *chdr;
    chdr = packetbuf_dataptr();
    if(chdr->id != CONTIKIMAC_ID) {
      PRINTF("contikimac: failed to parse hdr (%u)\n", packetbuf_totlen());
      return;
    }
    packetbuf_hdrreduce(sizeof(struct hdr));
    packetbuf_set_datalen(chdr->len);
#endif /* WITH_CONTIKIMAC_HEADER */

    if(packetbuf_datalen() > 0 &&
       packetbuf_totlen() > 0 &&
       (rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                     &rimeaddr_node_addr) ||
        rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                     &rimeaddr_null))) {
      /* This is a regular packet that is destined to us or to the
         broadcast address. */

      /* If FRAME_PENDING is set, we are receiving a packets in a burst */
      we_are_receiving_burst = packetbuf_attr(PACKETBUF_ATTR_PENDING);
      if(we_are_receiving_burst) {
        on();
        /* Set a timer to turn the radio off in case we do not receive a next packet */
        ctimer_set(&ct, INTER_PACKET_DEADLINE, recv_burst_off, NULL);
      } else {
        off();
        ctimer_stop(&ct);
      }

      /* Check for duplicate packet by comparing the sequence number
         of the incoming packet with the last few ones we saw. */
      {
        int i;
        for(i = 0; i < MAX_SEQNOS; ++i) {
          if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == received_seqnos[i].seqno &&
             rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER),
                          &received_seqnos[i].sender)) {
            /* Drop the packet. */
            /*        printf("Drop duplicate ContikiMAC layer packet\n");*/
            return;
          }
        }
        for(i = MAX_SEQNOS - 1; i > 0; --i) {
          memcpy(&received_seqnos[i], &received_seqnos[i - 1],
                 sizeof(struct seqno));
        }
        received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);
        rimeaddr_copy(&received_seqnos[0].sender,
                      packetbuf_addr(PACKETBUF_ADDR_SENDER));
      }

#if CONTIKIMAC_CONF_COMPOWER
      /* Accumulate the power consumption for the packet reception. */
      compower_accumulate(&current_packet);
      /* Convert the accumulated power consumption for the received
         packet to packet attributes so that the higher levels can
         keep track of the amount of energy spent on receiving the
         packet. */
      compower_attrconv(&current_packet);

      /* Clear the accumulated power consumption so that it is ready
         for the next packet. */
      compower_clear(&current_packet);
#endif /* CONTIKIMAC_CONF_COMPOWER */

      PRINTDEBUG("contikimac: data (%u)\n", packetbuf_datalen());
      NETSTACK_MAC.input();
      return;
    } else {
      PRINTDEBUG("contikimac: data not for us\n");
    }
  } else {
    PRINTF("contikimac: failed to parse (%u)\n", packetbuf_totlen());
  }
}
Exemplo n.º 22
0
/* Function send for TSCH-MAC, puts the packet in packetbuf in the MAC queue */
static void
send_packet(mac_callback_t sent, void *ptr)
{
  int ret = MAC_TX_DEFERRED;
  int packet_count_before;
  int hdr_len = 0;
  const linkaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);

  if(!tsch_is_associated) {
    if(!tsch_is_initialized) {
      PRINTF("TSCH:! not initialized (see earlier logs), drop outgoing packet\n");
    } else {
      PRINTF("TSCH:! not associated, drop outgoing packet\n");
    }
    ret = MAC_TX_ERR;
    mac_call_sent_callback(sent, ptr, ret, 1);
    return;
  }

  /* Ask for ACK if we are sending anything other than broadcast */
  if(!linkaddr_cmp(addr, &linkaddr_null)) {
    packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
  } else {
    /* Broadcast packets shall be added to broadcast queue
     * The broadcast address in Contiki is linkaddr_null which is equal
     * to tsch_eb_address */
    addr = &tsch_broadcast_address;
  }

  packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME);

#if LLSEC802154_ENABLED
  if(tsch_is_pan_secured) {
    /* Set security level, key id and index */
    packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, TSCH_SECURITY_KEY_SEC_LEVEL_OTHER);
    packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, FRAME802154_1_BYTE_KEY_ID_MODE); /* Use 1-byte key index */
    packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX, TSCH_SECURITY_KEY_INDEX_OTHER);
  }
#endif /* LLSEC802154_ENABLED */

  packet_count_before = tsch_queue_packet_count(addr);

#if !NETSTACK_CONF_BRIDGE_MODE
  /*
   * In the Contiki stack, the source address of a frame is set at the RDC
   * layer. Since TSCH doesn't use any RDC protocol and bypasses the layer to
   * transmit a frame, it should set the source address by itself.
   */
  packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
#endif

  if((hdr_len = NETSTACK_FRAMER.create()) < 0) {
    PRINTF("TSCH:! can't send packet due to framer error\n");
    ret = MAC_TX_ERR;
  } else {
    struct tsch_packet *p;
    /* Enqueue packet */
    p = tsch_queue_add_packet(addr, sent, ptr);
    if(p == NULL) {
      PRINTF("TSCH:! can't send packet to %u with seqno %u, queue %u %u\n",
          TSCH_LOG_ID_FROM_LINKADDR(addr),
          packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO),
          packet_count_before,
          tsch_queue_packet_count(addr));
      ret = MAC_TX_ERR;
    } else {
      p->header_len = hdr_len;
      PRINTF("TSCH: send packet to %u with seqno %u, queue %u %u, len %u %u\n",
             TSCH_LOG_ID_FROM_LINKADDR(addr),
             packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO),
             packet_count_before,
             tsch_queue_packet_count(addr),
             p->header_len,
             queuebuf_datalen(p->qb));
      (void)packet_count_before; /* Discard "variable set but unused" warning in case of TSCH_LOG_LEVEL of 0 */
    }
  }
  if(ret != MAC_TX_DEFERRED) {
    mac_call_sent_callback(sent, ptr, ret, 1);
  }
}
Exemplo n.º 23
0
/*---------------------------------------------------------------------------*/
static int
create(void)
{
  frame802154_t params;
  uint8_t len;

  /* init to zeros */
  memset(&params, 0, sizeof(params));

  /* Build the FCF. */
  params.fcf.frame_type = FRAME802154_DATAFRAME;
  params.fcf.security_enabled = 0;
  params.fcf.frame_pending = 0;
  params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_RELIABLE);
  params.fcf.panid_compression = 0;

  /* Insert IEEE 802.15.4 (2003) version bit. */
  params.fcf.frame_version = FRAME802154_IEEE802154_2003;

  /* Increment and set the data sequence number. */
  params.seq = mac_dsn++;
/*   params.seq = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); */

  /* Complete the addressing fields. */
  /**
     \todo For phase 1 the addresses are all long. We'll need a mechanism
     in the rime attributes to tell the mac to use long or short for phase 2.
  */
  params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE;
  params.dest_pid = mac_dst_pan_id;

  /*
   *  If the output address is NULL in the Rime buf, then it is broadcast
   *  on the 802.15.4 network.
   */
  if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
    /* Broadcast requires short address mode. */
    params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE;
    params.dest_addr.u8[0] = 0xFF;
    params.dest_addr.u8[1] = 0xFF;

  } else {
    rimeaddr_copy(&params.dest_addr, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
    params.fcf.dest_addr_mode = FRAME802154_LONGADDRMODE;
  }

  /* Set the source PAN ID to the global variable. */
  params.src_pid = mac_src_pan_id;

  /*
   * Set up the source address using only the long address mode for
   * phase 1.
   */
  rimeaddr_copy(&params.src_addr, &rimeaddr_node_addr);

  params.payload = packetbuf_dataptr();
  params.payload_len = packetbuf_datalen();
  len = frame802154_hdrlen(&params);
  if(packetbuf_hdralloc(len)) {
    frame802154_create(&params, packetbuf_hdrptr(), len);

    PRINTF("P6MAC-UT: %2X", params.fcf.frame_type);
    PRINTADDR(params.dest_addr.u8);
    PRINTF("%u %u (%u)\n", len, packetbuf_datalen(), packetbuf_totlen());

    return len;
  } else {
    PRINTF("P6MAC-UT: too large header: %u\n", len);
    return 0;
  }
}
Exemplo n.º 24
0
/*---------------------------------------------------------------------------*/
static void
input_packet(void)
{
  static struct ctimer ct;
  if(!we_are_receiving_burst) {
    off();
  }

  /*  printf("cycle_start 0x%02x 0x%02x\n", cycle_start, cycle_start % CYCLE_TIME);*/

  if(packetbuf_totlen() > 0 && NETSTACK_FRAMER.parse() >= 0) {
    if(packetbuf_datalen() > 0 &&
       packetbuf_totlen() > 0 &&
       (linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                     &linkaddr_node_addr) ||
        packetbuf_holds_broadcast())) {
      /* This is a regular packet that is destined to us or to the
         broadcast address. */

      /* If FRAME_PENDING is set, we are receiving a packets in a burst */
      /* TODO To prevent denial-of-sleep attacks, the transceiver should
         be disabled upon receipt of an unauthentic frame. */
      we_are_receiving_burst = packetbuf_attr(PACKETBUF_ATTR_PENDING);
      if(we_are_receiving_burst) {
        on();
        /* Set a timer to turn the radio off in case we do not receive
	   a next packet */
        ctimer_set(&ct, INTER_PACKET_DEADLINE, recv_burst_off, NULL);
      } else {
        off();
        ctimer_stop(&ct);
      }

#if RDC_WITH_DUPLICATE_DETECTION
      /* Check for duplicate packet. */
      if(mac_sequence_is_duplicate()) {
        /* Drop the packet. */
        /*        printf("Drop duplicate ContikiMAC layer packet\n");*/
        return;
      }
      mac_sequence_register_seqno();
#endif /* RDC_WITH_DUPLICATE_DETECTION */

#if CONTIKIMAC_CONF_COMPOWER
      /* Accumulate the power consumption for the packet reception. */
      compower_accumulate(&current_packet);
      /* Convert the accumulated power consumption for the received
         packet to packet attributes so that the higher levels can
         keep track of the amount of energy spent on receiving the
         packet. */
      compower_attrconv(&current_packet);

      /* Clear the accumulated power consumption so that it is ready
         for the next packet. */
      compower_clear(&current_packet);
#endif /* CONTIKIMAC_CONF_COMPOWER */

      PRINTDEBUG("contikimac: data (%u)\n", packetbuf_datalen());
      NETSTACK_MAC.input();
      return;
    } else {
      PRINTDEBUG("contikimac: data not for us\n");
    }
  } else {
    PRINTF("contikimac: failed to parse (%u)\n", packetbuf_totlen());
  }
}
Exemplo n.º 25
0
/**
 *
 * Send a packet. This function builds a complete packet with an LPP
 * header and queues the packet. When a probe is heard (in the
 * read_packet() function), and the sender of the probe matches the
 * receiver of the queued packet, the queued packet is sent.
 *
 * ACK packets are treated differently from other packets: if a node
 * sends a packet that it expects to be ACKed, the sending node keeps
 * its radio on for some time after sending its packet. So we do not
 * need to wait for a probe packet: we just transmit the ACK packet
 * immediately.
 *
 */
static void
send_packet(mac_callback_t sent, void *ptr)
{
  struct lpp_hdr hdr;
  clock_time_t timeout;
  uint8_t is_broadcast = 0;

  rimeaddr_copy(&hdr.sender, &rimeaddr_node_addr);
  rimeaddr_copy(&hdr.receiver, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
  if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) {
    is_broadcast = 1;
  }
  hdr.type = TYPE_DATA;

  packetbuf_hdralloc(sizeof(struct lpp_hdr));
  memcpy(packetbuf_hdrptr(), &hdr, sizeof(struct lpp_hdr));
  packetbuf_compact();

  packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);

  {
    int hdrlen = NETSTACK_FRAMER.create();
    if(hdrlen == 0) {
      /* Failed to send */
      mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 0);
      return;
    }
  }

  PRINTF("%d.%d: queueing packet to %d.%d, channel %d\n",
	 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
	 hdr.receiver.u8[0], hdr.receiver.u8[1],
	 packetbuf_attr(PACKETBUF_ATTR_CHANNEL));
#if WITH_ACK_OPTIMIZATION
  if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_ACK) {
    /* Send ACKs immediately. */
    NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
    mac_call_sent_callback(sent, ptr, MAC_TX_OK, 1);
    return;
  }
#endif /* WITH_ACK_OPTIMIZATION */

#if WITH_ADAPTIVE_OFF_TIME
  off_time = LOWEST_OFF_TIME;
  restart_dutycycle(off_time);
#endif /* WITH_ADAPTIVE_OFF_TIME */

  {
    struct queue_list_item *i;
    i = memb_alloc(&queued_packets_memb);
    if(i != NULL) {
      i->sent_callback = sent;
      i->sent_callback_ptr = ptr;
      i->num_transmissions = 0;
      i->packet = queuebuf_new_from_packetbuf();
      if(i->packet == NULL) {
	memb_free(&queued_packets_memb, i);
        printf("null packet\n");
        mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 0);
	return;
      } else {
        if(is_broadcast) {
          timeout = PACKET_LIFETIME;
#if WITH_PENDING_BROADCAST
	  /* We set the broadcast state of the packet to be
	     waiting. This means that the packet is waiting for our
	     next probe to be sent. Our next probe is used to check if
	     there are any neighbors currently broadcasting a
	     packet. If so, we will get a broadcast packet in response
	     to our probe. If no broadcast packet is received in
	     response to our probe, we mark the packet as ready to be
	     sent. */
	  set_broadcast_flag(i, BROADCAST_FLAG_WAITING);
	  PRINTF("-> waiting\n");
#endif /* WITH_PENDING_BROADCAST */
        } else {
	  timeout = UNICAST_TIMEOUT;
#if WITH_PENDING_BROADCAST
	  i->broadcast_flag = BROADCAST_FLAG_NONE;
#endif /* WITH_PENDING_BROADCAST */
	}
	ctimer_set(&i->removal_timer, timeout,
                   remove_queued_old_packet_callback, i);

	/* Wait for a probe packet from a neighbor. The actual packet
	   transmission is handled by the read_packet() function,
	   which receives the probe from the neighbor. */
        turn_radio_on_for_neighbor(&hdr.receiver, i);

      }
    } else {
      printf("i == NULL\n");
      mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 0);
    }
  }
}
Exemplo n.º 26
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);
}
Exemplo n.º 27
0
/*---------------------------------------------------------------------------*/
static int
cc2420_transmit(unsigned short payload_len)
{
  int i, txpower;
  uint8_t total_len;
#if CC2420_CONF_CHECKSUM
  uint16_t checksum;
#endif /* CC2420_CONF_CHECKSUM */

  GET_LOCK();

  txpower = 0;
  if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
    /* Remember the current transmission power */
    txpower = cc2420_get_txpower();
    /* Set the specified transmission power */
    set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1);
  }

  total_len = payload_len + AUX_LEN;
  
  /* The TX FIFO can only hold one packet. Make sure to not overrun
   * FIFO by waiting for transmission to start here and synchronizing
   * with the CC2420_TX_ACTIVE check in cc2420_send.
   *
   * Note that we may have to wait up to 320 us (20 symbols) before
   * transmission starts.
   */
#ifndef CC2420_CONF_SYMBOL_LOOP_COUNT
#error CC2420_CONF_SYMBOL_LOOP_COUNT needs to be set!!!
#else
#define LOOP_20_SYMBOLS CC2420_CONF_SYMBOL_LOOP_COUNT
#endif

#if WITH_SEND_CCA
  strobe(CC2420_SRXON);
  BUSYWAIT_UNTIL(status() & BV(CC2420_RSSI_VALID), RTIMER_SECOND / 10);
  strobe(CC2420_STXONCCA);
#else /* WITH_SEND_CCA */
  strobe(CC2420_STXON);
#endif /* WITH_SEND_CCA */
  for(i = LOOP_20_SYMBOLS; i > 0; i--) {
    if(CC2420_SFD_IS_1) {
      {
        rtimer_clock_t sfd_timestamp;
        sfd_timestamp = cc2420_sfd_start_time;
        if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
           PACKETBUF_ATTR_PACKET_TYPE_TIMESTAMP) {
          /* Write timestamp to last two bytes of packet in TXFIFO. */
          CC2420_WRITE_RAM(&sfd_timestamp, CC2420RAM_TXFIFO + payload_len - 1, 2);
        }
      }

      if(!(status() & BV(CC2420_TX_ACTIVE))) {
        /* SFD went high but we are not transmitting. This means that
           we just started receiving a packet, so we drop the
           transmission. */
        RELEASE_LOCK();
        return RADIO_TX_COLLISION;
      }
      if(receive_on) {
	ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
      }
      ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
      /* We wait until transmission has ended so that we get an
	 accurate measurement of the transmission time.*/
      BUSYWAIT_UNTIL(!(status() & BV(CC2420_TX_ACTIVE)), RTIMER_SECOND / 10);

#ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS
      ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,cc2420_get_txpower());
#endif
      ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
      if(receive_on) {
	ENERGEST_ON(ENERGEST_TYPE_LISTEN);
      } else {
	/* We need to explicitly turn off the radio,
	 * since STXON[CCA] -> TX_ACTIVE -> RX_ACTIVE */
	off();
      }

      if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
        /* Restore the transmission power */
        set_txpower(txpower & 0xff);
      }

      RELEASE_LOCK();
      return RADIO_TX_OK;
    }
  }

  /* If we are using WITH_SEND_CCA, we get here if the packet wasn't
     transmitted because of other channel activity. */
  RIMESTATS_ADD(contentiondrop);
  PRINTF("cc2420: do_send() transmission never started\n");

  if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
    /* Restore the transmission power */
    set_txpower(txpower & 0xff);
  }

  RELEASE_LOCK();
  return RADIO_TX_COLLISION;
}
Exemplo n.º 28
0
/*---------------------------------------------------------------------------*/
static void
qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
{
  struct rdc_buf_list *curr;
  struct rdc_buf_list *next;
  int ret;
  int is_receiver_awake;
  int pending;

  if(buf_list == NULL) {
    return;
  }
  /* Do not send during reception of a burst */
  if(we_are_receiving_burst) {
    /* Prepare the packetbuf for callback */
    queuebuf_to_packetbuf(buf_list->buf);
    /* Return COLLISION so the MAC may try again later */
    mac_call_sent_callback(sent, ptr, MAC_TX_COLLISION, 1);
    return;
  }

  /* Create and secure frames in advance */
  curr = buf_list;
  do {
    next = list_item_next(curr);
    queuebuf_to_packetbuf(curr->buf);
    if(!packetbuf_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED)) {
      /* create and secure this frame */
      if(next != NULL) {
        packetbuf_set_attr(PACKETBUF_ATTR_PENDING, 1);
      }
#if !NETSTACK_CONF_BRIDGE_MODE
      /* If NETSTACK_CONF_BRIDGE_MODE is set, assume PACKETBUF_ADDR_SENDER is already set. */
      packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
#endif
      packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
      if(NETSTACK_FRAMER.create() < 0) {
        PRINTF("contikimac: framer failed\n");
        mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 1);
        return;
      }

      packetbuf_set_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED, 1);
      queuebuf_update_from_packetbuf(curr->buf);
    }
    curr = next;
  } while(next != NULL);

  /* The receiver needs to be awoken before we send */
  is_receiver_awake = 0;
  curr = buf_list;
  do { /* A loop sending a burst of packets from buf_list */
    next = list_item_next(curr);

    /* Prepare the packetbuf */
    queuebuf_to_packetbuf(curr->buf);

    pending = packetbuf_attr(PACKETBUF_ATTR_PENDING);

    /* Send the current packet */
    ret = send_packet(sent, ptr, curr, is_receiver_awake);
    if(ret != MAC_TX_DEFERRED) {
      mac_call_sent_callback(sent, ptr, ret, 1);
    }

    if(ret == MAC_TX_OK) {
      if(next != NULL) {
        /* We're in a burst, no need to wake the receiver up again */
        is_receiver_awake = 1;
        curr = next;
      }
    } else {
      /* The transmission failed, we stop the burst */
      next = NULL;
    }
  } while((next != NULL) && pending);
}
Exemplo n.º 29
0
/*---------------------------------------------------------------------------*/
static int
send_packet(void)
{
  rtimer_clock_t t0;
  rtimer_clock_t t;
  rtimer_clock_t encounter_time = 0;
  int strobes;
  int ret;
#if 0
  struct xmac_hdr *hdr;
#endif
  uint8_t got_strobe_ack = 0;
  uint8_t got_ack = 0;
  uint8_t strobe[MAX_STROBE_SIZE];
  int strobe_len, len;
  int is_broadcast = 0;
/*int is_reliable; */
  struct encounter *e;
  struct queuebuf *packet;
  int is_already_streaming = 0;
  uint8_t collisions;

  /* Create the X-MAC header for the data packet. */
  packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
  if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
    is_broadcast = 1;
    PRINTDEBUG("xmac: send broadcast\n");
  } else {
#if UIP_CONF_IPV6
    PRINTDEBUG("xmac: send unicast to %02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[2],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[3],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[4],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[5],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[6],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[7]);
#else
    PRINTDEBUG("xmac: send unicast to %u.%u\n",
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1]);
#endif /* UIP_CONF_IPV6 */
  }
/*  is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
    packetbuf_attr(PACKETBUF_ATTR_ERELIABLE); */

  packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
  len = NETSTACK_FRAMER.create();
  strobe_len = len + sizeof(struct xmac_hdr);
  if(len < 0 || strobe_len > (int)sizeof(strobe)) {
    /* Failed to send */
   PRINTF("xmac: send failed, too large header\n");
    return MAC_TX_ERR_FATAL;
  }
  memcpy(strobe, packetbuf_hdrptr(), len);
  strobe[len] = DISPATCH; /* dispatch */
  strobe[len + 1] = TYPE_STROBE; /* type */

  packetbuf_compact();
  packet = queuebuf_new_from_packetbuf();
  if(packet == NULL) {
    /* No buffer available */
    PRINTF("xmac: send failed, no queue buffer available (of %u)\n",
           QUEUEBUF_CONF_NUM);
    return MAC_TX_ERR;
  }

#if WITH_STREAMING
  if(is_streaming == 1 &&
     (rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
		   &is_streaming_to) ||
      rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
		   &is_streaming_to_too))) {
    is_already_streaming = 1;
  }
  if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
     PACKETBUF_ATTR_PACKET_TYPE_STREAM) {
    is_streaming = 1;
    if(rimeaddr_cmp(&is_streaming_to, &rimeaddr_null)) {
      rimeaddr_copy(&is_streaming_to, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
    } else if(!rimeaddr_cmp(&is_streaming_to, packetbuf_addr(PACKETBUF_ADDR_RECEIVER))) {
      rimeaddr_copy(&is_streaming_to_too, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
    }
    stream_until = RTIMER_NOW() + DEFAULT_STREAM_TIME;
  }
#endif /* WITH_STREAMING */

  off();

#if WITH_ENCOUNTER_OPTIMIZATION
  /* We go through the list of encounters to find if we have recorded
     an encounter with this particular neighbor. If so, we can compute
     the time for the next expected encounter and setup a ctimer to
     switch on the radio just before the encounter. */
  for(e = list_head(encounter_list); e != NULL; e = list_item_next(e)) {
    const rimeaddr_t *neighbor = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);

    if(rimeaddr_cmp(neighbor, &e->neighbor)) {
      rtimer_clock_t wait, now, expected;

      /* We expect encounters to happen every DEFAULT_PERIOD time
	 units. The next expected encounter is at time e->time +
	 DEFAULT_PERIOD. To compute a relative offset, we subtract
	 with clock_time(). Because we are only interested in turning
	 on the radio within the DEFAULT_PERIOD period, we compute the
	 waiting time with modulo DEFAULT_PERIOD. */

      now = RTIMER_NOW();
      wait = ((rtimer_clock_t)(e->time - now)) % (DEFAULT_PERIOD);
      if(wait < 2 * DEFAULT_ON_TIME) {
        wait = DEFAULT_PERIOD;
      }
      expected = now + wait - 2 * DEFAULT_ON_TIME;

#if WITH_ACK_OPTIMIZATION
      /* Wait until the receiver is expected to be awake */
      if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) !=
	 PACKETBUF_ATTR_PACKET_TYPE_ACK &&
	 is_streaming == 0) {
	/* Do not wait if we are sending an ACK, because then the
	   receiver will already be awake. */
	while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected));
      }
#else /* WITH_ACK_OPTIMIZATION */
      /* Wait until the receiver is expected to be awake */
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected));
#endif /* WITH_ACK_OPTIMIZATION */
    }
  }
#endif /* WITH_ENCOUNTER_OPTIMIZATION */

  /* By setting we_are_sending to one, we ensure that the rtimer
     powercycle interrupt do not interfere with us sending the packet. */
  we_are_sending = 1;
  
  t0 = RTIMER_NOW();
  strobes = 0;

  LEDS_ON(LEDS_BLUE);

  /* Send a train of strobes until the receiver answers with an ACK. */

  /* Turn on the radio to listen for the strobe ACK. */
  //  on();
  collisions = 0;
  if(!is_already_streaming) {
    watchdog_stop();
    got_strobe_ack = 0;
    t = RTIMER_NOW();
    for(strobes = 0, collisions = 0;
	got_strobe_ack == 0 && collisions == 0 &&
	  RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + xmac_config.strobe_time);
	strobes++) {

      while(got_strobe_ack == 0 &&
	    RTIMER_CLOCK_LT(RTIMER_NOW(), t + xmac_config.strobe_wait_time)) {
#if 0
	rtimer_clock_t now = RTIMER_NOW();

	/* See if we got an ACK */
	packetbuf_clear();
	len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE);
	if(len > 0) {
	  packetbuf_set_datalen(len);
	  if(NETSTACK_FRAMER.parse() >= 0) {
	    hdr = packetbuf_dataptr();
	    if(hdr->dispatch == DISPATCH && hdr->type == TYPE_STROBE_ACK) {
	      if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
			      &rimeaddr_node_addr)) {
		/* We got an ACK from the receiver, so we can immediately send
		   the packet. */
		got_strobe_ack = 1;
		encounter_time = now;
	      } else {
		PRINTDEBUG("xmac: strobe ack for someone else\n");
	      }
	    } else /*if(hdr->dispatch == DISPATCH && hdr->type == TYPE_STROBE)*/ {
	      PRINTDEBUG("xmac: strobe from someone else\n");
	      collisions++;
	    }
	  } else {
	    PRINTF("xmac: send failed to parse %u\n", len);
	  }
	}
#endif /* 0 */
      }
      
      t = RTIMER_NOW();
            /* Send the strobe packet. */
      if(got_strobe_ack == 0 && collisions == 0) {

	if(is_broadcast) {
#if WITH_STROBE_BROADCAST
	  ret = NETSTACK_RADIO.send(strobe, strobe_len);
#else
	  /* restore the packet to send */
	  queuebuf_to_packetbuf(packet);
	  ret = NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
#endif
          off();
	} else {
#if 0
	  rtimer_clock_t wt;
#endif
          on();
	  ret = NETSTACK_RADIO.send(strobe, strobe_len);
#if 0
	  /* Turn off the radio for a while to let the other side
	     respond. We don't need to keep our radio on when we know
	     that the other side needs some time to produce a reply. */
	  off();
	  wt = RTIMER_NOW();
	  while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + WAIT_TIME_BEFORE_STROBE_ACK));
#endif /* 0 */
#if RDC_CONF_HARDWARE_ACK
 	  if(ret == RADIO_TX_OK) {
            got_strobe_ack = 1;
          } else {
            off();
          }
#else
          if(detect_ack()) {
            got_strobe_ack = 1;
          } else {
            off();
          }
#endif /* RDC_CONF_HARDWARE_ACK */

        }
      }
    }
  }

#if WITH_ACK_OPTIMIZATION
  /* If we have received the strobe ACK, and we are sending a packet
     that will need an upper layer ACK (as signified by the
     PACKETBUF_ATTR_RELIABLE packet attribute), we keep the radio on. */
  if(got_strobe_ack && (packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
			packetbuf_attr(PACKETBUF_ATTR_ERELIABLE) ||
			packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
			PACKETBUF_ATTR_PACKET_TYPE_STREAM)) {
    on(); /* Wait for ACK packet */
    waiting_for_packet = 1;
  } else {
    off();
  }
#endif /* WITH_ACK_OPTIMIZATION */

  /* restore the packet to send */
  queuebuf_to_packetbuf(packet);
  queuebuf_free(packet);

  /* Send the data packet. */
  if((is_broadcast || got_strobe_ack || is_streaming) && collisions == 0) {
    ret = NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());

    if(!is_broadcast) {
#if RDC_CONF_HARDWARE_ACK
      if(ret == RADIO_TX_OK) {
        got_ack = 1;
      }
#else
      if(detect_ack()) {
        got_ack = 1;
      }
#endif /* RDC_CONF_HARDWARE_ACK */
    }
  }
  off();

#if WITH_ENCOUNTER_OPTIMIZATION
  if(got_strobe_ack && !is_streaming) {
    register_encounter(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), encounter_time);
  }
#endif /* WITH_ENCOUNTER_OPTIMIZATION */
  watchdog_start();

  PRINTF("xmac: send (strobes=%u,len=%u,%s), done\n", strobes,
	 packetbuf_totlen(), got_strobe_ack ? "ack" : "no ack");

#if XMAC_CONF_COMPOWER
  /* Accumulate the power consumption for the packet transmission. */
  compower_accumulate(&current_packet);

  /* Convert the accumulated power consumption for the transmitted
     packet to packet attributes so that the higher levels can keep
     track of the amount of energy spent on transmitting the
     packet. */
  compower_attrconv(&current_packet);

  /* Clear the accumulated power consumption so that it is ready for
     the next packet. */
  compower_clear(&current_packet);
#endif /* XMAC_CONF_COMPOWER */

  we_are_sending = 0;

  LEDS_OFF(LEDS_BLUE);
  if(collisions == 0) {
    if(is_broadcast == 0 && got_ack == 0) {
      return MAC_TX_NOACK;
    } else {
      return MAC_TX_OK;
    }
  } else {
    someone_is_sending++;
    return MAC_TX_COLLISION;
  }

}
Exemplo n.º 30
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;
      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_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);
      }
    }
  }
}