mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-18 12:52:44 +01:00
gnrc_sixlowpan_frag: introduce reassembly buffer base class
This commit is contained in:
parent
495eaa36a6
commit
52e4247798
@ -75,24 +75,19 @@ typedef struct gnrc_sixlowpan_rbuf_int {
|
|||||||
} gnrc_sixlowpan_rbuf_int_t;
|
} gnrc_sixlowpan_rbuf_int_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief An entry in the 6LoWPAN reassembly buffer.
|
* @brief Base class for both reassembly buffer and virtual reassembly buffer
|
||||||
*
|
|
||||||
* A recipient of a fragment SHALL use
|
|
||||||
*
|
*
|
||||||
* 1. the source address,
|
* 1. the source address,
|
||||||
* 2. the destination address,
|
* 2. the destination address,
|
||||||
* 3. the datagram size (gnrc_pktsnip_t::size of rbuf_t::pkt), and
|
* 3. the datagram size, and
|
||||||
* 4. the datagram tag
|
* 4. the datagram tag
|
||||||
*
|
*
|
||||||
* to identify all fragments that belong to the given datagram.
|
* 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)
|
* @see [RFC 4944, section 5.3](https://tools.ietf.org/html/rfc4944#section-5.3)
|
||||||
|
* @see https://tools.ietf.org/html/draft-ietf-lwig-6lowpan-virtual-reassembly-01
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/**
|
|
||||||
* @brief The reassembled packet in the packet buffer
|
|
||||||
*/
|
|
||||||
gnrc_pktsnip_t *pkt;
|
|
||||||
gnrc_sixlowpan_rbuf_int_t *ints; /**< intervals of already received fragments */
|
gnrc_sixlowpan_rbuf_int_t *ints; /**< intervals of already received fragments */
|
||||||
uint8_t src[IEEE802154_LONG_ADDRESS_LEN]; /**< source address */
|
uint8_t src[IEEE802154_LONG_ADDRESS_LEN]; /**< source address */
|
||||||
uint8_t dst[IEEE802154_LONG_ADDRESS_LEN]; /**< destination address */
|
uint8_t dst[IEEE802154_LONG_ADDRESS_LEN]; /**< destination address */
|
||||||
@ -105,6 +100,20 @@ typedef struct {
|
|||||||
* @brief The number of bytes currently received of the complete datagram
|
* @brief The number of bytes currently received of the complete datagram
|
||||||
*/
|
*/
|
||||||
uint16_t current_size;
|
uint16_t current_size;
|
||||||
|
} gnrc_sixlowpan_rbuf_base_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief An entry in the 6LoWPAN reassembly buffer.
|
||||||
|
*
|
||||||
|
* A recipient of a fragment SHALL use
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
gnrc_sixlowpan_rbuf_base_t super; /**< base class */
|
||||||
|
/**
|
||||||
|
* @brief The reassembled packet in the packet buffer
|
||||||
|
*/
|
||||||
|
gnrc_pktsnip_t *pkt;
|
||||||
} gnrc_sixlowpan_rbuf_t;
|
} gnrc_sixlowpan_rbuf_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -345,11 +345,11 @@ void gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(gnrc_sixlowpan_rbuf_t *rbuf
|
|||||||
{
|
{
|
||||||
assert(rbuf);
|
assert(rbuf);
|
||||||
assert(netif_hdr);
|
assert(netif_hdr);
|
||||||
if (rbuf->current_size == rbuf->pkt->size) {
|
if (rbuf->super.current_size == rbuf->pkt->size) {
|
||||||
gnrc_pktsnip_t *netif = gnrc_netif_hdr_build(rbuf->src,
|
gnrc_pktsnip_t *netif = gnrc_netif_hdr_build(rbuf->super.src,
|
||||||
rbuf->src_len,
|
rbuf->super.src_len,
|
||||||
rbuf->dst,
|
rbuf->super.dst,
|
||||||
rbuf->dst_len);
|
rbuf->super.dst_len);
|
||||||
|
|
||||||
if (netif == NULL) {
|
if (netif == NULL) {
|
||||||
DEBUG("6lo rbuf: error allocating netif header\n");
|
DEBUG("6lo rbuf: error allocating netif header\n");
|
||||||
|
@ -112,7 +112,7 @@ static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
|||||||
return RBUF_ADD_ERROR;
|
return RBUF_ADD_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = entry->ints;
|
ptr = entry->super.ints;
|
||||||
|
|
||||||
/* dispatches in the first fragment are ignored */
|
/* dispatches in the first fragment are ignored */
|
||||||
if (offset == 0) {
|
if (offset == 0) {
|
||||||
@ -159,7 +159,7 @@ static int _rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
|||||||
|
|
||||||
if (_rbuf_update_ints(entry, offset, frag_size)) {
|
if (_rbuf_update_ints(entry, offset, frag_size)) {
|
||||||
DEBUG("6lo rbuf: add fragment data\n");
|
DEBUG("6lo rbuf: add fragment data\n");
|
||||||
entry->current_size += (uint16_t)frag_size;
|
entry->super.current_size += (uint16_t)frag_size;
|
||||||
if (offset == 0) {
|
if (offset == 0) {
|
||||||
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
|
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
|
||||||
if (sixlowpan_iphc_is(data)) {
|
if (sixlowpan_iphc_is(data)) {
|
||||||
@ -209,13 +209,13 @@ static gnrc_sixlowpan_rbuf_int_t *_rbuf_int_get_free(void)
|
|||||||
|
|
||||||
void rbuf_rm(gnrc_sixlowpan_rbuf_t *entry)
|
void rbuf_rm(gnrc_sixlowpan_rbuf_t *entry)
|
||||||
{
|
{
|
||||||
while (entry->ints != NULL) {
|
while (entry->super.ints != NULL) {
|
||||||
gnrc_sixlowpan_rbuf_int_t *next = entry->ints->next;
|
gnrc_sixlowpan_rbuf_int_t *next = entry->super.ints->next;
|
||||||
|
|
||||||
entry->ints->start = 0;
|
entry->super.ints->start = 0;
|
||||||
entry->ints->end = 0;
|
entry->super.ints->end = 0;
|
||||||
entry->ints->next = NULL;
|
entry->super.ints->next = NULL;
|
||||||
entry->ints = next;
|
entry->super.ints = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
entry->pkt = NULL;
|
entry->pkt = NULL;
|
||||||
@ -238,15 +238,15 @@ static bool _rbuf_update_ints(gnrc_sixlowpan_rbuf_t *entry, uint16_t offset,
|
|||||||
new->end = end;
|
new->end = end;
|
||||||
|
|
||||||
DEBUG("6lo rfrag: add interval (%" PRIu16 ", %" PRIu16 ") to entry (%s, ",
|
DEBUG("6lo rfrag: add interval (%" PRIu16 ", %" PRIu16 ") to entry (%s, ",
|
||||||
new->start, new->end, gnrc_netif_addr_to_str(entry->src,
|
new->start, new->end, gnrc_netif_addr_to_str(entry->super.src,
|
||||||
entry->src_len,
|
entry->super.src_len,
|
||||||
l2addr_str));
|
l2addr_str));
|
||||||
DEBUG("%s, %u, %u)\n", gnrc_netif_addr_to_str(entry->dst,
|
DEBUG("%s, %u, %u)\n", gnrc_netif_addr_to_str(entry->super.dst,
|
||||||
entry->dst_len,
|
entry->super.dst_len,
|
||||||
l2addr_str),
|
l2addr_str),
|
||||||
(unsigned)entry->pkt->size, entry->tag);
|
(unsigned)entry->pkt->size, entry->super.tag);
|
||||||
|
|
||||||
LL_PREPEND(entry->ints, new);
|
LL_PREPEND(entry->super.ints, new);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -259,16 +259,16 @@ void rbuf_gc(void)
|
|||||||
for (i = 0; i < RBUF_SIZE; i++) {
|
for (i = 0; i < RBUF_SIZE; i++) {
|
||||||
/* since pkt occupies pktbuf, aggressivly collect garbage */
|
/* since pkt occupies pktbuf, aggressivly collect garbage */
|
||||||
if ((rbuf[i].pkt != NULL) &&
|
if ((rbuf[i].pkt != NULL) &&
|
||||||
((now_usec - rbuf[i].arrival) > RBUF_TIMEOUT)) {
|
((now_usec - rbuf[i].super.arrival) > RBUF_TIMEOUT)) {
|
||||||
DEBUG("6lo rfrag: entry (%s, ",
|
DEBUG("6lo rfrag: entry (%s, ",
|
||||||
gnrc_netif_addr_to_str(rbuf[i].src,
|
gnrc_netif_addr_to_str(rbuf[i].super.src,
|
||||||
rbuf[i].src_len,
|
rbuf[i].super.src_len,
|
||||||
l2addr_str));
|
l2addr_str));
|
||||||
DEBUG("%s, %u, %u) timed out\n",
|
DEBUG("%s, %u, %u) timed out\n",
|
||||||
gnrc_netif_addr_to_str(rbuf[i].dst,
|
gnrc_netif_addr_to_str(rbuf[i].super.dst,
|
||||||
rbuf[i].dst_len,
|
rbuf[i].super.dst_len,
|
||||||
l2addr_str),
|
l2addr_str),
|
||||||
(unsigned)rbuf[i].pkt->size, rbuf[i].tag);
|
(unsigned)rbuf[i].pkt->size, rbuf[i].super.tag);
|
||||||
|
|
||||||
gnrc_pktbuf_release(rbuf[i].pkt);
|
gnrc_pktbuf_release(rbuf[i].pkt);
|
||||||
rbuf_rm(&(rbuf[i]));
|
rbuf_rm(&(rbuf[i]));
|
||||||
@ -292,20 +292,20 @@ static gnrc_sixlowpan_rbuf_t *_rbuf_get(const void *src, size_t src_len,
|
|||||||
for (unsigned int i = 0; i < RBUF_SIZE; i++) {
|
for (unsigned int i = 0; i < RBUF_SIZE; i++) {
|
||||||
/* check first if entry already available */
|
/* check first if entry already available */
|
||||||
if ((rbuf[i].pkt != NULL) && (rbuf[i].pkt->size == size) &&
|
if ((rbuf[i].pkt != NULL) && (rbuf[i].pkt->size == size) &&
|
||||||
(rbuf[i].tag == tag) && (rbuf[i].src_len == src_len) &&
|
(rbuf[i].super.tag == tag) && (rbuf[i].super.src_len == src_len) &&
|
||||||
(rbuf[i].dst_len == dst_len) &&
|
(rbuf[i].super.dst_len == dst_len) &&
|
||||||
(memcmp(rbuf[i].src, src, src_len) == 0) &&
|
(memcmp(rbuf[i].super.src, src, src_len) == 0) &&
|
||||||
(memcmp(rbuf[i].dst, dst, dst_len) == 0)) {
|
(memcmp(rbuf[i].super.dst, dst, dst_len) == 0)) {
|
||||||
DEBUG("6lo rfrag: entry %p (%s, ", (void *)(&rbuf[i]),
|
DEBUG("6lo rfrag: entry %p (%s, ", (void *)(&rbuf[i]),
|
||||||
gnrc_netif_addr_to_str(rbuf[i].src,
|
gnrc_netif_addr_to_str(rbuf[i].super.src,
|
||||||
rbuf[i].src_len,
|
rbuf[i].super.src_len,
|
||||||
l2addr_str));
|
l2addr_str));
|
||||||
DEBUG("%s, %u, %u) found\n",
|
DEBUG("%s, %u, %u) found\n",
|
||||||
gnrc_netif_addr_to_str(rbuf[i].dst,
|
gnrc_netif_addr_to_str(rbuf[i].super.dst,
|
||||||
rbuf[i].dst_len,
|
rbuf[i].super.dst_len,
|
||||||
l2addr_str),
|
l2addr_str),
|
||||||
(unsigned)rbuf[i].pkt->size, rbuf[i].tag);
|
(unsigned)rbuf[i].pkt->size, rbuf[i].super.tag);
|
||||||
rbuf[i].arrival = now_usec;
|
rbuf[i].super.arrival = now_usec;
|
||||||
_set_rbuf_timeout();
|
_set_rbuf_timeout();
|
||||||
return &(rbuf[i]);
|
return &(rbuf[i]);
|
||||||
}
|
}
|
||||||
@ -318,7 +318,7 @@ static gnrc_sixlowpan_rbuf_t *_rbuf_get(const void *src, size_t src_len,
|
|||||||
/* remember oldest slot */
|
/* remember oldest slot */
|
||||||
/* note that xtimer_now will overflow in ~1.2 hours */
|
/* note that xtimer_now will overflow in ~1.2 hours */
|
||||||
if ((oldest == NULL) ||
|
if ((oldest == NULL) ||
|
||||||
(oldest->arrival - rbuf[i].arrival < UINT32_MAX / 2)) {
|
(oldest->super.arrival - rbuf[i].super.arrival < UINT32_MAX / 2)) {
|
||||||
oldest = &(rbuf[i]);
|
oldest = &(rbuf[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -330,7 +330,7 @@ static gnrc_sixlowpan_rbuf_t *_rbuf_get(const void *src, size_t src_len,
|
|||||||
* oldest could have been picked as res) */
|
* oldest could have been picked as res) */
|
||||||
assert(!rbuf_entry_empty(oldest));
|
assert(!rbuf_entry_empty(oldest));
|
||||||
if (GNRC_SIXLOWPAN_FRAG_RBUF_AGGRESSIVE_OVERRIDE ||
|
if (GNRC_SIXLOWPAN_FRAG_RBUF_AGGRESSIVE_OVERRIDE ||
|
||||||
((now_usec - oldest->arrival) >
|
((now_usec - oldest->super.arrival) >
|
||||||
GNRC_SIXLOWPAN_FRAG_RBUF_TIMEOUT_US)) {
|
GNRC_SIXLOWPAN_FRAG_RBUF_TIMEOUT_US)) {
|
||||||
DEBUG("6lo rfrag: reassembly buffer full, remove oldest entry\n");
|
DEBUG("6lo rfrag: reassembly buffer full, remove oldest entry\n");
|
||||||
gnrc_pktbuf_release(oldest->pkt);
|
gnrc_pktbuf_release(oldest->pkt);
|
||||||
@ -363,21 +363,21 @@ static gnrc_sixlowpan_rbuf_t *_rbuf_get(const void *src, size_t src_len,
|
|||||||
|
|
||||||
*((uint64_t *)res->pkt->data) = 0; /* clean first few bytes for later
|
*((uint64_t *)res->pkt->data) = 0; /* clean first few bytes for later
|
||||||
* look-ups */
|
* look-ups */
|
||||||
res->arrival = now_usec;
|
res->super.arrival = now_usec;
|
||||||
memcpy(res->src, src, src_len);
|
memcpy(res->super.src, src, src_len);
|
||||||
memcpy(res->dst, dst, dst_len);
|
memcpy(res->super.dst, dst, dst_len);
|
||||||
res->src_len = src_len;
|
res->super.src_len = src_len;
|
||||||
res->dst_len = dst_len;
|
res->super.dst_len = dst_len;
|
||||||
res->tag = tag;
|
res->super.tag = tag;
|
||||||
res->current_size = 0;
|
res->super.current_size = 0;
|
||||||
|
|
||||||
DEBUG("6lo rfrag: entry %p (%s, ", (void *)res,
|
DEBUG("6lo rfrag: entry %p (%s, ", (void *)res,
|
||||||
gnrc_netif_addr_to_str(res->src, res->src_len,
|
gnrc_netif_addr_to_str(res->super.src, res->super.src_len,
|
||||||
l2addr_str));
|
l2addr_str));
|
||||||
DEBUG("%s, %u, %u) created\n",
|
DEBUG("%s, %u, %u) created\n",
|
||||||
gnrc_netif_addr_to_str(res->dst, res->dst_len,
|
gnrc_netif_addr_to_str(res->super.dst, res->super.dst_len,
|
||||||
l2addr_str), (unsigned)res->pkt->size,
|
l2addr_str), (unsigned)res->pkt->size,
|
||||||
res->tag);
|
res->super.tag);
|
||||||
|
|
||||||
_set_rbuf_timeout();
|
_set_rbuf_timeout();
|
||||||
|
|
||||||
|
@ -577,7 +577,7 @@ void gnrc_sixlowpan_iphc_recv(gnrc_pktsnip_t *sixlo, void *rbuf_ptr,
|
|||||||
((uint8_t *)sixlo->data) + payload_offset,
|
((uint8_t *)sixlo->data) + payload_offset,
|
||||||
sixlo->size - payload_offset);
|
sixlo->size - payload_offset);
|
||||||
if (rbuf != NULL) {
|
if (rbuf != NULL) {
|
||||||
rbuf->current_size += (uncomp_hdr_len - payload_offset);
|
rbuf->super.current_size += (uncomp_hdr_len - payload_offset);
|
||||||
gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(rbuf, netif_hdr);
|
gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(rbuf, netif_hdr);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -223,20 +223,22 @@ static void _test_entry(const gnrc_sixlowpan_rbuf_t *entry,
|
|||||||
TEST_ASSERT_NOT_NULL(entry);
|
TEST_ASSERT_NOT_NULL(entry);
|
||||||
TEST_ASSERT_NOT_NULL(entry->pkt);
|
TEST_ASSERT_NOT_NULL(entry->pkt);
|
||||||
TEST_ASSERT_EQUAL_INT(TEST_DATAGRAM_SIZE, entry->pkt->size);
|
TEST_ASSERT_EQUAL_INT(TEST_DATAGRAM_SIZE, entry->pkt->size);
|
||||||
TEST_ASSERT_EQUAL_INT(sizeof(_test_netif_hdr_src), entry->src_len);
|
TEST_ASSERT_EQUAL_INT(sizeof(_test_netif_hdr_src),
|
||||||
TEST_ASSERT_MESSAGE(memcmp(entry->src, _test_netif_hdr_src,
|
entry->super.src_len);
|
||||||
entry->src_len) == 0,
|
TEST_ASSERT_MESSAGE(memcmp(entry->super.src, _test_netif_hdr_src,
|
||||||
"entry->src != TEST_NETIF_HDR_SRC");
|
entry->super.src_len) == 0,
|
||||||
TEST_ASSERT_EQUAL_INT(sizeof(_test_netif_hdr_dst), entry->dst_len);
|
"entry->super.src != TEST_NETIF_HDR_SRC");
|
||||||
TEST_ASSERT_MESSAGE(memcmp(entry->dst, _test_netif_hdr_dst,
|
TEST_ASSERT_EQUAL_INT(sizeof(_test_netif_hdr_dst),
|
||||||
entry->dst_len) == 0,
|
entry->super.dst_len);
|
||||||
"entry->dst != TEST_NETIF_HDR_DST");
|
TEST_ASSERT_MESSAGE(memcmp(entry->super.dst, _test_netif_hdr_dst,
|
||||||
TEST_ASSERT_EQUAL_INT(TEST_TAG, entry->tag);
|
entry->super.dst_len) == 0,
|
||||||
TEST_ASSERT_EQUAL_INT(exp_current_size, entry->current_size);
|
"entry->super.dst != TEST_NETIF_HDR_DST");
|
||||||
TEST_ASSERT_NOT_NULL(entry->ints);
|
TEST_ASSERT_EQUAL_INT(TEST_TAG, entry->super.tag);
|
||||||
TEST_ASSERT_NULL(entry->ints->next);
|
TEST_ASSERT_EQUAL_INT(exp_current_size, entry->super.current_size);
|
||||||
TEST_ASSERT_EQUAL_INT(exp_int_start, entry->ints->start);
|
TEST_ASSERT_NOT_NULL(entry->super.ints);
|
||||||
TEST_ASSERT_EQUAL_INT(exp_int_end, entry->ints->end);
|
TEST_ASSERT_NULL(entry->super.ints->next);
|
||||||
|
TEST_ASSERT_EQUAL_INT(exp_int_start, entry->super.ints->start);
|
||||||
|
TEST_ASSERT_EQUAL_INT(exp_int_end, entry->super.ints->end);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _check_pktbuf(const gnrc_sixlowpan_rbuf_t *entry)
|
static void _check_pktbuf(const gnrc_sixlowpan_rbuf_t *entry)
|
||||||
@ -513,7 +515,7 @@ static void test_rbuf_gc__manually(void)
|
|||||||
entry = (gnrc_sixlowpan_rbuf_t *)_first_non_empty_rbuf();
|
entry = (gnrc_sixlowpan_rbuf_t *)_first_non_empty_rbuf();
|
||||||
TEST_ASSERT_NOT_NULL(entry);
|
TEST_ASSERT_NOT_NULL(entry);
|
||||||
/* set arrival RBUF_TIMEOUT into the past */
|
/* set arrival RBUF_TIMEOUT into the past */
|
||||||
entry->arrival -= RBUF_TIMEOUT;
|
entry->super.arrival -= RBUF_TIMEOUT;
|
||||||
rbuf_gc();
|
rbuf_gc();
|
||||||
/* reassembly buffer is now empty */
|
/* reassembly buffer is now empty */
|
||||||
TEST_ASSERT_NULL(_first_non_empty_rbuf());
|
TEST_ASSERT_NULL(_first_non_empty_rbuf());
|
||||||
|
Loading…
Reference in New Issue
Block a user