예제 #1
0
/*---------------------------------------------------------------------------*/
static void
handle_beacon_send_timer(struct net_buf *buf, void *p)
{
  struct net_buf *mbuf;
  frame802154_t params;
  uint8_t len;

  mbuf = l2_buf_get_reserve(0);
  if(!mbuf) {
    return;
  }

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

  /* use packetbuf for sending ?? */
  packetbuf_clear(mbuf);
  /* Build the FCF. */
  params.fcf.frame_type = FRAME802154_BEACONFRAME;

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

  /* assume long for now */
  params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE;
  linkaddr_copy((linkaddr_t *)&params.src_addr, &linkaddr_node_addr);

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

  params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE;
  params.dest_addr[0] = 0xFF;
  params.dest_addr[1] = 0xFF;

  params.dest_pid = 0xffff;

  params.seq = framer_802154_next_seqno();

  /* Calculate beacon length and copy it to packetbuf */
  beacon_payload_len = handler_802154_calculate_beacon_payload_length(beacon_payload, BEACON_PAYLOAD_BUFFER_SIZE);
  packetbuf_copyfrom(mbuf, beacon_payload, beacon_payload_len);

  /* Set payload and payload length */
  params.payload = packetbuf_dataptr(mbuf);
  params.payload_len = packetbuf_datalen(mbuf);

  len = frame802154_hdrlen(&params);
  if(packetbuf_hdralloc(mbuf, len)) {
    frame802154_create(&params, packetbuf_hdrptr(mbuf), len);
    if(NETSTACK_RADIO.send(mbuf, packetbuf_hdrptr(mbuf),
                  packetbuf_totlen(mbuf)) != RADIO_TX_OK) {
      l2_buf_unref(mbuf);
      return;
    }

    HANDLER_802154_STAT(handler_802154_stats.beacons_sent++);
  }
}
예제 #2
0
/* called to send a beacon request */
void
handler_802154_send_beacon_request(void)
{
  struct net_buf *mbuf;
  frame802154_t params;
  uint8_t len;

  mbuf = l2_buf_get_reserve(0);
  if(!mbuf) {
    return;
  }

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

  /* use packetbuf for sending ?? */
  packetbuf_clear(mbuf);
  /* Build the FCF. */
  params.fcf.frame_type = FRAME802154_CMDFRAME;

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

  params.fcf.src_addr_mode = FRAME802154_NOADDR;

  params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE;
  params.dest_addr[0] = 0xFF;
  params.dest_addr[1] = 0xFF;

  params.dest_pid = 0xffff;

  params.seq = chseqno;

  packetbuf_set_datalen(mbuf, 1);
  params.payload = packetbuf_dataptr(mbuf);
  /* set the type in the payload */
  params.payload[0] = FRAME802154_BEACONREQ;
  params.payload_len = packetbuf_datalen(mbuf);
  len = frame802154_hdrlen(&params);

  if(packetbuf_hdralloc(mbuf, len)) {
    frame802154_create(&params, packetbuf_hdrptr(mbuf), len);
    if(NETSTACK_RADIO.send(mbuf, packetbuf_hdrptr(mbuf),
             packetbuf_totlen(mbuf)) != RADIO_TX_OK) {
      l2_buf_unref(mbuf);
      return;
    }
    HANDLER_802154_STAT(handler_802154_stats.beacons_reqs_sent++);
  }
}
예제 #3
0
static inline bool send_ack_packet(struct net_buf *buf, uint8_t *status)
{
	struct net_buf *ack_buf;
	frame802154_t frame;

	if (packetbuf_attr(buf, PACKETBUF_ATTR_FRAME_TYPE) !=
	    FRAME802154_DATAFRAME) {
		return false;
	}

	frame802154_parse(packetbuf_dataptr(buf),
			  packetbuf_datalen(buf),
			  &frame);

	if (frame.fcf.ack_required == 0 ||
	    !linkaddr_cmp((linkaddr_t *)&frame.dest_addr,
			  &linkaddr_node_addr)) {
		return false;
	}

	ack_buf = l2_buf_get_reserve(0);
	if (!ack_buf) {
		*status = MAC_TX_ERR;
		return false;
	}

	uip_pkt_packetbuf(ack_buf)[0] = FRAME802154_ACKFRAME;
	uip_pkt_packetbuf(ack_buf)[1] = 0;
	uip_pkt_packetbuf(ack_buf)[2] = frame.seq;

	*status = NETSTACK_RADIO.send(ack_buf, NULL, ACK_LEN);

	l2_buf_unref(ack_buf);

	PRINTF("simplerdc: Send ACK to packet %u\n",
	       packetbuf_attr(buf, PACKETBUF_ATTR_MAC_SEQNO));

	return true;
}
예제 #4
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;
}