Exemple #1
0
/*---------------------------------------------------------------------------*/
int
anti_replay_was_replayed(struct anti_replay_info *info)
{
  uint32_t received_counter;
  
  received_counter = anti_replay_get_counter();
  
  if(packetbuf_holds_broadcast()) {
    /* broadcast */
    if(received_counter <= info->last_broadcast_counter) {
      return 1;
    } else {
      info->last_broadcast_counter = received_counter;
      return 0;
    }
  } else {
    /* unicast */
    if(received_counter <= info->last_unicast_counter) {
      return 1;
    } else {
      info->last_unicast_counter = received_counter;
      return 0;
    }
  }
}
Exemple #2
0
/*---------------------------------------------------------------------------*/
void
anti_replay_restore_counter(struct anti_replay_info *info)
{
  uint8_t seqno;
  frame802154_frame_counter_t copied_counter;
  
  seqno = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO);
  copied_counter.u32 = packetbuf_holds_broadcast()
      ? info->his_broadcast_counter.u32
      : info->his_unicast_counter.u32;
  
  if(seqno < copied_counter.u8[0]) {
    copied_counter.u8[1]++;
    if(!copied_counter.u8[1]) {
      copied_counter.u8[2]++;
      if(!copied_counter.u8[2]) {
        copied_counter.u8[3]++;
      }
    }
  }
  copied_counter.u8[0] = seqno;
  
  packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, copied_counter.u16[0]);
  packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, copied_counter.u16[1]);
}
Exemple #3
0
/*---------------------------------------------------------------------------*/
int
anti_replay_was_replayed(struct anti_replay_info *info)
{
  uint32_t received_counter;
  
  received_counter = anti_replay_get_counter();
  
  if(packetbuf_holds_broadcast()) {
#if DEBUG
    if(received_counter < info->his_broadcast_counter.u32) {
      PRINTF("anti-replay: Broadcast out of order\n");
    }
#endif /* DEBUG */
    if(received_counter <= info->his_broadcast_counter.u32) {
      return 1;
    } else {
      info->his_broadcast_counter.u32 = received_counter;
      return 0;
    }
  } else {
#if DEBUG
    if(received_counter < info->his_unicast_counter.u32) {
      PRINTF("anti-replay: Unicast out of order\n");
    }
#endif /* DEBUG */
    if(received_counter <= info->his_unicast_counter.u32) {
      return 1;
    } else {
      info->his_unicast_counter.u32 = received_counter;
      return 0;
    }
  }
}
Exemple #4
0
/*---------------------------------------------------------------------------*/
static void packet_input(void)
{
  if(packetbuf_datalen() == ACK_LEN){
    /* Ignore ack packets */
    PRINTF("nullrdc: ignored ack\n"); 
  }else if(NETSTACK_FRAMER.parse() < 0){
    PRINTF("nullrdc: failed to parse %u\n", packetbuf_datalen());
#if NULLRDC_ADDRESS_FILTER
  }else if(!linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                          &linkaddr_node_addr) &&
           !packetbuf_holds_broadcast()){
    PRINTF("nullrdc: not for us\n");
#endif /* NULLRDC_ADDRESS_FILTER */
  }else{
    int duplicate = 0;

    /* Check for duplicate packet. */
    duplicate = mac_sequence_is_duplicate();
    if(duplicate){
      /* Drop the packet. */
      PRINTF("nullrdc: drop duplicate link layer packet %u\n",
             packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO));
    }else{
      mac_sequence_register_seqno();
    }

    if(!duplicate) {
      NETSTACK_MAC.input();
    }
  }
}
Exemple #5
0
/*---------------------------------------------------------------------------*/
uint8_t
adaptivesec_get_sec_lvl(void)
{
  switch(packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE)) {
  case FRAME802154_CMDFRAME:
    switch(adaptivesec_get_cmd_id()) {
    case AKES_HELLO_IDENTIFIER:
      return ADAPTIVESEC_BROADCAST_SEC_LVL & 3;
    case AKES_HELLOACK_IDENTIFIER:
    case AKES_HELLOACK_P_IDENTIFIER:
    case AKES_ACK_IDENTIFIER:
      return AKES_ACKS_SEC_LVL;
    case AKES_UPDATE_IDENTIFIER:
    case AKES_UPDATEACK_IDENTIFIER:
      return AKES_UPDATES_SEC_LVL;
    }
    break;
  case FRAME802154_DATAFRAME:
    return packetbuf_holds_broadcast()
        ? ADAPTIVESEC_BROADCAST_SEC_LVL
        : ADAPTIVESEC_UNICAST_SEC_LVL;
    break;
  }
  return 0;
}
Exemple #6
0
/*---------------------------------------------------------------------------*/
static int
on_frame_created(void)
{
  uint8_t sec_lvl;
  enum akes_nbr_status status;
  struct akes_nbr_entry *entry;
  uint8_t *dataptr;
  uint8_t datalen;

  sec_lvl = adaptivesec_get_sec_lvl();
  if(sec_lvl && !packetbuf_holds_broadcast()) {
    status = akes_get_receiver_status();
    entry = akes_nbr_get_receiver_entry();

    if(!entry || !entry->refs[status]) {
      return 0;
    }

    dataptr = packetbuf_dataptr();
    datalen = packetbuf_datalen();

    adaptivesec_aead(entry->refs[status]->pairwise_key,
        sec_lvl & (1 << 2),
        dataptr + datalen,
        1);
    packetbuf_set_datalen(datalen + ADAPTIVESEC_UNICAST_MIC_LEN);
  }
  return 1;
}
Exemple #7
0
/*---------------------------------------------------------------------------*/
static enum adaptivesec_verify
verify(struct akes_nbr *sender)
{
  if(packetbuf_holds_broadcast()) {
    if(verify_broadcast(sender)) {
      PRINTF("coresec-strategy: Inauthentic broadcast\n");
      return 0;
    }
  } else {
#if ANTI_REPLAY_WITH_SUPPRESSION
    packetbuf_set_attr(PACKETBUF_ATTR_NEIGHBOR_INDEX, sender->foreign_index);
#endif /* ANTI_REPLAY_WITH_SUPPRESSION */
    if(adaptivesec_verify(sender->pairwise_key)) {
      PRINTF("coresec-strategy: Inauthentic unicast\n");
      return ADAPTIVESEC_VERIFY_INAUTHENTIC;
    }
  }

#if !POTR_ENABLED
  if(anti_replay_was_replayed(&sender->anti_replay_info)) {
    PRINTF("coresec-strategy: Replayed\n");
    return ADAPTIVESEC_VERIFY_REPLAYED;
  }
#endif /* !POTR_ENABLED */

  return ADAPTIVESEC_VERIFY_SUCCESS;
}
Exemple #8
0
/*---------------------------------------------------------------------------*/
static void
send(mac_callback_t sent, void *ptr)
{
  struct akes_nbr_entry *entry;

  packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME);
  if(packetbuf_holds_broadcast()) {
    if(!akes_nbr_count(AKES_NBR_PERMANENT)) {
      mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 0);
      return;
    }
    adaptivesec_add_security_header(NULL);
  } else {
    entry = akes_nbr_get_receiver_entry();
    if(!entry || !entry->permanent) {
      mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 0);
      return;
    }
    adaptivesec_add_security_header(&entry->permanent->anti_replay_info);
#if ANTI_REPLAY_WITH_SUPPRESSION
    packetbuf_set_attr(PACKETBUF_ATTR_NEIGHBOR_INDEX, entry->local_index);
#endif /* ANTI_REPLAY_WITH_SUPPRESSION */
  }
#if !ANTI_REPLAY_WITH_SUPPRESSION && !POTR_ENABLED
  framer_802154_set_seqno();
#endif /* ANTI_REPLAY_WITH_SUPPRESSION && !POTR_ENABLED */
  ADAPTIVESEC_STRATEGY.send(sent, ptr);
}
Exemple #9
0
/*---------------------------------------------------------------------------*/
static int
decrypt_verify(struct neighbor *sender)
{
    if(packetbuf_holds_broadcast()) {
        if(!decrypt_verify_broadcast(sender)) {
            PRINTF("coresec-strategy: Unauthentic broadcast\n");
            return 0;
        }
    } else {
#if ANTI_REPLAY_WITH_SUPPRESSION
        packetbuf_set_attr(PACKETBUF_ATTR_NEIGHBOR_INDEX, sender->foreign_index);
#endif /* ANTI_REPLAY_WITH_SUPPRESSION */
        if(!adaptivesec_decrypt_verify(sender->pairwise_key)) {
            PRINTF("coresec-strategy: Unauthentic unicast\n");
            return 0;
        }
    }

    if(anti_replay_was_replayed(&sender->anti_replay_info)) {
        PRINTF("coresec-strategy: Replayed\n");
        return 0;
    }

    return 1;
}
Exemple #10
0
/*---------------------------------------------------------------------------*/
static void
send(mac_callback_t sent, void *ptr)
{
  if(packetbuf_holds_broadcast()) {
    send_broadcast(sent, ptr);
  } else {
    NETSTACK_MAC.send(sent, ptr);
  }
}
Exemple #11
0
/*---------------------------------------------------------------------------*/
int
anti_replay_set_counter(struct anti_replay_info *receiver_info)
{
#if ANTI_REPLAY_WITH_SUPPRESSION
  if(packetbuf_holds_broadcast()) {
    order_and_set_counter(++anti_replay_my_broadcast_counter);
  } else {
    if(++my_unicast_counter == 0xFFFFFFFF) {
      return 0;
    }
    order_and_set_counter(++receiver_info->my_unicast_counter.u32);
  }
#else /* ANTI_REPLAY_WITH_SUPPRESSION */
  order_and_set_counter(++my_counter);
#endif /* ANTI_REPLAY_WITH_SUPPRESSION */
  return (anti_replay_get_counter() != 0xFFFFFFFF);
}
Exemple #12
0
static uint8_t send_packet(struct net_buf *buf,
			   mac_callback_t sent_callback, void *ptr)
{
	bool is_broadcast, ack_required;
	uint8_t attempts;
	uint8_t retries;
	int ret;

#ifdef SIMPLERDC_802154_ACK_REQ
	packetbuf_set_attr(buf, PACKETBUF_ATTR_MAC_ACK, 1);
#endif

	retries = prepare_packet(buf);
	if (!retries) {
		return MAC_TX_ERR_FATAL;
	}

	ack_required = prepare_for_ack(buf);
	is_broadcast = !!packetbuf_holds_broadcast(buf);
	attempts = 0;

	while (retries) {
		attempts++;
		retries--;

		ret = NETSTACK_RADIO.transmit(buf, packetbuf_totlen(buf));
		if (ret == RADIO_TX_COLLISION) {
			continue;
		}

		ret = wait_for_ack(is_broadcast, ack_required);
		if (ret == MAC_TX_OK) {
			break;
		}
	}

	mac_call_sent_callback(buf, sent_callback, ptr, ret, attempts);

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

	return 0;
}
Exemple #13
0
/**
 * \brief Take a packet received over the 802.15.4 link, and send it
 * out over ethernet, performing any translations needed.
 */
void mac_LowpanToEthernet(void)
{
/*   parsed_frame = sicslowmac_get_frame(); */

  //Setup generic ethernet stuff
  ETHBUF(uip_buf)->type = htons(UIP_ETHTYPE_IPV6);

  //Check for broadcast message
  if(packetbuf_holds_broadcast()) {
/*   if(  ( parsed_frame->fcf->destAddrMode == SHORTADDRMODE) && */
/*        ( parsed_frame->dest_addr->addr16 == 0xffff) ) { */
    ETHBUF(uip_buf)->dest.addr[0] = 0x33;
    ETHBUF(uip_buf)->dest.addr[1] = 0x33;
    ETHBUF(uip_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12];
    ETHBUF(uip_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13];
    ETHBUF(uip_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14];
    ETHBUF(uip_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15];
  } else {
	//Otherwise we have a real address
	mac_createEthernetAddr((uint8_t *) &(ETHBUF(uip_buf)->dest.addr[0]),
                        (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
  }


  mac_createEthernetAddr((uint8_t *) &(ETHBUF(uip_buf)->src.addr[0]),
                         (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));

  //We only do address translation in network mode!
  if (usbstick_mode.translate) {
    //Some IP packets have link layer in them, need to change them around!
    mac_translateIPLinkLayer(ll_8023_type);
  }

  PRINTF("Low2Eth: Sending packet to ethernet\n");

  uip_len += UIP_LLH_LEN;

/*   rndis_send(uip_buf, uip_len, 1); */
/*   rndis_stat.rxok++; */
/*   uip_len = 0; */
}
Exemple #14
0
/*---------------------------------------------------------------------------*/
static void
input(void)
{
  struct akes_nbr_entry *entry;

#if LLSEC802154_USES_AUX_HEADER && POTR_ENABLED
  packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, adaptivesec_get_sec_lvl());
#endif /* LLSEC802154_USES_AUX_HEADER && POTR_ENABLED */
  switch(packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE)) {
  case FRAME802154_CMDFRAME:
    cmd_broker_publish();
    break;
  case FRAME802154_DATAFRAME:
    entry = akes_nbr_get_sender_entry();
    if(!entry || !entry->permanent) {
      PRINTF("adaptivesec: Ignored incoming frame\n");
      return;
    }

#if SECRDC_WITH_SECURE_PHASE_LOCK
    if(packetbuf_holds_broadcast()
        && ADAPTIVESEC_STRATEGY.verify(entry->permanent)) {
      return;
    }
#else /* SECRDC_WITH_SECURE_PHASE_LOCK */
#if ANTI_REPLAY_WITH_SUPPRESSION && !POTR_ENABLED
    anti_replay_restore_counter(&entry->permanent->anti_replay_info);
#endif /* ANTI_REPLAY_WITH_SUPPRESSION && !POTR_ENABLED */

    if(ADAPTIVESEC_STRATEGY.verify(entry->permanent) != ADAPTIVESEC_VERIFY_SUCCESS) {
      return;
    }
#endif /* SECRDC_WITH_SECURE_PHASE_LOCK */

    akes_nbr_prolong(entry->permanent);

    NETSTACK_NETWORK.input();
    break;
  }
}
Exemple #15
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 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;
  
  /* 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(packetbuf_holds_broadcast()) {
    is_broadcast = 1;
    PRINTDEBUG("contikimac: send broadcast\n");

    if(broadcast_rate_drop()) {
      return MAC_TX_COLLISION;
    }
  } else {
#if NETSTACK_CONF_WITH_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 /* NETSTACK_CONF_WITH_IPV6 */
    PRINTDEBUG("contikimac: send unicast to %u.%u\n",
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1]);
#endif /* NETSTACK_CONF_WITH_IPV6 */
  }
  is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE)
#if NETSTACK_CONF_WITH_RIME
          || packetbuf_attr(PACKETBUF_ATTR_ERELIABLE)
#endif /* NETSTACK_CONF_WITH_RIME */
      ;

  if(!packetbuf_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED)) {
    packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
    if(NETSTACK_FRAMER.create_and_secure() < 0) {
      PRINTF("contikimac: framer failed\n");
      return MAC_TX_ERR_FATAL;
    }
  }
  
  transmit_len = packetbuf_totlen();
  NETSTACK_RADIO.prepare(packetbuf_hdrptr(), transmit_len);
  
  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;
}
Exemple #16
0
/*---------------------------------------------------------------------------*/
static void
input_packet(void)
{
  static struct ctimer ct;
  int duplicate = 0;

#if CONTIKIMAC_SEND_SW_ACK
  int original_datalen;
  uint8_t *original_dataptr;

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

  if(!we_are_receiving_burst) {
    off();
  }

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

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

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

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

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

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

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

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

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

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

      if(!duplicate) {
        NETSTACK_MAC.input();
      }
      return;
    } else {
      PRINTDEBUG("contikimac: data not for us\n");
    }
  } else {
    PRINTF("contikimac: failed to parse (%u)\n", packetbuf_totlen());
  }
}
Exemple #17
0
/*---------------------------------------------------------------------------*/
static uint8_t
packet_input(struct net_buf *buf)
{
#if NULLRDC_SEND_802154_ACK
  int original_datalen;
  uint8_t *original_dataptr;

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

#if NULLRDC_802154_AUTOACK
  if(packetbuf_datalen(buf) == ACK_LEN) {
    /* Ignore ack packets */
    PRINTF("nullrdc: ignored ack\n");
  } else
#endif /* NULLRDC_802154_AUTOACK */
  if(NETSTACK_FRAMER.parse(buf) < 0) {
    PRINTF("nullrdc: failed to parse msg len %u\n", packetbuf_datalen(buf));
#if NULLRDC_ADDRESS_FILTER
  } else if(!linkaddr_cmp(packetbuf_addr(buf, PACKETBUF_ADDR_RECEIVER),
                                         &linkaddr_node_addr) &&
            !packetbuf_holds_broadcast(buf)) {
    PRINTF("nullrdc: not for us\n");
#endif /* NULLRDC_ADDRESS_FILTER */
  } else {
    int duplicate = 0;

#if NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW
    /* If llsec is not doing anti replay checks this needs to be done */
    if(anti_replay_is_anti_replay_checked(buf) == 0) {
      /* Check for duplicate packet. */
      duplicate = mac_sequence_is_duplicate(buf);
      if(duplicate) {
        /* Drop the packet. */
        PRINTF("nullrdc: drop duplicate link layer packet %u\n",
               packetbuf_attr(buf, PACKETBUF_ATTR_MAC_SEQNO));
      } else {
        mac_sequence_register_seqno(buf);
      }
    }
#endif /* NULLRDC_802154_AUTOACK */

/* TODO We may want to acknowledge only authentic frames */
#if NULLRDC_SEND_802154_ACK
    {
      frame802154_t info154;
      frame802154_parse(original_dataptr, original_datalen, &info154);
      if(info154.fcf.frame_type == FRAME802154_DATAFRAME &&
         info154.fcf.ack_required != 0 &&
         linkaddr_cmp((linkaddr_t *)&info154.dest_addr,
                      &linkaddr_node_addr)) {
        uint8_t ackdata[ACK_LEN] = {0, 0, 0};

        ackdata[0] = FRAME802154_ACKFRAME;
        ackdata[1] = 0;
        ackdata[2] = info154.seq;
        return NETSTACK_RADIO.send(ackdata, ACK_LEN);
      }
    }
#endif /* NULLRDC_SEND_ACK */
    if(!duplicate) {
      return NETSTACK_MAC.input(buf);
    }
  }

  return 0;
}
Exemple #18
0
/*---------------------------------------------------------------------------*/
static int
send_one_packet(struct net_buf *buf, mac_callback_t sent, void *ptr)
{
  int ret;
  int last_sent_ok = 0;
#if NULLRDC_ENABLE_RETRANSMISSIONS
  rtimer_clock_t target_time;
  uint8_t tx_attempts = 0;
  uint8_t max_tx_attempts;

  if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) > 0) {
    max_tx_attempts = packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
  } else {
    max_tx_attempts = NULLRDC_MAX_RETRANSMISSIONS + 1;
  }
#endif /* NULLRDC_ENABLE_RETRANSMISSIONS */

  packetbuf_set_addr(buf, PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
#if NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW
  packetbuf_set_attr(buf, PACKETBUF_ATTR_MAC_ACK, 1);
#endif /* NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW */

  if(NETSTACK_FRAMER.create_and_secure(buf) < 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 = packetbuf_holds_broadcast();

    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);
      }
#if NULLRDC_ENABLE_RETRANSMISSIONS
  while(1) {
    /* Transmit packet and check status */
    tx_attempts++;
#endif /* NULLRDC_ENABLE_RETRANSMISSIONS */

      switch(NETSTACK_RADIO.transmit(packetbuf_totlen(buf))) {
      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("nullrdc tx noack\n");
	  }
        }
        break;
      case RADIO_TX_COLLISION:
        ret = MAC_TX_COLLISION;
        break;
      default:
        ret = MAC_TX_ERR;
        break;
      }
#if NULLRDC_ENABLE_RETRANSMISSIONS
    if(is_broadcast) {
#if !NULLRDC_ENABLE_RETRANSMISSIONS_BCAST
      break;
#else  /* NULLRDC_ENABLE_RETRANSMISSIONS_BCAST */
      if(ret != MAC_TX_COLLISION) {
        /* Retry broadcast frame only upon collision */
        break;
      }
#endif /* NULLRDC_ENABLE_RETRANSMISSIONS_BCAST */
    } else {
      /* Frame is unicast. Do not retry unless NO_ACK or COLLISION */
      if((ret != MAC_TX_NOACK) && (ret != MAC_TX_COLLISION)) {
        break;
      }
    }
    /* Do not retry if max attempts reached. */
    if(tx_attempts >= max_tx_attempts) {
      PRINTF("nullrdc: max tx attempts reached\n");
      break;
    }
    /* Block-wait before retrying the frame. */
    target_time = RTIMER_NOW() +
      (RTIMER_SECOND * NULLRDC_TX_RETRY_DELAY_MS / 1000);
    watchdog_periodic();
    while(RTIMER_CLOCK_LT(RTIMER_NOW(), target_time)) {
      /* Wait */
    }
    /* Attempt a new frame (re)transmission */
  }
#endif /* NULLRDC_ENABLE_RETRANSMISSIONS */
    }

#else /* ! NULLRDC_802154_AUTOACK */

    switch(NETSTACK_RADIO.send(buf, packetbuf_hdrptr(buf), packetbuf_totlen(buf))) {
    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 */
  }
  if(ret == MAC_TX_OK) {
    last_sent_ok = 1;
  }
#if ! NULLRDC_ENABLE_RETRANSMISSIONS
  mac_call_sent_callback(buf, sent, ptr, ret, 1);
#else
  mac_call_sent_callback(buf, sent, ptr, ret, tx_attempts);
#endif /* !NULLRDC_ENABLE_RETRANSMISSIONS */
  return last_sent_ok;
}
Exemple #19
0
/*---------------------------------------------------------------------------*/
static uint8_t
get_overhead(void)
{
  return packetbuf_holds_broadcast() ? 0 : ADAPTIVESEC_UNICAST_MIC_LEN;
}
Exemple #20
0
/*---------------------------------------------------------------------------*/
uint8_t
adaptivesec_mic_len(void)
{
  return packetbuf_holds_broadcast() ? ADAPTIVESEC_BROADCAST_MIC_LEN : ADAPTIVESEC_UNICAST_MIC_LEN;
}
/*---------------------------------------------------------------------------*/
static int
send_packet(void)
{
  rtimer_clock_t t0;
  rtimer_clock_t t;
  rtimer_clock_t encounter_time = 0;
  int strobes;
  struct cxmac_hdr *hdr;
  int got_strobe_ack = 0;
  uint8_t strobe[MAX_STROBE_SIZE];
  int strobe_len, len;
  int is_broadcast = 0;
  int is_dispatch, is_strobe_ack;
  /*int is_reliable;*/
  struct encounter *e;
  struct queuebuf *packet;
  int is_already_streaming = 0;
  uint8_t collisions;


  /* Create the X-MAC header for the data packet. */
#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(packetbuf_holds_broadcast()) {
    is_broadcast = 1;
    PRINTDEBUG("cxmac: send broadcast\n");
  } else {
#if NETSTACK_CONF_WITH_IPV6
    PRINTDEBUG("cxmac: send unicast to %02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[2],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[3],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[4],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[5],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[6],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[7]);
#else
    PRINTDEBUG("cxmac: send unicast to %u.%u\n",
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1]);
#endif /* NETSTACK_CONF_WITH_IPV6 */
  }
/* is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
    packetbuf_attr(PACKETBUF_ATTR_ERELIABLE);*/
  len = NETSTACK_FRAMER.create();
  strobe_len = len + sizeof(struct cxmac_hdr);
  if(len < 0 || strobe_len > (int)sizeof(strobe)) {
    /* Failed to send */
   PRINTF("cxmac: send failed, too large header\n");
    return MAC_TX_ERR_FATAL;
  }
  memcpy(strobe, packetbuf_hdrptr(), len);
  strobe[len] = DISPATCH; /* dispatch */
  strobe[len + 1] = TYPE_STROBE; /* type */

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

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

  off();

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

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

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

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

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

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

  LEDS_ON(LEDS_BLUE);

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

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

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

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

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

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

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

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

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

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

#if CXMAC_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 /* CXMAC_CONF_COMPOWER */

  we_are_sending = 0;

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

}
Exemple #22
0
/*---------------------------------------------------------------------------*/
static uint8_t
send_packet(struct net_buf *buf, mac_callback_t sent, void *ptr)
{
  frame802154_t params;
  uint8_t len;
  uint8_t ret = 0;

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

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

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

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

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

  if(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));
    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.
   */
#if NETSTACK_CONF_BRIDGE_MODE
  linkaddr_copy((linkaddr_t *)&params.src_addr,packetbuf_addr(PACKETBUF_ADDR_SENDER));
#else
  linkaddr_copy((linkaddr_t *)&params.src_addr, &linkaddr_node_addr);
#endif

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

    PRINTF("6MAC-UT: type %X dest ", params.fcf.frame_type);
    PRINTLLADDR((uip_lladdr_t *)params.dest_addr);
    PRINTF(" len %u datalen %u (totlen %u)\n", len, packetbuf_datalen(buf),
	   packetbuf_totlen(buf));

    ret = NETSTACK_RADIO.send(buf, packetbuf_hdrptr(buf), packetbuf_totlen(buf));
    if(sent) {
      switch(ret) {
      case RADIO_TX_OK:
        sent(buf, ptr, MAC_TX_OK, 1);
        break;
      case RADIO_TX_ERR:
        sent(buf, ptr, MAC_TX_ERR, 1);
        break;
      case RADIO_TX_COLLISION:
        sent(buf, ptr, MAC_TX_COLLISION, 1);
        break;
      }
    }
  } else {
    PRINTF("6MAC-UT: too large header: %u\n", len);
  }

  return ret;
}
/*---------------------------------------------------------------------------*/
int
sicslowmac_dataRequest(void)
{

  _delay_ms(SICSLOW_CORRECTION_DELAY);

   /* create structure to store result. */
  frame_create_params_t params;
  frame_result_t result;

  /* Save the msduHandle in a global variable. */
  msduHandle = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);

  /* Build the FCF. */
  params.fcf.frameType = DATAFRAME;
  params.fcf.securityEnabled = false;
  params.fcf.framePending = false;
  params.fcf.ackRequired = packetbuf_attr(PACKETBUF_ATTR_RELIABLE);
  params.fcf.panIdCompression = false;

  /* Insert IEEE 802.15.4 (2003) version bit. */
  params.fcf.frameVersion = IEEE802154_2003;

  /* Increment and set the data sequence number. */
  params.seq = macDSN++;

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

  if(packetbuf_holds_broadcast()) {
    /* Broadcast requires short address mode. */
    params.fcf.destAddrMode = SHORTADDRMODE;
    params.dest_pid = BROADCASTPANDID;
    params.dest_addr.addr16 = BROADCASTADDR;

  } else {

    /* Phase 1.5 - end nodes send to anyone? */
    memcpy(&params.dest_addr, (uint8_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER), LONG_ADDR_LEN);
	
    /* Change from sicslowpan byte arrangement to sicslowmac */
    byte_reverse((uint8_t*)&params.dest_addr.addr64, LONG_ADDR_LEN);

    /* Phase 1 - end nodes only sends to pan coordinator node. */
    /* params.dest_addr.addr64 = ieee15_4ManagerAddress.get_coord_long_addr(); */
    params.fcf.destAddrMode = LONGADDRMODE;
  }

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

  /*
   * Set up the source address using only the long address mode for
   * phase 1.
   */
  params.src_addr.addr64 = ieee15_4ManagerAddress.get_long_addr();

  /* Copy the payload data. */
  params.payload_len = packetbuf_datalen();
  params.payload =  packetbuf_dataptr();

  /* Create transmission frame. */
  frame_tx_create(&params, &result);
  
  /* Log if needed */
  LOG_FRAME(&params, &result);

  /* Retry up to this many times to send the packet if radio is busy */
  uint8_t retry_count = 3;

  while(retry_count) {

	  PRINTF("sicslowmac: sending packet of length %d to radio, result:", result.length);
	  
	    

	  /* Send data to radio. */
	  radio_status_t rv = radio_send_data(result.length, result.frame);

	  if (rv == RADIO_SUCCESS) {
	      PRINTF(" Success\n");

		  return 1; /* True says that the packet could be sent */
      }


	  if (rv != RADIO_WRONG_STATE) {
	      PRINTF(" Failed\n");
	  	  return 0;
      }

	  PRINTF(" Radio busy, retrying\n");

      /** \todo: Fix delay in sicslowmac so they do not block receiving */

       //We have blocking delay here, it is safest this way. BUT doesn't solve the
	   //problem of TX when you are RXing.. as the RX code can't execute!
	  if (retry_count == 3) {
	 	  _delay_ms(10);
	  } else if (retry_count == 2) {
	      _delay_ms(50);
	  } else if (retry_count == 1) {
	      _delay_ms(200);
	  }

	  retry_count--;
  }

  PRINTF("sicslowmac: Unable to send packet, dropped\n");
  return 0;

}
Exemple #24
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);
  packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);

  if(NETSTACK_FRAMER.create_and_secure() < 0){
    /* Failed to allocate space for headers */
    PRINTF("nullrdc: send failed, too large header\n");
    ret = MAC_TX_ERR_FATAL;
  }else{
    int is_broadcast;
    uint8_t dsn;
    dsn = ((uint8_t *)packetbuf_hdrptr())[2] & 0xff;

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

    is_broadcast = packetbuf_holds_broadcast();

    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));

          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(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("nullrdc tx noack\n");
          }
        }
        break;
      case RADIO_TX_COLLISION:
        ret = MAC_TX_COLLISION;
        break;
      default:
        ret = MAC_TX_ERR;
        break;
      }
    }
  }
  if(ret == MAC_TX_OK) {
    last_sent_ok = 1;
  }
  mac_call_sent_callback(sent, ptr, ret, 1);
  return last_sent_ok;
}
Exemple #25
0
/*---------------------------------------------------------------------------*/
static void
input_packet(void)
{
  static struct ctimer ct;
  if(!we_are_receiving_burst) {
    off();
  }

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

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

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

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

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

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

      PRINTDEBUG("contikimac: data (%u)\n", packetbuf_datalen());
      NETSTACK_MAC.input();
      return;
    } else {
      PRINTDEBUG("contikimac: data not for us\n");
    }
  } else {
    PRINTF("contikimac: failed to parse (%u)\n", packetbuf_totlen());
  }
}
Exemple #26
0
/*---------------------------------------------------------------------------*/
static int
create_frame(int type, int do_create)
{
  frame802154_t params;
  int hdr_len;

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

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

  /* Build the FCF. */
  params.fcf.frame_type = packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE);
  params.fcf.frame_pending = packetbuf_attr(PACKETBUF_ATTR_PENDING);
  if(packetbuf_holds_broadcast()) {
    params.fcf.ack_required = 0;
  } else {
    params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_MAC_ACK);
  }
  params.fcf.panid_compression = 0;

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

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

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

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

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

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

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

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

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

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

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

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

    return hdr_len;
  } else {
    PRINTF("15.4-OUT: too large header: %u\n", hdr_len);
    return FRAMER_FAILED;
  }
}
Exemple #27
0
/*---------------------------------------------------------------------------*/
static void
packet_input(void)
{
  radio_value_t channel;
#if NULLRDC_SEND_802154_ACK
  int original_datalen;
  uint8_t *original_dataptr;

  original_datalen = packetbuf_datalen();
  original_dataptr = packetbuf_dataptr();
#endif
  NETSTACK_RADIO.get_value(RADIO_PARAM_CHANNEL, &channel);
  packetbuf_set_attr(PACKETBUF_ATTR_CHANNEL, channel);

#if NULLRDC_802154_AUTOACK
  if(packetbuf_datalen() == ACK_LEN) {
    /* Ignore ack packets */
    PRINTF("nullrdc: ignored ack\n"); 
  } else
#endif /* NULLRDC_802154_AUTOACK */
  if(NETSTACK_FRAMER.parse() < 0) {
    PRINTF("nullrdc: failed to parse %u\n", packetbuf_datalen());
#if NULLRDC_ADDRESS_FILTER
  } else if(!linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                                         &linkaddr_node_addr) &&
            !packetbuf_holds_broadcast()) {
    PRINTF("nullrdc: not for us\n");
#endif /* NULLRDC_ADDRESS_FILTER */
  } else {
    int duplicate = 0;

#if NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW
#if RDC_WITH_DUPLICATE_DETECTION
    /* Check for duplicate packet. */
    duplicate = mac_sequence_is_duplicate();
    if(duplicate) {
      /* Drop the packet. */
      PRINTF("nullrdc: drop duplicate link layer packet %u\n",
             packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO));
    } else {
      mac_sequence_register_seqno();
    }
#endif /* RDC_WITH_DUPLICATE_DETECTION */
#endif /* NULLRDC_802154_AUTOACK */

/* TODO We may want to acknowledge only authentic frames */ 
#if NULLRDC_SEND_802154_ACK
    {
      frame802154_t info154;
      frame802154_parse(original_dataptr, original_datalen, &info154);
      if(info154.fcf.frame_type == FRAME802154_DATAFRAME &&
         info154.fcf.ack_required != 0 &&
         linkaddr_cmp((linkaddr_t *)&info154.dest_addr,
                      &linkaddr_node_addr)) {
        uint8_t ackdata[ACK_LEN] = {0, 0, 0};

        ackdata[0] = FRAME802154_ACKFRAME;
        ackdata[1] = 0;
        ackdata[2] = info154.seq;
        NETSTACK_RADIO.send(ackdata, ACK_LEN);
      }
    }
#endif /* NULLRDC_SEND_ACK */
    if(!duplicate) {
      NETSTACK_MAC.input();
    }
  }
}