Esempio n. 1
0
/*---------------------------------------------------------------------------*/
static int coap_context_send(coap_context_t *ctx, struct net_buf *buf)
{
  int max_data_len, ret;

  max_data_len = IP_BUF_MAX_DATA - UIP_IPUDPH_LEN;

  PRINTF("%s: send to peer data %p len %d\n", __FUNCTION__,
	 ip_buf_appdata(buf), ip_buf_appdatalen(buf));

  if (ip_buf_appdatalen(buf) > max_data_len) {
    PRINTF("%s: too much (%d bytes) data to send (max %d bytes)\n",
	   __FUNCTION__, ip_buf_appdatalen(buf), max_data_len);
    ip_buf_unref(buf);
    ret = -EINVAL;
    goto out;
  }

  ret = net_send(buf);
  if (ret < 0) {
    PRINT("%s: sending %d bytes failed\n", __FUNCTION__,
	  ip_buf_appdatalen(buf));
    ip_buf_unref(buf);
  }

out:
  return ret;
}
Esempio n. 2
0
static inline void receive_and_reply(struct net_context *recv,
				     struct net_context *mcast_recv)
{
	struct net_buf *buf;

	buf = net_receive(recv, TICKS_UNLIMITED);
	if (buf) {
		prepare_reply("unicast ", buf);

		if (net_reply(recv, buf)) {
			ip_buf_unref(buf);
		}
		return;
	}

	buf = net_receive(mcast_recv, TICKS_UNLIMITED);
	if (buf) {
		prepare_reply("multicast ", buf);

		if (net_reply(mcast_recv, buf)) {
			ip_buf_unref(buf);
		}
		return;
	}
}
Esempio n. 3
0
/*---------------------------------------------------------------------------*/
static int prepare_and_send_buf(coap_context_t *ctx, session_t *session,
				uint8_t *data, size_t len)
{
  struct net_buf *buf;
  int max_data_len;

  /* This net_buf gets sent to network, so it is not released
   * by this function unless there was an error and buf was
   * not actually sent.
   */
  buf = ip_buf_get_tx(ctx->net_ctx);
  if (!buf) {
    len = -ENOBUFS;
    goto out;
  }

  max_data_len = IP_BUF_MAX_DATA - UIP_IPUDPH_LEN;

  PRINTF("%s: reply to peer data %p len %d\n", __FUNCTION__, data, len);

  if (len > max_data_len) {
    PRINTF("%s: too much (%d bytes) data to send (max %d bytes)\n",
	  __FUNCTION__, len, max_data_len);
    ip_buf_unref(buf);
    len = -EINVAL;
    goto out;
  }

  /* Note that we have reversed the addresses here
   * because net_reply() will reverse them again.
   */
#ifdef CONFIG_NETWORKING_WITH_IPV6
  uip_ip6addr_copy(&NET_BUF_IP(buf)->destipaddr, (uip_ip6addr_t *)&ctx->my_addr.in6_addr);
  uip_ip6addr_copy(&NET_BUF_IP(buf)->srcipaddr,
		   (uip_ip6addr_t *)&session->addr.ipaddr);
#else
  uip_ip4addr_copy(&NET_BUF_IP(buf)->destipaddr,
		   (uip_ip4addr_t *)&ctx->my_addr.in_addr);
  uip_ip4addr_copy(&NET_BUF_IP(buf)->srcipaddr,
		   (uip_ip4addr_t *)&session->addr.ipaddr);
#endif
  NET_BUF_UDP(buf)->destport = uip_ntohs(ctx->my_port);
  NET_BUF_UDP(buf)->srcport = session->addr.port;

  uip_set_udp_conn(buf) = net_context_get_udp_connection(ctx->net_ctx);

  memcpy(net_buf_add(buf, len), data, len);
  ip_buf_appdatalen(buf) = len;
  ip_buf_appdata(buf) = buf->data + ip_buf_reserve(buf);

  if (net_reply(ctx->net_ctx, buf)) {
    ip_buf_unref(buf);
  }
out:
  return len;
}
Esempio n. 4
0
/*---------------------------------------------------------------------------*/
static int
event(struct dtls_context_t *ctx, session_t *session,
      dtls_alert_level_t level, unsigned short code)
{
  coap_context_t *coap_ctx;
  coap_ctx = dtls_get_app_data(ctx);

  if(coap_ctx == COAP_CONTEXT_NONE || coap_ctx->is_used == 0) {
    /* The context is no longer in use */
  } else if(code == DTLS_EVENT_CONNECTED) {
    coap_ctx->status = STATUS_CONNECTED;
    PRINTF("coap-context: DTLS CLIENT CONNECTED!\n");
    process_post(coap_ctx->process, coap_context_event, coap_ctx);
  } else if(code == DTLS_EVENT_CONNECT || code == DTLS_EVENT_RENEGOTIATE) {
    coap_ctx->status = STATUS_CONNECTING;
    PRINTF("coap-context: DTLS CLIENT NOT CONNECTED!\n");
    process_post(coap_ctx->process, coap_context_event, coap_ctx);
  } else if(level == DTLS_ALERT_LEVEL_FATAL && code < 256) {
    /* Fatal alert */
    if (coap_ctx && coap_ctx->buf) {
      ip_buf_unref(coap_ctx->buf);
      coap_ctx->buf = NULL;
    }
    coap_ctx->status = STATUS_ALERT;
    PRINTF("coap-context: DTLS CLIENT ALERT %u!\n", code);
    process_post(coap_ctx->process, coap_context_event, coap_ctx);
  }
  return 0;
}
Esempio n. 5
0
static void send_data(const char *taskname, struct net_context *ctx)
{
	int len = strlen(lorem_ipsum);
	struct net_buf *buf;

	buf = ip_buf_get_tx(ctx);
	if (buf) {
		uint8_t *ptr;
		uint16_t sent_len;

		ptr = net_buf_add(buf, 0);
		memcpy(ptr, lorem_ipsum, len);
		ptr = net_buf_add(buf, len);
		ptr = net_buf_add(buf, 1); /* add \0 */
		*ptr = '\0';
		sent_len = buf->len;

		if (net_send(buf) < 0) {
			PRINT("%s: %s(): sending %d bytes failed\n",
			      taskname, __func__, len);
			ip_buf_unref(buf);
		} else {
			PRINT("%s: %s(): sent %d bytes\n", taskname,
			      __func__, sent_len);
		}
	}
}
Esempio n. 6
0
static inline bool send_packet(const char *name,
			       struct net_context *ctx,
			       int ipsum_len,
			       int pos)
{
	struct net_buf *buf;
	bool fail = false;

	buf = ip_buf_get_tx(ctx);
	if (buf) {
		uint8_t *ptr;
		int sending_len = ipsum_len - pos;

		ptr = net_buf_add(buf, sending_len);
		memcpy(ptr, lorem_ipsum + pos, sending_len);
		sending_len = buf->len;

		if (net_send(buf) < 0) {
			PRINT("%s: sending %d bytes failed\n",
			      __func__, sending_len);
			ip_buf_unref(buf);
			fail = true;
			goto out;
		} else {
			PRINT("%s: sent %d bytes\n", __func__,
			      sending_len);
		}
	}

out:
	return fail;
}
static struct net_buf *copy_buf(struct net_buf *mbuf)
{
  struct net_buf *buf;

  buf = ip_buf_get_reserve_rx(0);
  if(!buf) {
    return NULL;
  }

  /* Copy from the fragment context info buffer first */
  linkaddr_copy(&ip_buf_ll_dest(buf),
		packetbuf_addr(mbuf, PACKETBUF_ADDR_RECEIVER));
  linkaddr_copy(&ip_buf_ll_src(buf),
		packetbuf_addr(mbuf, PACKETBUF_ADDR_SENDER));

  PRINTF("%s: mbuf datalen %d dataptr %p buf %p\n", __FUNCTION__,
	  packetbuf_datalen(mbuf), packetbuf_dataptr(mbuf), uip_buf(buf));
  if(packetbuf_datalen(mbuf) > 0 &&
     packetbuf_datalen(mbuf) <= UIP_BUFSIZE - UIP_LLH_LEN) {
    memcpy(uip_buf(buf), packetbuf_dataptr(mbuf), packetbuf_datalen(mbuf));
    uip_len(buf) = packetbuf_datalen(mbuf);
    net_buf_add(buf, uip_len(buf));
  } else {
    ip_buf_unref(buf);
    buf = NULL;
  }

  return buf;
}
Esempio n. 8
0
File: tcp.c Progetto: hudkmr/zephyr
int tcp_tx(struct net_context *ctx, uint8_t *buf,  size_t size)
{
	struct net_buf *nbuf = NULL;
	uint8_t *ptr;
	int rc = 0;

	nbuf = ip_buf_get_tx(ctx);
	if (nbuf == NULL) {
		printk("[%s:%d] Unable to get buffer\n", __func__, __LINE__);
		return -EINVAL;
	}

	ptr = net_buf_add(nbuf, size);
	memcpy(ptr, buf, size);
	ip_buf_appdatalen(nbuf) = size;

	do {
		rc = net_send(nbuf);
		if (rc >= 0) {
			ip_buf_unref(nbuf);
			return 0;
		}
		switch (rc) {
		case -EINPROGRESS:
			printk("%s: no connection yet, try again\n", __func__);
			fiber_sleep(TCP_RETRY_TIMEOUT);
			break;
		case -EAGAIN:
		case -ECONNRESET:
			printk("%s: no connection, try again later\n", __func__);
			fiber_sleep(TCP_RETRY_TIMEOUT);
			break;
		default:
			printk("%s: sending %d bytes failed\n",
			      __func__, size);
			ip_buf_unref(nbuf);
			return -EIO;
		}
	} while (1);

	return 0;
}
Esempio n. 9
0
/*---------------------------------------------------------------------------*/
int coap_context_reply(coap_context_t *ctx, struct net_buf *buf)
{
  int max_data_len, ret;

  max_data_len = IP_BUF_MAX_DATA - UIP_IPUDPH_LEN;

  PRINTF("%s: reply to peer data %p len %d\n", __FUNCTION__,
	 ip_buf_appdata(buf), ip_buf_appdatalen(buf));

  if (ip_buf_appdatalen(buf) > max_data_len) {
    PRINTF("%s: too much (%d bytes) data to send (max %d bytes)\n",
	  __FUNCTION__, ip_buf_appdatalen(buf), max_data_len);
    ip_buf_unref(buf);
    ret = -EINVAL;
    goto out;
  }

  if (net_reply(ctx->net_ctx, buf)) {
    ip_buf_unref(buf);
  }
out:
  return ret;
}
Esempio n. 10
0
static inline bool wait_reply(const char *name,
			      struct net_context *ctx,
			      int ipsum_len,
			      int pos)
{
	struct net_buf *buf;
	bool fail = false;
	int expected_len = ipsum_len - pos;

	/* Wait for the answer */
	buf = net_receive(ctx, WAIT_TICKS);
	if (buf) {
		if (ip_buf_appdatalen(buf) != expected_len) {
			PRINT("%s: received %d bytes, expected %d\n",
			      name, ip_buf_appdatalen(buf), expected_len);
			fail = true;
			goto free_buf;
		}

		/* In this test we reverse the received bytes.
		 * We could just pass the data back as is but
		 * this way it is possible to see how the app
		 * can manipulate the received data.
		 */
		reverse(ip_buf_appdata(buf), ip_buf_appdatalen(buf));

		/* Did we get all the data back?
		 */
		if (memcmp(lorem_ipsum + pos, ip_buf_appdata(buf),
			   expected_len)) {
			PRINT("%s: received data mismatch.\n", name);
			fail = true;
			goto free_buf;
		}

		PRINT("%s: received %d bytes\n", __func__,
			      expected_len);

	free_buf:
		ip_buf_unref(buf);
	} else {
		PRINT("%s: expected data, got none\n", name);
		fail = true;
	}

	return fail;
}
Esempio n. 11
0
File: tcp.c Progetto: hudkmr/zephyr
int tcp_rx(struct net_context *ctx, uint8_t *buf, size_t *read_bytes, size_t size)
{
	struct net_buf *nbuf;
	int rc;

	nbuf = net_receive(ctx, TCP_RX_TIMEOUT);
	rc = -EIO;
	if (nbuf != NULL) {
		*read_bytes = ip_buf_appdatalen(nbuf);
		if (*read_bytes > size) {
			rc = -ENOMEM;
		} else {
			memcpy(buf, ip_buf_appdata(nbuf), *read_bytes);
			rc = 0;
		}
		ip_buf_unref(nbuf);
	}
	return rc;
}
Esempio n. 12
0
/*---------------------------------------------------------------------------*/
int coap_context_wait_data(coap_context_t *coap_ctx, int32_t ticks)
{
  struct net_buf *buf;

  buf = net_receive(coap_ctx->net_ctx, ticks);
  if (buf) {
    session_t session;
    int ret;

    uip_ipaddr_copy(&session.addr.ipaddr, &UIP_IP_BUF(buf)->srcipaddr);
    session.addr.port = UIP_UDP_BUF(buf)->srcport;
    session.size = sizeof(session.addr);
    session.ifindex = 1;

    PRINTF("coap-context: got dtls message from ");
    PRINT6ADDR(&session.addr.ipaddr);
    PRINTF(":%d %u bytes\n", uip_ntohs(session.addr.port), uip_appdatalen(buf));

    PRINTF("Received appdata %p appdatalen %d\n",
	   ip_buf_appdata(buf), ip_buf_appdatalen(buf));

    coap_ctx->buf = buf;

    ret = dtls_handle_message(coap_ctx->dtls_context, &session,
			      ip_buf_appdata(buf), ip_buf_appdatalen(buf));

    /* We always release the buffer here as this buffer is never sent
     * to network anyway.
     */
    if (coap_ctx->buf) {
      ip_buf_unref(coap_ctx->buf);
      coap_ctx->buf = NULL;
    }

    return ret;
  }

  return 0;
}
Esempio n. 13
0
static void receive_data(const char *taskname, struct net_context *ctx)
{
	struct net_buf *buf;
#ifdef CONFIG_NET_SANITY_TEST
	int rp;
#endif

	buf = net_receive(ctx, TICKS_NONE);
	if (buf) {
		PRINT("%s: %s(): received %d bytes\n", taskname,
		      __func__, ip_buf_appdatalen(buf));
		if (memcmp(ip_buf_appdata(buf),
			   lorem_ipsum, sizeof(lorem_ipsum))) {
			PRINT("ERROR: data does not match\n");

#ifdef CONFIG_NET_SANITY_TEST
			rp = TC_FAIL;
		} else {
			rp = TC_PASS;
#endif
		}

		ip_buf_unref(buf);

#ifdef CONFIG_NET_SANITY_TEST
		loopback++;
		test_rp = test_rp && rp;
		TC_END_RESULT(rp);

		if (loopback == CONFIG_NET_15_4_LOOPBACK_NUM) {
			loopback = 0;
			TC_END_REPORT(test_rp);
		}
#endif
	}
}
Esempio n. 14
0
static int reassemble(struct net_buf *mbuf)
{
  /* size of the IP packet (read from fragment) */
  uint16_t frag_size = 0;
  int8_t frag_context = 0;
  /* offset of the fragment in the IP packet */
  uint8_t frag_offset = 0;
  uint8_t is_fragment = 0;
  /* tag of the fragment */
  uint16_t frag_tag = 0;
  uint8_t first_fragment = 0, last_fragment = 0;
  struct net_buf *buf = NULL; 

  /* init */
  uip_uncomp_hdr_len(mbuf) = 0;
  uip_packetbuf_hdr_len(mbuf) = 0;

  /* The MAC puts the 15.4 payload inside the packetbuf data buffer */
  uip_packetbuf_ptr(mbuf) = packetbuf_dataptr(mbuf);

  /* Save the RSSI of the incoming packet in case the upper layer will
     want to query us for it later. */
  last_rssi = (signed short)packetbuf_attr(mbuf, PACKETBUF_ATTR_RSSI);

   /*
   * Since we don't support the mesh and broadcast header, the first header
   * we look for is the fragmentation header
   */
  switch((GET16(uip_packetbuf_ptr(mbuf), PACKETBUF_FRAG_DISPATCH_SIZE) & 0xf800) >> 8) {
    case SICSLOWPAN_DISPATCH_FRAG1:
      PRINTF("reassemble: FRAG1 ");
      frag_offset = 0;
      frag_size = GET16(uip_packetbuf_ptr(mbuf), PACKETBUF_FRAG_DISPATCH_SIZE) & 0x07ff;
      frag_tag = GET16(uip_packetbuf_ptr(mbuf), PACKETBUF_FRAG_TAG);

      PRINTF("size %d, tag %d, offset %d\n", frag_size, frag_tag, frag_offset);

      if (frag_size > IP_BUF_MAX_DATA) {
        PRINTF("Too big packet %d bytes (max %d), fragment discarded\n",
	       frag_size, IP_BUF_MAX_DATA);
	goto fail;
      }

      uip_packetbuf_hdr_len(mbuf) += SICSLOWPAN_FRAG1_HDR_LEN;
      first_fragment = 1;
      is_fragment = 1;

      /* Add the fragment to the fragmentation context (this will also copy the payload)*/
      frag_context = add_fragment(mbuf, frag_tag, frag_size, frag_offset);
      if(frag_context == -1) {
        goto fail;
      }

      break;

    case SICSLOWPAN_DISPATCH_FRAGN:
      /*
       * set offset, tag, size
       * Offset is in units of 8 bytes
       */
      PRINTF("reassemble: FRAGN ");
      frag_offset = uip_packetbuf_ptr(mbuf)[PACKETBUF_FRAG_OFFSET];
      frag_tag = GET16(uip_packetbuf_ptr(mbuf), PACKETBUF_FRAG_TAG);
      frag_size = GET16(uip_packetbuf_ptr(mbuf), PACKETBUF_FRAG_DISPATCH_SIZE) & 0x07ff;

      PRINTF("reassemble: size %d, tag %d, offset %d\n", frag_size, frag_tag, frag_offset);

      uip_packetbuf_hdr_len(mbuf) += SICSLOWPAN_FRAGN_HDR_LEN;

      /* If this is the last fragment, we may shave off any extrenous
         bytes at the end. We must be liberal in what we accept. */
      /* Add the fragment to the fragmentation context  (this will also copy the payload) */
      frag_context = add_fragment(mbuf, frag_tag, frag_size, frag_offset);
      if(frag_context == -1) {
        goto fail;
      }

      if(frag_info[frag_context].reassembled_len >= frag_size) {
        last_fragment = 1;
      }
      is_fragment = 1;
      break;

    default:
      /* If there is no fragmentation header, then assume that the packet
       * is not fragmented and pass it as is to IP stack.
       */
      buf = copy_buf(mbuf);
      if(!buf || net_driver_15_4_recv(buf) < 0) {
        goto fail;
      }
      goto out;
  }

  /*
   * copy "payload" from the packetbuf buffer to the sicslowpan_buf
   * if this is a first fragment or not fragmented packet,
   * we have already copied the compressed headers, uncomp_hdr_len
   * and packetbuf_hdr_len are non 0, frag_offset is.
   * If this is a subsequent fragment, this is the contrary.
   */
  if(packetbuf_datalen(mbuf) < uip_packetbuf_hdr_len(mbuf)) {
    PRINTF("reassemble: packet dropped due to header > total packet\n");
    goto fail;
  }

  uip_packetbuf_payload_len(mbuf) = packetbuf_datalen(mbuf) - uip_packetbuf_hdr_len(mbuf);

  /* Sanity-check size of incoming packet to avoid buffer overflow */
  {
    int req_size = UIP_LLH_LEN + (uint16_t)(frag_offset << 3)
        + uip_packetbuf_payload_len(mbuf);

    if(req_size > UIP_BUFSIZE) {
      PRINTF("reassemble: packet dropped, minimum required IP_BUF size: %d+%d+%d=%d (current size: %d)\n", UIP_LLH_LEN, (uint16_t)(frag_offset << 3),
              uip_packetbuf_payload_len(mbuf), req_size, UIP_BUFSIZE);
      goto fail;
    }
  }

  if(frag_size > 0) {
    /* Add the size of the header only for the first fragment. */
    if(first_fragment != 0) {
      frag_info[frag_context].reassembled_len = uip_uncomp_hdr_len(mbuf) + uip_packetbuf_payload_len(mbuf);
    }

    /* For the last fragment, we are OK if there is extrenous bytes at
       the end of the packet. */
    if(last_fragment != 0) {
      frag_info[frag_context].reassembled_len = frag_size;
      /* copy to uip(net_buf) */
      buf = copy_frags2uip(frag_context);
      if(!buf)
        goto fail;
    }
  }

  /*
   * If we have a full IP packet in sicslowpan_buf, deliver it to
   * the IP stack
   */
  if(!is_fragment || last_fragment) {
    /* packet is in uip already - just set length */
    if(is_fragment != 0 && last_fragment != 0) {
      uip_len(buf) = frag_size;
    } else {
      uip_len(buf) = uip_packetbuf_payload_len(mbuf) + uip_uncomp_hdr_len(mbuf);
    }

    PRINTF("reassemble: IP packet ready (length %d)\n", uip_len(buf));

    if(net_driver_15_4_recv(buf) < 0) {
      goto fail;
    }
  }

out:
  /* free MAC buffer */
  l2_buf_unref(mbuf);
  return 1;

fail:
   if(buf) {
     ip_buf_unref(buf);
   }
   return 0;
}
Esempio n. 15
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;
}