diff --git a/sys/include/net/gnrc/sixlowpan/frag.h b/sys/include/net/gnrc/sixlowpan/frag.h index 68f2c4d9bf9eefc42ff3be033f077884c0a53a04..995640c3648d82d8525b9aa847f2718940485286 100644 --- a/sys/include/net/gnrc/sixlowpan/frag.h +++ b/sys/include/net/gnrc/sixlowpan/frag.h @@ -31,6 +31,7 @@ #include "byteorder.h" #include "kernel_types.h" #include "net/gnrc/pkt.h" +#include "net/ieee802154.h" #include "net/sixlowpan.h" #ifdef __cplusplus @@ -42,6 +43,32 @@ extern "C" { */ #define GNRC_SIXLOWPAN_MSG_FRAG_SND (0x0225) +/** + * @brief An entry in the 6LoWPAN reassembly buffer. + * + * A recipient of a fragment SHALL use + * + * 1. the source address, + * 2. the destination address, + * 3. the datagram size (gnrc_pktsnip_t::size of rbuf_t::pkt), and + * 4. the datagram tag + * + * to identify all fragments that belong to the given datagram. + * + * @see [RFC 4944, section 5.3](https://tools.ietf.org/html/rfc4944#section-5.3) + */ +typedef struct { + /** + * @brief The reassembled packet in the packet buffer + */ + gnrc_pktsnip_t *pkt; + uint8_t src[IEEE802154_LONG_ADDRESS_LEN]; /**< source address */ + uint8_t dst[IEEE802154_LONG_ADDRESS_LEN]; /**< destination address */ + uint8_t src_len; /**< length of gnrc_sixlowpan_rbuf_t::src */ + uint8_t dst_len; /**< length of gnrc_sixlowpan_rbuf_t::dst */ + uint16_t tag; /**< the datagram's tag */ +} gnrc_sixlowpan_rbuf_t; + /** * @brief Definition of 6LoWPAN fragmentation type. */ diff --git a/sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.c b/sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.c index 4638b9c621f3b588af714c064292227e36fb61cf..8aef46371ab743a8efe35d90ce82bceb2ea313a8 100644 --- a/sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.c +++ b/sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.c @@ -46,7 +46,7 @@ static rbuf_int_t rbuf_int[RBUF_INT_SIZE]; static rbuf_t rbuf[RBUF_SIZE]; -static char l2addr_str[3 * RBUF_L2ADDR_MAX_LEN]; +static char l2addr_str[3 * IEEE802154_LONG_ADDRESS_LEN]; /* ------------------------------------ * internal function definitions @@ -100,11 +100,13 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt, #ifdef MODULE_GNRC_SIXLOWPAN_IPHC else if (sixlowpan_iphc_is(data)) { size_t iphc_len, nh_len = 0; - iphc_len = gnrc_sixlowpan_iphc_decode(&entry->pkt, pkt, entry->pkt->size, - sizeof(sixlowpan_frag_t), &nh_len); + iphc_len = gnrc_sixlowpan_iphc_decode(&entry->super.pkt, pkt, + entry->super.pkt->size, + sizeof(sixlowpan_frag_t), + &nh_len); if (iphc_len == 0) { DEBUG("6lo rfrag: could not decode IPHC dispatch\n"); - gnrc_pktbuf_release(entry->pkt); + gnrc_pktbuf_release(entry->super.pkt); _rbuf_rem(entry); return; } @@ -121,9 +123,9 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt, data++; /* FRAGN header is one byte longer (offset) */ } - if ((offset + frag_size) > entry->pkt->size) { + if ((offset + frag_size) > entry->super.pkt->size) { DEBUG("6lo rfrag: fragment too big for resulting datagram, discarding datagram\n"); - gnrc_pktbuf_release(entry->pkt); + gnrc_pktbuf_release(entry->super.pkt); _rbuf_rem(entry); return; } @@ -134,7 +136,7 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt, while (ptr != NULL) { if (_rbuf_int_overlap_partially(ptr, offset, offset + frag_size - 1)) { DEBUG("6lo rfrag: overlapping intervals, discarding datagram\n"); - gnrc_pktbuf_release(entry->pkt); + gnrc_pktbuf_release(entry->super.pkt); _rbuf_rem(entry); /* "A fresh reassembly may be commenced with the most recently @@ -151,17 +153,19 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt, if (_rbuf_update_ints(entry, offset, frag_size)) { DEBUG("6lo rbuf: add fragment data\n"); entry->cur_size += (uint16_t)frag_size; - memcpy(((uint8_t *)entry->pkt->data) + offset + data_offset, data, + memcpy(((uint8_t *)entry->super.pkt->data) + offset + data_offset, data, frag_size - data_offset); } - if (entry->cur_size == entry->pkt->size) { - gnrc_pktsnip_t *netif = gnrc_netif_hdr_build(entry->src, entry->src_len, - entry->dst, entry->dst_len); + if (entry->cur_size == entry->super.pkt->size) { + gnrc_pktsnip_t *netif = gnrc_netif_hdr_build(entry->super.src, + entry->super.src_len, + entry->super.dst, + entry->super.dst_len); if (netif == NULL) { DEBUG("6lo rbuf: error allocating netif header\n"); - gnrc_pktbuf_release(entry->pkt); + gnrc_pktbuf_release(entry->super.pkt); _rbuf_rem(entry); return; } @@ -175,8 +179,8 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt, new_netif_hdr->flags = netif_hdr->flags; new_netif_hdr->lqi = netif_hdr->lqi; new_netif_hdr->rssi = netif_hdr->rssi; - LL_APPEND(entry->pkt, netif); - gnrc_sixlowpan_dispatch_recv(entry->pkt, NULL, 0); + LL_APPEND(entry->super.pkt, netif); + gnrc_sixlowpan_dispatch_recv(entry->super.pkt, NULL, 0); _rbuf_rem(entry); } } @@ -210,7 +214,7 @@ static void _rbuf_rem(rbuf_t *entry) entry->ints = next; } - entry->pkt = NULL; + entry->super.pkt = NULL; } static bool _rbuf_update_ints(rbuf_t *entry, uint16_t offset, size_t frag_size) @@ -229,12 +233,13 @@ static bool _rbuf_update_ints(rbuf_t *entry, uint16_t offset, size_t frag_size) new->end = end; DEBUG("6lo rfrag: add interval (%" PRIu16 ", %" PRIu16 ") to entry (%s, ", - new->start, new->end, gnrc_netif_addr_to_str(entry->src, - entry->src_len, + new->start, new->end, gnrc_netif_addr_to_str(entry->super.src, + entry->super.src_len, l2addr_str)); - DEBUG("%s, %u, %u)\n", gnrc_netif_addr_to_str(entry->dst, entry->dst_len, + DEBUG("%s, %u, %u)\n", gnrc_netif_addr_to_str(entry->super.dst, + entry->super.dst_len, l2addr_str), - (unsigned)entry->pkt->size, entry->tag); + (unsigned)entry->super.pkt->size, entry->super.tag); LL_PREPEND(entry->ints, new); @@ -248,17 +253,19 @@ static void _rbuf_gc(void) for (i = 0; i < RBUF_SIZE; i++) { /* since pkt occupies pktbuf, aggressivly collect garbage */ - if ((rbuf[i].pkt != NULL) && + if ((rbuf[i].super.pkt != NULL) && ((now_usec - rbuf[i].arrival) > RBUF_TIMEOUT)) { DEBUG("6lo rfrag: entry (%s, ", - gnrc_netif_addr_to_str(rbuf[i].src, rbuf[i].src_len, + gnrc_netif_addr_to_str(rbuf[i].super.src, + rbuf[i].super.src_len, l2addr_str)); DEBUG("%s, %u, %u) timed out\n", - gnrc_netif_addr_to_str(rbuf[i].dst, rbuf[i].dst_len, + gnrc_netif_addr_to_str(rbuf[i].super.dst, + rbuf[i].super.dst_len, l2addr_str), - (unsigned)rbuf[i].pkt->size, rbuf[i].tag); + (unsigned)rbuf[i].super.pkt->size, rbuf[i].super.tag); - gnrc_pktbuf_release(rbuf[i].pkt); + gnrc_pktbuf_release(rbuf[i].super.pkt); _rbuf_rem(&(rbuf[i])); } } @@ -273,24 +280,26 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len, for (unsigned int i = 0; i < RBUF_SIZE; i++) { /* check first if entry already available */ - if ((rbuf[i].pkt != NULL) && (rbuf[i].pkt->size == size) && - (rbuf[i].tag == tag) && (rbuf[i].src_len == src_len) && - (rbuf[i].dst_len == dst_len) && - (memcmp(rbuf[i].src, src, src_len) == 0) && - (memcmp(rbuf[i].dst, dst, dst_len) == 0)) { + if ((rbuf[i].super.pkt != NULL) && (rbuf[i].super.pkt->size == size) && + (rbuf[i].super.tag == tag) && (rbuf[i].super.src_len == src_len) && + (rbuf[i].super.dst_len == dst_len) && + (memcmp(rbuf[i].super.src, src, src_len) == 0) && + (memcmp(rbuf[i].super.dst, dst, dst_len) == 0)) { DEBUG("6lo rfrag: entry %p (%s, ", (void *)(&rbuf[i]), - gnrc_netif_addr_to_str(rbuf[i].src, rbuf[i].src_len, + gnrc_netif_addr_to_str(rbuf[i].super.src, + rbuf[i].super.src_len, l2addr_str)); DEBUG("%s, %u, %u) found\n", - gnrc_netif_addr_to_str(rbuf[i].dst, rbuf[i].dst_len, + gnrc_netif_addr_to_str(rbuf[i].super.dst, + rbuf[i].super.dst_len, l2addr_str), - (unsigned)rbuf[i].pkt->size, rbuf[i].tag); + (unsigned)rbuf[i].super.pkt->size, rbuf[i].super.tag); rbuf[i].arrival = now_usec; return &(rbuf[i]); } /* if there is a free spot: remember it */ - if ((res == NULL) && (rbuf[i].pkt == NULL)) { + if ((res == NULL) && (rbuf[i].super.pkt == NULL)) { res = &(rbuf[i]); } @@ -304,36 +313,39 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len, /* entry not in buffer and no empty spot found */ if (res == NULL) { assert(oldest != NULL); - assert(oldest->pkt != NULL); /* if oldest->pkt == NULL, res must not be NULL */ + /* if oldest->pkt == NULL, res must not be NULL */ + assert(oldest->super.pkt != NULL); DEBUG("6lo rfrag: reassembly buffer full, remove oldest entry\n"); - gnrc_pktbuf_release(oldest->pkt); + gnrc_pktbuf_release(oldest->super.pkt); _rbuf_rem(oldest); res = oldest; } /* now we have an empty spot */ - res->pkt = gnrc_pktbuf_add(NULL, NULL, size, GNRC_NETTYPE_IPV6); - if (res->pkt == NULL) { + res->super.pkt = gnrc_pktbuf_add(NULL, NULL, size, GNRC_NETTYPE_IPV6); + if (res->super.pkt == NULL) { DEBUG("6lo rfrag: can not allocate reassembly buffer space.\n"); return NULL; } - *((uint64_t *)res->pkt->data) = 0; /* clean first few bytes for later - * look-ups */ + *((uint64_t *)res->super.pkt->data) = 0; /* clean first few bytes for later + * look-ups */ res->arrival = now_usec; - memcpy(res->src, src, src_len); - memcpy(res->dst, dst, dst_len); - res->src_len = src_len; - res->dst_len = dst_len; - res->tag = tag; + memcpy(res->super.src, src, src_len); + memcpy(res->super.dst, dst, dst_len); + res->super.src_len = src_len; + res->super.dst_len = dst_len; + res->super.tag = tag; res->cur_size = 0; DEBUG("6lo rfrag: entry %p (%s, ", (void *)res, - gnrc_netif_addr_to_str(res->src, res->src_len, l2addr_str)); + gnrc_netif_addr_to_str(res->super.src, res->super.src_len, + l2addr_str)); DEBUG("%s, %u, %u) created\n", - gnrc_netif_addr_to_str(res->dst, res->dst_len, l2addr_str), (unsigned)res->pkt->size, - res->tag); + gnrc_netif_addr_to_str(res->super.dst, res->super.dst_len, + l2addr_str), (unsigned)res->super.pkt->size, + res->super.tag); return res; } diff --git a/sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.h b/sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.h index 2e56a1612564454d503db7acc7bd28565189aa6c..405e424052506da6e8c455b0ec9e0fbde94ab13d 100644 --- a/sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.h +++ b/sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.h @@ -30,7 +30,6 @@ extern "C" { #endif -#define RBUF_L2ADDR_MAX_LEN (8U) /**< maximum length for link-layer addresses */ #define RBUF_SIZE (4U) /**< size of the reassembly buffer */ #define RBUF_TIMEOUT (3U * US_PER_SEC) /**< timeout for reassembly in microseconds */ @@ -53,33 +52,19 @@ typedef struct rbuf_int { } rbuf_int_t; /** - * @brief An entry in the 6LoWPAN reassembly buffer. + * @brief Internal representation of the 6LoWPAN reassembly buffer. * - * @details A receipient of a fragment SHALL use - * - * 1. the source address, - * 2. the destination address, - * 3. the datagram size (gnrc_pktsnip_t::size of rbuf_t::pkt), and - * 4. the datagram tag - * - * to identify all fragments that belong to the given datagram. - * - * @see <a href="https://tools.ietf.org/html/rfc4944#section-5.3"> - * RFC 4944, section 5.3 - * </a> + * Additional members help with correct reassembly of the buffer. * * @internal + * + * @extends gnrc_sixlowpan_rbuf_t */ typedef struct { + gnrc_sixlowpan_rbuf_t super; /**< exposed part of the reassembly buffer */ rbuf_int_t *ints; /**< intervals of the fragment */ - gnrc_pktsnip_t *pkt; /**< the reassembled packet in packet buffer */ uint32_t arrival; /**< time in microseconds of arrival of * last received fragment */ - uint8_t src[RBUF_L2ADDR_MAX_LEN]; /**< source address */ - uint8_t dst[RBUF_L2ADDR_MAX_LEN]; /**< destination address */ - uint8_t src_len; /**< length of source address */ - uint8_t dst_len; /**< length of destination address */ - uint16_t tag; /**< the datagram's tag */ uint16_t cur_size; /**< the datagram's current size */ } rbuf_t;