mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-18 12:52:44 +01:00
gnrc_sixlowpan_frag: expose (parts of) reassembly buffer
This exposes the parts of the reassembly buffer to be usable as context as proposed in #8511. I only exposed *parts of* for two reasons: 1. I don't need to expose further types (like `rbuf_int_t`), that are not of interest outside of fragmentation. 2. This allows for an easy future extension for the virtual reassembly buffer as proposed in [[1]]. This makes this change a little bit more involved, because instead of just renaming the type, I also need to add the usage of the `super` member, but I think in the end this little preparation work will be beneficial in the future. [1]: https://tools.ietf.org/html/draft-watteyne-6lo-minimal-fragment-01#section-3
This commit is contained in:
parent
e91e0a7807
commit
86cbde2db5
@ -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.
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user