Ejemplo n.º 1
0
/*---------------------------------------------------------------------------*/
static void
prepare_update_command(uint8_t cmd_id,
    struct akes_nbr_entry *entry,
    enum akes_nbr_status status)
{
  uint8_t *payload;
  uint8_t payload_len;

  payload = adaptivesec_prepare_command(cmd_id, akes_nbr_get_addr(entry));
  adaptivesec_add_security_header(entry->refs[status]);
  anti_replay_suppress_counter();
  if(status) {
    /* avoids that csma.c confuses frames for tentative and permanent neighbors */
    packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO,
        0xff00 + packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO));
  }
#if ANTI_REPLAY_WITH_SUPPRESSION
  packetbuf_set_attr(PACKETBUF_ATTR_NEIGHBOR_INDEX, akes_nbr_index_of(entry->refs[status]));
#endif /* ANTI_REPLAY_WITH_SUPPRESSION */

  switch(cmd_id) {
  case AKES_HELLOACK_IDENTIFIER:
  case AKES_HELLOACK_P_IDENTIFIER:
  case AKES_ACK_IDENTIFIER:
    packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS,
        MAX_RETRANSMISSIONS_OF_HELLOACKS_AND_ACKS + 1);
    break;
  default:
    break;
  }

  /* write payload */
  if(status) {
    akes_nbr_copy_challenge(payload, entry->tentative->challenge);
    payload += AKES_NBR_CHALLENGE_LEN;
  }

#if AKES_NBR_WITH_INDICES
  payload[0] = akes_nbr_index_of(entry->refs[status]);
  payload++;
#endif /* AKES_NBR_WITH_INDICES */
#if ANTI_REPLAY_WITH_SUPPRESSION
  {
    frame802154_frame_counter_t reordered_counter;
    anti_replay_write_counter(payload);
    payload += 4;
    reordered_counter.u32 = LLSEC802154_HTONL(anti_replay_my_broadcast_counter);
    memcpy(payload, reordered_counter.u8, 4);
    payload += 4;
  }
#endif /* ANTI_REPLAY_WITH_SUPPRESSION */

  payload_len = payload - ((uint8_t *)packetbuf_hdrptr());

#if AKES_NBR_WITH_GROUP_KEYS
  switch(cmd_id) {
  case AKES_HELLOACK_IDENTIFIER:
  case AKES_HELLOACK_P_IDENTIFIER:
  case AKES_ACK_IDENTIFIER:
    akes_nbr_copy_key(payload, adaptivesec_group_key);
    packetbuf_set_attr(PACKETBUF_ATTR_UNENCRYPTED_BYTES, payload_len);
    payload_len += AES_128_KEY_LENGTH;
    break;
  }
#endif /* AKES_NBR_WITH_GROUP_KEYS */
  packetbuf_set_datalen(payload_len);
}
Ejemplo n.º 2
0
/*---------------------------------------------------------------------------*/
static int
create_frame(struct net_buf *buf, int do_create)
{
  frame802154_t params;
  int hdr_len;

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

  /* Build the FCF. */
  params.fcf.frame_type = packetbuf_attr(buf, PACKETBUF_ATTR_FRAME_TYPE);
  params.fcf.frame_pending = packetbuf_attr(buf, PACKETBUF_ATTR_PENDING);
  if(packetbuf_holds_broadcast(buf)) {
    params.fcf.ack_required = 0;
  } else {
    params.fcf.ack_required = packetbuf_attr(buf, 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(buf, PACKETBUF_ATTR_SECURITY_LEVEL)) {
    params.fcf.security_enabled = 1;
  }
  /* Setting security-related attributes */
  params.aux_hdr.security_control.security_level = packetbuf_attr(buf, PACKETBUF_ATTR_SECURITY_LEVEL);
  params.aux_hdr.frame_counter.u16[0] = packetbuf_attr(buf, PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1);
  params.aux_hdr.frame_counter.u16[1] = packetbuf_attr(buf, PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3);
#if LLSEC802154_USES_EXPLICIT_KEYS
  params.aux_hdr.security_control.key_id_mode = packetbuf_attr(buf, PACKETBUF_ATTR_KEY_ID_MODE);
  params.aux_hdr.key_index = packetbuf_attr(buf, PACKETBUF_ATTR_KEY_INDEX);
  params.aux_hdr.key_source.u16[0] = packetbuf_attr(buf, 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) {
    /* Only length calculation - no sequence number is needed and
       should not be consumed. */

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

  } else {
    params.seq = framer_802154_next_seqno();
    packetbuf_set_attr(buf, 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(buf)) {
    /* 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(buf, 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);

  params.payload = packetbuf_dataptr(buf);
  params.payload_len = packetbuf_datalen(buf);
  hdr_len = frame802154_hdrlen(&params);
  if(!do_create) {
    /* Only calculate header length */
    return hdr_len;

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

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

    return hdr_len;
  } else {
    PRINTF("15.4-OUT: too large header: %u\n", hdr_len);
    return FRAMER_FAILED;
  }
}
Ejemplo n.º 3
0
Archivo: lpp.c Proyecto: EDAyele/wsn430
/**
 *
 * 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);
    }
  }
}
Ejemplo n.º 4
0
/*---------------------------------------------------------------------------*/
static int
read(void *buf, unsigned short bufsize)
{
  uint8_t i;
  uint8_t len;

  PRINTF("RF: Read\n");

  if((REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) == 0) {
    return 0;
  }

  /* Check the length */
  len = REG(RFCORE_SFR_RFDATA);

  /* Check for validity */
  if(len > CC2538_RF_MAX_PACKET_LEN) {
    /* Oops, we must be out of sync. */
    PRINTF("RF: bad sync\n");

    RIMESTATS_ADD(badsynch);
    CC2538_RF_CSP_ISFLUSHRX();
    return 0;
  }

  if(len <= CC2538_RF_MIN_PACKET_LEN) {
    PRINTF("RF: too short\n");

    RIMESTATS_ADD(tooshort);
    CC2538_RF_CSP_ISFLUSHRX();
    return 0;
  }

  if(len - CHECKSUM_LEN > bufsize) {
    PRINTF("RF: too long\n");

    RIMESTATS_ADD(toolong);
    CC2538_RF_CSP_ISFLUSHRX();
    return 0;
  }

  /* If we reach here, chances are the FIFO is holding a valid frame */
  PRINTF("RF: read (0x%02x bytes) = ", len);
  len -= CHECKSUM_LEN;

  /* Don't bother with uDMA for short frames (e.g. ACKs) */
  if(CC2538_RF_CONF_RX_USE_DMA && len > UDMA_RX_SIZE_THRESHOLD) {
    PRINTF("<uDMA payload>");

    /* Set the transfer destination's end address */
    udma_set_channel_dst(CC2538_RF_CONF_RX_DMA_CHAN,
                         (uint32_t)(buf) + len - 1);

    /* Configure the control word */
    udma_set_channel_control_word(CC2538_RF_CONF_RX_DMA_CHAN,
                                  UDMA_RX_FLAGS | udma_xfer_size(len));

    /* Enabled the RF RX uDMA channel */
    udma_channel_enable(CC2538_RF_CONF_RX_DMA_CHAN);

    /* Trigger the uDMA transfer */
    udma_channel_sw_request(CC2538_RF_CONF_RX_DMA_CHAN);

    /* Wait for the transfer to complete. */
    while(udma_channel_get_mode(CC2538_RF_CONF_RX_DMA_CHAN));
  } else {
    for(i = 0; i < len; ++i) {
      ((unsigned char *)(buf))[i] = REG(RFCORE_SFR_RFDATA);
      PRINTF("%02x", ((unsigned char *)(buf))[i]);
    }
  }

  /* Read the RSSI and CRC/Corr bytes */
  rssi = ((int8_t)REG(RFCORE_SFR_RFDATA)) - RSSI_OFFSET;
  crc_corr = REG(RFCORE_SFR_RFDATA);

  PRINTF("%02x%02x\n", (uint8_t)rssi, crc_corr);

  /* MS bit CRC OK/Not OK, 7 LS Bits, Correlation value */
  if(crc_corr & CRC_BIT_MASK) {
    packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi);
    packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, crc_corr & LQI_BIT_MASK);
    RIMESTATS_ADD(llrx);
  } else {
    RIMESTATS_ADD(badcrc);
    PRINTF("RF: Bad CRC\n");
    CC2538_RF_CSP_ISFLUSHRX();
    return 0;
  }

#if CC2538_RF_CONF_SNIFFER
  write_byte(magic[0]);
  write_byte(magic[1]);
  write_byte(magic[2]);
  write_byte(magic[3]);
  write_byte(len + 2);
  for(i = 0; i < len; ++i) {
    write_byte(((unsigned char *)(buf))[i]);
  }
  write_byte(rssi);
  write_byte(crc_corr);
  flush();
#endif

  if(!poll_mode) {
    /* If FIFOP==1 and FIFO==0 then we had a FIFO overflow at some point. */
    if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) {
      if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFO) {
        process_poll(&cc2538_rf_process);
      } else {
        CC2538_RF_CSP_ISFLUSHRX();
      }
    }
  }

  CC2538_RF_CSP_ISFLUSHRX();

  return len;
}
Ejemplo n.º 5
0
// TDMA_BS_send() -- called at a specific time
static void TDMA_BS_send(void)
{

  //printf("%05u,",RTIMER_NOW());//call time for BS_send

  // uint8_t bkn_len = 16;
  // uint8_t bkn_pkt[16]={0};
  // bkn_pkt[14]=1;
  // bkn_pkt[15]=2;


  if (disable_sending == 1)
    return;


  

  // set timer for next BS send
  // right now, rtimer_timer does not consider drifting. For long time experiment, it may have problem
  rtimer_set(&BSTimer,RTIMER_TIME(&BSTimer)+segment_period,0,TDMA_BS_send,NULL);

  //update packet sequence number
  seq_num = seq_num + 1;

  if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_CMD) // has command to send
  {
    // Assume for BS, if the tdma_rdc_buf is not empty, then the payload should be command.
    // Should be changed if BS can send other types of data.
/*
    packetbuf_copyfrom((void *)&tdma_rdc_buffer[0],sizeof(uint8_t)*tdma_rdc_buf_ptr);
    packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE,PACKETBUF_ATTR_PACKET_TYPE_CMD);
    tdma_rdc_buf_full_flg = 0;
    tdma_rdc_buf_ptr = 0;
    tdma_rdc_buf_send_ptr = 0;
*/
    PRINTF("send command %s %d\n",tdma_rdc_buffer,packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE));
  }
  else
  {
    packetbuf_copyfrom((void *)&bkn_pkt,sizeof(uint8_t)*bkn_len);

    packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_TIMESTAMP);

  }


  BS_RX_start_time = radio_TX_time+BS_period;

  packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO,seq_num);


  uint8_t hdr_len = NETSTACK_FRAMER.create();

  // fail to create framer
  if(hdr_len < 0)
    return;

  //send packet -- pushed to radio layer
  if(NETSTACK_RADIO.send(packetbuf_hdrptr(),packetbuf_totlen()) != RADIO_TX_OK)
  {
    printf("TDMA RDC: BS fails to send packet\n");
  }
  else
  {
    printf("TDMA RDC: BS sends %u, %u bits\n",seq_num,packetbuf_datalen());
    char* data_ptr = (char *)packetbuf_dataptr();
   // PRINTF("%c%c%c\n",data_ptr[0],data_ptr[1],data_ptr[2]);
  }



}
Ejemplo n.º 6
0
/*---------------------------------------------------------------------------*/
static int
send_one_packet(mac_callback_t sent, void *ptr)
{
	int ret;
	int last_sent_ok = 0;

	packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
#if DISCOVERY_AWARE_RDC_802154_AUTOACK || DISCOVERY_AWARE_RDC_802154_AUTOACK_HW
	packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
#endif /* DISCOVERY_AWARE_RDC_802154_AUTOACK || DISCOVERY_AWARE_RDC_802154_AUTOACK_HW */

	if (!radio_status) {
		on();
	}


	if(NETSTACK_FRAMER.create() < 0) {
		/* Failed to allocate space for headers */
	    PRINTF("RDC: send failed, too large header\n");
		ret = MAC_TX_ERR_FATAL;
	} else {

#ifdef NETSTACK_ENCRYPT
		NETSTACK_ENCRYPT();
#endif /* NETSTACK_ENCRYPT */

#if DISCOVERY_AWARE_RDC_802154_AUTOACK
		int is_broadcast;
		uint8_t dsn;
		dsn = ((uint8_t *)packetbuf_hdrptr())[2] & 0xff;

		NETSTACK_RADIO.prepare(packetbuf_hdrptr(), packetbuf_totlen());

		is_broadcast = linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
				&linkaddr_null);

		if(NETSTACK_RADIO.receiving_packet() ||
				(!is_broadcast && NETSTACK_RADIO.pending_packet())) {

			/* Currently receiving a packet over air or the radio has
         already received a packet that needs to be read before
         sending with auto ack. */
			ret = MAC_TX_COLLISION;

		} else {
  		  if(!is_broadcast) {
			RIMESTATS_ADD(reliabletx);
		  }

			switch(NETSTACK_RADIO.transmit(packetbuf_totlen())) {
			case RADIO_TX_OK:
				if(is_broadcast) {
					ret = MAC_TX_OK;
				} else {
					rtimer_clock_t wt;

					/* Check for ack */
					wt = RTIMER_NOW();
					watchdog_periodic();
					while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + ACK_WAIT_TIME)) {
#if CONTIKI_TARGET_COOJA
						simProcessRunValue = 1;
						cooja_mt_yield();
#endif /* CONTIKI_TARGET_COOJA */
					}

					ret = MAC_TX_NOACK;
					if(NETSTACK_RADIO.receiving_packet() ||
							NETSTACK_RADIO.pending_packet() ||
							NETSTACK_RADIO.channel_clear() == 0) {
						int len;
						uint8_t ackbuf[ACK_LEN];

						if(AFTER_ACK_DETECTED_WAIT_TIME > 0) {
							wt = RTIMER_NOW();
							watchdog_periodic();
							while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + AFTER_ACK_DETECTED_WAIT_TIME)) {
#if CONTIKI_TARGET_COOJA
								simProcessRunValue = 1;
								cooja_mt_yield();
#endif /* CONTIKI_TARGET_COOJA */
							}
						}

						if(NETSTACK_RADIO.pending_packet()) {
							len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
							if(len == ACK_LEN && ackbuf[2] == dsn) {
								/* Ack received */
								RIMESTATS_ADD(ackrx);
								ret = MAC_TX_OK;
							} else {
								/* Not an ack or ack not for us: collision */
								ret = MAC_TX_COLLISION;
							}
						}
					} else {
						PRINTF("RDC tx noack\n");
					}
				}
				break;
			case RADIO_TX_COLLISION:
				ret = MAC_TX_COLLISION;
				break;
			default:
				ret = MAC_TX_ERR;
				break;
			}
		}

#else /* ! DISCOVERY_AWARE_RDC_802154_AUTOACK */

		switch(NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen())) {
		case RADIO_TX_OK:
			ret = MAC_TX_OK;
			break;
		case RADIO_TX_COLLISION:
			ret = MAC_TX_COLLISION;
			break;
		case RADIO_TX_NOACK:
			ret = MAC_TX_NOACK;
			break;
		default:
			ret = MAC_TX_ERR;
			break;
		}

#endif /* ! DISCOVERY_AWARE_RDC_802154_AUTOACK */
	}



	if (!linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &linkaddr_null)
			&&  ret == MAC_TX_OK) {
		send_flag = 1;
		to_modifier+=10;
	}

	if(ret == MAC_TX_OK) {
		last_sent_ok = 1;
	}

	mac_call_sent_callback(sent, ptr, ret, 1);

	return last_sent_ok;
}
Ejemplo n.º 7
0
/*---------------------------------------------------------------------------*/
static int
read(void *buf, unsigned short bufsize)
{
  uint8_t i;
  uint8_t len;
  uint8_t crc_corr;
  int8_t rssi;

  PUTSTRING("RF: Read\n");

  /* Check the length */
  len = RFD;

  /* Check for validity */
  if(len > CC2530_RF_MAX_PACKET_LEN) {
    /* Oops, we must be out of sync. */
    PUTSTRING("RF: bad sync\n");

    RIMESTATS_ADD(badsynch);
    CC2530_CSP_ISFLUSHRX();
    return 0;
  }

  if(len <= CC2530_RF_MIN_PACKET_LEN) {
    PUTSTRING("RF: too short\n");

    RIMESTATS_ADD(tooshort);
    CC2530_CSP_ISFLUSHRX();
    return 0;
  }

  if(len - CHECKSUM_LEN > bufsize) {
    PUTSTRING("RF: too long\n");

    RIMESTATS_ADD(toolong);
    CC2530_CSP_ISFLUSHRX();
    return 0;
  }

#if CC2530_RF_CONF_HEXDUMP
  /* If we reach here, chances are the FIFO is holding a valid frame */
  io_arch_writeb(magic[0]);
  io_arch_writeb(magic[1]);
  io_arch_writeb(magic[2]);
  io_arch_writeb(magic[3]);
  io_arch_writeb(len);
#endif

  RF_RX_LED_ON();

  PUTSTRING("RF: read (0x");
  PUTHEX(len);
  PUTSTRING(" bytes) = ");
  len -= CHECKSUM_LEN;
  for(i = 0; i < len; ++i) {
    ((unsigned char *)(buf))[i] = RFD;
#if CC2530_RF_CONF_HEXDUMP
    io_arch_writeb(((unsigned char *)(buf))[i]);
#endif
    PUTHEX(((unsigned char *)(buf))[i]);
  }
  PUTSTRING("\n");

  /* Read the RSSI and CRC/Corr bytes */
  rssi = ((int8_t) RFD) - RSSI_OFFSET;
  crc_corr = RFD;

#if CC2530_RF_CONF_HEXDUMP
  io_arch_writeb(rssi);
  io_arch_writeb(crc_corr);
  io_arch_flush();
#endif

  /* MS bit CRC OK/Not OK, 7 LS Bits, Correlation value */
  if(crc_corr & CRC_BIT_MASK) {
    packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi);
    packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, crc_corr & LQI_BIT_MASK);
    RIMESTATS_ADD(llrx);
  } else {
    RIMESTATS_ADD(badcrc);
    CC2530_CSP_ISFLUSHRX();
    RF_RX_LED_OFF();
    return 0;
  }

  /* If FIFOP==1 and FIFO==0 then we had a FIFO overflow at some point. */
  if((FSMSTAT1 & (FSMSTAT1_FIFO | FSMSTAT1_FIFOP)) == FSMSTAT1_FIFOP) {
    /*
     * If we reach here means that there might be more intact packets in the
     * FIFO despite the overflow. This can happen with bursts of small packets.
     *
     * Only flush if the FIFO is actually empty. If not, then next pass we will
     * pick up one more packet or flush due to an error.
     */
    if(!RXFIFOCNT) {
      CC2530_CSP_ISFLUSHRX();
    }
  }

  RF_RX_LED_OFF();

  return (len);
}
Ejemplo n.º 8
0
static int fragment(struct net_buf *buf, void *ptr)
{
   struct queuebuf *q;
   int max_payload;
   int framer_hdrlen;
   uint16_t frag_tag;

   /* Number of bytes processed. */
   uint16_t processed_ip_out_len;
   struct net_buf *mbuf;
   bool last_fragment = false;

#define USE_FRAMER_HDRLEN 0
#if USE_FRAMER_HDRLEN
  framer_hdrlen = NETSTACK_FRAMER.length();
  if(framer_hdrlen < 0) {
    /* Framing failed, we assume the maximum header length */
    framer_hdrlen = 21;
  }
#else /* USE_FRAMER_HDRLEN */
  framer_hdrlen = 21;
#endif /* USE_FRAMER_HDRLEN */
  max_payload = MAC_MAX_PAYLOAD - framer_hdrlen - NETSTACK_LLSEC.get_overhead();

  PRINTF("max_payload: %d, framer_hdrlen: %d \n",max_payload, framer_hdrlen);

  mbuf = l2_buf_get_reserve(0);
  if (!mbuf) {
     goto fail;
  }
	uip_last_tx_status(mbuf) = MAC_TX_OK;

  /*
   * The destination address will be tagged to each outbound
   * packet. If the argument localdest is NULL, we are sending a
   * broadcast packet.
   */

  if((int)uip_len(buf) <= max_payload) {
    /* The packet does not need to be fragmented, send buf */
    packetbuf_copyfrom(mbuf, uip_buf(buf), uip_len(buf));
    send_packet(mbuf, &ip_buf_ll_dest(buf), true, ptr);
    ip_buf_unref(buf);
    return 1;
   }

    uip_uncomp_hdr_len(mbuf) = 0;
    uip_packetbuf_hdr_len(mbuf) = 0;
    packetbuf_clear(mbuf);
    uip_packetbuf_ptr(mbuf) = packetbuf_dataptr(mbuf);

    packetbuf_set_attr(mbuf, PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS,
                                     SICSLOWPAN_MAX_MAC_TRANSMISSIONS);

    PRINTF("fragmentation: total packet len %d\n", uip_len(buf));

    /*
     * The outbound IPv6 packet is too large to fit into a single 15.4
     * packet, so we fragment it into multiple packets and send them.
     * The first fragment contains frag1 dispatch, then
     * IPv6/HC1/HC06/HC_UDP dispatchs/headers.
     * The following fragments contain only the fragn dispatch.
     */
    int estimated_fragments = ((int)uip_len(buf)) / ((int)MAC_MAX_PAYLOAD - SICSLOWPAN_FRAGN_HDR_LEN) + 1;
    int freebuf = queuebuf_numfree(mbuf) - 1;
    PRINTF("uip_len: %d, fragments: %d, free bufs: %d\n", uip_len(buf), estimated_fragments, freebuf);
    if(freebuf < estimated_fragments) {
      PRINTF("Dropping packet, not enough free bufs\n");
      goto fail;
    }

    /* Create 1st Fragment */
    SET16(uip_packetbuf_ptr(mbuf), PACKETBUF_FRAG_DISPATCH_SIZE,
          ((SICSLOWPAN_DISPATCH_FRAG1 << 8) | uip_len(buf)));

    frag_tag = my_tag++;
    SET16(uip_packetbuf_ptr(mbuf), PACKETBUF_FRAG_TAG, frag_tag);
    PRINTF("fragmentation: fragment %d \n", frag_tag);

    /* Copy payload and send */
    uip_packetbuf_hdr_len(mbuf) += SICSLOWPAN_FRAG1_HDR_LEN;
    uip_packetbuf_payload_len(mbuf) = (max_payload - uip_packetbuf_hdr_len(mbuf)) & 0xfffffff8;
    PRINTF("(payload len %d, hdr len %d, tag %d)\n",
               uip_packetbuf_payload_len(mbuf), uip_packetbuf_hdr_len(mbuf), frag_tag);

    memcpy(uip_packetbuf_ptr(mbuf) + uip_packetbuf_hdr_len(mbuf),
              uip_buf(buf), uip_packetbuf_payload_len(mbuf));
    packetbuf_set_datalen(mbuf, uip_packetbuf_payload_len(mbuf) + uip_packetbuf_hdr_len(mbuf));
    q = queuebuf_new_from_packetbuf(mbuf);
    if(q == NULL) {
      PRINTF("could not allocate queuebuf for first fragment, dropping packet\n");
      goto fail;
    }
    net_buf_ref(mbuf);
    send_packet(mbuf, &ip_buf_ll_dest(buf), last_fragment, ptr);
    queuebuf_to_packetbuf(mbuf, q);
    queuebuf_free(q);
    q = NULL;

    /* Check tx result. */
    if((uip_last_tx_status(mbuf) == MAC_TX_COLLISION) ||
       (uip_last_tx_status(mbuf) == MAC_TX_ERR) ||
       (uip_last_tx_status(mbuf) == MAC_TX_ERR_FATAL)) {
      PRINTF("error in fragment tx, dropping subsequent fragments.\n");
      goto fail;
    }

    /* set processed_ip_out_len to what we already sent from the IP payload*/
    processed_ip_out_len = uip_packetbuf_payload_len(mbuf);

    /*
     * Create following fragments
     * Datagram tag is already in the buffer, we need to set the
     * FRAGN dispatch and for each fragment, the offset
     */
    uip_packetbuf_hdr_len(mbuf) = SICSLOWPAN_FRAGN_HDR_LEN;
    SET16(uip_packetbuf_ptr(mbuf), PACKETBUF_FRAG_DISPATCH_SIZE,
          ((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len(buf)));
    uip_packetbuf_payload_len(mbuf) = (max_payload - uip_packetbuf_hdr_len(mbuf)) & 0xfffffff8;

    while(processed_ip_out_len < uip_len(buf)) {
      PRINTF("fragmentation: fragment:%d, processed_ip_out_len:%d \n", my_tag, processed_ip_out_len);
      uip_packetbuf_ptr(mbuf)[PACKETBUF_FRAG_OFFSET] = processed_ip_out_len >> 3;

      /* Copy payload and send */
      if(uip_len(buf) - processed_ip_out_len < uip_packetbuf_payload_len(mbuf)) {
        /* last fragment */
        last_fragment = true;
        uip_packetbuf_payload_len(mbuf) = uip_len(buf) - processed_ip_out_len;
      }
      PRINTF("(offset %d, len %d, tag %d)\n",
             processed_ip_out_len >> 3, uip_packetbuf_payload_len(mbuf), my_tag);
      memcpy(uip_packetbuf_ptr(mbuf) + uip_packetbuf_hdr_len(mbuf),
             (uint8_t *)UIP_IP_BUF(buf) + processed_ip_out_len, uip_packetbuf_payload_len(mbuf));
      packetbuf_set_datalen(mbuf, uip_packetbuf_payload_len(mbuf) + uip_packetbuf_hdr_len(mbuf));
      q = queuebuf_new_from_packetbuf(mbuf);
      if(q == NULL) {
        PRINTF("could not allocate queuebuf, dropping fragment\n");
        goto fail;
      }
      net_buf_ref(mbuf);
      send_packet(mbuf, &ip_buf_ll_dest(buf), last_fragment, ptr);
      queuebuf_to_packetbuf(mbuf, q);
      queuebuf_free(q);
      q = NULL;
      processed_ip_out_len += uip_packetbuf_payload_len(mbuf);

      /* Check tx result. */
      if((uip_last_tx_status(mbuf) == MAC_TX_COLLISION) ||
         (uip_last_tx_status(mbuf) == MAC_TX_ERR) ||
         (uip_last_tx_status(mbuf) == MAC_TX_ERR_FATAL)) {
        PRINTF("error in fragment tx, dropping subsequent fragments.\n");
        goto fail;
      }
    }

    ip_buf_unref(buf);
    l2_buf_unref(mbuf);
    return 1;

fail:
    if (mbuf) {
      l2_buf_unref(mbuf);
    }
    return 0;
}
Ejemplo n.º 9
0
/*---------------------------------------------------------------------------*/
static void
recv_from_stunicast(struct stunicast_conn *stunicast, const rimeaddr_t *from)
{
  struct runicast_conn *c = (struct runicast_conn *)stunicast;
  /*  struct runicast_hdr *hdr = packetbuf_dataptr();*/

  PRINTF("%d.%d: runicast: recv_from_stunicast from %d.%d type %d seqno %d\n",
	 rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
	 from->u8[0], from->u8[1],
	 packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE),
	 packetbuf_attr(PACKETBUF_ATTR_PACKET_ID));

  if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
     PACKETBUF_ATTR_PACKET_TYPE_ACK) {
      PRINTF("%d.%d: runicast: got ACK from %d.%d, seqno %d (%d)\n",
	     rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
	     from->u8[0], from->u8[1],
	     packetbuf_attr(PACKETBUF_ATTR_PACKET_ID),
	     c->sndnxt);
    if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == c->sndnxt) {
      RIMESTATS_ADD(ackrx);
      PRINTF("%d.%d: runicast: ACKed %d\n",
	     rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
	     packetbuf_attr(PACKETBUF_ATTR_PACKET_ID));
      c->sndnxt = (c->sndnxt + 1) % (1 << RUNICAST_PACKET_ID_BITS);
      c->is_tx = 0;
      stunicast_cancel(&c->c);
      if(c->u->sent != NULL) {
	c->u->sent(c, stunicast_receiver(&c->c), c->rxmit);
      }
    } else {
      PRINTF("%d.%d: runicast: received bad ACK %d for %d\n",
	     rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
	     packetbuf_attr(PACKETBUF_ATTR_PACKET_ID),
	     c->sndnxt);
      RIMESTATS_ADD(badackrx);
    }
  } else if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
	    PACKETBUF_ATTR_PACKET_TYPE_DATA) {
    /*    int send_ack = 1;*/
    uint16_t packet_seqno;
    struct queuebuf *q;

    RIMESTATS_ADD(reliablerx);

    PRINTF("%d.%d: runicast: got packet %d\n",
	   rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
	   packetbuf_attr(PACKETBUF_ATTR_PACKET_ID));

    packet_seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);

    /*    packetbuf_hdrreduce(sizeof(struct runicast_hdr));*/

    q = queuebuf_new_from_packetbuf();
    if(q != NULL) {
      PRINTF("%d.%d: runicast: Sending ACK to %d.%d for %d\n",
	     rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
	     from->u8[0], from->u8[1],
	     packet_seqno);
      packetbuf_clear();
      /*    packetbuf_hdralloc(sizeof(struct runicast_hdr));
	    hdr = packetbuf_hdrptr();
	    hdr->type = TYPE_ACK;
	    hdr->seqno = packet_seqno;*/
      packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_ACK);
      packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, packet_seqno);
      stunicast_send(&c->c, from);
      RIMESTATS_ADD(acktx);

      queuebuf_to_packetbuf(q);
      queuebuf_free(q);
    } else {
      PRINTF("%d.%d: runicast: could not send ACK to %d.%d for %d: no queued buffers\n",
	     rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
	     from->u8[0], from->u8[1],
	     packet_seqno);
    }
    if(c->u->recv != NULL) {
      c->u->recv(c, from, packet_seqno);
    }
  }
}
Ejemplo n.º 10
0
Archivo: tests.c Proyecto: An-S/contiki
/* Test vector C.2.1.2 from IEEE 802.15.4-2006 */
static void
test_sec_lvl_6()
{
  uint8_t key[16] = { 0xC0 , 0xC1 , 0xC2 , 0xC3 ,
                      0xC4 , 0xC5 , 0xC6 , 0xC7 ,
                      0xC8 , 0xC9 , 0xCA , 0xCB ,
                      0xCC , 0xCD , 0xCE , 0xCF };
  uint8_t extended_source_address[8] = { 0xAC , 0xDE , 0x48 , 0x00 ,
                                         0x00 , 0x00 , 0x00 , 0x01 };
  uint8_t data[30] = { 0x2B , 0xDC , 0x84 , 0x21 , 0x43 ,
                       /* Destination Address */
                       0x02 , 0x00 , 0x00 , 0x00 , 0x00 , 0x48 , 0xDE , 0xAC ,
                       /* PAN-ID */
                       0xFF , 0xFF ,
                       /* Source Address */
                       0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x48 , 0xDE , 0xAC ,
                       /* Security Level */
                       0x06 ,
                       /* Frame Counter */
                       0x05 , 0x00 , 0x00 , 0x00 ,
                       0x01 , 0xCE };
  uint8_t oracle[LLSEC802154_MIC_LENGTH] = { 0x4F , 0xDE , 0x52 , 0x90 ,
                                             0x61 , 0xF9 , 0xC6 , 0xF1 };
  frame802154_frame_counter_t counter;
  uint8_t mic[LLSEC802154_MIC_LENGTH];
  
  printf("Testing verification ... ");
  
  packetbuf_clear();
  packetbuf_set_datalen(30);
  memcpy(packetbuf_hdrptr(), data, 30);
  counter.u32 = 5;
  packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, counter.u16[0]);
  packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, counter.u16[1]);
  packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, LLSEC802154_SECURITY_LEVEL);
  packetbuf_hdrreduce(29);
  
  CCM_STAR.set_key(key);
  ccm_star_mic_packetbuf(extended_source_address, mic, LLSEC802154_MIC_LENGTH);
  
  if(memcmp(mic, oracle, LLSEC802154_MIC_LENGTH) == 0) {
    printf("Success\n");
  } else {
    printf("Failure\n");
  }
  
  printf("Testing encryption ... ");
  
  ccm_star_ctr_packetbuf(extended_source_address);
  if(((uint8_t *) packetbuf_hdrptr())[29] == 0xD8) {
    printf("Success\n");
  } else {
    printf("Failure\n");
  }
  
  printf("Testing decryption ... ");
  ccm_star_ctr_packetbuf(extended_source_address);
  if(((uint8_t *) packetbuf_hdrptr())[29] == 0xCE) {
    printf("Success\n");
  } else {
    printf("Failure\n");
  }
}
Ejemplo n.º 11
0
/*---------------------------------------------------------------------------*/
static int
create_frame(int type, int do_create)
{
    frame802154_t params;
    int len;

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

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

    /* Build the FCF. */
    params.fcf.frame_type = FRAME802154_DATAFRAME;
    params.fcf.security_enabled = 0;
    params.fcf.frame_pending = packetbuf_attr(PACKETBUF_ATTR_PENDING);
    if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &linkaddr_null)) {
        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 (2003) version bit. */
    params.fcf.frame_version = FRAME802154_IEEE802154_2003;

    /* 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 {
        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 the output address is NULL in the Rime buf, then it is broadcast
     *  on the 802.15.4 network.
     */
    if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &linkaddr_null)) {
        /* 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);

    params.payload = packetbuf_dataptr();
    params.payload_len = packetbuf_datalen();
    len = frame802154_hdrlen(&params);
    if(!do_create) {
        /* Only calculate header length */
        return len;

    } else if(packetbuf_hdralloc(len)) {
        frame802154_create(&params, packetbuf_hdrptr(), len);

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

        return len;
    } else {
        PRINTF("15.4-OUT: too large header: %u\n", len);
        return FRAMER_FAILED;
    }
}
Ejemplo n.º 12
0
// TDMA_BS_send() -- called at a specific time
static void TDMA_BS_send(void)
{

  //printf("%05u,",RTIMER_NOW());//call time for BS_send

  //uint8_t bkn_len = 16;
  //uint8_t bkn_pkt[16]={0};
  //bkn_pkt[14]=1;
  //bkn_pkt[15]=2;
  char bkn_pkt[100];

  // Lab 5
  switch(beacon_msg_counter)
  {
    case 0:
      strncpy(bkn_pkt,"Welcome to CEE155/255  ",100);
      break;
    case 1:
      strncpy(bkn_pkt,"This msg is from the base station  ",100);
      break;
    case 2:
      strncpy(bkn_pkt,"Answer following questions:  ",100);
      break;
    case 3:
      strncpy(bkn_pkt,"1.fs of a 20Hz sine wave  ",100);
      break;
    case 4:
      strncpy(bkn_pkt,"2.Data rate of a 16 bit ADC and fs = 5Hz  ",100);
      break;
    case 5:
      strncpy(bkn_pkt,"3. list 6 blocks of sensor network  ",100);
      break;

  }

   //Lab 5
  uint8_t bkn_len = strlen(bkn_pkt)+1;
  beacon_msg_counter = (beacon_msg_counter+1)%6;

  // set timer for next BS send
  // right now, rtimer_timer does not consider drifting. For long time experiment, it may have problem
  rtimer_set(&BSTimer,RTIMER_TIME(&BSTimer)+segment_period,0,TDMA_BS_send,NULL);

  //update packet sequence number
  seq_num = seq_num + 1;

  if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_CMD) // has command to send
  {
    // Assume for BS, if the tdma_rdc_buf is not empty, then the payload should be command.
    // Should be changed if BS can send other types of data.
/*
    packetbuf_copyfrom((void *)&tdma_rdc_buffer[0],sizeof(uint8_t)*tdma_rdc_buf_ptr);
    packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE,PACKETBUF_ATTR_PACKET_TYPE_CMD);
    tdma_rdc_buf_full_flg = 0;
    tdma_rdc_buf_ptr = 0;
    tdma_rdc_buf_send_ptr = 0;
*/
    PRINTF("send command %s %d\n",tdma_rdc_buffer,packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE));
  }
  else
  {
    packetbuf_copyfrom((void *)&bkn_pkt,sizeof(uint8_t)*bkn_len);
    packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_TIMESTAMP);
  }


  BS_RX_start_time = radio_TX_time+BS_period;

  packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO,seq_num);


  uint8_t hdr_len = NETSTACK_FRAMER.create();

  // fail to create framer
  if(hdr_len < 0)
    return;

  //send packet -- pushed to radio layer
  if(NETSTACK_RADIO.send(packetbuf_hdrptr(),packetbuf_totlen()) != RADIO_TX_OK)
  {
    printf("TDMA RDC: BS fails to send packet\n");
  }
  else
  {
    printf("TDMA RDC: BS sends %u, %u bits\n",seq_num,packetbuf_datalen());
    char* data_ptr = (char *)packetbuf_dataptr();
   // PRINTF("%c%c%c\n",data_ptr[0],data_ptr[1],data_ptr[2]);
  }



}
Ejemplo n.º 13
0
PROCESS_THREAD(query_process, ev, data)
{
  static db_handle_t handle;
  db_result_t result;
  static tuple_id_t matching;
  static tuple_id_t processed;
#if !PREPARE_DB
  static struct etimer sampling_timer;
#endif
  static unsigned i, errors;

  PROCESS_BEGIN();

  printf("NetDB host\n");

  db_init();
  db_set_output_function(buffer_db_data);

  db_query(NULL, "REMOVE RELATION samples;");
  db_query(NULL, "CREATE RELATION samples;");
  db_query(NULL, "CREATE ATTRIBUTE time DOMAIN INT IN samples;");
  db_query(NULL, "CREATE ATTRIBUTE hum DOMAIN INT IN samples;");
  db_query(NULL, "CREATE INDEX samples.time TYPE INLINE;");

#if PREPARE_DB
  printf("Preparing the DB with %d tuples...\n", CARDINALITY);
  errors = 0;
  for(i = 1; i <= CARDINALITY; i++) {
    PROCESS_PAUSE();

    result = db_query(NULL, "INSERT (%u, %u) INTO samples;",
                      i, (unsigned)random_rand());
    if(DB_ERROR(result)) {
      errors++;
    }
  }
  printf("Done. Insertion errors: %d\n", errors);
  printf("Ready to process queries\n");
#else
  etimer_set(&sampling_timer, SAMPLING_INTERVAL * CLOCK_SECOND);
#endif

  for(;;) {
    PROCESS_WAIT_EVENT();

    if(ev == serial_line_event_message && data != NULL) {
      printf("START %s\n", (char *)data);
      result = db_query(&handle, data);
      if(DB_ERROR(result)) {
	buffer_db_data("Query error: %s\n", db_get_result_message(result));
        stop_handler(NULL);
	db_free(&handle);
	continue;
      }

      if(!db_processing(&handle)) {
	buffer_db_data("OK\n");
	send_buffered_data();
        stop_handler(NULL);
	continue;
      }

      packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE,
			 PACKETBUF_ATTR_PACKET_TYPE_STREAM);

      db_print_header(&handle);

      matching = 0;
      processed = 0;

      while(db_processing(&handle)) {
	PROCESS_PAUSE();

        if(matching == RESPONSE_LIMIT) {
	    buffer_db_data("Response suppressed at %u tuples: limit reached\n",
                           RESPONSE_LIMIT);
            stop_handler(NULL);
            db_free(&handle);
            break;
        }

	result = db_process(&handle);
        if(result == DB_GOT_ROW) {
	  /* The processed tuple matched the condition in the query. */
	  matching++;
	  processed++;
	  db_print_tuple(&handle);
	} else if(result == DB_OK) {
	  /* A tuple was processed, but did not match the condition. */
	  processed++;
	  continue;
	} else {
	  if(result == DB_FINISHED) {
	    /* The processing has finished. Wait for a new command. */
	    buffer_db_data("[%ld tuples returned; %ld tuples processed]\n",
			   (long)matching, (long)processed);
	    buffer_db_data("OK\n");
	  } else if(DB_ERROR(result)) {
	    buffer_db_data("Processing error: %s\n",
			   db_get_result_message(result));      
	  }
          stop_handler(NULL);
	  db_free(&handle);
	}
      }
      send_buffered_data();
    }

#if !PREPARE_DB
    if(etimer_expired(&sampling_timer)) {
      take_sample();
      etimer_reset(&sampling_timer);
    }
#endif
  }

  PROCESS_END();
}
Ejemplo n.º 14
0
/*---------------------------------------------------------------------------*/
static enum cmd_broker_result
on_helloack(uint8_t *payload, int p_flag)
{
  struct akes_nbr_entry *entry;
  uint8_t *secret;
  uint8_t key[AKES_NBR_CHALLENGE_LEN * 2];
  int is_new;

  PRINTF("akes: Received HELLOACK\n");

  if(!akes_is_acceptable_helloack()) {
    return CMD_BROKER_ERROR;
  }

  akes_nbr_delete_expired_tentatives();
  entry = akes_nbr_get_sender_entry();
  if(entry && entry->permanent && p_flag) {
    PRINTF("akes: No need to start a new session\n");
    return CMD_BROKER_ERROR;
  }

  secret = AKES_SCHEME.get_secret_with_helloack_sender(packetbuf_addr(PACKETBUF_ADDR_SENDER));
  if(!secret) {
    PRINTF("akes: No secret with HELLOACK sender\n");
    return CMD_BROKER_ERROR;
  }

  /* copy challenges and generate key */
  akes_nbr_copy_challenge(key, hello_challenge);
  akes_nbr_copy_challenge(key + AKES_NBR_CHALLENGE_LEN, payload);
  generate_pairwise_key(key, secret);

#if ANTI_REPLAY_WITH_SUPPRESSION
  packetbuf_set_attr(PACKETBUF_ATTR_NEIGHBOR_INDEX, payload[AKES_NBR_CHALLENGE_LEN]);
  anti_replay_parse_counter(payload + AKES_NBR_CHALLENGE_LEN + 1);
#endif /* ANTI_REPLAY_WITH_SUPPRESSION */
  if(adaptivesec_verify(key)) {
    PRINTF("akes: Invalid HELLOACK\n");
    return CMD_BROKER_ERROR;
  }

  is_new = 1;
  if(entry) {
    if(entry->permanent) {
      if(
#if AKES_NBR_WITH_PAIRWISE_KEYS
          !memcmp(key, entry->permanent->pairwise_key, AES_128_KEY_LENGTH)) {
#else /* AKES_NBR_WITH_PAIRWISE_KEYS */
          !memcmp(payload, entry->permanent->helloack_challenge, AKES_NBR_CACHED_HELLOACK_CHALLENGE_LEN)) {
#endif /* AKES_NBR_WITH_PAIRWISE_KEYS */

        PRINTF("akes: Replayed HELLOACK\n");
        return CMD_BROKER_ERROR;
      } else {
        akes_nbr_delete(entry, AKES_NBR_PERMANENT);
        is_new = 0;
      }
    }

    if(entry->tentative) {
#if !AKES_NBR_WITH_PAIRWISE_KEYS
      if(!entry->tentative->meta->has_wait_timer) {
        PRINTF("akes: Awaiting acknowledgement of ACK\n");
        return CMD_BROKER_ERROR;
      }
#endif /* !AKES_NBR_WITH_PAIRWISE_KEYS */

      if(ctimer_expired(&entry->tentative->meta->wait_timer)) {
        PRINTF("akes: Awaiting ACK\n");
        return CMD_BROKER_ERROR;
      } else {
        PRINTF("akes: Skipping HELLOACK\n");
        ctimer_stop(&entry->tentative->meta->wait_timer);
        akes_nbr_delete(entry, AKES_NBR_TENTATIVE);
      }
    }
  }
static void
send_announcement(void *ptr)
{
  int announcement_len;
  int transmit_len;
#if WITH_CONTIKIMAC_HEADER
  struct hdr *chdr;
#endif /* WITH_CONTIKIMAC_HEADER */
  
  /* Set up the probe header. */
  packetbuf_clear();
  announcement_len = format_announcement(packetbuf_dataptr());

  if(announcement_len > 0) {
    packetbuf_set_datalen(announcement_len);

    packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
    packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &rimeaddr_null);
    packetbuf_set_attr(PACKETBUF_ATTR_RADIO_TXPOWER,
                       announcement_radio_txpower);
#if WITH_CONTIKIMAC_HEADER
    transmit_len = packetbuf_totlen();
    if(packetbuf_hdralloc(sizeof(struct hdr)) == 0) {
      /* Failed to allocate space for contikimac header */
      PRINTF("contikimac: send announcement failed, too large header\n");
      return;
    }
    chdr = packetbuf_hdrptr();
    chdr->id = CONTIKIMAC_ID;
    chdr->len = transmit_len;
#endif /* WITH_CONTIKIMAC_HEADER */

    if(NETSTACK_FRAMER.create()) {
      rtimer_clock_t t;
      int i, collisions;
      we_are_sending = 1;

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

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

      collisions = 0;
      /* Check for collisions */
      for(i = 0; i < CCA_COUNT_MAX; ++i) {
        t = RTIMER_NOW();
        on();
#if NURTIMER
        while(RTIMER_CLOCK_LT(t, RTIMER_NOW(), t + CCA_CHECK_TIME));
#else
        while(RTIMER_CLOCK_LT(RTIMER_NOW(), t + CCA_CHECK_TIME));
#endif
        if(NETSTACK_RADIO.channel_clear() == 0) {
          collisions++;
          off();
          break;
        }
        off();
#if NURTIMER
        while(RTIMER_CLOCK_LT(t0, RTIMER_NOW(), t + CCA_SLEEP_TIME + CCA_CHECK_TIME));
#else
        while(RTIMER_CLOCK_LT(RTIMER_NOW(), t + CCA_SLEEP_TIME + CCA_CHECK_TIME)) { }
#endif
      }

      if(collisions == 0) {
        
        NETSTACK_RADIO.prepare(packetbuf_hdrptr(), transmit_len);
        
        NETSTACK_RADIO.transmit(transmit_len);
        t = RTIMER_NOW();
#if NURTIMER
        while(RTIMER_CLOCK_LT(t, RTIMER_NOW(), t + INTER_PACKET_INTERVAL));
#else
        while(RTIMER_CLOCK_LT(RTIMER_NOW(), t + INTER_PACKET_INTERVAL)) { }
#endif
        NETSTACK_RADIO.transmit(transmit_len);
      }
      we_are_sending = 0;
    }
  }
}
Ejemplo n.º 16
0
/**
 * \brief      read a received frame out of the radio buffer 
 * \param buf         pointer to where to copy received data
 * \param bufsize     Maximum size we can copy into bufsize
 * \return     Returns length of data read (> 0) if successful
 * \retval -1  Failed, was transmitting so FIFO is invalid
 * \retval -2  Failed, rx timed out (stuck in rx?)
 * \retval -3  Failed, too large frame for buffer
 * \retval -4  Failed, CRC/FCS failed (if USE_HW_FCS_CHECK is true)
 */
static int
rf212_read(void *buf, unsigned short bufsize)
{
  
  uint8_t ed;       /* frame metadata */
  uint8_t frame_len = 0;
  uint8_t len = 0;
  int rssi;
#if DEBUG_PRINTDATA
  uint8_t tempreadlen;
#endif  /* DEBUG_PRINTDATA */

  if(pending_frame == 0) {
    return 0;
  }
  pending_frame = 0;

 /* check that data in FIFO is valid */
 //radio_state = RF212_STATUS();
  //if(radio_state == STATE_BUSY_TX) {
    ///* data is invalid, bail out */
    //PRINTF("RF212: read while in BUSY_TX ie invalid, dropping.\n");
    //return -1;
  //}
  //if(radio_state == STATE_BUSY_RX) {
    ///* still receiving - data is invalid, wait for it to finish */
    //PRINTF("RF212: read while BUSY_RX, waiting.\n");
    //BUSYWAIT_UNTIL(RF212_STATUS() != STATE_BUSY_RX, 10 * RTIMER_SECOND/1000);
	//#if (DATA_RATE==BPSK_20||BPSK_40||OQPSK_SIN_RC_100)
	//BUSYWAIT_UNTIL(RF212_STATUS() != STATE_BUSY_RX, 10 * RTIMER_SECOND/1000);
	//BUSYWAIT_UNTIL(RF212_STATUS() != STATE_BUSY_RX, 10 * RTIMER_SECOND/1000);
	//BUSYWAIT_UNTIL(RF212_STATUS() != STATE_BUSY_RX, 10 * RTIMER_SECOND/1000);
	//BUSYWAIT_UNTIL(RF212_STATUS() != STATE_BUSY_RX, 10 * RTIMER_SECOND/1000);
	//#endif
    //if(RF212_STATUS() == STATE_BUSY_RX) {
      //PRINTF("RF212: timed out, still BUSY_RX, dropping.\n");
      //return -2;
    //}
  //} 

  /* get length of data in FIFO */
  trx_frame_read(&frame_len, 1);
#if DEBUG_PRINTDATA
  tempreadlen = frame_len;
#endif  /* DEBUG_PRINTDATA */
  if(frame_len == 1) {
    frame_len = 0;
  }

  len = frame_len;
#if USE_HW_FCS_CHECK
  /* FCS has already been stripped */
  len = frame_len - 2;
#endif  /* USE_HW_FCS_CHECK */

  if(frame_len == 0) {
    return 0;
  }
  if(len > bufsize) {
    /* too large frame for the buffer, drop */
    PRINTF("RF212: too large frame for buffer, dropping (%u > %u).\n", frame_len, bufsize);
    flush_buffer();
    return -3;
  }
  PRINTF("RF212 read %u B\n", frame_len);

  /* read out the data into the buffer, disregarding the length and metadata bytes */
    trx_sram_read(1,(uint8_t *)buf, len);
#if DEBUG_PRINTDATA
  {
    int k;
    PRINTF("RF212: Read frame (%u/%u): ", tempreadlen, frame_len);
    for(k = 0; k < frame_len; k++) {
      PRINTF("%02x", *((uint8_t *)buf + k));
    }
    PRINTF("\n");
  }
#endif  /* DEBUG_PRINTDATA */

  /* 
   * Energy level during reception, ranges from 0x00 to 0x53 (=83d) with a
   * resolution of 1dB and accuracy of +/- 5dB. 0xFF means invalid measurement.
   * 0x00 means <= RSSI(base_val), which is -91dBm (typ). See datasheet 12.7.
   * Ergo, real RSSI is (ed-91) dBm or less.
   */
  #define RSSI_OFFSET       (91)
  ed = trx_reg_read(RF212_REG_PHY_ED_LEVEL);
  rssi = (int) ed - RSSI_OFFSET;
  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi);
  flush_buffer();

//#if USE_HW_FCS_CHECK
  //{
    //uint8_t crc_ok;   /* frame metadata */
    //crc_ok = rf212_arch_read_reg(RF212_REG_PHY_RSSI) & PHY_RSSI_CRC_VALID;
    //if(crc_ok == 0) {
      ///* CRC/FCS fail, drop */
      //PRINTF("RF212: CRC/FCS fail, dropping.\n");
      //flush_buffer();
      //return -4;
    //}
  //}
//#endif  /* USE_HW_FCS_CHECK */ 

  return len;
}
/*---------------------------------------------------------------------------*/
static int
send_packet(mac_callback_t mac_callback, void *mac_callback_ptr)
{
  rtimer_clock_t t0;
  rtimer_clock_t t;
  rtimer_clock_t encounter_time = 0, last_transmission_time = 0;
  uint8_t first_transmission = 1;
  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 i;
  int ret;
#if WITH_CONTIKIMAC_HEADER
  struct hdr *chdr;
#endif /* WITH_CONTIKIMAC_HEADER */

  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);
  
  if(WITH_STREAMING) {
    if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
       PACKETBUF_ATTR_PACKET_TYPE_STREAM) {
      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;
      is_streaming = 1;
    } else {
      is_streaming = 0;
    }
  }

  if(is_streaming) {
    packetbuf_set_attr(PACKETBUF_ATTR_PENDING, 1);
  }
  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 /* WITH_CONTIKIMAC_HEADER */
  /* 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 /* WITH_CONTIKIMAC_HEADER */

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

    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_streaming) {
#if WITH_PHASE_OPTIMIZATION
    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) {
        
        ret = phase_wait(&phase_list, packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                         CYCLE_TIME, GUARD_TIME,
                         mac_callback, mac_callback_ptr);
        if(ret == PHASE_DEFERRED) {
          return MAC_TX_DEFERRED;
        }
        if(ret != PHASE_UNKNOWN) {
          is_known_receiver = 1;
        }
      }
    } else {
      ret = phase_wait(&phase_list, packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                       CYCLE_TIME, GUARD_TIME,
                       mac_callback, mac_callback_ptr);
      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;

  if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) !=
     PACKETBUF_ATTR_PACKET_TYPE_ACK && is_streaming == 0) {
    /* Check if there are any transmissions by others. */
    for(i = 0; i < CCA_COUNT_MAX; ++i) {
      t0 = RTIMER_NOW();
      on();
#if NURTIMER
      while(RTIMER_CLOCK_LT(t0, RTIMER_NOW(), t0 + CCA_CHECK_TIME));
#else
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + CCA_CHECK_TIME)) { }
#endif
      if(NETSTACK_RADIO.channel_clear() == 0) {
        collisions++;
        off();
        break;
      }
      off();
      t0 = RTIMER_NOW();
#if NURTIMER
      while(RTIMER_CLOCK_LT(t0, RTIMER_NOW(), t0 + CCA_SLEEP_TIME));
#else
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + CCA_SLEEP_TIME)) { }
#endif
    }
  }

  if(collisions > 0) {
    we_are_sending = 0;
    off();
    PRINTF("contikimac: collisions before sending\n");
    return MAC_TX_COLLISION;
  }

  if(!is_broadcast) {
    on();
  }
  
  watchdog_periodic();
  t0 = RTIMER_NOW();
  t = RTIMER_NOW();
#if NURTIMER
  for(strobes = 0, collisions = 0;
      got_strobe_ack == 0 && collisions == 0 &&
      RTIMER_CLOCK_LT(t0, RTIMER_NOW(), t0 + STROBE_TIME); strobes++) {
#else
  for(strobes = 0, collisions = 0;
      got_strobe_ack == 0 && collisions == 0 &&
      RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + STROBE_TIME); strobes++) {
#endif

    watchdog_periodic();
    
    if(is_known_receiver && !RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + MAX_PHASE_STROBE_TIME)) {
      break;
    }
    
    len = 0;

    t = RTIMER_NOW();
    
    {
      rtimer_clock_t wt;
      rtimer_clock_t now = RTIMER_NOW();
      int ret;

      ret = NETSTACK_RADIO.transmit(transmit_len);

      wt = RTIMER_NOW();
#if NURTIMER
      while(RTIMER_CLOCK_LT(wt, RTIMER_NOW(), wt + INTER_PACKET_INTERVAL));
#else
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }
#endif
      if(!is_broadcast && (NETSTACK_RADIO.receiving_packet() ||
                           NETSTACK_RADIO.pending_packet() ||
                           NETSTACK_RADIO.channel_clear() == 0)) {
        uint8_t ackbuf[ACK_LEN];
        wt = RTIMER_NOW();
#if NURTIMER
        while(RTIMER_CLOCK_LT(wt, RTIMER_NOW(), wt + AFTER_ACK_DETECTECT_WAIT_TIME));
#else
        while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + AFTER_ACK_DETECTECT_WAIT_TIME)) { }
#endif
        len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
        if(len == ACK_LEN) {
          got_strobe_ack = 1;
          //          encounter_time = last_transmission_time;
          encounter_time = now;
          break;
        } else {
          PRINTF("contikimac: collisions while sending\n");
          collisions++;
        }
      }
      last_transmission_time = now;
      first_transmission = 0;
    }
  }

  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 && is_reliable) {
      on();                       /* Wait for ACK packet */
    } else {
      off();
    }
  } else {
    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 */

  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(!first_transmission)*/ {

    /*    COOJA_DEBUG_PRINTF("first phase 0x%02x\n", encounter_time % CYCLE_TIME);*/
    
    if(WITH_ACK_OPTIMIZATION) {
      if(collisions == 0 && packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) !=
         PACKETBUF_ATTR_PACKET_TYPE_ACK && is_streaming == 0) {
        phase_update(&phase_list, packetbuf_addr(PACKETBUF_ADDR_RECEIVER), encounter_time,
                     ret);
      }
    } else {
      if(collisions == 0 && is_streaming == 0) {
        phase_update(&phase_list, packetbuf_addr(PACKETBUF_ADDR_RECEIVER), encounter_time,
                     ret);
      }
    }
  }
#endif /* WITH_PHASE_OPTIMIZATION */

  return ret;
}
/*---------------------------------------------------------------------------*/
static void
qsend_packet(mac_callback_t sent, void *ptr)
{
  int ret = send_packet(sent, ptr);
  if(ret != MAC_TX_DEFERRED) {
    //    printf("contikimac qsend_packet %p\n", ptr);
    mac_call_sent_callback(sent, ptr, ret, 1);
  }
}
Ejemplo n.º 18
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);
      }
      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);
}
Ejemplo n.º 19
0
/*---------------------------------------------------------------------------*/
static void
send_packet(mac_callback_t sent, void *ptr)
{
  int ret;
  packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
#if NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW
  packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
#endif /* NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW */

  if(NETSTACK_FRAMER.create() < 0) {
    /* Failed to allocate space for headers */
    PRINTF("nullrdc: send failed, too large header\n");
    ret = MAC_TX_ERR_FATAL;
  } else {

#if NULLRDC_802154_AUTOACK
    int is_broadcast;
    uint8_t dsn;
    dsn = ((uint8_t *)packetbuf_hdrptr())[2] & 0xff;

    NETSTACK_RADIO.prepare(packetbuf_hdrptr(), packetbuf_totlen());

    is_broadcast = rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                                &rimeaddr_null);

    if(NETSTACK_RADIO.receiving_packet() ||
       (!is_broadcast && NETSTACK_RADIO.pending_packet())) {

      /* Currently receiving a packet over air or the radio has
         already received a packet that needs to be read before
         sending with auto ack. */
      ret = MAC_TX_COLLISION;

    } else {
      switch(NETSTACK_RADIO.transmit(packetbuf_totlen())) {
      case RADIO_TX_OK:
        if(is_broadcast) {
          ret = MAC_TX_OK;
        } else {
          rtimer_clock_t wt;

          /* Check for ack */
          wt = RTIMER_NOW();
          watchdog_periodic();
          while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + ACK_WAIT_TIME));

          ret = MAC_TX_NOACK;
          if(NETSTACK_RADIO.receiving_packet() ||
             NETSTACK_RADIO.pending_packet() ||
             NETSTACK_RADIO.channel_clear() == 0) {
            int len;
            uint8_t ackbuf[ACK_LEN];

            wt = RTIMER_NOW();
            watchdog_periodic();
            while(RTIMER_CLOCK_LT(RTIMER_NOW(),
                                  wt + AFTER_ACK_DETECTED_WAIT_TIME));

            if(NETSTACK_RADIO.pending_packet()) {
              len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
              if(len == ACK_LEN && ackbuf[2] == dsn) {
                /* Ack received */
                ret = MAC_TX_OK;
              } else {
                /* Not an ack or ack not for us: collision */
                ret = MAC_TX_COLLISION;
              }
            }
          }
        }
        break;
      case RADIO_TX_COLLISION:
        ret = MAC_TX_COLLISION;
        break;
      default:
        ret = MAC_TX_ERR;
        break;
      }
    }

#else /* ! NULLRDC_802154_AUTOACK */

    switch(NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen())) {
    case RADIO_TX_OK:
      ret = MAC_TX_OK;
      break;
    case RADIO_TX_COLLISION:
      ret = MAC_TX_COLLISION;
      break;
    case RADIO_TX_NOACK:
      ret = MAC_TX_NOACK;
      break;
    default:
      ret = MAC_TX_ERR;
      break;
    }

#endif /* ! NULLRDC_802154_AUTOACK */
  }
  mac_call_sent_callback(sent, ptr, ret, 1);
}
Ejemplo n.º 20
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 */
    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);
}
Ejemplo n.º 21
0
/*---------------------------------------------------------------------------*/
static int
cc2420_read(void *buf, unsigned short bufsize)
{
  uint8_t footer[2];
  uint8_t len;
#if CC2420_CONF_CHECKSUM
  uint16_t checksum;
#endif /* CC2420_CONF_CHECKSUM */

  if(!CC2420_FIFOP_IS_1) {
    return 0;
  }
  /*  if(!pending) {
    return 0;
    }*/
  
  pending = 0;
  
  GET_LOCK();

  cc2420_packets_read++;

  getrxbyte(&len);

  if(len > CC2420_MAX_PACKET_LEN) {
    /* Oops, we must be out of sync. */
    flushrx();
    RIMESTATS_ADD(badsynch);
    RELEASE_LOCK();
    return 0;
  }

  if(len <= AUX_LEN) {
    flushrx();
    RIMESTATS_ADD(tooshort);
    RELEASE_LOCK();
    return 0;
  }

  if(len - AUX_LEN > bufsize) {
    flushrx();
    RIMESTATS_ADD(toolong);
    RELEASE_LOCK();
    return 0;
  }

  getrxdata(buf, len - AUX_LEN);
#if CC2420_CONF_CHECKSUM
  getrxdata(&checksum, CHECKSUM_LEN);
#endif /* CC2420_CONF_CHECKSUM */
  getrxdata(footer, FOOTER_LEN);

#if CC2420_CONF_CHECKSUM
  if(checksum != crc16_data(buf, len - AUX_LEN, 0)) {
    PRINTF("checksum failed 0x%04x != 0x%04x\n",
	   checksum, crc16_data(buf, len - AUX_LEN, 0));
  }

  if(footer[1] & FOOTER1_CRC_OK &&
     checksum == crc16_data(buf, len - AUX_LEN, 0)) {
#else
  if(footer[1] & FOOTER1_CRC_OK) {
#endif /* CC2420_CONF_CHECKSUM */
    cc2420_last_rssi = footer[0];
    cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION;


    packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2420_last_rssi);
    packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2420_last_correlation);

    RIMESTATS_ADD(llrx);

  } else {
    RIMESTATS_ADD(badcrc);
    len = AUX_LEN;
  }

  if(CC2420_FIFOP_IS_1) {
    if(!CC2420_FIFO_IS_1) {
      /* Clean up in case of FIFO overflow!  This happens for every
       * full length frame and is signaled by FIFOP = 1 and FIFO =
       * 0. */
      flushrx();
    } else {
      /* Another packet has been received and needs attention. */
      process_poll(&cc2420_process);
    }
  }

  RELEASE_LOCK();

  if(len < AUX_LEN) {
    return 0;
  }

  return len - AUX_LEN;
}
/*---------------------------------------------------------------------------*/
void
cc2420_set_txpower(uint8_t power)
{
  GET_LOCK();
  set_txpower(power);
  RELEASE_LOCK();
}
Ejemplo n.º 22
0
Archivo: tsch.c Proyecto: CCH55/contiki
/* A periodic process to send TSCH Enhanced Beacons (EB) */
PROCESS_THREAD(tsch_send_eb_process, ev, data)
{
  static struct etimer eb_timer;

  PROCESS_BEGIN();

  /* Wait until association */
  etimer_set(&eb_timer, CLOCK_SECOND / 10);
  while(!tsch_is_associated) {
    PROCESS_WAIT_UNTIL(etimer_expired(&eb_timer));
    etimer_reset(&eb_timer);
  }

  /* Set an initial delay except for coordinator, which should send an EB asap */
  if(!tsch_is_coordinator) {
    etimer_set(&eb_timer, random_rand() % TSCH_EB_PERIOD);
    PROCESS_WAIT_UNTIL(etimer_expired(&eb_timer));
  }

  while(1) {
    unsigned long delay;

    if(tsch_is_associated && tsch_current_eb_period > 0) {
      /* Enqueue EB only if there isn't already one in queue */
      if(tsch_queue_packet_count(&tsch_eb_address) == 0) {
        int eb_len;
        uint8_t hdr_len = 0;
        uint8_t tsch_sync_ie_offset;
        /* Prepare the EB packet and schedule it to be sent */
        packetbuf_clear();
        /* We don't use seqno 0 */
        if(++tsch_packet_seqno == 0) {
          tsch_packet_seqno++;
        }
        packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_BEACONFRAME);
        packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, tsch_packet_seqno);
#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_EB);
          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_EB);
        }
#endif /* LLSEC802154_ENABLED */
        eb_len = tsch_packet_create_eb(packetbuf_dataptr(), PACKETBUF_SIZE,
            tsch_packet_seqno, &hdr_len, &tsch_sync_ie_offset);
        if(eb_len != 0) {
          struct tsch_packet *p;
          packetbuf_set_datalen(eb_len);
          /* Enqueue EB packet */
          if(!(p = tsch_queue_add_packet(&tsch_eb_address, NULL, NULL))) {
            PRINTF("TSCH:! could not enqueue EB packet\n");
          } else {
            PRINTF("TSCH: enqueue EB packet %u %u\n", eb_len, hdr_len);
            p->tsch_sync_ie_offset = tsch_sync_ie_offset;
            p->header_len = hdr_len;
          }
        }
      }
    }
    if(tsch_current_eb_period > 0) {
      /* Next EB transmission with a random delay
       * within [tsch_current_eb_period*0.75, tsch_current_eb_period[ */
      delay = (tsch_current_eb_period - tsch_current_eb_period / 4)
        + random_rand() % (tsch_current_eb_period / 4);
    } else {
      delay = TSCH_EB_PERIOD;
    }
    etimer_set(&eb_timer, delay);
    PROCESS_WAIT_UNTIL(etimer_expired(&eb_timer));
  }
  PROCESS_END();
}
Ejemplo n.º 23
0
/*---------------------------------------------------------------------------*/
static void
send(mac_callback_t sent, void *ptr)
{
  packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME);
  NETSTACK_MAC.send(sent, ptr);
}
Ejemplo n.º 24
0
Archivo: tsch.c Proyecto: CCH55/contiki
/* 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;
  }

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

  /* 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);
  packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, tsch_packet_seqno);

#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((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 !tsch_queue_add_packet\n");
      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), tsch_packet_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);
  }
}
Ejemplo n.º 25
0
// TDMA_SN_send() -- called at a assigned time slot
static void TDMA_SN_send(void)
{
  //set timer for open RADIO -- for opening earlier 2 ms
  //uint16_t time = RTIMER_TIME(&SNTimer)+RTIMER_MS*(segment_period-BS_period-my_slot*TS_period);
  uint16_t callBkTime = RTIMER_NOW();
  radioontime = SN_RX_start_time+segment_period-GRD_PERIOD;//RTIMER_TIME(&SNTimer) + (total_slot_num-my_slot)*TS_period-GRD_PERIOD;//(segment_period-BS_period-(my_slot)*TS_period - GRD_PERIOD);
  rtimer_set(&SNTimer,radioontime,0,NETSTACK_RADIO.on,NULL);


  //update packet sequence number
  seq_num = seq_num + 1;

  //wait if the tdma_rdc_buffer is accessing by other functions
  while(tdma_rdc_buf_in_using_flg);

  // lock tdma_rdc_buffer and preventing access from other functions.
  tdma_rdc_buf_in_using_flg = 1;


  if (tdma_rdc_buf_full_flg == 0)
  {
    packetbuf_copyfrom((void *)&tdma_rdc_buffer[0],sizeof(uint8_t)*tdma_rdc_buf_ptr);
    packetbuf_set_datalen(tdma_rdc_buf_ptr);
  }
  else
  {
    uint8_t temp_len = MAX_PKT_PAYLOAD_SIZE - tdma_rdc_buf_send_ptr;
    memcpy(packetbuf_dataptr(),tdma_rdc_buffer+tdma_rdc_buf_send_ptr,sizeof(uint8_t)*temp_len);
    memcpy(packetbuf_dataptr()+temp_len,tdma_rdc_buffer,sizeof(uint8_t)*tdma_rdc_buf_send_ptr);
    packetbuf_set_datalen(MAX_PKT_PAYLOAD_SIZE);
  }


  // send packet -- pushed to radio layer
  if(NETSTACK_RADIO.on())
  {
    packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO,seq_num);
    uint8_t hdr_len = NETSTACK_FRAMER.create();


    if(NETSTACK_RADIO.send(packetbuf_hdrptr(),packetbuf_totlen()) != RADIO_TX_OK)
    {
      printf("TDMA RDC: SN fails to send packet\n");
    }
    else
    {
      //lab 5
      //printf("TDMA RDC: SN sends %d, %d bytes\n",seq_num,packetbuf_datalen());
    }
    tdma_rdc_buf_full_flg = 0;
    tdma_rdc_buf_ptr = 0;
    tdma_rdc_buf_send_ptr = 0;
    memset(tdma_rdc_buffer,0,MAX_PKT_PAYLOAD_SIZE);
  }
  else
  {
    printf("TDMA RDC: SN fails to open radio\n");
  }
  // turn off radio
  NETSTACK_RADIO.off();

  // release tdma_rdc_buffer
  tdma_rdc_buf_in_using_flg = 0;

}
Ejemplo n.º 26
0
/*---------------------------------------------------------------------------*/
phase_status_t
phase_wait(const linkaddr_t *neighbor, rtimer_clock_t cycle_time,
           rtimer_clock_t guard_time,
           mac_callback_t mac_callback, void *mac_callback_ptr,
           struct rdc_buf_list *buf_list)
{
  struct phase *e;
  //  const linkaddr_t *neighbor = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
  /* We go through the list of phases to find if we have recorded a
     phase for this particular neighbor. If so, we can compute the
     time for the next expected phase and setup a ctimer to switch on
     the radio just before the phase. */
  e = nbr_table_get_from_lladdr(nbr_phase, neighbor);
  if(e != NULL) {
    rtimer_clock_t wait, now, expected, sync;
    clock_time_t ctimewait;
    
    /* We expect phases to happen every CYCLE_TIME time
       units. The next expected phase is at time e->time +
       CYCLE_TIME. To compute a relative offset, we subtract
       with clock_time(). Because we are only interested in turning
       on the radio within the CYCLE_TIME period, we compute the
       waiting time with modulo CYCLE_TIME. */
    
    /*      printf("neighbor phase 0x%02x (cycle 0x%02x)\n", e->time & (cycle_time - 1),
            cycle_time);*/

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

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

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

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

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

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

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

    expected = now + wait - guard_time;
    if(!RTIMER_CLOCK_LT(expected, now)) {
      /* Wait until the receiver is expected to be awake */
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected));
    }
    return PHASE_SEND_NOW;
  }
  return PHASE_UNKNOWN;
}
Ejemplo n.º 27
0
/*---------------------------------------------------------------------------*/
static int
send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
	    struct rdc_buf_list *buf_list,
            int is_receiver_awake)
{
  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;
  }

#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
  if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &linkaddr_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();

#ifdef NETSTACK_ENCRYPT
  NETSTACK_ENCRYPT();
#endif /* NETSTACK_ENCRYPT */

  transmit_len = packetbuf_totlen();

  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(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_broadcast && (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 /* RDC_CONF_HARDWARE_ACK */
     /* 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(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
		   encounter_time, ret);
    }
  }
#endif /* WITH_PHASE_OPTIMIZATION */

  return ret;
}
Ejemplo n.º 28
0
/*---------------------------------------------------------------------------*/
static void
node_packet_received(struct runicast_conn *c, const rimeaddr_t *from,
                     uint8_t seqno)
{
    struct collect_conn *tc = (struct collect_conn *)
                              ((char *)c - offsetof(struct collect_conn, runicast_conn));
    int i;

    /* To protect against forwarding duplicate packets, we keep a list
       of recently forwarded packet seqnos. If the seqno of the current
       packet exists in the list, we drop the packet. */

    for(i = 0; i < NUM_RECENT_PACKETS; i++) {
        if(recent_packets[i].seqno == packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID) &&
                rimeaddr_cmp(&recent_packets[i].originator,
                             packetbuf_addr(PACKETBUF_ADDR_ESENDER))) {
            PRINTF("%d.%d: dropping duplicate packet from %d.%d with seqno %d\n",
                   rimeaddr_node_addr.u8[RIMEADDR_SIZE-2], rimeaddr_node_addr.u8[RIMEADDR_SIZE-1],
                   recent_packets[i].originator.u8[RIMEADDR_SIZE-2], recent_packets[i].originator.u8[RIMEADDR_SIZE-1],
                   packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID));
            /* Drop the packet. */
            return;
        }
    }
    recent_packets[recent_packet_ptr].seqno = packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID);
    rimeaddr_copy(&recent_packets[recent_packet_ptr].originator,
                  packetbuf_addr(PACKETBUF_ADDR_ESENDER));
    recent_packet_ptr = (recent_packet_ptr + 1) % NUM_RECENT_PACKETS;

    if(tc->rtmetric == SINK) {

        /* If we are the sink, we call the receive function. */

        PRINTF("%d.%d: sink received packet from %d.%d via %d.%d\n",
               rimeaddr_node_addr.u8[RIMEADDR_SIZE-2], rimeaddr_node_addr.u8[RIMEADDR_SIZE-1],
               packetbuf_addr(PACKETBUF_ADDR_ESENDER)->u8[RIMEADDR_SIZE-2],
               packetbuf_addr(PACKETBUF_ADDR_ESENDER)->u8[RIMEADDR_SIZE-1],
               from->u8[RIMEADDR_SIZE-2], from->u8[RIMEADDR_SIZE-1]);

        if(tc->cb->recv != NULL) {
            tc->cb->recv(packetbuf_addr(PACKETBUF_ADDR_ESENDER),
                         packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID),
                         packetbuf_attr(PACKETBUF_ATTR_HOPS));
        }
        return;
    } else if(packetbuf_attr(PACKETBUF_ATTR_TTL) > 1 &&
              tc->rtmetric != RTMETRIC_MAX) {

        /* If we are not the sink, we forward the packet to the best
           neighbor. */
        packetbuf_set_attr(PACKETBUF_ATTR_HOPS, packetbuf_attr(PACKETBUF_ATTR_HOPS) + 1);
        packetbuf_set_attr(PACKETBUF_ATTR_TTL, packetbuf_attr(PACKETBUF_ATTR_TTL) - 1);


        PRINTF("%d.%d: packet received from %d.%d via %d.%d, forwarding %d\n",
               rimeaddr_node_addr.u8[RIMEADDR_SIZE-2], rimeaddr_node_addr.u8[RIMEADDR_SIZE-1],
               packetbuf_addr(PACKETBUF_ADDR_ESENDER)->u8[RIMEADDR_SIZE-2],
               packetbuf_addr(PACKETBUF_ADDR_ESENDER)->u8[RIMEADDR_SIZE-1],
               from->u8[RIMEADDR_SIZE-2], from->u8[RIMEADDR_SIZE-1], tc->forwarding);

        if(packetqueue_enqueue_packetbuf(&forwarding_queue, FORWARD_PACKET_LIFETIME,
                                         tc)) {
            send_queued_packet();
        } else {
            PRINTF("%d.%d: packet dropped: no queue buffer available\n",
                   rimeaddr_node_addr.u8[RIMEADDR_SIZE-2], rimeaddr_node_addr.u8[RIMEADDR_SIZE-1]);
        }
    }

    return;
}
Ejemplo n.º 29
0
/*---------------------------------------------------------------------------*/
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 */
        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);
  } else {
    PRINTF("csma: send broadcast\n");
    NETSTACK_RDC.send(sent, ptr);
  }
}
Ejemplo n.º 30
0
/*---------------------------------------------------------------------------*/
int
nrf24l01_read(void *buf, unsigned short bufsize)
{
  uint8_t *framep;
 // uint8_t footer[2];
  uint8_t len;
 
#if RF230_CONF_CHECKSUM
  uint16_t checksum;
#endif /* RF230_CONF_CHECKSUM */

#if RF230_CONF_TIMESTAMPS
  struct timestamp t;
#endif /* RF230_CONF_TIMESTAMPS */

  PRINTF("rf230_read: %u bytes lqi %u crc %u\n",rxframe.length,rxframe.lqi,rxframe.crc);

#if DEBUG>1
  for (len=0;len<rxframe.length;len++) PRINTF(" %x",rxframe.data[len]);PRINTF("\n");
#endif
  if (rxframe.length==0) {
    return 0;
  }

#if RF230_CONF_TIMESTAMPS
bomb
  if(interrupt_time_set) {
    rf230_time_of_arrival = interrupt_time;
    interrupt_time_set = 0;
  } else {
    rf230_time_of_arrival = 0;
  }
  rf230_time_of_departure = 0;
#endif /* RF230_CONF_TIMESTAMPS */
  GET_LOCK();
//  if(rxframe.length > RF230_MAX_PACKET_LEN) {
//    // Oops, we must be out of sync.
//  flushrx();
//    RIMESTATS_ADD(badsynch);
//    RELEASE_LOCK();
//    return 0;
//  }

//hal returns two extra bytes containing the checksum
//below works because auxlen is 2
  len = rxframe.length;
  if(len <= AUX_LEN) {
 // flushrx();
    RIMESTATS_ADD(tooshort);
    RELEASE_LOCK();
    return 0;
  }
  
  if(len - AUX_LEN > bufsize) {
//  flushrx();
    RIMESTATS_ADD(toolong);
    RELEASE_LOCK();
    return 0;
  }
  /* Transfer the frame, stripping the checksum */
  framep=&(rxframe.data[0]);
  memcpy(buf,framep,len-2);
  /* Clear the length field to allow buffering of the next packet */
  rxframe.length=0;
 // framep+=len-AUX_LEN+2;

#if RADIOSTATS
  RF230_receivepackets++;
#endif

#if RF230_CONF_CHECKSUM
bomb
  memcpy(&checksum,framep,CHECKSUM_LEN);
  framep+=CHECKSUM_LEN;
#endif /* RF230_CONF_CHECKSUM */
#if RF230_CONF_TIMESTAMPS
bomb
  memcpy(&t,framep,TIMESTAMP_LEN);
  framep+=TIMESTAMP_LEN;
#endif /* RF230_CONF_TIMESTAMPS */
//  memcpy(&footer,framep,FOOTER_LEN);
 
#if RF230_CONF_CHECKSUM
bomb
  if(checksum != crc16_data(buf, len - AUX_LEN, 0)) {
    PRINTF("rf230: checksum failed 0x%04x != 0x%04x\n",
	   checksum, crc16_data(buf, len - AUX_LEN, 0));
  }
  
  if(footer[1] & FOOTER1_CRC_OK &&
     checksum == crc16_data(buf, len - AUX_LEN, 0)) {
#else
  if (rxframe.crc) {
#endif /* RF230_CONF_CHECKSUM */

 #if RADIOSTATS
    RF230_rsigsi=hal_subregister_read( SR_RSSI );
#endif      
    //nick packetbuf_set_attr(PACKETBUF_ATTR_RSSI, hal_subregister_read( SR_RSSI ));
    //nick packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, rxframe.lqi);
    
    RIMESTATS_ADD(llrx);
    
#if RF230_CONF_TIMESTAMPS
bomb
    rf230_time_of_departure =
      t.time +
      setup_time_for_transmission +
      (total_time_for_transmission * (len - 2)) / total_transmission_len;
  
    rf230_authority_level_of_sender = t.authority_level;

    packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, t.time);
#endif /* RF230_CONF_TIMESTAMPS */
  
  } else {
    PRINTF("rf230: Bad CRC\n");

#if RADIOSTATS
    RF230_receivefail++;
#endif

    RIMESTATS_ADD(badcrc);
    len = AUX_LEN;
  }
// if (?)
     /* Another packet has been received and needs attention. */
//    process_poll(&nrf24l01_process);
//  }
  
  RELEASE_LOCK();
  
  if(len < AUX_LEN) {
    return 0;
  }

  return len - AUX_LEN;
  }

/*---------------------------------------------------------------------------*/
void
nrf24l01_init(uint8_t mode)
{
  rf_mode = mode;

  /* Initialize Hardware Abstraction Layer. */
  //hal_init();
  
  //init the spi functions
  spi_init();

  SPI_CHIP_ENABLE();
  
  if(RF_TX_MODE == mode)  //tx mode
        {              
            SPI_WRITE_REG(WRITE_REG, 0x0C); //RX_DR, TX_DS, MAX_RT interrupts enabled, CRC enabled, CRC encoding with 2bytes and as PTX
	    //SPI_WRITE_REG(WRITE_REG+EN_AA, 0x3F); //Enable auto-acknowledge for all data pipe
	    //SPI_WRITE_REG(WRITE_REG+EN_RXADDR, 0x01); //Enable RX address data pipe 0, reset value is 0x03 (data pipe 0 and 1)
	    //SPI_WRITE_REG(WRITE_REG+SETUP_AW, 0x03); //Setup of address width, reset value is 0x33--5 bytes
	    SPI_WRITE_REG(WRITE_REG+SETUP_RETR, 0xFF); //Set auto-retransmision, ARD(auto retransmit delay): 1111, ARC(auto retransmit count): 1111
	    //SPI_WRITE_REG(WRITE_REG+RF_CH, 0x02); //RF Channel 2 (default, not really needed)
	    //SPI_WRITE_REG(WRITE_REG+RF_SETUP, 0x03); //Air data rate 1Mbit, -12dBm, Setup LNA

	    //SPI_WRITE_BUF(WRITE_REG+RX_ADDR_P0, (uint8_t*)&TX_ADDRESS, ADDR_WIDTH); //Set receive address to receive aut-ACK, it is equal to TX_ADDR if enbel enhanced shock burst
	    //SPI_WRITE_BUF(WRITE_REG+TX_ADDR, (uint8_t*)&TX_ADDRESS, ADDR_WIDTH); //Set transmit address: 0xE7E7E7E7E7
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P0, 0x04); // 4 byte receive payload
	
	    //the next 2 commands are relative with dynamic payload lenght, you need disable them if use static payload length
	    //enable dynamic payload length, enable dynamic ACK in specific package(then you can 
	    //use command W_TX_PAYLOAD_NOACK to set a specfic package that needn't wait for ACK)
	    SPI_WRITE_REG(WRITE_REG+DYNPD, 0x01);  //as PTX, at least enable pipe 0	
	    SPI_WRITE_REG(WRITE_REG+FEATURE, 0x05);  			
	    //SPI_WRITE_REG(WRITE_REG, 0x0E); //power upr	            
        }
	else   //rx mode
	{	    
            SPI_WRITE_REG(WRITE_REG, 0x0D); //RX_DR, TX_DS, MAX_RT interrupts enabled, CRC enabled, CRC encoding with 2bytes and as PRX
	    //SPI_WRITE_REG(WRITE_REG+EN_AA, 0x3F); //Enable auto-acknowledge for all data pipes(0-5)
	    SPI_WRITE_REG(WRITE_REG+EN_RXADDR, 0x3F); //Enable RX address for all data pipes(0-5)     
	    //SPI_WRITE_REG(WRITE_REG+SETUP_AW, 0x03); //Setup of address width, reset value is 0x33--5 bytes
	    SPI_WRITE_REG(WRITE_REG+SETUP_RETR, 0xFF); //Set auto-retransmision, ARD(auto retransmit delay): 1111, ARC(auto retransmit count): 1111
	    //SPI_WRITE_REG(WRITE_REG+RF_CH, 0x02); //RF Channel 2 (default, not really needed)
	    //SPI_WRITE_REG(WRITE_REG+RF_SETUP, 0x03); //Air data rate 1Mbit, -12dBm, Setup LNA

	    //SPI_WRITE_BUF(WRITE_REG+RX_ADDR_P0, (uint8_t*)&TX_ADDRESS, ADDR_WIDTH); //Set receive address for pipe0
	    //SPI_WRITE_BUF(WRITE_REG+RX_ADDR_P1, (uint8_t*)&RX_ADDRESS, ADDR_WIDTH); //Set receive address for pipe1
	    //SPI_WRITE_REG(WRITE_REG+RX_ADDR_P2, 0XC3); //Set receive address for pipe2
	    //SPI_WRITE_REG(WRITE_REG+RX_ADDR_P3, 0XC4); //Set receive address for pipe3
	    //SPI_WRITE_REG(WRITE_REG+RX_ADDR_P4, 0XC5); //Set receive address for pipe4
	    //SPI_WRITE_REG(WRITE_REG+RX_ADDR_P5, 0XC6); //Set receive address for pipe5

	    SPI_WRITE_REG(WRITE_REG+RX_PW_P0, 0x04); // 4 byte receive payload for pipe 0
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P1, 0x04); // 4 byte receive payload
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P2, 0x04); // 4 byte receive payload
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P3, 0x04); // 4 byte receive payload
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P4, 0x04); // 4 byte receive payload
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P5, 0x04); // 4 byte receive payload for pipe 5	
	
	    //don't use static payload length
	    /*SPI_WRITE_REG(WRITE_REG+RX_PW_P0, 0xFF);  //data pipe 0, number of bytes: 32
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P1, 0xFF);  //data pipe 1, number of bytes: 32
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P2, 0xFF);  //data pipe 2, number of bytes: 32
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P3, 0xFF);  //data pipe 3, number of bytes: 32
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P4, 0xFF);  //data pipe 4, number of bytes: 32
	    SPI_WRITE_REG(WRITE_REG+RX_PW_P5, 0xFF);  //data pipe 5, number of bytes: 32
	    */
	    SPI_WRITE_REG(WRITE_REG+DYNPD, 0x3F);  //as PRX, enable all pipes
	    SPI_WRITE_REG(WRITE_REG+FEATURE, 0x05);  //enable dynamic payload length			

	    //SPI_WRITE_REG(WRITE_REG, 0x0F); //power upr
	}	
	SPI_CHIP_DISABLE();
	
  /* Start the packet receive process */
  process_start(&nrf24l01_process, NULL);
}