Exemple #1
0
static uint16_t _send_1st_fragment(gnrc_netif_t *iface, gnrc_pktsnip_t *pkt,
                                   size_t payload_len, size_t datagram_size)
{
    gnrc_pktsnip_t *frag;
    uint16_t local_offset = 0;
    /* payload_len: actual size of the packet vs
     * datagram_size: size of the uncompressed IPv6 packet */
    int payload_diff = (datagram_size - payload_len);
    /* virtually add payload_diff to flooring to account for offset (must be divisable by 8)
     * in uncompressed datagram */
    uint16_t max_frag_size = _floor8(iface->sixlo.max_frag_size + payload_diff -
                                     sizeof(sixlowpan_frag_t)) - payload_diff;
    sixlowpan_frag_t *hdr;
    uint8_t *data;

    DEBUG("6lo frag: determined max_frag_size = %" PRIu16 "\n", max_frag_size);

    frag = _build_frag_pkt(pkt, payload_len,
                           max_frag_size + sizeof(sixlowpan_frag_t));

    if (frag == NULL) {
        return 0;
    }

    hdr = frag->next->data;
    data = (uint8_t *)(hdr + 1);

    hdr->disp_size = byteorder_htons((uint16_t)datagram_size);
    hdr->disp_size.u8[0] |= SIXLOWPAN_FRAG_1_DISP;
    hdr->tag = byteorder_htons(_tag);

    /* Tell the link layer that we will send more fragments */
    gnrc_netif_hdr_t *netif_hdr = frag->data;
    netif_hdr->flags |= GNRC_NETIF_HDR_FLAGS_MORE_DATA;

    pkt = pkt->next;    /* don't copy netif header */

    while (pkt != NULL) {
        size_t clen = _min(max_frag_size - local_offset, pkt->size);

        memcpy(data + local_offset, pkt->data, clen);
        local_offset += clen;

        if (local_offset >= max_frag_size) {
            break;
        }

        pkt = pkt->next;
    }

    DEBUG("6lo frag: send first fragment (datagram size: %u, "
          "datagram tag: %" PRIu16 ", fragment size: %" PRIu16 ")\n",
          (unsigned int)datagram_size, _tag, local_offset);
    gnrc_sixlowpan_dispatch_send(frag, NULL, 0);
    return local_offset;
}
static uint16_t _send_1st_fragment(ng_sixlowpan_netif_t *iface, ng_pktsnip_t *pkt,
                                   size_t payload_len, size_t datagram_size)
{
    ng_pktsnip_t *frag;
    uint16_t max_frag_size = _floor8(iface->max_frag_size -
                                     (payload_len - datagram_size) -
                                     sizeof(ng_sixlowpan_frag_t));
    uint16_t local_offset = 0;
    ng_sixlowpan_frag_t *hdr;
    uint8_t *data;

    DEBUG("6lo frag: determined max_frag_size = %" PRIu16 "\n", max_frag_size);

    /* 6LoWPAN dispatches don't count into that */
    max_frag_size += (payload_len - datagram_size);

    frag = _build_frag_pkt(pkt, payload_len,
                           max_frag_size + sizeof(ng_sixlowpan_frag_t));

    if (frag == NULL) {
        return 0;
    }

    hdr = frag->next->data;
    data = (uint8_t *)(hdr + 1);

    hdr->disp_size = byteorder_htons((uint16_t)datagram_size);
    hdr->disp_size.u8[0] |= NG_SIXLOWPAN_FRAG_1_DISP;
    hdr->tag = byteorder_htons(_tag);

    pkt = pkt->next;    /* don't copy netif header */

    while (pkt != NULL) {
        size_t clen = _min(max_frag_size - local_offset, pkt->size);

        memcpy(data + local_offset, pkt->data, clen);
        local_offset += clen;

        if (local_offset >= max_frag_size) {
            break;
        }

        pkt = pkt->next;
    }

    DEBUG("6lo frag: send first fragment (datagram size: %u, "
          "datagram tag: %" PRIu16 ", fragment size: %" PRIu16 ")\n",
          (unsigned int)datagram_size, _tag, local_offset);
    ng_netapi_send(iface->pid, frag);

    return local_offset;
}
Exemple #3
0
static uint16_t _send_nth_fragment(gnrc_netif_t *iface, gnrc_pktsnip_t *pkt,
                                   size_t payload_len, size_t datagram_size,
                                   uint16_t offset)
{
    gnrc_pktsnip_t *frag;
    /* since dispatches aren't supposed to go into subsequent fragments, we need not account
     * for payload difference as for the first fragment */
    uint16_t max_frag_size = _floor8(iface->sixlo.max_frag_size - sizeof(sixlowpan_frag_n_t));
    uint16_t local_offset = 0, offset_count = 0;
    sixlowpan_frag_n_t *hdr;
    uint8_t *data;

    DEBUG("6lo frag: determined max_frag_size = %" PRIu16 "\n", max_frag_size);

    frag = _build_frag_pkt(pkt,
                           payload_len - offset + sizeof(sixlowpan_frag_n_t),
                           max_frag_size + sizeof(sixlowpan_frag_n_t));

    if (frag == NULL) {
        return 0;
    }

    hdr = frag->next->data;
    data = (uint8_t *)(hdr + 1);

    /* XXX: truncation of datagram_size > 4095 may happen here */
    hdr->disp_size = byteorder_htons((uint16_t)datagram_size);
    hdr->disp_size.u8[0] |= SIXLOWPAN_FRAG_N_DISP;
    hdr->tag = byteorder_htons(_tag);
    /* don't mention payload diff in offset */
    hdr->offset = (uint8_t)((offset + (datagram_size - payload_len)) >> 3);
    pkt = pkt->next;    /* don't copy netif header */

    while ((pkt != NULL) && (offset_count != offset)) {   /* go to offset */
        offset_count += (uint16_t)pkt->size;

        if (offset_count > offset) {    /* we overshot */
            /* => copy rest of partly send packet snip */
            uint16_t pkt_offset = offset - (offset_count - ((uint16_t)pkt->size));
            size_t clen = _min(max_frag_size, pkt->size - pkt_offset);

            memcpy(data, ((uint8_t *)pkt->data) + pkt_offset, clen);
            local_offset = clen;
            if (local_offset == max_frag_size) {
                if ((clen < (pkt->size - pkt_offset)) || (pkt->next != NULL)) {
                    /* Tell the link layer that we will send more fragments */
                    gnrc_netif_hdr_t *netif_hdr = frag->data;
                    netif_hdr->flags |= GNRC_NETIF_HDR_FLAGS_MORE_DATA;
                }
            }
            pkt = pkt->next;
            break;
        }

        pkt = pkt->next;
    }

    if (local_offset < max_frag_size) { /* copy other packet snips */
        while (pkt != NULL) {
            size_t clen = _min(max_frag_size - local_offset, pkt->size);

            memcpy(data + local_offset, pkt->data, clen);
            local_offset += clen;

            if (local_offset == max_frag_size) {
                if ((clen < pkt->size) || (pkt->next != NULL)) {
                    /* Tell the link layer that we will send more fragments */
                    gnrc_netif_hdr_t *netif_hdr = frag->data;
                    netif_hdr->flags |= GNRC_NETIF_HDR_FLAGS_MORE_DATA;
                }
                break;
            }

            pkt = pkt->next;
        }
    }

    DEBUG("6lo frag: send subsequent fragment (datagram size: %u, "
          "datagram tag: %" PRIu16 ", offset: %" PRIu8 " (%u bytes), "
          "fragment size: %" PRIu16 ")\n",
          (unsigned int)datagram_size, _tag, hdr->offset, hdr->offset << 3,
          local_offset);
    gnrc_sixlowpan_dispatch_send(frag, NULL, 0);
    return local_offset;
}
static uint16_t _send_nth_fragment(ng_sixlowpan_netif_t *iface, ng_pktsnip_t *pkt,
                                   size_t payload_len, size_t datagram_size,
                                   uint16_t offset)
{
    ng_pktsnip_t *frag;
    uint16_t max_frag_size = _floor8(iface->max_frag_size - sizeof(ng_sixlowpan_frag_n_t));
    uint16_t local_offset = 0, offset_count = 0;
    ng_sixlowpan_frag_n_t *hdr;
    uint8_t *data;

    DEBUG("6lo frag: determined max_frag_size = %" PRIu16 "\n", max_frag_size);

    frag = _build_frag_pkt(pkt,
                           payload_len - offset + sizeof(ng_sixlowpan_frag_n_t),
                           max_frag_size + sizeof(ng_sixlowpan_frag_n_t));

    if (frag == NULL) {
        return 0;
    }

    hdr = frag->next->data;
    data = (uint8_t *)(hdr + 1);

    /* XXX: truncation of datagram_size > 4095 may happen here */
    hdr->disp_size = byteorder_htons((uint16_t)datagram_size);
    hdr->disp_size.u8[0] |= NG_SIXLOWPAN_FRAG_N_DISP;
    hdr->tag = byteorder_htons(_tag);
    hdr->offset = (uint8_t)(offset >> 3);
    pkt = pkt->next;    /* don't copy netif header */

    while ((pkt != NULL) && (offset_count != offset)) {   /* go to offset */
        offset_count += (uint16_t)pkt->size;

        if (offset_count > offset) {    /* we overshot */
            /* => copy rest of partly send packet snip */
            uint16_t pkt_offset = offset - (offset_count - ((uint16_t)pkt->size));
            size_t clen = _min(max_frag_size, pkt->size - pkt_offset);

            memcpy(data, ((uint8_t *)pkt->data) + pkt_offset, clen);
            local_offset = clen;
            pkt = pkt->next;
            break;
        }

        pkt = pkt->next;
    }

    if (local_offset < max_frag_size) { /* copy other packet snips */
        while (pkt != NULL) {
            size_t clen = _min(max_frag_size - local_offset, pkt->size);

            memcpy(data + local_offset, pkt->data, clen);
            local_offset += clen;

            if (local_offset == max_frag_size) {
                break;
            }

            pkt = pkt->next;
        }
    }

    DEBUG("6lo frag: send subsequent fragment (datagram size: %u, "
          "datagram tag: %" PRIu16 ", offset: %" PRIu8 " (%u bytes), "
          "fragment size: %" PRIu16 ")\n",
          (unsigned int)datagram_size, _tag, hdr->offset, hdr->offset << 3,
          local_offset);
    ng_netapi_send(iface->pid, frag);

    return local_offset;
}