Exemple #1
0
/* Check if a packet is for us */
static int
is_packet_for_us(uint8_t *buf, int len, int do_send_ack)
{
  frame802154_t frame;
  int result;
  uint8_t parsed = frame802154_parse(buf, len, &frame);
  if(parsed) {
    if(frame.fcf.dest_addr_mode) {
      int has_dest_panid;
      frame802154_has_panid(&frame.fcf, NULL, &has_dest_panid);
      if(has_dest_panid
         && frame802154_get_pan_id() != FRAME802154_BROADCASTPANDID
         && frame.dest_pid != frame802154_get_pan_id()
         && frame.dest_pid != FRAME802154_BROADCASTPANDID) {
        /* Packet to another PAN */
        return 0;
      }
      if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) {
        result = linkaddr_cmp((linkaddr_t *)frame.dest_addr, &linkaddr_node_addr);
        if(autoack_enabled && result && do_send_ack) {
          /* this is a unicast frame and sending ACKs is enabled */
          send_ack(&frame);
        }
        return result;
      }
    }
    return 1;
  } else {
    return 0;
  }
}
Exemple #2
0
/*---------------------------------------------------------------------------*/
static int
parse(void)
{
  frame802154_t frame;
  int hdr_len;

  hdr_len = frame802154_parse(packetbuf_dataptr(), packetbuf_datalen(), &frame);

  if(hdr_len && packetbuf_hdrreduce(hdr_len)) {
    packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, frame.fcf.frame_type);

    if(frame.fcf.dest_addr_mode) {
      if(frame.dest_pid != frame802154_get_pan_id() &&
         frame.dest_pid != FRAME802154_BROADCASTPANDID) {
        /* Packet to another PAN */
        PRINTF("15.4: for another pan %u\n", frame.dest_pid);
        return FRAMER_FAILED;
      }
      if(!frame802154_is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) {
        packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (linkaddr_t *)&frame.dest_addr);
      }
    }
    packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr);
    packetbuf_set_attr(PACKETBUF_ATTR_PENDING, frame.fcf.frame_pending);
    if(frame.fcf.sequence_number_suppression == 0) {
      packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, frame.seq);
    } else {
      packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, 0xffff);
    }
#if NETSTACK_CONF_WITH_RIME
    packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, frame.seq);
#endif

#if LLSEC802154_USES_AUX_HEADER
    if(frame.fcf.security_enabled) {
      packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, frame.aux_hdr.security_control.security_level);
#if LLSEC802154_USES_FRAME_COUNTER
      packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, frame.aux_hdr.frame_counter.u16[0]);
      packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, frame.aux_hdr.frame_counter.u16[1]);
#endif /* LLSEC802154_USES_FRAME_COUNTER */
#if LLSEC802154_USES_EXPLICIT_KEYS
      packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, frame.aux_hdr.security_control.key_id_mode);
      packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX, frame.aux_hdr.key_index);
      packetbuf_set_attr(PACKETBUF_ATTR_KEY_SOURCE_BYTES_0_1, frame.aux_hdr.key_source.u16[0]);
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
    }
#endif /* LLSEC802154_USES_AUX_HEADER */

    PRINTF("15.4-IN: %2X", frame.fcf.frame_type);
    PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
    PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
    PRINTF("%d %u (%u)\n", hdr_len, packetbuf_datalen(), packetbuf_totlen());

    return hdr_len;
  }
  return FRAMER_FAILED;
}
Exemple #3
0
/* Setup TSCH as a coordinator */
static void
tsch_start_coordinator(void)
{
  frame802154_set_pan_id(IEEE802154_PANID);
  /* Initialize hopping sequence as default */
  memcpy(tsch_hopping_sequence, TSCH_DEFAULT_HOPPING_SEQUENCE, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
  ASN_DIVISOR_INIT(tsch_hopping_sequence_length, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
#if TSCH_SCHEDULE_WITH_6TISCH_MINIMAL
  tsch_schedule_create_minimal();
#endif

  tsch_is_associated = 1;
  tsch_join_priority = 0;

  PRINTF("TSCH: starting as coordinator, PAN ID %x, asn-%x.%lx\n",
      frame802154_get_pan_id(), current_asn.ms1b, current_asn.ls4b);

  /* Start slot operation */
  tsch_slot_operation_sync(RTIMER_NOW(), &current_asn);
}
Exemple #4
0
/*---------------------------------------------------------------------------*/
static int
create_frame(int type, int do_create)
{
  frame802154_t params;
  int hdr_len;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return hdr_len;
  } else {
    PRINTF("15.4-OUT: too large header: %u\n", hdr_len);
    return FRAMER_FAILED;
  }
}
Exemple #5
0
/* Create an EB packet */
int
tsch_packet_create_eb(uint8_t *buf, int buf_size, uint8_t seqno,
                      uint8_t *hdr_len, uint8_t *tsch_sync_ie_offset)
{
    int ret = 0;
    uint8_t curr_len = 0;
    uint8_t mlme_ie_offset;

    frame802154_t p;
    struct ieee802154_ies ies;

    if(buf_size < TSCH_PACKET_MAX_LEN) {
        return 0;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return curr_len;
}
Exemple #6
0
/*---------------------------------------------------------------------------*/
static int
init(void)
{
  int put_index;
  tsExtAddr node_long_address;
  uint16_t node_short_address;

  tx_in_progress = 0;

  u32JPT_Init();
  vMMAC_Enable();

  /* Enable/disable interrupts */
  if(poll_mode) {
    vMMAC_EnableInterrupts(NULL);
    vMMAC_ConfigureInterruptSources(0);
  } else {
    vMMAC_EnableInterrupts(&radio_interrupt_handler);
  } vMMAC_ConfigureRadio();
  set_channel(MICROMAC_CONF_CHANNEL);
  set_txpower(MICROMAC_CONF_TX_POWER);

  vMMAC_GetMacAddress(&node_long_address);

  /* Short addresses are disabled by default */
  node_short_address = (uint16_t)node_long_address.u32L;
  vMMAC_SetRxAddress(frame802154_get_pan_id(), node_short_address, &node_long_address);

  /* Disable hardware backoff */
  vMMAC_SetTxParameters(1, 0, 0, 0);
  vMMAC_SetCutOffTimer(0, FALSE);

  /* Initialize ring buffer and first input packet pointer */
  ringbufindex_init(&input_ringbuf, MIRCOMAC_CONF_BUF_NUM);
  /* get pointer to next input slot */
  put_index = ringbufindex_peek_put(&input_ringbuf);
  if(put_index == -1) {
    rx_frame_buffer = NULL;
    printf("micromac_radio init:! no buffer available. Abort init.\n");
    off();
    return 0;
  } else {
    rx_frame_buffer = &input_array[put_index];
  }
  input_frame_buffer = rx_frame_buffer;

  process_start(&micromac_radio_process, NULL);

#if RADIO_TEST_MODE == RADIO_TEST_MODE_HIGH_PWR
  /* Enable high power mode.
   * In this mode DIO2 goes high during RX
   * and DIO3 goes high during TX
   **/
  vREG_SysWrite(REG_SYS_PWR_CTRL,
                u32REG_SysRead(REG_SYS_PWR_CTRL)
                | REG_SYSCTRL_PWRCTRL_RFRXEN_MASK
                | REG_SYSCTRL_PWRCTRL_RFTXEN_MASK);
#elif RADIO_TEST_MODE == RADIO_TEST_MODE_ADVANCED
  /* output internal radio status on IO pins.
   * See Chris@NXP email */
  vREG_SysWrite(REG_SYS_PWR_CTRL,
                u32REG_SysRead(REG_SYS_PWR_CTRL) | (1UL << 26UL));
#endif /* TEST_MODE */

  return 1;
}