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